Commit 66b0d031 authored by mvstanton's avatar mvstanton Committed by Commit bot

Basic TurboFan support for rest arguments.

TurboFan can accept them, it calls a runtime function to initialize
the rest object as a JSArray.

BUG=
R=bmeurer@chromium.org

Review URL: https://codereview.chromium.org/1543253002

Cr-Commit-Position: refs/heads/master@{#33071}
parent 3d6f79bc
......@@ -585,6 +585,11 @@ bool AstNumberingVisitor::Renumber(FunctionLiteral* node) {
DisableCrankshaft(kContextAllocatedArguments);
}
int rest_index;
if (scope->rest_parameter(&rest_index)) {
DisableCrankshaft(kRestParameter);
}
VisitDeclarations(scope->declarations());
VisitStatements(node->body());
......
......@@ -3229,9 +3229,19 @@ Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) {
Node* AstGraphBuilder::BuildRestArgumentsArray(Variable* rest, int index) {
if (rest == NULL) return NULL;
// TODO(mvstanton): Handle rest arguments.
SetStackOverflow();
return jsgraph()->UndefinedConstant();
// Allocate and initialize a new arguments object.
CreateArgumentsParameters::Type type = CreateArgumentsParameters::kRestArray;
const Operator* op = javascript()->CreateArguments(type, index);
Node* object = NewNode(op, GetFunctionClosure());
PrepareFrameState(object, BailoutId::None());
// Assign the object to the {rest} variable. This should never lazy
// deopt, so it is fine to send invalid bailout id.
DCHECK(rest->IsContextSlot() || rest->IsStackAllocated());
FrameStateBeforeAndAfter states(this, BailoutId::None());
BuildVariableAssignment(rest, object, Token::ASSIGN, VectorSlotPair(),
BailoutId::None(), states);
return object;
}
......
......@@ -463,7 +463,8 @@ void JSGenericLowering::LowerJSCreateArguments(Node* node) {
ReplaceWithRuntimeCall(node, Runtime::kNewStrictArguments_Generic);
break;
case CreateArgumentsParameters::kRestArray:
UNIMPLEMENTED();
node->InsertInput(zone(), 1, jsgraph()->Constant(p.start_index()));
ReplaceWithRuntimeCall(node, Runtime::kNewRestArguments_Generic);
break;
}
}
......
......@@ -521,6 +521,26 @@ Handle<JSObject> NewStrictArguments(Isolate* isolate, Handle<JSFunction> callee,
}
template <typename T>
Handle<JSObject> NewRestArguments(Isolate* isolate, Handle<JSFunction> callee,
T parameters, int argument_count,
int start_index) {
int num_elements = std::max(0, argument_count - start_index);
Handle<JSObject> result = isolate->factory()->NewJSArray(
FAST_ELEMENTS, num_elements, num_elements, Strength::WEAK,
DONT_INITIALIZE_ARRAY_ELEMENTS);
{
DisallowHeapAllocation no_gc;
FixedArray* elements = FixedArray::cast(result->elements());
WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
for (int i = 0; i < num_elements; i++) {
elements->set(i, parameters[i + start_index], mode);
}
}
return result;
}
class HandleArguments BASE_EMBEDDED {
public:
explicit HandleArguments(Handle<Object>* array) : array_(array) {}
......@@ -571,6 +591,22 @@ RUNTIME_FUNCTION(Runtime_NewStrictArguments_Generic) {
}
RUNTIME_FUNCTION(Runtime_NewRestArguments_Generic) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0)
CONVERT_SMI_ARG_CHECKED(start_index, 1);
// This generic runtime function can also be used when the caller has been
// inlined, we use the slow but accurate {Runtime::GetCallerArguments}.
int argument_count = 0;
base::SmartArrayPointer<Handle<Object>> arguments =
Runtime::GetCallerArguments(isolate, 0, &argument_count);
HandleArguments argument_getter(arguments.get());
return *NewRestArguments(isolate, callee, argument_getter, argument_count,
start_index);
}
RUNTIME_FUNCTION(Runtime_NewSloppyArguments) {
HandleScope scope(isolate);
DCHECK(args.length() == 3);
......
......@@ -560,6 +560,7 @@ namespace internal {
F(InitializeLegacyConstLookupSlot, 3, 1) \
F(NewSloppyArguments_Generic, 1, 1) \
F(NewStrictArguments_Generic, 1, 1) \
F(NewRestArguments_Generic, 2, 1) \
F(NewSloppyArguments, 3, 1) \
F(NewStrictArguments, 3, 1) \
F(NewRestParam, 4, 1) \
......
......@@ -35,9 +35,6 @@ TEST(ArgumentsUnmapped) {
TEST(ArgumentsRest) {
// TODO(mvstanton): restore this test when Turbofan again supports rest args.
// (soon).
return;
FunctionTester T("(function(a, ...args) { return args; })");
Handle<Object> arguments;
......
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