fix assignment of parameters from stack for lambda expressions with parameters

This commit is contained in:
Volker Berlin 2021-03-28 10:56:51 +02:00
parent d480471e27
commit f4fd312d31

View File

@ -17,6 +17,7 @@ package de.inetsoftware.jwebassembly.module;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.function.Function; import java.util.function.Function;
@ -854,7 +855,7 @@ public abstract class WasmCodeBuilder {
} }
/** /**
* Add invoke dynamic operation. * Add invoke dynamic operation. (Creating of a lambda expression)
* *
* @param method * @param method
* the BootstrapMethod, described the method that should be executed * the BootstrapMethod, described the method that should be executed
@ -869,9 +870,12 @@ public abstract class WasmCodeBuilder {
* the line number in the Java source code * the line number in the Java source code
*/ */
protected void addInvokeDynamic( BootstrapMethod method, String factorySignature, String interfaceMethodName, int javaCodePos, int lineNumber ) { protected void addInvokeDynamic( BootstrapMethod method, String factorySignature, String interfaceMethodName, int javaCodePos, int lineNumber ) {
// mark the static, synthetic method which implement the lambda code, as needed
ConstantMethodRef implMethod = method.getImplMethod(); ConstantMethodRef implMethod = method.getImplMethod();
FunctionName name = new FunctionName( implMethod ); FunctionName name = new FunctionName( implMethod );
functions.markAsNeeded( name ); functions.markAsNeeded( name );
// Create the synthetic lambda class that hold the lambda expression.
String lambdaTypeName = implMethod.getClassName() + "$$" + implMethod.getName() + "/" + Math.abs( name.hashCode() ); String lambdaTypeName = implMethod.getClassName() + "$$" + implMethod.getName() + "/" + Math.abs( name.hashCode() );
ValueTypeParser parser = new ValueTypeParser( factorySignature, types ); ValueTypeParser parser = new ValueTypeParser( factorySignature, types );
ArrayList<AnyType> params = new ArrayList<>(); ArrayList<AnyType> params = new ArrayList<>();
@ -884,11 +888,28 @@ public abstract class WasmCodeBuilder {
} while( true ); } while( true );
StructType interfaceType = (StructType)parser.next(); StructType interfaceType = (StructType)parser.next();
LambdaType type = types.lambdaType( lambdaTypeName, params, interfaceType, name, interfaceMethodName ); LambdaType type = types.lambdaType( lambdaTypeName, params, interfaceType, name, interfaceMethodName );
addStructInstruction( StructOperator.NEW_DEFAULT, lambdaTypeName, null, javaCodePos, lineNumber );
for( NamedStorageType field : type.getParamFields() ) { // Create the instance of the synthetic lambda class and save the parameters in fields
addDupInstruction( javaCodePos, lineNumber ); ArrayList<NamedStorageType> paramFields = type.getParamFields();
instructions.add( new WasmStructInstruction( StructOperator.SET, lambdaTypeName, field, javaCodePos, lineNumber, types ) ); int paramCount = paramFields.size();
if( paramCount == 0 ) {
addStructInstruction( StructOperator.NEW_DEFAULT, lambdaTypeName, null, javaCodePos, lineNumber );
} else {
// Lambda with parameters from the stack
int idx = StackInspector.findInstructionThatPushValue( instructions, paramCount, javaCodePos ).idx;
int pos = instructions.size();
addStructInstruction( StructOperator.NEW_DEFAULT, lambdaTypeName, null, javaCodePos, lineNumber );
int slot = ((WasmLocalInstruction)findInstructionThatPushValue( 1, javaCodePos )).getSlot();
// move the creating of the lambda instance before the parameters on the stack
Collections.rotate( instructions.subList( idx, instructions.size() ), idx - pos );
for( int i = 0; i < paramCount; i++ ) {
NamedStorageType field = paramFields.get( i );
idx = StackInspector.findInstructionThatPushValue( instructions, paramCount - i, javaCodePos ).idx;
instructions.add( idx, new WasmLoadStoreInstruction( VariableOperator.get, slot, localVariables, javaCodePos, lineNumber ) );
instructions.add( new WasmStructInstruction( StructOperator.SET, lambdaTypeName, field, javaCodePos, lineNumber, types ) );
}
} }
} }