Commit e7a33bd7 authored by Georg Neis's avatar Georg Neis Committed by Commit Bot

[turbofan] Collect Array and Object prototypes upfront.

As part of the standard objects serialization, collect the identities of
the Array prototype and the Object prototype from all native contexts.
This information is then be consulted at compile time instead of having
to call Isolate::IsInAnyContext (which accesses the heap).

Bug: v8:7790
Change-Id: I26a8271afadfce243a8032e4a012f249ce3c2a60
Reviewed-on: https://chromium-review.googlesource.com/c/1275815
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56599}
parent ce1ce547
......@@ -253,8 +253,9 @@ Reduction JSCallReducer::ReduceObjectConstructor(Node* node) {
Node* effect = NodeProperties::GetEffectInput(node);
// We can fold away the Object(x) call if |x| is definitely not a primitive.
if (NodeProperties::CanBePrimitive(isolate(), value, effect)) {
if (!NodeProperties::CanBeNullOrUndefined(isolate(), value, effect)) {
if (NodeProperties::CanBePrimitive(js_heap_broker(), value, effect)) {
if (!NodeProperties::CanBeNullOrUndefined(js_heap_broker(), value,
effect)) {
// Turn the {node} into a {JSToObject} call if we know that
// the {value} cannot be null or undefined.
NodeProperties::ReplaceValueInputs(node, value);
......@@ -295,7 +296,7 @@ Reduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) {
// If {arguments_list} cannot be null or undefined, we don't need
// to expand this {node} to control-flow.
if (!NodeProperties::CanBeNullOrUndefined(isolate(), arguments_list,
if (!NodeProperties::CanBeNullOrUndefined(js_heap_broker(), arguments_list,
effect)) {
// Massage the value inputs appropriately.
node->ReplaceInput(0, target);
......@@ -408,7 +409,7 @@ Reduction JSCallReducer::ReduceFunctionPrototypeBind(Node* node) {
// definitely a constructor or not a constructor.
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(isolate(), receiver, effect,
NodeProperties::InferReceiverMaps(js_heap_broker(), receiver, effect,
&receiver_maps);
if (result == NodeProperties::kNoReceiverMaps) return NoChange();
DCHECK_NE(0, receiver_maps.size());
......@@ -570,7 +571,7 @@ Reduction JSCallReducer::ReduceObjectGetPrototype(Node* node, Node* object) {
// Try to determine the {object} map.
ZoneHandleSet<Map> object_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(isolate(), object, effect,
NodeProperties::InferReceiverMaps(js_heap_broker(), object, effect,
&object_maps);
if (result != NodeProperties::kNoReceiverMaps) {
Handle<Map> candidate_map = object_maps[0];
......@@ -731,7 +732,7 @@ Reduction JSCallReducer::ReduceObjectPrototypeIsPrototypeOf(Node* node) {
// the ToObject step of Object.prototype.isPrototypeOf is a no-op).
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(isolate(), receiver, effect,
NodeProperties::InferReceiverMaps(js_heap_broker(), receiver, effect,
&receiver_maps);
if (result == NodeProperties::kNoReceiverMaps) return NoChange();
for (size_t i = 0; i < receiver_maps.size(); ++i) {
......@@ -1028,7 +1029,7 @@ Reduction JSCallReducer::ReduceArrayForEach(Node* node,
: jsgraph()->UndefinedConstant();
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(isolate(), receiver, effect,
NodeProperties::InferReceiverMaps(js_heap_broker(), receiver, effect,
&receiver_maps);
if (result == NodeProperties::kNoReceiverMaps) return NoChange();
......@@ -1218,7 +1219,7 @@ Reduction JSCallReducer::ReduceArrayReduce(Node* node,
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(isolate(), receiver, effect,
NodeProperties::InferReceiverMaps(js_heap_broker(), receiver, effect,
&receiver_maps);
if (result == NodeProperties::kNoReceiverMaps) return NoChange();
......@@ -1495,7 +1496,7 @@ Reduction JSCallReducer::ReduceArrayMap(Node* node,
: jsgraph()->UndefinedConstant();
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(isolate(), receiver, effect,
NodeProperties::InferReceiverMaps(js_heap_broker(), receiver, effect,
&receiver_maps);
if (result == NodeProperties::kNoReceiverMaps) return NoChange();
......@@ -1707,7 +1708,7 @@ Reduction JSCallReducer::ReduceArrayFilter(Node* node,
: jsgraph()->UndefinedConstant();
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(isolate(), receiver, effect,
NodeProperties::InferReceiverMaps(js_heap_broker(), receiver, effect,
&receiver_maps);
if (result == NodeProperties::kNoReceiverMaps) return NoChange();
......@@ -1990,7 +1991,7 @@ Reduction JSCallReducer::ReduceArrayFind(Node* node, ArrayFindVariant variant,
: jsgraph()->UndefinedConstant();
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(isolate(), receiver, effect,
NodeProperties::InferReceiverMaps(js_heap_broker(), receiver, effect,
&receiver_maps);
if (result == NodeProperties::kNoReceiverMaps) return NoChange();
......@@ -2305,7 +2306,7 @@ Reduction JSCallReducer::ReduceArrayEvery(Node* node,
: jsgraph()->UndefinedConstant();
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(isolate(), receiver, effect,
NodeProperties::InferReceiverMaps(js_heap_broker(), receiver, effect,
&receiver_maps);
if (result == NodeProperties::kNoReceiverMaps) return NoChange();
......@@ -2566,7 +2567,8 @@ Reduction JSCallReducer::ReduceArrayIndexOfIncludes(
}
Handle<Map> receiver_map;
if (!NodeProperties::GetMapWitness(isolate(), node).ToHandle(&receiver_map))
if (!NodeProperties::GetMapWitness(js_heap_broker(), node)
.ToHandle(&receiver_map))
return NoChange();
if (!CanInlineArrayIteratingBuiltin(isolate(), receiver_map))
......@@ -2652,7 +2654,7 @@ Reduction JSCallReducer::ReduceArraySome(Node* node,
: jsgraph()->UndefinedConstant();
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(isolate(), receiver, effect,
NodeProperties::InferReceiverMaps(js_heap_broker(), receiver, effect,
&receiver_maps);
if (result == NodeProperties::kNoReceiverMaps) return NoChange();
......@@ -2887,7 +2889,7 @@ Reduction JSCallReducer::ReduceCallApiFunction(
// callback based on those.
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(isolate(), receiver, effect,
NodeProperties::InferReceiverMaps(js_heap_broker(), receiver, effect,
&receiver_maps);
if (result == NodeProperties::kNoReceiverMaps) return NoChange();
for (size_t i = 0; i < receiver_maps.size(); ++i) {
......@@ -3303,7 +3305,8 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) {
// Update the JSCall operator on {node}.
ConvertReceiverMode const convert_mode =
NodeProperties::CanBeNullOrUndefined(isolate(), bound_this, effect)
NodeProperties::CanBeNullOrUndefined(js_heap_broker(), bound_this,
effect)
? ConvertReceiverMode::kAny
: ConvertReceiverMode::kNotNullOrUndefined;
NodeProperties::ChangeOp(
......@@ -4353,7 +4356,7 @@ Reduction JSCallReducer::ReduceArrayPrototypePush(Node* node) {
// Try to determine the {receiver} map(s).
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(isolate(), receiver, effect,
NodeProperties::InferReceiverMaps(js_heap_broker(), receiver, effect,
&receiver_maps);
if (result == NodeProperties::kNoReceiverMaps) return NoChange();
DCHECK_NE(0, receiver_maps.size());
......@@ -4465,7 +4468,7 @@ Reduction JSCallReducer::ReduceArrayPrototypePop(Node* node) {
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(isolate(), receiver, effect,
NodeProperties::InferReceiverMaps(js_heap_broker(), receiver, effect,
&receiver_maps);
if (result == NodeProperties::kNoReceiverMaps) return NoChange();
DCHECK_NE(0, receiver_maps.size());
......@@ -4584,7 +4587,7 @@ Reduction JSCallReducer::ReduceArrayPrototypeShift(Node* node) {
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(isolate(), receiver, effect,
NodeProperties::InferReceiverMaps(js_heap_broker(), receiver, effect,
&receiver_maps);
if (result == NodeProperties::kNoReceiverMaps) return NoChange();
DCHECK_NE(0, receiver_maps.size());
......@@ -4789,7 +4792,7 @@ Reduction JSCallReducer::ReduceArrayPrototypeSlice(Node* node) {
// Try to determine the {receiver} map.
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(isolate(), receiver, effect,
NodeProperties::InferReceiverMaps(js_heap_broker(), receiver, effect,
&receiver_maps);
if (result == NodeProperties::kNoReceiverMaps) return NoChange();
......@@ -4877,7 +4880,7 @@ Reduction JSCallReducer::ReduceArrayIterator(Node* node, IterationKind kind) {
// Check if we know that {receiver} is a valid JSReceiver.
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(isolate(), receiver, effect,
NodeProperties::InferReceiverMaps(js_heap_broker(), receiver, effect,
&receiver_maps);
if (result == NodeProperties::kNoReceiverMaps) return NoChange();
DCHECK_NE(0, receiver_maps.size());
......@@ -4898,14 +4901,14 @@ Reduction JSCallReducer::ReduceArrayIterator(Node* node, IterationKind kind) {
namespace {
bool InferIteratedObjectMaps(Isolate* isolate, Node* iterator,
bool InferIteratedObjectMaps(JSHeapBroker* broker, Node* iterator,
ZoneHandleSet<Map>* iterated_object_maps) {
DCHECK_EQ(IrOpcode::kJSCreateArrayIterator, iterator->opcode());
Node* iterated_object = NodeProperties::GetValueInput(iterator, 0);
Node* effect = NodeProperties::GetEffectInput(iterator);
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(isolate, iterated_object, effect,
NodeProperties::InferReceiverMaps(broker, iterated_object, effect,
iterated_object_maps);
return result != NodeProperties::kNoReceiverMaps;
}
......@@ -4932,7 +4935,8 @@ Reduction JSCallReducer::ReduceArrayIteratorPrototypeNext(Node* node) {
// Try to infer the [[IteratedObject]] maps from the {iterator}.
ZoneHandleSet<Map> iterated_object_maps;
if (!InferIteratedObjectMaps(isolate(), iterator, &iterated_object_maps)) {
if (!InferIteratedObjectMaps(js_heap_broker(), iterator,
&iterated_object_maps)) {
return NoChange();
}
DCHECK_NE(0, iterated_object_maps.size());
......@@ -5374,7 +5378,7 @@ Reduction JSCallReducer::ReduceStringIteratorPrototypeNext(Node* node) {
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
Node* context = NodeProperties::GetContextInput(node);
if (NodeProperties::HasInstanceTypeWitness(isolate(), receiver, effect,
if (NodeProperties::HasInstanceTypeWitness(js_heap_broker(), receiver, effect,
JS_STRING_ITERATOR_TYPE)) {
Node* string = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForJSStringIteratorString()),
......@@ -5783,7 +5787,7 @@ Reduction JSCallReducer::ReducePromisePrototypeCatch(Node* node) {
// Check if we know something about {receiver} already.
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(isolate(), receiver, effect,
NodeProperties::InferReceiverMaps(js_heap_broker(), receiver, effect,
&receiver_maps);
if (result == NodeProperties::kNoReceiverMaps) return NoChange();
DCHECK_NE(0, receiver_maps.size());
......@@ -5860,7 +5864,7 @@ Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) {
// Check if we know something about {receiver} already.
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(isolate(), receiver, effect,
NodeProperties::InferReceiverMaps(js_heap_broker(), receiver, effect,
&receiver_maps);
if (result == NodeProperties::kNoReceiverMaps) return NoChange();
DCHECK_NE(0, receiver_maps.size());
......@@ -6013,7 +6017,7 @@ Reduction JSCallReducer::ReducePromisePrototypeThen(Node* node) {
// Check if we know something about {receiver} already.
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult infer_receiver_maps_result =
NodeProperties::InferReceiverMaps(isolate(), receiver, effect,
NodeProperties::InferReceiverMaps(js_heap_broker(), receiver, effect,
&receiver_maps);
if (infer_receiver_maps_result == NodeProperties::kNoReceiverMaps) {
return NoChange();
......@@ -6082,7 +6086,7 @@ Reduction JSCallReducer::ReducePromiseResolveTrampoline(Node* node) {
// Check if we know something about {receiver} already.
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult infer_receiver_maps_result =
NodeProperties::InferReceiverMaps(isolate(), receiver, effect,
NodeProperties::InferReceiverMaps(js_heap_broker(), receiver, effect,
&receiver_maps);
if (infer_receiver_maps_result == NodeProperties::kNoReceiverMaps) {
return NoChange();
......@@ -6278,8 +6282,8 @@ Reduction JSCallReducer::ReduceMapPrototypeGet(Node* node) {
Node* control = NodeProperties::GetControlInput(node);
Node* key = NodeProperties::GetValueInput(node, 2);
if (!NodeProperties::HasInstanceTypeWitness(isolate(), receiver, effect,
JS_MAP_TYPE))
if (!NodeProperties::HasInstanceTypeWitness(js_heap_broker(), receiver,
effect, JS_MAP_TYPE))
return NoChange();
Node* table = effect = graph()->NewNode(
......@@ -6323,8 +6327,8 @@ Reduction JSCallReducer::ReduceMapPrototypeHas(Node* node) {
Node* control = NodeProperties::GetControlInput(node);
Node* key = NodeProperties::GetValueInput(node, 2);
if (!NodeProperties::HasInstanceTypeWitness(isolate(), receiver, effect,
JS_MAP_TYPE))
if (!NodeProperties::HasInstanceTypeWitness(js_heap_broker(), receiver,
effect, JS_MAP_TYPE))
return NoChange();
Node* table = effect = graph()->NewNode(
......@@ -6364,7 +6368,7 @@ Reduction JSCallReducer::ReduceCollectionIteration(
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
if (NodeProperties::HasInstanceTypeWitness(
isolate(), receiver, effect,
js_heap_broker(), receiver, effect,
InstanceTypeForCollectionKind(collection_kind))) {
Node* js_create_iterator = effect = graph()->NewNode(
javascript()->CreateCollectionIterator(collection_kind, iteration_kind),
......@@ -6382,7 +6386,7 @@ Reduction JSCallReducer::ReduceCollectionPrototypeSize(
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
if (NodeProperties::HasInstanceTypeWitness(
isolate(), receiver, effect,
js_heap_broker(), receiver, effect,
InstanceTypeForCollectionKind(collection_kind))) {
Node* table = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForJSCollectionTable()),
......@@ -6423,7 +6427,7 @@ Reduction JSCallReducer::ReduceCollectionIteratorPrototypeNext(
InstanceType receiver_instance_type;
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(isolate(), receiver, effect,
NodeProperties::InferReceiverMaps(js_heap_broker(), receiver, effect,
&receiver_maps);
if (result == NodeProperties::kNoReceiverMaps) return NoChange();
DCHECK_NE(0, receiver_maps.size());
......@@ -6701,7 +6705,7 @@ Reduction JSCallReducer::ReduceArrayBufferViewAccessor(
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
if (NodeProperties::HasInstanceTypeWitness(isolate(), receiver, effect,
if (NodeProperties::HasInstanceTypeWitness(js_heap_broker(), receiver, effect,
instance_type)) {
// Load the {receiver}s field.
Node* value = effect = graph()->NewNode(simplified()->LoadField(access),
......@@ -6787,7 +6791,7 @@ Reduction JSCallReducer::ReduceDataViewAccess(Node* node, DataViewAccess access,
}
// Only do stuff if the {receiver} is really a DataView.
if (NodeProperties::HasInstanceTypeWitness(isolate(), receiver, effect,
if (NodeProperties::HasInstanceTypeWitness(js_heap_broker(), receiver, effect,
JS_DATA_VIEW_TYPE)) {
// Check that the {offset} is within range for the {receiver}.
HeapObjectMatcher m(receiver);
......@@ -6974,7 +6978,7 @@ Reduction JSCallReducer::ReduceDatePrototypeGetTime(Node* node) {
Node* receiver = NodeProperties::GetValueInput(node, 1);
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
if (NodeProperties::HasInstanceTypeWitness(isolate(), receiver, effect,
if (NodeProperties::HasInstanceTypeWitness(js_heap_broker(), receiver, effect,
JS_DATE_TYPE)) {
Node* value = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForJSDateValue()), receiver,
......@@ -7038,7 +7042,7 @@ Reduction JSCallReducer::ReduceRegExpPrototypeTest(Node* node) {
// Check if we know something about the {regexp}.
ZoneHandleSet<Map> regexp_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(isolate(), regexp, effect,
NodeProperties::InferReceiverMaps(js_heap_broker(), regexp, effect,
&regexp_maps);
bool need_map_check = false;
......
......@@ -1338,7 +1338,8 @@ JSHeapBroker::JSHeapBroker(Isolate* isolate, Zone* broker_zone)
broker_zone_(broker_zone),
current_zone_(broker_zone),
refs_(new (zone())
RefsMap(kMinimalRefsBucketCount, AddressMatcher(), zone())) {
RefsMap(kMinimalRefsBucketCount, AddressMatcher(), zone())),
array_and_object_prototypes_(zone()) {
// Note that this initialization of the refs_ pointer with the minimal
// initial capacity is redundant in the normal use case (concurrent
// compilation enabled, standard objects to be serialized), as the map
......@@ -1456,6 +1457,37 @@ void JSHeapBroker::SerializeShareableObjects() {
current_zone_ = broker_zone_;
}
void JSHeapBroker::CollectArrayAndObjectPrototypes() {
DisallowHeapAllocation no_gc;
CHECK_EQ(mode(), kSerializing);
CHECK(array_and_object_prototypes_.empty());
Object* maybe_context = isolate()->heap()->native_contexts_list();
while (!maybe_context->IsUndefined(isolate())) {
Context* context = Context::cast(maybe_context);
Object* array_prot = context->get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX);
Object* object_prot = context->get(Context::INITIAL_OBJECT_PROTOTYPE_INDEX);
array_and_object_prototypes_.emplace(JSObject::cast(array_prot), isolate());
array_and_object_prototypes_.emplace(JSObject::cast(object_prot),
isolate());
maybe_context = context->next_context_link();
}
CHECK(!array_and_object_prototypes_.empty());
}
bool JSHeapBroker::IsArrayOrObjectPrototype(const JSObjectRef& object) const {
if (mode() == kDisabled) {
return isolate()->IsInAnyContext(*object.object(),
Context::INITIAL_ARRAY_PROTOTYPE_INDEX) ||
isolate()->IsInAnyContext(*object.object(),
Context::INITIAL_OBJECT_PROTOTYPE_INDEX);
}
CHECK(!array_and_object_prototypes_.empty());
return array_and_object_prototypes_.find(object.object<JSObject>()) !=
array_and_object_prototypes_.end();
}
void JSHeapBroker::SerializeStandardObjects() {
if (mode() == kDisabled) return;
CHECK_EQ(mode(), kSerializing);
......@@ -1464,6 +1496,8 @@ void JSHeapBroker::SerializeStandardObjects() {
TraceScope tracer(this, "JSHeapBroker::SerializeStandardObjects");
CollectArrayAndObjectPrototypes();
SetNativeContextRef();
native_context().Serialize();
......
......@@ -512,6 +512,10 @@ class V8_EXPORT_PRIVATE JSHeapBroker : public NON_EXPORTED_BASE(ZoneObject) {
// Like the previous but wraps argument in handle first (for convenience).
ObjectData* GetOrCreateData(Object*);
// Check if {object} is any native context's %ArrayPrototype% or
// %ObjectPrototype%.
bool IsArrayOrObjectPrototype(const JSObjectRef& object) const;
void Trace(const char* format, ...) const;
void IncrementTracingIndentation();
void DecrementTracingIndentation();
......@@ -522,12 +526,16 @@ class V8_EXPORT_PRIVATE JSHeapBroker : public NON_EXPORTED_BASE(ZoneObject) {
friend class ObjectData;
void SerializeShareableObjects();
void CollectArrayAndObjectPrototypes();
Isolate* const isolate_;
Zone* const broker_zone_;
Zone* current_zone_;
base::Optional<NativeContextRef> native_context_;
RefsMap* refs_;
ZoneUnorderedSet<Handle<JSObject>, Handle<JSObject>::hash,
Handle<JSObject>::equal_to>
array_and_object_prototypes_;
BrokerMode mode_ = kDisabled;
unsigned tracing_indentation_ = 0;
......
......@@ -16,10 +16,11 @@ class JSInliningHeuristic final : public AdvancedReducer {
enum Mode { kGeneralInlining, kRestrictedInlining, kStressInlining };
JSInliningHeuristic(Editor* editor, Mode mode, Zone* local_zone,
OptimizedCompilationInfo* info, JSGraph* jsgraph,
JSHeapBroker* broker,
SourcePositionTable* source_positions)
: AdvancedReducer(editor),
mode_(mode),
inliner_(editor, local_zone, info, jsgraph, source_positions),
inliner_(editor, local_zone, info, jsgraph, broker, source_positions),
candidates_(local_zone),
seen_(local_zone),
source_positions_(source_positions),
......
......@@ -606,7 +606,8 @@ Reduction JSInliner::ReduceJSCall(Node* node) {
if (node->opcode() == IrOpcode::kJSCall &&
is_sloppy(shared_info->language_mode()) && !shared_info->native()) {
Node* effect = NodeProperties::GetEffectInput(node);
if (NodeProperties::CanBePrimitive(isolate(), call.receiver(), effect)) {
if (NodeProperties::CanBePrimitive(js_heap_broker(), call.receiver(),
effect)) {
CallParameters const& p = CallParametersOf(node->op());
Node* global_proxy = jsgraph()->HeapConstant(
handle(info_->native_context()->global_proxy(), isolate()));
......
......@@ -24,11 +24,13 @@ class SourcePositionTable;
class JSInliner final : public AdvancedReducer {
public:
JSInliner(Editor* editor, Zone* local_zone, OptimizedCompilationInfo* info,
JSGraph* jsgraph, SourcePositionTable* source_positions)
JSGraph* jsgraph, JSHeapBroker* js_heap_broker,
SourcePositionTable* source_positions)
: AdvancedReducer(editor),
local_zone_(local_zone),
info_(info),
jsgraph_(jsgraph),
js_heap_broker_(js_heap_broker),
source_positions_(source_positions) {}
const char* reducer_name() const override { return "JSInliner"; }
......@@ -47,12 +49,15 @@ class JSInliner final : public AdvancedReducer {
SimplifiedOperatorBuilder* simplified() const;
Graph* graph() const;
JSGraph* jsgraph() const { return jsgraph_; }
// TODO(neis): Make heap broker a component of JSGraph?
JSHeapBroker* js_heap_broker() const { return js_heap_broker_; }
Isolate* isolate() const { return jsgraph_->isolate(); }
Handle<Context> native_context() const;
Zone* const local_zone_;
OptimizedCompilationInfo* info_;
JSGraph* const jsgraph_;
JSHeapBroker* const js_heap_broker_;
SourcePositionTable* const source_positions_;
bool DetermineCallTarget(Node* node,
......
......@@ -517,7 +517,7 @@ JSNativeContextSpecialization::InferHasInPrototypeChain(
Node* receiver, Node* effect, Handle<HeapObject> prototype) {
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(isolate(), receiver, effect,
NodeProperties::InferReceiverMaps(js_heap_broker(), receiver, effect,
&receiver_maps);
if (result == NodeProperties::kNoReceiverMaps) return kMayBeInPrototypeChain;
......@@ -660,7 +660,8 @@ Reduction JSNativeContextSpecialization::ReduceJSPromiseResolve(Node* node) {
// Check if we know something about the {value}.
ZoneHandleSet<Map> value_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(isolate(), value, effect, &value_maps);
NodeProperties::InferReceiverMaps(js_heap_broker(), value, effect,
&value_maps);
if (result == NodeProperties::kNoReceiverMaps) return NoChange();
DCHECK_NE(0, value_maps.size());
......@@ -690,7 +691,7 @@ Reduction JSNativeContextSpecialization::ReduceJSResolvePromise(Node* node) {
// Check if we know something about the {resolution}.
ZoneHandleSet<Map> resolution_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(isolate(), resolution, effect,
NodeProperties::InferReceiverMaps(js_heap_broker(), resolution, effect,
&resolution_maps);
if (result != NodeProperties::kReliableReceiverMaps) return NoChange();
DCHECK_NE(0, resolution_maps.size());
......@@ -2413,7 +2414,7 @@ Reduction JSNativeContextSpecialization::ReduceJSToObject(Node* node) {
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(isolate(), receiver, effect,
NodeProperties::InferReceiverMaps(js_heap_broker(), receiver, effect,
&receiver_maps);
if (result == NodeProperties::kNoReceiverMaps) return NoChange();
......@@ -3072,13 +3073,15 @@ bool JSNativeContextSpecialization::CanTreatHoleAsUndefined(
// Check if all {receiver_maps} either have one of the initial Array.prototype
// or Object.prototype objects as their prototype (in any of the current
// native contexts, as the global Array protector works isolate-wide).
for (Handle<Map> receiver_map : receiver_maps) {
DisallowHeapAllocation no_gc;
Object* const receiver_prototype = receiver_map->prototype();
if (!isolate()->IsInAnyContext(receiver_prototype,
Context::INITIAL_ARRAY_PROTOTYPE_INDEX) &&
!isolate()->IsInAnyContext(receiver_prototype,
Context::INITIAL_OBJECT_PROTOTYPE_INDEX)) {
for (Handle<Map> map : receiver_maps) {
MapRef receiver_map(js_heap_broker(), map);
// TODO(neis): Remove SerializePrototype call once brokerization is
// complete.
receiver_map.SerializePrototype();
ObjectRef receiver_prototype = receiver_map.prototype();
if (!receiver_prototype.IsJSObject() ||
!js_heap_broker()->IsArrayOrObjectPrototype(
receiver_prototype.AsJSObject())) {
return false;
}
}
......@@ -3135,7 +3138,8 @@ bool JSNativeContextSpecialization::InferReceiverMaps(
Node* receiver, Node* effect, MapHandles* receiver_maps) {
ZoneHandleSet<Map> maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(isolate(), receiver, effect, &maps);
NodeProperties::InferReceiverMaps(js_heap_broker(), receiver, effect,
&maps);
if (result == NodeProperties::kReliableReceiverMaps) {
for (size_t i = 0; i < maps.size(); ++i) {
receiver_maps->push_back(maps[i]);
......
......@@ -364,11 +364,11 @@ bool NodeProperties::IsSame(Node* a, Node* b) {
// static
NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMaps(
Isolate* isolate, Node* receiver, Node* effect,
JSHeapBroker* broker, Node* receiver, Node* effect,
ZoneHandleSet<Map>* maps_return) {
HeapObjectMatcher m(receiver);
if (m.HasValue()) {
Handle<HeapObject> receiver = m.Value();
HeapObjectRef receiver = m.Ref(broker).AsHeapObject();
// 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
......@@ -376,15 +376,12 @@ NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMaps(
//
// 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()) {
if (!receiver.IsJSObject() ||
!broker->IsArrayOrObjectPrototype(receiver.AsJSObject())) {
if (receiver.map().is_stable()) {
// The {receiver_map} is only reliable when we install a stability
// code dependency.
*maps_return = ZoneHandleSet<Map>(receiver_map);
*maps_return = ZoneHandleSet<Map>(receiver.map().object<Map>());
return kUnreliableReceiverMaps;
}
}
......@@ -418,7 +415,7 @@ NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMaps(
Handle<JSFunction>::cast(mnewtarget.Value());
if (original_constructor->has_initial_map()) {
Handle<Map> initial_map(original_constructor->initial_map(),
isolate);
broker->isolate());
if (initial_map->constructor_or_backpointer() ==
*mtarget.Value()) {
*maps_return = ZoneHandleSet<Map>(initial_map);
......@@ -505,12 +502,13 @@ NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMaps(
}
// static
MaybeHandle<Map> NodeProperties::GetMapWitness(Isolate* isolate, Node* node) {
MaybeHandle<Map> NodeProperties::GetMapWitness(JSHeapBroker* broker,
Node* node) {
ZoneHandleSet<Map> maps;
Node* receiver = NodeProperties::GetValueInput(node, 1);
Node* effect = NodeProperties::GetEffectInput(node);
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(isolate, receiver, effect, &maps);
NodeProperties::InferReceiverMaps(broker, receiver, effect, &maps);
if (result == NodeProperties::kReliableReceiverMaps && maps.size() == 1) {
return maps[0];
}
......@@ -518,12 +516,12 @@ MaybeHandle<Map> NodeProperties::GetMapWitness(Isolate* isolate, Node* node) {
}
// static
bool NodeProperties::HasInstanceTypeWitness(Isolate* isolate, Node* receiver,
Node* effect,
bool NodeProperties::HasInstanceTypeWitness(JSHeapBroker* broker,
Node* receiver, Node* effect,
InstanceType instance_type) {
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(isolate, receiver, effect,
NodeProperties::InferReceiverMaps(broker, receiver, effect,
&receiver_maps);
switch (result) {
case NodeProperties::kUnreliableReceiverMaps:
......@@ -555,7 +553,7 @@ bool NodeProperties::NoObservableSideEffectBetween(Node* effect,
}
// static
bool NodeProperties::CanBePrimitive(Isolate* isolate, Node* receiver,
bool NodeProperties::CanBePrimitive(JSHeapBroker* broker, Node* receiver,
Node* effect) {
switch (receiver->opcode()) {
#define CASE(Opcode) case IrOpcode::k##Opcode:
......@@ -576,7 +574,7 @@ bool NodeProperties::CanBePrimitive(Isolate* isolate, Node* receiver,
// just the instance types, which don't change
// across potential side-effecting operations.
ZoneHandleSet<Map> maps;
if (InferReceiverMaps(isolate, receiver, effect, &maps) !=
if (InferReceiverMaps(broker, receiver, effect, &maps) !=
kNoReceiverMaps) {
// Check if all {maps} are actually JSReceiver maps.
for (size_t i = 0; i < maps.size(); ++i) {
......@@ -590,9 +588,9 @@ bool NodeProperties::CanBePrimitive(Isolate* isolate, Node* receiver,
}
// static
bool NodeProperties::CanBeNullOrUndefined(Isolate* isolate, Node* receiver,
bool NodeProperties::CanBeNullOrUndefined(JSHeapBroker* broker, Node* receiver,
Node* effect) {
if (CanBePrimitive(isolate, receiver, effect)) {
if (CanBePrimitive(broker, receiver, effect)) {
switch (receiver->opcode()) {
case IrOpcode::kCheckInternalizedString:
case IrOpcode::kCheckNumber:
......@@ -609,7 +607,7 @@ bool NodeProperties::CanBeNullOrUndefined(Isolate* isolate, Node* receiver,
return false;
case IrOpcode::kHeapConstant: {
Handle<HeapObject> value = HeapObjectMatcher(receiver).Value();
return value->IsNullOrUndefined(isolate);
return value->IsNullOrUndefined(broker->isolate());
}
default:
return true;
......
......@@ -152,11 +152,11 @@ class V8_EXPORT_PRIVATE NodeProperties final {
// but instance type is reliable.
};
static InferReceiverMapsResult InferReceiverMaps(
Isolate* isolate, Node* receiver, Node* effect,
JSHeapBroker* broker, Node* receiver, Node* effect,
ZoneHandleSet<Map>* maps_return);
static MaybeHandle<Map> GetMapWitness(Isolate* isolate, Node* node);
static bool HasInstanceTypeWitness(Isolate* isolate, Node* receiver,
static MaybeHandle<Map> GetMapWitness(JSHeapBroker* broker, Node* node);
static bool HasInstanceTypeWitness(JSHeapBroker* broker, Node* receiver,
Node* effect, InstanceType instance_type);
// Walks up the {effect} chain to check that there's no observable side-effect
......@@ -167,11 +167,12 @@ class V8_EXPORT_PRIVATE NodeProperties final {
// Returns true if the {receiver} can be a primitive value (i.e. is not
// definitely a JavaScript object); might walk up the {effect} chain to
// find map checks on {receiver}.
static bool CanBePrimitive(Isolate* isolate, Node* receiver, Node* effect);
static bool CanBePrimitive(JSHeapBroker* broker, Node* receiver,
Node* effect);
// Returns true if the {receiver} can be null or undefined. Might walk
// up the {effect} chain to find map checks for {receiver}.
static bool CanBeNullOrUndefined(Isolate* isolate, Node* receiver,
static bool CanBeNullOrUndefined(JSHeapBroker* broker, Node* receiver,
Node* effect);
// ---------------------------------------------------------------------------
......
......@@ -1235,11 +1235,13 @@ struct InliningPhase {
JSNativeContextSpecialization native_context_specialization(
&graph_reducer, data->jsgraph(), data->js_heap_broker(), flags,
data->native_context(), data->dependencies(), temp_zone, info->zone());
JSInliningHeuristic inlining(
&graph_reducer, data->info()->is_inlining_enabled()
? JSInliningHeuristic::kGeneralInlining
: JSInliningHeuristic::kRestrictedInlining,
temp_zone, data->info(), data->jsgraph(), data->source_positions());
JSInliningHeuristic inlining(&graph_reducer,
data->info()->is_inlining_enabled()
? JSInliningHeuristic::kGeneralInlining
: JSInliningHeuristic::kRestrictedInlining,
temp_zone, data->info(), data->jsgraph(),
data->js_heap_broker(),
data->source_positions());
JSIntrinsicLowering intrinsic_lowering(&graph_reducer, data->jsgraph());
AddReducer(data, &graph_reducer, &dead_code_elimination);
AddReducer(data, &graph_reducer, &checkpoint_elimination);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment