mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-25 07:27:52 +01:00
Use a single CoeInputStream pro method instead chucks pro line number
This commit is contained in:
parent
0c83869a81
commit
ecd61dcde7
@ -18,8 +18,6 @@ package de.inetsoftware.classparser;
|
|||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@ -128,28 +126,12 @@ public class Code {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a list of CodeInputStream separated by source code line number.
|
* Get the stream of Java Byte code instruction of this method.
|
||||||
*
|
*
|
||||||
* @return the list
|
* @return the stream
|
||||||
* @throws IOException
|
|
||||||
* if any I/O error occur
|
|
||||||
*/
|
*/
|
||||||
public Collection<CodeInputStream> getByteCodes() throws IOException {
|
public CodeInputStream getByteCode() {
|
||||||
ArrayList<CodeInputStream> list = new ArrayList<>();
|
return new CodeInputStream( codeData, 0, codeData.length, this );
|
||||||
LineNumberTable lineNumberTable = getLineNumberTable();
|
|
||||||
if( lineNumberTable != null ) {
|
|
||||||
int lineNumber;
|
|
||||||
for( int i = 0; i < lineNumberTable.size(); i++ ) {
|
|
||||||
lineNumber = lineNumberTable.getLineNumber( i );
|
|
||||||
int offset = lineNumberTable.getStartOffset( i );
|
|
||||||
int nextOffset = i + 1 == lineNumberTable.size() ? getCodeSize()
|
|
||||||
: lineNumberTable.getStartOffset( i + 1 );
|
|
||||||
list.add( new CodeInputStream( codeData, offset, nextOffset - offset, lineNumber ) );
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
list.add( new CodeInputStream( codeData, 0, codeData.length, -1 ) );
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCodeSize(){
|
public int getCodeSize(){
|
||||||
|
@ -18,6 +18,7 @@ package de.inetsoftware.classparser;
|
|||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extends the DataInputStream with a code position.
|
* Extends the DataInputStream with a code position.
|
||||||
@ -26,7 +27,7 @@ import java.io.DataInputStream;
|
|||||||
*/
|
*/
|
||||||
public class CodeInputStream extends DataInputStream {
|
public class CodeInputStream extends DataInputStream {
|
||||||
|
|
||||||
private int lineNumber;
|
private Code code;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance of CodeInputStream.
|
* Create a new instance of CodeInputStream.
|
||||||
@ -37,12 +38,12 @@ public class CodeInputStream extends DataInputStream {
|
|||||||
* the offset in the array
|
* the offset in the array
|
||||||
* @param length
|
* @param length
|
||||||
* the length
|
* the length
|
||||||
* @param lineNumber
|
* @param code
|
||||||
* the lineNumber in the source code or -1 if not available
|
* the calling code to get the line numbers
|
||||||
*/
|
*/
|
||||||
CodeInputStream( byte[] buf, int offset, int length, int lineNumber ) {
|
CodeInputStream( byte[] buf, int offset, int length, Code code ) {
|
||||||
this( new ByteCodeArrayInputStream( buf, offset, length ) );
|
this( new ByteCodeArrayInputStream( buf, offset, length ) );
|
||||||
this.lineNumber = lineNumber;
|
this.code = code;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CodeInputStream( ByteCodeArrayInputStream in ) {
|
private CodeInputStream( ByteCodeArrayInputStream in ) {
|
||||||
@ -64,6 +65,22 @@ public class CodeInputStream extends DataInputStream {
|
|||||||
* @return the line number
|
* @return the line number
|
||||||
*/
|
*/
|
||||||
public int getLineNumber() {
|
public int getLineNumber() {
|
||||||
|
int lineNumber = -1;
|
||||||
|
try {
|
||||||
|
LineNumberTable lineNumberTable = code.getLineNumberTable();
|
||||||
|
if( lineNumberTable != null ) {
|
||||||
|
int codePos = getCodePosition();
|
||||||
|
for( int i = 0; i < lineNumberTable.size(); i++ ) {
|
||||||
|
int offset = lineNumberTable.getStartOffset( i );
|
||||||
|
if( offset > codePos ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lineNumber = lineNumberTable.getLineNumber( i );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch( IOException e ) {
|
||||||
|
// ignore, line naumber are only needed for debug information
|
||||||
|
}
|
||||||
return lineNumber;
|
return lineNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
package de.inetsoftware.jwebassembly.module;
|
package de.inetsoftware.jwebassembly.module;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
@ -149,10 +148,9 @@ public class ModuleGenerator {
|
|||||||
* if some Java code can't converted
|
* if some Java code can't converted
|
||||||
*/
|
*/
|
||||||
private void writeMethod( MethodInfo method ) throws WasmException {
|
private void writeMethod( MethodInfo method ) throws WasmException {
|
||||||
int lineNumber = -1;
|
CodeInputStream byteCode = null;
|
||||||
try {
|
try {
|
||||||
Code code = method.getCode();
|
Code code = method.getCode();
|
||||||
lineNumber = code.getFirstLineNr();
|
|
||||||
if( code != null && method.getAnnotation( "org.webassembly.annotation.Import" ) == null ) { // abstract methods and interface methods does not have code
|
if( code != null && method.getAnnotation( "org.webassembly.annotation.Import" ) == null ) { // abstract methods and interface methods does not have code
|
||||||
FunctionName name = new FunctionName( method );
|
FunctionName name = new FunctionName( method );
|
||||||
writeExport( name, method );
|
writeExport( name, method );
|
||||||
@ -162,19 +160,14 @@ public class ModuleGenerator {
|
|||||||
localVariables.reset();
|
localVariables.reset();
|
||||||
stackManager.reset();
|
stackManager.reset();
|
||||||
branchManager.reset();
|
branchManager.reset();
|
||||||
for( CodeInputStream byteCode : code.getByteCodes() ) {
|
byteCode = code.getByteCode();
|
||||||
prepareCodeChunk( byteCode, lineNumber = byteCode.getLineNumber(), method.getConstantPool() );
|
prepareCodeChunk( byteCode, method.getConstantPool() );
|
||||||
}
|
|
||||||
branchManager.calculate();
|
branchManager.calculate();
|
||||||
localVariables.calculate();
|
localVariables.calculate();
|
||||||
|
|
||||||
CodeInputStream byteCode = null;
|
|
||||||
boolean endWithReturn = false;
|
boolean endWithReturn = false;
|
||||||
Iterator<CodeInputStream> byteCodes = code.getByteCodes().iterator();
|
byteCode = code.getByteCode();
|
||||||
while( byteCodes.hasNext() ) {
|
endWithReturn = writeCode( byteCode, method.getConstantPool() );
|
||||||
byteCode = byteCodes.next();
|
|
||||||
endWithReturn = writeCodeChunk( byteCode, lineNumber = byteCode.getLineNumber(), method.getConstantPool() );
|
|
||||||
}
|
|
||||||
branchManager.handle( byteCode, writer ); // write the last end operators
|
branchManager.handle( byteCode, writer ); // write the last end operators
|
||||||
if( !endWithReturn && returnType != null ) {
|
if( !endWithReturn && returnType != null ) {
|
||||||
// if a method ends with a loop without a break then code after the loop is no reachable
|
// if a method ends with a loop without a break then code after the loop is no reachable
|
||||||
@ -193,12 +186,14 @@ public class ModuleGenerator {
|
|||||||
case f64:
|
case f64:
|
||||||
writer.writeConstDouble( 0 );
|
writer.writeConstDouble( 0 );
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
}
|
}
|
||||||
writer.writeBlockCode( WasmBlockOperator.RETURN, null );
|
writer.writeBlockCode( WasmBlockOperator.RETURN, null );
|
||||||
}
|
}
|
||||||
writer.writeMethodFinish( localVariables.getLocalTypes( paramCount ) );
|
writer.writeMethodFinish( localVariables.getLocalTypes( paramCount ) );
|
||||||
}
|
}
|
||||||
} catch( Exception ioex ) {
|
} catch( Exception ioex ) {
|
||||||
|
int lineNumber = byteCode == null ? -1 : byteCode.getLineNumber();
|
||||||
throw WasmException.create( ioex, sourceFile, lineNumber );
|
throw WasmException.create( ioex, sourceFile, lineNumber );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -298,14 +293,12 @@ public class ModuleGenerator {
|
|||||||
*
|
*
|
||||||
* @param byteCode
|
* @param byteCode
|
||||||
* a stream of byte code
|
* a stream of byte code
|
||||||
* @param lineNumber
|
|
||||||
* the current line number
|
|
||||||
* @param constantPool
|
* @param constantPool
|
||||||
* the constant pool of the the current class
|
* the constant pool of the the current class
|
||||||
* @throws WasmException
|
* @throws WasmException
|
||||||
* if some Java code can't converted
|
* if some Java code can't converted
|
||||||
*/
|
*/
|
||||||
private void prepareCodeChunk( CodeInputStream byteCode, int lineNumber, ConstantPool constantPool ) throws WasmException {
|
private void prepareCodeChunk( CodeInputStream byteCode, ConstantPool constantPool ) throws WasmException {
|
||||||
try {
|
try {
|
||||||
while( byteCode.available() > 0 ) {
|
while( byteCode.available() > 0 ) {
|
||||||
int codePosition = byteCode.getCodePosition();
|
int codePosition = byteCode.getCodePosition();
|
||||||
@ -466,15 +459,15 @@ public class ModuleGenerator {
|
|||||||
case 165: // if_acmpeq
|
case 165: // if_acmpeq
|
||||||
case 166: // if_acmpne
|
case 166: // if_acmpne
|
||||||
int offset = byteCode.readShort();
|
int offset = byteCode.readShort();
|
||||||
branchManager.start( JavaBlockOperator.IF, codePosition, offset, lineNumber );
|
branchManager.start( JavaBlockOperator.IF, codePosition, offset, byteCode.getLineNumber() );
|
||||||
break;
|
break;
|
||||||
case 167: // goto
|
case 167: // goto
|
||||||
offset = byteCode.readShort();
|
offset = byteCode.readShort();
|
||||||
branchManager.start( JavaBlockOperator.GOTO, codePosition, offset, lineNumber );
|
branchManager.start( JavaBlockOperator.GOTO, codePosition, offset, byteCode.getLineNumber() );
|
||||||
break;
|
break;
|
||||||
case 170: // tableswitch
|
case 170: // tableswitch
|
||||||
case 171: // lookupswitch
|
case 171: // lookupswitch
|
||||||
prepareSwitchCode( byteCode, op == 171, lineNumber );
|
prepareSwitchCode( byteCode, op == 171, byteCode.getLineNumber() );
|
||||||
break;
|
break;
|
||||||
case 184: // invokestatic
|
case 184: // invokestatic
|
||||||
ConstantRef method = (ConstantRef)constantPool.get( byteCode.readUnsignedShort() );
|
ConstantRef method = (ConstantRef)constantPool.get( byteCode.readUnsignedShort() );
|
||||||
@ -487,7 +480,7 @@ public class ModuleGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch( Exception ex ) {
|
} catch( Exception ex ) {
|
||||||
throw WasmException.create( ex, sourceFile, lineNumber );
|
throw WasmException.create( ex, sourceFile, byteCode.getLineNumber() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -537,19 +530,17 @@ public class ModuleGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write a chunk of byte code.
|
* Write the byte code of a method.
|
||||||
*
|
*
|
||||||
* @param byteCode
|
* @param byteCode
|
||||||
* a stream of byte code
|
* a stream of byte code
|
||||||
* @param lineNumber
|
|
||||||
* the current line number
|
|
||||||
* @param constantPool
|
* @param constantPool
|
||||||
* the constant pool of the the current class
|
* the constant pool of the the current class
|
||||||
* @throws WasmException
|
* @throws WasmException
|
||||||
* if some Java code can't converted
|
* if some Java code can't converted
|
||||||
* @return true, if the last operation was a return
|
* @return true, if the last operation was a return
|
||||||
*/
|
*/
|
||||||
private boolean writeCodeChunk( CodeInputStream byteCode, int lineNumber, ConstantPool constantPool ) throws WasmException {
|
private boolean writeCode( CodeInputStream byteCode, ConstantPool constantPool ) throws WasmException {
|
||||||
boolean endWithReturn = false;
|
boolean endWithReturn = false;
|
||||||
try {
|
try {
|
||||||
while( byteCode.available() > 0 ) {
|
while( byteCode.available() > 0 ) {
|
||||||
@ -681,7 +672,7 @@ public class ModuleGenerator {
|
|||||||
case 94: // dup2_x2
|
case 94: // dup2_x2
|
||||||
case 95: // swap
|
case 95: // swap
|
||||||
// can be do with functions with more as one return value in future WASM standard
|
// can be do with functions with more as one return value in future WASM standard
|
||||||
throw new WasmException( "Stack duplicate is not supported in current WASM. try to save immediate values in a local variable: " + op, sourceFile, lineNumber );
|
throw new WasmException( "Stack duplicate is not supported in current WASM. try to save immediate values in a local variable: " + op, sourceFile, byteCode.getLineNumber() );
|
||||||
case 96: // iadd
|
case 96: // iadd
|
||||||
writer.writeNumericOperator( NumericOperator.add, ValueType.i32);
|
writer.writeNumericOperator( NumericOperator.add, ValueType.i32);
|
||||||
break;
|
break;
|
||||||
@ -739,7 +730,7 @@ public class ModuleGenerator {
|
|||||||
case 114: // frem
|
case 114: // frem
|
||||||
case 115: // drem
|
case 115: // drem
|
||||||
//TODO can be implemented with a helper function like: (a - (long)(a / b) * (double)b)
|
//TODO can be implemented with a helper function like: (a - (long)(a / b) * (double)b)
|
||||||
throw new WasmException( "Modulo/Remainder for floating numbers is not supported in WASM. Use int or long data types." + op, sourceFile, lineNumber );
|
throw new WasmException( "Modulo/Remainder for floating numbers is not supported in WASM. Use int or long data types." + op, sourceFile, byteCode.getLineNumber() );
|
||||||
case 116: // ineg
|
case 116: // ineg
|
||||||
writer.writeConstInt( -1 );
|
writer.writeConstInt( -1 );
|
||||||
writer.writeNumericOperator( NumericOperator.mul, ValueType.i32 );
|
writer.writeNumericOperator( NumericOperator.mul, ValueType.i32 );
|
||||||
@ -922,13 +913,13 @@ public class ModuleGenerator {
|
|||||||
writer.writeFunctionCall( method.getConstantClass().getName() + '.' + method.getName() + method.getType() );
|
writer.writeFunctionCall( method.getConstantClass().getName() + '.' + method.getName() + method.getType() );
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new WasmException( "Unimplemented Java byte code operation: " + op, sourceFile, lineNumber );
|
throw new WasmException( "Unimplemented Java byte code operation: " + op, sourceFile, byteCode.getLineNumber() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch( WasmException ex ) {
|
} catch( WasmException ex ) {
|
||||||
throw ex;
|
throw ex;
|
||||||
} catch( Exception ex ) {
|
} catch( Exception ex ) {
|
||||||
throw WasmException.create( ex, sourceFile, lineNumber );
|
throw WasmException.create( ex, sourceFile, byteCode.getLineNumber() );
|
||||||
}
|
}
|
||||||
return endWithReturn;
|
return endWithReturn;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user