Closed Bug 495158 Opened 13 years ago Closed 12 years ago

nanojit: fix incorrect operand counts in LIRopcode.tbl?

Categories

(Core :: JavaScript Engine, defect)

x86
Linux
defect
Not set
normal

Tracking

()

RESOLVED FIXED

People

(Reporter: n.nethercote, Unassigned)

References

Details

(Whiteboard: fixed-in-tracemonkey)

Attachments

(2 files, 1 obsolete file)

LIRopcode.tbl has an operand count for every LIR instruction.  Some of these look to be wrong;  at least, they don't match the number of operands as determined by the particular insertion function (eg. ins1(), ins2()) used to create them.

The attached patch is an attempt to fix the ones I could see didn't match.  I had to disable an assertion for the change to LIR_xt/LIR_xf to be acceptable.  I'm not sure if the patch is correct because I'm not sure what the exact definition of "operand" used in LIRopcode.tbl is.  And the fact that the assertion in CseFilter::insGuard is conditional on isCseOpcode() seems strange.

I also don't know how the operand counts are used... eg. I tried changing the operand count for LIR_add to 1 and, after disabling one failing assertion, trace-test.js ran fine.  So that concerns me a bit.

So if my patch is incorrect, I guess I'd like to see a comment in LIRopcode.tbl explaining exactly what the operand count represents and what the effects are if it is wrong.
Attachment #380015 - Flags: review?(jwalden+bmo)
Comment on attachment 380015 [details] [diff] [review]
patch altering LIRopcode.tbl operand counts

I don't know what the operand counts mean, unfortunately.  Prior to the addition of that file those values were in a huge array, separate from a number of other arrays for per-opcode information, and I just blindly copied them over.  Ed or any other nanojit hacker certainly knows better than I do, in any case.
Attachment #380015 - Flags: review?(jwalden+bmo)
Comment on attachment 380015 [details] [diff] [review]
patch altering LIRopcode.tbl operand counts

THe assert in insGuard is correct in the sense that if we do find1, we better only stick unary lir instructions in there. The code around it might be buggy of course.

I am not sure loop really has 2 args. x might have a constant as 1st arg always (have to check). This might need some cleanup outside the table as well.

I am pretty sure xbarrier is unary. And xtbl too.

A lot of this points to inconsistencies and potential bugs, but the patch isn't enough to fix it.
Attachment #380015 - Flags: review-
I looked at tamarin-redux.  The values for file, line, xbarrier and xtbl match
those in my patch.  The values for the others match what is currently in TM. 
Confusing.

In response to comment #2, I didn't really expect it to fix the problems, rather to highlight them.  If we don't know how many operands all our instructions have... that's a problem.
(In reply to comment #3)
> In response to comment #2, I didn't really expect it to fix the problems,
> rather to highlight them.  If we don't know how many operands all our
> instructions have... that's a problem.

especially with a variable-sized LIns!
Working on bug 498807, I've come to understand this better.  It's confusing because the number of what-are-considered-operands (aka. the arity) doesn't necessarily match the number of fields needed for the instruction.  To clarify:

xt/xf: have two fields, the condition, and the GuardRecord.  But the GuardRecord isn't considered an operand.  So arity=1

loop/x/xbarrier: have two fields, the condition, and the GuardRecord.  But the condition is always set to insImm(1) and subsequently ignored.  So arity=0.  But xbarrier is listed as arity=1 in LIRopcode.tbl, which I'm pretty sure should be 0.

xtbl: has two fields, the difference value (whatever that is), and the GuardRecord.  So arity=1.

jf/jt: have two fields, the condition, and the target label.  The target label isn't considered an operand.  So arity=1.  (Nb: All the calls to insBranch() that create jf/jt instructions, except those in lirasm.cpp, set the target to NULL... I haven't worked out why that is yet.  Do they get patched later?  If so, that argument could be removed from insBranch().)

Hopefully this clears things up (Graydon, Julian and I had a very confused discussion about this on IRC recently).  My in-progress patch for bug 492866 will make the number of fields needed for each opcode clearer, and I have some ideas for bug 498807 that will clarify the confusion between the different kinds of guards (conditional, unconditional, and switch).  I'll come back to this once they're done.
Depends on: 492866, 498807
(In reply to comment #5)
> 
> xt/xf: have two fields, the condition, and the GuardRecord.  But the
> GuardRecord isn't considered an operand.  So arity=1

Thinking about this more, I'm concerned this could cause problems with CseFilter.

CseFilter only looks at the "operand", ie. the condition, when deciding if two LIR_xt instructions are equivalent (and likewise for LIR_xf).  AFAICT, if two LIR_xt/xf instructions had identical opcodes and conditions but different GuardRecords they will be incorrectly commoned up.

Can anyone see why the above reasoning might be wrong?
> (In reply to comment #5)
> But xbarrier is listed as arity=1 in LIRopcode.tbl, which I'm pretty sure
> should be 0.

The commit in bug 504705 fixes this.  So the only issue left to be resolved in this bug is the one in comment 6.  (Well, ultimately I want to kill of the operandCount field altogether, but that's another bug...)
(In reply to comment #7)
> So the only issue left to be resolved in
> this bug is the one in comment 6.

Actually, LIR_file and LIR_line should probably have operandCount of 1.  But bug 505662 will remove operandCount altogether.  So comment 6 is the only thing left to worry about here.
(In reply to comment #6)
> (In reply to comment #5)
> > 
> > xt/xf: have two fields, the condition, and the GuardRecord.  But the
> > GuardRecord isn't considered an operand.  So arity=1
> 
> Thinking about this more, I'm concerned this could cause problems with
> CseFilter.
> 
> CseFilter only looks at the "operand", ie. the condition, when deciding if two
> LIR_xt instructions are equivalent (and likewise for LIR_xf).  AFAICT, if two
> LIR_xt/xf instructions had identical opcodes and conditions but different
> GuardRecords they will be incorrectly commoned up.
> 
> Can anyone see why the above reasoning might be wrong?

If the first guard is taken (exits), the second is never reached (*).  if the first guard is not taken, then neither is the second one, so it shouldn't matter if the second one has a different guard record.

(*) assuming there's never a path from the side exit of guard 1, back to guard 2.  for tree-shaped fragments this should be true.  Also, this could be an invalid argument if there is important information in the guard record *other* than just whats needed to execute a successful bailout.  but i can't think of anything like that.
Ah, I see.  It also assumes that the CSE algorithm always preserves the first guard seen and removes the second one -- that is true for the current code but not true for some conceivable alternatives.

I've attached a patch that adds a comment describing all this.
Attachment #390110 - Flags: review?(edwsmith)
Attachment #390110 - Attachment is obsolete: true
Attachment #390112 - Flags: review?(edwsmith)
Attachment #390110 - Flags: review?(edwsmith)
Attachment #390112 - Flags: review?(edwsmith) → review+
http://hg.mozilla.org/mozilla-central/rev/c580e9a2a18e
Status: NEW → RESOLVED
Closed: 12 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.