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