Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(89)

Unified Diff: src/compiler/js-native-context-specialization.cc

Issue 1452563002: [turbofan] Add support for elements kind transitions. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/compiler/access-info.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/js-native-context-specialization.cc
diff --git a/src/compiler/js-native-context-specialization.cc b/src/compiler/js-native-context-specialization.cc
index a0a5c1b2148cc7037a47c05adb81fb3cc8fc8b2f..608f14445520532499e3300ccbc496c8ddc4defa 100644
--- a/src/compiler/js-native-context-specialization.cc
+++ b/src/compiler/js-native-context-specialization.cc
@@ -500,6 +500,7 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
DCHECK(node->opcode() == IrOpcode::kJSLoadProperty ||
node->opcode() == IrOpcode::kJSStoreProperty);
Node* receiver = NodeProperties::GetValueInput(node, 0);
+ Node* context = NodeProperties::GetContextInput(node);
Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
@@ -547,7 +548,7 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
Node* this_receiver = receiver;
Node* this_value = value;
Node* this_index = index;
- Node* this_effect = effect;
+ Node* this_effect;
Node* this_control;
// Perform map check on {receiver}.
@@ -555,24 +556,77 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
bool receiver_is_jsarray = true;
{
ZoneVector<Node*> this_controls(zone());
+ ZoneVector<Node*> this_effects(zone());
for (auto i = access_info.receiver_type()->Classes(); !i.Done();
i.Advance()) {
Handle<Map> map = i.Current();
Node* check =
- graph()->NewNode(simplified()->ReferenceEqual(Type::Internal()),
+ graph()->NewNode(simplified()->ReferenceEqual(Type::Any()),
receiver_map, jsgraph()->Constant(map));
Node* branch =
graph()->NewNode(common()->Branch(), check, fallthrough_control);
this_controls.push_back(graph()->NewNode(common()->IfTrue(), branch));
+ this_effects.push_back(effect);
fallthrough_control = graph()->NewNode(common()->IfFalse(), branch);
if (!map->IsJSArrayMap()) receiver_is_jsarray = false;
}
+
+ // Generate possible elements kind transitions.
+ for (auto transition : access_info.transitions()) {
+ Handle<Map> transition_source = transition.first;
+ Handle<Map> transition_target = transition.second;
+
+ // Check if {receiver} has the specified {transition_source} map.
+ Node* check = graph()->NewNode(
+ simplified()->ReferenceEqual(Type::Any()), receiver_map,
+ jsgraph()->HeapConstant(transition_source));
+ Node* branch =
+ graph()->NewNode(common()->Branch(), check, fallthrough_control);
+
+ // Migrate {receiver} from {transition_source} to {transition_target}.
+ Node* transition_control = graph()->NewNode(common()->IfTrue(), branch);
+ Node* transition_effect = effect;
+ if (IsSimpleMapChangeTransition(transition_source->elements_kind(),
+ transition_target->elements_kind())) {
+ // In-place migration, just store the {transition_target} map.
+ transition_effect = graph()->NewNode(
+ simplified()->StoreField(AccessBuilder::ForMap()), receiver,
+ jsgraph()->HeapConstant(transition_target), transition_effect,
+ transition_control);
+ } else {
+ // Instance migration, let the stub deal with the {receiver}.
+ TransitionElementsKindStub stub(isolate(),
+ transition_source->elements_kind(),
+ transition_target->elements_kind(),
+ transition_source->IsJSArrayMap());
+ CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
+ isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(), 0,
+ CallDescriptor::kNeedsFrameState, node->op()->properties());
+ transition_effect = graph()->NewNode(
+ common()->Call(desc), jsgraph()->HeapConstant(stub.GetCode()),
+ receiver, jsgraph()->HeapConstant(transition_target), context,
+ frame_state, transition_effect, transition_control);
+ }
+ this_controls.push_back(transition_control);
+ this_effects.push_back(transition_effect);
+
+ fallthrough_control = graph()->NewNode(common()->IfFalse(), branch);
+ }
+
+ // Create single chokepoint for the control.
int const this_control_count = static_cast<int>(this_controls.size());
- this_control =
- (this_control_count == 1)
- ? this_controls.front()
- : graph()->NewNode(common()->Merge(this_control_count),
- this_control_count, &this_controls.front());
+ if (this_control_count == 1) {
+ this_control = this_controls.front();
+ this_effect = this_effects.front();
+ } else {
+ this_control =
+ graph()->NewNode(common()->Merge(this_control_count),
+ this_control_count, &this_controls.front());
+ this_effects.push_back(this_control);
+ this_effect =
+ graph()->NewNode(common()->EffectPhi(this_control_count),
+ this_control_count + 1, &this_effects.front());
+ }
}
// Certain stores need a prototype chain check because shape changes
« no previous file with comments | « src/compiler/access-info.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698