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

View File

@ -19,7 +19,6 @@ package de.inetsoftware.jwebassembly.module;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@ -27,6 +26,7 @@ import javax.annotation.Nullable;
import de.inetsoftware.classparser.LocalVariable;
import de.inetsoftware.classparser.LocalVariableTable;
import de.inetsoftware.classparser.MethodInfo;
import de.inetsoftware.jwebassembly.WasmException;
import de.inetsoftware.jwebassembly.wasm.AnyType;
import de.inetsoftware.jwebassembly.wasm.ValueType;
@ -78,8 +78,10 @@ class LocaleVariableManager {
*
* @param variableTable
* 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;
if( variableTable == null ) {
@ -150,8 +152,24 @@ class LocaleVariableManager {
var.name = findUniqueVarName( var.name );
}
// add all missing slots that we can add self temporary variables
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++ ) {
for( int j = 0; j < size; j++ ) {
Variable var = variables[j];
@ -159,17 +177,27 @@ class LocaleVariableManager {
continue NEXT;
}
}
ensureCapacity( size + 1 );
Variable var = variables[size];
var.valueType = null;
var.name = null;
var.idx = i;
var.startPos = 0;
var.endPos = Integer.MAX_VALUE;
size++;
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 );
Variable var = variables[size];
var.valueType = type;
var.name = null;
var.idx = size;
var.startPos = 0;
var.endPos = Integer.MAX_VALUE;
size++;
}
/**
* Find a unique variable name.
*

View File

@ -436,10 +436,10 @@ public class ModuleGenerator {
if( signature == null ) {
signature = method.getType();
}
watParser.parse( watCode, code == null ? -1 : code.getFirstLineNr() );
watParser.parse( watCode, method, code == null ? -1 : code.getFirstLineNr() );
return watParser;
} 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;
} else {
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
* 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();
localVariables.reset( variableTable );
localVariables.reset( variableTable, method );
}
/**

View File

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

View File

@ -23,6 +23,7 @@ import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import de.inetsoftware.classparser.MethodInfo;
import de.inetsoftware.jwebassembly.WasmException;
import de.inetsoftware.jwebassembly.module.ValueTypeConvertion;
import de.inetsoftware.jwebassembly.module.WasmCodeBuilder;
@ -44,10 +45,12 @@ public class WatParser extends WasmCodeBuilder {
* the text format content of a function
* @param lineNumber
* 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 {
reset( null );
reset( null, method );
List<String> tokens = splitTokens( wat );
for( int i = 0; i < tokens.size(); i++ ) {

View File

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