Preserve feedback and speculation mode for JSCall
Changing the target of JSCall nodes (e.g. while lowering higher order calls) now preserves feedback and speculation mode to allow further (speculative) optimizations. A flag is introduced to mark feedback unrelated to the call target after such a transformation. This flag is used to prevent access to the feedback without the need to invalidate it. Bug: v8:9702 Change-Id: I311d3a4b1b22d6f65e5837a23b0b7585c8d75eed Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1844788 Commit-Queue: Nico Hartmann <nicohartmann@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Cr-Commit-Position: refs/heads/master@{#64733}
This commit is contained in:
parent
0ec75c9173
commit
149e4935ba
@ -2231,8 +2231,9 @@ void BytecodeGraphBuilder::BuildCall(ConvertReceiverMode receiver_mode,
|
||||
FeedbackSource feedback = CreateFeedbackSource(slot_id);
|
||||
CallFrequency frequency = ComputeCallFrequency(slot_id);
|
||||
SpeculationMode speculation_mode = GetSpeculationMode(slot_id);
|
||||
const Operator* op = javascript()->Call(arg_count, frequency, feedback,
|
||||
receiver_mode, speculation_mode);
|
||||
const Operator* op =
|
||||
javascript()->Call(arg_count, frequency, feedback, receiver_mode,
|
||||
speculation_mode, CallFeedbackRelation::kRelated);
|
||||
|
||||
JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedCall(
|
||||
op, args, static_cast<int>(arg_count), feedback.slot);
|
||||
@ -2415,8 +2416,9 @@ void BytecodeGraphBuilder::VisitCallWithSpread() {
|
||||
int const slot_id = bytecode_iterator().GetIndexOperand(3);
|
||||
FeedbackSource feedback = CreateFeedbackSource(slot_id);
|
||||
CallFrequency frequency = ComputeCallFrequency(slot_id);
|
||||
SpeculationMode speculation_mode = GetSpeculationMode(slot_id);
|
||||
const Operator* op = javascript()->CallWithSpread(
|
||||
static_cast<int>(reg_count + 1), frequency, feedback);
|
||||
static_cast<int>(reg_count + 1), frequency, feedback, speculation_mode);
|
||||
|
||||
JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedCall(
|
||||
op, args, static_cast<int>(arg_count), feedback.slot);
|
||||
|
@ -36,6 +36,24 @@ inline size_t hash_value(StackCheckKind kind) {
|
||||
return static_cast<size_t>(kind);
|
||||
}
|
||||
|
||||
// The CallFeedbackRelation states whether the target feedback stored with a
|
||||
// JSCall is related to the call. If, during lowering, a JSCall (e.g. of a
|
||||
// higher order function) is replaced by a JSCall with another target, the
|
||||
// feedback has to be kept but is now unrelated.
|
||||
enum class CallFeedbackRelation { kRelated, kUnrelated };
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os,
|
||||
CallFeedbackRelation call_feedback_relation) {
|
||||
switch (call_feedback_relation) {
|
||||
case CallFeedbackRelation::kRelated:
|
||||
return os << "CallFeedbackRelation::kRelated";
|
||||
case CallFeedbackRelation::kUnrelated:
|
||||
return os << "CallFeedbackRelation::kUnrelated";
|
||||
}
|
||||
UNREACHABLE();
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -314,8 +314,10 @@ Reduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) {
|
||||
while (arity-- > 3) node->RemoveInput(3);
|
||||
|
||||
// Morph the {node} to a {JSCallWithArrayLike}.
|
||||
NodeProperties::ChangeOp(node,
|
||||
javascript()->CallWithArrayLike(p.frequency()));
|
||||
NodeProperties::ChangeOp(
|
||||
node, javascript()->CallWithArrayLike(
|
||||
p.frequency(), p.feedback(), p.speculation_mode(),
|
||||
CallFeedbackRelation::kUnrelated));
|
||||
Reduction const reduction = ReduceJSCallWithArrayLike(node);
|
||||
return reduction.Changed() ? reduction : Changed(node);
|
||||
} else {
|
||||
@ -342,8 +344,11 @@ Reduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) {
|
||||
Node* effect0 = effect;
|
||||
Node* control0 = control;
|
||||
Node* value0 = effect0 = control0 = graph()->NewNode(
|
||||
javascript()->CallWithArrayLike(p.frequency()), target, this_argument,
|
||||
arguments_list, context, frame_state, effect0, control0);
|
||||
javascript()->CallWithArrayLike(p.frequency(), p.feedback(),
|
||||
p.speculation_mode(),
|
||||
CallFeedbackRelation::kUnrelated),
|
||||
target, this_argument, arguments_list, context, frame_state, effect0,
|
||||
control0);
|
||||
|
||||
// Lower to {JSCall} if {arguments_list} is either null or undefined.
|
||||
Node* effect1 = effect;
|
||||
@ -387,14 +392,10 @@ Reduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) {
|
||||
}
|
||||
}
|
||||
// Change {node} to the new {JSCall} operator.
|
||||
// TODO(mslekova): Since this introduces a Call that will get optimized by
|
||||
// the JSCallReducer, we basically might have to do all the serialization
|
||||
// that we do for that here as well. The only difference is that here we
|
||||
// disable speculation (cf. the empty FeedbackSource above), causing the
|
||||
// JSCallReducer to do much less work. We should revisit this later.
|
||||
NodeProperties::ChangeOp(
|
||||
node,
|
||||
javascript()->Call(arity, p.frequency(), FeedbackSource(), convert_mode));
|
||||
node, javascript()->Call(arity, p.frequency(), p.feedback(), convert_mode,
|
||||
p.speculation_mode(),
|
||||
CallFeedbackRelation::kUnrelated));
|
||||
// Try to further reduce the JSCall {node}.
|
||||
Reduction const reduction = ReduceJSCall(node);
|
||||
return reduction.Changed() ? reduction : Changed(node);
|
||||
@ -569,8 +570,9 @@ Reduction JSCallReducer::ReduceFunctionPrototypeCall(Node* node) {
|
||||
--arity;
|
||||
}
|
||||
NodeProperties::ChangeOp(
|
||||
node,
|
||||
javascript()->Call(arity, p.frequency(), FeedbackSource(), convert_mode));
|
||||
node, javascript()->Call(arity, p.frequency(), p.feedback(), convert_mode,
|
||||
p.speculation_mode(),
|
||||
CallFeedbackRelation::kUnrelated));
|
||||
// Try to further reduce the JSCall {node}.
|
||||
Reduction const reduction = ReduceJSCall(node);
|
||||
return reduction.Changed() ? reduction : Changed(node);
|
||||
@ -801,8 +803,10 @@ Reduction JSCallReducer::ReduceReflectApply(Node* node) {
|
||||
while (arity-- > 3) {
|
||||
node->RemoveInput(arity);
|
||||
}
|
||||
NodeProperties::ChangeOp(node,
|
||||
javascript()->CallWithArrayLike(p.frequency()));
|
||||
NodeProperties::ChangeOp(
|
||||
node, javascript()->CallWithArrayLike(p.frequency(), p.feedback(),
|
||||
p.speculation_mode(),
|
||||
CallFeedbackRelation::kUnrelated));
|
||||
Reduction const reduction = ReduceJSCallWithArrayLike(node);
|
||||
return reduction.Changed() ? reduction : Changed(node);
|
||||
}
|
||||
@ -1194,8 +1198,11 @@ Reduction JSCallReducer::ReduceArrayForEach(
|
||||
outer_frame_state, ContinuationFrameStateMode::LAZY);
|
||||
|
||||
control = effect = graph()->NewNode(
|
||||
javascript()->Call(5, p.frequency()), fncallback, this_arg, element, k,
|
||||
receiver, context, frame_state, effect, control);
|
||||
javascript()->Call(5, p.frequency(), p.feedback(),
|
||||
ConvertReceiverMode::kAny, p.speculation_mode(),
|
||||
CallFeedbackRelation::kUnrelated),
|
||||
fncallback, this_arg, element, k, receiver, context, frame_state, effect,
|
||||
control);
|
||||
|
||||
// Rewire potential exception edges.
|
||||
Node* on_exception = nullptr;
|
||||
@ -1448,10 +1455,12 @@ Reduction JSCallReducer::ReduceArrayReduce(
|
||||
&checkpoint_params[0], stack_parameters - 1, outer_frame_state,
|
||||
ContinuationFrameStateMode::LAZY);
|
||||
|
||||
next_cur = control = effect =
|
||||
graph()->NewNode(javascript()->Call(6, p.frequency()), fncallback,
|
||||
jsgraph()->UndefinedConstant(), cur, element, k,
|
||||
receiver, context, frame_state, effect, control);
|
||||
next_cur = control = effect = graph()->NewNode(
|
||||
javascript()->Call(6, p.frequency(), p.feedback(),
|
||||
ConvertReceiverMode::kAny, p.speculation_mode(),
|
||||
CallFeedbackRelation::kUnrelated),
|
||||
fncallback, jsgraph()->UndefinedConstant(), cur, element, k, receiver,
|
||||
context, frame_state, effect, control);
|
||||
}
|
||||
|
||||
// Rewire potential exception edges.
|
||||
@ -1643,8 +1652,11 @@ Reduction JSCallReducer::ReduceArrayMap(Node* node,
|
||||
outer_frame_state, ContinuationFrameStateMode::LAZY);
|
||||
|
||||
Node* callback_value = control = effect = graph()->NewNode(
|
||||
javascript()->Call(5, p.frequency()), fncallback, this_arg, element, k,
|
||||
receiver, context, frame_state, effect, control);
|
||||
javascript()->Call(5, p.frequency(), p.feedback(),
|
||||
ConvertReceiverMode::kAny, p.speculation_mode(),
|
||||
CallFeedbackRelation::kUnrelated),
|
||||
fncallback, this_arg, element, k, receiver, context, frame_state, effect,
|
||||
control);
|
||||
|
||||
// Rewire potential exception edges.
|
||||
Node* on_exception = nullptr;
|
||||
@ -1864,8 +1876,11 @@ Reduction JSCallReducer::ReduceArrayFilter(
|
||||
outer_frame_state, ContinuationFrameStateMode::LAZY);
|
||||
|
||||
callback_value = control = effect = graph()->NewNode(
|
||||
javascript()->Call(5, p.frequency()), fncallback, this_arg, element, k,
|
||||
receiver, context, frame_state, effect, control);
|
||||
javascript()->Call(5, p.frequency(), p.feedback(),
|
||||
ConvertReceiverMode::kAny, p.speculation_mode(),
|
||||
CallFeedbackRelation::kUnrelated),
|
||||
fncallback, this_arg, element, k, receiver, context, frame_state,
|
||||
effect, control);
|
||||
}
|
||||
|
||||
// Rewire potential exception edges.
|
||||
@ -2074,8 +2089,11 @@ Reduction JSCallReducer::ReduceArrayFind(Node* node, ArrayFindVariant variant,
|
||||
ContinuationFrameStateMode::LAZY);
|
||||
|
||||
callback_value = control = effect = graph()->NewNode(
|
||||
javascript()->Call(5, p.frequency()), fncallback, this_arg, element, k,
|
||||
receiver, context, frame_state, effect, control);
|
||||
javascript()->Call(5, p.frequency(), p.feedback(),
|
||||
ConvertReceiverMode::kAny, p.speculation_mode(),
|
||||
CallFeedbackRelation::kUnrelated),
|
||||
fncallback, this_arg, element, k, receiver, context, frame_state,
|
||||
effect, control);
|
||||
}
|
||||
|
||||
// Rewire potential exception edges.
|
||||
@ -2392,8 +2410,11 @@ Reduction JSCallReducer::ReduceArrayEvery(Node* node,
|
||||
outer_frame_state, ContinuationFrameStateMode::LAZY);
|
||||
|
||||
callback_value = control = effect = graph()->NewNode(
|
||||
javascript()->Call(5, p.frequency()), fncallback, this_arg, element, k,
|
||||
receiver, context, frame_state, effect, control);
|
||||
javascript()->Call(5, p.frequency(), p.feedback(),
|
||||
ConvertReceiverMode::kAny, p.speculation_mode(),
|
||||
CallFeedbackRelation::kUnrelated),
|
||||
fncallback, this_arg, element, k, receiver, context, frame_state,
|
||||
effect, control);
|
||||
}
|
||||
|
||||
// Rewire potential exception edges.
|
||||
@ -2726,8 +2747,11 @@ Reduction JSCallReducer::ReduceArraySome(Node* node,
|
||||
outer_frame_state, ContinuationFrameStateMode::LAZY);
|
||||
|
||||
callback_value = control = effect = graph()->NewNode(
|
||||
javascript()->Call(5, p.frequency()), fncallback, this_arg, element, k,
|
||||
receiver, context, frame_state, effect, control);
|
||||
javascript()->Call(5, p.frequency(), p.feedback(),
|
||||
ConvertReceiverMode::kAny, p.speculation_mode(),
|
||||
CallFeedbackRelation::kUnrelated),
|
||||
fncallback, this_arg, element, k, receiver, context, frame_state,
|
||||
effect, control);
|
||||
}
|
||||
|
||||
// Rewire potential exception edges.
|
||||
@ -3003,11 +3027,14 @@ bool IsSafeArgumentsElements(Node* node) {
|
||||
|
||||
Reduction JSCallReducer::ReduceCallOrConstructWithArrayLikeOrSpread(
|
||||
Node* node, int arity, CallFrequency const& frequency,
|
||||
FeedbackSource const& feedback) {
|
||||
FeedbackSource const& feedback, SpeculationMode speculation_mode,
|
||||
CallFeedbackRelation feedback_relation) {
|
||||
DCHECK(node->opcode() == IrOpcode::kJSCallWithArrayLike ||
|
||||
node->opcode() == IrOpcode::kJSCallWithSpread ||
|
||||
node->opcode() == IrOpcode::kJSConstructWithArrayLike ||
|
||||
node->opcode() == IrOpcode::kJSConstructWithSpread);
|
||||
DCHECK_IMPLIES(speculation_mode == SpeculationMode::kAllowSpeculation,
|
||||
feedback.IsValid());
|
||||
|
||||
Node* arguments_list = NodeProperties::GetValueInput(node, arity);
|
||||
if (arguments_list->opcode() != IrOpcode::kJSCreateArguments) {
|
||||
@ -3145,7 +3172,9 @@ Reduction JSCallReducer::ReduceCallOrConstructWithArrayLikeOrSpread(
|
||||
if (node->opcode() == IrOpcode::kJSCallWithArrayLike ||
|
||||
node->opcode() == IrOpcode::kJSCallWithSpread) {
|
||||
NodeProperties::ChangeOp(
|
||||
node, javascript()->Call(arity + 1, frequency, feedback));
|
||||
node, javascript()->Call(arity + 1, frequency, feedback,
|
||||
ConvertReceiverMode::kAny, speculation_mode,
|
||||
CallFeedbackRelation::kUnrelated));
|
||||
Reduction const reduction = ReduceJSCall(node);
|
||||
return reduction.Changed() ? reduction : Changed(node);
|
||||
} else {
|
||||
@ -3286,8 +3315,9 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) {
|
||||
}
|
||||
|
||||
NodeProperties::ChangeOp(
|
||||
node, javascript()->Call(arity, p.frequency(), FeedbackSource(),
|
||||
convert_mode));
|
||||
node, javascript()->Call(arity, p.frequency(), p.feedback(),
|
||||
convert_mode, p.speculation_mode(),
|
||||
CallFeedbackRelation::kUnrelated));
|
||||
|
||||
// Try to further reduce the JSCall {node}.
|
||||
Reduction const reduction = ReduceJSCall(node);
|
||||
@ -3334,25 +3364,30 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) {
|
||||
? ConvertReceiverMode::kAny
|
||||
: ConvertReceiverMode::kNotNullOrUndefined;
|
||||
NodeProperties::ChangeOp(
|
||||
node, javascript()->Call(arity, p.frequency(), FeedbackSource(),
|
||||
convert_mode));
|
||||
node, javascript()->Call(arity, p.frequency(), p.feedback(),
|
||||
convert_mode, p.speculation_mode(),
|
||||
CallFeedbackRelation::kUnrelated));
|
||||
|
||||
// Try to further reduce the JSCall {node}.
|
||||
Reduction const reduction = ReduceJSCall(node);
|
||||
return reduction.Changed() ? reduction : Changed(node);
|
||||
}
|
||||
|
||||
if (!p.feedback().IsValid()) return NoChange();
|
||||
if (!ShouldUseCallICFeedback(target) ||
|
||||
p.feedback_relation() != CallFeedbackRelation::kRelated ||
|
||||
!p.feedback().IsValid()) {
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
ProcessedFeedback const& feedback =
|
||||
broker()->GetFeedbackForCall(FeedbackSource(p.feedback()));
|
||||
broker()->GetFeedbackForCall(p.feedback());
|
||||
if (feedback.IsInsufficient()) {
|
||||
return ReduceSoftDeoptimize(
|
||||
node, DeoptimizeReason::kInsufficientTypeFeedbackForCall);
|
||||
}
|
||||
|
||||
base::Optional<HeapObjectRef> feedback_target = feedback.AsCall().target();
|
||||
if (feedback_target.has_value() && ShouldUseCallICFeedback(target) &&
|
||||
feedback_target->map().is_callable()) {
|
||||
if (feedback_target.has_value() && feedback_target->map().is_callable()) {
|
||||
Node* target_function = jsgraph()->Constant(*feedback_target);
|
||||
|
||||
// Check that the {target} is still the {target_function}.
|
||||
@ -3728,9 +3763,12 @@ Reduction JSCallReducer::ReduceJSCall(Node* node,
|
||||
|
||||
Reduction JSCallReducer::ReduceJSCallWithArrayLike(Node* node) {
|
||||
DCHECK_EQ(IrOpcode::kJSCallWithArrayLike, node->opcode());
|
||||
CallFrequency frequency = CallFrequencyOf(node->op());
|
||||
return ReduceCallOrConstructWithArrayLikeOrSpread(node, 2, frequency,
|
||||
FeedbackSource());
|
||||
const CallParameters& p = CallParametersOf(node->op());
|
||||
int arity = static_cast<int>(p.arity());
|
||||
DCHECK_EQ(arity, 2);
|
||||
return ReduceCallOrConstructWithArrayLikeOrSpread(
|
||||
node, arity, p.frequency(), p.feedback(), p.speculation_mode(),
|
||||
p.feedback_relation());
|
||||
}
|
||||
|
||||
Reduction JSCallReducer::ReduceJSCallWithSpread(Node* node) {
|
||||
@ -3740,8 +3778,9 @@ Reduction JSCallReducer::ReduceJSCallWithSpread(Node* node) {
|
||||
int arity = static_cast<int>(p.arity() - 1);
|
||||
CallFrequency frequency = p.frequency();
|
||||
FeedbackSource feedback = p.feedback();
|
||||
return ReduceCallOrConstructWithArrayLikeOrSpread(node, arity, frequency,
|
||||
feedback);
|
||||
return ReduceCallOrConstructWithArrayLikeOrSpread(
|
||||
node, arity, frequency, feedback, p.speculation_mode(),
|
||||
p.feedback_relation());
|
||||
}
|
||||
|
||||
Reduction JSCallReducer::ReduceJSConstruct(Node* node) {
|
||||
@ -4287,8 +4326,9 @@ Reduction JSCallReducer::ReduceStringPrototypeSubstr(Node* node) {
|
||||
Reduction JSCallReducer::ReduceJSConstructWithArrayLike(Node* node) {
|
||||
DCHECK_EQ(IrOpcode::kJSConstructWithArrayLike, node->opcode());
|
||||
CallFrequency frequency = CallFrequencyOf(node->op());
|
||||
return ReduceCallOrConstructWithArrayLikeOrSpread(node, 1, frequency,
|
||||
FeedbackSource());
|
||||
return ReduceCallOrConstructWithArrayLikeOrSpread(
|
||||
node, 1, frequency, FeedbackSource(),
|
||||
SpeculationMode::kDisallowSpeculation, CallFeedbackRelation::kRelated);
|
||||
}
|
||||
|
||||
Reduction JSCallReducer::ReduceJSConstructWithSpread(Node* node) {
|
||||
@ -4298,8 +4338,9 @@ Reduction JSCallReducer::ReduceJSConstructWithSpread(Node* node) {
|
||||
int arity = static_cast<int>(p.arity() - 2);
|
||||
CallFrequency frequency = p.frequency();
|
||||
FeedbackSource feedback = p.feedback();
|
||||
return ReduceCallOrConstructWithArrayLikeOrSpread(node, arity, frequency,
|
||||
feedback);
|
||||
return ReduceCallOrConstructWithArrayLikeOrSpread(
|
||||
node, arity, frequency, feedback, SpeculationMode::kDisallowSpeculation,
|
||||
CallFeedbackRelation::kRelated);
|
||||
}
|
||||
|
||||
Reduction JSCallReducer::ReduceReturnReceiver(Node* node) {
|
||||
@ -5757,8 +5798,7 @@ Reduction JSCallReducer::ReducePromiseConstructor(Node* node) {
|
||||
// 9. Call executor with both resolving functions
|
||||
effect = control = graph()->NewNode(
|
||||
javascript()->Call(4, p.frequency(), FeedbackSource(),
|
||||
ConvertReceiverMode::kNullOrUndefined,
|
||||
SpeculationMode::kDisallowSpeculation),
|
||||
ConvertReceiverMode::kNullOrUndefined),
|
||||
executor, jsgraph()->UndefinedConstant(), resolve, reject, context,
|
||||
frame_state, effect, control);
|
||||
|
||||
@ -5770,8 +5810,7 @@ Reduction JSCallReducer::ReducePromiseConstructor(Node* node) {
|
||||
// 10a. Call reject if the call to executor threw.
|
||||
exception_effect = exception_control = graph()->NewNode(
|
||||
javascript()->Call(3, p.frequency(), FeedbackSource(),
|
||||
ConvertReceiverMode::kNullOrUndefined,
|
||||
SpeculationMode::kDisallowSpeculation),
|
||||
ConvertReceiverMode::kNullOrUndefined),
|
||||
reject, jsgraph()->UndefinedConstant(), reason, context, frame_state,
|
||||
exception_effect, exception_control);
|
||||
|
||||
@ -5862,7 +5901,8 @@ Reduction JSCallReducer::ReducePromisePrototypeCatch(Node* node) {
|
||||
NodeProperties::ChangeOp(
|
||||
node, javascript()->Call(2 + arity, p.frequency(), p.feedback(),
|
||||
ConvertReceiverMode::kNotNullOrUndefined,
|
||||
p.speculation_mode()));
|
||||
p.speculation_mode(),
|
||||
CallFeedbackRelation::kUnrelated));
|
||||
Reduction const reduction = ReducePromisePrototypeThen(node);
|
||||
return reduction.Changed() ? reduction : Changed(node);
|
||||
}
|
||||
@ -5989,7 +6029,8 @@ Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) {
|
||||
NodeProperties::ChangeOp(
|
||||
node, javascript()->Call(2 + arity, p.frequency(), p.feedback(),
|
||||
ConvertReceiverMode::kNotNullOrUndefined,
|
||||
p.speculation_mode()));
|
||||
p.speculation_mode(),
|
||||
CallFeedbackRelation::kUnrelated));
|
||||
Reduction const reduction = ReducePromisePrototypeThen(node);
|
||||
return reduction.Changed() ? reduction : Changed(node);
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "src/base/flags.h"
|
||||
#include "src/compiler/frame-states.h"
|
||||
#include "src/compiler/globals.h"
|
||||
#include "src/compiler/graph-reducer.h"
|
||||
#include "src/compiler/node-properties.h"
|
||||
#include "src/deoptimizer/deoptimize-reason.h"
|
||||
@ -106,7 +107,8 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer {
|
||||
|
||||
Reduction ReduceCallOrConstructWithArrayLikeOrSpread(
|
||||
Node* node, int arity, CallFrequency const& frequency,
|
||||
FeedbackSource const& feedback);
|
||||
FeedbackSource const& feedback, SpeculationMode speculation_mode,
|
||||
CallFeedbackRelation feedback_relation);
|
||||
Reduction ReduceJSConstruct(Node* node);
|
||||
Reduction ReduceJSConstructWithArrayLike(Node* node);
|
||||
Reduction ReduceJSConstructWithSpread(Node* node);
|
||||
|
@ -1439,7 +1439,8 @@ Reduction JSNativeContextSpecialization::ReduceJSGetIterator(Node* node) {
|
||||
: feedback.AsCall().speculation_mode();
|
||||
const Operator* call_op =
|
||||
javascript()->Call(2, CallFrequency(), p.callFeedback(),
|
||||
ConvertReceiverMode::kNotNullOrUndefined, mode);
|
||||
ConvertReceiverMode::kNotNullOrUndefined, mode,
|
||||
CallFeedbackRelation::kRelated);
|
||||
Node* call_property = graph()->NewNode(call_op, load_property, receiver,
|
||||
context, frame_state, effect, control);
|
||||
effect = call_property;
|
||||
|
@ -23,8 +23,7 @@ std::ostream& operator<<(std::ostream& os, CallFrequency const& f) {
|
||||
}
|
||||
|
||||
CallFrequency CallFrequencyOf(Operator const* op) {
|
||||
DCHECK(op->opcode() == IrOpcode::kJSCallWithArrayLike ||
|
||||
op->opcode() == IrOpcode::kJSConstructWithArrayLike);
|
||||
DCHECK_EQ(op->opcode(), IrOpcode::kJSConstructWithArrayLike);
|
||||
return OpParameter<CallFrequency>(op);
|
||||
}
|
||||
|
||||
@ -66,11 +65,13 @@ ConstructParameters const& ConstructParametersOf(Operator const* op) {
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, CallParameters const& p) {
|
||||
return os << p.arity() << ", " << p.frequency() << ", " << p.convert_mode();
|
||||
return os << p.arity() << ", " << p.frequency() << ", " << p.convert_mode()
|
||||
<< ", " << p.speculation_mode() << ", " << p.feedback_relation();
|
||||
}
|
||||
|
||||
const CallParameters& CallParametersOf(const Operator* op) {
|
||||
DCHECK(op->opcode() == IrOpcode::kJSCall ||
|
||||
op->opcode() == IrOpcode::kJSCallWithArrayLike ||
|
||||
op->opcode() == IrOpcode::kJSCallWithSpread);
|
||||
return OpParameter<CallParameters>(op);
|
||||
}
|
||||
@ -882,15 +883,12 @@ const Operator* JSOperatorBuilder::CallForwardVarargs(size_t arity,
|
||||
parameters); // parameter
|
||||
}
|
||||
|
||||
const Operator* JSOperatorBuilder::Call(size_t arity,
|
||||
CallFrequency const& frequency,
|
||||
FeedbackSource const& feedback,
|
||||
ConvertReceiverMode convert_mode,
|
||||
SpeculationMode speculation_mode) {
|
||||
DCHECK_IMPLIES(speculation_mode == SpeculationMode::kAllowSpeculation,
|
||||
feedback.IsValid());
|
||||
const Operator* JSOperatorBuilder::Call(
|
||||
size_t arity, CallFrequency const& frequency,
|
||||
FeedbackSource const& feedback, ConvertReceiverMode convert_mode,
|
||||
SpeculationMode speculation_mode, CallFeedbackRelation feedback_relation) {
|
||||
CallParameters parameters(arity, frequency, feedback, convert_mode,
|
||||
speculation_mode);
|
||||
speculation_mode, feedback_relation);
|
||||
return new (zone()) Operator1<CallParameters>( // --
|
||||
IrOpcode::kJSCall, Operator::kNoProperties, // opcode
|
||||
"JSCall", // name
|
||||
@ -899,21 +897,26 @@ const Operator* JSOperatorBuilder::Call(size_t arity,
|
||||
}
|
||||
|
||||
const Operator* JSOperatorBuilder::CallWithArrayLike(
|
||||
CallFrequency const& frequency) {
|
||||
return new (zone()) Operator1<CallFrequency>( // --
|
||||
const CallFrequency& frequency, const FeedbackSource& feedback,
|
||||
SpeculationMode speculation_mode, CallFeedbackRelation feedback_relation) {
|
||||
CallParameters parameters(2, frequency, feedback, ConvertReceiverMode::kAny,
|
||||
speculation_mode, feedback_relation);
|
||||
return new (zone()) Operator1<CallParameters>( // --
|
||||
IrOpcode::kJSCallWithArrayLike, Operator::kNoProperties, // opcode
|
||||
"JSCallWithArrayLike", // name
|
||||
3, 1, 1, 1, 1, 2, // counts
|
||||
frequency); // parameter
|
||||
parameters); // parameter
|
||||
}
|
||||
|
||||
const Operator* JSOperatorBuilder::CallWithSpread(
|
||||
uint32_t arity, CallFrequency const& frequency,
|
||||
FeedbackSource const& feedback, SpeculationMode speculation_mode) {
|
||||
FeedbackSource const& feedback, SpeculationMode speculation_mode,
|
||||
CallFeedbackRelation feedback_relation) {
|
||||
DCHECK_IMPLIES(speculation_mode == SpeculationMode::kAllowSpeculation,
|
||||
feedback.IsValid());
|
||||
CallParameters parameters(arity, frequency, feedback,
|
||||
ConvertReceiverMode::kAny, speculation_mode);
|
||||
ConvertReceiverMode::kAny, speculation_mode,
|
||||
feedback_relation);
|
||||
return new (zone()) Operator1<CallParameters>( // --
|
||||
IrOpcode::kJSCallWithSpread, Operator::kNoProperties, // opcode
|
||||
"JSCallWithSpread", // name
|
||||
|
@ -165,12 +165,20 @@ class CallParameters final {
|
||||
CallParameters(size_t arity, CallFrequency const& frequency,
|
||||
FeedbackSource const& feedback,
|
||||
ConvertReceiverMode convert_mode,
|
||||
SpeculationMode speculation_mode)
|
||||
SpeculationMode speculation_mode,
|
||||
CallFeedbackRelation feedback_relation)
|
||||
: bit_field_(ArityField::encode(arity) |
|
||||
CallFeedbackRelationField::encode(feedback_relation) |
|
||||
SpeculationModeField::encode(speculation_mode) |
|
||||
ConvertReceiverModeField::encode(convert_mode)),
|
||||
frequency_(frequency),
|
||||
feedback_(feedback) {}
|
||||
feedback_(feedback) {
|
||||
// CallFeedbackRelation is ignored if the feedback slot is invalid.
|
||||
DCHECK_IMPLIES(speculation_mode == SpeculationMode::kAllowSpeculation,
|
||||
feedback.IsValid());
|
||||
DCHECK_IMPLIES(!feedback.IsValid(),
|
||||
feedback_relation == CallFeedbackRelation::kUnrelated);
|
||||
}
|
||||
|
||||
size_t arity() const { return ArityField::decode(bit_field_); }
|
||||
CallFrequency const& frequency() const { return frequency_; }
|
||||
@ -183,6 +191,10 @@ class CallParameters final {
|
||||
return SpeculationModeField::decode(bit_field_);
|
||||
}
|
||||
|
||||
CallFeedbackRelation feedback_relation() const {
|
||||
return CallFeedbackRelationField::decode(bit_field_);
|
||||
}
|
||||
|
||||
bool operator==(CallParameters const& that) const {
|
||||
return this->bit_field_ == that.bit_field_ &&
|
||||
this->frequency_ == that.frequency_ &&
|
||||
@ -197,7 +209,8 @@ class CallParameters final {
|
||||
feedback_hash(p.feedback_));
|
||||
}
|
||||
|
||||
using ArityField = BitField<size_t, 0, 28>;
|
||||
using ArityField = BitField<size_t, 0, 27>;
|
||||
using CallFeedbackRelationField = BitField<CallFeedbackRelation, 27, 1>;
|
||||
using SpeculationModeField = BitField<SpeculationMode, 28, 1>;
|
||||
using ConvertReceiverModeField = BitField<ConvertReceiverMode, 29, 2>;
|
||||
|
||||
@ -815,12 +828,19 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final
|
||||
size_t arity, CallFrequency const& frequency = CallFrequency(),
|
||||
FeedbackSource const& feedback = FeedbackSource(),
|
||||
ConvertReceiverMode convert_mode = ConvertReceiverMode::kAny,
|
||||
SpeculationMode speculation_mode = SpeculationMode::kDisallowSpeculation);
|
||||
const Operator* CallWithArrayLike(CallFrequency const& frequency);
|
||||
SpeculationMode speculation_mode = SpeculationMode::kDisallowSpeculation,
|
||||
CallFeedbackRelation feedback_relation =
|
||||
CallFeedbackRelation::kUnrelated);
|
||||
const Operator* CallWithArrayLike(
|
||||
CallFrequency const& frequency,
|
||||
const FeedbackSource& feedback = FeedbackSource{},
|
||||
SpeculationMode speculation_mode = SpeculationMode::kDisallowSpeculation,
|
||||
CallFeedbackRelation feedback_relation = CallFeedbackRelation::kRelated);
|
||||
const Operator* CallWithSpread(
|
||||
uint32_t arity, CallFrequency const& frequency = CallFrequency(),
|
||||
FeedbackSource const& feedback = FeedbackSource(),
|
||||
SpeculationMode speculation_mode = SpeculationMode::kDisallowSpeculation);
|
||||
SpeculationMode speculation_mode = SpeculationMode::kDisallowSpeculation,
|
||||
CallFeedbackRelation feedback_relation = CallFeedbackRelation::kRelated);
|
||||
const Operator* CallRuntime(Runtime::FunctionId id);
|
||||
const Operator* CallRuntime(Runtime::FunctionId id, size_t arity);
|
||||
const Operator* CallRuntime(const Runtime::Function* function, size_t arity);
|
||||
|
@ -1804,8 +1804,9 @@ Reduction JSTypedLowering::ReduceJSCall(Node* node) {
|
||||
// Maybe we did at least learn something about the {receiver}.
|
||||
if (p.convert_mode() != convert_mode) {
|
||||
NodeProperties::ChangeOp(
|
||||
node, javascript()->Call(p.arity(), p.frequency(), p.feedback(),
|
||||
convert_mode, p.speculation_mode()));
|
||||
node,
|
||||
javascript()->Call(p.arity(), p.frequency(), p.feedback(), convert_mode,
|
||||
p.speculation_mode(), p.feedback_relation()));
|
||||
return Changed(node);
|
||||
}
|
||||
|
||||
|
@ -2138,14 +2138,12 @@ void SerializerForBackgroundCompilation::ProcessBuiltinCall(
|
||||
new_arguments.push_back(arguments[0]); // O
|
||||
for (auto constant : callback.constants()) {
|
||||
ProcessCalleeForCallOrConstruct(constant, base::nullopt,
|
||||
new_arguments,
|
||||
SpeculationMode::kDisallowSpeculation,
|
||||
new_arguments, speculation_mode,
|
||||
kMissingArgumentsAreUndefined);
|
||||
}
|
||||
for (auto blueprint : callback.function_blueprints()) {
|
||||
ProcessCalleeForCallOrConstruct(Callee(blueprint), base::nullopt,
|
||||
new_arguments,
|
||||
SpeculationMode::kDisallowSpeculation,
|
||||
new_arguments, speculation_mode,
|
||||
kMissingArgumentsAreUndefined);
|
||||
}
|
||||
}
|
||||
@ -2165,14 +2163,12 @@ void SerializerForBackgroundCompilation::ProcessBuiltinCall(
|
||||
new_arguments.push_back(arguments[0]); // O
|
||||
for (auto constant : callback.constants()) {
|
||||
ProcessCalleeForCallOrConstruct(constant, base::nullopt,
|
||||
new_arguments,
|
||||
SpeculationMode::kDisallowSpeculation,
|
||||
new_arguments, speculation_mode,
|
||||
kMissingArgumentsAreUndefined);
|
||||
}
|
||||
for (auto blueprint : callback.function_blueprints()) {
|
||||
ProcessCalleeForCallOrConstruct(Callee(blueprint), base::nullopt,
|
||||
new_arguments,
|
||||
SpeculationMode::kDisallowSpeculation,
|
||||
new_arguments, speculation_mode,
|
||||
kMissingArgumentsAreUndefined);
|
||||
}
|
||||
}
|
||||
@ -2189,8 +2185,7 @@ void SerializerForBackgroundCompilation::ProcessBuiltinCall(
|
||||
HintsVector new_arguments({new_receiver}, zone());
|
||||
for (auto constant : arguments[0].constants()) {
|
||||
ProcessCalleeForCallOrConstruct(constant, base::nullopt,
|
||||
new_arguments,
|
||||
SpeculationMode::kDisallowSpeculation,
|
||||
new_arguments, speculation_mode,
|
||||
kMissingArgumentsAreUnknown);
|
||||
}
|
||||
}
|
||||
@ -2222,9 +2217,9 @@ void SerializerForBackgroundCompilation::ProcessBuiltinCall(
|
||||
HintsVector new_arguments(arguments.begin() + 1, arguments.end(),
|
||||
zone());
|
||||
for (auto constant : arguments[0].constants()) {
|
||||
ProcessCalleeForCallOrConstruct(
|
||||
constant, base::nullopt, new_arguments,
|
||||
SpeculationMode::kDisallowSpeculation, padding);
|
||||
ProcessCalleeForCallOrConstruct(constant, base::nullopt,
|
||||
new_arguments, speculation_mode,
|
||||
padding);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
250
test/mjsunit/compiler/opt-higher-order-functions.js
Normal file
250
test/mjsunit/compiler/opt-higher-order-functions.js
Normal file
@ -0,0 +1,250 @@
|
||||
// Copyright 2019 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax --opt --no-always-opt
|
||||
|
||||
"use strict";
|
||||
const mathAbs = Math.abs;
|
||||
const mathImul = Math.imul;
|
||||
|
||||
|
||||
// Testing: FunctionPrototypeApply
|
||||
function TestFunctionPrototypeApplyHelper() {
|
||||
return mathAbs.apply(undefined, arguments);
|
||||
}
|
||||
|
||||
function TestFunctionPrototypeApply(x) {
|
||||
return TestFunctionPrototypeApplyHelper(x);
|
||||
}
|
||||
|
||||
%PrepareFunctionForOptimization(TestFunctionPrototypeApplyHelper);
|
||||
%PrepareFunctionForOptimization(TestFunctionPrototypeApply);
|
||||
assertEquals(TestFunctionPrototypeApply(-13), 13);
|
||||
assertEquals(TestFunctionPrototypeApply(42), 42);
|
||||
%OptimizeFunctionOnNextCall(TestFunctionPrototypeApply);
|
||||
assertEquals(TestFunctionPrototypeApply(-13), 13);
|
||||
assertOptimized(TestFunctionPrototypeApply);
|
||||
TestFunctionPrototypeApply("abc");
|
||||
assertUnoptimized(TestFunctionPrototypeApply);
|
||||
|
||||
|
||||
// Testing: FunctionPrototypeCall
|
||||
function TestFunctionPrototypeCall(x) {
|
||||
return mathAbs.call(undefined, x);
|
||||
}
|
||||
|
||||
%PrepareFunctionForOptimization(TestFunctionPrototypeCall);
|
||||
TestFunctionPrototypeCall(42);
|
||||
TestFunctionPrototypeCall(52);
|
||||
%OptimizeFunctionOnNextCall(TestFunctionPrototypeCall);
|
||||
TestFunctionPrototypeCall(12);
|
||||
assertOptimized(TestFunctionPrototypeCall);
|
||||
TestFunctionPrototypeCall("abc");
|
||||
assertUnoptimized(TestFunctionPrototypeCall);
|
||||
|
||||
|
||||
// Testing: ArrayForEach
|
||||
function TestArrayForEach(x) {
|
||||
x.forEach(mathAbs);
|
||||
}
|
||||
|
||||
%PrepareFunctionForOptimization(TestArrayForEach);
|
||||
TestArrayForEach([1, 3, -4]);
|
||||
TestArrayForEach([-9, 9, 0]);
|
||||
%OptimizeFunctionOnNextCall(TestArrayForEach);
|
||||
TestArrayForEach([1, 3, -4]);
|
||||
assertOptimized(TestArrayForEach);
|
||||
TestArrayForEach(["abc", "xy"]);
|
||||
assertUnoptimized(TestArrayForEach);
|
||||
|
||||
|
||||
// Testing: ArrayReduce
|
||||
function TestArrayReduce(x) {
|
||||
return x.reduce(mathImul);
|
||||
}
|
||||
|
||||
%PrepareFunctionForOptimization(TestArrayReduce);
|
||||
assertEquals(TestArrayReduce([1, 2, -3, 4]), -24);
|
||||
assertEquals(TestArrayReduce([3, 5, 7]), 105);
|
||||
%OptimizeFunctionOnNextCall(TestArrayReduce);
|
||||
assertEquals(TestArrayReduce([1, 2, -3, 4]), -24);
|
||||
assertOptimized(TestArrayReduce);
|
||||
TestArrayReduce(["abc", "xy"]);
|
||||
assertUnoptimized(TestArrayReduce);
|
||||
|
||||
|
||||
// Testing: ArrayReduceRight
|
||||
function TestArrayReduceRight(x) {
|
||||
return x.reduceRight(mathImul);
|
||||
}
|
||||
|
||||
%PrepareFunctionForOptimization(TestArrayReduceRight);
|
||||
assertEquals(TestArrayReduceRight([1, 2, -3, 4]), -24);
|
||||
assertEquals(TestArrayReduceRight([3, 5, 7]), 105);
|
||||
%OptimizeFunctionOnNextCall(TestArrayReduceRight);
|
||||
assertEquals(TestArrayReduceRight([1, 2, -3, 4]), -24);
|
||||
assertOptimized(TestArrayReduceRight);
|
||||
TestArrayReduceRight(["abc", "xy"]);
|
||||
assertUnoptimized(TestArrayReduceRight);
|
||||
|
||||
|
||||
// Testing: ArrayMap
|
||||
function TestArrayMap(x) {
|
||||
return x.map(mathAbs);
|
||||
}
|
||||
|
||||
%PrepareFunctionForOptimization(TestArrayMap);
|
||||
assertEquals(TestArrayMap([1, -2, -3, 4]), [1, 2, 3, 4]);
|
||||
assertEquals(TestArrayMap([5, -5, 5, -5]), [5, 5, 5, 5]);
|
||||
%OptimizeFunctionOnNextCall(TestArrayMap);
|
||||
assertEquals(TestArrayMap([1, -2, 3, -4]), [1, 2, 3, 4]);
|
||||
assertOptimized(TestArrayMap);
|
||||
TestArrayMap(["abc", "xy"]);
|
||||
assertUnoptimized(TestArrayMap);
|
||||
|
||||
|
||||
// Testing: ArrayFilter
|
||||
function TestArrayFilter(x) {
|
||||
return x.filter(mathAbs);
|
||||
}
|
||||
|
||||
%PrepareFunctionForOptimization(TestArrayFilter);
|
||||
assertEquals(TestArrayFilter([-2, 0, 3, -4]), [-2, 3, -4]);
|
||||
assertEquals(TestArrayFilter([0, 1, 1, 0]), [1, 1]);
|
||||
%OptimizeFunctionOnNextCall(TestArrayFilter);
|
||||
assertEquals(TestArrayFilter([-2, 0, 3, -4]), [-2, 3, -4]);
|
||||
assertOptimized(TestArrayFilter);
|
||||
TestArrayFilter(["abc", "xy"]);
|
||||
assertUnoptimized(TestArrayFilter);
|
||||
|
||||
|
||||
// Testing: ArrayFind
|
||||
function TestArrayFind(x) {
|
||||
return x.find(mathAbs);
|
||||
}
|
||||
|
||||
%PrepareFunctionForOptimization(TestArrayFind);
|
||||
assertEquals(TestArrayFind([0, 0, -3, 12]), -3);
|
||||
assertEquals(TestArrayFind([0, -18]), -18);
|
||||
%OptimizeFunctionOnNextCall(TestArrayFind);
|
||||
assertEquals(TestArrayFind([0, 0, -3, 12]), -3);
|
||||
assertOptimized(TestArrayFind);
|
||||
TestArrayFind(["", "abc", "xy"]);
|
||||
assertUnoptimized(TestArrayFind);
|
||||
|
||||
|
||||
// Testing: ArrayFindIndex
|
||||
function TestArrayFindIndex(x) {
|
||||
return x.findIndex(mathAbs);
|
||||
}
|
||||
|
||||
%PrepareFunctionForOptimization(TestArrayFindIndex);
|
||||
assertEquals(TestArrayFindIndex([0, 0, -3, 12]), 2);
|
||||
assertEquals(TestArrayFindIndex([0, -18]), 1);
|
||||
%OptimizeFunctionOnNextCall(TestArrayFindIndex);
|
||||
assertEquals(TestArrayFindIndex([0, 0, -3, 12]), 2);
|
||||
assertOptimized(TestArrayFindIndex);
|
||||
TestArrayFindIndex(["", "abc", "xy"]);
|
||||
assertUnoptimized(TestArrayFindIndex);
|
||||
|
||||
|
||||
// Testing: ArrayEvery
|
||||
function TestArrayEvery(x) {
|
||||
return x.every(mathAbs);
|
||||
}
|
||||
|
||||
%PrepareFunctionForOptimization(TestArrayEvery);
|
||||
assertEquals(TestArrayEvery([3, 0, -9]), false);
|
||||
assertEquals(TestArrayEvery([2, 12, -1]), true);
|
||||
%OptimizeFunctionOnNextCall(TestArrayEvery);
|
||||
assertEquals(TestArrayEvery([3, 0, -9]), false);
|
||||
assertOptimized(TestArrayEvery);
|
||||
TestArrayEvery(["abc", "xy"]);
|
||||
assertUnoptimized(TestArrayEvery);
|
||||
|
||||
|
||||
// Testing: ArraySome
|
||||
function TestArraySome(x) {
|
||||
return x.some(mathAbs);
|
||||
}
|
||||
|
||||
%PrepareFunctionForOptimization(TestArraySome);
|
||||
assertEquals(TestArraySome([3, 0, -9]), true);
|
||||
assertEquals(TestArraySome([0, 0]), false);
|
||||
%OptimizeFunctionOnNextCall(TestArraySome);
|
||||
assertEquals(TestArraySome([3, 0, -9]), true);
|
||||
assertOptimized(TestArraySome);
|
||||
TestArraySome(["abc", "xy"]);
|
||||
assertUnoptimized(TestArraySome);
|
||||
|
||||
|
||||
// Testing: JSCall (JSFunction)
|
||||
const boundMathImul = mathImul.bind(undefined, -3);
|
||||
function TestJSCallWithJSFunction(x) {
|
||||
return boundMathImul(x);
|
||||
}
|
||||
|
||||
%PrepareFunctionForOptimization(TestJSCallWithJSFunction);
|
||||
assertEquals(TestJSCallWithJSFunction(-14), 42);
|
||||
assertEquals(TestJSCallWithJSFunction(14), -42);
|
||||
%OptimizeFunctionOnNextCall(TestJSCallWithJSFunction);
|
||||
assertEquals(TestJSCallWithJSFunction(-14), 42);
|
||||
assertOptimized(TestJSCallWithJSFunction);
|
||||
TestJSCallWithJSFunction("abc");
|
||||
assertUnoptimized(TestJSCallWithJSFunction);
|
||||
|
||||
|
||||
// Testing: JSCall (JSBoundFunction)
|
||||
function TestJSCallWithJSBoundFunction(x) {
|
||||
return mathImul.bind(undefined, -3)(x);
|
||||
}
|
||||
|
||||
%PrepareFunctionForOptimization(TestJSCallWithJSBoundFunction);
|
||||
assertEquals(TestJSCallWithJSBoundFunction(-14), 42);
|
||||
assertEquals(TestJSCallWithJSBoundFunction(14), -42);
|
||||
%OptimizeFunctionOnNextCall(TestJSCallWithJSBoundFunction);
|
||||
assertEquals(TestJSCallWithJSBoundFunction(-14), 42);
|
||||
assertOptimized(TestJSCallWithJSBoundFunction);
|
||||
TestJSCallWithJSBoundFunction("abc");
|
||||
assertUnoptimized(TestJSCallWithJSBoundFunction);
|
||||
|
||||
|
||||
// Testing: ReflectApply
|
||||
function TestReflectApplyHelper() {
|
||||
return Reflect.apply(mathAbs, undefined, arguments);
|
||||
}
|
||||
|
||||
function TestReflectApply(x) {
|
||||
return TestReflectApplyHelper(x);
|
||||
}
|
||||
|
||||
%PrepareFunctionForOptimization(TestReflectApplyHelper);
|
||||
%PrepareFunctionForOptimization(TestReflectApply);
|
||||
assertEquals(TestReflectApply(-9), 9);
|
||||
assertEquals(TestReflectApply(7), 7);
|
||||
%OptimizeFunctionOnNextCall(TestReflectApply);
|
||||
assertEquals(TestReflectApply(-9), 9);
|
||||
assertOptimized(TestReflectApply);
|
||||
TestReflectApply("abc");
|
||||
assertUnoptimized(TestReflectApply);
|
||||
|
||||
|
||||
// Testing: CallWithSpread
|
||||
function TestCallWithSpreadHelper() {
|
||||
return mathImul(...arguments);
|
||||
}
|
||||
|
||||
function TestCallWithSpread(x) {
|
||||
return TestCallWithSpreadHelper(x, x);
|
||||
}
|
||||
|
||||
%PrepareFunctionForOptimization(TestCallWithSpreadHelper);
|
||||
%PrepareFunctionForOptimization(TestCallWithSpread);
|
||||
assertEquals(TestCallWithSpread(-13), 169);
|
||||
assertEquals(TestCallWithSpread(7), 49);
|
||||
%OptimizeFunctionOnNextCall(TestCallWithSpread);
|
||||
assertEquals(TestCallWithSpread(-13), 169);
|
||||
assertOptimized(TestCallWithSpread);
|
||||
TestCallWithSpread("abc");
|
||||
assertUnoptimized(TestCallWithSpread);
|
@ -1106,6 +1106,9 @@
|
||||
'compiler/diamond-followedby-branch': [SKIP],
|
||||
'compiler/load-elimination-const-field': [SKIP],
|
||||
'compiler/constant-fold-add-static': [SKIP],
|
||||
|
||||
# Some tests rely on inlining.
|
||||
'compiler/opt-higher-order-functions': [SKIP],
|
||||
}], # variant == turboprop
|
||||
|
||||
##############################################################################
|
||||
|
@ -115,9 +115,9 @@ class JSCallReducerTest : public TypedGraphTest {
|
||||
Handle<FeedbackVector> vector =
|
||||
FeedbackVector::New(isolate(), shared, closure_feedback_cell_array);
|
||||
FeedbackSource feedback(vector, FeedbackSlot(0));
|
||||
return javascript()->Call(arity, CallFrequency(), feedback,
|
||||
ConvertReceiverMode::kAny,
|
||||
SpeculationMode::kAllowSpeculation);
|
||||
return javascript()->Call(
|
||||
arity, CallFrequency(), feedback, ConvertReceiverMode::kAny,
|
||||
SpeculationMode::kAllowSpeculation, CallFeedbackRelation::kRelated);
|
||||
}
|
||||
|
||||
private:
|
||||
|
Loading…
Reference in New Issue
Block a user