Index: src/compiler/node-properties.cc |
diff --git a/src/compiler/node-properties.cc b/src/compiler/node-properties.cc |
index 2e1e1bde8e83ef491ea1a7320b2b7e2429b237b7..e559844cbfa932d63480a3228733fd3846761067 100644 |
--- a/src/compiler/node-properties.cc |
+++ b/src/compiler/node-properties.cc |
@@ -7,7 +7,9 @@ |
#include "src/compiler/graph.h" |
#include "src/compiler/js-operator.h" |
#include "src/compiler/linkage.h" |
+#include "src/compiler/node-matchers.h" |
#include "src/compiler/operator-properties.h" |
+#include "src/compiler/simplified-operator.h" |
#include "src/compiler/verifier.h" |
#include "src/handles-inl.h" |
#include "src/objects-inl.h" |
@@ -328,6 +330,90 @@ bool NodeProperties::IsSame(Node* a, Node* b) { |
} |
// static |
+bool NodeProperties::InferReceiverMaps(Node* receiver, Node* effect, |
+ ZoneHandleSet<Map>* maps_return) { |
+ HeapObjectMatcher m(receiver); |
+ if (m.HasValue()) { |
+ Handle<Map> receiver_map(m.Value()->map()); |
+ if (receiver_map->is_stable()) { |
+ *maps_return = ZoneHandleSet<Map>(receiver_map); |
+ return true; |
+ } |
+ } |
+ while (true) { |
+ switch (effect->opcode()) { |
+ case IrOpcode::kCheckMaps: { |
+ Node* const object = GetValueInput(effect, 0); |
+ if (IsSame(receiver, object)) { |
+ *maps_return = CheckMapsParametersOf(effect->op()).maps(); |
+ return true; |
+ } |
+ break; |
+ } |
+ case IrOpcode::kJSCreate: { |
+ if (IsSame(receiver, effect)) { |
+ HeapObjectMatcher mtarget(GetValueInput(effect, 0)); |
+ HeapObjectMatcher mnewtarget(GetValueInput(effect, 1)); |
+ if (mtarget.HasValue() && mnewtarget.HasValue()) { |
+ Handle<JSFunction> original_constructor = |
+ Handle<JSFunction>::cast(mnewtarget.Value()); |
+ if (original_constructor->has_initial_map()) { |
+ Handle<Map> initial_map(original_constructor->initial_map()); |
+ if (initial_map->constructor_or_backpointer() == |
+ *mtarget.Value()) { |
+ *maps_return = ZoneHandleSet<Map>(initial_map); |
+ return true; |
+ } |
+ } |
+ } |
+ // We reached the allocation of the {receiver}. |
+ return false; |
+ } |
+ break; |
+ } |
+ case IrOpcode::kStoreField: { |
+ // We only care about StoreField of maps. |
+ Node* const object = GetValueInput(effect, 0); |
+ FieldAccess const& access = FieldAccessOf(effect->op()); |
+ if (access.base_is_tagged == kTaggedBase && |
+ access.offset == HeapObject::kMapOffset) { |
+ if (IsSame(receiver, object)) { |
+ Node* const value = GetValueInput(effect, 1); |
+ HeapObjectMatcher m(value); |
+ if (m.HasValue()) { |
+ *maps_return = ZoneHandleSet<Map>(Handle<Map>::cast(m.Value())); |
+ return true; |
+ } |
+ } |
+ // Without alias analysis we cannot tell whether this |
+ // StoreField[map] affects {receiver} or not. |
+ return false; |
+ } |
+ break; |
+ } |
+ case IrOpcode::kJSStoreMessage: |
+ case IrOpcode::kJSStoreModule: |
+ case IrOpcode::kStoreElement: |
+ case IrOpcode::kStoreTypedElement: { |
+ // These never change the map of objects. |
+ break; |
+ } |
+ default: { |
+ DCHECK_EQ(1, effect->op()->EffectOutputCount()); |
+ if (effect->op()->EffectInputCount() != 1 || |
+ !effect->op()->HasProperty(Operator::kNoWrite)) { |
+ // Didn't find any appropriate CheckMaps node. |
+ return false; |
+ } |
+ break; |
+ } |
+ } |
+ DCHECK_EQ(1, effect->op()->EffectInputCount()); |
+ effect = NodeProperties::GetEffectInput(effect); |
+ } |
+} |
+ |
+// static |
MaybeHandle<Context> NodeProperties::GetSpecializationContext( |
Node* node, MaybeHandle<Context> context) { |
switch (node->opcode()) { |