Changeset 125637 in webkit
- Timestamp:
- Aug 14, 2012 7:48:35 PM (12 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 2 added
- 30 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/CMakeLists.txt
r124404 r125637 40 40 assembler/LinkBuffer.cpp 41 41 42 bytecode/ArrayProfile.cpp 42 43 bytecode/CallLinkInfo.cpp 43 44 bytecode/CallLinkStatus.cpp -
trunk/Source/JavaScriptCore/ChangeLog
r125541 r125637 1 2012-08-13 Filip Pizlo <fpizlo@apple.com> 2 3 Array checks should use the structure, not the class info 4 https://bugs.webkit.org/show_bug.cgi?id=93150 5 6 Reviewed by Mark Hahnenberg. 7 8 This changes all array checks used in array accesses (get, put, get length, 9 push, pop) to use the structure, not the class info. Additionally, these 10 checks in the LLInt and baseline JIT record the structure in an ArrayProfile, 11 so that the DFG can know exactly what structure to check for. 12 13 * CMakeLists.txt: 14 * GNUmakefile.list.am: 15 * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: 16 * JavaScriptCore.xcodeproj/project.pbxproj: 17 * Target.pri: 18 * bytecode/ArrayProfile.cpp: Added. 19 (JSC): 20 (JSC::ArrayProfile::computeUpdatedPrediction): 21 * bytecode/ArrayProfile.h: Added. 22 (JSC): 23 (JSC::arrayModeFromStructure): 24 (ArrayProfile): 25 (JSC::ArrayProfile::ArrayProfile): 26 (JSC::ArrayProfile::bytecodeOffset): 27 (JSC::ArrayProfile::addressOfLastSeenStructure): 28 (JSC::ArrayProfile::observeStructure): 29 (JSC::ArrayProfile::expectedStructure): 30 (JSC::ArrayProfile::structureIsPolymorphic): 31 (JSC::ArrayProfile::hasDefiniteStructure): 32 (JSC::ArrayProfile::observedArrayModes): 33 * bytecode/CodeBlock.cpp: 34 (JSC::CodeBlock::dump): 35 (JSC::CodeBlock::getArrayProfile): 36 (JSC): 37 (JSC::CodeBlock::getOrAddArrayProfile): 38 (JSC::CodeBlock::updateAllPredictionsAndCountLiveness): 39 * bytecode/CodeBlock.h: 40 (JSC::CodeBlock::executionEntryCount): 41 (JSC::CodeBlock::numberOfArrayProfiles): 42 (JSC::CodeBlock::arrayProfiles): 43 (JSC::CodeBlock::addArrayProfile): 44 (CodeBlock): 45 * bytecode/Instruction.h: 46 (JSC): 47 (JSC::Instruction::Instruction): 48 * bytecode/Opcode.h: 49 (JSC): 50 (JSC::padOpcodeName): 51 * bytecompiler/BytecodeGenerator.cpp: 52 (JSC::BytecodeGenerator::emitGetArgumentByVal): 53 (JSC::BytecodeGenerator::emitGetByVal): 54 (JSC::BytecodeGenerator::emitPutByVal): 55 * dfg/DFGAbstractState.cpp: 56 (JSC::DFG::AbstractState::initialize): 57 (JSC::DFG::AbstractState::execute): 58 * dfg/DFGAbstractValue.h: 59 (JSC::DFG::StructureAbstractValue::hasSingleton): 60 (StructureAbstractValue): 61 (JSC::DFG::StructureAbstractValue::singleton): 62 * dfg/DFGArgumentsSimplificationPhase.cpp: 63 (JSC::DFG::ArgumentsSimplificationPhase::run): 64 * dfg/DFGByteCodeParser.cpp: 65 (JSC::DFG::ByteCodeParser::parseBlock): 66 * dfg/DFGFixupPhase.cpp: 67 (JSC::DFG::FixupPhase::fixupNode): 68 * dfg/DFGSpeculativeJIT.cpp: 69 (JSC::DFG::SpeculativeJIT::speculateArray): 70 (DFG): 71 (JSC::DFG::SpeculativeJIT::compile): 72 (JSC::DFG::SpeculativeJIT::checkArgumentTypes): 73 (JSC::DFG::SpeculativeJIT::compileGetIndexedPropertyStorage): 74 * dfg/DFGSpeculativeJIT.h: 75 (SpeculativeJIT): 76 * dfg/DFGSpeculativeJIT32_64.cpp: 77 (JSC::DFG::SpeculativeJIT::compile): 78 * dfg/DFGSpeculativeJIT64.cpp: 79 (JSC::DFG::SpeculativeJIT::compile): 80 * dfg/DFGStructureCheckHoistingPhase.cpp: 81 (JSC::DFG::StructureCheckHoistingPhase::run): 82 * jit/JITPropertyAccess.cpp: 83 (JSC::JIT::emit_op_get_by_val): 84 (JSC::JIT::emit_op_put_by_val): 85 (JSC::JIT::privateCompilePatchGetArrayLength): 86 * jit/JITPropertyAccess32_64.cpp: 87 (JSC::JIT::emit_op_get_by_val): 88 (JSC::JIT::emit_op_put_by_val): 89 (JSC::JIT::privateCompilePatchGetArrayLength): 90 * llint/LLIntOffsetsExtractor.cpp: 91 * llint/LowLevelInterpreter32_64.asm: 92 * llint/LowLevelInterpreter64.asm: 93 * runtime/Structure.h: 94 (Structure): 95 (JSC::Structure::classInfoOffset): 96 1 97 2012-08-14 Gabor Ballabas <gaborb@inf.u-szeged.hu> 2 98 -
trunk/Source/JavaScriptCore/GNUmakefile.list.am
r124757 r125637 83 83 Source/JavaScriptCore/assembler/SH4Assembler.h \ 84 84 Source/JavaScriptCore/assembler/X86Assembler.h \ 85 Source/JavaScriptCore/bytecode/ArrayProfile.cpp \ 86 Source/JavaScriptCore/bytecode/ArrayProfile.h \ 85 87 Source/JavaScriptCore/bytecode/BytecodeConventions.h \ 86 88 Source/JavaScriptCore/bytecode/CallLinkInfo.cpp \ -
trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
r122544 r125637 1531 1531 > 1532 1532 <File 1533 RelativePath="..\..\bytecode\ArrayProfile.cpp" 1534 > 1535 </File> 1536 <File 1537 RelativePath="..\..\bytecode\ArrayProfile.h" 1538 > 1539 </File> 1540 <File 1533 1541 RelativePath="..\..\bytecode\CallLinkInfo.cpp" 1534 1542 > -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r124404 r125637 141 141 0F63943F15C75F19006A597C /* DFGStructureCheckHoistingPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F63943D15C75F14006A597C /* DFGStructureCheckHoistingPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; 142 142 0F63944015C75F1D006A597C /* DFGStructureCheckHoistingPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F63943C15C75F14006A597C /* DFGStructureCheckHoistingPhase.cpp */; }; 143 0F63945415D07055006A597C /* ArrayProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F63945115D07051006A597C /* ArrayProfile.cpp */; }; 144 0F63945515D07057006A597C /* ArrayProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F63945215D07051006A597C /* ArrayProfile.h */; settings = {ATTRIBUTES = (Private, ); }; }; 143 145 0F66E16B14DF3F1600B7B2E4 /* DFGAdjacencyList.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F66E16814DF3F1300B7B2E4 /* DFGAdjacencyList.h */; settings = {ATTRIBUTES = (Private, ); }; }; 144 146 0F66E16C14DF3F1600B7B2E4 /* DFGEdge.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F66E16914DF3F1300B7B2E4 /* DFGEdge.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 890 892 0F63943C15C75F14006A597C /* DFGStructureCheckHoistingPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStructureCheckHoistingPhase.cpp; path = dfg/DFGStructureCheckHoistingPhase.cpp; sourceTree = "<group>"; }; 891 893 0F63943D15C75F14006A597C /* DFGStructureCheckHoistingPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStructureCheckHoistingPhase.h; path = dfg/DFGStructureCheckHoistingPhase.h; sourceTree = "<group>"; }; 894 0F63945115D07051006A597C /* ArrayProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayProfile.cpp; sourceTree = "<group>"; }; 895 0F63945215D07051006A597C /* ArrayProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayProfile.h; sourceTree = "<group>"; }; 892 896 0F66E16814DF3F1300B7B2E4 /* DFGAdjacencyList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAdjacencyList.h; path = dfg/DFGAdjacencyList.h; sourceTree = "<group>"; }; 893 897 0F66E16914DF3F1300B7B2E4 /* DFGEdge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGEdge.h; path = dfg/DFGEdge.h; sourceTree = "<group>"; }; … … 2408 2412 isa = PBXGroup; 2409 2413 children = ( 2414 0F63945115D07051006A597C /* ArrayProfile.cpp */, 2415 0F63945215D07051006A597C /* ArrayProfile.h */, 2410 2416 0F56A1D415001CF2002992B1 /* ExecutionCounter.cpp */, 2411 2417 0F56A1D115000F31002992B1 /* ExecutionCounter.h */, … … 2868 2874 0F766D4615B3701F008F363E /* DFGScratchRegisterAllocator.h in Headers */, 2869 2875 0F63943F15C75F19006A597C /* DFGStructureCheckHoistingPhase.h in Headers */, 2876 0F63945515D07057006A597C /* ArrayProfile.h in Headers */, 2870 2877 ); 2871 2878 runOnlyForDeploymentPostprocessing = 0; … … 3466 3473 0F766D3815AE4A1C008F363E /* StructureStubClearingWatchpoint.cpp in Sources */, 3467 3474 0F63944015C75F1D006A597C /* DFGStructureCheckHoistingPhase.cpp in Sources */, 3475 0F63945415D07055006A597C /* ArrayProfile.cpp in Sources */, 3468 3476 ); 3469 3477 runOnlyForDeploymentPostprocessing = 0; -
trunk/Source/JavaScriptCore/Target.pri
r125452 r125637 47 47 assembler/MacroAssemblerARM.cpp \ 48 48 assembler/MacroAssemblerSH4.cpp \ 49 bytecode/ArrayProfile.cpp \ 49 50 bytecode/CallLinkInfo.cpp \ 50 51 bytecode/CallLinkStatus.cpp \ -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r124729 r125637 1156 1156 dumpBytecodeCommentAndNewLine(location); 1157 1157 it++; 1158 it++; 1158 1159 break; 1159 1160 } … … 1164 1165 dataLog("[%4d] get_argument_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); 1165 1166 dumpBytecodeCommentAndNewLine(location); 1167 ++it; 1166 1168 ++it; 1167 1169 break; … … 1184 1186 dataLog("[%4d] put_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); 1185 1187 dumpBytecodeCommentAndNewLine(location); 1188 ++it; 1186 1189 break; 1187 1190 } … … 2770 2773 2771 2774 #if ENABLE(VALUE_PROFILER) 2775 ArrayProfile* CodeBlock::getArrayProfile(unsigned bytecodeOffset) 2776 { 2777 for (unsigned i = 0; i < m_arrayProfiles.size(); ++i) { 2778 if (m_arrayProfiles[i].bytecodeOffset() == bytecodeOffset) 2779 return &m_arrayProfiles[i]; 2780 } 2781 return 0; 2782 } 2783 2784 ArrayProfile* CodeBlock::getOrAddArrayProfile(unsigned bytecodeOffset) 2785 { 2786 ArrayProfile* result = getArrayProfile(bytecodeOffset); 2787 if (result) 2788 return result; 2789 return addArrayProfile(bytecodeOffset); 2790 } 2791 2772 2792 void CodeBlock::updateAllPredictionsAndCountLiveness( 2773 2793 OperationInProgress operation, unsigned& numberOfLiveNonArgumentValueProfiles, unsigned& numberOfSamplesInProfiles) … … 2793 2813 m_lazyOperandValueProfiles.computeUpdatedPredictions(operation); 2794 2814 #endif 2815 2816 // Don't count the array profiles towards statistics, since each array profile 2817 // site also has a value profile site - so we already know whether or not it's 2818 // live. 2819 for (unsigned i = m_arrayProfiles.size(); i--;) 2820 m_arrayProfiles[i].computeUpdatedPrediction(operation); 2795 2821 } 2796 2822 -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.h
r123042 r125637 31 31 #define CodeBlock_h 32 32 33 #include "ArrayProfile.h" 33 34 #include "BytecodeConventions.h" 34 35 #include "CallLinkInfo.h" … … 752 753 753 754 unsigned executionEntryCount() const { return m_executionEntryCount; } 754 #endif 755 755 756 unsigned numberOfArrayProfiles() const { return m_arrayProfiles.size(); } 757 const ArrayProfileVector& arrayProfiles() { return m_arrayProfiles; } 758 ArrayProfile* addArrayProfile(unsigned bytecodeOffset) 759 { 760 m_arrayProfiles.append(ArrayProfile(bytecodeOffset)); 761 return &m_arrayProfiles.last(); 762 } 763 ArrayProfile* getArrayProfile(unsigned bytecodeOffset); 764 ArrayProfile* getOrAddArrayProfile(unsigned bytecodeOffset); 765 #endif 766 756 767 unsigned globalResolveInfoCount() const 757 768 { … … 1334 1345 SegmentedVector<RareCaseProfile, 8> m_rareCaseProfiles; 1335 1346 SegmentedVector<RareCaseProfile, 8> m_specialFastCaseProfiles; 1347 ArrayProfileVector m_arrayProfiles; 1336 1348 unsigned m_executionEntryCount; 1337 1349 #endif -
trunk/Source/JavaScriptCore/bytecode/Instruction.h
r122166 r125637 47 47 // solution for now - will need to something smarter if/when we actually want mixed-mode operation. 48 48 49 class ArrayProfile; 49 50 class JSCell; 50 51 class Structure; … … 191 192 192 193 Instruction(ValueProfile* profile) { u.profile = profile; } 194 Instruction(ArrayProfile* profile) { u.arrayProfile = profile; } 193 195 194 196 Instruction(WriteBarrier<Unknown>* registerPointer) { u.registerPointer = registerPointer; } … … 206 208 LLIntCallLinkInfo* callLinkInfo; 207 209 ValueProfile* profile; 210 ArrayProfile* arrayProfile; 208 211 void* pointer; 209 212 bool* predicatePointer; -
trunk/Source/JavaScriptCore/bytecode/Opcode.h
r124729 r125637 133 133 macro(op_put_by_id_generic, 9) \ 134 134 macro(op_del_by_id, 4) \ 135 macro(op_get_by_val, 5) /* has value profiling */ \136 macro(op_get_argument_by_val, 5) /* must be the same size as op_get_by_val */ \135 macro(op_get_by_val, 6) /* has value profiling */ \ 136 macro(op_get_argument_by_val, 6) /* must be the same size as op_get_by_val */ \ 137 137 macro(op_get_by_pname, 7) \ 138 macro(op_put_by_val, 4) \138 macro(op_put_by_val, 5) \ 139 139 macro(op_del_by_val, 4) \ 140 140 macro(op_put_by_index, 4) \ -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r124729 r125637 708 708 } 709 709 #endif 710 711 ArrayProfile* BytecodeGenerator::newArrayProfile() 712 { 713 #if ENABLE(VALUE_PROFILER) 714 return m_codeBlock->addArrayProfile(instructions().size()); 715 #else 716 return 0; 717 #endif 718 } 710 719 711 720 ValueProfile* BytecodeGenerator::emitProfiledOpcode(OpcodeID opcodeID) … … 1670 1679 RegisterID* BytecodeGenerator::emitGetArgumentByVal(RegisterID* dst, RegisterID* base, RegisterID* property) 1671 1680 { 1681 ArrayProfile* arrayProfile = newArrayProfile(); 1672 1682 ValueProfile* profile = emitProfiledOpcode(op_get_argument_by_val); 1673 1683 instructions().append(dst->index()); … … 1675 1685 instructions().append(base->index()); 1676 1686 instructions().append(property->index()); 1687 instructions().append(arrayProfile); 1677 1688 instructions().append(profile); 1678 1689 return dst; … … 1694 1705 } 1695 1706 } 1707 ArrayProfile* arrayProfile = newArrayProfile(); 1696 1708 ValueProfile* profile = emitProfiledOpcode(op_get_by_val); 1697 1709 instructions().append(dst->index()); 1698 1710 instructions().append(base->index()); 1699 1711 instructions().append(property->index()); 1712 instructions().append(arrayProfile); 1700 1713 instructions().append(profile); 1701 1714 return dst; … … 1704 1717 RegisterID* BytecodeGenerator::emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value) 1705 1718 { 1719 ArrayProfile* arrayProfile = newArrayProfile(); 1706 1720 emitOpcode(op_put_by_val); 1707 1721 instructions().append(base->index()); 1708 1722 instructions().append(property->index()); 1709 1723 instructions().append(value->index()); 1724 instructions().append(arrayProfile); 1710 1725 return value; 1711 1726 } -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r124729 r125637 556 556 557 557 void emitOpcode(OpcodeID); 558 ArrayProfile* newArrayProfile(); 558 559 ValueProfile* emitProfiledOpcode(OpcodeID); 559 560 void retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index); -
trunk/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
r124404 r125637 107 107 if (isInt32Speculation(prediction)) 108 108 root->valuesAtHead.argument(i).set(SpecInt32); 109 else if (isArraySpeculation(prediction))110 root->valuesAtHead.argument(i).set(SpecArray);111 109 else if (isBooleanSpeculation(prediction)) 112 110 root->valuesAtHead.argument(i).set(SpecBoolean); … … 291 289 if (isInt32Speculation(predictedType)) 292 290 speculateInt32Unary(node); 293 else if (isArraySpeculation(predictedType)) { 294 node.setCanExit(!isArraySpeculation(forNode(node.child1()).m_type)); 295 forNode(node.child1()).filter(SpecArray); 296 } else if (isCellSpeculation(predictedType)) { 291 else if (isCellSpeculation(predictedType)) { 297 292 node.setCanExit(!isCellSpeculation(forNode(node.child1()).m_type)); 298 293 forNode(node.child1()).filter(SpecCell); … … 868 863 break; 869 864 } 870 if (! isActionableArraySpeculation(m_graph[node.child1()].prediction()) || !m_graph[node.child2()].shouldSpeculateInteger()) {865 if (!m_graph[node.child2()].shouldSpeculateInteger() || (!node.child3() && !m_graph[node.child1()].shouldSpeculateArguments())) { 871 866 clobberWorld(node.codeOrigin, indexInBlock); 872 867 forNode(nodeIndex).makeTop(); … … 943 938 break; 944 939 } 945 ASSERT(m_graph[node.child1()].shouldSpeculateArray()); 946 forNode(node.child1()).filter(SpecArray); 940 forNode(node.child1()).filter(SpecCell); 947 941 forNode(node.child2()).filter(SpecInt32); 948 942 forNode(nodeIndex).makeTop(); … … 1054 1048 break; 1055 1049 } 1056 ASSERT(m_graph[child1].shouldSpeculateArray()); 1057 forNode(child1).filter(SpecArray); 1050 forNode(child1).filter(SpecCell); 1058 1051 forNode(child2).filter(SpecInt32); 1059 1052 if (node.op() == PutByValSafe) … … 1064 1057 case ArrayPush: 1065 1058 node.setCanExit(true); 1066 forNode(node.child1()).filter(Spec Array);1059 forNode(node.child1()).filter(SpecCell); 1067 1060 forNode(nodeIndex).set(SpecNumber); 1068 1061 break; … … 1070 1063 case ArrayPop: 1071 1064 node.setCanExit(true); 1072 forNode(node.child1()).filter(Spec Array);1065 forNode(node.child1()).filter(SpecCell); 1073 1066 forNode(nodeIndex).makeTop(); 1074 1067 break; … … 1355 1348 case GetArrayLength: 1356 1349 node.setCanExit(true); 1357 forNode(node.child1()).filter(Spec Array);1350 forNode(node.child1()).filter(SpecCell); 1358 1351 forNode(nodeIndex).set(SpecInt32); 1359 1352 break; … … 1454 1447 break; 1455 1448 case GetIndexedPropertyStorage: { 1449 ASSERT(m_graph[node.child1()].prediction()); 1450 ASSERT(m_graph[node.child2()].shouldSpeculateInteger()); 1456 1451 node.setCanExit(true); // Lies, but this is (almost) always followed by GetByVal, which does exit. So no point in trying to be more precise. 1457 SpeculatedType basePrediction = m_graph[node.child2()].prediction();1458 if (!(basePrediction & SpecInt32) && basePrediction) {1459 forNode(nodeIndex).clear();1460 break;1461 }1462 1452 if (m_graph[node.child1()].shouldSpeculateArguments()) { 1463 1453 ASSERT_NOT_REACHED(); … … 1515 1505 break; 1516 1506 } 1517 forNode(node.child1()).filter(Spec Array);1507 forNode(node.child1()).filter(SpecCell); 1518 1508 forNode(nodeIndex).clear(); 1519 1509 break; -
trunk/Source/JavaScriptCore/dfg/DFGAbstractValue.h
r124404 r125637 283 283 } 284 284 285 bool hasSingleton() const 286 { 287 return isNeitherClearNorTop(); 288 } 289 290 Structure* singleton() const 291 { 292 ASSERT(isNeitherClearNorTop()); 293 return m_structure; 294 } 295 285 296 bool operator==(const StructureAbstractValue& other) const 286 297 { -
trunk/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp
r121717 r125637 318 318 break; 319 319 320 case CheckStructure: 321 case StructureTransitionWatchpoint: 322 // We don't care about these because if we get uses of the relevant 323 // variable then we can safely get rid of these, too. This of course 324 // relies on there not being any information transferred by the CFA 325 // from a CheckStructure on one variable to the information about the 326 // structures of another variable. 327 break; 328 320 329 default: 321 330 observeBadArgumentsUses(node); … … 472 481 } 473 482 483 case CheckStructure: 484 case StructureTransitionWatchpoint: { 485 // We can just get rid of this node, if it references a phantom argument. 486 if (!isOKToOptimize(m_graph[node.child1()])) 487 break; 488 m_graph.deref(node.child1()); 489 node.setOpAndDefaultFlags(Phantom); 490 node.children.setChild1(Edge()); 491 break; 492 } 493 474 494 case GetByVal: { 475 495 if (!node.prediction() -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r124667 r125637 2150 2150 NodeIndex base = get(currentInstruction[2].u.operand); 2151 2151 NodeIndex property = get(currentInstruction[3].u.operand); 2152 ArrayProfile* profile = currentInstruction[4].u.arrayProfile; 2153 profile->computeUpdatedPrediction(); 2154 if (profile->hasDefiniteStructure()) 2155 addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(profile->expectedStructure())), base); 2152 2156 NodeIndex propertyStorage = addToGraph(GetIndexedPropertyStorage, base, property); 2153 2157 NodeIndex getByVal = addToGraph(GetByVal, OpInfo(0), OpInfo(prediction), base, property, propertyStorage); … … 2161 2165 NodeIndex property = get(currentInstruction[2].u.operand); 2162 2166 NodeIndex value = get(currentInstruction[3].u.operand); 2167 2168 ArrayProfile* profile = currentInstruction[4].u.arrayProfile; 2169 profile->computeUpdatedPrediction(); 2170 if (profile->hasDefiniteStructure()) 2171 addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(profile->expectedStructure())), base); 2172 2173 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) 2174 dataLog("Slow case profile for bc#%u: %u\n", m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter); 2175 #endif 2163 2176 2164 2177 bool makeSafe = -
trunk/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp
r122541 r125637 614 614 ASSERT(node.shouldGenerate()); 615 615 Node& possibleLocalOp = m_graph[node.child1()]; 616 if (possibleLocalOp.hasLocal() && !possibleLocalOp.variableAccessData()->isCaptured()) { 616 if (possibleLocalOp.op() != GetLocal 617 && possibleLocalOp.hasLocal() 618 && !possibleLocalOp.variableAccessData()->isCaptured()) { 617 619 NodeIndex setLocalIndex = 618 620 firstBlock->variablesAtTail.operand(possibleLocalOp.local()); -
trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
r122541 r125637 104 104 105 105 m_state.execute(indexInBlock); 106 if (!node.shouldGenerate() 107 || m_state.didClobber() 108 || node.hasConstant()) 106 if (!node.shouldGenerate() || m_state.didClobber() || node.hasConstant()) 109 107 continue; 110 108 JSValue value = m_state.forNode(nodeIndex).value(); -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r124398 r125637 97 97 dataLog(" @%u -> %s", m_compileIndex, isArray ? "GetArrayLength" : "GetStringLength"); 98 98 #endif 99 if (isArray) 99 if (isArray) { 100 100 node.setOp(GetArrayLength); 101 else if (isArguments) 101 ASSERT(node.flags() & NodeMustGenerate); 102 node.clearFlags(NodeMustGenerate); 103 m_graph.deref(m_compileIndex); 104 105 ArrayProfile* arrayProfile = 106 m_graph.baselineCodeBlockFor(node.codeOrigin)->getArrayProfile( 107 node.codeOrigin.bytecodeIndex); 108 if (!arrayProfile) 109 break; 110 arrayProfile->computeUpdatedPrediction(); 111 if (!arrayProfile->hasDefiniteStructure()) 112 break; 113 m_graph.ref(node.child1()); 114 Node checkStructure(CheckStructure, node.codeOrigin, OpInfo(m_graph.addStructureSet(arrayProfile->expectedStructure())), node.child1().index()); 115 checkStructure.ref(); 116 NodeIndex checkStructureIndex = m_graph.size(); 117 m_graph.append(checkStructure); 118 m_insertionSet.append(m_indexInBlock, checkStructureIndex); 119 break; 120 } 121 if (isArguments) 102 122 node.setOp(GetArgumentsLength); 103 123 else if (isString) … … 130 150 } 131 151 case GetIndexedPropertyStorage: { 132 SpeculatedType basePrediction = m_graph[node.child2()].prediction(); 133 if ((!(basePrediction & SpecInt32) && basePrediction) 134 || m_graph[node.child1()].shouldSpeculateArguments() 135 || !isActionableArraySpeculation(m_graph[node.child1()].prediction())) { 152 if (!m_graph[node.child1()].prediction() 153 || !m_graph[node.child2()].shouldSpeculateInteger() 154 || m_graph[node.child1()].shouldSpeculateArguments()) { 136 155 node.setOpAndDefaultFlags(Nop); 137 156 m_graph.clearAndDerefChild1(node); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r124476 r125637 156 156 157 157 Node* nextNode = &at(m_jit.graph().m_blocks[m_block]->at(setLocalIndexInBlock + 1)); 158 if (nextNode->op() == Jump && nextNode->codeOrigin == at(m_compileIndex).codeOrigin) { 159 // We're at an inlined return. Use a backward speculation instead. 160 return; 161 } 158 162 ASSERT(nextNode->codeOrigin != at(m_compileIndex).codeOrigin); 159 163 … … 245 249 m_gprs = RegisterBank<GPRInfo>(); 246 250 m_fprs = RegisterBank<FPRInfo>(); 251 } 252 253 void SpeculativeJIT::speculateArray(Edge edge, GPRReg baseReg) 254 { 255 AbstractValue& arrayValue = m_state.forNode(edge); 256 if (arrayValue.m_structure.hasSingleton() 257 && arrayValue.m_structure.singleton()->classInfo() == &JSArray::s_info) 258 return; 259 260 GPRTemporary temp(this); 261 m_jit.loadPtr( 262 MacroAssembler::Address(baseReg, JSCell::structureOffset()), temp.gpr()); 263 speculationCheck( 264 Uncountable, JSValueRegs(), NoNode, 265 m_jit.branchPtr( 266 MacroAssembler::NotEqual, 267 MacroAssembler::Address(temp.gpr(), Structure::classInfoOffset()), 268 MacroAssembler::TrustedImmPtr(&JSArray::s_info))); 247 269 } 248 270 … … 1221 1243 else if (isInt32Speculation(argumentPosition.prediction())) 1222 1244 valueSource = ValueSource(Int32InRegisterFile); 1223 else if (is ArraySpeculation(argumentPosition.prediction()) || isCellSpeculation(argumentPosition.prediction()))1245 else if (isCellSpeculation(argumentPosition.prediction())) 1224 1246 valueSource = ValueSource(CellInRegisterFile); 1225 1247 else if (isBooleanSpeculation(argumentPosition.prediction())) … … 1344 1366 if (isInt32Speculation(predictedType)) 1345 1367 speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), GPRInfo::tagTypeNumberRegister)); 1346 else if (isArraySpeculation(predictedType)) { 1347 GPRTemporary temp(this); 1348 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr()); 1349 speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister)); 1350 speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info))); 1351 } else if (isBooleanSpeculation(predictedType)) { 1368 else if (isBooleanSpeculation(predictedType)) { 1352 1369 GPRTemporary temp(this); 1353 1370 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr()); … … 1404 1421 if (isInt32Speculation(predictedType)) 1405 1422 speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag))); 1406 else if (isArraySpeculation(predictedType)) { 1407 GPRTemporary temp(this); 1408 m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr()); 1409 speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag))); 1410 m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr()); 1411 speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info))); 1412 } else if (isBooleanSpeculation(predictedType)) 1423 else if (isBooleanSpeculation(predictedType)) 1413 1424 speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag))); 1414 1425 else if (isInt8ArraySpeculation(predictedType)) { … … 1592 1603 1593 1604 if (!isStringSpeculation(m_state.forNode(node.child1()).m_type)) { 1594 ASSERT(!(at(node.child1()).prediction() & SpecString));1595 1605 terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); 1596 1606 noResult(m_compileIndex); … … 3038 3048 void SpeculativeJIT::compileGetIndexedPropertyStorage(Node& node) 3039 3049 { 3040 if (!node.prediction() || !at(node.child1()).prediction() || !at(node.child2()).prediction()) { 3041 terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode); 3042 return; 3043 } 3050 ASSERT(at(node.child1()).prediction()); 3051 ASSERT(at(node.child2()).shouldSpeculateInteger()); 3044 3052 3045 3053 SpeculateCellOperand base(this, node.child1()); 3046 3054 GPRReg baseReg = base.gpr(); 3047 3048 SpeculatedType basePrediction = at(node.child2()).prediction();3049 if (!(basePrediction & SpecInt32) && basePrediction) {3050 ASSERT_NOT_REACHED();3051 terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);3052 noResult(m_compileIndex);3053 return;3054 }3055 3055 3056 3056 GPRTemporary storage(this); … … 3114 3114 m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg); 3115 3115 } else { 3116 if (!isArraySpeculation(m_state.forNode(node.child1()).m_type)) 3117 speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info))); 3116 speculateArray(node.child1(), baseReg); 3118 3117 m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg); 3119 3118 } -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r124422 r125637 2192 2192 void terminateSpeculativeExecutionWithConditionalDirection(ExitKind, JSValueRegs, NodeIndex, bool isForward); 2193 2193 2194 void speculateArray(Edge baseEdge, GPRReg baseReg); 2195 2194 2196 template<bool strict> 2195 2197 GPRReg fillSpeculateIntInternal(NodeIndex, DataFormat& returnFormat); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r124476 r125637 1919 1919 } 1920 1920 1921 if (is ArraySpeculation(value.m_type) || isCellSpeculation(value.m_type)) {1921 if (isCellSpeculation(value.m_type)) { 1922 1922 GPRTemporary result(this); 1923 1923 m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr()); … … 2037 2037 break; 2038 2038 } 2039 if (isArraySpeculation(predictedType)) {2040 SpeculateCellOperand cell(this, node.child1());2041 GPRReg cellGPR = cell.gpr();2042 if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))2043 speculationCheck(BadType, JSValueSource::unboxedCell(cellGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));2044 m_jit.storePtr(cellGPR, JITCompiler::payloadFor(node.local()));2045 noResult(m_compileIndex);2046 recordSetLocal(node.local(), ValueSource(CellInRegisterFile));2047 break;2048 }2049 2039 if (isCellSpeculation(predictedType)) { 2050 2040 SpeculateCellOperand cell(this, node.child1()); … … 2357 2347 } 2358 2348 2359 if (!at(node.child2()).shouldSpeculateInteger() || !isActionableArraySpeculation(at(node.child1()).prediction())) {2349 if (!at(node.child2()).shouldSpeculateInteger() || (!node.child3() && !at(node.child1()).shouldSpeculateArguments())) { 2360 2350 SpeculateCellOperand base(this, node.child1()); // Save a register, speculate cell. We'll probably be right. 2361 2351 JSValueOperand property(this, node.child2()); … … 2450 2440 } 2451 2441 2452 ASSERT(at(node.child1()).shouldSpeculateArray());2453 2454 2442 SpeculateStrictInt32Operand property(this, node.child2()); 2455 2443 StorageOperand storage(this, node.child3()); … … 2465 2453 SpeculateCellOperand base(this, node.child1()); 2466 2454 GPRReg baseReg = base.gpr(); 2467 if (!isArraySpeculation(m_state.forNode(node.child1()).m_type)) 2468 speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info))); 2455 // We've already speculated that it's some kind of array, at this point. 2469 2456 speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset()))); 2470 2457 } … … 2473 2460 GPRTemporary resultPayload(this); 2474 2461 2475 // FIXME: In cases where there are subsequent by_val accesses to the same base it might help to cache2476 // the storage pointer - especially if there happens to be another register free right now. If we do so,2477 // then we'll need to allocate a new temporary for result.2478 2462 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag.gpr()); 2479 2463 speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::Equal, resultTag.gpr(), TrustedImm32(JSValue::EmptyValueTag))); … … 2496 2480 2497 2481 if (!at(child2).shouldSpeculateInteger() 2498 || !isActionableMutableArraySpeculation(at(child1).prediction())2499 2482 || at(child1).shouldSpeculateArguments()) { 2500 2483 SpeculateCellOperand base(this, child1); // Save a register, speculate cell. We'll probably be right. … … 2579 2562 } 2580 2563 2581 ASSERT(at(child1).shouldSpeculateArray());2582 2583 2564 JSValueOperand value(this, child3); 2584 GPRTemporary scratch(this);2585 2586 2565 // Map base, property & value into registers, allocate a scratch register. 2587 2566 GPRReg baseReg = base.gpr(); … … 2589 2568 GPRReg valueTagReg = value.tagGPR(); 2590 2569 GPRReg valuePayloadReg = value.payloadGPR(); 2591 GPRReg scratchReg = scratch.gpr();2592 2570 2593 2571 if (!m_compileOkay) 2594 2572 return; 2595 2596 writeBarrier(baseReg, valueTagReg, child3, WriteBarrierForPropertyAccess, scratchReg); 2597 2598 // Check that base is an array, and that property is contained within m_vector (< m_vectorLength). 2599 // If we have predicted the base to be type array, we can skip the check. 2600 if (!isArraySpeculation(m_state.forNode(child1).m_type)) 2601 speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), child1, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info))); 2573 2574 { 2575 GPRTemporary scratch(this); 2576 GPRReg scratchReg = scratch.gpr(); 2577 writeBarrier(baseReg, valueTagReg, child3, WriteBarrierForPropertyAccess, scratchReg); 2578 } 2579 2580 speculateArray(child1, baseReg); 2602 2581 2603 2582 MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())); … … 2610 2589 2611 2590 // Get the array storage. 2612 GPRReg storageReg = scratchReg; 2591 GPRTemporary storage(this); 2592 GPRReg storageReg = storage.gpr(); 2613 2593 m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg); 2614 2594 … … 2796 2776 SpeculateCellOperand base(this, node.child1()); 2797 2777 JSValueOperand value(this, node.child2()); 2798 GPRTemporary storage(this);2799 2778 GPRTemporary storageLength(this); 2800 2779 … … 2802 2781 GPRReg valueTagGPR = value.tagGPR(); 2803 2782 GPRReg valuePayloadGPR = value.payloadGPR(); 2783 GPRReg storageLengthGPR = storageLength.gpr(); 2784 2785 { 2786 GPRTemporary scratch(this); 2787 writeBarrier(baseGPR, valueTagGPR, node.child2(), WriteBarrierForPropertyAccess, scratch.gpr(), storageLengthGPR); 2788 } 2789 2790 speculateArray(node.child1(), baseGPR); 2791 2792 GPRTemporary storage(this); 2804 2793 GPRReg storageGPR = storage.gpr(); 2805 GPRReg storageLengthGPR = storageLength.gpr(); 2806 2807 writeBarrier(baseGPR, valueTagGPR, node.child2(), WriteBarrierForPropertyAccess, storageGPR, storageLengthGPR); 2808 2809 if (!isArraySpeculation(m_state.forNode(node.child1()).m_type)) 2810 speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info))); 2811 2794 2812 2795 m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR); 2813 2796 m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR); … … 2845 2828 GPRReg storageLengthGPR = storageLength.gpr(); 2846 2829 2847 if (!isArraySpeculation(m_state.forNode(node.child1()).m_type)) 2848 speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info))); 2830 speculateArray(node.child1(), baseGPR); 2849 2831 2850 2832 m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR); … … 3396 3378 GPRReg baseGPR = base.gpr(); 3397 3379 3398 if (!isArraySpeculation(m_state.forNode(node.child1()).m_type)) 3399 speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info))); 3380 speculateArray(node.child1(), baseGPR); 3400 3381 3401 3382 GPRTemporary result(this); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r124555 r125637 2073 2073 break; 2074 2074 } 2075 if (isArraySpeculation(predictedType)) {2076 SpeculateCellOperand cell(this, node.child1());2077 GPRReg cellGPR = cell.gpr();2078 if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))2079 speculationCheck(BadType, JSValueRegs(cellGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));2080 m_jit.storePtr(cellGPR, JITCompiler::addressFor(node.local()));2081 noResult(m_compileIndex);2082 recordSetLocal(node.local(), ValueSource(CellInRegisterFile));2083 break;2084 }2085 2075 if (isCellSpeculation(predictedType)) { 2086 2076 SpeculateCellOperand cell(this, node.child1()); … … 2390 2380 } 2391 2381 2392 if (!at(node.child2()).shouldSpeculateInteger() || !isActionableArraySpeculation(at(node.child1()).prediction())) {2382 if (!at(node.child2()).shouldSpeculateInteger() || (!node.child3() && !at(node.child1()).shouldSpeculateArguments())) { 2393 2383 JSValueOperand base(this, node.child1()); 2394 2384 JSValueOperand property(this, node.child2()); … … 2481 2471 } 2482 2472 2483 ASSERT(at(node.child1()).shouldSpeculateArray());2484 2485 2473 SpeculateCellOperand base(this, node.child1()); 2486 2474 SpeculateStrictInt32Operand property(this, node.child2()); … … 2494 2482 return; 2495 2483 2496 if (!isArraySpeculation(m_state.forNode(node.child1()).m_type)) 2497 speculationCheck(BadType, JSValueRegs(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info))); 2484 // We will have already speculated that the base is some kind of array, 2485 // at this point. 2486 2498 2487 speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset()))); 2499 2488 2500 // FIXME: In cases where there are subsequent by_val accesses to the same base it might help to cache2501 // the storage pointer - especially if there happens to be another register free right now. If we do so,2502 // then we'll need to allocate a new temporary for result.2503 2489 GPRTemporary result(this); 2504 2490 m_jit.loadPtr(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), result.gpr()); … … 2520 2506 } 2521 2507 2522 if (!at(child2).shouldSpeculateInteger() || !isActionableMutableArraySpeculation(at(child1).prediction())) {2508 if (!at(child2).shouldSpeculateInteger()) { 2523 2509 JSValueOperand arg1(this, child1); 2524 2510 JSValueOperand arg2(this, child2); … … 2538 2524 SpeculateStrictInt32Operand property(this, child2); 2539 2525 if (at(child1).shouldSpeculateArguments()) { 2526 dataLog(" in here "); 2540 2527 JSValueOperand value(this, child3); 2541 SpeculateCellOperand base(this, child1);2542 SpeculateStrictInt32Operand property(this, child2);2543 2528 GPRTemporary scratch(this); 2544 2529 GPRTemporary scratch2(this); … … 2657 2642 } 2658 2643 2659 ASSERT(at(child1).shouldSpeculateArray());2660 2661 2644 JSValueOperand value(this, child3); 2662 2645 GPRTemporary scratch(this); … … 2673 2656 writeBarrier(baseReg, value.gpr(), child3, WriteBarrierForPropertyAccess, scratchReg); 2674 2657 2675 // Check that base is an array, and that property is contained within m_vector (< m_vectorLength). 2676 // If we have predicted the base to be type array, we can skip the check. 2677 if (!isArraySpeculation(m_state.forNode(child1).m_type)) 2678 speculationCheck(BadType, JSValueRegs(baseReg), child1, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info))); 2679 2658 speculateArray(child1, baseReg); 2659 2680 2660 MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())); 2681 2661 if (node.op() == PutByVal) … … 2880 2860 writeBarrier(baseGPR, valueGPR, node.child2(), WriteBarrierForPropertyAccess, storageGPR, storageLengthGPR); 2881 2861 2882 if (!isArraySpeculation(m_state.forNode(node.child1()).m_type)) 2883 speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info))); 2884 2862 speculateArray(node.child1(), baseGPR); 2863 2885 2864 m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR); 2886 2865 m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR); … … 2918 2897 GPRReg storageLengthGPR = storageLength.gpr(); 2919 2898 2920 if (!isArraySpeculation(m_state.forNode(node.child1()).m_type)) 2921 speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info))); 2922 2899 speculateArray(node.child1(), baseGPR); 2900 2923 2901 m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR); 2924 2902 m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR); … … 3416 3394 GPRReg resultGPR = result.gpr(); 3417 3395 3418 if (!isArraySpeculation(m_state.forNode(node.child1()).m_type)) 3419 speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info))); 3420 3396 speculateArray(node.child1(), baseGPR); 3397 3421 3398 m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), resultGPR); 3422 3399 m_jit.load32(MacroAssembler::Address(resultGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), resultGPR); -
trunk/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp
r124655 r125637 95 95 case ReallocatePropertyStorage: 96 96 case GetPropertyStorage: 97 case GetByVal: 98 case PutByVal: 99 case PutByValAlias: 100 case GetArrayLength: 101 case Phantom: 97 102 // Don't count these uses. 98 103 break; -
trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp
r124476 r125637 111 111 112 112 emitJumpSlowCaseIfNotJSCell(regT0, base); 113 addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info))); 113 loadPtr(Address(regT0, JSCell::structureOffset()), regT2); 114 storePtr(regT2, currentInstruction[4].u.arrayProfile->addressOfLastSeenStructure()); 115 addSlowCase(branchPtr(NotEqual, Address(regT2, Structure::classInfoOffset()), TrustedImmPtr(&JSArray::s_info))); 114 116 115 117 loadPtr(Address(regT0, JSArray::storageOffset()), regT2); … … 232 234 zeroExtend32ToPtr(regT1, regT1); 233 235 emitJumpSlowCaseIfNotJSCell(regT0, base); 234 addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info))); 236 loadPtr(Address(regT0, JSCell::structureOffset()), regT2); 237 storePtr(regT2, currentInstruction[4].u.arrayProfile->addressOfLastSeenStructure()); 238 addSlowCase(branchPtr(NotEqual, Address(regT2, Structure::classInfoOffset()), TrustedImmPtr(&JSArray::s_info))); 235 239 addSlowCase(branch32(AboveOrEqual, regT1, Address(regT0, JSArray::vectorLengthOffset()))); 236 240 … … 646 650 647 651 // Check eax is an array 648 Jump failureCases1 = branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info)); 652 loadPtr(Address(regT0, JSCell::structureOffset()), regT3); 653 storePtr(regT3, m_codeBlock->getOrAddArrayProfile(stubInfo->bytecodeIndex)->addressOfLastSeenStructure()); 654 Jump failureCases1 = branchPtr(NotEqual, Address(regT3, Structure::classInfoOffset()), TrustedImmPtr(&JSArray::s_info)); 649 655 650 656 // Checks out okay! - get the length from the storage -
trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
r124476 r125637 210 210 addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); 211 211 emitJumpSlowCaseIfNotJSCell(base, regT1); 212 addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info))); 212 loadPtr(Address(regT0, JSCell::structureOffset()), regT1); 213 storePtr(regT1, currentInstruction[4].u.arrayProfile->addressOfLastSeenStructure()); 214 addSlowCase(branchPtr(NotEqual, Address(regT1, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info))); 213 215 214 216 loadPtr(Address(regT0, JSArray::storageOffset()), regT3); … … 265 267 addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); 266 268 emitJumpSlowCaseIfNotJSCell(base, regT1); 267 addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info))); 269 loadPtr(Address(regT0, JSCell::structureOffset()), regT1); 270 storePtr(regT1, currentInstruction[4].u.arrayProfile->addressOfLastSeenStructure()); 271 addSlowCase(branchPtr(NotEqual, Address(regT1, Structure::classInfoOffset()), TrustedImmPtr(&JSArray::s_info))); 268 272 addSlowCase(branch32(AboveOrEqual, regT2, Address(regT0, JSArray::vectorLengthOffset()))); 269 273 … … 609 613 610 614 // Check for array 611 Jump failureCases1 = branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info)); 615 loadPtr(Address(regT0, JSCell::structureOffset()), regT2); 616 storePtr(regT2, m_codeBlock->getOrAddArrayProfile(stubInfo->bytecodeIndex)->addressOfLastSeenStructure()); 617 Jump failureCases1 = branchPtr(NotEqual, Address(regT2, Structure::classInfoOffset()), TrustedImmPtr(&JSArray::s_info)); 612 618 613 619 // Checks out okay! - get the length from the storage -
trunk/Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp
r109678 r125637 26 26 #include "config.h" 27 27 28 #include "ArrayProfile.h" 28 29 #include "CodeBlock.h" 29 30 #include "Executable.h" -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
r123417 r125637 1256 1256 _llint_op_get_by_val: 1257 1257 traceExecution() 1258 loadp CodeBlock[cfr], t11259 1258 loadi 8[PC], t2 1260 1259 loadi 12[PC], t3 1261 loadp CodeBlock::m_globalData[t1], t11262 1260 loadConstantOrVariablePayload(t2, CellTag, t0, .opGetByValSlow) 1263 loadp JSGlobalData::jsArrayClassInfo[t1], t21264 1261 loadConstantOrVariablePayload(t3, Int32Tag, t1, .opGetByValSlow) 1265 bpneq [t0], t2, .opGetByValSlow 1262 loadp JSCell::m_structure[t0], t3 1263 loadp 16[PC], t2 1264 storep t3, ArrayProfile::m_lastSeenStructure[t2] 1265 loadp CodeBlock[cfr], t2 1266 loadp CodeBlock::m_globalData[t2], t2 1267 loadp JSGlobalData::jsArrayClassInfo[t2], t2 1268 bpneq Structure::m_classInfo[t3], t2, .opGetByValSlow 1266 1269 loadp JSArray::m_storage[t0], t3 1267 1270 biaeq t1, JSArray::m_vectorLength[t0], .opGetByValSlow … … 1272 1275 storei t2, TagOffset[cfr, t0, 8] 1273 1276 storei t1, PayloadOffset[cfr, t0, 8] 1274 loadi 16[PC], t01277 loadi 20[PC], t0 1275 1278 valueProfile(t2, t1, t0) 1276 dispatch( 5)1279 dispatch(6) 1277 1280 1278 1281 .opGetByValSlow: 1279 1282 callSlowPath(_llint_slow_path_get_by_val) 1280 dispatch( 5)1283 dispatch(6) 1281 1284 1282 1285 1283 1286 _llint_op_get_argument_by_val: 1287 # FIXME: At some point we should array profile this. Right now it isn't necessary 1288 # since the DFG will never turn a get_argument_by_val into a GetByVal. 1284 1289 traceExecution() 1285 1290 loadi 8[PC], t0 … … 1294 1299 loadi ThisArgumentOffset + TagOffset[cfr, t2, 8], t0 1295 1300 loadi ThisArgumentOffset + PayloadOffset[cfr, t2, 8], t1 1296 loadi 16[PC], t21301 loadi 20[PC], t2 1297 1302 storei t0, TagOffset[cfr, t3, 8] 1298 1303 storei t1, PayloadOffset[cfr, t3, 8] 1299 1304 valueProfile(t0, t1, t2) 1300 dispatch( 5)1305 dispatch(6) 1301 1306 1302 1307 .opGetArgumentByValSlow: 1303 1308 callSlowPath(_llint_slow_path_get_argument_by_val) 1304 dispatch( 5)1309 dispatch(6) 1305 1310 1306 1311 … … 1339 1344 loadi 8[PC], t0 1340 1345 loadConstantOrVariablePayload(t0, Int32Tag, t2, .opPutByValSlow) 1346 loadp JSCell::m_structure[t1], t3 1347 loadp 16[PC], t0 1348 storep t3, ArrayProfile::m_lastSeenStructure[t0] 1341 1349 loadp CodeBlock[cfr], t0 1342 1350 loadp CodeBlock::m_globalData[t0], t0 1343 1351 loadp JSGlobalData::jsArrayClassInfo[t0], t0 1344 bpneq [t1], t0, .opPutByValSlow1352 bpneq Structure::m_classInfo[t3], t0, .opPutByValSlow 1345 1353 biaeq t2, JSArray::m_vectorLength[t1], .opPutByValSlow 1346 1354 loadp JSArray::m_storage[t1], t0 … … 1352 1360 storei t1, ArrayStorage::m_vector + TagOffset[t0, t2, 8] 1353 1361 storei t3, ArrayStorage::m_vector + PayloadOffset[t0, t2, 8] 1354 dispatch( 4)1362 dispatch(5) 1355 1363 1356 1364 .opPutByValEmpty: … … 1363 1371 .opPutByValSlow: 1364 1372 callSlowPath(_llint_slow_path_put_by_val) 1365 dispatch( 4)1373 dispatch(5) 1366 1374 1367 1375 -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
r123417 r125637 1100 1100 _llint_op_get_by_val: 1101 1101 traceExecution() 1102 loadp CodeBlock[cfr], t11103 1102 loadis 16[PB, PC, 8], t2 1104 1103 loadis 24[PB, PC, 8], t3 1105 loadp CodeBlock::m_globalData[t1], t11106 1104 loadConstantOrVariableCell(t2, t0, .opGetByValSlow) 1107 loadp JSGlobalData::jsArrayClassInfo[t1], t21108 1105 loadConstantOrVariableInt32(t3, t1, .opGetByValSlow) 1109 1106 sxi2p t1, t1 1110 bpneq [t0], t2, .opGetByValSlow 1107 loadp JSCell::m_structure[t0], t3 1108 loadp 32[PB, PC, 8], t2 1109 storep t3, ArrayProfile::m_lastSeenStructure[t2] 1110 loadp CodeBlock[cfr], t2 1111 loadp CodeBlock::m_globalData[t2], t2 1112 loadp JSGlobalData::jsArrayClassInfo[t2], t2 1113 bpneq Structure::m_classInfo[t3], t2, .opGetByValSlow 1111 1114 loadp JSArray::m_storage[t0], t3 1112 1115 biaeq t1, JSArray::m_vectorLength[t0], .opGetByValSlow … … 1115 1118 btpz t2, .opGetByValSlow 1116 1119 storep t2, [cfr, t0, 8] 1117 loadp 32[PB, PC, 8], t01120 loadp 40[PB, PC, 8], t0 1118 1121 valueProfile(t2, t0) 1119 dispatch( 5)1122 dispatch(6) 1120 1123 1121 1124 .opGetByValSlow: 1122 1125 callSlowPath(_llint_slow_path_get_by_val) 1123 dispatch( 5)1126 dispatch(6) 1124 1127 1125 1128 1126 1129 _llint_op_get_argument_by_val: 1130 # FIXME: At some point we should array profile this. Right now it isn't necessary 1131 # since the DFG will never turn a get_argument_by_val into a GetByVal. 1127 1132 traceExecution() 1128 1133 loadis 16[PB, PC, 8], t0 … … 1140 1145 storep t0, [cfr, t3, 8] 1141 1146 valueProfile(t0, t1) 1142 dispatch( 5)1147 dispatch(6) 1143 1148 1144 1149 .opGetArgumentByValSlow: 1145 1150 callSlowPath(_llint_slow_path_get_argument_by_val) 1146 dispatch( 5)1151 dispatch(6) 1147 1152 1148 1153 … … 1183 1188 loadConstantOrVariableInt32(t0, t2, .opPutByValSlow) 1184 1189 sxi2p t2, t2 1190 loadp JSCell::m_structure[t1], t3 1191 loadp 32[PB, PC, 8], t0 1192 storep t3, ArrayProfile::m_lastSeenStructure[t0] 1185 1193 loadp CodeBlock[cfr], t0 1186 1194 loadp CodeBlock::m_globalData[t0], t0 1187 1195 loadp JSGlobalData::jsArrayClassInfo[t0], t0 1188 bpneq [t1], t0, .opPutByValSlow1196 bpneq Structure::m_classInfo[t3], t0, .opPutByValSlow 1189 1197 biaeq t2, JSArray::m_vectorLength[t1], .opPutByValSlow 1190 1198 loadp JSArray::m_storage[t1], t0 … … 1195 1203 writeBarrier(t1) 1196 1204 storep t1, ArrayStorage::m_vector[t0, t2, 8] 1197 dispatch( 4)1205 dispatch(5) 1198 1206 1199 1207 .opPutByValEmpty: … … 1206 1214 .opPutByValSlow: 1207 1215 callSlowPath(_llint_slow_path_put_by_val) 1208 dispatch( 4)1216 dispatch(5) 1209 1217 1210 1218 -
trunk/Source/JavaScriptCore/runtime/Structure.h
r124355 r125637 323 323 return OBJECT_OFFSETOF(Structure, m_typeInfo) + TypeInfo::typeOffset(); 324 324 } 325 326 static ptrdiff_t classInfoOffset() 327 { 328 return OBJECT_OFFSETOF(Structure, m_classInfo); 329 } 325 330 326 331 static Structure* createStructure(JSGlobalData&);
Note: See TracChangeset
for help on using the changeset viewer.