Commit bef80fcf authored by caitpotter88's avatar caitpotter88 Committed by Commit bot

[es6] generate rest parameters correctly for subclass constructors

BUG=v8:3977
R=dslomov@chromium.org, arv@chromium.org
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#27344}
parent 86a6b6ff
......@@ -240,6 +240,11 @@ void FullCodeGenerator::Generate() {
}
}
ArgumentsAccessStub::HasNewTarget has_new_target =
IsSubclassConstructor(info->function()->kind())
? ArgumentsAccessStub::HAS_NEW_TARGET
: ArgumentsAccessStub::NO_NEW_TARGET;
// Possibly allocate RestParameters
int rest_index;
Variable* rest_param = scope()->rest_parameter(&rest_index);
......@@ -248,6 +253,11 @@ void FullCodeGenerator::Generate() {
int num_parameters = info->scope()->num_parameters();
int offset = num_parameters * kPointerSize;
if (has_new_target == ArgumentsAccessStub::HAS_NEW_TARGET) {
--num_parameters;
++rest_index;
}
__ add(r3, fp, Operand(StandardFrameConstants::kCallerSPOffset + offset));
__ mov(r2, Operand(Smi::FromInt(num_parameters)));
__ mov(r1, Operand(Smi::FromInt(rest_index)));
......@@ -281,10 +291,6 @@ void FullCodeGenerator::Generate() {
// function, receiver address, parameter count.
// The stub will rewrite receiever and parameter count if the previous
// stack frame was an arguments adapter frame.
ArgumentsAccessStub::HasNewTarget has_new_target =
IsSubclassConstructor(info->function()->kind())
? ArgumentsAccessStub::HAS_NEW_TARGET
: ArgumentsAccessStub::NO_NEW_TARGET;
ArgumentsAccessStub::Type type;
if (is_strict(language_mode()) || !is_simple_parameter_list()) {
type = ArgumentsAccessStub::NEW_STRICT;
......
......@@ -241,6 +241,11 @@ void FullCodeGenerator::Generate() {
}
}
ArgumentsAccessStub::HasNewTarget has_new_target =
IsSubclassConstructor(info->function()->kind())
? ArgumentsAccessStub::HAS_NEW_TARGET
: ArgumentsAccessStub::NO_NEW_TARGET;
// Possibly allocate RestParameters
int rest_index;
Variable* rest_param = scope()->rest_parameter(&rest_index);
......@@ -249,6 +254,11 @@ void FullCodeGenerator::Generate() {
int num_parameters = info->scope()->num_parameters();
int offset = num_parameters * kPointerSize;
if (has_new_target == ArgumentsAccessStub::HAS_NEW_TARGET) {
--num_parameters;
++rest_index;
}
__ Add(x3, fp, StandardFrameConstants::kCallerSPOffset + offset);
__ Mov(x2, Smi::FromInt(num_parameters));
__ Mov(x1, Smi::FromInt(rest_index));
......@@ -281,10 +291,6 @@ void FullCodeGenerator::Generate() {
// function, receiver address, parameter count.
// The stub will rewrite receiver and parameter count if the previous
// stack frame was an arguments adapter frame.
ArgumentsAccessStub::HasNewTarget has_new_target =
IsSubclassConstructor(info->function()->kind())
? ArgumentsAccessStub::HAS_NEW_TARGET
: ArgumentsAccessStub::NO_NEW_TARGET;
ArgumentsAccessStub::Type type;
if (is_strict(language_mode()) || !is_simple_parameter_list()) {
type = ArgumentsAccessStub::NEW_STRICT;
......
......@@ -236,6 +236,11 @@ void FullCodeGenerator::Generate() {
}
}
ArgumentsAccessStub::HasNewTarget has_new_target =
IsSubclassConstructor(info->function()->kind())
? ArgumentsAccessStub::HAS_NEW_TARGET
: ArgumentsAccessStub::NO_NEW_TARGET;
// Possibly allocate RestParameters
int rest_index;
Variable* rest_param = scope()->rest_parameter(&rest_index);
......@@ -244,6 +249,11 @@ void FullCodeGenerator::Generate() {
int num_parameters = info->scope()->num_parameters();
int offset = num_parameters * kPointerSize;
if (has_new_target == ArgumentsAccessStub::HAS_NEW_TARGET) {
--num_parameters;
++rest_index;
}
__ lea(edx,
Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset));
__ push(edx);
......@@ -284,10 +294,7 @@ void FullCodeGenerator::Generate() {
} else {
type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
}
ArgumentsAccessStub::HasNewTarget has_new_target =
IsSubclassConstructor(info->function()->kind())
? ArgumentsAccessStub::HAS_NEW_TARGET
: ArgumentsAccessStub::NO_NEW_TARGET;
ArgumentsAccessStub stub(isolate(), type, has_new_target);
__ CallStub(&stub);
......
......@@ -232,6 +232,11 @@ void FullCodeGenerator::Generate() {
}
}
ArgumentsAccessStub::HasNewTarget has_new_target =
IsSubclassConstructor(info->function()->kind())
? ArgumentsAccessStub::HAS_NEW_TARGET
: ArgumentsAccessStub::NO_NEW_TARGET;
// Possibly allocate RestParameters
int rest_index;
Variable* rest_param = scope()->rest_parameter(&rest_index);
......@@ -240,6 +245,11 @@ void FullCodeGenerator::Generate() {
int num_parameters = info->scope()->num_parameters();
int offset = num_parameters * kPointerSize;
if (has_new_target == ArgumentsAccessStub::HAS_NEW_TARGET) {
--num_parameters;
++rest_index;
}
__ leap(rdx,
Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset));
__ Push(rdx);
......@@ -275,10 +285,6 @@ void FullCodeGenerator::Generate() {
// The stub will rewrite receiver and parameter count if the previous
// stack frame was an arguments adapter frame.
ArgumentsAccessStub::HasNewTarget has_new_target =
IsSubclassConstructor(info->function()->kind())
? ArgumentsAccessStub::HAS_NEW_TARGET
: ArgumentsAccessStub::NO_NEW_TARGET;
ArgumentsAccessStub::Type type;
if (is_strict(language_mode()) || !is_simple_parameter_list()) {
type = ArgumentsAccessStub::NEW_STRICT;
......
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-rest-parameters
// Flags: --harmony-rest-parameters --harmony-classes
(function testRestIndex() {
assertEquals(5, (function(...args) { return args.length; })(1,2,3,4,5));
......@@ -180,3 +180,35 @@ var O = {
assertEquals([], ((...args) => args)());
assertEquals([1,2,3], ((...args) => args)(1,2,3));
})();*/
(function testRestParamsWithNewTarget() {
"use strict";
class Base {
constructor(...a) {
this.base = a;
assertEquals(arguments.length, a.length);
var args = [];
for (var i = 0; i < arguments.length; ++i) {
args.push(arguments[i]);
}
assertEquals(args, a);
}
}
class Child extends Base {
constructor(...b) {
super(1, 2, 3);
this.child = b;
assertEquals(arguments.length, b.length);
var args = [];
for (var i = 0; i < arguments.length; ++i) {
args.push(arguments[i]);
}
assertEquals(args, b);
}
}
var c = new Child(1, 2, 3);
assertEquals([1, 2, 3], c.child);
assertEquals([1, 2, 3], c.base);
})();
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