next step in handling virtual methods

This commit is contained in:
Volker Berlin 2019-05-14 21:47:49 +02:00
parent 45d1731126
commit 983d78de54
6 changed files with 65 additions and 54 deletions

View File

@ -19,6 +19,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Stream;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -199,6 +200,18 @@ public class FunctionManager {
return newMethod != null ? newMethod : method;
}
/**
* Get all function names for the class.
*
* @param className
* the className
* @return a stream with the names
*/
Stream<FunctionName> getNamesOfClass( String className ) {
return states.keySet().stream().filter( ( name ) -> name.className.equals( className ) );
}
/**
* State of a function/method
*/

View File

@ -576,6 +576,10 @@ class JavaMethodWasmCodeBuilder extends WasmCodeBuilder {
addStructInstruction( StructOperator.SET, ref.getClassName(), new NamedStorageType( ref, getTypeManager() ), codePos, lineNumber );
break;
case 182: // invokevirtual
idx = byteCode.readUnsignedShort();
ref = (ConstantRef)constantPool.get( idx );
addCallVirtualInstruction( new FunctionName( ref ), codePos, lineNumber );
break;
case 183: // invokespecial, invoke a constructor
case 184: // invokestatic
idx = byteCode.readUnsignedShort();

View File

@ -23,6 +23,7 @@ import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@ -213,6 +214,7 @@ public class ModuleGenerator {
for( WasmInstruction instruction : instructions ) {
switch( instruction.getType() ) {
case Call:
case CallIndirect:
((WasmCallInstruction)instruction).markAsNeeded( functions );
break;
default:
@ -314,13 +316,23 @@ public class ModuleGenerator {
listStructFields( superClassName, list );
}
FieldInfo[] fields = classFile.getFields();
for( FieldInfo field : fields ) {
for( FieldInfo field : classFile.getFields() ) {
if( field.isStatic() ) {
continue;
}
list.add( new NamedStorageType( className, field, types ) );
}
HashMap<String,Boolean> virtualFunctions = new HashMap<>();
functions.getNamesOfClass( className ).forEach( (name) -> {
String methodName = name.methodName;
Boolean virtual = virtualFunctions.get( methodName );
if( virtual == null ) {
virtualFunctions.put( methodName, Boolean.FALSE );
} else {
virtualFunctions.put( methodName, Boolean.TRUE );
}
} );
}
/**
@ -491,6 +503,7 @@ public class ModuleGenerator {
}
break;
case Call:
case CallIndirect:
((WasmCallInstruction)instruction).markAsNeeded( functions );
break;
case Struct:

View File

@ -17,25 +17,16 @@
package de.inetsoftware.jwebassembly.module;
import java.io.IOException;
import java.util.Iterator;
import javax.annotation.Nonnull;
import de.inetsoftware.jwebassembly.wasm.AnyType;
/**
* WasmInstruction for a function call.
*
* @author Volker Berlin
*
*/
class WasmCallIndirectInstruction extends WasmInstruction {
private AnyType valueType;
private final FunctionName name;
private int paramCount = -1;
class WasmCallIndirectInstruction extends WasmCallInstruction {
/**
* Create an instance of a function call instruction
@ -48,8 +39,7 @@ class WasmCallIndirectInstruction extends WasmInstruction {
* the line number in the Java source code
*/
WasmCallIndirectInstruction( FunctionName name, int javaCodePos, int lineNumber ) {
super( javaCodePos, lineNumber );
this.name = name;
super( name, javaCodePos, lineNumber );
}
/**
@ -60,29 +50,16 @@ class WasmCallIndirectInstruction extends WasmInstruction {
return Type.CallIndirect;
}
/**
* Get the function name that should be called
*
* @return the name
*/
@Nonnull
FunctionName getFunctionName() {
return name;
}
/**
* {@inheritDoc}
*/
@Override
public void writeTo( @Nonnull ModuleWriter writer ) throws IOException {
writer.writeFunctionCallIndirect( name );
}
/**
* {@inheritDoc}
*/
AnyType getPushValueType() {
countParams();
return valueType;
if( true ) { // TODO
super.writeTo( writer );
} else {
writer.writeFunctionCallIndirect( getFunctionName() );
}
}
/**
@ -90,26 +67,6 @@ class WasmCallIndirectInstruction extends WasmInstruction {
*/
@Override
int getPopCount() {
countParams();
return paramCount;
}
/**
* Count the parameters in the signature
*/
private void countParams() {
if( paramCount >= 0 ) {
return;
}
Iterator<AnyType> parser = name.getSignature();
paramCount = 1;
while( parser.next() != null ) {
paramCount++;
}
valueType = parser.next();
while( parser.hasNext() ) {
valueType = parser.next();
paramCount--;
}
return super.getPopCount() + 1; // this -> +1
}
}

View File

@ -60,6 +60,16 @@ class WasmCallInstruction extends WasmInstruction {
return Type.Call;
}
/**
* Get the function name that should be called
*
* @return the name
*/
@Nonnull
FunctionName getFunctionName() {
return name;
}
/**
* Mark the function as needed in the functions manager and replace the function name with a possible super name.
*

View File

@ -273,6 +273,20 @@ public abstract class WasmCodeBuilder {
instructions.add( new WasmCallInstruction( name, javaCodePos, lineNumber ) );
}
/**
* Add a virtual/method function call.
*
* @param name
* the function name that should be called
* @param javaCodePos
* the code position/offset in the Java method
* @param lineNumber
* the line number in the Java source code
*/
protected void addCallVirtualInstruction( FunctionName name, int javaCodePos, int lineNumber ) {
instructions.add( new WasmCallIndirectInstruction( name, javaCodePos, lineNumber ) );
}
/**
* Add a block operation.
*