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,35 +1,42 @@
/*
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.module;
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.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 );
} 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))" );
if( dim > 2 ) {
watParser.addMultiNewArrayInstruction( dim - 1, (ArrayType)arrayType, javaCodePos++, -1 );
} else {
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 );
}
js.append( ')' );
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 );
}
/**