aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/js-call-reducer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler/js-call-reducer.cc')
-rw-r--r--deps/v8/src/compiler/js-call-reducer.cc587
1 files changed, 285 insertions, 302 deletions
diff --git a/deps/v8/src/compiler/js-call-reducer.cc b/deps/v8/src/compiler/js-call-reducer.cc
index d16e38a458..4bc55c3abe 100644
--- a/deps/v8/src/compiler/js-call-reducer.cc
+++ b/deps/v8/src/compiler/js-call-reducer.cc
@@ -944,9 +944,10 @@ Reduction JSCallReducer::ReduceReflectHas(Node* node) {
Node* etrue = effect;
Node* vtrue;
{
+ // TODO(magardn): collect feedback so this can be optimized
vtrue = etrue = if_true =
- graph()->NewNode(javascript()->HasProperty(), target, key, context,
- frame_state, etrue, if_true);
+ graph()->NewNode(javascript()->HasProperty(VectorSlotPair()), target,
+ key, context, frame_state, etrue, if_true);
}
// Rewire potential exception edges.
@@ -1070,10 +1071,7 @@ Reduction JSCallReducer::ReduceArrayForEach(
return NoChange();
}
- // Install code dependencies on the {receiver} prototype maps and the
- // global array protector cell.
- dependencies()->DependOnProtector(
- PropertyCellRef(broker(), factory()->no_elements_protector()));
+ if (!dependencies()->DependOnNoElementsProtector()) UNREACHABLE();
// If we have unreliable maps, we need a map check.
if (result == NodeProperties::kUnreliableReceiverMaps) {
@@ -1089,9 +1087,9 @@ Reduction JSCallReducer::ReduceArrayForEach(
simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)), receiver,
effect, control);
- std::vector<Node*> checkpoint_params(
- {receiver, fncallback, this_arg, k, original_length});
- const int stack_parameters = static_cast<int>(checkpoint_params.size());
+ Node* checkpoint_params[] = {receiver, fncallback, this_arg, k,
+ original_length};
+ const int stack_parameters = arraysize(checkpoint_params);
// Check whether the given callback function is callable. Note that this has
// to happen outside the loop to make sure we also throw on empty arrays.
@@ -1111,7 +1109,7 @@ Reduction JSCallReducer::ReduceArrayForEach(
Node* continue_test =
graph()->NewNode(simplified()->NumberLessThan(), k, original_length);
- Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
+ Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kNone),
continue_test, control);
Node* if_true = graph()->NewNode(common()->IfTrue(), continue_branch);
@@ -1257,10 +1255,7 @@ Reduction JSCallReducer::ReduceArrayReduce(
}
};
- // Install code dependencies on the {receiver} prototype maps and the
- // global array protector cell.
- dependencies()->DependOnProtector(
- PropertyCellRef(broker(), factory()->no_elements_protector()));
+ if (!dependencies()->DependOnNoElementsProtector()) UNREACHABLE();
// If we have unreliable maps, we need a map check.
if (result == NodeProperties::kUnreliableReceiverMaps) {
@@ -1287,13 +1282,12 @@ Reduction JSCallReducer::ReduceArrayReduce(
Builtins::Name builtin_lazy =
left ? Builtins::kArrayReduceLoopLazyDeoptContinuation
: Builtins::kArrayReduceRightLoopLazyDeoptContinuation;
- const std::vector<Node*> checkpoint_params(
- {receiver, fncallback, k, original_length,
- jsgraph()->UndefinedConstant()});
- const int stack_parameters = static_cast<int>(checkpoint_params.size());
+ Node* checkpoint_params[] = {receiver, fncallback, k, original_length,
+ jsgraph()->UndefinedConstant()};
+ const int stack_parameters = arraysize(checkpoint_params);
check_frame_state = CreateJavaScriptBuiltinContinuationFrameState(
jsgraph(), shared, builtin_lazy, node->InputAt(0), context,
- checkpoint_params.data(), stack_parameters - 1, outer_frame_state,
+ &checkpoint_params[0], stack_parameters - 1, outer_frame_state,
ContinuationFrameStateMode::LAZY);
}
Node* check_fail = nullptr;
@@ -1315,13 +1309,12 @@ Reduction JSCallReducer::ReduceArrayReduce(
Builtins::Name builtin_eager =
left ? Builtins::kArrayReducePreLoopEagerDeoptContinuation
: Builtins::kArrayReduceRightPreLoopEagerDeoptContinuation;
- const std::vector<Node*> checkpoint_params(
- {receiver, fncallback, original_length});
- const int stack_parameters = static_cast<int>(checkpoint_params.size());
+ Node* checkpoint_params[] = {receiver, fncallback, original_length};
+ const int stack_parameters = arraysize(checkpoint_params);
Node* find_first_element_frame_state =
CreateJavaScriptBuiltinContinuationFrameState(
jsgraph(), shared, builtin_eager, node->InputAt(0), context,
- checkpoint_params.data(), stack_parameters, outer_frame_state,
+ &checkpoint_params[0], stack_parameters, outer_frame_state,
ContinuationFrameStateMode::EAGER);
Node* vloop = k = WireInLoopStart(k, &control, &effect);
@@ -1374,7 +1367,7 @@ Reduction JSCallReducer::ReduceArrayReduce(
: graph()->NewNode(simplified()->NumberLessThanOrEqual(),
jsgraph()->ZeroConstant(), k);
- Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
+ Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kNone),
continue_test, control);
Node* if_true = graph()->NewNode(common()->IfTrue(), continue_branch);
@@ -1385,12 +1378,12 @@ Reduction JSCallReducer::ReduceArrayReduce(
Builtins::Name builtin_eager =
left ? Builtins::kArrayReduceLoopEagerDeoptContinuation
: Builtins::kArrayReduceRightLoopEagerDeoptContinuation;
- const std::vector<Node*> checkpoint_params(
- {receiver, fncallback, k, original_length, curloop});
- const int stack_parameters = static_cast<int>(checkpoint_params.size());
+ Node* checkpoint_params[] = {receiver, fncallback, k, original_length,
+ curloop};
+ const int stack_parameters = arraysize(checkpoint_params);
Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
jsgraph(), shared, builtin_eager, node->InputAt(0), context,
- checkpoint_params.data(), stack_parameters, outer_frame_state,
+ &checkpoint_params[0], stack_parameters, outer_frame_state,
ContinuationFrameStateMode::EAGER);
effect =
graph()->NewNode(common()->Checkpoint(), frame_state, effect, control);
@@ -1431,12 +1424,12 @@ Reduction JSCallReducer::ReduceArrayReduce(
Builtins::Name builtin_lazy =
left ? Builtins::kArrayReduceLoopLazyDeoptContinuation
: Builtins::kArrayReduceRightLoopLazyDeoptContinuation;
- const std::vector<Node*> checkpoint_params(
- {receiver, fncallback, next_k, original_length, curloop});
- const int stack_parameters = static_cast<int>(checkpoint_params.size());
+ Node* checkpoint_params[] = {receiver, fncallback, next_k, original_length,
+ curloop};
+ const int stack_parameters = arraysize(checkpoint_params);
Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
jsgraph(), shared, builtin_lazy, node->InputAt(0), context,
- checkpoint_params.data(), stack_parameters - 1, outer_frame_state,
+ &checkpoint_params[0], stack_parameters - 1, outer_frame_state,
ContinuationFrameStateMode::LAZY);
next_cur = control = effect =
@@ -1526,12 +1519,9 @@ Reduction JSCallReducer::ReduceArrayMap(Node* node,
}
if (IsHoleyElementsKind(kind)) {
- dependencies()->DependOnProtector(
- PropertyCellRef(broker(), factory()->no_elements_protector()));
+ if (!dependencies()->DependOnNoElementsProtector()) UNREACHABLE();
}
-
- dependencies()->DependOnProtector(
- PropertyCellRef(broker(), factory()->array_species_protector()));
+ if (!dependencies()->DependOnArraySpeciesProtector()) UNREACHABLE();
Node* array_constructor = jsgraph()->Constant(
native_context().GetInitialJSArrayMap(kind).GetConstructor());
@@ -1550,6 +1540,13 @@ Reduction JSCallReducer::ReduceArrayMap(Node* node,
simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)), receiver,
effect, control);
+ // If the array length >= kMaxFastArrayLength, then CreateArray
+ // will create a dictionary. We should deopt in this case, and make sure
+ // not to attempt inlining again.
+ original_length = effect = graph()->NewNode(
+ simplified()->CheckBounds(p.feedback()), original_length,
+ jsgraph()->Constant(JSArray::kMaxFastArrayLength), effect, control);
+
// Even though {JSCreateArray} is not marked as {kNoThrow}, we can elide the
// exceptional projections because it cannot throw with the given parameters.
Node* a = control = effect = graph()->NewNode(
@@ -1557,9 +1554,9 @@ Reduction JSCallReducer::ReduceArrayMap(Node* node,
array_constructor, array_constructor, original_length, context,
outer_frame_state, effect, control);
- std::vector<Node*> checkpoint_params(
- {receiver, fncallback, this_arg, a, k, original_length});
- const int stack_parameters = static_cast<int>(checkpoint_params.size());
+ Node* checkpoint_params[] = {receiver, fncallback, this_arg,
+ a, k, original_length};
+ const int stack_parameters = arraysize(checkpoint_params);
// Check whether the given callback function is callable. Note that this has
// to happen outside the loop to make sure we also throw on empty arrays.
@@ -1579,7 +1576,7 @@ Reduction JSCallReducer::ReduceArrayMap(Node* node,
Node* continue_test =
graph()->NewNode(simplified()->NumberLessThan(), k, original_length);
- Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
+ Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kNone),
continue_test, control);
Node* if_true = graph()->NewNode(common()->IfTrue(), continue_branch);
@@ -1729,12 +1726,9 @@ Reduction JSCallReducer::ReduceArrayFilter(
const ElementsKind packed_kind = GetPackedElementsKind(kind);
if (IsHoleyElementsKind(kind)) {
- dependencies()->DependOnProtector(
- PropertyCellRef(broker(), factory()->no_elements_protector()));
+ if (!dependencies()->DependOnNoElementsProtector()) UNREACHABLE();
}
-
- dependencies()->DependOnProtector(
- PropertyCellRef(broker(), factory()->array_species_protector()));
+ if (!dependencies()->DependOnArraySpeciesProtector()) UNREACHABLE();
MapRef initial_map = native_context().GetInitialJSArrayMap(packed_kind);
@@ -1781,9 +1775,9 @@ Reduction JSCallReducer::ReduceArrayFilter(
// checkpoint_params yet, but that's okay because it'll never be called.
// Therefore, "to" is mentioned twice, once standing in for the k_value
// value.
- std::vector<Node*> checkpoint_params(
- {receiver, fncallback, this_arg, a, k, original_length, to, to});
- const int stack_parameters = static_cast<int>(checkpoint_params.size());
+ Node* checkpoint_params[] = {receiver, fncallback, this_arg, a,
+ k, original_length, to, to};
+ const int stack_parameters = arraysize(checkpoint_params);
Node* check_frame_state = CreateJavaScriptBuiltinContinuationFrameState(
jsgraph(), shared, Builtins::kArrayFilterLoopLazyDeoptContinuation,
@@ -1801,7 +1795,7 @@ Reduction JSCallReducer::ReduceArrayFilter(
Node* continue_test =
graph()->NewNode(simplified()->NumberLessThan(), k, original_length);
- Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
+ Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kNone),
continue_test, control);
Node* if_true = graph()->NewNode(common()->IfTrue(), continue_branch);
@@ -1809,9 +1803,9 @@ Reduction JSCallReducer::ReduceArrayFilter(
control = if_true;
{
- std::vector<Node*> checkpoint_params(
- {receiver, fncallback, this_arg, a, k, original_length, to});
- const int stack_parameters = static_cast<int>(checkpoint_params.size());
+ Node* checkpoint_params[] = {receiver, fncallback, this_arg, a,
+ k, original_length, to};
+ const int stack_parameters = arraysize(checkpoint_params);
Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
jsgraph(), shared, Builtins::kArrayFilterLoopEagerDeoptContinuation,
@@ -1866,9 +1860,9 @@ Reduction JSCallReducer::ReduceArrayFilter(
{
// This frame state is dealt with by hand in
// Builtins::kArrayFilterLoopLazyDeoptContinuation.
- std::vector<Node*> checkpoint_params(
- {receiver, fncallback, this_arg, a, k, original_length, element, to});
- const int stack_parameters = static_cast<int>(checkpoint_params.size());
+ Node* checkpoint_params[] = {receiver, fncallback, this_arg, a,
+ k, original_length, element, to};
+ const int stack_parameters = arraysize(checkpoint_params);
Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
jsgraph(), shared, Builtins::kArrayFilterLoopLazyDeoptContinuation,
@@ -1895,10 +1889,10 @@ Reduction JSCallReducer::ReduceArrayFilter(
// point in this case. This is safe, because re-evaluating a [ToBoolean]
// coercion is safe.
{
- std::vector<Node*> checkpoint_params({receiver, fncallback, this_arg, a, k,
- original_length, element, to,
- callback_value});
- const int stack_parameters = static_cast<int>(checkpoint_params.size());
+ Node* checkpoint_params[] = {receiver, fncallback, this_arg,
+ a, k, original_length,
+ element, to, callback_value};
+ const int stack_parameters = arraysize(checkpoint_params);
Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
jsgraph(), shared, Builtins::kArrayFilterLoopLazyDeoptContinuation,
node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
@@ -1997,10 +1991,7 @@ Reduction JSCallReducer::ReduceArrayFind(Node* node, ArrayFindVariant variant,
return NoChange();
}
- // Install code dependencies on the {receiver} prototype maps and the
- // global array protector cell.
- dependencies()->DependOnProtector(
- PropertyCellRef(broker(), factory()->no_elements_protector()));
+ if (!dependencies()->DependOnNoElementsProtector()) UNREACHABLE();
// If we have unreliable maps, we need a map check.
if (result == NodeProperties::kUnreliableReceiverMaps) {
@@ -2016,9 +2007,9 @@ Reduction JSCallReducer::ReduceArrayFind(Node* node, ArrayFindVariant variant,
simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)), receiver,
effect, control);
- std::vector<Node*> checkpoint_params(
- {receiver, fncallback, this_arg, k, original_length});
- const int stack_parameters = static_cast<int>(checkpoint_params.size());
+ Node* checkpoint_params[] = {receiver, fncallback, this_arg, k,
+ original_length};
+ const int stack_parameters = arraysize(checkpoint_params);
// Check whether the given callback function is callable. Note that this has
// to happen outside the loop to make sure we also throw on empty arrays.
@@ -2044,7 +2035,7 @@ Reduction JSCallReducer::ReduceArrayFind(Node* node, ArrayFindVariant variant,
Node* continue_test =
graph()->NewNode(simplified()->NumberLessThan(), k, original_length);
Node* continue_branch = graph()->NewNode(
- common()->Branch(BranchHint::kTrue), continue_test, control);
+ common()->Branch(BranchHint::kNone), continue_test, control);
control = graph()->NewNode(common()->IfTrue(), continue_branch);
if_false = graph()->NewNode(common()->IfFalse(), continue_branch);
}
@@ -2091,11 +2082,10 @@ Reduction JSCallReducer::ReduceArrayFind(Node* node, ArrayFindVariant variant,
// Call the callback.
Node* callback_value = nullptr;
{
- std::vector<Node*> call_checkpoint_params({receiver, fncallback, this_arg,
- next_k, original_length,
- if_found_return_value});
- const int call_stack_parameters =
- static_cast<int>(call_checkpoint_params.size());
+ Node* call_checkpoint_params[] = {receiver, fncallback,
+ this_arg, next_k,
+ original_length, if_found_return_value};
+ const int call_stack_parameters = arraysize(call_checkpoint_params);
Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
jsgraph(), shared, after_callback_lazy_continuation_builtin,
@@ -2317,12 +2307,9 @@ Reduction JSCallReducer::ReduceArrayEvery(Node* node,
}
if (IsHoleyElementsKind(kind)) {
- dependencies()->DependOnProtector(
- PropertyCellRef(broker(), factory()->no_elements_protector()));
+ if (!dependencies()->DependOnNoElementsProtector()) UNREACHABLE();
}
-
- dependencies()->DependOnProtector(
- PropertyCellRef(broker(), factory()->array_species_protector()));
+ if (!dependencies()->DependOnArraySpeciesProtector()) UNREACHABLE();
// If we have unreliable maps, we need a map check.
if (result == NodeProperties::kUnreliableReceiverMaps) {
@@ -2351,9 +2338,9 @@ Reduction JSCallReducer::ReduceArrayEvery(Node* node,
// This frame state doesn't ever call the deopt continuation, it's only
// necessary to specifiy a continuation in order to handle the exceptional
// case.
- std::vector<Node*> checkpoint_params(
- {receiver, fncallback, this_arg, k, original_length});
- const int stack_parameters = static_cast<int>(checkpoint_params.size());
+ Node* checkpoint_params[] = {receiver, fncallback, this_arg, k,
+ original_length};
+ const int stack_parameters = arraysize(checkpoint_params);
Node* check_frame_state = CreateJavaScriptBuiltinContinuationFrameState(
jsgraph(), shared, Builtins::kArrayEveryLoopLazyDeoptContinuation,
@@ -2369,7 +2356,7 @@ Reduction JSCallReducer::ReduceArrayEvery(Node* node,
Node* continue_test =
graph()->NewNode(simplified()->NumberLessThan(), k, original_length);
- Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
+ Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kNone),
continue_test, control);
Node* if_true = graph()->NewNode(common()->IfTrue(), continue_branch);
@@ -2377,9 +2364,9 @@ Reduction JSCallReducer::ReduceArrayEvery(Node* node,
control = if_true;
{
- std::vector<Node*> checkpoint_params(
- {receiver, fncallback, this_arg, k, original_length});
- const int stack_parameters = static_cast<int>(checkpoint_params.size());
+ Node* checkpoint_params[] = {receiver, fncallback, this_arg, k,
+ original_length};
+ const int stack_parameters = arraysize(checkpoint_params);
Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
jsgraph(), shared, Builtins::kArrayEveryLoopEagerDeoptContinuation,
@@ -2433,9 +2420,9 @@ Reduction JSCallReducer::ReduceArrayEvery(Node* node,
{
// This frame state is dealt with by hand in
// Builtins::kArrayEveryLoopLazyDeoptContinuation.
- std::vector<Node*> checkpoint_params(
- {receiver, fncallback, this_arg, k, original_length});
- const int stack_parameters = static_cast<int>(checkpoint_params.size());
+ Node* checkpoint_params[] = {receiver, fncallback, this_arg, k,
+ original_length};
+ const int stack_parameters = arraysize(checkpoint_params);
Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
jsgraph(), shared, Builtins::kArrayEveryLoopLazyDeoptContinuation,
@@ -2565,23 +2552,36 @@ Reduction JSCallReducer::ReduceArrayIndexOfIncludes(
return NoChange();
}
- Handle<Map> map;
- if (!NodeProperties::GetMapWitness(broker(), node).ToHandle(&map))
+ Node* receiver = NodeProperties::GetValueInput(node, 1);
+ Node* effect = NodeProperties::GetEffectInput(node);
+ Node* control = NodeProperties::GetControlInput(node);
+
+ ZoneHandleSet<Map> receiver_maps;
+ NodeProperties::InferReceiverMapsResult result =
+ NodeProperties::InferReceiverMaps(broker(), receiver, effect,
+ &receiver_maps);
+ if (result == NodeProperties::kNoReceiverMaps) return NoChange();
+
+ ElementsKind kind;
+ if (!CanInlineArrayIteratingBuiltin(broker(), receiver_maps, &kind)) {
return NoChange();
+ }
- MapRef receiver_map(broker(), map);
- if (!receiver_map.supports_fast_array_iteration()) return NoChange();
+ if (IsHoleyElementsKind(kind)) {
+ if (!dependencies()->DependOnNoElementsProtector()) UNREACHABLE();
+ }
- ElementsKind const elements_kind = receiver_map.elements_kind();
- if (IsHoleyElementsKind(elements_kind)) {
- dependencies()->DependOnProtector(
- PropertyCellRef(broker(), factory()->no_elements_protector()));
+ // If we have unreliable maps, we need a map check.
+ if (result == NodeProperties::kUnreliableReceiverMaps) {
+ effect =
+ graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
+ receiver_maps, p.feedback()),
+ receiver, effect, control);
}
- Callable const callable =
- search_variant == SearchVariant::kIndexOf
- ? GetCallableForArrayIndexOf(elements_kind, isolate())
- : GetCallableForArrayIncludes(elements_kind, isolate());
+ Callable const callable = search_variant == SearchVariant::kIndexOf
+ ? GetCallableForArrayIndexOf(kind, isolate())
+ : GetCallableForArrayIncludes(kind, isolate());
CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
graph()->zone(), callable.descriptor(),
callable.descriptor().GetStackParameterCount(), CallDescriptor::kNoFlags,
@@ -2589,9 +2589,6 @@ Reduction JSCallReducer::ReduceArrayIndexOfIncludes(
// The stub expects the following arguments: the receiver array, its elements,
// the search_element, the array length, and the index to start searching
// from.
- Node* receiver = NodeProperties::GetValueInput(node, 1);
- Node* effect = NodeProperties::GetEffectInput(node);
- Node* control = NodeProperties::GetControlInput(node);
Node* elements = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver,
effect, control);
@@ -2599,8 +2596,8 @@ Reduction JSCallReducer::ReduceArrayIndexOfIncludes(
? NodeProperties::GetValueInput(node, 2)
: jsgraph()->UndefinedConstant();
Node* length = effect = graph()->NewNode(
- simplified()->LoadField(AccessBuilder::ForJSArrayLength(elements_kind)),
- receiver, effect, control);
+ simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)), receiver,
+ effect, control);
Node* new_from_index = jsgraph()->ZeroConstant();
if (node->op()->ValueInputCount() >= 4) {
Node* from_index = NodeProperties::GetValueInput(node, 3);
@@ -2664,12 +2661,9 @@ Reduction JSCallReducer::ReduceArraySome(Node* node,
}
if (IsHoleyElementsKind(kind)) {
- dependencies()->DependOnProtector(
- PropertyCellRef(broker(), factory()->no_elements_protector()));
+ if (!dependencies()->DependOnNoElementsProtector()) UNREACHABLE();
}
-
- dependencies()->DependOnProtector(
- PropertyCellRef(broker(), factory()->array_species_protector()));
+ if (!dependencies()->DependOnArraySpeciesProtector()) UNREACHABLE();
Node* k = jsgraph()->ZeroConstant();
@@ -2698,9 +2692,9 @@ Reduction JSCallReducer::ReduceArraySome(Node* node,
// This frame state doesn't ever call the deopt continuation, it's only
// necessary to specifiy a continuation in order to handle the exceptional
// case.
- std::vector<Node*> checkpoint_params(
- {receiver, fncallback, this_arg, k, original_length});
- const int stack_parameters = static_cast<int>(checkpoint_params.size());
+ Node* checkpoint_params[] = {receiver, fncallback, this_arg, k,
+ original_length};
+ const int stack_parameters = arraysize(checkpoint_params);
Node* check_frame_state = CreateJavaScriptBuiltinContinuationFrameState(
jsgraph(), shared, Builtins::kArraySomeLoopLazyDeoptContinuation,
@@ -2721,7 +2715,7 @@ Reduction JSCallReducer::ReduceArraySome(Node* node,
Node* continue_test =
graph()->NewNode(simplified()->NumberLessThan(), k, original_length);
- Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
+ Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kNone),
continue_test, control);
Node* if_true = graph()->NewNode(common()->IfTrue(), continue_branch);
@@ -2729,9 +2723,9 @@ Reduction JSCallReducer::ReduceArraySome(Node* node,
control = if_true;
{
- std::vector<Node*> checkpoint_params(
- {receiver, fncallback, this_arg, k, original_length});
- const int stack_parameters = static_cast<int>(checkpoint_params.size());
+ Node* checkpoint_params[] = {receiver, fncallback, this_arg, k,
+ original_length};
+ const int stack_parameters = arraysize(checkpoint_params);
Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
jsgraph(), shared, Builtins::kArraySomeLoopEagerDeoptContinuation,
@@ -2785,9 +2779,9 @@ Reduction JSCallReducer::ReduceArraySome(Node* node,
{
// This frame state is dealt with by hand in
// Builtins::kArrayEveryLoopLazyDeoptContinuation.
- std::vector<Node*> checkpoint_params(
- {receiver, fncallback, this_arg, k, original_length});
- const int stack_parameters = static_cast<int>(checkpoint_params.size());
+ Node* checkpoint_params[] = {receiver, fncallback, this_arg, k,
+ original_length};
+ const int stack_parameters = arraysize(checkpoint_params);
Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
jsgraph(), shared, Builtins::kArraySomeLoopLazyDeoptContinuation,
@@ -2866,68 +2860,116 @@ Reduction JSCallReducer::ReduceCallApiFunction(
DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
CallParameters const& p = CallParametersOf(node->op());
int const argc = static_cast<int>(p.arity()) - 2;
- Node* target = NodeProperties::GetValueInput(node, 0);
- Node* receiver =
- (p.convert_mode() == ConvertReceiverMode::kNullOrUndefined)
- ? jsgraph()->Constant(native_context().global_proxy_object())
- : NodeProperties::GetValueInput(node, 1);
+ Node* global_proxy =
+ jsgraph()->Constant(native_context().global_proxy_object());
+ Node* receiver = (p.convert_mode() == ConvertReceiverMode::kNullOrUndefined)
+ ? global_proxy
+ : NodeProperties::GetValueInput(node, 1);
+ Node* holder;
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
+ // See if we can optimize this API call to {shared}.
Handle<FunctionTemplateInfo> function_template_info(
FunctionTemplateInfo::cast(shared.object()->function_data()), isolate());
+ CallOptimization call_optimization(isolate(), function_template_info);
+ if (!call_optimization.is_simple_api_call()) return NoChange();
- // Infer the {receiver} maps, and check if we can inline the API function
- // callback based on those.
+ // Try to infer the {receiver} maps from the graph.
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(broker(), receiver, effect,
&receiver_maps);
- if (result == NodeProperties::kNoReceiverMaps) return NoChange();
- for (Handle<Map> map : receiver_maps) {
- MapRef receiver_map(broker(), map);
- if (!receiver_map.IsJSObjectMap() ||
- (!function_template_info->accept_any_receiver() &&
- receiver_map.is_access_check_needed())) {
- return NoChange();
- }
- // In case of unreliable {receiver} information, the {receiver_maps}
- // must all be stable in order to consume the information.
- if (result == NodeProperties::kUnreliableReceiverMaps) {
- if (!receiver_map.is_stable()) return NoChange();
- }
- }
-
- // See if we can constant-fold the compatible receiver checks.
- CallOptimization call_optimization(isolate(), function_template_info);
- if (!call_optimization.is_simple_api_call()) return NoChange();
- CallOptimization::HolderLookup lookup;
- Handle<JSObject> api_holder =
- call_optimization.LookupHolderOfExpectedType(receiver_maps[0], &lookup);
- if (lookup == CallOptimization::kHolderNotFound) return NoChange();
- for (size_t i = 1; i < receiver_maps.size(); ++i) {
- CallOptimization::HolderLookup lookupi;
- Handle<JSObject> holder = call_optimization.LookupHolderOfExpectedType(
- receiver_maps[i], &lookupi);
- if (lookup != lookupi) return NoChange();
- if (!api_holder.is_identical_to(holder)) return NoChange();
- }
-
- // Install stability dependencies for unreliable {receiver_maps}.
- if (result == NodeProperties::kUnreliableReceiverMaps) {
+ if (result != NodeProperties::kNoReceiverMaps) {
+ // Check that all {receiver_maps} are actually JSReceiver maps and
+ // that the {function_template_info} accepts them without access
+ // checks (even if "access check needed" is set for {receiver}).
+ //
+ // Note that we don't need to know the concrete {receiver} maps here,
+ // meaning it's fine if the {receiver_maps} are unreliable, and we also
+ // don't need to install any stability dependencies, since the only
+ // relevant information regarding the {receiver} is the Map::constructor
+ // field on the root map (which is different from the JavaScript exposed
+ // "constructor" property) and that field cannot change.
+ //
+ // So if we know that {receiver} had a certain constructor at some point
+ // in the past (i.e. it had a certain map), then this constructor is going
+ // to be the same later, since this information cannot change with map
+ // transitions.
+ //
+ // The same is true for the instance type, e.g. we still know that the
+ // instance type is JSObject even if that information is unreliable, and
+ // the "access check needed" bit, which also cannot change later.
for (Handle<Map> map : receiver_maps) {
MapRef receiver_map(broker(), map);
- dependencies()->DependOnStableMap(receiver_map);
+ if (!receiver_map.IsJSReceiverMap() ||
+ (receiver_map.is_access_check_needed() &&
+ !function_template_info->accept_any_receiver())) {
+ return NoChange();
+ }
}
- }
- // Load the {target}s context.
- Node* context = effect = graph()->NewNode(
- simplified()->LoadField(AccessBuilder::ForJSFunctionContext()), target,
- effect, control);
+ // See if we can constant-fold the compatible receiver checks.
+ CallOptimization::HolderLookup lookup;
+ Handle<JSObject> api_holder =
+ call_optimization.LookupHolderOfExpectedType(receiver_maps[0], &lookup);
+ if (lookup == CallOptimization::kHolderNotFound) return NoChange();
+ for (size_t i = 1; i < receiver_maps.size(); ++i) {
+ CallOptimization::HolderLookup lookupi;
+ Handle<JSObject> holderi = call_optimization.LookupHolderOfExpectedType(
+ receiver_maps[i], &lookupi);
+ if (lookup != lookupi) return NoChange();
+ if (!api_holder.is_identical_to(holderi)) return NoChange();
+ }
+
+ // Determine the appropriate holder for the {lookup}.
+ holder = lookup == CallOptimization::kHolderFound
+ ? jsgraph()->HeapConstant(api_holder)
+ : receiver;
+ } else if (function_template_info->accept_any_receiver() &&
+ function_template_info->signature()->IsUndefined(isolate())) {
+ // We haven't found any {receiver_maps}, but we might still be able to
+ // optimize the API call depending on the {function_template_info}.
+ // If the API function accepts any kind of {receiver}, we only need to
+ // ensure that the {receiver} is actually a JSReceiver at this point,
+ // and also pass that as the {holder}. There are two independent bits
+ // here:
+ //
+ // a. When the "accept any receiver" bit is set, it means we don't
+ // need to perform access checks, even if the {receiver}'s map
+ // has the "needs access check" bit set.
+ // b. When the {function_template_info} has no signature, we don't
+ // need to do the compatible receiver check, since all receivers
+ // are considered compatible at that point, and the {receiver}
+ // will be pass as the {holder}.
+ //
+ receiver = holder = effect =
+ graph()->NewNode(simplified()->ConvertReceiver(p.convert_mode()),
+ receiver, global_proxy, effect, control);
+ } else {
+ // We don't have enough information to eliminate the access check
+ // and/or the compatible receiver check, so use the generic builtin
+ // that does those checks dynamically. This is still significantly
+ // faster than the generic call sequence.
+ Builtins::Name builtin_name =
+ !function_template_info->accept_any_receiver()
+ ? (function_template_info->signature()->IsUndefined(isolate())
+ ? Builtins::kCallFunctionTemplate_CheckAccess
+ : Builtins::
+ kCallFunctionTemplate_CheckAccessAndCompatibleReceiver)
+ : Builtins::kCallFunctionTemplate_CheckCompatibleReceiver;
+ Callable callable = Builtins::CallableFor(isolate(), builtin_name);
+ auto call_descriptor = Linkage::GetStubCallDescriptor(
+ graph()->zone(), callable.descriptor(),
+ argc + 1 /* implicit receiver */, CallDescriptor::kNeedsFrameState);
+ node->InsertInput(graph()->zone(), 0,
+ jsgraph()->HeapConstant(callable.code()));
+ node->ReplaceInput(1, jsgraph()->HeapConstant(function_template_info));
+ node->InsertInput(graph()->zone(), 2, jsgraph()->Constant(argc));
+ NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
+ return Changed(node);
+ }
- // CallApiCallbackStub's register arguments: code, target, call data, holder,
- // function address.
// TODO(turbofan): Consider introducing a JSCallApiCallback operator for
// this and lower it during JSGenericLowering, and unify this with the
// JSNativeContextSpecialization::InlineApiCall method a bit.
@@ -2937,25 +2979,18 @@ Reduction JSCallReducer::ReduceCallApiFunction(
Callable call_api_callback = CodeFactory::CallApiCallback(isolate());
CallInterfaceDescriptor cid = call_api_callback.descriptor();
auto call_descriptor = Linkage::GetStubCallDescriptor(
- graph()->zone(), cid,
- cid.GetStackParameterCount() + argc + 1 /* implicit receiver */,
+ graph()->zone(), cid, argc + 1 /* implicit receiver */,
CallDescriptor::kNeedsFrameState);
ApiFunction api_function(v8::ToCData<Address>(call_handler_info->callback()));
- Node* holder = lookup == CallOptimization::kHolderFound
- ? jsgraph()->HeapConstant(api_holder)
- : receiver;
ExternalReference function_reference = ExternalReference::Create(
&api_function, ExternalReference::DIRECT_API_CALL);
node->InsertInput(graph()->zone(), 0,
jsgraph()->HeapConstant(call_api_callback.code()));
- node->ReplaceInput(1, context);
- node->InsertInput(graph()->zone(), 2,
- jsgraph()->ExternalConstant(function_reference));
- node->InsertInput(graph()->zone(), 3, jsgraph()->Constant(argc));
- node->InsertInput(graph()->zone(), 4, jsgraph()->Constant(data));
- node->InsertInput(graph()->zone(), 5, holder);
- node->ReplaceInput(6, receiver);
- node->RemoveInput(7 + argc); // Remove context input.
+ node->ReplaceInput(1, jsgraph()->ExternalConstant(function_reference));
+ node->InsertInput(graph()->zone(), 2, jsgraph()->Constant(argc));
+ node->InsertInput(graph()->zone(), 3, jsgraph()->Constant(data));
+ node->InsertInput(graph()->zone(), 4, holder);
+ node->ReplaceInput(5, receiver); // Update receiver input.
node->ReplaceInput(8 + argc, effect); // Update effect input.
NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
return Changed(node);
@@ -3094,8 +3129,7 @@ Reduction JSCallReducer::ReduceCallOrConstructWithArrayLikeOrSpread(
// that no one messed with the %ArrayIteratorPrototype%.next method.
if (node->opcode() == IrOpcode::kJSCallWithSpread ||
node->opcode() == IrOpcode::kJSConstructWithSpread) {
- dependencies()->DependOnProtector(
- PropertyCellRef(broker(), factory()->array_iterator_protector()));
+ if (!dependencies()->DependOnArrayIteratorProtector()) UNREACHABLE();
}
// Remove the {arguments_list} input from the {node}.
@@ -3332,12 +3366,8 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) {
if (!p.feedback().IsValid()) return NoChange();
FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot());
if (nexus.IsUninitialized()) {
- if (flags() & kBailoutOnUninitialized) {
- // Introduce a SOFT deopt if the call {node} wasn't executed so far.
- return ReduceSoftDeoptimize(
- node, DeoptimizeReason::kInsufficientTypeFeedbackForCall);
- }
- return NoChange();
+ return ReduceSoftDeoptimize(
+ node, DeoptimizeReason::kInsufficientTypeFeedbackForCall);
}
base::Optional<HeapObjectRef> feedback =
@@ -3752,13 +3782,8 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) {
if (p.feedback().IsValid()) {
FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot());
if (nexus.IsUninitialized()) {
- if (flags() & kBailoutOnUninitialized) {
- // Introduce a SOFT deopt if the construct {node} wasn't executed so
- // far.
- return ReduceSoftDeoptimize(
- node, DeoptimizeReason::kInsufficientTypeFeedbackForConstruct);
- }
- return NoChange();
+ return ReduceSoftDeoptimize(
+ node, DeoptimizeReason::kInsufficientTypeFeedbackForConstruct);
}
base::Optional<HeapObjectRef> feedback =
@@ -4304,18 +4329,21 @@ Reduction JSCallReducer::ReduceReturnReceiver(Node* node) {
Reduction JSCallReducer::ReduceSoftDeoptimize(Node* node,
DeoptimizeReason reason) {
- Node* effect = NodeProperties::GetEffectInput(node);
- Node* control = NodeProperties::GetControlInput(node);
- Node* frame_state = NodeProperties::FindFrameStateBefore(node);
- Node* deoptimize = graph()->NewNode(
- common()->Deoptimize(DeoptimizeKind::kSoft, reason, VectorSlotPair()),
- frame_state, effect, control);
- // TODO(bmeurer): This should be on the AdvancedReducer somehow.
- NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
- Revisit(graph()->end());
- node->TrimInputCount(0);
- NodeProperties::ChangeOp(node, common()->Dead());
- return Changed(node);
+ if (flags() & kBailoutOnUninitialized) {
+ Node* effect = NodeProperties::GetEffectInput(node);
+ Node* control = NodeProperties::GetControlInput(node);
+ Node* frame_state = NodeProperties::FindFrameStateBefore(node);
+ Node* deoptimize = graph()->NewNode(
+ common()->Deoptimize(DeoptimizeKind::kSoft, reason, VectorSlotPair()),
+ frame_state, effect, control);
+ // TODO(bmeurer): This should be on the AdvancedReducer somehow.
+ NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
+ Revisit(graph()->end());
+ node->TrimInputCount(0);
+ NodeProperties::ChangeOp(node, common()->Dead());
+ return Changed(node);
+ }
+ return NoChange();
}
// ES6 section 22.1.3.18 Array.prototype.push ( )
@@ -4343,8 +4371,7 @@ Reduction JSCallReducer::ReduceArrayPrototypePush(Node* node) {
return NoChange();
}
- dependencies()->DependOnProtector(
- PropertyCellRef(broker(), factory()->no_elements_protector()));
+ if (!dependencies()->DependOnNoElementsProtector()) UNREACHABLE();
// If the {receiver_maps} information is not reliable, we need
// to check that the {receiver} still has one of these maps.
@@ -4448,8 +4475,7 @@ Reduction JSCallReducer::ReduceArrayPrototypePop(Node* node) {
return NoChange();
}
- dependencies()->DependOnProtector(
- PropertyCellRef(broker(), factory()->no_elements_protector()));
+ if (!dependencies()->DependOnNoElementsProtector()) UNREACHABLE();
// If the {receiver_maps} information is not reliable, we need
// to check that the {receiver} still has one of these maps.
@@ -4558,8 +4584,7 @@ Reduction JSCallReducer::ReduceArrayPrototypeShift(Node* node) {
return NoChange();
}
- dependencies()->DependOnProtector(
- PropertyCellRef(broker(), factory()->no_elements_protector()));
+ if (!dependencies()->DependOnNoElementsProtector()) UNREACHABLE();
// If the {receiver_maps} information is not reliable, we need
// to check that the {receiver} still has one of these maps.
@@ -4770,15 +4795,10 @@ Reduction JSCallReducer::ReduceArrayPrototypeSlice(Node* node) {
}
}
- // Install code dependency on the Array[@@species] protector.
- dependencies()->DependOnProtector(
- PropertyCellRef(broker(), factory()->array_species_protector()));
-
- // Install code dependency on the array protector for holey arrays.
if (can_be_holey) {
- dependencies()->DependOnProtector(
- PropertyCellRef(broker(), factory()->no_elements_protector()));
+ if (!dependencies()->DependOnNoElementsProtector()) UNREACHABLE();
}
+ if (!dependencies()->DependOnArraySpeciesProtector()) UNREACHABLE();
// If we have unreliable maps, we need a map check, as there might be
// side-effects caused by the evaluation of the {node}s parameters.
@@ -4931,8 +4951,7 @@ Reduction JSCallReducer::ReduceArrayIteratorPrototypeNext(Node* node) {
// Install code dependency on the array protector for holey arrays.
if (IsHoleyElementsKind(elements_kind)) {
- dependencies()->DependOnProtector(
- PropertyCellRef(broker(), factory()->no_elements_protector()));
+ if (!dependencies()->DependOnNoElementsProtector()) UNREACHABLE();
}
// Load the (current) {iterated_object} from the {iterator}.
@@ -4949,12 +4968,7 @@ Reduction JSCallReducer::ReduceArrayIteratorPrototypeNext(Node* node) {
if (IsFixedTypedArrayElementsKind(elements_kind)) {
// See if we can skip the detaching check.
- if (isolate()->IsArrayBufferDetachingIntact()) {
- // Add a code dependency so we are deoptimized in case an ArrayBuffer
- // gets detached.
- dependencies()->DependOnProtector(PropertyCellRef(
- broker(), factory()->array_buffer_detaching_protector()));
- } else {
+ if (!dependencies()->DependOnArrayBufferDetachingProtector()) {
// Bail out if the {iterated_object}s JSArrayBuffer was detached.
Node* buffer = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
@@ -5013,7 +5027,7 @@ Reduction JSCallReducer::ReduceArrayIteratorPrototypeNext(Node* node) {
// Check whether {index} is within the valid range for the {iterated_object}.
Node* check = graph()->NewNode(simplified()->NumberLessThan(), index, length);
Node* branch =
- graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
+ graph()->NewNode(common()->Branch(BranchHint::kNone), check, control);
Node* done_true;
Node* value_true;
@@ -5355,7 +5369,7 @@ Reduction JSCallReducer::ReduceStringIteratorPrototypeNext(Node* node) {
Node* check0 =
graph()->NewNode(simplified()->NumberLessThan(), index, length);
Node* branch0 =
- graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
+ graph()->NewNode(common()->Branch(BranchHint::kNone), check0, control);
Node* etrue0 = effect;
Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
@@ -5490,13 +5504,11 @@ Reduction JSCallReducer::ReducePromiseConstructor(Node* node) {
Node* control = NodeProperties::GetControlInput(node);
if (!FLAG_experimental_inline_promise_constructor) return NoChange();
- if (!isolate()->IsPromiseHookProtectorIntact()) return NoChange();
// Only handle builtins Promises, not subclasses.
if (target != new_target) return NoChange();
- dependencies()->DependOnProtector(
- PropertyCellRef(broker(), factory()->promise_hook_protector()));
+ if (!dependencies()->DependOnPromiseHookProtector()) return NoChange();
SharedFunctionInfoRef promise_shared =
native_context().promise_function().shared();
@@ -5648,10 +5660,7 @@ Reduction JSCallReducer::ReducePromiseInternalConstructor(Node* node) {
Node* effect = NodeProperties::GetEffectInput(node);
// Check that promises aren't being observed through (debug) hooks.
- if (!isolate()->IsPromiseHookProtectorIntact()) return NoChange();
-
- dependencies()->DependOnProtector(
- PropertyCellRef(broker(), factory()->promise_hook_protector()));
+ if (!dependencies()->DependOnPromiseHookProtector()) return NoChange();
// Create a new pending promise.
Node* value = effect =
@@ -5720,12 +5729,6 @@ Reduction JSCallReducer::ReducePromisePrototypeCatch(Node* node) {
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
- // Check that the Promise.then protector is intact. This protector guards
- // that all JSPromise instances whose [[Prototype]] is the initial
- // %PromisePrototype% yield the initial %PromisePrototype%.then method
- // when looking up "then".
- if (!isolate()->IsPromiseThenLookupChainIntact()) return NoChange();
-
// Check if we know something about {receiver} already.
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult result =
@@ -5746,8 +5749,11 @@ Reduction JSCallReducer::ReducePromisePrototypeCatch(Node* node) {
}
}
- dependencies()->DependOnProtector(
- PropertyCellRef(broker(), factory()->promise_then_protector()));
+ // Check that the Promise.then protector is intact. This protector guards
+ // that all JSPromise instances whose [[Prototype]] is the initial
+ // %PromisePrototype% yield the initial %PromisePrototype%.then method
+ // when looking up "then".
+ if (!dependencies()->DependOnPromiseThenProtector()) return NoChange();
// If the {receiver_maps} aren't reliable, we need to repeat the
// map check here, guarded by the CALL_IC.
@@ -5790,21 +5796,6 @@ Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) {
return NoChange();
}
- // Check that promises aren't being observed through (debug) hooks.
- if (!isolate()->IsPromiseHookProtectorIntact()) return NoChange();
-
- // Check that the Promise#then protector is intact. This protector guards
- // that all JSPromise instances whose [[Prototype]] is the initial
- // %PromisePrototype% yield the initial %PromisePrototype%.then method
- // when looking up "then".
- if (!isolate()->IsPromiseThenLookupChainIntact()) return NoChange();
-
- // Also check that the @@species protector is intact, which guards the
- // lookup of "constructor" on JSPromise instances, whoch [[Prototype]] is
- // the initial %PromisePrototype%, and the Symbol.species lookup on the
- // %PromisePrototype%.
- if (!isolate()->IsPromiseSpeciesLookupChainIntact()) return NoChange();
-
// Check if we know something about {receiver} already.
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult result =
@@ -5825,12 +5816,20 @@ Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) {
}
}
- dependencies()->DependOnProtector(
- PropertyCellRef(broker(), factory()->promise_hook_protector()));
- dependencies()->DependOnProtector(
- PropertyCellRef(broker(), factory()->promise_then_protector()));
- dependencies()->DependOnProtector(
- PropertyCellRef(broker(), factory()->promise_species_protector()));
+ // Check that promises aren't being observed through (debug) hooks.
+ if (!dependencies()->DependOnPromiseHookProtector()) return NoChange();
+
+ // Check that the Promise#then protector is intact. This protector guards
+ // that all JSPromise instances whose [[Prototype]] is the initial
+ // %PromisePrototype% yield the initial %PromisePrototype%.then method
+ // when looking up "then".
+ if (!dependencies()->DependOnPromiseThenProtector()) return NoChange();
+
+ // Also check that the @@species protector is intact, which guards the
+ // lookup of "constructor" on JSPromise instances, whoch [[Prototype]] is
+ // the initial %PromisePrototype%, and the Symbol.species lookup on the
+ // %PromisePrototype%.
+ if (!dependencies()->DependOnPromiseSpeciesProtector()) return NoChange();
// If the {receiver_maps} aren't reliable, we need to repeat the
// map check here, guarded by the CALL_IC.
@@ -5951,15 +5950,6 @@ Reduction JSCallReducer::ReducePromisePrototypeThen(Node* node) {
Node* control = NodeProperties::GetControlInput(node);
Node* frame_state = NodeProperties::GetFrameStateInput(node);
- // Check that promises aren't being observed through (debug) hooks.
- if (!isolate()->IsPromiseHookProtectorIntact()) return NoChange();
-
- // Check if the @@species protector is intact. The @@species protector
- // guards the "constructor" lookup on all JSPromise instances and the
- // initial Promise.prototype, as well as the Symbol.species lookup on
- // the Promise constructor.
- if (!isolate()->IsPromiseSpeciesLookupChainIntact()) return NoChange();
-
// Check if we know something about {receiver} already.
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult infer_receiver_maps_result =
@@ -5982,10 +5972,14 @@ Reduction JSCallReducer::ReducePromisePrototypeThen(Node* node) {
}
}
- dependencies()->DependOnProtector(
- PropertyCellRef(broker(), factory()->promise_hook_protector()));
- dependencies()->DependOnProtector(
- PropertyCellRef(broker(), factory()->promise_species_protector()));
+ // Check that promises aren't being observed through (debug) hooks.
+ if (!dependencies()->DependOnPromiseHookProtector()) return NoChange();
+
+ // Check if the @@species protector is intact. The @@species protector
+ // guards the "constructor" lookup on all JSPromise instances and the
+ // initial Promise.prototype, as well as the Symbol.species lookup on
+ // the Promise constructor.
+ if (!dependencies()->DependOnPromiseSpeciesProtector()) return NoChange();
// If the {receiver_maps} aren't reliable, we need to repeat the
// map check here, guarded by the CALL_IC.
@@ -6676,12 +6670,7 @@ Reduction JSCallReducer::ReduceArrayBufferViewAccessor(
receiver, effect, control);
// See if we can skip the detaching check.
- if (isolate()->IsArrayBufferDetachingIntact()) {
- // Add a code dependency so we are deoptimized in case an ArrayBuffer
- // gets detached.
- dependencies()->DependOnProtector(PropertyCellRef(
- broker(), factory()->array_buffer_detaching_protector()));
- } else {
+ if (!dependencies()->DependOnArrayBufferDetachingProtector()) {
// Check whether {receiver}s JSArrayBuffer was detached.
Node* buffer = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
@@ -6825,12 +6814,7 @@ Reduction JSCallReducer::ReduceDataViewAccess(Node* node, DataViewAccess access,
simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
receiver, effect, control);
- if (isolate()->IsArrayBufferDetachingIntact()) {
- // Add a code dependency so we are deoptimized in case an ArrayBuffer
- // gets detached.
- dependencies()->DependOnProtector(PropertyCellRef(
- broker(), factory()->array_buffer_detaching_protector()));
- } else {
+ if (!dependencies()->DependOnArrayBufferDetachingProtector()) {
// Bail out if the {buffer} was detached.
Node* buffer_bit_field = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForJSArrayBufferBitField()),
@@ -7017,8 +7001,8 @@ Reduction JSCallReducer::ReduceRegExpPrototypeTest(Node* node) {
// Compute property access info for "exec" on {resolution}.
PropertyAccessInfo ai_exec;
- AccessInfoFactory access_info_factory(
- broker(), dependencies(), native_context().object(), graph()->zone());
+ AccessInfoFactory access_info_factory(broker(), dependencies(),
+ graph()->zone());
if (!access_info_factory.ComputePropertyAccessInfo(
MapHandles(regexp_maps.begin(), regexp_maps.end()),
factory()->exec_string(), AccessMode::kLoad, &ai_exec)) {
@@ -7044,19 +7028,18 @@ Reduction JSCallReducer::ReduceRegExpPrototypeTest(Node* node) {
// Protect the prototype chain from changes.
dependencies()->DependOnStablePrototypeChains(
- broker(), ai_exec.receiver_maps(), JSObjectRef(broker(), holder));
+ ai_exec.receiver_maps(), JSObjectRef(broker(), holder));
// Protect the exec method change in the holder.
Handle<Object> exec_on_proto;
- Handle<Map> holder_map(holder->map(), isolate());
- Handle<DescriptorArray> descriptors(holder_map->instance_descriptors(),
- isolate());
+ MapRef holder_map(broker(), handle(holder->map(), isolate()));
+ Handle<DescriptorArray> descriptors(
+ holder_map.object()->instance_descriptors(), isolate());
int descriptor_index =
- descriptors->Search(*(factory()->exec_string()), *holder_map);
+ descriptors->Search(*(factory()->exec_string()), *holder_map.object());
CHECK_NE(descriptor_index, DescriptorArray::kNotFound);
-
- dependencies()->DependOnFieldType(MapRef(broker(), holder_map),
- descriptor_index);
+ holder_map.SerializeOwnDescriptors();
+ dependencies()->DependOnFieldType(holder_map, descriptor_index);
} else {
return NoChange();
}
@@ -7067,7 +7050,7 @@ Reduction JSCallReducer::ReduceRegExpPrototypeTest(Node* node) {
Handle<JSObject> holder;
if (ai_exec.holder().ToHandle(&holder)) {
dependencies()->DependOnStablePrototypeChains(
- broker(), ai_exec.receiver_maps(), JSObjectRef(broker(), holder));
+ ai_exec.receiver_maps(), JSObjectRef(broker(), holder));
}
if (need_map_check) {