Closed
Bug 499772
Opened 15 years ago
Closed 15 years ago
TM: TraceRecorder::test_property_cache missing JSClass.getProperty checks when a property isn't found on an object
Categories
(Core :: JavaScript Engine, defect)
Core
JavaScript Engine
Tracking
()
RESOLVED
FIXED
People
(Reporter: Waldo, Assigned: Waldo)
References
Details
(Keywords: fixed1.9.1.1, Whiteboard: fixed-in-tracemonkey)
Attachments
(1 file, 1 obsolete file)
1.38 KB,
patch
|
jorendorff
:
review+
brendan
:
review+
beltzner
:
approval1.9.1.1+
|
Details | Diff | Splinter Review |
See bug 452899, particularly the verbose log, when getlocalprop is traced: we attempt to trace the reading of wrappedStmt.params, which isn't yet present on the object, so we do the walk-up-the-proto-chain-shape-guarding trick and return undefined. Then we enter the interpreter, resolve the property returns nothing, then we call JSClass.getProperty -- which is not stubbed and which returns a value, and then subsequent traced methods think they're operating on an object, and (I think, memory hazy, verifying details is an exercise for the reader) when we enter trace we assert when unboxing undefined as an object. This can bite extensions which have loops which include accesses to properties defined by nsIXPCScriptable::GetProperty (not to mention our own code, as evidenced by the bug this blocks), and I expect such will happen in extensions (to what extent it's difficult to say), hence the wanted? nomination.
Attachment #384469 -
Flags: review?(jorendorff)
Flags: wanted1.9.1.x?
Assignee | ||
Comment 1•15 years ago
|
||
(Ignore the spurious change, didn't realize I'd let that into this patch.)
Comment 2•15 years ago
|
||
Comment on attachment 384469 [details] [diff] [review] Abort if JSClass.getProperty isn't stubbed, guard on the class at runtime >From: Jeff Walden <jwalden@mit.edu> > >Ware JSClass.getProperty when tracing through an undefined-property access. NOT REVIEWED YET > >diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp >--- a/js/src/jstracer.cpp >+++ b/js/src/jstracer.cpp >@@ -9062,6 +9062,19 @@ TraceRecorder::prop(JSObject* obj, LIns* > const JSCodeSpec& cs = js_CodeSpec[*cx->fp->regs->pc]; > if (PCVAL_IS_NULL(pcval)) { > /* >+ * We can't trace here if a value might be returned by the object's >+ * JSClass.getProperty hook. We could specialize to guard on just the Wahh, cheese-eating French spacing. >+ * identity of JSClass.getProperty, but a mere class guard will be >+ * slightly faster and is more likely to prevent overtracing if a >+ * differing class is a good predictor of future aborts or side exits. How would we know that? This code wouldn't. S'ok to use a simpler "cover" guard for now. >+ */ >+ if (OBJ_GET_CLASS(cx, obj)->getProperty != JS_PropertyStub) { >+ ABORT_TRACE("can't trace through access to undefined property if " >+ "JSClass.getProperty hook might return a value"); >+ } >+ guardClass(obj, obj_ins, OBJ_GET_CLASS(cx, obj), snapshot(MISMATCH_EXIT)); >+ >+ /* > * This trace will be valid as long as neither the object nor any object > * on its prototype chain change shape. Bonus for fixing the grammar here by using "changes". /be
Assignee | ||
Comment 3•15 years ago
|
||
While I'm thinking of it, do the shape guards defend against JSClass.getProperty or JSObjectOps.getProperty hooks along the proto chain? (Gaah, stupid name conflict.) Is either even called? I don't *think* the former is from a code skim, but I don't know about the latter.
Attachment #384469 -
Attachment is obsolete: true
Attachment #384491 -
Flags: review?(jorendorff)
Attachment #384491 -
Flags: review?(brendan)
Attachment #384469 -
Flags: review?(jorendorff)
Comment 4•15 years ago
|
||
Comment on attachment 384491 [details] [diff] [review] No more cheese means no more wine :-( , wahh back, adjust some comments and the abort message I still think the comment is wordy. :) You had me at "simpler". > While I'm thinking of it, do the shape guards defend against > JSClass.getProperty or JSObjectOps.getProperty hooks along the proto chain? > (Gaah, stupid name conflict.) Is either even called? I don't *think* the > former is from a code skim, but I don't know about the latter. JSClass.getProperty is not called in that case, but JSObjectOps.getProperty is, and I don't know if we guard against that. XPC wrappers apparently use the native JSObjectOps.getProperty, and I don't think it can matter for With objects. If that is correct, it could only be a problem for E4X objects. Again, not sure there *is* a problem, but it seems worth checking.
Attachment #384491 -
Flags: review?(jorendorff) → review+
Comment 5•15 years ago
|
||
(In reply to comment #4) > (From update of attachment 384491 [details] [diff] [review]) > I still think the comment is wordy. :) You had me at "simpler". Me too. Waldo, shorten! > > While I'm thinking of it, do the shape guards defend against > > JSClass.getProperty or JSObjectOps.getProperty hooks along the proto chain? > > (Gaah, stupid name conflict.) Is either even called? I don't *think* the > > former is from a code skim, but I don't know about the latter. Only the direct object's class getProperty is called as a last ditch before returning undefined (with a possible strict warning), see js_GetProperty: if (!prop) { *vp = JSVAL_VOID; if (!OBJ_GET_CLASS(cx, obj)->getProperty(cx, obj, ID_TO_VALUE(id), vp)) return JS_FALSE; ... > JSClass.getProperty is not called in that case, Not on any proto, but on the direct object it is, as shown above. > but JSObjectOps.getProperty is, > and I don't know if we guard against that. You mean where js_GetProperty finds the id'ed prop in a non-native object and so vectors off via OBJ_GET_PROPERTY: if (!OBJ_IS_NATIVE(obj2)) { OBJ_DROP_PROPERTY(cx, obj2, prop); return OBJ_GET_PROPERTY(cx, obj2, id, vp); } But this won't trace because the property was found in a non-native proto, IIRC. Right? Agree this needs double-checking. /be
Updated•15 years ago
|
Attachment #384491 -
Flags: review?(brendan) → review+
Assignee | ||
Comment 6•15 years ago
|
||
http://hg.mozilla.org/tracemonkey/rev/21d46a88aed6 (In reply to comment #5) > Me too. Waldo, shorten! Okay, shortened a bit more. > Only the direct object's class getProperty is called as a last ditch before > returning undefined (with a possible strict warning), see js_GetProperty: That was my reading, but it seems...not what I'd have expected. Given: var o = Object.create(wrappedStmt); I'd expect |o.params !== undefined|, but my reading says that just isn't the case. > But this won't trace because the property was found in a non-native proto, > IIRC. Right? Agree this needs double-checking. Yeah, that case is fine, we'd have had problems long ago if it weren't -- see the map_is_native check in test_property_cache. Time to let bake, then maybe get in 191 if we have the RCs to do it, else for a dot release. Incidentally, I had an in-person JS assert debug request which turned out to be this bug a second time, so even if no one else hits it (unlikely) *we* will probably keep hitting it without a fix.
Whiteboard: fixed-in-tracemonkey
Comment 7•15 years ago
|
||
(In reply to comment #5) > > JSClass.getProperty is not called in that case, > > Not on any proto, but on the direct object it is, as shown above. Yes, that's exactly what I meant. > > but JSObjectOps.getProperty is, > > and I don't know if we guard against that. > > You mean where js_GetProperty finds the id'ed prop in a non-native object and > so vectors off via OBJ_GET_PROPERTY: > > if (!OBJ_IS_NATIVE(obj2)) { > OBJ_DROP_PROPERTY(cx, obj2, prop); > return OBJ_GET_PROPERTY(cx, obj2, id, vp); > } > > But this won't trace because the property was found in a non-native proto, > IIRC. Right? Agree this needs double-checking. A few objects have a non-native JSObjectOps.getProperty but have scopes and count as native. The property cache (at least) depends on an invariant that JSObjectOps.lookupProperty + js_NativeGet = JSObjectOps.getProperty for these objects. That looks reasonable, and I think it holds--I just didn't know about it before. However I think we do probably have some bugs around these semi-native objects. Here's one: p = <a><b>ok</b></a>; c = {__proto__: p}; assertEq(c.b, p.b); test.js:6: TypeError: Assertion failed: got (void 0), expected <b>ok</b> I think that one could be fixed by patching js_LookupPropertyWithFlags: proto = LOCKED_OBJ_GET_PROTO(obj); JS_UNLOCK_OBJ(cx, obj); if (!proto) break; - if (!OBJ_IS_NATIVE(proto)) { + if (proto->map->ops->lookupProperty != js_LookupProperty) { if (!OBJ_LOOKUP_PROPERTY(cx, proto, id, objp, propp)) return -1; return protoIndex + 1; } But I'm not sure about the implications of this fix. It might result in the tracer filling the property cache in situations where the interpreter wouldn't. I don't know if that would be OK. I do know that *not* filling the property cache could be bad, since JIT and interpreter must see the same result type. (Currently they see the same result type here because, thanks to the bug, the lookup misses.) If we do not bump the XML node's shape when it is mutated, that's probably another bug.
Assignee | ||
Updated•15 years ago
|
Whiteboard: fixed-in-tracemonkey → [3.5.1?] fixed-in-tracemonkey
Updated•15 years ago
|
Flags: wanted1.9.1.x?
Flags: wanted1.9.1.x+
Flags: blocking1.9.1.1?
Whiteboard: [3.5.1?] fixed-in-tracemonkey → fixed-in-tracemonkey
Comment 8•15 years ago
|
||
http://hg.mozilla.org/mozilla-central/rev/21d46a88aed6
Status: ASSIGNED → RESOLVED
Closed: 15 years ago
Resolution: --- → FIXED
Assignee | ||
Updated•15 years ago
|
Attachment #384491 -
Flags: approval1.9.1.1?
Assignee | ||
Comment 9•15 years ago
|
||
Comment on attachment 384491 [details] [diff] [review] No more cheese means no more wine :-( , wahh back, adjust some comments and the abort message Simple and well-understood fix, crash could bite an indeterminate number of extensions, also can bite if they touch our visible APIs just wrongly enough, and I think a web page might be able to trigger the crash...definitely something to take.
Comment 10•15 years ago
|
||
Comment on attachment 384491 [details] [diff] [review] No more cheese means no more wine :-( , wahh back, adjust some comments and the abort message Let's get this in, please, ASAP.
Attachment #384491 -
Flags: approval1.9.1.1? → approval1.9.1.1+
Updated•15 years ago
|
Flags: blocking1.9.1.1? → blocking1.9.1.1+
Comment 11•15 years ago
|
||
http://hg.mozilla.org/releases/mozilla-1.9.1/rev/79292a9fdeb1
Keywords: fixed1.9.1.1
Comment 12•15 years ago
|
||
Jeff, how would we test this?
Assignee | ||
Comment 13•15 years ago
|
||
The bug this blocks added an xpcshell test which hits this. Other than that we could add a jsshell test if we hacked up an object with a JSClass.getProperty hook; I don't believe any such objects exists in the world of the shell, or at least I saw none when I looked during writing the patch, but it's certainly feasible. I didn't think it was particularly important to do the shell-hackery and test-writing given the xpcshell-test backstop.
Comment 14•15 years ago
|
||
Waldo: can you verify that this is fixed in latest-mozilla1.9.1 nightly or better yet the 3.5.1 release candidate: ftp://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/3.5.1-candidates/build1/
You need to log in
before you can comment on or make changes to this bug.
Description
•