Closed Bug 1143704 Opened 9 years ago Closed 9 years ago

Some bytecode emitter cleanup

Categories

(Core :: JavaScript Engine, defect)

defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla39

People

(Reporter: jandem, Assigned: jandem)

References

Details

Attachments

(15 files)

287.84 KB, patch
jorendorff
: feedback+
Waldo
: feedback+
luke
: feedback+
Details | Diff | Splinter Review
100.33 KB, patch
luke
: review+
Details | Diff | Splinter Review
15.33 KB, patch
jorendorff
: review+
Details | Diff | Splinter Review
4.49 KB, patch
shu
: review+
Details | Diff | Splinter Review
95.15 KB, patch
bhackett1024
: review+
Details | Diff | Splinter Review
5.76 KB, patch
Waldo
: review+
Details | Diff | Splinter Review
49.13 KB, patch
efaust
: review+
Details | Diff | Splinter Review
38.30 KB, patch
bhackett1024
: review+
Details | Diff | Splinter Review
69.92 KB, patch
luke
: review+
Details | Diff | Splinter Review
94.37 KB, patch
shu
: review+
Details | Diff | Splinter Review
130.92 KB, patch
efaust
: review+
Details | Diff | Splinter Review
121.14 KB, patch
jorendorff
: review+
Details | Diff | Splinter Review
150.38 KB, patch
bhackett1024
: review+
Details | Diff | Splinter Review
36.21 KB, patch
luke
: review+
Details | Diff | Splinter Review
27.44 KB, patch
luke
: review+
Details | Diff | Splinter Review
Attached patch PatchSplinter Review
Functions like Emit1 are pretty annoying to use because they return a ptrdiff_t, so all callers have to check if the result < 0. It'd be nicer if these functions returned a bool (or were infallible, but that can wait for now). I did that and then I ended up moving most functions into the BytecodeEmitter class, so that we don't need to pass cx and bce around everywhere.

Anyway, this (folded!) patch is not complete but requesting feedback from people to see if they think this is the right direction.
Attachment #8578067 - Flags: feedback?(luke)
Attachment #8578067 - Flags: feedback?(jwalden+bmo)
Attachment #8578067 - Flags: feedback?(jorendorff)
Comment on attachment 8578067 [details] [diff] [review]
Patch

Review of attachment 8578067 [details] [diff] [review]:
-----------------------------------------------------------------

The general idea makes sense, though I only just scanned it lightly.  A few thoughts:
 - I wonder if most BCE fields could be private now.
 - With a bit of refactoring of BytecodeCompiler (perhaps just moving some functions into BytecodeEmitter.cpp), could the definition of BytecodeEmitter be moved into BytecodeEmitter.cpp so the whole thing was just an impl detail of emitting?
Attachment #8578067 - Flags: feedback?(luke) → feedback+
On second thought (re: my second bullet), BCE is not any worse, and symmetric to, Parser.  This is just an instance of the problem that C++'s classes force you to put a lot of private details in the public interface description of a class.  We could use ye olde PIMPL idiom to work around this, but that seems like overkill.
Comment on attachment 8578067 [details] [diff] [review]
Patch

Yeah, this has been on my cleanup todo list forever.
Attachment #8578067 - Flags: feedback?(jorendorff) → feedback+
Big but mechanical.

EmitLoopEntry was the only place where we actually wanted the offset. That was easily fixed by calling bce->offset() before the Emit1 call, as we do elsewhere.
Assignee: nobody → jdemooij
Status: NEW → ASSIGNED
Attachment #8578507 - Flags: review?(luke)
Also straight-forward. The only wrinkle is that EmitGoto uses the offset returned by EmitBackPatchOp, but we can use the *lastp outparam there. All other callers just need a bool.
Attachment #8578514 - Flags: review?(jorendorff)
EmitLoopHead returns a ptrdiff_t, but it's clearer to have it return a bool and let the callers do |top = bce->offset();| before the call.

We were already doing that for all for-loops, with this patch we do the same for do and while loops.
Attachment #8578523 - Flags: review?(shu)
Large but mechanical change.
Attachment #8578530 - Flags: review?(bhackett1024)
We'll no longer pass a cx to every function, and using sc->context requires an extra dereference, so this patch just adds a cx to BytecodeEmitter.

