Closed Bug 878503 Opened 12 years ago Closed 8 years ago

[meta] IonMonkey: Add Resume instructions.

Categories

(Core :: JavaScript Engine: JIT, defect, P3)

defect

Tracking

()

RESOLVED FIXED

People

(Reporter: nbp, Assigned: nbp)

References

(Depends on 2 open bugs, Blocks 1 open bug)

Details

(Keywords: feature, perf)

Attachments

(2 files, 18 obsolete files)

(deleted), patch
Details | Diff | Splinter Review
(deleted), text/plain
Details
Attached patch Add Resume Instructions (obsolete) (deleted) — Splinter Review
Ion optimizations are constrained by the interpreter/baseline to be able to resume a state which can be used to continue in case of failure. Currently these constraints are enforced by evaluating everything before the resume point which captures the expressions which are needed. Resume instructions is a way to weaken such constraint by adding the ability to resume an instruction which has not been executed before. In practice, this should not give any performance improvements. On the other hand, this enable a new set of optimizations, such as escape analysis (Bug 856533), where we should be able to move instructions below the resume points or, such as JS branch profiling (Bug 877872), by removing code only used in removed branches.
Attachment #757049 - Flags: review?(hv1989)
This patch extract the structure out of the LSnapshot to put them in charge of the LRecover. A snapshot now contains an index into the recover buffer, which describe its structure, and a list of slots. A Recover buffer can be shared, in the same way as MResumePoint are implicitly used by multiple MIR. Before: MResumePoint ->* LSnapshot After: MResumePoint structure -> LRecover MResumePoint operands ->* LSnapshot (allocations) SnapshotIterators are made more clever and abstract over the structure given by the RecoverReader and the slots stored in the SnapshotReader. The SnapshotIterator is now in charge of extracting values when this is possible, and to provide a view on the fact that a value can be read or not. The Slot, previously located in the SnapshotReader are moved out-side of it to be able to represent locations which are corresponding to the result of the execution of a RInstruction. A Slot is some-kind of abstract Value pointer which might be located in the code, on the stack, in a register or in the vector of results of RInstructions. The SnapshotIterator provides way to read the Slot, to check if it is readable and to read the corresponding Value. Delta with previous patch: - Rebase previous patch. - Add comments on Slots and RInstruction.
Attachment #757049 - Attachment is obsolete: true
Attachment #757049 - Flags: review?(hv1989)
Attachment #757058 - Flags: review?(hv1989)
The current patch add a 0.2% - 0.3% regression on sunspider and kraken (checked over 1000 runs each).
This looks pretty interesting and I can see how it could be useful to delay work until we actually bailout and need it. However, what worries me is that it's a big patch that adds a lot of code/complexity but has no immediate perf/memory wins. Do we know how much escape analysis will improve our benchmark score eventually? Do we really need escape analysis, especially once we have GGC? Can we prototype that first before landing this patch? I really think we need more data to answer these kind of questions before we land this patch.
(In reply to Jan de Mooij [:jandem] (PTO June 3-7) from comment #3) > This looks pretty interesting and I can see how it could be useful to delay > work until we actually bailout and need it. > > However, what worries me is that it's a big patch that adds a lot of > code/complexity but has no immediate perf/memory wins. Do we know how much > escape analysis will improve our benchmark score eventually? Do we really > need escape analysis, especially once we have GGC? Can we prototype that > first before landing this patch? > > I really think we need more data to answer these kind of questions before we > land this patch. It seems like escape analysis would be a big deal in code such as octane:raytrace, as well as game code which creates lots of temporary small objects. GGC will be helpful in these cases, but the big win for escape analysis is in allowing us to elide allocations in the first place, avoid doing a number of heavyweight memory writes inside hot code. Object initialization is expensive, and if we can avoid that, we can see some major wins. I agree, though, that we should wait to land this until we are ready to start the work on escape analysis. This patch would make more sense as the first of a series of landings implementing escape analysis.
We definitely need to justify large patches like this. Escape analysis is a wide range of optimizations and knowing which ones we want would help direct how it is constructed. We should be able to (1) know what optimization we're aiming for (2) show that it would apply to a benchmark and (3) prototype that it would have measurable results. Lacking any of this information, it seems premature to propose large design changes.
Comment on attachment 757058 [details] [diff] [review] Prototype: Add Resume Instructions Review of attachment 757058 [details] [diff] [review]: ----------------------------------------------------------------- Clearing review. We decided it is better to wait until we have an improvement, before pushing this big change into the tree.
Attachment #757058 - Flags: review?(hv1989)
(In reply to Nicolas B. Pierron [:nbp] from comment #1) > Created attachment 757058 [details] [diff] [review] > Add Resume Instructions Just as a side note for people who want to see how to use this patch, here is a dummy test case I made a while ago to show how to barely used additions which might be captured in resume points. https://github.com/nbp/mozilla-central/compare/t/resume-op...t/resume-op-test
Attached patch Part 1: Move Slots outside of snapshots. (obsolete) (deleted) — Splinter Review
This extract the Slot data structure such as later we can separate the SnapshotIterator read from the readSlot. By moving this out-side the SnapshotReader, this avoid including the SnapshotReader header to refer to a Slot when we just want to store them in ResumeInstructions.
Attachment #778909 - Flags: review?(hv1989)
Attached patch Part 2: Remove SnapshotReader inheritance. (obsolete) (deleted) — Splinter Review
The Snapshot reader is a legacy which is blocking the extraction of the LResumePoint, as we expect every data to come directly from the SnapshotReader. At the end it makes more sense to separate the two such as the SnapshotIterator becomes just a way to interpret data coming from all the information needed to recover the state of a frame.
Attachment #778910 - Flags: review?(hv1989)
Currently, we store 2 SnapshotIterators to be able to seek at the beginning of the snapshot. By adding the restart function, we can avoid duplicating and copying everything every time we go to the next inlined frame.
Attachment #778911 - Flags: review?(hv1989)
Attached patch Part 4: Clean-up readFrameArgs. (obsolete) (deleted) — Splinter Review
Move readFrameArgs from the SnapshotIterator to the InlineFrameIterator. The goal of the snapshot iterator is not to interpret frames the data that it recovers. Rename it to readFormalFrameArgs (which was its former intent), and simplify forEachCanonicalActualArg by separating the formal part from the overflow part.
Attachment #778912 - Flags: review?(hv1989)
Move maybeReadSlotByIndex from the SnapshotIterator to the InlineFrameIterator, as the slot referred here are specific to frame usage and not generic to any kind of operations.
Attachment #778913 - Flags: review?(hv1989)
Extract the frame layout from the snapshot writer. Add a new LIR type for the resume point (LResumePoint) which are capturing the number of operands and the MIR node (resume point) which have to be recovered by the SnapshotIterator. The LResumePoint are then encoded and packed into the RecoverBuffer and read by the SnapshotIterator, which recover the offset of it from the snapshot. The boundary of the modification is hidden behind the SnapshotIterator which keeps the same interface as before. And no frame logic is changed.
Attachment #778914 - Flags: review?(hv1989)
Attachment #757058 - Attachment description: Add Resume Instructions → Prototype: Add Resume Instructions
Attached patch Part 7: Add Slot default constructor. (obsolete) (deleted) — Splinter Review
Add a default constructor to be able to include it in other structures without having to initialize all Slots.
Attachment #779608 - Flags: review?(hv1989)
Attachment #779609 - Flags: review?(hv1989)
Introduce a RResumePoint structure to track the ResumePoint representation and remember a few useful slots of the |scopeChain|, |argObj| and |this|. This avoid cloning a new SnapshotIterator every time we need to access these information.
Attachment #779610 - Flags: review?(hv1989)
Attached patch Part 10: Make SnapshotIterator non-copyable. (obsolete) (deleted) — Splinter Review
Make SnapshotIterator seek-able & reset-able, by remembering the position of the last frame or re-initializing the content. Create a fake random access SlotVector class to abstract over the readSlot interface. This SlotVector use the seek feature to reinitialize the SnapshotIterator instead of making copies of it.
Attachment #779612 - Flags: review?(hv1989)
Move RResumePoint into the SnapshotIterator such as the Bailout code can rely on it, see part 12.
Attachment #779614 - Flags: review?(hv1989)
Use the RResumePoint to read the data contained in the snapshot. Remove read() & skip() functions, which gives the ability to later split the SnapshotIterator into 2. One part for the Snapshot-To-Slot reads and the other part for the Slot-to-Value conversions.
Attachment #779615 - Flags: review?(hv1989)
Attached patch Part 13: Move RResumePoint into its own file. (obsolete) (deleted) — Splinter Review
Attachment #779618 - Flags: review?(hv1989)
Make a parallel between MResumePoint::writeRecover and RResumePoint constructor. Move the RResumePoint to the RecoverReader to be created for reading the content of the buffer.
Attachment #779620 - Flags: review?(hv1989)
Trivial renaming for adding more meaning to the followup patches.
Attachment #779622 - Flags: review?(hv1989)
This patch contains the logic to convert the current code to handle any instruction as recovering instruction instead of being a normal instruction in the MIR Graph. When an instruction is flagged as being a Recovering instruction, it would no longer be lowered and a space would be kept in the LRecover vector of instructions. For each recovering instruction, we reserve the space for each operand in the snapshot, as well as in the recover buffer (see the parallel in part 14). Each decoded operation will be resumed during a bailout.
Attachment #779624 - Flags: review?(hv1989)
Adding the recovering flag as part of the computation of the valueHash, such as phases like GVN won't fold a Recovering instruction with a non-recovering one. One example would be that we can have an If branch where we do the same thing on both side of the branch. GVN will try to fold them, where we might have flagged one as being a Recovering instruction. In which case, we can prevent the execution in one of the branches.
Attachment #779626 - Flags: review?(hv1989)
Comment on attachment 778909 [details] [diff] [review] Part 1: Move Slots outside of snapshots. Review of attachment 778909 [details] [diff] [review]: ----------------------------------------------------------------- ::: js/src/ion/Slots.h @@ +28,5 @@ > + > + public: > + > + class Location > + { For me it doesn't make sense to have this inlined in the class Slot. Esp. since Location is also used as input to Slot construction. Can we move this back to out of the Slot class and rename it SlotLocation ?? @@ +61,5 @@ > + return stackSlot_ != INVALID_STACK_SLOT; > + } > + }; > + > + enum SlotMode s/SlotMode/Mode ::: js/src/ion/arm/Architecture-arm.h @@ -24,5 @@ > // +8 for double spills > static const uint32_t ION_FRAME_SLACK_SIZE = 20; > > -// An offset that is illegal for a local variable's stack allocation. > -static const int32_t INVALID_STACK_SLOT = -1; Glad this is moved to platform independent file, since the value is same for all.
Attachment #778909 - Flags: review?(hv1989) → review+
Comment on attachment 779624 [details] [diff] [review] Part 16: Generalized RResumePoint to any instructions. Review of attachment 779624 [details] [diff] [review]: ----------------------------------------------------------------- ::: js/src/ion/MIR.h @@ +61,5 @@ > + * way to encode its data into the recover buffer such as the corresponding > + * RInstruction can be executed. A recover instruction should never depends > + * on it-self. > + */ \ > + _(Recovering) \ sstangl suggested that instead of flagging instructions which will be used as recovering instruction, we should move them out of the graph. One of the reasons why I kept them in the graph is to make them captured by resume points. But sstangl still has a good point which is highlighted by Part 17, which is that other optimizations might still work on top of instructions without looking at the flags. So as long as these instructions are in the graph, they might still be considered in optimizations. So, I think we should wrap these instructions in a MRecoverInstruction which will hold any instruction as a resume point, and not be considered by any other optimizations. This way Part 17 will not be necessary and we will not have any issue with any flag that we forgot to check.
Blocks: 897606
Attachment #778910 - Flags: review?(hv1989) → review?(jdemooij)
Attachment #778911 - Flags: review?(hv1989) → review?(jdemooij)
Attachment #778912 - Flags: review?(hv1989) → review?(jdemooij)
Attachment #778913 - Flags: review?(hv1989) → review?(jdemooij)
Attachment #778914 - Flags: review?(hv1989) → review?(jdemooij)
Attachment #779608 - Flags: review?(hv1989) → review?(jdemooij)
Attachment #779609 - Flags: review?(hv1989) → review?(jdemooij)
Attachment #779610 - Flags: review?(hv1989) → review?(jdemooij)
Attachment #779612 - Flags: review?(hv1989) → review?(jdemooij)
Attachment #779614 - Flags: review?(hv1989) → review?(jdemooij)
Attachment #779615 - Flags: review?(hv1989) → review?(jdemooij)
Attachment #779618 - Flags: review?(hv1989) → review?(jdemooij)
Attachment #779620 - Flags: review?(hv1989) → review?(jdemooij)
Attachment #779622 - Flags: review?(hv1989) → review?(jdemooij)
Attachment #779624 - Flags: review?(hv1989) → review?(jdemooij)
Attachment #779626 - Flags: review?(hv1989) → review?(jdemooij)
Jandem: If you are not convinced yet, please have a look at this draft, that I wish I can *publish after* making this refactoring. Somebody told me that I should write it an publish it before such as I can convince people that we should do it. But I think you will not like to be the only person standing against it, so I let you review it first: https://blog.mozilla.org/javascript/?p=604&preview=true
Flags: needinfo?(jdemooij)
Attached file IRC Q/A jandem & nbp (deleted) —
Attachment #778909 - Attachment is obsolete: true
Attachment #778909 - Flags: review+
Attachment #778910 - Attachment is obsolete: true
Attachment #778910 - Flags: review?(jdemooij)
Attachment #778911 - Attachment is obsolete: true
Attachment #778911 - Flags: review?(jdemooij)
Attachment #778912 - Attachment is obsolete: true
Attachment #778912 - Flags: review?(jdemooij)
Attachment #778913 - Attachment is obsolete: true
Attachment #778913 - Flags: review?(jdemooij)
Attachment #778914 - Attachment is obsolete: true
Attachment #778914 - Flags: review?(jdemooij)
Attachment #779608 - Attachment is obsolete: true
Attachment #779608 - Flags: review?(jdemooij)
Attachment #779609 - Attachment is obsolete: true
Attachment #779609 - Flags: review?(jdemooij)
Attachment #779610 - Attachment is obsolete: true
Attachment #779610 - Flags: review?(jdemooij)
Attachment #779612 - Attachment is obsolete: true
Attachment #779612 - Flags: review?(jdemooij)
Attachment #779614 - Attachment is obsolete: true
Attachment #779614 - Flags: review?(jdemooij)
Attachment #779615 - Attachment is obsolete: true
Attachment #779615 - Flags: review?(jdemooij)
Attachment #779618 - Attachment is obsolete: true
Attachment #779618 - Flags: review?(jdemooij)
Attachment #779620 - Attachment is obsolete: true
Attachment #779620 - Flags: review?(jdemooij)
Attachment #779622 - Attachment is obsolete: true
Attachment #779622 - Flags: review?(jdemooij)
Attachment #779624 - Attachment is obsolete: true
Attachment #779624 - Flags: review?(jdemooij)
Comment on attachment 779626 [details] [diff] [review] Part 17: Prevent aliasing of instructions with different flags. Sorry for the noise.
Attachment #779626 - Attachment is obsolete: true
Attachment #779626 - Flags: review?(jdemooij)
Summary: IonMonkey: Add Resume instructions. → [meta] IonMonkey: Add Resume instructions.
Depends on: 988903
Depends on: 988958
Depends on: 983598
Depends on: 989344
Flags: needinfo?(jdemooij)
Component: JavaScript Engine → JavaScript Engine: JIT
Keywords: feature
Depends on: 989641
Depends on: 989667
Depends on: 989748
Depends on: 989759
Depends on: 989930
Depends on: 990106
Depends on: 991656
Depends on: 991720
Depends on: 1003801
No longer blocks: 897606
Priority: -- → P5
Blocks: jsperf
Status: ASSIGNED → RESOLVED
Closed: 8 years ago
Keywords: perf
Priority: P5 → P3
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: