From ec898cad71d0b0c7b82d53f73e25f6c326304a8c Mon Sep 17 00:00:00 2001 From: Volker Berlin Date: Sun, 29 Sep 2019 13:47:45 +0200 Subject: [PATCH] skip ELSE blocks on counting the stack --- .../jwebassembly/module/BranchManger.java | 56 +++++++++++++++++-- 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/src/de/inetsoftware/jwebassembly/module/BranchManger.java b/src/de/inetsoftware/jwebassembly/module/BranchManger.java index 3a40aab..9a5bf90 100644 --- a/src/de/inetsoftware/jwebassembly/module/BranchManger.java +++ b/src/de/inetsoftware/jwebassembly/module/BranchManger.java @@ -1054,18 +1054,13 @@ class BranchManger { if( startBlock != null && startBlock.getOperation() == WasmBlockOperator.IF ) { ArrayDeque stack = new ArrayDeque<>(); stack.push( ValueType.empty ); + INSTRUCTIONS: for( int i = startIdx; i < instructions.size(); i++ ) { WasmInstruction instr = instructions.get( i ); int codePos = instr.getCodePosition(); if( codePos >= endPos ) { break; } - if( instr.getType() == Type.Block && ((WasmBlockInstruction)instr).getOperation() == WasmBlockOperator.RETURN ) { - while( stack.size() > 1 ) { - stack.pop(); - } - break; - } int popCount = instr.getPopCount(); for( int p = 0; p < popCount; p++ ) { stack.pop(); @@ -1074,10 +1069,59 @@ class BranchManger { if( pushValue != null ) { stack.push( pushValue ); } + + if( instr.getType() == Type.Block ) { + switch( ((WasmBlockInstruction)instr).getOperation() ) { + case RETURN: + // set "empty" block type + while( stack.size() > 1 ) { + stack.pop(); + } + break INSTRUCTIONS; + case IF: + case BLOCK: + case LOOP: + // skip the content of the block, important to not count ELSE blocks + i = findEndInstruction( instructions, i ); + break; + } + } } startBlock.setData( stack.pop() ); } } + + /** + * Find the END instruction of the block. + * + * @param instructions + * the list of instructions + * @param idx + * the index of the block start + * @return the END index + */ + private int findEndInstruction( List instructions, int idx ) { + int count = 0; + for( ; idx < instructions.size(); idx++ ) { + WasmInstruction instr = instructions.get( idx ); + if( instr.getType() == Type.Block ) { + switch( ((WasmBlockInstruction)instr).getOperation() ) { + case IF: + case BLOCK: + case LOOP: + count++; + break; + case END: + count--; + break; + } + } + if( count == 0 ) { + break; + } + } + return idx; + } } /**