(I used 'cx' and not 'context' so that I don't have to rename it when converting functions to BytecodeEmitter methods.)
Attachment #8578535 - Flags: review?(jwalden+bmo)
More of the same. Note that all these methods have to be public for now; once we're done we can make most of them private.
Attachment #8578550 - Flags: review?(efaustbmo)
This patch also replaces the EMIT_UINT16_IMM_OP macro with BytecodeEmitter::emitUint16Operand.

BackPatch always returns true so I made BytecodeEmitter::backPatch return void.
Attachment #8578552 - Flags: review?(bhackett1024)
Attachment #8578560 - Flags: review?(luke)
Attachment #8578568 - Flags: review?(shu)
Attachment #8578572 - Flags: review?(efaustbmo)
Because BytecodeEmitter::backPatch is now infallible, BytecodeEmitter::popStatement (was PopStatementBCE) always returns true and can just return void.

Other than that it's just more mechanical changes.
Attachment #8578580 - Flags: review?(jorendorff)
There will be a few more parts, but those can wait for now. After that I hope we can make most BytecodeEmitter fields/methods private.

It might also be nice to make emit1 and friends infallible and set an OOM flag that we can check at the end (just like the JIT's assemblers etc) but that's more complicated and not for this bug.
Comment on attachment 8578507 [details] [diff] [review]
Part 1 - Make Emit1/Emit2 return bool

Good one.
Attachment #8578507 - Flags: review?(luke) → review+
Comment on attachment 8578560 [details] [diff] [review]
Part 8 - Move more methods

I see at this point in the patch queue there are still some more ptrdiff_t-returning emit calls.  Do you intend to convert them all to bool?  Otherwise I'm a bit scared that some inevitable <0 on bool or ! on ptrdiff_t mistakes will arise.
Attachment #8578560 - Flags: review?(luke) → review+
(In reply to Luke Wagner [:luke] from comment #17)
> I see at this point in the patch queue there are still some more
> ptrdiff_t-returning emit calls.  Do you intend to convert them all to bool? 
> Otherwise I'm a bit scared that some inevitable <0 on bool or ! on ptrdiff_t
> mistakes will arise.

Right, this is also a problem without my patches because some Emit* functions already return bool.

Most callers of emitJump, emitGoto etc do need the offset, so I didn't change them. I should probably make them return bool and add a ptrdiff_t outparam, so that we can eliminate the <0 or >=0 tests completely.
Attachment #8578530 - Flags: review?(bhackett1024) → review+
Attachment #8578552 - Flags: review?(bhackett1024) → review+
It would be nice if the bytecode emitter methods were all infallible, or at least infallible to the greatest degree possible.  If an allocation fails, just do nothing and set a flag on the emitter which causes things to fail later on, in the same fashion as the JIT macro assembler and other passes.  If we need to backpatch emitted bytecode and have a possibly bogus offset, check the flag before writing.  This is a little more complicated than that case because the emitter can fail for reasons other than OOM, but it seems like the emitter could just remember the first error as an exception object or frontend::CompileError and then throw it when it finally does get around to failing.
(In reply to Brian Hackett (:bhackett) from comment #19)
> It would be nice if the bytecode emitter methods were all infallible, or at
> least infallible to the greatest degree possible.

Agreed, see also comment 15. Maybe I'll do this as a follow-up..

> This is a little more complicated than that
> case because the emitter can fail for reasons other than OOM, but it seems
> like the emitter could just remember the first error as an exception object
> or frontend::CompileError and then throw it when it finally does get around
> to failing.

I think a good first step is to make only the "trival" methods like emit1 infallible, because that's where the error-checking is most annoying (because there are so many calls to them..)
Comment on attachment 8578535 [details] [diff] [review]
Part 5 - Add a 'cx' to BytecodeEmitter

Review of attachment 8578535 [details] [diff] [review]:
-----------------------------------------------------------------

Feh, contexts.
Attachment #8578535 - Flags: review?(jwalden+bmo) → review+
Attachment #8578067 - Flags: feedback?(jwalden+bmo) → feedback+
Attachment #8578523 - Flags: review?(shu) → review+
Comment on attachment 8578568 [details] [diff] [review]
Part 9 - Even more methods

Review of attachment 8578568 [details] [diff] [review]:
-----------------------------------------------------------------

Seems reasonable and mechanical. FYI I didn't pore over every line.
Attachment #8578568 - Flags: review?(shu) → review+
Attachment #8578514 - Flags: review?(jorendorff) → review+
Attachment #8578580 - Flags: review?(jorendorff) → review+
Comment on attachment 8578550 [details] [diff] [review]
Part 6 - Move more functions into BytecodeEmitter

Review of attachment 8578550 [details] [diff] [review]:
-----------------------------------------------------------------

I like how incrementally this can be done. Nice work. r=me
Attachment #8578550 - Flags: review?(efaustbmo) → review+
Comment on attachment 8578572 [details] [diff] [review]
Part 10 - And even more methods

Review of attachment 8578572 [details] [diff] [review]:
-----------------------------------------------------------------

Well done.

::: js/src/frontend/BytecodeEmitter.cpp
@@ +4899,4 @@
>          return false;
>  
>      if (type == STMT_SPREAD)
> +        stackDepth++;

Thoughts on making this, and lower references into |this->stackDepth|? I personally find it annoying to see bare names used this way. It costs me time looking for the local definition. It looks like you already did this for the code involving |loopDepth|, so let's just make it universal.
Attachment #8578572 - Flags: review?(efaustbmo) → review+
(In reply to Eric Faust [:efaust] from comment #24)
> Thoughts on making this, and lower references into |this->stackDepth|? I
> personally find it annoying to see bare names used this way. It costs me
> time looking for the local definition. It looks like you already did this
> for the code involving |loopDepth|, so let's just make it universal.

Good point. I think when I make these fields private, I'll rename them to stackDepth_/loopDepth_, to make it clear these are class members.
Attachment #8582324 - Flags: review?(bhackett1024)
This changes emitJump/emitCheck/emitN to return bool instead of intptr_t, with an intptr_t* outparam where necessary.

I considered changing the type to size_t/unsigned, since the offset is always positive now, but we subtract these values to determine jump offsets etc, so I kept intptr_t to avoid subtle sign issues.
Attachment #8582330 - Flags: review?(luke)
Make newSrcNote* return bool with an optional unsigned* index outparam, instead of an int return type.

With this patch there are no more "< 0" or ">= 0" OOM checks in BytecodeEmitter.cpp
Attachment #8582337 - Flags: review?(luke)
Attachment #8582330 - Flags: review?(luke) → review+
Comment on attachment 8582337 [details] [diff] [review]
Part 14 - Make newSrcNote* return bool

Review of attachment 8582337 [details] [diff] [review]:
-----------------------------------------------------------------

Nice
Attachment #8582337 - Flags: review?(luke) → review+
Attachment #8582324 - Flags: review?(bhackett1024) → review+
Closing this as all patches landed. There's always more we can do but it's clearer to file new bugs.
Status: ASSIGNED → RESOLVED
Closed: 9 years ago
Keywords: leave-open
Resolution: --- → FIXED
Target Milestone: --- → mozilla39
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: