From 03957b09884ebabd84fff0c74d846f7970094a69 Mon Sep 17 00:00:00 2001 From: Volker Berlin Date: Thu, 26 Mar 2020 18:21:50 +0100 Subject: [PATCH] Add a placeholder for jumps instructions to better inspect the stack. --- .../jwebassembly/module/BranchManger.java | 11 ++- .../module/JavaMethodWasmCodeBuilder.java | 5 +- .../jwebassembly/module/JumpInstruction.java | 93 +++++++++++++++++++ .../jwebassembly/module/WasmCodeBuilder.java | 16 ++++ .../jwebassembly/module/WasmInstruction.java | 2 +- 5 files changed, 121 insertions(+), 6 deletions(-) create mode 100644 src/de/inetsoftware/jwebassembly/module/JumpInstruction.java diff --git a/src/de/inetsoftware/jwebassembly/module/BranchManger.java b/src/de/inetsoftware/jwebassembly/module/BranchManger.java index 9fe5580..2c1a05e 100644 --- a/src/de/inetsoftware/jwebassembly/module/BranchManger.java +++ b/src/de/inetsoftware/jwebassembly/module/BranchManger.java @@ -110,7 +110,9 @@ class BranchManger { * the compare instruction */ void addIfOperator( int startPosition, int offset, int lineNumber, WasmNumericInstruction instr ) { - allParsedOperations.add( new IfParsedBlock( startPosition, offset, lineNumber, instr ) ); + JumpInstruction jump = new JumpInstruction( startPosition + offset, 1, startPosition, lineNumber ); + instructions.add( jump ); + allParsedOperations.add( new IfParsedBlock( startPosition, offset, lineNumber, instr, jump ) ); } /** @@ -299,11 +301,13 @@ class BranchManger { * the not consumed operations in the parent branch */ private void calculateIf( BranchNode parent, IfParsedBlock startBlock, List parsedOperations ) { + instructions.remove( startBlock.jump ); IfPositions positions = searchElsePosition( startBlock, parsedOperations ); BranchNode main = parent; for( int i = 0; i < positions.ifCount; i++ ) { IfParsedBlock parsedBlock = (IfParsedBlock)parsedOperations.remove( 0 ); + instructions.remove( parsedBlock.jump ); if( startBlock.endPosition < positions.thenPos || startBlock.endPosition == positions.elsePos ) { // AND concatenation (&& operator) int pos = parsedBlock.startPosition + 1; @@ -988,6 +992,8 @@ class BranchManger { private WasmNumericInstruction instr; + private JumpInstruction jump; + /** * Create new instance * @@ -1000,9 +1006,10 @@ class BranchManger { * @param instr * the compare instruction */ - private IfParsedBlock( int startPosition, int offset, int lineNumber, WasmNumericInstruction instr ) { + private IfParsedBlock( int startPosition, int offset, int lineNumber, WasmNumericInstruction instr, JumpInstruction jump ) { super( JavaBlockOperator.IF, startPosition, offset, startPosition + 3, lineNumber ); this.instr = instr; + this.jump = jump; } /** diff --git a/src/de/inetsoftware/jwebassembly/module/JavaMethodWasmCodeBuilder.java b/src/de/inetsoftware/jwebassembly/module/JavaMethodWasmCodeBuilder.java index 28bcc95..3b2c577 100644 --- a/src/de/inetsoftware/jwebassembly/module/JavaMethodWasmCodeBuilder.java +++ b/src/de/inetsoftware/jwebassembly/module/JavaMethodWasmCodeBuilder.java @@ -521,7 +521,7 @@ class JavaMethodWasmCodeBuilder extends WasmCodeBuilder { case 167: // goto int offset = byteCode.readShort(); branchManager.addGotoOperator( codePos, offset, byteCode.getCodePosition(), lineNumber ); - addNopInstruction( codePos, lineNumber ); // marker of the line number for the branch manager + addJumpPlaceholder( codePos + offset, 0, codePos, lineNumber ); // marker of the line number for the branch manager break; case 168: // jsr case 169: // ret @@ -891,9 +891,8 @@ class JavaMethodWasmCodeBuilder extends WasmCodeBuilder { throw new WasmException( "Unexpected compare sub operation: " + nextOp, -1 ); } int offset = byteCode.readShort(); - WasmNumericInstruction compare = new WasmNumericInstruction( numOp, valueType, codePos, lineNumber ); + WasmNumericInstruction compare = addNumericInstruction( numOp, valueType, codePos, lineNumber ); branchManager.addIfOperator( codePos, offset, byteCode.getLineNumber(), compare ); - getInstructions().add( compare ); } } diff --git a/src/de/inetsoftware/jwebassembly/module/JumpInstruction.java b/src/de/inetsoftware/jwebassembly/module/JumpInstruction.java new file mode 100644 index 0000000..26889ec --- /dev/null +++ b/src/de/inetsoftware/jwebassembly/module/JumpInstruction.java @@ -0,0 +1,93 @@ +/* + Copyright 2020 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.io.IOException; + +import javax.annotation.Nonnull; + +import de.inetsoftware.jwebassembly.wasm.AnyType; + +/** + * Placeholder for a jump to inspect the stack. It is like a nop operation. + * + * @author Volker Berlin + * + */ +class JumpInstruction extends WasmInstruction { + + private int jumpPos; + + private int popCount; + + /** + * Create an instance of a nop instruction + * + * @param jumpPos + * the position of the jump + * @param popCount + * the the count of values that are removed from the stack. + * @param javaCodePos + * the code position/offset in the Java method + * @param lineNumber + * the line number in the Java source code + */ + JumpInstruction( int jumpPos, int popCount, int javaCodePos, int lineNumber ) { + super( javaCodePos, lineNumber ); + this.jumpPos = jumpPos; + this.popCount = popCount; + } + + /** + * {@inheritDoc} + */ + @Override + Type getType() { + return Type.Jump; + } + + /** + * {@inheritDoc} + */ + public void writeTo( @Nonnull ModuleWriter writer ) throws IOException { + // nothing + } + + /** + * {@inheritDoc} + */ + AnyType getPushValueType() { + return null; + } + + /** + * {@inheritDoc} + */ + @Override + int getPopCount() { + return popCount; + } + + /** + * Get the jump position + * + * @return the position + */ + int getJumpPosition() { + return jumpPos; + } +} diff --git a/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java b/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java index 9d02059..9960011 100644 --- a/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java +++ b/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java @@ -598,6 +598,22 @@ public abstract class WasmCodeBuilder { instructions.add( new WasmNopInstruction( javaCodePos, lineNumber ) ); } + /** + * Add a Jump instruction for later stack inspection + * + * @param jumpPos + * the position of the jump + * @param popCount + * the the count of values that are removed from the stack. + * @param javaCodePos + * the code position/offset in the Java method + * @param lineNumber + * the line number in the Java source code + */ + protected void addJumpPlaceholder( int jumpPos, int popCount, int javaCodePos, int lineNumber ) { + instructions.add( new JumpInstruction( jumpPos, popCount, javaCodePos, lineNumber ) ); + } + /** * Get a non GC polyfill function. * @param name the function name diff --git a/src/de/inetsoftware/jwebassembly/module/WasmInstruction.java b/src/de/inetsoftware/jwebassembly/module/WasmInstruction.java index a2886ba..e040ff4 100644 --- a/src/de/inetsoftware/jwebassembly/module/WasmInstruction.java +++ b/src/de/inetsoftware/jwebassembly/module/WasmInstruction.java @@ -35,7 +35,7 @@ abstract class WasmInstruction { * Type of instruction to faster differ as with instanceof. */ static enum Type { - Const, Convert, Local, Global, Table, Memory, Block, Numeric, Nop, Call, CallVirtual, CallInterface, Array, Struct, Dup, DupThis; + Const, Convert, Local, Global, Table, Memory, Block, Numeric, Nop, Jump, Call, CallVirtual, CallInterface, Array, Struct, Dup, DupThis; } private int javaCodePos;