Index: src/compiler/escape-analysis.cc |
diff --git a/src/compiler/escape-analysis.cc b/src/compiler/escape-analysis.cc |
index 867afd62017003684eeedb7638fccf9b7518647a..2e5e8bf01200b6be5ec83e1fa1ed9172bb9021d3 100644 |
--- a/src/compiler/escape-analysis.cc |
+++ b/src/compiler/escape-analysis.cc |
@@ -807,6 +807,7 @@ bool EscapeStatusAnalysis::CheckUsesForEscape(Node* uses, Node* rep, |
case IrOpcode::kStateValues: |
case IrOpcode::kReferenceEqual: |
case IrOpcode::kFinishRegion: |
+ case IrOpcode::kCheckMaps: |
if (IsEscaped(use) && SetEscaped(rep)) { |
TRACE( |
"Setting #%d (%s) to escaped because of use by escaping node " |
@@ -1124,6 +1125,9 @@ bool EscapeAnalysis::Process(Node* node) { |
case IrOpcode::kLoadElement: |
ProcessLoadElement(node); |
break; |
+ case IrOpcode::kCheckMaps: |
+ ProcessCheckMaps(node); |
+ break; |
case IrOpcode::kStart: |
ProcessStart(node); |
break; |
@@ -1161,6 +1165,10 @@ void EscapeAnalysis::ProcessAllocationUsers(Node* node) { |
case IrOpcode::kFinishRegion: |
case IrOpcode::kObjectIsSmi: |
break; |
+ case IrOpcode::kCheckMaps: { |
+ CheckMapsParameters params = CheckMapsParametersOf(node->op()); |
+ if (params.flags() == CheckMapsFlag::kNone) break; |
+ } // Fallthrough. |
default: |
VirtualState* state = virtual_states_[node->id()]; |
if (VirtualObject* obj = |
@@ -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) { |
DCHECK_EQ(node->opcode(), IrOpcode::kLoadElement); |
ForwardVirtualState(node); |