Chromium Code Reviews| 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 76eed6554f4c3e1eadd8702d7016c2e55fb519a1..cc47eded8740572f2c704cd54e72bc5e3af8ff1e 100644 |
| --- a/src/compiler/js-native-context-specialization.cc |
| +++ b/src/compiler/js-native-context-specialization.cc |
| @@ -967,7 +967,8 @@ JSNativeContextSpecialization::BuildPropertyAccess( |
| Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot) { |
| // Determine actual holder and perform prototype chain checks. |
| Handle<JSObject> holder; |
| - if (access_info.holder().ToHandle(&holder)) { |
| + if (access_info.holder().ToHandle(&holder) && |
|
Benedikt Meurer
2017/01/10 08:25:55
There should never be a holder for kStoreInLiteral
Franzi
2017/01/10 10:54:02
OK. Done.
|
| + access_mode != AccessMode::kStoreInLiteral) { |
| AssumePrototypesStable(access_info.receiver_maps(), holder); |
| } |
| @@ -1028,6 +1029,7 @@ JSNativeContextSpecialization::BuildPropertyAccess( |
| } |
| break; |
| } |
| + case AccessMode::kStoreInLiteral: |
| case AccessMode::kStore: { |
| // We need a FrameState for the setter stub to restore the correct |
| // context and return the appropriate value to fullcodegen. |
| @@ -1258,8 +1260,76 @@ JSNativeContextSpecialization::BuildPropertyAccess( |
| Reduction JSNativeContextSpecialization::ReduceJSStoreDataPropertyInLiteral( |
| Node* node) { |
| - // TODO(franzih): Use feedback |
| - return NoChange(); |
| + DCHECK_EQ(IrOpcode::kJSStoreDataPropertyInLiteral, node->opcode()); |
| + |
| + // If deoptimization is disabled, we cannot optimize. |
| + if (!(flags() & kDeoptimizationEnabled)) return NoChange(); |
| + |
| + DataPropertyParameters const& p = DataPropertyParametersOf(node->op()); |
| + |
| + if (!p.feedback().IsValid()) return NoChange(); |
| + |
| + StoreDataPropertyInLiteralICNexus nexus(p.feedback().vector(), |
| + p.feedback().slot()); |
| + if (nexus.IsUninitialized()) { |
| + return NoChange(); |
| + } |
| + |
| + if (nexus.ic_state() == MEGAMORPHIC) { |
| + return NoChange(); |
| + } |
| + |
| + DCHECK_EQ(MONOMORPHIC, nexus.ic_state()); |
| + |
| + Handle<Map> receiver_map(nexus.FindFirstMap(), isolate()); |
| + Handle<Name> cached_name = |
| + handle(Name::cast(nexus.GetFeedbackExtra()), isolate()); |
| + |
| + PropertyAccessInfo access_info; |
| + AccessInfoFactory access_info_factory(dependencies(), native_context(), |
| + graph()->zone()); |
| + if (!access_info_factory.ComputePropertyAccessInfo( |
| + receiver_map, cached_name, AccessMode::kStoreInLiteral, |
| + &access_info)) { |
| + return NoChange(); |
| + } |
| + |
| + DCHECK_EQ(1, access_info.receiver_maps().size()); |
|
Benedikt Meurer
2017/01/10 08:25:55
This check doesn't need to be here.
Franzi
2017/01/10 10:54:01
Oops, left-over debugging stuff. Deleted.
|
| + |
| + if (access_info.IsGeneric()) { |
| + return NoChange(); |
| + } |
| + |
| + Node* receiver = NodeProperties::GetValueInput(node, 0); |
| + Node* effect = NodeProperties::GetEffectInput(node); |
| + Node* control = NodeProperties::GetControlInput(node); |
| + |
| + // Monomorphic property access. |
| + receiver = BuildCheckHeapObject(receiver, &effect, control); |
| + |
| + effect = BuildCheckMaps(receiver, effect, control, MapList{receiver_map}); |
|
Benedikt Meurer
2017/01/10 08:25:54
You can use access_info.receiver_maps() here inste
Franzi
2017/01/10 10:54:01
Done. Changed the other uses of MapList{} as well.
|
| + |
| + // Ensure that {name} matches the cached name. |
| + Node* name = NodeProperties::GetValueInput(node, 1); |
| + Node* check = graph()->NewNode(simplified()->ReferenceEqual(), name, |
| + jsgraph()->HeapConstant(cached_name)); |
| + effect = graph()->NewNode(simplified()->CheckIf(), check, effect, control); |
| + |
| + Node* value = NodeProperties::GetValueInput(node, 2); |
| + Node* context = NodeProperties::GetContextInput(node); |
| + Node* frame_state_lazy = NodeProperties::GetFrameStateInput(node); |
| + |
| + // Generate the actual property access. |
| + ValueEffectControl continuation = BuildPropertyAccess( |
| + receiver, value, context, frame_state_lazy, effect, control, cached_name, |
| + access_info, AccessMode::kStoreInLiteral, LanguageMode::SLOPPY, |
| + p.feedback().vector(), p.feedback().slot()); |
| + value = continuation.value(); |
| + effect = continuation.effect(); |
| + control = continuation.control(); |
| + |
| + ReplaceWithValue(node, value, effect, control); |
| + return Replace(value); |
| } |
| namespace { |
| @@ -1381,6 +1451,7 @@ JSNativeContextSpecialization::BuildElementAccess( |
| base_pointer, external_pointer, index, effect, control); |
| break; |
| } |
| + case AccessMode::kStoreInLiteral: |
| case AccessMode::kStore: { |
| // Ensure that the {value} is actually a Number. |
| value = effect = graph()->NewNode(simplified()->CheckNumber(), value, |
| @@ -1436,7 +1507,8 @@ JSNativeContextSpecialization::BuildElementAccess( |
| effect, control); |
| // Don't try to store to a copy-on-write backing store. |
| - if (access_mode == AccessMode::kStore && |
| + if ((access_mode == AccessMode::kStore || |
| + access_mode == AccessMode::kStoreInLiteral) && |
|
Benedikt Meurer
2017/01/10 08:25:54
This doesn't make sense. We never do a store in li
Franzi
2017/01/10 10:54:01
OK, also added a DCHECK to beginning of the functi
|
| IsFastSmiOrObjectElementsKind(elements_kind) && |
| store_mode != STORE_NO_TRANSITION_HANDLE_COW) { |
| effect = graph()->NewNode(simplified()->CheckMaps(ZoneHandleSet<Map>( |