Skip to content

Commit

Permalink
Attempt at bandaid fixing concurrency issues
Browse files Browse the repository at this point in the history
  • Loading branch information
LatvianModder committed Dec 9, 2023
1 parent 9332a65 commit 278a047
Show file tree
Hide file tree
Showing 13 changed files with 81 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ public ArrowFunction(Context cx, Scriptable scope, Callable targetFunction, Scri
}

@Override
public synchronized Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
Scriptable callThis = boundThis != null ? boundThis : ScriptRuntime.getTopCallScope(cx);
public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
Scriptable callThis = boundThis != null ? boundThis : cx.getTopCallOrThrow();
return targetFunction.call(cx, scope, callThis, args);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public BoundFunction(Context cx, Scriptable scope, Callable targetFunction, Scri

@Override
public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] extraArgs) {
Scriptable callThis = boundThis != null ? boundThis : ScriptRuntime.getTopCallScope(cx);
Scriptable callThis = boundThis != null ? boundThis : cx.getTopCallOrThrow();
return targetFunction.call(cx, scope, callThis, concat(boundArgs, extraArgs));
}

Expand Down
52 changes: 38 additions & 14 deletions common/src/main/java/dev/latvian/mods/rhino/Context.java
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ public static String getSourcePositionFromStack(Context cx, int[] linep) {

// Generate an observer count on compiled code
public boolean generateObserverCount = false;
Scriptable topCallScope;
private Scriptable topCallScope;
boolean isContinuationsTopCall;
NativeCall currentActivationCall;
BaseFunction typeErrorThrower;
Expand All @@ -358,12 +358,9 @@ public static String getSourcePositionFromStack(Context cx, int[] linep) {
// It can be used to return the second uint32 result from function
long scratchUint32;
// It can be used to return the second Scriptable result from function
Scriptable scratchScriptable;
private Scriptable scratchScriptable;
boolean isTopLevelStrict;
private Object sealKey;
private ErrorReporter errorReporter;
private int maximumInterpreterStackDepth;
private Object propertyListeners;
private Map<Object, Object> threadLocalMap;
private ClassLoader applicationClassLoader;

Expand All @@ -385,10 +382,6 @@ public static String getSourcePositionFromStack(Context cx, int[] linep) {
* Creates a new context. Provided as a preferred super constructor for
* subclasses in place of the deprecated default public constructor.
*
* @param factory the context factory associated with this context (most
* likely, the one that created the context). Can not be null. The context
* features are inherited from the factory, and the context will also
* otherwise use its factory's services.
* @throws IllegalArgumentException if factory parameter is null.
*/
protected Context() {
Expand Down Expand Up @@ -421,10 +414,7 @@ public final String getImplementationVersion() {
* @see ErrorReporter
*/
public final ErrorReporter getErrorReporter() {
if (errorReporter == null) {
return DefaultErrorReporter.instance;
}
return errorReporter;
return DefaultErrorReporter.instance;
}

/**
Expand Down Expand Up @@ -681,7 +671,7 @@ public Object callFunctionWithContinuations(Callable function, Scriptable scope,
// Can only be applied to scripts
throw new IllegalArgumentException("Function argument was not" + " created by interpreted mode ");
}
if (ScriptRuntime.hasTopCall(this)) {
if (hasTopCallScope()) {
throw new IllegalStateException("Cannot have any pending top " + "calls when executing a script with continuations");
}
// Annotate so we can check later to ensure no java code in
Expand Down Expand Up @@ -1368,4 +1358,38 @@ public final void setWrapFactory(WrapFactory wrapFactory) {
}
this.wrapFactory = wrapFactory;
}

public synchronized boolean hasTopCallScope() {
return topCallScope != null;
}

public synchronized Scriptable getTopCallScope() {
return topCallScope;
}

public synchronized Scriptable getTopCallOrThrow() {
if (topCallScope == null) {
throw new IllegalStateException();
}

return topCallScope;
}

public synchronized void setTopCall(Scriptable scope) {
topCallScope = scope;
}

public synchronized void storeScriptable(Scriptable value) {
// The previously stored scratchScriptable should be consumed
if (scratchScriptable != null) {
throw new IllegalStateException();
}
scratchScriptable = value;
}

public synchronized Scriptable lastStoredScriptable() {
Scriptable result = scratchScriptable;
scratchScriptable = null;
return result;
}
}
4 changes: 2 additions & 2 deletions common/src/main/java/dev/latvian/mods/rhino/ES6Generator.java
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ private Scriptable resumeDelegee(Context cx, Scriptable scope, Object value) {
Object[] nextArgs = Undefined.instance.equals(value) ? ScriptRuntime.EMPTY_OBJECTS : new Object[]{value};

Callable nextFn = ScriptRuntime.getPropFunctionAndThis(cx, scope, delegee, ES6Iterator.NEXT_METHOD);
Scriptable nextThis = ScriptRuntime.lastStoredScriptable(cx);
Scriptable nextThis = cx.lastStoredScriptable();
Object nr = nextFn.call(cx, scope, nextThis, nextArgs);

Scriptable nextResult = ScriptableObject.ensureScriptable(nr, cx);
Expand Down Expand Up @@ -178,7 +178,7 @@ private Scriptable resumeDelegeeThrow(Context cx, Scriptable scope, Object value
try {
// Delegate to "throw" method. If it's not defined we'll get an error here.
Callable throwFn = ScriptRuntime.getPropFunctionAndThis(cx, scope, delegee, "throw");
Scriptable nextThis = ScriptRuntime.lastStoredScriptable(cx);
Scriptable nextThis = cx.lastStoredScriptable();
Object throwResult = throwFn.call(cx, scope, nextThis, new Object[]{value});

if (ScriptRuntime.isIteratorDone(cx, throwResult)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ static Object create(Context cx, Class<?> cl, ScriptableObject object) {
throw new IllegalArgumentException();
}

Scriptable topScope = ScriptRuntime.getTopCallScope(cx);
Scriptable topScope = cx.getTopCallOrThrow();
InterfaceAdapter adapter;
adapter = (InterfaceAdapter) cx.getInterfaceAdapter(cl);
if (adapter == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public String getFunctionName() {
*/
@Override
public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
if (!ScriptRuntime.hasTopCall(cx)) {
if (!cx.hasTopCallScope()) {
return ScriptRuntime.doTopCall(cx, scope, this, thisObj, args, idata.isStrict);
}
return Interpreter.interpret(this, cx, scope, thisObj, args);
Expand All @@ -78,7 +78,7 @@ public Object exec(Context cx, Scriptable scope) {
// Can only be applied to scripts
throw new IllegalStateException();
}
if (!ScriptRuntime.hasTopCall(cx)) {
if (!cx.hasTopCallScope()) {
// It will go through "call" path. but they are equivalent
return ScriptRuntime.doTopCall(cx, scope, this, scope, ScriptRuntime.EMPTY_OBJECTS, idata.isStrict);
}
Expand Down
18 changes: 9 additions & 9 deletions common/src/main/java/dev/latvian/mods/rhino/Interpreter.java
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ public boolean equals(Object other) {
// in order to evaluate their attributes.
//final Context cx = Context.enter();
//try {
if (ScriptRuntime.hasTopCall(localContext)) {
if (localContext.hasTopCallScope()) {
return equalsInTopScope(otherCallFrame);
}
final Scriptable top = ScriptableObject.getTopLevelScope(scope);
Expand Down Expand Up @@ -412,7 +412,7 @@ private static void initFunction(Context cx, Scriptable scope, InterpretedFuncti
}

static Object interpret(InterpretedFunction ifun, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
if (!ScriptRuntime.hasTopCall(cx)) {
if (!cx.hasTopCallScope()) {
Kit.codeBug();
}

Expand Down Expand Up @@ -445,7 +445,7 @@ public static Object resumeGenerator(Context cx, Scriptable scope, int operation
}

public static Object restartContinuation(NativeContinuation c, Context cx, Scriptable scope, Object[] args) {
if (!ScriptRuntime.hasTopCall(cx)) {
if (!cx.hasTopCallScope()) {
return ScriptRuntime.doTopCall(cx, scope, c, null, args, cx.isTopLevelStrict);
}

Expand Down Expand Up @@ -935,7 +935,7 @@ private static Object interpretLoop(Context cx, CallFrame frame, Object throwabl
++stackTop;
stack[stackTop] = ScriptRuntime.getNameFunctionAndThis(cx, frame.scope, stringReg);
++stackTop;
stack[stackTop] = ScriptRuntime.lastStoredScriptable(cx);
stack[stackTop] = cx.lastStoredScriptable();
continue;
case Icode_PROP_AND_THIS: {
Object obj = stack[stackTop];
Expand All @@ -945,7 +945,7 @@ private static Object interpretLoop(Context cx, CallFrame frame, Object throwabl
// stringReg: property
stack[stackTop] = ScriptRuntime.getPropFunctionAndThis(cx, frame.scope, obj, stringReg);
++stackTop;
stack[stackTop] = ScriptRuntime.lastStoredScriptable(cx);
stack[stackTop] = cx.lastStoredScriptable();
continue;
}
case Icode_ELEM_AND_THIS: {
Expand All @@ -958,7 +958,7 @@ private static Object interpretLoop(Context cx, CallFrame frame, Object throwabl
id = ScriptRuntime.wrapNumber(sDbl[stackTop]);
}
stack[stackTop - 1] = ScriptRuntime.getElemFunctionAndThis(cx, frame.scope, obj, id);
stack[stackTop] = ScriptRuntime.lastStoredScriptable(cx);
stack[stackTop] = cx.lastStoredScriptable();
continue;
}
case Icode_VALUE_AND_THIS: {
Expand All @@ -968,7 +968,7 @@ private static Object interpretLoop(Context cx, CallFrame frame, Object throwabl
}
stack[stackTop] = ScriptRuntime.getValueFunctionAndThis(cx, value);
++stackTop;
stack[stackTop] = ScriptRuntime.lastStoredScriptable(cx);
stack[stackTop] = cx.lastStoredScriptable();
continue;
}
case Icode_CALLSPECIAL: {
Expand Down Expand Up @@ -2118,7 +2118,7 @@ private static CallFrame initFrameForApplyOrCall(Context cx, CallFrame frame, in
}
if (applyThis == null) {
// This covers the case of args[0] == (null|undefined) as well.
applyThis = ScriptRuntime.getTopCallScope(cx);
applyThis = cx.getTopCallOrThrow();
}
if (op == Icode_TAIL_CALL) {
exitFrame(cx, frame, null);
Expand Down Expand Up @@ -2223,7 +2223,7 @@ public static NativeContinuation captureContinuation(Context cx) {

private static NativeContinuation captureContinuation(Context cx, CallFrame frame, boolean requireContinuationsTopFrame) {
NativeContinuation c = new NativeContinuation();
ScriptRuntime.setObjectProtoAndParent(cx, ScriptRuntime.getTopCallScope(cx), c);
ScriptRuntime.setObjectProtoAndParent(cx, cx.getTopCallOrThrow(), c);

// Make sure that all frames are frozen
CallFrame x = frame;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public IteratorLikeIterable(Context cx, Scriptable scope, Object target) {
this.scope = scope;
// This will throw if "next" is not a function or undefined
next = ScriptRuntime.getPropFunctionAndThis(cx, scope, target, ES6Iterator.NEXT_METHOD);
iterator = ScriptRuntime.lastStoredScriptable(cx);
iterator = cx.lastStoredScriptable();
Object retObj = ScriptRuntime.getObjectPropNoWarn(cx, scope, target, ES6Iterator.RETURN_PROPERTY);
// We only care about "return" if it is not null or undefined
if ((retObj != null) && !Undefined.isUndefined(retObj)) {
Expand Down
4 changes: 2 additions & 2 deletions common/src/main/java/dev/latvian/mods/rhino/NativeArray.java
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ private static String toStringHelper(Context cx, Scriptable scope, Scriptable th
Callable fun;
Scriptable funThis;
fun = ScriptRuntime.getPropFunctionAndThis(cx, scope, elem, "toLocaleString");
funThis = ScriptRuntime.lastStoredScriptable(cx);
funThis = cx.lastStoredScriptable();
elem = fun.call(cx, scope, funThis, ScriptRuntime.EMPTY_OBJECTS);
}
result.append(ScriptRuntime.toString(cx, elem));
Expand Down Expand Up @@ -586,7 +586,7 @@ private static Scriptable js_sort(final Context cx, final Scriptable scope, fina
final Comparator<Object> comparator;
if (args.length > 0 && Undefined.instance != args[0]) {
final Callable jsCompareFunction = ScriptRuntime.getValueFunctionAndThis(cx, args[0]);
final Scriptable funThis = ScriptRuntime.lastStoredScriptable(cx);
final Scriptable funThis = cx.lastStoredScriptable();
final Object[] cmpBuf = new Object[2]; // Buffer for cmp arguments
comparator = new ElementComparator((x, y) -> {
// This comparator is invoked only for non-undefined objects
Expand Down
2 changes: 1 addition & 1 deletion common/src/main/java/dev/latvian/mods/rhino/NativeMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ static void loadFromIterable(Context cx, Scriptable scope, ScriptableObject map,
// so that we can get our own prototype.
ScriptableObject dummy = ensureScriptableObject(cx.newObject(scope, map.getClassName()), cx);
final Callable set = ScriptRuntime.getPropFunctionAndThis(cx, scope, dummy.getPrototype(cx), "set");
ScriptRuntime.lastStoredScriptable(cx);
cx.lastStoredScriptable();

// Finally, run through all the iterated values and add them!
try (IteratorLikeIterable it = new IteratorLikeIterable(cx, scope, ito)) {
Expand Down
2 changes: 1 addition & 1 deletion common/src/main/java/dev/latvian/mods/rhino/NativeSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ static void loadFromIterable(Context cx, Scriptable scope, ScriptableObject set,
ScriptableObject dummy = ensureScriptableObject(cx.newObject(scope, set.getClassName()), cx);
final Callable add = ScriptRuntime.getPropFunctionAndThis(cx, scope, dummy.getPrototype(cx), "add");
// Clean up the value left around by the previous function
ScriptRuntime.lastStoredScriptable(cx);
cx.lastStoredScriptable();

// Finally, run through all the iterated values and add them!
try (IteratorLikeIterable it = new IteratorLikeIterable(cx, scope, ito)) {
Expand Down
Loading

0 comments on commit 278a047

Please sign in to comment.