Changeset 252763 in webkit
- Timestamp:
- Nov 21, 2019 9:41:56 PM (4 years ago)
- Location:
- trunk
- Files:
-
- 9 added
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r252758 r252763 1 2019-11-21 Saam Barati <sbarati@apple.com> 2 3 GetByStatus should not say it took the slow path for multiple identifiers and should have a way to indicate if the StructureStubInfo it saw took the slow path 4 https://bugs.webkit.org/show_bug.cgi?id=204435 5 6 Reviewed by Tadeu Zagallo. 7 8 * microbenchmarks/get-by-val-polymorphic-ic-1.js: Added. 9 (assert): 10 (test1.foo): 11 (test1): 12 * microbenchmarks/get-by-val-polymorphic-ic-2.js: Added. 13 (assert): 14 (test2.foo): 15 (test2): 16 * microbenchmarks/get-by-val-polymorphic-ic-3.js: Added. 17 (assert): 18 (test3.foo): 19 (test3.args): 20 (test3): 21 * microbenchmarks/get-by-val-polymorphic-ic-4.js: Added. 22 (assert): 23 (test4.foo): 24 (test4.capture): 25 (test4.args): 26 (test4): 27 * microbenchmarks/get-by-val-polymorphic-ic-5.js: Added. 28 (assert): 29 (test5.foo): 30 (test5.capture): 31 (test5.args): 32 (test5): 33 * microbenchmarks/get-by-val-polymorphic-ic-6.js: Added. 34 (assert): 35 (test6.foo): 36 (test6.capture): 37 (test6.args): 38 (test6): 39 * microbenchmarks/get-by-val-polymorphic-ic-7.js: Added. 40 (assert): 41 (test7.foo): 42 (test7): 43 * microbenchmarks/get-by-val-polymorphic-ic-8.js: Added. 44 (assert): 45 (test7.foo): 46 (test7): 47 * microbenchmarks/get-by-val-polymorphic-ic-9.js: Added. 48 (assert): 49 (test7.foo): 50 (test7): 51 1 52 2019-11-21 Mark Lam <mark.lam@apple.com> 2 53 -
trunk/Source/JavaScriptCore/ChangeLog
r252758 r252763 1 2019-11-21 Saam Barati <sbarati@apple.com> 2 3 GetByStatus should not say it took the slow path for multiple identifiers and should have a way to indicate if the StructureStubInfo it saw took the slow path 4 https://bugs.webkit.org/show_bug.cgi?id=204435 5 6 Reviewed by Tadeu Zagallo. 7 8 I discovered some issues with get by val ICs when re-running the microbenchmarks 9 I wrote. I noticed that we were faster when not running with the DFG. The reason 10 for this is that we were only emitting a get by val IC in the DFG/FTL when we 11 observe the GetByStatus says it didn't "go to the slow path". The logic in GetByStatus 12 for building up a variant list was wrong for ICs with multiple identifiers. We have 13 a consistency check when building up the list to ensure that no two variants have 14 structure sets which overlap, because we wouldn't know which one to choose. However, 15 we were accidentally saying two GetByIdVariants overlap when they had different identifiers. 16 This patch fixes that bug by also doing an identifier comparison check. Two GetByIdVariants 17 with different identifiers do not overlap. 18 19 We also used to say a GetByStatus "goes to the slow path" if any of the cases were an 20 array-like load. I wrote that code thinking that ArrayProfile would just handle it. 21 However, sometimes we have a get by val IC that both has string properties and int32 properties. 22 In these kinds of scenarios, an IC is super profitable. This patch now distinguishes 23 between a GetByStatus saying "we're a slow path" and if we actually observed the StructureStubInfo 24 go to the slow path. In the DFG/FTL, we only forgo emitting a get by val IC when observing a 25 prior StructureStubInfo that went to the slow path. 26 27 I also realized are call to StructureStubInfo::considerCaching was wrong for get by val ICs. 28 We were only considering the Structure in isolation, not the { Structure, Identifier } 29 pair. For get by val, we need to consider the pair together, since {s1, "a"} 30 and {s1, "b"} will be two different access cases. 31 32 This patch demonstrates that on these microbenchmarks, get by val ICs can 33 be between 50-200% faster. 34 35 * bytecode/GetByIdVariant.cpp: 36 (JSC::GetByIdVariant::dumpInContext const): 37 * bytecode/GetByIdVariant.h: 38 (JSC::GetByIdVariant::overlaps): 39 * bytecode/GetByStatus.cpp: 40 (JSC::GetByStatus::GetByStatus): 41 (JSC::GetByStatus::computeForStubInfoWithoutExitSiteFeedback): 42 (JSC::GetByStatus::makesCalls const): 43 (JSC::GetByStatus::slowVersion const): 44 (JSC::GetByStatus::merge): 45 (JSC::GetByStatus::dump const): 46 * bytecode/GetByStatus.h: 47 (JSC::GetByStatus::GetByStatus): 48 (JSC::GetByStatus::takesSlowPath const): 49 (JSC::GetByStatus::observedStructureStubInfoSlowPath const): 50 * bytecode/ICStatusUtils.h: 51 (JSC::appendICStatusVariant): 52 * bytecode/InByIdVariant.h: 53 (JSC::InByIdVariant::overlaps): 54 * bytecode/InstanceOfVariant.h: 55 (JSC::InstanceOfVariant::overlaps): 56 * bytecode/PutByIdVariant.h: 57 (JSC::PutByIdVariant::overlaps): 58 * bytecode/StructureStubInfo.cpp: 59 (JSC::StructureStubInfo::visitWeakReferences): 60 * bytecode/StructureStubInfo.h: 61 (JSC::StructureStubInfo::considerCaching): 62 * dfg/DFGByteCodeParser.cpp: 63 (JSC::DFG::ByteCodeParser::parseBlock): 64 * jit/JITOperations.cpp: 65 1 66 2019-11-21 Mark Lam <mark.lam@apple.com> 2 67 -
trunk/Source/JavaScriptCore/bytecode/GetByIdVariant.cpp
r252684 r252763 182 182 void GetByIdVariant::dumpInContext(PrintStream& out, DumpContext* context) const 183 183 { 184 out.print("<"); 185 out.print("id='", m_identifier ? *m_identifier : Identifier(), "', "); 184 186 if (!isSet()) { 185 out.print(" <empty>");187 out.print("empty>"); 186 188 return; 187 189 } 188 189 out.print( 190 "<", inContext(structureSet(), context), ", ", inContext(m_conditionSet, context)); 190 out.print(inContext(structureSet(), context), ", ", inContext(m_conditionSet, context)); 191 191 out.print(", offset = ", offset()); 192 192 if (m_callLinkStatus) -
trunk/Source/JavaScriptCore/bytecode/GetByIdVariant.h
r252684 r252763 84 84 85 85 Box<Identifier> identifier() const { return m_identifier; } 86 87 bool overlaps(const GetByIdVariant& other) 88 { 89 if (!!m_identifier != !!other.m_identifier) 90 return true; 91 if (m_identifier) { 92 if (m_identifier->impl() != other.m_identifier->impl()) 93 return false; 94 } 95 return structureSet().overlaps(other.structureSet()); 96 } 86 97 87 98 private: -
trunk/Source/JavaScriptCore/bytecode/GetByStatus.cpp
r252684 r252763 53 53 } 54 54 55 GetByStatus GetByStatus::computeFromLLInt(CodeBlock* profiledBlock, BytecodeIndex bytecodeIndex )55 GetByStatus GetByStatus::computeFromLLInt(CodeBlock* profiledBlock, BytecodeIndex bytecodeIndex, TrackIdentifiers trackIdentifiers) 56 56 { 57 57 VM& vm = profiledBlock->vm(); … … 92 92 } 93 93 94 ASSERT_UNUSED(trackIdentifiers, trackIdentifiers == TrackIdentifiers::No); // We could make this work in the future, but nobody needs it right now. 95 94 96 if (!structureID) 95 97 return GetByStatus(NoInformation, false); … … 112 114 } 113 115 114 GetByStatus GetByStatus::computeFor(CodeBlock* profiledBlock, ICStatusMap& map, BytecodeIndex bytecodeIndex, ExitFlag didExit, CallLinkStatus::ExitSiteData callExitSiteData )116 GetByStatus GetByStatus::computeFor(CodeBlock* profiledBlock, ICStatusMap& map, BytecodeIndex bytecodeIndex, ExitFlag didExit, CallLinkStatus::ExitSiteData callExitSiteData, TrackIdentifiers trackIdentifiers) 115 117 { 116 118 ConcurrentJSLocker locker(profiledBlock->m_lock); … … 120 122 #if ENABLE(DFG_JIT) 121 123 result = computeForStubInfoWithoutExitSiteFeedback( 122 locker, profiledBlock, map.get(CodeOrigin(bytecodeIndex)).stubInfo, callExitSiteData );124 locker, profiledBlock, map.get(CodeOrigin(bytecodeIndex)).stubInfo, callExitSiteData, trackIdentifiers); 123 125 124 126 if (didExit) … … 131 133 132 134 if (!result) 133 return computeFromLLInt(profiledBlock, bytecodeIndex );135 return computeFromLLInt(profiledBlock, bytecodeIndex, trackIdentifiers); 134 136 135 137 return result; … … 137 139 138 140 #if ENABLE(JIT) 141 GetByStatus::GetByStatus(StubInfoSummary summary, StructureStubInfo& stubInfo) 142 : m_wasSeenInJIT(true) 143 { 144 switch (summary) { 145 case StubInfoSummary::NoInformation: 146 m_state = NoInformation; 147 return; 148 case StubInfoSummary::Simple: 149 case StubInfoSummary::MakesCalls: 150 RELEASE_ASSERT_NOT_REACHED(); 151 return; 152 case StubInfoSummary::TakesSlowPath: 153 m_state = stubInfo.tookSlowPath ? ObservedTakesSlowPath : LikelyTakesSlowPath; 154 return; 155 case StubInfoSummary::TakesSlowPathAndMakesCalls: 156 m_state = stubInfo.tookSlowPath ? ObservedSlowPathAndMakesCalls : MakesCalls; 157 return; 158 } 159 RELEASE_ASSERT_NOT_REACHED(); 160 } 161 139 162 GetByStatus::GetByStatus(const ModuleNamespaceAccessCase& accessCase) 140 163 : m_moduleNamespaceData(Box<ModuleNamespaceData>::create(ModuleNamespaceData { accessCase.moduleNamespaceObject(), accessCase.moduleEnvironment(), accessCase.scopeOffset(), accessCase.identifier() })) … … 145 168 146 169 GetByStatus GetByStatus::computeForStubInfoWithoutExitSiteFeedback( 147 const ConcurrentJSLocker& locker, CodeBlock* profiledBlock, StructureStubInfo* stubInfo, CallLinkStatus::ExitSiteData callExitSiteData )170 const ConcurrentJSLocker& locker, CodeBlock* profiledBlock, StructureStubInfo* stubInfo, CallLinkStatus::ExitSiteData callExitSiteData, TrackIdentifiers trackIdentifiers) 148 171 { 149 172 StubInfoSummary summary = StructureStubInfo::summary(stubInfo); 150 173 if (!isInlineable(summary)) 151 return GetByStatus(summary );174 return GetByStatus(summary, *stubInfo); 152 175 153 176 // Finally figure out if we can derive an access strategy. … … 162 185 Structure* structure = stubInfo->u.byIdSelf.baseObjectStructure.get(); 163 186 if (structure->takesSlowPathInDFGForImpureProperty()) 164 return GetByStatus(JSC::slowVersion(summary) );187 return GetByStatus(JSC::slowVersion(summary), *stubInfo); 165 188 Box<Identifier> identifier = stubInfo->getByIdSelfIdentifier(); 166 189 UniquedStringImpl* uid = identifier->impl(); 167 190 RELEASE_ASSERT(uid); 191 if (trackIdentifiers == TrackIdentifiers::No) 192 identifier = nullptr; 168 193 GetByIdVariant variant(WTFMove(identifier)); 169 194 unsigned attributes; 170 195 variant.m_offset = structure->getConcurrently(uid, attributes); 171 196 if (!isValidOffset(variant.m_offset)) 172 return GetByStatus(JSC::slowVersion(summary) );197 return GetByStatus(JSC::slowVersion(summary), *stubInfo); 173 198 if (attributes & PropertyAttribute::CustomAccessorOrValue) 174 return GetByStatus(JSC::slowVersion(summary) );199 return GetByStatus(JSC::slowVersion(summary), *stubInfo); 175 200 176 201 variant.m_structureSet.add(structure); … … 195 220 const AccessCase& access = list->at(listIndex); 196 221 if (access.viaProxy()) 197 return GetByStatus(JSC::slowVersion(summary) );222 return GetByStatus(JSC::slowVersion(summary), *stubInfo); 198 223 199 224 if (access.usesPolyProto()) 200 return GetByStatus(JSC::slowVersion(summary) );225 return GetByStatus(JSC::slowVersion(summary), *stubInfo); 201 226 202 227 if (!access.requiresIdentifierNameMatch()) { … … 204 229 // information, and probably better than ArrayProfile when it's available. 205 230 // https://bugs.webkit.org/show_bug.cgi?id=204215 206 return GetByStatus(JSC::slowVersion(summary) );231 return GetByStatus(JSC::slowVersion(summary), *stubInfo); 207 232 } 208 233 … … 215 240 // could have told us. But, it works well enough. So, our only concern here is to not 216 241 // crash on null structure. 217 return GetByStatus(JSC::slowVersion(summary) );242 return GetByStatus(JSC::slowVersion(summary), *stubInfo); 218 243 } 219 244 … … 226 251 227 252 case ComplexGetStatus::TakesSlowPath: 228 return GetByStatus(JSC::slowVersion(summary) );253 return GetByStatus(JSC::slowVersion(summary), *stubInfo); 229 254 230 255 case ComplexGetStatus::Inlineable: { … … 256 281 customAccessorGetter = access.as<GetterSetterAccessCase>().customAccessor(); 257 282 if (!access.as<GetterSetterAccessCase>().domAttribute()) 258 return GetByStatus(JSC::slowVersion(summary) );283 return GetByStatus(JSC::slowVersion(summary), *stubInfo); 259 284 domAttribute = WTF::makeUnique<DOMAttributeAnnotation>(*access.as<GetterSetterAccessCase>().domAttribute()); 260 285 haveDOMAttribute = true; … … 265 290 // FIXME: It would be totally sweet to support more of these at some point in the 266 291 // future. https://bugs.webkit.org/show_bug.cgi?id=133052 267 return GetByStatus(JSC::slowVersion(summary) );292 return GetByStatus(JSC::slowVersion(summary), *stubInfo); 268 293 } } 269 294 270 295 ASSERT((AccessCase::Miss == access.type()) == (access.offset() == invalidOffset)); 271 296 GetByIdVariant variant( 272 access.identifier(), StructureSet(structure), complexGetStatus.offset(),297 trackIdentifiers == TrackIdentifiers::Yes ? access.identifier() : Box<Identifier>(nullptr), StructureSet(structure), complexGetStatus.offset(), 273 298 complexGetStatus.conditionSet(), WTFMove(callLinkStatus), 274 299 intrinsicFunction, … … 277 302 278 303 if (!result.appendVariant(variant)) 279 return GetByStatus(JSC::slowVersion(summary) );304 return GetByStatus(JSC::slowVersion(summary), *stubInfo); 280 305 281 306 if (haveDOMAttribute) { 282 307 // Give up when custom accesses are not merged into one. 283 308 if (result.numVariants() != 1) 284 return GetByStatus(JSC::slowVersion(summary) );309 return GetByStatus(JSC::slowVersion(summary), *stubInfo); 285 310 } else { 286 311 // Give up when custom access and simple access are mixed. 287 312 if (result.m_state == Custom) 288 return GetByStatus(JSC::slowVersion(summary) );313 return GetByStatus(JSC::slowVersion(summary), *stubInfo); 289 314 } 290 315 break; … … 296 321 297 322 default: 298 return GetByStatus(JSC::slowVersion(summary) );323 return GetByStatus(JSC::slowVersion(summary), *stubInfo); 299 324 } 300 325 … … 305 330 GetByStatus GetByStatus::computeFor( 306 331 CodeBlock* profiledBlock, ICStatusMap& baselineMap, 307 ICStatusContextStack& icContextStack, CodeOrigin codeOrigin )332 ICStatusContextStack& icContextStack, CodeOrigin codeOrigin, TrackIdentifiers trackIdentifiers) 308 333 { 309 334 BytecodeIndex bytecodeIndex = codeOrigin.bytecodeIndex(); … … 320 345 GetByStatus baselineResult = computeFor( 321 346 profiledBlock, baselineMap, bytecodeIndex, didExit, 322 callExitSiteData );347 callExitSiteData, trackIdentifiers); 323 348 baselineResult.merge(result); 324 349 return baselineResult; … … 334 359 ConcurrentJSLocker locker(context->optimizedCodeBlock->m_lock); 335 360 result = computeForStubInfoWithoutExitSiteFeedback( 336 locker, context->optimizedCodeBlock, status.stubInfo, callExitSiteData );361 locker, context->optimizedCodeBlock, status.stubInfo, callExitSiteData, trackIdentifiers); 337 362 } 338 363 if (result.isSet()) … … 344 369 } 345 370 346 return computeFor(profiledBlock, baselineMap, bytecodeIndex, didExit, callExitSiteData );371 return computeFor(profiledBlock, baselineMap, bytecodeIndex, didExit, callExitSiteData, trackIdentifiers); 347 372 } 348 373 … … 360 385 361 386 if (parseIndex(*uid)) 362 return GetByStatus( TakesSlowPath);387 return GetByStatus(LikelyTakesSlowPath); 363 388 364 389 GetByStatus result; … … 368 393 Structure* structure = set[i]; 369 394 if (structure->typeInfo().overridesGetOwnPropertySlot() && structure->typeInfo().type() != GlobalObjectType) 370 return GetByStatus( TakesSlowPath);395 return GetByStatus(LikelyTakesSlowPath); 371 396 372 397 if (!structure->propertyAccessesAreCacheable()) 373 return GetByStatus( TakesSlowPath);398 return GetByStatus(LikelyTakesSlowPath); 374 399 375 400 unsigned attributes; 376 401 PropertyOffset offset = structure->getConcurrently(uid, attributes); 377 402 if (!isValidOffset(offset)) 378 return GetByStatus( TakesSlowPath); // It's probably a prototype lookup. Give up on life for now, even though we could totally be way smarter about it.403 return GetByStatus(LikelyTakesSlowPath); // It's probably a prototype lookup. Give up on life for now, even though we could totally be way smarter about it. 379 404 if (attributes & PropertyAttribute::Accessor) 380 405 return GetByStatus(MakesCalls); // We could be smarter here, like strength-reducing this to a Call. 381 406 if (attributes & PropertyAttribute::CustomAccessorOrValue) 382 return GetByStatus( TakesSlowPath);407 return GetByStatus(LikelyTakesSlowPath); 383 408 384 409 if (!result.appendVariant(GetByIdVariant(nullptr, structure, offset))) 385 return GetByStatus( TakesSlowPath);410 return GetByStatus(LikelyTakesSlowPath); 386 411 } 387 412 … … 394 419 switch (m_state) { 395 420 case NoInformation: 396 case TakesSlowPath: 421 case LikelyTakesSlowPath: 422 case ObservedTakesSlowPath: 397 423 case Custom: 398 424 case ModuleNamespace: … … 405 431 return false; 406 432 case MakesCalls: 433 case ObservedSlowPathAndMakesCalls: 407 434 return true; 408 435 } … … 414 441 GetByStatus GetByStatus::slowVersion() const 415 442 { 416 return GetByStatus(makesCalls() ? MakesCalls : TakesSlowPath, wasSeenInJIT()); 443 if (observedStructureStubInfoSlowPath()) 444 return GetByStatus(makesCalls() ? ObservedSlowPathAndMakesCalls : ObservedTakesSlowPath, wasSeenInJIT()); 445 return GetByStatus(makesCalls() ? MakesCalls : LikelyTakesSlowPath, wasSeenInJIT()); 417 446 } 418 447 … … 423 452 424 453 auto mergeSlow = [&] () { 425 *this = GetByStatus((makesCalls() || other.makesCalls()) ? MakesCalls : TakesSlowPath); 454 if (observedStructureStubInfoSlowPath() || other.observedStructureStubInfoSlowPath()) 455 *this = GetByStatus((makesCalls() || other.makesCalls()) ? ObservedSlowPathAndMakesCalls : ObservedTakesSlowPath); 456 else 457 *this = GetByStatus((makesCalls() || other.makesCalls()) ? MakesCalls : LikelyTakesSlowPath); 426 458 }; 427 459 … … 457 489 return; 458 490 459 case TakesSlowPath: 491 case LikelyTakesSlowPath: 492 case ObservedTakesSlowPath: 460 493 case MakesCalls: 494 case ObservedSlowPathAndMakesCalls: 461 495 return mergeSlow(); 462 496 } … … 538 572 out.print("ModuleNamespace"); 539 573 break; 540 case TakesSlowPath: 541 out.print("TakesSlowPath"); 574 case LikelyTakesSlowPath: 575 out.print("LikelyTakesSlowPath"); 576 break; 577 case ObservedTakesSlowPath: 578 out.print("ObservedTakesSlowPath"); 542 579 break; 543 580 case MakesCalls: 544 581 out.print("MakesCalls"); 545 582 break; 583 case ObservedSlowPathAndMakesCalls: 584 out.print("ObservedSlowPathAndMakesCalls"); 585 break; 546 586 } 547 587 out.print(", ", listDump(m_variants), ", seenInJIT = ", m_wasSeenInJIT, ")"); -
trunk/Source/JavaScriptCore/bytecode/GetByStatus.h
r252684 r252763 57 57 // It's cached for an access to a module namespace object's binding. 58 58 ModuleNamespace, 59 // It's known to often take slow path. 60 TakesSlowPath, 61 // It's known to take paths that make calls. 59 // It will likely take the slow path. 60 LikelyTakesSlowPath, 61 // It's known to take slow path. We also observed that the slow path was taken on StructureStubInfo. 62 ObservedTakesSlowPath, 63 // It will likely take the slow path and will make calls. 62 64 MakesCalls, 65 // It known to take paths that make calls. We also observed that the slow path was taken on StructureStubInfo. 66 ObservedSlowPathAndMakesCalls , 67 }; 68 69 enum class TrackIdentifiers : uint8_t { 70 No, // Used for get_by_id 71 Yes, // Used for get_by_val 63 72 }; 64 73 … … 71 80 : m_state(state) 72 81 { 73 ASSERT(state == NoInformation || state == TakesSlowPath || state ==MakesCalls);82 ASSERT(state == NoInformation || state == LikelyTakesSlowPath || state == ObservedTakesSlowPath || state == MakesCalls || state == ObservedSlowPathAndMakesCalls); 74 83 } 75 84 76 explicit GetByStatus(StubInfoSummary summary) 77 : m_wasSeenInJIT(true) 78 { 79 switch (summary) { 80 case StubInfoSummary::NoInformation: 81 m_state = NoInformation; 82 return; 83 case StubInfoSummary::Simple: 84 case StubInfoSummary::MakesCalls: 85 RELEASE_ASSERT_NOT_REACHED(); 86 return; 87 case StubInfoSummary::TakesSlowPath: 88 m_state = TakesSlowPath; 89 return; 90 case StubInfoSummary::TakesSlowPathAndMakesCalls: 91 m_state = MakesCalls; 92 return; 93 } 94 RELEASE_ASSERT_NOT_REACHED(); 95 } 85 explicit GetByStatus(StubInfoSummary, StructureStubInfo&); 96 86 97 87 GetByStatus( … … 102 92 } 103 93 104 static GetByStatus computeFor(CodeBlock* baselineBlock, ICStatusMap& baselineMap, ICStatusContextStack& dfgContextStack, CodeOrigin );94 static GetByStatus computeFor(CodeBlock* baselineBlock, ICStatusMap& baselineMap, ICStatusContextStack& dfgContextStack, CodeOrigin, TrackIdentifiers); 105 95 static GetByStatus computeFor(const StructureSet&, UniquedStringImpl*); 106 96 … … 118 108 const GetByIdVariant& operator[](size_t index) const { return at(index); } 119 109 120 bool takesSlowPath() const { return m_state == TakesSlowPath || m_state == MakesCalls || m_state == Custom || m_state == ModuleNamespace; } 110 bool takesSlowPath() const { return m_state == LikelyTakesSlowPath || m_state == ObservedTakesSlowPath || m_state == MakesCalls || m_state == ObservedSlowPathAndMakesCalls || m_state == Custom || m_state == ModuleNamespace; } 111 bool observedStructureStubInfoSlowPath() const { return m_state == ObservedTakesSlowPath || m_state == ObservedSlowPathAndMakesCalls; } 121 112 bool makesCalls() const; 122 113 … … 124 115 125 116 bool wasSeenInJIT() const { return m_wasSeenInJIT; } 126 127 void merge(const GetByStatus&);128 117 129 118 // Attempts to reduce the set of variants to fit the given structure set. This may be approximate. … … 144 133 145 134 private: 135 void merge(const GetByStatus&); 136 146 137 #if ENABLE(JIT) 147 138 GetByStatus(const ModuleNamespaceAccessCase&); 148 139 static GetByStatus computeForStubInfoWithoutExitSiteFeedback( 149 const ConcurrentJSLocker&, CodeBlock* profiledBlock, StructureStubInfo*, CallLinkStatus::ExitSiteData );140 const ConcurrentJSLocker&, CodeBlock* profiledBlock, StructureStubInfo*, CallLinkStatus::ExitSiteData, TrackIdentifiers); 150 141 #endif 151 static GetByStatus computeFromLLInt(CodeBlock*, BytecodeIndex );152 static GetByStatus computeFor(CodeBlock*, ICStatusMap&, BytecodeIndex, ExitFlag, CallLinkStatus::ExitSiteData );142 static GetByStatus computeFromLLInt(CodeBlock*, BytecodeIndex, TrackIdentifiers); 143 static GetByStatus computeFor(CodeBlock*, ICStatusMap&, BytecodeIndex, ExitFlag, CallLinkStatus::ExitSiteData, TrackIdentifiers); 153 144 154 145 struct ModuleNamespaceData { -
trunk/Source/JavaScriptCore/bytecode/ICStatusUtils.h
r251690 r252763 44 44 if (i == j) 45 45 continue; 46 if (variants[j]. structureSet().overlaps(mergedVariant.structureSet()))46 if (variants[j].overlaps(mergedVariant)) 47 47 return false; 48 48 } … … 55 55 // defensive and bail if we detect crazy. 56 56 for (unsigned i = 0; i < variants.size(); ++i) { 57 if (variants[i]. structureSet().overlaps(variant.structureSet()))57 if (variants[i].overlaps(variant)) 58 58 return false; 59 59 } -
trunk/Source/JavaScriptCore/bytecode/InByIdVariant.h
r248546 r252763 64 64 void dumpInContext(PrintStream&, DumpContext*) const; 65 65 66 bool overlaps(const InByIdVariant& other) 67 { 68 return structureSet().overlaps(other.structureSet()); 69 } 70 66 71 private: 67 72 friend class InByIdStatus; -
trunk/Source/JavaScriptCore/bytecode/InstanceOfVariant.h
r248546 r252763 54 54 void dump(PrintStream&) const; 55 55 void dumpInContext(PrintStream&, DumpContext*) const; 56 57 bool overlaps(const InstanceOfVariant& other) 58 { 59 return structureSet().overlaps(other.structureSet()); 60 } 56 61 57 62 private: -
trunk/Source/JavaScriptCore/bytecode/PutByIdVariant.h
r248546 r252763 139 139 void dumpInContext(PrintStream&, DumpContext*) const; 140 140 141 bool overlaps(const PutByIdVariant& other) 142 { 143 return structureSet().overlaps(other.structureSet()); 144 } 145 141 146 private: 142 147 bool attemptToMergeTransitionWithReplace(const PutByIdVariant& replace); -
trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp
r252684 r252763 284 284 VM& vm = codeBlock->vm(); 285 285 286 bufferedStructures.genericFilter( 287 [&] (Structure* structure) -> bool { 288 return vm.heap.isMarked(structure); 286 bufferedStructures.removeIf( 287 [&] (auto& pair) -> bool { 288 Structure* structure = pair.first; 289 return !vm.heap.isMarked(structure); 289 290 }); 290 291 -
trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h
r252684 r252763 95 95 bool propagateTransitions(SlotVisitor&); 96 96 97 ALWAYS_INLINE bool considerCaching(VM& vm, CodeBlock* codeBlock, Structure* structure )97 ALWAYS_INLINE bool considerCaching(VM& vm, CodeBlock* codeBlock, Structure* structure, UniquedStringImpl* impl = nullptr) 98 98 { 99 99 DisallowGC disallowGC; … … 155 155 // the base's structure. That seems unlikely for the canonical use of instanceof, where 156 156 // the prototype is fixed. 157 bool isNewlyAdded = bufferedStructures.add( structure);157 bool isNewlyAdded = bufferedStructures.add({ structure, impl }).isNewEntry; 158 158 if (isNewlyAdded) 159 159 vm.heap.writeBarrier(codeBlock); … … 189 189 } 190 190 191 private: 191 192 // Represents those structures that already have buffered AccessCases in the PolymorphicAccess. 192 193 // Note that it's always safe to clear this. If we clear it prematurely, then if we see the same 193 194 // structure again during this buffering countdown, we will create an AccessCase object for it. 194 195 // That's not so bad - we'll get rid of the redundant ones once we regenerate. 195 StructureSet bufferedStructures; 196 HashSet<std::pair<Structure*, RefPtr<UniquedStringImpl>>> bufferedStructures; 197 public: 196 198 197 199 struct { -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r252684 r252763 4714 4714 m_inlineStackTop->m_profiledBlock, 4715 4715 m_inlineStackTop->m_baselineMap, m_icContextStack, 4716 currentCodeOrigin() );4716 currentCodeOrigin(), GetByStatus::TrackIdentifiers::No); 4717 4717 4718 4718 AccessType type = AccessType::GetById; … … 5623 5623 Node* property = get(bytecode.m_property); 5624 5624 bool shouldCompileAsGetById = false; 5625 GetByStatus getByStatus = GetByStatus::computeFor(m_inlineStackTop->m_profiledBlock, m_inlineStackTop->m_baselineMap, m_icContextStack, currentCodeOrigin() );5625 GetByStatus getByStatus = GetByStatus::computeFor(m_inlineStackTop->m_profiledBlock, m_inlineStackTop->m_baselineMap, m_icContextStack, currentCodeOrigin(), GetByStatus::TrackIdentifiers::Yes); 5626 5626 unsigned identifierNumber = 0; 5627 5627 { … … 5656 5656 m_exitOK = false; // GetByVal must be treated as if it clobbers exit state, since FixupPhase may make it generic. 5657 5657 set(bytecode.m_dst, getByVal); 5658 if (getByStatus. takesSlowPath())5658 if (getByStatus.observedStructureStubInfoSlowPath()) 5659 5659 m_graph.m_slowGetByVal.add(getByVal); 5660 5660 } -
trunk/Source/JavaScriptCore/jit/JITOperations.cpp
r252756 r252763 2037 2037 LOG_IC((ICEvent::OperationGetByValOptimize, baseValue.classInfoOrNull(vm), propertyName, baseValue == slot.slotBase())); 2038 2038 2039 if (stubInfo->considerCaching(vm, codeBlock, baseValue.structureOrNull() ))2039 if (stubInfo->considerCaching(vm, codeBlock, baseValue.structureOrNull(), propertyName.impl())) 2040 2040 repatchGetBy(globalObject, codeBlock, baseValue, propertyName, slot, *stubInfo, GetByKind::NormalByVal); 2041 2041 return found ? slot.getValue(globalObject, propertyName) : jsUndefined();
Note: See TracChangeset
for help on using the changeset viewer.