Diff
Modified: trunk/JSTests/ChangeLog (220723 => 220724)
--- trunk/JSTests/ChangeLog 2017-08-14 23:33:27 UTC (rev 220723)
+++ trunk/JSTests/ChangeLog 2017-08-14 23:37:06 UTC (rev 220724)
@@ -1,3 +1,16 @@
+2017-08-14 Robin Morisset <[email protected]>
+
+ Support the with keyword in DFG
+ https://bugs.webkit.org/show_bug.cgi?id=175470
+
+ Reviewed by Saam Barati.
+
+ Added a new stress-test for the 'with' keyword, that caught a bug in a
+ previous version of this code.
+
+ * stress/with.js: Added.
+ (i.with):
+
2017-08-14 Ryan Haddad <[email protected]>
Skip flaky JSC test test/fieldopts/objtypespec-newobj-invalidation.1.js
Added: trunk/JSTests/stress/with.js (0 => 220724)
--- trunk/JSTests/stress/with.js (rev 0)
+++ trunk/JSTests/stress/with.js 2017-08-14 23:37:06 UTC (rev 220724)
@@ -0,0 +1,36 @@
+for (var i = 0; i < 10000; ++i) {
+ var x = 1;
+ var y = 2;
+
+ var z = {a: 42};
+ with (z) {
+ x = y;
+ }
+ if (x !== 2 || y !== 2 || z.a !== 42) {
+ throw "Error: bad result, first case, for i = " + i;
+ }
+
+ z = {y: 42}
+ with (z) {
+ x = y;
+ }
+ if (x !== 42 || y !== 2 || z.y !== 42) {
+ throw "Error: bad result, second case, for i = " + i;
+ }
+
+ z = {x: 13};
+ with (z) {
+ x = y;
+ }
+ if (x !== 42 || y !== 2 || z.x !== 2) {
+ throw "Error: bad result, third case, for i = " + i;
+ }
+
+ z = {x:13, y:14};
+ with (z) {
+ x = y;
+ }
+ if (x !== 42 || y !== 2 || z.x !== 14 || z.y !== 14) {
+ throw "Error: bad result, fourth case, for i = " + i;
+ }
+}
Modified: trunk/Source/_javascript_Core/ChangeLog (220723 => 220724)
--- trunk/Source/_javascript_Core/ChangeLog 2017-08-14 23:33:27 UTC (rev 220723)
+++ trunk/Source/_javascript_Core/ChangeLog 2017-08-14 23:37:06 UTC (rev 220724)
@@ -1,3 +1,40 @@
+2017-08-14 Robin Morisset <[email protected]>
+
+ Support the 'with' keyword in DFG
+ https://bugs.webkit.org/show_bug.cgi?id=175470
+
+ Reviewed by Saam Barati.
+
+ Not particularly optimized at the moment, the goal is just to avoid
+ the DFG bailing out of any function with this keyword.
+
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * dfg/DFGCapabilities.cpp:
+ (JSC::DFG::capabilityLevel):
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGDoesGC.cpp:
+ (JSC::DFG::doesGC):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+ * dfg/DFGNodeType.h:
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ * dfg/DFGSafeToExecute.h:
+ (JSC::DFG::safeToExecute):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compilePushWithScope):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::callOperation):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * jit/JITOperations.cpp:
+ * jit/JITOperations.h:
+
2017-08-14 Mark Lam <[email protected]>
Add some convenience utility accessor methods to MacroAssembler::CPUState.
Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (220723 => 220724)
--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2017-08-14 23:33:27 UTC (rev 220723)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2017-08-14 23:37:06 UTC (rev 220724)
@@ -2062,6 +2062,13 @@
break;
}
+ case PushWithScope:
+ clobberWorld(node->origin.semantic, clobberLimit);
+
+ // We don't use the more precise withScopeStructure() here because it is a LazyProperty and may not yet be allocated.
+ forNode(node).setType(m_graph, SpecObjectOther);
+ break;
+
case CreateActivation:
case MaterializeCreateActivation:
forNode(node).set(
Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (220723 => 220724)
--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2017-08-14 23:33:27 UTC (rev 220723)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2017-08-14 23:37:06 UTC (rev 220724)
@@ -5639,6 +5639,13 @@
NEXT_OPCODE(op_create_lexical_environment);
}
+ case op_push_with_scope: {
+ Node* scopeObject = get(VirtualRegister(currentInstruction[2].u.operand));
+ Node* currentScope = get(VirtualRegister(currentInstruction[3].u.operand));
+ set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(PushWithScope, scopeObject, currentScope));
+ NEXT_OPCODE(op_push_with_scope);
+ }
+
case op_get_parent_scope: {
Node* currentScope = get(VirtualRegister(currentInstruction[2].u.operand));
Node* newScope = addToGraph(SkipScope, currentScope);
Modified: trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp (220723 => 220724)
--- trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp 2017-08-14 23:33:27 UTC (rev 220723)
+++ trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp 2017-08-14 23:37:06 UTC (rev 220724)
@@ -245,6 +245,7 @@
case op_new_async_func_exp:
case op_set_function_name:
case op_create_lexical_environment:
+ case op_push_with_scope:
case op_get_parent_scope:
case op_catch:
case op_create_rest:
Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (220723 => 220724)
--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2017-08-14 23:33:27 UTC (rev 220723)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2017-08-14 23:37:06 UTC (rev 220724)
@@ -478,7 +478,7 @@
write(HeapObjectCount);
return;
}
-
+
case CreateDirectArguments:
case CreateScopedArguments:
case CreateClonedArguments:
@@ -604,6 +604,7 @@
case PutDynamicVar:
case ResolveScopeForHoistingFuncDeclInEval:
case ResolveScope:
+ case PushWithScope:
read(World);
write(Heap);
return;
Modified: trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp (220723 => 220724)
--- trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp 2017-08-14 23:33:27 UTC (rev 220723)
+++ trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp 2017-08-14 23:37:06 UTC (rev 220724)
@@ -279,6 +279,7 @@
case AtomicsSub:
case AtomicsXor:
case AtomicsIsLockFree:
+ case PushWithScope:
return false;
case CreateActivation:
Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (220723 => 220724)
--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2017-08-14 23:33:27 UTC (rev 220723)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2017-08-14 23:37:06 UTC (rev 220724)
@@ -1717,6 +1717,12 @@
break;
}
+ case PushWithScope: {
+ // Child2 is always the current scope, which is guaranteed to be an object.
+ fixEdge<KnownCellUse>(node->child2());
+ break;
+ }
+
case SetFunctionName: {
// The first child is guaranteed to be a cell because op_set_function_name is only used
// on a newly instantiated function object (the first child).
Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (220723 => 220724)
--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2017-08-14 23:33:27 UTC (rev 220723)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2017-08-14 23:37:06 UTC (rev 220724)
@@ -359,6 +359,7 @@
macro(HasOwnProperty, NodeResultBoolean) \
\
macro(CreateActivation, NodeResultJS) \
+ macro(PushWithScope, NodeResultJS | NodeMustGenerate) \
\
macro(CreateDirectArguments, NodeResultJS) \
macro(PhantomDirectArguments, NodeResultJS | NodeMustGenerate) \
Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (220723 => 220724)
--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2017-08-14 23:33:27 UTC (rev 220723)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2017-08-14 23:37:06 UTC (rev 220724)
@@ -895,6 +895,7 @@
break;
}
+ case PushWithScope:
case CreateActivation: {
setPrediction(SpecObjectOther);
break;
Modified: trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h (220723 => 220724)
--- trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2017-08-14 23:33:27 UTC (rev 220723)
+++ trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2017-08-14 23:37:06 UTC (rev 220724)
@@ -294,6 +294,7 @@
case MakeRope:
case In:
case HasOwnProperty:
+ case PushWithScope:
case CreateActivation:
case CreateDirectArguments:
case CreateScopedArguments:
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (220723 => 220724)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2017-08-14 23:33:27 UTC (rev 220723)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2017-08-14 23:37:06 UTC (rev 220724)
@@ -1124,6 +1124,23 @@
unblessedBooleanResult(resultGPR, node, UseChildrenCalledExplicitly);
}
+void SpeculativeJIT::compilePushWithScope(Node* node)
+{
+ JSValueOperand scopeObject(this, node->child1());
+ SpeculateCellOperand currentScope(this, node->child2());
+ JSValueRegs scopeObjectRegs = scopeObject.jsValueRegs();
+ GPRReg currentScopeGPR = currentScope.gpr();
+
+ GPRFlushedCallResult result(this);
+ GPRReg resultGPR = result.gpr();
+
+ flushRegisters();
+ callOperation(operationPushWithScope, resultGPR, currentScopeGPR, scopeObjectRegs);
+ m_jit.exceptionCheck();
+
+ cellResult(resultGPR, node);
+}
+
bool SpeculativeJIT::nonSpeculativeCompare(Node* node, MacroAssembler::RelationalCondition cond, S_JITOperation_EJJ helperFunction)
{
unsigned branchIndexInBlock = detectPeepHoleBranch();
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (220723 => 220724)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2017-08-14 23:33:27 UTC (rev 220723)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2017-08-14 23:37:06 UTC (rev 220724)
@@ -744,6 +744,7 @@
void compileDeleteById(Node*);
void compileDeleteByVal(Node*);
+ void compilePushWithScope(Node*);
void compileTryGetById(Node*);
void compileIn(Node*);
@@ -1390,6 +1391,11 @@
m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
return appendCallSetResult(operation, result);
}
+ JITCompiler::Call callOperation(C_JITOperation_ECJ operation, GPRReg result, GPRReg arg1, JSValueRegs arg2)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2.gpr());
+ return appendCallSetResult(operation, result);
+ }
JITCompiler::Call callOperation(J_JITOperation_EJMic operation, JSValueRegs result, JSValueRegs arg, TrustedImmPtr mathIC)
{
m_jit.setupArgumentsWithExecState(arg.gpr(), mathIC);
@@ -1939,6 +1945,11 @@
m_jit.setupArgumentsWithExecState(arg1, arg2.payloadGPR(), arg2.tagGPR(), arg3);
return appendCallSetResult(operation, result);
}
+ JITCompiler::Call callOperation(C_JITOperation_ECJ operation, GPRReg result, GPRReg arg1, JSValueRegs arg2)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2.payloadGPR(), arg2.tagGPR());
+ return appendCallSetResult(operation, result);
+ }
JITCompiler::Call callOperation(J_JITOperation_EJMic operation, JSValueRegs result, JSValueRegs arg, TrustedImmPtr mathIC)
{
m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg.payloadGPR(), arg.tagGPR(), mathIC);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (220723 => 220724)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2017-08-14 23:33:27 UTC (rev 220723)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2017-08-14 23:37:06 UTC (rev 220724)
@@ -5017,6 +5017,11 @@
compileCreateActivation(node);
break;
}
+
+ case PushWithScope: {
+ compilePushWithScope(node);
+ break;
+ }
case CreateDirectArguments: {
compileCreateDirectArguments(node);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (220723 => 220724)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2017-08-14 23:33:27 UTC (rev 220723)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2017-08-14 23:37:06 UTC (rev 220724)
@@ -5425,7 +5425,12 @@
compileCreateActivation(node);
break;
}
-
+
+ case PushWithScope: {
+ compilePushWithScope(node);
+ break;
+ }
+
case CreateDirectArguments: {
compileCreateDirectArguments(node);
break;
Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (220723 => 220724)
--- trunk/Source/_javascript_Core/jit/JITOperations.cpp 2017-08-14 23:33:27 UTC (rev 220723)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp 2017-08-14 23:37:06 UTC (rev 220724)
@@ -57,6 +57,7 @@
#include "JSGlobalObjectFunctions.h"
#include "JSLexicalEnvironment.h"
#include "JSPropertyNameEnumerator.h"
+#include "JSWithScope.h"
#include "ModuleProgramCodeBlock.h"
#include "ObjectConstructor.h"
#include "PolymorphicAccess.h"
@@ -1995,6 +1996,20 @@
return couldDelete;
}
+JSCell* JIT_OPERATION operationPushWithScope(ExecState* exec, JSCell* currentScopeCell, EncodedJSValue scopeObjectValue)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ JSObject* newScope = JSValue::decode(scopeObjectValue).toObject(exec);
+ RETURN_IF_EXCEPTION(scope, nullptr);
+
+ JSScope* currentScope = jsCast<JSScope*>(currentScopeCell);
+
+ return JSWithScope::create(vm, exec->lexicalGlobalObject(), newScope, currentScope);
+}
+
EncodedJSValue JIT_OPERATION operationInstanceOf(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedProto)
{
VM& vm = exec->vm();
Modified: trunk/Source/_javascript_Core/jit/JITOperations.h (220723 => 220724)
--- trunk/Source/_javascript_Core/jit/JITOperations.h 2017-08-14 23:33:27 UTC (rev 220723)
+++ trunk/Source/_javascript_Core/jit/JITOperations.h 2017-08-14 23:37:06 UTC (rev 220724)
@@ -212,6 +212,7 @@
typedef JSCell* (JIT_OPERATION *C_JITOperation_EZ)(ExecState*, int32_t);
typedef JSCell* (JIT_OPERATION *C_JITOperation_EJscI)(ExecState*, JSScope*, UniquedStringImpl*);
typedef JSCell* (JIT_OPERATION *C_JITOperation_ECJZ)(ExecState*, JSCell*, EncodedJSValue, int32_t);
+typedef JSCell* (JIT_OPERATION *C_JITOperation_ECJ)(ExecState*, JSCell*, EncodedJSValue);
typedef double (JIT_OPERATION *D_JITOperation_D)(double);
typedef double (JIT_OPERATION *D_JITOperation_G)(JSGlobalObject*);
typedef double (JIT_OPERATION *D_JITOperation_DD)(double, double);
@@ -418,6 +419,7 @@
size_t JIT_OPERATION operationDeleteById(ExecState*, EncodedJSValue base, UniquedStringImpl*) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationDeleteByValJSResult(ExecState*, EncodedJSValue base, EncodedJSValue target) WTF_INTERNAL;
size_t JIT_OPERATION operationDeleteByVal(ExecState*, EncodedJSValue base, EncodedJSValue target) WTF_INTERNAL;
+JSCell* JIT_OPERATION operationPushWithScope(ExecState*, JSCell* currentScopeCell, EncodedJSValue scopeObject) WTF_INTERNAL;
JSCell* JIT_OPERATION operationGetPNames(ExecState*, JSObject*) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationInstanceOf(ExecState*, EncodedJSValue, EncodedJSValue proto) WTF_INTERNAL;
int32_t JIT_OPERATION operationSizeFrameForForwardArguments(ExecState*, EncodedJSValue arguments, int32_t numUsedStackSlots, int32_t firstVarArgOffset) WTF_INTERNAL;