diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-02-09 14:16:12 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-02-09 14:16:12 +0100 |
commit | 03e12282df9aa1e1fb05a8b90f1cfc2e08764cec (patch) | |
tree | 52599cd0ab782b1768e23ad176f7618f98333cb6 /Source/JavaScriptCore/dfg | |
parent | cd44dc59cdfc39534aef4d417e9f3c412e3be139 (diff) | |
download | qtwebkit-03e12282df9aa1e1fb05a8b90f1cfc2e08764cec.tar.gz |
Imported WebKit commit e09a82039aa4273ab318b71122e92d8e5f233525 (http://svn.webkit.org/repository/webkit/trunk@107223)
Diffstat (limited to 'Source/JavaScriptCore/dfg')
22 files changed, 678 insertions, 575 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp index bd35e1d43..72c1759c7 100644 --- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp +++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp @@ -262,22 +262,6 @@ bool AbstractState::execute(NodeIndex nodeIndex) forNode(nodeIndex).set(PredictInt32); break; - case ValueToNumber: - if (m_graph[node.child1()].shouldNotSpeculateInteger()) { - forNode(node.child1()).filter(PredictNumber); - forNode(nodeIndex).set(PredictDouble); - break; - } - - forNode(node.child1()).filter(PredictInt32); - forNode(nodeIndex).set(PredictInt32); - break; - - case ValueToDouble: - forNode(node.child1()).filter(PredictNumber); - forNode(nodeIndex).set(PredictDouble); - break; - case ValueAdd: case ArithAdd: { if (m_graph.addShouldSpeculateInteger(node, m_codeBlock)) { diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.h b/Source/JavaScriptCore/dfg/DFGAbstractState.h index 337a4d0b4..015563485 100644 --- a/Source/JavaScriptCore/dfg/DFGAbstractState.h +++ b/Source/JavaScriptCore/dfg/DFGAbstractState.h @@ -101,6 +101,11 @@ public: return m_nodes[nodeIndex - m_block->begin]; } + AbstractValue& forNode(NodeUse nodeUse) + { + return forNode(nodeUse.index()); + } + // Call this before beginning CFA to initialize the abstract values of // arguments, and to indicate which blocks should be listed for CFA // execution. diff --git a/Source/JavaScriptCore/dfg/DFGAbstractValue.h b/Source/JavaScriptCore/dfg/DFGAbstractValue.h index 15bc0d496..aa5518187 100644 --- a/Source/JavaScriptCore/dfg/DFGAbstractValue.h +++ b/Source/JavaScriptCore/dfg/DFGAbstractValue.h @@ -287,7 +287,6 @@ public: return m_structure == other.m_structure; } -#ifndef NDEBUG void dump(FILE* out) const { if (isTop()) { @@ -300,7 +299,6 @@ public: fprintf(out, "%p", m_structure); fprintf(out, "]"); } -#endif private: static Structure* topValue() { return reinterpret_cast<Structure*>(1); } @@ -466,14 +464,12 @@ struct AbstractValue { // complexity of the code. } -#ifndef NDEBUG void dump(FILE* out) const { fprintf(out, "(%s, ", predictionToString(m_type)); m_structure.dump(out); fprintf(out, ")"); } -#endif StructureAbstractValue m_structure; PredictedType m_type; diff --git a/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h b/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h index e0d817c9f..0d7dd3a27 100644 --- a/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h +++ b/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h @@ -39,9 +39,7 @@ namespace JSC { namespace DFG { -#ifndef NDEBUG typedef void (*V_DFGDebugOperation_EP)(ExecState*, void*); -#endif class AssemblyHelpers : public MacroAssembler { public: @@ -152,7 +150,6 @@ public: return branch8(Below, Address(structureReg, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType)); } -#ifndef NDEBUG // Add a debug call. This call has no effect on JIT code execution state. void debugCall(V_DFGDebugOperation_EP function, void* argument) { @@ -182,7 +179,6 @@ public: for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i) loadPtr(buffer + i, GPRInfo::toRegister(i)); } -#endif // These methods JIT generate dynamic, debug-only checks - akin to ASSERTs. #if DFG_ENABLE(JIT_ASSERT) diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp index 87c3a23b9..2a5d249b3 100644 --- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp +++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp @@ -170,7 +170,7 @@ private: Node& flushChild = m_graph[nodePtr->child1()]; if (flushChild.op == Phi) { VariableAccessData* variableAccessData = flushChild.variableAccessData(); - nodeIndex = addToGraph(GetLocal, OpInfo(variableAccessData), nodePtr->child1()); + nodeIndex = addToGraph(GetLocal, OpInfo(variableAccessData), nodePtr->child1().index()); m_currentBlock->variablesAtTail.local(operand) = nodeIndex; return nodeIndex; } @@ -179,7 +179,7 @@ private: if (nodePtr->op == GetLocal) return nodeIndex; ASSERT(nodePtr->op == SetLocal); - return nodePtr->child1(); + return nodePtr->child1().index(); } // Check for reads of temporaries from prior blocks, @@ -219,7 +219,7 @@ private: Node& flushChild = m_graph[nodePtr->child1()]; if (flushChild.op == Phi) { VariableAccessData* variableAccessData = flushChild.variableAccessData(); - nodeIndex = addToGraph(GetLocal, OpInfo(variableAccessData), nodePtr->child1()); + nodeIndex = addToGraph(GetLocal, OpInfo(variableAccessData), nodePtr->child1().index()); m_currentBlock->variablesAtTail.local(operand) = nodeIndex; return nodeIndex; } @@ -238,7 +238,7 @@ private: return nodeIndex; ASSERT(nodePtr->op == SetLocal); - return nodePtr->child1(); + return nodePtr->child1().index(); } VariableAccessData* variableAccessData = newVariableAccessData(operand); @@ -313,10 +313,6 @@ private: { return toInt32(get(operand)); } - NodeIndex getToNumber(int operand) - { - return toNumber(get(operand)); - } // Perform an ES5 ToInt32 operation - returns a node of type NodeResultInt32. NodeIndex toInt32(NodeIndex index) @@ -327,7 +323,7 @@ private: return index; if (node.op == UInt32ToNumber) - return node.child1(); + return node.child1().index(); // Check for numeric constants boxed as JSValues. if (node.op == JSConstant) { @@ -341,23 +337,6 @@ private: return addToGraph(ValueToInt32, index); } - // Perform an ES5 ToNumber operation - returns a node of type NodeResultDouble. - NodeIndex toNumber(NodeIndex index) - { - Node& node = m_graph[index]; - - if (node.hasNumberResult()) - return index; - - if (node.op == JSConstant) { - JSValue v = valueOfJSConstant(index); - if (v.isNumber()) - return getJSConstant(node.constantNumber()); - } - - return addToGraph(ValueToNumber, OpInfo(NodeUseBottom), index); - } - NodeIndex getJSConstantForValue(JSValue constantValue) { unsigned constantIndex = m_codeBlock->addOrFindConstant(constantValue); @@ -572,7 +551,7 @@ private: } void addVarArgChild(NodeIndex child) { - m_graph.m_varArgChildren.append(child); + m_graph.m_varArgChildren.append(NodeUse(child)); m_numPassedVarArgs++; } @@ -1198,12 +1177,12 @@ bool ByteCodeParser::handleMinMax(bool usesResult, int resultOperand, NodeType o } if (argumentCountIncludingThis == 2) { // Math.min(x) - set(resultOperand, getToNumber(registerOffset + argumentToOperand(1))); + set(resultOperand, get(registerOffset + argumentToOperand(1))); return true; } if (argumentCountIncludingThis == 3) { // Math.min(x, y) - set(resultOperand, addToGraph(op, OpInfo(NodeUseBottom), getToNumber(registerOffset + argumentToOperand(1)), getToNumber(registerOffset + argumentToOperand(2)))); + set(resultOperand, addToGraph(op, OpInfo(NodeUseBottom), get(registerOffset + argumentToOperand(1)), get(registerOffset + argumentToOperand(2)))); return true; } @@ -1231,7 +1210,7 @@ bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrins if (!MacroAssembler::supportsFloatingPointAbs()) return false; - NodeIndex nodeIndex = addToGraph(ArithAbs, OpInfo(NodeUseBottom), getToNumber(registerOffset + argumentToOperand(1))); + NodeIndex nodeIndex = addToGraph(ArithAbs, OpInfo(NodeUseBottom), get(registerOffset + argumentToOperand(1))); if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow)) m_graph[nodeIndex].mergeArithNodeFlags(NodeMayOverflow); set(resultOperand, nodeIndex); @@ -1256,7 +1235,7 @@ bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrins if (!MacroAssembler::supportsFloatingPointSqrt()) return false; - set(resultOperand, addToGraph(ArithSqrt, getToNumber(registerOffset + argumentToOperand(1)))); + set(resultOperand, addToGraph(ArithSqrt, get(registerOffset + argumentToOperand(1)))); return true; } @@ -1512,7 +1491,7 @@ bool ByteCodeParser::parseBlock(unsigned limit) case op_pre_inc: { unsigned srcDst = currentInstruction[1].u.operand; - NodeIndex op = getToNumber(srcDst); + NodeIndex op = get(srcDst); set(srcDst, makeSafe(addToGraph(ArithAdd, OpInfo(NodeUseBottom), op, one()))); NEXT_OPCODE(op_pre_inc); } @@ -1521,7 +1500,7 @@ bool ByteCodeParser::parseBlock(unsigned limit) unsigned result = currentInstruction[1].u.operand; unsigned srcDst = currentInstruction[2].u.operand; ASSERT(result != srcDst); // Required for assumptions we make during OSR. - NodeIndex op = getToNumber(srcDst); + NodeIndex op = get(srcDst); set(result, op); set(srcDst, makeSafe(addToGraph(ArithAdd, OpInfo(NodeUseBottom), op, one()))); NEXT_OPCODE(op_post_inc); @@ -1529,7 +1508,7 @@ bool ByteCodeParser::parseBlock(unsigned limit) case op_pre_dec: { unsigned srcDst = currentInstruction[1].u.operand; - NodeIndex op = getToNumber(srcDst); + NodeIndex op = get(srcDst); set(srcDst, makeSafe(addToGraph(ArithSub, OpInfo(NodeUseBottom), op, one()))); NEXT_OPCODE(op_pre_dec); } @@ -1537,7 +1516,7 @@ bool ByteCodeParser::parseBlock(unsigned limit) case op_post_dec: { unsigned result = currentInstruction[1].u.operand; unsigned srcDst = currentInstruction[2].u.operand; - NodeIndex op = getToNumber(srcDst); + NodeIndex op = get(srcDst); set(result, op); set(srcDst, makeSafe(addToGraph(ArithSub, OpInfo(NodeUseBottom), op, one()))); NEXT_OPCODE(op_post_dec); @@ -1549,37 +1528,37 @@ bool ByteCodeParser::parseBlock(unsigned limit) NodeIndex op1 = get(currentInstruction[2].u.operand); NodeIndex op2 = get(currentInstruction[3].u.operand); if (m_graph[op1].hasNumberResult() && m_graph[op2].hasNumberResult()) - set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithAdd, OpInfo(NodeUseBottom), toNumber(op1), toNumber(op2)))); + set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithAdd, OpInfo(NodeUseBottom), op1, op2))); else set(currentInstruction[1].u.operand, makeSafe(addToGraph(ValueAdd, OpInfo(NodeUseBottom), op1, op2))); NEXT_OPCODE(op_add); } case op_sub: { - NodeIndex op1 = getToNumber(currentInstruction[2].u.operand); - NodeIndex op2 = getToNumber(currentInstruction[3].u.operand); + NodeIndex op1 = get(currentInstruction[2].u.operand); + NodeIndex op2 = get(currentInstruction[3].u.operand); set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithSub, OpInfo(NodeUseBottom), op1, op2))); NEXT_OPCODE(op_sub); } case op_mul: { // Multiply requires that the inputs are not truncated, unfortunately. - NodeIndex op1 = getToNumber(currentInstruction[2].u.operand); - NodeIndex op2 = getToNumber(currentInstruction[3].u.operand); + NodeIndex op1 = get(currentInstruction[2].u.operand); + NodeIndex op2 = get(currentInstruction[3].u.operand); set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithMul, OpInfo(NodeUseBottom), op1, op2))); NEXT_OPCODE(op_mul); } case op_mod: { - NodeIndex op1 = getToNumber(currentInstruction[2].u.operand); - NodeIndex op2 = getToNumber(currentInstruction[3].u.operand); + NodeIndex op1 = get(currentInstruction[2].u.operand); + NodeIndex op2 = get(currentInstruction[3].u.operand); set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithMod, OpInfo(NodeUseBottom), op1, op2))); NEXT_OPCODE(op_mod); } case op_div: { - NodeIndex op1 = getToNumber(currentInstruction[2].u.operand); - NodeIndex op2 = getToNumber(currentInstruction[3].u.operand); + NodeIndex op1 = get(currentInstruction[2].u.operand); + NodeIndex op2 = get(currentInstruction[3].u.operand); set(currentInstruction[1].u.operand, makeDivSafe(addToGraph(ArithDiv, OpInfo(NodeUseBottom), op1, op2))); NEXT_OPCODE(op_div); } @@ -2241,9 +2220,9 @@ void ByteCodeParser::processPhiStack() // GetLocal and its block-local Phi. Strictly speaking we only need the two // to be unified. But for efficiency, we want the code that creates GetLocals // and Phis to try to reuse VariableAccessDatas as much as possible. - ASSERT(m_graph[valueInPredecessor].variableAccessData() == m_graph[m_graph[valueInPredecessor].child1()].variableAccessData()); + ASSERT(m_graph[valueInPredecessor].variableAccessData() == m_graph[m_graph[valueInPredecessor].child1().index()].variableAccessData()); - valueInPredecessor = m_graph[valueInPredecessor].child1(); + valueInPredecessor = m_graph[valueInPredecessor].child1().index(); } else { #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) printf(" Found @%u.\n", valueInPredecessor); @@ -2266,11 +2245,11 @@ void ByteCodeParser::processPhiStack() m_graph.ref(valueInPredecessor); } - if (phiNode->child1() == NoNode) { + if (!phiNode->child1()) { #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) printf(" Setting @%u->child1 = @%u.\n", entry.m_phi, valueInPredecessor); #endif - phiNode->children.fixed.child1 = valueInPredecessor; + phiNode->children.setChild1(NodeUse(valueInPredecessor)); #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) printf(" Children of @%u: ", entry.m_phi); phiNode->dumpChildren(stdout); @@ -2278,11 +2257,11 @@ void ByteCodeParser::processPhiStack() #endif continue; } - if (phiNode->child2() == NoNode) { + if (!phiNode->child2()) { #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) printf(" Setting @%u->child2 = @%u.\n", entry.m_phi, valueInPredecessor); #endif - phiNode->children.fixed.child2 = valueInPredecessor; + phiNode->children.setChild2(NodeUse(valueInPredecessor)); #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) printf(" Children of @%u: ", entry.m_phi); phiNode->dumpChildren(stdout); @@ -2290,11 +2269,11 @@ void ByteCodeParser::processPhiStack() #endif continue; } - if (phiNode->child3() == NoNode) { + if (!phiNode->child3()) { #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) printf(" Setting @%u->child3 = @%u.\n", entry.m_phi, valueInPredecessor); #endif - phiNode->children.fixed.child3 = valueInPredecessor; + phiNode->children.setChild3(NodeUse(valueInPredecessor)); #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) printf(" Children of @%u: ", entry.m_phi); phiNode->dumpChildren(stdout); @@ -2314,9 +2293,7 @@ void ByteCodeParser::processPhiStack() if (phiNode->refCount()) m_graph.ref(newPhi); - newPhiNode.children.fixed.child1 = phiNode->child1(); - newPhiNode.children.fixed.child2 = phiNode->child2(); - newPhiNode.children.fixed.child3 = phiNode->child3(); + newPhiNode.children = phiNode->children; #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) printf(" Children of @%u: ", newPhi); @@ -2324,9 +2301,7 @@ void ByteCodeParser::processPhiStack() printf(".\n"); #endif - phiNode->children.fixed.child1 = newPhi; - phiNode->children.fixed.child2 = valueInPredecessor; - phiNode->children.fixed.child3 = NoNode; + phiNode->children.initialize(newPhi, valueInPredecessor, NoNode); #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) printf(" Children of @%u: ", entry.m_phi); diff --git a/Source/JavaScriptCore/dfg/DFGCommon.h b/Source/JavaScriptCore/dfg/DFGCommon.h index 469dbd33e..14edff3a5 100644 --- a/Source/JavaScriptCore/dfg/DFGCommon.h +++ b/Source/JavaScriptCore/dfg/DFGCommon.h @@ -92,6 +92,11 @@ struct NodeIndexTraits { } }; +enum UseKind { + UntypedUse, + LastUseKind // Must always be the last entry in the enum, as it is used to denote the number of enum elements. +}; + } } // namespace JSC::DFG #endif // ENABLE(DFG_JIT) diff --git a/Source/JavaScriptCore/dfg/DFGFPRInfo.h b/Source/JavaScriptCore/dfg/DFGFPRInfo.h index dbd60a4e6..6af45dd81 100644 --- a/Source/JavaScriptCore/dfg/DFGFPRInfo.h +++ b/Source/JavaScriptCore/dfg/DFGFPRInfo.h @@ -78,7 +78,6 @@ public: return (unsigned)reg; } -#ifndef NDEBUG static const char* debugName(FPRReg reg) { ASSERT(reg != InvalidFPRReg); @@ -99,7 +98,6 @@ public: #endif return nameForRegister[reg]; } -#endif }; #endif @@ -141,7 +139,6 @@ public: return (unsigned)reg; } -#ifndef NDEBUG static const char* debugName(FPRReg reg) { ASSERT(reg != InvalidFPRReg); @@ -158,7 +155,6 @@ public: }; return nameForRegister[reg]; } -#endif }; #endif diff --git a/Source/JavaScriptCore/dfg/DFGGPRInfo.h b/Source/JavaScriptCore/dfg/DFGGPRInfo.h index 2f779d645..f010d8c18 100644 --- a/Source/JavaScriptCore/dfg/DFGGPRInfo.h +++ b/Source/JavaScriptCore/dfg/DFGGPRInfo.h @@ -292,7 +292,6 @@ public: return result; } -#ifndef NDEBUG static const char* debugName(GPRReg reg) { ASSERT(reg != InvalidGPRReg); @@ -303,7 +302,6 @@ public: }; return nameForRegister[reg]; } -#endif private: static const unsigned InvalidIndex = 0xffffffff; @@ -363,7 +361,6 @@ public: return result; } -#ifndef NDEBUG static const char* debugName(GPRReg reg) { ASSERT(reg != InvalidGPRReg); @@ -376,7 +373,6 @@ public: }; return nameForRegister[reg]; } -#endif private: static const unsigned InvalidIndex = 0xffffffff; @@ -436,7 +432,6 @@ public: return result; } -#ifndef NDEBUG static const char* debugName(GPRReg reg) { ASSERT(reg != InvalidGPRReg); @@ -449,7 +444,6 @@ public: }; return nameForRegister[reg]; } -#endif private: static const unsigned InvalidIndex = 0xffffffff; diff --git a/Source/JavaScriptCore/dfg/DFGGraph.cpp b/Source/JavaScriptCore/dfg/DFGGraph.cpp index e01bea195..c304dc8e7 100644 --- a/Source/JavaScriptCore/dfg/DFGGraph.cpp +++ b/Source/JavaScriptCore/dfg/DFGGraph.cpp @@ -32,8 +32,6 @@ namespace JSC { namespace DFG { -#ifndef NDEBUG - // Creates an array of stringized names. static const char* dfgOpNames[] = { #define STRINGIZE_DFG_OP_ENUM(opcode, flags) #opcode , @@ -165,16 +163,16 @@ void Graph::dump(NodeIndex nodeIndex, CodeBlock* codeBlock) printf(", "); else hasPrinted = true; - printf("@%u", m_varArgChildren[childIdx]); + printf("@%u", m_varArgChildren[childIdx].index()); } } else { - if (node.child1() != NoNode) - printf("@%u", node.child1()); - if (node.child2() != NoNode) - printf(", @%u", node.child2()); - if (node.child3() != NoNode) - printf(", @%u", node.child3()); - hasPrinted = node.child1() != NoNode; + if (!!node.child1()) + printf("@%u", node.child1().index()); + if (!!node.child2()) + printf(", @%u", node.child2().index()); + if (!!node.child3()) + printf(", @%u", node.child3().index()); + hasPrinted = !!node.child1(); } if (node.hasArithNodeFlags()) { @@ -298,8 +296,6 @@ void Graph::dump(CodeBlock* codeBlock) dump(i, codeBlock); } -#endif - // FIXME: Convert this to be iterative, not recursive. #define DO_TO_CHILDREN(node, thingToDo) do { \ Node& _node = (node); \ @@ -309,20 +305,20 @@ void Graph::dump(CodeBlock* codeBlock) _childIdx++) \ thingToDo(m_varArgChildren[_childIdx]); \ } else { \ - if (_node.child1() == NoNode) { \ - ASSERT(_node.child2() == NoNode \ - && _node.child3() == NoNode); \ + if (!_node.child1()) { \ + ASSERT(!_node.child2() \ + && !_node.child3()); \ break; \ } \ thingToDo(_node.child1()); \ \ - if (_node.child2() == NoNode) { \ - ASSERT(_node.child3() == NoNode); \ + if (!_node.child2()) { \ + ASSERT(!_node.child3()); \ break; \ } \ thingToDo(_node.child2()); \ \ - if (_node.child3() == NoNode) \ + if (!_node.child3()) \ break; \ thingToDo(_node.child3()); \ } \ diff --git a/Source/JavaScriptCore/dfg/DFGGraph.h b/Source/JavaScriptCore/dfg/DFGGraph.h index d3f16a0f4..ecd77b3a4 100644 --- a/Source/JavaScriptCore/dfg/DFGGraph.h +++ b/Source/JavaScriptCore/dfg/DFGGraph.h @@ -71,6 +71,15 @@ struct ResolveGlobalData { // Nodes that are 'dead' remain in the vector with refCount 0. class Graph : public Vector<Node, 64> { public: + using Vector<Node, 64>::operator[]; + using Vector<Node, 64>::at; + + Node& operator[](NodeUse nodeUse) { return at(nodeUse.index()); } + const Node& operator[](NodeUse nodeUse) const { return at(nodeUse.index()); } + + Node& at(NodeUse nodeUse) { return at(nodeUse.index()); } + const Node& at(NodeUse nodeUse) const { return at(nodeUse.index()); } + // Mark a node as being referenced. void ref(NodeIndex nodeIndex) { @@ -79,38 +88,45 @@ public: if (node.ref()) refChildren(nodeIndex); } + void ref(NodeUse nodeUse) + { + ref(nodeUse.index()); + } void deref(NodeIndex nodeIndex) { if (at(nodeIndex).deref()) derefChildren(nodeIndex); } + void deref(NodeUse nodeUse) + { + deref(nodeUse.index()); + } void clearAndDerefChild1(Node& node) { - if (node.children.fixed.child1 == NoNode) + if (!node.child1()) return; - deref(node.children.fixed.child1); - node.children.fixed.child1 = NoNode; + deref(node.child1()); + node.children.child1() = NodeUse(); } void clearAndDerefChild2(Node& node) { - if (node.children.fixed.child2 == NoNode) + if (!node.child2()) return; - deref(node.children.fixed.child2); - node.children.fixed.child2 = NoNode; + deref(node.child2()); + node.children.child2() = NodeUse(); } void clearAndDerefChild3(Node& node) { - if (node.children.fixed.child3 == NoNode) + if (!node.child3()) return; - deref(node.children.fixed.child3); - node.children.fixed.child3 = NoNode; + deref(node.child3()); + node.children.child3() = NodeUse(); } -#ifndef NDEBUG // CodeBlock is optional, but may allow additional information to be dumped (e.g. Identifier names). void dump(CodeBlock* = 0); void dump(NodeIndex, CodeBlock* = 0); @@ -118,7 +134,6 @@ public: // Dump the code origin of the given node as a diff from the code origin of the // preceding node. void dumpCodeOrigin(NodeIndex); -#endif BlockIndex blockIndexForBytecodeOffset(Vector<BlockIndex>& blocks, unsigned bytecodeBegin); @@ -214,12 +229,10 @@ public: return asFunction(function); } -#ifndef NDEBUG static const char *opName(NodeType); // This is O(n), and should only be used for verbose dumps. const char* nameOfVariableAccessData(VariableAccessData*); -#endif void predictArgumentTypes(CodeBlock*); @@ -259,7 +272,7 @@ public: } Vector< OwnPtr<BasicBlock> , 8> m_blocks; - Vector<NodeIndex, 16> m_varArgChildren; + Vector<NodeUse, 16> m_varArgChildren; Vector<StorageAccessData> m_storageAccessData; Vector<ResolveGlobalData> m_resolveGlobalData; Vector<NodeIndex, 8> m_arguments; diff --git a/Source/JavaScriptCore/dfg/DFGJITCompiler.h b/Source/JavaScriptCore/dfg/DFGJITCompiler.h index 451bee6ca..5596876fc 100644 --- a/Source/JavaScriptCore/dfg/DFGJITCompiler.h +++ b/Source/JavaScriptCore/dfg/DFGJITCompiler.h @@ -272,6 +272,7 @@ public: // Helper methods to get predictions PredictedType getPrediction(Node& node) { return node.prediction(); } PredictedType getPrediction(NodeIndex nodeIndex) { return getPrediction(graph()[nodeIndex]); } + PredictedType getPrediction(NodeUse nodeUse) { return getPrediction(nodeUse.index()); } #if USE(JSVALUE32_64) void* addressOfDoubleConstant(NodeIndex nodeIndex) diff --git a/Source/JavaScriptCore/dfg/DFGNode.h b/Source/JavaScriptCore/dfg/DFGNode.h index 7366c1c40..2b6ebdb7f 100644 --- a/Source/JavaScriptCore/dfg/DFGNode.h +++ b/Source/JavaScriptCore/dfg/DFGNode.h @@ -33,6 +33,7 @@ #include "CodeBlock.h" #include "CodeOrigin.h" #include "DFGCommon.h" +#include "DFGNodeReferenceBlob.h" #include "DFGOperands.h" #include "DFGVariableAccessData.h" #include "JSValue.h" @@ -96,7 +97,6 @@ static inline bool nodeCanSpeculateInteger(ArithNodeFlags flags) return true; } -#ifndef NDEBUG static inline const char* arithNodeFlagsAsString(ArithNodeFlags flags) { if (!flags) @@ -138,7 +138,6 @@ static inline const char* arithNodeFlagsAsString(ArithNodeFlags flags) return description; } -#endif // Entries in the NodeType enum (below) are composed of an id, a result type (possibly none) // and some additional informative flags (must generate, is constant, etc). @@ -212,11 +211,6 @@ static inline const char* arithNodeFlagsAsString(ArithNodeFlags flags) macro(ArithMin, NodeResultNumber) \ macro(ArithMax, NodeResultNumber) \ macro(ArithSqrt, NodeResultNumber) \ - /* Arithmetic operators call ToNumber on their operands. */\ - macro(ValueToNumber, NodeResultNumber | NodeMustGenerate) \ - \ - /* A variant of ValueToNumber, which a hint that the parents will always use this as a double. */\ - macro(ValueToDouble, NodeResultNumber | NodeMustGenerate) \ \ /* Add of values may either be arithmetic, or result in string concatenation. */\ macro(ValueAdd, NodeResultJS | NodeMustGenerate | NodeMightClobber) \ @@ -349,36 +343,33 @@ struct Node { Node(NodeType op, CodeOrigin codeOrigin, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode) : op(op) , codeOrigin(codeOrigin) + , children(NodeReferenceBlob::Fixed, child1, child2, child3) , m_virtualRegister(InvalidVirtualRegister) , m_refCount(0) , m_prediction(PredictNone) { ASSERT(!(op & NodeHasVarArgs)); ASSERT(!hasArithNodeFlags()); - children.fixed.child1 = child1; - children.fixed.child2 = child2; - children.fixed.child3 = child3; } // Construct a node with up to 3 children and an immediate value. Node(NodeType op, CodeOrigin codeOrigin, OpInfo imm, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode) : op(op) , codeOrigin(codeOrigin) + , children(NodeReferenceBlob::Fixed, child1, child2, child3) , m_virtualRegister(InvalidVirtualRegister) , m_refCount(0) , m_opInfo(imm.m_value) , m_prediction(PredictNone) { ASSERT(!(op & NodeHasVarArgs)); - children.fixed.child1 = child1; - children.fixed.child2 = child2; - children.fixed.child3 = child3; } // Construct a node with up to 3 children and two immediate values. Node(NodeType op, CodeOrigin codeOrigin, OpInfo imm1, OpInfo imm2, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode) : op(op) , codeOrigin(codeOrigin) + , children(NodeReferenceBlob::Fixed, child1, child2, child3) , m_virtualRegister(InvalidVirtualRegister) , m_refCount(0) , m_opInfo(imm1.m_value) @@ -386,15 +377,13 @@ struct Node { , m_prediction(PredictNone) { ASSERT(!(op & NodeHasVarArgs)); - children.fixed.child1 = child1; - children.fixed.child2 = child2; - children.fixed.child3 = child3; } // Construct a node with a variable number of children and two immediate values. Node(VarArgTag, NodeType op, CodeOrigin codeOrigin, OpInfo imm1, OpInfo imm2, unsigned firstChild, unsigned numChildren) : op(op) , codeOrigin(codeOrigin) + , children(NodeReferenceBlob::Variable, firstChild, numChildren) , m_virtualRegister(InvalidVirtualRegister) , m_refCount(0) , m_opInfo(imm1.m_value) @@ -402,8 +391,6 @@ struct Node { , m_prediction(PredictNone) { ASSERT(op & NodeHasVarArgs); - children.variable.firstChild = firstChild; - children.variable.numChildren = numChildren; } bool mustGenerate() @@ -499,7 +486,6 @@ struct Node { return variableAccessData()->local(); } -#ifndef NDEBUG bool hasIdentifier() { switch (op) { @@ -515,7 +501,6 @@ struct Node { return false; } } -#endif unsigned identifierNumber() { @@ -532,8 +517,6 @@ struct Node { bool hasArithNodeFlags() { switch (op) { - case ValueToNumber: - case ValueToDouble: case UInt32ToNumber: case ArithAdd: case ArithSub: @@ -849,42 +832,42 @@ struct Node { return !--m_refCount; } - NodeIndex child1() + NodeUse child1() { ASSERT(!(op & NodeHasVarArgs)); - return children.fixed.child1; + return children.child1(); } // This is useful if you want to do a fast check on the first child // before also doing a check on the opcode. Use this with care and // avoid it if possible. - NodeIndex child1Unchecked() + NodeUse child1Unchecked() { - return children.fixed.child1; + return children.child1Unchecked(); } - NodeIndex child2() + NodeUse child2() { ASSERT(!(op & NodeHasVarArgs)); - return children.fixed.child2; + return children.child2(); } - NodeIndex child3() + NodeUse child3() { ASSERT(!(op & NodeHasVarArgs)); - return children.fixed.child3; + return children.child3(); } unsigned firstChild() { ASSERT(op & NodeHasVarArgs); - return children.variable.firstChild; + return children.firstChild(); } unsigned numChildren() { ASSERT(op & NodeHasVarArgs); - return children.variable.numChildren; + return children.numChildren(); } PredictedType prediction() @@ -1036,35 +1019,25 @@ struct Node { return nodeCanSpeculateInteger(arithNodeFlags()); } -#ifndef NDEBUG void dumpChildren(FILE* out) { - if (child1() == NoNode) + if (!child1()) return; - fprintf(out, "@%u", child1()); - if (child2() == NoNode) + fprintf(out, "@%u", child1().index()); + if (!child2()) return; - fprintf(out, ", @%u", child2()); - if (child3() == NoNode) + fprintf(out, ", @%u", child2().index()); + if (!child3()) return; - fprintf(out, ", @%u", child3()); + fprintf(out, ", @%u", child3().index()); } -#endif // This enum value describes the type of the node. NodeType op; // Used to look up exception handling information (currently implemented as a bytecode index). CodeOrigin codeOrigin; - // References to up to 3 children (0 for no child). - union { - struct { - NodeIndex child1, child2, child3; - } fixed; - struct { - unsigned firstChild; - unsigned numChildren; - } variable; - } children; + // References to up to 3 children, or links to a variable length set of children. + NodeReferenceBlob children; private: // The virtual register number (spill location) associated with this . diff --git a/Source/JavaScriptCore/dfg/DFGNodeReferenceBlob.h b/Source/JavaScriptCore/dfg/DFGNodeReferenceBlob.h new file mode 100644 index 000000000..df3ff5f5f --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGNodeReferenceBlob.h @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DFGNodeReferenceBlob_h +#define DFGNodeReferenceBlob_h + +#include <wtf/Platform.h> + +#if ENABLE(DFG_JIT) + +#include "DFGCommon.h" +#include "DFGNodeUse.h" + +namespace JSC { namespace DFG { + +class NodeReferenceBlob { +public: + enum Kind { + Fixed, + Variable + }; + + NodeReferenceBlob(Kind kind) +#if !ASSERT_DISABLED + : m_kind(kind) +#endif + { + if (kind == Variable) { + m_words[0].m_encodedWord = UINT_MAX; + m_words[1].m_encodedWord = UINT_MAX; + } + } + + NodeReferenceBlob(Kind kind, NodeIndex child1, NodeIndex child2, NodeIndex child3) +#if !ASSERT_DISABLED + : m_kind(Fixed) +#endif + { + ASSERT_UNUSED(kind, kind == Fixed); + initialize(child1, child2, child3); + } + + NodeReferenceBlob(Kind kind, unsigned firstChild, unsigned numChildren) +#if !ASSERT_DISABLED + : m_kind(Variable) +#endif + { + ASSERT_UNUSED(kind, kind == Variable); + setFirstChild(firstChild); + setNumChildren(numChildren); + } + + const NodeUse& child(unsigned i) const + { + ASSERT(i < 3); + ASSERT(m_kind == Fixed); + return m_words[i]; + } + + NodeUse& child(unsigned i) + { + ASSERT(i < 3); + ASSERT(m_kind == Fixed); + return m_words[i]; + } + + void setChild(unsigned i, NodeUse nodeUse) + { + ASSERT(i < 30); + ASSERT(m_kind == Fixed); + m_words[i] = nodeUse; + } + + NodeUse child1() const { return child(0); } + NodeUse child2() const { return child(1); } + NodeUse child3() const { return child(2); } + + NodeUse& child1() { return child(0); } + NodeUse& child2() { return child(1); } + NodeUse& child3() { return child(2); } + + void setChild1(NodeUse nodeUse) { setChild(0, nodeUse); } + void setChild2(NodeUse nodeUse) { setChild(1, nodeUse); } + void setChild3(NodeUse nodeUse) { setChild(2, nodeUse); } + + NodeUse child1Unchecked() const { return m_words[0]; } + + void initialize(NodeUse child1, NodeUse child2, NodeUse child3) + { + child(0) = child1; + child(1) = child2; + child(2) = child3; + } + + void initialize(NodeIndex child1, NodeIndex child2, NodeIndex child3) + { + initialize(NodeUse(child1), NodeUse(child2), NodeUse(child3)); + } + + unsigned firstChild() const + { + ASSERT(m_kind == Variable); + return m_words[0].m_encodedWord; + } + void setFirstChild(unsigned firstChild) + { + ASSERT(m_kind == Variable); + m_words[0].m_encodedWord = firstChild; + } + + unsigned numChildren() const + { + ASSERT(m_kind == Variable); + return m_words[1].m_encodedWord; + } + void setNumChildren(unsigned numChildren) + { + ASSERT(m_kind == Variable); + m_words[1].m_encodedWord = numChildren; + } + +private: + NodeUse m_words[3]; +#if !ASSERT_DISABLED + Kind m_kind; +#endif +}; + +} } // namespace JSC::DFG + +#endif // ENABLE(DFG_JIT) + +#endif // DFGNodeReferenceBlob_h diff --git a/Source/JavaScriptCore/dfg/DFGNodeUse.h b/Source/JavaScriptCore/dfg/DFGNodeUse.h new file mode 100644 index 000000000..71154997c --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGNodeUse.h @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DFGNodeUse_h +#define DFGNodeUse_h + +#include <wtf/Platform.h> + +#if ENABLE(DFG_JIT) + +#include "DFGCommon.h" + +namespace JSC { namespace DFG { + +class NodeReferenceBlob; + +class NodeUse { +public: + NodeUse() + : m_encodedWord(makeWord(NoNode, UntypedUse)) + { + } + + explicit NodeUse(NodeIndex nodeIndex) + : m_encodedWord(makeWord(nodeIndex, UntypedUse)) + { + } + + NodeUse(NodeIndex nodeIndex, UseKind useKind) + : m_encodedWord(makeWord(nodeIndex, useKind)) + { + } + + NodeIndex indexUnchecked() const { return m_encodedWord >> shift(); } + NodeIndex index() const + { + ASSERT(isSet()); + return m_encodedWord >> shift(); + } + void setIndex(NodeIndex nodeIndex) + { + m_encodedWord = makeWord(nodeIndex, useKind()); + } + + UseKind useKind() const + { + ASSERT(isSet()); + unsigned masked = m_encodedWord & (((1 << shift()) - 1)); + ASSERT(masked < LastUseKind); + return static_cast<UseKind>(masked); + } + void setUseKind(UseKind useKind) + { + ASSERT(isSet()); + m_encodedWord = makeWord(index(), useKind); + } + + bool isSet() const { return indexUnchecked() != NoNode; } + bool operator!() const { return !isSet(); } + + bool operator==(NodeUse other) const + { + return m_encodedWord == other.m_encodedWord; + } + bool operator!=(NodeUse other) const + { + return m_encodedWord != other.m_encodedWord; + } + +private: + friend class NodeReferenceBlob; + + static uint32_t shift() { return 4; } + + static int32_t makeWord(NodeIndex nodeIndex, UseKind useKind) + { + ASSERT(static_cast<uint32_t>(((static_cast<int32_t>(nodeIndex) << shift()) >> shift())) == nodeIndex); + ASSERT(useKind >= 0 && useKind < LastUseKind); + ASSERT(LastUseKind <= (1 << shift())); + return (nodeIndex << shift()) | useKind; + } + + int32_t m_encodedWord; +}; + +inline bool operator==(NodeUse nodeUse, NodeIndex nodeIndex) +{ + return nodeUse.indexUnchecked() == nodeIndex; +} +inline bool operator==(NodeIndex nodeIndex, NodeUse nodeUse) +{ + return nodeUse.indexUnchecked() == nodeIndex; +} +inline bool operator!=(NodeUse nodeUse, NodeIndex nodeIndex) +{ + return nodeUse.indexUnchecked() != nodeIndex; +} +inline bool operator!=(NodeIndex nodeIndex, NodeUse nodeUse) +{ + return nodeUse.indexUnchecked() != nodeIndex; +} + +} } // namespace JSC::DFG + +#endif // ENABLE(DFG_JIT) + +#endif // DFGNodeUse_h + diff --git a/Source/JavaScriptCore/dfg/DFGOSRExit.cpp b/Source/JavaScriptCore/dfg/DFGOSRExit.cpp index 7b1941146..113f2ea0d 100644 --- a/Source/JavaScriptCore/dfg/DFGOSRExit.cpp +++ b/Source/JavaScriptCore/dfg/DFGOSRExit.cpp @@ -53,7 +53,6 @@ OSRExit::OSRExit(ExitKind kind, JSValueSource jsValueSource, ValueProfile* value m_variables[variable] = jit->computeValueRecoveryFor(jit->m_variables[variable]); } -#ifndef NDEBUG void OSRExit::dump(FILE* out) const { for (unsigned argument = 0; argument < m_arguments.size(); ++argument) @@ -62,7 +61,6 @@ void OSRExit::dump(FILE* out) const for (unsigned variable = 0; variable < m_variables.size(); ++variable) m_variables[variable].dump(out); } -#endif bool OSRExit::considerAddingAsFrequentExitSiteSlow(CodeBlock* dfgCodeBlock, CodeBlock* profiledCodeBlock) { diff --git a/Source/JavaScriptCore/dfg/DFGOSRExit.h b/Source/JavaScriptCore/dfg/DFGOSRExit.h index cf96f4f3a..8e3fa6a5d 100644 --- a/Source/JavaScriptCore/dfg/DFGOSRExit.h +++ b/Source/JavaScriptCore/dfg/DFGOSRExit.h @@ -137,9 +137,7 @@ struct OSRExit { return considerAddingAsFrequentExitSiteSlow(dfgCodeBlock, profiledCodeBlock); } -#ifndef NDEBUG void dump(FILE* out) const; -#endif Vector<ValueRecovery, 0> m_arguments; Vector<ValueRecovery, 0> m_variables; diff --git a/Source/JavaScriptCore/dfg/DFGPropagator.cpp b/Source/JavaScriptCore/dfg/DFGPropagator.cpp index acfd2d364..f00f13e96 100644 --- a/Source/JavaScriptCore/dfg/DFGPropagator.cpp +++ b/Source/JavaScriptCore/dfg/DFGPropagator.cpp @@ -138,8 +138,6 @@ private: break; } - case ValueToNumber: - case ValueToDouble: case UInt32ToNumber: { changed |= m_graph[node.child1()].mergeArithNodeFlags(flags); break; @@ -147,7 +145,7 @@ private: case ArithAdd: case ValueAdd: { - if (isNotNegZero(node.child1()) || isNotNegZero(node.child2())) + if (isNotNegZero(node.child1().index()) || isNotNegZero(node.child2().index())) flags &= ~NodeNeedsNegZero; changed |= m_graph[node.child1()].mergeArithNodeFlags(flags); @@ -156,7 +154,7 @@ private: } case ArithSub: { - if (isNotZero(node.child1()) || isNotZero(node.child2())) + if (isNotZero(node.child1().index()) || isNotZero(node.child2().index())) flags &= ~NodeNeedsNegZero; changed |= m_graph[node.child1()].mergeArithNodeFlags(flags); @@ -210,13 +208,13 @@ private: for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++) changed |= m_graph[m_graph.m_varArgChildren[childIdx]].mergeArithNodeFlags(flags); } else { - if (node.child1() == NoNode) + if (!node.child1()) break; changed |= m_graph[node.child1()].mergeArithNodeFlags(flags); - if (node.child2() == NoNode) + if (!node.child2()) break; changed |= m_graph[node.child2()].mergeArithNodeFlags(flags); - if (node.child3() == NoNode) + if (!node.child3()) break; changed |= m_graph[node.child3()].mergeArithNodeFlags(flags); } @@ -363,19 +361,6 @@ private: break; } - case ValueToNumber: { - PredictedType prediction = m_graph[node.child1()].prediction(); - - if (prediction) { - if (!(prediction & PredictDouble) && nodeCanSpeculateInteger(node.arithNodeFlags())) - changed |= mergePrediction(PredictInt32); - else - changed |= mergePrediction(PredictNumber); - } - - break; - } - case ValueAdd: { PredictedType left = m_graph[node.child1()].prediction(); PredictedType right = m_graph[node.child2()].prediction(); @@ -597,7 +582,6 @@ private: break; } - case ValueToDouble: case GetArrayLength: case GetByteArrayLength: case GetInt8ArrayLength: @@ -676,21 +660,19 @@ private: propagateNodePredictions(m_graph[m_compileIndex]); } - void vote(NodeIndex nodeIndex, VariableAccessData::Ballot ballot) + void vote(NodeUse nodeUse, VariableAccessData::Ballot ballot) { - switch (m_graph[nodeIndex].op) { - case ValueToNumber: - case ValueToDouble: + switch (m_graph[nodeUse].op) { case ValueToInt32: case UInt32ToNumber: - nodeIndex = m_graph[nodeIndex].child1(); + nodeUse = m_graph[nodeUse].child1(); break; default: break; } - if (m_graph[nodeIndex].op == GetLocal) - m_graph[nodeIndex].variableAccessData()->vote(ballot); + if (m_graph[nodeUse].op == GetLocal) + m_graph[nodeUse].variableAccessData()->vote(ballot); } void vote(Node& node, VariableAccessData::Ballot ballot) @@ -701,13 +683,13 @@ private: return; } - if (node.child1() == NoNode) + if (!node.child1()) return; vote(node.child1(), ballot); - if (node.child2() == NoNode) + if (!node.child2()) return; vote(node.child2(), ballot); - if (node.child3() == NoNode) + if (!node.child3()) return; vote(node.child3(), ballot); } @@ -775,11 +757,6 @@ private: vote(node.child1(), VariableAccessData::VoteDouble); break; - case ValueToNumber: - case ValueToDouble: - // Don't vote. - break; - case SetLocal: { PredictedType prediction = m_graph[node.child1()].prediction(); if (isDoublePrediction(prediction)) @@ -835,16 +812,6 @@ private: } while (m_changed); } - void toDouble(NodeIndex nodeIndex) - { - if (m_graph[nodeIndex].op == ValueToNumber) { -#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - printf(" @%u -> ValueToDouble", nodeIndex); -#endif - m_graph[nodeIndex].op = ValueToDouble; - } - } - void fixupNode(Node& node) { if (!node.shouldGenerate()) @@ -857,60 +824,6 @@ private: #endif switch (op) { - case ValueAdd: - case ArithAdd: - case ArithSub: { - PredictedType left = m_graph[node.child1()].prediction(); - PredictedType right = m_graph[node.child2()].prediction(); - - if (left && right - && isNumberPrediction(left) && isNumberPrediction(right) - && !m_graph.addShouldSpeculateInteger(node, m_codeBlock)) { - toDouble(node.child1()); - toDouble(node.child2()); - } - break; - } - - case ArithMul: - case ArithMin: - case ArithMax: - case ArithMod: - case ArithDiv: { - if (!nodeCanSpeculateInteger(node.arithNodeFlags())) { - toDouble(node.child1()); - toDouble(node.child2()); - break; - } - - PredictedType left = m_graph[node.child1()].prediction(); - PredictedType right = m_graph[node.child2()].prediction(); - - if (left && right - && ((left & PredictDouble) || (right & PredictDouble))) { - toDouble(node.child1()); - toDouble(node.child2()); - } - break; - } - - case ArithAbs: { - if (!nodeCanSpeculateInteger(node.arithNodeFlags())) { - toDouble(node.child1()); - break; - } - - PredictedType prediction = m_graph[node.child1()].prediction(); - if (prediction & PredictDouble) - toDouble(node.child1()); - break; - } - - case ArithSqrt: { - toDouble(node.child1()); - break; - } - case GetById: { if (!isInt32Prediction(m_graph[m_compileIndex].prediction())) break; @@ -977,8 +890,8 @@ private: case GetByVal: case StringCharAt: case StringCharCodeAt: { - if (node.child3() != NoNode && m_graph[node.child3()].op == Nop) - node.children.fixed.child3 = NoNode; + if (!!node.child3() && m_graph[node.child3()].op == Nop) + node.children.child3() = NodeUse(); break; } default: @@ -1004,14 +917,15 @@ private: if (nodeIndex == NoNode) return NoNode; - if (m_graph[nodeIndex].op == ValueToNumber) - nodeIndex = m_graph[nodeIndex].child1(); - if (m_graph[nodeIndex].op == ValueToInt32) - nodeIndex = m_graph[nodeIndex].child1(); + nodeIndex = m_graph[nodeIndex].child1().index(); return nodeIndex; } + NodeIndex canonicalize(NodeUse nodeUse) + { + return canonicalize(nodeUse.indexUnchecked()); + } // Computes where the search for a candidate for CSE should start. Don't call // this directly; call startIndex() instead as it does logging in debug mode. @@ -1061,7 +975,10 @@ private: NodeIndex startIndex() { Node& node = m_graph[m_compileIndex]; - return startIndexForChildren(node.child1(), node.child2(), node.child3()); + return startIndexForChildren( + node.child1().indexUnchecked(), + node.child2().indexUnchecked(), + node.child3().indexUnchecked()); } NodeIndex endIndexForPureCSE() @@ -1207,7 +1124,7 @@ private: break; case PutGlobalVar: if (node.varNumber() == varNumber && m_codeBlock->globalObjectFor(node.codeOrigin) == globalObject) - return node.child1(); + return node.child1().index(); break; default: break; @@ -1235,7 +1152,7 @@ private: if (!byValIsPure(node)) return NoNode; if (node.child1() == child1 && canonicalize(node.child2()) == canonicalize(child2)) - return node.child3(); + return node.child3().index(); // We must assume that the PutByVal will clobber the location we're getting from. // FIXME: We can do better; if we know that the PutByVal is accessing an array of a // different type than the GetByVal, then we know that they won't clobber each other. @@ -1328,7 +1245,7 @@ private: case PutByOffset: if (m_graph.m_storageAccessData[node.storageAccessDataIndex()].identifierNumber == identifierNumber) { if (node.child2() == child1) - return node.child3(); + return node.child3().index(); return NoNode; } break; @@ -1442,22 +1359,22 @@ private: return NoNode; } - void performSubstitution(NodeIndex& child, bool addRef = true) + void performSubstitution(NodeUse& child, bool addRef = true) { // Check if this operand is actually unused. - if (child == NoNode) + if (!child) return; // Check if there is any replacement. - NodeIndex replacement = m_replacements[child]; + NodeIndex replacement = m_replacements[child.index()]; if (replacement == NoNode) return; - child = replacement; + child.setIndex(replacement); // There is definitely a replacement. Assert that the replacement does not // have a replacement. - ASSERT(m_replacements[child] == NoNode); + ASSERT(m_replacements[child.index()] == NoNode); if (addRef) m_graph[child].ref(); @@ -1505,9 +1422,9 @@ private: for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++) performSubstitution(m_graph.m_varArgChildren[childIdx], shouldGenerate); } else { - performSubstitution(node.children.fixed.child1, shouldGenerate); - performSubstitution(node.children.fixed.child2, shouldGenerate); - performSubstitution(node.children.fixed.child3, shouldGenerate); + performSubstitution(node.children.child1(), shouldGenerate); + performSubstitution(node.children.child2(), shouldGenerate); + performSubstitution(node.children.child3(), shouldGenerate); } if (!shouldGenerate) @@ -1602,37 +1519,37 @@ private: case GetByVal: if (byValIsPure(node)) - setReplacement(getByValLoadElimination(node.child1(), node.child2())); + setReplacement(getByValLoadElimination(node.child1().index(), node.child2().index())); break; case PutByVal: - if (byValIsPure(node) && getByValLoadElimination(node.child1(), node.child2()) != NoNode) + if (byValIsPure(node) && getByValLoadElimination(node.child1().index(), node.child2().index()) != NoNode) node.op = PutByValAlias; break; case CheckStructure: - if (checkStructureLoadElimination(node.structureSet(), node.child1())) + if (checkStructureLoadElimination(node.structureSet(), node.child1().index())) eliminate(); break; case CheckFunction: - if (checkFunctionElimination(node.function(), node.child1())) + if (checkFunctionElimination(node.function(), node.child1().index())) eliminate(); break; case GetIndexedPropertyStorage: { PredictedType basePrediction = m_graph[node.child2()].prediction(); bool nodeHasIntegerIndexPrediction = !(!(basePrediction & PredictInt32) && basePrediction); - setReplacement(getIndexedPropertyStorageLoadElimination(node.child1(), nodeHasIntegerIndexPrediction)); + setReplacement(getIndexedPropertyStorageLoadElimination(node.child1().index(), nodeHasIntegerIndexPrediction)); break; } case GetPropertyStorage: - setReplacement(getPropertyStorageLoadElimination(node.child1())); + setReplacement(getPropertyStorageLoadElimination(node.child1().index())); break; case GetByOffset: - setReplacement(getByOffsetLoadElimination(m_graph.m_storageAccessData[node.storageAccessDataIndex()].identifierNumber, node.child1())); + setReplacement(getByOffsetLoadElimination(m_graph.m_storageAccessData[node.storageAccessDataIndex()].identifierNumber, node.child1().index())); break; default: diff --git a/Source/JavaScriptCore/dfg/DFGScoreBoard.h b/Source/JavaScriptCore/dfg/DFGScoreBoard.h index 7f9211a26..cc3272812 100644 --- a/Source/JavaScriptCore/dfg/DFGScoreBoard.h +++ b/Source/JavaScriptCore/dfg/DFGScoreBoard.h @@ -28,7 +28,7 @@ #if ENABLE(DFG_JIT) -#include <dfg/DFGGraph.h> +#include "DFGGraph.h" #include <wtf/BitVector.h> #include <wtf/Vector.h> @@ -106,6 +106,10 @@ public: m_free.append(index); } } + void use(NodeUse child) + { + use(child.indexUnchecked()); + } unsigned highWatermark() { diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp index e647fb87a..77b3e54b1 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp @@ -87,22 +87,22 @@ void SpeculativeJIT::useChildren(Node& node) for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++) use(m_jit.graph().m_varArgChildren[childIdx]); } else { - NodeIndex child1 = node.child1(); - if (child1 == NoNode) { - ASSERT(node.child2() == NoNode && node.child3() == NoNode); + NodeUse child1 = node.child1(); + if (!child1) { + ASSERT(!node.child2() && !node.child3()); return; } use(child1); - NodeIndex child2 = node.child2(); - if (child2 == NoNode) { - ASSERT(node.child3() == NoNode); + NodeUse child2 = node.child2(); + if (!child2) { + ASSERT(!node.child3()); return; } use(child2); - NodeIndex child3 = node.child3(); - if (child3 == NoNode) + NodeUse child3 = node.child3(); + if (!child3) return; use(child3); } @@ -249,7 +249,7 @@ void SpeculativeJIT::markCellCard(MacroAssembler& jit, GPRReg owner, GPRReg scra #endif } -void SpeculativeJIT::writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, NodeIndex valueIndex, WriteBarrierUseKind useKind, GPRReg scratch1, GPRReg scratch2) +void SpeculativeJIT::writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, NodeUse valueUse, WriteBarrierUseKind useKind, GPRReg scratch1, GPRReg scratch2) { UNUSED_PARAM(ownerGPR); UNUSED_PARAM(valueGPR); @@ -257,7 +257,7 @@ void SpeculativeJIT::writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, NodeIndex va UNUSED_PARAM(scratch2); UNUSED_PARAM(useKind); - if (isKnownNotCell(valueIndex)) + if (isKnownNotCell(valueUse.index())) return; #if ENABLE(WRITE_BARRIER_PROFILING) @@ -280,7 +280,7 @@ void SpeculativeJIT::writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, NodeIndex va JITCompiler::Jump rhsNotCell; bool hadCellCheck = false; - if (!isKnownCell(valueIndex) && !isCellPrediction(m_jit.getPrediction(valueIndex))) { + if (!isKnownCell(valueUse.index()) && !isCellPrediction(m_jit.getPrediction(valueUse.index()))) { hadCellCheck = true; rhsNotCell = m_jit.branchIfNotCell(valueGPR); } @@ -325,14 +325,14 @@ void SpeculativeJIT::writeBarrier(GPRReg ownerGPR, JSCell* value, WriteBarrierUs #endif } -void SpeculativeJIT::writeBarrier(JSCell* owner, GPRReg valueGPR, NodeIndex valueIndex, WriteBarrierUseKind useKind, GPRReg scratch) +void SpeculativeJIT::writeBarrier(JSCell* owner, GPRReg valueGPR, NodeUse valueUse, WriteBarrierUseKind useKind, GPRReg scratch) { UNUSED_PARAM(owner); UNUSED_PARAM(valueGPR); UNUSED_PARAM(scratch); UNUSED_PARAM(useKind); - if (isKnownNotCell(valueIndex)) + if (isKnownNotCell(valueUse.index())) return; #if ENABLE(WRITE_BARRIER_PROFILING) @@ -342,7 +342,7 @@ void SpeculativeJIT::writeBarrier(JSCell* owner, GPRReg valueGPR, NodeIndex valu #if ENABLE(GGC) JITCompiler::Jump rhsNotCell; bool hadCellCheck = false; - if (!isKnownCell(valueIndex) && !isCellPrediction(m_jit.getPrediction(valueIndex))) { + if (!isKnownCell(valueUse.index()) && !isCellPrediction(m_jit.getPrediction(valueUse.index()))) { hadCellCheck = true; rhsNotCell = m_jit.branchIfNotCell(valueGPR); } @@ -383,7 +383,7 @@ bool SpeculativeJIT::nonSpeculativeCompare(Node& node, MacroAssembler::Relationa bool SpeculativeJIT::nonSpeculativeStrictEq(Node& node, bool invert) { - if (!invert && (isKnownNumeric(node.child1()) || isKnownNumeric(node.child2()))) + if (!invert && (isKnownNumeric(node.child1().index()) || isKnownNumeric(node.child2().index()))) return nonSpeculativeCompare(node, MacroAssembler::Equal, operationCompareStrictEq); NodeIndex branchNodeIndex = detectPeepHoleBranch(); @@ -831,9 +831,9 @@ void SpeculativeJIT::compilePeepHoleObjectEquality(Node& node, NodeIndex branchN GPRReg op2GPR = op2.gpr(); if (!predictionCheck(m_state.forNode(node.child1()).m_type)) - speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo))); + speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node.child1().index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo))); if (!predictionCheck(m_state.forNode(node.child2()).m_type)) - speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node.child2(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo))); + speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node.child2().index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo))); addBranch(m_jit.branchPtr(condition, op1GPR, op2GPR), taken); if (notTaken != (m_block + 1)) @@ -855,13 +855,13 @@ void SpeculativeJIT::compilePeepHoleIntegerBranch(Node& node, NodeIndex branchNo notTaken = tmp; } - if (isInt32Constant(node.child1())) { - int32_t imm = valueOfInt32Constant(node.child1()); + if (isInt32Constant(node.child1().index())) { + int32_t imm = valueOfInt32Constant(node.child1().index()); SpeculateIntegerOperand op2(this, node.child2()); addBranch(m_jit.branch32(condition, JITCompiler::Imm32(imm), op2.gpr()), taken); - } else if (isInt32Constant(node.child2())) { + } else if (isInt32Constant(node.child2().index())) { SpeculateIntegerOperand op1(this, node.child1()); - int32_t imm = valueOfInt32Constant(node.child2()); + int32_t imm = valueOfInt32Constant(node.child2().index()); addBranch(m_jit.branch32(condition, op1.gpr(), JITCompiler::Imm32(imm)), taken); } else { SpeculateIntegerOperand op1(this, node.child1()); @@ -913,7 +913,7 @@ void SpeculativeJIT::compileMovHint(Node& node) { ASSERT(node.op == SetLocal); - setNodeIndexForOperand(node.child1(), node.local()); + setNodeIndexForOperand(node.child1().index(), node.local()); m_lastSetOperand = node.local(); } @@ -1268,15 +1268,8 @@ ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSo // Try to see if there is an alternate node that would contain the value we want. // There are four possibilities: // - // ValueToNumber: If the only live version of the value is a ValueToNumber node - // then it means that all remaining uses of the value would have performed a - // ValueToNumber conversion anyway. Thus, we can substitute ValueToNumber. - // - // ValueToInt32: Likewise, if the only remaining live version of the value is - // ValueToInt32, then we can use it. But if there is both a ValueToInt32 - // and a ValueToNumber, then we better go with ValueToNumber because it - // means that some remaining uses would have converted to number while - // others would have converted to Int32. + // ValueToInt32: If the only remaining live version of the value is + // ValueToInt32, then we can use it. // // UInt32ToNumber: If the only live version of the value is a UInt32ToNumber // then the only remaining uses are ones that want a properly formed number @@ -1289,7 +1282,7 @@ ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSo bool found = false; if (nodePtr->op == UInt32ToNumber) { - NodeIndex nodeIndex = nodePtr->child1(); + NodeIndex nodeIndex = nodePtr->child1().index(); nodePtr = &at(nodeIndex); infoPtr = &m_generationInfo[nodePtr->virtualRegister()]; if (infoPtr->alive() && infoPtr->nodeIndex() == nodeIndex) @@ -1297,7 +1290,6 @@ ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSo } if (!found) { - NodeIndex valueToNumberIndex = NoNode; NodeIndex valueToInt32Index = NoNode; NodeIndex uint32ToNumberIndex = NoNode; @@ -1311,10 +1303,6 @@ ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSo if (node.child1Unchecked() != valueSource.nodeIndex()) continue; switch (node.op) { - case ValueToNumber: - case ValueToDouble: - valueToNumberIndex = info.nodeIndex(); - break; case ValueToInt32: valueToInt32Index = info.nodeIndex(); break; @@ -1327,9 +1315,7 @@ ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSo } NodeIndex nodeIndexToUse; - if (valueToNumberIndex != NoNode) - nodeIndexToUse = valueToNumberIndex; - else if (valueToInt32Index != NoNode) + if (valueToInt32Index != NoNode) nodeIndexToUse = valueToInt32Index; else if (uint32ToNumberIndex != NoNode) nodeIndexToUse = uint32ToNumberIndex; @@ -1594,16 +1580,16 @@ static void compileClampDoubleToByte(JITCompiler& jit, GPRReg result, FPRReg sou void SpeculativeJIT::compilePutByValForByteArray(GPRReg base, GPRReg property, Node& node) { - NodeIndex baseIndex = node.child1(); - NodeIndex valueIndex = node.child3(); + NodeUse baseUse = node.child1(); + NodeUse valueUse = node.child3(); - if (!isByteArrayPrediction(m_state.forNode(baseIndex).m_type)) - speculationCheck(BadType, JSValueSource::unboxedCell(base), baseIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info))); + if (!isByteArrayPrediction(m_state.forNode(baseUse).m_type)) + speculationCheck(BadType, JSValueSource::unboxedCell(base), baseUse.index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info))); GPRTemporary value; GPRReg valueGPR; - if (at(valueIndex).isConstant()) { - JSValue jsValue = valueOfJSConstant(valueIndex); + if (at(valueUse).isConstant()) { + JSValue jsValue = valueOfJSConstant(valueUse.index()); if (!jsValue.isNumber()) { terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); noResult(m_compileIndex); @@ -1615,8 +1601,8 @@ void SpeculativeJIT::compilePutByValForByteArray(GPRReg base, GPRReg property, N m_jit.move(Imm32(clampedValue), scratchReg); value.adopt(scratch); valueGPR = scratchReg; - } else if (!at(valueIndex).shouldNotSpeculateInteger()) { - SpeculateIntegerOperand valueOp(this, valueIndex); + } else if (!at(valueUse).shouldNotSpeculateInteger()) { + SpeculateIntegerOperand valueOp(this, valueUse); GPRTemporary scratch(this); GPRReg scratchReg = scratch.gpr(); m_jit.move(valueOp.gpr(), scratchReg); @@ -1624,7 +1610,7 @@ void SpeculativeJIT::compilePutByValForByteArray(GPRReg base, GPRReg property, N value.adopt(scratch); valueGPR = scratchReg; } else { - SpeculateDoubleOperand valueOp(this, valueIndex); + SpeculateDoubleOperand valueOp(this, valueUse); GPRTemporary result(this); FPRTemporary floatScratch(this); FPRReg fpr = valueOp.fpr(); @@ -1745,16 +1731,16 @@ void SpeculativeJIT::compileGetByValOnIntTypedArray(const TypedArrayDescriptor& void SpeculativeJIT::compilePutByValForIntTypedArray(const TypedArrayDescriptor& descriptor, GPRReg base, GPRReg property, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements, TypedArraySignedness signedness, TypedArrayRounding rounding) { - NodeIndex baseIndex = node.child1(); - NodeIndex valueIndex = node.child3(); + NodeUse baseUse = node.child1(); + NodeUse valueUse = node.child3(); if (speculationRequirements != NoTypedArrayTypeSpecCheck) - speculationCheck(BadType, JSValueSource::unboxedCell(base), baseIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo))); + speculationCheck(BadType, JSValueSource::unboxedCell(base), baseUse, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo))); GPRTemporary value; GPRReg valueGPR; - if (at(valueIndex).isConstant()) { - JSValue jsValue = valueOfJSConstant(valueIndex); + if (at(valueUse).isConstant()) { + JSValue jsValue = valueOfJSConstant(valueUse.index()); if (!jsValue.isNumber()) { terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); noResult(m_compileIndex); @@ -1770,8 +1756,8 @@ void SpeculativeJIT::compilePutByValForIntTypedArray(const TypedArrayDescriptor& m_jit.move(Imm32(static_cast<int>(d)), scratchReg); value.adopt(scratch); valueGPR = scratchReg; - } else if (!at(valueIndex).shouldNotSpeculateInteger()) { - SpeculateIntegerOperand valueOp(this, valueIndex); + } else if (!at(valueUse).shouldNotSpeculateInteger()) { + SpeculateIntegerOperand valueOp(this, valueUse); GPRTemporary scratch(this); GPRReg scratchReg = scratch.gpr(); m_jit.move(valueOp.gpr(), scratchReg); @@ -1783,7 +1769,7 @@ void SpeculativeJIT::compilePutByValForIntTypedArray(const TypedArrayDescriptor& valueGPR = scratchReg; } else if (rounding == ClampRounding) { ASSERT(elementSize == 1); - SpeculateDoubleOperand valueOp(this, valueIndex); + SpeculateDoubleOperand valueOp(this, valueUse); GPRTemporary result(this); FPRTemporary floatScratch(this); FPRReg fpr = valueOp.fpr(); @@ -1792,7 +1778,7 @@ void SpeculativeJIT::compilePutByValForIntTypedArray(const TypedArrayDescriptor& value.adopt(result); valueGPR = gpr; } else { - SpeculateDoubleOperand valueOp(this, valueIndex); + SpeculateDoubleOperand valueOp(this, valueUse); GPRTemporary result(this); FPRReg fpr = valueOp.fpr(); GPRReg gpr = result.gpr(); @@ -1891,13 +1877,13 @@ void SpeculativeJIT::compileGetByValOnFloatTypedArray(const TypedArrayDescriptor void SpeculativeJIT::compilePutByValForFloatTypedArray(const TypedArrayDescriptor& descriptor, GPRReg base, GPRReg property, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements) { - NodeIndex baseIndex = node.child1(); - NodeIndex valueIndex = node.child3(); + NodeUse baseUse = node.child1(); + NodeUse valueUse = node.child3(); - SpeculateDoubleOperand valueOp(this, valueIndex); + SpeculateDoubleOperand valueOp(this, valueUse); if (speculationRequirements != NoTypedArrayTypeSpecCheck) - speculationCheck(BadType, JSValueSource::unboxedCell(base), baseIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo))); + speculationCheck(BadType, JSValueSource::unboxedCell(base), baseUse.index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo))); GPRTemporary result(this); @@ -2042,8 +2028,8 @@ void SpeculativeJIT::compileSoftModulo(Node& node) SpeculateStrictInt32Operand op1(this, node.child1()); GPRReg op1Gpr = op1.gpr(); - if (isInt32Constant(node.child2())) { - int32_t divisor = valueOfInt32Constant(node.child2()); + if (isInt32Constant(node.child2().index())) { + int32_t divisor = valueOfInt32Constant(node.child2().index()); if (divisor < 0) divisor = -divisor; @@ -2199,8 +2185,8 @@ void SpeculativeJIT::compileSoftModulo(Node& node) void SpeculativeJIT::compileAdd(Node& node) { if (m_jit.graph().addShouldSpeculateInteger(node, m_jit.codeBlock())) { - if (isNumberConstant(node.child1())) { - int32_t imm1 = valueOfNumberConstantAsInt32(node.child1()); + if (isNumberConstant(node.child1().index())) { + int32_t imm1 = valueOfNumberConstantAsInt32(node.child1().index()); SpeculateIntegerOperand op2(this, node.child2()); GPRTemporary result(this); @@ -2214,9 +2200,9 @@ void SpeculativeJIT::compileAdd(Node& node) return; } - if (isNumberConstant(node.child2())) { + if (isNumberConstant(node.child2().index())) { SpeculateIntegerOperand op1(this, node.child1()); - int32_t imm2 = valueOfNumberConstantAsInt32(node.child2()); + int32_t imm2 = valueOfNumberConstantAsInt32(node.child2().index()); GPRTemporary result(this); if (nodeCanTruncateInteger(node.arithNodeFlags())) { @@ -2279,9 +2265,9 @@ void SpeculativeJIT::compileAdd(Node& node) void SpeculativeJIT::compileArithSub(Node& node) { if (m_jit.graph().addShouldSpeculateInteger(node, m_jit.codeBlock())) { - if (isNumberConstant(node.child2())) { + if (isNumberConstant(node.child2().index())) { SpeculateIntegerOperand op1(this, node.child1()); - int32_t imm2 = valueOfNumberConstantAsInt32(node.child2()); + int32_t imm2 = valueOfNumberConstantAsInt32(node.child2().index()); GPRTemporary result(this); if (nodeCanTruncateInteger(node.arithNodeFlags())) { @@ -2294,8 +2280,8 @@ void SpeculativeJIT::compileArithSub(Node& node) return; } - if (isNumberConstant(node.child1())) { - int32_t imm1 = valueOfNumberConstantAsInt32(node.child1()); + if (isNumberConstant(node.child1().index())) { + int32_t imm1 = valueOfNumberConstantAsInt32(node.child1().index()); SpeculateIntegerOperand op2(this, node.child2()); GPRTemporary result(this); @@ -2421,7 +2407,7 @@ bool SpeculativeJIT::compare(Node& node, MacroAssembler::RelationalCondition con return false; } -bool SpeculativeJIT::compileStrictEqForConstant(Node& node, NodeIndex value, JSValue constant) +bool SpeculativeJIT::compileStrictEqForConstant(Node& node, NodeUse value, JSValue constant) { JSValueOperand op1(this, value); @@ -2498,14 +2484,14 @@ bool SpeculativeJIT::compileStrictEq(Node& node) // 1) If either operand is a constant and that constant is not a double, integer, // or string, then do a JSValue comparison. - if (isJSConstant(node.child1())) { - JSValue value = valueOfJSConstant(node.child1()); + if (isJSConstant(node.child1().index())) { + JSValue value = valueOfJSConstant(node.child1().index()); if (!value.isNumber() && !value.isString()) return compileStrictEqForConstant(node, node.child2(), value); } - if (isJSConstant(node.child2())) { - JSValue value = valueOfJSConstant(node.child2()); + if (isJSConstant(node.child2().index())) { + JSValue value = valueOfJSConstant(node.child2().index()); if (!value.isNumber() && !value.isString()) return compileStrictEqForConstant(node, node.child1(), value); } diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h index 0098da3a1..cfb2189cf 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h @@ -33,6 +33,7 @@ #include "DFGJITCompiler.h" #include "DFGOSRExit.h" #include "DFGOperations.h" +#include "MarkedAllocator.h" #include "ValueRecovery.h" namespace JSC { namespace DFG { @@ -181,6 +182,10 @@ public: { return m_jit.graph()[nodeIndex]; } + Node& at(NodeUse nodeUse) + { + return at(nodeUse.index()); + } GPRReg fillInteger(NodeIndex, DataFormat& returnFormat); FPRReg fillDouble(NodeIndex); @@ -217,6 +222,10 @@ public: GenerationInfo& info = m_generationInfo[virtualRegister]; return info.canReuse(); } + bool canReuse(NodeUse nodeUse) + { + return canReuse(nodeUse.index()); + } GPRReg reuse(GPRReg reg) { m_gprs.lock(reg); @@ -317,13 +326,17 @@ public: m_gprs.release(info.gpr()); #endif } + void use(NodeUse nodeUse) + { + use(nodeUse.index()); + } static void markCellCard(MacroAssembler&, GPRReg ownerGPR, GPRReg scratchGPR1, GPRReg scratchGPR2); static void writeBarrier(MacroAssembler&, GPRReg ownerGPR, GPRReg scratchGPR1, GPRReg scratchGPR2, WriteBarrierUseKind); - void writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, NodeIndex valueIndex, WriteBarrierUseKind, GPRReg scratchGPR1 = InvalidGPRReg, GPRReg scratchGPR2 = InvalidGPRReg); + void writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, NodeUse valueUse, WriteBarrierUseKind, GPRReg scratchGPR1 = InvalidGPRReg, GPRReg scratchGPR2 = InvalidGPRReg); void writeBarrier(GPRReg ownerGPR, JSCell* value, WriteBarrierUseKind, GPRReg scratchGPR1 = InvalidGPRReg, GPRReg scratchGPR2 = InvalidGPRReg); - void writeBarrier(JSCell* owner, GPRReg valueGPR, NodeIndex valueIndex, WriteBarrierUseKind, GPRReg scratchGPR1 = InvalidGPRReg); + void writeBarrier(JSCell* owner, GPRReg valueGPR, NodeUse valueUse, WriteBarrierUseKind, GPRReg scratchGPR1 = InvalidGPRReg); static GPRReg selectScratchGPR(GPRReg preserve1 = InvalidGPRReg, GPRReg preserve2 = InvalidGPRReg, GPRReg preserve3 = InvalidGPRReg, GPRReg preserve4 = InvalidGPRReg) { @@ -874,7 +887,7 @@ private: // Check if the lastNode is a branch on this node. Node& lastNode = at(lastNodeIndex); - return lastNode.op == Branch && lastNode.child1() == m_compileIndex ? lastNodeIndex : NoNode; + return lastNode.op == Branch && lastNode.child1().index() == m_compileIndex ? lastNodeIndex : NoNode; } void nonSpeculativeValueToNumber(Node&); @@ -884,15 +897,15 @@ private: enum SpillRegistersMode { NeedToSpill, DontSpill }; #if USE(JSVALUE64) JITCompiler::Call cachedGetById(CodeOrigin, GPRReg baseGPR, GPRReg resultGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), SpillRegistersMode = NeedToSpill); - void cachedPutById(CodeOrigin, GPRReg base, GPRReg value, NodeIndex valueIndex, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump()); + void cachedPutById(CodeOrigin, GPRReg base, GPRReg value, NodeUse valueUse, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump()); #elif USE(JSVALUE32_64) JITCompiler::Call cachedGetById(CodeOrigin, GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), SpillRegistersMode = NeedToSpill); - void cachedPutById(CodeOrigin, GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, NodeIndex valueIndex, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump()); + void cachedPutById(CodeOrigin, GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, NodeUse valueUse, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump()); #endif - void nonSpeculativeNonPeepholeCompareNull(NodeIndex operand, bool invert = false); - void nonSpeculativePeepholeBranchNull(NodeIndex operand, NodeIndex branchNodeIndex, bool invert = false); - bool nonSpeculativeCompareNull(Node&, NodeIndex operand, bool invert = false); + void nonSpeculativeNonPeepholeCompareNull(NodeUse operand, bool invert = false); + void nonSpeculativePeepholeBranchNull(NodeUse operand, NodeIndex branchNodeIndex, bool invert = false); + bool nonSpeculativeCompareNull(Node&, NodeUse operand, bool invert = false); void nonSpeculativePeepholeBranch(Node&, NodeIndex branchNodeIndex, MacroAssembler::RelationalCondition, S_DFGOperation_EJJ helperFunction); void nonSpeculativeNonPeepholeCompare(Node&, MacroAssembler::RelationalCondition, S_DFGOperation_EJJ helperFunction); @@ -1504,15 +1517,15 @@ private: void compilePeepHoleObjectEquality(Node&, NodeIndex branchNodeIndex, const ClassInfo*, PredictionChecker); void compileObjectEquality(Node&, const ClassInfo*, PredictionChecker); void compileValueAdd(Node&); - void compileObjectOrOtherLogicalNot(NodeIndex value, const ClassInfo*, bool needSpeculationCheck); + void compileObjectOrOtherLogicalNot(NodeUse value, const ClassInfo*, bool needSpeculationCheck); void compileLogicalNot(Node&); - void emitObjectOrOtherBranch(NodeIndex value, BlockIndex taken, BlockIndex notTaken, const ClassInfo*, bool needSpeculationCheck); + void emitObjectOrOtherBranch(NodeUse value, BlockIndex taken, BlockIndex notTaken, const ClassInfo*, bool needSpeculationCheck); void emitBranch(Node&); void compileIntegerCompare(Node&, MacroAssembler::RelationalCondition); void compileDoubleCompare(Node&, MacroAssembler::DoubleCondition); - bool compileStrictEqForConstant(Node&, NodeIndex value, JSValue constant); + bool compileStrictEqForConstant(Node&, NodeUse value, JSValue constant); bool compileStrictEq(Node&); @@ -1552,9 +1565,9 @@ private: template<typename T> void emitAllocateJSFinalObject(T structure, GPRReg resultGPR, GPRReg scratchGPR, MacroAssembler::JumpList& slowPath) { - MarkedSpace::SizeClass* sizeClass = &m_jit.globalData()->heap.sizeClassForObject(sizeof(JSFinalObject)); + MarkedAllocator* allocator = &m_jit.globalData()->heap.allocatorForObject(sizeof(JSFinalObject)); - m_jit.loadPtr(&sizeClass->firstFreeCell, resultGPR); + m_jit.loadPtr(&allocator->m_firstFreeCell, resultGPR); slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, resultGPR)); // The object is half-allocated: we have what we know is a fresh object, but @@ -1566,7 +1579,7 @@ private: // Now that we have scratchGPR back, remove the object from the free list m_jit.loadPtr(MacroAssembler::Address(resultGPR), scratchGPR); - m_jit.storePtr(scratchGPR, &sizeClass->firstFreeCell); + m_jit.storePtr(scratchGPR, &allocator->m_firstFreeCell); // Initialize the object's classInfo pointer m_jit.storePtr(MacroAssembler::TrustedImmPtr(&JSFinalObject::s_info), MacroAssembler::Address(resultGPR, JSCell::classInfoOffset())); @@ -1592,6 +1605,10 @@ private: return; m_jit.codeBlock()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.valueProfileFor(nodeIndex), jumpToFail, this)); } + void speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeUse nodeUse, MacroAssembler::Jump jumpToFail) + { + speculationCheck(kind, jsValueSource, nodeUse.index(), jumpToFail); + } // Add a set of speculation checks without additional recovery. void speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::JumpList& jumpsToFail) { @@ -1599,6 +1616,10 @@ private: for (unsigned i = 0; i < JumpVector.size(); ++i) speculationCheck(kind, jsValueSource, nodeIndex, JumpVector[i]); } + void speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeUse nodeUse, MacroAssembler::JumpList& jumpsToFail) + { + speculationCheck(kind, jsValueSource, nodeUse.index(), jumpsToFail); + } // Add a speculation check with additional recovery. void speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery) { @@ -1607,6 +1628,10 @@ private: m_jit.codeBlock()->appendSpeculationRecovery(recovery); m_jit.codeBlock()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.valueProfileFor(nodeIndex), jumpToFail, this, m_jit.codeBlock()->numberOfSpeculationRecoveries())); } + void speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeUse nodeUse, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery) + { + speculationCheck(kind, jsValueSource, nodeUse.index(), jumpToFail, recovery); + } // Called when we statically determine that a speculation will fail. void terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, NodeIndex nodeIndex) @@ -1619,6 +1644,10 @@ private: speculationCheck(kind, jsValueRegs, nodeIndex, m_jit.jump()); m_compileOkay = false; } + void terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, NodeUse nodeUse) + { + terminateSpeculativeExecution(kind, jsValueRegs, nodeUse.index()); + } template<bool strict> GPRReg fillSpeculateIntInternal(NodeIndex, DataFormat& returnFormat); @@ -1711,16 +1740,16 @@ private: class IntegerOperand { public: - explicit IntegerOperand(SpeculativeJIT* jit, NodeIndex index) + explicit IntegerOperand(SpeculativeJIT* jit, NodeUse use) : m_jit(jit) - , m_index(index) + , m_index(use.index()) , m_gprOrInvalid(InvalidGPRReg) #ifndef NDEBUG , m_format(DataFormatNone) #endif { ASSERT(m_jit); - if (jit->isFilled(index)) + if (jit->isFilled(m_index)) gpr(); } @@ -1763,13 +1792,13 @@ private: class DoubleOperand { public: - explicit DoubleOperand(SpeculativeJIT* jit, NodeIndex index) + explicit DoubleOperand(SpeculativeJIT* jit, NodeUse use) : m_jit(jit) - , m_index(index) + , m_index(use.index()) , m_fprOrInvalid(InvalidFPRReg) { ASSERT(m_jit); - if (jit->isFilledDouble(index)) + if (jit->isFilledDouble(m_index)) fpr(); } @@ -1804,9 +1833,9 @@ private: class JSValueOperand { public: - explicit JSValueOperand(SpeculativeJIT* jit, NodeIndex index) + explicit JSValueOperand(SpeculativeJIT* jit, NodeUse use) : m_jit(jit) - , m_index(index) + , m_index(use.index()) #if USE(JSVALUE64) , m_gprOrInvalid(InvalidGPRReg) #elif USE(JSVALUE32_64) @@ -1815,12 +1844,12 @@ public: { ASSERT(m_jit); #if USE(JSVALUE64) - if (jit->isFilled(index)) + if (jit->isFilled(m_index)) gpr(); #elif USE(JSVALUE32_64) m_register.pair.tagGPR = InvalidGPRReg; m_register.pair.payloadGPR = InvalidGPRReg; - if (jit->isFilled(index)) + if (jit->isFilled(m_index)) fill(); #endif } @@ -1918,13 +1947,13 @@ private: class StorageOperand { public: - explicit StorageOperand(SpeculativeJIT* jit, NodeIndex index) + explicit StorageOperand(SpeculativeJIT* jit, NodeUse use) : m_jit(jit) - , m_index(index) + , m_index(use.index()) , m_gprOrInvalid(InvalidGPRReg) { ASSERT(m_jit); - if (jit->isFilled(index)) + if (jit->isFilled(m_index)) gpr(); } @@ -2087,16 +2116,16 @@ private: class SpeculateIntegerOperand { public: - explicit SpeculateIntegerOperand(SpeculativeJIT* jit, NodeIndex index) + explicit SpeculateIntegerOperand(SpeculativeJIT* jit, NodeUse use) : m_jit(jit) - , m_index(index) + , m_index(use.index()) , m_gprOrInvalid(InvalidGPRReg) #ifndef NDEBUG , m_format(DataFormatNone) #endif { ASSERT(m_jit); - if (jit->isFilled(index)) + if (jit->isFilled(m_index)) gpr(); } @@ -2134,13 +2163,13 @@ private: class SpeculateStrictInt32Operand { public: - explicit SpeculateStrictInt32Operand(SpeculativeJIT* jit, NodeIndex index) + explicit SpeculateStrictInt32Operand(SpeculativeJIT* jit, NodeUse use) : m_jit(jit) - , m_index(index) + , m_index(use.index()) , m_gprOrInvalid(InvalidGPRReg) { ASSERT(m_jit); - if (jit->isFilled(index)) + if (jit->isFilled(m_index)) gpr(); } @@ -2175,13 +2204,13 @@ private: class SpeculateDoubleOperand { public: - explicit SpeculateDoubleOperand(SpeculativeJIT* jit, NodeIndex index) + explicit SpeculateDoubleOperand(SpeculativeJIT* jit, NodeUse use) : m_jit(jit) - , m_index(index) + , m_index(use.index()) , m_fprOrInvalid(InvalidFPRReg) { ASSERT(m_jit); - if (jit->isFilled(index)) + if (jit->isFilled(m_index)) fpr(); } @@ -2211,13 +2240,13 @@ private: class SpeculateCellOperand { public: - explicit SpeculateCellOperand(SpeculativeJIT* jit, NodeIndex index) + explicit SpeculateCellOperand(SpeculativeJIT* jit, NodeUse use) : m_jit(jit) - , m_index(index) + , m_index(use.index()) , m_gprOrInvalid(InvalidGPRReg) { ASSERT(m_jit); - if (jit->isFilled(index)) + if (jit->isFilled(m_index)) gpr(); } @@ -2252,13 +2281,13 @@ private: class SpeculateBooleanOperand { public: - explicit SpeculateBooleanOperand(SpeculativeJIT* jit, NodeIndex index) + explicit SpeculateBooleanOperand(SpeculativeJIT* jit, NodeUse use) : m_jit(jit) - , m_index(index) + , m_index(use.index()) , m_gprOrInvalid(InvalidGPRReg) { ASSERT(m_jit); - if (jit->isFilled(index)) + if (jit->isFilled(m_index)) gpr(); } diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp index e1f92ba9e..a2cdec086 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp @@ -360,7 +360,7 @@ bool SpeculativeJIT::fillJSValue(NodeIndex nodeIndex, GPRReg& tagGPR, GPRReg& pa void SpeculativeJIT::nonSpeculativeValueToNumber(Node& node) { - if (isKnownNumeric(node.child1())) { + if (isKnownNumeric(node.child1().index())) { JSValueOperand op1(this, node.child1()); op1.fill(); if (op1.isDouble()) { @@ -381,8 +381,8 @@ void SpeculativeJIT::nonSpeculativeValueToNumber(Node& node) GPRTemporary resultTag(this, op1); GPRTemporary resultPayload(this, op1, false); - ASSERT(!isInt32Constant(node.child1())); - ASSERT(!isNumberConstant(node.child1())); + ASSERT(!isInt32Constant(node.child1().index())); + ASSERT(!isNumberConstant(node.child1().index())); GPRReg tagGPR = op1.tagGPR(); GPRReg payloadGPR = op1.payloadGPR(); @@ -415,9 +415,9 @@ void SpeculativeJIT::nonSpeculativeValueToNumber(Node& node) void SpeculativeJIT::nonSpeculativeValueToInt32(Node& node) { - ASSERT(!isInt32Constant(node.child1())); + ASSERT(!isInt32Constant(node.child1().index())); - if (isKnownInteger(node.child1())) { + if (isKnownInteger(node.child1().index())) { IntegerOperand op1(this, node.child1()); GPRTemporary result(this, op1); m_jit.move(op1.gpr(), result.gpr()); @@ -532,14 +532,14 @@ JITCompiler::Call SpeculativeJIT::cachedGetById(CodeOrigin codeOrigin, GPRReg ba return functionCall; } -void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, NodeIndex valueIndex, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget) +void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, NodeUse valueUse, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget) { m_jit.beginUninterruptedSequence(); JITCompiler::DataLabelPtr structureToCompare; JITCompiler::Jump structureCheck = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(basePayloadGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1))); m_jit.endUninterruptedSequence(); - writeBarrier(basePayloadGPR, valueTagGPR, valueIndex, WriteBarrierForPropertyAccess, scratchGPR); + writeBarrier(basePayloadGPR, valueTagGPR, valueUse, WriteBarrierForPropertyAccess, scratchGPR); m_jit.loadPtr(JITCompiler::Address(basePayloadGPR, JSObject::offsetOfPropertyStorage()), scratchGPR); JITCompiler::DataLabel32 tagStoreWithPatch = m_jit.store32WithAddressOffsetPatch(valueTagGPR, JITCompiler::Address(scratchGPR, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag))); @@ -576,7 +576,7 @@ void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg basePayloadGPR, m_jit.addPropertyAccess(PropertyAccessRecord(codeOrigin, structureToCompare, functionCall, structureCheck, JITCompiler::DataLabelCompact(tagStoreWithPatch.label()), JITCompiler::DataLabelCompact(payloadStoreWithPatch.label()), slowCase, doneLabel, safeCast<int8_t>(basePayloadGPR), safeCast<int8_t>(valueTagGPR), safeCast<int8_t>(valuePayloadGPR), safeCast<int8_t>(scratchGPR))); } -void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull(NodeIndex operand, bool invert) +void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull(NodeUse operand, bool invert) { JSValueOperand arg(this, operand); GPRReg argTagGPR = arg.tagGPR(); @@ -586,13 +586,13 @@ void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull(NodeIndex operand, boo GPRReg resultPayloadGPR = resultPayload.gpr(); JITCompiler::Jump notCell; - if (!isKnownCell(operand)) + if (!isKnownCell(operand.index())) notCell = m_jit.branch32(MacroAssembler::NotEqual, argTagGPR, TrustedImm32(JSValue::CellTag)); m_jit.loadPtr(JITCompiler::Address(argPayloadGPR, JSCell::structureOffset()), resultPayloadGPR); m_jit.test8(invert ? JITCompiler::Zero : JITCompiler::NonZero, JITCompiler::Address(resultPayloadGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined), resultPayloadGPR); - if (!isKnownCell(operand)) { + if (!isKnownCell(operand.index())) { JITCompiler::Jump done = m_jit.jump(); notCell.link(&m_jit); @@ -608,7 +608,7 @@ void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull(NodeIndex operand, boo booleanResult(resultPayloadGPR, m_compileIndex); } -void SpeculativeJIT::nonSpeculativePeepholeBranchNull(NodeIndex operand, NodeIndex branchNodeIndex, bool invert) +void SpeculativeJIT::nonSpeculativePeepholeBranchNull(NodeUse operand, NodeIndex branchNodeIndex, bool invert) { Node& branchNode = at(branchNodeIndex); BlockIndex taken = branchNode.takenBlockIndex(); @@ -630,13 +630,13 @@ void SpeculativeJIT::nonSpeculativePeepholeBranchNull(NodeIndex operand, NodeInd JITCompiler::Jump notCell; - if (!isKnownCell(operand)) + if (!isKnownCell(operand.index())) notCell = m_jit.branch32(MacroAssembler::NotEqual, argTagGPR, TrustedImm32(JSValue::CellTag)); m_jit.loadPtr(JITCompiler::Address(argPayloadGPR, JSCell::structureOffset()), resultGPR); addBranch(m_jit.branchTest8(invert ? JITCompiler::Zero : JITCompiler::NonZero, JITCompiler::Address(resultGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined)), taken); - if (!isKnownCell(operand)) { + if (!isKnownCell(operand.index())) { addBranch(m_jit.jump(), notTaken); notCell.link(&m_jit); @@ -651,7 +651,7 @@ void SpeculativeJIT::nonSpeculativePeepholeBranchNull(NodeIndex operand, NodeInd addBranch(m_jit.jump(), notTaken); } -bool SpeculativeJIT::nonSpeculativeCompareNull(Node& node, NodeIndex operand, bool invert) +bool SpeculativeJIT::nonSpeculativeCompareNull(Node& node, NodeUse operand, bool invert) { NodeIndex branchNodeIndex = detectPeepHoleBranch(); if (branchNodeIndex != NoNode) { @@ -698,7 +698,7 @@ void SpeculativeJIT::nonSpeculativePeepholeBranch(Node& node, NodeIndex branchNo JITCompiler::JumpList slowPath; - if (isKnownNotInteger(node.child1()) || isKnownNotInteger(node.child2())) { + if (isKnownNotInteger(node.child1().index()) || isKnownNotInteger(node.child2().index())) { GPRResult result(this); GPRReg resultGPR = result.gpr(); @@ -716,14 +716,14 @@ void SpeculativeJIT::nonSpeculativePeepholeBranch(Node& node, NodeIndex branchNo arg1.use(); arg2.use(); - if (!isKnownInteger(node.child1())) + if (!isKnownInteger(node.child1().index())) slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, arg1TagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag))); - if (!isKnownInteger(node.child2())) + if (!isKnownInteger(node.child2().index())) slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, arg2TagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag))); addBranch(m_jit.branch32(cond, arg1PayloadGPR, arg2PayloadGPR), taken); - if (!isKnownInteger(node.child1()) || !isKnownInteger(node.child2())) { + if (!isKnownInteger(node.child1().index()) || !isKnownInteger(node.child2().index())) { addBranch(m_jit.jump(), notTaken); slowPath.link(&m_jit); @@ -751,7 +751,7 @@ void SpeculativeJIT::nonSpeculativeNonPeepholeCompare(Node& node, MacroAssembler JITCompiler::JumpList slowPath; - if (isKnownNotInteger(node.child1()) || isKnownNotInteger(node.child2())) { + if (isKnownNotInteger(node.child1().index()) || isKnownNotInteger(node.child2().index())) { GPRResult result(this); GPRReg resultPayloadGPR = result.gpr(); @@ -769,14 +769,14 @@ void SpeculativeJIT::nonSpeculativeNonPeepholeCompare(Node& node, MacroAssembler arg1.use(); arg2.use(); - if (!isKnownInteger(node.child1())) + if (!isKnownInteger(node.child1().index())) slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, arg1TagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag))); - if (!isKnownInteger(node.child2())) + if (!isKnownInteger(node.child2().index())) slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, arg2TagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag))); m_jit.compare32(cond, arg1PayloadGPR, arg2PayloadGPR, resultPayloadGPR); - if (!isKnownInteger(node.child1()) || !isKnownInteger(node.child2())) { + if (!isKnownInteger(node.child1().index()) || !isKnownInteger(node.child2().index())) { JITCompiler::Jump haveResult = m_jit.jump(); slowPath.link(&m_jit); @@ -822,7 +822,7 @@ void SpeculativeJIT::nonSpeculativePeepholeStrictEq(Node& node, NodeIndex branch arg1.use(); arg2.use(); - if (isKnownCell(node.child1()) && isKnownCell(node.child2())) { + if (isKnownCell(node.child1().index()) && isKnownCell(node.child2().index())) { // see if we get lucky: if the arguments are cells and they reference the same // cell, then they must be strictly equal. addBranch(m_jit.branchPtr(JITCompiler::Equal, arg1PayloadGPR, arg2PayloadGPR), invert ? notTaken : taken); @@ -861,7 +861,7 @@ void SpeculativeJIT::nonSpeculativeNonPeepholeStrictEq(Node& node, bool invert) arg1.use(); arg2.use(); - if (isKnownCell(node.child1()) && isKnownCell(node.child2())) { + if (isKnownCell(node.child1().index()) && isKnownCell(node.child2().index())) { // see if we get lucky: if the arguments are cells and they reference the same // cell, then they must be strictly equal. JITCompiler::Jump notEqualCase = m_jit.branchPtr(JITCompiler::NotEqual, arg1PayloadGPR, arg2PayloadGPR); @@ -908,11 +908,11 @@ void SpeculativeJIT::emitCall(Node& node) CallLinkInfo::CallType callType = node.op == Call ? CallLinkInfo::Call : CallLinkInfo::Construct; - NodeIndex calleeNodeIndex = m_jit.graph().m_varArgChildren[node.firstChild()]; - JSValueOperand callee(this, calleeNodeIndex); + NodeUse calleeNodeUse = m_jit.graph().m_varArgChildren[node.firstChild()]; + JSValueOperand callee(this, calleeNodeUse); GPRReg calleeTagGPR = callee.tagGPR(); GPRReg calleePayloadGPR = callee.payloadGPR(); - use(calleeNodeIndex); + use(calleeNodeUse); // The call instruction's first child is either the function (normal call) or the // receiver (method call). subsequent children are the arguments. @@ -924,11 +924,11 @@ void SpeculativeJIT::emitCall(Node& node) m_jit.store32(calleeTagGPR, callFrameTagSlot(RegisterFile::Callee)); for (int i = 0; i < numPassedArgs; i++) { - NodeIndex argNodeIndex = m_jit.graph().m_varArgChildren[node.firstChild() + 1 + i]; - JSValueOperand arg(this, argNodeIndex); + NodeUse argNodeUse = m_jit.graph().m_varArgChildren[node.firstChild() + 1 + i]; + JSValueOperand arg(this, argNodeUse); GPRReg argTagGPR = arg.tagGPR(); GPRReg argPayloadGPR = arg.payloadGPR(); - use(argNodeIndex); + use(argNodeUse); m_jit.store32(argTagGPR, argumentTagSlot(i + dummyThisArgument)); m_jit.store32(argPayloadGPR, argumentPayloadSlot(i + dummyThisArgument)); @@ -1439,7 +1439,7 @@ void SpeculativeJIT::compileValueAdd(Node& node) GPRResult2 resultTag(this); GPRResult resultPayload(this); - if (isKnownNotNumber(node.child1()) || isKnownNotNumber(node.child2())) + if (isKnownNotNumber(node.child1().index()) || isKnownNotNumber(node.child2().index())) callOperation(operationValueAddNotNumber, resultTag.gpr(), resultPayload.gpr(), op1TagGPR, op1PayloadGPR, op2TagGPR, op2PayloadGPR); else callOperation(operationValueAdd, resultTag.gpr(), resultPayload.gpr(), op1TagGPR, op1PayloadGPR, op2TagGPR, op2PayloadGPR); @@ -1447,9 +1447,9 @@ void SpeculativeJIT::compileValueAdd(Node& node) jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex); } -void SpeculativeJIT::compileObjectOrOtherLogicalNot(NodeIndex nodeIndex, const ClassInfo* classInfo, bool needSpeculationCheck) +void SpeculativeJIT::compileObjectOrOtherLogicalNot(NodeUse nodeUse, const ClassInfo* classInfo, bool needSpeculationCheck) { - JSValueOperand value(this, nodeIndex); + JSValueOperand value(this, nodeUse); GPRTemporary resultPayload(this); GPRReg valueTagGPR = value.tagGPR(); GPRReg valuePayloadGPR = value.payloadGPR(); @@ -1457,7 +1457,7 @@ void SpeculativeJIT::compileObjectOrOtherLogicalNot(NodeIndex nodeIndex, const C MacroAssembler::Jump notCell = m_jit.branch32(MacroAssembler::NotEqual, valueTagGPR, TrustedImm32(JSValue::CellTag)); if (needSpeculationCheck) - speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valuePayloadGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo))); + speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valuePayloadGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo))); m_jit.move(TrustedImm32(0), resultPayloadGPR); MacroAssembler::Jump done = m_jit.jump(); @@ -1467,7 +1467,7 @@ void SpeculativeJIT::compileObjectOrOtherLogicalNot(NodeIndex nodeIndex, const C if (needSpeculationCheck) { m_jit.move(valueTagGPR, resultPayloadGPR); m_jit.or32(TrustedImm32(1), resultPayloadGPR); - speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, resultPayloadGPR, TrustedImm32(JSValue::NullTag))); + speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, m_jit.branch32(MacroAssembler::NotEqual, resultPayloadGPR, TrustedImm32(JSValue::NullTag))); } m_jit.move(TrustedImm32(1), resultPayloadGPR); @@ -1478,7 +1478,7 @@ void SpeculativeJIT::compileObjectOrOtherLogicalNot(NodeIndex nodeIndex, const C void SpeculativeJIT::compileLogicalNot(Node& node) { - if (isKnownBoolean(node.child1()) || isBooleanPrediction(m_jit.getPrediction(node.child1()))) { + if (isKnownBoolean(node.child1().index()) || isBooleanPrediction(m_jit.getPrediction(node.child1().index()))) { SpeculateBooleanOperand value(this, node.child1()); GPRTemporary result(this, value); m_jit.xor32(TrustedImm32(1), value.gpr(), result.gpr()); @@ -1535,9 +1535,9 @@ void SpeculativeJIT::compileLogicalNot(Node& node) booleanResult(resultPayloadGPR, m_compileIndex, UseChildrenCalledExplicitly); } -void SpeculativeJIT::emitObjectOrOtherBranch(NodeIndex nodeIndex, BlockIndex taken, BlockIndex notTaken, const ClassInfo* classInfo, bool needSpeculationCheck) +void SpeculativeJIT::emitObjectOrOtherBranch(NodeUse nodeUse, BlockIndex taken, BlockIndex notTaken, const ClassInfo* classInfo, bool needSpeculationCheck) { - JSValueOperand value(this, nodeIndex); + JSValueOperand value(this, nodeUse); GPRTemporary scratch(this); GPRReg valueTagGPR = value.tagGPR(); GPRReg valuePayloadGPR = value.payloadGPR(); @@ -1545,7 +1545,7 @@ void SpeculativeJIT::emitObjectOrOtherBranch(NodeIndex nodeIndex, BlockIndex tak MacroAssembler::Jump notCell = m_jit.branch32(MacroAssembler::NotEqual, valueTagGPR, TrustedImm32(JSValue::CellTag)); if (needSpeculationCheck) - speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valuePayloadGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo))); + speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valuePayloadGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo))); addBranch(m_jit.jump(), taken); notCell.link(&m_jit); @@ -1554,7 +1554,7 @@ void SpeculativeJIT::emitObjectOrOtherBranch(NodeIndex nodeIndex, BlockIndex tak if (needSpeculationCheck) { m_jit.move(valueTagGPR, scratchGPR); m_jit.or32(TrustedImm32(1), scratchGPR); - speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, scratchGPR, TrustedImm32(JSValue::NullTag))); + speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, m_jit.branch32(MacroAssembler::NotEqual, scratchGPR, TrustedImm32(JSValue::NullTag))); } if (notTaken != (m_block + 1)) @@ -1568,7 +1568,7 @@ void SpeculativeJIT::emitBranch(Node& node) BlockIndex taken = node.takenBlockIndex(); BlockIndex notTaken = node.notTakenBlockIndex(); - if (isKnownBoolean(node.child1())) { + if (isKnownBoolean(node.child1().index())) { SpeculateBooleanOperand value(this, node.child1()); MacroAssembler::ResultCondition condition = MacroAssembler::NonZero; @@ -1800,18 +1800,18 @@ void SpeculativeJIT::compile(Node& node) case BitAnd: case BitOr: case BitXor: - if (isInt32Constant(node.child1())) { + if (isInt32Constant(node.child1().index())) { SpeculateIntegerOperand op2(this, node.child2()); GPRTemporary result(this, op2); - bitOp(op, valueOfInt32Constant(node.child1()), op2.gpr(), result.gpr()); + bitOp(op, valueOfInt32Constant(node.child1().index()), op2.gpr(), result.gpr()); integerResult(result.gpr(), m_compileIndex); - } else if (isInt32Constant(node.child2())) { + } else if (isInt32Constant(node.child2().index())) { SpeculateIntegerOperand op1(this, node.child1()); GPRTemporary result(this, op1); - bitOp(op, valueOfInt32Constant(node.child2()), op1.gpr(), result.gpr()); + bitOp(op, valueOfInt32Constant(node.child2().index()), op1.gpr(), result.gpr()); integerResult(result.gpr(), m_compileIndex); } else { @@ -1830,11 +1830,11 @@ void SpeculativeJIT::compile(Node& node) case BitRShift: case BitLShift: case BitURShift: - if (isInt32Constant(node.child2())) { + if (isInt32Constant(node.child2().index())) { SpeculateIntegerOperand op1(this, node.child1()); GPRTemporary result(this, op1); - shiftOp(op, op1.gpr(), valueOfInt32Constant(node.child2()) & 0x1f, result.gpr()); + shiftOp(op, op1.gpr(), valueOfInt32Constant(node.child2().index()) & 0x1f, result.gpr()); integerResult(result.gpr(), m_compileIndex); } else { @@ -1861,30 +1861,6 @@ void SpeculativeJIT::compile(Node& node) break; } - case ValueToNumber: { - if (at(node.child1()).shouldNotSpeculateInteger()) { - SpeculateDoubleOperand op1(this, node.child1()); - FPRTemporary result(this, op1); - m_jit.moveDouble(op1.fpr(), result.fpr()); - doubleResult(result.fpr(), m_compileIndex); - break; - } - - SpeculateIntegerOperand op1(this, node.child1()); - GPRTemporary result(this, op1); - m_jit.move(op1.gpr(), result.gpr()); - integerResult(result.gpr(), m_compileIndex, op1.format()); - break; - } - - case ValueToDouble: { - SpeculateDoubleOperand op1(this, node.child1()); - FPRTemporary result(this, op1); - m_jit.moveDouble(op1.fpr(), result.fpr()); - doubleResult(result.fpr(), m_compileIndex); - break; - } - case ValueAdd: case ArithAdd: compileAdd(node); @@ -2091,12 +2067,12 @@ void SpeculativeJIT::compile(Node& node) break; case CompareEq: - if (isNullConstant(node.child1())) { + if (isNullConstant(node.child1().index())) { if (nonSpeculativeCompareNull(node, node.child2())) return; break; } - if (isNullConstant(node.child2())) { + if (isNullConstant(node.child2().index())) { if (nonSpeculativeCompareNull(node, node.child1())) return; break; @@ -2631,7 +2607,7 @@ void SpeculativeJIT::compile(Node& node) } case Branch: - if (isStrictInt32(node.child1()) || at(node.child1()).shouldSpeculateInteger()) { + if (isStrictInt32(node.child1().index()) || at(node.child1()).shouldSpeculateInteger()) { SpeculateIntegerOperand op(this, node.child1()); BlockIndex taken = node.takenBlockIndex(); @@ -2720,7 +2696,7 @@ void SpeculativeJIT::compile(Node& node) // FIXME: Add string speculation here. - bool wasPrimitive = isKnownNumeric(node.child1()) || isKnownBoolean(node.child1()); + bool wasPrimitive = isKnownNumeric(node.child1().index()) || isKnownBoolean(node.child1().index()); JSValueOperand op1(this, node.child1()); GPRTemporary resultTag(this, op1); diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp index 139dedded..0dc207f75 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp @@ -360,7 +360,7 @@ GPRReg SpeculativeJIT::fillJSValue(NodeIndex nodeIndex) void SpeculativeJIT::nonSpeculativeValueToNumber(Node& node) { - if (isKnownNumeric(node.child1())) { + if (isKnownNumeric(node.child1().index())) { JSValueOperand op1(this, node.child1()); GPRTemporary result(this, op1); m_jit.move(op1.gpr(), result.gpr()); @@ -371,8 +371,8 @@ void SpeculativeJIT::nonSpeculativeValueToNumber(Node& node) JSValueOperand op1(this, node.child1()); GPRTemporary result(this); - ASSERT(!isInt32Constant(node.child1())); - ASSERT(!isNumberConstant(node.child1())); + ASSERT(!isInt32Constant(node.child1().index())); + ASSERT(!isNumberConstant(node.child1().index())); GPRReg jsValueGpr = op1.gpr(); GPRReg gpr = result.gpr(); @@ -404,9 +404,9 @@ void SpeculativeJIT::nonSpeculativeValueToNumber(Node& node) void SpeculativeJIT::nonSpeculativeValueToInt32(Node& node) { - ASSERT(!isInt32Constant(node.child1())); + ASSERT(!isInt32Constant(node.child1().index())); - if (isKnownInteger(node.child1())) { + if (isKnownInteger(node.child1().index())) { IntegerOperand op1(this, node.child1()); GPRTemporary result(this, op1); m_jit.move(op1.gpr(), result.gpr()); @@ -512,13 +512,13 @@ JITCompiler::Call SpeculativeJIT::cachedGetById(CodeOrigin codeOrigin, GPRReg ba return functionCall; } -void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg valueGPR, NodeIndex valueIndex, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget) +void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg valueGPR, NodeUse valueUse, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget) { JITCompiler::DataLabelPtr structureToCompare; JITCompiler::Jump structureCheck = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1))); - writeBarrier(baseGPR, valueGPR, valueIndex, WriteBarrierForPropertyAccess, scratchGPR); + writeBarrier(baseGPR, valueGPR, valueUse, WriteBarrierForPropertyAccess, scratchGPR); m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), scratchGPR); JITCompiler::DataLabel32 storeWithPatch = m_jit.storePtrWithAddressOffsetPatch(valueGPR, JITCompiler::Address(scratchGPR, 0)); @@ -554,7 +554,7 @@ void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg m_jit.addPropertyAccess(PropertyAccessRecord(codeOrigin, structureToCompare, functionCall, structureCheck, JITCompiler::DataLabelCompact(storeWithPatch.label()), slowCase, doneLabel, safeCast<int8_t>(baseGPR), safeCast<int8_t>(valueGPR), safeCast<int8_t>(scratchGPR))); } -void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull(NodeIndex operand, bool invert) +void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull(NodeUse operand, bool invert) { JSValueOperand arg(this, operand); GPRReg argGPR = arg.gpr(); @@ -564,13 +564,13 @@ void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull(NodeIndex operand, boo JITCompiler::Jump notCell; - if (!isKnownCell(operand)) + if (!isKnownCell(operand.index())) notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, argGPR, GPRInfo::tagMaskRegister); m_jit.loadPtr(JITCompiler::Address(argGPR, JSCell::structureOffset()), resultGPR); m_jit.test8(invert ? JITCompiler::Zero : JITCompiler::NonZero, JITCompiler::Address(resultGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined), resultGPR); - if (!isKnownCell(operand)) { + if (!isKnownCell(operand.index())) { JITCompiler::Jump done = m_jit.jump(); notCell.link(&m_jit); @@ -586,7 +586,7 @@ void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull(NodeIndex operand, boo jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean); } -void SpeculativeJIT::nonSpeculativePeepholeBranchNull(NodeIndex operand, NodeIndex branchNodeIndex, bool invert) +void SpeculativeJIT::nonSpeculativePeepholeBranchNull(NodeUse operand, NodeIndex branchNodeIndex, bool invert) { Node& branchNode = at(branchNodeIndex); BlockIndex taken = branchNode.takenBlockIndex(); @@ -607,13 +607,13 @@ void SpeculativeJIT::nonSpeculativePeepholeBranchNull(NodeIndex operand, NodeInd JITCompiler::Jump notCell; - if (!isKnownCell(operand)) + if (!isKnownCell(operand.index())) notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, argGPR, GPRInfo::tagMaskRegister); m_jit.loadPtr(JITCompiler::Address(argGPR, JSCell::structureOffset()), resultGPR); addBranch(m_jit.branchTest8(invert ? JITCompiler::Zero : JITCompiler::NonZero, JITCompiler::Address(resultGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined)), taken); - if (!isKnownCell(operand)) { + if (!isKnownCell(operand.index())) { addBranch(m_jit.jump(), notTaken); notCell.link(&m_jit); @@ -627,7 +627,7 @@ void SpeculativeJIT::nonSpeculativePeepholeBranchNull(NodeIndex operand, NodeInd addBranch(m_jit.jump(), notTaken); } -bool SpeculativeJIT::nonSpeculativeCompareNull(Node& node, NodeIndex operand, bool invert) +bool SpeculativeJIT::nonSpeculativeCompareNull(Node& node, NodeUse operand, bool invert) { NodeIndex branchNodeIndex = detectPeepHoleBranch(); if (branchNodeIndex != NoNode) { @@ -672,7 +672,7 @@ void SpeculativeJIT::nonSpeculativePeepholeBranch(Node& node, NodeIndex branchNo JITCompiler::JumpList slowPath; - if (isKnownNotInteger(node.child1()) || isKnownNotInteger(node.child2())) { + if (isKnownNotInteger(node.child1().index()) || isKnownNotInteger(node.child2().index())) { GPRResult result(this); GPRReg resultGPR = result.gpr(); @@ -690,14 +690,14 @@ void SpeculativeJIT::nonSpeculativePeepholeBranch(Node& node, NodeIndex branchNo arg1.use(); arg2.use(); - if (!isKnownInteger(node.child1())) + if (!isKnownInteger(node.child1().index())) slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister)); - if (!isKnownInteger(node.child2())) + if (!isKnownInteger(node.child2().index())) slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister)); addBranch(m_jit.branch32(cond, arg1GPR, arg2GPR), taken); - if (!isKnownInteger(node.child1()) || !isKnownInteger(node.child2())) { + if (!isKnownInteger(node.child1().index()) || !isKnownInteger(node.child2().index())) { addBranch(m_jit.jump(), notTaken); slowPath.link(&m_jit); @@ -723,7 +723,7 @@ void SpeculativeJIT::nonSpeculativeNonPeepholeCompare(Node& node, MacroAssembler JITCompiler::JumpList slowPath; - if (isKnownNotInteger(node.child1()) || isKnownNotInteger(node.child2())) { + if (isKnownNotInteger(node.child1().index()) || isKnownNotInteger(node.child2().index())) { GPRResult result(this); GPRReg resultGPR = result.gpr(); @@ -742,14 +742,14 @@ void SpeculativeJIT::nonSpeculativeNonPeepholeCompare(Node& node, MacroAssembler arg1.use(); arg2.use(); - if (!isKnownInteger(node.child1())) + if (!isKnownInteger(node.child1().index())) slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister)); - if (!isKnownInteger(node.child2())) + if (!isKnownInteger(node.child2().index())) slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister)); m_jit.compare32(cond, arg1GPR, arg2GPR, resultGPR); - if (!isKnownInteger(node.child1()) || !isKnownInteger(node.child2())) { + if (!isKnownInteger(node.child1().index()) || !isKnownInteger(node.child2().index())) { JITCompiler::Jump haveResult = m_jit.jump(); slowPath.link(&m_jit); @@ -795,7 +795,7 @@ void SpeculativeJIT::nonSpeculativePeepholeStrictEq(Node& node, NodeIndex branch arg1.use(); arg2.use(); - if (isKnownCell(node.child1()) && isKnownCell(node.child2())) { + if (isKnownCell(node.child1().index()) && isKnownCell(node.child2().index())) { // see if we get lucky: if the arguments are cells and they reference the same // cell, then they must be strictly equal. addBranch(m_jit.branchPtr(JITCompiler::Equal, arg1GPR, arg2GPR), invert ? notTaken : taken); @@ -844,7 +844,7 @@ void SpeculativeJIT::nonSpeculativeNonPeepholeStrictEq(Node& node, bool invert) arg1.use(); arg2.use(); - if (isKnownCell(node.child1()) && isKnownCell(node.child2())) { + if (isKnownCell(node.child1().index()) && isKnownCell(node.child2().index())) { // see if we get lucky: if the arguments are cells and they reference the same // cell, then they must be strictly equal. JITCompiler::Jump notEqualCase = m_jit.branchPtr(JITCompiler::NotEqual, arg1GPR, arg2GPR); @@ -917,10 +917,10 @@ void SpeculativeJIT::emitCall(Node& node) CallLinkInfo::CallType callType = node.op == Call ? CallLinkInfo::Call : CallLinkInfo::Construct; - NodeIndex calleeNodeIndex = m_jit.graph().m_varArgChildren[node.firstChild()]; - JSValueOperand callee(this, calleeNodeIndex); + NodeUse calleeNodeUse = m_jit.graph().m_varArgChildren[node.firstChild()]; + JSValueOperand callee(this, calleeNodeUse); GPRReg calleeGPR = callee.gpr(); - use(calleeNodeIndex); + use(calleeNodeUse); // The call instruction's first child is either the function (normal call) or the // receiver (method call). subsequent children are the arguments. @@ -931,10 +931,10 @@ void SpeculativeJIT::emitCall(Node& node) m_jit.storePtr(calleeGPR, callFrameSlot(RegisterFile::Callee)); for (int i = 0; i < numPassedArgs; i++) { - NodeIndex argNodeIndex = m_jit.graph().m_varArgChildren[node.firstChild() + 1 + i]; - JSValueOperand arg(this, argNodeIndex); + NodeUse argNodeUse = m_jit.graph().m_varArgChildren[node.firstChild() + 1 + i]; + JSValueOperand arg(this, argNodeUse); GPRReg argGPR = arg.gpr(); - use(argNodeIndex); + use(argNodeUse); m_jit.storePtr(argGPR, argumentSlot(i + dummyThisArgument)); } @@ -1459,9 +1459,9 @@ void SpeculativeJIT::compileObjectEquality(Node& node, const ClassInfo* classInf GPRReg resultGPR = result.gpr(); if (!predictionCheck(m_state.forNode(node.child1()).m_type)) - speculationCheck(BadType, JSValueRegs(op1GPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo))); + speculationCheck(BadType, JSValueRegs(op1GPR), node.child1().index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo))); if (!predictionCheck(m_state.forNode(node.child2()).m_type)) - speculationCheck(BadType, JSValueRegs(op2GPR), node.child2(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo))); + speculationCheck(BadType, JSValueRegs(op2GPR), node.child2().index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo))); MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR); m_jit.move(Imm32(ValueTrue), resultGPR); @@ -1511,7 +1511,7 @@ void SpeculativeJIT::compileValueAdd(Node& node) flushRegisters(); GPRResult result(this); - if (isKnownNotNumber(node.child1()) || isKnownNotNumber(node.child2())) + if (isKnownNotNumber(node.child1().index()) || isKnownNotNumber(node.child2().index())) callOperation(operationValueAddNotNumber, result.gpr(), op1GPR, op2GPR); else callOperation(operationValueAdd, result.gpr(), op1GPR, op2GPR); @@ -1519,16 +1519,16 @@ void SpeculativeJIT::compileValueAdd(Node& node) jsValueResult(result.gpr(), m_compileIndex); } -void SpeculativeJIT::compileObjectOrOtherLogicalNot(NodeIndex nodeIndex, const ClassInfo* classInfo, bool needSpeculationCheck) +void SpeculativeJIT::compileObjectOrOtherLogicalNot(NodeUse nodeUse, const ClassInfo* classInfo, bool needSpeculationCheck) { - JSValueOperand value(this, nodeIndex); + JSValueOperand value(this, nodeUse); GPRTemporary result(this); GPRReg valueGPR = value.gpr(); GPRReg resultGPR = result.gpr(); MacroAssembler::Jump notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister); if (needSpeculationCheck) - speculationCheck(BadType, JSValueRegs(valueGPR), nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valueGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo))); + speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valueGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo))); m_jit.move(TrustedImm32(static_cast<int32_t>(ValueFalse)), resultGPR); MacroAssembler::Jump done = m_jit.jump(); @@ -1537,7 +1537,7 @@ void SpeculativeJIT::compileObjectOrOtherLogicalNot(NodeIndex nodeIndex, const C if (needSpeculationCheck) { m_jit.move(valueGPR, resultGPR); m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR); - speculationCheck(BadType, JSValueRegs(valueGPR), nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, resultGPR, MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull)))); + speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse, m_jit.branchPtr(MacroAssembler::NotEqual, resultGPR, MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull)))); } m_jit.move(TrustedImm32(static_cast<int32_t>(ValueTrue)), resultGPR); @@ -1548,7 +1548,7 @@ void SpeculativeJIT::compileObjectOrOtherLogicalNot(NodeIndex nodeIndex, const C void SpeculativeJIT::compileLogicalNot(Node& node) { - if (isKnownBoolean(node.child1())) { + if (isKnownBoolean(node.child1().index())) { SpeculateBooleanOperand value(this, node.child1()); GPRTemporary result(this, value); @@ -1623,16 +1623,16 @@ void SpeculativeJIT::compileLogicalNot(Node& node) jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly); } -void SpeculativeJIT::emitObjectOrOtherBranch(NodeIndex nodeIndex, BlockIndex taken, BlockIndex notTaken, const ClassInfo* classInfo, bool needSpeculationCheck) +void SpeculativeJIT::emitObjectOrOtherBranch(NodeUse nodeUse, BlockIndex taken, BlockIndex notTaken, const ClassInfo* classInfo, bool needSpeculationCheck) { - JSValueOperand value(this, nodeIndex); + JSValueOperand value(this, nodeUse); GPRTemporary scratch(this); GPRReg valueGPR = value.gpr(); GPRReg scratchGPR = scratch.gpr(); MacroAssembler::Jump notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister); if (needSpeculationCheck) - speculationCheck(BadType, JSValueRegs(valueGPR), nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valueGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo))); + speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse.index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valueGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo))); addBranch(m_jit.jump(), taken); notCell.link(&m_jit); @@ -1640,7 +1640,7 @@ void SpeculativeJIT::emitObjectOrOtherBranch(NodeIndex nodeIndex, BlockIndex tak if (needSpeculationCheck) { m_jit.move(valueGPR, scratchGPR); m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), scratchGPR); - speculationCheck(BadType, JSValueRegs(valueGPR), nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, scratchGPR, MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull)))); + speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse.index(), m_jit.branchPtr(MacroAssembler::NotEqual, scratchGPR, MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull)))); } if (notTaken != (m_block + 1)) addBranch(m_jit.jump(), notTaken); @@ -1656,7 +1656,7 @@ void SpeculativeJIT::emitBranch(Node& node) BlockIndex taken = node.takenBlockIndex(); BlockIndex notTaken = node.notTakenBlockIndex(); - if (isKnownBoolean(node.child1())) { + if (isKnownBoolean(node.child1().index())) { MacroAssembler::ResultCondition condition = MacroAssembler::NonZero; if (taken == (m_block + 1)) { @@ -1879,18 +1879,18 @@ void SpeculativeJIT::compile(Node& node) case BitAnd: case BitOr: case BitXor: - if (isInt32Constant(node.child1())) { + if (isInt32Constant(node.child1().index())) { SpeculateIntegerOperand op2(this, node.child2()); GPRTemporary result(this, op2); - bitOp(op, valueOfInt32Constant(node.child1()), op2.gpr(), result.gpr()); + bitOp(op, valueOfInt32Constant(node.child1().index()), op2.gpr(), result.gpr()); integerResult(result.gpr(), m_compileIndex); - } else if (isInt32Constant(node.child2())) { + } else if (isInt32Constant(node.child2().index())) { SpeculateIntegerOperand op1(this, node.child1()); GPRTemporary result(this, op1); - bitOp(op, valueOfInt32Constant(node.child2()), op1.gpr(), result.gpr()); + bitOp(op, valueOfInt32Constant(node.child2().index()), op1.gpr(), result.gpr()); integerResult(result.gpr(), m_compileIndex); } else { @@ -1909,11 +1909,11 @@ void SpeculativeJIT::compile(Node& node) case BitRShift: case BitLShift: case BitURShift: - if (isInt32Constant(node.child2())) { + if (isInt32Constant(node.child2().index())) { SpeculateIntegerOperand op1(this, node.child1()); GPRTemporary result(this, op1); - shiftOp(op, op1.gpr(), valueOfInt32Constant(node.child2()) & 0x1f, result.gpr()); + shiftOp(op, op1.gpr(), valueOfInt32Constant(node.child2().index()) & 0x1f, result.gpr()); integerResult(result.gpr(), m_compileIndex); } else { @@ -1940,30 +1940,6 @@ void SpeculativeJIT::compile(Node& node) break; } - case ValueToNumber: { - if (at(node.child1()).shouldNotSpeculateInteger()) { - SpeculateDoubleOperand op1(this, node.child1()); - FPRTemporary result(this, op1); - m_jit.moveDouble(op1.fpr(), result.fpr()); - doubleResult(result.fpr(), m_compileIndex); - break; - } - - SpeculateIntegerOperand op1(this, node.child1()); - GPRTemporary result(this, op1); - m_jit.move(op1.gpr(), result.gpr()); - integerResult(result.gpr(), m_compileIndex, op1.format()); - break; - } - - case ValueToDouble: { - SpeculateDoubleOperand op1(this, node.child1()); - FPRTemporary result(this, op1); - m_jit.moveDouble(op1.fpr(), result.fpr()); - doubleResult(result.fpr(), m_compileIndex); - break; - } - case ValueAdd: case ArithAdd: compileAdd(node); @@ -2147,12 +2123,12 @@ void SpeculativeJIT::compile(Node& node) break; case CompareEq: - if (isNullConstant(node.child1())) { + if (isNullConstant(node.child1().index())) { if (nonSpeculativeCompareNull(node, node.child2())) return; break; } - if (isNullConstant(node.child2())) { + if (isNullConstant(node.child2().index())) { if (nonSpeculativeCompareNull(node, node.child1())) return; break; @@ -2661,7 +2637,7 @@ void SpeculativeJIT::compile(Node& node) } case Branch: - if (isStrictInt32(node.child1()) || at(node.child1()).shouldSpeculateInteger()) { + if (isStrictInt32(node.child1().index()) || at(node.child1()).shouldSpeculateInteger()) { SpeculateIntegerOperand op(this, node.child1()); BlockIndex taken = node.takenBlockIndex(); @@ -2738,7 +2714,7 @@ void SpeculativeJIT::compile(Node& node) // FIXME: Add string speculation here. - bool wasPrimitive = isKnownNumeric(node.child1()) || isKnownBoolean(node.child1()); + bool wasPrimitive = isKnownNumeric(node.child1().index()) || isKnownBoolean(node.child1().index()); JSValueOperand op1(this, node.child1()); GPRTemporary result(this, op1); |