Changeset 249247 in webkit
- Timestamp:
- Aug 28, 2019 11:49:28 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r249225 r249247 1 2019-08-28 Mark Lam <mark.lam@apple.com> 2 3 DFG/FTL: We should prefetch structures and do a loadLoadFence before doing PrototypeChainIsSane checks. 4 https://bugs.webkit.org/show_bug.cgi?id=201281 5 <rdar://problem/54028228> 6 7 Reviewed by Yusuke Suzuki and Saam Barati. 8 9 * stress/structure-storedPrototype-should-only-assert-on-the-mutator-thread.js: Added. 10 1 11 2019-08-28 Mark Lam <mark.lam@apple.com> 2 12 -
trunk/Source/JavaScriptCore/ChangeLog
r249225 r249247 1 2019-08-28 Mark Lam <mark.lam@apple.com> 2 3 DFG/FTL: We should prefetch structures and do a loadLoadFence before doing PrototypeChainIsSane checks. 4 https://bugs.webkit.org/show_bug.cgi?id=201281 5 <rdar://problem/54028228> 6 7 Reviewed by Yusuke Suzuki and Saam Barati. 8 9 This (see title above) is already the preferred idiom used in most places in our 10 compiler, except for 2: DFG's SpeculativeJIT::compileGetByValOnString() and FTL's 11 compileStringCharAt(). Consider the following: 12 13 bool prototypeChainIsSane = false; 14 if (globalObject->stringPrototypeChainIsSane()) { 15 ... 16 m_graph.registerAndWatchStructureTransition(globalObject->stringPrototype()->structure(vm())); 17 m_graph.registerAndWatchStructureTransition(globalObject->objectPrototype()->structure(vm())); 18 19 prototypeChainIsSane = globalObject->stringPrototypeChainIsSane(); 20 } 21 22 What's essential for correctness here is that the stringPrototype and objectPrototype 23 structures be loaded before the loads in the second stringPrototypeChainIsSane() 24 check. Without a loadLoadFence before the second stringPrototypeChainIsSane() 25 check, we can't guarantee that. Elsewhere in the compiler, the preferred idiom 26 for doing this right is to pre-load the structures first, do a loadLoadFence, and 27 then do the IsSane check just once after e.g. 28 29 Structure* arrayPrototypeStructure = globalObject->arrayPrototype()->structure(m_vm); 30 Structure* objectPrototypeStructure = globalObject->objectPrototype()->structure(m_vm); 31 32 if (arrayPrototypeStructure->transitionWatchpointSetIsStillValid() // has loadLoadFences. 33 && objectPrototypeStructure->transitionWatchpointSetIsStillValid() // has loadLoadFences. 34 && globalObject->arrayPrototypeChainIsSane()) { 35 36 m_graph.registerAndWatchStructureTransition(arrayPrototypeStructure); 37 m_graph.registerAndWatchStructureTransition(objectPrototypeStructure); 38 ... 39 } 40 41 This patch changes DFG's SpeculativeJIT::compileGetByValOnString() and FTL's 42 compileStringCharAt() to follow the same idiom. 43 44 We also fix a bad assertion in Structure::storedPrototype() and 45 Structure::storedPrototypeObject(). The assertion is only correct when those 46 methods are called from the mutator thread. The assertion has been updated to 47 only check its test condition if the current thread is the mutator thread. 48 49 * dfg/DFGSpeculativeJIT.cpp: 50 (JSC::DFG::SpeculativeJIT::compileGetByValOnString): 51 * ftl/FTLLowerDFGToB3.cpp: 52 (JSC::FTL::DFG::LowerDFGToB3::compileStringCharAt): 53 * runtime/StructureInlines.h: 54 (JSC::Structure::storedPrototype const): 55 (JSC::Structure::storedPrototypeObject const): 56 1 57 2019-08-28 Mark Lam <mark.lam@apple.com> 2 58 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r249184 r249247 2232 2232 2233 2233 JSGlobalObject* globalObject = m_jit.globalObjectFor(node->origin.semantic); 2234 bool prototypeChainIsSane = false; 2234 Structure* stringPrototypeStructure = globalObject->stringPrototype()->structure(vm); 2235 Structure* objectPrototypeStructure = globalObject->objectPrototype()->structure(vm); 2236 WTF::loadLoadFence(); 2237 2235 2238 if (globalObject->stringPrototypeChainIsSane()) { 2236 2239 // FIXME: This could be captured using a Speculation mode that means "out-of-bounds … … 2240 2243 // indexed properties either. 2241 2244 // https://bugs.webkit.org/show_bug.cgi?id=144668 2242 m_jit.graph().registerAndWatchStructureTransition(globalObject->stringPrototype()->structure(vm)); 2243 m_jit.graph().registerAndWatchStructureTransition(globalObject->objectPrototype()->structure(vm)); 2244 prototypeChainIsSane = globalObject->stringPrototypeChainIsSane(); 2245 } 2246 if (prototypeChainIsSane) { 2245 m_jit.graph().registerAndWatchStructureTransition(stringPrototypeStructure); 2246 m_jit.graph().registerAndWatchStructureTransition(objectPrototypeStructure); 2247 2247 2248 #if USE(JSVALUE64) 2248 2249 addSlowPathGenerator(makeUnique<SaneStringGetByValSlowPathGenerator>( -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r249184 r249247 6979 6979 } else { 6980 6980 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic); 6981 6982 bool prototypeChainIsSane = false; 6981 Structure* stringPrototypeStructure = globalObject->stringPrototype()->structure(vm()); 6982 Structure* objectPrototypeStructure = globalObject->objectPrototype()->structure(vm()); 6983 WTF::loadLoadFence(); 6984 6983 6985 if (globalObject->stringPrototypeChainIsSane()) { 6984 6986 // FIXME: This could be captured using a Speculation mode that means … … 6987 6989 // https://bugs.webkit.org/show_bug.cgi?id=144668 6988 6990 6989 m_graph.registerAndWatchStructureTransition(globalObject->stringPrototype()->structure(vm())); 6990 m_graph.registerAndWatchStructureTransition(globalObject->objectPrototype()->structure(vm())); 6991 6992 prototypeChainIsSane = globalObject->stringPrototypeChainIsSane(); 6993 } 6994 if (prototypeChainIsSane) { 6991 m_graph.registerAndWatchStructureTransition(stringPrototypeStructure); 6992 m_graph.registerAndWatchStructureTransition(objectPrototypeStructure); 6993 6995 6994 LBasicBlock negativeIndex = m_out.newBlock(); 6996 6995 -
trunk/Source/JavaScriptCore/runtime/StructureInlines.h
r249175 r249247 109 109 ALWAYS_INLINE JSValue Structure::storedPrototype(const JSObject* object) const 110 110 { 111 ASSERT( object->structure() == this);111 ASSERT(!isMainThread() || object->structure() == this); 112 112 if (hasMonoProto()) 113 113 return storedPrototype(); … … 117 117 ALWAYS_INLINE JSObject* Structure::storedPrototypeObject(const JSObject* object) const 118 118 { 119 ASSERT( object->structure() == this);119 ASSERT(!isMainThread() || object->structure() == this); 120 120 if (hasMonoProto()) 121 121 return storedPrototypeObject();
Note: See TracChangeset
for help on using the changeset viewer.