summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/node-properties.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler/node-properties.cc')
-rw-r--r--deps/v8/src/compiler/node-properties.cc111
1 files changed, 103 insertions, 8 deletions
diff --git a/deps/v8/src/compiler/node-properties.cc b/deps/v8/src/compiler/node-properties.cc
index d84c27e86d..e312dc4354 100644
--- a/deps/v8/src/compiler/node-properties.cc
+++ b/deps/v8/src/compiler/node-properties.cc
@@ -277,6 +277,23 @@ Node* NodeProperties::FindProjection(Node* node, size_t projection_index) {
// static
+void NodeProperties::CollectValueProjections(Node* node, Node** projections,
+ size_t projection_count) {
+#ifdef DEBUG
+ for (size_t index = 0; index < projection_count; ++index) {
+ DCHECK_NULL(projections[index]);
+ }
+#endif
+ for (Edge const edge : node->use_edges()) {
+ if (!IsValueEdge(edge)) continue;
+ Node* use = edge.from();
+ DCHECK_EQ(IrOpcode::kProjection, use->opcode());
+ projections[ProjectionIndexOf(use->op())] = use;
+ }
+}
+
+
+// static
void NodeProperties::CollectControlProjections(Node* node, Node** projections,
size_t projection_count) {
#ifdef DEBUG
@@ -348,12 +365,26 @@ NodeProperties::InferReceiverMapsResult 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()) {
- // The {receiver_map} is only reliable when we install a stability
- // code dependency.
- *maps_return = ZoneHandleSet<Map>(receiver_map);
- return kUnreliableReceiverMaps;
+ Handle<HeapObject> receiver = m.Value();
+ Isolate* const isolate = m.Value()->GetIsolate();
+ // We don't use ICs for the Array.prototype and the Object.prototype
+ // because the runtime has to be able to intercept them properly, so
+ // we better make sure that TurboFan doesn't outsmart the system here
+ // by storing to elements of either prototype directly.
+ //
+ // TODO(bmeurer): This can be removed once the Array.prototype and
+ // Object.prototype have NO_ELEMENTS elements kind.
+ if (!isolate->IsInAnyContext(*receiver,
+ Context::INITIAL_ARRAY_PROTOTYPE_INDEX) &&
+ !isolate->IsInAnyContext(*receiver,
+ Context::INITIAL_OBJECT_PROTOTYPE_INDEX)) {
+ Handle<Map> receiver_map(receiver->map(), isolate);
+ if (receiver_map->is_stable()) {
+ // The {receiver_map} is only reliable when we install a stability
+ // code dependency.
+ *maps_return = ZoneHandleSet<Map>(receiver_map);
+ return kUnreliableReceiverMaps;
+ }
}
}
InferReceiverMapsResult result = kReliableReceiverMaps;
@@ -362,7 +393,7 @@ NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMaps(
case IrOpcode::kMapGuard: {
Node* const object = GetValueInput(effect, 0);
if (IsSame(receiver, object)) {
- *maps_return = MapGuardMapsOf(effect->op());
+ *maps_return = MapGuardMapsOf(effect->op()).maps();
return result;
}
break;
@@ -379,7 +410,8 @@ NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMaps(
if (IsSame(receiver, effect)) {
HeapObjectMatcher mtarget(GetValueInput(effect, 0));
HeapObjectMatcher mnewtarget(GetValueInput(effect, 1));
- if (mtarget.HasValue() && mnewtarget.HasValue()) {
+ if (mtarget.HasValue() && mnewtarget.HasValue() &&
+ mnewtarget.Value()->IsJSFunction()) {
Handle<JSFunction> original_constructor =
Handle<JSFunction>::cast(mnewtarget.Value());
if (original_constructor->has_initial_map()) {
@@ -470,6 +502,69 @@ bool NodeProperties::NoObservableSideEffectBetween(Node* effect,
}
// static
+bool NodeProperties::CanBePrimitive(Node* receiver, Node* effect) {
+ switch (receiver->opcode()) {
+#define CASE(Opcode) case IrOpcode::k##Opcode:
+ JS_CONSTRUCT_OP_LIST(CASE)
+ JS_CREATE_OP_LIST(CASE)
+#undef CASE
+ case IrOpcode::kCheckReceiver:
+ case IrOpcode::kConvertReceiver:
+ case IrOpcode::kJSGetSuperConstructor:
+ case IrOpcode::kJSToObject:
+ return false;
+ case IrOpcode::kHeapConstant: {
+ Handle<HeapObject> value = HeapObjectMatcher(receiver).Value();
+ return value->IsPrimitive();
+ }
+ default: {
+ // We don't really care about the exact maps here,
+ // just the instance types, which don't change
+ // across potential side-effecting operations.
+ ZoneHandleSet<Map> maps;
+ if (InferReceiverMaps(receiver, effect, &maps) != kNoReceiverMaps) {
+ // Check if all {maps} are actually JSReceiver maps.
+ for (size_t i = 0; i < maps.size(); ++i) {
+ if (!maps[i]->IsJSReceiverMap()) return true;
+ }
+ return false;
+ }
+ return true;
+ }
+ }
+}
+
+// static
+bool NodeProperties::CanBeNullOrUndefined(Node* receiver, Node* effect) {
+ if (CanBePrimitive(receiver, effect)) {
+ switch (receiver->opcode()) {
+ case IrOpcode::kCheckSmi:
+ case IrOpcode::kCheckNumber:
+ case IrOpcode::kCheckSymbol:
+ case IrOpcode::kCheckString:
+ case IrOpcode::kCheckSeqString:
+ case IrOpcode::kCheckInternalizedString:
+ case IrOpcode::kToBoolean:
+ case IrOpcode::kJSToInteger:
+ case IrOpcode::kJSToLength:
+ case IrOpcode::kJSToName:
+ case IrOpcode::kJSToNumber:
+ case IrOpcode::kJSToNumeric:
+ case IrOpcode::kJSToString:
+ return false;
+ case IrOpcode::kHeapConstant: {
+ Handle<HeapObject> value = HeapObjectMatcher(receiver).Value();
+ Isolate* const isolate = value->GetIsolate();
+ return value->IsNullOrUndefined(isolate);
+ }
+ default:
+ return true;
+ }
+ }
+ return false;
+}
+
+// static
Node* NodeProperties::GetOuterContext(Node* node, size_t* depth) {
Node* context = NodeProperties::GetContextInput(node);
while (*depth > 0 &&