From c2c1d78f13664e23a74794fd7e68bd8f2801e193 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Sun, 24 Sep 2023 20:15:44 +0200 Subject: [PATCH] wasm: fix issue in exception handling transformer --- .../org/teavm/backend/wasm/WasmTarget.java | 17 ++++++++++ ...ceptionHandlingShadowStackContributor.java | 33 ++++++++++++------- .../lowlevel/ShadowStackTransformer.java | 3 +- 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java b/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java index 52cdcbcc4..a12abbbd3 100644 --- a/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java +++ b/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java @@ -163,6 +163,7 @@ import org.teavm.model.transformation.BoundCheckInsertion; import org.teavm.model.transformation.ClassPatch; import org.teavm.model.transformation.NullCheckInsertion; import org.teavm.model.util.AsyncMethodFinder; +import org.teavm.model.util.TransitionExtractor; import org.teavm.runtime.Allocator; import org.teavm.runtime.EventQueue; import org.teavm.runtime.ExceptionHandling; @@ -440,9 +441,25 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost { .apply(program, method.getReference()); checkTransformation.apply(program, method.getResultType()); shadowStackTransformer.apply(program, method); + checkPhis(program, method); writeBarrierInsertion.apply(program); } + private void checkPhis(Program program, MethodReader method) { + var transitionExtractor = new TransitionExtractor(); + for (var block : program.getBasicBlocks()) { + for (var phi : block.getPhis()) { + for (var incoming : phi.getIncomings()) { + incoming.getSource().getLastInstruction().acceptVisitor(transitionExtractor); + if (!Arrays.asList(transitionExtractor.getTargets()).contains(block)) { + throw new RuntimeException("Method " + method.getReference() + ", block " + + block.getIndex() + ", from " + incoming.getSource().getIndex()); + } + } + } + } + } + @Override public void emit(ListableClassHolderSource classes, BuildTarget buildTarget, String outputName) throws IOException { diff --git a/core/src/main/java/org/teavm/model/lowlevel/ExceptionHandlingShadowStackContributor.java b/core/src/main/java/org/teavm/model/lowlevel/ExceptionHandlingShadowStackContributor.java index 57760a9e4..0685a0539 100644 --- a/core/src/main/java/org/teavm/model/lowlevel/ExceptionHandlingShadowStackContributor.java +++ b/core/src/main/java/org/teavm/model/lowlevel/ExceptionHandlingShadowStackContributor.java @@ -17,7 +17,6 @@ package org.teavm.model.lowlevel; import com.carrotsearch.hppc.IntHashSet; import com.carrotsearch.hppc.IntObjectHashMap; -import com.carrotsearch.hppc.IntObjectMap; import com.carrotsearch.hppc.IntSet; import java.util.ArrayList; import java.util.Arrays; @@ -151,16 +150,16 @@ public class ExceptionHandlingShadowStackContributor { private int contributeToBasicBlock(BasicBlock block) { int[] currentJointSources = new int[program.variableCount()]; - IntObjectMap jointReceiverMaps = new IntObjectHashMap<>(); + var jointReceiverMaps = new IntObjectHashMap(); Arrays.fill(currentJointSources, -1); IntSet variablesDefinedHere = new IntHashSet(); - for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { + for (var tryCatch : block.getTryCatchBlocks()) { int[] jointReceiverMap = new int[program.variableCount()]; Arrays.fill(jointReceiverMap, -1); for (Phi phi : tryCatch.getHandler().getPhis()) { - List sourceVariables = phi.getIncomings().stream() + var sourceVariables = phi.getIncomings().stream() .filter(incoming -> incoming.getSource() == tryCatch.getProtectedBlock()) .map(incoming -> incoming.getValue()) .collect(Collectors.toList()); @@ -198,7 +197,7 @@ public class ExceptionHandlingShadowStackContributor { variablesDefinedHere.add(definedVar.getIndex()); } - DefinitionExtractor defExtractor = new DefinitionExtractor(); + var defExtractor = new DefinitionExtractor(); List blocksToClearHandlers = new ArrayList<>(); blocksToClearHandlers.add(block); BasicBlock initialBlock = block; @@ -252,11 +251,11 @@ public class ExceptionHandlingShadowStackContributor { } } - CallSiteLocation[] locations = CallSiteLocation.fromTextLocation(insn.getLocation(), method); - CallSiteDescriptor callSite = new CallSiteDescriptor(callSiteIdGen++, locations); + var locations = CallSiteLocation.fromTextLocation(insn.getLocation(), method); + var callSite = new CallSiteDescriptor(callSiteIdGen++, locations); callSites.add(callSite); - List pre = setLocation(getInstructionsBeforeCallSite(callSite), insn.getLocation()); - List post = getInstructionsAfterCallSite(initialBlock, block, next, callSite, + var pre = setLocation(getInstructionsBeforeCallSite(callSite), insn.getLocation()); + var post = getInstructionsAfterCallSite(initialBlock, block, next, callSite, currentJointSources, variablesDefinedHere); post = setLocation(post, insn.getLocation()); block.getLastInstruction().insertPreviousAll(pre); @@ -271,7 +270,7 @@ public class ExceptionHandlingShadowStackContributor { } } - fixOutgoingPhis(initialBlock, block, currentJointSources, variablesDefinedHere); + removeOutgoingPhis(block); for (BasicBlock blockToClear : blocksToClearHandlers) { blockToClear.getTryCatchBlocks().clear(); } @@ -422,7 +421,7 @@ public class ExceptionHandlingShadowStackContributor { List additionalIncomings = new ArrayList<>(); for (int i = 0; i < phi.getIncomings().size(); i++) { Incoming incoming = phi.getIncomings().get(i); - if (incoming.getSource() != block || incoming.getSource() == newBlock) { + if (incoming.getSource() != block) { continue; } if (incoming.getValue().getIndex() == value) { @@ -442,6 +441,18 @@ public class ExceptionHandlingShadowStackContributor { } } + private void removeOutgoingPhis(BasicBlock block) { + for (var tryCatch : block.getTryCatchBlocks()) { + for (var iterator = tryCatch.getHandler().getPhis().iterator(); iterator.hasNext();) { + var phi = iterator.next(); + phi.getIncomings().removeIf(incoming -> incoming.getSource() == block); + if (phi.getIncomings().isEmpty()) { + iterator.remove(); + } + } + } + } + private BasicBlock getDefaultExceptionHandler() { if (defaultExceptionHandler == null) { defaultExceptionHandler = program.createBasicBlock(); diff --git a/core/src/main/java/org/teavm/model/lowlevel/ShadowStackTransformer.java b/core/src/main/java/org/teavm/model/lowlevel/ShadowStackTransformer.java index 6baa4b4cc..0d8897178 100644 --- a/core/src/main/java/org/teavm/model/lowlevel/ShadowStackTransformer.java +++ b/core/src/main/java/org/teavm/model/lowlevel/ShadowStackTransformer.java @@ -55,8 +55,7 @@ public class ShadowStackTransformer { boolean exceptions; if (exceptionHandling) { List callSites = new ArrayList<>(); - ExceptionHandlingShadowStackContributor exceptionContributor = - new ExceptionHandlingShadowStackContributor(characteristics, callSites, + var exceptionContributor = new ExceptionHandlingShadowStackContributor(characteristics, callSites, method.getReference(), program); exceptionContributor.callSiteIdGen = callSiteIdGen; exceptions = exceptionContributor.contribute();