Changeset 132701 in webkit
- Timestamp:
- Oct 26, 2012, 3:18:59 PM (13 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r132636 r132701 1 2012-10-25 Filip Pizlo <fpizlo@apple.com> 2 3 Forward OSR calculation is wrong in the presence of multiple SetLocals, or a mix of SetLocals and Phantoms 4 https://bugs.webkit.org/show_bug.cgi?id=100461 5 6 Reviewed by Oliver Hunt and Gavin Barraclough. 7 8 This does a couple of things. First, it removes the part of the change in r131822 that made the forward 9 OSR exit calculator capable of handling multiple SetLocals. That change was wrong, because it would 10 blindly assume that all SetLocals had the same ValueRecovery, and would ignore the possibility that if 11 there is no value recovery then a ForwardCheckStructure on the first SetLocal would not know how to 12 recover the state associated with the second SetLocal. Then, it introduces the invariant that any bytecode 13 op that decomposes into multiple SetLocals must first emit dead SetLocals as hints and then emit a second 14 set of SetLocals to actually do the setting of the locals. This means that if a ForwardCheckStructure (or 15 any other hoisted forward speculation) is inserted, it will always be inserted on the second set of 16 SetLocals (since hoisting only touches the live ones), at which point OSR will already know about the 17 mov hints implied by the first set of (dead) SetLocals. This gives us the behavior we wanted, namely, that 18 a ForwardCheckStructure applied to a variant set by a resolve_with_base-like operation can correctly do a 19 forward exit while also ensuring that prior to exiting we set the appropriate locals. 20 21 * dfg/DFGByteCodeParser.cpp: 22 (JSC::DFG::ByteCodeParser::parseBlock): 23 * dfg/DFGOSRExit.cpp: 24 (JSC::DFG::OSRExit::OSRExit): 25 * dfg/DFGOSRExit.h: 26 (OSRExit): 27 * dfg/DFGOSRExitCompiler.cpp: 28 * dfg/DFGOSRExitCompiler32_64.cpp: 29 (JSC::DFG::OSRExitCompiler::compileExit): 30 * dfg/DFGOSRExitCompiler64.cpp: 31 (JSC::DFG::OSRExitCompiler::compileExit): 32 * dfg/DFGSpeculativeJIT.cpp: 33 (JSC::DFG::SpeculativeJIT::convertLastOSRExitToForward): 34 1 35 2012-10-26 Simon Hausmann <simon.hausmann@digia.com> 2 36 -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r132499 r132701 3109 3109 NodeIndex value = 0; 3110 3110 if (parseResolveOperations(prediction, identifier, operations, putToBaseOperation, &base, &value)) { 3111 // First create OSR hints only. 3112 set(baseDst, base); 3113 set(valueDst, value); 3114 3115 // If we try to hoist structure checks into here, then we're guaranteed that they will occur 3116 // *after* we have already set up the values for OSR. 3117 3118 // Then do the real SetLocals. 3111 3119 set(baseDst, base); 3112 3120 set(valueDst, value); … … 3129 3137 NodeIndex value = 0; 3130 3138 if (parseResolveOperations(prediction, identifier, operations, 0, &base, &value)) { 3139 // First create OSR hints only. 3140 set(baseDst, base); 3141 set(valueDst, value); 3142 3143 // If we try to hoist structure checks into here, then we're guaranteed that they will occur 3144 // *after* we have already set up the values for OSR. 3145 3146 // Then do the real SetLocals. 3131 3147 set(baseDst, base); 3132 3148 set(valueDst, value); -
trunk/Source/JavaScriptCore/dfg/DFGOSRExit.cpp
r131822 r132701 46 46 , m_count(0) 47 47 , m_streamIndex(streamIndex) 48 , m_lastSetOperand(jit->m_lastSetOperand) 48 49 { 49 50 ASSERT(m_codeOrigin.isSet()); 50 m_setOperands.append(jit->m_lastSetOperand);51 51 } 52 52 -
trunk/Source/JavaScriptCore/dfg/DFGOSRExit.h
r131822 r132701 111 111 112 112 unsigned m_streamIndex; 113 Vector<int, 1> m_setOperands;113 int m_lastSetOperand; 114 114 115 Vector<RefPtr<ValueRecoveryOverride>, 1> m_valueRecoveryOverrides;115 RefPtr<ValueRecoveryOverride> m_valueRecoveryOverride; 116 116 117 117 private: -
trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp
r131822 r132701 71 71 codeBlock->variableEventStream().reconstruct(codeBlock, exit.m_codeOrigin, codeBlock->minifiedDFG(), exit.m_streamIndex, operands); 72 72 73 // There may be overrides, for forward speculations. 74 for (size_t i = 0; i < exit.m_valueRecoveryOverrides.size(); i++) 75 operands.setOperand(exit.m_valueRecoveryOverrides[i]->operand, exit.m_valueRecoveryOverrides[i]->recovery); 76 73 // There may be an override, for forward speculations. 74 if (!!exit.m_valueRecoveryOverride) { 75 operands.setOperand( 76 exit.m_valueRecoveryOverride->operand, exit.m_valueRecoveryOverride->recovery); 77 } 77 78 78 79 SpeculationRecovery* recovery = 0; -
trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp
r131868 r132701 733 733 // 15) Load the result of the last bytecode operation into regT0. 734 734 735 for (size_t i = 0; i < exit.m_setOperands.size(); i++) {736 m_jit.load32(AssemblyHelpers::payloadFor((VirtualRegister)exit.m_ setOperands[i]), GPRInfo::cachedResultRegister);737 m_jit.load32(AssemblyHelpers::tagFor((VirtualRegister)exit.m_ setOperands[i]), GPRInfo::cachedResultRegister2);735 if (exit.m_lastSetOperand != std::numeric_limits<int>::max()) { 736 m_jit.load32(AssemblyHelpers::payloadFor((VirtualRegister)exit.m_lastSetOperand), GPRInfo::cachedResultRegister); 737 m_jit.load32(AssemblyHelpers::tagFor((VirtualRegister)exit.m_lastSetOperand), GPRInfo::cachedResultRegister2); 738 738 } 739 739 -
trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp
r131874 r132701 682 682 // 16) Load the result of the last bytecode operation into regT0. 683 683 684 for (size_t i = 0; i < exit.m_setOperands.size(); i++)685 m_jit.load 64(AssemblyHelpers::addressFor((VirtualRegister)exit.m_setOperands[i]), GPRInfo::cachedResultRegister);686 684 if (exit.m_lastSetOperand != std::numeric_limits<int>::max()) 685 m_jit.loadPtr(AssemblyHelpers::addressFor((VirtualRegister)exit.m_lastSetOperand), GPRInfo::cachedResultRegister); 686 687 687 // 17) Adjust the call frame pointer. 688 688 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r132162 r132701 154 154 void SpeculativeJIT::convertLastOSRExitToForward(const ValueRecovery& valueRecovery) 155 155 { 156 #if !ASSERT_DISABLED157 156 if (!valueRecovery) { 158 157 // Check that the preceding node was a SetLocal with the same code origin. 159 158 Node* setLocal = &at(m_jit.graph().m_blocks[m_block]->at(m_indexInBlock - 1)); 160 ASSERT(setLocal->op() == SetLocal); 161 ASSERT(setLocal->codeOrigin == at(m_compileIndex).codeOrigin); 162 } 163 #endif 159 ASSERT_UNUSED(setLocal, setLocal->op() == SetLocal); 160 ASSERT_UNUSED(setLocal, setLocal->codeOrigin == at(m_compileIndex).codeOrigin); 161 162 // Find the next node. 163 unsigned indexInBlock = m_indexInBlock + 1; 164 Node* node = 0; 165 for (;;) { 166 if (indexInBlock == m_jit.graph().m_blocks[m_block]->size()) { 167 // This is an inline return. Give up and do a backwards speculation. This is safe 168 // because an inline return has its own bytecode index and it's always safe to 169 // reexecute that bytecode. 170 ASSERT(node->op() == Jump); 171 return; 172 } 173 node = &at(m_jit.graph().m_blocks[m_block]->at(indexInBlock)); 174 if (node->codeOrigin != at(m_compileIndex).codeOrigin) 175 break; 176 indexInBlock++; 177 } 178 179 ASSERT(node->codeOrigin != at(m_compileIndex).codeOrigin); 180 OSRExit& exit = m_jit.codeBlock()->lastOSRExit(); 181 exit.m_codeOrigin = node->codeOrigin; 182 return; 183 } 164 184 165 185 unsigned setLocalIndexInBlock = m_indexInBlock + 1; 166 167 OSRExit& exit = m_jit.codeBlock()->lastOSRExit(); 168 186 169 187 Node* setLocal = &at(m_jit.graph().m_blocks[m_block]->at(setLocalIndexInBlock)); 170 188 bool hadInt32ToDouble = false; … … 176 194 if (setLocal->op() == Flush || setLocal->op() == Phantom) 177 195 setLocal = &at(m_jit.graph().m_blocks[m_block]->at(++setLocalIndexInBlock)); 178 179 if (!!valueRecovery) { 180 if (hadInt32ToDouble) 181 ASSERT(at(setLocal->child1()).child1() == m_compileIndex); 182 else 183 ASSERT(setLocal->child1() == m_compileIndex); 184 } 196 197 if (hadInt32ToDouble) 198 ASSERT(at(setLocal->child1()).child1() == m_compileIndex); 199 else 200 ASSERT(setLocal->child1() == m_compileIndex); 185 201 ASSERT(setLocal->op() == SetLocal); 186 202 ASSERT(setLocal->codeOrigin == at(m_compileIndex).codeOrigin); … … 191 207 return; 192 208 } 193 194 exit.m_setOperands[0] = setLocal->local();195 while (nextNode->codeOrigin == at(m_compileIndex).codeOrigin) {196 ++setLocalIndexInBlock;197 Node* nextSetLocal = nextNode;198 if (nextSetLocal->op() == Int32ToDouble)199 nextSetLocal = &at(m_jit.graph().m_blocks[m_block]->at(++setLocalIndexInBlock));200 201 if (nextSetLocal->op() == Flush || nextSetLocal->op() == Phantom)202 nextSetLocal = &at(m_jit.graph().m_blocks[m_block]->at(++setLocalIndexInBlock));203 204 nextNode = &at(m_jit.graph().m_blocks[m_block]->at(setLocalIndexInBlock + 1));205 ASSERT(nextNode->op() != Jump || nextNode->codeOrigin != at(m_compileIndex).codeOrigin);206 ASSERT(nextSetLocal->op() == SetLocal);207 exit.m_setOperands.append(nextSetLocal->local());208 }209 210 209 ASSERT(nextNode->codeOrigin != at(m_compileIndex).codeOrigin); 211 210 211 OSRExit& exit = m_jit.codeBlock()->lastOSRExit(); 212 212 exit.m_codeOrigin = nextNode->codeOrigin; 213 213 214 if (!valueRecovery) 215 return; 216 217 ASSERT(exit.m_setOperands.size() == 1); 218 for (size_t i = 0; i < exit.m_setOperands.size(); i++) 219 exit.m_valueRecoveryOverrides.append(adoptRef(new ValueRecoveryOverride(exit.m_setOperands[i], valueRecovery))); 220 214 exit.m_lastSetOperand = setLocal->local(); 215 exit.m_valueRecoveryOverride = adoptRef( 216 new ValueRecoveryOverride(setLocal->local(), valueRecovery)); 221 217 } 222 218
Note:
See TracChangeset
for help on using the changeset viewer.