Commit 6f9674e4 authored by Maya Lekova's avatar Maya Lekova Committed by Commit Bot

[turbofan] Add serializer support for Call/ConstructWithSpread

This CL implements handling of Call/ConstructWithSpread bytecodes
by passing empty hints for the parameters mapped to the spread argument.

R=neis@chromium.org

Bug: v8:7790
Change-Id: I00f4e87e7bf62c3f387ee92d9aa4d252bdf79838
Reviewed-on: https://chromium-review.googlesource.com/c/1429864
Commit-Queue: Maya Lekova <mslekova@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59057}
parent 25457c60
...@@ -409,8 +409,37 @@ void SerializerForBackgroundCompilation::VisitCallProperty2( ...@@ -409,8 +409,37 @@ void SerializerForBackgroundCompilation::VisitCallProperty2(
ProcessCallOrConstruct(callee, parameters); ProcessCallOrConstruct(callee, parameters);
} }
void SerializerForBackgroundCompilation::VisitCallWithSpread(
interpreter::BytecodeArrayIterator* iterator) {
ProcessCallVarArgs(iterator, ConvertReceiverMode::kAny, true);
}
Hints SerializerForBackgroundCompilation::RunChildSerializer(
FunctionBlueprint function, const HintsVector& arguments,
bool with_spread) {
if (with_spread) {
DCHECK_LT(0, arguments.size());
// Pad the missing arguments in case we were called with spread operator.
// Drop the last actually passed argument, which contains the spread.
// We don't know what the spread element produces. Therefore we pretend
// that the function is called with the maximal number of parameters and
// 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.shared->GetBytecodeArray()->parameter_count(),
Hints(zone()));
return RunChildSerializer(function, padded, false);
}
SerializerForBackgroundCompilation child_serializer(broker(), zone(),
function, arguments);
return child_serializer.Run();
}
void SerializerForBackgroundCompilation::ProcessCallOrConstruct( void SerializerForBackgroundCompilation::ProcessCallOrConstruct(
const Hints& callee, const HintsVector& arguments) { const Hints& callee, const HintsVector& arguments, bool with_spread) {
environment()->accumulator_hints().Clear(); environment()->accumulator_hints().Clear();
for (auto hint : callee.constants()) { for (auto hint : callee.constants()) {
...@@ -424,22 +453,21 @@ void SerializerForBackgroundCompilation::ProcessCallOrConstruct( ...@@ -424,22 +453,21 @@ void SerializerForBackgroundCompilation::ProcessCallOrConstruct(
Handle<SharedFunctionInfo> shared(function->shared(), broker()->isolate()); Handle<SharedFunctionInfo> shared(function->shared(), broker()->isolate());
Handle<FeedbackVector> feedback(function->feedback_vector(), Handle<FeedbackVector> feedback(function->feedback_vector(),
broker()->isolate()); broker()->isolate());
SerializerForBackgroundCompilation child_serializer(
broker(), zone(), {shared, feedback}, arguments); environment()->accumulator_hints().Add(
environment()->accumulator_hints().Add(child_serializer.Run()); RunChildSerializer({shared, feedback}, arguments, with_spread));
} }
for (auto hint : callee.function_blueprints()) { for (auto hint : callee.function_blueprints()) {
if (!hint.shared->IsInlineable()) continue; if (!hint.shared->IsInlineable()) continue;
SerializerForBackgroundCompilation child_serializer(broker(), zone(), hint, environment()->accumulator_hints().Add(
arguments); RunChildSerializer(hint, arguments, with_spread));
environment()->accumulator_hints().Add(child_serializer.Run());
} }
} }
void SerializerForBackgroundCompilation::ProcessCallVarArgs( void SerializerForBackgroundCompilation::ProcessCallVarArgs(
interpreter::BytecodeArrayIterator* iterator, interpreter::BytecodeArrayIterator* iterator,
ConvertReceiverMode receiver_mode) { ConvertReceiverMode receiver_mode, bool with_spread) {
const Hints& callee = const Hints& callee =
environment()->register_hints(iterator->GetRegisterOperand(0)); environment()->register_hints(iterator->GetRegisterOperand(0));
interpreter::Register first_reg = iterator->GetRegisterOperand(1); interpreter::Register first_reg = iterator->GetRegisterOperand(1);
...@@ -494,12 +522,36 @@ void SerializerForBackgroundCompilation::VisitConstruct( ...@@ -494,12 +522,36 @@ void SerializerForBackgroundCompilation::VisitConstruct(
arguments.push_back( arguments.push_back(
environment()->register_hints(interpreter::Register(arg_base + i))); environment()->register_hints(interpreter::Register(arg_base + i)));
} }
// Push the new_target of the construct. // TODO(mslekova): Support new.target.
arguments.push_back(environment()->accumulator_hints());
ProcessCallOrConstruct(callee, arguments); ProcessCallOrConstruct(callee, arguments);
} }
void SerializerForBackgroundCompilation::VisitConstructWithSpread(
interpreter::BytecodeArrayIterator* iterator) {
const Hints& callee =
environment()->register_hints(iterator->GetRegisterOperand(0));
interpreter::Register first_reg = iterator->GetRegisterOperand(1);
size_t reg_count = iterator->GetRegisterCountOperand(2);
HintsVector arguments(zone());
// Push the target (callee) of the construct.
arguments.push_back(callee);
// The function arguments are in consecutive registers.
// TODO(mslekova): Introduce a helper for this pattern since it appears
// a few times.
int arg_base = first_reg.index();
for (int i = 0; i < static_cast<int>(reg_count); ++i) {
arguments.push_back(
environment()->register_hints(interpreter::Register(arg_base + i)));
}
// TODO(mslekova): Support new.target.
ProcessCallOrConstruct(callee, arguments, true);
}
#define DEFINE_SKIPPED_JUMP(name, ...) \ #define DEFINE_SKIPPED_JUMP(name, ...) \
void SerializerForBackgroundCompilation::Visit##name( \ void SerializerForBackgroundCompilation::Visit##name( \
interpreter::BytecodeArrayIterator* iterator) { \ interpreter::BytecodeArrayIterator* iterator) { \
......
...@@ -62,8 +62,6 @@ namespace compiler { ...@@ -62,8 +62,6 @@ namespace compiler {
V(Throw) V(Throw)
#define CLEAR_ACCUMULATOR_LIST(V) \ #define CLEAR_ACCUMULATOR_LIST(V) \
V(CallWithSpread) \
V(ConstructWithSpread) \
V(CreateEmptyObjectLiteral) \ V(CreateEmptyObjectLiteral) \
V(CreateMappedArguments) \ V(CreateMappedArguments) \
V(CreateRestParameter) \ V(CreateRestParameter) \
...@@ -89,7 +87,9 @@ namespace compiler { ...@@ -89,7 +87,9 @@ namespace compiler {
V(CallUndefinedReceiver0) \ V(CallUndefinedReceiver0) \
V(CallUndefinedReceiver1) \ V(CallUndefinedReceiver1) \
V(CallUndefinedReceiver2) \ V(CallUndefinedReceiver2) \
V(CallWithSpread) \
V(Construct) \ V(Construct) \
V(ConstructWithSpread) \
V(CreateClosure) \ V(CreateClosure) \
V(ExtraWide) \ V(ExtraWide) \
V(Illegal) \ V(Illegal) \
...@@ -164,10 +164,14 @@ class SerializerForBackgroundCompilation { ...@@ -164,10 +164,14 @@ class SerializerForBackgroundCompilation {
JSHeapBroker* broker() const { return broker_; } JSHeapBroker* broker() const { return broker_; }
Environment* environment() const { return environment_; } Environment* environment() const { return environment_; }
void ProcessCallOrConstruct(const Hints& callee, void ProcessCallOrConstruct(const Hints& callee, const HintsVector& arguments,
const HintsVector& arguments); bool with_spread = false);
void ProcessCallVarArgs(interpreter::BytecodeArrayIterator* iterator, void ProcessCallVarArgs(interpreter::BytecodeArrayIterator* iterator,
ConvertReceiverMode receiver_mode); ConvertReceiverMode receiver_mode,
bool with_spread = false);
Hints RunChildSerializer(FunctionBlueprint function,
const HintsVector& arguments, bool with_spread);
JSHeapBroker* broker_; JSHeapBroker* broker_;
Zone* zone_; Zone* zone_;
......
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