Changeset 171613 in webkit for trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
- Timestamp:
- Jul 25, 2014, 1:55:17 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r171391 r171613 133 133 , m_currentBlock(0) 134 134 , m_currentIndex(0) 135 , m_constantUndefined(UINT_MAX) 136 , m_constantNull(UINT_MAX) 137 , m_constantNaN(UINT_MAX) 138 , m_constant1(UINT_MAX) 139 , m_constants(m_codeBlock->numberOfConstantRegisters()) 135 , m_constantUndefined(graph.freeze(jsUndefined())) 136 , m_constantNull(graph.freeze(jsNull())) 137 , m_constantNaN(graph.freeze(jsNumber(PNaN))) 138 , m_constantOne(graph.freeze(jsNumber(1))) 140 139 , m_numArguments(m_codeBlock->numParameters()) 141 140 , m_numLocals(m_codeBlock->m_numCalleeRegisters) … … 144 143 , m_inlineStackTop(0) 145 144 , m_haveBuiltOperandMaps(false) 146 , m_emptyJSValueIndex(UINT_MAX)147 145 , m_currentInstruction(0) 148 146 { … … 195 193 Node* base, unsigned identifierNumber, Node* value, const PutByIdStatus&, 196 194 bool isDirect); 197 Node* emitPrototypeChecks(Structure*, IntendedStructureChain*);195 void emitChecks(const ConstantStructureCheckVector&); 198 196 199 197 Node* getScope(bool skipTop, unsigned skipCount); … … 218 216 Node* getDirect(VirtualRegister operand) 219 217 { 220 // Is this a constant? 221 if (operand.isConstant()) { 222 unsigned constant = operand.toConstantIndex(); 223 ASSERT(constant < m_constants.size()); 224 return getJSConstant(constant); 225 } 218 ASSERT(!operand.isConstant()); 226 219 227 220 // Is this an argument? … … 235 228 Node* get(VirtualRegister operand) 236 229 { 230 if (operand.isConstant()) { 231 unsigned constantIndex = operand.toConstantIndex(); 232 unsigned oldSize = m_constants.size(); 233 if (constantIndex >= oldSize || !m_constants[constantIndex]) { 234 JSValue value = m_inlineStackTop->m_codeBlock->getConstant(operand.offset()); 235 if (constantIndex >= oldSize) { 236 m_constants.grow(constantIndex + 1); 237 for (unsigned i = oldSize; i < m_constants.size(); ++i) 238 m_constants[i] = nullptr; 239 } 240 m_constants[constantIndex] = 241 addToGraph(JSConstant, OpInfo(m_graph.freezeStrong(value))); 242 } 243 ASSERT(m_constants[constantIndex]); 244 return m_constants[constantIndex]; 245 } 246 237 247 if (inlineCallFrame()) { 238 248 if (!inlineCallFrame()->isClosureCall) { 239 249 JSFunction* callee = inlineCallFrame()->calleeConstant(); 240 250 if (operand.offset() == JSStack::Callee) 241 return cellConstant(callee);251 return weakJSConstant(callee); 242 252 if (operand.offset() == JSStack::ScopeChain) 243 return cellConstant(callee->scope());253 return weakJSConstant(callee->scope()); 244 254 } 245 255 } else if (operand.offset() == JSStack::Callee) … … 310 320 addToGraph(FunctionReentryWatchpoint, OpInfo(m_codeBlock->symbolTable())); 311 321 addToGraph(VariableWatchpoint, OpInfo(set)); 312 // Note: this is very special from an OSR exit standpoint. We wouldn't be 313 // able to do this for most locals, but it works here because we're dealing 314 // with a flushed local. For most locals we would need to issue a GetLocal 315 // here and ensure that we have uses in DFG IR wherever there would have 316 // been uses in bytecode. Clearly this optimization does not do this. But 317 // that's fine, because we don't need to track liveness for captured 318 // locals, and this optimization only kicks in for captured locals. 319 return inferredConstant(value); 322 return weakJSConstant(value); 320 323 } 321 324 } … … 368 371 VariableAccessData* variableAccessData = newVariableAccessData(operand, isCaptured); 369 372 variableAccessData->mergeStructureCheckHoistingFailed( 370 m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache) 371 || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCacheWatchpoint)); 373 m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)); 372 374 variableAccessData->mergeCheckArrayHoistingFailed( 373 375 m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIndexingType)); … … 425 427 426 428 variableAccessData->mergeStructureCheckHoistingFailed( 427 m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache) 428 || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCacheWatchpoint)); 429 m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)); 429 430 variableAccessData->mergeCheckArrayHoistingFailed( 430 431 m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIndexingType)); … … 467 468 } 468 469 469 void addConstant(JSValue value)470 {471 unsigned constantIndex = m_codeBlock->addConstantLazily();472 initializeLazyWriteBarrierForConstant(473 m_graph.m_plan.writeBarriers,474 m_codeBlock->constants()[constantIndex],475 m_codeBlock,476 constantIndex,477 m_codeBlock->ownerExecutable(),478 value);479 }480 481 470 void flush(VirtualRegister operand) 482 471 { … … 555 544 } 556 545 557 // NOTE: Only use this to construct constants that arise from non-speculative 558 // constant folding. I.e. creating constants using this if we had constant 559 // field inference would be a bad idea, since the bytecode parser's folding 560 // doesn't handle liveness preservation. 561 Node* getJSConstantForValue(JSValue constantValue) 562 { 563 unsigned constantIndex; 564 if (!m_codeBlock->findConstant(constantValue, constantIndex)) { 565 addConstant(constantValue); 566 m_constants.append(ConstantRecord()); 567 } 568 569 ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters()); 570 571 return getJSConstant(constantIndex); 572 } 573 574 Node* getJSConstant(unsigned constant) 575 { 576 Node* node = m_constants[constant].asJSValue; 577 if (node) 578 return node; 579 580 Node* result = addToGraph(JSConstant, OpInfo(constant)); 581 m_constants[constant].asJSValue = result; 582 return result; 546 // Assumes that the constant should be strongly marked. 547 Node* jsConstant(JSValue constantValue) 548 { 549 return addToGraph(JSConstant, OpInfo(m_graph.freezeStrong(constantValue))); 550 } 551 552 Node* weakJSConstant(JSValue constantValue) 553 { 554 return addToGraph(JSConstant, OpInfo(m_graph.freeze(constantValue))); 583 555 } 584 556 … … 594 566 } 595 567 596 // Convenience methods for checking nodes for constants.597 bool isJSConstant(Node* node)598 {599 return node->op() == JSConstant;600 }601 bool isInt32Constant(Node* node)602 {603 return isJSConstant(node) && valueOfJSConstant(node).isInt32();604 }605 // Convenience methods for getting constant values.606 JSValue valueOfJSConstant(Node* node)607 {608 ASSERT(isJSConstant(node));609 return m_codeBlock->getConstant(FirstConstantRegisterIndex + node->constantNumber());610 }611 int32_t valueOfInt32Constant(Node* node)612 {613 ASSERT(isInt32Constant(node));614 return valueOfJSConstant(node).asInt32();615 }616 617 // This method returns a JSConstant with the value 'undefined'.618 Node* constantUndefined()619 {620 // Has m_constantUndefined been set up yet?621 if (m_constantUndefined == UINT_MAX) {622 // Search the constant pool for undefined, if we find it, we can just reuse this!623 unsigned numberOfConstants = m_codeBlock->numberOfConstantRegisters();624 for (m_constantUndefined = 0; m_constantUndefined < numberOfConstants; ++m_constantUndefined) {625 JSValue testMe = m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantUndefined);626 if (testMe.isUndefined())627 return getJSConstant(m_constantUndefined);628 }629 630 // Add undefined to the CodeBlock's constants, and add a corresponding slot in m_constants.631 ASSERT(m_constants.size() == numberOfConstants);632 addConstant(jsUndefined());633 m_constants.append(ConstantRecord());634 ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());635 }636 637 // m_constantUndefined must refer to an entry in the CodeBlock's constant pool that has the value 'undefined'.638 ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantUndefined).isUndefined());639 return getJSConstant(m_constantUndefined);640 }641 642 // This method returns a JSConstant with the value 'null'.643 Node* constantNull()644 {645 // Has m_constantNull been set up yet?646 if (m_constantNull == UINT_MAX) {647 // Search the constant pool for null, if we find it, we can just reuse this!648 unsigned numberOfConstants = m_codeBlock->numberOfConstantRegisters();649 for (m_constantNull = 0; m_constantNull < numberOfConstants; ++m_constantNull) {650 JSValue testMe = m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantNull);651 if (testMe.isNull())652 return getJSConstant(m_constantNull);653 }654 655 // Add null to the CodeBlock's constants, and add a corresponding slot in m_constants.656 ASSERT(m_constants.size() == numberOfConstants);657 addConstant(jsNull());658 m_constants.append(ConstantRecord());659 ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());660 }661 662 // m_constantNull must refer to an entry in the CodeBlock's constant pool that has the value 'null'.663 ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantNull).isNull());664 return getJSConstant(m_constantNull);665 }666 667 // This method returns a DoubleConstant with the value 1.668 Node* one()669 {670 // Has m_constant1 been set up yet?671 if (m_constant1 == UINT_MAX) {672 // Search the constant pool for the value 1, if we find it, we can just reuse this!673 unsigned numberOfConstants = m_codeBlock->numberOfConstantRegisters();674 for (m_constant1 = 0; m_constant1 < numberOfConstants; ++m_constant1) {675 JSValue testMe = m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constant1);676 if (testMe.isInt32() && testMe.asInt32() == 1)677 return getJSConstant(m_constant1);678 }679 680 // Add the value 1 to the CodeBlock's constants, and add a corresponding slot in m_constants.681 ASSERT(m_constants.size() == numberOfConstants);682 addConstant(jsNumber(1));683 m_constants.append(ConstantRecord());684 ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());685 }686 687 // m_constant1 must refer to an entry in the CodeBlock's constant pool that has the integer value 1.688 ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constant1).isInt32());689 ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constant1).asInt32() == 1);690 return getJSConstant(m_constant1);691 }692 693 // This method returns a DoubleConstant with the value NaN.694 Node* constantNaN()695 {696 JSValue nan = jsNaN();697 698 // Has m_constantNaN been set up yet?699 if (m_constantNaN == UINT_MAX) {700 // Search the constant pool for the value NaN, if we find it, we can just reuse this!701 unsigned numberOfConstants = m_codeBlock->numberOfConstantRegisters();702 for (m_constantNaN = 0; m_constantNaN < numberOfConstants; ++m_constantNaN) {703 JSValue testMe = m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantNaN);704 if (JSValue::encode(testMe) == JSValue::encode(nan))705 return getJSConstant(m_constantNaN);706 }707 708 // Add the value nan to the CodeBlock's constants, and add a corresponding slot in m_constants.709 ASSERT(m_constants.size() == numberOfConstants);710 addConstant(nan);711 m_constants.append(ConstantRecord());712 ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());713 }714 715 // m_constantNaN must refer to an entry in the CodeBlock's constant pool that has the value nan.716 ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantNaN).isDouble());717 ASSERT(std::isnan(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantNaN).asDouble()));718 return getJSConstant(m_constantNaN);719 }720 721 Node* cellConstant(JSCell* cell)722 {723 HashMap<JSCell*, Node*>::AddResult result = m_cellConstantNodes.add(cell, nullptr);724 if (result.isNewEntry) {725 ASSERT(!Heap::isZombified(cell));726 result.iterator->value = addToGraph(WeakJSConstant, OpInfo(cell));727 }728 729 return result.iterator->value;730 }731 732 Node* inferredConstant(JSValue value)733 {734 if (value.isCell())735 return cellConstant(value.asCell());736 return getJSConstantForValue(value);737 }738 739 568 InlineCallFrame* inlineCallFrame() 740 569 { … … 821 650 m_parameterSlots = parameterSlots; 822 651 823 int dummyThisArgument = op == Call ? 0 : 1;652 int dummyThisArgument = op == Call || op == NativeCall ? 0 : 1; 824 653 for (int i = 0 + dummyThisArgument; i < argCount; ++i) 825 654 addVarArgChild(get(virtualRegisterForArgument(i, registerOffset))); … … 832 661 Node* cellConstantWithStructureCheck(JSCell* object, Structure* structure) 833 662 { 834 Node* objectNode = cellConstant(object);663 Node* objectNode = weakJSConstant(object); 835 664 addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(structure)), objectNode); 836 665 return objectNode; 837 666 } 838 667 839 Node* cellConstantWithStructureCheck(JSCell* object)840 {841 return cellConstantWithStructureCheck(object, object->structure());842 }843 844 668 SpeculatedType getPredictionWithoutOSRExit(unsigned bytecodeIndex) 845 669 { … … 972 796 } 973 797 974 bool structureChainIsStillValid(bool direct, Structure* previousStructure, StructureChain* chain)975 {976 if (direct)977 return true;978 979 if (!previousStructure->storedPrototype().isNull() && previousStructure->storedPrototype().asCell()->structure() != chain->head()->get())980 return false;981 982 for (WriteBarrier<Structure>* it = chain->head(); *it; ++it) {983 if (!(*it)->storedPrototype().isNull() && (*it)->storedPrototype().asCell()->structure() != it[1].get())984 return false;985 }986 987 return true;988 }989 990 798 void buildOperandMapsIfNecessary(); 991 799 … … 1000 808 unsigned m_currentIndex; 1001 809 1002 // We use these values during code generation, and to avoid the need for 1003 // special handling we make sure they are available as constants in the 1004 // CodeBlock's constant pool. These variables are initialized to 1005 // UINT_MAX, and lazily updated to hold an index into the CodeBlock's 1006 // constant pool, as necessary. 1007 unsigned m_constantUndefined; 1008 unsigned m_constantNull; 1009 unsigned m_constantNaN; 1010 unsigned m_constant1; 1011 HashMap<JSCell*, unsigned> m_cellConstants; 1012 HashMap<JSCell*, Node*> m_cellConstantNodes; 1013 1014 // A constant in the constant pool may be represented by more than one 1015 // node in the graph, depending on the context in which it is being used. 1016 struct ConstantRecord { 1017 ConstantRecord() 1018 : asInt32(0) 1019 , asNumeric(0) 1020 , asJSValue(0) 1021 { 1022 } 1023 1024 Node* asInt32; 1025 Node* asNumeric; 1026 Node* asJSValue; 1027 }; 1028 1029 // Track the index of the node whose result is the current value for every 1030 // register value in the bytecode - argument, local, and temporary. 1031 Vector<ConstantRecord, 16> m_constants; 810 FrozenValue* m_constantUndefined; 811 FrozenValue* m_constantNull; 812 FrozenValue* m_constantNaN; 813 FrozenValue* m_constantOne; 814 Vector<Node*, 16> m_constants; 1032 815 1033 816 // The number of arguments passed to the function. … … 1064 847 // direct, caller). 1065 848 Vector<unsigned> m_identifierRemap; 1066 Vector<unsigned> m_constantRemap;1067 849 Vector<unsigned> m_constantBufferRemap; 1068 850 Vector<unsigned> m_switchRemap; … … 1135 917 return operand; 1136 918 1137 if (operand.isConstant()) { 1138 VirtualRegister result = VirtualRegister(m_constantRemap[operand.toConstantIndex()]); 1139 ASSERT(result.isConstant()); 1140 return result; 1141 } 919 ASSERT(!operand.isConstant()); 1142 920 1143 921 return VirtualRegister(operand.offset() + m_inlineCallFrame->stackOffset); … … 1173 951 // Mapping between identifier names and numbers. 1174 952 BorrowedIdentifierMap m_identifierMap; 1175 // Mapping between values and constant numbers.1176 JSValueMap m_jsValueMap;1177 // Index of the empty value, or UINT_MAX if there is no mapping. This is a horrible1178 // work-around for the fact that JSValueMap can't handle "empty" values.1179 unsigned m_emptyJSValueIndex;1180 953 1181 954 CodeBlock* m_dfgCodeBlock; … … 1225 998 CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind); 1226 999 1227 if (m_graph.isConstant(callTarget)) { 1228 callLinkStatus = CallLinkStatus( 1229 m_graph.valueOfJSConstant(callTarget)).setIsProved(true); 1230 } 1000 if (callTarget->hasConstant()) 1001 callLinkStatus = CallLinkStatus(callTarget->asJSValue()).setIsProved(true); 1231 1002 1232 1003 if (!callLinkStatus.canOptimize()) { … … 1274 1045 m_graph.compilation()->noticeInlinedCall(); 1275 1046 return; 1276 } else if (JSFunction* function = callLinkStatus.function()) 1277 if (function->isHostFunction()) { 1047 } else if (isFTL(m_graph.m_plan.mode)) { 1048 JSFunction* function = callLinkStatus.function(); 1049 if (function && function->isHostFunction()) { 1278 1050 emitFunctionChecks(callLinkStatus, callTarget, registerOffset, specializationKind); 1279 1051 knownFunction = function; 1280 } 1281 1282 addCall(result, op, callTarget, argumentCountIncludingThis, registerOffset)->giveKnownFunction(knownFunction); 1052 1053 if (op == Call) 1054 op = NativeCall; 1055 else { 1056 ASSERT(op == Construct); 1057 op = NativeConstruct; 1058 } 1059 } 1060 } 1061 Node* call = addCall(result, op, callTarget, argumentCountIncludingThis, registerOffset); 1062 1063 if (knownFunction) 1064 call->giveKnownFunction(knownFunction); 1283 1065 } 1284 1066 … … 1299 1081 1300 1082 if (JSFunction* function = callLinkStatus.function()) 1301 addToGraph(CheckFunction, OpInfo( function), callTarget, thisArgument);1083 addToGraph(CheckFunction, OpInfo(m_graph.freeze(function)), callTarget, thisArgument); 1302 1084 else { 1303 1085 ASSERT(callLinkStatus.structure()); … … 1456 1238 1457 1239 parseCodeBlock(); 1240 prepareToParseBlock(); // Reset our state now that we're back to the outer code. 1458 1241 1459 1242 m_currentIndex = oldIndex; … … 1545 1328 { 1546 1329 if (argumentCountIncludingThis == 1) { // Math.min() 1547 set(VirtualRegister(resultOperand), constantNaN());1330 set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantNaN))); 1548 1331 return true; 1549 1332 } … … 1570 1353 case AbsIntrinsic: { 1571 1354 if (argumentCountIncludingThis == 1) { // Math.abs() 1572 set(VirtualRegister(resultOperand), constantNaN());1355 set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantNaN))); 1573 1356 return true; 1574 1357 } … … 1594 1377 case SinIntrinsic: { 1595 1378 if (argumentCountIncludingThis == 1) { 1596 set(VirtualRegister(resultOperand), constantNaN());1379 set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantNaN))); 1597 1380 return true; 1598 1381 } … … 1741 1524 1742 1525 case DFGTrueIntrinsic: { 1743 set(VirtualRegister(resultOperand), getJSConstantForValue(jsBoolean(true)));1526 set(VirtualRegister(resultOperand), jsConstant(jsBoolean(true))); 1744 1527 return true; 1745 1528 } … … 1747 1530 case OSRExitIntrinsic: { 1748 1531 addToGraph(ForceOSRExit); 1749 set(VirtualRegister(resultOperand), constantUndefined());1532 set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantUndefined))); 1750 1533 return true; 1751 1534 } … … 1753 1536 case IsFinalTierIntrinsic: { 1754 1537 set(VirtualRegister(resultOperand), 1755 getJSConstantForValue(jsBoolean(Options::useFTLJIT() ? isFTL(m_graph.m_plan.mode) : true)));1538 jsConstant(jsBoolean(Options::useFTLJIT() ? isFTL(m_graph.m_plan.mode) : true))); 1756 1539 return true; 1757 1540 } … … 1763 1546 node->setHeapPrediction(SpecInt32); 1764 1547 } 1765 set(VirtualRegister(resultOperand), constantUndefined());1548 set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantUndefined))); 1766 1549 return true; 1767 1550 } … … 1869 1652 1870 1653 if (argumentCountIncludingThis <= 1) 1871 result = cellConstant(m_vm->smallStrings.emptyString());1654 result = jsConstant(m_vm->smallStrings.emptyString()); 1872 1655 else 1873 1656 result = addToGraph(ToString, get(virtualRegisterForArgument(1, registerOffset))); … … 1925 1708 } 1926 1709 1927 Node* ByteCodeParser::emitPrototypeChecks( 1928 Structure* structure, IntendedStructureChain* chain) 1710 void ByteCodeParser::emitChecks(const ConstantStructureCheckVector& vector) 1929 1711 { 1930 ASSERT(structure); 1931 Node* base = 0; 1932 m_graph.chains().addLazily(chain); 1933 Structure* currentStructure = structure; 1934 JSObject* currentObject = 0; 1935 for (unsigned i = 0; i < chain->size(); ++i) { 1936 currentObject = asObject(currentStructure->prototypeForLookup(m_inlineStackTop->m_codeBlock)); 1937 currentStructure = chain->at(i); 1938 base = cellConstantWithStructureCheck(currentObject, currentStructure); 1939 } 1940 return base; 1712 for (unsigned i = 0; i < vector.size(); ++i) 1713 cellConstantWithStructureCheck(vector[i].constant(), vector[i].structure()); 1941 1714 } 1942 1715 … … 1967 1740 // optimal, if there is some rarely executed case in the chain that requires a lot 1968 1741 // of checks and those checks are not watchpointable. 1969 for (unsigned variantIndex = getByIdStatus.numVariants(); variantIndex--;) { 1970 if (getByIdStatus[variantIndex].chain()) { 1971 emitPrototypeChecks( 1972 getByIdStatus[variantIndex].structureSet().onlyStructure(), 1973 getByIdStatus[variantIndex].chain()); 1974 } 1975 } 1742 for (unsigned variantIndex = getByIdStatus.numVariants(); variantIndex--;) 1743 emitChecks(getByIdStatus[variantIndex].constantChecks()); 1976 1744 1977 1745 // 2) Emit a MultiGetByOffset … … 1994 1762 addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.structureSet())), base); 1995 1763 1996 if (variant.chain()) {1997 base = emitPrototypeChecks( 1998 variant.structureSet().onlyStructure(), variant.chain());1999 }1764 emitChecks(variant.constantChecks()); 1765 1766 if (variant.alternateBase()) 1767 base = weakJSConstant(variant.alternateBase()); 2000 1768 2001 1769 // Unless we want bugs like https://bugs.webkit.org/show_bug.cgi?id=88783, we need to … … 2010 1778 Node* loadedValue; 2011 1779 if (variant.specificValue()) 2012 loadedValue = cellConstant(variant.specificValue().asCell());1780 loadedValue = weakJSConstant(variant.specificValue()); 2013 1781 else { 2014 1782 loadedValue = handleGetByOffset( … … 2094 1862 if (putByIdStatus[variantIndex].kind() != PutByIdVariant::Transition) 2095 1863 continue; 2096 if (!putByIdStatus[variantIndex].structureChain()) 2097 continue; 2098 emitPrototypeChecks( 2099 putByIdStatus[variantIndex].oldStructure(), 2100 putByIdStatus[variantIndex].structureChain()); 1864 emitChecks(putByIdStatus[variantIndex].constantChecks()); 2101 1865 } 2102 1866 } … … 2125 1889 } 2126 1890 2127 if (variant.structureChain() && !variant.structureChain()->isStillValid()) {2128 emitPutById(base, identifierNumber, value, putByIdStatus, isDirect);2129 return;2130 }2131 2132 m_graph.chains().addLazily(variant.structureChain());2133 2134 1891 addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.oldStructure())), base); 2135 if (!isDirect) 2136 emitPrototypeChecks(variant.oldStructure(), variant.structureChain()); 1892 emitChecks(variant.constantChecks()); 2137 1893 2138 1894 ASSERT(variant.oldStructure()->transitionWatchpointSetHasBeenInvalidated()); … … 2184 1940 void ByteCodeParser::prepareToParseBlock() 2185 1941 { 2186 for (unsigned i = 0; i < m_constants.size(); ++i) 2187 m_constants[i] = ConstantRecord(); 2188 m_cellConstantNodes.clear(); 1942 m_constants.resize(0); 2189 1943 } 2190 1944 … … 2218 1972 virtualRegisterForArgument(argument), m_codeBlock->isCaptured(virtualRegisterForArgument(argument))); 2219 1973 variable->mergeStructureCheckHoistingFailed( 2220 m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache) 2221 || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCacheWatchpoint)); 1974 m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)); 2222 1975 variable->mergeCheckArrayHoistingFailed( 2223 1976 m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIndexingType)); … … 2265 2018 // === Function entry opcodes === 2266 2019 2267 case op_enter: 2020 case op_enter: { 2021 Node* undefined = addToGraph(JSConstant, OpInfo(m_constantUndefined)); 2268 2022 // Initialize all locals to undefined. 2269 2023 for (int i = 0; i < m_inlineStackTop->m_codeBlock->m_numVars; ++i) 2270 set(virtualRegisterForLocal(i), constantUndefined(), ImmediateNakedSet);2024 set(virtualRegisterForLocal(i), undefined, ImmediateNakedSet); 2271 2025 if (m_inlineStackTop->m_codeBlock->specializationKind() == CodeForConstruct) 2272 set(virtualRegisterForArgument(0), constantUndefined(), ImmediateNakedSet);2026 set(virtualRegisterForArgument(0), undefined, ImmediateNakedSet); 2273 2027 NEXT_OPCODE(op_enter); 2028 } 2274 2029 2275 2030 case op_touch_entry: … … 2286 2041 || m_inlineStackTop->m_profiledBlock->couldTakeSlowCase(m_currentIndex) 2287 2042 || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache) 2288 || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCacheWatchpoint)2289 2043 || (op1->op() == GetLocal && op1->variableAccessData()->structureCheckHoistingFailed())) { 2290 2044 setThis(addToGraph(ToThis, op1)); … … 2303 2057 Node* callee = get(VirtualRegister(calleeOperand)); 2304 2058 bool alreadyEmitted = false; 2305 if (callee->op() == WeakJSConstant) { 2306 JSCell* cell = callee->weakConstant(); 2307 ASSERT(cell->inherits(JSFunction::info())); 2308 2309 JSFunction* function = jsCast<JSFunction*>(cell); 2059 if (JSFunction* function = callee->dynamicCastConstant<JSFunction*>()) { 2310 2060 if (Structure* structure = function->allocationStructure()) { 2311 addToGraph(AllocationProfileWatchpoint, OpInfo( function));2061 addToGraph(AllocationProfileWatchpoint, OpInfo(m_graph.freeze(function))); 2312 2062 // The callee is still live up to this point. 2313 2063 addToGraph(Phantom, callee); … … 2381 2131 set(VirtualRegister(currentInstruction[1].u.operand), get(VirtualRegister(JSStack::Callee))); 2382 2132 } else { 2133 FrozenValue* frozen = m_graph.freeze(cachedFunction); 2383 2134 ASSERT(cachedFunction->inherits(JSFunction::info())); 2384 2135 Node* actualCallee = get(VirtualRegister(JSStack::Callee)); 2385 addToGraph(CheckFunction, OpInfo( cachedFunction), actualCallee);2386 set(VirtualRegister(currentInstruction[1].u.operand), addToGraph( WeakJSConstant, OpInfo(cachedFunction)));2136 addToGraph(CheckFunction, OpInfo(frozen), actualCallee); 2137 set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(JSConstant, OpInfo(frozen))); 2387 2138 } 2388 2139 NEXT_OPCODE(op_get_callee); … … 2448 2199 VirtualRegister srcDstVirtualRegister = VirtualRegister(srcDst); 2449 2200 Node* op = get(srcDstVirtualRegister); 2450 set(srcDstVirtualRegister, makeSafe(addToGraph(ArithAdd, op, one())));2201 set(srcDstVirtualRegister, makeSafe(addToGraph(ArithAdd, op, addToGraph(JSConstant, OpInfo(m_constantOne))))); 2451 2202 NEXT_OPCODE(op_inc); 2452 2203 } … … 2456 2207 VirtualRegister srcDstVirtualRegister = VirtualRegister(srcDst); 2457 2208 Node* op = get(srcDstVirtualRegister); 2458 set(srcDstVirtualRegister, makeSafe(addToGraph(ArithSub, op, one())));2209 set(srcDstVirtualRegister, makeSafe(addToGraph(ArithSub, op, addToGraph(JSConstant, OpInfo(m_constantOne))))); 2459 2210 NEXT_OPCODE(op_dec); 2460 2211 } … … 2673 2424 case op_eq_null: { 2674 2425 Node* value = get(VirtualRegister(currentInstruction[2].u.operand)); 2675 set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(CompareEqConstant, value, constantNull()));2426 set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(CompareEqConstant, value, addToGraph(JSConstant, OpInfo(m_constantNull)))); 2676 2427 NEXT_OPCODE(op_eq_null); 2677 2428 } … … 2693 2444 case op_neq_null: { 2694 2445 Node* value = get(VirtualRegister(currentInstruction[2].u.operand)); 2695 set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(LogicalNot, addToGraph(CompareEqConstant, value, constantNull())));2446 set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(LogicalNot, addToGraph(CompareEqConstant, value, addToGraph(JSConstant, OpInfo(m_constantNull))))); 2696 2447 NEXT_OPCODE(op_neq_null); 2697 2448 } … … 2818 2569 unsigned relativeOffset = currentInstruction[2].u.operand; 2819 2570 Node* value = get(VirtualRegister(currentInstruction[1].u.operand)); 2820 Node* condition = addToGraph(CompareEqConstant, value, constantNull());2571 Node* condition = addToGraph(CompareEqConstant, value, addToGraph(JSConstant, OpInfo(m_constantNull))); 2821 2572 addToGraph(Branch, OpInfo(branchData(m_currentIndex + relativeOffset, m_currentIndex + OPCODE_LENGTH(op_jeq_null))), condition); 2822 2573 LAST_OPCODE(op_jeq_null); … … 2826 2577 unsigned relativeOffset = currentInstruction[2].u.operand; 2827 2578 Node* value = get(VirtualRegister(currentInstruction[1].u.operand)); 2828 Node* condition = addToGraph(CompareEqConstant, value, constantNull());2579 Node* condition = addToGraph(CompareEqConstant, value, addToGraph(JSConstant, OpInfo(m_constantNull))); 2829 2580 addToGraph(Branch, OpInfo(branchData(m_currentIndex + OPCODE_LENGTH(op_jneq_null), m_currentIndex + relativeOffset)), condition); 2830 2581 LAST_OPCODE(op_jneq_null); … … 2915 2666 if (target == data.fallThrough.bytecodeIndex()) 2916 2667 continue; 2917 data.cases.append(SwitchCase::withBytecodeIndex( jsNumber(static_cast<int32_t>(table.min + i)), target));2668 data.cases.append(SwitchCase::withBytecodeIndex(m_graph.freeze(jsNumber(static_cast<int32_t>(table.min + i))), target)); 2918 2669 } 2919 2670 flushIfTerminal(data); … … 3066 2817 addToGraph( 3067 2818 CheckFunction, 3068 OpInfo(actualPointerFor(m_inlineStackTop->m_codeBlock, currentInstruction[2].u.specialPointer)), 2819 OpInfo(m_graph.freeze(static_cast<JSCell*>(actualPointerFor( 2820 m_inlineStackTop->m_codeBlock, currentInstruction[2].u.specialPointer)))), 3069 2821 get(VirtualRegister(currentInstruction[1].u.operand))); 3070 2822 addToGraph(Jump, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jneq_ptr))); … … 3085 2837 case GlobalPropertyWithVarInjectionChecks: 3086 2838 case GlobalVarWithVarInjectionChecks: 3087 set(VirtualRegister(dst), cellConstant(m_inlineStackTop->m_codeBlock->globalObject()));2839 set(VirtualRegister(dst), weakJSConstant(m_inlineStackTop->m_codeBlock->globalObject())); 3088 2840 break; 3089 2841 case ClosureVar: … … 3093 2845 && activation->symbolTable()->m_functionEnteredOnce.isStillValid()) { 3094 2846 addToGraph(FunctionReentryWatchpoint, OpInfo(activation->symbolTable())); 3095 set(VirtualRegister(dst), cellConstant(activation));2847 set(VirtualRegister(dst), weakJSConstant(activation)); 3096 2848 break; 3097 2849 } … … 3142 2894 addToGraph(Phantom, get(VirtualRegister(scope))); 3143 2895 if (JSValue specificValue = status[0].specificValue()) 3144 set(VirtualRegister(dst), cellConstant(specificValue.asCell()));2896 set(VirtualRegister(dst), weakJSConstant(specificValue.asCell())); 3145 2897 else 3146 2898 set(VirtualRegister(dst), handleGetByOffset(prediction, base, identifierNumber, operand)); … … 3161 2913 3162 2914 addToGraph(VariableWatchpoint, OpInfo(watchpointSet)); 3163 set(VirtualRegister(dst), inferredConstant(specificValue));2915 set(VirtualRegister(dst), weakJSConstant(specificValue)); 3164 2916 break; 3165 2917 } … … 3177 2929 addToGraph(Phantom, scopeNode); 3178 2930 addToGraph(VariableWatchpoint, OpInfo(watchpointSet)); 3179 set(VirtualRegister(dst), inferredConstant(value));2931 set(VirtualRegister(dst), weakJSConstant(value)); 3180 2932 break; 3181 2933 } … … 3278 3030 3279 3031 case op_init_lazy_reg: { 3280 set(VirtualRegister(currentInstruction[1].u.operand), getJSConstantForValue(JSValue()));3032 set(VirtualRegister(currentInstruction[1].u.operand), jsConstant(JSValue())); 3281 3033 ASSERT(operandIsLocal(currentInstruction[1].u.operand)); 3282 3034 m_graph.m_lazyVars.set(VirtualRegister(currentInstruction[1].u.operand).toLocal()); … … 3433 3185 for (size_t i = 0; i < m_codeBlock->numberOfIdentifiers(); ++i) 3434 3186 m_identifierMap.add(m_codeBlock->identifier(i).impl(), i); 3435 for (size_t i = 0; i < m_codeBlock->numberOfConstantRegisters(); ++i) {3436 JSValue value = m_codeBlock->getConstant(i + FirstConstantRegisterIndex);3437 if (!value)3438 m_emptyJSValueIndex = i + FirstConstantRegisterIndex;3439 else3440 m_jsValueMap.add(JSValue::encode(value), i + FirstConstantRegisterIndex);3441 }3442 3187 3443 3188 m_haveBuiltOperandMaps = true; … … 3537 3282 3538 3283 m_identifierRemap.resize(codeBlock->numberOfIdentifiers()); 3539 m_constantRemap.resize(codeBlock->numberOfConstantRegisters());3540 3284 m_constantBufferRemap.resize(codeBlock->numberOfConstantBuffers()); 3541 3285 m_switchRemap.resize(codeBlock->numberOfSwitchJumpTables()); … … 3547 3291 byteCodeParser->m_graph.identifiers().addLazily(rep); 3548 3292 m_identifierRemap[i] = result.iterator->value; 3549 }3550 for (size_t i = 0; i < codeBlock->numberOfConstantRegisters(); ++i) {3551 JSValue value = codeBlock->getConstant(i + FirstConstantRegisterIndex);3552 if (!value) {3553 if (byteCodeParser->m_emptyJSValueIndex == UINT_MAX) {3554 byteCodeParser->m_emptyJSValueIndex = byteCodeParser->m_codeBlock->numberOfConstantRegisters() + FirstConstantRegisterIndex;3555 byteCodeParser->addConstant(JSValue());3556 byteCodeParser->m_constants.append(ConstantRecord());3557 }3558 m_constantRemap[i] = byteCodeParser->m_emptyJSValueIndex;3559 continue;3560 }3561 JSValueMap::AddResult result = byteCodeParser->m_jsValueMap.add(JSValue::encode(value), byteCodeParser->m_codeBlock->numberOfConstantRegisters() + FirstConstantRegisterIndex);3562 if (result.isNewEntry) {3563 byteCodeParser->addConstant(value);3564 byteCodeParser->m_constants.append(ConstantRecord());3565 }3566 m_constantRemap[i] = result.iterator->value;3567 3293 } 3568 3294 for (unsigned i = 0; i < codeBlock->numberOfConstantBuffers(); ++i) { … … 3596 3322 3597 3323 m_identifierRemap.resize(codeBlock->numberOfIdentifiers()); 3598 m_constantRemap.resize(codeBlock->numberOfConstantRegisters());3599 3324 m_constantBufferRemap.resize(codeBlock->numberOfConstantBuffers()); 3600 3325 m_switchRemap.resize(codeBlock->numberOfSwitchJumpTables()); 3601 3326 for (size_t i = 0; i < codeBlock->numberOfIdentifiers(); ++i) 3602 3327 m_identifierRemap[i] = i; 3603 for (size_t i = 0; i < codeBlock->numberOfConstantRegisters(); ++i)3604 m_constantRemap[i] = i + FirstConstantRegisterIndex;3605 3328 for (size_t i = 0; i < codeBlock->numberOfConstantBuffers(); ++i) 3606 3329 m_constantBufferRemap[i] = i; … … 3610 3333 } 3611 3334 3612 for (size_t i = 0; i < m_constantRemap.size(); ++i)3613 ASSERT(m_constantRemap[i] >= static_cast<unsigned>(FirstConstantRegisterIndex));3614 3615 3335 byteCodeParser->m_inlineStackTop = this; 3616 3336 } … … 3618 3338 void ByteCodeParser::parseCodeBlock() 3619 3339 { 3340 prepareToParseBlock(); 3341 3620 3342 CodeBlock* codeBlock = m_inlineStackTop->m_codeBlock; 3621 3343
Note:
See TracChangeset
for help on using the changeset viewer.