Skip to content

Instantly share code, notes, and snippets.

@smarr
Created March 25, 2018 11:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save smarr/c7b626dbc8d8c33251d952d6653c2ef3 to your computer and use it in GitHub Desktop.
Save smarr/c7b626dbc8d8c33251d952d6653c2ef3 to your computer and use it in GitHub Desktop.
Debugging helpers code for race conditions in object model
From 0d1d5b9ebf01d65ecffc93c8425528be9e6d8e64 Mon Sep 17 00:00:00 2001
From: Stefan Marr <git@stefan-marr.de>
Date: Sat, 24 Mar 2018 16:24:23 +0000
Subject: [PATCH] Race condition in object model, further debugging needed
This debugging code helps debugging a race condition in the object model.
This seems to be observable rather reliably with accesses to cached class fields.
Specifically, we can see that in Parser.ns, we read the slot `R`, and retrieve an `A class` instead of `R class` rather reliably.
First, I assumed something to be wrong in the outer read nodes.
But now I am convinced that the object model is to blame.
I see reads that a specialized for the current object layout and access the slot storage, which normally should belong to R, but contains A.
Not sure where the problem happens.
It could be the writing and/or the object transitioning that is at fault.
This is reproducible in the interpreter without Graal by running the BasicInterpreterTests, possibly multiple times.
Signed-off-by: Stefan Marr <git@stefan-marr.de>
---
src/som/interpreter/nodes/MessageSendNode.java | 33 ++++
src/som/interpreter/nodes/OuterObjectRead.java | 4 +
src/som/vm/VmSettings.java | 2 +-
tests/java/som/tests/BasicInterpreterTests.java | 234 ++++++++++++------------
4 files changed, 160 insertions(+), 113 deletions(-)
diff --git a/src/som/interpreter/nodes/MessageSendNode.java b/src/som/interpreter/nodes/MessageSendNode.java
index cdf427a45..c843975f3 100644
--- a/src/som/interpreter/nodes/MessageSendNode.java
+++ b/src/som/interpreter/nodes/MessageSendNode.java
@@ -26,6 +26,8 @@
import som.interpreter.nodes.nary.EagerlySpecializableNode;
import som.interpreter.nodes.nary.ExprWithTagsNode;
import som.vm.Primitives;
+import som.vm.Symbols;
+import som.vmobjects.SAbstractObject;
import som.vmobjects.SSymbol;
import tools.Send;
import tools.SourceCoordinate;
@@ -33,6 +35,8 @@
public final class MessageSendNode {
+ private final static SSymbol TEST_SYM = Symbols.symbolFor("a:b:c:");
+ private final static SSymbol TEST_CLS = Symbols.symbolFor("A class");
public static ExpressionNode createMessageSend(final SSymbol selector,
final ExpressionNode[] arguments, final SourceSection source, final VM vm) {
@@ -132,7 +136,28 @@ public Object executeGeneric(final VirtualFrame frame) {
private Object[] evaluateArguments(final VirtualFrame frame) {
Object[] arguments = new Object[argumentNodes.length];
for (int i = 0; i < argumentNodes.length; i++) {
+ ExpressionNode prev = null;
+ if (getSelector() == TEST_SYM && i == 0) {
+ prev = ((AbstractMessageSendNode) argumentNodes[i]).argumentNodes[0];
+ }
+
arguments[i] = argumentNodes[i].executeGeneric(frame);
+
+ if (getSelector() == TEST_SYM && i == 0) {
+ SAbstractObject o = (SAbstractObject) arguments[0];
+ if (o.getSOMClass().getName() == TEST_CLS) {
+ int j = 0;
+ Object secondTime = argumentNodes[i].executeGeneric(frame);
+ System.out.println(prev);
+ System.out.println(secondTime);
+ j += 1 + j;
+
+ argumentNodes[i].executeGeneric(frame);
+ argumentNodes[i].executeGeneric(frame);
+
+ }
+ }
+
assert arguments[i] != null : "Some expression evaluated to null, which is not supported.";
}
return arguments;
@@ -310,6 +335,14 @@ protected boolean isTaggedWith(final Class<?> tag) {
@Override
public Object doPreEvaluated(final VirtualFrame frame,
final Object[] arguments) {
+ if (selector == TEST_SYM) {
+ SAbstractObject o = (SAbstractObject) arguments[0];
+ if (o.getSOMClass().getName() == TEST_CLS) {
+ int i = 0;
+ i += 1 + i;
+ }
+ }
+
return dispatchNode.executeDispatch(arguments);
}
diff --git a/src/som/interpreter/nodes/OuterObjectRead.java b/src/som/interpreter/nodes/OuterObjectRead.java
index 91dacaeb0..c2d4141d3 100644
--- a/src/som/interpreter/nodes/OuterObjectRead.java
+++ b/src/som/interpreter/nodes/OuterObjectRead.java
@@ -143,6 +143,8 @@ protected static final SClass getEnclosingClassWithPotentialFailure(
public final Object doForFurtherOuter(final SObjectWithClass receiver,
@Cached("receiver.getSOMClass()") final SClass rcvrClass,
@Cached("getEnclosingClass(receiver)") final SClass lexicalClass) {
+ System.out.println(
+ "doForFurtherOuter: " + mixinId + " t: " + Thread.currentThread().getId());
return getEnclosingObject(lexicalClass);
}
@@ -165,11 +167,13 @@ public final Object fixedLookup(final SObjectWithClass receiver,
@Cached("getIdx(receiver)") final int superclassIdx,
@Cached("getEnclosingClass(receiver).getInstanceFactory()") final ClassFactory factory) {
assert factory != null;
+ System.out.println("fixedLookup: " + mixinId + " t: " + Thread.currentThread().getId());
return getEnclosingObject(getEnclosingClassWithPotentialFailure(receiver, superclassIdx));
}
@Specialization(replaces = "fixedLookup")
public final Object fallback(final SObjectWithClass receiver) {
+ System.out.println("fallback: " + mixinId + " t: " + Thread.currentThread().getId());
return getEnclosingObject(getEnclosingClass(receiver));
}
diff --git a/src/som/vm/VmSettings.java b/src/som/vm/VmSettings.java
index 8195c6792..5e6ebefe6 100644
--- a/src/som/vm/VmSettings.java
+++ b/src/som/vm/VmSettings.java
@@ -68,7 +68,7 @@
DYNAMIC_METRICS = dm;
INSTRUMENTATION = dm || getBool(INSTRUMENTATION_PROP, false);
- DNU_PRINT_STACK_TRACE = getBool("som.printStackTraceOnDNU", false);
+ DNU_PRINT_STACK_TRACE = getBool("som.printStackTraceOnDNU", true);
IGV_DUMP_AFTER_PARSING = getBool("som.igvDumpAfterParsing", false);
diff --git a/tests/java/som/tests/BasicInterpreterTests.java b/tests/java/som/tests/BasicInterpreterTests.java
index 47471b03f..87540abeb 100644
--- a/tests/java/som/tests/BasicInterpreterTests.java
+++ b/tests/java/som/tests/BasicInterpreterTests.java
@@ -57,121 +57,131 @@
@Parameters(name = "{0}.{1} [{index}]")
public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][] {
- {"MethodCall", "test", 42, Long.class, null},
- {"MethodCall", "test2", 42, Long.class, null},
-
- {"NonLocalReturn", "test1", 42, Long.class, null},
- {"NonLocalReturn", "test2", 43, Long.class, null},
- {"NonLocalReturn", "test3", 3, Long.class, null},
- {"NonLocalReturn", "test4", 42, Long.class, null},
- {"NonLocalReturn", "test5", 22, Long.class, null},
-
- {"Blocks", "arg1", 42, Long.class, null},
- {"Blocks", "arg2", 77, Long.class, null},
- {"Blocks", "argAndLocal", 8, Long.class, null},
- {"Blocks", "argAndContext", 8, Long.class, null},
-
- {"Return", "returnSelf", "Return", SClass.class, null},
- {"Return", "returnSelfImplicitly", "Return", SClass.class, null},
- {"Return", "noReturnReturnsSelf", "Return", SClass.class, null},
- {"Return", "blockReturnsImplicitlyLastValue", 4, Long.class, null},
- {"Return", "returnIntLiteral", 33, Long.class, null},
- {"Return", "returnUnarySend", 33, Long.class, null},
-
- {"IfTrueIfFalse", "test", 42, Long.class, null},
- {"IfTrueIfFalse", "test2", 33, Long.class, null},
- {"IfTrueIfFalse", "test3", 4, Long.class, null},
-
- {"CompilerSimplification", "returnConstantSymbol", "constant", SSymbol.class, null},
- {"CompilerSimplification", "returnConstantInt", 42, Long.class, null},
- {"CompilerSimplification", "returnSelf", "CompilerSimplification", SClass.class, null},
- {"CompilerSimplification", "returnSelfImplicitly", "CompilerSimplification",
- SClass.class, null},
- {"CompilerSimplification", "testReturnArgumentN", 55, Long.class, null},
- {"CompilerSimplification", "testReturnArgumentA", 44, Long.class, null},
- {"CompilerSimplification", "testSetField", "foo", SSymbol.class, null},
- {"CompilerSimplification", "testGetField", 40, Long.class, null},
-
- {"Arrays", "testArrayCreation", "Array", Object.class, null},
- {"Arrays", "testEmptyToInts", 3, Long.class, null},
- {"Arrays", "testPutAllInt", 5, Long.class, null},
- {"Arrays", "testPutAllNil", null, Object.class, null},
- {"Arrays", "testNewWithAll", 1, Long.class, null},
-
- {"BlockInlining", "testNoInlining", 1, Long.class, null},
- {"BlockInlining", "testOneLevelInlining", 1, Long.class, null},
- {"BlockInlining", "testOneLevelInliningWithLocalShadowTrue", 2, Long.class, null},
- {"BlockInlining", "testOneLevelInliningWithLocalShadowFalse", 1, Long.class, null},
- {"BlockInlining", "testBlockNestedInIfTrue", 2, Long.class, null},
- {"BlockInlining", "testBlockNestedInIfFalse", 42, Long.class, null},
- {"BlockInlining", "testDeepNestedInlinedIfTrue", 3, Long.class, null},
- {"BlockInlining", "testDeepNestedInlinedIfFalse", 42, Long.class, null},
- {"BlockInlining", "testDeepNestedBlocksInInlinedIfTrue", 5, Long.class, null},
- {"BlockInlining", "testDeepNestedBlocksInInlinedIfFalse", 43, Long.class, null},
- {"BlockInlining", "testDeepDeepNestedTrue", 9, Long.class, null},
- {"BlockInlining", "testDeepDeepNestedFalse", 43, Long.class, null},
- {"BlockInlining", "testToDoNestDoNestIfTrue", 2, Long.class, null},
-
- {"BlockInlining2", "test", 33, Long.class, null},
- {"BlockInlining3", "test", 33, Long.class, null},
- {"BlockInlining4", "test", 33, Long.class, null},
- {"BlockInlining5", "test", 33, Long.class, null},
-
- {"Lookup", "testClassMethodsNotBlockingOuterMethods", 42, Long.class, UNSAFE_OM},
- {"Lookup", "testExplicitOuterInInitializer", 182, Long.class, UNSAFE_OM},
- {"Lookup", "testImplicitOuterInInitializer", 182, Long.class, UNSAFE_OM},
- {"Lookup", "testImplicitSend", 42, Long.class, UNSAFE_OM},
- {"Lookup", "testSiblingLookupA", 42, Long.class, UNSAFE_OM},
- {"Lookup", "testSiblingLookupB", 43, Long.class, UNSAFE_OM},
- {"Lookup", "testNesting1", 91, Long.class, UNSAFE_OM},
- {"Lookup", "testNesting2", 182, Long.class, UNSAFE_OM},
- {"Lookup", "testNesting3", 364, Long.class, UNSAFE_OM},
- {"Lookup", "testInner18", 999, Long.class, UNSAFE_OM},
-
- {"Lookup", "testImplicitReceiverSendToPrivateMethod", 55, Long.class, null},
- {"Lookup", "testSelfSendToPrivateMethod", 55, Long.class, null},
- {"Lookup", "testImplicitReceiverSendToPrivateMethodFromSubclass", 55, Long.class,
- null},
- {"Lookup", "testSelfSendToPrivateMethodFromSubclass", 55, Long.class, null},
-
- {"SuperSends", "testSuperClassClause1A", 44, Long.class, null},
- {"SuperSends", "testSuperClassClause1B", 88, Long.class, null},
- {"SuperSends", "testSuperClassClause2A", 44, Long.class, null},
- {"SuperSends", "testSuperClassClause2B", 88, Long.class, null},
- {"SuperSends", "testSuperClassClause3A", 44, Long.class, null},
- {"SuperSends", "testSuperClassClause3B", 88, Long.class, null},
- {"SuperSends", "testSuperClassClause4A", 44, Long.class, null},
- {"SuperSends", "testSuperClassClause4B", 88, Long.class, null},
- {"SuperSends", "testSuperInBlock1", 42, Long.class, null},
- {"SuperSends", "testSuperInBlock2", 42, Long.class, null},
-
- {"OuterSends", "testOuterBindings1", 3, Long.class, null},
- {"OuterSends", "testOuterBindings2", 2, Long.class, null},
- {"OuterSends", "testOuterBindings3", 6, Long.class, null},
- {"OuterSends", "testOuterSendLegalTargets", 666, Long.class, null},
-
- {"ObjectCreation", "testNew", "ObjectCreation", Object.class, null},
- {"ObjectCreation", "testImmutableRead", 3, Long.class, null},
- {"ObjectCreation", "testImmutableReadInner", 42, Long.class, null},
-
- {"Parser", "testOuterInKeyword", 32 * 32 * 32, Long.class, UNSAFE_OM},
+ /*
+ * {"MethodCall", "test", 42, Long.class, null},
+ * {"MethodCall", "test2", 42, Long.class, null},
+ * {"NonLocalReturn", "test1", 42, Long.class, null},
+ * {"NonLocalReturn", "test2", 43, Long.class, null},
+ * {"NonLocalReturn", "test3", 3, Long.class, null},
+ * {"NonLocalReturn", "test4", 42, Long.class, null},
+ * {"NonLocalReturn", "test5", 22, Long.class, null},
+ * {"Blocks", "arg1", 42, Long.class, null},
+ * {"Blocks", "arg2", 77, Long.class, null},
+ * {"Blocks", "argAndLocal", 8, Long.class, null},
+ * {"Blocks", "argAndContext", 8, Long.class, null},
+ * {"Return", "returnSelf", "Return", SClass.class, null},
+ * {"Return", "returnSelfImplicitly", "Return", SClass.class, null},
+ * {"Return", "noReturnReturnsSelf", "Return", SClass.class, null},
+ * {"Return", "blockReturnsImplicitlyLastValue", 4, Long.class, null},
+ * {"Return", "returnIntLiteral", 33, Long.class, null},
+ * {"Return", "returnUnarySend", 33, Long.class, null},
+ * {"IfTrueIfFalse", "test", 42, Long.class, null},
+ * {"IfTrueIfFalse", "test2", 33, Long.class, null},
+ * {"IfTrueIfFalse", "test3", 4, Long.class, null},
+ * {"CompilerSimplification", "returnConstantSymbol", "constant", SSymbol.class, null},
+ * {"CompilerSimplification", "returnConstantInt", 42, Long.class, null},
+ * {"CompilerSimplification", "returnSelf", "CompilerSimplification", SClass.class,
+ * null},
+ * {"CompilerSimplification", "returnSelfImplicitly", "CompilerSimplification",
+ * SClass.class, null},
+ * {"CompilerSimplification", "testReturnArgumentN", 55, Long.class, null},
+ * {"CompilerSimplification", "testReturnArgumentA", 44, Long.class, null},
+ * {"CompilerSimplification", "testSetField", "foo", SSymbol.class, null},
+ * {"CompilerSimplification", "testGetField", 40, Long.class, null},
+ * {"Arrays", "testArrayCreation", "Array", Object.class, null},
+ * {"Arrays", "testEmptyToInts", 3, Long.class, null},
+ * {"Arrays", "testPutAllInt", 5, Long.class, null},
+ * {"Arrays", "testPutAllNil", null, Object.class, null},
+ * {"Arrays", "testNewWithAll", 1, Long.class, null},
+ * {"BlockInlining", "testNoInlining", 1, Long.class, null},
+ * {"BlockInlining", "testOneLevelInlining", 1, Long.class, null},
+ * {"BlockInlining", "testOneLevelInliningWithLocalShadowTrue", 2, Long.class, null},
+ * {"BlockInlining", "testOneLevelInliningWithLocalShadowFalse", 1, Long.class, null},
+ * {"BlockInlining", "testBlockNestedInIfTrue", 2, Long.class, null},
+ * {"BlockInlining", "testBlockNestedInIfFalse", 42, Long.class, null},
+ * {"BlockInlining", "testDeepNestedInlinedIfTrue", 3, Long.class, null},
+ * {"BlockInlining", "testDeepNestedInlinedIfFalse", 42, Long.class, null},
+ * {"BlockInlining", "testDeepNestedBlocksInInlinedIfTrue", 5, Long.class, null},
+ * {"BlockInlining", "testDeepNestedBlocksInInlinedIfFalse", 43, Long.class, null},
+ * {"BlockInlining", "testDeepDeepNestedTrue", 9, Long.class, null},
+ * {"BlockInlining", "testDeepDeepNestedFalse", 43, Long.class, null},
+ * {"BlockInlining", "testToDoNestDoNestIfTrue", 2, Long.class, null},
+ * {"BlockInlining2", "test", 33, Long.class, null},
+ * {"BlockInlining3", "test", 33, Long.class, null},
+ * {"BlockInlining4", "test", 33, Long.class, null},
+ * {"BlockInlining5", "test", 33, Long.class, null},
+ * {"Lookup", "testClassMethodsNotBlockingOuterMethods", 42, Long.class, null},
+ * {"Lookup", "testExplicitOuterInInitializer", 182, Long.class, null},
+ * {"Lookup", "testImplicitOuterInInitializer", 182, Long.class, null},
+ * {"Lookup", "testImplicitSend", 42, Long.class, null},
+ * {"Lookup", "testSiblingLookupA", 42, Long.class, null},
+ * {"Lookup", "testSiblingLookupB", 43, Long.class, null},
+ * {"Lookup", "testNesting1", 91, Long.class, null},
+ * {"Lookup", "testNesting2", 182, Long.class, null},
+ * {"Lookup", "testNesting3", 364, Long.class, null},
+ * {"Lookup", "testInner18", 999, Long.class, UNSAFE_OM},
+ * {"Lookup", "testImplicitReceiverSendToPrivateMethod", 55, Long.class, null},
+ * {"Lookup", "testSelfSendToPrivateMethod", 55, Long.class, null},
+ * {"Lookup", "testImplicitReceiverSendToPrivateMethodFromSubclass", 55, Long.class,
+ * null},
+ * {"Lookup", "testSelfSendToPrivateMethodFromSubclass", 55, Long.class, null},
+ * {"SuperSends", "testSuperClassClause1A", 44, Long.class, null},
+ * {"SuperSends", "testSuperClassClause1B", 88, Long.class, null},
+ * {"SuperSends", "testSuperClassClause2A", 44, Long.class, null},
+ * {"SuperSends", "testSuperClassClause2B", 88, Long.class, null},
+ * {"SuperSends", "testSuperClassClause3A", 44, Long.class, null},
+ * {"SuperSends", "testSuperClassClause3B", 88, Long.class, null},
+ * {"SuperSends", "testSuperClassClause4A", 44, Long.class, null},
+ * {"SuperSends", "testSuperClassClause4B", 88, Long.class, null},
+ * {"SuperSends", "testSuperInBlock1", 42, Long.class, null},
+ * {"SuperSends", "testSuperInBlock2", 42, Long.class, null},
+ * {"OuterSends", "testOuterBindings1", 3, Long.class, null},
+ * {"OuterSends", "testOuterBindings2", 2, Long.class, null},
+ * {"OuterSends", "testOuterBindings3", 6, Long.class, null},
+ * {"OuterSends", "testOuterSendLegalTargets", 666, Long.class, null},
+ * {"ObjectCreation", "testNew", "ObjectCreation", Object.class, null},
+ * {"ObjectCreation", "testImmutableRead", 3, Long.class, null},
+ * {"ObjectCreation", "testImmutableReadInner", 42, Long.class, null},
+ */
+
+ {"Parser", "testOuterInKeyword", 32 * 32 * 32, Long.class, null},
{"Parser", "testOuterWithKeyword", 3 * 4, Long.class, null},
- {"Parser", "testOuterInheritancePrefix", 32, Long.class, null},
-
- {"Initializers", "testInit1", 42, Long.class, null},
- {"Initializers", "testInit2", 42, Long.class, null},
- {"DoesNotUnderstand", "test", "Foo", SSymbol.class, null},
-
- {"Exceptions", "testSignalOnDo", 4, Long.class, null},
- {"Exceptions", "testSignalOnDoMethod", 5, Long.class, null},
- {"Exceptions", "testNestedSignalOnDo", 22, Long.class, UNSAFE_OM},
- {"Exceptions", "testSignalOnDoMethod", 5, Long.class, UNSAFE_OM},
- {"Exceptions", "testCustomExceptionSignalOnDo", 343, Long.class, UNSAFE_OM},
- {"Exceptions", "testEnsure", 444, Long.class, UNSAFE_OM},
- {"Exceptions", "testEnsureWithSignal", 66, Long.class, UNSAFE_OM},
+ {"Parser", "testOuterInKeyword", 32 * 32 * 32, Long.class, null},
+ {"Parser", "testOuterWithKeyword", 3 * 4, Long.class, null},
+ {"Parser", "testOuterInKeyword", 32 * 32 * 32, Long.class, null},
+ {"Parser", "testOuterWithKeyword", 3 * 4, Long.class, null},
+ {"Parser", "testOuterInKeyword", 32 * 32 * 32, Long.class, null},
+ {"Parser", "testOuterWithKeyword", 3 * 4, Long.class, null},
+ {"Parser", "testOuterInKeyword", 32 * 32 * 32, Long.class, null},
+ {"Parser", "testOuterWithKeyword", 3 * 4, Long.class, null},
+ {"Parser", "testOuterInKeyword", 32 * 32 * 32, Long.class, null},
+ {"Parser", "testOuterWithKeyword", 3 * 4, Long.class, null},
+ {"Parser", "testOuterInKeyword", 32 * 32 * 32, Long.class, null},
+ {"Parser", "testOuterWithKeyword", 3 * 4, Long.class, null},
+ {"Parser", "testOuterInKeyword", 32 * 32 * 32, Long.class, null},
+ {"Parser", "testOuterWithKeyword", 3 * 4, Long.class, null},
+ {"Parser", "testOuterInKeyword", 32 * 32 * 32, Long.class, null},
+ {"Parser", "testOuterWithKeyword", 3 * 4, Long.class, null},
+ {"Parser", "testOuterInKeyword", 32 * 32 * 32, Long.class, null},
+ {"Parser", "testOuterWithKeyword", 3 * 4, Long.class, null},
+ {"Parser", "testOuterInKeyword", 32 * 32 * 32, Long.class, null},
+ {"Parser", "testOuterWithKeyword", 3 * 4, Long.class, null},
- {"FieldAccess", "inheritanceOfLocalClass", 33, Long.class, null},
+ {"Parser", "testOuterInheritancePrefix", 32, Long.class, null},
+ /*
+ * {"Initializers", "testInit1", 42, Long.class, null},
+ * {"Initializers", "testInit2", 42, Long.class, null},
+ * {"DoesNotUnderstand", "test", "Foo", SSymbol.class, null},
+ * {"Exceptions", "testSignalOnDo", 4, Long.class, null},
+ * {"Exceptions", "testSignalOnDoMethod", 5, Long.class, null},
+ * {"Exceptions", "testNestedSignalOnDo", 22, Long.class, null},
+ * {"Exceptions", "testSignalOnDoMethod", 5, Long.class, null},
+ * {"Exceptions", "testCustomExceptionSignalOnDo", 343, Long.class, null},
+ * {"Exceptions", "testEnsure", 444, Long.class, null},
+ * {"Exceptions", "testEnsureWithSignal", 66, Long.class, null},
+ * {"FieldAccess", "inheritanceOfLocalClass", 33, Long.class, null},
+ */
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment