use synthetic method for dup instruction to handle the type dynamically

This commit is contained in:
Volker Berlin 2019-01-20 10:41:33 +01:00
parent 238a281757
commit 29911bc586
5 changed files with 131 additions and 69 deletions

View File

@ -274,25 +274,9 @@ class JavaMethodWasmCodeBuilder extends WasmCodeBuilder {
break;
case 89: // dup: duplicate the value on top of the stack
case 92: // dup2
switch( findPreviousPushInstructionPushValueType() ) {
case i32:
addCallInstruction( new SyntheticMember( "de/inetsoftware/jwebassembly/module/NativeHelperCode", "dup_i32", "(I)II" ), codePos );
break OP;
case f32:
addCallInstruction( new SyntheticMember( "de/inetsoftware/jwebassembly/module/NativeHelperCode", "dup_f32", "(F)FF" ), codePos );
break OP;
case i64:
addCallInstruction( new SyntheticMember( "de/inetsoftware/jwebassembly/module/NativeHelperCode", "dup_i64", "(J)JJ" ), codePos );
break OP;
case f64:
addCallInstruction( new SyntheticMember( "de/inetsoftware/jwebassembly/module/NativeHelperCode", "dup_f64", "(D)DD" ), codePos );
break OP;
case anyref:
addCallInstruction( new SyntheticMember( "de/inetsoftware/jwebassembly/module/NativeHelperCode", "dup_anyref", "(Ljava.lang.Object;)Ljava.lang.Object;Ljava.lang.Object;" ), codePos );
break OP;
default:
}
//$FALL-THROUGH$
storeType = findPreviousPushInstructionPushValueType();
addCallInstruction( new SyntheticFunctionName( "dup" + storeType, "get_local 0 get_local 0 return", storeType, null, storeType, storeType ), codePos );
break;
case 90: // dup_x1
case 91: // dup_x2
case 93: // dup2_x1
@ -576,7 +560,7 @@ class JavaMethodWasmCodeBuilder extends WasmCodeBuilder {
case 184: // invokestatic
idx = byteCode.readUnsignedShort();
ref = (ConstantRef)constantPool.get( idx );
addCallInstruction( ref, codePos );
addCallInstruction( new FunctionName( ref ), codePos );
break;
//TODO case 185: // invokeinterface
//TODO case 186: // invokedynamic

View File

@ -110,29 +110,35 @@ public class ModuleGenerator {
while( (next = functions.nextWriteLater()) != null ) {
InputStream stream = libraries.getResourceAsStream( next.className + ".class" );
if( stream == null ) {
throw new WasmException( "Missing function: " + next.signatureName, -1 );
}
ClassFile classFile = new ClassFile( stream );
iterateMethods( classFile, method -> {
try {
FunctionName name;
Map<String, Object> wat = method.getAnnotation( JWebAssembly.TEXTCODE_ANNOTATION );
if( wat != null ) {
String signature = (String)wat.get( "signature" );
if( signature == null ) {
signature = method.getType();
}
name = new FunctionName( method, signature );
} else {
name = new FunctionName( method );
}
if( functions.isToWrite( name ) ) {
writeMethod( method );
}
} catch (IOException ioex){
throw WasmException.create( ioex, sourceFile, className, -1 );
if( next instanceof SyntheticFunctionName ) {
watParser.parse( ((SyntheticFunctionName)next).getCode(), -1 );
writeMethodImpl( next, true, null, watParser );
} else {
throw new WasmException( "Missing function: " + next.signatureName, -1 );
}
} );
} else {
ClassFile classFile = new ClassFile( stream );
iterateMethods( classFile, method -> {
try {
FunctionName name;
Map<String, Object> wat = method.getAnnotation( JWebAssembly.TEXTCODE_ANNOTATION );
if( wat != null ) {
String signature = (String)wat.get( "signature" );
if( signature == null ) {
signature = method.getType();
}
name = new FunctionName( method, signature );
} else {
name = new FunctionName( method );
}
if( functions.isToWrite( name ) ) {
writeMethod( method );
}
} catch (IOException ioex){
throw WasmException.create( ioex, sourceFile, className, -1 );
}
} );
}
if( functions.isToWrite( next ) ) {
throw new WasmException( "Missing function: " + next.signatureName, -1 );
@ -268,6 +274,7 @@ public class ModuleGenerator {
}
WasmCodeBuilder codeBuilder;
Code code = method.getCode();
LocalVariableTable localVariableTable;
FunctionName name;
if( method.getAnnotation( JWebAssembly.TEXTCODE_ANNOTATION ) != null ) {
Map<String, Object> wat = method.getAnnotation( JWebAssembly.TEXTCODE_ANNOTATION );
@ -279,38 +286,43 @@ public class ModuleGenerator {
name = new FunctionName( method, signature );
watParser.parse( watCode, code == null ? -1 : code.getFirstLineNr() );
codeBuilder = watParser;
localVariableTable = null;
} else if( code != null ) { // abstract methods and interface methods does not have code
name = new FunctionName( method );
javaCodeBuilder.buildCode( code, !method.getType().endsWith( ")V" ) );
codeBuilder = javaCodeBuilder;
localVariableTable = code.getLocalVariableTable();
} else {
return;
}
writeExport( name, method );
writer.writeMethodStart( name );
functions.writeFunction( name );
LocalVariableTable localVariableTable = code == null ? null : code.getLocalVariableTable();
writeMethodSignature( name, method.isStatic(), localVariableTable, codeBuilder );
for( WasmInstruction instruction : codeBuilder.getInstructions() ) {
switch( instruction.getType() ) {
case Call:
functions.functionCall( ((WasmCallInstruction)instruction).getFunctionName() );
break;
case Struct:
setStructType( (WasmStructInstruction)instruction );
break;
default:
}
instruction.writeTo( writer );
}
writer.writeMethodFinish();
writeMethodImpl( name, method.isStatic(), localVariableTable, codeBuilder );
} catch( Exception ioex ) {
int lineNumber = byteCode == null ? -1 : byteCode.getLineNumber();
throw WasmException.create( ioex, sourceFile, className, lineNumber );
}
}
private void writeMethodImpl( FunctionName name, boolean isStatic, LocalVariableTable localVariableTable, WasmCodeBuilder codeBuilder ) throws WasmException, IOException {
writer.writeMethodStart( name );
functions.writeFunction( name );
writeMethodSignature( name, isStatic, localVariableTable, codeBuilder );
for( WasmInstruction instruction : codeBuilder.getInstructions() ) {
switch( instruction.getType() ) {
case Call:
functions.functionCall( ((WasmCallInstruction)instruction).getFunctionName() );
break;
case Struct:
setStructType( (WasmStructInstruction)instruction );
break;
default:
}
instruction.writeTo( writer );
}
writer.writeMethodFinish();
}
/**
* Look for a Export annotation and if there write an export directive.
*

View File

@ -0,0 +1,67 @@
/*
Copyright 2019 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;
import java.util.Arrays;
import java.util.Iterator;
import de.inetsoftware.jwebassembly.wasm.AnyType;
/**
* Synthetic/dynamic method.
*
* @author Volker Berlin
*/
public class SyntheticFunctionName extends FunctionName {
private final AnyType[] signature;
private final String code;
/**
* Create a new instance.
*
* @param name
* the function name
* @param code
* the WAT code (WASM in text form)
* @param signature
* the method signature
*/
public SyntheticFunctionName( String name, String code, AnyType... signature ) {
super( "", name, "()V" ); //TODO better signature name
this.signature = signature;
this.code = code;
}
/**
* {@inheritDoc}
*/
@Override
public Iterator<AnyType> getSignature() {
return Arrays.asList( signature ).iterator();
}
/**
* Get the WAT code (WASM in text form)
*
* @return the code
*/
public String getCode() {
return code;
}
}

View File

@ -21,7 +21,6 @@ import java.util.Iterator;
import javax.annotation.Nonnull;
import de.inetsoftware.classparser.Member;
import de.inetsoftware.jwebassembly.wasm.AnyType;
import de.inetsoftware.jwebassembly.wasm.ValueType;
@ -42,14 +41,14 @@ class WasmCallInstruction extends WasmInstruction {
/**
* Create an instance of a function call instruction
*
* @param method
* the reference to the Java method
* @param name
* the function name that should be called
* @param javaCodePos
* the code position/offset in the Java method
*/
WasmCallInstruction( Member method, int javaCodePos ) {
WasmCallInstruction( FunctionName name, int javaCodePos ) {
super( javaCodePos );
this.name = new FunctionName( method );
this.name = name;
}
/**

View File

@ -178,13 +178,13 @@ public abstract class WasmCodeBuilder {
/**
* Add a static function call.
*
* @param method
* reference to a static method
* @param name
* the function name that should be called
* @param javaCodePos
* the code position/offset in the Java method
*/
protected void addCallInstruction( Member method, int javaCodePos ) {
instructions.add( new WasmCallInstruction( method, javaCodePos ) );
protected void addCallInstruction( FunctionName name, int javaCodePos ) {
instructions.add( new WasmCallInstruction( name, javaCodePos ) );
}
/**