Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (221471 => 221472)
--- trunk/Source/_javascript_Core/ChangeLog 2017-09-01 04:10:20 UTC (rev 221471)
+++ trunk/Source/_javascript_Core/ChangeLog 2017-09-01 05:41:08 UTC (rev 221472)
@@ -1,5 +1,55 @@
2017-08-31 Saam Barati <sbar...@apple.com>
+ Throwing an exception in the DFG/FTL should not cause a jettison
+ https://bugs.webkit.org/show_bug.cgi?id=176060
+ <rdar://problem/34143348>
+
+ Reviewed by Keith Miller.
+
+ Throwing an exception is not something that should be a jettison-able
+ OSR exit. We used to count Throw/ThrowStaticError towards our OSR exit
+ counts which could cause a CodeBlock to jettison and recompile. This
+ was dumb. Throwing an exception is not a reason to jettison and
+ recompile in the way that a speculation failure is. This patch
+ treats Throw/ThrowStaticError as true terminals in DFG IR.
+
+ * bytecode/BytecodeUseDef.h:
+ (JSC::computeUsesForBytecodeOffset):
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+ * dfg/DFGInPlaceAbstractState.cpp:
+ (JSC::DFG::InPlaceAbstractState::mergeToSuccessors):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::isTerminal):
+ (JSC::DFG::Node::isPseudoTerminal):
+ (JSC::DFG::Node::errorType):
+ * dfg/DFGNodeType.h:
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGOperations.h:
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileThrow):
+ (JSC::DFG::SpeculativeJIT::compileThrowStaticError):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::callOperation):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * ftl/FTLLowerDFGToB3.cpp:
+ (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+ (JSC::FTL::DFG::LowerDFGToB3::compileThrow):
+ (JSC::FTL::DFG::LowerDFGToB3::compileThrowStaticError):
+ * jit/JITOperations.h:
+
+2017-08-31 Saam Barati <sbar...@apple.com>
+
Graph::methodOfGettingAValueProfileFor compares NodeOrigin instead of the semantic CodeOrigin
https://bugs.webkit.org/show_bug.cgi?id=176206
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h (221471 => 221472)
--- trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h 2017-09-01 04:10:20 UTC (rev 221471)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h 2017-09-01 05:41:08 UTC (rev 221472)
@@ -63,6 +63,7 @@
case op_identity_with_profile:
case op_profile_type:
case op_throw:
+ case op_throw_static_error:
case op_end:
case op_ret:
case op_jtrue:
@@ -71,8 +72,7 @@
case op_jneq_null:
case op_dec:
case op_inc:
- case op_log_shadow_chicken_prologue:
- case op_throw_static_error: {
+ case op_log_shadow_chicken_prologue: {
ASSERT(opcodeLengths[opcodeID] > 1);
functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
return;
Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (221471 => 221472)
--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2017-09-01 04:10:20 UTC (rev 221471)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2017-09-01 05:41:08 UTC (rev 221472)
@@ -1870,6 +1870,8 @@
m_state.setIsValid(false);
break;
+ case Throw:
+ case ThrowStaticError:
case TailCall:
case DirectTailCall:
case TailCallVarargs:
@@ -1878,11 +1880,6 @@
m_state.setIsValid(false);
break;
- case Throw:
- case ThrowStaticError:
- m_state.setIsValid(false);
- break;
-
case ToPrimitive: {
JSValue childConst = forNode(node->child1()).value();
if (childConst && childConst.isNumber()) {
Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (221471 => 221472)
--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2017-09-01 04:10:20 UTC (rev 221471)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2017-09-01 05:41:08 UTC (rev 221472)
@@ -5216,15 +5216,14 @@
case op_throw:
addToGraph(Throw, get(VirtualRegister(currentInstruction[1].u.operand)));
flushForTerminal();
- addToGraph(Unreachable);
LAST_OPCODE(op_throw);
- case op_throw_static_error:
- addToGraph(ThrowStaticError);
- addToGraph(Phantom, get(VirtualRegister(currentInstruction[1].u.operand))); // Keep argument live.
+ case op_throw_static_error: {
+ uint32_t errorType = currentInstruction[2].u.unsignedValue;
+ addToGraph(ThrowStaticError, OpInfo(errorType), get(VirtualRegister(currentInstruction[1].u.operand)));
flushForTerminal();
- addToGraph(Unreachable);
LAST_OPCODE(op_throw_static_error);
+ }
case op_catch: {
m_graph.m_hasExceptionHandlers = true;
Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (221471 => 221472)
--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2017-09-01 04:10:20 UTC (rev 221471)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2017-09-01 05:41:08 UTC (rev 221472)
@@ -426,7 +426,6 @@
case Jump:
case Branch:
case Switch:
- case Throw:
case ForceOSRExit:
case CheckBadCell:
case Return:
@@ -648,6 +647,8 @@
write(Heap);
return;
+ case Throw:
+ case ThrowStaticError:
case TailCall:
case DirectTailCall:
case TailCallVarargs:
@@ -1530,10 +1531,6 @@
return;
}
- case ThrowStaticError:
- write(SideState);
- return;
-
case CountExecution:
read(InternalState);
write(InternalState);
Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (221471 => 221472)
--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2017-09-01 04:10:20 UTC (rev 221471)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2017-09-01 05:41:08 UTC (rev 221472)
@@ -1948,6 +1948,10 @@
break;
}
+ case ThrowStaticError:
+ fixEdge<StringUse>(node->child1());
+ break;
+
#if !ASSERT_DISABLED
// Have these no-op cases here to ensure that nobody forgets to add handlers for new opcodes.
case SetArgument:
@@ -2000,7 +2004,6 @@
case DirectTailCall:
case TailCallVarargs:
case Throw:
- case ThrowStaticError:
case CountExecution:
case ForceOSRExit:
case CheckBadCell:
Modified: trunk/Source/_javascript_Core/dfg/DFGInPlaceAbstractState.cpp (221471 => 221472)
--- trunk/Source/_javascript_Core/dfg/DFGInPlaceAbstractState.cpp 2017-09-01 04:10:20 UTC (rev 221471)
+++ trunk/Source/_javascript_Core/dfg/DFGInPlaceAbstractState.cpp 2017-09-01 05:41:08 UTC (rev 221472)
@@ -378,6 +378,8 @@
case TailCallVarargs:
case TailCallForwardVarargs:
case Unreachable:
+ case Throw:
+ case ThrowStaticError:
ASSERT(basicBlock->cfaBranchDirection == InvalidBranchDirection);
return false;
Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (221471 => 221472)
--- trunk/Source/_javascript_Core/dfg/DFGNode.h 2017-09-01 04:10:20 UTC (rev 221471)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h 2017-09-01 05:41:08 UTC (rev 221472)
@@ -1318,6 +1318,8 @@
case TailCallVarargs:
case TailCallForwardVarargs:
case Unreachable:
+ case Throw:
+ case ThrowStaticError:
return true;
default:
return false;
@@ -1342,8 +1344,6 @@
switch (op()) {
case ForceOSRExit:
case CheckBadCell:
- case Throw:
- case ThrowStaticError:
return true;
default:
return false;
@@ -2583,6 +2583,12 @@
return m_opInfo.as<BucketOwnerType>();
}
+ uint32_t errorType()
+ {
+ ASSERT(op() == ThrowStaticError);
+ return m_opInfo.as<uint32_t>();
+ }
+
void dumpChildren(PrintStream& out)
{
if (!child1())
Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (221471 => 221472)
--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2017-09-01 04:10:20 UTC (rev 221471)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2017-09-01 05:41:08 UTC (rev 221472)
@@ -385,10 +385,6 @@
\
macro(NewAsyncFunction, NodeResultJS) \
\
- /* These aren't terminals but always exit */ \
- macro(Throw, NodeMustGenerate) \
- macro(ThrowStaticError, NodeMustGenerate) \
- \
/* Block terminals. */\
macro(Jump, NodeMustGenerate) \
macro(Branch, NodeMustGenerate) \
@@ -399,6 +395,8 @@
macro(TailCallVarargs, NodeMustGenerate) \
macro(TailCallForwardVarargs, NodeMustGenerate) \
macro(Unreachable, NodeMustGenerate) \
+ macro(Throw, NodeMustGenerate) \
+ macro(ThrowStaticError, NodeMustGenerate) \
\
/* Count execution. */\
macro(CountExecution, NodeMustGenerate) \
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (221471 => 221472)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2017-09-01 04:10:20 UTC (rev 221471)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2017-09-01 05:41:08 UTC (rev 221472)
@@ -2313,6 +2313,23 @@
return *bucket;
}
+void JIT_OPERATION operationThrowDFG(ExecState* exec, EncodedJSValue valueToThrow)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ scope.throwException(exec, JSValue::decode(valueToThrow));
+}
+
+void JIT_OPERATION operationThrowStaticError(ExecState* exec, JSString* message, uint32_t errorType)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ String errorMessage = message->value(exec);
+ scope.throwException(exec, createError(exec, static_cast<ErrorType>(errorType), errorMessage));
+}
+
extern "C" void JIT_OPERATION triggerReoptimizationNow(CodeBlock* codeBlock, OSRExitBase* exit)
{
// It's sort of preferable that we don't GC while in here. Anyways, doing so wouldn't
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (221471 => 221472)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.h 2017-09-01 04:10:20 UTC (rev 221471)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h 2017-09-01 05:41:08 UTC (rev 221472)
@@ -202,6 +202,8 @@
void JIT_OPERATION operationThrowStackOverflowForVarargs(ExecState*) WTF_INTERNAL;
int32_t JIT_OPERATION operationSizeOfVarargs(ExecState*, EncodedJSValue arguments, int32_t firstVarArgOffset);
void JIT_OPERATION operationLoadVarargs(ExecState*, int32_t firstElementDest, EncodedJSValue arguments, int32_t offset, int32_t length, int32_t mandatoryMinimum);
+void JIT_OPERATION operationThrowDFG(ExecState*, EncodedJSValue);
+void JIT_OPERATION operationThrowStaticError(ExecState*, JSString*, uint32_t);
int32_t JIT_OPERATION operationHasOwnProperty(ExecState*, JSObject*, EncodedJSValue);
Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (221471 => 221472)
--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2017-09-01 04:10:20 UTC (rev 221471)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2017-09-01 05:41:08 UTC (rev 221472)
@@ -1106,11 +1106,12 @@
case PutClosureVar:
case PutToArguments:
case Return:
+ case Throw:
+ case ThrowStaticError:
case TailCall:
case DirectTailCall:
case TailCallVarargs:
case TailCallForwardVarargs:
- case Throw:
case PutById:
case PutByIdFlush:
case PutByIdDirect:
@@ -1128,7 +1129,6 @@
case Switch:
case ProfileType:
case ProfileControlFlow:
- case ThrowStaticError:
case ForceOSRExit:
case SetArgument:
case SetFunctionName:
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (221471 => 221472)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2017-09-01 04:10:20 UTC (rev 221471)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2017-09-01 05:41:08 UTC (rev 221472)
@@ -10284,6 +10284,29 @@
jsValueResult(resultRegs, node);
}
+void SpeculativeJIT::compileThrow(Node* node)
+{
+ JSValueOperand value(this, node->child1());
+ JSValueRegs valueRegs = value.jsValueRegs();
+ flushRegisters();
+ callOperation(operationThrowDFG, valueRegs);
+ m_jit.exceptionCheck();
+ m_jit.breakpoint();
+ noResult(node);
+}
+
+void SpeculativeJIT::compileThrowStaticError(Node* node)
+{
+ SpeculateCellOperand message(this, node->child1());
+ GPRReg messageGPR = message.gpr();
+ speculateString(node->child1(), messageGPR);
+ flushRegisters();
+ callOperation(operationThrowStaticError, messageGPR, node->errorType());
+ m_jit.exceptionCheck();
+ m_jit.breakpoint();
+ noResult(node);
+}
+
} } // namespace JSC::DFG
#endif
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (221471 => 221472)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2017-09-01 04:10:20 UTC (rev 221471)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2017-09-01 05:41:08 UTC (rev 221472)
@@ -962,6 +962,11 @@
m_jit.setupArgumentsWithExecState(arg1, arg2);
return appendCallSetResult(operation, result);
}
+ JITCompiler::Call callOperation(V_JITOperation_EJssUi operation, GPRReg arg1, uint32_t arg2)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, TrustedImm32(arg2));
+ return appendCall(operation);
+ }
JITCompiler::Call callOperation(P_JITOperation_EO operation, GPRReg result, GPRReg object)
{
m_jit.setupArgumentsWithExecState(object);
@@ -1380,7 +1385,17 @@
return appendCallSetResult(operation, result);
}
+ JITCompiler::Call callOperation(V_JITOperation_EJ operation, JSValueRegs arg1)
+ {
#if USE(JSVALUE64)
+ m_jit.setupArgumentsWithExecState(arg1.gpr());
+#else
+ m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1.payloadGPR(), arg1.tagGPR());
+#endif
+ return appendCall(operation);
+ }
+
+#if USE(JSVALUE64)
JITCompiler::Call callOperation(Z_JITOperation_EOJ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
{
m_jit.setupArgumentsWithExecState(arg1, arg2);
@@ -2388,12 +2403,6 @@
return appendCall(operation);
}
- JITCompiler::Call callOperation(V_JITOperation_EJ operation, JSValueRegs arg1)
- {
- m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1.payloadGPR(), arg1.tagGPR());
- return appendCall(operation);
- }
-
JITCompiler::Call callOperation(V_JITOperation_EJPP operation, JSValueRegs arg1, GPRReg arg2, void* pointer)
{
m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1.payloadGPR(), arg1.tagGPR(), arg2, TrustedImmPtr(pointer));
@@ -2915,6 +2924,8 @@
void compileDefineDataProperty(Node*);
void compileDefineAccessorProperty(Node*);
void compileToLowerCase(Node*);
+ void compileThrow(Node*);
+ void compileThrowStaticError(Node*);
void moveTrueTo(GPRReg);
void moveFalseTo(GPRReg);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (221471 => 221472)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2017-09-01 04:10:20 UTC (rev 221471)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2017-09-01 05:41:08 UTC (rev 221472)
@@ -3647,14 +3647,16 @@
break;
}
- case Throw:
+ case Throw: {
+ compileThrow(node);
+ break;
+ }
+
case ThrowStaticError: {
- // We expect that throw statements are rare and are intended to exit the code block
- // anyway, so we just OSR back to the old JIT for now.
- terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
+ compileThrowStaticError(node);
break;
}
-
+
case BooleanToNumber: {
switch (node->child1().useKind()) {
case BooleanUse: {
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (221471 => 221472)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2017-09-01 04:10:20 UTC (rev 221471)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2017-09-01 05:41:08 UTC (rev 221472)
@@ -3870,11 +3870,13 @@
break;
}
- case Throw:
+ case Throw: {
+ compileThrow(node);
+ break;
+ }
+
case ThrowStaticError: {
- // We expect that throw statements are rare and are intended to exit the code block
- // anyway, so we just OSR back to the old JIT for now.
- terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
+ compileThrowStaticError(node);
break;
}
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (221471 => 221472)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2017-09-01 04:10:20 UTC (rev 221471)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2017-09-01 05:41:08 UTC (rev 221472)
@@ -945,9 +945,11 @@
compileForceOSRExit();
break;
case Throw:
- case ThrowStaticError:
compileThrow();
break;
+ case ThrowStaticError:
+ compileThrowStaticError();
+ break;
case InvalidationPoint:
compileInvalidationPoint();
break;
@@ -7800,8 +7802,20 @@
void compileThrow()
{
- terminate(Uncountable);
+ LValue error = lowJSValue(m_node->child1());
+ vmCall(Void, m_out.operation(operationThrowDFG), m_callFrame, error);
+ // vmCall() does an exception check so we should never reach this.
+ m_out.unreachable();
}
+
+ void compileThrowStaticError()
+ {
+ LValue errorMessage = lowString(m_node->child1());
+ LValue errorType = m_out.constInt32(m_node->errorType());
+ vmCall(Void, m_out.operation(operationThrowStaticError), m_callFrame, errorMessage, errorType);
+ // vmCall() does an exception check so we should never reach this.
+ m_out.unreachable();
+ }
void compileInvalidationPoint()
{
Modified: trunk/Source/_javascript_Core/jit/JITOperations.h (221471 => 221472)
--- trunk/Source/_javascript_Core/jit/JITOperations.h 2017-09-01 04:10:20 UTC (rev 221471)
+++ trunk/Source/_javascript_Core/jit/JITOperations.h 2017-09-01 05:41:08 UTC (rev 221472)
@@ -296,6 +296,7 @@
typedef void (JIT_OPERATION *V_JITOperation_EVm)(ExecState*, VM*);
typedef void (JIT_OPERATION *V_JITOperation_J)(EncodedJSValue);
typedef void (JIT_OPERATION *V_JITOperation_Z)(int32_t);
+typedef void (JIT_OPERATION *V_JITOperation_EJssUi)(ExecState*, JSString*, uint32_t);
typedef JSCell* (JIT_OPERATION *C_JITOperation_ERUiUi)(ExecState*, Register*, uint32_t, uint32_t);
typedef void (JIT_OPERATION *V_JITOperation_EOJIUi)(ExecState*, JSObject*, EncodedJSValue, UniquedStringImpl*, uint32_t);
typedef char* (JIT_OPERATION *P_JITOperation_E)(ExecState*);