Closed
Bug 480657
Opened 16 years ago
Closed 16 years ago
TM: Add an API to define traceable constructors
Categories
(Core :: JavaScript Engine, defect, P2)
Tracking
()
VERIFIED
FIXED
mozilla1.9.1
People
(Reporter: gal, Assigned: brendan)
References
Details
(Keywords: verified1.9.1, Whiteboard: fixed-in-tracemonkey)
Attachments
(2 files, 5 obsolete files)
|
26.51 KB,
patch
|
jorendorff
:
review+
gal
:
review+
|
Details | Diff | Splinter Review |
|
1.80 KB,
patch
|
gal
:
review+
|
Details | Diff | Splinter Review |
No description provided.
| Reporter | ||
Comment 1•16 years ago
|
||
Assignee: general → gal
Attachment #364601 -
Flags: review?(jorendorff)
Comment 2•16 years ago
|
||
This asserts in FUN_CLASP if you try to record `new Math.sin` or some other traceable native.
I don't like adding a field to JSClass for this.
Per convention, js_Object_tn_ci should be called js_Object_ci. I am too crosseyed today to figure out exactly which things you would have to rename to make that happen though...
Updated•16 years ago
|
Attachment #364601 -
Flags: review?(jorendorff)
| Reporter | ||
Comment 3•16 years ago
|
||
Attachment #364601 -
Attachment is obsolete: true
| Reporter | ||
Updated•16 years ago
|
Attachment #364624 -
Flags: review?(brendan)
| Assignee | ||
Comment 4•16 years ago
|
||
Comment on attachment 364624 [details] [diff] [review]
v2
>+++ b/js/src/jsapi.h
>@@ -1305,17 +1305,17 @@ struct JSClass {
> JSPropertyOp addProperty;
> JSPropertyOp delProperty;
> JSPropertyOp getProperty;
> JSPropertyOp setProperty;
> JSEnumerateOp enumerate;
> JSResolveOp resolve;
> JSConvertOp convert;
> JSFinalizeOp finalize;
>-
>+
> /* Optionally non-null members start here. */
> JSGetObjectOps getObjectOps;
> JSCheckAccessOp checkAccess;
> JSNative call;
> JSNative construct;
> JSXDRObjectOp xdrObject;
> JSHasInstanceOp hasInstance;
> JSMarkOp mark;
Revert, revert! Trailing whitespace red flashing alert!
> #define JS_DEFINE_TRCINFO_1(name, tn0) \
> _JS_DEFINE_CALLINFO_n tn0 \
> JSTraceableNative name##_trcinfo[] = { \
>- { name, _JS_TN_INIT_HELPER_n tn0 } \
>+ { (JSFastNative)name, _JS_TN_INIT_HELPER_n tn0 } \
Sad to have to cast to JSFastNative, just for constructors. Food for thought.
>+/* Defined in jsobj.cpp */
>+JS_DECLARE_CALLINFO(js_Object_tn)
>+
> /* Defined in jsarray.cpp */
Nit (one preexisting): full stop at end of such sentences in comments.
>+++ b/js/src/jsfun.h
>@@ -68,22 +68,20 @@ struct JSFunction {
> uint16 nargs; /* maximum number of specified arguments,
> reflected as f.length/f.arity */
> uint16 flags; /* flags, see JSFUN_* below and in jsapi.h */
> union {
> struct {
> uint16 extra; /* number of arg slots for local GC roots */
> uint16 spare; /* reserved for future use */
> JSNative native; /* native method pointer or null */
>+ JSClass *clasp; /* class of objects constructed
>+ by this function */
Line up * with declarators, not before first declarator column.
>+ JSTraceableNative *trcinfo; /* tracer metadata; can be first
>+ element of array */
I wonder if we shouldn't union trcinfo with extra+spare (which could be one uint32). Only functions defined using JS_InitClass's trailing fs and static_fs parameters, and via JS_DefineFunctions, need extra.
> #define FUN_CLASP(fun) (JS_ASSERT(!FUN_INTERPRETED(fun)), \
> JS_ASSERT(!((fun)->flags & JSFUN_TRACEABLE)), \
>- fun->u.n.u.clasp)
>+ fun->u.n.clasp)
The assertion that fun is not traceable is obsolete now.
>+void
>+js_SetTraceableNativeCallInfo(JSContext *cx, JSObject *proto, JSTraceableNative *trcinfo)
>+{
>+ JSFunction *fun = GET_FUNCTION_PRIVATE(cx, JS_GetConstructor(cx, proto));
>+ JS_ASSERT(!(fun->flags & JSFUN_TRACEABLE));
>+ fun->u.n.trcinfo = trcinfo;
>+ fun->flags |= JSFUN_TRACEABLE;
>+}
Use a shorter and arguably more descriptive (in light of flag setting) name: js_SetTraceableNative.
/be
| Assignee | ||
Comment 5•16 years ago
|
||
(In reply to comment #4)
> I wonder if we shouldn't union trcinfo with extra+spare (which could be one
> uint32). Only functions defined using JS_InitClass's trailing fs and static_fs
> parameters, and via JS_DefineFunctions, need extra.
Never mind, this won't work -- lots of such string, etc. methods defined in the engine with extra and traceable. Better to work on booting out extra+spare in a separate bug.
/be
| Reporter | ||
Comment 6•16 years ago
|
||
Attachment #364624 -
Attachment is obsolete: true
Attachment #364624 -
Flags: review?(brendan)
| Reporter | ||
Updated•16 years ago
|
Attachment #364727 -
Flags: review?(brendan)
| Reporter | ||
Updated•16 years ago
|
Attachment #364624 -
Flags: review?(brendan)
| Assignee | ||
Comment 7•16 years ago
|
||
Comment on attachment 364727 [details] [diff] [review]
v3
> js_InitObjectClass(JSContext *cx, JSObject *obj)
> {
>- return JS_InitClass(cx, obj, NULL, &js_ObjectClass, js_Object, 1,
>- object_props, object_methods, NULL,
>- object_static_methods);
>+ obj = JS_InitClass(cx, obj, NULL, &js_ObjectClass, js_Object, 1,
>+ object_props, object_methods, NULL,
>+ object_static_methods);
>+#ifdef JS_TRACER
>+ if (obj)
>+ js_SetTraceableNative(cx, obj, js_Object_trcinfo);
>+#endif
>+ return obj;
> }
Uber-nit: would be clearer to use JSObject *proto = JS_InitClass(...); ... return proto; here instead of reusing obj (the top-level or global object). r=me anyway, thanks.
/be
Attachment #364727 -
Flags: review?(brendan) → review+
| Reporter | ||
Comment 8•16 years ago
|
||
I live to serve. Pushed with uber-nit fixed.
http://hg.mozilla.org/tracemonkey/rev/43d1d9137629
Status: NEW → ASSIGNED
Whiteboard: fixed-in-tracemonkey
| Assignee | ||
Comment 9•16 years ago
|
||
(In reply to comment #2)
> Per convention, js_Object_tn_ci should be called js_Object_ci.
Looks like this comment from Jason was missed -- sorry I didn't check for it.
/be
| Assignee | ||
Comment 10•16 years ago
|
||
Also, with C++ it's possible to declare at first use (set, initialization) site, so we don't need C's army of uninitialized decls up top in each function. So either
js_InitObjectClass(...)
{
JSObject *proto = JS_InitClass(...);
...
or else
js_InitObjectClass(...)
{
JSObject *proto;
proto = JS_InitClass(...);
...
but not the checked-in form that crunches lines together with uninitialized decls and no blank line separating decls from stmts.
Same for js_SetTraceableNative.
/be
| Assignee | ||
Updated•16 years ago
|
Attachment #364624 -
Flags: review?(brendan)
| Reporter | ||
Comment 11•16 years ago
|
||
The CALLINFO macro picked the js_Object_tn_ci naming, not me. I can't change it.
The extra spaces moves the JS_InitClass beyond the old world boundaries. As long thats ok I will follow up with a quick patch.
| Assignee | ||
Comment 12•16 years ago
|
||
Do we need the _tn suffix on the explicitly defined function name? If that is not dictated by a macro, we could have js_Object, js_Date, etc. Or a convention that extends the name without colliding with existing js_NewObject, etc., names.
I've been going past 79 judiciously in old files. But you could rewrap params, sometimes related ones pair or triple up nicely.
/be
| Reporter | ||
Comment 13•16 years ago
|
||
js_Object_tn is the name of the FASTCALL native we call from trace. I can't rename it to js_Object since thats the name of the actual JSFastNative.
I re-wrapped as suggested.
| Assignee | ||
Comment 14•16 years ago
|
||
Ok, _tn_ci and an occasional _helper, Helper, or _sub it is ;-). Too much of this makes for cybercrud, though.
/be
| Reporter | ||
Comment 15•16 years ago
|
||
| Reporter | ||
Updated•16 years ago
|
Whiteboard: fixed-in-tracemonkey
| Assignee | ||
Comment 17•16 years ago
|
||
Testcase from bug 480791:
eval("new Math.sin");
/be
| Assignee | ||
Comment 18•16 years ago
|
||
Looking to get this into TM soon, upvar2 depends on it.
/be
Assignee: gal → brendan
Attachment #364727 -
Attachment is obsolete: true
Attachment #365063 -
Flags: review?(jorendorff)
| Assignee | ||
Comment 19•16 years ago
|
||
Why this matters for upvar2: user-defined functions may be constructors, in which case for function f, (new f).__proto__ === f.prototype. This means touching the current js_FastNewObject code in ways that overlap this patch, and benefit from it landing first.
/be
Assignee: brendan → gal
Flags: blocking1.9.1?
Updated•16 years ago
|
Attachment #365063 -
Flags: review?(jorendorff) → review+
Comment 20•16 years ago
|
||
Comment on attachment 365063 [details] [diff] [review]
v4
The name _JS_CTYPE_CALLEE_PROTO wasn't immediately clear. Maybe _JS_CTYPE_CLASS_PROTOTYPE?
getClassPrototype looks like it's only valid if the .prototype property is PERMANENT and READONLY (as is the case only for a few builtin constructors). It could assert that, just as an executable comment. (To avoid adding a lot of clutter, the assertion could use a very-high-level API like JS_GetPropertyAttributes.)
There's code in js_Object_tn that calculates clasp, but the answer is always the same, right? It should just say:
JS_ASSERT(FUN_INTERPRETED(ctor) || FUN_CLASP(ctor) == &js_ObjectClass);
If there were one traceable native for Object() and a separate one for interpreted constructors, Object() could be faster (it could use CALLEE_PROTO). Maybe not worth it.
| Assignee | ||
Comment 21•16 years ago
|
||
(In reply to comment #20)
> (From update of attachment 365063 [details] [diff] [review])
> The name _JS_CTYPE_CALLEE_PROTO wasn't immediately clear. Maybe
> _JS_CTYPE_CLASS_PROTOTYPE?
Will do.
> getClassPrototype looks like it's only valid if the .prototype property is
> PERMANENT and READONLY (as is the case only for a few builtin constructors).
> It could assert that, just as an executable comment. (To avoid adding a lot of
> clutter, the assertion could use a very-high-level API like
> JS_GetPropertyAttributes.)
Ditto.
> There's code in js_Object_tn that calculates clasp, but the answer is always
> the same, right? It should just say:
>
> JS_ASSERT(FUN_INTERPRETED(ctor) || FUN_CLASP(ctor) == &js_ObjectClass);
I realized this over dinner. Fixing.
> If there were one traceable native for Object() and a separate one for
> interpreted constructors, Object() could be faster (it could use CALLEE_PROTO).
> Maybe not worth it.
I was planning to do this, here or in a followup (possibly upvar2). Will do it here, patch shortly. Thanks,
/be
Assignee: gal → brendan
OS: Mac OS X → All
Priority: -- → P2
Hardware: x86 → All
Target Milestone: --- → mozilla1.9.1
| Assignee | ||
Comment 22•16 years ago
|
||
js_NewInstance follows the user-defined ctor.prototype rules on trace without needing to use FAIL_STATUS. Jason, thanks for the excellent comments -- I would appreciate one more review from you.
/be
Attachment #365063 -
Attachment is obsolete: true
Attachment #365154 -
Flags: review?(jorendorff)
Updated•16 years ago
|
Attachment #365154 -
Flags: review?(jorendorff) → review+
Comment 23•16 years ago
|
||
Comment on attachment 365154 [details] [diff] [review]
v5
One bug here:
>+JS_DEFINE_CALLINFO_2(extern, CONSTRUCTOR_RETRY, js_NewInstance, CONTEXT, CLASS_PROTOTYPE, 0, 0)
That should be CALLEE, not CLASS_PROTOTYPE.
IIUC, js_NewInstance has some significant bug fixes over the existing js_FastNewObject code (handling the case where ctor shares a scope, for instance). Can you give a test case that would expose the bugs?
Style nits: In a few places the new code strikes me as too low-level -- using != in the for-loop condition instead of the idiomatic <, and obj->fslots[JSSLOT_PARENT] instead of OBJ_GET_PARENT(cx, obj).
Except for rooting, the interpreter could use this code too (in case JSOP_NEW when FUN_INTERPRETED(fun)). Alas I think the root-as-we-go in JSOP_NEW is necessary with JS_THREADSAFE.
r=me with the one fix.
| Assignee | ||
Comment 24•16 years ago
|
||
(In reply to comment #23)
> (From update of attachment 365154 [details] [diff] [review])
> One bug here:
>
> >+JS_DEFINE_CALLINFO_2(extern, CONSTRUCTOR_RETRY, js_NewInstance, CONTEXT, CLASS_PROTOTYPE, 0, 0)
>
> That should be CALLEE, not CLASS_PROTOTYPE.
Oops, fixed.
> IIUC, js_NewInstance has some significant bug fixes over the existing
> js_FastNewObject code (handling the case where ctor shares a scope, for
> instance). Can you give a test case that would expose the bugs?
Gary's fuzzing produced one that depends on the upvar2 patch:
for (var x = 0; x < 3; ++x) { new function(){} }
Without the upvar2 patch, the buggy TraceRecorder::record_JSOP_LAMBDA stuffs the compiler-created function object into the trace, which satisfies the "own scope" assertion in js_FastNewObject but does not provide the right prototype per new call (observable via the completion value for the loop).
I'll see if I can write a test for this tomorrow.
> Style nits: In a few places the new code strikes me as too low-level -- using
> != in the for-loop condition instead of the idiomatic <, and
Clashing styles:
Yoyodyne:src brendaneich$ grep ' < JS_INITIAL_NSLOTS' *.cpp
jstracer.cpp: if (size_t(p - globalObj->fslots) < JS_INITIAL_NSLOTS)
jstracer.cpp: return ((size_t(p - globalObj->fslots) < JS_INITIAL_NSLOTS) ||
jstracer.cpp: if (slot < JS_INITIAL_NSLOTS) {
jstracer.cpp: JS_ASSERT(slot < JS_INITIAL_NSLOTS);
jstracer.cpp: if (slot < JS_INITIAL_NSLOTS)
Yoyodyne:src brendaneich$ grep ' != JS_INITIAL_NSLOTS' *.cpp
jsarray.cpp: for (unsigned i = JSSLOT_ARRAY_COUNT + 1; i != JS_INITIAL_NSLOTS; ++i)
jsdate.cpp: for (unsigned i = JSSLOT_LOCAL_TIME + 1; i != JS_INITIAL_NSLOTS; ++i)
jsobj.cpp: for (unsigned i = JSSLOT_PRIVATE; i != JS_INITIAL_NSLOTS; ++i)
jsobj.cpp: for (unsigned i = JSSLOT_PRIVATE; i != JS_INITIAL_NSLOTS; ++i)
jsobj.cpp: for (i = JSSLOT_PRIVATE; i != JS_INITIAL_NSLOTS; ++i)
The first two jsobj.cpp ones are from this bug's patch; the last predates and is in js_NewObjectWithGivenProto. I'm gonna stick with that for now.
> obj->fslots[JSSLOT_PARENT] instead of OBJ_GET_PARENT(cx, obj).
That's intentional style, Igor and I have been using it for newborns and other thread-local objects to avoid the macro obfuscation and show the C economics as clearly as possible.
> Except for rooting, the interpreter could use this code too (in case JSOP_NEW
> when FUN_INTERPRETED(fun)). Alas I think the root-as-we-go in JSOP_NEW is
> necessary with JS_THREADSAFE.
Yup.
> r=me with the one fix.
Ok, will commit with whatever tests are feasible tomorrow. Thanks again,
/be
Assignee: brendan → gal
OS: All → Mac OS X
Priority: P2 → --
Hardware: All → x86
Target Milestone: mozilla1.9.1 → ---
| Assignee | ||
Updated•16 years ago
|
Assignee: gal → brendan
Priority: -- → P2
Target Milestone: --- → mozilla1.9.1
| Assignee | ||
Comment 25•16 years ago
|
||
The js_SetTraceableNative approach fails in-browser due to security checks failing when trying to get Object.prototype.constructor (given the return value of JS_InitClass in js_InitObjectClass, call it proto, js_SetTraceableNative used JS_GetConstructor to get the ctor, etc. -- when cx->fp is null this means the security manager can't get a subject principal, so it censors the ctor).
I added a JS_InitTraceableClass API. The name isn't quite right but I'm loath to add JS_InitClassWithTraceableConstructor. Suggestions welcome.
/be
Attachment #365154 -
Attachment is obsolete: true
Attachment #365369 -
Flags: review?(jorendorff)
| Assignee | ||
Updated•16 years ago
|
Attachment #365369 -
Flags: review?(gal)
| Reporter | ||
Updated•16 years ago
|
Attachment #365369 -
Flags: review?(gal) → review+
| Assignee | ||
Comment 26•16 years ago
|
||
Committed to tm:
http://hg.mozilla.org/tracemonkey/rev/3b5f828befde
I wanted to get this cycling tonight. Jason, let me know if you want any changes. We can do cosmetics and any further work in bug 480759.
/be
Whiteboard: fixed-in-tracemonkey
| Assignee | ||
Comment 27•16 years ago
|
||
Build bustage for PPC Mac -- checking in.
/be
Attachment #365397 -
Flags: review?(gal)
| Reporter | ||
Updated•16 years ago
|
Attachment #365397 -
Flags: review?(gal) → review+
| Assignee | ||
Comment 28•16 years ago
|
||
Followup fix is in tm:
http://hg.mozilla.org/tracemonkey/rev/f82a4510d4b8
/be
Comment 29•16 years ago
|
||
Brendan, can we change JS_InitTraceableClass -> js_InitClass and move it to jsobj.h?
It seems weird having a function in jsapi.h that embeddings can't call short of including nonpublic headers.
| Assignee | ||
Comment 30•16 years ago
|
||
/be(In reply to comment #29)
> Brendan, can we change JS_InitTraceableClass -> js_InitClass and move it to
> jsobj.h?
Good idea, shoulda thought of that. I will do this in an updated patch for bug 480759. One question, though:
> It seems weird having a function in jsapi.h that embeddings can't call short of
> including nonpublic headers.
Do we expect no embedding will want to make its class constructors traceable? Or will they have to use non-public headers?
/be
| Assignee | ||
Comment 31•16 years ago
|
||
(In reply to comment #30)
> > It seems weird having a function in jsapi.h that embeddings can't call short of
> > including nonpublic headers.
>
> Do we expect no embedding will want to make its class constructors traceable?
> Or will they have to use non-public headers?
To answer my own question, it seems we want a generic traceable native wrapper for outside-the-engine stuff, and internal APIs such as js_InitClass for inside. If the generic wrapper can be done soon and it meets the needs of embeddings (like, the Gecko DOM!), I am more than happy.
/be
Updated•16 years ago
|
Attachment #365369 -
Flags: review?(jorendorff) → review+
Comment 32•16 years ago
|
||
Comment 31 re-raises questions that we should finish discussing in bug 463238 (where conversation apparently trailed off in confusion).
| Assignee | ||
Comment 33•16 years ago
|
||
(In reply to comment #32)
> Comment 31 re-raises questions that we should finish discussing in bug 463238
> (where conversation apparently trailed off in confusion).
I commented in bug 463238 comment 11. HTH,
/be
| Assignee | ||
Comment 34•16 years ago
|
||
Comment on attachment 364727 [details] [diff] [review]
v3
>- if (!constructing && !(fun->flags & JSFUN_TRACEABLE))
>+ if (!(fun->flags & JSFUN_TRACEABLE))
> ABORT_TRACE("untraceable native");
Argh, the removal of the !constructing predicate caused bug 481754.
/be
| Assignee | ||
Comment 35•16 years ago
|
||
(In reply to comment #34)
> (From update of attachment 364727 [details] [diff] [review])
> >- if (!constructing && !(fun->flags & JSFUN_TRACEABLE))
> >+ if (!(fun->flags & JSFUN_TRACEABLE))
> > ABORT_TRACE("untraceable native");
>
> Argh, the removal of the !constructing predicate caused bug 481754.
That removal was necessary given the next few lines in the patch, but we need a special case for js_Array, the slow native. Fixing over in bug 481754.
/be
Comment 36•16 years ago
|
||
http://hg.mozilla.org/tracemonkey/rev/1c16405d7d6c
/cvsroot/mozilla/js/tests/js1_8_1/trace/trace-test.js,v <-- trace-test.js
new revision: 1.12; previous revision: 1.11
Flags: in-testsuite+
Comment 37•16 years ago
|
||
Status: ASSIGNED → RESOLVED
Closed: 16 years ago
Resolution: --- → FIXED
Updated•16 years ago
|
Flags: blocking1.9.1? → blocking1.9.1+
Comment 38•16 years ago
|
||
Keywords: fixed1.9.1
Comment 39•16 years ago
|
||
v 1.9.1, 1.9.2
Status: RESOLVED → VERIFIED
Keywords: fixed1.9.1 → verified1.9.1
You need to log in
before you can comment on or make changes to this bug.
Description
•