mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 08:34:11 -08:00
WASM: refactoring shadow stack
This commit is contained in:
parent
b67d243ad4
commit
4e431e2f77
|
@ -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()) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
throw new IllegalArgumentException(invocation.getMethod().toString());
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
51
core/src/main/java/org/teavm/runtime/ShadowStack.java
Normal file
51
core/src/main/java/org/teavm/runtime/ShadowStack.java
Normal 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);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user