Commit 15f0263f authored by Georg Neis's avatar Georg Neis Committed by Commit Bot

[turbofan] Brokerize parts of JSCallReducer.

Bug: v8:7790
Change-Id: I1e168132f5d3c90e1a3ee5c13ebc6dbc11e9daa1
Reviewed-on: https://chromium-review.googlesource.com/c/1288250
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56859}
parent 50f713c9
...@@ -412,26 +412,31 @@ Reduction JSCallReducer::ReduceFunctionPrototypeBind(Node* node) { ...@@ -412,26 +412,31 @@ Reduction JSCallReducer::ReduceFunctionPrototypeBind(Node* node) {
&receiver_maps); &receiver_maps);
if (result == NodeProperties::kNoReceiverMaps) return NoChange(); if (result == NodeProperties::kNoReceiverMaps) return NoChange();
DCHECK_NE(0, receiver_maps.size()); DCHECK_NE(0, receiver_maps.size());
bool const is_constructor = receiver_maps[0]->is_constructor(); MapRef const first_receiver_map(broker(), receiver_maps[0]);
Handle<Object> const prototype(receiver_maps[0]->prototype(), isolate()); bool const is_constructor = first_receiver_map.is_constructor();
for (Handle<Map> const receiver_map : receiver_maps) { ObjectRef const prototype = first_receiver_map.prototype();
for (Handle<Map> const map : receiver_maps) {
MapRef receiver_map(broker(), map);
// Check for consistency among the {receiver_maps}. // Check for consistency among the {receiver_maps}.
STATIC_ASSERT(LAST_TYPE == LAST_FUNCTION_TYPE); STATIC_ASSERT(LAST_TYPE == LAST_FUNCTION_TYPE);
if (receiver_map->prototype() != *prototype) return NoChange(); if (!receiver_map.prototype().equals(prototype) ||
if (receiver_map->is_constructor() != is_constructor) return NoChange(); receiver_map.is_constructor() != is_constructor ||
if (receiver_map->instance_type() < FIRST_FUNCTION_TYPE) return NoChange(); receiver_map.instance_type() < FIRST_FUNCTION_TYPE) {
return NoChange();
}
// Disallow binding of slow-mode functions. We need to figure out // Disallow binding of slow-mode functions. We need to figure out
// whether the length and name property are in the original state. // whether the length and name property are in the original state.
if (receiver_map->is_dictionary_map()) return NoChange(); if (receiver_map.is_dictionary_map()) return NoChange();
// Check whether the length and name properties are still present // Check whether the length and name properties are still present
// as AccessorInfo objects. In that case, their values can be // as AccessorInfo objects. In that case, their values can be
// recomputed even if the actual value of the object changes. // recomputed even if the actual value of the object changes.
// This mirrors the checks done in builtins-function-gen.cc at // This mirrors the checks done in builtins-function-gen.cc at
// runtime otherwise. // runtime otherwise.
Handle<DescriptorArray> descriptors(receiver_map->instance_descriptors(), Handle<DescriptorArray> descriptors(
isolate()); receiver_map.object()->instance_descriptors(), isolate());
if (descriptors->number_of_descriptors() < 2) return NoChange(); if (descriptors->number_of_descriptors() < 2) return NoChange();
if (descriptors->GetKey(JSFunction::kLengthDescriptorIndex) != if (descriptors->GetKey(JSFunction::kLengthDescriptorIndex) !=
ReadOnlyRoots(isolate()).length_string()) { ReadOnlyRoots(isolate()).length_string()) {
...@@ -453,12 +458,10 @@ Reduction JSCallReducer::ReduceFunctionPrototypeBind(Node* node) { ...@@ -453,12 +458,10 @@ Reduction JSCallReducer::ReduceFunctionPrototypeBind(Node* node) {
// Choose the map for the resulting JSBoundFunction (but bail out in case of a // Choose the map for the resulting JSBoundFunction (but bail out in case of a
// custom prototype). // custom prototype).
Handle<Map> map( MapRef map = is_constructor
is_constructor ? native_context().bound_function_with_constructor_map()
? native_context()->bound_function_with_constructor_map() : native_context().bound_function_without_constructor_map();
: native_context()->bound_function_without_constructor_map(), if (!map.prototype().equals(prototype)) return NoChange();
isolate());
if (map->prototype() != *prototype) return NoChange();
// Make sure we can rely on the {receiver_maps}. // Make sure we can rely on the {receiver_maps}.
if (result == NodeProperties::kUnreliableReceiverMaps) { if (result == NodeProperties::kUnreliableReceiverMaps) {
...@@ -479,8 +482,9 @@ Reduction JSCallReducer::ReduceFunctionPrototypeBind(Node* node) { ...@@ -479,8 +482,9 @@ Reduction JSCallReducer::ReduceFunctionPrototypeBind(Node* node) {
inputs[2 + arity + 0] = context; inputs[2 + arity + 0] = context;
inputs[2 + arity + 1] = effect; inputs[2 + arity + 1] = effect;
inputs[2 + arity + 2] = control; inputs[2 + arity + 2] = control;
Node* value = effect = graph()->NewNode( Node* value = effect =
javascript()->CreateBoundFunction(arity, map), input_count, inputs); graph()->NewNode(javascript()->CreateBoundFunction(arity, map.object()),
input_count, inputs);
ReplaceWithValue(node, value, effect, control); ReplaceWithValue(node, value, effect, control);
return Replace(value); return Replace(value);
} }
...@@ -730,8 +734,9 @@ Reduction JSCallReducer::ReduceObjectPrototypeIsPrototypeOf(Node* node) { ...@@ -730,8 +734,9 @@ Reduction JSCallReducer::ReduceObjectPrototypeIsPrototypeOf(Node* node) {
NodeProperties::InferReceiverMaps(broker(), receiver, effect, NodeProperties::InferReceiverMaps(broker(), receiver, effect,
&receiver_maps); &receiver_maps);
if (result == NodeProperties::kNoReceiverMaps) return NoChange(); if (result == NodeProperties::kNoReceiverMaps) return NoChange();
for (size_t i = 0; i < receiver_maps.size(); ++i) { for (Handle<Map> map : receiver_maps) {
if (!receiver_maps[i]->IsJSReceiverMap()) return NoChange(); MapRef receiver_map(broker(), map);
if (!receiver_map.IsJSReceiverMap()) return NoChange();
} }
// We don't check whether {value} is a proper JSReceiver here explicitly, // We don't check whether {value} is a proper JSReceiver here explicitly,
...@@ -972,14 +977,13 @@ Reduction JSCallReducer::ReduceReflectHas(Node* node) { ...@@ -972,14 +977,13 @@ Reduction JSCallReducer::ReduceReflectHas(Node* node) {
} }
bool CanInlineArrayIteratingBuiltin(Isolate* isolate, bool CanInlineArrayIteratingBuiltin(Isolate* isolate,
Handle<Map> receiver_map) { const MapRef& receiver_map) {
if (!receiver_map->prototype()->IsJSArray()) return false; if (!receiver_map.prototype().IsJSArray()) return false;
Handle<JSArray> receiver_prototype(JSArray::cast(receiver_map->prototype()), JSArrayRef receiver_prototype = receiver_map.prototype().AsJSArray();
isolate); return receiver_map.instance_type() == JS_ARRAY_TYPE &&
return receiver_map->instance_type() == JS_ARRAY_TYPE && IsFastElementsKind(receiver_map.elements_kind()) &&
IsFastElementsKind(receiver_map->elements_kind()) &&
isolate->IsNoElementsProtectorIntact() && isolate->IsNoElementsProtectorIntact() &&
isolate->IsAnyInitialArrayPrototype(receiver_prototype); isolate->IsAnyInitialArrayPrototype(receiver_prototype.object());
} }
Node* JSCallReducer::WireInLoopStart(Node* k, Node** control, Node** effect) { Node* JSCallReducer::WireInLoopStart(Node* k, Node** control, Node** effect) {
...@@ -1034,8 +1038,9 @@ Reduction JSCallReducer::ReduceArrayForEach(Node* node, ...@@ -1034,8 +1038,9 @@ Reduction JSCallReducer::ReduceArrayForEach(Node* node,
if (IsSmiElementsKind(kind)) { if (IsSmiElementsKind(kind)) {
kind = FastSmiToObjectElementsKind(kind); kind = FastSmiToObjectElementsKind(kind);
} }
for (Handle<Map> receiver_map : receiver_maps) { for (Handle<Map> map : receiver_maps) {
ElementsKind next_kind = receiver_map->elements_kind(); MapRef receiver_map(broker(), map);
ElementsKind next_kind = receiver_map.elements_kind();
if (!CanInlineArrayIteratingBuiltin(isolate(), receiver_map)) { if (!CanInlineArrayIteratingBuiltin(isolate(), receiver_map)) {
return NoChange(); return NoChange();
} }
...@@ -1219,10 +1224,11 @@ Reduction JSCallReducer::ReduceArrayReduce(Node* node, ...@@ -1219,10 +1224,11 @@ Reduction JSCallReducer::ReduceArrayReduce(Node* node,
if (result == NodeProperties::kNoReceiverMaps) return NoChange(); if (result == NodeProperties::kNoReceiverMaps) return NoChange();
ElementsKind kind = receiver_maps[0]->elements_kind(); ElementsKind kind = receiver_maps[0]->elements_kind();
for (Handle<Map> receiver_map : receiver_maps) { for (Handle<Map> map : receiver_maps) {
MapRef receiver_map(broker(), map);
if (!CanInlineArrayIteratingBuiltin(isolate(), receiver_map)) if (!CanInlineArrayIteratingBuiltin(isolate(), receiver_map))
return NoChange(); return NoChange();
if (!UnionElementsKindUptoSize(&kind, receiver_map->elements_kind())) if (!UnionElementsKindUptoSize(&kind, receiver_map.elements_kind()))
return NoChange(); return NoChange();
} }
...@@ -1500,12 +1506,13 @@ Reduction JSCallReducer::ReduceArrayMap(Node* node, ...@@ -1500,12 +1506,13 @@ Reduction JSCallReducer::ReduceArrayMap(Node* node,
const ElementsKind kind = receiver_maps[0]->elements_kind(); const ElementsKind kind = receiver_maps[0]->elements_kind();
for (Handle<Map> receiver_map : receiver_maps) { for (Handle<Map> map : receiver_maps) {
MapRef receiver_map(broker(), map);
if (!CanInlineArrayIteratingBuiltin(isolate(), receiver_map)) if (!CanInlineArrayIteratingBuiltin(isolate(), receiver_map))
return NoChange(); return NoChange();
// We can handle different maps, as long as their elements kind are the // We can handle different maps, as long as their elements kind are the
// same. // same.
if (receiver_map->elements_kind() != kind) return NoChange(); if (receiver_map.elements_kind() != kind) return NoChange();
} }
if (IsHoleyElementsKind(kind)) { if (IsHoleyElementsKind(kind)) {
...@@ -1516,12 +1523,8 @@ Reduction JSCallReducer::ReduceArrayMap(Node* node, ...@@ -1516,12 +1523,8 @@ Reduction JSCallReducer::ReduceArrayMap(Node* node,
dependencies()->DependOnProtector( dependencies()->DependOnProtector(
PropertyCellRef(broker(), factory()->array_species_protector())); PropertyCellRef(broker(), factory()->array_species_protector()));
Handle<JSFunction> handle_constructor( Node* array_constructor = jsgraph()->Constant(
JSFunction::cast( native_context().GetInitialJSArrayMap(kind).GetConstructor());
native_context()->GetInitialJSArrayMap(kind)->GetConstructor()),
isolate());
Node* array_constructor = jsgraph()->HeapConstant(handle_constructor);
Node* k = jsgraph()->ZeroConstant(); Node* k = jsgraph()->ZeroConstant();
...@@ -1641,15 +1644,12 @@ Reduction JSCallReducer::ReduceArrayMap(Node* node, ...@@ -1641,15 +1644,12 @@ Reduction JSCallReducer::ReduceArrayMap(Node* node,
// The array {a} should be HOLEY_SMI_ELEMENTS because we'd only come into this // The array {a} should be HOLEY_SMI_ELEMENTS because we'd only come into this
// loop if the input array length is non-zero, and "new Array({x > 0})" always // loop if the input array length is non-zero, and "new Array({x > 0})" always
// produces a HOLEY array. // produces a HOLEY array.
Handle<Map> double_map(Map::cast(native_context()->get( MapRef holey_double_map =
Context::ArrayMapIndex(HOLEY_DOUBLE_ELEMENTS))), native_context().GetInitialJSArrayMap(HOLEY_DOUBLE_ELEMENTS);
isolate()); MapRef holey_map = native_context().GetInitialJSArrayMap(HOLEY_ELEMENTS);
Handle<Map> fast_map( effect = graph()->NewNode(simplified()->TransitionAndStoreElement(
Map::cast(native_context()->get(Context::ArrayMapIndex(HOLEY_ELEMENTS))), holey_double_map.object(), holey_map.object()),
isolate()); a, k, callback_value, effect, control);
effect = graph()->NewNode(
simplified()->TransitionAndStoreElement(double_map, fast_map), a, k,
callback_value, effect, control);
if (IsHoleyElementsKind(kind)) { if (IsHoleyElementsKind(kind)) {
Node* after_call_and_store_control = control; Node* after_call_and_store_control = control;
...@@ -1714,13 +1714,14 @@ Reduction JSCallReducer::ReduceArrayFilter(Node* node, ...@@ -1714,13 +1714,14 @@ Reduction JSCallReducer::ReduceArrayFilter(Node* node,
// The output array is packed (filter doesn't visit holes). // The output array is packed (filter doesn't visit holes).
const ElementsKind packed_kind = GetPackedElementsKind(kind); const ElementsKind packed_kind = GetPackedElementsKind(kind);
for (Handle<Map> receiver_map : receiver_maps) { for (Handle<Map> map : receiver_maps) {
MapRef receiver_map(broker(), map);
if (!CanInlineArrayIteratingBuiltin(isolate(), receiver_map)) { if (!CanInlineArrayIteratingBuiltin(isolate(), receiver_map)) {
return NoChange(); return NoChange();
} }
// We can handle different maps, as long as their elements kind are the // We can handle different maps, as long as their elements kind are the
// same. // same.
if (receiver_map->elements_kind() != kind) return NoChange(); if (receiver_map.elements_kind() != kind) return NoChange();
} }
if (IsHoleyElementsKind(kind)) { if (IsHoleyElementsKind(kind)) {
...@@ -1731,9 +1732,7 @@ Reduction JSCallReducer::ReduceArrayFilter(Node* node, ...@@ -1731,9 +1732,7 @@ Reduction JSCallReducer::ReduceArrayFilter(Node* node,
dependencies()->DependOnProtector( dependencies()->DependOnProtector(
PropertyCellRef(broker(), factory()->array_species_protector())); PropertyCellRef(broker(), factory()->array_species_protector()));
Handle<Map> initial_map( MapRef initial_map = native_context().GetInitialJSArrayMap(packed_kind);
Map::cast(native_context()->GetInitialJSArrayMap(packed_kind)),
isolate());
Node* k = jsgraph()->ZeroConstant(); Node* k = jsgraph()->ZeroConstant();
Node* to = jsgraph()->ZeroConstant(); Node* to = jsgraph()->ZeroConstant();
...@@ -1749,16 +1748,15 @@ Reduction JSCallReducer::ReduceArrayFilter(Node* node, ...@@ -1749,16 +1748,15 @@ Reduction JSCallReducer::ReduceArrayFilter(Node* node,
Node* a; // Construct the output array. Node* a; // Construct the output array.
{ {
AllocationBuilder ab(jsgraph(), effect, control); AllocationBuilder ab(jsgraph(), effect, control);
ab.Allocate(initial_map->instance_size(), NOT_TENURED, Type::Array()); ab.Allocate(initial_map.instance_size(), NOT_TENURED, Type::Array());
ab.Store(AccessBuilder::ForMap(), initial_map); ab.Store(AccessBuilder::ForMap(), initial_map);
Node* empty_fixed_array = jsgraph()->EmptyFixedArrayConstant(); Node* empty_fixed_array = jsgraph()->EmptyFixedArrayConstant();
ab.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), empty_fixed_array); ab.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), empty_fixed_array);
ab.Store(AccessBuilder::ForJSObjectElements(), empty_fixed_array); ab.Store(AccessBuilder::ForJSObjectElements(), empty_fixed_array);
ab.Store(AccessBuilder::ForJSArrayLength(packed_kind), ab.Store(AccessBuilder::ForJSArrayLength(packed_kind),
jsgraph()->ZeroConstant()); jsgraph()->ZeroConstant());
for (int i = 0; i < initial_map->GetInObjectProperties(); ++i) { for (int i = 0; i < initial_map.GetInObjectProperties(); ++i) {
ab.Store(AccessBuilder::ForJSObjectInObjectProperty( ab.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
MapRef(broker(), initial_map), i),
jsgraph()->UndefinedConstant()); jsgraph()->UndefinedConstant());
} }
a = effect = ab.Finish(); a = effect = ab.Finish();
...@@ -1992,12 +1990,13 @@ Reduction JSCallReducer::ReduceArrayFind(Node* node, ArrayFindVariant variant, ...@@ -1992,12 +1990,13 @@ Reduction JSCallReducer::ReduceArrayFind(Node* node, ArrayFindVariant variant,
const ElementsKind kind = receiver_maps[0]->elements_kind(); const ElementsKind kind = receiver_maps[0]->elements_kind();
for (Handle<Map> receiver_map : receiver_maps) { for (Handle<Map> map : receiver_maps) {
MapRef receiver_map(broker(), map);
if (!CanInlineArrayIteratingBuiltin(isolate(), receiver_map)) if (!CanInlineArrayIteratingBuiltin(isolate(), receiver_map))
return NoChange(); return NoChange();
// We can handle different maps, as long as their elements kind are the // We can handle different maps, as long as their elements kind are the
// same. // same.
if (receiver_map->elements_kind() != kind) return NoChange(); if (receiver_map.elements_kind() != kind) return NoChange();
} }
// Install code dependencies on the {receiver} prototype maps and the // Install code dependencies on the {receiver} prototype maps and the
...@@ -2310,12 +2309,13 @@ Reduction JSCallReducer::ReduceArrayEvery(Node* node, ...@@ -2310,12 +2309,13 @@ Reduction JSCallReducer::ReduceArrayEvery(Node* node,
const ElementsKind kind = receiver_maps[0]->elements_kind(); const ElementsKind kind = receiver_maps[0]->elements_kind();
for (Handle<Map> receiver_map : receiver_maps) { for (Handle<Map> map : receiver_maps) {
MapRef receiver_map(broker(), map);
if (!CanInlineArrayIteratingBuiltin(isolate(), receiver_map)) if (!CanInlineArrayIteratingBuiltin(isolate(), receiver_map))
return NoChange(); return NoChange();
// We can handle different maps, as long as their elements kind are the // We can handle different maps, as long as their elements kind are the
// same. // same.
if (receiver_map->elements_kind() != kind) return NoChange(); if (receiver_map.elements_kind() != kind) return NoChange();
} }
if (IsHoleyElementsKind(kind)) { if (IsHoleyElementsKind(kind)) {
...@@ -2565,7 +2565,8 @@ Reduction JSCallReducer::ReduceArrayIndexOfIncludes( ...@@ -2565,7 +2565,8 @@ Reduction JSCallReducer::ReduceArrayIndexOfIncludes(
if (!NodeProperties::GetMapWitness(broker(), node).ToHandle(&receiver_map)) if (!NodeProperties::GetMapWitness(broker(), node).ToHandle(&receiver_map))
return NoChange(); return NoChange();
if (!CanInlineArrayIteratingBuiltin(isolate(), receiver_map)) if (!CanInlineArrayIteratingBuiltin(isolate(),
MapRef(broker(), receiver_map)))
return NoChange(); return NoChange();
if (IsHoleyElementsKind(receiver_map->elements_kind())) { if (IsHoleyElementsKind(receiver_map->elements_kind())) {
...@@ -2659,12 +2660,13 @@ Reduction JSCallReducer::ReduceArraySome(Node* node, ...@@ -2659,12 +2660,13 @@ Reduction JSCallReducer::ReduceArraySome(Node* node,
const ElementsKind kind = receiver_maps[0]->elements_kind(); const ElementsKind kind = receiver_maps[0]->elements_kind();
for (Handle<Map> receiver_map : receiver_maps) { for (Handle<Map> map : receiver_maps) {
MapRef receiver_map(broker(), map);
if (!CanInlineArrayIteratingBuiltin(isolate(), receiver_map)) if (!CanInlineArrayIteratingBuiltin(isolate(), receiver_map))
return NoChange(); return NoChange();
// We can handle different maps, as long as their elements kind are the // We can handle different maps, as long as their elements kind are the
// same. // same.
if (receiver_map->elements_kind() != kind) return NoChange(); if (receiver_map.elements_kind() != kind) return NoChange();
} }
if (IsHoleyElementsKind(kind)) { if (IsHoleyElementsKind(kind)) {
...@@ -2865,8 +2867,9 @@ Reduction JSCallReducer::ReduceCallApiFunction( ...@@ -2865,8 +2867,9 @@ Reduction JSCallReducer::ReduceCallApiFunction(
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = CallParametersOf(node->op());
int const argc = static_cast<int>(p.arity()) - 2; int const argc = static_cast<int>(p.arity()) - 2;
Node* target = NodeProperties::GetValueInput(node, 0); Node* target = NodeProperties::GetValueInput(node, 0);
Node* receiver = (p.convert_mode() == ConvertReceiverMode::kNullOrUndefined) Node* receiver =
? jsgraph()->HeapConstant(global_proxy()) (p.convert_mode() == ConvertReceiverMode::kNullOrUndefined)
? jsgraph()->Constant(native_context().global_proxy_object())
: NodeProperties::GetValueInput(node, 1); : NodeProperties::GetValueInput(node, 1);
Node* effect = NodeProperties::GetEffectInput(node); Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node); Node* control = NodeProperties::GetControlInput(node);
...@@ -2886,17 +2889,17 @@ Reduction JSCallReducer::ReduceCallApiFunction( ...@@ -2886,17 +2889,17 @@ Reduction JSCallReducer::ReduceCallApiFunction(
NodeProperties::InferReceiverMaps(broker(), receiver, effect, NodeProperties::InferReceiverMaps(broker(), receiver, effect,
&receiver_maps); &receiver_maps);
if (result == NodeProperties::kNoReceiverMaps) return NoChange(); if (result == NodeProperties::kNoReceiverMaps) return NoChange();
for (size_t i = 0; i < receiver_maps.size(); ++i) { for (Handle<Map> map : receiver_maps) {
Handle<Map> receiver_map = receiver_maps[i]; MapRef receiver_map(broker(), map);
if (!receiver_map->IsJSObjectMap() || if (!receiver_map.IsJSObjectMap() ||
(!function_template_info->accept_any_receiver() && (!function_template_info->accept_any_receiver() &&
receiver_map->is_access_check_needed())) { receiver_map.is_access_check_needed())) {
return NoChange(); return NoChange();
} }
// In case of unreliable {receiver} information, the {receiver_maps} // In case of unreliable {receiver} information, the {receiver_maps}
// must all be stable in order to consume the information. // must all be stable in order to consume the information.
if (result == NodeProperties::kUnreliableReceiverMaps) { if (result == NodeProperties::kUnreliableReceiverMaps) {
if (!receiver_map->is_stable()) return NoChange(); if (!receiver_map.is_stable()) return NoChange();
} }
} }
...@@ -2917,8 +2920,9 @@ Reduction JSCallReducer::ReduceCallApiFunction( ...@@ -2917,8 +2920,9 @@ Reduction JSCallReducer::ReduceCallApiFunction(
// Install stability dependencies for unreliable {receiver_maps}. // Install stability dependencies for unreliable {receiver_maps}.
if (result == NodeProperties::kUnreliableReceiverMaps) { if (result == NodeProperties::kUnreliableReceiverMaps) {
for (size_t i = 0; i < receiver_maps.size(); ++i) { for (Handle<Map> map : receiver_maps) {
dependencies()->DependOnStableMap(MapRef(broker(), receiver_maps[i])); MapRef receiver_map(broker(), map);
dependencies()->DependOnStableMap(receiver_map);
} }
} }
...@@ -3223,13 +3227,16 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) { ...@@ -3223,13 +3227,16 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) {
// Try to specialize JSCall {node}s with constant {target}s. // Try to specialize JSCall {node}s with constant {target}s.
HeapObjectMatcher m(target); HeapObjectMatcher m(target);
if (m.HasValue()) { if (m.HasValue()) {
if (m.Value()->IsJSFunction()) { if (m.Ref(broker()).IsJSFunction()) {
Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value()); JSFunctionRef function = m.Ref(broker()).AsJSFunction();
function.Serialize();
// Don't inline cross native context. // Don't inline cross native context.
if (function->native_context() != *native_context()) return NoChange(); if (!function.native_context().equals(native_context())) {
return NoChange();
}
return ReduceJSCall(node, handle(function->shared(), isolate())); return ReduceJSCall(node, function.shared().object());
} else if (m.Value()->IsJSBoundFunction()) { } else if (m.Value()->IsJSBoundFunction()) {
Handle<JSBoundFunction> function = Handle<JSBoundFunction> function =
Handle<JSBoundFunction>::cast(m.Value()); Handle<JSBoundFunction>::cast(m.Value());
...@@ -3759,9 +3766,8 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) { ...@@ -3759,9 +3766,8 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) {
Handle<AllocationSite> site(AllocationSite::cast(feedback_object), Handle<AllocationSite> site(AllocationSite::cast(feedback_object),
isolate()); isolate());
// Retrieve the Array function from the {node}. Node* array_function =
Node* array_function = jsgraph()->HeapConstant( jsgraph()->Constant(native_context().array_function());
handle(native_context()->array_function(), isolate()));
// Check that the {target} is still the {array_function}. // Check that the {target} is still the {array_function}.
Node* check = graph()->NewNode(simplified()->ReferenceEqual(), target, Node* check = graph()->NewNode(simplified()->ReferenceEqual(), target,
...@@ -3818,18 +3824,21 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) { ...@@ -3818,18 +3824,21 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) {
return Changed(node); return Changed(node);
} }
if (m.Value()->IsJSFunction()) { if (m.Ref(broker()).IsJSFunction()) {
Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value()); JSFunctionRef function = m.Ref(broker()).AsJSFunction();
function.Serialize();
// Do not reduce constructors with break points. // Do not reduce constructors with break points.
if (function->shared()->HasBreakInfo()) return NoChange(); if (function.shared().HasBreakInfo()) return NoChange();
// Don't inline cross native context. // Don't inline cross native context.
if (function->native_context() != *native_context()) return NoChange(); if (!function.native_context().equals(native_context())) {
return NoChange();
}
// Check for known builtin functions. // Check for known builtin functions.
int builtin_id = function->shared()->HasBuiltinId() int builtin_id = function.shared().HasBuiltinId()
? function->shared()->builtin_id() ? function.shared().builtin_id()
: Builtins::kNoBuiltinId; : Builtins::kNoBuiltinId;
switch (builtin_id) { switch (builtin_id) {
case Builtins::kArrayConstructor: { case Builtins::kArrayConstructor: {
...@@ -3857,7 +3866,8 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) { ...@@ -3857,7 +3866,8 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) {
// the value parameter is ignored, which is only the case if // the value parameter is ignored, which is only the case if
// the {new_target} and {target} are definitely not identical. // the {new_target} and {target} are definitely not identical.
HeapObjectMatcher mnew_target(new_target); HeapObjectMatcher mnew_target(new_target);
if (mnew_target.HasValue() && *mnew_target.Value() != *function) { if (mnew_target.HasValue() &&
!mnew_target.Ref(broker()).equals(function)) {
// Drop the value inputs. // Drop the value inputs.
for (int i = arity; i > 0; --i) node->RemoveInput(i); for (int i = arity; i > 0; --i) node->RemoveInput(i);
NodeProperties::ChangeOp(node, javascript()->Create()); NodeProperties::ChangeOp(node, javascript()->Create());
...@@ -3868,8 +3878,7 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) { ...@@ -3868,8 +3878,7 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) {
case Builtins::kPromiseConstructor: case Builtins::kPromiseConstructor:
return ReducePromiseConstructor(node); return ReducePromiseConstructor(node);
case Builtins::kTypedArrayConstructor: case Builtins::kTypedArrayConstructor:
return ReduceTypedArrayConstructor( return ReduceTypedArrayConstructor(node, function.shared().object());
node, handle(function->shared(), isolate()));
default: default:
break; break;
} }
...@@ -4320,15 +4329,15 @@ bool IsReadOnlyLengthDescriptor(Isolate* isolate, Handle<Map> jsarray_map) { ...@@ -4320,15 +4329,15 @@ bool IsReadOnlyLengthDescriptor(Isolate* isolate, Handle<Map> jsarray_map) {
} }
// TODO(turbofan): This was copied from old compiler, might be too restrictive. // TODO(turbofan): This was copied from old compiler, might be too restrictive.
bool CanInlineArrayResizeOperation(Isolate* isolate, Handle<Map> receiver_map) { bool CanInlineArrayResizeOperation(Isolate* isolate,
if (!receiver_map->prototype()->IsJSArray()) return false; const MapRef& receiver_map) {
Handle<JSArray> receiver_prototype(JSArray::cast(receiver_map->prototype()), if (!receiver_map.prototype().IsJSArray()) return false;
isolate); JSArrayRef receiver_prototype = receiver_map.prototype().AsJSArray();
return receiver_map->instance_type() == JS_ARRAY_TYPE && return receiver_map.instance_type() == JS_ARRAY_TYPE &&
IsFastElementsKind(receiver_map->elements_kind()) && IsFastElementsKind(receiver_map.elements_kind()) &&
!receiver_map->is_dictionary_map() && receiver_map->is_extensible() && !receiver_map.is_dictionary_map() && receiver_map.is_extensible() &&
isolate->IsAnyInitialArrayPrototype(receiver_prototype) && isolate->IsAnyInitialArrayPrototype(receiver_prototype.object()) &&
!IsReadOnlyLengthDescriptor(isolate, receiver_map); !IsReadOnlyLengthDescriptor(isolate, receiver_map.object());
} }
} // namespace } // namespace
...@@ -4358,10 +4367,12 @@ Reduction JSCallReducer::ReduceArrayPrototypePush(Node* node) { ...@@ -4358,10 +4367,12 @@ Reduction JSCallReducer::ReduceArrayPrototypePush(Node* node) {
ElementsKind kind = receiver_maps[0]->elements_kind(); ElementsKind kind = receiver_maps[0]->elements_kind();
for (Handle<Map> receiver_map : receiver_maps) { for (Handle<Map> map : receiver_maps) {
MapRef receiver_map(broker(), map);
receiver_map.SerializePrototype();
if (!CanInlineArrayResizeOperation(isolate(), receiver_map)) if (!CanInlineArrayResizeOperation(isolate(), receiver_map))
return NoChange(); return NoChange();
if (!UnionElementsKindUptoPackedness(&kind, receiver_map->elements_kind())) if (!UnionElementsKindUptoPackedness(&kind, receiver_map.elements_kind()))
return NoChange(); return NoChange();
} }
...@@ -4469,14 +4480,16 @@ Reduction JSCallReducer::ReduceArrayPrototypePop(Node* node) { ...@@ -4469,14 +4480,16 @@ Reduction JSCallReducer::ReduceArrayPrototypePop(Node* node) {
DCHECK_NE(0, receiver_maps.size()); DCHECK_NE(0, receiver_maps.size());
ElementsKind kind = receiver_maps[0]->elements_kind(); ElementsKind kind = receiver_maps[0]->elements_kind();
for (Handle<Map> receiver_map : receiver_maps) { for (Handle<Map> map : receiver_maps) {
MapRef receiver_map(broker(), map);
receiver_map.SerializePrototype();
if (!CanInlineArrayResizeOperation(isolate(), receiver_map)) if (!CanInlineArrayResizeOperation(isolate(), receiver_map))
return NoChange(); return NoChange();
// TODO(turbofan): Extend this to also handle fast holey double elements // TODO(turbofan): Extend this to also handle fast holey double elements
// once we got the hole NaN mess sorted out in TurboFan/V8. // once we got the hole NaN mess sorted out in TurboFan/V8.
if (receiver_map->elements_kind() == HOLEY_DOUBLE_ELEMENTS) if (receiver_map.elements_kind() == HOLEY_DOUBLE_ELEMENTS)
return NoChange(); return NoChange();
if (!UnionElementsKindUptoSize(&kind, receiver_map->elements_kind())) if (!UnionElementsKindUptoSize(&kind, receiver_map.elements_kind()))
return NoChange(); return NoChange();
} }
...@@ -4588,14 +4601,16 @@ Reduction JSCallReducer::ReduceArrayPrototypeShift(Node* node) { ...@@ -4588,14 +4601,16 @@ Reduction JSCallReducer::ReduceArrayPrototypeShift(Node* node) {
DCHECK_NE(0, receiver_maps.size()); DCHECK_NE(0, receiver_maps.size());
ElementsKind kind = receiver_maps[0]->elements_kind(); ElementsKind kind = receiver_maps[0]->elements_kind();
for (Handle<Map> receiver_map : receiver_maps) { for (Handle<Map> map : receiver_maps) {
MapRef receiver_map(broker(), map);
receiver_map.SerializePrototype();
if (!CanInlineArrayResizeOperation(isolate(), receiver_map)) if (!CanInlineArrayResizeOperation(isolate(), receiver_map))
return NoChange(); return NoChange();
// TODO(turbofan): Extend this to also handle fast holey double elements // TODO(turbofan): Extend this to also handle fast holey double elements
// once we got the hole NaN mess sorted out in TurboFan/V8. // once we got the hole NaN mess sorted out in TurboFan/V8.
if (receiver_map->elements_kind() == HOLEY_DOUBLE_ELEMENTS) if (receiver_map.elements_kind() == HOLEY_DOUBLE_ELEMENTS)
return NoChange(); return NoChange();
if (!UnionElementsKindUptoSize(&kind, receiver_map->elements_kind())) if (!UnionElementsKindUptoSize(&kind, receiver_map.elements_kind()))
return NoChange(); return NoChange();
} }
...@@ -4798,11 +4813,12 @@ Reduction JSCallReducer::ReduceArrayPrototypeSlice(Node* node) { ...@@ -4798,11 +4813,12 @@ Reduction JSCallReducer::ReduceArrayPrototypeSlice(Node* node) {
bool can_be_holey = false; bool can_be_holey = false;
// Check that the maps are of JSArray (and more) // Check that the maps are of JSArray (and more)
for (Handle<Map> receiver_map : receiver_maps) { for (Handle<Map> map : receiver_maps) {
MapRef receiver_map(broker(), map);
if (!CanInlineArrayIteratingBuiltin(isolate(), receiver_map)) if (!CanInlineArrayIteratingBuiltin(isolate(), receiver_map))
return NoChange(); return NoChange();
if (IsHoleyElementsKind(receiver_map->elements_kind())) can_be_holey = true; if (IsHoleyElementsKind(receiver_map.elements_kind())) can_be_holey = true;
} }
// Install code dependency on the array protector for holey arrays. // Install code dependency on the array protector for holey arrays.
...@@ -4949,12 +4965,13 @@ Reduction JSCallReducer::ReduceArrayIteratorPrototypeNext(Node* node) { ...@@ -4949,12 +4965,13 @@ Reduction JSCallReducer::ReduceArrayIteratorPrototypeNext(Node* node) {
} }
} }
} else { } else {
for (Handle<Map> iterated_object_map : iterated_object_maps) { for (Handle<Map> map : iterated_object_maps) {
MapRef iterated_object_map(broker(), map);
if (!CanInlineArrayIteratingBuiltin(isolate(), iterated_object_map)) { if (!CanInlineArrayIteratingBuiltin(isolate(), iterated_object_map)) {
return NoChange(); return NoChange();
} }
if (!UnionElementsKindUptoSize(&elements_kind, if (!UnionElementsKindUptoSize(&elements_kind,
iterated_object_map->elements_kind())) { iterated_object_map.elements_kind())) {
return NoChange(); return NoChange();
} }
} }
...@@ -5549,17 +5566,17 @@ Reduction JSCallReducer::ReducePromiseConstructor(Node* node) { ...@@ -5549,17 +5566,17 @@ Reduction JSCallReducer::ReducePromiseConstructor(Node* node) {
dependencies()->DependOnProtector( dependencies()->DependOnProtector(
PropertyCellRef(broker(), factory()->promise_hook_protector())); PropertyCellRef(broker(), factory()->promise_hook_protector()));
Handle<SharedFunctionInfo> promise_shared( SharedFunctionInfoRef promise_shared =
handle(native_context()->promise_function()->shared(), isolate())); native_context().promise_function().shared();
// Insert a construct stub frame into the chain of frame states. This will // Insert a construct stub frame into the chain of frame states. This will
// reconstruct the proper frame when deoptimizing within the constructor. // reconstruct the proper frame when deoptimizing within the constructor.
// For the frame state, we only provide the executor parameter, even if more // For the frame state, we only provide the executor parameter, even if more
// arugments were passed. This is not observable from JS. // arugments were passed. This is not observable from JS.
DCHECK_EQ(1, promise_shared->internal_formal_parameter_count()); DCHECK_EQ(1, promise_shared.internal_formal_parameter_count());
Node* constructor_frame_state = CreateArtificialFrameState( Node* constructor_frame_state = CreateArtificialFrameState(
node, outer_frame_state, 1, BailoutId::ConstructStubInvoke(), node, outer_frame_state, 1, BailoutId::ConstructStubInvoke(),
FrameStateType::kConstructStub, promise_shared, context); FrameStateType::kConstructStub, promise_shared.object(), context);
// The deopt continuation of this frame state is never called; the frame state // The deopt continuation of this frame state is never called; the frame state
// is only necessary to obtain the right stack trace. // is only necessary to obtain the right stack trace.
...@@ -5572,7 +5589,7 @@ Reduction JSCallReducer::ReducePromiseConstructor(Node* node) { ...@@ -5572,7 +5589,7 @@ Reduction JSCallReducer::ReducePromiseConstructor(Node* node) {
int checkpoint_parameters_size = int checkpoint_parameters_size =
static_cast<int>(checkpoint_parameters.size()); static_cast<int>(checkpoint_parameters.size());
Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState( Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
jsgraph(), promise_shared, jsgraph(), promise_shared.object(),
Builtins::kPromiseConstructorLazyDeoptContinuation, target, context, Builtins::kPromiseConstructorLazyDeoptContinuation, target, context,
checkpoint_parameters.data(), checkpoint_parameters_size, checkpoint_parameters.data(), checkpoint_parameters_size,
constructor_frame_state, ContinuationFrameStateMode::LAZY); constructor_frame_state, ContinuationFrameStateMode::LAZY);
...@@ -5589,9 +5606,9 @@ Reduction JSCallReducer::ReducePromiseConstructor(Node* node) { ...@@ -5589,9 +5606,9 @@ Reduction JSCallReducer::ReducePromiseConstructor(Node* node) {
// 8. CreatePromiseResolvingFunctions // 8. CreatePromiseResolvingFunctions
// Allocate a promise context for the closures below. // Allocate a promise context for the closures below.
Node* promise_context = effect = Node* promise_context = effect = graph()->NewNode(
graph()->NewNode(javascript()->CreateFunctionContext( javascript()->CreateFunctionContext(
handle(native_context()->scope_info(), isolate()), handle(native_context().object()->scope_info(), isolate()),
PromiseBuiltinsAssembler::kPromiseContextLength - PromiseBuiltinsAssembler::kPromiseContextLength -
Context::MIN_CONTEXT_SLOTS, Context::MIN_CONTEXT_SLOTS,
FUNCTION_SCOPE), FUNCTION_SCOPE),
...@@ -5610,23 +5627,21 @@ Reduction JSCallReducer::ReducePromiseConstructor(Node* node) { ...@@ -5610,23 +5627,21 @@ Reduction JSCallReducer::ReducePromiseConstructor(Node* node) {
promise_context, jsgraph()->TrueConstant(), effect, control); promise_context, jsgraph()->TrueConstant(), effect, control);
// Allocate the closure for the resolve case. // Allocate the closure for the resolve case.
Handle<SharedFunctionInfo> resolve_shared( SharedFunctionInfoRef resolve_shared =
native_context()->promise_capability_default_resolve_shared_fun(), native_context().promise_capability_default_resolve_shared_fun();
isolate()); Node* resolve = effect = graph()->NewNode(
Node* resolve = effect = javascript()->CreateClosure(
graph()->NewNode(javascript()->CreateClosure( resolve_shared.object(), factory()->many_closures_cell(),
resolve_shared, factory()->many_closures_cell(), handle(resolve_shared.object()->GetCode(), isolate())),
handle(resolve_shared->GetCode(), isolate())),
promise_context, effect, control); promise_context, effect, control);
// Allocate the closure for the reject case. // Allocate the closure for the reject case.
Handle<SharedFunctionInfo> reject_shared( SharedFunctionInfoRef reject_shared =
native_context()->promise_capability_default_reject_shared_fun(), native_context().promise_capability_default_reject_shared_fun();
isolate()); Node* reject = effect = graph()->NewNode(
Node* reject = effect = javascript()->CreateClosure(
graph()->NewNode(javascript()->CreateClosure( reject_shared.object(), factory()->many_closures_cell(),
reject_shared, factory()->many_closures_cell(), handle(reject_shared.object()->GetCode(), isolate())),
handle(reject_shared->GetCode(), isolate())),
promise_context, effect, control); promise_context, effect, control);
const std::vector<Node*> checkpoint_parameters_continuation( const std::vector<Node*> checkpoint_parameters_continuation(
...@@ -5636,7 +5651,7 @@ Reduction JSCallReducer::ReducePromiseConstructor(Node* node) { ...@@ -5636,7 +5651,7 @@ Reduction JSCallReducer::ReducePromiseConstructor(Node* node) {
// This continuation just returns the created promise and takes care of // This continuation just returns the created promise and takes care of
// exceptions thrown by the executor. // exceptions thrown by the executor.
frame_state = CreateJavaScriptBuiltinContinuationFrameState( frame_state = CreateJavaScriptBuiltinContinuationFrameState(
jsgraph(), promise_shared, jsgraph(), promise_shared.object(),
Builtins::kPromiseConstructorLazyDeoptContinuation, target, context, Builtins::kPromiseConstructorLazyDeoptContinuation, target, context,
checkpoint_parameters_continuation.data(), checkpoint_parameters_continuation.data(),
checkpoint_parameters_continuation_size, constructor_frame_state, checkpoint_parameters_continuation_size, constructor_frame_state,
...@@ -5790,9 +5805,11 @@ Reduction JSCallReducer::ReducePromisePrototypeCatch(Node* node) { ...@@ -5790,9 +5805,11 @@ Reduction JSCallReducer::ReducePromisePrototypeCatch(Node* node) {
// Check whether all {receiver_maps} are JSPromise maps and // Check whether all {receiver_maps} are JSPromise maps and
// have the initial Promise.prototype as their [[Prototype]]. // have the initial Promise.prototype as their [[Prototype]].
for (Handle<Map> receiver_map : receiver_maps) { for (Handle<Map> map : receiver_maps) {
if (!receiver_map->IsJSPromiseMap()) return NoChange(); MapRef receiver_map(broker(), map);
if (receiver_map->prototype() != native_context()->promise_prototype()) { if (!receiver_map.IsJSPromiseMap()) return NoChange();
if (!receiver_map.prototype().equals(
native_context().promise_prototype())) {
return NoChange(); return NoChange();
} }
} }
...@@ -5812,8 +5829,7 @@ Reduction JSCallReducer::ReducePromisePrototypeCatch(Node* node) { ...@@ -5812,8 +5829,7 @@ Reduction JSCallReducer::ReducePromisePrototypeCatch(Node* node) {
// Massage the {node} to call "then" instead by first removing all inputs // Massage the {node} to call "then" instead by first removing all inputs
// following the onRejected parameter, and then filling up the parameters // following the onRejected parameter, and then filling up the parameters
// to two inputs from the left with undefined. // to two inputs from the left with undefined.
Node* target = Node* target = jsgraph()->Constant(native_context().promise_then());
jsgraph()->Constant(handle(native_context()->promise_then(), isolate()));
NodeProperties::ReplaceValueInput(node, target, 0); NodeProperties::ReplaceValueInput(node, target, 0);
NodeProperties::ReplaceEffectInput(node, effect); NodeProperties::ReplaceEffectInput(node, effect);
for (; arity > 1; --arity) node->RemoveInput(3); for (; arity > 1; --arity) node->RemoveInput(3);
...@@ -5867,9 +5883,11 @@ Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) { ...@@ -5867,9 +5883,11 @@ Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) {
// Check whether all {receiver_maps} are JSPromise maps and // Check whether all {receiver_maps} are JSPromise maps and
// have the initial Promise.prototype as their [[Prototype]]. // have the initial Promise.prototype as their [[Prototype]].
for (Handle<Map> receiver_map : receiver_maps) { for (Handle<Map> map : receiver_maps) {
if (!receiver_map->IsJSPromiseMap()) return NoChange(); MapRef receiver_map(broker(), map);
if (receiver_map->prototype() != native_context()->promise_prototype()) { if (!receiver_map.IsJSPromiseMap()) return NoChange();
if (!receiver_map.prototype().equals(
native_context().promise_prototype())) {
return NoChange(); return NoChange();
} }
} }
...@@ -5901,14 +5919,14 @@ Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) { ...@@ -5901,14 +5919,14 @@ Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) {
Node* catch_true; Node* catch_true;
Node* then_true; Node* then_true;
{ {
Node* context = jsgraph()->HeapConstant(native_context()); Node* context = jsgraph()->Constant(native_context());
Node* constructor = jsgraph()->HeapConstant( Node* constructor =
handle(native_context()->promise_function(), isolate())); jsgraph()->Constant(native_context().promise_function());
// Allocate shared context for the closures below. // Allocate shared context for the closures below.
context = etrue = graph()->NewNode( context = etrue = graph()->NewNode(
javascript()->CreateFunctionContext( javascript()->CreateFunctionContext(
handle(native_context()->scope_info(), isolate()), handle(native_context().object()->scope_info(), isolate()),
PromiseBuiltinsAssembler::kPromiseFinallyContextLength - PromiseBuiltinsAssembler::kPromiseFinallyContextLength -
Context::MIN_CONTEXT_SLOTS, Context::MIN_CONTEXT_SLOTS,
FUNCTION_SCOPE), FUNCTION_SCOPE),
...@@ -5923,21 +5941,21 @@ Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) { ...@@ -5923,21 +5941,21 @@ Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) {
context, constructor, etrue, if_true); context, constructor, etrue, if_true);
// Allocate the closure for the reject case. // Allocate the closure for the reject case.
Handle<SharedFunctionInfo> catch_finally( SharedFunctionInfoRef catch_finally =
native_context()->promise_catch_finally_shared_fun(), isolate()); native_context().promise_catch_finally_shared_fun();
catch_true = etrue = catch_true = etrue = graph()->NewNode(
graph()->NewNode(javascript()->CreateClosure( javascript()->CreateClosure(
catch_finally, factory()->many_closures_cell(), catch_finally.object(), factory()->many_closures_cell(),
handle(catch_finally->GetCode(), isolate())), handle(catch_finally.object()->GetCode(), isolate())),
context, etrue, if_true); context, etrue, if_true);
// Allocate the closure for the fulfill case. // Allocate the closure for the fulfill case.
Handle<SharedFunctionInfo> then_finally( SharedFunctionInfoRef then_finally =
native_context()->promise_then_finally_shared_fun(), isolate()); native_context().promise_then_finally_shared_fun();
then_true = etrue = then_true = etrue = graph()->NewNode(
graph()->NewNode(javascript()->CreateClosure( javascript()->CreateClosure(
then_finally, factory()->many_closures_cell(), then_finally.object(), factory()->many_closures_cell(),
handle(then_finally->GetCode(), isolate())), handle(then_finally.object()->GetCode(), isolate())),
context, etrue, if_true); context, etrue, if_true);
} }
...@@ -5964,8 +5982,7 @@ Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) { ...@@ -5964,8 +5982,7 @@ Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) {
// Massage the {node} to call "then" instead by first removing all inputs // Massage the {node} to call "then" instead by first removing all inputs
// following the onFinally parameter, and then replacing the only parameter // following the onFinally parameter, and then replacing the only parameter
// input with the {on_finally} value. // input with the {on_finally} value.
Node* target = Node* target = jsgraph()->Constant(native_context().promise_then());
jsgraph()->Constant(handle(native_context()->promise_then(), isolate()));
NodeProperties::ReplaceValueInput(node, target, 0); NodeProperties::ReplaceValueInput(node, target, 0);
NodeProperties::ReplaceEffectInput(node, effect); NodeProperties::ReplaceEffectInput(node, effect);
NodeProperties::ReplaceControlInput(node, control); NodeProperties::ReplaceControlInput(node, control);
...@@ -6022,9 +6039,11 @@ Reduction JSCallReducer::ReducePromisePrototypeThen(Node* node) { ...@@ -6022,9 +6039,11 @@ Reduction JSCallReducer::ReducePromisePrototypeThen(Node* node) {
// Check whether all {receiver_maps} are JSPromise maps and // Check whether all {receiver_maps} are JSPromise maps and
// have the initial Promise.prototype as their [[Prototype]]. // have the initial Promise.prototype as their [[Prototype]].
for (Handle<Map> receiver_map : receiver_maps) { for (Handle<Map> map : receiver_maps) {
if (!receiver_map->IsJSPromiseMap()) return NoChange(); MapRef receiver_map(broker(), map);
if (receiver_map->prototype() != native_context()->promise_prototype()) { if (!receiver_map.IsJSPromiseMap()) return NoChange();
if (!receiver_map.prototype().equals(
native_context().promise_prototype())) {
return NoChange(); return NoChange();
} }
} }
...@@ -6070,11 +6089,10 @@ Reduction JSCallReducer::ReducePromisePrototypeThen(Node* node) { ...@@ -6070,11 +6089,10 @@ Reduction JSCallReducer::ReducePromisePrototypeThen(Node* node) {
// doesn't escape to user JavaScript. So bake this information // doesn't escape to user JavaScript. So bake this information
// into the graph such that subsequent passes can use the // into the graph such that subsequent passes can use the
// information for further optimizations. // information for further optimizations.
Handle<Map> result_map(native_context()->promise_function()->initial_map(), MapRef result_map = native_context().promise_function().initial_map();
isolate()); effect = graph()->NewNode(
effect = simplified()->MapGuard(ZoneHandleSet<Map>(result_map.object())), result,
graph()->NewNode(simplified()->MapGuard(ZoneHandleSet<Map>(result_map)), effect, control);
result, effect, control);
ReplaceWithValue(node, result, effect, control); ReplaceWithValue(node, result, effect, control);
return Replace(result); return Replace(result);
...@@ -7070,8 +7088,8 @@ Reduction JSCallReducer::ReduceRegExpPrototypeTest(Node* node) { ...@@ -7070,8 +7088,8 @@ Reduction JSCallReducer::ReduceRegExpPrototypeTest(Node* node) {
// Compute property access info for "exec" on {resolution}. // Compute property access info for "exec" on {resolution}.
PropertyAccessInfo ai_exec; PropertyAccessInfo ai_exec;
AccessInfoFactory access_info_factory(broker(), dependencies(), AccessInfoFactory access_info_factory(
native_context(), graph()->zone()); broker(), dependencies(), native_context().object(), graph()->zone());
if (!access_info_factory.ComputePropertyAccessInfo( if (!access_info_factory.ComputePropertyAccessInfo(
MapHandles(regexp_maps.begin(), regexp_maps.end()), MapHandles(regexp_maps.begin(), regexp_maps.end()),
factory()->exec_string(), AccessMode::kLoad, &ai_exec)) { factory()->exec_string(), AccessMode::kLoad, &ai_exec)) {
...@@ -7141,13 +7159,13 @@ Reduction JSCallReducer::ReduceNumberConstructor(Node* node) { ...@@ -7141,13 +7159,13 @@ Reduction JSCallReducer::ReduceNumberConstructor(Node* node) {
Node* frame_state = NodeProperties::GetFrameStateInput(node); Node* frame_state = NodeProperties::GetFrameStateInput(node);
// Create the artificial frame state in the middle of the Number constructor. // Create the artificial frame state in the middle of the Number constructor.
Handle<SharedFunctionInfo> shared_info( SharedFunctionInfoRef shared_info =
handle(native_context()->number_function()->shared(), isolate())); native_context().number_function().shared();
Node* stack_parameters[] = {receiver}; Node* stack_parameters[] = {receiver};
int stack_parameter_count = arraysize(stack_parameters); int stack_parameter_count = arraysize(stack_parameters);
Node* continuation_frame_state = Node* continuation_frame_state =
CreateJavaScriptBuiltinContinuationFrameState( CreateJavaScriptBuiltinContinuationFrameState(
jsgraph(), shared_info, jsgraph(), shared_info.object(),
Builtins::kGenericConstructorLazyDeoptContinuation, target, context, Builtins::kGenericConstructorLazyDeoptContinuation, target, context,
stack_parameters, stack_parameter_count, frame_state, stack_parameters, stack_parameter_count, frame_state,
ContinuationFrameStateMode::LAZY); ContinuationFrameStateMode::LAZY);
...@@ -7165,11 +7183,6 @@ Isolate* JSCallReducer::isolate() const { return jsgraph()->isolate(); } ...@@ -7165,11 +7183,6 @@ Isolate* JSCallReducer::isolate() const { return jsgraph()->isolate(); }
Factory* JSCallReducer::factory() const { return isolate()->factory(); } Factory* JSCallReducer::factory() const { return isolate()->factory(); }
Handle<JSGlobalProxy> JSCallReducer::global_proxy() const {
return handle(JSGlobalProxy::cast(native_context()->global_proxy()),
isolate());
}
CommonOperatorBuilder* JSCallReducer::common() const { CommonOperatorBuilder* JSCallReducer::common() const {
return jsgraph()->common(); return jsgraph()->common();
} }
......
...@@ -39,13 +39,11 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer { ...@@ -39,13 +39,11 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer {
typedef base::Flags<Flag> Flags; typedef base::Flags<Flag> Flags;
JSCallReducer(Editor* editor, JSGraph* jsgraph, JSHeapBroker* broker, JSCallReducer(Editor* editor, JSGraph* jsgraph, JSHeapBroker* broker,
Flags flags, Handle<Context> native_context, Flags flags, CompilationDependencies* dependencies)
CompilationDependencies* dependencies)
: AdvancedReducer(editor), : AdvancedReducer(editor),
jsgraph_(jsgraph), jsgraph_(jsgraph),
broker_(broker), broker_(broker),
flags_(flags), flags_(flags),
native_context_(native_context),
dependencies_(dependencies) {} dependencies_(dependencies) {}
const char* reducer_name() const override { return "JSCallReducer"; } const char* reducer_name() const override { return "JSCallReducer"; }
...@@ -237,8 +235,7 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer { ...@@ -237,8 +235,7 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer {
JSHeapBroker* broker() const { return broker_; } JSHeapBroker* broker() const { return broker_; }
Isolate* isolate() const; Isolate* isolate() const;
Factory* factory() const; Factory* factory() const;
Handle<Context> native_context() const { return native_context_; } NativeContextRef native_context() const { return broker()->native_context(); }
Handle<JSGlobalProxy> global_proxy() const;
CommonOperatorBuilder* common() const; CommonOperatorBuilder* common() const;
JSOperatorBuilder* javascript() const; JSOperatorBuilder* javascript() const;
SimplifiedOperatorBuilder* simplified() const; SimplifiedOperatorBuilder* simplified() const;
...@@ -248,7 +245,6 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer { ...@@ -248,7 +245,6 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer {
JSGraph* const jsgraph_; JSGraph* const jsgraph_;
JSHeapBroker* const broker_; JSHeapBroker* const broker_;
Flags const flags_; Flags const flags_;
Handle<Context> const native_context_;
CompilationDependencies* const dependencies_; CompilationDependencies* const dependencies_;
std::set<Node*> waitlist_; std::set<Node*> waitlist_;
}; };
......
...@@ -47,7 +47,7 @@ bool IsAllocationInlineable(const JSFunctionRef& target, ...@@ -47,7 +47,7 @@ bool IsAllocationInlineable(const JSFunctionRef& target,
CHECK_IMPLIES(new_target.has_initial_map(), CHECK_IMPLIES(new_target.has_initial_map(),
!new_target.initial_map().is_dictionary_map()); !new_target.initial_map().is_dictionary_map());
return new_target.has_initial_map() && return new_target.has_initial_map() &&
new_target.initial_map().constructor_or_backpointer().equals(target); new_target.initial_map().GetConstructor().equals(target);
} }
// When initializing arrays, we'll unfold the loop if the number of // When initializing arrays, we'll unfold the loop if the number of
......
...@@ -628,10 +628,10 @@ class MapData : public HeapObjectData { ...@@ -628,10 +628,10 @@ class MapData : public HeapObjectData {
return instance_descriptors_; return instance_descriptors_;
} }
void SerializeConstructorOrBackpointer(JSHeapBroker* broker); void SerializeConstructor(JSHeapBroker* broker);
ObjectData* constructor_or_backpointer() const { ObjectData* GetConstructor() const {
CHECK(serialized_constructor_or_backpointer_); CHECK(serialized_constructor_);
return constructor_or_backpointer_; return constructor_;
} }
void SerializePrototype(JSHeapBroker* broker); void SerializePrototype(JSHeapBroker* broker);
...@@ -658,8 +658,8 @@ class MapData : public HeapObjectData { ...@@ -658,8 +658,8 @@ class MapData : public HeapObjectData {
bool serialized_own_descriptors_ = false; bool serialized_own_descriptors_ = false;
DescriptorArrayData* instance_descriptors_ = nullptr; DescriptorArrayData* instance_descriptors_ = nullptr;
bool serialized_constructor_or_backpointer_ = false; bool serialized_constructor_ = false;
ObjectData* constructor_or_backpointer_ = nullptr; ObjectData* constructor_ = nullptr;
bool serialized_prototype_ = false; bool serialized_prototype_ = false;
ObjectData* prototype_ = nullptr; ObjectData* prototype_ = nullptr;
...@@ -769,7 +769,7 @@ void JSFunctionData::Serialize(JSHeapBroker* broker) { ...@@ -769,7 +769,7 @@ void JSFunctionData::Serialize(JSHeapBroker* broker) {
if (initial_map_->instance_type() == JS_ARRAY_TYPE) { if (initial_map_->instance_type() == JS_ARRAY_TYPE) {
initial_map_->SerializeElementsKindGeneralizations(broker); initial_map_->SerializeElementsKindGeneralizations(broker);
} }
initial_map_->SerializeConstructorOrBackpointer(broker); initial_map_->SerializeConstructor(broker);
// TODO(neis): This is currently only needed for native_context's // TODO(neis): This is currently only needed for native_context's
// object_function, as used by GetObjectCreateMap. If no further use sites // object_function, as used by GetObjectCreateMap. If no further use sites
// show up, we should move this into NativeContextData::Serialize. // show up, we should move this into NativeContextData::Serialize.
...@@ -1187,15 +1187,14 @@ void JSObjectData::SerializeElements(JSHeapBroker* broker) { ...@@ -1187,15 +1187,14 @@ void JSObjectData::SerializeElements(JSHeapBroker* broker) {
elements_ = broker->GetOrCreateData(elements_object)->AsFixedArrayBase(); elements_ = broker->GetOrCreateData(elements_object)->AsFixedArrayBase();
} }
void MapData::SerializeConstructorOrBackpointer(JSHeapBroker* broker) { void MapData::SerializeConstructor(JSHeapBroker* broker) {
if (serialized_constructor_or_backpointer_) return; if (serialized_constructor_) return;
serialized_constructor_or_backpointer_ = true; serialized_constructor_ = true;
TraceScope tracer(broker, this, "MapData::SerializeConstructorOrBackpointer"); TraceScope tracer(broker, this, "MapData::SerializeConstructor");
Handle<Map> map = Handle<Map>::cast(object()); Handle<Map> map = Handle<Map>::cast(object());
DCHECK_NULL(constructor_or_backpointer_); DCHECK_NULL(constructor_);
constructor_or_backpointer_ = constructor_ = broker->GetOrCreateData(map->GetConstructor());
broker->GetOrCreateData(map->constructor_or_backpointer());
} }
void MapData::SerializePrototype(JSHeapBroker* broker) { void MapData::SerializePrototype(JSHeapBroker* broker) {
...@@ -2070,18 +2069,21 @@ BIMODAL_ACCESSOR_C(JSTypedArray, size_t, length_value) ...@@ -2070,18 +2069,21 @@ BIMODAL_ACCESSOR_C(JSTypedArray, size_t, length_value)
BIMODAL_ACCESSOR(JSTypedArray, HeapObject, buffer) BIMODAL_ACCESSOR(JSTypedArray, HeapObject, buffer)
BIMODAL_ACCESSOR_B(Map, bit_field2, elements_kind, Map::ElementsKindBits) BIMODAL_ACCESSOR_B(Map, bit_field2, elements_kind, Map::ElementsKindBits)
BIMODAL_ACCESSOR_B(Map, bit_field2, is_extensible, Map::IsExtensibleBit)
BIMODAL_ACCESSOR_B(Map, bit_field3, is_deprecated, Map::IsDeprecatedBit) BIMODAL_ACCESSOR_B(Map, bit_field3, is_deprecated, Map::IsDeprecatedBit)
BIMODAL_ACCESSOR_B(Map, bit_field3, is_dictionary_map, Map::IsDictionaryMapBit) BIMODAL_ACCESSOR_B(Map, bit_field3, is_dictionary_map, Map::IsDictionaryMapBit)
BIMODAL_ACCESSOR_B(Map, bit_field3, NumberOfOwnDescriptors, BIMODAL_ACCESSOR_B(Map, bit_field3, NumberOfOwnDescriptors,
Map::NumberOfOwnDescriptorsBits) Map::NumberOfOwnDescriptorsBits)
BIMODAL_ACCESSOR_B(Map, bit_field, has_prototype_slot, Map::HasPrototypeSlotBit) BIMODAL_ACCESSOR_B(Map, bit_field, has_prototype_slot, Map::HasPrototypeSlotBit)
BIMODAL_ACCESSOR_B(Map, bit_field, is_access_check_needed,
Map::IsAccessCheckNeededBit)
BIMODAL_ACCESSOR_B(Map, bit_field, is_callable, Map::IsCallableBit) BIMODAL_ACCESSOR_B(Map, bit_field, is_callable, Map::IsCallableBit)
BIMODAL_ACCESSOR_B(Map, bit_field, is_constructor, Map::IsConstructorBit) BIMODAL_ACCESSOR_B(Map, bit_field, is_constructor, Map::IsConstructorBit)
BIMODAL_ACCESSOR_B(Map, bit_field, is_undetectable, Map::IsUndetectableBit) BIMODAL_ACCESSOR_B(Map, bit_field, is_undetectable, Map::IsUndetectableBit)
BIMODAL_ACCESSOR_C(Map, int, instance_size) BIMODAL_ACCESSOR_C(Map, int, instance_size)
BIMODAL_ACCESSOR(Map, Object, prototype) BIMODAL_ACCESSOR(Map, Object, prototype)
BIMODAL_ACCESSOR_C(Map, InstanceType, instance_type) BIMODAL_ACCESSOR_C(Map, InstanceType, instance_type)
BIMODAL_ACCESSOR(Map, Object, constructor_or_backpointer) BIMODAL_ACCESSOR(Map, Object, GetConstructor)
#define DEF_NATIVE_CONTEXT_ACCESSOR(type, name) \ #define DEF_NATIVE_CONTEXT_ACCESSOR(type, name) \
BIMODAL_ACCESSOR(NativeContext, type, name) BIMODAL_ACCESSOR(NativeContext, type, name)
...@@ -2459,13 +2461,17 @@ void NativeContextData::Serialize(JSHeapBroker* broker) { ...@@ -2459,13 +2461,17 @@ void NativeContextData::Serialize(JSHeapBroker* broker) {
#define SERIALIZE_MEMBER(type, name) \ #define SERIALIZE_MEMBER(type, name) \
DCHECK_NULL(name##_); \ DCHECK_NULL(name##_); \
name##_ = broker->GetOrCreateData(context->name())->As##type(); \ name##_ = broker->GetOrCreateData(context->name())->As##type(); \
if (name##_->IsJSFunction()) name##_->AsJSFunction()->Serialize(broker); if (name##_->IsJSFunction()) name##_->AsJSFunction()->Serialize(broker); \
if (name##_->IsMap()) name##_->AsMap()->SerializeConstructor(broker);
BROKER_COMPULSORY_NATIVE_CONTEXT_FIELDS(SERIALIZE_MEMBER) BROKER_COMPULSORY_NATIVE_CONTEXT_FIELDS(SERIALIZE_MEMBER)
if (!broker->isolate()->bootstrapper()->IsActive()) { if (!broker->isolate()->bootstrapper()->IsActive()) {
BROKER_OPTIONAL_NATIVE_CONTEXT_FIELDS(SERIALIZE_MEMBER) BROKER_OPTIONAL_NATIVE_CONTEXT_FIELDS(SERIALIZE_MEMBER)
} }
#undef SERIALIZE_MEMBER #undef SERIALIZE_MEMBER
bound_function_with_constructor_map_->SerializePrototype(broker);
bound_function_without_constructor_map_->SerializePrototype(broker);
DCHECK(function_maps_.empty()); DCHECK(function_maps_.empty());
int const first = Context::FIRST_FUNCTION_MAP_INDEX; int const first = Context::FIRST_FUNCTION_MAP_INDEX;
int const last = Context::LAST_FUNCTION_MAP_INDEX; int const last = Context::LAST_FUNCTION_MAP_INDEX;
......
...@@ -258,9 +258,13 @@ class ContextRef : public HeapObjectRef { ...@@ -258,9 +258,13 @@ class ContextRef : public HeapObjectRef {
V(JSFunction, number_function) \ V(JSFunction, number_function) \
V(JSFunction, object_function) \ V(JSFunction, object_function) \
V(JSFunction, promise_function) \ V(JSFunction, promise_function) \
V(JSFunction, promise_then) \
V(JSFunction, string_function) \ V(JSFunction, string_function) \
V(JSFunction, symbol_function) \ V(JSFunction, symbol_function) \
V(JSGlobalProxy, global_proxy_object) \ V(JSGlobalProxy, global_proxy_object) \
V(JSObject, promise_prototype) \
V(Map, bound_function_with_constructor_map) \
V(Map, bound_function_without_constructor_map) \
V(Map, fast_aliased_arguments_map) \ V(Map, fast_aliased_arguments_map) \
V(Map, initial_array_iterator_map) \ V(Map, initial_array_iterator_map) \
V(Map, initial_string_iterator_map) \ V(Map, initial_string_iterator_map) \
...@@ -274,7 +278,11 @@ class ContextRef : public HeapObjectRef { ...@@ -274,7 +278,11 @@ class ContextRef : public HeapObjectRef {
V(Map, sloppy_arguments_map) \ V(Map, sloppy_arguments_map) \
V(Map, slow_object_with_null_prototype_map) \ V(Map, slow_object_with_null_prototype_map) \
V(Map, strict_arguments_map) \ V(Map, strict_arguments_map) \
V(ScriptContextTable, script_context_table) V(ScriptContextTable, script_context_table) \
V(SharedFunctionInfo, promise_capability_default_reject_shared_fun) \
V(SharedFunctionInfo, promise_catch_finally_shared_fun) \
V(SharedFunctionInfo, promise_then_finally_shared_fun) \
V(SharedFunctionInfo, promise_capability_default_resolve_shared_fun)
// Those are set by Bootstrapper::ExportFromRuntime, which may not yet have // Those are set by Bootstrapper::ExportFromRuntime, which may not yet have
// happened when Turbofan is invoked via --always-opt. // happened when Turbofan is invoked via --always-opt.
...@@ -378,8 +386,10 @@ class MapRef : public HeapObjectRef { ...@@ -378,8 +386,10 @@ class MapRef : public HeapObjectRef {
int constructor_function_index() const; int constructor_function_index() const;
ElementsKind elements_kind() const; ElementsKind elements_kind() const;
bool is_stable() const; bool is_stable() const;
bool is_extensible() const;
bool is_constructor() const; bool is_constructor() const;
bool has_prototype_slot() const; bool has_prototype_slot() const;
bool is_access_check_needed() const;
bool is_deprecated() const; bool is_deprecated() const;
bool CanBeDeprecated() const; bool CanBeDeprecated() const;
bool CanTransition() const; bool CanTransition() const;
...@@ -394,7 +404,7 @@ class MapRef : public HeapObjectRef { ...@@ -394,7 +404,7 @@ class MapRef : public HeapObjectRef {
INSTANCE_TYPE_CHECKERS(DEF_TESTER) INSTANCE_TYPE_CHECKERS(DEF_TESTER)
#undef DEF_TESTER #undef DEF_TESTER
ObjectRef constructor_or_backpointer() const; ObjectRef GetConstructor() const;
void SerializePrototype(); void SerializePrototype();
ObjectRef prototype() const; ObjectRef prototype() const;
......
...@@ -416,8 +416,7 @@ NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMaps( ...@@ -416,8 +416,7 @@ NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMaps(
if (original_constructor.has_initial_map()) { if (original_constructor.has_initial_map()) {
original_constructor.Serialize(); original_constructor.Serialize();
MapRef initial_map = original_constructor.initial_map(); MapRef initial_map = original_constructor.initial_map();
if (initial_map.constructor_or_backpointer().equals( if (initial_map.GetConstructor().equals(mtarget.Ref(broker))) {
mtarget.Ref(broker))) {
*maps_return = ZoneHandleSet<Map>(initial_map.object()); *maps_return = ZoneHandleSet<Map>(initial_map.object());
return result; return result;
} }
......
...@@ -1213,7 +1213,7 @@ struct InliningPhase { ...@@ -1213,7 +1213,7 @@ struct InliningPhase {
data->info()->is_bailout_on_uninitialized() data->info()->is_bailout_on_uninitialized()
? JSCallReducer::kBailoutOnUninitialized ? JSCallReducer::kBailoutOnUninitialized
: JSCallReducer::kNoFlags, : JSCallReducer::kNoFlags,
data->native_context(), data->dependencies()); data->dependencies());
JSContextSpecialization context_specialization( JSContextSpecialization context_specialization(
&graph_reducer, data->jsgraph(), data->broker(), &graph_reducer, data->jsgraph(), data->broker(),
ChooseSpecializationContext(isolate, data->info()), ChooseSpecializationContext(isolate, data->info()),
......
...@@ -38,7 +38,7 @@ class JSCallReducerTest : public TypedGraphTest { ...@@ -38,7 +38,7 @@ class JSCallReducerTest : public TypedGraphTest {
GraphReducer graph_reducer(zone(), graph()); GraphReducer graph_reducer(zone(), graph());
JSCallReducer reducer(&graph_reducer, &jsgraph, broker(), JSCallReducer reducer(&graph_reducer, &jsgraph, broker(),
JSCallReducer::kNoFlags, native_context(), &deps_); JSCallReducer::kNoFlags, &deps_);
return reducer.Reduce(node); return reducer.Reduce(node);
} }
......
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