| 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);
|
|
|