Commit 9881b6c7 authored by tebbi's avatar tebbi Committed by Commit bot

[turbofan] extend escape analysis to reduce CheckMaps

R=bmeurer@chromium.org

BUG=

Review-Url: https://codereview.chromium.org/2680973013
Cr-Original-Commit-Position: refs/heads/master@{#43163}
Committed: https://chromium.googlesource.com/v8/v8/+/f01c8a6e4b24ab38e58bb141fc251bc6b75dbe21
Review-Url: https://codereview.chromium.org/2680973013
Cr-Commit-Position: refs/heads/master@{#43478}
parent 3c36aacc
...@@ -46,6 +46,8 @@ Reduction EscapeAnalysisReducer::ReduceNode(Node* node) { ...@@ -46,6 +46,8 @@ Reduction EscapeAnalysisReducer::ReduceNode(Node* node) {
case IrOpcode::kStoreField: case IrOpcode::kStoreField:
case IrOpcode::kStoreElement: case IrOpcode::kStoreElement:
return ReduceStore(node); return ReduceStore(node);
case IrOpcode::kCheckMaps:
return ReduceCheckMaps(node);
case IrOpcode::kAllocate: case IrOpcode::kAllocate:
return ReduceAllocate(node); return ReduceAllocate(node);
case IrOpcode::kFinishRegion: case IrOpcode::kFinishRegion:
...@@ -171,6 +173,21 @@ Reduction EscapeAnalysisReducer::ReduceStore(Node* node) { ...@@ -171,6 +173,21 @@ Reduction EscapeAnalysisReducer::ReduceStore(Node* node) {
return NoChange(); return NoChange();
} }
Reduction EscapeAnalysisReducer::ReduceCheckMaps(Node* node) {
DCHECK(node->opcode() == IrOpcode::kCheckMaps);
if (node->id() < static_cast<NodeId>(fully_reduced_.length())) {
fully_reduced_.Add(node->id());
}
if (escape_analysis()->IsVirtual(
SkipTypeGuards(NodeProperties::GetValueInput(node, 0))) &&
!escape_analysis()->IsEscaped(node)) {
TRACE("Removed #%d (%s) from effect chain\n", node->id(),
node->op()->mnemonic());
RelaxEffectsAndControls(node);
return Changed(node);
}
return NoChange();
}
Reduction EscapeAnalysisReducer::ReduceAllocate(Node* node) { Reduction EscapeAnalysisReducer::ReduceAllocate(Node* node) {
DCHECK_EQ(node->opcode(), IrOpcode::kAllocate); DCHECK_EQ(node->opcode(), IrOpcode::kAllocate);
......
...@@ -38,6 +38,7 @@ class V8_EXPORT_PRIVATE EscapeAnalysisReducer final ...@@ -38,6 +38,7 @@ class V8_EXPORT_PRIVATE EscapeAnalysisReducer final
Reduction ReduceNode(Node* node); Reduction ReduceNode(Node* node);
Reduction ReduceLoad(Node* node); Reduction ReduceLoad(Node* node);
Reduction ReduceStore(Node* node); Reduction ReduceStore(Node* node);
Reduction ReduceCheckMaps(Node* node);
Reduction ReduceAllocate(Node* node); Reduction ReduceAllocate(Node* node);
Reduction ReduceFinishRegion(Node* node); Reduction ReduceFinishRegion(Node* node);
Reduction ReduceReferenceEqual(Node* node); Reduction ReduceReferenceEqual(Node* node);
......
...@@ -807,6 +807,7 @@ bool EscapeStatusAnalysis::CheckUsesForEscape(Node* uses, Node* rep, ...@@ -807,6 +807,7 @@ bool EscapeStatusAnalysis::CheckUsesForEscape(Node* uses, Node* rep,
case IrOpcode::kStateValues: case IrOpcode::kStateValues:
case IrOpcode::kReferenceEqual: case IrOpcode::kReferenceEqual:
case IrOpcode::kFinishRegion: case IrOpcode::kFinishRegion:
case IrOpcode::kCheckMaps:
if (IsEscaped(use) && SetEscaped(rep)) { if (IsEscaped(use) && SetEscaped(rep)) {
TRACE( TRACE(
"Setting #%d (%s) to escaped because of use by escaping node " "Setting #%d (%s) to escaped because of use by escaping node "
...@@ -1124,6 +1125,9 @@ bool EscapeAnalysis::Process(Node* node) { ...@@ -1124,6 +1125,9 @@ bool EscapeAnalysis::Process(Node* node) {
case IrOpcode::kLoadElement: case IrOpcode::kLoadElement:
ProcessLoadElement(node); ProcessLoadElement(node);
break; break;
case IrOpcode::kCheckMaps:
ProcessCheckMaps(node);
break;
case IrOpcode::kStart: case IrOpcode::kStart:
ProcessStart(node); ProcessStart(node);
break; break;
...@@ -1161,6 +1165,10 @@ void EscapeAnalysis::ProcessAllocationUsers(Node* node) { ...@@ -1161,6 +1165,10 @@ void EscapeAnalysis::ProcessAllocationUsers(Node* node) {
case IrOpcode::kFinishRegion: case IrOpcode::kFinishRegion:
case IrOpcode::kObjectIsSmi: case IrOpcode::kObjectIsSmi:
break; break;
case IrOpcode::kCheckMaps: {
CheckMapsParameters params = CheckMapsParametersOf(node->op());
if (params.flags() == CheckMapsFlag::kNone) break;
} // Fallthrough.
default: default:
VirtualState* state = virtual_states_[node->id()]; VirtualState* state = virtual_states_[node->id()];
if (VirtualObject* obj = if (VirtualObject* obj =
...@@ -1514,6 +1522,46 @@ void EscapeAnalysis::ProcessLoadField(Node* node) { ...@@ -1514,6 +1522,46 @@ void EscapeAnalysis::ProcessLoadField(Node* node) {
} }
} }
void EscapeAnalysis::ProcessCheckMaps(Node* node) {
DCHECK_EQ(node->opcode(), IrOpcode::kCheckMaps);
ForwardVirtualState(node);
Node* checked = ResolveReplacement(NodeProperties::GetValueInput(node, 0));
if (FLAG_turbo_experimental) {
VirtualState* state = virtual_states_[node->id()];
if (VirtualObject* object = GetVirtualObject(state, checked)) {
if (!object->IsTracked()) {
if (status_analysis_->SetEscaped(node)) {
TRACE(
"Setting #%d (%s) to escaped because checked object #%i is not "
"tracked\n",
node->id(), node->op()->mnemonic(), object->id());
}
return;
}
CheckMapsParameters params = CheckMapsParametersOf(node->op());
Node* value = object->GetField(HeapObject::kMapOffset / kPointerSize);
if (value) {
value = ResolveReplacement(value);
// TODO(tebbi): We want to extend this beyond constant folding with a
// CheckMapsValue operator that takes the load-eliminated map value as
// input.
if (value->opcode() == IrOpcode::kHeapConstant &&
params.maps().contains(ZoneHandleSet<Map>(
Handle<Map>::cast(OpParameter<Handle<HeapObject>>(value))))) {
TRACE("CheckMaps #%i seems to be redundant (until now).\n",
node->id());
return;
}
}
}
}
if (status_analysis_->SetEscaped(node)) {
TRACE("Setting #%d (%s) to escaped (checking #%i)\n", node->id(),
node->op()->mnemonic(), checked->id());
}
}
void EscapeAnalysis::ProcessLoadElement(Node* node) { void EscapeAnalysis::ProcessLoadElement(Node* node) {
DCHECK_EQ(node->opcode(), IrOpcode::kLoadElement); DCHECK_EQ(node->opcode(), IrOpcode::kLoadElement);
ForwardVirtualState(node); ForwardVirtualState(node);
......
...@@ -45,6 +45,7 @@ class V8_EXPORT_PRIVATE EscapeAnalysis { ...@@ -45,6 +45,7 @@ class V8_EXPORT_PRIVATE EscapeAnalysis {
void ProcessStoreField(Node* node); void ProcessStoreField(Node* node);
void ProcessLoadElement(Node* node); void ProcessLoadElement(Node* node);
void ProcessStoreElement(Node* node); void ProcessStoreElement(Node* node);
void ProcessCheckMaps(Node* node);
void ProcessAllocationUsers(Node* node); void ProcessAllocationUsers(Node* node);
void ProcessAllocation(Node* node); void ProcessAllocation(Node* node);
void ProcessFinishRegion(Node* node); void ProcessFinishRegion(Node* node);
......
...@@ -499,6 +499,8 @@ DEFINE_BOOL(turbo_stress_instruction_scheduling, false, ...@@ -499,6 +499,8 @@ DEFINE_BOOL(turbo_stress_instruction_scheduling, false,
"randomly schedule instructions to stress dependency tracking") "randomly schedule instructions to stress dependency tracking")
DEFINE_BOOL(turbo_store_elimination, true, DEFINE_BOOL(turbo_store_elimination, true,
"enable store-store elimination in TurboFan") "enable store-store elimination in TurboFan")
DEFINE_BOOL(turbo_experimental, false,
"enable crashing features, for testing purposes only")
// TODO(turbofan): Rename --crankshaft to --optimize eventually. // TODO(turbofan): Rename --crankshaft to --optimize eventually.
DEFINE_IMPLICATION(turbo, crankshaft) DEFINE_IMPLICATION(turbo, crankshaft)
......
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --turbo --turbo-escape --turbo-experimental
function f() {
var x = {};
x.a = "a";
x.b = "b";
assertEquals("a", x.a);
assertEquals("b", x.b);
}
f();
f();
% OptimizeFunctionOnNextCall(f);
f();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment