pass the method with signature to the VariableManager as fallback

This commit is contained in:
Volker Berlin 2019-09-23 20:33:21 +02:00
parent e3eb66efc9
commit d1bb7cac23
7 changed files with 58 additions and 23 deletions

View File

@ -25,6 +25,7 @@ import de.inetsoftware.classparser.CodeInputStream;
import de.inetsoftware.classparser.ConstantClass; import de.inetsoftware.classparser.ConstantClass;
import de.inetsoftware.classparser.ConstantPool; import de.inetsoftware.classparser.ConstantPool;
import de.inetsoftware.classparser.ConstantRef; import de.inetsoftware.classparser.ConstantRef;
import de.inetsoftware.classparser.MethodInfo;
import de.inetsoftware.jwebassembly.WasmException; import de.inetsoftware.jwebassembly.WasmException;
import de.inetsoftware.jwebassembly.wasm.AnyType; import de.inetsoftware.jwebassembly.wasm.AnyType;
import de.inetsoftware.jwebassembly.wasm.ArrayOperator; import de.inetsoftware.jwebassembly.wasm.ArrayOperator;
@ -49,18 +50,19 @@ class JavaMethodWasmCodeBuilder extends WasmCodeBuilder {
* *
* @param code * @param code
* the Java method code * the Java method code
* @param hasReturn * @param method
* true, if the method has a return value; false, if it is void * the method with signature as fallback for a missing variable table
* @throws WasmException * @throws WasmException
* if some Java code can't converted * if some Java code can't converted
*/ */
void buildCode( @Nonnull Code code, boolean hasReturn ) { void buildCode( @Nonnull Code code, MethodInfo method ) {
CodeInputStream byteCode = null; CodeInputStream byteCode = null;
try { try {
reset( code.getLocalVariableTable() ); reset( code.getLocalVariableTable(), method );
branchManager.reset( code ); branchManager.reset( code );
byteCode = code.getByteCode(); byteCode = code.getByteCode();
boolean hasReturn = !method.getType().endsWith( ")V" );
writeCode( byteCode, code.getConstantPool(), hasReturn ); writeCode( byteCode, code.getConstantPool(), hasReturn );
calculateVariables(); calculateVariables();
} catch( Exception ioex ) { } catch( Exception ioex ) {

View File

@ -19,7 +19,6 @@ package de.inetsoftware.jwebassembly.module;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -27,6 +26,7 @@ import javax.annotation.Nullable;
import de.inetsoftware.classparser.LocalVariable; import de.inetsoftware.classparser.LocalVariable;
import de.inetsoftware.classparser.LocalVariableTable; import de.inetsoftware.classparser.LocalVariableTable;
import de.inetsoftware.classparser.MethodInfo;
import de.inetsoftware.jwebassembly.WasmException; import de.inetsoftware.jwebassembly.WasmException;
import de.inetsoftware.jwebassembly.wasm.AnyType; import de.inetsoftware.jwebassembly.wasm.AnyType;
import de.inetsoftware.jwebassembly.wasm.ValueType; import de.inetsoftware.jwebassembly.wasm.ValueType;
@ -78,8 +78,10 @@ class LocaleVariableManager {
* *
* @param variableTable * @param variableTable
* variable table of the Java method. * variable table of the Java method.
* @param method
* the method with signature as fallback for a missing variable table
*/ */
void reset( LocalVariableTable variableTable ) { void reset( LocalVariableTable variableTable, MethodInfo method ) {
size = 0; size = 0;
if( variableTable == null ) { if( variableTable == null ) {
@ -150,8 +152,24 @@ class LocaleVariableManager {
var.name = findUniqueVarName( var.name ); var.name = findUniqueVarName( var.name );
} }
// add all missing slots that we can add self temporary variables
int maxLocals = variableTable.getMaxLocals(); int maxLocals = variableTable.getMaxLocals();
// add missing slots from signature
if( maxLocals > 0 && vars.length == 0 && method != null ) {
ValueTypeParser parser = new ValueTypeParser( method.getType(), types );
if( !method.isStatic() ) {
resetAddVar( ValueType.anyref );
}
while( size < maxLocals ) {
AnyType type = parser.next();
if( type == null ) {
break;
}
resetAddVar( type );
}
}
// add all missing slots that we can add self temporary variables
NEXT: for( int i = 0; i < maxLocals; i++ ) { NEXT: for( int i = 0; i < maxLocals; i++ ) {
for( int j = 0; j < size; j++ ) { for( int j = 0; j < size; j++ ) {
Variable var = variables[j]; Variable var = variables[j];
@ -159,16 +177,26 @@ class LocaleVariableManager {
continue NEXT; continue NEXT;
} }
} }
resetAddVar( null );
}
}
/**
* Add a variable in the reset with range.
*
* @param type
* the type of the variable
*/
private void resetAddVar( AnyType type ) {
ensureCapacity( size + 1 ); ensureCapacity( size + 1 );
Variable var = variables[size]; Variable var = variables[size];
var.valueType = null; var.valueType = type;
var.name = null; var.name = null;
var.idx = i; var.idx = size;
var.startPos = 0; var.startPos = 0;
var.endPos = Integer.MAX_VALUE; var.endPos = Integer.MAX_VALUE;
size++; size++;
} }
}
/** /**
* Find a unique variable name. * Find a unique variable name.

View File

@ -436,10 +436,10 @@ public class ModuleGenerator {
if( signature == null ) { if( signature == null ) {
signature = method.getType(); signature = method.getType();
} }
watParser.parse( watCode, code == null ? -1 : code.getFirstLineNr() ); watParser.parse( watCode, method, code == null ? -1 : code.getFirstLineNr() );
return watParser; return watParser;
} else if( code != null ) { // abstract methods and interface methods does not have code } else if( code != null ) { // abstract methods and interface methods does not have code
javaCodeBuilder.buildCode( code, !method.getType().endsWith( ")V" ) ); javaCodeBuilder.buildCode( code, method );
return javaCodeBuilder; return javaCodeBuilder;
} else { } else {
throw new WasmException( "Abstract or native method can not be used: " + new FunctionName( method ).signatureName, -1 ); throw new WasmException( "Abstract or native method can not be used: " + new FunctionName( method ).signatureName, -1 );

View File

@ -147,10 +147,12 @@ public abstract class WasmCodeBuilder {
* *
* @param variableTable * @param variableTable
* variable table of the Java method. * variable table of the Java method.
* @param method
* the method with signature as fallback for a missing variable table
*/ */
protected void reset( LocalVariableTable variableTable ) { protected void reset( LocalVariableTable variableTable, MethodInfo method ) {
instructions.clear(); instructions.clear();
localVariables.reset( variableTable ); localVariables.reset( variableTable, method );
} }
/** /**

View File

@ -56,7 +56,7 @@ class WatCodeSyntheticFunctionName extends SyntheticFunctionName {
*/ */
@Override @Override
protected WasmCodeBuilder getCodeBuilder( WatParser watParser ) { protected WasmCodeBuilder getCodeBuilder( WatParser watParser ) {
watParser.parse( code, -1 ); watParser.parse( code, null, -1 );
return watParser; return watParser;
} }
} }

View File

@ -23,6 +23,7 @@ import javax.annotation.Nonnegative;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import de.inetsoftware.classparser.MethodInfo;
import de.inetsoftware.jwebassembly.WasmException; import de.inetsoftware.jwebassembly.WasmException;
import de.inetsoftware.jwebassembly.module.ValueTypeConvertion; import de.inetsoftware.jwebassembly.module.ValueTypeConvertion;
import de.inetsoftware.jwebassembly.module.WasmCodeBuilder; import de.inetsoftware.jwebassembly.module.WasmCodeBuilder;
@ -44,10 +45,12 @@ public class WatParser extends WasmCodeBuilder {
* the text format content of a function * the text format content of a function
* @param lineNumber * @param lineNumber
* the line number for an error message * the line number for an error message
* @param method
* the method with signature as fallback for a missing variable table
*/ */
public void parse( String wat, int lineNumber ) { public void parse( String wat, MethodInfo method, int lineNumber ) {
try { try {
reset( null ); reset( null, method );
List<String> tokens = splitTokens( wat ); List<String> tokens = splitTokens( wat );
for( int i = 0; i < tokens.size(); i++ ) { for( int i = 0; i < tokens.size(); i++ ) {

View File

@ -41,7 +41,7 @@ public class WatParserTest {
WatParser parser = new WatParser(); WatParser parser = new WatParser();
WasmCodeBuilder codeBuilder = parser; WasmCodeBuilder codeBuilder = parser;
codeBuilder.init( null, null, options ); codeBuilder.init( null, null, options );
parser.parse( wat, 100 ); parser.parse( wat, null, 100 );
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
ModuleWriter writer = new TextModuleWriter( new WasmTarget( builder ), options ); ModuleWriter writer = new TextModuleWriter( new WasmTarget( builder ), options );
writer.writeMethodStart( new FunctionName( "A.a()V" ), null ); writer.writeMethodStart( new FunctionName( "A.a()V" ), null );