The needThis flag must be set already on marking a function as needing. If it will set on scan it is to late for stack calculation.

This commit is contained in:
Volker Berlin 2021-04-17 20:27:28 +02:00
parent d271ac1a2f
commit b35279a960
9 changed files with 45 additions and 49 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2018 - 2020 Volker Berlin (i-net software)
* Copyright 2018 - 2021 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.
@ -135,7 +135,7 @@ class FunctionManager {
states.remove( name );
states.put( name, state );
}
markAsNeeded( name );
markAsNeeded( name, !name.istStatic() );
}
/**
@ -143,15 +143,18 @@ class FunctionManager {
*
* @param name
* the function name
* @param needThisParameter
* if this function need additional to the parameter of the signature an extra "this" parameter
* @return the real function name
*/
FunctionName markAsNeeded( @Nonnull FunctionName name ) {
FunctionName markAsNeeded( @Nonnull FunctionName name, boolean needThisParameter ) {
FunctionState state = getOrCreate( name );
if( state.state == State.None ) {
if( isFinish ) {
throw new WasmException( "Prepare was already finish: " + name.signatureName, -1 );
}
state.state = State.Needed;
state.needThisParameter = needThisParameter;
JWebAssembly.LOGGER.fine( "\t\tcall: " + name.signatureName );
usedClasses.add( name.className );
}
@ -163,10 +166,8 @@ class FunctionManager {
*
* @param name
* the function name
* @param needThisParameter
* if this function need additional to the parameter of the signature an extra "this" parameter
*/
void markAsScanned( @Nonnull FunctionName name, boolean needThisParameter ) {
void markAsScanned( @Nonnull FunctionName name ) {
FunctionState state = getOrCreate( name );
switch( state.state ) {
case None:
@ -174,7 +175,6 @@ class FunctionManager {
state.state = State.Scanned;
break;
}
state.needThisParameter = needThisParameter;
}
/**

View File

@ -362,14 +362,14 @@ class JavaMethodWasmCodeBuilder extends WasmCodeBuilder {
break;
case 108: // idiv
if( getOptions().useEH() ) {
addCallInstruction( new FunctionName( "de/inetsoftware/jwebassembly/module/WasmEmbbeddedCode", "idiv", "(II)I" ), codePos, lineNumber );
addCallInstruction( new FunctionName( "de/inetsoftware/jwebassembly/module/WasmEmbbeddedCode", "idiv", "(II)I" ), false, codePos, lineNumber );
} else {
addNumericInstruction( NumericOperator.div, ValueType.i32, codePos, lineNumber );
}
break;
case 109: // ldiv
if( getOptions().useEH() ) {
addCallInstruction( new FunctionName( "de/inetsoftware/jwebassembly/module/WasmEmbbeddedCode", "ldiv", "(JJ)J" ), codePos, lineNumber );
addCallInstruction( new FunctionName( "de/inetsoftware/jwebassembly/module/WasmEmbbeddedCode", "ldiv", "(JJ)J" ), false, codePos, lineNumber );
} else {
addNumericInstruction( NumericOperator.div, ValueType.i64, codePos, lineNumber );
}
@ -388,11 +388,11 @@ class JavaMethodWasmCodeBuilder extends WasmCodeBuilder {
break;
case 114: // frem
//helper function like: (a - (int)(a / b) * (float)b)
addCallInstruction( new WatCodeSyntheticFunctionName( "frem", "local.get 0 local.get 0 local.get 1 f32.div i32.trunc_sat_f32_s f32.convert_i32_s local.get 1 f32.mul f32.sub return", ValueType.f32, ValueType.f32, null, ValueType.f32 ), codePos, lineNumber );
addCallInstruction( new WatCodeSyntheticFunctionName( "frem", "local.get 0 local.get 0 local.get 1 f32.div i32.trunc_sat_f32_s f32.convert_i32_s local.get 1 f32.mul f32.sub return", ValueType.f32, ValueType.f32, null, ValueType.f32 ), false, codePos, lineNumber );
break;
case 115: // drem
//helper function like: (a - (long)(a / b) * (double)b)
addCallInstruction( new WatCodeSyntheticFunctionName( "drem", "local.get 0 local.get 0 local.get 1 f64.div i64.trunc_sat_f64_s f64.convert_i64_s local.get 1 f64.mul f64.sub return", ValueType.f64, ValueType.f64, null, ValueType.f64 ), codePos, lineNumber );
addCallInstruction( new WatCodeSyntheticFunctionName( "drem", "local.get 0 local.get 0 local.get 1 f64.div i64.trunc_sat_f64_s f64.convert_i64_s local.get 1 f64.mul f64.sub return", ValueType.f64, ValueType.f64, null, ValueType.f64 ), false, codePos, lineNumber );
break;
case 116: // ineg
addConstInstruction( -1, ValueType.i32, codePos, lineNumber );
@ -621,10 +621,10 @@ class JavaMethodWasmCodeBuilder extends WasmCodeBuilder {
addCallVirtualInstruction( funcName, codePos, lineNumber );
break;
case 183:
addCallInstruction( funcName, codePos, lineNumber );
addCallInstruction( funcName, true, codePos, lineNumber );
break;
case 184:
addCallInstruction( funcName, codePos, lineNumber );
addCallInstruction( funcName, false, codePos, lineNumber );
break;
case 185:
addCallInterfaceInstruction( funcName, codePos, lineNumber );

View File

@ -208,7 +208,7 @@ public class ModuleGenerator {
} else {
functions.markAsImport( synth, synth.getAnnotation() );
}
functions.markAsScanned( next, !synth.istStatic() );
functions.markAsScanned( next );
continue;
}
@ -224,11 +224,8 @@ public class ModuleGenerator {
}
if( method != null ) {
createInstructions( functions.replace( next, method ) );
boolean needThisParameter = !method.isStatic() // if not static there is a not declared THIS parameter
|| "<init>".equals( method.getName() ) // constructor method need also the THIS parameter also if marked as static
/*|| (method.isLambda() )*/; // lambda functions are static but will call with a THIS parameter which need be removed from stack
functions.markAsScanned( next, needThisParameter );
if( needThisParameter ) {
functions.markAsScanned( next );
if( functions.needThisParameter( next ) ) {
types.valueOf( next.className ); // for the case that the type unknown yet
}
continue;
@ -240,7 +237,7 @@ public class ModuleGenerator {
method = superClassFile.getMethod( next.methodName, next.signature );
if( method != null ) {
FunctionName name = new FunctionName( method );
functions.markAsNeeded( name );
functions.markAsNeeded( name, !method.isStatic() );
functions.setAlias( next, name );
continue NEXT; // we have found a super method
}
@ -256,7 +253,7 @@ public class ModuleGenerator {
method = iClassFile.getMethod( next.methodName, next.signature );
if( method != null ) {
FunctionName name = new FunctionName( method );
functions.markAsNeeded( name );
functions.markAsNeeded( name, !method.isStatic() );
functions.setAlias( next, name );
continue NEXT; // we have found a super method
}
@ -344,7 +341,7 @@ public class ModuleGenerator {
if( classFile != null ) {
MethodInfo method = classFile.getMethod( "<clinit>", "()V" );
if( method != null ) {
functions.markAsNeeded( new FunctionName( method ) );
functions.markAsNeeded( new FunctionName( method ), false );
}
}
}
@ -360,7 +357,7 @@ public class ModuleGenerator {
// add the start function/section only if there are static code
if( functions.getWriteLaterClinit().hasNext() ) {
FunctionName start = new StaticCodeBuilder( writer.options, classFileLoader, javaCodeBuilder ).createStartFunction();
functions.markAsNeeded( start );
functions.markAsNeeded( start, false );
writeMethodSignature( start, FunctionType.Start, null );
}
}
@ -474,7 +471,7 @@ public class ModuleGenerator {
if( !method.isStatic() ) {
throw new WasmException( "Export method must be static: " + name.fullName, -1 );
}
functions.markAsNeeded( name );
functions.markAsNeeded( name, false );
return;
}
} catch( Exception ioex ) {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2020 Volker Berlin (i-net software)
* Copyright 2020 - 2021 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.
@ -85,7 +85,7 @@ class StaticCodeBuilder {
while( !clinits.isEmpty() ) {
FunctionName name = clinits.pop();
watParser.addCallInstruction( name, 0, -1 );
watParser.addCallInstruction( name, false, 0, -1 );
scanAndPatchIfNeeded( name );
}
return watParser;

View File

@ -1,5 +1,5 @@
/*
Copyright 2019 - 2020 Volker Berlin (i-net software)
Copyright 2019 - 2021 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.
@ -84,7 +84,7 @@ public class StringManager extends LinkedHashMap<String, Integer> {
}
};
functions.markAsNeededAndReplaceIfExists( offsetFunction );
functions.markAsNeeded( stringConstantFunction );
functions.markAsNeeded( stringConstantFunction, false );
}
return stringConstantFunction;

View File

@ -254,7 +254,7 @@ public class TypeManager {
return "i32.const " + typeTableOffset;
}
};
options.functions.markAsNeeded( offsetFunction );
options.functions.markAsNeeded( offsetFunction, !offsetFunction.istStatic() );
return offsetFunction;
}
@ -804,7 +804,7 @@ public class TypeManager {
if( func.methodName.equals( funcName.methodName ) && func.signature.equals( funcName.signature ) ) {
if( !isDefault || functions.getITableIndex( func ) >= 0 ) {
vtable.set( idx, funcName ); // use the override method
functions.markAsNeeded( funcName ); // mark all overridden methods also as needed if the super method is used
functions.markAsNeeded( funcName, true ); // mark all overridden methods also as needed if the super method is used
}
break;
}
@ -891,7 +891,7 @@ public class TypeManager {
if( method != null ) {
FunctionName methodName = new FunctionName( method );
functions.markAsNeeded( methodName );
functions.markAsNeeded( methodName, !method.isStatic() );
if( iMethods == null ) {
interfaceMethods.put( type, iMethods = new ArrayList<>() );
}
@ -1210,7 +1210,7 @@ public class TypeManager {
codebuilder.addStructInstruction( StructOperator.GET, name, paramFields.get( i ), 0, -1 );
}
codebuilder.addCallInstruction( syntheticLambdaFunctionName, 0, -1 );
codebuilder.addCallInstruction( syntheticLambdaFunctionName, false, 0, -1 );
return watParser;
}
};

View File

@ -477,7 +477,7 @@ public abstract class WasmCodeBuilder {
Integer id = types.valueOf( className ).getClassIndex();
FunctionName name = types.getClassConstantFunction();
instructions.add( new WasmConstInstruction( id, ValueType.i32, javaCodePos, lineNumber ) );
addCallInstruction( name, javaCodePos, lineNumber );
addCallInstruction( name, false, javaCodePos, lineNumber );
} else {
//TODO There can be ConstantClass, MethodType and MethodHandle
throw new WasmException( "Class constants are not supported. : " + value, lineNumber );
@ -520,7 +520,7 @@ public abstract class WasmCodeBuilder {
WasmNumericInstruction numeric = new WasmNumericInstruction( numOp, valueType, javaCodePos, lineNumber );
instructions.add( numeric );
if( !options.useGC() && options.ref_eq == null && (numOp == NumericOperator.ref_eq || numOp == NumericOperator.ref_ne ) ) {
functions.markAsNeeded( options.ref_eq = getNonGC( "ref_eq", lineNumber ) );
functions.markAsNeeded( options.ref_eq = getNonGC( "ref_eq", lineNumber ), false );
}
return numeric;
}
@ -549,9 +549,8 @@ public abstract class WasmCodeBuilder {
* @param lineNumber
* the line number in the Java source code
*/
protected void addCallInstruction( FunctionName name, int javaCodePos, int lineNumber ) {
name = functions.markAsNeeded( name );
boolean needThisParameter = functions.needThisParameter( name );
protected void addCallInstruction( FunctionName name, boolean needThisParameter, int javaCodePos, int lineNumber ) {
name = functions.markAsNeeded( name, needThisParameter );
WasmCallInstruction instruction = new WasmCallInstruction( name, javaCodePos, lineNumber, types, needThisParameter );
if( "<init>".equals( name.methodName ) ) {
@ -642,7 +641,7 @@ public abstract class WasmCodeBuilder {
* the line number in the Java source code
*/
protected void addCallVirtualInstruction( FunctionName name, int javaCodePos, int lineNumber ) {
name = functions.markAsNeeded( name );
name = functions.markAsNeeded( name, true );
addCallIndirectInstruction( new WasmCallVirtualInstruction( name, javaCodePos, lineNumber, types, options ) );
options.getCallVirtual(); // mark the function as needed
functions.markClassAsUsed( name.className );
@ -658,7 +657,7 @@ public abstract class WasmCodeBuilder {
* the line number in the Java source code
*/
protected void addCallInterfaceInstruction( FunctionName name, int javaCodePos, int lineNumber ) {
name = functions.markAsNeeded( name );
name = functions.markAsNeeded( name, true );
addCallIndirectInstruction( new WasmCallInterfaceInstruction( name, javaCodePos, lineNumber, types, options ) );
options.getCallInterface(); // mark the function as needed
functions.markClassAsUsed( name.className );
@ -773,7 +772,7 @@ public abstract class WasmCodeBuilder {
instructions.add( arrayInst );
SyntheticFunctionName name = arrayInst.createNonGcFunction( useGC );
if( name != null ) {
functions.markAsNeeded( name );
functions.markAsNeeded( name, !name.istStatic() );
functions.markAsImport( name, name.getAnnotation() );
}
}
@ -809,7 +808,7 @@ public abstract class WasmCodeBuilder {
*/
protected void addMultiNewArrayInstruction( int dim, ArrayType type, int javaCodePos, int lineNumber ) {
MultiArrayFunctionName name = new MultiArrayFunctionName( dim, type );
addCallInstruction( name, javaCodePos, lineNumber );
addCallInstruction( name, false, javaCodePos, lineNumber );
}
/**
@ -846,7 +845,7 @@ public abstract class WasmCodeBuilder {
if( !options.useGC() ) {
SyntheticFunctionName name = structInst.createNonGcFunction();
if( name != null ) {
functions.markAsNeeded( name );
functions.markAsNeeded( name, !name.istStatic() );
functions.markAsImport( name, name.getAnnotation() );
}
}
@ -881,7 +880,7 @@ public abstract class WasmCodeBuilder {
} while( true );
StructType interfaceType = (StructType)parser.next();
LambdaType type = types.lambdaType( method, params, interfaceType, interfaceMethodName );
functions.markAsNeeded( type.getLambdaMethod() );
functions.markAsNeeded( type.getLambdaMethod(), true );
String lambdaTypeName = type.getName();
// Create the instance of the synthetic lambda class and save the parameters in fields

View File

@ -126,7 +126,7 @@ public class WasmOptions {
if( get_i32 == null ) {
SyntheticFunctionName name;
get_i32 = name = new JavaScriptSyntheticFunctionName( "NonGC", "get_i32", () -> "(a,i) => a[i]", ValueType.externref, ValueType.i32, null, ValueType.i32 );
functions.markAsNeeded( name );
functions.markAsNeeded( name, !name.istStatic() );
functions.markAsImport( name, name.getAnnotation() );
}
}
@ -142,7 +142,7 @@ public class WasmOptions {
FunctionName name = callVirtual;
if( name == null ) {
callVirtual = name = types.createCallVirtual();
functions.markAsNeeded( name );
functions.markAsNeeded( name, false );
registerGet_i32();
}
return name;
@ -159,7 +159,7 @@ public class WasmOptions {
FunctionName name = callInterface;
if( name == null ) {
callInterface = name = types.createCallInterface();
functions.markAsNeeded( name );
functions.markAsNeeded( name, false );
registerGet_i32();
}
return name;
@ -176,7 +176,7 @@ public class WasmOptions {
SyntheticFunctionName name = instanceOf;
if( name == null ) {
instanceOf = name = types.createInstanceOf();
functions.markAsNeeded( name );
functions.markAsNeeded( name, !name.istStatic() );
registerGet_i32();
}
return name;
@ -193,7 +193,7 @@ public class WasmOptions {
SyntheticFunctionName name = cast;
if( name == null ) {
cast = name = types.createCast();
functions.markAsNeeded( name );
functions.markAsNeeded( name, !name.istStatic() );
getInstanceOf();
}
return name;

View File

@ -234,7 +234,7 @@ public class WatParser extends WasmCodeBuilder {
} while ( !")".equals( str ) );
builder.append( get( tokens, ++i ) );
FunctionName name = new FunctionName( builder.substring( 1 ) );
addCallInstruction( name, javaCodePos, lineNumber );
addCallInstruction( name, false, javaCodePos, lineNumber );
} catch( Exception ex ) {
throw WasmException.create( "The syntax for a function name is $package.ClassName.methodName(paramSignature)returnSignature", ex );
}