mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-25 07:27:52 +01:00
Use also the object model with vtable and hashcode for array objects.
This commit is contained in:
parent
13ffea0ca9
commit
c29ed6340c
@ -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;
|
package de.inetsoftware.jwebassembly.module;
|
||||||
|
|
||||||
import java.util.Arrays;
|
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.AnyType;
|
||||||
|
import de.inetsoftware.jwebassembly.wasm.ArrayOperator;
|
||||||
import de.inetsoftware.jwebassembly.wasm.ArrayType;
|
import de.inetsoftware.jwebassembly.wasm.ArrayType;
|
||||||
|
import de.inetsoftware.jwebassembly.wasm.NumericOperator;
|
||||||
import de.inetsoftware.jwebassembly.wasm.ValueType;
|
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
|
* Synthetic functions for creating multidimensional dimensional arrays
|
||||||
*
|
*
|
||||||
* @author Volker Berlin
|
* @author Volker Berlin
|
||||||
*/
|
*/
|
||||||
public class MultiArrayFunctionName extends JavaScriptSyntheticFunctionName {
|
public class MultiArrayFunctionName extends WatCodeSyntheticFunctionName {
|
||||||
|
|
||||||
|
private int dim;
|
||||||
|
|
||||||
|
private ArrayType type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance
|
* Create a new instance
|
||||||
@ -39,8 +46,10 @@ public class MultiArrayFunctionName extends JavaScriptSyntheticFunctionName {
|
|||||||
* @param type
|
* @param type
|
||||||
* the full type of the allocated array
|
* the full type of the allocated array
|
||||||
*/
|
*/
|
||||||
public MultiArrayFunctionName( int dim, ArrayType type ) {
|
MultiArrayFunctionName( int dim, ArrayType type ) {
|
||||||
super( "NonGC", createName( dim, type ), createJS( dim, type ), createSignature( dim, 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 ) {
|
private static ValueType getElementType( ArrayType type ) {
|
||||||
do {
|
do {
|
||||||
AnyType arrayType = type.getArrayType();
|
AnyType arrayType = type.getArrayType();
|
||||||
if( arrayType.getClass() != ArrayType.class ) {
|
if( arrayType.getClass() == ArrayType.class ) {
|
||||||
type = (ArrayType)arrayType;
|
type = (ArrayType)arrayType;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -91,74 +100,59 @@ public class MultiArrayFunctionName extends JavaScriptSyntheticFunctionName {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the factory for the JavaScript method
|
* {@inheritDoc}
|
||||||
*
|
|
||||||
* @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 ) {
|
@Override
|
||||||
return () -> {
|
protected WasmCodeBuilder getCodeBuilder( WatParser watParser ) {
|
||||||
// the dimention that must be array and not typed array
|
watParser.reset( null, null, getSignature( null ) );
|
||||||
int dimMulti = dim - 1;
|
int javaCodePos = 0;
|
||||||
|
|
||||||
// create parameter signature
|
// allocate the main array (top most) and save it in a local variable
|
||||||
StringBuilder js = new StringBuilder( "(" );
|
AnyType arrayType = type.getArrayType();
|
||||||
for( int i = 0; i < dimMulti; i++ ) {
|
watParser.addLocalInstruction( VariableOperator.get, 0, javaCodePos++, -1 );
|
||||||
js.append( 'd' ).append( i );
|
watParser.addArrayInstruction( ArrayOperator.NEW, arrayType, javaCodePos++, -1 );
|
||||||
js.append( ',' );
|
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)=>" );
|
if( dim > 2 ) {
|
||||||
|
watParser.addMultiNewArrayInstruction( dim - 1, (ArrayType)arrayType, javaCodePos++, -1 );
|
||||||
createJsArray( js, 0, dimMulti, type );
|
} else {
|
||||||
|
watParser.addArrayInstruction( ArrayOperator.NEW, arrayType, javaCodePos++, -1 );
|
||||||
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))" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,6 @@ 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.NonGC;
|
import de.inetsoftware.jwebassembly.javascript.NonGC;
|
||||||
import de.inetsoftware.jwebassembly.module.StackInspector.StackValue;
|
import de.inetsoftware.jwebassembly.module.StackInspector.StackValue;
|
||||||
import de.inetsoftware.jwebassembly.module.WasmInstruction.Type;
|
import de.inetsoftware.jwebassembly.module.WasmInstruction.Type;
|
||||||
@ -737,15 +736,14 @@ public abstract class WasmCodeBuilder {
|
|||||||
* the line number in the Java source code
|
* the line number in the Java source code
|
||||||
*/
|
*/
|
||||||
protected void addArrayInstruction( ArrayOperator op, AnyType type, int javaCodePos, int lineNumber ) {
|
protected void addArrayInstruction( ArrayOperator op, AnyType type, int javaCodePos, int lineNumber ) {
|
||||||
if( options.useGC() ) {
|
WasmArrayInstruction arrayInst = new WasmArrayInstruction( op, type, types, javaCodePos, lineNumber );
|
||||||
instructions.add( new WasmArrayInstruction( op, type, types, javaCodePos, lineNumber ) );
|
instructions.add( arrayInst );
|
||||||
} else {
|
if( !options.useGC() ) {
|
||||||
if( type.getCode() >= 0 || type.getCode() == ValueType.externref.getCode() ) {
|
SyntheticFunctionName name = arrayInst.createNonGcFunction();
|
||||||
type = ValueType.externref; // handle all not native types as anyref
|
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 ) {
|
protected void addMultiNewArrayInstruction( int dim, String typeName, int javaCodePos, int lineNumber ) {
|
||||||
ArrayType type = (ArrayType)new ValueTypeParser( typeName, types ).next();
|
ArrayType type = (ArrayType)new ValueTypeParser( typeName, types ).next();
|
||||||
if( options.useGC() ) {
|
addMultiNewArrayInstruction( dim, type, javaCodePos, lineNumber );
|
||||||
throw new WasmException( "multi new array is not supported", lineNumber );
|
}
|
||||||
} else {
|
|
||||||
FunctionName name = new JavaScriptNewMultiArrayFunctionName( dim, type );
|
/**
|
||||||
addCallInstruction( name, javaCodePos, lineNumber );
|
* Add a new multi dimensional array instruction
|
||||||
}
|
*
|
||||||
|
* @param dim
|
||||||
|
* the dimension of the array >= 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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user