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

[turbofan] Be more precise about arguments hints

When simulating how standard higher-order builtins call their function
argument, we were inconsistent and imprecise in what hints we used for
the arguments.

Bug: v8:7790
Change-Id: I9a76225f0f036f3e7ce1a62644204790e4eba74d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1849519
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64196}
parent 807a7058
...@@ -3013,12 +3013,13 @@ Reduction JSCallReducer::ReduceCallOrConstructWithArrayLikeOrSpread( ...@@ -3013,12 +3013,13 @@ Reduction JSCallReducer::ReduceCallOrConstructWithArrayLikeOrSpread(
node->opcode() == IrOpcode::kJSConstructWithArrayLike || node->opcode() == IrOpcode::kJSConstructWithArrayLike ||
node->opcode() == IrOpcode::kJSConstructWithSpread); node->opcode() == IrOpcode::kJSConstructWithSpread);
// Check if {arguments_list} is an arguments object, and {node} is the only
// value user of {arguments_list} (except for value uses in frame states).
Node* arguments_list = NodeProperties::GetValueInput(node, arity); Node* arguments_list = NodeProperties::GetValueInput(node, arity);
if (arguments_list->opcode() != IrOpcode::kJSCreateArguments) { if (arguments_list->opcode() != IrOpcode::kJSCreateArguments) {
return NoChange(); return NoChange();
} }
// Check if {node} is the only value user of {arguments_list} (except for
// value uses in frame states). If not, we give up for now.
for (Edge edge : arguments_list->use_edges()) { for (Edge edge : arguments_list->use_edges()) {
if (!NodeProperties::IsValueEdge(edge)) continue; if (!NodeProperties::IsValueEdge(edge)) continue;
Node* const user = edge.from(); Node* const user = edge.from();
......
...@@ -415,6 +415,13 @@ class Callee { ...@@ -415,6 +415,13 @@ class Callee {
base::Optional<FunctionBlueprint> const blueprint_; base::Optional<FunctionBlueprint> const blueprint_;
}; };
// If a list of arguments (hints) is shorter than the function's parameter
// count, this enum expresses what we know about the missing arguments.
enum MissingArgumentsPolicy {
kMissingArgumentsAreUndefined, // ... as in the JS undefined value
kMissingArgumentsAreUnknown,
};
// The SerializerForBackgroundCompilation makes sure that the relevant function // The SerializerForBackgroundCompilation makes sure that the relevant function
// data such as bytecode, SharedFunctionInfo and FeedbackVector, used by later // data such as bytecode, SharedFunctionInfo and FeedbackVector, used by later
// optimizations in the compiler, is copied to the heap broker. // optimizations in the compiler, is copied to the heap broker.
...@@ -433,6 +440,7 @@ class SerializerForBackgroundCompilation { ...@@ -433,6 +440,7 @@ class SerializerForBackgroundCompilation {
ZoneStats* zone_stats, JSHeapBroker* broker, ZoneStats* zone_stats, JSHeapBroker* broker,
CompilationDependencies* dependencies, CompilationSubject function, CompilationDependencies* dependencies, CompilationSubject function,
base::Optional<Hints> new_target, const HintsVector& arguments, base::Optional<Hints> new_target, const HintsVector& arguments,
MissingArgumentsPolicy padding,
SerializerForBackgroundCompilationFlags flags); SerializerForBackgroundCompilationFlags flags);
bool BailoutOnUninitialized(ProcessedFeedback const& feedback); bool BailoutOnUninitialized(ProcessedFeedback const& feedback);
...@@ -448,19 +456,19 @@ class SerializerForBackgroundCompilation { ...@@ -448,19 +456,19 @@ class SerializerForBackgroundCompilation {
base::Optional<Hints> new_target, base::Optional<Hints> new_target,
const HintsVector& arguments, const HintsVector& arguments,
SpeculationMode speculation_mode, SpeculationMode speculation_mode,
bool with_spread); MissingArgumentsPolicy padding);
void ProcessCalleeForCallOrConstruct(Handle<Object> callee, void ProcessCalleeForCallOrConstruct(Handle<Object> callee,
base::Optional<Hints> new_target, base::Optional<Hints> new_target,
const HintsVector& arguments, const HintsVector& arguments,
SpeculationMode speculation_mode, SpeculationMode speculation_mode,
bool with_spread = false); MissingArgumentsPolicy padding);
void ProcessCallOrConstruct(Hints callee, base::Optional<Hints> new_target, void ProcessCallOrConstruct(Hints callee, base::Optional<Hints> new_target,
const HintsVector& arguments, FeedbackSlot slot, const HintsVector& arguments, FeedbackSlot slot,
bool with_spread = false); MissingArgumentsPolicy padding);
void ProcessCallVarArgs(ConvertReceiverMode receiver_mode, void ProcessCallVarArgs(
Hints const& callee, interpreter::Register first_reg, ConvertReceiverMode receiver_mode, Hints const& callee,
int reg_count, FeedbackSlot slot, interpreter::Register first_reg, int reg_count, FeedbackSlot slot,
bool with_spread = false); MissingArgumentsPolicy padding = kMissingArgumentsAreUndefined);
void ProcessApiCall(Handle<SharedFunctionInfo> target, void ProcessApiCall(Handle<SharedFunctionInfo> target,
const HintsVector& arguments); const HintsVector& arguments);
void ProcessReceiverMapForApiCall(FunctionTemplateInfoRef target, void ProcessReceiverMapForApiCall(FunctionTemplateInfoRef target,
...@@ -468,7 +476,8 @@ class SerializerForBackgroundCompilation { ...@@ -468,7 +476,8 @@ class SerializerForBackgroundCompilation {
void ProcessBuiltinCall(Handle<SharedFunctionInfo> target, void ProcessBuiltinCall(Handle<SharedFunctionInfo> target,
base::Optional<Hints> new_target, base::Optional<Hints> new_target,
const HintsVector& arguments, const HintsVector& arguments,
SpeculationMode speculation_mode, bool with_spread); SpeculationMode speculation_mode,
MissingArgumentsPolicy padding);
void ProcessJump(interpreter::BytecodeArrayIterator* iterator); void ProcessJump(interpreter::BytecodeArrayIterator* iterator);
...@@ -536,7 +545,8 @@ class SerializerForBackgroundCompilation { ...@@ -536,7 +545,8 @@ class SerializerForBackgroundCompilation {
Hints RunChildSerializer(CompilationSubject function, Hints RunChildSerializer(CompilationSubject function,
base::Optional<Hints> new_target, base::Optional<Hints> new_target,
const HintsVector& arguments, bool with_spread); const HintsVector& arguments,
MissingArgumentsPolicy padding);
// When (forward-)branching bytecodes are encountered, e.g. a conditional // When (forward-)branching bytecodes are encountered, e.g. a conditional
// jump, we call ContributeToJumpTargetEnvironment to "remember" the current // jump, we call ContributeToJumpTargetEnvironment to "remember" the current
...@@ -726,7 +736,8 @@ class SerializerForBackgroundCompilation::Environment : public ZoneObject { ...@@ -726,7 +736,8 @@ class SerializerForBackgroundCompilation::Environment : public ZoneObject {
public: public:
Environment(Zone* zone, CompilationSubject function); Environment(Zone* zone, CompilationSubject function);
Environment(Zone* zone, Isolate* isolate, CompilationSubject function, Environment(Zone* zone, Isolate* isolate, CompilationSubject function,
base::Optional<Hints> new_target, const HintsVector& arguments); base::Optional<Hints> new_target, const HintsVector& arguments,
MissingArgumentsPolicy padding);
bool IsDead() const { return ephemeral_hints_.empty(); } bool IsDead() const { return ephemeral_hints_.empty(); }
...@@ -828,7 +839,8 @@ SerializerForBackgroundCompilation::Environment::Environment( ...@@ -828,7 +839,8 @@ SerializerForBackgroundCompilation::Environment::Environment(
SerializerForBackgroundCompilation::Environment::Environment( SerializerForBackgroundCompilation::Environment::Environment(
Zone* zone, Isolate* isolate, CompilationSubject function, Zone* zone, Isolate* isolate, CompilationSubject function,
base::Optional<Hints> new_target, const HintsVector& arguments) base::Optional<Hints> new_target, const HintsVector& arguments,
MissingArgumentsPolicy padding)
: Environment(zone, function) { : Environment(zone, function) {
// Copy the hints for the actually passed arguments, at most up to // Copy the hints for the actually passed arguments, at most up to
// the parameter_count. // the parameter_count.
...@@ -837,11 +849,14 @@ SerializerForBackgroundCompilation::Environment::Environment( ...@@ -837,11 +849,14 @@ SerializerForBackgroundCompilation::Environment::Environment(
ephemeral_hints_[i] = arguments[i]; ephemeral_hints_[i] = arguments[i];
} }
// Pad the rest with "undefined". if (padding == kMissingArgumentsAreUndefined) {
Hints undefined_hint = Hints undefined_hint =
Hints::SingleConstant(isolate->factory()->undefined_value(), zone); Hints::SingleConstant(isolate->factory()->undefined_value(), zone);
for (size_t i = arguments.size(); i < param_count; ++i) { for (size_t i = arguments.size(); i < param_count; ++i) {
ephemeral_hints_[i] = undefined_hint; ephemeral_hints_[i] = undefined_hint;
}
} else {
DCHECK_EQ(padding, kMissingArgumentsAreUnknown);
} }
interpreter::Register new_target_reg = interpreter::Register new_target_reg =
...@@ -952,12 +967,14 @@ SerializerForBackgroundCompilation::SerializerForBackgroundCompilation( ...@@ -952,12 +967,14 @@ SerializerForBackgroundCompilation::SerializerForBackgroundCompilation(
ZoneStats* zone_stats, JSHeapBroker* broker, ZoneStats* zone_stats, JSHeapBroker* broker,
CompilationDependencies* dependencies, CompilationSubject function, CompilationDependencies* dependencies, CompilationSubject function,
base::Optional<Hints> new_target, const HintsVector& arguments, base::Optional<Hints> new_target, const HintsVector& arguments,
MissingArgumentsPolicy padding,
SerializerForBackgroundCompilationFlags flags) SerializerForBackgroundCompilationFlags flags)
: broker_(broker), : broker_(broker),
dependencies_(dependencies), dependencies_(dependencies),
zone_scope_(zone_stats, ZONE_NAME), zone_scope_(zone_stats, ZONE_NAME),
environment_(new (zone()) Environment(zone(), broker_->isolate(), environment_(new (zone())
function, new_target, arguments)), Environment(zone(), broker_->isolate(), function,
new_target, arguments, padding)),
jump_target_environments_(zone()), jump_target_environments_(zone()),
flags_(flags), flags_(flags),
osr_offset_(BailoutId::None()) { osr_offset_(BailoutId::None()) {
...@@ -1137,7 +1154,8 @@ void SerializerForBackgroundCompilation::VisitGetIterator( ...@@ -1137,7 +1154,8 @@ void SerializerForBackgroundCompilation::VisitGetIterator(
const Hints& callee = Hints(); const Hints& callee = Hints();
FeedbackSlot call_slot = iterator->GetSlotOperand(2); FeedbackSlot call_slot = iterator->GetSlotOperand(2);
HintsVector parameters({receiver}, zone()); HintsVector parameters({receiver}, zone());
ProcessCallOrConstruct(callee, base::nullopt, parameters, call_slot); ProcessCallOrConstruct(callee, base::nullopt, parameters, call_slot,
kMissingArgumentsAreUndefined);
} }
void SerializerForBackgroundCompilation::VisitGetSuperConstructor( void SerializerForBackgroundCompilation::VisitGetSuperConstructor(
...@@ -1660,7 +1678,8 @@ void SerializerForBackgroundCompilation::VisitCallUndefinedReceiver0( ...@@ -1660,7 +1678,8 @@ void SerializerForBackgroundCompilation::VisitCallUndefinedReceiver0(
Hints receiver = Hints::SingleConstant( Hints receiver = Hints::SingleConstant(
broker()->isolate()->factory()->undefined_value(), zone()); broker()->isolate()->factory()->undefined_value(), zone());
HintsVector parameters({receiver}, zone()); HintsVector parameters({receiver}, zone());
ProcessCallOrConstruct(callee, base::nullopt, parameters, slot); ProcessCallOrConstruct(callee, base::nullopt, parameters, slot,
kMissingArgumentsAreUndefined);
} }
void SerializerForBackgroundCompilation::VisitCallUndefinedReceiver1( void SerializerForBackgroundCompilation::VisitCallUndefinedReceiver1(
...@@ -1674,7 +1693,8 @@ void SerializerForBackgroundCompilation::VisitCallUndefinedReceiver1( ...@@ -1674,7 +1693,8 @@ void SerializerForBackgroundCompilation::VisitCallUndefinedReceiver1(
Hints receiver = Hints::SingleConstant( Hints receiver = Hints::SingleConstant(
broker()->isolate()->factory()->undefined_value(), zone()); broker()->isolate()->factory()->undefined_value(), zone());
HintsVector parameters({receiver, arg0}, zone()); HintsVector parameters({receiver, arg0}, zone());
ProcessCallOrConstruct(callee, base::nullopt, parameters, slot); ProcessCallOrConstruct(callee, base::nullopt, parameters, slot,
kMissingArgumentsAreUndefined);
} }
void SerializerForBackgroundCompilation::VisitCallUndefinedReceiver2( void SerializerForBackgroundCompilation::VisitCallUndefinedReceiver2(
...@@ -1690,7 +1710,8 @@ void SerializerForBackgroundCompilation::VisitCallUndefinedReceiver2( ...@@ -1690,7 +1710,8 @@ void SerializerForBackgroundCompilation::VisitCallUndefinedReceiver2(
Hints receiver = Hints::SingleConstant( Hints receiver = Hints::SingleConstant(
broker()->isolate()->factory()->undefined_value(), zone()); broker()->isolate()->factory()->undefined_value(), zone());
HintsVector parameters({receiver, arg0, arg1}, zone()); HintsVector parameters({receiver, arg0, arg1}, zone());
ProcessCallOrConstruct(callee, base::nullopt, parameters, slot); ProcessCallOrConstruct(callee, base::nullopt, parameters, slot,
kMissingArgumentsAreUndefined);
} }
void SerializerForBackgroundCompilation::VisitCallAnyReceiver( void SerializerForBackgroundCompilation::VisitCallAnyReceiver(
...@@ -1734,7 +1755,8 @@ void SerializerForBackgroundCompilation::VisitCallProperty0( ...@@ -1734,7 +1755,8 @@ void SerializerForBackgroundCompilation::VisitCallProperty0(
FeedbackSlot slot = iterator->GetSlotOperand(2); FeedbackSlot slot = iterator->GetSlotOperand(2);
HintsVector parameters({receiver}, zone()); HintsVector parameters({receiver}, zone());
ProcessCallOrConstruct(callee, base::nullopt, parameters, slot); ProcessCallOrConstruct(callee, base::nullopt, parameters, slot,
kMissingArgumentsAreUndefined);
} }
void SerializerForBackgroundCompilation::VisitCallProperty1( void SerializerForBackgroundCompilation::VisitCallProperty1(
...@@ -1748,7 +1770,8 @@ void SerializerForBackgroundCompilation::VisitCallProperty1( ...@@ -1748,7 +1770,8 @@ void SerializerForBackgroundCompilation::VisitCallProperty1(
FeedbackSlot slot = iterator->GetSlotOperand(3); FeedbackSlot slot = iterator->GetSlotOperand(3);
HintsVector parameters({receiver, arg0}, zone()); HintsVector parameters({receiver, arg0}, zone());
ProcessCallOrConstruct(callee, base::nullopt, parameters, slot); ProcessCallOrConstruct(callee, base::nullopt, parameters, slot,
kMissingArgumentsAreUndefined);
} }
void SerializerForBackgroundCompilation::VisitCallProperty2( void SerializerForBackgroundCompilation::VisitCallProperty2(
...@@ -1764,7 +1787,8 @@ void SerializerForBackgroundCompilation::VisitCallProperty2( ...@@ -1764,7 +1787,8 @@ void SerializerForBackgroundCompilation::VisitCallProperty2(
FeedbackSlot slot = iterator->GetSlotOperand(4); FeedbackSlot slot = iterator->GetSlotOperand(4);
HintsVector parameters({receiver, arg0, arg1}, zone()); HintsVector parameters({receiver, arg0, arg1}, zone());
ProcessCallOrConstruct(callee, base::nullopt, parameters, slot); ProcessCallOrConstruct(callee, base::nullopt, parameters, slot,
kMissingArgumentsAreUndefined);
} }
void SerializerForBackgroundCompilation::VisitCallWithSpread( void SerializerForBackgroundCompilation::VisitCallWithSpread(
...@@ -1775,7 +1799,7 @@ void SerializerForBackgroundCompilation::VisitCallWithSpread( ...@@ -1775,7 +1799,7 @@ void SerializerForBackgroundCompilation::VisitCallWithSpread(
int reg_count = static_cast<int>(iterator->GetRegisterCountOperand(2)); int reg_count = static_cast<int>(iterator->GetRegisterCountOperand(2));
FeedbackSlot slot = iterator->GetSlotOperand(3); FeedbackSlot slot = iterator->GetSlotOperand(3);
ProcessCallVarArgs(ConvertReceiverMode::kAny, callee, first_reg, reg_count, ProcessCallVarArgs(ConvertReceiverMode::kAny, callee, first_reg, reg_count,
slot, true); slot, kMissingArgumentsAreUnknown);
} }
void SerializerForBackgroundCompilation::VisitCallJSRuntime( void SerializerForBackgroundCompilation::VisitCallJSRuntime(
...@@ -1795,55 +1819,35 @@ void SerializerForBackgroundCompilation::VisitCallJSRuntime( ...@@ -1795,55 +1819,35 @@ void SerializerForBackgroundCompilation::VisitCallJSRuntime(
Hints SerializerForBackgroundCompilation::RunChildSerializer( Hints SerializerForBackgroundCompilation::RunChildSerializer(
CompilationSubject function, base::Optional<Hints> new_target, CompilationSubject function, base::Optional<Hints> new_target,
const HintsVector& arguments, bool with_spread) { const HintsVector& arguments, MissingArgumentsPolicy padding) {
if (with_spread) { SerializerForBackgroundCompilation child_serializer(
DCHECK_LT(0, arguments.size()); zone_scope_.zone_stats(), broker(), dependencies(), function, new_target,
// Pad the missing arguments in case we were called with spread operator. arguments, padding, flags());
// Drop the last actually passed argument, which contains the spread. // The Hints returned by the call to Run are allocated in the zone
// We don't know what the spread element produces. Therefore we pretend // created by the child serializer. Adding those hints to a hints
// that the function is called with the maximal number of parameters and // object created in our zone will preserve the information.
// that we have no information about the parameters that were not
// explicitly provided.
HintsVector padded = arguments;
padded.pop_back(); // Remove the spread element.
// Fill the rest with empty hints.
padded.resize(
function.blueprint().shared()->GetBytecodeArray().parameter_count(),
Hints());
return RunChildSerializer(function, new_target, padded, false);
}
Hints hints; Hints hints;
{ hints.AddFromChildSerializer(child_serializer.Run(), zone());
// The Hints returned by the call to Run are allocated in the zone
// created by the child serializer. Adding those hints to a hints
// object created in our zone will preserve the information.
SerializerForBackgroundCompilation child_serializer(
zone_scope_.zone_stats(), broker(), dependencies(), function,
new_target, arguments, flags());
hints.AddFromChildSerializer(child_serializer.Run(), zone());
}
return hints; return hints;
} }
void SerializerForBackgroundCompilation::ProcessSFIForCallOrConstruct( void SerializerForBackgroundCompilation::ProcessSFIForCallOrConstruct(
Callee const& callee, base::Optional<Hints> new_target, Callee const& callee, base::Optional<Hints> new_target,
const HintsVector& arguments, SpeculationMode speculation_mode, const HintsVector& arguments, SpeculationMode speculation_mode,
bool with_spread) { MissingArgumentsPolicy padding) {
Handle<SharedFunctionInfo> shared = callee.shared(broker()->isolate()); Handle<SharedFunctionInfo> shared = callee.shared(broker()->isolate());
if (shared->IsApiFunction()) { if (shared->IsApiFunction()) {
ProcessApiCall(shared, arguments); ProcessApiCall(shared, arguments);
DCHECK(!shared->IsInlineable()); DCHECK(!shared->IsInlineable());
} else if (shared->HasBuiltinId()) { } else if (shared->HasBuiltinId()) {
ProcessBuiltinCall(shared, new_target, arguments, speculation_mode, ProcessBuiltinCall(shared, new_target, arguments, speculation_mode,
with_spread); padding);
DCHECK(!shared->IsInlineable()); DCHECK(!shared->IsInlineable());
} else if (shared->IsInlineable() && callee.HasFeedbackVector()) { } else if (shared->IsInlineable() && callee.HasFeedbackVector()) {
CompilationSubject subject = CompilationSubject subject =
callee.ToCompilationSubject(broker()->isolate(), zone()); callee.ToCompilationSubject(broker()->isolate(), zone());
environment()->accumulator_hints().Add( environment()->accumulator_hints().Add(
RunChildSerializer(subject, new_target, arguments, with_spread), RunChildSerializer(subject, new_target, arguments, padding), zone());
zone());
} }
} }
...@@ -1886,7 +1890,7 @@ JSReceiverRef UnrollBoundFunction(JSBoundFunctionRef const& bound_function, ...@@ -1886,7 +1890,7 @@ JSReceiverRef UnrollBoundFunction(JSBoundFunctionRef const& bound_function,
void SerializerForBackgroundCompilation::ProcessCalleeForCallOrConstruct( void SerializerForBackgroundCompilation::ProcessCalleeForCallOrConstruct(
Handle<Object> callee, base::Optional<Hints> new_target, Handle<Object> callee, base::Optional<Hints> new_target,
const HintsVector& arguments, SpeculationMode speculation_mode, const HintsVector& arguments, SpeculationMode speculation_mode,
bool with_spread) { MissingArgumentsPolicy padding) {
const HintsVector* actual_arguments = &arguments; const HintsVector* actual_arguments = &arguments;
HintsVector expanded_arguments(zone()); HintsVector expanded_arguments(zone());
if (callee->IsJSBoundFunction()) { if (callee->IsJSBoundFunction()) {
...@@ -1904,12 +1908,13 @@ void SerializerForBackgroundCompilation::ProcessCalleeForCallOrConstruct( ...@@ -1904,12 +1908,13 @@ void SerializerForBackgroundCompilation::ProcessCalleeForCallOrConstruct(
function.Serialize(); function.Serialize();
Callee new_callee(function.object()); Callee new_callee(function.object());
ProcessSFIForCallOrConstruct(new_callee, new_target, *actual_arguments, ProcessSFIForCallOrConstruct(new_callee, new_target, *actual_arguments,
speculation_mode, with_spread); speculation_mode, padding);
} }
void SerializerForBackgroundCompilation::ProcessCallOrConstruct( void SerializerForBackgroundCompilation::ProcessCallOrConstruct(
Hints callee, base::Optional<Hints> new_target, Hints callee, base::Optional<Hints> new_target,
const HintsVector& arguments, FeedbackSlot slot, bool with_spread) { const HintsVector& arguments, FeedbackSlot slot,
MissingArgumentsPolicy padding) {
SpeculationMode speculation_mode = SpeculationMode::kDisallowSpeculation; SpeculationMode speculation_mode = SpeculationMode::kDisallowSpeculation;
if (!slot.IsInvalid()) { if (!slot.IsInvalid()) {
FeedbackSource source(feedback_vector(), slot); FeedbackSource source(feedback_vector(), slot);
...@@ -1941,20 +1946,20 @@ void SerializerForBackgroundCompilation::ProcessCallOrConstruct( ...@@ -1941,20 +1946,20 @@ void SerializerForBackgroundCompilation::ProcessCallOrConstruct(
// For JSCallReducer::ReduceJSCall and JSCallReducer::ReduceJSConstruct. // For JSCallReducer::ReduceJSCall and JSCallReducer::ReduceJSConstruct.
for (auto constant : callee.constants()) { for (auto constant : callee.constants()) {
ProcessCalleeForCallOrConstruct(constant, new_target, arguments, ProcessCalleeForCallOrConstruct(constant, new_target, arguments,
speculation_mode, with_spread); speculation_mode, padding);
} }
// For JSCallReducer::ReduceJSCall and JSCallReducer::ReduceJSConstruct. // For JSCallReducer::ReduceJSCall and JSCallReducer::ReduceJSConstruct.
for (auto hint : callee.function_blueprints()) { for (auto hint : callee.function_blueprints()) {
ProcessSFIForCallOrConstruct(Callee(hint), new_target, arguments, ProcessSFIForCallOrConstruct(Callee(hint), new_target, arguments,
speculation_mode, with_spread); speculation_mode, padding);
} }
} }
void SerializerForBackgroundCompilation::ProcessCallVarArgs( void SerializerForBackgroundCompilation::ProcessCallVarArgs(
ConvertReceiverMode receiver_mode, Hints const& callee, ConvertReceiverMode receiver_mode, Hints const& callee,
interpreter::Register first_reg, int reg_count, FeedbackSlot slot, interpreter::Register first_reg, int reg_count, FeedbackSlot slot,
bool with_spread) { MissingArgumentsPolicy padding) {
HintsVector arguments(zone()); HintsVector arguments(zone());
// The receiver is either given in the first register or it is implicitly // The receiver is either given in the first register or it is implicitly
// the {undefined} value. // the {undefined} value.
...@@ -1964,7 +1969,7 @@ void SerializerForBackgroundCompilation::ProcessCallVarArgs( ...@@ -1964,7 +1969,7 @@ void SerializerForBackgroundCompilation::ProcessCallVarArgs(
} }
environment()->ExportRegisterHints(first_reg, reg_count, &arguments); environment()->ExportRegisterHints(first_reg, reg_count, &arguments);
ProcessCallOrConstruct(callee, base::nullopt, arguments, slot); ProcessCallOrConstruct(callee, base::nullopt, arguments, slot, padding);
} }
void SerializerForBackgroundCompilation::ProcessApiCall( void SerializerForBackgroundCompilation::ProcessApiCall(
...@@ -2038,7 +2043,7 @@ void SerializerForBackgroundCompilation::ProcessHintsForObjectCreate( ...@@ -2038,7 +2043,7 @@ void SerializerForBackgroundCompilation::ProcessHintsForObjectCreate(
void SerializerForBackgroundCompilation::ProcessBuiltinCall( void SerializerForBackgroundCompilation::ProcessBuiltinCall(
Handle<SharedFunctionInfo> target, base::Optional<Hints> new_target, Handle<SharedFunctionInfo> target, base::Optional<Hints> new_target,
const HintsVector& arguments, SpeculationMode speculation_mode, const HintsVector& arguments, SpeculationMode speculation_mode,
bool with_spread) { MissingArgumentsPolicy padding) {
DCHECK(target->HasBuiltinId()); DCHECK(target->HasBuiltinId());
const int builtin_id = target->builtin_id(); const int builtin_id = target->builtin_id();
const char* name = Builtins::name(builtin_id); const char* name = Builtins::name(builtin_id);
...@@ -2118,16 +2123,46 @@ void SerializerForBackgroundCompilation::ProcessBuiltinCall( ...@@ -2118,16 +2123,46 @@ void SerializerForBackgroundCompilation::ProcessBuiltinCall(
case Builtins::kArrayPrototypeFind: case Builtins::kArrayPrototypeFind:
case Builtins::kArrayPrototypeFindIndex: case Builtins::kArrayPrototypeFindIndex:
case Builtins::kArrayMap: case Builtins::kArrayMap:
case Builtins::kArraySome:
if (arguments.size() >= 2 &&
speculation_mode != SpeculationMode::kDisallowSpeculation) {
Hints const& callback = arguments[1];
// "Call(callbackfn, T, « kValue, k, O »)"
HintsVector new_arguments(zone());
new_arguments.push_back(
arguments.size() < 3
? Hints::SingleConstant(
broker()->isolate()->factory()->undefined_value(), zone())
: arguments[2]); // T
new_arguments.push_back(Hints()); // kValue
new_arguments.push_back(Hints()); // k
new_arguments.push_back(arguments[0]); // O
for (auto constant : callback.constants()) {
ProcessCalleeForCallOrConstruct(constant, base::nullopt,
new_arguments,
SpeculationMode::kDisallowSpeculation,
kMissingArgumentsAreUndefined);
}
}
break;
case Builtins::kArrayReduce: case Builtins::kArrayReduce:
case Builtins::kArrayReduceRight: case Builtins::kArrayReduceRight:
case Builtins::kArraySome:
if (arguments.size() >= 2 && if (arguments.size() >= 2 &&
speculation_mode != SpeculationMode::kDisallowSpeculation) { speculation_mode != SpeculationMode::kDisallowSpeculation) {
Hints const& callback = arguments[1]; Hints const& callback = arguments[1];
// "Call(callbackfn, undefined, « accumulator, kValue, k, O »)"
HintsVector new_arguments(zone());
new_arguments.push_back(Hints::SingleConstant(
broker()->isolate()->factory()->undefined_value(), zone()));
new_arguments.push_back(Hints()); // accumulator
new_arguments.push_back(Hints()); // kValue
new_arguments.push_back(Hints()); // k
new_arguments.push_back(arguments[0]); // O
for (auto constant : callback.constants()) { for (auto constant : callback.constants()) {
ProcessCalleeForCallOrConstruct( ProcessCalleeForCallOrConstruct(constant, base::nullopt,
constant, base::nullopt, HintsVector(zone()), new_arguments,
SpeculationMode::kDisallowSpeculation, false); SpeculationMode::kDisallowSpeculation,
kMissingArgumentsAreUndefined);
} }
} }
break; break;
...@@ -2135,12 +2170,36 @@ void SerializerForBackgroundCompilation::ProcessBuiltinCall( ...@@ -2135,12 +2170,36 @@ void SerializerForBackgroundCompilation::ProcessBuiltinCall(
// TODO(neis): Might need something like a FunctionBlueprint but for // TODO(neis): Might need something like a FunctionBlueprint but for
// creating bound functions rather than creating closures. // creating bound functions rather than creating closures.
case Builtins::kFunctionPrototypeApply: case Builtins::kFunctionPrototypeApply:
if (arguments.size() >= 1) {
// Drop hints for all arguments except the user-given receiver.
Hints new_receiver =
arguments.size() >= 2
? arguments[1]
: Hints::SingleConstant(
broker()->isolate()->factory()->undefined_value(),
zone());
HintsVector new_arguments({new_receiver}, zone());
for (auto constant : arguments[0].constants()) {
ProcessCalleeForCallOrConstruct(constant, base::nullopt,
new_arguments,
SpeculationMode::kDisallowSpeculation,
kMissingArgumentsAreUnknown);
}
}
break;
case Builtins::kPromiseConstructor: case Builtins::kPromiseConstructor:
if (arguments.size() >= 1) { if (arguments.size() >= 1) {
// "Call(executor, undefined, « resolvingFunctions.[[Resolve]],
// resolvingFunctions.[[Reject]] »)"
HintsVector new_arguments(
{Hints::SingleConstant(
broker()->isolate()->factory()->undefined_value(), zone())},
zone());
for (auto constant : arguments[0].constants()) { for (auto constant : arguments[0].constants()) {
ProcessCalleeForCallOrConstruct( ProcessCalleeForCallOrConstruct(constant, base::nullopt,
constant, base::nullopt, HintsVector(zone()), new_arguments,
SpeculationMode::kDisallowSpeculation, false); SpeculationMode::kDisallowSpeculation,
kMissingArgumentsAreUnknown);
} }
} }
break; break;
...@@ -2151,7 +2210,7 @@ void SerializerForBackgroundCompilation::ProcessBuiltinCall( ...@@ -2151,7 +2210,7 @@ void SerializerForBackgroundCompilation::ProcessBuiltinCall(
for (auto constant : arguments[0].constants()) { for (auto constant : arguments[0].constants()) {
ProcessCalleeForCallOrConstruct( ProcessCalleeForCallOrConstruct(
constant, base::nullopt, new_arguments, constant, base::nullopt, new_arguments,
SpeculationMode::kDisallowSpeculation, with_spread); SpeculationMode::kDisallowSpeculation, padding);
} }
} }
break; break;
...@@ -2159,8 +2218,9 @@ void SerializerForBackgroundCompilation::ProcessBuiltinCall( ...@@ -2159,8 +2218,9 @@ void SerializerForBackgroundCompilation::ProcessBuiltinCall(
case Builtins::kReflectConstruct: case Builtins::kReflectConstruct:
if (arguments.size() >= 2) { if (arguments.size() >= 2) {
for (auto constant : arguments[1].constants()) { for (auto constant : arguments[1].constants()) {
if (constant->IsJSFunction()) if (constant->IsJSFunction()) {
JSFunctionRef(broker(), constant).Serialize(); JSFunctionRef(broker(), constant).Serialize();
}
} }
} }
break; break;
...@@ -2438,7 +2498,8 @@ void SerializerForBackgroundCompilation::VisitConstruct( ...@@ -2438,7 +2498,8 @@ void SerializerForBackgroundCompilation::VisitConstruct(
HintsVector arguments(zone()); HintsVector arguments(zone());
environment()->ExportRegisterHints(first_reg, reg_count, &arguments); environment()->ExportRegisterHints(first_reg, reg_count, &arguments);
ProcessCallOrConstruct(callee, new_target, arguments, slot); ProcessCallOrConstruct(callee, new_target, arguments, slot,
kMissingArgumentsAreUndefined);
} }
void SerializerForBackgroundCompilation::VisitConstructWithSpread( void SerializerForBackgroundCompilation::VisitConstructWithSpread(
...@@ -2452,8 +2513,10 @@ void SerializerForBackgroundCompilation::VisitConstructWithSpread( ...@@ -2452,8 +2513,10 @@ void SerializerForBackgroundCompilation::VisitConstructWithSpread(
HintsVector arguments(zone()); HintsVector arguments(zone());
environment()->ExportRegisterHints(first_reg, reg_count, &arguments); environment()->ExportRegisterHints(first_reg, reg_count, &arguments);
DCHECK(!arguments.empty());
ProcessCallOrConstruct(callee, new_target, arguments, slot, true); arguments.pop_back(); // Remove the spread element.
ProcessCallOrConstruct(callee, new_target, arguments, slot,
kMissingArgumentsAreUnknown);
} }
void SerializerForBackgroundCompilation::ProcessGlobalAccess(FeedbackSlot slot, void SerializerForBackgroundCompilation::ProcessGlobalAccess(FeedbackSlot slot,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment