mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-25 07:27:52 +01:00
add support for multi dimension array allocation
This commit is contained in:
parent
d460aac03f
commit
8379416cb8
@ -0,0 +1,163 @@
|
|||||||
|
package de.inetsoftware.jwebassembly.javascript;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
/*
|
||||||
|
Copyright 2020 Volker Berlin (i-net software)
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import de.inetsoftware.jwebassembly.wasm.AnyType;
|
||||||
|
import de.inetsoftware.jwebassembly.wasm.ArrayType;
|
||||||
|
import de.inetsoftware.jwebassembly.wasm.ValueType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synthetic functions for creating multidimensional dimensional arrays
|
||||||
|
*
|
||||||
|
* @author Volker Berlin
|
||||||
|
*/
|
||||||
|
public class JavaScriptNewMultiArrayFunctionName extends JavaScriptSyntheticFunctionName {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance
|
||||||
|
*
|
||||||
|
* @param dim
|
||||||
|
* the count of dimensions, should be >= 2
|
||||||
|
* @param type
|
||||||
|
* the full type of the allocated array
|
||||||
|
*/
|
||||||
|
public JavaScriptNewMultiArrayFunctionName( int dim, ArrayType type ) {
|
||||||
|
super( "NonGC", createName( dim, type ), createJS( dim, type ), createSignature( dim, type ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The element type of the array
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* the full type of the allocated array
|
||||||
|
* @return the element type
|
||||||
|
*/
|
||||||
|
private static ValueType getElementType( ArrayType type ) {
|
||||||
|
do {
|
||||||
|
AnyType arrayType = type.getArrayType();
|
||||||
|
if( arrayType.getClass() != ArrayType.class ) {
|
||||||
|
type = (ArrayType)arrayType;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return arrayType.getClass() == ValueType.class ? (ValueType)arrayType : ValueType.anyref;
|
||||||
|
} while( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the unique name depends on dimension and type
|
||||||
|
*
|
||||||
|
* @param dim
|
||||||
|
* the dimension
|
||||||
|
* @param type
|
||||||
|
* the full type of the allocated array
|
||||||
|
* @return the name
|
||||||
|
*/
|
||||||
|
private static String createName( int dim, ArrayType type ) {
|
||||||
|
return "array_newmulti" + dim + "_" + getElementType( type );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the signature of the function.
|
||||||
|
*
|
||||||
|
* @param dim
|
||||||
|
* the dimension
|
||||||
|
* @param type
|
||||||
|
* the full type of the allocated array
|
||||||
|
* @return the signature
|
||||||
|
*/
|
||||||
|
private static AnyType[] createSignature( int dim, ArrayType type ) {
|
||||||
|
AnyType[] signature = new AnyType[dim + 2];
|
||||||
|
Arrays.fill( signature, 0, dim, ValueType.i32 );
|
||||||
|
signature[dim + 1] = type;
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the factory for the JavaScript method
|
||||||
|
*
|
||||||
|
* @param dim
|
||||||
|
* the dimension
|
||||||
|
* @param type
|
||||||
|
* the full type of the allocated array
|
||||||
|
* @return the JavaScript factory
|
||||||
|
*/
|
||||||
|
private static Supplier<String> createJS( int dim, ArrayType type ) {
|
||||||
|
return () -> {
|
||||||
|
// the dimention that must be array and not typed array
|
||||||
|
int dimMulti = dim - 1;
|
||||||
|
|
||||||
|
// create parameter signature
|
||||||
|
StringBuilder js = new StringBuilder( "(" );
|
||||||
|
for( int i = 0; i < dimMulti; i++ ) {
|
||||||
|
js.append( 'd' ).append( i );
|
||||||
|
js.append( ',' );
|
||||||
|
}
|
||||||
|
js.append( "l)=>" );
|
||||||
|
|
||||||
|
createJsArray( js, 0, dimMulti, type );
|
||||||
|
|
||||||
|
return js.toString();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursion for the allocation with default value
|
||||||
|
*
|
||||||
|
* @param js
|
||||||
|
* the target
|
||||||
|
* @param idx
|
||||||
|
* running dimension index
|
||||||
|
* @param dimMulti
|
||||||
|
* the count of not typed dimensions
|
||||||
|
* @param type
|
||||||
|
* the full type of the allocated array
|
||||||
|
*/
|
||||||
|
private static void createJsArray( StringBuilder js, int idx, int dimMulti, ArrayType type ) {
|
||||||
|
js.append( "Array.from({length:d" ).append( idx ).append( "}, ()=>" );
|
||||||
|
idx++;
|
||||||
|
if( idx < dimMulti ) {
|
||||||
|
createJsArray( js, idx, dimMulti, type );
|
||||||
|
} else {
|
||||||
|
switch( getElementType( type ) ) {
|
||||||
|
case i8:
|
||||||
|
js.append( "new Uint8Array(l)" );
|
||||||
|
break;
|
||||||
|
case i16:
|
||||||
|
js.append( "new Int16Array(l)" );
|
||||||
|
break;
|
||||||
|
case i32:
|
||||||
|
js.append( "new Int32Array(l)" );
|
||||||
|
break;
|
||||||
|
case i64:
|
||||||
|
js.append( "new BigInt64Array(l)" );
|
||||||
|
break;
|
||||||
|
case f32:
|
||||||
|
js.append( "new Float32Array(l)" );
|
||||||
|
break;
|
||||||
|
case f64:
|
||||||
|
js.append( "new Float64Array(l)" );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
js.append( "Object.seal(new Array(l).fill(null))" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
js.append( ')' );
|
||||||
|
}
|
||||||
|
}
|
@ -670,7 +670,11 @@ class JavaMethodWasmCodeBuilder extends WasmCodeBuilder {
|
|||||||
// https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.wide
|
// https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.wide
|
||||||
wide = true;
|
wide = true;
|
||||||
continue;
|
continue;
|
||||||
//TODO case 197: // multianewarray
|
case 197: // multianewarray
|
||||||
|
name = ((ConstantClass)constantPool.get( byteCode.readUnsignedShort() )).getName();
|
||||||
|
idx = byteCode.readUnsignedByte();
|
||||||
|
addMultiNewArrayInstruction( idx, name, codePos, lineNumber );
|
||||||
|
break;
|
||||||
case 198: // ifnull
|
case 198: // ifnull
|
||||||
opIfCompareCondition( NumericOperator.ifnull, byteCode, codePos, lineNumber );
|
opIfCompareCondition( NumericOperator.ifnull, byteCode, codePos, lineNumber );
|
||||||
break;
|
break;
|
||||||
|
@ -29,11 +29,13 @@ import de.inetsoftware.classparser.LocalVariableTable;
|
|||||||
import de.inetsoftware.classparser.Member;
|
import de.inetsoftware.classparser.Member;
|
||||||
import de.inetsoftware.classparser.MethodInfo;
|
import de.inetsoftware.classparser.MethodInfo;
|
||||||
import de.inetsoftware.jwebassembly.WasmException;
|
import de.inetsoftware.jwebassembly.WasmException;
|
||||||
|
import de.inetsoftware.jwebassembly.javascript.JavaScriptNewMultiArrayFunctionName;
|
||||||
import de.inetsoftware.jwebassembly.javascript.JavaScriptSyntheticFunctionName;
|
import de.inetsoftware.jwebassembly.javascript.JavaScriptSyntheticFunctionName;
|
||||||
import de.inetsoftware.jwebassembly.javascript.NonGC;
|
import de.inetsoftware.jwebassembly.javascript.NonGC;
|
||||||
import de.inetsoftware.jwebassembly.module.WasmInstruction.Type;
|
import de.inetsoftware.jwebassembly.module.WasmInstruction.Type;
|
||||||
import de.inetsoftware.jwebassembly.wasm.AnyType;
|
import de.inetsoftware.jwebassembly.wasm.AnyType;
|
||||||
import de.inetsoftware.jwebassembly.wasm.ArrayOperator;
|
import de.inetsoftware.jwebassembly.wasm.ArrayOperator;
|
||||||
|
import de.inetsoftware.jwebassembly.wasm.ArrayType;
|
||||||
import de.inetsoftware.jwebassembly.wasm.MemoryOperator;
|
import de.inetsoftware.jwebassembly.wasm.MemoryOperator;
|
||||||
import de.inetsoftware.jwebassembly.wasm.NamedStorageType;
|
import de.inetsoftware.jwebassembly.wasm.NamedStorageType;
|
||||||
import de.inetsoftware.jwebassembly.wasm.NumericOperator;
|
import de.inetsoftware.jwebassembly.wasm.NumericOperator;
|
||||||
@ -591,6 +593,28 @@ public abstract class WasmCodeBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new multi dimensional array instruction
|
||||||
|
*
|
||||||
|
* @param dim
|
||||||
|
* the dimension of the array >= 2
|
||||||
|
* @param typeName
|
||||||
|
* the full type name
|
||||||
|
* @param javaCodePos
|
||||||
|
* the code position/offset in the Java method
|
||||||
|
* @param lineNumber
|
||||||
|
* the line number in the Java source code
|
||||||
|
*/
|
||||||
|
protected void addMultiNewArrayInstruction( int dim, String typeName, int javaCodePos, int lineNumber ) {
|
||||||
|
ArrayType type = (ArrayType)new ValueTypeParser( typeName, types ).next();
|
||||||
|
if( options.useGC() ) {
|
||||||
|
throw new WasmException( "multi new array is not supported", lineNumber );
|
||||||
|
} else {
|
||||||
|
FunctionName name = new JavaScriptNewMultiArrayFunctionName( dim, type );
|
||||||
|
addCallInstruction( name, javaCodePos, lineNumber );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an array operation to the instruction list as marker on the code position.
|
* Add an array operation to the instruction list as marker on the code position.
|
||||||
*
|
*
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 Volker Berlin (i-net software)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package de.inetsoftware.jwebassembly.runtime;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.zip.CRC32;
|
||||||
|
|
||||||
|
import org.junit.Assume;
|
||||||
|
import org.junit.ClassRule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runners.Parameterized.Parameters;
|
||||||
|
|
||||||
|
import de.inetsoftware.jwebassembly.ScriptEngine;
|
||||||
|
import de.inetsoftware.jwebassembly.WasmRule;
|
||||||
|
import de.inetsoftware.jwebassembly.api.annotation.Export;
|
||||||
|
|
||||||
|
public class MultiArrayOperations extends AbstractBaseTest {
|
||||||
|
|
||||||
|
@ClassRule
|
||||||
|
public static WasmRule rule = new WasmRule( TestClass.class );
|
||||||
|
|
||||||
|
public MultiArrayOperations( ScriptEngine script, String method, Object[] params ) {
|
||||||
|
super( rule, script, method, params );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Parameters( name = "{0}-{1}" )
|
||||||
|
public static Collection<Object[]> data() {
|
||||||
|
ArrayList<Object[]> list = new ArrayList<>();
|
||||||
|
|
||||||
|
ScriptEngine[] engines = ScriptEngine.testEngines();
|
||||||
|
for( ScriptEngine script : engines ) {
|
||||||
|
addParam( list, script, "multi" );
|
||||||
|
}
|
||||||
|
rule.setTestParameters( list );
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Override
|
||||||
|
public void test() {
|
||||||
|
super.test();
|
||||||
|
}
|
||||||
|
|
||||||
|
static class TestClass {
|
||||||
|
|
||||||
|
@Export
|
||||||
|
static int multi() {
|
||||||
|
int[][][] val = new int[1][2][3];
|
||||||
|
return val.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user