Closed Bug 529833 Opened 16 years ago Closed 16 years ago

We can jit-compile coerceUnboxEnter

Categories

(Tamarin Graveyard :: Virtual Machine, defect)

defect
Not set
normal

Tracking

(Not tracked)

VERIFIED FIXED
Future

People

(Reporter: edwsmith, Assigned: edwsmith)

References

Details

Attachments

(1 file, 13 obsolete files)

25.80 KB, patch
rreitmai
: review+
Details | Diff | Splinter Review
When this function is jit-compiled, all boxing/unboxing, coercing, and argument count checking can be done with known values and types, and unrolled. when closure or event handler invocation is common, this approach is a win even over just specializing the subcases in bug 529832
Blocks: 414870
Target Milestone: --- → Future
Attached patch encapsulate isInterpreted() (obsolete) — Splinter Review
Assignee: nobody → edwsmith
Attachment #413599 - Flags: review?(lhansen)
Attachment #413599 - Flags: review?(lhansen) → review+
Attachment #413599 - Attachment is obsolete: true
This also avoids the problem that MethodEnv->implGPR sometimes points to delegateEnter and gives a false negative. The extra load is a tiny overhead but with upcoming changes to coerceEnter() call paths, this function will move off the critical path.
Attachment #415389 - Flags: superreview?(lhansen)
Attachment #415389 - Flags: superreview?(lhansen) → superreview+
It's a slow path and doesn't need inlining, and soon we will need to call it from jit code directly.
Attachment #415392 - Flags: superreview?(lhansen)
Attachment #415392 - Flags: superreview?(lhansen) → superreview+
Comment on attachment 415392 [details] [diff] [review] factor argc error path out of inlined startCoerce() http://hg.mozilla.org/tamarin-redux/rev/40414973b229
Attachment #415392 - Attachment is obsolete: true
Comment on attachment 415389 [details] [diff] [review] MethodEnv::isInterpreted delegates to MethodInfo::isInterpreted http://hg.mozilla.org/tamarin-redux/rev/4ce206f11fe9
Attachment #415389 - Attachment is obsolete: true
MethodInfoProcHolder is always constructed in an initial state pointing to verifyEnterGPR, so we don't need the parameter; this is better encapsulation. setNativeImpl() will get more complex soon, encapsulate access to MethodInfo::_implGPR/FPR function pointer fields.
Attachment #415406 - Flags: superreview?(lhansen)
Attachment #415406 - Flags: superreview?(lhansen) → superreview+
Comment on attachment 415406 [details] [diff] [review] Refactor MethodInfoProcHolder and add setNativeImpl to encapsulate access to function pointers http://hg.mozilla.org/tamarin-redux/rev/c68ac1f262b8
Attachment #415406 - Attachment is obsolete: true
We have an overloaded form of coerceEnter for the 0 arg case; use it when possible.
Attachment #415469 - Flags: superreview?(stejohns)
Attachment #415469 - Flags: superreview?(stejohns) → superreview+
Posting now for early comments, no review required yet. four specialized cases supported (this is before the jit patch): 1. interp general case for calling interpreter 2. interp_nocoerce specialized for no typed args (any arg count, esp. 0) 3. generic general case for jit or native methods 4. generic_nocoerce specialized for no typed args in testing, #1 and #4 are hardly ever called. Once the jit patch lands, we probably don't need #4 at all. #2 is common for global and static initializers. #4 is always used for getters and any other 0-arg function.
Comment on attachment 415469 [details] [diff] [review] use 0-arg form of coerceEnter() when possible http://hg.mozilla.org/users/edwsmith_adobe.com/enter-jit/rev/04ed1f987598 note: this patch further inhibited tail calls, since the 0-arg form of coerceEnter cannot tail-call interpBoxed(), while the 3-arg form can. that will be fixed in the next patch.
Attachment #415469 - Attachment is obsolete: true
First, this patch introduces a function pointer used for invoking any function without knowing its signature. (used in all late bound situations, as well as for closure invocation). "invoker" handlers are specialized in the context of the called method, where the expected arg count and argument types are constant. For interpreted functions, this patch supports two specialized coerceEnter handlers; a generic one, and one which is used when no arguments need to be coerced. This includes the 0-arg case that previously was in MethodEnv::coerceEnter(Atom thisArg). Both tail-call to interpBoxed(). interpBoxed() no longer takes a MethodSignature parameter, which prevented tail-calls from working on x86, or any other cpu with less than 4 argument registers (are there any?) For native and jit'd functions, coerceEnter_generic() is used, which corresponds to the old coerceUnboxEnter() function. An upcoming patch will add a jit-compiler for specialized handlers for these two cases as well. FunctionObject::as3_call was simplified, the argc == 0 case was moved into coerceEnter(thisArg, argc, args*) (ie the one overloaded for Function.call style invocation). Finally, MethodEnv::coerceEnter(Atom) and (argc, Atom*) are now simply one-liner inline functions that invoke via the new function pointer. Future: we could generate C++ handlers for native methods in nativegen.py, instead of using the JIT or the generic invoker.
Attachment #415477 - Attachment is obsolete: true
Attachment #415786 - Flags: superreview?(lhansen)
In interpreter-only configurations, we will never invoke any function via the "native" ABI (i.e. via the GprMethodProc or FprMethodProc signatures). So, we could eliminate the MethodEnv and MethodInfo._implGPR/FPR pointers and compile the VM with only generic late bound thunks.
Protecting the callee's right to overwrite incoming args.
Attachment #415859 - Flags: superreview?(lhansen)
Comment on attachment 415859 [details] [diff] [review] DEBUG code to clobber coerceEnter args after the call Nifty!
Attachment #415859 - Flags: superreview?(lhansen) → superreview+
Attachment #415786 - Flags: superreview?(lhansen) → superreview+
Comment on attachment 415786 [details] [diff] [review] Adds function pointer for coerceEnter calls (v2) Skimmed it but looks good.
Comment on attachment 415786 [details] [diff] [review] Adds function pointer for coerceEnter calls (v2) http://hg.mozilla.org/tamarin-redux/rev/bec2de85a66c
Attachment #415786 - Attachment is obsolete: true
Attachment #415859 - Attachment is obsolete: true
(In reply to comment #14) > Created an attachment (id=415859) [details] > DEBUG code to clobber coerceEnter args after the call instead of memset to 0, perhaps memset to a more obviously poisoned value (eg 0xfb)?
This doesn't change any functionality, just moves code around and adds several new helpers that will be used by both CodegenLIR and the new invoker compiler.
Attachment #416125 - Flags: review?(rreitmai)
Comment on attachment 416125 [details] [diff] [review] Moves helpers from CodegenLIR to LirHelper, adds a bunch more. Rubber stamping, let me know if you'd like a more thorough review.
Attachment #416125 - Flags: review?(rreitmai) → review+
as long as you dont have concerns about the direction of this refactoring arc, then we're good. (a helper per instruction greatly cleans up code).
If it cleans up code, r++
Attachment #416125 - Attachment is obsolete: true
Comment on attachment 416125 [details] [diff] [review] Moves helpers from CodegenLIR to LirHelper, adds a bunch more. pushed http://hg.mozilla.org/tamarin-redux/rev/815bf83401af
testing on Flex apps shows the extra code growth from JIT-compiling these methods is typically 5% and as high as 12%, using the policy that the first call via coerceEnter triggers compilation if the underlying method is JIT compiled or native. All other app frameworks tested (HaXe, Alchemy, Papervision) had smaller growth than Flex.
More code cleanup; nothing functional should have changed.
Attachment #416616 - Flags: review?(rreitmai)
Attachment #416616 - Flags: review?(rreitmai) → review+
Comment on attachment 416616 [details] [diff] [review] use new helper functions throughout CodegenLIR Now that the storeIns()'s have been separated, should we put asserts inside stq/sti/stp to capture bad args? Also, I wonder if optional_label is really optional?
Reloading ms in the catch block but that doesn't suppress the warning. Since access is infrequent, and several other longlived variables are marked volatile, this patch makes ms volatile and cures the warning. safe?
Attachment #416789 - Flags: superreview?(lhansen)
Comment on attachment 416616 [details] [diff] [review] use new helper functions throughout CodegenLIR pushed http://hg.mozilla.org/tamarin-redux/rev/6638de6cf671
Attachment #416616 - Attachment is obsolete: true
Attachment #416789 - Flags: superreview?(lhansen) → superreview+
Comment on attachment 416789 [details] [diff] [review] mark ms volatile to make it setjmp/longjmp safe. pushed http://hg.mozilla.org/tamarin-redux/rev/a6a0811ff689
Attachment #416789 - Attachment is obsolete: true
Attachment #416965 - Flags: review?(rreitmai)
Comment on attachment 416965 [details] [diff] [review] move more shared stuff up to LirHelper minor nit: duplicate keyword 'protected' near LirHelper decl.
Attachment #416965 - Flags: review?(rreitmai) → review+
Attachment #416965 - Attachment is obsolete: true
Adds JIT copiler for coerceEnter stubs. These are stubs that unroll and specialize MethodEnv::coerceEnter_generic for the method being called. In the context of the called method, the expected argument count, argument types, and even the address of the jit'd (or native) code is known, allowing lots of specialization. On 64-bit cpu's and in most cases on 32-bit cpu's, the arguments are unboxed and coerced in-place. However, on a 32-bit cpu, if at least one declared argument is a double, then the arguments must be copied. If, in that case, the method wants rest args or arguments (varargs), then we must punt because we cannot currently jit code that does alloca(). (future: we could actually jit code that uses gc-alloc for the args, by inlining VMPI_alloca()). Alternatively we could modify the ABI so that all Atom args are 8-aligned (ouch).
Attachment #417112 - Flags: review?(rreitmai)
Comment on attachment 417112 [details] [diff] [review] jit stubs for coerceEnter(), for jit methods and native methods (not interpreted methods) Nit: use REALLY_INLINE.
(In reply to comment #34) > (From update of attachment 417112 [details] [diff] [review]) > Nit: use REALLY_INLINE. good point, pushed as a separate patch. http://hg.mozilla.org/tamarin-redux/rev/149eff886640
Updated and commented. Modified jit policy (for the coerceEnter stub only) to compile on second call; this reduces code size and compile time significantly for some Flex tests with no adverse performance effects. (Flex apparently uses a high number of closures for one-time initialization tasks).
Attachment #417112 - Attachment is obsolete: true
Attachment #417474 - Flags: review?(rreitmai)
Attachment #417112 - Flags: review?(rreitmai)
Attachment #417474 - Flags: review?(rreitmai) → review+
Comment on attachment 417474 [details] [diff] [review] (v2) jit stubs for coerceEnter(), for jit methods and native methods (not interpreted methods) [1] minor nit, names of invoker1 and invoker2 should be swapped for clarity [2] outside of scope but the code required to create a 'compiler' ... new frag, lirbuf, lirwriter , etc is awkward would be nice to have something simpler, like : Complier comp(codeMgr, ABI_CDECL); [3] for optional args; was trying to think of another way to code it up (e.g. jmp indirect offset), as the multi-way branch seems inelegant. But in practice i doubt this will be an issue. [4] wonder if its worth exploring a faster intToAtom, uintToAtom. E.g. jit a box/unbox compare and jump to slow path if it fails. [5] nice!
(In reply to comment #37) > (From update of attachment 417474 [details] [diff] [review]) > [1] minor nit, names of invoker1 and invoker2 should be swapped for clarity > [2] outside of scope but the code required to create a 'compiler' ... new frag, > lirbuf, lirwriter , etc is awkward would be nice to have something simpler, > like : Complier comp(codeMgr, ABI_CDECL); agreed, would be nice, soon > [3] for optional args; was trying to think of another way to code it up (e.g. > jmp indirect offset), as the multi-way branch seems inelegant. But in practice > i doubt this will be an issue. I spent time prototyping a solution using switch(argc), roughly: // 2 required, 2 optional switch(argc) { case 4: /* downcast + unbox arg 4 */ case 3: /* downcast + unbox arg 3 */ case 2: break; default: /* throw arg count error */ } /* downcast + unbox arg 2 */ /* downcast + unbox arg 1 */ only to realize it breaks visible left-to-right evaluation order semantics. (say the arg types are Number and the values are Object and we call valueOf() on each one). so, the left-to-right solution is a series of short-circuit branches: /* downcast + unbox arg 1 */ /* downcast + unbox arg 2 */ if (argc < 3) goto done /* downcast + coerce arg 3 */ if (argc < 4) goto done /* downcast + coerce arg 4 */ done: /* do the call */ future note: this all assumes we're going to invoke the underlying method, which also has a series of branches for its own (typed) optional arg processing, to select between the incoming value and the default value. bug 512686 has more ideas on streamlining calls with optional args. > [4] wonder if its worth exploring a faster intToAtom, uintToAtom. E.g. jit a > box/unbox compare and jump to slow path if it fails. Yes, all the cases for downcasting can benefit from inlining the no-convert/no-error path. also, the subtypeof() test used in object downcasting can be heavily specialized. will create followup bug. > [5] nice! thanks!
Status: NEW → RESOLVED
Closed: 16 years ago
Resolution: --- → FIXED
Status: RESOLVED → VERIFIED
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: