Changeset 188105 in webkit
- Timestamp:
- Aug 6, 2015 7:08:07 PM (9 years ago)
- Location:
- trunk
- Files:
-
- 51 added
- 38 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r188085 r188105 1 2015-08-06 Yusuke Suzuki <utatane.tea@gmail.com> 2 3 Introduce get_by_id like IC into get_by_val when the given name is String or Symbol 4 https://bugs.webkit.org/show_bug.cgi?id=147480 5 6 Reviewed by Filip Pizlo. 7 8 Add synthetic benchmarks that replaces normal property load with symbol/string keyed load. 9 10 * js/regress/get-by-val-with-string-bimorphic-check-structure-elimination-expected.txt: Added. 11 * js/regress/get-by-val-with-string-bimorphic-check-structure-elimination-simple-expected.txt: Added. 12 * js/regress/get-by-val-with-string-bimorphic-check-structure-elimination-simple.html: Added. 13 * js/regress/get-by-val-with-string-bimorphic-check-structure-elimination.html: Added. 14 * js/regress/get-by-val-with-string-chain-from-try-block-expected.txt: Added. 15 * js/regress/get-by-val-with-string-chain-from-try-block.html: Added. 16 * js/regress/get-by-val-with-string-check-structure-elimination-expected.txt: Added. 17 * js/regress/get-by-val-with-string-check-structure-elimination.html: Added. 18 * js/regress/get-by-val-with-string-proto-or-self-expected.txt: Added. 19 * js/regress/get-by-val-with-string-proto-or-self.html: Added. 20 * js/regress/get-by-val-with-string-quadmorphic-check-structure-elimination-simple-expected.txt: Added. 21 * js/regress/get-by-val-with-string-quadmorphic-check-structure-elimination-simple.html: Added. 22 * js/regress/get-by-val-with-string-self-or-proto-expected.txt: Added. 23 * js/regress/get-by-val-with-string-self-or-proto.html: Added. 24 * js/regress/get-by-val-with-symbol-bimorphic-check-structure-elimination-expected.txt: Added. 25 * js/regress/get-by-val-with-symbol-bimorphic-check-structure-elimination-simple-expected.txt: Added. 26 * js/regress/get-by-val-with-symbol-bimorphic-check-structure-elimination-simple.html: Added. 27 * js/regress/get-by-val-with-symbol-bimorphic-check-structure-elimination.html: Added. 28 * js/regress/get-by-val-with-symbol-chain-from-try-block-expected.txt: Added. 29 * js/regress/get-by-val-with-symbol-chain-from-try-block.html: Added. 30 * js/regress/get-by-val-with-symbol-check-structure-elimination-expected.txt: Added. 31 * js/regress/get-by-val-with-symbol-check-structure-elimination.html: Added. 32 * js/regress/get-by-val-with-symbol-proto-or-self-expected.txt: Added. 33 * js/regress/get-by-val-with-symbol-proto-or-self.html: Added. 34 * js/regress/get-by-val-with-symbol-quadmorphic-check-structure-elimination-simple-expected.txt: Added. 35 * js/regress/get-by-val-with-symbol-quadmorphic-check-structure-elimination-simple.html: Added. 36 * js/regress/get-by-val-with-symbol-self-or-proto-expected.txt: Added. 37 * js/regress/get-by-val-with-symbol-self-or-proto.html: Added. 38 * js/regress/script-tests/get-by-val-with-string-bimorphic-check-structure-elimination-simple.js: Added. 39 * js/regress/script-tests/get-by-val-with-string-bimorphic-check-structure-elimination.js: Added. 40 * js/regress/script-tests/get-by-val-with-string-chain-from-try-block.js: Added. 41 (A): 42 (B): 43 (C): 44 (D): 45 (E): 46 (F): 47 (G): 48 (foo): 49 * js/regress/script-tests/get-by-val-with-string-check-structure-elimination.js: Added. 50 * js/regress/script-tests/get-by-val-with-string-proto-or-self.js: Added. 51 (foo): 52 (bar): 53 (Foo): 54 * js/regress/script-tests/get-by-val-with-string-quadmorphic-check-structure-elimination-simple.js: Added. 55 * js/regress/script-tests/get-by-val-with-string-self-or-proto.js: Added. 56 (foo): 57 (bar): 58 (Foo): 59 * js/regress/script-tests/get-by-val-with-symbol-bimorphic-check-structure-elimination-simple.js: Added. 60 * js/regress/script-tests/get-by-val-with-symbol-bimorphic-check-structure-elimination.js: Added. 61 * js/regress/script-tests/get-by-val-with-symbol-chain-from-try-block.js: Added. 62 (A): 63 (B): 64 (C): 65 (D): 66 (E): 67 (F): 68 (G): 69 (foo): 70 * js/regress/script-tests/get-by-val-with-symbol-check-structure-elimination.js: Added. 71 * js/regress/script-tests/get-by-val-with-symbol-proto-or-self.js: Added. 72 (foo): 73 (bar): 74 (Foo): 75 * js/regress/script-tests/get-by-val-with-symbol-quadmorphic-check-structure-elimination-simple.js: Added. 76 * js/regress/script-tests/get-by-val-with-symbol-self-or-proto.js: Added. 77 (foo): 78 (bar): 79 (Foo): 80 1 81 2015-08-06 Keith Miller <keith_miller@apple.com> 2 82 -
trunk/Source/JavaScriptCore/ChangeLog
r188100 r188105 1 2015-08-06 Yusuke Suzuki <utatane.tea@gmail.com> 2 3 Introduce get_by_id like IC into get_by_val when the given name is String or Symbol 4 https://bugs.webkit.org/show_bug.cgi?id=147480 5 6 Reviewed by Filip Pizlo. 7 8 This patch adds get_by_id IC to get_by_val operation by caching the string / symbol id. 9 The IC site only caches one id. After checking that the given id is the same to the 10 cached one, we perform the get_by_id IC onto it. 11 And by collecting IC StructureStubInfo information, we pass it to the DFG and DFG 12 compiles get_by_val op code into CheckIdent (with edge type check) and GetById related 13 operations when the given get_by_val leverages the property load with the cached id. 14 15 To ensure the incoming value is the expected id, in DFG layer, we use SymbolUse and 16 StringIdentUse to enforce the type. To use it, this patch implements SymbolUse. 17 This can be leveraged to optimize symbol operations in DFG. 18 19 And since byValInfo is frequently used, we align the byValInfo design to the stubInfo like one. 20 Allocated by the Bag and operations take the raw byValInfo pointer directly instead of performing 21 binary search onto m_byValInfos. And by storing ArrayProfile* under the ByValInfo, we replaced the 22 argument ArrayProfile* in the operations with ByValInfo*. 23 24 * bytecode/ByValInfo.h: 25 (JSC::ByValInfo::ByValInfo): 26 * bytecode/CodeBlock.cpp: 27 (JSC::CodeBlock::getByValInfoMap): 28 (JSC::CodeBlock::addByValInfo): 29 * bytecode/CodeBlock.h: 30 (JSC::CodeBlock::getByValInfo): Deleted. 31 (JSC::CodeBlock::setNumberOfByValInfos): Deleted. 32 (JSC::CodeBlock::numberOfByValInfos): Deleted. 33 (JSC::CodeBlock::byValInfo): Deleted. 34 * bytecode/ExitKind.cpp: 35 (JSC::exitKindToString): 36 * bytecode/ExitKind.h: 37 * bytecode/GetByIdStatus.cpp: 38 (JSC::GetByIdStatus::computeFor): 39 (JSC::GetByIdStatus::computeForStubInfo): 40 (JSC::GetByIdStatus::computeForStubInfoWithoutExitSiteFeedback): 41 * bytecode/GetByIdStatus.h: 42 * dfg/DFGAbstractInterpreterInlines.h: 43 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 44 * dfg/DFGByteCodeParser.cpp: 45 (JSC::DFG::ByteCodeParser::parseBlock): 46 (JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry): 47 * dfg/DFGClobberize.h: 48 (JSC::DFG::clobberize): 49 * dfg/DFGConstantFoldingPhase.cpp: 50 (JSC::DFG::ConstantFoldingPhase::foldConstants): 51 * dfg/DFGDoesGC.cpp: 52 (JSC::DFG::doesGC): 53 * dfg/DFGFixupPhase.cpp: 54 (JSC::DFG::FixupPhase::fixupNode): 55 (JSC::DFG::FixupPhase::observeUseKindOnNode): 56 * dfg/DFGNode.h: 57 (JSC::DFG::Node::hasUidOperand): 58 (JSC::DFG::Node::uidOperand): 59 * dfg/DFGNodeType.h: 60 * dfg/DFGPredictionPropagationPhase.cpp: 61 (JSC::DFG::PredictionPropagationPhase::propagate): 62 * dfg/DFGSafeToExecute.h: 63 (JSC::DFG::SafeToExecuteEdge::operator()): 64 (JSC::DFG::safeToExecute): 65 * dfg/DFGSpeculativeJIT.cpp: 66 (JSC::DFG::SpeculativeJIT::compileCheckIdent): 67 (JSC::DFG::SpeculativeJIT::speculateSymbol): 68 (JSC::DFG::SpeculativeJIT::speculate): 69 * dfg/DFGSpeculativeJIT.h: 70 * dfg/DFGSpeculativeJIT32_64.cpp: 71 (JSC::DFG::SpeculativeJIT::compile): 72 * dfg/DFGSpeculativeJIT64.cpp: 73 (JSC::DFG::SpeculativeJIT::compile): 74 * dfg/DFGUseKind.cpp: 75 (WTF::printInternal): 76 * dfg/DFGUseKind.h: 77 (JSC::DFG::typeFilterFor): 78 (JSC::DFG::isCell): 79 * ftl/FTLAbstractHeapRepository.h: 80 * ftl/FTLCapabilities.cpp: 81 (JSC::FTL::canCompile): 82 * ftl/FTLLowerDFGToLLVM.cpp: 83 (JSC::FTL::DFG::LowerDFGToLLVM::compileNode): 84 (JSC::FTL::DFG::LowerDFGToLLVM::compileCheckIdent): 85 (JSC::FTL::DFG::LowerDFGToLLVM::lowSymbol): 86 (JSC::FTL::DFG::LowerDFGToLLVM::speculate): 87 (JSC::FTL::DFG::LowerDFGToLLVM::isNotSymbol): 88 (JSC::FTL::DFG::LowerDFGToLLVM::speculateSymbol): 89 * jit/JIT.cpp: 90 (JSC::JIT::privateCompile): 91 * jit/JIT.h: 92 (JSC::ByValCompilationInfo::ByValCompilationInfo): 93 (JSC::JIT::compileGetByValWithCachedId): 94 * jit/JITInlines.h: 95 (JSC::JIT::callOperation): 96 * jit/JITOpcodes.cpp: 97 (JSC::JIT::emit_op_has_indexed_property): 98 (JSC::JIT::emitSlow_op_has_indexed_property): 99 * jit/JITOpcodes32_64.cpp: 100 (JSC::JIT::emit_op_has_indexed_property): 101 (JSC::JIT::emitSlow_op_has_indexed_property): 102 * jit/JITOperations.cpp: 103 (JSC::getByVal): 104 * jit/JITOperations.h: 105 * jit/JITPropertyAccess.cpp: 106 (JSC::JIT::emit_op_get_by_val): 107 (JSC::JIT::emitGetByValWithCachedId): 108 (JSC::JIT::emitSlow_op_get_by_val): 109 (JSC::JIT::emit_op_put_by_val): 110 (JSC::JIT::emitSlow_op_put_by_val): 111 (JSC::JIT::privateCompileGetByVal): 112 (JSC::JIT::privateCompileGetByValWithCachedId): 113 * jit/JITPropertyAccess32_64.cpp: 114 (JSC::JIT::emit_op_get_by_val): 115 (JSC::JIT::emitGetByValWithCachedId): 116 (JSC::JIT::emitSlow_op_get_by_val): 117 (JSC::JIT::emit_op_put_by_val): 118 (JSC::JIT::emitSlow_op_put_by_val): 119 * runtime/Symbol.h: 120 * tests/stress/get-by-val-with-string-constructor.js: Added. 121 (Hello): 122 (get Hello.prototype.generate): 123 (ok): 124 * tests/stress/get-by-val-with-string-exit.js: Added. 125 (shouldBe): 126 (getByVal): 127 (getStr1): 128 (getStr2): 129 * tests/stress/get-by-val-with-string-generated.js: Added. 130 (shouldBe): 131 (getByVal): 132 (getStr1): 133 (getStr2): 134 * tests/stress/get-by-val-with-string-getter.js: Added. 135 (object.get hello): 136 (ok): 137 * tests/stress/get-by-val-with-string.js: Added. 138 (shouldBe): 139 (getByVal): 140 (getStr1): 141 (getStr2): 142 * tests/stress/get-by-val-with-symbol-constructor.js: Added. 143 (Hello): 144 (get Hello.prototype.generate): 145 (ok): 146 * tests/stress/get-by-val-with-symbol-exit.js: Added. 147 (shouldBe): 148 (getByVal): 149 (getSym1): 150 (getSym2): 151 * tests/stress/get-by-val-with-symbol-getter.js: Added. 152 (object.get hello): 153 (.get ok): 154 * tests/stress/get-by-val-with-symbol.js: Added. 155 (shouldBe): 156 (getByVal): 157 (getSym1): 158 (getSym2): 159 1 160 2015-08-05 Filip Pizlo <fpizlo@apple.com> 2 161 -
trunk/Source/JavaScriptCore/bytecode/ByValInfo.h
r181993 r188105 27 27 #define ByValInfo_h 28 28 29 #if ENABLE(JIT)30 31 29 #include "ClassInfo.h" 32 30 #include "CodeLocation.h" 31 #include "CodeOrigin.h" 33 32 #include "IndexingType.h" 34 33 #include "JITStubRoutine.h" 35 34 #include "Structure.h" 35 #include "StructureStubInfo.h" 36 36 37 37 namespace JSC { 38 39 #if ENABLE(JIT) 38 40 39 41 enum JITArrayMode { … … 202 204 struct ByValInfo { 203 205 ByValInfo() { } 204 205 ByValInfo(unsigned bytecodeIndex, CodeLocationJump badTypeJump, JITArrayMode arrayMode, int16_t badTypeJumpToDone, int16_t returnAddressToSlowPath)206 207 ByValInfo(unsigned bytecodeIndex, CodeLocationJump notIndexJump, CodeLocationJump badTypeJump, JITArrayMode arrayMode, ArrayProfile* arrayProfile, int16_t badTypeJumpToDone, int16_t returnAddressToSlowPath) 206 208 : bytecodeIndex(bytecodeIndex) 209 , notIndexJump(notIndexJump) 207 210 , badTypeJump(badTypeJump) 208 211 , arrayMode(arrayMode) 212 , arrayProfile(arrayProfile) 209 213 , badTypeJumpToDone(badTypeJumpToDone) 210 214 , returnAddressToSlowPath(returnAddressToSlowPath) 211 215 , slowPathCount(0) 216 , stubInfo(nullptr) 217 , tookSlowPath(false) 212 218 { 213 219 } 214 220 215 221 unsigned bytecodeIndex; 222 CodeLocationJump notIndexJump; 216 223 CodeLocationJump badTypeJump; 217 224 JITArrayMode arrayMode; // The array mode that was baked into the inline JIT code. 225 ArrayProfile* arrayProfile; 218 226 int16_t badTypeJumpToDone; 219 227 int16_t returnAddressToSlowPath; 220 228 unsigned slowPathCount; 221 229 RefPtr<JITStubRoutine> stubRoutine; 230 Identifier cachedId; 231 StructureStubInfo* stubInfo; 232 bool tookSlowPath; 222 233 }; 223 234 … … 227 238 } 228 239 240 typedef HashMap<CodeOrigin, ByValInfo*, CodeOriginApproximateHash> ByValInfoMap; 241 242 #else // ENABLE(JIT) 243 244 typedef HashMap<int, void*> ByValInfoMap; 245 246 #endif // ENABLE(JIT) 247 229 248 } // namespace JSC 230 249 231 #endif // ENABLE(JIT)232 233 250 #endif // ByValInfo_h 234 251 -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r187969 r188105 2674 2674 } 2675 2675 2676 void CodeBlock::getByValInfoMap(const ConcurrentJITLocker&, ByValInfoMap& result) 2677 { 2678 #if ENABLE(JIT) 2679 for (auto* byValInfo : m_byValInfos) 2680 result.add(CodeOrigin(byValInfo->bytecodeIndex), byValInfo); 2681 #else 2682 UNUSED_PARAM(result); 2683 #endif 2684 } 2685 2686 void CodeBlock::getByValInfoMap(ByValInfoMap& result) 2687 { 2688 ConcurrentJITLocker locker(m_lock); 2689 getByValInfoMap(locker, result); 2690 } 2691 2676 2692 #if ENABLE(JIT) 2677 2693 StructureStubInfo* CodeBlock::addStubInfo() … … 2688 2704 } 2689 2705 return nullptr; 2706 } 2707 2708 ByValInfo* CodeBlock::addByValInfo() 2709 { 2710 ConcurrentJITLocker locker(m_lock); 2711 return m_byValInfos.add(); 2690 2712 } 2691 2713 -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.h
r187524 r188105 201 201 void getCallLinkInfoMap(const ConcurrentJITLocker&, CallLinkInfoMap& result); 202 202 void getCallLinkInfoMap(CallLinkInfoMap& result); 203 204 void getByValInfoMap(const ConcurrentJITLocker&, ByValInfoMap& result); 205 void getByValInfoMap(ByValInfoMap& result); 203 206 204 207 #if ENABLE(JIT) … … 212 215 213 216 void resetStub(StructureStubInfo&); 214 215 ByValInfo& getByValInfo(unsigned bytecodeIndex) 216 { 217 return *(binarySearch<ByValInfo, unsigned>(m_byValInfos, m_byValInfos.size(), bytecodeIndex, getByValInfoBytecodeIndex)); 218 } 217 218 ByValInfo* addByValInfo(); 219 219 220 220 CallLinkInfo* addCallLinkInfo(); … … 367 367 368 368 String nameForRegister(VirtualRegister); 369 370 #if ENABLE(JIT)371 void setNumberOfByValInfos(size_t size) { m_byValInfos.resizeToFit(size); }372 size_t numberOfByValInfos() const { return m_byValInfos.size(); }373 ByValInfo& byValInfo(size_t index) { return m_byValInfos[index]; }374 #endif375 369 376 370 unsigned numberOfArgumentValueProfiles() … … 1017 1011 #if ENABLE(JIT) 1018 1012 Bag<StructureStubInfo> m_stubInfos; 1019 Vector<ByValInfo> m_byValInfos;1013 Bag<ByValInfo> m_byValInfos; 1020 1014 Bag<CallLinkInfo> m_callLinkInfos; 1021 1015 SentinelLinkedList<CallLinkInfo, BasicRawSentinelNode<CallLinkInfo>> m_incomingCalls; -
trunk/Source/JavaScriptCore/bytecode/ExitKind.cpp
r181466 r188105 41 41 case BadCell: 42 42 return "BadCell"; 43 case BadIdent: 44 return "BadIdent"; 43 45 case BadExecutable: 44 46 return "BadExecutable"; -
trunk/Source/JavaScriptCore/bytecode/ExitKind.h
r181466 r188105 33 33 BadType, // We exited because a type prediction was wrong. 34 34 BadCell, // We exited because we made an incorrect assumption about what cell we would see. Usually used for function checks. 35 BadIdent, // We exited because we made an incorrect assumption about what identifier we would see. Usually used for cached Id check in get_by_val. 35 36 BadExecutable, // We exited because we made an incorrect assumption about what executable we would see. 36 37 BadCache, // We exited because an inline cache was wrong. -
trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp
r187780 r188105 99 99 100 100 #if ENABLE(DFG_JIT) 101 result = computeForStubInfo (101 result = computeForStubInfoWithoutExitSiteFeedback( 102 102 locker, profiledBlock, map.get(CodeOrigin(bytecodeIndex)), uid, 103 103 CallLinkStatus::computeExitSiteData(locker, profiledBlock, bytecodeIndex)); … … 117 117 118 118 #if ENABLE(JIT) 119 GetByIdStatus GetByIdStatus::computeForStubInfo( 119 GetByIdStatus GetByIdStatus::computeForStubInfo(const ConcurrentJITLocker& locker, CodeBlock* profiledBlock, StructureStubInfo* stubInfo, CodeOrigin codeOrigin, UniquedStringImpl* uid) 120 { 121 GetByIdStatus result = GetByIdStatus::computeForStubInfoWithoutExitSiteFeedback( 122 locker, profiledBlock, stubInfo, uid, 123 CallLinkStatus::computeExitSiteData(locker, profiledBlock, codeOrigin.bytecodeIndex)); 124 125 if (!result.takesSlowPath() && GetByIdStatus::hasExitSite(locker, profiledBlock, codeOrigin.bytecodeIndex)) 126 return GetByIdStatus(result.makesCalls() ? GetByIdStatus::MakesCalls : GetByIdStatus::TakesSlowPath, true); 127 return result; 128 } 129 #endif // ENABLE(JIT) 130 131 #if ENABLE(JIT) 132 GetByIdStatus GetByIdStatus::computeForStubInfoWithoutExitSiteFeedback( 120 133 const ConcurrentJITLocker& locker, CodeBlock* profiledBlock, StructureStubInfo* stubInfo, UniquedStringImpl* uid, 121 134 CallLinkStatus::ExitSiteData callExitSiteData) … … 243 256 { 244 257 ConcurrentJITLocker locker(dfgBlock->m_lock); 245 result = computeForStubInfo (258 result = computeForStubInfoWithoutExitSiteFeedback( 246 259 locker, dfgBlock, dfgMap.get(codeOrigin), uid, exitSiteData); 247 260 } -
trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.h
r185103 r188105 72 72 73 73 static GetByIdStatus computeFor(CodeBlock* baselineBlock, CodeBlock* dfgBlock, StubInfoMap& baselineMap, StubInfoMap& dfgMap, CodeOrigin, UniquedStringImpl* uid); 74 74 75 #if ENABLE(JIT) 76 static GetByIdStatus computeForStubInfo(const ConcurrentJITLocker&, CodeBlock* baselineBlock, StructureStubInfo*, CodeOrigin, UniquedStringImpl* uid); 77 #endif 78 75 79 State state() const { return m_state; } 76 80 … … 96 100 #endif 97 101 #if ENABLE(JIT) 98 static GetByIdStatus computeForStubInfo (102 static GetByIdStatus computeForStubInfoWithoutExitSiteFeedback( 99 103 const ConcurrentJITLocker&, CodeBlock* profiledBlock, StructureStubInfo*, 100 104 UniquedStringImpl* uid, CallLinkStatus::ExitSiteData); -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r187780 r188105 2164 2164 } 2165 2165 2166 case CheckIdent: { 2167 AbstractValue& value = forNode(node->child1()); 2168 UniquedStringImpl* uid = node->uidOperand(); 2169 ASSERT(uid->isSymbol() ? !(value.m_type & ~SpecSymbol) : !(value.m_type & ~SpecStringIdent)); // Edge filtering should have already ensured this. 2170 2171 JSValue childConstant = value.value(); 2172 if (childConstant) { 2173 if (uid->isSymbol()) { 2174 ASSERT(childConstant.isSymbol()); 2175 if (asSymbol(childConstant)->privateName().uid() == uid) { 2176 m_state.setFoundConstants(true); 2177 break; 2178 } 2179 } else { 2180 ASSERT(childConstant.isString()); 2181 if (asString(childConstant)->tryGetValueImpl() == uid) { 2182 m_state.setFoundConstants(true); 2183 break; 2184 } 2185 } 2186 } 2187 2188 filter(value, uid->isSymbol() ? SpecSymbol : SpecStringIdent); 2189 break; 2190 } 2191 2166 2192 case CheckInBounds: { 2167 2193 JSValue left = forNode(node->child1()).value(); -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r187780 r188105 970 970 CallLinkInfoMap m_callLinkInfos; 971 971 StubInfoMap m_stubInfos; 972 ByValInfoMap m_byValInfos; 972 973 973 974 // Did we see any returns? We need to handle the (uncommon but necessary) … … 3398 3399 case op_get_by_val: { 3399 3400 SpeculatedType prediction = getPredictionWithoutOSRExit(); 3400 3401 3401 3402 Node* base = get(VirtualRegister(currentInstruction[2].u.operand)); 3402 ArrayMode arrayMode = getArrayMode(currentInstruction[4].u.arrayProfile, Array::Read);3403 3403 Node* property = get(VirtualRegister(currentInstruction[3].u.operand)); 3404 Node* getByVal = addToGraph(GetByVal, OpInfo(arrayMode.asWord()), OpInfo(prediction), base, property); 3405 set(VirtualRegister(currentInstruction[1].u.operand), getByVal); 3404 bool compiledAsGetById = false; 3405 { 3406 ConcurrentJITLocker locker(m_inlineStackTop->m_profiledBlock->m_lock); 3407 ByValInfo* byValInfo = m_inlineStackTop->m_byValInfos.get(CodeOrigin(currentCodeOrigin().bytecodeIndex)); 3408 // FIXME: When the bytecode is not compiled in the baseline JIT, byValInfo becomes null. 3409 // At that time, there is no information. 3410 if (byValInfo && byValInfo->stubInfo && !byValInfo->tookSlowPath && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIdent)) { 3411 compiledAsGetById = true; 3412 unsigned identifierNumber = m_graph.identifiers().ensure(byValInfo->cachedId.impl()); 3413 UniquedStringImpl* uid = m_graph.identifiers()[identifierNumber]; 3414 3415 addToGraph(CheckIdent, OpInfo(uid), property); 3416 3417 GetByIdStatus getByIdStatus = GetByIdStatus::computeForStubInfo( 3418 locker, m_inlineStackTop->m_profiledBlock, 3419 byValInfo->stubInfo, currentCodeOrigin(), uid); 3420 3421 handleGetById(currentInstruction[1].u.operand, prediction, base, identifierNumber, getByIdStatus); 3422 } 3423 } 3424 3425 if (!compiledAsGetById) { 3426 ArrayMode arrayMode = getArrayMode(currentInstruction[4].u.arrayProfile, Array::Read); 3427 Node* getByVal = addToGraph(GetByVal, OpInfo(arrayMode.asWord()), OpInfo(prediction), base, property); 3428 set(VirtualRegister(currentInstruction[1].u.operand), getByVal); 3429 } 3406 3430 3407 3431 NEXT_OPCODE(op_get_by_val); … … 4306 4330 m_profiledBlock->getStubInfoMap(locker, m_stubInfos); 4307 4331 m_profiledBlock->getCallLinkInfoMap(locker, m_callLinkInfos); 4332 m_profiledBlock->getByValInfoMap(locker, m_byValInfos); 4308 4333 } 4309 4334 } -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r187555 r188105 269 269 return; 270 270 271 case CheckIdent: 272 def(PureValue(CheckIdent, AdjacencyList(AdjacencyList::Fixed, node->child1()), node->uidOperand())); 273 return; 274 271 275 case ConstantStoragePointer: 272 276 def(PureValue(node, node->storagePointer())); -
trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
r187780 r188105 209 209 } 210 210 211 case CheckIdent: { 212 UniquedStringImpl* uid = node->uidOperand(); 213 JSValue childConstant = m_state.forNode(node->child1()).value(); 214 const UniquedStringImpl* constantUid = nullptr; 215 if (childConstant) { 216 if (uid->isSymbol()) { 217 if (childConstant.isSymbol()) 218 constantUid = asSymbol(childConstant)->privateName().uid(); 219 } else { 220 if (childConstant.isString()) { 221 // Since we already filtered the value with StringIdentUse, 222 // the held impl is always atomic. 223 if (const auto* impl = asString(childConstant)->tryGetValueImpl()) { 224 ASSERT(impl->isAtomic()); 225 constantUid = static_cast<const UniquedStringImpl*>(impl); 226 } 227 } 228 } 229 } 230 231 if (constantUid == uid) { 232 node->remove(); 233 eliminated = true; 234 } 235 break; 236 } 237 211 238 case CheckInBounds: { 212 239 JSValue left = m_state.forNode(node->child1()).value(); -
trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
r187555 r188105 108 108 case CheckCell: 109 109 case CheckNotEmpty: 110 case CheckIdent: 110 111 case RegExpExec: 111 112 case RegExpTest: -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r187555 r188105 1013 1013 break; 1014 1014 } 1015 1016 case CheckIdent: { 1017 UniquedStringImpl* uid = node->uidOperand(); 1018 if (uid->isSymbol()) 1019 fixEdge<SymbolUse>(node->child1()); 1020 else 1021 fixEdge<StringIdentUse>(node->child1()); 1022 break; 1023 } 1015 1024 1016 1025 case Arrayify: … … 1761 1770 case StringUse: 1762 1771 case KnownStringUse: 1772 case SymbolUse: 1763 1773 case StringObjectUse: 1764 1774 case StringOrStringObjectUse: -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r187780 r188105 1329 1329 } 1330 1330 1331 bool hasUidOperand() 1332 { 1333 return op() == CheckIdent; 1334 } 1335 1336 UniquedStringImpl* uidOperand() 1337 { 1338 ASSERT(hasUidOperand()); 1339 return reinterpret_cast<UniquedStringImpl*>(m_opInfo); 1340 } 1341 1331 1342 bool hasTransition() 1332 1343 { -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r187555 r188105 210 210 macro(CheckBadCell, NodeMustGenerate) \ 211 211 macro(CheckInBounds, NodeMustGenerate) \ 212 macro(CheckIdent, NodeMustGenerate) \ 212 213 \ 213 214 /* Optimizations for array mutation. */\ -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r187555 r188105 650 650 case CheckCell: 651 651 case CheckNotEmpty: 652 case CheckIdent: 652 653 case CheckBadCell: 653 654 case PutStructure: -
trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
r187780 r188105 60 60 case StringIdentUse: 61 61 case StringUse: 62 case SymbolUse: 62 63 case StringObjectUse: 63 64 case StringOrStringObjectUse: … … 189 190 case CheckBadCell: 190 191 case CheckNotEmpty: 192 case CheckIdent: 191 193 case RegExpExec: 192 194 case RegExpTest: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r186860 r188105 4577 4577 } 4578 4578 4579 void SpeculativeJIT::compileCheckIdent(Node* node) 4580 { 4581 SpeculateCellOperand operand(this, node->child1()); 4582 UniquedStringImpl* uid = node->uidOperand(); 4583 if (uid->isSymbol()) { 4584 speculateSymbol(node->child1(), operand.gpr()); 4585 speculationCheck( 4586 BadIdent, JSValueSource(), nullptr, 4587 m_jit.branchPtr( 4588 JITCompiler::NotEqual, 4589 JITCompiler::Address(operand.gpr(), Symbol::offsetOfPrivateName()), 4590 TrustedImmPtr(uid))); 4591 } else { 4592 speculateString(node->child1(), operand.gpr()); 4593 speculateStringIdent(node->child1(), operand.gpr()); 4594 speculationCheck( 4595 BadIdent, JSValueSource(), nullptr, 4596 m_jit.branchPtr( 4597 JITCompiler::NotEqual, 4598 JITCompiler::Address(operand.gpr(), JSString::offsetOfValue()), 4599 TrustedImmPtr(uid))); 4600 } 4601 noResult(node); 4602 } 4603 4579 4604 void SpeculativeJIT::compileNewFunction(Node* node) 4580 4605 { … … 5732 5757 } 5733 5758 5759 void SpeculativeJIT::speculateSymbol(Edge edge, GPRReg cell) 5760 { 5761 DFG_TYPE_CHECK(JSValueSource::unboxedCell(cell), edge, SpecSymbol, m_jit.branchIfNotSymbol(cell)); 5762 } 5763 5764 void SpeculativeJIT::speculateSymbol(Edge edge) 5765 { 5766 if (!needsTypeCheck(edge, SpecSymbol)) 5767 return; 5768 5769 SpeculateCellOperand operand(this, edge); 5770 speculateSymbol(edge, operand.gpr()); 5771 } 5772 5734 5773 void SpeculativeJIT::speculateNotCell(Edge edge) 5735 5774 { … … 5842 5881 case StringUse: 5843 5882 speculateString(edge); 5883 break; 5884 case SymbolUse: 5885 speculateSymbol(edge); 5844 5886 break; 5845 5887 case StringObjectUse: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r186860 r188105 2192 2192 2193 2193 void compileGetArrayLength(Node*); 2194 2195 void compileCheckIdent(Node*); 2194 2196 2195 2197 void compileValueRep(Node*); … … 2407 2409 void speculateStringObject(Edge); 2408 2410 void speculateStringOrStringObject(Edge); 2411 void speculateSymbol(Edge, GPRReg cell); 2412 void speculateSymbol(Edge); 2409 2413 void speculateNotCell(Edge); 2410 2414 void speculateOther(Edge); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r187555 r188105 3821 3821 } 3822 3822 3823 case CheckIdent: 3824 compileCheckIdent(node); 3825 break; 3826 3823 3827 case GetExecutable: { 3824 3828 SpeculateCellOperand function(this, node->child1()); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r187555 r188105 3851 3851 } 3852 3852 3853 case CheckIdent: 3854 compileCheckIdent(node); 3855 break; 3856 3853 3857 case GetExecutable: { 3854 3858 SpeculateCellOperand function(this, node->child1()); -
trunk/Source/JavaScriptCore/dfg/DFGUseKind.cpp
r185239 r188105 98 98 out.print("KnownString"); 99 99 return; 100 case SymbolUse: 101 out.print("Symbol"); 102 return; 100 103 case StringObjectUse: 101 104 out.print("StringObject"); -
trunk/Source/JavaScriptCore/dfg/DFGUseKind.h
r185239 r188105 58 58 StringUse, 59 59 KnownStringUse, 60 SymbolUse, 60 61 StringObjectUse, 61 62 StringOrStringObjectUse, … … 118 119 case KnownStringUse: 119 120 return SpecString; 121 case SymbolUse: 122 return SpecSymbol; 120 123 case StringObjectUse: 121 124 return SpecStringObject; … … 197 200 case StringUse: 198 201 case KnownStringUse: 202 case SymbolUse: 199 203 case StringObjectUse: 200 204 case StringOrStringObjectUse: -
trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h
r182929 r188105 88 88 macro(Structure_globalObject, Structure::globalObjectOffset()) \ 89 89 macro(Structure_prototype, Structure::prototypeOffset()) \ 90 macro(Structure_structureID, Structure::structureIDOffset()) 90 macro(Structure_structureID, Structure::structureIDOffset()) \ 91 macro(Symbol_privateName, Symbol::offsetOfPrivateName()) 91 92 92 93 #define FOR_EACH_INDEXED_ABSTRACT_HEAP(macro) \ -
trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
r187555 r188105 119 119 case CheckBadCell: 120 120 case CheckNotEmpty: 121 case CheckIdent: 121 122 case StringCharCodeAt: 122 123 case AllocatePropertyStorage: … … 416 417 case StringObjectUse: 417 418 case StringOrStringObjectUse: 419 case SymbolUse: 418 420 case FinalObjectUse: 419 421 case NotCellUse: -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
r188086 r188105 533 533 compileCheckBadCell(); 534 534 break; 535 case CheckIdent: 536 compileCheckIdent(); 537 break; 535 538 case GetExecutable: 536 539 compileGetExecutable(); … … 2028 2031 { 2029 2032 speculate(TDZFailure, noValue(), nullptr, m_out.isZero64(lowJSValue(m_node->child1()))); 2033 } 2034 2035 void compileCheckIdent() 2036 { 2037 UniquedStringImpl* uid = m_node->uidOperand(); 2038 if (uid->isSymbol()) { 2039 LValue symbol = lowSymbol(m_node->child1()); 2040 LValue stringImpl = m_out.loadPtr(symbol, m_heaps.Symbol_privateName); 2041 speculate(BadIdent, noValue(), nullptr, m_out.notEqual(stringImpl, m_out.constIntPtr(uid))); 2042 } else { 2043 LValue string = lowStringIdent(m_node->child1()); 2044 LValue stringImpl = m_out.loadPtr(string, m_heaps.JSString_value); 2045 speculate(BadIdent, noValue(), nullptr, m_out.notEqual(stringImpl, m_out.constIntPtr(uid))); 2046 } 2030 2047 } 2031 2048 … … 7021 7038 return stringImpl; 7022 7039 } 7023 7040 7041 LValue lowSymbol(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation) 7042 { 7043 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == SymbolUse); 7044 7045 LValue result = lowCell(edge, mode); 7046 speculateSymbol(edge, result); 7047 return result; 7048 } 7049 7024 7050 LValue lowNonNullObject(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation) 7025 7051 { … … 7418 7444 speculateStringIdent(edge); 7419 7445 break; 7446 case SymbolUse: 7447 speculateSymbol(edge); 7448 break; 7420 7449 case StringObjectUse: 7421 7450 speculateStringObject(edge); … … 7514 7543 m_out.constInt32(vm().stringStructure->id())); 7515 7544 } 7516 7545 7546 LValue isNotSymbol(LValue cell, SpeculatedType type = SpecFullTop) 7547 { 7548 if (LValue proven = isProvenValue(type & SpecCell, ~SpecSymbol)) 7549 return proven; 7550 return m_out.notEqual( 7551 m_out.load32(cell, m_heaps.JSCell_structureID), 7552 m_out.constInt32(vm().symbolStructure->id())); 7553 } 7554 7517 7555 LValue isArrayType(LValue cell, ArrayMode arrayMode) 7518 7556 { … … 7737 7775 m_out.notEqual(structureID, weakStructureID(stringObjectStructure))); 7738 7776 } 7739 7777 7778 void speculateSymbol(Edge edge, LValue cell) 7779 { 7780 FTL_TYPE_CHECK(jsValueValue(cell), edge, SpecSymbol | ~SpecCell, isNotSymbol(cell)); 7781 } 7782 7783 void speculateSymbol(Edge edge) 7784 { 7785 speculateSymbol(edge, lowCell(edge)); 7786 } 7787 7740 7788 void speculateNonNullObject(Edge edge, LValue cell) 7741 7789 { -
trunk/Source/JavaScriptCore/jit/JIT.cpp
r187969 r188105 658 658 m_putByIds[i].finalize(patchBuffer); 659 659 660 m_codeBlock->setNumberOfByValInfos(m_byValCompilationInfo.size()); 661 for (unsigned i = 0; i < m_byValCompilationInfo.size(); ++i) { 662 CodeLocationJump badTypeJump = CodeLocationJump(patchBuffer.locationOf(m_byValCompilationInfo[i].badTypeJump)); 663 CodeLocationLabel doneTarget = patchBuffer.locationOf(m_byValCompilationInfo[i].doneTarget); 664 CodeLocationLabel slowPathTarget = patchBuffer.locationOf(m_byValCompilationInfo[i].slowPathTarget); 665 CodeLocationCall returnAddress = patchBuffer.locationOf(m_byValCompilationInfo[i].returnAddress); 666 667 m_codeBlock->byValInfo(i) = ByValInfo( 668 m_byValCompilationInfo[i].bytecodeIndex, 660 for (const auto& byValCompilationInfo : m_byValCompilationInfo) { 661 PatchableJump patchableNotIndexJump = byValCompilationInfo.notIndexJump; 662 CodeLocationJump notIndexJump = CodeLocationJump(); 663 if (Jump(patchableNotIndexJump).isSet()) 664 notIndexJump = CodeLocationJump(patchBuffer.locationOf(patchableNotIndexJump)); 665 CodeLocationJump badTypeJump = CodeLocationJump(patchBuffer.locationOf(byValCompilationInfo.badTypeJump)); 666 CodeLocationLabel doneTarget = patchBuffer.locationOf(byValCompilationInfo.doneTarget); 667 CodeLocationLabel slowPathTarget = patchBuffer.locationOf(byValCompilationInfo.slowPathTarget); 668 CodeLocationCall returnAddress = patchBuffer.locationOf(byValCompilationInfo.returnAddress); 669 670 *byValCompilationInfo.byValInfo = ByValInfo( 671 byValCompilationInfo.bytecodeIndex, 672 notIndexJump, 669 673 badTypeJump, 670 m_byValCompilationInfo[i].arrayMode, 674 byValCompilationInfo.arrayMode, 675 byValCompilationInfo.arrayProfile, 671 676 differenceBetweenCodePtr(badTypeJump, doneTarget), 672 677 differenceBetweenCodePtr(returnAddress, slowPathTarget)); -
trunk/Source/JavaScriptCore/jit/JIT.h
r187969 r188105 150 150 ByValCompilationInfo() { } 151 151 152 ByValCompilationInfo(unsigned bytecodeIndex, MacroAssembler::PatchableJump badTypeJump, JITArrayMode arrayMode, MacroAssembler::Label doneTarget) 153 : bytecodeIndex(bytecodeIndex) 152 ByValCompilationInfo(ByValInfo* byValInfo, unsigned bytecodeIndex, MacroAssembler::PatchableJump notIndexJump, MacroAssembler::PatchableJump badTypeJump, JITArrayMode arrayMode, ArrayProfile* arrayProfile, MacroAssembler::Label doneTarget) 153 : byValInfo(byValInfo) 154 , bytecodeIndex(bytecodeIndex) 155 , notIndexJump(notIndexJump) 154 156 , badTypeJump(badTypeJump) 155 157 , arrayMode(arrayMode) 158 , arrayProfile(arrayProfile) 156 159 , doneTarget(doneTarget) 157 160 { 158 161 } 159 162 163 ByValInfo* byValInfo; 160 164 unsigned bytecodeIndex; 165 MacroAssembler::PatchableJump notIndexJump; 161 166 MacroAssembler::PatchableJump badTypeJump; 162 167 JITArrayMode arrayMode; 168 ArrayProfile* arrayProfile; 163 169 MacroAssembler::Label doneTarget; 164 170 MacroAssembler::Label slowPathTarget; … … 205 211 } 206 212 213 static void compileGetByValWithCachedId(VM* vm, CodeBlock* codeBlock, ByValInfo* byValInfo, ReturnAddressPtr returnAddress, const Identifier& propertyName) 214 { 215 JIT jit(vm, codeBlock); 216 jit.m_bytecodeOffset = byValInfo->bytecodeIndex; 217 jit.privateCompileGetByValWithCachedId(byValInfo, returnAddress, propertyName); 218 } 219 207 220 static void compilePutByVal(VM* vm, CodeBlock* codeBlock, ByValInfo* byValInfo, ReturnAddressPtr returnAddress, JITArrayMode arrayMode) 208 221 { … … 247 260 248 261 void privateCompileGetByVal(ByValInfo*, ReturnAddressPtr, JITArrayMode); 262 void privateCompileGetByValWithCachedId(ByValInfo*, ReturnAddressPtr, const Identifier&); 249 263 void privateCompilePutByVal(ByValInfo*, ReturnAddressPtr, JITArrayMode); 250 264 … … 372 386 JumpList emitIntTypedArrayPutByVal(Instruction*, PatchableJump& badType, TypedArrayType); 373 387 JumpList emitFloatTypedArrayPutByVal(Instruction*, PatchableJump& badType, TypedArrayType); 374 388 389 JITGetByIdGenerator emitGetByValWithCachedId(Instruction*, const Identifier&, JumpList& doneCases, JumpList& slowCases); 390 375 391 enum FinalObjectMode { MayBeFinal, KnownNotFinal }; 376 392 … … 702 718 MacroAssembler::Call callOperation(J_JITOperation_EJJ, int, GPRReg, GPRReg); 703 719 MacroAssembler::Call callOperation(J_JITOperation_EJJAp, int, GPRReg, GPRReg, ArrayProfile*); 720 MacroAssembler::Call callOperation(J_JITOperation_EJJBy, int, GPRReg, GPRReg, ByValInfo*); 704 721 MacroAssembler::Call callOperation(C_JITOperation_EJsc, GPRReg); 705 722 MacroAssembler::Call callOperation(J_JITOperation_EJscC, int, GPRReg, JSCell*); … … 746 763 MacroAssembler::Call callOperation(V_JITOperation_EJJJ, RegisterID, RegisterID, RegisterID); 747 764 MacroAssembler::Call callOperation(V_JITOperation_EJJJAp, RegisterID, RegisterID, RegisterID, ArrayProfile*); 765 MacroAssembler::Call callOperation(V_JITOperation_EJJJBy, RegisterID, RegisterID, RegisterID, ByValInfo*); 748 766 MacroAssembler::Call callOperation(V_JITOperation_EJZJ, RegisterID, int32_t, RegisterID); 749 767 MacroAssembler::Call callOperation(V_JITOperation_EJZ, RegisterID, int32_t); … … 762 780 MacroAssembler::Call callOperation(J_JITOperation_EJJ, int, GPRReg, GPRReg, GPRReg, GPRReg); 763 781 MacroAssembler::Call callOperation(J_JITOperation_EJJAp, int, GPRReg, GPRReg, GPRReg, GPRReg, ArrayProfile*); 782 MacroAssembler::Call callOperation(J_JITOperation_EJJBy, int, GPRReg, GPRReg, GPRReg, GPRReg, ByValInfo*); 764 783 MacroAssembler::Call callOperation(P_JITOperation_EJS, GPRReg, GPRReg, size_t); 765 784 MacroAssembler::Call callOperation(S_JITOperation_EJ, RegisterID, RegisterID); … … 769 788 MacroAssembler::Call callOperation(V_JITOperation_EJJJ, RegisterID, RegisterID, RegisterID, RegisterID, RegisterID, RegisterID); 770 789 MacroAssembler::Call callOperation(V_JITOperation_EJJJAp, RegisterID, RegisterID, RegisterID, RegisterID, RegisterID, RegisterID, ArrayProfile*); 790 MacroAssembler::Call callOperation(V_JITOperation_EJJJBy, RegisterID, RegisterID, RegisterID, RegisterID, RegisterID, RegisterID, ByValInfo*); 771 791 MacroAssembler::Call callOperation(V_JITOperation_EJZ, RegisterID, RegisterID, int32_t); 772 792 MacroAssembler::Call callOperation(V_JITOperation_EJZJ, RegisterID, RegisterID, int32_t, RegisterID, RegisterID); -
trunk/Source/JavaScriptCore/jit/JITInlines.h
r186860 r188105 412 412 } 413 413 414 ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJJJBy operation, RegisterID regOp1, RegisterID regOp2, RegisterID regOp3, ByValInfo* byValInfo) 415 { 416 setupArgumentsWithExecState(regOp1, regOp2, regOp3, TrustedImmPtr(byValInfo)); 417 return appendCallWithExceptionCheck(operation); 418 } 419 414 420 ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EZJ operation, int dst, GPRReg arg) 415 421 { … … 457 463 { 458 464 setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(arrayProfile)); 465 return appendCallWithExceptionCheckSetJSValueResult(operation, dst); 466 } 467 468 ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJJBy operation, int dst, GPRReg arg1, GPRReg arg2, ByValInfo* byValInfo) 469 { 470 setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(byValInfo)); 459 471 return appendCallWithExceptionCheckSetJSValueResult(operation, dst); 460 472 } … … 601 613 } 602 614 615 ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJJBy operation, int dst, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload, ByValInfo* byValInfo) 616 { 617 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, SH4_32BIT_DUMMY_ARG arg2Payload, arg2Tag, TrustedImmPtr(byValInfo)); 618 return appendCallWithExceptionCheckSetJSValueResult(operation, dst); 619 } 620 603 621 ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(JIT::WithProfileTag, J_JITOperation_EJJ operation, int dst, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload) 604 622 { … … 664 682 { 665 683 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG regOp1Payload, regOp1Tag, SH4_32BIT_DUMMY_ARG regOp2Payload, regOp2Tag, regOp3Payload, regOp3Tag, TrustedImmPtr(arrayProfile)); 684 return appendCallWithExceptionCheck(operation); 685 } 686 687 ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJJJBy operation, RegisterID regOp1Tag, RegisterID regOp1Payload, RegisterID regOp2Tag, RegisterID regOp2Payload, RegisterID regOp3Tag, RegisterID regOp3Payload, ByValInfo* byValInfo) 688 { 689 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG regOp1Payload, regOp1Tag, SH4_32BIT_DUMMY_ARG regOp2Payload, regOp2Tag, regOp3Payload, regOp3Tag, TrustedImmPtr(byValInfo)); 666 690 return appendCallWithExceptionCheck(operation); 667 691 } -
trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp
r187969 r188105 1069 1069 int property = currentInstruction[3].u.operand; 1070 1070 ArrayProfile* profile = currentInstruction[4].u.arrayProfile; 1071 ByValInfo* byValInfo = m_codeBlock->addByValInfo(); 1071 1072 1072 1073 emitGetVirtualRegisters(base, regT0, property, regT1); … … 1100 1101 emitPutVirtualRegister(dst); 1101 1102 1102 m_byValCompilationInfo.append(ByValCompilationInfo( m_bytecodeOffset, badType, mode, done));1103 m_byValCompilationInfo.append(ByValCompilationInfo(byValInfo, m_bytecodeOffset, PatchableJump(), badType, mode, profile, done)); 1103 1104 } 1104 1105 … … 1108 1109 int base = currentInstruction[2].u.operand; 1109 1110 int property = currentInstruction[3].u.operand; 1110 ArrayProfile* profile = currentInstruction[4].u.arrayProfile;1111 ByValInfo* byValInfo = m_byValCompilationInfo[m_byValInstructionIndex].byValInfo; 1111 1112 1112 1113 linkSlowCaseIfNotJSCell(iter, base); // base cell check … … 1119 1120 emitGetVirtualRegister(base, regT0); 1120 1121 emitGetVirtualRegister(property, regT1); 1121 Call call = callOperation(operationHasIndexedPropertyDefault, dst, regT0, regT1, profile);1122 Call call = callOperation(operationHasIndexedPropertyDefault, dst, regT0, regT1, byValInfo); 1122 1123 1123 1124 m_byValCompilationInfo[m_byValInstructionIndex].slowPathTarget = slowPath; -
trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
r187969 r188105 1069 1069 int property = currentInstruction[3].u.operand; 1070 1070 ArrayProfile* profile = currentInstruction[4].u.arrayProfile; 1071 ByValInfo* byValInfo = m_codeBlock->addByValInfo(); 1071 1072 1072 1073 emitLoadPayload(base, regT0); … … 1101 1102 emitStoreBool(dst, regT0); 1102 1103 1103 m_byValCompilationInfo.append(ByValCompilationInfo( m_bytecodeOffset, badType, mode, done));1104 m_byValCompilationInfo.append(ByValCompilationInfo(byValInfo, m_bytecodeOffset, PatchableJump(), badType, mode, profile, done)); 1104 1105 } 1105 1106 … … 1109 1110 int base = currentInstruction[2].u.operand; 1110 1111 int property = currentInstruction[3].u.operand; 1111 ArrayProfile* profile = currentInstruction[4].u.arrayProfile;1112 ByValInfo* byValInfo = m_byValCompilationInfo[m_byValInstructionIndex].byValInfo; 1112 1113 1113 1114 linkSlowCaseIfNotJSCell(iter, base); // base cell check … … 1120 1121 emitLoad(base, regT1, regT0); 1121 1122 emitLoad(property, regT3, regT2); 1122 Call call = callOperation(operationHasIndexedPropertyDefault, dst, regT1, regT0, regT3, regT2, profile);1123 Call call = callOperation(operationHasIndexedPropertyDefault, dst, regT1, regT0, regT3, regT2, byValInfo); 1123 1124 1124 1125 m_byValCompilationInfo[m_byValInstructionIndex].slowPathTarget = slowPath; -
trunk/Source/JavaScriptCore/jit/JITOperations.cpp
r187969 r188105 479 479 } 480 480 481 static void putByVal(CallFrame* callFrame, JSValue baseValue, JSValue subscript, JSValue value, ArrayProfile* arrayProfile)481 static void putByVal(CallFrame* callFrame, JSValue baseValue, JSValue subscript, JSValue value, ByValInfo* byValInfo) 482 482 { 483 483 VM& vm = callFrame->vm(); … … 489 489 object->setIndexQuickly(callFrame->vm(), i, value); 490 490 else { 491 arrayProfile->setOutOfBounds();491 byValInfo->arrayProfile->setOutOfBounds(); 492 492 object->methodTable(vm)->putByIndex(object, callFrame, i, value, callFrame->codeBlock()->isStrictMode()); 493 493 } … … 503 503 } 504 504 505 static void directPutByVal(CallFrame* callFrame, JSObject* baseObject, JSValue subscript, JSValue value, ArrayProfile* arrayProfile)505 static void directPutByVal(CallFrame* callFrame, JSObject* baseObject, JSValue subscript, JSValue value, ByValInfo* byValInfo) 506 506 { 507 507 bool isStrictMode = callFrame->codeBlock()->isStrictMode(); … … 515 515 } 516 516 517 arrayProfile->setOutOfBounds();517 byValInfo->arrayProfile->setOutOfBounds(); 518 518 baseObject->putDirectIndex(callFrame, index, value, 0, isStrictMode ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow); 519 519 return; … … 541 541 } 542 542 } 543 void JIT_OPERATION operationPutByVal(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ArrayProfile* arrayProfile)543 void JIT_OPERATION operationPutByVal(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ByValInfo* byValInfo) 544 544 { 545 545 VM& vm = exec->vm(); … … 555 555 bool didOptimize = false; 556 556 557 unsigned bytecodeOffset = exec->locationAsBytecodeOffset(); 558 ASSERT(bytecodeOffset); 559 ByValInfo& byValInfo = exec->codeBlock()->getByValInfo(bytecodeOffset - 1); 560 ASSERT(!byValInfo.stubRoutine); 557 ASSERT(exec->locationAsBytecodeOffset()); 558 ASSERT(!byValInfo->stubRoutine); 561 559 562 560 Structure* structure = object->structure(vm); … … 564 562 // Attempt to optimize. 565 563 JITArrayMode arrayMode = jitArrayModeForStructure(structure); 566 if (jitArrayModePermitsPut(arrayMode) && arrayMode != byValInfo .arrayMode) {564 if (jitArrayModePermitsPut(arrayMode) && arrayMode != byValInfo->arrayMode) { 567 565 CodeBlock* codeBlock = exec->codeBlock(); 568 566 ConcurrentJITLocker locker(codeBlock->m_lock); 569 arrayProfile->computeUpdatedPrediction(locker, codeBlock, structure);570 571 JIT::compilePutByVal(&vm, exec->codeBlock(), &byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);567 byValInfo->arrayProfile->computeUpdatedPrediction(locker, codeBlock, structure); 568 569 JIT::compilePutByVal(&vm, exec->codeBlock(), byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode); 572 570 didOptimize = true; 573 571 } … … 580 578 // where we see non-index-intercepting objects, this gives 10 iterations worth of 581 579 // opportunity for us to observe that the get_by_val may be polymorphic. 582 if (++byValInfo .slowPathCount >= 10580 if (++byValInfo->slowPathCount >= 10 583 581 || object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) { 584 582 // Don't ever try to optimize. … … 588 586 } 589 587 590 putByVal(exec, baseValue, subscript, value, arrayProfile);591 } 592 593 void JIT_OPERATION operationDirectPutByVal(ExecState* callFrame, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ArrayProfile* arrayProfile)588 putByVal(exec, baseValue, subscript, value, byValInfo); 589 } 590 591 void JIT_OPERATION operationDirectPutByVal(ExecState* callFrame, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ByValInfo* byValInfo) 594 592 { 595 593 VM& vm = callFrame->vm(); … … 604 602 // See if it's worth optimizing at all. 605 603 bool didOptimize = false; 606 607 unsigned bytecodeOffset = callFrame->locationAsBytecodeOffset(); 608 ASSERT(bytecodeOffset); 609 ByValInfo& byValInfo = callFrame->codeBlock()->getByValInfo(bytecodeOffset - 1); 610 ASSERT(!byValInfo.stubRoutine); 604 605 ASSERT(callFrame->locationAsBytecodeOffset()); 606 ASSERT(!byValInfo->stubRoutine); 611 607 612 608 Structure* structure = object->structure(vm); … … 614 610 // Attempt to optimize. 615 611 JITArrayMode arrayMode = jitArrayModeForStructure(structure); 616 if (jitArrayModePermitsPut(arrayMode) && arrayMode != byValInfo .arrayMode) {612 if (jitArrayModePermitsPut(arrayMode) && arrayMode != byValInfo->arrayMode) { 617 613 CodeBlock* codeBlock = callFrame->codeBlock(); 618 614 ConcurrentJITLocker locker(codeBlock->m_lock); 619 arrayProfile->computeUpdatedPrediction(locker, codeBlock, structure);620 621 JIT::compileDirectPutByVal(&vm, callFrame->codeBlock(), &byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);615 byValInfo->arrayProfile->computeUpdatedPrediction(locker, codeBlock, structure); 616 617 JIT::compileDirectPutByVal(&vm, callFrame->codeBlock(), byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode); 622 618 didOptimize = true; 623 619 } … … 630 626 // where we see non-index-intercepting objects, this gives 10 iterations worth of 631 627 // opportunity for us to observe that the get_by_val may be polymorphic. 632 if (++byValInfo .slowPathCount >= 10628 if (++byValInfo->slowPathCount >= 10 633 629 || object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) { 634 630 // Don't ever try to optimize. … … 637 633 } 638 634 } 639 directPutByVal(callFrame, object, subscript, value, arrayProfile);640 } 641 642 void JIT_OPERATION operationPutByValGeneric(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ArrayProfile* arrayProfile)635 directPutByVal(callFrame, object, subscript, value, byValInfo); 636 } 637 638 void JIT_OPERATION operationPutByValGeneric(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ByValInfo* byValInfo) 643 639 { 644 640 VM& vm = exec->vm(); … … 649 645 JSValue value = JSValue::decode(encodedValue); 650 646 651 putByVal(exec, baseValue, subscript, value, arrayProfile);652 } 653 654 655 void JIT_OPERATION operationDirectPutByValGeneric(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ArrayProfile* arrayProfile)647 putByVal(exec, baseValue, subscript, value, byValInfo); 648 } 649 650 651 void JIT_OPERATION operationDirectPutByValGeneric(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ByValInfo* byValInfo) 656 652 { 657 653 VM& vm = exec->vm(); … … 662 658 JSValue value = JSValue::decode(encodedValue); 663 659 RELEASE_ASSERT(baseValue.isObject()); 664 directPutByVal(exec, asObject(baseValue), subscript, value, arrayProfile);660 directPutByVal(exec, asObject(baseValue), subscript, value, byValInfo); 665 661 } 666 662 … … 1430 1426 } 1431 1427 1432 static JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript, ArrayProfile* arrayProfile, ReturnAddressPtr returnAddress)1428 static JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript, ByValInfo* byValInfo, ReturnAddressPtr returnAddress) 1433 1429 { 1434 1430 if (LIKELY(baseValue.isCell() && subscript.isString())) { … … 1437 1433 if (JSCell::canUseFastGetOwnProperty(structure)) { 1438 1434 if (RefPtr<AtomicStringImpl> existingAtomicString = asString(subscript)->toExistingAtomicString(exec)) { 1439 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, existingAtomicString.get())) 1435 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, existingAtomicString.get())) { 1436 ASSERT(exec->locationAsBytecodeOffset()); 1437 if (byValInfo->stubInfo && byValInfo->cachedId.impl() != existingAtomicString) 1438 byValInfo->tookSlowPath = true; 1440 1439 return result; 1440 } 1441 1441 } 1442 1442 } … … 1444 1444 1445 1445 if (subscript.isUInt32()) { 1446 ASSERT(exec->locationAsBytecodeOffset()); 1447 byValInfo->tookSlowPath = true; 1448 1446 1449 uint32_t i = subscript.asUInt32(); 1447 1450 if (isJSString(baseValue)) { … … 1450 1453 return asString(baseValue)->getIndex(exec, i); 1451 1454 } 1452 arrayProfile->setOutOfBounds();1455 byValInfo->arrayProfile->setOutOfBounds(); 1453 1456 } else if (baseValue.isObject()) { 1454 1457 JSObject* object = asObject(baseValue); … … 1457 1460 1458 1461 if (!canAccessArgumentIndexQuickly(*object, i)) 1459 arrayProfile->setOutOfBounds();1462 byValInfo->arrayProfile->setOutOfBounds(); 1460 1463 } 1461 1464 … … 1469 1472 if (exec->hadException()) 1470 1473 return jsUndefined(); 1474 1475 ASSERT(exec->locationAsBytecodeOffset()); 1476 if (byValInfo->stubInfo && byValInfo->cachedId != property) 1477 byValInfo->tookSlowPath = true; 1478 1471 1479 return baseValue.get(exec, property); 1472 1480 } … … 1474 1482 extern "C" { 1475 1483 1476 EncodedJSValue JIT_OPERATION operationGetByValGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ArrayProfile* arrayProfile)1484 EncodedJSValue JIT_OPERATION operationGetByValGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo* byValInfo) 1477 1485 { 1478 1486 VM& vm = exec->vm(); … … 1481 1489 JSValue subscript = JSValue::decode(encodedSubscript); 1482 1490 1483 JSValue result = getByVal(exec, baseValue, subscript, arrayProfile, ReturnAddressPtr(OUR_RETURN_ADDRESS));1491 JSValue result = getByVal(exec, baseValue, subscript, byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS)); 1484 1492 return JSValue::encode(result); 1485 1493 } 1486 1494 1487 EncodedJSValue JIT_OPERATION operationGetByValOptimize(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ArrayProfile* arrayProfile)1495 EncodedJSValue JIT_OPERATION operationGetByValOptimize(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo* byValInfo) 1488 1496 { 1489 1497 VM& vm = exec->vm(); … … 1491 1499 JSValue baseValue = JSValue::decode(encodedBase); 1492 1500 JSValue subscript = JSValue::decode(encodedSubscript); 1493 1501 1494 1502 if (baseValue.isObject() && subscript.isInt32()) { 1495 1503 // See if it's worth optimizing this at all. … … 1497 1505 bool didOptimize = false; 1498 1506 1499 unsigned bytecodeOffset = exec->locationAsBytecodeOffset(); 1500 ASSERT(bytecodeOffset); 1501 ByValInfo& byValInfo = exec->codeBlock()->getByValInfo(bytecodeOffset - 1); 1502 ASSERT(!byValInfo.stubRoutine); 1503 1507 ASSERT(exec->locationAsBytecodeOffset()); 1508 ASSERT(!byValInfo->stubRoutine); 1509 1504 1510 if (hasOptimizableIndexing(object->structure(vm))) { 1505 1511 // Attempt to optimize. 1506 1512 Structure* structure = object->structure(vm); 1507 1513 JITArrayMode arrayMode = jitArrayModeForStructure(structure); 1508 if (arrayMode != byValInfo .arrayMode) {1514 if (arrayMode != byValInfo->arrayMode) { 1509 1515 // If we reached this case, we got an interesting array mode we did not expect when we compiled. 1510 1516 // Let's update the profile to do better next time. 1511 1517 CodeBlock* codeBlock = exec->codeBlock(); 1512 1518 ConcurrentJITLocker locker(codeBlock->m_lock); 1513 arrayProfile->computeUpdatedPrediction(locker, codeBlock, structure);1514 1515 JIT::compileGetByVal(&vm, exec->codeBlock(), &byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);1519 byValInfo->arrayProfile->computeUpdatedPrediction(locker, codeBlock, structure); 1520 1521 JIT::compileGetByVal(&vm, exec->codeBlock(), byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode); 1516 1522 didOptimize = true; 1517 1523 } 1518 1524 } 1519 1525 1520 1526 if (!didOptimize) { 1521 1527 // If we take slow path more than 10 times without patching then make sure we … … 1524 1530 // where we see non-index-intercepting objects, this gives 10 iterations worth of 1525 1531 // opportunity for us to observe that the get_by_val may be polymorphic. 1526 if (++byValInfo .slowPathCount >= 101532 if (++byValInfo->slowPathCount >= 10 1527 1533 || object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) { 1528 1534 // Don't ever try to optimize. … … 1531 1537 } 1532 1538 } 1533 1534 JSValue result = getByVal(exec, baseValue, subscript, arrayProfile, ReturnAddressPtr(OUR_RETURN_ADDRESS)); 1539 1540 if (baseValue.isObject() && (subscript.isSymbol() || subscript.isString())) { 1541 const Identifier propertyName = subscript.toPropertyKey(exec); 1542 1543 if (!subscript.isString() || !parseIndex(propertyName)) { 1544 ASSERT(exec->locationAsBytecodeOffset()); 1545 ASSERT(!byValInfo->stubRoutine); 1546 JIT::compileGetByValWithCachedId(&vm, exec->codeBlock(), byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), propertyName); 1547 } 1548 1549 PropertySlot slot(baseValue); 1550 bool hasResult = baseValue.getPropertySlot(exec, propertyName, slot); 1551 return JSValue::encode(hasResult ? slot.getValue(exec, propertyName) : jsUndefined()); 1552 } 1553 1554 JSValue result = getByVal(exec, baseValue, subscript, byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS)); 1535 1555 return JSValue::encode(result); 1536 1556 } 1537 1538 EncodedJSValue JIT_OPERATION operationHasIndexedPropertyDefault(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ArrayProfile* arrayProfile)1557 1558 EncodedJSValue JIT_OPERATION operationHasIndexedPropertyDefault(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo* byValInfo) 1539 1559 { 1540 1560 VM& vm = exec->vm(); … … 1549 1569 bool didOptimize = false; 1550 1570 1551 unsigned bytecodeOffset = exec->locationAsBytecodeOffset(); 1552 ASSERT(bytecodeOffset); 1553 ByValInfo& byValInfo = exec->codeBlock()->getByValInfo(bytecodeOffset - 1); 1554 ASSERT(!byValInfo.stubRoutine); 1571 ASSERT(exec->locationAsBytecodeOffset()); 1572 ASSERT(!byValInfo->stubRoutine); 1555 1573 1556 1574 if (hasOptimizableIndexing(object->structure(vm))) { 1557 1575 // Attempt to optimize. 1558 1576 JITArrayMode arrayMode = jitArrayModeForStructure(object->structure(vm)); 1559 if (arrayMode != byValInfo .arrayMode) {1560 JIT::compileHasIndexedProperty(&vm, exec->codeBlock(), &byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);1577 if (arrayMode != byValInfo->arrayMode) { 1578 JIT::compileHasIndexedProperty(&vm, exec->codeBlock(), byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode); 1561 1579 didOptimize = true; 1562 1580 } … … 1569 1587 // where we see non-index-intercepting objects, this gives 10 iterations worth of 1570 1588 // opportunity for us to observe that the get_by_val may be polymorphic. 1571 if (++byValInfo .slowPathCount >= 101589 if (++byValInfo->slowPathCount >= 10 1572 1590 || object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) { 1573 1591 // Don't ever try to optimize. 1574 ctiPatchCallByReturnAddress(exec->codeBlock(), ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationHasIndexedPropertyGeneric)); 1592 ctiPatchCallByReturnAddress(exec->codeBlock(), ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationHasIndexedPropertyGeneric)); 1575 1593 } 1576 1594 } … … 1581 1599 1582 1600 if (!canAccessArgumentIndexQuickly(*object, index)) 1583 arrayProfile->setOutOfBounds();1601 byValInfo->arrayProfile->setOutOfBounds(); 1584 1602 return JSValue::encode(jsBoolean(object->hasProperty(exec, index))); 1585 1603 } 1586 1604 1587 EncodedJSValue JIT_OPERATION operationHasIndexedPropertyGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ArrayProfile* arrayProfile)1605 EncodedJSValue JIT_OPERATION operationHasIndexedPropertyGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo* byValInfo) 1588 1606 { 1589 1607 VM& vm = exec->vm(); … … 1601 1619 1602 1620 if (!canAccessArgumentIndexQuickly(*object, index)) 1603 arrayProfile->setOutOfBounds();1621 byValInfo->arrayProfile->setOutOfBounds(); 1604 1622 return JSValue::encode(jsBoolean(object->hasProperty(exec, subscript.asUInt32()))); 1605 1623 } 1606 1624 1607 EncodedJSValue JIT_OPERATION operationGetByValString(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript )1625 EncodedJSValue JIT_OPERATION operationGetByValString(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo* byValInfo) 1608 1626 { 1609 1627 VM& vm = exec->vm(); … … 1620 1638 result = baseValue.get(exec, i); 1621 1639 if (!isJSString(baseValue)) { 1622 unsigned bytecodeOffset = exec->locationAsBytecodeOffset(); 1623 ASSERT(bytecodeOffset); 1624 ByValInfo& byValInfo = exec->codeBlock()->getByValInfo(bytecodeOffset - 1); 1625 ctiPatchCallByReturnAddress(exec->codeBlock(), ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(byValInfo.stubRoutine ? operationGetByValGeneric : operationGetByValOptimize)); 1640 ASSERT(exec->locationAsBytecodeOffset()); 1641 ctiPatchCallByReturnAddress(exec->codeBlock(), ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(byValInfo->stubRoutine ? operationGetByValGeneric : operationGetByValOptimize)); 1626 1642 } 1627 1643 } -
trunk/Source/JavaScriptCore/jit/JITOperations.h
r187750 r188105 59 59 Aap: ArrayAllocationProfile* 60 60 Ap: ArrayProfile* 61 By: ByValInfo* 61 62 C: JSCell* 62 63 Cb: CodeBlock* … … 114 115 typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJJ)(ExecState*, EncodedJSValue, EncodedJSValue); 115 116 typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJJAp)(ExecState*, EncodedJSValue, EncodedJSValue, ArrayProfile*); 117 typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJJBy)(ExecState*, EncodedJSValue, EncodedJSValue, ByValInfo*); 116 118 typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJssZ)(ExecState*, JSString*, int32_t); 117 119 typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJP)(ExecState*, EncodedJSValue, void*); … … 196 198 typedef void JIT_OPERATION (*V_JITOperation_EJJJ)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue); 197 199 typedef void JIT_OPERATION (*V_JITOperation_EJJJAp)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ArrayProfile*); 200 typedef void JIT_OPERATION (*V_JITOperation_EJJJBy)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ByValInfo*); 198 201 typedef void JIT_OPERATION (*V_JITOperation_EJPP)(ExecState*, EncodedJSValue, void*, void*); 199 202 typedef void JIT_OPERATION (*V_JITOperation_EJZJ)(ExecState*, EncodedJSValue, int32_t, EncodedJSValue); … … 260 263 void JIT_OPERATION operationPutByIdDirectNonStrictBuildList(ExecState*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl*) WTF_INTERNAL; 261 264 void JIT_OPERATION operationReallocateStorageAndFinishPut(ExecState*, JSObject*, Structure*, PropertyOffset, EncodedJSValue) WTF_INTERNAL; 262 void JIT_OPERATION operationPutByVal(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ArrayProfile*) WTF_INTERNAL;263 void JIT_OPERATION operationDirectPutByVal(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ArrayProfile*) WTF_INTERNAL;264 void JIT_OPERATION operationPutByValGeneric(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ArrayProfile*) WTF_INTERNAL;265 void JIT_OPERATION operationDirectPutByValGeneric(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ArrayProfile*) WTF_INTERNAL;265 void JIT_OPERATION operationPutByVal(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ByValInfo*) WTF_INTERNAL; 266 void JIT_OPERATION operationDirectPutByVal(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ByValInfo*) WTF_INTERNAL; 267 void JIT_OPERATION operationPutByValGeneric(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ByValInfo*) WTF_INTERNAL; 268 void JIT_OPERATION operationDirectPutByValGeneric(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ByValInfo*) WTF_INTERNAL; 266 269 EncodedJSValue JIT_OPERATION operationCallEval(ExecState*, ExecState*) WTF_INTERNAL; 267 270 char* JIT_OPERATION operationLinkCall(ExecState*, CallLinkInfo*) WTF_INTERNAL; … … 311 314 void JIT_OPERATION operationProfileWillCall(ExecState*, EncodedJSValue) WTF_INTERNAL; 312 315 EncodedJSValue JIT_OPERATION operationCheckHasInstance(ExecState*, EncodedJSValue, EncodedJSValue baseVal) WTF_INTERNAL; 313 EncodedJSValue JIT_OPERATION operationGetByValOptimize(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ArrayProfile*) WTF_INTERNAL;314 EncodedJSValue JIT_OPERATION operationGetByValGeneric(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ArrayProfile*) WTF_INTERNAL;315 EncodedJSValue JIT_OPERATION operationGetByValString(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript ) WTF_INTERNAL;316 EncodedJSValue JIT_OPERATION operationHasIndexedPropertyDefault(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ArrayProfile*) WTF_INTERNAL;317 EncodedJSValue JIT_OPERATION operationHasIndexedPropertyGeneric(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ArrayProfile*) WTF_INTERNAL;316 EncodedJSValue JIT_OPERATION operationGetByValOptimize(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo*) WTF_INTERNAL; 317 EncodedJSValue JIT_OPERATION operationGetByValGeneric(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo*) WTF_INTERNAL; 318 EncodedJSValue JIT_OPERATION operationGetByValString(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo*) WTF_INTERNAL; 319 EncodedJSValue JIT_OPERATION operationHasIndexedPropertyDefault(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo*) WTF_INTERNAL; 320 EncodedJSValue JIT_OPERATION operationHasIndexedPropertyGeneric(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo*) WTF_INTERNAL; 318 321 EncodedJSValue JIT_OPERATION operationDeleteById(ExecState*, EncodedJSValue base, const Identifier*) WTF_INTERNAL; 319 322 JSCell* JIT_OPERATION operationGetPNames(ExecState*, JSObject*) WTF_INTERNAL; -
trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp
r187750 r188105 99 99 int property = currentInstruction[3].u.operand; 100 100 ArrayProfile* profile = currentInstruction[4].u.arrayProfile; 101 101 ByValInfo* byValInfo = m_codeBlock->addByValInfo(); 102 102 103 emitGetVirtualRegisters(base, regT0, property, regT1); 103 emitJumpSlowCaseIfNotImmediateInteger(regT1); 104 104 105 emitJumpSlowCaseIfNotJSCell(regT0, base); 106 107 // FIXME: patchableBranch64 could reduce the following 2 jumps into 1. Like, 108 // 109 // PatchableJump notIndex = emitJumpIfNotImmediateInteger(regT1); 110 // 111 // To use patchableBranch64, we need to fix the existing patchableBranchPtr in ARM64 112 // and introduce patchableBranch64 helper function for 64bit environments. 113 // https://bugs.webkit.org/show_bug.cgi?id=147761 114 Jump isIndex = emitJumpIfImmediateInteger(regT1); 115 PatchableJump notIndex = patchableJump(); 116 addSlowCase(notIndex); 117 118 isIndex.link(this); 105 119 // This is technically incorrect - we're zero-extending an int32. On the hot path this doesn't matter. 106 120 // We check the value as if it was a uint32 against the m_vectorLength - which will always fail if … … 111 125 zeroExtend32ToPtr(regT1, regT1); 112 126 113 emitJumpSlowCaseIfNotJSCell(regT0, base);114 127 emitArrayProfilingSiteWithCell(regT0, regT2, profile); 115 128 and32(TrustedImm32(IndexingShapeMask), regT2); … … 150 163 emitValueProfilingSite(); 151 164 emitPutVirtualRegister(dst); 152 153 m_byValCompilationInfo.append(ByValCompilationInfo( m_bytecodeOffset, badType, mode, done));165 166 m_byValCompilationInfo.append(ByValCompilationInfo(byValInfo, m_bytecodeOffset, notIndex, badType, mode, profile, done)); 154 167 } 155 168 … … 196 209 } 197 210 211 JITGetByIdGenerator JIT::emitGetByValWithCachedId(Instruction* currentInstruction, const Identifier& propertyName, JumpList& doneCases, JumpList& slowCases) 212 { 213 // base: regT0 214 // property: regT1 215 // scratch: regT3 216 217 int dst = currentInstruction[1].u.operand; 218 219 slowCases.append(emitJumpIfNotJSCell(regT1)); 220 if (propertyName.isSymbol()) { 221 slowCases.append(branchStructure(NotEqual, Address(regT1, JSCell::structureIDOffset()), m_vm->symbolStructure.get())); 222 loadPtr(Address(regT1, Symbol::offsetOfPrivateName()), regT3); 223 } else { 224 slowCases.append(branchStructure(NotEqual, Address(regT1, JSCell::structureIDOffset()), m_vm->stringStructure.get())); 225 loadPtr(Address(regT1, JSString::offsetOfValue()), regT3); 226 slowCases.append(branchTestPtr(Zero, regT3)); 227 slowCases.append(branchTest32(Zero, Address(regT3, StringImpl::flagsOffset()), TrustedImm32(StringImpl::flagIsAtomic()))); 228 } 229 slowCases.append(branchPtr(NotEqual, regT3, TrustedImmPtr(propertyName.impl()))); 230 231 JITGetByIdGenerator gen( 232 m_codeBlock, CodeOrigin(m_bytecodeOffset), RegisterSet::specialRegisters(), 233 JSValueRegs(regT0), JSValueRegs(regT0), DontSpill); 234 gen.generateFastPath(*this); 235 236 doneCases.append(jump()); 237 238 Label coldPathBegin = label(); 239 gen.slowPathJump().link(this); 240 241 Call call = callOperation(WithProfile, operationGetByIdOptimize, dst, gen.stubInfo(), regT0, propertyName.impl()); 242 gen.reportSlowPathCall(coldPathBegin, call); 243 doneCases.append(jump()); 244 245 return gen; 246 } 247 198 248 void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 199 249 { … … 201 251 int base = currentInstruction[2].u.operand; 202 252 int property = currentInstruction[3].u.operand; 203 ArrayProfile* profile = currentInstruction[4].u.arrayProfile; 204 253 ByValInfo* byValInfo = m_byValCompilationInfo[m_byValInstructionIndex].byValInfo; 254 255 linkSlowCaseIfNotJSCell(iter, base); // base cell check 205 256 linkSlowCase(iter); // property int32 check 206 linkSlowCaseIfNotJSCell(iter, base); // base cell check207 257 Jump nonCell = jump(); 208 258 linkSlowCase(iter); // base array check … … 225 275 emitGetVirtualRegister(base, regT0); 226 276 emitGetVirtualRegister(property, regT1); 227 Call call = callOperation(operationGetByValOptimize, dst, regT0, regT1, profile);277 Call call = callOperation(operationGetByValOptimize, dst, regT0, regT1, byValInfo); 228 278 229 279 m_byValCompilationInfo[m_byValInstructionIndex].slowPathTarget = slowPath; … … 264 314 int property = currentInstruction[2].u.operand; 265 315 ArrayProfile* profile = currentInstruction[4].u.arrayProfile; 316 ByValInfo* byValInfo = m_codeBlock->addByValInfo(); 266 317 267 318 emitGetVirtualRegisters(base, regT0, property, regT1); … … 300 351 Label done = label(); 301 352 302 m_byValCompilationInfo.append(ByValCompilationInfo(m_bytecodeOffset, badType, mode, done)); 303 353 m_byValCompilationInfo.append(ByValCompilationInfo(byValInfo, m_bytecodeOffset, PatchableJump(), badType, mode, profile, done)); 304 354 } 305 355 … … 400 450 int value = currentInstruction[3].u.operand; 401 451 ArrayProfile* profile = currentInstruction[4].u.arrayProfile; 452 ByValInfo* byValInfo = m_byValCompilationInfo[m_byValInstructionIndex].byValInfo; 402 453 403 454 linkSlowCase(iter); // property int32 check … … 425 476 emitGetVirtualRegister(value, regT2); 426 477 bool isDirect = m_interpreter->getOpcodeID(currentInstruction->u.opcode) == op_put_by_val_direct; 427 Call call = callOperation(isDirect ? operationDirectPutByVal : operationPutByVal, regT0, regT1, regT2, profile);478 Call call = callOperation(isDirect ? operationDirectPutByVal : operationPutByVal, regT0, regT1, regT2, byValInfo); 428 479 429 480 m_byValCompilationInfo[m_byValInstructionIndex].slowPathTarget = slowPath; … … 997 1048 RepatchBuffer repatchBuffer(m_codeBlock); 998 1049 repatchBuffer.relink(byValInfo->badTypeJump, CodeLocationLabel(byValInfo->stubRoutine->code().code())); 1050 repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(operationGetByValGeneric)); 1051 } 1052 1053 void JIT::privateCompileGetByValWithCachedId(ByValInfo* byValInfo, ReturnAddressPtr returnAddress, const Identifier& propertyName) 1054 { 1055 Instruction* currentInstruction = m_codeBlock->instructions().begin() + byValInfo->bytecodeIndex; 1056 1057 JumpList doneCases; 1058 JumpList slowCases; 1059 1060 JITGetByIdGenerator gen = emitGetByValWithCachedId(currentInstruction, propertyName, doneCases, slowCases); 1061 1062 ConcurrentJITLocker locker(m_codeBlock->m_lock); 1063 LinkBuffer patchBuffer(*m_vm, *this, m_codeBlock); 1064 patchBuffer.link(slowCases, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(returnAddress.value())).labelAtOffset(byValInfo->returnAddressToSlowPath)); 1065 patchBuffer.link(doneCases, byValInfo->badTypeJump.labelAtOffset(byValInfo->badTypeJumpToDone)); 1066 for (const auto& callSite : m_calls) { 1067 if (callSite.to) 1068 patchBuffer.link(callSite.from, FunctionPtr(callSite.to)); 1069 } 1070 gen.finalize(patchBuffer); 1071 1072 byValInfo->stubRoutine = FINALIZE_CODE_FOR_STUB( 1073 m_codeBlock, patchBuffer, 1074 ("Baseline get_by_val with cached property name '%s' stub for %s, return point %p", propertyName.impl()->utf8().data(), toCString(*m_codeBlock).data(), returnAddress.value())); 1075 byValInfo->cachedId = propertyName; 1076 byValInfo->stubInfo = gen.stubInfo(); 1077 1078 RepatchBuffer repatchBuffer(m_codeBlock); 1079 repatchBuffer.relink(byValInfo->notIndexJump, CodeLocationLabel(byValInfo->stubRoutine->code().code())); 999 1080 repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(operationGetByValGeneric)); 1000 1081 } -
trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
r187750 r188105 150 150 int property = currentInstruction[3].u.operand; 151 151 ArrayProfile* profile = currentInstruction[4].u.arrayProfile; 152 ByValInfo* byValInfo = m_codeBlock->addByValInfo(); 152 153 153 154 emitLoad2(base, regT1, regT0, property, regT3, regT2); 154 155 155 addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));156 156 emitJumpSlowCaseIfNotJSCell(base, regT1); 157 PatchableJump notIndex = patchableBranch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)); 158 addSlowCase(notIndex); 157 159 emitArrayProfilingSiteWithCell(regT0, regT1, profile); 158 160 and32(TrustedImm32(IndexingShapeMask), regT1); … … 193 195 emitStore(dst, regT1, regT0); 194 196 195 m_byValCompilationInfo.append(ByValCompilationInfo( m_bytecodeOffset, badType, mode, done));197 m_byValCompilationInfo.append(ByValCompilationInfo(byValInfo, m_bytecodeOffset, notIndex, badType, mode, profile, done)); 196 198 } 197 199 … … 237 239 return slowCases; 238 240 } 239 241 242 JITGetByIdGenerator JIT::emitGetByValWithCachedId(Instruction* currentInstruction, const Identifier& propertyName, JumpList& doneCases, JumpList& slowCases) 243 { 244 int dst = currentInstruction[1].u.operand; 245 246 // base: tag(regT1), payload(regT0) 247 // property: tag(regT3), payload(regT2) 248 // scratch: regT4 249 250 slowCases.append(emitJumpIfNotJSCell(regT3)); 251 if (propertyName.isSymbol()) { 252 slowCases.append(branchStructure(NotEqual, Address(regT2, JSCell::structureIDOffset()), m_vm->symbolStructure.get())); 253 loadPtr(Address(regT2, Symbol::offsetOfPrivateName()), regT4); 254 } else { 255 slowCases.append(branchStructure(NotEqual, Address(regT2, JSCell::structureIDOffset()), m_vm->stringStructure.get())); 256 loadPtr(Address(regT2, JSString::offsetOfValue()), regT4); 257 slowCases.append(branchTestPtr(Zero, regT4)); 258 slowCases.append(branchTest32(Zero, Address(regT4, StringImpl::flagsOffset()), TrustedImm32(StringImpl::flagIsAtomic()))); 259 } 260 slowCases.append(branchPtr(NotEqual, regT4, TrustedImmPtr(propertyName.impl()))); 261 262 JITGetByIdGenerator gen( 263 m_codeBlock, CodeOrigin(m_bytecodeOffset), RegisterSet::specialRegisters(), 264 JSValueRegs::payloadOnly(regT0), JSValueRegs(regT1, regT0), DontSpill); 265 gen.generateFastPath(*this); 266 267 doneCases.append(jump()); 268 269 Label coldPathBegin = label(); 270 gen.slowPathJump().link(this); 271 272 Call call = callOperation(WithProfile, operationGetByIdOptimize, dst, gen.stubInfo(), regT1, regT0, propertyName.impl()); 273 gen.reportSlowPathCall(coldPathBegin, call); 274 doneCases.append(jump()); 275 276 return gen; 277 } 278 240 279 void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 241 280 { … … 243 282 int base = currentInstruction[2].u.operand; 244 283 int property = currentInstruction[3].u.operand; 245 ArrayProfile* profile = currentInstruction[4].u.arrayProfile; 246 284 ByValInfo* byValInfo = m_byValCompilationInfo[m_byValInstructionIndex].byValInfo; 285 286 linkSlowCaseIfNotJSCell(iter, base); // base cell check 247 287 linkSlowCase(iter); // property int32 check 248 linkSlowCaseIfNotJSCell(iter, base); // base cell check249 288 250 289 Jump nonCell = jump(); … … 266 305 emitLoad(base, regT1, regT0); 267 306 emitLoad(property, regT3, regT2); 268 Call call = callOperation(operationGetByValOptimize, dst, regT1, regT0, regT3, regT2, profile);307 Call call = callOperation(operationGetByValOptimize, dst, regT1, regT0, regT3, regT2, byValInfo); 269 308 270 309 m_byValCompilationInfo[m_byValInstructionIndex].slowPathTarget = slowPath; … … 280 319 int property = currentInstruction[2].u.operand; 281 320 ArrayProfile* profile = currentInstruction[4].u.arrayProfile; 321 ByValInfo* byValInfo = m_codeBlock->addByValInfo(); 282 322 283 323 emitLoad2(base, regT1, regT0, property, regT3, regT2); … … 315 355 Label done = label(); 316 356 317 m_byValCompilationInfo.append(ByValCompilationInfo( m_bytecodeOffset, badType, mode, done));357 m_byValCompilationInfo.append(ByValCompilationInfo(byValInfo, m_bytecodeOffset, PatchableJump(), badType, mode, profile, done)); 318 358 } 319 359 … … 420 460 int value = currentInstruction[3].u.operand; 421 461 ArrayProfile* profile = currentInstruction[4].u.arrayProfile; 462 ByValInfo* byValInfo = m_byValCompilationInfo[m_byValInstructionIndex].byValInfo; 422 463 423 464 linkSlowCase(iter); // property int32 check … … 459 500 addCallArgument(regT1); 460 501 addCallArgument(regT0); 461 addCallArgument(TrustedImmPtr( profile));502 addCallArgument(TrustedImmPtr(byValInfo)); 462 503 Call call = appendCallWithExceptionCheck(isDirect ? operationDirectPutByVal : operationPutByVal); 463 504 #else … … 467 508 emitLoad(property, regT3, regT0); 468 509 emitLoad(value, regT5, regT4); 469 Call call = callOperation(isDirect ? operationDirectPutByVal : operationPutByVal, regT2, regT1, regT3, regT0, regT5, regT4, profile);510 Call call = callOperation(isDirect ? operationDirectPutByVal : operationPutByVal, regT2, regT1, regT3, regT0, regT5, regT4, byValInfo); 470 511 #endif 471 512 -
trunk/Source/JavaScriptCore/runtime/Symbol.h
r185002 r188105 80 80 double toNumber(ExecState*) const; 81 81 82 static size_t offsetOfPrivateName() { return OBJECT_OFFSETOF(Symbol, m_privateName); } 83 82 84 protected: 83 85 static void destroy(JSCell*);
Note: See TracChangeset
for help on using the changeset viewer.