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..f356a4fcd4b84508db346207513b97932f3e476e 100644 |
--- a/src/compiler/js-native-context-specialization.cc |
+++ b/src/compiler/js-native-context-specialization.cc |
@@ -129,8 +129,8 @@ Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) { |
} |
// Monomorphic property access. |
- effect = |
- BuildCheckMaps(constructor, effect, control, MapList{receiver_map}); |
+ effect = BuildCheckMaps(constructor, effect, control, |
+ access_info.receiver_maps()); |
// Lower to OrdinaryHasInstance(C, O). |
NodeProperties::ReplaceValueInput(node, constructor, 0); |
@@ -150,8 +150,8 @@ Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) { |
} |
// Monomorphic property access. |
- effect = |
- BuildCheckMaps(constructor, effect, control, MapList{receiver_map}); |
+ effect = BuildCheckMaps(constructor, effect, control, |
+ access_info.receiver_maps()); |
// Call the @@hasInstance handler. |
Node* target = jsgraph()->Constant(access_info.constant()); |
@@ -968,6 +968,7 @@ JSNativeContextSpecialization::BuildPropertyAccess( |
// Determine actual holder and perform prototype chain checks. |
Handle<JSObject> holder; |
if (access_info.holder().ToHandle(&holder)) { |
+ DCHECK_NE(AccessMode::kStoreInLiteral, access_mode); |
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,75 @@ 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(); |
+ } |
+ |
+ 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, access_info.receiver_maps()); |
+ |
+ // 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 { |
@@ -1285,6 +1354,8 @@ JSNativeContextSpecialization::BuildElementAccess( |
Node* receiver, Node* index, Node* value, Node* effect, Node* control, |
ElementAccessInfo const& access_info, AccessMode access_mode, |
KeyedAccessStoreMode store_mode) { |
+ DCHECK_NE(AccessMode::kStoreInLiteral, access_mode); |
+ |
// TODO(bmeurer): We currently specialize based on elements kind. We should |
// also be able to properly support strings and other JSObjects here. |
ElementsKind elements_kind = access_info.elements_kind(); |
@@ -1381,6 +1452,9 @@ JSNativeContextSpecialization::BuildElementAccess( |
base_pointer, external_pointer, index, effect, control); |
break; |
} |
+ case AccessMode::kStoreInLiteral: |
+ UNREACHABLE(); |
+ break; |
case AccessMode::kStore: { |
// Ensure that the {value} is actually a Number. |
value = effect = graph()->NewNode(simplified()->CheckNumber(), value, |