diff options
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp')
-rw-r--r-- | Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp | 369 |
1 files changed, 268 insertions, 101 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp index b69d53600..a1ac899a2 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp @@ -1032,7 +1032,7 @@ void SpeculativeJIT::emitCall(Node& node) m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister); slowPath = m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, MacroAssembler::TrustedImmPtr(JSValue::encode(JSValue()))); - m_jit.loadPtr(MacroAssembler::Address(calleeGPR, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), resultGPR); + m_jit.loadPtr(MacroAssembler::Address(calleeGPR, OBJECT_OFFSETOF(JSFunction, m_scope)), resultGPR); m_jit.storePtr(resultGPR, MacroAssembler::Address(GPRInfo::callFrameRegister, static_cast<ptrdiff_t>(sizeof(Register)) * RegisterFile::ScopeChain)); CodeOrigin codeOrigin = at(m_compileIndex).codeOrigin; @@ -1538,7 +1538,7 @@ JITCompiler::Jump SpeculativeJIT::convertToDouble(GPRReg value, FPRReg result, G return notNumber; } -void SpeculativeJIT::compileObjectEquality(Node& node, const ClassInfo* classInfo, SpeculatedTypeChecker speculatedTypeChecker) +void SpeculativeJIT::compileObjectEquality(Node& node) { SpeculateCellOperand op1(this, node.child1()); SpeculateCellOperand op2(this, node.child2()); @@ -1547,11 +1547,47 @@ void SpeculativeJIT::compileObjectEquality(Node& node, const ClassInfo* classInf GPRReg op1GPR = op1.gpr(); GPRReg op2GPR = op2.gpr(); GPRReg resultGPR = result.gpr(); - - if (!speculatedTypeChecker(m_state.forNode(node.child1()).m_type)) - speculationCheck(BadType, JSValueRegs(op1GPR), node.child1().index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo))); - if (!speculatedTypeChecker(m_state.forNode(node.child2()).m_type)) - speculationCheck(BadType, JSValueRegs(op2GPR), node.child2().index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo))); + + if (m_jit.graph().globalObjectFor(node.codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { + m_jit.graph().globalObjectFor(node.codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); + speculationCheck(BadType, JSValueRegs(op1GPR), node.child1().index(), + m_jit.branchPtr( + MacroAssembler::Equal, + MacroAssembler::Address(op1GPR, JSCell::structureOffset()), + MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); + speculationCheck(BadType, JSValueRegs(op2GPR), node.child2().index(), + m_jit.branchPtr( + MacroAssembler::Equal, + MacroAssembler::Address(op2GPR, JSCell::structureOffset()), + MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); + } else { + GPRTemporary structure(this); + GPRReg structureGPR = structure.gpr(); + + m_jit.loadPtr(MacroAssembler::Address(op1GPR, JSCell::structureOffset()), structureGPR); + speculationCheck(BadType, JSValueRegs(op1GPR), node.child1().index(), + m_jit.branchPtr( + MacroAssembler::Equal, + structureGPR, + MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); + speculationCheck(BadType, JSValueRegs(op1GPR), node.child1().index(), + m_jit.branchTest8( + MacroAssembler::NonZero, + MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), + MacroAssembler::TrustedImm32(MasqueradesAsUndefined))); + + m_jit.loadPtr(MacroAssembler::Address(op2GPR, JSCell::structureOffset()), structureGPR); + speculationCheck(BadType, JSValueRegs(op2GPR), node.child2().index(), + m_jit.branchPtr( + MacroAssembler::Equal, + structureGPR, + MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); + speculationCheck(BadType, JSValueRegs(op2GPR), node.child2().index(), + m_jit.branchTest8( + MacroAssembler::NonZero, + MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), + MacroAssembler::TrustedImm32(MasqueradesAsUndefined))); + } MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR); m_jit.move(TrustedImm32(ValueTrue), resultGPR); @@ -1563,10 +1599,9 @@ void SpeculativeJIT::compileObjectEquality(Node& node, const ClassInfo* classInf jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean); } -void SpeculativeJIT::compileObjectToObjectOrOtherEquality( - Edge leftChild, Edge rightChild, - const ClassInfo* classInfo, SpeculatedTypeChecker speculatedTypeChecker) +void SpeculativeJIT::compileObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild) { + Node& leftNode = m_jit.graph()[leftChild.index()]; SpeculateCellOperand op1(this, leftChild); JSValueOperand op2(this, rightChild); GPRTemporary result(this); @@ -1574,14 +1609,29 @@ void SpeculativeJIT::compileObjectToObjectOrOtherEquality( GPRReg op1GPR = op1.gpr(); GPRReg op2GPR = op2.gpr(); GPRReg resultGPR = result.gpr(); - - if (!speculatedTypeChecker(m_state.forNode(leftChild).m_type)) { - speculationCheck( - BadType, JSValueRegs(op1GPR), leftChild.index(), + + if (m_jit.graph().globalObjectFor(leftNode.codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { + m_jit.graph().globalObjectFor(leftNode.codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); + speculationCheck(BadType, JSValueRegs(op1GPR), leftChild.index(), + m_jit.branchPtr( + MacroAssembler::Equal, + MacroAssembler::Address(op1GPR, JSCell::structureOffset()), + MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); + } else { + GPRTemporary structure(this); + GPRReg structureGPR = structure.gpr(); + + m_jit.loadPtr(MacroAssembler::Address(op1GPR, JSCell::structureOffset()), structureGPR); + speculationCheck(BadType, JSValueRegs(op1GPR), leftChild.index(), m_jit.branchPtr( - MacroAssembler::NotEqual, - MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), - MacroAssembler::TrustedImmPtr(classInfo))); + MacroAssembler::Equal, + structureGPR, + MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); + speculationCheck(BadType, JSValueRegs(op1GPR), leftChild.index(), + m_jit.branchTest8( + MacroAssembler::NonZero, + MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), + MacroAssembler::TrustedImm32(MasqueradesAsUndefined))); } // It seems that most of the time when programs do a == b where b may be either null/undefined @@ -1589,17 +1639,29 @@ void SpeculativeJIT::compileObjectToObjectOrOtherEquality( MacroAssembler::Jump rightNotCell = m_jit.branchTestPtr(MacroAssembler::NonZero, op2GPR, GPRInfo::tagMaskRegister); - // We know that within this branch, rightChild must be a cell. If the CFA can tell us that the - // proof, when filtered on cell, demonstrates that we have an object of the desired type - // (speculationCheck() will test for FinalObject or Array, currently), then we can skip the - // speculation. - if (!speculatedTypeChecker(m_state.forNode(rightChild).m_type & SpecCell)) { - speculationCheck( - BadType, JSValueRegs(op2GPR), rightChild.index(), + // We know that within this branch, rightChild must be a cell. + if (m_jit.graph().globalObjectFor(leftNode.codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { + m_jit.graph().globalObjectFor(leftNode.codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); + speculationCheck(BadType, JSValueRegs(op2GPR), rightChild.index(), + m_jit.branchPtr( + MacroAssembler::Equal, + MacroAssembler::Address(op2GPR, JSCell::structureOffset()), + MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); + } else { + GPRTemporary structure(this); + GPRReg structureGPR = structure.gpr(); + + m_jit.loadPtr(MacroAssembler::Address(op2GPR, JSCell::structureOffset()), structureGPR); + speculationCheck(BadType, JSValueRegs(op2GPR), rightChild.index(), m_jit.branchPtr( - MacroAssembler::NotEqual, - MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()), - MacroAssembler::TrustedImmPtr(classInfo))); + MacroAssembler::Equal, + structureGPR, + MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); + speculationCheck(BadType, JSValueRegs(op2GPR), rightChild.index(), + m_jit.branchTest8( + MacroAssembler::NonZero, + MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), + MacroAssembler::TrustedImm32(MasqueradesAsUndefined))); } // At this point we know that we can perform a straight-forward equality comparison on pointer @@ -1633,9 +1695,7 @@ void SpeculativeJIT::compileObjectToObjectOrOtherEquality( jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean); } -void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality( - Edge leftChild, Edge rightChild, NodeIndex branchNodeIndex, - const ClassInfo* classInfo, SpeculatedTypeChecker speculatedTypeChecker) +void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild, NodeIndex branchNodeIndex) { Node& branchNode = at(branchNodeIndex); BlockIndex taken = branchNode.takenBlockIndex(); @@ -1649,13 +1709,28 @@ void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality( GPRReg op2GPR = op2.gpr(); GPRReg resultGPR = result.gpr(); - if (!speculatedTypeChecker(m_state.forNode(leftChild).m_type)) { - speculationCheck( - BadType, JSValueRegs(op1GPR), leftChild.index(), + if (m_jit.graph().globalObjectFor(branchNode.codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { + m_jit.graph().globalObjectFor(branchNode.codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); + speculationCheck(BadType, JSValueRegs(op1GPR), leftChild.index(), m_jit.branchPtr( - MacroAssembler::NotEqual, - MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), - MacroAssembler::TrustedImmPtr(classInfo))); + MacroAssembler::Equal, + MacroAssembler::Address(op1GPR, JSCell::structureOffset()), + MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); + } else { + GPRTemporary structure(this); + GPRReg structureGPR = structure.gpr(); + + m_jit.loadPtr(MacroAssembler::Address(op1GPR, JSCell::structureOffset()), structureGPR); + speculationCheck(BadType, JSValueRegs(op1GPR), leftChild.index(), + m_jit.branchPtr( + MacroAssembler::Equal, + structureGPR, + MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); + speculationCheck(BadType, JSValueRegs(op1GPR), leftChild.index(), + m_jit.branchTest8( + MacroAssembler::NonZero, + MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), + MacroAssembler::TrustedImm32(MasqueradesAsUndefined))); } // It seems that most of the time when programs do a == b where b may be either null/undefined @@ -1663,17 +1738,29 @@ void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality( MacroAssembler::Jump rightNotCell = m_jit.branchTestPtr(MacroAssembler::NonZero, op2GPR, GPRInfo::tagMaskRegister); - // We know that within this branch, rightChild must be a cell. If the CFA can tell us that the - // proof, when filtered on cell, demonstrates that we have an object of the desired type - // (speculationCheck() will test for FinalObject or Array, currently), then we can skip the - // speculation. - if (!speculatedTypeChecker(m_state.forNode(rightChild).m_type & SpecCell)) { - speculationCheck( - BadType, JSValueRegs(op2GPR), rightChild.index(), + // We know that within this branch, rightChild must be a cell. + if (m_jit.graph().globalObjectFor(branchNode.codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { + m_jit.graph().globalObjectFor(branchNode.codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); + speculationCheck(BadType, JSValueRegs(op2GPR), rightChild.index(), m_jit.branchPtr( - MacroAssembler::NotEqual, - MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()), - MacroAssembler::TrustedImmPtr(classInfo))); + MacroAssembler::Equal, + MacroAssembler::Address(op2GPR, JSCell::structureOffset()), + MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); + } else { + GPRTemporary structure(this); + GPRReg structureGPR = structure.gpr(); + + m_jit.loadPtr(MacroAssembler::Address(op2GPR, JSCell::structureOffset()), structureGPR); + speculationCheck(BadType, JSValueRegs(op2GPR), rightChild.index(), + m_jit.branchPtr( + MacroAssembler::Equal, + structureGPR, + MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); + speculationCheck(BadType, JSValueRegs(op2GPR), rightChild.index(), + m_jit.branchTest8( + MacroAssembler::NonZero, + MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), + MacroAssembler::TrustedImm32(MasqueradesAsUndefined))); } // At this point we know that we can perform a straight-forward equality comparison on pointer @@ -1748,7 +1835,7 @@ void SpeculativeJIT::compileValueAdd(Node& node) jsValueResult(result.gpr(), m_compileIndex); } -void SpeculativeJIT::compileObjectOrOtherLogicalNot(Edge nodeUse, const ClassInfo* classInfo, bool needSpeculationCheck) +void SpeculativeJIT::compileNonStringCellOrOtherLogicalNot(Edge nodeUse, bool needSpeculationCheck) { JSValueOperand value(this, nodeUse); GPRTemporary result(this); @@ -1756,19 +1843,59 @@ void SpeculativeJIT::compileObjectOrOtherLogicalNot(Edge nodeUse, const ClassInf GPRReg resultGPR = result.gpr(); MacroAssembler::Jump notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister); - if (needSpeculationCheck) - 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); + if (m_jit.graph().globalObjectFor(m_jit.graph()[nodeUse.index()].codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { + m_jit.graph().globalObjectFor(m_jit.graph()[nodeUse.index()].codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); + + if (needSpeculationCheck) { + speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse, + m_jit.branchPtr( + MacroAssembler::Equal, + MacroAssembler::Address(valueGPR, JSCell::structureOffset()), + MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); + } + } else { + GPRTemporary structure(this); + GPRReg structureGPR = structure.gpr(); + + m_jit.loadPtr(MacroAssembler::Address(valueGPR, JSCell::structureOffset()), structureGPR); + + if (needSpeculationCheck) { + speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse, + m_jit.branchPtr( + MacroAssembler::Equal, + structureGPR, + MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); + } + + MacroAssembler::Jump isNotMasqueradesAsUndefined = + m_jit.branchTest8( + MacroAssembler::Zero, + MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), + MacroAssembler::TrustedImm32(MasqueradesAsUndefined)); + + speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse, + m_jit.branchPtr( + MacroAssembler::Equal, + MacroAssembler::Address(structureGPR, Structure::globalObjectOffset()), + MacroAssembler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_jit.graph()[nodeUse.index()].codeOrigin)))); + + isNotMasqueradesAsUndefined.link(&m_jit); + } + m_jit.move(TrustedImm32(ValueFalse), resultGPR); MacroAssembler::Jump done = m_jit.jump(); notCell.link(&m_jit); - + if (needSpeculationCheck) { m_jit.move(valueGPR, resultGPR); m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR); - speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse, 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); + m_jit.move(TrustedImm32(ValueTrue), resultGPR); done.link(&m_jit); @@ -1777,12 +1904,9 @@ void SpeculativeJIT::compileObjectOrOtherLogicalNot(Edge nodeUse, const ClassInf void SpeculativeJIT::compileLogicalNot(Node& node) { - if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) { - compileObjectOrOtherLogicalNot(node.child1(), &JSFinalObject::s_info, !isFinalObjectOrOtherSpeculation(m_state.forNode(node.child1()).m_type)); - return; - } - if (at(node.child1()).shouldSpeculateArrayOrOther()) { - compileObjectOrOtherLogicalNot(node.child1(), &JSArray::s_info, !isArrayOrOtherSpeculation(m_state.forNode(node.child1()).m_type)); + if (at(node.child1()).shouldSpeculateNonStringCellOrOther()) { + compileNonStringCellOrOtherLogicalNot(node.child1(), + !isNonStringCellOrOtherSpeculation(m_state.forNode(node.child1()).m_type)); return; } if (at(node.child1()).shouldSpeculateInteger()) { @@ -1850,7 +1974,7 @@ void SpeculativeJIT::compileLogicalNot(Node& node) jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly); } -void SpeculativeJIT::emitObjectOrOtherBranch(Edge nodeUse, BlockIndex taken, BlockIndex notTaken, const ClassInfo* classInfo, bool needSpeculationCheck) +void SpeculativeJIT::emitNonStringCellOrOtherBranch(Edge nodeUse, BlockIndex taken, BlockIndex notTaken, bool needSpeculationCheck) { JSValueOperand value(this, nodeUse); GPRTemporary scratch(this); @@ -1858,8 +1982,37 @@ void SpeculativeJIT::emitObjectOrOtherBranch(Edge nodeUse, BlockIndex taken, Blo GPRReg scratchGPR = scratch.gpr(); MacroAssembler::Jump notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister); - if (needSpeculationCheck) - speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse.index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valueGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo))); + if (m_jit.graph().globalObjectFor(m_jit.graph()[nodeUse.index()].codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { + m_jit.graph().globalObjectFor(m_jit.graph()[nodeUse.index()].codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); + + if (needSpeculationCheck) { + speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse.index(), + m_jit.branchPtr( + MacroAssembler::Equal, + MacroAssembler::Address(valueGPR, JSCell::structureOffset()), + MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); + } + } else { + m_jit.loadPtr(MacroAssembler::Address(valueGPR, JSCell::structureOffset()), scratchGPR); + + if (needSpeculationCheck) { + speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse.index(), + m_jit.branchPtr( + MacroAssembler::Equal, + scratchGPR, + MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); + } + + JITCompiler::Jump isNotMasqueradesAsUndefined = m_jit.branchTest8(JITCompiler::Zero, MacroAssembler::Address(scratchGPR, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)); + + speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse.index(), + m_jit.branchPtr( + MacroAssembler::Equal, + MacroAssembler::Address(scratchGPR, Structure::globalObjectOffset()), + MacroAssembler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_jit.graph()[nodeUse.index()].codeOrigin)))); + + isNotMasqueradesAsUndefined.link(&m_jit); + } jump(taken, ForceJump); notCell.link(&m_jit); @@ -1879,10 +2032,9 @@ void SpeculativeJIT::emitBranch(Node& node) BlockIndex taken = node.takenBlockIndex(); BlockIndex notTaken = node.notTakenBlockIndex(); - if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) { - emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSFinalObject::s_info, !isFinalObjectOrOtherSpeculation(m_state.forNode(node.child1()).m_type)); - } else if (at(node.child1()).shouldSpeculateArrayOrOther()) { - emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSArray::s_info, !isArrayOrOtherSpeculation(m_state.forNode(node.child1()).m_type)); + if (at(node.child1()).shouldSpeculateNonStringCellOrOther()) { + emitNonStringCellOrOtherBranch(node.child1(), taken, notTaken, + !isNonStringCellOrOtherSpeculation(m_state.forNode(node.child1()).m_type)); } else if (at(node.child1()).shouldSpeculateNumber()) { if (at(node.child1()).shouldSpeculateInteger()) { bool invert = false; @@ -2406,6 +2558,11 @@ void SpeculativeJIT::compile(Node& node) compileGetByValOnString(node); break; } + + case CheckArray: { + checkArray(node); + break; + } case GetByVal: { switch (node.arrayMode()) { @@ -2443,11 +2600,24 @@ void SpeculativeJIT::compile(Node& node) // We will have already speculated that the base is some kind of array, // at this point. - speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset()))); + MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())); + if (node.arrayMode() == Array::JSArray) + speculationCheck(OutOfBounds, JSValueRegs(), NoNode, outOfBounds); GPRTemporary result(this); m_jit.loadPtr(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), result.gpr()); - speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::Zero, result.gpr())); + MacroAssembler::Jump hole = m_jit.branchTestPtr(MacroAssembler::Zero, result.gpr()); + if (node.arrayMode() == Array::JSArray) + speculationCheck(OutOfBounds, JSValueRegs(), NoNode, hole); + else { + MacroAssembler::JumpList slowCases; + slowCases.append(outOfBounds); + slowCases.append(hole); + addSlowPathGenerator( + slowPathCall( + slowCases, this, operationGetByValArrayInt, + result.gpr(), baseReg, propertyReg)); + } jsValueResult(result.gpr(), m_compileIndex); break; @@ -2497,6 +2667,7 @@ void SpeculativeJIT::compile(Node& node) Edge child1 = m_jit.graph().varArgChild(node, 0); Edge child2 = m_jit.graph().varArgChild(node, 1); Edge child3 = m_jit.graph().varArgChild(node, 2); + Edge child4 = m_jit.graph().varArgChild(node, 3); Array::Mode arrayMode = modeForPut(node.arrayMode()); bool alreadyHandled = false; @@ -2538,27 +2709,26 @@ void SpeculativeJIT::compile(Node& node) GPRReg baseReg = base.gpr(); GPRReg propertyReg = property.gpr(); - speculateArray(arrayMode, child1, baseReg); - switch (arrayMode) { case Array::JSArray: case Array::JSArrayOutOfBounds: { JSValueOperand value(this, child3); - GPRTemporary scratch(this); // Map base, property & value into registers, allocate a scratch register. GPRReg valueReg = value.gpr(); - GPRReg scratchReg = scratch.gpr(); if (!m_compileOkay) return; - writeBarrier(baseReg, value.gpr(), child3, WriteBarrierForPropertyAccess, scratchReg); + if (Heap::isWriteBarrierEnabled()) { + GPRTemporary scratch(this); + writeBarrier(baseReg, value.gpr(), child3, WriteBarrierForPropertyAccess, scratch.gpr()); + } + + StorageOperand storage(this, child4); + GPRReg storageReg = storage.gpr(); if (node.op() == PutByValAlias) { - GPRReg storageReg = scratchReg; - m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg); - // Store the value to the array. GPRReg propertyReg = property.gpr(); GPRReg valueReg = value.gpr(); @@ -2575,11 +2745,8 @@ void SpeculativeJIT::compile(Node& node) base.use(); property.use(); value.use(); + storage.use(); - // Get the array storage. - GPRReg storageReg = scratchReg; - m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg); - // Check if we're writing to a hole; if so increment m_numValuesInVector. MacroAssembler::Jump notHoleValue = m_jit.branchTestPtr(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))); m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector))); @@ -2747,21 +2914,24 @@ void SpeculativeJIT::compile(Node& node) } case ArrayPush: { + ASSERT(modeIsJSArray(node.arrayMode())); + SpeculateCellOperand base(this, node.child1()); JSValueOperand value(this, node.child2()); - GPRTemporary storage(this); GPRTemporary storageLength(this); GPRReg baseGPR = base.gpr(); GPRReg valueGPR = value.gpr(); - GPRReg storageGPR = storage.gpr(); GPRReg storageLengthGPR = storageLength.gpr(); - writeBarrier(baseGPR, valueGPR, node.child2(), WriteBarrierForPropertyAccess, storageGPR, storageLengthGPR); + if (Heap::isWriteBarrierEnabled()) { + GPRTemporary scratch(this); + writeBarrier(baseGPR, valueGPR, node.child2(), WriteBarrierForPropertyAccess, scratch.gpr(), storageLengthGPR); + } - speculateArray(Array::JSArray, node.child1(), baseGPR); + StorageOperand storage(this, node.child3()); + GPRReg storageGPR = storage.gpr(); - m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR); m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR); // Refuse to handle bizarre lengths. @@ -2786,19 +2956,18 @@ void SpeculativeJIT::compile(Node& node) } case ArrayPop: { + ASSERT(modeIsJSArray(node.arrayMode())); + SpeculateCellOperand base(this, node.child1()); + StorageOperand storage(this, node.child2()); GPRTemporary value(this); - GPRTemporary storage(this); GPRTemporary storageLength(this); GPRReg baseGPR = base.gpr(); - GPRReg valueGPR = value.gpr(); GPRReg storageGPR = storage.gpr(); + GPRReg valueGPR = value.gpr(); GPRReg storageLengthGPR = storageLength.gpr(); - speculateArray(Array::JSArray, node.child1(), baseGPR); - - m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR); m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR); JITCompiler::JumpList setUndefinedCases; @@ -3175,34 +3344,32 @@ void SpeculativeJIT::compile(Node& node) JITCompiler::Jump activationNotCreated; if (checkTopLevel) activationNotCreated = m_jit.branchTestPtr(JITCompiler::Zero, JITCompiler::addressFor(static_cast<VirtualRegister>(m_jit.codeBlock()->activationRegister()))); - m_jit.loadPtr(JITCompiler::Address(resultGPR, OBJECT_OFFSETOF(ScopeChainNode, next)), resultGPR); + m_jit.loadPtr(JITCompiler::Address(resultGPR, JSScope::offsetOfNext()), resultGPR); activationNotCreated.link(&m_jit); } while (skip--) - m_jit.loadPtr(JITCompiler::Address(resultGPR, OBJECT_OFFSETOF(ScopeChainNode, next)), resultGPR); + m_jit.loadPtr(JITCompiler::Address(resultGPR, JSScope::offsetOfNext()), resultGPR); - m_jit.loadPtr(JITCompiler::Address(resultGPR, OBJECT_OFFSETOF(ScopeChainNode, object)), resultGPR); - cellResult(resultGPR, m_compileIndex); break; } case GetScopedVar: { - SpeculateCellOperand scopeChain(this, node.child1()); + SpeculateCellOperand scope(this, node.child1()); GPRTemporary result(this); GPRReg resultGPR = result.gpr(); - m_jit.loadPtr(JITCompiler::Address(scopeChain.gpr(), JSVariableObject::offsetOfRegisters()), resultGPR); + m_jit.loadPtr(JITCompiler::Address(scope.gpr(), JSVariableObject::offsetOfRegisters()), resultGPR); m_jit.loadPtr(JITCompiler::Address(resultGPR, node.varNumber() * sizeof(Register)), resultGPR); jsValueResult(resultGPR, m_compileIndex); break; } case PutScopedVar: { - SpeculateCellOperand scopeChain(this, node.child1()); + SpeculateCellOperand scope(this, node.child1()); GPRTemporary scratchRegister(this); GPRReg scratchGPR = scratchRegister.gpr(); - m_jit.loadPtr(JITCompiler::Address(scopeChain.gpr(), JSVariableObject::offsetOfRegisters()), scratchGPR); + m_jit.loadPtr(JITCompiler::Address(scope.gpr(), JSVariableObject::offsetOfRegisters()), scratchGPR); JSValueOperand value(this, node.child2()); m_jit.storePtr(value.gpr(), JITCompiler::Address(scratchGPR, node.varNumber() * sizeof(Register))); - writeBarrier(scopeChain.gpr(), value.gpr(), node.child2(), WriteBarrierForVariableAccess, scratchGPR); + writeBarrier(scope.gpr(), value.gpr(), node.child2(), WriteBarrierForVariableAccess, scratchGPR); noResult(m_compileIndex); break; } @@ -3518,7 +3685,7 @@ void SpeculativeJIT::compile(Node& node) JSValueOperand value(this, node.child1()); WatchpointSet* watchpointSet = - m_jit.globalObjectFor(node.codeOrigin)->symbolTable().get( + m_jit.globalObjectFor(node.codeOrigin)->symbolTable()->get( identifier(node.identifierNumberForCheck())->impl()).watchpointSet(); addSlowPathGenerator( slowPathCall( @@ -3541,7 +3708,7 @@ void SpeculativeJIT::compile(Node& node) } case GlobalVarWatchpoint: { - m_jit.globalObjectFor(node.codeOrigin)->symbolTable().get( + m_jit.globalObjectFor(node.codeOrigin)->symbolTable()->get( identifier(node.identifierNumberForCheck())->impl()).addWatchpoint( speculationWatchpoint()); |