Chromium Code Reviews| Index: src/compiler/effect-control-linearizer.cc |
| diff --git a/src/compiler/effect-control-linearizer.cc b/src/compiler/effect-control-linearizer.cc |
| index 965831c0bbc21d9dcdc218a3ecebb520dfba06f7..b88906cfc1c1adfbbb39bdcdaf72ab72919d7143 100644 |
| --- a/src/compiler/effect-control-linearizer.cc |
| +++ b/src/compiler/effect-control-linearizer.cc |
| @@ -1058,25 +1058,79 @@ Node* EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) { |
| Node* value = node->InputAt(0); |
| ZoneHandleSet<Map> const& maps = p.maps(); |
| - int const map_count = static_cast<int>(maps.size()); |
| + size_t const map_count = maps.size(); |
| + |
| + if (p.flags() & CheckMapsFlag::kTryMigrateInstance) { |
| + auto done = |
| + __ MakeLabelFor(GraphAssemblerLabelType::kNonDeferred, map_count * 2); |
| + auto migrate = __ MakeDeferredLabel<1>(); |
| + |
| + // Load the current map of the {value}. |
| + Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); |
| + |
| + // Perform the map checks. |
| + for (size_t i = 0; i < map_count; ++i) { |
| + Node* map = __ HeapConstant(maps[i]); |
| + Node* check = __ WordEqual(value_map, map); |
| + if (i == map_count - 1) { |
| + __ GotoUnless(check, &migrate); |
|
Jarin
2017/01/13 12:05:38
__ Branch(check, &done, &migrate);
Benedikt Meurer
2017/01/13 12:08:10
Doesn't work with the current template magic, will
|
| + __ Goto(&done); |
| + } else { |
| + __ GotoIf(check, &done); |
| + } |
| + } |
| - auto done = __ MakeLabelFor(GraphAssemblerLabelType::kNonDeferred, |
| - static_cast<size_t>(map_count)); |
| + // Perform the (deferred) instance migration. |
| + __ Bind(&migrate); |
| + { |
| + Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow; |
| + Runtime::FunctionId id = Runtime::kTryMigrateInstance; |
| + CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor( |
| + graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags); |
| + Node* result = |
| + __ Call(desc, __ CEntryStubConstant(1), value, |
| + __ ExternalConstant(ExternalReference(id, isolate())), |
| + __ Int32Constant(1), __ NoContextConstant()); |
| + Node* check = ObjectIsSmi(result); |
| + __ DeoptimizeIf(DeoptimizeReason::kInstanceMigrationFailed, check, |
| + frame_state); |
| + } |
| - // Load the current map of the {value}. |
| - Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); |
| + // Reload the current map of the {value}. |
| + value_map = __ LoadField(AccessBuilder::ForMap(), value); |
| - for (int i = 0; i < map_count; ++i) { |
| - Node* map = __ HeapConstant(maps[i]); |
| - Node* check = __ WordEqual(value_map, map); |
| - if (i == map_count - 1) { |
| - __ DeoptimizeUnless(DeoptimizeReason::kWrongMap, check, frame_state); |
| - } else { |
| - __ GotoIf(check, &done); |
| + // Perform the map checks again. |
| + for (size_t i = 0; i < map_count; ++i) { |
| + Node* map = __ HeapConstant(maps[i]); |
| + Node* check = __ WordEqual(value_map, map); |
| + if (i == map_count - 1) { |
| + __ DeoptimizeUnless(DeoptimizeReason::kWrongMap, check, frame_state); |
| + } else { |
| + __ GotoIf(check, &done); |
| + } |
| + } |
| + |
| + __ Goto(&done); |
| + __ Bind(&done); |
| + } else { |
| + auto done = |
| + __ MakeLabelFor(GraphAssemblerLabelType::kNonDeferred, map_count); |
| + |
| + // Load the current map of the {value}. |
| + Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); |
| + |
| + for (size_t i = 0; i < map_count; ++i) { |
| + Node* map = __ HeapConstant(maps[i]); |
| + Node* check = __ WordEqual(value_map, map); |
| + if (i == map_count - 1) { |
| + __ DeoptimizeUnless(DeoptimizeReason::kWrongMap, check, frame_state); |
| + } else { |
| + __ GotoIf(check, &done); |
| + } |
| } |
| + __ Goto(&done); |
| + __ Bind(&done); |
| } |
| - __ Goto(&done); |
| - __ Bind(&done); |
| return value; |
| } |