Changeset 164207 in webkit
- Timestamp:
- Feb 16, 2014 10:35:32 PM (10 years ago)
- Location:
- trunk
- Files:
-
- 9 added
- 40 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r164206 r164207 1 2014-02-15 Filip Pizlo <fpizlo@apple.com> 2 3 FTL should inline polymorphic heap accesses 4 https://bugs.webkit.org/show_bug.cgi?id=128795 5 6 Reviewed by Oliver Hunt. 7 8 * js/regress/polymorphic-get-by-id-expected.txt: Added. 9 * js/regress/polymorphic-get-by-id.html: Added. 10 * js/regress/script-tests/polymorphic-get-by-id.js: Added. 11 (foo): 12 1 13 2014-02-16 Filip Pizlo <fpizlo@apple.com> 2 14 -
trunk/Source/JavaScriptCore/CMakeLists.txt
r164096 r164207 71 71 bytecode/ExecutionCounter.cpp 72 72 bytecode/ExitKind.cpp 73 bytecode/ExitingJITType.cpp 73 74 bytecode/GetByIdStatus.cpp 75 bytecode/GetByIdVariant.cpp 74 76 bytecode/InlineCallFrameSet.cpp 75 77 bytecode/JumpTable.cpp -
trunk/Source/JavaScriptCore/ChangeLog
r164205 r164207 1 2014-02-15 Filip Pizlo <fpizlo@apple.com> 2 3 FTL should inline polymorphic heap accesses 4 https://bugs.webkit.org/show_bug.cgi?id=128795 5 6 Reviewed by Oliver Hunt. 7 8 We now inline GetByIds that we know are pure but polymorphic. They manifest in DFG IR 9 as MultiGetByOffset, and in LLVM IR as a switch with a basic block for each kind of 10 read. 11 12 2% speed-up on Octane mostly due to a 18% speed-up on deltablue. 13 14 * CMakeLists.txt: 15 * GNUmakefile.list.am: 16 * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj: 17 * JavaScriptCore.xcodeproj/project.pbxproj: 18 * bytecode/CodeBlock.cpp: 19 (JSC::CodeBlock::dumpBytecode): 20 * bytecode/ExitingJITType.cpp: Added. 21 (WTF::printInternal): 22 * bytecode/ExitingJITType.h: 23 * bytecode/GetByIdStatus.cpp: 24 (JSC::GetByIdStatus::computeFromLLInt): 25 (JSC::GetByIdStatus::computeForChain): 26 (JSC::GetByIdStatus::computeForStubInfo): 27 (JSC::GetByIdStatus::computeFor): 28 (JSC::GetByIdStatus::dump): 29 * bytecode/GetByIdStatus.h: 30 (JSC::GetByIdStatus::GetByIdStatus): 31 (JSC::GetByIdStatus::numVariants): 32 (JSC::GetByIdStatus::variants): 33 (JSC::GetByIdStatus::at): 34 (JSC::GetByIdStatus::operator[]): 35 * bytecode/GetByIdVariant.cpp: Added. 36 (JSC::GetByIdVariant::dump): 37 (JSC::GetByIdVariant::dumpInContext): 38 * bytecode/GetByIdVariant.h: Added. 39 (JSC::GetByIdVariant::GetByIdVariant): 40 (JSC::GetByIdVariant::isSet): 41 (JSC::GetByIdVariant::operator!): 42 (JSC::GetByIdVariant::structureSet): 43 (JSC::GetByIdVariant::chain): 44 (JSC::GetByIdVariant::specificValue): 45 (JSC::GetByIdVariant::offset): 46 * dfg/DFGAbstractInterpreterInlines.h: 47 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 48 * dfg/DFGByteCodeParser.cpp: 49 (JSC::DFG::ByteCodeParser::emitPrototypeChecks): 50 (JSC::DFG::ByteCodeParser::handleGetById): 51 (JSC::DFG::ByteCodeParser::parseBlock): 52 * dfg/DFGCSEPhase.cpp: 53 (JSC::DFG::CSEPhase::getByOffsetLoadElimination): 54 (JSC::DFG::CSEPhase::performNodeCSE): 55 * dfg/DFGClobberize.h: 56 (JSC::DFG::clobberize): 57 * dfg/DFGCommon.h: 58 (JSC::DFG::verboseCompilationEnabled): 59 (JSC::DFG::logCompilationChanges): 60 (JSC::DFG::shouldShowDisassembly): 61 * dfg/DFGConstantFoldingPhase.cpp: 62 (JSC::DFG::ConstantFoldingPhase::foldConstants): 63 (JSC::DFG::ConstantFoldingPhase::emitGetByOffset): 64 * dfg/DFGDriver.cpp: 65 (JSC::DFG::compileImpl): 66 * dfg/DFGFixupPhase.cpp: 67 (JSC::DFG::FixupPhase::fixupNode): 68 * dfg/DFGGraph.cpp: 69 (JSC::DFG::Graph::dump): 70 * dfg/DFGGraph.h: 71 (JSC::DFG::Graph::convertToConstant): 72 * dfg/DFGNode.h: 73 (JSC::DFG::Node::convertToGetByOffset): 74 (JSC::DFG::Node::hasHeapPrediction): 75 (JSC::DFG::Node::hasMultiGetByOffsetData): 76 (JSC::DFG::Node::multiGetByOffsetData): 77 * dfg/DFGNodeType.h: 78 * dfg/DFGPhase.h: 79 (JSC::DFG::Phase::graph): 80 (JSC::DFG::runAndLog): 81 * dfg/DFGPlan.cpp: 82 (JSC::DFG::dumpAndVerifyGraph): 83 (JSC::DFG::Plan::compileInThread): 84 (JSC::DFG::Plan::compileInThreadImpl): 85 * dfg/DFGPredictionPropagationPhase.cpp: 86 (JSC::DFG::PredictionPropagationPhase::propagate): 87 * dfg/DFGSafeToExecute.h: 88 (JSC::DFG::safeToExecute): 89 * dfg/DFGSpeculativeJIT32_64.cpp: 90 (JSC::DFG::SpeculativeJIT::compile): 91 * dfg/DFGSpeculativeJIT64.cpp: 92 (JSC::DFG::SpeculativeJIT::compile): 93 * dfg/DFGTypeCheckHoistingPhase.cpp: 94 (JSC::DFG::TypeCheckHoistingPhase::identifyRedundantStructureChecks): 95 (JSC::DFG::TypeCheckHoistingPhase::identifyRedundantArrayChecks): 96 * ftl/FTLCapabilities.cpp: 97 (JSC::FTL::canCompile): 98 * ftl/FTLCompile.cpp: 99 (JSC::FTL::fixFunctionBasedOnStackMaps): 100 (JSC::FTL::compile): 101 * ftl/FTLLowerDFGToLLVM.cpp: 102 (JSC::FTL::LowerDFGToLLVM::compileNode): 103 (JSC::FTL::LowerDFGToLLVM::compileMultiGetByOffset): 104 * ftl/FTLState.h: 105 (JSC::FTL::verboseCompilationEnabled): 106 (JSC::FTL::showDisassembly): 107 * jsc.cpp: 108 (GlobalObject::finishCreation): 109 (functionEffectful42): 110 * runtime/IntendedStructureChain.cpp: 111 (JSC::IntendedStructureChain::dump): 112 (JSC::IntendedStructureChain::dumpInContext): 113 * runtime/IntendedStructureChain.h: 114 * runtime/Options.cpp: 115 (JSC::recomputeDependentOptions): 116 * runtime/Options.h: 117 * tests/stress/fold-multi-get-by-offset-to-get-by-offset-with-watchpoint.js: Added. 118 (foo): 119 (bar): 120 * tests/stress/fold-multi-get-by-offset-to-get-by-offset.js: Added. 121 (foo): 122 (bar): 123 * tests/stress/multi-get-by-offset-proto-and-self.js: Added. 124 (foo): 125 (Foo): 126 1 127 2014-02-16 Filip Pizlo <fpizlo@apple.com> 2 128 -
trunk/Source/JavaScriptCore/GNUmakefile.list.am
r164059 r164207 148 148 Source/JavaScriptCore/bytecode/ExitKind.cpp \ 149 149 Source/JavaScriptCore/bytecode/ExitKind.h \ 150 Source/JavaScriptCore/bytecode/ExitingJITType.cpp \ 151 Source/JavaScriptCore/bytecode/ExitingJITType.h \ 150 152 Source/JavaScriptCore/bytecode/ExpressionRangeInfo.h \ 151 153 Source/JavaScriptCore/bytecode/FullBytecodeLiveness.h \ 152 154 Source/JavaScriptCore/bytecode/GetByIdStatus.cpp \ 153 155 Source/JavaScriptCore/bytecode/GetByIdStatus.h \ 156 Source/JavaScriptCore/bytecode/GetByIdVariant.cpp \ 157 Source/JavaScriptCore/bytecode/GetByIdVariant.h \ 154 158 Source/JavaScriptCore/bytecode/HandlerInfo.h \ 155 159 Source/JavaScriptCore/bytecode/InlineCallFrameSet.cpp \ -
trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
r164164 r164207 326 326 <ClCompile Include="..\bytecode\ExecutionCounter.cpp" /> 327 327 <ClCompile Include="..\bytecode\ExitKind.cpp" /> 328 <ClCompile Include="..\bytecode\ExitingJITType.cpp" /> 328 329 <ClCompile Include="..\bytecode\GetByIdStatus.cpp" /> 330 <ClCompile Include="..\bytecode\GetByIdVariant.cpp" /> 329 331 <ClCompile Include="..\bytecode\InlineCallFrameSet.cpp" /> 330 332 <ClCompile Include="..\bytecode\JumpTable.cpp" /> … … 841 843 <ClInclude Include="..\bytecode\ExpressionRangeInfo.h" /> 842 844 <ClInclude Include="..\bytecode\GetByIdStatus.h" /> 845 <ClInclude Include="..\bytecode\GetByIdVariant.h" /> 843 846 <ClInclude Include="..\bytecode\HandlerInfo.h" /> 844 847 <ClInclude Include="..\bytecode\InlineCallFrameSet.h" /> -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r164144 r164207 60 60 61 61 /* Begin PBXBuildFile section */ 62 0F0332C018ADFAE1005F979A /* ExitingJITType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0332BF18ADFAE1005F979A /* ExitingJITType.cpp */; }; 63 0F0332C318B01763005F979A /* GetByIdVariant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0332C118B01763005F979A /* GetByIdVariant.cpp */; }; 64 0F0332C418B01763005F979A /* GetByIdVariant.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0332C218B01763005F979A /* GetByIdVariant.h */; settings = {ATTRIBUTES = (Private, ); }; }; 62 65 0F05C3B41683CF9200BAF45B /* DFGArrayifySlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; }; 63 66 0F0776BF14FF002B00102332 /* JITCompilationEffort.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0776BD14FF002800102332 /* JITCompilationEffort.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 211 214 0F2FCCFE18A60070001A27F8 /* DFGThreadData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2FCCF718A60070001A27F8 /* DFGThreadData.cpp */; }; 212 215 0F2FCCFF18A60070001A27F8 /* DFGThreadData.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2FCCF818A60070001A27F8 /* DFGThreadData.h */; settings = {ATTRIBUTES = (Private, ); }; }; 216 0F300B7818AB051100A6D72E /* DFGNodeOrigin.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F300B7718AB051100A6D72E /* DFGNodeOrigin.h */; settings = {ATTRIBUTES = (Private, ); }; }; 213 217 0F300B7B18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F300B7918AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.cpp */; }; 214 218 0F300B7C18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F300B7A18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; 215 0F300B7818AB051100A6D72E /* DFGNodeOrigin.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F300B7718AB051100A6D72E /* DFGNodeOrigin.h */; settings = {ATTRIBUTES = (Private, ); }; };216 219 0F34B14916D42010001CDA5A /* DFGUseKind.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F34B14716D4200E001CDA5A /* DFGUseKind.cpp */; }; 217 220 0F34B14A16D42013001CDA5A /* DFGUseKind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F34B14816D4200E001CDA5A /* DFGUseKind.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 1525 1528 1526 1529 /* Begin PBXFileReference section */ 1530 0F0332BF18ADFAE1005F979A /* ExitingJITType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExitingJITType.cpp; sourceTree = "<group>"; }; 1531 0F0332C118B01763005F979A /* GetByIdVariant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GetByIdVariant.cpp; sourceTree = "<group>"; }; 1532 0F0332C218B01763005F979A /* GetByIdVariant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GetByIdVariant.h; sourceTree = "<group>"; }; 1527 1533 0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArrayifySlowPathGenerator.h; path = dfg/DFGArrayifySlowPathGenerator.h; sourceTree = "<group>"; }; 1528 1534 0F0776BD14FF002800102332 /* JITCompilationEffort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITCompilationEffort.h; sourceTree = "<group>"; }; … … 1675 1681 0F2FCCF718A60070001A27F8 /* DFGThreadData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGThreadData.cpp; path = dfg/DFGThreadData.cpp; sourceTree = "<group>"; }; 1676 1682 0F2FCCF818A60070001A27F8 /* DFGThreadData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGThreadData.h; path = dfg/DFGThreadData.h; sourceTree = "<group>"; }; 1683 0F300B7718AB051100A6D72E /* DFGNodeOrigin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGNodeOrigin.h; path = dfg/DFGNodeOrigin.h; sourceTree = "<group>"; }; 1677 1684 0F300B7918AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGIntegerCheckCombiningPhase.cpp; path = dfg/DFGIntegerCheckCombiningPhase.cpp; sourceTree = "<group>"; }; 1678 1685 0F300B7A18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGIntegerCheckCombiningPhase.h; path = dfg/DFGIntegerCheckCombiningPhase.h; sourceTree = "<group>"; }; 1679 0F300B7718AB051100A6D72E /* DFGNodeOrigin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGNodeOrigin.h; path = dfg/DFGNodeOrigin.h; sourceTree = "<group>"; };1680 1686 0F34B14716D4200E001CDA5A /* DFGUseKind.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGUseKind.cpp; path = dfg/DFGUseKind.cpp; sourceTree = "<group>"; }; 1681 1687 0F34B14816D4200E001CDA5A /* DFGUseKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGUseKind.h; path = dfg/DFGUseKind.h; sourceTree = "<group>"; }; … … 4520 4526 0F56A1D415001CF2002992B1 /* ExecutionCounter.cpp */, 4521 4527 0F56A1D115000F31002992B1 /* ExecutionCounter.h */, 4528 0F0332BF18ADFAE1005F979A /* ExitingJITType.cpp */, 4522 4529 0F3AC753188E5EC80032029F /* ExitingJITType.h */, 4523 4530 0FB105821675480C00F8AB6E /* ExitKind.cpp */, … … 4527 4534 0F93329514CA7DC10085F3C6 /* GetByIdStatus.cpp */, 4528 4535 0F93329614CA7DC10085F3C6 /* GetByIdStatus.h */, 4536 0F0332C118B01763005F979A /* GetByIdVariant.cpp */, 4537 0F0332C218B01763005F979A /* GetByIdVariant.h */, 4529 4538 0F0B83A814BCF55E00885B4F /* HandlerInfo.h */, 4530 4539 0F24E55317F0B71C00ABB217 /* InlineCallFrameSet.cpp */, … … 4823 4832 BC18C3E70E16F5CD00B34460 /* ArrayPrototype.h in Headers */, 4824 4833 BC18C5240E16FC8A00B34460 /* ArrayPrototype.lut.h in Headers */, 4834 0F0332C418B01763005F979A /* GetByIdVariant.h in Headers */, 4825 4835 0FB7F39615ED8E4600F167B2 /* ArrayStorage.h in Headers */, 4826 4836 9688CB150ED12B4E001D649F /* AssemblerBuffer.h in Headers */, … … 6094 6104 A704D90517A0BAA8006BA554 /* DFGInPlaceAbstractState.cpp in Sources */, 6095 6105 0FC97F3D18202119002C9B26 /* DFGInvalidationPointInjectionPhase.cpp in Sources */, 6106 0F0332C018ADFAE1005F979A /* ExitingJITType.cpp in Sources */, 6096 6107 0FEA0A33170D40BF00BB722C /* DFGJITCode.cpp in Sources */, 6097 6108 86EC9DCB1328DF82002B2AD7 /* DFGJITCompiler.cpp in Sources */, … … 6377 6388 148F21B7107EC5470042EC2C /* Nodes.cpp in Sources */, 6378 6389 655EB29B10CE2581001A990E /* NodesCodegen.cpp in Sources */, 6390 0F0332C318B01763005F979A /* GetByIdVariant.cpp in Sources */, 6379 6391 14469DE2107EC7E700650446 /* NumberConstructor.cpp in Sources */, 6380 6392 14469DE3107EC7E700650446 /* NumberObject.cpp in Sources */, -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r164092 r164207 1378 1378 CommaPrinter comma; 1379 1379 for (unsigned i = 0; i < exitSites.size(); ++i) 1380 out.print(comma, exitSites[i].kind() );1380 out.print(comma, exitSites[i].kind(), " ", exitSites[i].jitType()); 1381 1381 } 1382 1382 #else // ENABLE(DFG_JIT) -
trunk/Source/JavaScriptCore/bytecode/ExitingJITType.h
r163027 r164207 52 52 } // namespace JSC 53 53 54 namespace WTF { 55 56 class PrintStream; 57 void printInternal(PrintStream&, JSC::ExitingJITType); 58 59 } // namespace WTF 60 54 61 #endif // ExitingJITType_h 55 62 -
trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp
r164164 r164207 32 32 #include "LowLevelInterpreter.h" 33 33 #include "JSCInlines.h" 34 #include <wtf/ListDump.h> 34 35 35 36 namespace JSC { … … 72 73 return GetByIdStatus(NoInformation, false); 73 74 74 return GetByIdStatus(Simple, false, StructureSet(structure), offset, specificValue);75 return GetByIdStatus(Simple, false, GetByIdVariant(StructureSet(structure), offset, specificValue)); 75 76 #else 76 77 return GetByIdStatus(NoInformation, false); … … 78 79 } 79 80 80 void GetByIdStatus::computeForChain(GetByIdStatus& result, CodeBlock* profiledBlock, StringImpl* uid)81 bool GetByIdStatus::computeForChain(CodeBlock* profiledBlock, StringImpl* uid, PassRefPtr<IntendedStructureChain> passedChain) 81 82 { 82 83 #if ENABLE(JIT) 84 RefPtr<IntendedStructureChain> chain = passedChain; 85 83 86 // Validate the chain. If the chain is invalid, then currently the best thing 84 87 // we can do is to assume that TakesSlow is true. In the future, it might be … … 91 94 // cached on in the baseline JIT and when the DFG tried to inline the access, 92 95 // then we fall back on a polymorphic access. 93 if (! result.m_chain->isStillValid())94 return ;95 96 if ( result.m_chain->head()->takesSlowPathInDFGForImpureProperty())97 return ;98 size_t chainSize = result.m_chain->size();96 if (!chain->isStillValid()) 97 return false; 98 99 if (chain->head()->takesSlowPathInDFGForImpureProperty()) 100 return false; 101 size_t chainSize = chain->size(); 99 102 for (size_t i = 0; i < chainSize; i++) { 100 if ( result.m_chain->at(i)->takesSlowPathInDFGForImpureProperty())101 return ;102 } 103 104 JSObject* currentObject = result.m_chain->terminalPrototype();105 Structure* currentStructure = result.m_chain->last();103 if (chain->at(i)->takesSlowPathInDFGForImpureProperty()) 104 return false; 105 } 106 107 JSObject* currentObject = chain->terminalPrototype(); 108 Structure* currentStructure = chain->last(); 106 109 107 110 ASSERT_UNUSED(currentObject, currentObject); 108 111 109 112 unsigned attributesIgnored; 110 113 JSCell* specificValue; 111 112 result.m_offset = currentStructure->getConcurrently(114 115 PropertyOffset offset = currentStructure->getConcurrently( 113 116 *profiledBlock->vm(), uid, attributesIgnored, specificValue); 114 117 if (currentStructure->isDictionary()) 115 118 specificValue = 0; 116 if (!isValidOffset( result.m_offset))117 return ;118 119 result.m_structureSet.add(result.m_chain->head());120 result.m_specificValue = JSValue(specificValue);121 #else 122 UNUSED_PARAM(result); 119 if (!isValidOffset(offset)) 120 return false; 121 122 m_variants.append( 123 GetByIdVariant(StructureSet(chain->head()), offset, specificValue, chain)); 124 return true; 125 #else // ENABLE(JIT) 123 126 UNUSED_PARAM(profiledBlock); 124 127 UNUSED_PARAM(uid); 128 UNUSED_PARAM(passedChain); 125 129 UNREACHABLE_FOR_PLATFORM(); 126 #endif 130 return false; 131 #endif // ENABLE(JIT) 127 132 } 128 133 … … 175 180 // Finally figure out if we can derive an access strategy. 176 181 GetByIdStatus result; 182 result.m_state = Simple; 177 183 result.m_wasSeenInJIT = true; // This is interesting for bytecode dumping only. 178 184 switch (stubInfo->accessType) { … … 186 192 unsigned attributesIgnored; 187 193 JSCell* specificValue; 188 result.m_offset = structure->getConcurrently( 194 GetByIdVariant variant; 195 variant.m_offset = structure->getConcurrently( 189 196 *profiledBlock->vm(), uid, attributesIgnored, specificValue); 197 if (!isValidOffset(variant.m_offset)) 198 return GetByIdStatus(TakesSlowPath, true); 199 190 200 if (structure->isDictionary()) 191 201 specificValue = 0; 192 202 193 if (isValidOffset(result.m_offset)) { 194 result.m_structureSet.add(structure); 195 result.m_specificValue = JSValue(specificValue); 196 } 197 198 if (isValidOffset(result.m_offset)) 199 ASSERT(result.m_structureSet.size()); 200 break; 203 variant.m_structureSet.add(structure); 204 variant.m_specificValue = JSValue(specificValue); 205 result.m_variants.append(variant); 206 return result; 201 207 } 202 208 203 209 case access_get_by_id_self_list: { 204 for (int i = 0; i < listSize; ++i) {205 ASSERT(list->list[ i].isDirect);206 207 Structure* structure = list->list[ i].base.get();210 for (int listIndex = 0; listIndex < listSize; ++listIndex) { 211 ASSERT(list->list[listIndex].isDirect); 212 213 Structure* structure = list->list[listIndex].base.get(); 208 214 if (structure->takesSlowPathInDFGForImpureProperty()) 209 215 return GetByIdStatus(TakesSlowPath, true); 210 211 if (result.m_structureSet.contains(structure)) 216 217 if (list->list[listIndex].chain.get()) { 218 RefPtr<IntendedStructureChain> chain = adoptRef(new IntendedStructureChain( 219 profiledBlock, structure, list->list[listIndex].chain.get(), 220 list->list[listIndex].count)); 221 if (!result.computeForChain(profiledBlock, uid, chain)) 222 return GetByIdStatus(TakesSlowPath, true); 212 223 continue; 224 } 213 225 214 226 unsigned attributesIgnored; … … 219 231 specificValue = 0; 220 232 221 if (!isValidOffset(myOffset)) { 222 result.m_offset = invalidOffset; 233 if (!isValidOffset(myOffset)) 234 return GetByIdStatus(TakesSlowPath, true); 235 236 bool found = false; 237 for (unsigned variantIndex = 0; variantIndex < result.m_variants.size(); ++variantIndex) { 238 GetByIdVariant& variant = result.m_variants[variantIndex]; 239 if (variant.m_chain) 240 continue; 241 242 if (variant.m_offset != myOffset) 243 continue; 244 245 found = true; 246 if (variant.m_structureSet.contains(structure)) 247 break; 248 249 if (variant.m_specificValue != JSValue(specificValue)) 250 variant.m_specificValue = JSValue(); 251 252 variant.m_structureSet.add(structure); 223 253 break; 224 254 } 225 226 if (!i) { 227 result.m_offset = myOffset; 228 result.m_specificValue = JSValue(specificValue); 229 } else if (result.m_offset != myOffset) { 230 result.m_offset = invalidOffset; 231 break; 232 } else if (result.m_specificValue != JSValue(specificValue)) 233 result.m_specificValue = JSValue(); 234 235 result.m_structureSet.add(structure); 255 256 if (found) 257 continue; 258 259 result.m_variants.append( 260 GetByIdVariant(StructureSet(structure), myOffset, specificValue)); 236 261 } 237 238 if (isValidOffset(result.m_offset)) 239 ASSERT(result.m_structureSet.size()); 240 break; 262 263 return result; 241 264 } 242 265 … … 244 267 if (!stubInfo->u.getByIdChain.isDirect) 245 268 return GetByIdStatus(MakesCalls, true); 246 result.m_chain = adoptRef(new IntendedStructureChain(269 RefPtr<IntendedStructureChain> chain = adoptRef(new IntendedStructureChain( 247 270 profiledBlock, 248 271 stubInfo->u.getByIdChain.baseObjectStructure.get(), 249 272 stubInfo->u.getByIdChain.chain.get(), 250 273 stubInfo->u.getByIdChain.count)); 251 computeForChain(result, profiledBlock, uid); 252 break; 274 if (result.computeForChain(profiledBlock, uid, chain)) 275 return result; 276 return GetByIdStatus(TakesSlowPath, true); 253 277 } 254 278 255 279 default: 256 ASSERT(!isValidOffset(result.m_offset)); 257 break; 258 } 259 260 if (!isValidOffset(result.m_offset)) { 261 result.m_state = TakesSlowPath; 262 result.m_structureSet.clear(); 263 result.m_chain.clear(); 264 result.m_specificValue = JSValue(); 265 } else 266 result.m_state = Simple; 267 268 return result; 280 return GetByIdStatus(TakesSlowPath, true); 281 } 282 283 RELEASE_ASSERT_NOT_REACHED(); 284 return GetByIdStatus(); 269 285 } 270 286 #endif // ENABLE(JIT) … … 281 297 result = computeForStubInfo(locker, dfgBlock, dfgMap.get(codeOrigin), uid); 282 298 } 283 299 284 300 if (result.takesSlowPath()) 285 301 return result; … … 319 335 return GetByIdStatus(TakesSlowPath); 320 336 321 GetByIdStatus result;322 result.m_wasSeenInJIT = false; // To my knowledge nobody that uses computeFor(VM&, Structure*, StringImpl*) reads this field, but I might as well be honest: no, it wasn't seen in the JIT, since I computed it statically.323 337 unsigned attributes; 324 338 JSCell* specificValue; 325 result.m_offset = structure->getConcurrently(vm, uid, attributes, specificValue);326 if (!isValidOffset( result.m_offset))339 PropertyOffset offset = structure->getConcurrently(vm, uid, attributes, specificValue); 340 if (!isValidOffset(offset)) 327 341 return GetByIdStatus(TakesSlowPath); // It's probably a prototype lookup. Give up on life for now, even though we could totally be way smarter about it. 328 342 if (attributes & Accessor) … … 330 344 if (structure->isDictionary()) 331 345 specificValue = 0; 332 result.m_structureSet.add(structure); 333 result.m_specificValue = JSValue(specificValue); 334 result.m_state = Simple; 335 return result; 346 return GetByIdStatus( 347 Simple, false, GetByIdVariant(StructureSet(structure), offset, specificValue)); 348 } 349 350 void GetByIdStatus::dump(PrintStream& out) const 351 { 352 out.print("("); 353 switch (m_state) { 354 case NoInformation: 355 out.print("NoInformation"); 356 break; 357 case Simple: 358 out.print("Simple"); 359 break; 360 case TakesSlowPath: 361 out.print("TakesSlowPath"); 362 break; 363 case MakesCalls: 364 out.print("MakesCalls"); 365 break; 366 } 367 out.print(", ", listDump(m_variants), ", seenInJIT = ", m_wasSeenInJIT, ")"); 336 368 } 337 369 -
trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.h
r164164 r164207 30 30 #include "ConcurrentJITLock.h" 31 31 #include "ExitingJITType.h" 32 #include "IntendedStructureChain.h" 33 #include "PropertyOffset.h" 34 #include "StructureSet.h" 32 #include "GetByIdVariant.h" 35 33 #include "StructureStubInfo.h" 36 34 … … 51 49 GetByIdStatus() 52 50 : m_state(NoInformation) 53 , m_offset(invalidOffset)54 51 { 55 52 } … … 57 54 explicit GetByIdStatus(State state) 58 55 : m_state(state) 59 , m_offset(invalidOffset)60 56 { 61 57 ASSERT(state == NoInformation || state == TakesSlowPath || state == MakesCalls); … … 63 59 64 60 GetByIdStatus( 65 State state, bool wasSeenInJIT, const StructureSet& structureSet = StructureSet(), 66 PropertyOffset offset = invalidOffset, JSValue specificValue = JSValue(), PassRefPtr<IntendedStructureChain> chain = nullptr) 61 State state, bool wasSeenInJIT, const GetByIdVariant& variant = GetByIdVariant()) 67 62 : m_state(state) 68 , m_structureSet(structureSet)69 , m_chain(chain)70 , m_specificValue(specificValue)71 , m_offset(offset)72 63 , m_wasSeenInJIT(wasSeenInJIT) 73 64 { 74 ASSERT((state == Simple) == (offset != invalidOffset)); 65 ASSERT((state == Simple) == variant.isSet()); 66 m_variants.append(variant); 75 67 } 76 68 … … 85 77 bool operator!() const { return !isSet(); } 86 78 bool isSimple() const { return m_state == Simple; } 79 80 size_t numVariants() const { return m_variants.size(); } 81 const Vector<GetByIdVariant, 1>& variants() const { return m_variants; } 82 const GetByIdVariant& at(size_t index) const { return m_variants[index]; } 83 const GetByIdVariant& operator[](size_t index) const { return at(index); } 84 87 85 bool takesSlowPath() const { return m_state == TakesSlowPath || m_state == MakesCalls; } 88 86 bool makesCalls() const { return m_state == MakesCalls; } 89 87 90 const StructureSet& structureSet() const { return m_structureSet; } 91 IntendedStructureChain* chain() const { return const_cast<IntendedStructureChain*>(m_chain.get()); } // Returns null if this is a direct access. 92 JSValue specificValue() const { return m_specificValue; } // Returns JSValue() if there is no specific value. 93 PropertyOffset offset() const { return m_offset; } 88 bool wasSeenInJIT() const { return m_wasSeenInJIT; } 94 89 95 bool wasSeenInJIT() const { return m_wasSeenInJIT; }90 void dump(PrintStream&) const; 96 91 97 92 private: … … 102 97 static GetByIdStatus computeForStubInfo(const ConcurrentJITLocker&, CodeBlock*, StructureStubInfo*, StringImpl* uid); 103 98 #endif 104 static void computeForChain(GetByIdStatus& result, CodeBlock*, StringImpl* uid);99 bool computeForChain(CodeBlock*, StringImpl* uid, PassRefPtr<IntendedStructureChain>); 105 100 static GetByIdStatus computeFromLLInt(CodeBlock*, unsigned bytecodeIndex, StringImpl* uid); 106 101 107 102 State m_state; 108 StructureSet m_structureSet; 109 RefPtr<IntendedStructureChain> m_chain; 110 JSValue m_specificValue; 111 PropertyOffset m_offset; 103 Vector<GetByIdVariant, 1> m_variants; 112 104 bool m_wasSeenInJIT; 113 105 }; -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r164059 r164207 1452 1452 m_graph.m_vm, structure, 1453 1453 m_graph.identifiers()[node->identifierNumber()]); 1454 if (status.isSimple() ) {1454 if (status.isSimple() && status.numVariants() == 1) { 1455 1455 // Assert things that we can't handle and that the computeFor() method 1456 1456 // above won't be able to return. 1457 ASSERT(status .structureSet().size() == 1);1458 ASSERT(!status .chain());1457 ASSERT(status[0].structureSet().size() == 1); 1458 ASSERT(!status[0].chain()); 1459 1459 1460 if (status .specificValue())1461 setConstant(node, status .specificValue());1460 if (status[0].specificValue()) 1461 setConstant(node, status[0].specificValue()); 1462 1462 else 1463 1463 forNode(node).makeHeapTop(); 1464 filter(node->child1(), status .structureSet());1464 filter(node->child1(), status[0].structureSet()); 1465 1465 1466 1466 m_state.setFoundConstants(true); … … 1630 1630 1631 1631 case GetByOffset: { 1632 forNode(node).makeHeapTop(); 1633 break; 1634 } 1635 1636 case MultiGetByOffset: { 1637 AbstractValue& value = forNode(node->child1()); 1638 ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this. 1639 1640 if (Structure* structure = value.bestProvenStructure()) { 1641 bool done = false; 1642 for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;) { 1643 const GetByIdVariant& variant = node->multiGetByOffsetData().variants[i]; 1644 if (!variant.structureSet().contains(structure)) 1645 continue; 1646 1647 if (variant.chain()) 1648 break; 1649 1650 filter(value, structure); 1651 forNode(node).makeHeapTop(); 1652 m_state.setFoundConstants(true); 1653 done = true; 1654 break; 1655 } 1656 if (done) 1657 break; 1658 } 1659 1660 StructureSet set; 1661 for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;) 1662 set.addAll(node->multiGetByOffsetData().variants[i].structureSet()); 1663 1664 filter(value, set); 1632 1665 forNode(node).makeHeapTop(); 1633 1666 break; -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r164059 r164207 181 181 int destinationOperand, SpeculatedType, Node* base, unsigned identifierNumber, 182 182 const GetByIdStatus&); 183 Node* emitPrototypeChecks(const GetByIdVariant&); 183 184 184 185 Node* getScope(bool skipTop, unsigned skipCount); … … 1828 1829 } 1829 1830 1831 Node* ByteCodeParser::emitPrototypeChecks(const GetByIdVariant& variant) 1832 { 1833 Node* base = 0; 1834 m_graph.chains().addLazily(variant.chain()); 1835 Structure* currentStructure = variant.structureSet().singletonStructure(); 1836 JSObject* currentObject = 0; 1837 for (unsigned i = 0; i < variant.chain()->size(); ++i) { 1838 currentObject = asObject(currentStructure->prototypeForLookup(m_inlineStackTop->m_codeBlock)); 1839 currentStructure = variant.chain()->at(i); 1840 base = cellConstantWithStructureCheck(currentObject, currentStructure); 1841 } 1842 RELEASE_ASSERT(base); 1843 return base; 1844 } 1845 1830 1846 void ByteCodeParser::handleGetById( 1831 1847 int destinationOperand, SpeculatedType prediction, Node* base, unsigned identifierNumber, … … 1840 1856 } 1841 1857 1842 ASSERT(getByIdStatus.structureSet().size()); 1858 if (getByIdStatus.numVariants() > 1) { 1859 if (!isFTL(m_graph.m_plan.mode)) { 1860 set(VirtualRegister(destinationOperand), 1861 addToGraph(GetById, OpInfo(identifierNumber), OpInfo(prediction), base)); 1862 return; 1863 } 1864 1865 // 1) Emit prototype structure checks for all chains. This could sort of maybe not be 1866 // optimal, if there is some rarely executed case in the chain that requires a lot 1867 // of checks and those checks are not watchpointable. 1868 for (unsigned variantIndex = getByIdStatus.numVariants(); variantIndex--;) { 1869 if (getByIdStatus[variantIndex].chain()) 1870 emitPrototypeChecks(getByIdStatus[variantIndex]); 1871 } 1872 1873 // 2) Emit a MultiGetByOffset 1874 MultiGetByOffsetData* data = m_graph.m_multiGetByOffsetData.add(); 1875 data->variants = getByIdStatus.variants(); 1876 data->identifierNumber = identifierNumber; 1877 set(VirtualRegister(destinationOperand), 1878 addToGraph(MultiGetByOffset, OpInfo(data), OpInfo(prediction), base)); 1879 return; 1880 } 1881 1882 ASSERT(getByIdStatus.numVariants() == 1); 1883 GetByIdVariant variant = getByIdStatus[0]; 1843 1884 1844 1885 if (m_graph.compilation()) … … 1847 1888 Node* originalBaseForBaselineJIT = base; 1848 1889 1849 addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(getByIdStatus.structureSet())), base); 1850 1851 if (getByIdStatus.chain()) { 1852 m_graph.chains().addLazily(getByIdStatus.chain()); 1853 Structure* currentStructure = getByIdStatus.structureSet().singletonStructure(); 1854 JSObject* currentObject = 0; 1855 for (unsigned i = 0; i < getByIdStatus.chain()->size(); ++i) { 1856 currentObject = asObject(currentStructure->prototypeForLookup(m_inlineStackTop->m_codeBlock)); 1857 currentStructure = getByIdStatus.chain()->at(i); 1858 base = cellConstantWithStructureCheck(currentObject, currentStructure); 1859 } 1860 } 1890 addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.structureSet())), base); 1891 1892 if (variant.chain()) 1893 base = emitPrototypeChecks(variant); 1861 1894 1862 1895 // Unless we want bugs like https://bugs.webkit.org/show_bug.cgi?id=88783, we need to … … 1866 1899 // access was compiled to a WeakJSConstant specific value, in which case we might not 1867 1900 // have any explicit use of the base at all. 1868 if ( getByIdStatus.specificValue() || originalBaseForBaselineJIT != base)1901 if (variant.specificValue() || originalBaseForBaselineJIT != base) 1869 1902 addToGraph(Phantom, originalBaseForBaselineJIT); 1870 1903 1871 if ( getByIdStatus.specificValue()) {1872 ASSERT( getByIdStatus.specificValue().isCell());1873 1874 set(VirtualRegister(destinationOperand), cellConstant( getByIdStatus.specificValue().asCell()));1904 if (variant.specificValue()) { 1905 ASSERT(variant.specificValue().isCell()); 1906 1907 set(VirtualRegister(destinationOperand), cellConstant(variant.specificValue().asCell())); 1875 1908 return; 1876 1909 } 1877 1910 1878 1911 handleGetByOffset( 1879 destinationOperand, prediction, base, identifierNumber, getByIdStatus.offset());1912 destinationOperand, prediction, base, identifierNumber, variant.offset()); 1880 1913 } 1881 1914 … … 3141 3174 case GlobalPropertyWithVarInjectionChecks: { 3142 3175 GetByIdStatus status = GetByIdStatus::computeFor(*m_vm, structure, uid); 3143 if (status. takesSlowPath()) {3176 if (status.state() != GetByIdStatus::Simple || status.numVariants() != 1) { 3144 3177 set(VirtualRegister(dst), addToGraph(GetByIdFlush, OpInfo(identifierNumber), OpInfo(prediction), get(VirtualRegister(scope)))); 3145 3178 break; 3146 3179 } 3147 Node* base = cellConstantWithStructureCheck(globalObject, status .structureSet().singletonStructure());3180 Node* base = cellConstantWithStructureCheck(globalObject, status[0].structureSet().singletonStructure()); 3148 3181 addToGraph(Phantom, get(VirtualRegister(scope))); 3149 if (JSValue specificValue = status .specificValue())3182 if (JSValue specificValue = status[0].specificValue()) 3150 3183 set(VirtualRegister(dst), cellConstant(specificValue.asCell())); 3151 3184 else -
trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
r164059 r164207 643 643 } 644 644 645 Node* getByOffsetLoadElimination(unsigned identifierNumber, Node* child1)646 { 647 for (unsigned i = m_indexInBlock; i--;) { 648 Node* node = m_currentBlock->at(i); 649 if (node == child1)645 Node* getByOffsetLoadElimination(unsigned identifierNumber, Node* base) 646 { 647 for (unsigned i = m_indexInBlock; i--;) { 648 Node* node = m_currentBlock->at(i); 649 if (node == base) 650 650 break; 651 651 652 652 switch (node->op()) { 653 653 case GetByOffset: 654 if (node->child 1() == child1654 if (node->child2() == base 655 655 && m_graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber == identifierNumber) 656 656 return node; 657 657 break; 658 658 659 case MultiGetByOffset: 660 if (node->child1() == base 661 && node->multiGetByOffsetData().identifierNumber == identifierNumber) 662 return node; 663 break; 664 659 665 case PutByOffset: 660 666 if (m_graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber == identifierNumber) { 661 if (node->child 1() == child1) // Must be same property storage.667 if (node->child2() == base) // Must be same property storage. 662 668 return node->child3().node(); 663 669 return 0; … … 1402 1408 if (cseMode == StoreElimination) 1403 1409 break; 1404 setReplacement(getByOffsetLoadElimination(m_graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber, node->child1().node())); 1410 setReplacement(getByOffsetLoadElimination(m_graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber, node->child2().node())); 1411 break; 1412 1413 case MultiGetByOffset: 1414 if (cseMode == StoreElimination) 1415 break; 1416 setReplacement(getByOffsetLoadElimination(node->multiGetByOffsetData().identifierNumber, node->child1().node())); 1405 1417 break; 1406 1418 -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r164059 r164207 471 471 return; 472 472 473 case MultiGetByOffset: 474 read(AbstractHeap(NamedProperties, node->multiGetByOffsetData().identifierNumber)); 475 return; 476 473 477 case PutByOffset: 474 478 write(AbstractHeap(NamedProperties, graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber)); -
trunk/Source/JavaScriptCore/dfg/DFGCommon.h
r163027 r164207 29 29 #include <wtf/Platform.h> 30 30 31 #include "DFGCompilationMode.h" 32 31 33 #if ENABLE(DFG_JIT) 32 34 … … 64 66 }; 65 67 66 inline bool verboseCompilationEnabled( )67 { 68 return Options::verboseCompilation() || Options::dumpGraphAtEachPhase() ;69 } 70 71 inline bool logCompilationChanges( )72 { 73 return verboseCompilationEnabled( ) || Options::logCompilationChanges();68 inline bool verboseCompilationEnabled(CompilationMode mode = DFGMode) 69 { 70 return Options::verboseCompilation() || Options::dumpGraphAtEachPhase() || (isFTL(mode) && Options::verboseFTLCompilation()); 71 } 72 73 inline bool logCompilationChanges(CompilationMode mode = DFGMode) 74 { 75 return verboseCompilationEnabled(mode) || Options::logCompilationChanges(); 74 76 } 75 77 … … 289 291 290 292 // Unconditionally disable DFG disassembly support if the DFG is not compiled in. 291 inline bool shouldShowDisassembly( )293 inline bool shouldShowDisassembly(CompilationMode mode = DFGMode) 292 294 { 293 295 #if ENABLE(DFG_JIT) 294 return Options::showDisassembly() || Options::showDFGDisassembly() ;296 return Options::showDisassembly() || Options::showDFGDisassembly() || (isFTL(mode) && Options::showFTLDisassembly()); 295 297 #else 296 298 return false; -
trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
r163946 r164207 152 152 break; 153 153 } 154 155 case MultiGetByOffset: { 156 Edge childEdge = node->child1(); 157 Node* child = childEdge.node(); 158 MultiGetByOffsetData& data = node->multiGetByOffsetData(); 159 160 Structure* structure = m_state.forNode(child).bestProvenStructure(); 161 if (!structure) 162 break; 163 164 for (unsigned i = data.variants.size(); i--;) { 165 const GetByIdVariant& variant = data.variants[i]; 166 if (!variant.structureSet().contains(structure)) 167 continue; 168 169 if (variant.chain()) 170 break; 171 172 emitGetByOffset(indexInBlock, node, structure, variant, data.identifierNumber); 173 eliminated = true; 174 break; 175 } 176 break; 177 } 154 178 155 179 case GetById: 156 180 case GetByIdFlush: { 157 NodeOrigin origin = node->origin;158 181 Edge childEdge = node->child1(); 159 182 Node* child = childEdge.node(); … … 167 190 break; 168 191 169 bool needsWatchpoint = !m_state.forNode(child).m_currentKnownStructure.hasSingleton();170 bool needsCellCheck = m_state.forNode(child).m_type & ~SpecCell;171 172 192 GetByIdStatus status = GetByIdStatus::computeFor( 173 193 vm(), structure, m_graph.identifiers()[identifierNumber]); 174 194 175 if (!status.isSimple() ) {195 if (!status.isSimple() || status.numVariants() != 1) { 176 196 // FIXME: We could handle prototype cases. 177 197 // https://bugs.webkit.org/show_bug.cgi?id=110386 … … 179 199 } 180 200 181 ASSERT(status.structureSet().size() == 1); 182 ASSERT(!status.chain()); 183 ASSERT(status.structureSet().singletonStructure() == structure); 184 185 // Now before we do anything else, push the CFA forward over the GetById 186 // and make sure we signal to the loop that it should continue and not 187 // do any eliminations. 188 m_interpreter.execute(indexInBlock); 201 emitGetByOffset(indexInBlock, node, structure, status[0], identifierNumber); 189 202 eliminated = true; 190 191 if (needsWatchpoint) {192 m_insertionSet.insertNode(193 indexInBlock, SpecNone, StructureTransitionWatchpoint, origin,194 OpInfo(structure), childEdge);195 } else if (needsCellCheck) {196 m_insertionSet.insertNode(197 indexInBlock, SpecNone, Phantom, origin, childEdge);198 }199 200 childEdge.setUseKind(KnownCellUse);201 202 Edge propertyStorage;203 204 if (isInlineOffset(status.offset()))205 propertyStorage = childEdge;206 else {207 propertyStorage = Edge(m_insertionSet.insertNode(208 indexInBlock, SpecNone, GetButterfly, origin, childEdge));209 }210 211 node->convertToGetByOffset(m_graph.m_storageAccessData.size(), propertyStorage);212 213 StorageAccessData storageAccessData;214 storageAccessData.offset = status.offset();215 storageAccessData.identifierNumber = identifierNumber;216 m_graph.m_storageAccessData.append(storageAccessData);217 203 break; 218 204 } … … 407 393 return changed; 408 394 } 395 396 void emitGetByOffset(unsigned indexInBlock, Node* node, Structure* structure, const GetByIdVariant& variant, unsigned identifierNumber) 397 { 398 NodeOrigin origin = node->origin; 399 Edge childEdge = node->child1(); 400 Node* child = childEdge.node(); 401 402 bool needsWatchpoint = !m_state.forNode(child).m_currentKnownStructure.hasSingleton(); 403 bool needsCellCheck = m_state.forNode(child).m_type & ~SpecCell; 404 405 ASSERT(!variant.chain()); 406 ASSERT(variant.structureSet().contains(structure)); 407 408 // Now before we do anything else, push the CFA forward over the GetById 409 // and make sure we signal to the loop that it should continue and not 410 // do any eliminations. 411 m_interpreter.execute(indexInBlock); 412 413 if (needsWatchpoint) { 414 m_insertionSet.insertNode( 415 indexInBlock, SpecNone, StructureTransitionWatchpoint, origin, 416 OpInfo(structure), childEdge); 417 } else if (needsCellCheck) { 418 m_insertionSet.insertNode( 419 indexInBlock, SpecNone, Phantom, origin, childEdge); 420 } 421 422 if (variant.specificValue()) { 423 m_graph.convertToConstant(node, variant.specificValue()); 424 return; 425 } 426 427 childEdge.setUseKind(KnownCellUse); 428 429 Edge propertyStorage; 430 431 if (isInlineOffset(variant.offset())) 432 propertyStorage = childEdge; 433 else { 434 propertyStorage = Edge(m_insertionSet.insertNode( 435 indexInBlock, SpecNone, GetButterfly, origin, childEdge)); 436 } 437 438 node->convertToGetByOffset(m_graph.m_storageAccessData.size(), propertyStorage); 439 440 StorageAccessData storageAccessData; 441 storageAccessData.offset = variant.offset(); 442 storageAccessData.identifierNumber = identifierNumber; 443 m_graph.m_storageAccessData.append(storageAccessData); 444 } 409 445 410 446 void addStructureTransitionCheck(NodeOrigin origin, unsigned indexInBlock, JSCell* cell) -
trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp
r163844 r164207 83 83 return CompilationInvalidated; 84 84 85 if (logCompilationChanges( ))85 if (logCompilationChanges(mode)) 86 86 dataLog("DFG(Driver) compiling ", *codeBlock, " with ", mode, ", number of instructions = ", codeBlock->instructionCount(), "\n"); 87 87 … … 116 116 Worklist* worklist = ensureGlobalWorklistFor(mode); 117 117 plan->callback = callback; 118 if (logCompilationChanges( ))118 if (logCompilationChanges(mode)) 119 119 dataLog("Deferring DFG compilation of ", *codeBlock, " with queue length ", worklist->queueLength(), ".\n"); 120 120 worklist->enqueue(plan); -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r164059 r164207 879 879 fixEdge<KnownCellUse>(node->child1()); 880 880 fixEdge<KnownCellUse>(node->child2()); 881 break; 882 } 883 884 case MultiGetByOffset: { 885 fixEdge<CellUse>(node->child1()); 881 886 break; 882 887 } -
trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp
r163946 r164207 247 247 out.print(", ", static_cast<ptrdiff_t>(storageAccessData.offset)); 248 248 } 249 if (node->hasMultiGetByOffsetData()) { 250 MultiGetByOffsetData& data = node->multiGetByOffsetData(); 251 out.print(comma, "id", data.identifierNumber, "{", identifiers()[data.identifierNumber], "}"); 252 for (unsigned i = 0; i < data.variants.size(); ++i) 253 out.print(comma, inContext(data.variants[i], context)); 254 } 249 255 ASSERT(node->hasVariableAccessData(*this) == node->hasLocal(*this)); 250 256 if (node->hasVariableAccessData(*this)) { -
trunk/Source/JavaScriptCore/dfg/DFGGraph.h
r164059 r164207 178 178 void convertToConstant(Node* node, JSValue value) 179 179 { 180 convertToConstant(node, constantRegisterForConstant(value)); 180 if (value.isObject()) 181 node->convertToWeakConstant(value.asCell()); 182 else 183 convertToConstant(node, constantRegisterForConstant(value)); 181 184 } 182 185 … … 828 831 SegmentedVector<NewArrayBufferData, 4> m_newArrayBufferData; 829 832 SegmentedVector<SwitchData, 4> m_switchData; 833 Bag<MultiGetByOffsetData> m_multiGetByOffsetData; 830 834 Vector<InlineVariableData, 4> m_inlineVariableData; 831 835 OwnPtr<InlineCallFrameSet> m_inlineCallFrames; -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r164059 r164207 42 42 #include "DFGNodeType.h" 43 43 #include "DFGVariableAccessData.h" 44 #include "GetByIdVariant.h" 44 45 #include "JSCJSValue.h" 45 46 #include "Operands.h" … … 53 54 class Graph; 54 55 struct BasicBlock; 56 57 struct MultiGetByOffsetData { 58 unsigned identifierNumber; 59 Vector<GetByIdVariant, 2> variants; 60 }; 55 61 56 62 struct StructureTransitionData { … … 407 413 void convertToGetByOffset(unsigned storageAccessDataIndex, Edge storage) 408 414 { 409 ASSERT(m_op == GetById || m_op == GetByIdFlush );415 ASSERT(m_op == GetById || m_op == GetByIdFlush || m_op == MultiGetByOffset); 410 416 m_opInfo = storageAccessDataIndex; 411 417 children.setChild2(children.child1()); … … 906 912 case Construct: 907 913 case GetByOffset: 914 case MultiGetByOffset: 908 915 case GetClosureVar: 909 916 case ArrayPop: … … 1053 1060 ASSERT(hasStorageAccessData()); 1054 1061 return m_opInfo; 1062 } 1063 1064 bool hasMultiGetByOffsetData() 1065 { 1066 return op() == MultiGetByOffset; 1067 } 1068 1069 MultiGetByOffsetData& multiGetByOffsetData() 1070 { 1071 return *reinterpret_cast<MultiGetByOffsetData*>(m_opInfo); 1055 1072 } 1056 1073 -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r164059 r164207 176 176 macro(TypedArrayWatchpoint, NodeMustGenerate) \ 177 177 macro(GetByOffset, NodeResultJS) \ 178 macro(MultiGetByOffset, NodeResultJS) \ 178 179 macro(PutByOffset, NodeMustGenerate) \ 179 180 macro(GetArrayLength, NodeResultInt32) \ -
trunk/Source/JavaScriptCore/dfg/DFGPhase.h
r163802 r164207 52 52 const char* name() const { return m_name; } 53 53 54 Graph& graph() { return m_graph; } 55 54 56 // Each phase must have a run() method. 55 57 … … 74 76 { 75 77 bool result = phase.run(); 76 if (result && logCompilationChanges( ))78 if (result && logCompilationChanges(phase.graph().m_plan.mode)) 77 79 dataLogF("Phase %s changed the IR.\n", phase.name()); 78 80 return result; -
trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp
r164059 r164207 86 86 { 87 87 GraphDumpMode modeForFinalValidate = DumpGraph; 88 if (verboseCompilationEnabled( )) {88 if (verboseCompilationEnabled(graph.m_plan.mode)) { 89 89 dataLog(text, "\n"); 90 90 graph.dump(); … … 150 150 CompilationScope compilationScope; 151 151 152 if (logCompilationChanges( ))152 if (logCompilationChanges(mode)) 153 153 dataLog("DFG(Plan) compiling ", *codeBlock, " with ", mode, ", number of instructions = ", codeBlock->instructionCount(), "\n"); 154 154 … … 184 184 Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState) 185 185 { 186 if (verboseCompilationEnabled( ) && osrEntryBytecodeIndex != UINT_MAX) {186 if (verboseCompilationEnabled(mode) && osrEntryBytecodeIndex != UINT_MAX) { 187 187 dataLog("\n"); 188 188 dataLog("Compiler must handle OSR entry from bc#", osrEntryBytecodeIndex, " with values: ", mustHandleValues, "\n"); … … 231 231 dfg.m_fixpointState = FixpointNotConverged; 232 232 for (;; ++count) { 233 if (logCompilationChanges( ))233 if (logCompilationChanges(mode)) 234 234 dataLogF("DFG beginning optimization fixpoint iteration #%u.\n", count); 235 235 bool changed = false; … … 251 251 } 252 252 253 if (logCompilationChanges( ))253 if (logCompilationChanges(mode)) 254 254 dataLogF("DFG optimization fixpoint converged in %u iterations.\n", count); 255 255 -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r164059 r164207 178 178 case GetMyArgumentByValSafe: 179 179 case GetByOffset: 180 case MultiGetByOffset: 180 181 case Call: 181 182 case Construct: -
trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
r164059 r164207 254 254 case ConstantStoragePointer: 255 255 case Check: 256 case MultiGetByOffset: 256 257 return true; 257 258 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r164059 r164207 4690 4690 case CheckInBounds: 4691 4691 case ArithIMul: 4692 case MultiGetByOffset: 4692 4693 RELEASE_ASSERT_NOT_REACHED(); 4693 4694 break; -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r164059 r164207 5011 5011 case CheckInBounds: 5012 5012 case ArithIMul: 5013 case MultiGetByOffset: 5013 5014 RELEASE_ASSERT_NOT_REACHED(); 5014 5015 break; -
trunk/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp
r164059 r164207 247 247 case HardPhantom: 248 248 case MovHint: 249 case MultiGetByOffset: 249 250 // Don't count these uses. 250 251 break; … … 346 347 case HardPhantom: 347 348 case MovHint: 349 case MultiGetByOffset: 348 350 // Don't count these uses. 349 351 break; -
trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
r164178 r164207 138 138 case GetById: 139 139 case ToThis: 140 case MultiGetByOffset: 140 141 // These are OK. 141 142 break; -
trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp
r164069 r164207 248 248 OSRExit& exit = jitCode->osrExit[i]; 249 249 250 if ( Options::verboseCompilation())250 if (verboseCompilationEnabled()) 251 251 dataLog("Handling OSR stackmap #", exit.m_stackmapID, " for ", exit.m_codeOrigin, "\n"); 252 252 … … 270 270 } 271 271 272 if ( Options::verboseCompilation()) {272 if (verboseCompilationEnabled()) { 273 273 DumpContext context; 274 274 dataLog(" Exit values: ", inContext(exit.m_values, &context), "\n"); … … 287 287 GetByIdDescriptor& getById = state.getByIds[i]; 288 288 289 if ( Options::verboseCompilation())289 if (verboseCompilationEnabled()) 290 290 dataLog("Handling GetById stackmap #", getById.stackmapID(), "\n"); 291 291 … … 325 325 PutByIdDescriptor& putById = state.putByIds[i]; 326 326 327 if ( Options::verboseCompilation())327 if (verboseCompilationEnabled()) 328 328 dataLog("Handling PutById stackmap #", putById.stackmapID(), "\n"); 329 329 … … 542 542 } 543 543 544 if ( DFG::shouldShowDisassembly() || DFG::verboseCompilationEnabled())544 if (shouldShowDisassembly() || verboseCompilationEnabled()) 545 545 state.dumpState("after optimization"); 546 546 … … 578 578 state.jitCode->unwindInfo.parse( 579 579 state.compactUnwind, state.compactUnwindSize, state.generatedFunction); 580 if ( DFG::shouldShowDisassembly())580 if (shouldShowDisassembly()) 581 581 dataLog("Unwind info for ", CodeBlockWithJITType(state.graph.m_codeBlock, JITCode::FTLJIT), ":\n ", state.jitCode->unwindInfo, "\n"); 582 582 -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
r164178 r164207 464 464 case GetByOffset: 465 465 compileGetByOffset(); 466 break; 467 case MultiGetByOffset: 468 compileMultiGetByOffset(); 466 469 break; 467 470 case PutByOffset: … … 3076 3079 } 3077 3080 3081 void compileMultiGetByOffset() 3082 { 3083 LValue base = lowCell(m_node->child1()); 3084 3085 MultiGetByOffsetData& data = m_node->multiGetByOffsetData(); 3086 3087 Vector<LBasicBlock, 2> blocks(data.variants.size()); 3088 for (unsigned i = data.variants.size(); i--;) 3089 blocks[i] = FTL_NEW_BLOCK(m_out, ("MultiGetByOffset case ", i)); 3090 LBasicBlock exit = FTL_NEW_BLOCK(m_out, ("MultiGetByOffset fail")); 3091 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("MultiGetByOffset continuation")); 3092 3093 Vector<SwitchCase, 2> cases; 3094 for (unsigned i = data.variants.size(); i--;) { 3095 GetByIdVariant variant = data.variants[i]; 3096 for (unsigned j = variant.structureSet().size(); j--;) 3097 cases.append(SwitchCase(weakPointer(variant.structureSet()[j]), blocks[i])); 3098 } 3099 m_out.switchInstruction(m_out.loadPtr(base, m_heaps.JSCell_structure), cases, exit); 3100 3101 LBasicBlock lastNext = m_out.m_nextBlock; 3102 3103 Vector<ValueFromBlock, 2> results; 3104 for (unsigned i = data.variants.size(); i--;) { 3105 m_out.appendTo(blocks[i], i + 1 < data.variants.size() ? blocks[i + 1] : exit); 3106 3107 GetByIdVariant variant = data.variants[i]; 3108 LValue result; 3109 if (variant.specificValue()) 3110 result = m_out.constInt64(JSValue::encode(variant.specificValue())); 3111 else { 3112 LValue propertyBase; 3113 if (variant.chain()) 3114 propertyBase = weakPointer(variant.chain()->terminalPrototype()); 3115 else 3116 propertyBase = base; 3117 if (!isInlineOffset(variant.offset())) 3118 propertyBase = m_out.loadPtr(propertyBase, m_heaps.JSObject_butterfly); 3119 result = m_out.load64( 3120 m_out.address( 3121 m_heaps.properties[data.identifierNumber], 3122 propertyBase, 3123 offsetRelativeToBase(variant.offset()))); 3124 } 3125 3126 results.append(m_out.anchor(result)); 3127 m_out.jump(continuation); 3128 } 3129 3130 m_out.appendTo(exit, continuation); 3131 terminate(BadCache); 3132 m_out.unreachable(); 3133 3134 m_out.appendTo(continuation, lastNext); 3135 setJSValue(m_out.phi(m_out.int64, results)); 3136 } 3137 3078 3138 void compilePutByOffset() 3079 3139 { -
trunk/Source/JavaScriptCore/ftl/FTLState.h
r164069 r164207 31 31 #if ENABLE(FTL_JIT) 32 32 33 #include "DFGCommon.h" 33 34 #include "DFGGraph.h" 34 35 #include "FTLAbbreviations.h" … … 42 43 43 44 namespace JSC { namespace FTL { 45 46 inline bool verboseCompilationEnabled() 47 { 48 return DFG::verboseCompilationEnabled(DFG::FTLMode); 49 } 50 51 inline bool showDisassembly() 52 { 53 return DFG::shouldShowDisassembly(DFG::FTLMode); 54 } 44 55 45 56 class State { -
trunk/Source/JavaScriptCore/jsc.cpp
r164059 r164207 239 239 static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*); 240 240 static EncodedJSValue JSC_HOST_CALL functionFalse(ExecState*); 241 static EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*); 241 242 242 243 #if ENABLE(SAMPLING_FLAGS) … … 374 375 putDirectNativeFunction(vm, this, Identifier(&vm, "DFGTrue"), 0, functionFalse, DFGTrue, DontEnum | JSC::Function); 375 376 377 addFunction(vm, "effectful42", functionEffectful42, 0); 378 376 379 JSArray* array = constructEmptyArray(globalExec(), 0); 377 380 for (size_t i = 0; i < arguments.size(); ++i) … … 726 729 { 727 730 return JSValue::encode(jsBoolean(false)); 731 } 732 733 EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*) 734 { 735 return JSValue::encode(jsNumber(42)); 728 736 } 729 737 -
trunk/Source/JavaScriptCore/runtime/IntendedStructureChain.cpp
r163844 r164207 30 30 #include "JSCInlines.h" 31 31 #include "StructureChain.h" 32 #include <wtf/CommaPrinter.h> 32 33 33 34 namespace JSC { … … 146 147 } 147 148 149 void IntendedStructureChain::dump(PrintStream& out) const 150 { 151 dumpInContext(out, 0); 152 } 153 154 void IntendedStructureChain::dumpInContext(PrintStream& out, DumpContext* context) const 155 { 156 out.print( 157 "(global = ", RawPointer(m_globalObject), ", head = ", 158 pointerDumpInContext(m_head, context), ", vector = ["); 159 CommaPrinter comma; 160 for (unsigned i = 0; i < m_vector.size(); ++i) 161 out.print(comma, pointerDumpInContext(m_vector[i], context)); 162 out.print("])"); 163 } 164 148 165 } // namespace JSC 149 166 -
trunk/Source/JavaScriptCore/runtime/IntendedStructureChain.h
r163691 r164207 36 36 class StructureChain; 37 37 class VM; 38 struct DumpContext; 38 39 39 40 class IntendedStructureChain : public RefCounted<IntendedStructureChain> { … … 62 63 63 64 void visitChildren(SlotVisitor&); 65 void dump(PrintStream&) const; 66 void dumpInContext(PrintStream&, DumpContext*) const; 64 67 65 68 private: -
trunk/Source/JavaScriptCore/runtime/Options.cpp
r163794 r164207 190 190 if (Options::showDisassembly() 191 191 || Options::showDFGDisassembly() 192 || Options::showFTLDisassembly() 192 193 || Options::dumpBytecodeAtDFGTime() 193 194 || Options::dumpGraphAtEachPhase() 194 195 || Options::verboseCompilation() 196 || Options::verboseFTLCompilation() 195 197 || Options::logCompilationChanges() 196 198 || Options::validateGraph() -
trunk/Source/JavaScriptCore/runtime/Options.h
r163838 r164207 113 113 v(bool, showDisassembly, false) \ 114 114 v(bool, showDFGDisassembly, false) \ 115 v(bool, showFTLDisassembly, false) \ 115 116 v(bool, showAllDFGNodes, false) \ 116 117 v(optionRange, bytecodeRangeToDFGCompile, 0) \ … … 118 119 v(bool, dumpGraphAtEachPhase, false) \ 119 120 v(bool, verboseCompilation, false) \ 121 v(bool, verboseFTLCompilation, false) \ 120 122 v(bool, logCompilationChanges, false) \ 121 123 v(bool, printEachOSRExit, false) \ -
trunk/Source/WTF/ChangeLog
r164190 r164207 1 2014-02-15 Filip Pizlo <fpizlo@apple.com> 2 3 FTL should inline polymorphic heap accesses 4 https://bugs.webkit.org/show_bug.cgi?id=128795 5 6 Reviewed by Oliver Hunt. 7 8 * wtf/PrintStream.h: 9 (WTF::PointerDumpInContext::PointerDumpInContext): 10 (WTF::PointerDumpInContext::dump): 11 (WTF::pointerDumpInContext): 12 1 13 2014-02-16 Zan Dobersek <zdobersek@igalia.com> 2 14 -
trunk/Source/WTF/wtf/PrintStream.h
r159448 r164207 366 366 367 367 template<typename T, typename U> 368 class PointerDumpInContext { 369 public: 370 PointerDumpInContext(const T* ptr, U* context) 371 : m_ptr(ptr) 372 , m_context(context) 373 { 374 } 375 376 void dump(PrintStream& out) const 377 { 378 if (m_ptr) 379 m_ptr->dumpInContext(out, m_context); 380 else 381 out.print("(null)"); 382 } 383 384 private: 385 const T* m_ptr; 386 U* m_context; 387 }; 388 389 template<typename T, typename U> 390 PointerDumpInContext<T, U> pointerDumpInContext(const T* ptr, U* context) 391 { 392 return PointerDumpInContext<T, U>(ptr, context); 393 } 394 395 template<typename T, typename U> 368 396 class ValueIgnoringContext { 369 397 public: … … 397 425 using WTF::inContext; 398 426 using WTF::pointerDump; 427 using WTF::pointerDumpInContext; 399 428 400 429 #endif // PrintStream_h
Note: See TracChangeset
for help on using the changeset viewer.