Use also the object model with vtable and hashcode for array objects.

This commit is contained in:
Volker Berlin 2020-07-05 14:08:46 +02:00
parent 13ffea0ca9
commit c29ed6340c
2 changed files with 105 additions and 101 deletions

View File

@ -1,6 +1,3 @@
package de.inetsoftware.jwebassembly.module;
import java.util.Arrays;
/*
Copyright 2020 Volker Berlin (i-net software)
@ -17,19 +14,29 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import java.util.function.Supplier;
package de.inetsoftware.jwebassembly.module;
import java.util.Arrays;
import de.inetsoftware.jwebassembly.javascript.JavaScriptSyntheticFunctionName;
import de.inetsoftware.jwebassembly.wasm.AnyType;
import de.inetsoftware.jwebassembly.wasm.ArrayOperator;
import de.inetsoftware.jwebassembly.wasm.ArrayType;
import de.inetsoftware.jwebassembly.wasm.NumericOperator;
import de.inetsoftware.jwebassembly.wasm.ValueType;
import de.inetsoftware.jwebassembly.wasm.VariableOperator;
import de.inetsoftware.jwebassembly.wasm.WasmBlockOperator;
import de.inetsoftware.jwebassembly.watparser.WatParser;
/**
* Synthetic functions for creating multidimensional dimensional arrays
*
* @author Volker Berlin
*/
public class MultiArrayFunctionName extends JavaScriptSyntheticFunctionName {
public class MultiArrayFunctionName extends WatCodeSyntheticFunctionName {
private int dim;
private ArrayType type;
/**
* Create a new instance
@ -39,8 +46,10 @@ public class MultiArrayFunctionName extends JavaScriptSyntheticFunctionName {
* @param type
* the full type of the allocated array
*/
public MultiArrayFunctionName( int dim, ArrayType type ) {
super( "NonGC", createName( dim, type ), createJS( dim, type ), createSignature( dim, type ) );
MultiArrayFunctionName( int dim, ArrayType type ) {
super( "NonGC", createName( dim, type ), "()V", null, createSignature( dim, type ) );
this.dim = dim;
this.type = type;
}
/**
@ -53,7 +62,7 @@ public class MultiArrayFunctionName extends JavaScriptSyntheticFunctionName {
private static ValueType getElementType( ArrayType type ) {
do {
AnyType arrayType = type.getArrayType();
if( arrayType.getClass() != ArrayType.class ) {
if( arrayType.getClass() == ArrayType.class ) {
type = (ArrayType)arrayType;
continue;
}
@ -91,74 +100,59 @@ public class MultiArrayFunctionName extends JavaScriptSyntheticFunctionName {
}
/**
* Get the factory for the JavaScript method
*
* @param dim
* the dimension
* @param type
* the full type of the allocated array
* @return the JavaScript factory
* {@inheritDoc}
*/
private static Supplier<String> createJS( int dim, ArrayType type ) {
return () -> {
// the dimention that must be array and not typed array
int dimMulti = dim - 1;
@Override
protected WasmCodeBuilder getCodeBuilder( WatParser watParser ) {
watParser.reset( null, null, getSignature( null ) );
int javaCodePos = 0;
// create parameter signature
StringBuilder js = new StringBuilder( "(" );
for( int i = 0; i < dimMulti; i++ ) {
js.append( 'd' ).append( i );
js.append( ',' );
// allocate the main array (top most) and save it in a local variable
AnyType arrayType = type.getArrayType();
watParser.addLocalInstruction( VariableOperator.get, 0, javaCodePos++, -1 );
watParser.addArrayInstruction( ArrayOperator.NEW, arrayType, javaCodePos++, -1 );
watParser.addLocalInstruction( VariableOperator.set, dim, javaCodePos++, -1 );
watParser.addBlockInstruction( WasmBlockOperator.BLOCK, null, javaCodePos++, -1 );
watParser.addBlockInstruction( WasmBlockOperator.LOOP, null, javaCodePos++, -1 );
{
// end condition
watParser.addLocalInstruction( VariableOperator.get, 0, javaCodePos++, -1 );
watParser.addNumericInstruction( NumericOperator.eqz, ValueType.i32, javaCodePos++, -1 );
watParser.addBlockInstruction( WasmBlockOperator.BR_IF, 1, javaCodePos++, -1 );
// get the reference to the top most array
watParser.addLocalInstruction( VariableOperator.get, dim, javaCodePos++, -1 );
// decrement the counter
watParser.addLocalInstruction( VariableOperator.get, 0, javaCodePos++, -1 );
watParser.addConstInstruction( 1, javaCodePos++, -1 );
watParser.addNumericInstruction( NumericOperator.sub, ValueType.i32, javaCodePos++, -1 );
watParser.addLocalInstruction( VariableOperator.tee, 0, javaCodePos++, -1 );
// allocate a sub array
for( int i = 1; i < dim; i++ ) {
watParser.addLocalInstruction( VariableOperator.get, i, javaCodePos++, -1 );
}
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 );
if( dim > 2 ) {
watParser.addMultiNewArrayInstruction( dim - 1, (ArrayType)arrayType, javaCodePos++, -1 );
} 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( ')' );
watParser.addArrayInstruction( ArrayOperator.NEW, arrayType, javaCodePos++, -1 );
}
// set the sub array into the main array
watParser.addArrayInstruction( ArrayOperator.SET, arrayType, javaCodePos++, -1 );
// continue the loop
watParser.addBlockInstruction( WasmBlockOperator.BR, 0, javaCodePos++, -1 );
}
watParser.addBlockInstruction( WasmBlockOperator.END, null, javaCodePos++, -1 );
watParser.addBlockInstruction( WasmBlockOperator.END, null, javaCodePos++, -1 );
//return the created array
watParser.addLocalInstruction( VariableOperator.get, dim, javaCodePos++, -1 );
watParser.addBlockInstruction( WasmBlockOperator.RETURN, null, javaCodePos++, -1 );
return watParser;
}
}

View File

@ -31,7 +31,6 @@ import de.inetsoftware.classparser.LocalVariableTable;
import de.inetsoftware.classparser.Member;
import de.inetsoftware.classparser.MethodInfo;
import de.inetsoftware.jwebassembly.WasmException;
import de.inetsoftware.jwebassembly.javascript.JavaScriptNewMultiArrayFunctionName;
import de.inetsoftware.jwebassembly.javascript.NonGC;
import de.inetsoftware.jwebassembly.module.StackInspector.StackValue;
import de.inetsoftware.jwebassembly.module.WasmInstruction.Type;
@ -737,15 +736,14 @@ public abstract class WasmCodeBuilder {
* the line number in the Java source code
*/
protected void addArrayInstruction( ArrayOperator op, AnyType type, int javaCodePos, int lineNumber ) {
if( options.useGC() ) {
instructions.add( new WasmArrayInstruction( op, type, types, javaCodePos, lineNumber ) );
} else {
if( type.getCode() >= 0 || type.getCode() == ValueType.externref.getCode() ) {
type = ValueType.externref; // handle all not native types as anyref
WasmArrayInstruction arrayInst = new WasmArrayInstruction( op, type, types, javaCodePos, lineNumber );
instructions.add( arrayInst );
if( !options.useGC() ) {
SyntheticFunctionName name = arrayInst.createNonGcFunction();
if( name != null ) {
functions.markAsNeeded( name );
functions.markAsImport( name, name.getAnnotation() );
}
String api = "array_" + op.toString().toLowerCase() + "_" + type;
FunctionName name = getNonGC( api, lineNumber );
addCallInstruction( name, javaCodePos, lineNumber );
}
}
@ -763,12 +761,24 @@ public abstract class WasmCodeBuilder {
*/
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 );
addMultiNewArrayInstruction( dim, type, javaCodePos, lineNumber );
}
/**
* Add a new multi dimensional array instruction
*
* @param dim
* the dimension of the array &gt;= 2
* @param type
* the full type
* @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, ArrayType type, int javaCodePos, int lineNumber ) {
MultiArrayFunctionName name = new MultiArrayFunctionName( dim, type );
addCallInstruction( name, javaCodePos, lineNumber );
}
/**