We should support delete in the DFG
https://bugs.webkit.org/show_bug.cgi?id=156607
Reviewed by Benjamin Poulain.
This patch adds support for the delete in the DFG as it appears that
some major frameworks use the operation in particularly hot functions.
As a result, even if the function rarely ever calls delete we would never
tier up to the DFG. This patch also changes operationDeleteById to take a
UniquedStringImpl and return a size_t.
* 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/DFGNode.h:
(JSC::DFG::Node::hasIdentifier):
* dfg/DFGNodeType.h:
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileDeleteById):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::callOperation):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* jit/JIT.h:
* jit/JITInlines.h:
(JSC::JIT::callOperation):
* jit/JITOperations.cpp:
* jit/JITOperations.h:
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emit_op_del_by_id):
* jit/JITPropertyAccess32_64.cpp:
(JSC::JIT::emit_op_del_by_id):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@199683 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
index eedcc24..4e6358e 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
+++ b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
@@ -2090,6 +2090,14 @@
forNode(node).setType(SpecInt32);
break;
}
+
+ case DeleteById: {
+ // FIXME: This could decide if the delete will be successful based on the set of structures that
+ // we get from our base value. https://bugs.webkit.org/show_bug.cgi?id=156611
+ clobberWorld(node->origin.semantic, clobberLimit);
+ forNode(node).setType(SpecBoolean);
+ break;
+ }
case CheckStructure: {
AbstractValue& value = forNode(node->child1());
diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
index 1aa1d2c..f276704 100644
--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
@@ -3973,6 +3973,13 @@
NEXT_OPCODE(op_put_getter_by_val);
}
+ case op_del_by_id: {
+ Node* base = get(VirtualRegister(currentInstruction[2].u.operand));
+ unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[3].u.operand];
+ addToGraph(DeleteById, OpInfo(identifierNumber), base);
+ NEXT_OPCODE(op_del_by_id);
+ }
+
case op_profile_type: {
Node* valueToProfile = get(VirtualRegister(currentInstruction[1].u.operand));
addToGraph(ProfileType, OpInfo(currentInstruction[2].u.location), valueToProfile);
diff --git a/Source/JavaScriptCore/dfg/DFGCapabilities.cpp b/Source/JavaScriptCore/dfg/DFGCapabilities.cpp
index 6bf334f..16a269e 100644
--- a/Source/JavaScriptCore/dfg/DFGCapabilities.cpp
+++ b/Source/JavaScriptCore/dfg/DFGCapabilities.cpp
@@ -161,6 +161,7 @@
case op_put_getter_setter_by_id:
case op_put_getter_by_val:
case op_put_setter_by_val:
+ case op_del_by_id:
case op_jmp:
case op_jtrue:
case op_jfalse:
diff --git a/Source/JavaScriptCore/dfg/DFGClobberize.h b/Source/JavaScriptCore/dfg/DFGClobberize.h
index ad105c4..4d1fe1b 100644
--- a/Source/JavaScriptCore/dfg/DFGClobberize.h
+++ b/Source/JavaScriptCore/dfg/DFGClobberize.h
@@ -445,6 +445,7 @@
case PutGetterSetterById:
case PutGetterByVal:
case PutSetterByVal:
+ case DeleteById:
case ArrayPush:
case ArrayPop:
case Call:
diff --git a/Source/JavaScriptCore/dfg/DFGDoesGC.cpp b/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
index 6a64647..73fbd92 100644
--- a/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
+++ b/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
@@ -107,6 +107,7 @@
case PutGetterSetterById:
case PutGetterByVal:
case PutSetterByVal:
+ case DeleteById:
case CheckStructure:
case GetExecutable:
case GetButterfly:
diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
index d387a2e..8edb0a2 100644
--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
@@ -1514,6 +1514,7 @@
case NewRegexp:
case ProfileWillCall:
case ProfileDidCall:
+ case DeleteById:
case IsArrayObject:
case IsJSArray:
case IsArrayConstructor:
diff --git a/Source/JavaScriptCore/dfg/DFGNode.h b/Source/JavaScriptCore/dfg/DFGNode.h
index f1f1c16..df5a126 100644
--- a/Source/JavaScriptCore/dfg/DFGNode.h
+++ b/Source/JavaScriptCore/dfg/DFGNode.h
@@ -875,6 +875,7 @@
case PutGetterById:
case PutSetterById:
case PutGetterSetterById:
+ case DeleteById:
return true;
default:
return false;
diff --git a/Source/JavaScriptCore/dfg/DFGNodeType.h b/Source/JavaScriptCore/dfg/DFGNodeType.h
index bcbfe1b..8311a72 100644
--- a/Source/JavaScriptCore/dfg/DFGNodeType.h
+++ b/Source/JavaScriptCore/dfg/DFGNodeType.h
@@ -193,6 +193,7 @@
macro(PutGetterSetterById, NodeMustGenerate) \
macro(PutGetterByVal, NodeMustGenerate) \
macro(PutSetterByVal, NodeMustGenerate) \
+ macro(DeleteById, NodeResultBoolean | NodeMustGenerate) \
macro(CheckStructure, NodeMustGenerate) \
macro(GetExecutable, NodeResultJS) \
macro(PutStructure, NodeMustGenerate) \
diff --git a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
index 844c749..bfb5ed3 100644
--- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
@@ -411,7 +411,8 @@
changed |= mergePrediction(speculatedDoubleTypeForPrediction(child));
break;
}
-
+
+ case DeleteById:
case LogicalNot:
case CompareLess:
case CompareLessEq:
diff --git a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
index 2204849..2307bbb 100644
--- a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
+++ b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
@@ -192,6 +192,7 @@
case ArithLog:
case ValueAdd:
case TryGetById:
+ case DeleteById:
case GetById:
case GetByIdFlush:
case PutById:
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
index 954be07..7c6657c 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
@@ -1066,6 +1066,23 @@
blessedBooleanResult(resultGPR, node, UseChildrenCalledExplicitly);
}
+void SpeculativeJIT::compileDeleteById(Node* node)
+{
+ JSValueOperand value(this, node->child1());
+ GPRFlushedCallResult result(this);
+
+ JSValueRegs valueRegs = value.jsValueRegs();
+ GPRReg resultGPR = result.gpr();
+
+ value.use();
+
+ flushRegisters();
+ callOperation(operationDeleteById, resultGPR, valueRegs, identifierUID(node->identifierNumber()));
+ m_jit.exceptionCheck();
+
+ unblessedBooleanResult(resultGPR, node, UseChildrenCalledExplicitly);
+}
+
bool SpeculativeJIT::nonSpeculativeCompare(Node* node, MacroAssembler::RelationalCondition cond, S_JITOperation_EJJ helperFunction)
{
unsigned branchIndexInBlock = detectPeepHoleBranch();
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
index 1a5fdb0..6e767e0 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
@@ -714,6 +714,7 @@
void cachedPutById(CodeOrigin, GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), SpillRegistersMode = NeedToSpill);
#endif
+ void compileDeleteById(Node*);
void compileTryGetById(Node*);
void compileIn(Node*);
@@ -1468,6 +1469,15 @@
m_jit.setupArgumentsWithExecState(arg1);
return appendCallSetResult(operation, result);
}
+ JITCompiler::Call callOperation(S_JITOperation_EJI operation, GPRReg result, GPRReg arg1, UniquedStringImpl* uid)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(uid));
+ return appendCallSetResult(operation, result);
+ }
+ JITCompiler::Call callOperation(S_JITOperation_EJI operation, GPRReg result, JSValueRegs arg1, UniquedStringImpl* uid)
+ {
+ return callOperation(operation, result, arg1.gpr(), uid);
+ }
JITCompiler::Call callOperation(S_JITOperation_EJJ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
{
m_jit.setupArgumentsWithExecState(arg1, arg2);
@@ -1882,6 +1892,17 @@
return callOperation(operation, result, arg1.tagGPR(), arg1.payloadGPR());
}
+ JITCompiler::Call callOperation(S_JITOperation_EJI operation, GPRReg result, GPRReg arg1Tag, GPRReg arg1Payload, UniquedStringImpl* uid)
+ {
+ m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, TrustedImmPtr(uid));
+ return appendCallSetResult(operation, result);
+ }
+
+ JITCompiler::Call callOperation(S_JITOperation_EJI operation, GPRReg result, JSValueRegs arg1Regs, UniquedStringImpl* uid)
+ {
+ return callOperation(operation, result, arg1Regs.tagGPR(), arg1Regs.payloadGPR(), uid);
+ }
+
JITCompiler::Call callOperation(S_JITOperation_EJJ operation, GPRReg result, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload)
{
m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, SH4_32BIT_DUMMY_ARG arg2Payload, arg2Tag);
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
index 6a70a68..fc2524e 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
@@ -4090,6 +4090,11 @@
case GetArrayLength:
compileGetArrayLength(node);
break;
+
+ case DeleteById: {
+ compileDeleteById(node);
+ break;
+ }
case CheckCell: {
SpeculateCellOperand cell(this, node->child1());
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
index 2be27da..ac2ac2b 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
@@ -4131,6 +4131,11 @@
case GetArrayLength:
compileGetArrayLength(node);
break;
+
+ case DeleteById: {
+ compileDeleteById(node);
+ break;
+ }
case CheckCell: {
SpeculateCellOperand cell(this, node->child1());