[turbofan] Handle initializing stores properly for alias analysis.

In LoadElimination leverage the fact that initializing stores (i.e.
stores to freshly allocated objects) cannot touch existing objects,
since the object can only escape once it's fully initialized and
then all accesses will happen on the FinishRegion node instead of
the naked Allocate node.

This helps to eliminate the redundant map checks and "length" accesses
to arrays, since TurboFan now knows that the iterated array cannot
alias with neither the freshly allocated ArrayIterator nor the
freshly allocated IterResultObject instances. This improves the times
on the benchmark in the tracking bug from

  console.timeEnd: forOf, 188.111000
  console.timeEnd: traditional, 116.380000
  console.timeEnd: forOf, 170.721000
  console.timeEnd: traditional, 108.209000
  console.timeEnd: forOf, 168.491000
  console.timeEnd: traditional, 108.839000

to

  console.timeEnd: forOf, 192.501000
  console.timeEnd: traditional, 106.909000
  console.timeEnd: forOf, 138.364000
  console.timeEnd: traditional, 103.232000
  console.timeEnd: forOf, 138.755000
  console.timeEnd: traditional, 102.928000

when running with untrusted code mitigations turned off, and thus
corresponds to a ~18% performance improvement, roughly cutting the
performance difference between the traditional for loop and the for..of
loop in half.

Besides for..of loops this will also help with array destructuring
patterns where TurboFan also emitted redundant map checks on the array
and didn't eliminate the redundant "length" accesses.

Bug: v8:8070
Change-Id: Iab283247f6d304d1e3c7c147f32ab957577aad21
Reviewed-on: https://chromium-review.googlesource.com/1188124
Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55373}
This commit is contained in:
Benedikt Meurer 2018-08-24 09:08:26 +02:00 committed by Commit Bot
parent afff62b4ab
commit 280361d2b5

View File

@ -676,6 +676,12 @@ Node* LoadElimination::AbstractState::LookupField(Node* object,
} }
bool LoadElimination::AliasStateInfo::MayAlias(Node* other) const { bool LoadElimination::AliasStateInfo::MayAlias(Node* other) const {
// If {object} is being initialized right here (indicated by {object} being
// an Allocate node instead of a FinishRegion node), we know that {other}
// can only alias with {object} if they refer to exactly the same node.
if (object_->opcode() == IrOpcode::kAllocate) {
return object_ == other;
}
// Decide aliasing based on the node kinds. // Decide aliasing based on the node kinds.
if (!compiler::MayAlias(object_, other)) { if (!compiler::MayAlias(object_, other)) {
return false; return false;