Changeset 100315 in webkit
- Timestamp:
- Nov 15, 2011, 1:54:38 PM (15 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 9 edited
-
ChangeLog (modified) (1 diff)
-
dfg/DFGAbstractState.cpp (modified) (2 diffs)
-
dfg/DFGByteCodeParser.cpp (modified) (4 diffs)
-
dfg/DFGGraph.cpp (modified) (2 diffs)
-
dfg/DFGGraph.h (modified) (5 diffs)
-
dfg/DFGNode.h (modified) (9 diffs)
-
dfg/DFGPropagator.cpp (modified) (4 diffs)
-
dfg/DFGSpeculativeJIT32_64.cpp (modified) (2 diffs)
-
dfg/DFGSpeculativeJIT64.cpp (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r100314 r100315 1 2011-11-15 Filip Pizlo <fpizlo@apple.com> 2 3 DFG should distinguish between constants in the constant pool and weak 4 constants added as artifacts of code generation 5 https://bugs.webkit.org/show_bug.cgi?id=72367 6 7 Reviewed by Geoff Garen. 8 9 Added the notion of a WeakJSConstant, which is like a JSConstant except that 10 it can only refer to JSCell*. Currently all WeakJSConstants are also backed 11 by constants in the constant pool, since weak references originated from 12 machine code are not yet properly handled. 13 14 Replaced CheckMethod, and MethodCheckData, with a combination of WeakJSConstant 15 and CheckStructure. This results in improved CSE, leading to a 1% win on V8. 16 17 * dfg/DFGAbstractState.cpp: 18 (JSC::DFG::AbstractState::execute): 19 * dfg/DFGByteCodeParser.cpp: 20 (JSC::DFG::ByteCodeParser::cellConstant): 21 (JSC::DFG::ByteCodeParser::prepareToParseBlock): 22 (JSC::DFG::ByteCodeParser::parseBlock): 23 * dfg/DFGGraph.cpp: 24 (JSC::DFG::Graph::dump): 25 * dfg/DFGGraph.h: 26 (JSC::DFG::Graph::getJSConstantPrediction): 27 (JSC::DFG::Graph::valueOfJSConstant): 28 (JSC::DFG::Graph::valueOfInt32Constant): 29 (JSC::DFG::Graph::valueOfNumberConstant): 30 (JSC::DFG::Graph::valueOfBooleanConstant): 31 * dfg/DFGNode.h: 32 (JSC::DFG::Node::isWeakConstant): 33 (JSC::DFG::Node::hasConstant): 34 (JSC::DFG::Node::weakConstant): 35 (JSC::DFG::Node::valueOfJSConstant): 36 (JSC::DFG::Node::isInt32Constant): 37 (JSC::DFG::Node::isDoubleConstant): 38 (JSC::DFG::Node::isNumberConstant): 39 (JSC::DFG::Node::isBooleanConstant): 40 (JSC::DFG::Node::hasIdentifier): 41 * dfg/DFGPropagator.cpp: 42 (JSC::DFG::Propagator::propagateNodePredictions): 43 (JSC::DFG::Propagator::performNodeCSE): 44 * dfg/DFGSpeculativeJIT32_64.cpp: 45 (JSC::DFG::SpeculativeJIT::compile): 46 * dfg/DFGSpeculativeJIT64.cpp: 47 (JSC::DFG::SpeculativeJIT::compile): 48 1 49 2011-11-15 Michael Saboff <msaboff@apple.com> 2 50 -
trunk/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
r99910 r100315 169 169 170 170 switch (node.op) { 171 case JSConstant: { 171 case JSConstant: 172 case WeakJSConstant: { 172 173 JSValue value = m_graph.valueOfJSConstant(m_codeBlock, nodeIndex); 173 174 if (value.isCell()) … … 602 603 break; 603 604 604 case CheckMethod:605 // FIXME: We should be able to propagate the structure sets of constants (i.e. prototypes).606 forNode(node.child1()).filter(m_graph.m_methodCheckData[node.methodCheckDataIndex()].structure);607 forNode(nodeIndex).set(PredictFunction);608 m_haveStructures = true;609 break;610 611 605 case CheckFunction: 612 606 forNode(node.child1()).filter(PredictFunction); -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r100221 r100315 532 532 NodeIndex cellConstant(JSCell* cell) 533 533 { 534 return getJSConstant(getCellConstantIndex(cell)); 534 pair<HashMap<JSCell*, NodeIndex>::iterator, bool> iter = m_cellConstantNodes.add(cell, NoNode); 535 if (iter.second) 536 iter.first->second = addToGraph(WeakJSConstant, OpInfo(cell)); 537 538 return iter.first->second; 535 539 } 536 540 … … 735 739 unsigned m_constant1; 736 740 HashMap<JSCell*, unsigned> m_cellConstants; 741 HashMap<JSCell*, NodeIndex> m_cellConstantNodes; 737 742 738 743 // A constant in the constant pool may be represented by more than one … … 1256 1261 for (unsigned i = 0; i < m_constants.size(); ++i) 1257 1262 m_constants[i] = ConstantRecord(); 1263 m_cellConstantNodes.clear(); 1258 1264 } 1259 1265 … … 1669 1675 // but the slow path (i.e. the normal get_by_id) never fired. 1670 1676 1671 pinCell(methodCall.cachedStructure.get()); 1672 pinCell(methodCall.cachedPrototypeStructure.get()); 1673 pinCell(methodCall.cachedFunction.get()); 1674 pinCell(methodCall.cachedPrototype.get()); 1675 1676 NodeIndex checkMethod = addToGraph(CheckMethod, OpInfo(identifier), OpInfo(m_graph.m_methodCheckData.size()), base); 1677 set(getInstruction[1].u.operand, checkMethod); 1677 pinCell(methodCall.cachedStructure.get()); // first check 1678 pinCell(methodCall.cachedPrototype.get()); // second check 1679 pinCell(methodCall.cachedPrototypeStructure.get()); // second check 1680 pinCell(methodCall.cachedFunction.get()); // result 1678 1681 1679 MethodCheckData methodCheckData; 1680 methodCheckData.structure = methodCall.cachedStructure.get(); 1681 methodCheckData.prototypeStructure = methodCall.cachedPrototypeStructure.get(); 1682 methodCheckData.function = methodCall.cachedFunction.get(); 1683 methodCheckData.prototype = methodCall.cachedPrototype.get(); 1684 m_graph.m_methodCheckData.append(methodCheckData); 1682 addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(methodCall.cachedStructure.get())), base); 1683 if (methodCall.cachedPrototype.get() != m_inlineStackTop->m_profiledBlock->globalObject()->methodCallDummy()) 1684 addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(methodCall.cachedPrototypeStructure.get())), cellConstant(methodCall.cachedPrototype.get())); 1685 1686 set(getInstruction[1].u.operand, cellConstant(methodCall.cachedFunction.get())); 1685 1687 } else { 1686 1688 NodeIndex getMethod = addToGraph(GetMethod, OpInfo(identifier), OpInfo(prediction), base); -
trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp
r99700 r100315 243 243 hasPrinted = true; 244 244 } 245 if (op == WeakJSConstant) { 246 printf("%s%p", hasPrinted ? ", " : "", node.weakConstant()); 247 hasPrinted = true; 248 } 245 249 if (node.isBranch() || node.isJump()) { 246 250 printf("%sT:#%u", hasPrinted ? ", " : "", node.takenBlockIndex()); … … 262 266 else if (node.hasHeapPrediction()) 263 267 printf(" predicting %s", predictionToString(node.getHeapPrediction())); 264 else if (node.hasMethodCheckData()) {265 MethodCheckData& methodCheckData = m_methodCheckData[node.methodCheckDataIndex()];266 JSCell* functionCell = getJSFunction(methodCheckData.function);267 ExecutableBase* executable = 0;268 CodeBlock* primaryForCall = 0;269 CodeBlock* secondaryForCall = 0;270 CodeBlock* primaryForConstruct = 0;271 CodeBlock* secondaryForConstruct = 0;272 if (functionCell) {273 JSFunction* function = asFunction(functionCell);274 executable = function->executable();275 if (!executable->isHostFunction()) {276 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);277 if (functionExecutable->isGeneratedForCall()) {278 primaryForCall = &functionExecutable->generatedBytecodeForCall();279 secondaryForCall = primaryForCall->alternative();280 }281 if (functionExecutable->isGeneratedForConstruct()) {282 primaryForConstruct = &functionExecutable->generatedBytecodeForConstruct();283 secondaryForConstruct = primaryForConstruct->alternative();284 }285 }286 }287 printf(" predicting function %p(%p(%p(%p) %p(%p)))", methodCheckData.function, executable, primaryForCall, secondaryForCall, primaryForConstruct, secondaryForConstruct);288 }289 268 } 290 269 -
trunk/Source/JavaScriptCore/dfg/DFGGraph.h
r98912 r100315 46 46 namespace DFG { 47 47 48 struct MethodCheckData {49 // It is safe to refer to these directly because they are shadowed by50 // the old JIT's CodeBlock's MethodCallLinkInfo.51 Structure* structure;52 Structure* prototypeStructure;53 JSObject* function;54 JSObject* prototype;55 56 bool operator==(const MethodCheckData& other) const57 {58 if (structure != other.structure)59 return false;60 if (prototypeStructure != other.prototypeStructure)61 return false;62 if (function != other.function)63 return false;64 if (prototype != other.prototype)65 return false;66 return true;67 }68 69 bool operator!=(const MethodCheckData& other) const70 {71 return !(*this == other);72 }73 };74 75 48 struct StorageAccessData { 76 49 size_t offset; … … 130 103 } 131 104 132 PredictedType getMethodCheckPrediction(Node& node)133 {134 return predictionFromCell(m_methodCheckData[node.methodCheckDataIndex()].function);135 }136 137 105 PredictedType getJSConstantPrediction(Node& node, CodeBlock* codeBlock) 138 106 { 139 return predictionFromValue(node.valueOfJSConstant Node(codeBlock));107 return predictionFromValue(node.valueOfJSConstant(codeBlock)); 140 108 } 141 109 … … 176 144 JSValue valueOfJSConstant(CodeBlock* codeBlock, NodeIndex nodeIndex) 177 145 { 178 if (at(nodeIndex).hasMethodCheckData()) 179 return JSValue(m_methodCheckData[at(nodeIndex).methodCheckDataIndex()].function); 180 return valueOfJSConstantNode(codeBlock, nodeIndex); 146 return at(nodeIndex).valueOfJSConstant(codeBlock); 181 147 } 182 148 int32_t valueOfInt32Constant(CodeBlock* codeBlock, NodeIndex nodeIndex) 183 149 { 184 return valueOfJSConstant Node(codeBlock, nodeIndex).asInt32();150 return valueOfJSConstant(codeBlock, nodeIndex).asInt32(); 185 151 } 186 152 double valueOfNumberConstant(CodeBlock* codeBlock, NodeIndex nodeIndex) 187 153 { 188 return valueOfJSConstant Node(codeBlock, nodeIndex).asNumber();154 return valueOfJSConstant(codeBlock, nodeIndex).asNumber(); 189 155 } 190 156 bool valueOfBooleanConstant(CodeBlock* codeBlock, NodeIndex nodeIndex) 191 157 { 192 return valueOfJSConstant Node(codeBlock, nodeIndex).asBoolean();158 return valueOfJSConstant(codeBlock, nodeIndex).asBoolean(); 193 159 } 194 160 JSFunction* valueOfFunctionConstant(CodeBlock* codeBlock, NodeIndex nodeIndex) … … 257 223 Vector< OwnPtr<BasicBlock> , 8> m_blocks; 258 224 Vector<NodeIndex, 16> m_varArgChildren; 259 Vector<MethodCheckData> m_methodCheckData;260 225 Vector<StorageAccessData> m_storageAccessData; 261 226 Vector<ResolveGlobalData> m_resolveGlobalData; … … 269 234 private: 270 235 271 JSValue valueOfJSConstantNode(CodeBlock* codeBlock, NodeIndex nodeIndex)272 {273 return codeBlock->constantRegister(FirstConstantRegisterIndex + at(nodeIndex).constantNumber()).get();274 }275 276 236 // When a node's refCount goes from 0 to 1, it must (logically) recursively ref all of its children, and vice versa. 277 237 void refChildren(NodeIndex); -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r99929 r100315 158 158 // This macro defines a set of information about all known node types, used to populate NodeId, NodeType below. 159 159 #define FOR_EACH_DFG_OP(macro) \ 160 /* Nodes for constants. */\160 /* A constant in the CodeBlock's constant pool. */\ 161 161 macro(JSConstant, NodeResultJS) \ 162 \ 163 /* A constant not in the CodeBlock's constant pool. Uses get patched to jumps that exit the */\ 164 /* code block. */\ 165 macro(WeakJSConstant, NodeResultJS) \ 162 166 \ 163 167 /* Nodes for handling functions (both as call and as construct). */\ … … 231 235 macro(GetByteArrayLength, NodeResultInt32) \ 232 236 macro(GetMethod, NodeResultJS | NodeMustGenerate) \ 233 macro(CheckMethod, NodeResultJS | NodeMustGenerate) \234 237 macro(GetScopeChain, NodeResultJS) \ 235 238 macro(GetScopedVar, NodeResultJS | NodeMustGenerate) \ … … 398 401 } 399 402 403 bool isWeakConstant() 404 { 405 return op == WeakJSConstant; 406 } 407 400 408 bool hasConstant() 401 409 { 402 return isConstant() || hasMethodCheckData();410 return isConstant() || isWeakConstant(); 403 411 } 404 412 … … 409 417 } 410 418 411 // NOTE: this only works for JSConstant nodes. 412 JSValue valueOfJSConstantNode(CodeBlock* codeBlock) 413 { 419 JSCell* weakConstant() 420 { 421 return bitwise_cast<JSCell*>(m_opInfo); 422 } 423 424 JSValue valueOfJSConstant(CodeBlock* codeBlock) 425 { 426 if (op == WeakJSConstant) 427 return JSValue(weakConstant()); 414 428 return codeBlock->constantRegister(FirstConstantRegisterIndex + constantNumber()).get(); 415 429 } … … 417 431 bool isInt32Constant(CodeBlock* codeBlock) 418 432 { 419 return isConstant() && valueOfJSConstant Node(codeBlock).isInt32();433 return isConstant() && valueOfJSConstant(codeBlock).isInt32(); 420 434 } 421 435 422 436 bool isDoubleConstant(CodeBlock* codeBlock) 423 437 { 424 bool result = isConstant() && valueOfJSConstant Node(codeBlock).isDouble();438 bool result = isConstant() && valueOfJSConstant(codeBlock).isDouble(); 425 439 if (result) 426 440 ASSERT(!isInt32Constant(codeBlock)); … … 430 444 bool isNumberConstant(CodeBlock* codeBlock) 431 445 { 432 bool result = isConstant() && valueOfJSConstant Node(codeBlock).isNumber();446 bool result = isConstant() && valueOfJSConstant(codeBlock).isNumber(); 433 447 ASSERT(result == (isInt32Constant(codeBlock) || isDoubleConstant(codeBlock))); 434 448 return result; … … 437 451 bool isBooleanConstant(CodeBlock* codeBlock) 438 452 { 439 return isConstant() && valueOfJSConstant Node(codeBlock).isBoolean();453 return isConstant() && valueOfJSConstant(codeBlock).isBoolean(); 440 454 } 441 455 … … 478 492 case PutByIdDirect: 479 493 case GetMethod: 480 case CheckMethod:481 494 case Resolve: 482 495 case ResolveBase: … … 724 737 } 725 738 726 bool hasMethodCheckData()727 {728 return op == CheckMethod;729 }730 731 unsigned methodCheckDataIndex()732 {733 ASSERT(hasMethodCheckData());734 return m_opInfo2;735 }736 737 739 bool hasFunctionCheckData() 738 740 { -
trunk/Source/JavaScriptCore/dfg/DFGPropagator.cpp
r99910 r100315 302 302 303 303 switch (op) { 304 case JSConstant: { 304 case JSConstant: 305 case WeakJSConstant: { 305 306 changed |= setPrediction(predictionFromValue(m_graph.valueOfJSConstant(m_codeBlock, m_compileIndex))); 306 307 break; … … 474 475 } 475 476 476 case CheckMethod: {477 changed |= setPrediction(m_graph.getMethodCheckPrediction(node));478 break;479 }480 481 477 case Call: 482 478 case Construct: { … … 1042 1038 } 1043 1039 1044 NodeIndex getMethodLoadElimination(const MethodCheckData& methodCheckData, unsigned identifierNumber, NodeIndex child1)1045 {1046 NodeIndex start = startIndexForChildren(child1);1047 for (NodeIndex index = m_compileIndex; index-- > start;) {1048 Node& node = m_graph[index];1049 switch (node.op) {1050 case CheckMethod:1051 if (node.child1() == child11052 && node.identifierNumber() == identifierNumber1053 && m_graph.m_methodCheckData[node.methodCheckDataIndex()] == methodCheckData)1054 return index;1055 break;1056 1057 case PutByOffset:1058 // If a put was optimized to by-offset then it's not changing the structure1059 break;1060 1061 case PutByVal:1062 case PutByValAlias:1063 if (byValHasIntBase(node)) {1064 // If PutByVal speculates that it's accessing an array with an1065 // integer index, then it's impossible for it to cause a structure1066 // change.1067 break;1068 }1069 return NoNode;1070 1071 case ArrayPush:1072 case ArrayPop:1073 // Pushing and popping cannot despecify a function.1074 break;1075 1076 default:1077 if (clobbersWorld(index))1078 return NoNode;1079 break;1080 }1081 }1082 return NoNode;1083 }1084 1085 1040 bool checkFunctionElimination(JSFunction* function, NodeIndex child1) 1086 1041 { … … 1393 1348 break; 1394 1349 1395 case CheckMethod:1396 setReplacement(getMethodLoadElimination(m_graph.m_methodCheckData[node.methodCheckDataIndex()], node.identifierNumber(), node.child1()));1397 break;1398 1399 1350 case CheckStructure: 1400 1351 if (checkStructureLoadElimination(node.structureSet(), node.child1())) -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r100260 r100315 2059 2059 switch (op) { 2060 2060 case JSConstant: 2061 case WeakJSConstant: 2061 2062 initConstantInfo(m_compileIndex); 2062 2063 break; … … 3630 3631 } 3631 3632 3632 case CheckMethod: {3633 MethodCheckData& methodCheckData = m_jit.graph().m_methodCheckData[node.methodCheckDataIndex()];3634 3635 SpeculateCellOperand base(this, node.child1());3636 GPRTemporary scratch(this); // this needs to be a separate register, unfortunately.3637 GPRReg baseGPR = base.gpr();3638 GPRReg scratchGPR = scratch.gpr();3639 3640 if (!m_state.forNode(node.child1()).m_structure.doesNotContainAnyOtherThan(methodCheckData.structure))3641 speculationCheck(JSValueRegs(), NoNode, m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(methodCheckData.structure)));3642 if (methodCheckData.prototype != m_jit.globalObjectFor(node.codeOrigin)->methodCallDummy()) {3643 m_jit.move(JITCompiler::TrustedImmPtr(methodCheckData.prototype->structureAddress()), scratchGPR);3644 speculationCheck(JSValueRegs(), NoNode, m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(scratchGPR), JITCompiler::TrustedImmPtr(methodCheckData.prototypeStructure)));3645 }3646 3647 useChildren(node);3648 initConstantInfo(m_compileIndex);3649 break;3650 }3651 3652 3633 case PutById: { 3653 3634 SpeculateCellOperand base(this, node.child1()); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r100244 r100315 2070 2070 switch (op) { 2071 2071 case JSConstant: 2072 case WeakJSConstant: 2072 2073 initConstantInfo(m_compileIndex); 2073 2074 break; … … 3544 3545 } 3545 3546 3546 case CheckMethod: {3547 MethodCheckData& methodCheckData = m_jit.graph().m_methodCheckData[node.methodCheckDataIndex()];3548 3549 SpeculateCellOperand base(this, node.child1());3550 GPRTemporary scratch(this); // this needs to be a separate register, unfortunately.3551 GPRReg baseGPR = base.gpr();3552 GPRReg scratchGPR = scratch.gpr();3553 3554 if (!m_state.forNode(node.child1()).m_structure.doesNotContainAnyOtherThan(methodCheckData.structure))3555 speculationCheck(JSValueRegs(), NoNode, m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(methodCheckData.structure)));3556 if (methodCheckData.prototype != m_jit.globalObjectFor(node.codeOrigin)->methodCallDummy()) {3557 m_jit.move(JITCompiler::TrustedImmPtr(methodCheckData.prototype->structureAddress()), scratchGPR);3558 speculationCheck(JSValueRegs(), NoNode, m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(scratchGPR), JITCompiler::TrustedImmPtr(methodCheckData.prototypeStructure)));3559 }3560 3561 useChildren(node);3562 initConstantInfo(m_compileIndex);3563 break;3564 }3565 3566 3547 case PutById: { 3567 3548 SpeculateCellOperand base(this, node.child1());
Note:
See TracChangeset
for help on using the changeset viewer.