Devirtualize MNode::kind()

RESOLVED FIXED in Firefox 57

Status

()

enhancement
RESOLVED FIXED
2 years ago
2 years ago

People

(Reporter: jandem, Assigned: jandem)

Tracking

(Blocks 1 bug)

unspecified
mozilla57
Points:
---
Dependency tree / graph

Firefox Tracking Flags

(firefox57 fixed)

Details

Attachments

(2 attachments, 1 obsolete attachment)

Posted patch PatchSplinter Review
MNode::kind is a pretty hot virtual function to determine isResumePoint() or isDefinition(). We can devirtualize it by making MNode::block_ a tagged pointer - the low bit can store the kind.

I also |= delete|'d these functions on the MDefinition and MResumePoint derived classes, this caught a place where we called isResumePoint() on an MDefinition (this is always false).
Attachment #8898759 - Flags: review?(nicolas.b.pierron)
Comment on attachment 8898759 [details] [diff] [review]
Patch

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

::: js/src/jit/MIR.h
@@ +343,3 @@
>      }
>      MBasicBlock* block() const {
> +        return reinterpret_cast<MBasicBlock*>(blockAndKind_ & ~KindMask);

Is this really worth it?

I would expect resume point to access the block()->info() pointer frequently.

@@ +527,5 @@
>      }
>  
> +    // Calling isDefinition or isResumePoint on MDefinition is unnecessary.
> +    bool isDefinition() const = delete;
> +    bool isResumePoint() const = delete;

Nice!
Attachment #8898759 - Flags: review?(nicolas.b.pierron) → review+
(In reply to Nicolas B. Pierron [:nbp] from comment #1)
> Is this really worth it?
> 
> I would expect resume point to access the block()->info() pointer frequently.

I just added some logging and ran Octane. MNode::kind() was called about 10.1 million times, MNode::block() 11.5 million times. So block() is called a bit more, but getting rid of the virtual call for kind() outweighs the unmasking there IMO.
One more thing that I forgot. Can you specialize MDefinition::block() to avoid the un-masking as and assert that the low bots are already 0.
Posted patch Followup (obsolete) — Splinter Review
What do you think of this one? It optimizes block() on both MDefinition and MResumePoint to be a bit more efficient than MNode::block().
Attachment #8898796 - Flags: review?(nicolas.b.pierron)
Posted patch FollowupSplinter Review
The right one.
Attachment #8898796 - Attachment is obsolete: true
Attachment #8898796 - Flags: review?(nicolas.b.pierron)
Attachment #8898797 - Flags: review?(nicolas.b.pierron)
Comment on attachment 8898797 [details] [diff] [review]
Followup

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

::: js/src/jit/MIR.h
@@ +338,5 @@
> +        MOZ_ASSERT(isResumePoint());
> +        static_assert(unsigned(Kind::ResumePoint) == 1, "Code below relies on low bit being 1");
> +        // Use a subtraction: if the caller does block()->foo, the compiler
> +        // will be able to fold it with the load.
> +        return reinterpret_cast<MBasicBlock*>(blockAndKind_ - 1);

Whoa, this is indeed nicer!
Attachment #8898797 - Flags: review?(nicolas.b.pierron) → review+
Blocks: 1245279
https://hg.mozilla.org/mozilla-central/rev/0cc6be22d7e0
Status: ASSIGNED → RESOLVED
Closed: 2 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla57
You need to log in before you can comment on or make changes to this bug.