Use a single CoeInputStream pro method instead chucks pro line number

This commit is contained in:
Volker Berlin 2018-06-03 11:54:45 +02:00
parent 0c83869a81
commit ecd61dcde7
3 changed files with 44 additions and 54 deletions

View File

@ -18,8 +18,6 @@ package de.inetsoftware.classparser;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import javax.annotation.Nonnull;
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
* @throws IOException
* if any I/O error occur
* @return the stream
*/
public Collection<CodeInputStream> getByteCodes() throws IOException {
ArrayList<CodeInputStream> list = new ArrayList<>();
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 CodeInputStream getByteCode() {
return new CodeInputStream( codeData, 0, codeData.length, this );
}
public int getCodeSize(){

View File

@ -18,6 +18,7 @@ package de.inetsoftware.classparser;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
/**
* Extends the DataInputStream with a code position.
@ -26,7 +27,7 @@ import java.io.DataInputStream;
*/
public class CodeInputStream extends DataInputStream {
private int lineNumber;
private Code code;
/**
* Create a new instance of CodeInputStream.
@ -37,12 +38,12 @@ public class CodeInputStream extends DataInputStream {
* the offset in the array
* @param length
* the length
* @param lineNumber
* the lineNumber in the source code or -1 if not available
* @param code
* 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.lineNumber = lineNumber;
this.code = code;
}
private CodeInputStream( ByteCodeArrayInputStream in ) {
@ -64,6 +65,22 @@ public class CodeInputStream extends DataInputStream {
* @return the line number
*/
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;
}

View File

@ -16,7 +16,6 @@
package de.inetsoftware.jwebassembly.module;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.function.Consumer;
@ -149,10 +148,9 @@ public class ModuleGenerator {
* if some Java code can't converted
*/
private void writeMethod( MethodInfo method ) throws WasmException {
int lineNumber = -1;
CodeInputStream byteCode = null;
try {
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
FunctionName name = new FunctionName( method );
writeExport( name, method );
@ -162,19 +160,14 @@ public class ModuleGenerator {
localVariables.reset();
stackManager.reset();
branchManager.reset();
for( CodeInputStream byteCode : code.getByteCodes() ) {
prepareCodeChunk( byteCode, lineNumber = byteCode.getLineNumber(), method.getConstantPool() );
}
byteCode = code.getByteCode();
prepareCodeChunk( byteCode, method.getConstantPool() );
branchManager.calculate();
localVariables.calculate();
CodeInputStream byteCode = null;
boolean endWithReturn = false;
Iterator<CodeInputStream> byteCodes = code.getByteCodes().iterator();
while( byteCodes.hasNext() ) {
byteCode = byteCodes.next();
endWithReturn = writeCodeChunk( byteCode, lineNumber = byteCode.getLineNumber(), method.getConstantPool() );
}
byteCode = code.getByteCode();
endWithReturn = writeCode( byteCode, method.getConstantPool() );
branchManager.handle( byteCode, writer ); // write the last end operators
if( !endWithReturn && returnType != null ) {
// 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:
writer.writeConstDouble( 0 );
break;
default:
}
writer.writeBlockCode( WasmBlockOperator.RETURN, null );
}
writer.writeMethodFinish( localVariables.getLocalTypes( paramCount ) );
}
} catch( Exception ioex ) {
int lineNumber = byteCode == null ? -1 : byteCode.getLineNumber();
throw WasmException.create( ioex, sourceFile, lineNumber );
}
}
@ -298,14 +293,12 @@ public class ModuleGenerator {
*
* @param byteCode
* a stream of byte code
* @param lineNumber
* the current line number
* @param constantPool
* the constant pool of the the current class
* @throws WasmException
* 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 {
while( byteCode.available() > 0 ) {
int codePosition = byteCode.getCodePosition();
@ -466,15 +459,15 @@ public class ModuleGenerator {
case 165: // if_acmpeq
case 166: // if_acmpne
int offset = byteCode.readShort();
branchManager.start( JavaBlockOperator.IF, codePosition, offset, lineNumber );
branchManager.start( JavaBlockOperator.IF, codePosition, offset, byteCode.getLineNumber() );
break;
case 167: // goto
offset = byteCode.readShort();
branchManager.start( JavaBlockOperator.GOTO, codePosition, offset, lineNumber );
branchManager.start( JavaBlockOperator.GOTO, codePosition, offset, byteCode.getLineNumber() );
break;
case 170: // tableswitch
case 171: // lookupswitch
prepareSwitchCode( byteCode, op == 171, lineNumber );
prepareSwitchCode( byteCode, op == 171, byteCode.getLineNumber() );
break;
case 184: // invokestatic
ConstantRef method = (ConstantRef)constantPool.get( byteCode.readUnsignedShort() );
@ -487,7 +480,7 @@ public class ModuleGenerator {
}
}
} 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
* a stream of byte code
* @param lineNumber
* the current line number
* @param constantPool
* the constant pool of the the current class
* @throws WasmException
* if some Java code can't converted
* @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;
try {
while( byteCode.available() > 0 ) {
@ -681,7 +672,7 @@ public class ModuleGenerator {
case 94: // dup2_x2
case 95: // swap
// 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
writer.writeNumericOperator( NumericOperator.add, ValueType.i32);
break;
@ -739,7 +730,7 @@ public class ModuleGenerator {
case 114: // frem
case 115: // drem
//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
writer.writeConstInt( -1 );
writer.writeNumericOperator( NumericOperator.mul, ValueType.i32 );
@ -922,13 +913,13 @@ public class ModuleGenerator {
writer.writeFunctionCall( method.getConstantClass().getName() + '.' + method.getName() + method.getType() );
break;
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 ) {
throw ex;
} catch( Exception ex ) {
throw WasmException.create( ex, sourceFile, lineNumber );
throw WasmException.create( ex, sourceFile, byteCode.getLineNumber() );
}
return endWithReturn;
}