summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/js-native-context-specialization.cc
diff options
context:
space:
mode:
authorMyles Borins <mylesborins@google.com>2019-09-24 11:56:38 -0400
committerMyles Borins <myles.borins@gmail.com>2019-10-07 03:19:23 -0400
commitf7f6c928c1c9c136b7926f892b8a2fda11d8b4b2 (patch)
treef5edbccb3ffda2573d70a6e291e7157f290e0ae0 /deps/v8/src/compiler/js-native-context-specialization.cc
parentffd22e81983056d09c064c59343a0e488236272d (diff)
downloadnode-new-f7f6c928c1c9c136b7926f892b8a2fda11d8b4b2.tar.gz
deps: update V8 to 7.8.279.9
PR-URL: https://github.com/nodejs/node/pull/29694 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Gus Caplan <me@gus.host> Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Ujjwal Sharma <usharma1998@gmail.com>
Diffstat (limited to 'deps/v8/src/compiler/js-native-context-specialization.cc')
-rw-r--r--deps/v8/src/compiler/js-native-context-specialization.cc633
1 files changed, 288 insertions, 345 deletions
diff --git a/deps/v8/src/compiler/js-native-context-specialization.cc b/deps/v8/src/compiler/js-native-context-specialization.cc
index 8f7552baa1..9f950c808c 100644
--- a/deps/v8/src/compiler/js-native-context-specialization.cc
+++ b/deps/v8/src/compiler/js-native-context-specialization.cc
@@ -19,7 +19,6 @@
#include "src/compiler/node-matchers.h"
#include "src/compiler/property-access-builder.h"
#include "src/compiler/type-cache.h"
-#include "src/compiler/vector-slot-pair.h"
#include "src/execution/isolate-inl.h"
#include "src/numbers/dtoa.h"
#include "src/objects/feedback-vector.h"
@@ -52,35 +51,26 @@ bool HasOnlyJSArrayMaps(JSHeapBroker* broker,
return true;
}
-void TryUpdateThenDropDeprecated(Isolate* isolate, MapHandles* maps) {
- for (auto it = maps->begin(); it != maps->end();) {
- if (Map::TryUpdate(isolate, *it).ToHandle(&*it)) {
- DCHECK(!(*it)->is_deprecated());
- ++it;
- } else {
- it = maps->erase(it);
- }
- }
-}
-
} // namespace
JSNativeContextSpecialization::JSNativeContextSpecialization(
Editor* editor, JSGraph* jsgraph, JSHeapBroker* broker, Flags flags,
- Handle<Context> native_context, CompilationDependencies* dependencies,
- Zone* zone, Zone* shared_zone)
+ CompilationDependencies* dependencies, Zone* zone, Zone* shared_zone)
: AdvancedReducer(editor),
jsgraph_(jsgraph),
broker_(broker),
flags_(flags),
- global_object_(native_context->global_object(), jsgraph->isolate()),
- global_proxy_(native_context->global_proxy(), jsgraph->isolate()),
+ global_object_(broker->target_native_context().global_object().object()),
+ global_proxy_(
+ broker->target_native_context().global_proxy_object().object()),
dependencies_(dependencies),
zone_(zone),
shared_zone_(shared_zone),
type_cache_(TypeCache::Get()) {}
Reduction JSNativeContextSpecialization::Reduce(Node* node) {
+ DisallowHeapAccessIf disallow_heap_access(FLAG_concurrent_inlining);
+
switch (node->opcode()) {
case IrOpcode::kJSAdd:
return ReduceJSAdd(node);
@@ -128,6 +118,8 @@ Reduction JSNativeContextSpecialization::Reduce(Node* node) {
return ReduceJSToObject(node);
case IrOpcode::kJSToString:
return ReduceJSToString(node);
+ case IrOpcode::kJSGetIterator:
+ return ReduceJSGetIterator(node);
default:
break;
}
@@ -236,11 +228,12 @@ Reduction JSNativeContextSpecialization::ReduceJSAsyncFunctionEnter(
// Create the JSAsyncFunctionObject based on the SharedFunctionInfo
// extracted from the top-most frame in {frame_state}.
- Handle<SharedFunctionInfo> shared =
- FrameStateInfoOf(frame_state->op()).shared_info().ToHandleChecked();
- DCHECK(shared->is_compiled());
- int register_count = shared->internal_formal_parameter_count() +
- shared->GetBytecodeArray().register_count();
+ SharedFunctionInfoRef shared(
+ broker(),
+ FrameStateInfoOf(frame_state->op()).shared_info().ToHandleChecked());
+ DCHECK(shared.is_compiled());
+ int register_count = shared.internal_formal_parameter_count() +
+ shared.GetBytecodeArray().register_count();
Node* value = effect =
graph()->NewNode(javascript()->CreateAsyncFunctionObject(register_count),
closure, receiver, promise, context, effect, control);
@@ -360,9 +353,7 @@ Reduction JSNativeContextSpecialization::ReduceJSGetSuperConstructor(
if (!m.HasValue()) return NoChange();
JSFunctionRef function = m.Ref(broker()).AsJSFunction();
MapRef function_map = function.map();
- if (!FLAG_concurrent_inlining) {
- function_map.SerializePrototype();
- } else if (!function_map.serialized_prototype()) {
+ if (FLAG_concurrent_inlining && !function_map.serialized_prototype()) {
TRACE_BROKER_MISSING(broker(), "data for map " << function_map);
return NoChange();
}
@@ -396,22 +387,37 @@ Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) {
// we have feedback from the InstanceOfIC.
Handle<JSObject> receiver;
HeapObjectMatcher m(constructor);
- if (m.HasValue() && m.Value()->IsJSObject()) {
- receiver = Handle<JSObject>::cast(m.Value());
+ if (m.HasValue() && m.Ref(broker()).IsJSObject()) {
+ receiver = m.Ref(broker()).AsJSObject().object();
} else if (p.feedback().IsValid()) {
- FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot());
- if (!nexus.GetConstructorFeedback().ToHandle(&receiver)) return NoChange();
+ ProcessedFeedback const& feedback =
+ broker()->GetFeedbackForInstanceOf(FeedbackSource(p.feedback()));
+ if (feedback.IsInsufficient()) return NoChange();
+ base::Optional<JSObjectRef> maybe_receiver =
+ feedback.AsInstanceOf().value();
+ if (!maybe_receiver.has_value()) return NoChange();
+ receiver = maybe_receiver->object();
} else {
return NoChange();
}
- Handle<Map> receiver_map(receiver->map(), isolate());
- // Compute property access info for @@hasInstance on the constructor.
- AccessInfoFactory access_info_factory(broker(), dependencies(),
- graph()->zone());
- PropertyAccessInfo access_info =
- access_info_factory.ComputePropertyAccessInfo(
- receiver_map, factory()->has_instance_symbol(), AccessMode::kLoad);
+ JSObjectRef receiver_ref(broker(), receiver);
+ MapRef receiver_map = receiver_ref.map();
+
+ PropertyAccessInfo access_info = PropertyAccessInfo::Invalid(graph()->zone());
+ if (FLAG_concurrent_inlining) {
+ access_info = broker()->GetPropertyAccessInfo(
+ receiver_map,
+ NameRef(broker(), isolate()->factory()->has_instance_symbol()),
+ AccessMode::kLoad);
+ } else {
+ AccessInfoFactory access_info_factory(broker(), dependencies(),
+ graph()->zone());
+ access_info = access_info_factory.ComputePropertyAccessInfo(
+ receiver_map.object(), factory()->has_instance_symbol(),
+ AccessMode::kLoad);
+ }
+
if (access_info.IsInvalid()) return NoChange();
access_info.RecordDependencies(dependencies());
@@ -420,7 +426,7 @@ Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) {
if (access_info.IsNotFound()) {
// If there's no @@hasInstance handler, the OrdinaryHasInstance operation
// takes over, but that requires the constructor to be callable.
- if (!receiver_map->is_callable()) return NoChange();
+ if (!receiver_map.is_callable()) return NoChange();
dependencies()->DependOnStablePrototypeChains(access_info.receiver_maps(),
kStartAtPrototype);
@@ -439,17 +445,15 @@ Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) {
}
if (access_info.IsDataConstant()) {
- // Determine actual holder.
Handle<JSObject> holder;
bool found_on_proto = access_info.holder().ToHandle(&holder);
- if (!found_on_proto) holder = receiver;
-
- FieldIndex field_index = access_info.field_index();
- Handle<Object> constant = JSObject::FastPropertyAt(
- holder, access_info.field_representation(), field_index);
- if (!constant->IsCallable()) {
+ JSObjectRef holder_ref =
+ found_on_proto ? JSObjectRef(broker(), holder) : receiver_ref;
+ base::Optional<ObjectRef> constant = holder_ref.GetOwnDataProperty(
+ access_info.field_representation(), access_info.field_index());
+ if (!constant.has_value() || !constant->IsHeapObject() ||
+ !constant->AsHeapObject().map().is_callable())
return NoChange();
- }
if (found_on_proto) {
dependencies()->DependOnStablePrototypeChains(
@@ -457,8 +461,6 @@ Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) {
JSObjectRef(broker(), holder));
}
- DCHECK(constant->IsCallable());
-
// Check that {constructor} is actually {receiver}.
constructor =
access_builder.BuildCheckValue(constructor, &effect, control, receiver);
@@ -478,14 +480,14 @@ Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) {
0, frame_state, ContinuationFrameStateMode::LAZY);
// Call the @@hasInstance handler.
- Node* target = jsgraph()->Constant(constant);
+ Node* target = jsgraph()->Constant(*constant);
node->InsertInput(graph()->zone(), 0, target);
node->ReplaceInput(1, constructor);
node->ReplaceInput(2, object);
node->ReplaceInput(4, continuation_frame_state);
node->ReplaceInput(5, effect);
NodeProperties::ChangeOp(
- node, javascript()->Call(3, CallFrequency(), VectorSlotPair(),
+ node, javascript()->Call(3, CallFrequency(), FeedbackSource(),
ConvertReceiverMode::kNotNullOrUndefined));
// Rewire the value uses of {node} to ToBoolean conversion of the result.
@@ -504,7 +506,7 @@ Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) {
JSNativeContextSpecialization::InferHasInPrototypeChainResult
JSNativeContextSpecialization::InferHasInPrototypeChain(
- Node* receiver, Node* effect, Handle<HeapObject> prototype) {
+ Node* receiver, Node* effect, HeapObjectRef const& prototype) {
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMapsUnsafe(broker(), receiver, effect,
@@ -517,28 +519,31 @@ JSNativeContextSpecialization::InferHasInPrototypeChain(
bool all = true;
bool none = true;
for (size_t i = 0; i < receiver_maps.size(); ++i) {
- Handle<Map> receiver_map = receiver_maps[i];
- if (receiver_map->instance_type() <= LAST_SPECIAL_RECEIVER_TYPE) {
- return kMayBeInPrototypeChain;
- }
- if (result == NodeProperties::kUnreliableReceiverMaps &&
- !receiver_map->is_stable()) {
+ MapRef map(broker(), receiver_maps[i]);
+ if (result == NodeProperties::kUnreliableReceiverMaps && !map.is_stable()) {
return kMayBeInPrototypeChain;
}
- for (PrototypeIterator it(isolate(), receiver_map);; it.Advance()) {
- if (it.IsAtEnd()) {
+ while (true) {
+ if (IsSpecialReceiverInstanceType(map.instance_type())) {
+ return kMayBeInPrototypeChain;
+ }
+ if (!map.IsJSObjectMap()) {
all = false;
break;
}
- Handle<HeapObject> current =
- PrototypeIterator::GetCurrent<HeapObject>(it);
- if (current.is_identical_to(prototype)) {
+ if (FLAG_concurrent_inlining && !map.serialized_prototype()) {
+ TRACE_BROKER_MISSING(broker(), "prototype data for map " << map);
+ return kMayBeInPrototypeChain;
+ }
+ if (map.prototype().equals(prototype)) {
none = false;
break;
}
- if (!current->map().is_stable() ||
- current->map().instance_type() <= LAST_SPECIAL_RECEIVER_TYPE) {
- return kMayBeInPrototypeChain;
+ map = map.prototype().map();
+ if (!map.is_stable()) return kMayBeInPrototypeChain;
+ if (map.oddball_type() == OddballType::kNull) {
+ all = false;
+ break;
}
}
}
@@ -554,8 +559,8 @@ JSNativeContextSpecialization::InferHasInPrototypeChain(
// might be a different object each time, so it's much simpler to include
// {prototype}. That does, however, mean that we must check {prototype}'s
// map stability.
- if (!prototype->map().is_stable()) return kMayBeInPrototypeChain;
- last_prototype.emplace(broker(), Handle<JSObject>::cast(prototype));
+ if (!prototype.map().is_stable()) return kMayBeInPrototypeChain;
+ last_prototype = prototype.AsJSObject();
}
WhereToStart start = result == NodeProperties::kUnreliableReceiverMaps
? kStartAtReceiver
@@ -580,7 +585,7 @@ Reduction JSNativeContextSpecialization::ReduceJSHasInPrototypeChain(
HeapObjectMatcher m(prototype);
if (m.HasValue()) {
InferHasInPrototypeChainResult result =
- InferHasInPrototypeChain(value, effect, m.Value());
+ InferHasInPrototypeChain(value, effect, m.Ref(broker()));
if (result != kMayBeInPrototypeChain) {
Node* value = jsgraph()->BooleanConstant(result == kIsInPrototypeChain);
ReplaceWithValue(node, value);
@@ -601,34 +606,41 @@ Reduction JSNativeContextSpecialization::ReduceJSOrdinaryHasInstance(
HeapObjectMatcher m(constructor);
if (!m.HasValue()) return NoChange();
- // Check if the {constructor} is a JSBoundFunction.
- if (m.Value()->IsJSBoundFunction()) {
- // OrdinaryHasInstance on bound functions turns into a recursive
- // invocation of the instanceof operator again.
- // ES6 section 7.3.19 OrdinaryHasInstance (C, O) step 2.
- Handle<JSBoundFunction> function = Handle<JSBoundFunction>::cast(m.Value());
- Handle<JSReceiver> bound_target_function(function->bound_target_function(),
- isolate());
+ if (m.Ref(broker()).IsJSBoundFunction()) {
+ // OrdinaryHasInstance on bound functions turns into a recursive invocation
+ // of the instanceof operator again.
+ JSBoundFunctionRef function = m.Ref(broker()).AsJSBoundFunction();
+ if (FLAG_concurrent_inlining && !function.serialized()) {
+ TRACE_BROKER_MISSING(broker(), "data for JSBoundFunction " << function);
+ return NoChange();
+ }
+
+ JSReceiverRef bound_target_function = function.bound_target_function();
+
NodeProperties::ReplaceValueInput(node, object, 0);
NodeProperties::ReplaceValueInput(
- node, jsgraph()->HeapConstant(bound_target_function), 1);
- NodeProperties::ChangeOp(node, javascript()->InstanceOf(VectorSlotPair()));
+ node, jsgraph()->Constant(bound_target_function), 1);
+ NodeProperties::ChangeOp(node, javascript()->InstanceOf(FeedbackSource()));
Reduction const reduction = ReduceJSInstanceOf(node);
return reduction.Changed() ? reduction : Changed(node);
}
- // Optimize if we currently know the "prototype" property.
- if (m.Value()->IsJSFunction()) {
+ if (m.Ref(broker()).IsJSFunction()) {
+ // Optimize if we currently know the "prototype" property.
+
JSFunctionRef function = m.Ref(broker()).AsJSFunction();
- // TODO(neis): This is a temporary hack needed because the copy reducer
- // runs only after this pass.
- function.Serialize();
+ if (FLAG_concurrent_inlining && !function.serialized()) {
+ TRACE_BROKER_MISSING(broker(), "data for JSFunction " << function);
+ return NoChange();
+ }
+
// TODO(neis): Remove the has_prototype_slot condition once the broker is
// always enabled.
if (!function.map().has_prototype_slot() || !function.has_prototype() ||
function.PrototypeRequiresRuntimeLookup()) {
return NoChange();
}
+
ObjectRef prototype = dependencies()->DependOnPrototypeProperty(function);
Node* prototype_constant = jsgraph()->Constant(prototype);
@@ -656,7 +668,7 @@ Reduction JSNativeContextSpecialization::ReduceJSPromiseResolve(Node* node) {
// Check if the {constructor} is the %Promise% function.
HeapObjectMatcher m(constructor);
if (!m.HasValue() ||
- !m.Ref(broker()).equals(broker()->native_context().promise_function())) {
+ !m.Ref(broker()).equals(native_context().promise_function())) {
return NoChange();
}
@@ -680,7 +692,6 @@ Reduction JSNativeContextSpecialization::ReduceJSPromiseResolve(Node* node) {
// ES section #sec-promise-resolve-functions
Reduction JSNativeContextSpecialization::ReduceJSResolvePromise(Node* node) {
- DisallowHeapAccessIf no_heap_access(FLAG_concurrent_inlining);
DCHECK_EQ(IrOpcode::kJSResolvePromise, node->opcode());
Node* promise = NodeProperties::GetValueInput(node, 0);
Node* resolution = NodeProperties::GetValueInput(node, 1);
@@ -705,7 +716,9 @@ Reduction JSNativeContextSpecialization::ReduceJSResolvePromise(Node* node) {
// Obtain pre-computed access infos from the broker.
for (auto map : resolution_maps) {
MapRef map_ref(broker(), map);
- access_infos.push_back(broker()->GetAccessInfoForLoadingThen(map_ref));
+ access_infos.push_back(broker()->GetPropertyAccessInfo(
+ map_ref, NameRef(broker(), isolate()->factory()->then_string()),
+ AccessMode::kLoad));
}
}
PropertyAccessInfo access_info =
@@ -948,7 +961,7 @@ Reduction JSNativeContextSpecialization::ReduceGlobalAccess(
} else {
// Check that the {value} is a Smi.
value = effect = graph()->NewNode(
- simplified()->CheckSmi(VectorSlotPair()), value, effect, control);
+ simplified()->CheckSmi(FeedbackSource()), value, effect, control);
property_cell_value_type = Type::SignedSmall();
representation = MachineType::RepCompressedTaggedSigned();
}
@@ -978,70 +991,85 @@ Reduction JSNativeContextSpecialization::ReduceGlobalAccess(
}
Reduction JSNativeContextSpecialization::ReduceJSLoadGlobal(Node* node) {
- DisallowHeapAccessIf no_heap_acess(FLAG_concurrent_inlining);
DCHECK_EQ(IrOpcode::kJSLoadGlobal, node->opcode());
LoadGlobalParameters const& p = LoadGlobalParametersOf(node->op());
if (!p.feedback().IsValid()) return NoChange();
- FeedbackSource source(p.feedback());
- // TODO(neis): Make consistent with other feedback processing code.
- GlobalAccessFeedback const* processed =
- FLAG_concurrent_inlining
- ? broker()->GetGlobalAccessFeedback(source)
- : broker()->ProcessFeedbackForGlobalAccess(source);
- if (processed == nullptr) return NoChange();
+ ProcessedFeedback const& processed =
+ broker()->GetFeedbackForGlobalAccess(FeedbackSource(p.feedback()));
+ if (processed.IsInsufficient()) return NoChange();
- if (processed->IsScriptContextSlot()) {
+ GlobalAccessFeedback const& feedback = processed.AsGlobalAccess();
+ if (feedback.IsScriptContextSlot()) {
Node* effect = NodeProperties::GetEffectInput(node);
- Node* script_context = jsgraph()->Constant(processed->script_context());
+ Node* script_context = jsgraph()->Constant(feedback.script_context());
Node* value = effect =
- graph()->NewNode(javascript()->LoadContext(0, processed->slot_index(),
- processed->immutable()),
+ graph()->NewNode(javascript()->LoadContext(0, feedback.slot_index(),
+ feedback.immutable()),
script_context, effect);
ReplaceWithValue(node, value, effect);
return Replace(value);
+ } else if (feedback.IsPropertyCell()) {
+ return ReduceGlobalAccess(node, nullptr, nullptr,
+ NameRef(broker(), p.name()), AccessMode::kLoad,
+ nullptr, feedback.property_cell());
+ } else {
+ DCHECK(feedback.IsMegamorphic());
+ return NoChange();
}
-
- CHECK(processed->IsPropertyCell());
- return ReduceGlobalAccess(node, nullptr, nullptr, NameRef(broker(), p.name()),
- AccessMode::kLoad, nullptr,
- processed->property_cell());
}
Reduction JSNativeContextSpecialization::ReduceJSStoreGlobal(Node* node) {
- DisallowHeapAccessIf no_heap_acess(FLAG_concurrent_inlining);
DCHECK_EQ(IrOpcode::kJSStoreGlobal, node->opcode());
Node* value = NodeProperties::GetValueInput(node, 0);
-
StoreGlobalParameters const& p = StoreGlobalParametersOf(node->op());
if (!p.feedback().IsValid()) return NoChange();
- FeedbackSource source(p.feedback());
- GlobalAccessFeedback const* processed =
- FLAG_concurrent_inlining
- ? broker()->GetGlobalAccessFeedback(source)
- : broker()->ProcessFeedbackForGlobalAccess(source);
- if (processed == nullptr) return NoChange();
+ ProcessedFeedback const& processed =
+ broker()->GetFeedbackForGlobalAccess(FeedbackSource(p.feedback()));
+ if (processed.IsInsufficient()) return NoChange();
- if (processed->IsScriptContextSlot()) {
- if (processed->immutable()) return NoChange();
+ GlobalAccessFeedback const& feedback = processed.AsGlobalAccess();
+ if (feedback.IsScriptContextSlot()) {
+ if (feedback.immutable()) return NoChange();
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
- Node* script_context = jsgraph()->Constant(processed->script_context());
+ Node* script_context = jsgraph()->Constant(feedback.script_context());
effect =
- graph()->NewNode(javascript()->StoreContext(0, processed->slot_index()),
+ graph()->NewNode(javascript()->StoreContext(0, feedback.slot_index()),
value, script_context, effect, control);
ReplaceWithValue(node, value, effect, control);
return Replace(value);
- }
-
- if (processed->IsPropertyCell()) {
+ } else if (feedback.IsPropertyCell()) {
return ReduceGlobalAccess(node, nullptr, value, NameRef(broker(), p.name()),
AccessMode::kStore, nullptr,
- processed->property_cell());
+ feedback.property_cell());
+ } else {
+ DCHECK(feedback.IsMegamorphic());
+ return NoChange();
}
+}
- UNREACHABLE();
+void JSNativeContextSpecialization::FilterMapsAndGetPropertyAccessInfos(
+ NamedAccessFeedback const& feedback, AccessMode access_mode, Node* receiver,
+ Node* effect, ZoneVector<PropertyAccessInfo>* access_infos) {
+ ZoneVector<Handle<Map>> receiver_maps(zone());
+
+ // Either infer maps from the graph or use the feedback.
+ if (!InferReceiverMaps(receiver, effect, &receiver_maps)) {
+ receiver_maps = feedback.maps();
+ }
+ RemoveImpossibleReceiverMaps(receiver, &receiver_maps);
+
+ for (Handle<Map> map_handle : receiver_maps) {
+ MapRef map(broker(), map_handle);
+ if (map.is_deprecated()) continue;
+ PropertyAccessInfo access_info = broker()->GetPropertyAccessInfo(
+ map, feedback.name(), access_mode, dependencies(),
+ FLAG_concurrent_inlining ? SerializationPolicy::kAssumeSerialized
+ : SerializationPolicy::kSerializeIfNeeded);
+ access_infos->push_back(access_info);
+ }
}
Reduction JSNativeContextSpecialization::ReduceNamedAccess(
@@ -1052,18 +1080,23 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
node->opcode() == IrOpcode::kJSLoadProperty ||
node->opcode() == IrOpcode::kJSStoreProperty ||
node->opcode() == IrOpcode::kJSStoreNamedOwn ||
- node->opcode() == IrOpcode::kJSHasProperty);
+ node->opcode() == IrOpcode::kJSStoreDataPropertyInLiteral ||
+ node->opcode() == IrOpcode::kJSHasProperty ||
+ node->opcode() == IrOpcode::kJSGetIterator);
Node* receiver = NodeProperties::GetValueInput(node, 0);
Node* context = NodeProperties::GetContextInput(node);
Node* frame_state = NodeProperties::GetFrameStateInput(node);
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
+ ZoneVector<PropertyAccessInfo> access_infos_for_feedback(zone());
ZoneVector<PropertyAccessInfo> access_infos(zone());
+ FilterMapsAndGetPropertyAccessInfos(feedback, access_mode, receiver, effect,
+ &access_infos_for_feedback);
AccessInfoFactory access_info_factory(broker(), dependencies(),
graph()->zone());
if (!access_info_factory.FinalizePropertyAccessInfos(
- feedback.access_infos(), access_mode, &access_infos)) {
+ access_infos_for_feedback, access_mode, &access_infos)) {
return NoChange();
}
@@ -1072,7 +1105,7 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
// to the current native context's global object instead.
if (access_infos.size() == 1 && access_infos[0].receiver_maps().size() == 1) {
MapRef receiver_map(broker(), access_infos[0].receiver_maps()[0]);
- if (receiver_map.IsMapOfCurrentGlobalProxy()) {
+ if (receiver_map.IsMapOfTargetGlobalProxy()) {
return ReduceGlobalAccess(node, receiver, value, feedback.name(),
access_mode, key);
}
@@ -1318,7 +1351,6 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccessFromNexus(
}
Reduction JSNativeContextSpecialization::ReduceJSLoadNamed(Node* node) {
- DisallowHeapAccessIf no_heap_access(FLAG_concurrent_inlining);
DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode());
NamedAccess const& p = NamedAccessOf(node->op());
Node* const receiver = NodeProperties::GetValueInput(node, 0);
@@ -1332,9 +1364,7 @@ Reduction JSNativeContextSpecialization::ReduceJSLoadNamed(Node* node) {
name.equals(ObjectRef(broker(), factory()->prototype_string()))) {
// Optimize "prototype" property of functions.
JSFunctionRef function = object.AsJSFunction();
- if (!FLAG_concurrent_inlining) {
- function.Serialize();
- } else if (!function.serialized()) {
+ if (FLAG_concurrent_inlining && !function.serialized()) {
TRACE_BROKER_MISSING(broker(), "data for function " << function);
return NoChange();
}
@@ -1363,8 +1393,16 @@ Reduction JSNativeContextSpecialization::ReduceJSLoadNamed(Node* node) {
AccessMode::kLoad);
}
+Reduction JSNativeContextSpecialization::ReduceJSGetIterator(Node* node) {
+ DCHECK_EQ(IrOpcode::kJSGetIterator, node->opcode());
+ PropertyAccess const& p = PropertyAccessOf(node->op());
+ NameRef name(broker(), factory()->iterator_symbol());
+
+ return ReducePropertyAccess(node, nullptr, name, jsgraph()->Dead(),
+ FeedbackSource(p.feedback()), AccessMode::kLoad);
+}
+
Reduction JSNativeContextSpecialization::ReduceJSStoreNamed(Node* node) {
- DisallowHeapAccessIf no_heap_access(FLAG_concurrent_inlining);
DCHECK_EQ(IrOpcode::kJSStoreNamed, node->opcode());
NamedAccess const& p = NamedAccessOf(node->op());
Node* const value = NodeProperties::GetValueInput(node, 1);
@@ -1376,7 +1414,6 @@ Reduction JSNativeContextSpecialization::ReduceJSStoreNamed(Node* node) {
}
Reduction JSNativeContextSpecialization::ReduceJSStoreNamedOwn(Node* node) {
- DisallowHeapAccessIf no_heap_access(FLAG_concurrent_inlining);
DCHECK_EQ(IrOpcode::kJSStoreNamedOwn, node->opcode());
StoreNamedOwnParameters const& p = StoreNamedOwnParametersOf(node->op());
Node* const value = NodeProperties::GetValueInput(node, 1);
@@ -1401,7 +1438,7 @@ Reduction JSNativeContextSpecialization::ReduceElementAccessOnString(
// Ensure that the {receiver} is actually a String.
receiver = effect = graph()->NewNode(
- simplified()->CheckString(VectorSlotPair()), receiver, effect, control);
+ simplified()->CheckString(FeedbackSource()), receiver, effect, control);
// Determine the {receiver} length.
Node* length = graph()->NewNode(simplified()->StringLength(), receiver);
@@ -1428,13 +1465,50 @@ base::Optional<JSTypedArrayRef> GetTypedArrayConstant(JSHeapBroker* broker,
}
} // namespace
+void JSNativeContextSpecialization::RemoveImpossibleReceiverMaps(
+ Node* receiver, ZoneVector<Handle<Map>>* receiver_maps) const {
+ base::Optional<MapRef> root_map = InferReceiverRootMap(receiver);
+ if (root_map.has_value()) {
+ DCHECK(!root_map->is_abandoned_prototype_map());
+ receiver_maps->erase(
+ std::remove_if(receiver_maps->begin(), receiver_maps->end(),
+ [root_map, this](Handle<Map> map) {
+ MapRef map_ref(broker(), map);
+ return map_ref.is_abandoned_prototype_map() ||
+ (map_ref.FindRootMap().has_value() &&
+ !map_ref.FindRootMap()->equals(*root_map));
+ }),
+ receiver_maps->end());
+ }
+}
+
+// Possibly refine the feedback using inferred map information from the graph.
+ElementAccessFeedback const&
+JSNativeContextSpecialization::TryRefineElementAccessFeedback(
+ ElementAccessFeedback const& feedback, Node* receiver, Node* effect) const {
+ AccessMode access_mode = feedback.keyed_mode().access_mode();
+ bool use_inference =
+ access_mode == AccessMode::kLoad || access_mode == AccessMode::kHas;
+ if (!use_inference) return feedback;
+
+ ZoneVector<Handle<Map>> inferred_maps(zone());
+ if (!InferReceiverMaps(receiver, effect, &inferred_maps)) return feedback;
+
+ RemoveImpossibleReceiverMaps(receiver, &inferred_maps);
+ // TODO(neis): After Refine, the resulting feedback can still contain
+ // impossible maps when a target is kept only because more than one of its
+ // sources was inferred. Think of a way to completely rule out impossible
+ // maps.
+ return feedback.Refine(inferred_maps, zone());
+}
+
Reduction JSNativeContextSpecialization::ReduceElementAccess(
Node* node, Node* index, Node* value,
- ElementAccessFeedback const& processed) {
- DisallowHeapAccessIf no_heap_access(FLAG_concurrent_inlining);
+ ElementAccessFeedback const& feedback) {
DCHECK(node->opcode() == IrOpcode::kJSLoadProperty ||
node->opcode() == IrOpcode::kJSStoreProperty ||
node->opcode() == IrOpcode::kJSStoreInArrayLiteral ||
+ node->opcode() == IrOpcode::kJSStoreDataPropertyInLiteral ||
node->opcode() == IrOpcode::kJSHasProperty);
Node* receiver = NodeProperties::GetValueInput(node, 0);
@@ -1443,30 +1517,34 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
Node* frame_state =
NodeProperties::FindFrameStateBefore(node, jsgraph()->Dead());
- AccessMode access_mode = processed.keyed_mode.access_mode();
+ // TODO(neis): It's odd that we do optimizations below that don't really care
+ // about the feedback, but we don't do them when the feedback is megamorphic.
+ if (feedback.transition_groups().empty()) return NoChange();
+
+ ElementAccessFeedback const& refined_feedback =
+ TryRefineElementAccessFeedback(feedback, receiver, effect);
+
+ AccessMode access_mode = refined_feedback.keyed_mode().access_mode();
if ((access_mode == AccessMode::kLoad || access_mode == AccessMode::kHas) &&
receiver->opcode() == IrOpcode::kHeapConstant) {
- Reduction reduction = ReduceKeyedLoadFromHeapConstant(
- node, index, access_mode, processed.keyed_mode.load_mode());
+ Reduction reduction = ReduceElementLoadFromHeapConstant(
+ node, index, access_mode, refined_feedback.keyed_mode().load_mode());
if (reduction.Changed()) return reduction;
}
- if (HasOnlyStringMaps(broker(), processed.receiver_maps)) {
- DCHECK(processed.transitions.empty());
+ if (!refined_feedback.transition_groups().empty() &&
+ refined_feedback.HasOnlyStringMaps(broker())) {
return ReduceElementAccessOnString(node, index, value,
- processed.keyed_mode);
+ refined_feedback.keyed_mode());
}
- // Compute element access infos for the receiver maps.
AccessInfoFactory access_info_factory(broker(), dependencies(),
graph()->zone());
ZoneVector<ElementAccessInfo> access_infos(zone());
- if (!access_info_factory.ComputeElementAccessInfos(processed, access_mode,
- &access_infos)) {
+ if (!access_info_factory.ComputeElementAccessInfos(refined_feedback,
+ &access_infos) ||
+ access_infos.empty()) {
return NoChange();
- } else if (access_infos.empty()) {
- return ReduceSoftDeoptimize(
- node, DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess);
}
// For holey stores or growing stores, we need to check that the prototype
@@ -1485,7 +1563,7 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
// then we need to check that all prototypes have stable maps with
// fast elements (and we need to guard against changes to that below).
if ((IsHoleyOrDictionaryElementsKind(receiver_map.elements_kind()) ||
- IsGrowStoreMode(processed.keyed_mode.store_mode())) &&
+ IsGrowStoreMode(feedback.keyed_mode().store_mode())) &&
!receiver_map.HasOnlyStablePrototypesWithFastElements(
&prototype_maps)) {
return NoChange();
@@ -1514,9 +1592,7 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
base::Optional<JSTypedArrayRef> typed_array =
GetTypedArrayConstant(broker(), receiver);
if (typed_array.has_value()) {
- if (!FLAG_concurrent_inlining) {
- typed_array->Serialize();
- } else if (!typed_array->serialized()) {
+ if (FLAG_concurrent_inlining && !typed_array->serialized()) {
TRACE_BROKER_MISSING(broker(), "data for typed array " << *typed_array);
return NoChange();
}
@@ -1558,7 +1634,7 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
// Access the actual element.
ValueEffectControl continuation =
BuildElementAccess(receiver, index, value, effect, control, access_info,
- processed.keyed_mode);
+ feedback.keyed_mode());
value = continuation.value();
effect = continuation.effect();
control = continuation.control();
@@ -1625,7 +1701,7 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
// Access the actual element.
ValueEffectControl continuation =
BuildElementAccess(this_receiver, this_index, this_value, this_effect,
- this_control, access_info, processed.keyed_mode);
+ this_control, access_info, feedback.keyed_mode());
values.push_back(continuation.value());
effects.push_back(continuation.effect());
controls.push_back(continuation.control());
@@ -1658,7 +1734,7 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
return Replace(value);
}
-Reduction JSNativeContextSpecialization::ReduceKeyedLoadFromHeapConstant(
+Reduction JSNativeContextSpecialization::ReduceElementLoadFromHeapConstant(
Node* node, Node* key, AccessMode access_mode,
KeyedAccessLoadMode load_mode) {
DCHECK(node->opcode() == IrOpcode::kJSLoadProperty ||
@@ -1733,67 +1809,35 @@ Reduction JSNativeContextSpecialization::ReduceKeyedLoadFromHeapConstant(
Reduction JSNativeContextSpecialization::ReducePropertyAccess(
Node* node, Node* key, base::Optional<NameRef> static_name, Node* value,
FeedbackSource const& source, AccessMode access_mode) {
+ DisallowHeapAccessIf disallow_heap_access(FLAG_concurrent_inlining);
+
DCHECK_EQ(key == nullptr, static_name.has_value());
DCHECK(node->opcode() == IrOpcode::kJSLoadProperty ||
node->opcode() == IrOpcode::kJSStoreProperty ||
node->opcode() == IrOpcode::kJSStoreInArrayLiteral ||
+ node->opcode() == IrOpcode::kJSStoreDataPropertyInLiteral ||
node->opcode() == IrOpcode::kJSHasProperty ||
node->opcode() == IrOpcode::kJSLoadNamed ||
node->opcode() == IrOpcode::kJSStoreNamed ||
- node->opcode() == IrOpcode::kJSStoreNamedOwn);
-
- Node* receiver = NodeProperties::GetValueInput(node, 0);
- Node* effect = NodeProperties::GetEffectInput(node);
-
- ProcessedFeedback const* processed = nullptr;
- if (FLAG_concurrent_inlining) {
- processed = broker()->GetFeedback(source);
- // TODO(neis): Infer maps from the graph and consolidate with feedback/hints
- // and filter impossible candidates based on inferred root map.
- } else {
- // TODO(neis): Try to unify this with the similar code in the serializer.
- FeedbackNexus nexus(source.vector, source.slot);
- if (nexus.ic_state() == UNINITIALIZED) {
- processed = new (zone()) InsufficientFeedback();
- } else {
- MapHandles receiver_maps;
- if (!ExtractReceiverMaps(receiver, effect, nexus, &receiver_maps)) {
- processed = new (zone()) InsufficientFeedback();
- } else if (!receiver_maps.empty()) {
- base::Optional<NameRef> name = static_name.has_value()
- ? static_name
- : broker()->GetNameFeedback(nexus);
- if (name.has_value()) {
- ZoneVector<PropertyAccessInfo> access_infos(zone());
- AccessInfoFactory access_info_factory(broker(), dependencies(),
- graph()->zone());
- access_info_factory.ComputePropertyAccessInfos(
- receiver_maps, name->object(), access_mode, &access_infos);
- processed = new (zone()) NamedAccessFeedback(*name, access_infos);
- } else if (nexus.GetKeyType() == ELEMENT &&
- MEGAMORPHIC != nexus.ic_state()) {
- processed = broker()->ProcessFeedbackMapsForElementAccess(
- receiver_maps, KeyedAccessMode::FromNexus(nexus));
- }
- }
- }
- }
+ node->opcode() == IrOpcode::kJSStoreNamedOwn ||
+ node->opcode() == IrOpcode::kJSGetIterator);
+ DCHECK_GE(node->op()->ControlOutputCount(), 1);
- if (processed == nullptr) return NoChange();
- switch (processed->kind()) {
+ ProcessedFeedback const& feedback =
+ broker()->GetFeedbackForPropertyAccess(source, access_mode, static_name);
+ switch (feedback.kind()) {
case ProcessedFeedback::kInsufficient:
return ReduceSoftDeoptimize(
node,
DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess);
case ProcessedFeedback::kNamedAccess:
- return ReduceNamedAccess(node, value, *processed->AsNamedAccess(),
+ return ReduceNamedAccess(node, value, feedback.AsNamedAccess(),
access_mode, key);
case ProcessedFeedback::kElementAccess:
- CHECK_EQ(processed->AsElementAccess()->keyed_mode.access_mode(),
- access_mode);
- return ReduceElementAccess(node, key, value,
- *processed->AsElementAccess());
- case ProcessedFeedback::kGlobalAccess:
+ DCHECK_EQ(feedback.AsElementAccess().keyed_mode().access_mode(),
+ access_mode);
+ return ReduceElementAccess(node, key, value, feedback.AsElementAccess());
+ default:
UNREACHABLE();
}
}
@@ -1807,7 +1851,7 @@ Reduction JSNativeContextSpecialization::ReduceSoftDeoptimize(
Node* frame_state =
NodeProperties::FindFrameStateBefore(node, jsgraph()->Dead());
Node* deoptimize = graph()->NewNode(
- common()->Deoptimize(DeoptimizeKind::kSoft, reason, VectorSlotPair()),
+ common()->Deoptimize(DeoptimizeKind::kSoft, reason, FeedbackSource()),
frame_state, effect, control);
// TODO(bmeurer): This should be on the AdvancedReducer somehow.
NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
@@ -1818,7 +1862,6 @@ Reduction JSNativeContextSpecialization::ReduceSoftDeoptimize(
}
Reduction JSNativeContextSpecialization::ReduceJSHasProperty(Node* node) {
- DisallowHeapAccessIf no_heap_access(FLAG_concurrent_inlining);
DCHECK_EQ(IrOpcode::kJSHasProperty, node->opcode());
PropertyAccess const& p = PropertyAccessOf(node->op());
Node* key = NodeProperties::GetValueInput(node, 1);
@@ -1936,7 +1979,6 @@ Reduction JSNativeContextSpecialization::ReduceJSLoadPropertyWithEnumeratedKey(
}
Reduction JSNativeContextSpecialization::ReduceJSLoadProperty(Node* node) {
- DisallowHeapAccessIf no_heap_acess(FLAG_concurrent_inlining);
DCHECK_EQ(IrOpcode::kJSLoadProperty, node->opcode());
PropertyAccess const& p = PropertyAccessOf(node->op());
Node* name = NodeProperties::GetValueInput(node, 1);
@@ -1953,7 +1995,6 @@ Reduction JSNativeContextSpecialization::ReduceJSLoadProperty(Node* node) {
}
Reduction JSNativeContextSpecialization::ReduceJSStoreProperty(Node* node) {
- DisallowHeapAccessIf no_heap_access(FLAG_concurrent_inlining);
DCHECK_EQ(IrOpcode::kJSStoreProperty, node->opcode());
PropertyAccess const& p = PropertyAccessOf(node->op());
Node* const key = NodeProperties::GetValueInput(node, 1);
@@ -1975,7 +2016,7 @@ Node* JSNativeContextSpecialization::InlinePropertyGetterCall(
Node* value;
if (constant.IsJSFunction()) {
value = *effect = *control = graph()->NewNode(
- jsgraph()->javascript()->Call(2, CallFrequency(), VectorSlotPair(),
+ jsgraph()->javascript()->Call(2, CallFrequency(), FeedbackSource(),
ConvertReceiverMode::kNotNullOrUndefined),
target, receiver, context, frame_state, *effect, *control);
} else {
@@ -2012,7 +2053,7 @@ void JSNativeContextSpecialization::InlinePropertySetterCall(
// Introduce the call to the setter function.
if (constant.IsJSFunction()) {
*effect = *control = graph()->NewNode(
- jsgraph()->javascript()->Call(3, CallFrequency(), VectorSlotPair(),
+ jsgraph()->javascript()->Call(3, CallFrequency(), FeedbackSource(),
ConvertReceiverMode::kNotNullOrUndefined),
target, receiver, value, context, frame_state, *effect, *control);
} else {
@@ -2197,12 +2238,10 @@ JSNativeContextSpecialization::BuildPropertyStore(
Node* storage = receiver;
if (!field_index.is_inobject()) {
storage = effect = graph()->NewNode(
- simplified()->LoadField(AccessBuilder::ForJSObjectPropertiesOrHash()),
+ simplified()->LoadField(
+ AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer()),
storage, effect, control);
}
- PropertyConstness constness = access_info.IsDataConstant()
- ? PropertyConstness::kConst
- : PropertyConstness::kMutable;
bool store_to_existing_constant_field = access_info.IsDataConstant() &&
access_mode == AccessMode::kStore &&
!access_info.HasTransitionMap();
@@ -2215,24 +2254,25 @@ JSNativeContextSpecialization::BuildPropertyStore(
MachineType::TypeForRepresentation(field_representation),
kFullWriteBarrier,
LoadSensitivity::kUnsafe,
- constness};
+ access_info.GetConstFieldInfo(),
+ access_mode == AccessMode::kStoreInLiteral};
switch (field_representation) {
case MachineRepresentation::kFloat64: {
value = effect =
- graph()->NewNode(simplified()->CheckNumber(VectorSlotPair()), value,
+ graph()->NewNode(simplified()->CheckNumber(FeedbackSource()), value,
effect, control);
if (!field_index.is_inobject() || !FLAG_unbox_double_fields) {
if (access_info.HasTransitionMap()) {
- // Allocate a MutableHeapNumber for the new property.
+ // Allocate a HeapNumber for the new property.
AllocationBuilder a(jsgraph(), effect, control);
a.Allocate(HeapNumber::kSize, AllocationType::kYoung,
Type::OtherInternal());
a.Store(AccessBuilder::ForMap(),
- factory()->mutable_heap_number_map());
+ MapRef(broker(), factory()->heap_number_map()));
FieldAccess value_field_access =
AccessBuilder::ForHeapNumberValue();
- value_field_access.constness = field_access.constness;
+ value_field_access.const_field_info = field_access.const_field_info;
a.Store(value_field_access, value);
value = effect = a.Finish();
@@ -2241,7 +2281,7 @@ JSNativeContextSpecialization::BuildPropertyStore(
MachineType::TypeCompressedTaggedPointer();
field_access.write_barrier_kind = kPointerWriteBarrier;
} else {
- // We just store directly to the MutableHeapNumber.
+ // We just store directly to the HeapNumber.
FieldAccess const storage_access = {
kTaggedBase,
field_index.offset(),
@@ -2251,7 +2291,8 @@ JSNativeContextSpecialization::BuildPropertyStore(
MachineType::TypeCompressedTaggedPointer(),
kPointerWriteBarrier,
LoadSensitivity::kUnsafe,
- constness};
+ access_info.GetConstFieldInfo(),
+ access_mode == AccessMode::kStoreInLiteral};
storage = effect =
graph()->NewNode(simplified()->LoadField(storage_access),
storage, effect, control);
@@ -2300,7 +2341,7 @@ JSNativeContextSpecialization::BuildPropertyStore(
if (field_representation == MachineRepresentation::kTaggedSigned ||
field_representation == MachineRepresentation::kCompressedSigned) {
value = effect = graph()->NewNode(
- simplified()->CheckSmi(VectorSlotPair()), value, effect, control);
+ simplified()->CheckSmi(FeedbackSource()), value, effect, control);
field_access.write_barrier_kind = kNoWriteBarrier;
} else if (field_representation ==
@@ -2356,7 +2397,7 @@ JSNativeContextSpecialization::BuildPropertyStore(
storage, value, effect, control);
// Atomically switch to the new properties below.
- field_access = AccessBuilder::ForJSObjectPropertiesOrHash();
+ field_access = AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer();
value = storage;
storage = receiver;
}
@@ -2382,80 +2423,18 @@ JSNativeContextSpecialization::BuildPropertyStore(
Reduction JSNativeContextSpecialization::ReduceJSStoreDataPropertyInLiteral(
Node* node) {
DCHECK_EQ(IrOpcode::kJSStoreDataPropertyInLiteral, node->opcode());
-
FeedbackParameter const& p = FeedbackParameterOf(node->op());
+ Node* const key = NodeProperties::GetValueInput(node, 1);
+ Node* const value = NodeProperties::GetValueInput(node, 2);
if (!p.feedback().IsValid()) return NoChange();
-
- FeedbackNexus 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());
-
- Map map = nexus.GetFirstMap();
- if (map.is_null()) {
- // Maps are weakly held in the type feedback vector, we may not have one.
- return NoChange();
- }
-
- Handle<Map> receiver_map(map, isolate());
- if (!Map::TryUpdate(isolate(), receiver_map).ToHandle(&receiver_map))
- return NoChange();
-
- NameRef cached_name(
- broker(),
- handle(Name::cast(nexus.GetFeedbackExtra()->GetHeapObjectAssumeStrong()),
- isolate()));
-
- AccessInfoFactory access_info_factory(broker(), dependencies(),
- graph()->zone());
- PropertyAccessInfo access_info =
- access_info_factory.ComputePropertyAccessInfo(
- receiver_map, cached_name.object(), AccessMode::kStoreInLiteral);
- if (access_info.IsInvalid()) return NoChange();
- access_info.RecordDependencies(dependencies());
-
- Node* receiver = NodeProperties::GetValueInput(node, 0);
- Node* effect = NodeProperties::GetEffectInput(node);
- Node* control = NodeProperties::GetControlInput(node);
-
- // Monomorphic property access.
- PropertyAccessBuilder access_builder(jsgraph(), broker(), dependencies());
- access_builder.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()->Constant(cached_name));
- effect = graph()->NewNode(simplified()->CheckIf(DeoptimizeReason::kWrongName),
- 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,
- nullptr, access_info, AccessMode::kStoreInLiteral);
- value = continuation.value();
- effect = continuation.effect();
- control = continuation.control();
-
- ReplaceWithValue(node, value, effect, control);
- return Replace(value);
+ return ReducePropertyAccess(node, key, base::nullopt, value,
+ FeedbackSource(p.feedback()),
+ AccessMode::kStoreInLiteral);
}
Reduction JSNativeContextSpecialization::ReduceJSStoreInArrayLiteral(
Node* node) {
- DisallowHeapAccessIf no_heap_access(FLAG_concurrent_inlining);
DCHECK_EQ(IrOpcode::kJSStoreInArrayLiteral, node->opcode());
FeedbackParameter const& p = FeedbackParameterOf(node->op());
Node* const index = NodeProperties::GetValueInput(node, 1);
@@ -2591,7 +2570,7 @@ JSNativeContextSpecialization::BuildElementAccess(
// bounds check below and just skip the property access if it's out of
// bounds for the {receiver}.
index = effect = graph()->NewNode(
- simplified()->CheckSmi(VectorSlotPair()), index, effect, control);
+ simplified()->CheckSmi(FeedbackSource()), index, effect, control);
// Cast the {index} to Unsigned32 range, so that the bounds checks
// below are performed on unsigned values, which means that all the
@@ -2600,7 +2579,7 @@ JSNativeContextSpecialization::BuildElementAccess(
} else {
// Check that the {index} is in the valid range for the {receiver}.
index = effect =
- graph()->NewNode(simplified()->CheckBounds(VectorSlotPair()), index,
+ graph()->NewNode(simplified()->CheckBounds(FeedbackSource()), index,
length, effect, control);
}
@@ -2660,7 +2639,7 @@ JSNativeContextSpecialization::BuildElementAccess(
// and truncate it to a Number appropriately.
value = effect = graph()->NewNode(
simplified()->SpeculativeToNumber(
- NumberOperationHint::kNumberOrOddball, VectorSlotPair()),
+ NumberOperationHint::kNumberOrOddball, FeedbackSource()),
value, effect, control);
// Introduce the appropriate truncation for {value}. Currently we
@@ -2756,12 +2735,12 @@ JSNativeContextSpecialization::BuildElementAccess(
// bounds check below and just skip the store below if it's out of
// bounds for the {receiver}.
index = effect = graph()->NewNode(
- simplified()->CheckBounds(VectorSlotPair()), index,
+ simplified()->CheckBounds(FeedbackSource()), index,
jsgraph()->Constant(Smi::kMaxValue), effect, control);
} else {
// Check that the {index} is in the valid range for the {receiver}.
index = effect =
- graph()->NewNode(simplified()->CheckBounds(VectorSlotPair()), index,
+ graph()->NewNode(simplified()->CheckBounds(FeedbackSource()), index,
length, effect, control);
}
@@ -2825,7 +2804,7 @@ JSNativeContextSpecialization::BuildElementAccess(
// truncating.
vtrue = etrue = graph()->NewNode(
simplified()->CheckFloat64Hole(
- CheckFloat64HoleMode::kAllowReturnHole, VectorSlotPair()),
+ CheckFloat64HoleMode::kAllowReturnHole, FeedbackSource()),
vtrue, etrue, if_true);
}
}
@@ -2874,7 +2853,7 @@ JSNativeContextSpecialization::BuildElementAccess(
mode = CheckFloat64HoleMode::kAllowReturnHole;
}
value = effect = graph()->NewNode(
- simplified()->CheckFloat64Hole(mode, VectorSlotPair()), value,
+ simplified()->CheckFloat64Hole(mode, FeedbackSource()), value,
effect, control);
}
}
@@ -2905,7 +2884,7 @@ JSNativeContextSpecialization::BuildElementAccess(
Node* etrue = effect;
Node* checked = etrue =
- graph()->NewNode(simplified()->CheckBounds(VectorSlotPair()), index,
+ graph()->NewNode(simplified()->CheckBounds(FeedbackSource()), index,
length, etrue, if_true);
Node* element = etrue =
@@ -2936,7 +2915,7 @@ JSNativeContextSpecialization::BuildElementAccess(
} else {
etrue = graph()->NewNode(
simplified()->CheckFloat64Hole(
- CheckFloat64HoleMode::kNeverReturnHole, VectorSlotPair()),
+ CheckFloat64HoleMode::kNeverReturnHole, FeedbackSource()),
element, etrue, if_true);
}
@@ -2956,10 +2935,10 @@ JSNativeContextSpecialization::BuildElementAccess(
if (IsSmiElementsKind(elements_kind)) {
value = effect = graph()->NewNode(
- simplified()->CheckSmi(VectorSlotPair()), value, effect, control);
+ simplified()->CheckSmi(FeedbackSource()), value, effect, control);
} else if (IsDoubleElementsKind(elements_kind)) {
value = effect =
- graph()->NewNode(simplified()->CheckNumber(VectorSlotPair()), value,
+ graph()->NewNode(simplified()->CheckNumber(FeedbackSource()), value,
effect, control);
// Make sure we do not store signalling NaNs into double arrays.
value = graph()->NewNode(simplified()->NumberSilenceNaN(), value);
@@ -2994,7 +2973,7 @@ JSNativeContextSpecialization::BuildElementAccess(
: graph()->NewNode(simplified()->NumberAdd(), length,
jsgraph()->OneConstant());
index = effect =
- graph()->NewNode(simplified()->CheckBounds(VectorSlotPair()), index,
+ graph()->NewNode(simplified()->CheckBounds(FeedbackSource()), index,
limit, effect, control);
// Grow {elements} backing store if necessary.
@@ -3003,7 +2982,7 @@ JSNativeContextSpecialization::BuildElementAccess(
? GrowFastElementsMode::kDoubleElements
: GrowFastElementsMode::kSmiOrObjectElements;
elements = effect = graph()->NewNode(
- simplified()->MaybeGrowFastElements(mode, VectorSlotPair()),
+ simplified()->MaybeGrowFastElements(mode, FeedbackSource()),
receiver, elements, index, elements_length, effect, control);
// If we didn't grow {elements}, it might still be COW, in which case we
@@ -3063,7 +3042,7 @@ Node* JSNativeContextSpecialization::BuildIndexedStringLoad(
dependencies()->DependOnNoElementsProtector()) {
// Ensure that the {index} is a valid String length.
index = *effect = graph()->NewNode(
- simplified()->CheckBounds(VectorSlotPair()), index,
+ simplified()->CheckBounds(FeedbackSource()), index,
jsgraph()->Constant(String::kMaxLength), *effect, *control);
// Load the single character string from {receiver} or yield
@@ -3095,7 +3074,7 @@ Node* JSNativeContextSpecialization::BuildIndexedStringLoad(
} else {
// Ensure that {index} is less than {receiver} length.
index = *effect =
- graph()->NewNode(simplified()->CheckBounds(VectorSlotPair()), index,
+ graph()->NewNode(simplified()->CheckBounds(FeedbackSource()), index,
length, *effect, *control);
Node* masked_index = graph()->NewNode(simplified()->PoisonIndex(), index);
@@ -3196,7 +3175,6 @@ bool JSNativeContextSpecialization::CanTreatHoleAsUndefined(
// native contexts, as the global Array protector works isolate-wide).
for (Handle<Map> map : receiver_maps) {
MapRef receiver_map(broker(), map);
- if (!FLAG_concurrent_inlining) receiver_map.SerializePrototype();
ObjectRef receiver_prototype = receiver_map.prototype();
if (!receiver_prototype.IsJSObject() ||
!broker()->IsArrayOrObjectPrototype(receiver_prototype.AsJSObject())) {
@@ -3208,47 +3186,9 @@ bool JSNativeContextSpecialization::CanTreatHoleAsUndefined(
return dependencies()->DependOnNoElementsProtector();
}
-// Returns false iff we have insufficient feedback (uninitialized or obsolete).
-bool JSNativeContextSpecialization::ExtractReceiverMaps(
- Node* receiver, Node* effect, FeedbackNexus const& nexus,
- MapHandles* receiver_maps) {
- DCHECK(receiver_maps->empty());
- if (nexus.IsUninitialized()) return false;
-
- // See if we can infer a concrete type for the {receiver}. Solely relying on
- // the inference is not safe for keyed stores, because we would potentially
- // miss out on transitions that need to be performed.
- {
- FeedbackSlotKind kind = nexus.kind();
- bool use_inference =
- !IsKeyedStoreICKind(kind) && !IsStoreInArrayLiteralICKind(kind);
- if (use_inference && InferReceiverMaps(receiver, effect, receiver_maps)) {
- TryUpdateThenDropDeprecated(isolate(), receiver_maps);
- return true;
- }
- }
-
- if (nexus.ExtractMaps(receiver_maps) == 0) return true;
-
- // Try to filter impossible candidates based on inferred root map.
- Handle<Map> root_map;
- if (InferReceiverRootMap(receiver).ToHandle(&root_map)) {
- DCHECK(!root_map->is_abandoned_prototype_map());
- Isolate* isolate = this->isolate();
- receiver_maps->erase(
- std::remove_if(receiver_maps->begin(), receiver_maps->end(),
- [root_map, isolate](Handle<Map> map) {
- return map->is_abandoned_prototype_map() ||
- map->FindRootMap(isolate) != *root_map;
- }),
- receiver_maps->end());
- }
- TryUpdateThenDropDeprecated(isolate(), receiver_maps);
- return !receiver_maps->empty();
-}
-
bool JSNativeContextSpecialization::InferReceiverMaps(
- Node* receiver, Node* effect, MapHandles* receiver_maps) {
+ Node* receiver, Node* effect,
+ ZoneVector<Handle<Map>>* receiver_maps) const {
ZoneHandleSet<Map> maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMapsUnsafe(broker(), receiver, effect,
@@ -3273,21 +3213,24 @@ bool JSNativeContextSpecialization::InferReceiverMaps(
return false;
}
-MaybeHandle<Map> JSNativeContextSpecialization::InferReceiverRootMap(
- Node* receiver) {
+base::Optional<MapRef> JSNativeContextSpecialization::InferReceiverRootMap(
+ Node* receiver) const {
HeapObjectMatcher m(receiver);
if (m.HasValue()) {
- return handle(m.Value()->map().FindRootMap(isolate()), isolate());
+ MapRef map = m.Ref(broker()).map();
+ return map.FindRootMap();
} else if (m.IsJSCreate()) {
base::Optional<MapRef> initial_map =
NodeProperties::GetJSCreateMap(broker(), receiver);
if (initial_map.has_value()) {
- DCHECK_EQ(*initial_map->object(),
- initial_map->object()->FindRootMap(isolate()));
- return initial_map->object();
+ if (!initial_map->FindRootMap().has_value()) {
+ return base::nullopt;
+ }
+ DCHECK(initial_map->equals(*initial_map->FindRootMap()));
+ return *initial_map;
}
}
- return MaybeHandle<Map>();
+ return base::nullopt;
}
Graph* JSNativeContextSpecialization::graph() const {