WASM: refactoring shadow stack

This commit is contained in:
Alexey Andreev 2016-09-22 19:02:53 +03:00
parent b67d243ad4
commit 4e431e2f77
12 changed files with 128 additions and 123 deletions

View File

@ -250,11 +250,11 @@ public final class WasmRuntime {
return result; return result;
} }
public static Address getStackGcRoots() { public static Address getStackTop() {
return stack != initStack() ? stack : null; return stack != initStack() ? stack : null;
} }
public static Address getNextStackRoots(Address address) { public static Address getNextStackFrame(Address address) {
int size = address.getInt() + 2; int size = address.getInt() + 2;
Address result = address.add(-size * 4); Address result = address.add(-size * 4);
if (result == initStack()) { if (result == initStack()) {

View File

@ -38,12 +38,13 @@ import org.teavm.backend.wasm.generate.WasmStringPool;
import org.teavm.backend.wasm.intrinsics.AddressIntrinsic; import org.teavm.backend.wasm.intrinsics.AddressIntrinsic;
import org.teavm.backend.wasm.intrinsics.AllocatorIntrinsic; import org.teavm.backend.wasm.intrinsics.AllocatorIntrinsic;
import org.teavm.backend.wasm.intrinsics.ClassIntrinsic; import org.teavm.backend.wasm.intrinsics.ClassIntrinsic;
import org.teavm.backend.wasm.intrinsics.ExceptionHandlingIntrinsic;
import org.teavm.backend.wasm.intrinsics.FunctionIntrinsic; import org.teavm.backend.wasm.intrinsics.FunctionIntrinsic;
import org.teavm.backend.wasm.intrinsics.GCIntrinsic; import org.teavm.backend.wasm.intrinsics.GCIntrinsic;
import org.teavm.backend.wasm.intrinsics.MutatorIntrinsic;
import org.teavm.backend.wasm.intrinsics.PlatformClassIntrinsic; import org.teavm.backend.wasm.intrinsics.PlatformClassIntrinsic;
import org.teavm.backend.wasm.intrinsics.PlatformIntrinsic; import org.teavm.backend.wasm.intrinsics.PlatformIntrinsic;
import org.teavm.backend.wasm.intrinsics.PlatformObjectIntrinsic; import org.teavm.backend.wasm.intrinsics.PlatformObjectIntrinsic;
import org.teavm.backend.wasm.intrinsics.ShadowStackIntrinsic;
import org.teavm.backend.wasm.intrinsics.StructureIntrinsic; import org.teavm.backend.wasm.intrinsics.StructureIntrinsic;
import org.teavm.backend.wasm.intrinsics.WasmRuntimeIntrinsic; import org.teavm.backend.wasm.intrinsics.WasmRuntimeIntrinsic;
import org.teavm.backend.wasm.model.WasmFunction; import org.teavm.backend.wasm.model.WasmFunction;
@ -105,7 +106,6 @@ import org.teavm.model.instructions.CloneArrayInstruction;
import org.teavm.model.instructions.InitClassInstruction; import org.teavm.model.instructions.InitClassInstruction;
import org.teavm.model.instructions.InvocationType; import org.teavm.model.instructions.InvocationType;
import org.teavm.model.instructions.InvokeInstruction; import org.teavm.model.instructions.InvokeInstruction;
import org.teavm.model.instructions.MutatorIntrinsic;
import org.teavm.model.lowlevel.ClassInitializerEliminator; import org.teavm.model.lowlevel.ClassInitializerEliminator;
import org.teavm.model.lowlevel.ClassInitializerTransformer; import org.teavm.model.lowlevel.ClassInitializerTransformer;
import org.teavm.model.lowlevel.ShadowStackTransformer; import org.teavm.model.lowlevel.ShadowStackTransformer;
@ -206,9 +206,9 @@ public class WasmTarget implements TeaVMTarget {
Address.class, int.class, void.class), null).use(); Address.class, int.class, void.class), null).use();
dependencyChecker.linkMethod(new MethodReference(WasmRuntime.class, "allocStack", dependencyChecker.linkMethod(new MethodReference(WasmRuntime.class, "allocStack",
int.class, Address.class), null).use(); int.class, Address.class), null).use();
dependencyChecker.linkMethod(new MethodReference(WasmRuntime.class, "getStackGcRoots", Address.class), dependencyChecker.linkMethod(new MethodReference(WasmRuntime.class, "getStackTop", Address.class),
null) .use(); null) .use();
dependencyChecker.linkMethod(new MethodReference(WasmRuntime.class, "getNextStackRoots", Address.class, dependencyChecker.linkMethod(new MethodReference(WasmRuntime.class, "getNextStackFrame", Address.class,
Address.class), null).use(); Address.class), null).use();
dependencyChecker.linkMethod(new MethodReference(WasmRuntime.class, "getStackRootCount", Address.class, dependencyChecker.linkMethod(new MethodReference(WasmRuntime.class, "getStackRootCount", Address.class,
int.class), null).use(); int.class), null).use();
@ -294,7 +294,7 @@ public class WasmTarget implements TeaVMTarget {
context.addIntrinsic(gcIntrinsic); context.addIntrinsic(gcIntrinsic);
MutatorIntrinsic mutatorIntrinsic = new MutatorIntrinsic(); MutatorIntrinsic mutatorIntrinsic = new MutatorIntrinsic();
context.addIntrinsic(mutatorIntrinsic); context.addIntrinsic(mutatorIntrinsic);
context.addIntrinsic(new ExceptionHandlingIntrinsic()); context.addIntrinsic(new ShadowStackIntrinsic());
WasmGenerator generator = new WasmGenerator(decompiler, classes, WasmGenerator generator = new WasmGenerator(decompiler, classes,
context, classGenerator); context, classGenerator);

View File

@ -113,10 +113,9 @@ import org.teavm.model.ValueType;
import org.teavm.model.classes.TagRegistry; import org.teavm.model.classes.TagRegistry;
import org.teavm.model.classes.VirtualTableEntry; import org.teavm.model.classes.VirtualTableEntry;
import org.teavm.runtime.Allocator; import org.teavm.runtime.Allocator;
import org.teavm.runtime.ExceptionHandling;
import org.teavm.runtime.Mutator;
import org.teavm.runtime.RuntimeArray; import org.teavm.runtime.RuntimeArray;
import org.teavm.runtime.RuntimeClass; import org.teavm.runtime.RuntimeClass;
import org.teavm.runtime.ShadowStack;
class WasmGenerationVisitor implements StatementVisitor, ExprVisitor { class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
private static FieldReference tagField = new FieldReference(RuntimeClass.class.getName(), "tag"); private static FieldReference tagField = new FieldReference(RuntimeClass.class.getName(), "tag");
@ -783,7 +782,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
@Override @Override
public void visit(InvocationExpr expr) { public void visit(InvocationExpr expr) {
if (expr.getMethod().getClassName().equals(Mutator.class.getName())) { if (expr.getMethod().getClassName().equals(ShadowStack.class.getName())) {
switch (expr.getMethod().getName()) { switch (expr.getMethod().getName()) {
case "allocStack": case "allocStack":
generateAllocStack(expr.getArguments().get(0)); generateAllocStack(expr.getArguments().get(0));
@ -791,19 +790,16 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
case "releaseStack": case "releaseStack":
generateReleaseStack(); generateReleaseStack();
return; return;
case "registerGcRoot": case "registerGCRoot":
generateRegisterGcRoot(expr.getArguments().get(0), expr.getArguments().get(1)); generateRegisterGcRoot(expr.getArguments().get(0), expr.getArguments().get(1));
return; return;
case "removeGcRoot": case "removeGCRoot":
generateRemoveGcRoot(expr.getArguments().get(0)); generateRemoveGcRoot(expr.getArguments().get(0));
return; return;
}
} else if (expr.getMethod().getClassName().equals(ExceptionHandling.class.getName())) {
switch (expr.getMethod().getName()) {
case "registerCallSite": case "registerCallSite":
generateRegisterCallSite(expr.getArguments().get(0)); generateRegisterCallSite(expr.getArguments().get(0));
return; return;
case "getHandlerId": case "getExceptionHandlerId":
generateGetHandlerId(); generateGetHandlerId();
return; return;
} }
@ -896,7 +892,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
private void generateAllocStack(Expr sizeExpr) { private void generateAllocStack(Expr sizeExpr) {
if (stackVariable != null) { if (stackVariable != null) {
throw new IllegalStateException("Call to Mutator.allocStack must be done only once"); throw new IllegalStateException("Call to ShadowStack.allocStack must be done only once");
} }
stackVariable = getTemporary(WasmType.INT32); stackVariable = getTemporary(WasmType.INT32);
stackVariable.setName("__stack__"); stackVariable.setName("__stack__");
@ -911,7 +907,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
private void generateReleaseStack() { private void generateReleaseStack() {
if (stackVariable == null) { if (stackVariable == null) {
throw new IllegalStateException("Call to Mutator.releaseStack must be dominated by " throw new IllegalStateException("Call to ShadowStack.releaseStack must be dominated by "
+ "Mutator.allocStack"); + "Mutator.allocStack");
} }
@ -924,7 +920,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
private void generateRegisterCallSite(Expr callSiteExpr) { private void generateRegisterCallSite(Expr callSiteExpr) {
if (stackVariable == null) { if (stackVariable == null) {
throw new IllegalStateException("Call to ExceptionHandling.registerCallSite must be dominated by " throw new IllegalStateException("Call to ShadowStack.registerCallSite must be dominated by "
+ "Mutator.allocStack"); + "Mutator.allocStack");
} }
@ -936,7 +932,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
private void generateGetHandlerId() { private void generateGetHandlerId() {
if (stackVariable == null) { if (stackVariable == null) {
throw new IllegalStateException("Call to ExceptionHandling.getHandlerId must be dominated by " throw new IllegalStateException("Call to ShadowStack.getHandlerId must be dominated by "
+ "Mutator.allocStack"); + "Mutator.allocStack");
} }
@ -945,7 +941,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
private void generateRegisterGcRoot(Expr slotExpr, Expr gcRootExpr) { private void generateRegisterGcRoot(Expr slotExpr, Expr gcRootExpr) {
if (stackVariable == null) { if (stackVariable == null) {
throw new IllegalStateException("Call to Mutator.registerGcRoot must be dominated by " throw new IllegalStateException("Call to ShadowStack.registerGCRoot must be dominated by "
+ "Mutator.allocStack"); + "Mutator.allocStack");
} }
@ -962,7 +958,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
private void generateRemoveGcRoot(Expr slotExpr) { private void generateRemoveGcRoot(Expr slotExpr) {
if (stackVariable == null) { if (stackVariable == null) {
throw new IllegalStateException("Call to Mutator.removeGcRoot must be dominated by " throw new IllegalStateException("Call to ShadowStack.removeGCRoot must be dominated by "
+ "Mutator.allocStack"); + "Mutator.allocStack");
} }

View File

@ -13,15 +13,11 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.model.instructions; package org.teavm.backend.wasm.intrinsics;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.teavm.ast.*; import org.teavm.ast.InvocationExpr;
import org.teavm.ast.InvocationType;
import org.teavm.backend.wasm.WasmRuntime;
import org.teavm.backend.wasm.intrinsics.WasmIntrinsic;
import org.teavm.backend.wasm.intrinsics.WasmIntrinsicManager;
import org.teavm.backend.wasm.model.expression.WasmExpression; import org.teavm.backend.wasm.model.expression.WasmExpression;
import org.teavm.backend.wasm.model.expression.WasmInt32Constant; import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
@ -30,46 +26,34 @@ import org.teavm.runtime.Mutator;
public class MutatorIntrinsic implements WasmIntrinsic { public class MutatorIntrinsic implements WasmIntrinsic {
private List<WasmInt32Constant> staticGcRootsExpressions = new ArrayList<>(); private List<WasmInt32Constant> staticGcRootsExpressions = new ArrayList<>();
@Override
public boolean isApplicable(MethodReference methodReference) {
if (!methodReference.getClassName().equals(Mutator.class.getName())) {
return false;
}
switch (methodReference.getName()) {
case "getStaticGcRoots":
case "getStackGcRoots":
case "getNextStackRoots":
case "getStackRootCount":
case "getStackRootPointer":
return true;
default:
return false;
}
}
public void setStaticGcRootsAddress(int address) { public void setStaticGcRootsAddress(int address) {
for (WasmInt32Constant constant : staticGcRootsExpressions) { for (WasmInt32Constant constant : staticGcRootsExpressions) {
constant.setValue(address); constant.setValue(address);
} }
} }
@Override
public boolean isApplicable(MethodReference methodReference) {
if (!methodReference.getClassName().equals(Mutator.class.getName())) {
return false;
}
switch (methodReference.getName()) {
case "getStaticGCRoots":
return true;
default:
return false;
}
}
@Override @Override
public WasmExpression apply(InvocationExpr invocation, WasmIntrinsicManager manager) { public WasmExpression apply(InvocationExpr invocation, WasmIntrinsicManager manager) {
switch (invocation.getMethod().getName()) { switch (invocation.getMethod().getName()) {
case "getStaticGcRoots": { case "getStaticGCRoots": {
WasmInt32Constant constant = new WasmInt32Constant(0); WasmInt32Constant constant = new WasmInt32Constant(0);
staticGcRootsExpressions.add(constant); staticGcRootsExpressions.add(constant);
return constant; return constant;
} }
default: {
InvocationExpr expr = new InvocationExpr();
MethodReference method = new MethodReference(WasmRuntime.class.getName(),
invocation.getMethod().getDescriptor());
expr.setMethod(method);
expr.setType(InvocationType.SPECIAL);
expr.getArguments().addAll(invocation.getArguments());
return manager.generate(expr);
}
} }
throw new IllegalArgumentException(invocation.getMethod().toString());
} }
} }

View File

@ -16,33 +16,37 @@
package org.teavm.backend.wasm.intrinsics; package org.teavm.backend.wasm.intrinsics;
import org.teavm.ast.InvocationExpr; import org.teavm.ast.InvocationExpr;
import org.teavm.ast.InvocationType;
import org.teavm.backend.wasm.WasmRuntime;
import org.teavm.backend.wasm.model.expression.WasmExpression; import org.teavm.backend.wasm.model.expression.WasmExpression;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
import org.teavm.runtime.ExceptionHandling; import org.teavm.runtime.ShadowStack;
public class ExceptionHandlingIntrinsic implements WasmIntrinsic { public class ShadowStackIntrinsic implements WasmIntrinsic {
@Override @Override
public boolean isApplicable(MethodReference methodReference) { public boolean isApplicable(MethodReference methodReference) {
if (!methodReference.getClassName().equals(ExceptionHandling.class.getName())) { if (!methodReference.getClassName().equals(ShadowStack.class.getName())) {
return false; return false;
} }
switch (methodReference.getName()) { switch (methodReference.getName()) {
case "registerCallSite": case "getStackTop":
case "getHandlerId": case "getNextStackFrame":
case "getStackRootCount":
case "getStackRootPointer":
return true; return true;
} default:
return false; return false;
} }
}
@Override @Override
public WasmExpression apply(InvocationExpr invocation, WasmIntrinsicManager manager) { public WasmExpression apply(InvocationExpr invocation, WasmIntrinsicManager manager) {
switch (invocation.getMethod().getName()) { InvocationExpr expr = new InvocationExpr();
case "registerCallSite": MethodReference method = new MethodReference(WasmRuntime.class.getName(),
break; invocation.getMethod().getDescriptor());
} expr.setMethod(method);
expr.setType(InvocationType.SPECIAL);
throw new IllegalArgumentException(invocation.getMethod().toString()); expr.getArguments().addAll(invocation.getArguments());
return manager.generate(expr);
} }
} }

View File

@ -50,6 +50,7 @@ import org.teavm.model.instructions.SwitchTableEntry;
import org.teavm.model.util.DefinitionExtractor; import org.teavm.model.util.DefinitionExtractor;
import org.teavm.model.util.ProgramUtils; import org.teavm.model.util.ProgramUtils;
import org.teavm.runtime.ExceptionHandling; import org.teavm.runtime.ExceptionHandling;
import org.teavm.runtime.ShadowStack;
public class ExceptionHandlingShadowStackContributor { public class ExceptionHandlingShadowStackContributor {
private ManagedMethodRepository managedMethodRepository; private ManagedMethodRepository managedMethodRepository;
@ -194,8 +195,7 @@ public class ExceptionHandlingShadowStackContributor {
instructions.add(idInsn); instructions.add(idInsn);
InvokeInstruction registerInsn = new InvokeInstruction(); InvokeInstruction registerInsn = new InvokeInstruction();
registerInsn.setMethod(new MethodReference(ExceptionHandling.class, "registerCallSite", registerInsn.setMethod(new MethodReference(ShadowStack.class, "registerCallSite", int.class, void.class));
int.class, void.class));
registerInsn.setType(InvocationType.SPECIAL); registerInsn.setType(InvocationType.SPECIAL);
registerInsn.getArguments().add(idVariable); registerInsn.getArguments().add(idVariable);
instructions.add(registerInsn); instructions.add(registerInsn);
@ -219,7 +219,7 @@ public class ExceptionHandlingShadowStackContributor {
Variable handlerIdVariable = program.createVariable(); Variable handlerIdVariable = program.createVariable();
InvokeInstruction getHandlerIdInsn = new InvokeInstruction(); InvokeInstruction getHandlerIdInsn = new InvokeInstruction();
getHandlerIdInsn.setMethod(new MethodReference(ExceptionHandling.class, "getHandlerId", int.class)); getHandlerIdInsn.setMethod(new MethodReference(ShadowStack.class, "getExceptionHandlerId", int.class));
getHandlerIdInsn.setType(InvocationType.SPECIAL); getHandlerIdInsn.setType(InvocationType.SPECIAL);
getHandlerIdInsn.setReceiver(handlerIdVariable); getHandlerIdInsn.setReceiver(handlerIdVariable);
instructions.add(getHandlerIdInsn); instructions.add(getHandlerIdInsn);

View File

@ -53,7 +53,7 @@ import org.teavm.model.util.ProgramUtils;
import org.teavm.model.util.TypeInferer; import org.teavm.model.util.TypeInferer;
import org.teavm.model.util.UsageExtractor; import org.teavm.model.util.UsageExtractor;
import org.teavm.model.util.VariableType; import org.teavm.model.util.VariableType;
import org.teavm.runtime.Mutator; import org.teavm.runtime.ShadowStack;
public class GCShadowStackContributor { public class GCShadowStackContributor {
private ManagedMethodRepository managedMethodRepository; private ManagedMethodRepository managedMethodRepository;
@ -92,9 +92,9 @@ public class GCShadowStackContributor {
findAutoSpilledPhis(spilled, destinationPhis, inputCount, autoSpilled, i); findAutoSpilledPhis(spilled, destinationPhis, inputCount, autoSpilled, i);
} }
List<IntObjectMap<int[]>> liveInStores = reduceGcRootStores(program, usedColors, liveInInformation, List<IntObjectMap<int[]>> liveInStores = reduceGCRootStores(program, usedColors, liveInInformation,
colors, autoSpilled); colors, autoSpilled);
putLiveInGcRoots(program, liveInStores); putLiveInGCRoots(program, liveInStores);
return usedColors; return usedColors;
} }
@ -241,7 +241,7 @@ public class GCShadowStackContributor {
return inputCount; return inputCount;
} }
private List<IntObjectMap<int[]>> reduceGcRootStores(Program program, int usedColors, private List<IntObjectMap<int[]>> reduceGCRootStores(Program program, int usedColors,
List<IntObjectMap<BitSet>> liveInInformation, int[] colors, boolean[] autoSpilled) { List<IntObjectMap<BitSet>> liveInInformation, int[] colors, boolean[] autoSpilled) {
class Step { class Step {
private final int node; private final int node;
@ -322,7 +322,7 @@ public class GCShadowStackContributor {
return comparison; return comparison;
} }
private void putLiveInGcRoots(Program program, List<IntObjectMap<int[]>> updateInformation) { private void putLiveInGCRoots(Program program, List<IntObjectMap<int[]>> updateInformation) {
for (int i = 0; i < program.basicBlockCount(); ++i) { for (int i = 0; i < program.basicBlockCount(); ++i) {
BasicBlock block = program.basicBlockAt(i); BasicBlock block = program.basicBlockAt(i);
IntObjectMap<int[]> updatesByIndex = updateInformation.get(i); IntObjectMap<int[]> updatesByIndex = updateInformation.get(i);
@ -359,11 +359,11 @@ public class GCShadowStackContributor {
registerInvocation.setType(InvocationType.SPECIAL); registerInvocation.setType(InvocationType.SPECIAL);
registerInvocation.getArguments().add(slotVar); registerInvocation.getArguments().add(slotVar);
if (var >= 0) { if (var >= 0) {
registerInvocation.setMethod(new MethodReference(Mutator.class, "registerGcRoot", int.class, registerInvocation.setMethod(new MethodReference(ShadowStack.class, "registerGCRoot", int.class,
Object.class, void.class)); Object.class, void.class));
registerInvocation.getArguments().add(program.variableAt(var)); registerInvocation.getArguments().add(program.variableAt(var));
} else { } else {
registerInvocation.setMethod(new MethodReference(Mutator.class, "removeGcRoot", int.class, registerInvocation.setMethod(new MethodReference(ShadowStack.class, "removeGCRoot", int.class,
void.class)); void.class));
} }
instructionsToAdd.add(registerInvocation); instructionsToAdd.add(registerInvocation);

View File

@ -31,7 +31,7 @@ import org.teavm.model.instructions.IntegerConstantInstruction;
import org.teavm.model.instructions.InvocationType; import org.teavm.model.instructions.InvocationType;
import org.teavm.model.instructions.InvokeInstruction; import org.teavm.model.instructions.InvokeInstruction;
import org.teavm.model.instructions.JumpInstruction; import org.teavm.model.instructions.JumpInstruction;
import org.teavm.runtime.Mutator; import org.teavm.runtime.ShadowStack;
public class ShadowStackTransformer { public class ShadowStackTransformer {
private ManagedMethodRepository managedMethodRepository; private ManagedMethodRepository managedMethodRepository;
@ -70,7 +70,7 @@ public class ShadowStackTransformer {
InvokeInstruction invocation = new InvokeInstruction(); InvokeInstruction invocation = new InvokeInstruction();
invocation.setType(InvocationType.SPECIAL); invocation.setType(InvocationType.SPECIAL);
invocation.setMethod(new MethodReference(Mutator.class, "allocStack", int.class, void.class)); invocation.setMethod(new MethodReference(ShadowStack.class, "allocStack", int.class, void.class));
invocation.getArguments().add(sizeVariable); invocation.getArguments().add(sizeVariable);
instructionsToAdd.add(invocation); instructionsToAdd.add(invocation);
@ -135,7 +135,7 @@ public class ShadowStackTransformer {
InvokeInstruction invocation = new InvokeInstruction(); InvokeInstruction invocation = new InvokeInstruction();
invocation.setType(InvocationType.SPECIAL); invocation.setType(InvocationType.SPECIAL);
invocation.setMethod(new MethodReference(Mutator.class, "releaseStack", int.class, void.class)); invocation.setMethod(new MethodReference(ShadowStack.class, "releaseStack", int.class, void.class));
invocation.getArguments().add(sizeVariable); invocation.getArguments().add(sizeVariable);
instructionsToAdd.add(invocation); instructionsToAdd.add(invocation);

View File

@ -26,20 +26,6 @@ public final class ExceptionHandling {
private ExceptionHandling() { private ExceptionHandling() {
} }
public static native void registerCallSite(int id);
public static native int callSiteResult();
public static native Address getStackTop();
public static native Address getNextStackFrame(Address stackFrame);
public static native int getCallSiteId(Address stackFrame);
public static native void setHandlerId(Address stackFrame, int id);
public static native int getHandlerId();
public static native CallSite findCallSiteById(int id); public static native CallSite findCallSiteById(int id);
public static void throwException(Throwable exception) { public static void throwException(Throwable exception) {
@ -47,23 +33,23 @@ public final class ExceptionHandling {
RuntimeClass exceptionClass = RuntimeClass.getClass(exceptionPtr); RuntimeClass exceptionClass = RuntimeClass.getClass(exceptionPtr);
IsSupertypeFunction isExceptionSupertype = exceptionClass.isSupertypeOf; IsSupertypeFunction isExceptionSupertype = exceptionClass.isSupertypeOf;
Address stackFrame = getStackTop(); Address stackFrame = ShadowStack.getStackTop();
stackLoop: while (stackFrame != null) { stackLoop: while (stackFrame != null) {
int callSiteId = getCallSiteId(stackFrame); int callSiteId = ShadowStack.getCallSiteId(stackFrame);
CallSite callSite = findCallSiteById(callSiteId); CallSite callSite = findCallSiteById(callSiteId);
ExceptionHandler handler = callSite.firstHandler; ExceptionHandler handler = callSite.firstHandler;
for (int i = 0; i < callSite.handlerCount; ++i) { for (int i = 0; i < callSite.handlerCount; ++i) {
if (isExceptionSupertype.apply(handler.exceptionClass)) { if (isExceptionSupertype.apply(handler.exceptionClass)) {
setHandlerId(stackFrame, handler.id); ShadowStack.setExceptionHandlerId(stackFrame, handler.id);
break stackLoop; break stackLoop;
} }
handler = Structure.add(ExceptionHandler.class, handler, 1); handler = Structure.add(ExceptionHandler.class, handler, 1);
} }
setHandlerId(stackFrame, callSiteId - 1); ShadowStack.setExceptionHandlerId(stackFrame, callSiteId - 1);
stackFrame = getNextStackFrame(stackFrame); stackFrame = ShadowStack.getNextStackFrame(stackFrame);
} }
} }
} }

View File

@ -109,7 +109,7 @@ public final class GC {
private static void mark() { private static void mark() {
Allocator.fillZero(regionsAddress().toAddress(), regionMaxCount() * Structure.sizeOf(Region.class)); Allocator.fillZero(regionsAddress().toAddress(), regionMaxCount() * Structure.sizeOf(Region.class));
Address staticRoots = Mutator.getStaticGcRoots(); Address staticRoots = Mutator.getStaticGCRoots();
int staticCount = staticRoots.getInt(); int staticCount = staticRoots.getInt();
staticRoots.add(8); staticRoots.add(8);
while (staticCount-- > 0) { while (staticCount-- > 0) {
@ -120,10 +120,10 @@ public final class GC {
staticRoots = staticRoots.add(Address.sizeOf()); staticRoots = staticRoots.add(Address.sizeOf());
} }
for (Address stackRoots = Mutator.getStackGcRoots(); stackRoots != null; for (Address stackRoots = ShadowStack.getStackTop(); stackRoots != null;
stackRoots = Mutator.getNextStackRoots(stackRoots)) { stackRoots = ShadowStack.getNextStackFrame(stackRoots)) {
int count = Mutator.getStackRootCount(stackRoots); int count = ShadowStack.getStackRootCount(stackRoots);
Address stackRootsPtr = Mutator.getStackRootPointer(stackRoots); Address stackRootsPtr = ShadowStack.getStackRootPointer(stackRoots);
while (count-- > 0) { while (count-- > 0) {
RuntimeObject obj = stackRootsPtr.getAddress().toStructure(); RuntimeObject obj = stackRootsPtr.getAddress().toStructure();
mark(obj); mark(obj);

View File

@ -25,21 +25,5 @@ public final class Mutator {
private Mutator() { private Mutator() {
} }
public static native void allocStack(int size); public static native Address getStaticGCRoots();
public static native void registerGcRoot(int index, Object object);
public static native void removeGcRoot(int index);
public static native void releaseStack(int size);
public static native Address getStaticGcRoots();
public static native Address getStackGcRoots();
public static native Address getNextStackRoots(Address address);
public static native int getStackRootCount(Address address);
public static native Address getStackRootPointer(Address address);
} }

View File

@ -0,0 +1,51 @@
/*
* Copyright 2016 Alexey Andreev.
*
* 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 org.teavm.runtime;
import org.teavm.interop.Address;
import org.teavm.interop.StaticInit;
import org.teavm.interop.Unmanaged;
@Unmanaged
@StaticInit
public final class ShadowStack {
private ShadowStack() {
}
public static native void allocStack(int size);
public static native void registerGCRoot(int index, Object object);
public static native void removeGCRoot(int index);
public static native void releaseStack(int size);
public static native Address getStackTop();
public static native Address getNextStackFrame(Address stackFrame);
public static native int getStackRootCount(Address stackFrame);
public static native Address getStackRootPointer(Address stackFrame);
public static native int getCallSiteId(Address stackFrame);
public static native void registerCallSite(int id);
public static native int getExceptionHandlerId();
public static native void setExceptionHandlerId(Address stackFrame, int id);
}