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>( |