[es6] Support super.property in eval and arrow functions

When we enter a method that needs access to the [[HomeObject]]
we allocate a local variable `.home_object` and assign it the
value from the [[HomeObject]] private symbol. Something along
the lines of:

  method() {
    var .home_object = %ThisFunction()[home_object_symbol];
    ...
  }

BUG=v8:3867, v8:4031
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#28644}
This commit is contained in:
arv 2015-05-26 13:29:47 -07:00 committed by Commit bot
parent 2dda8c3d4e
commit 44e9810345
24 changed files with 439 additions and 319 deletions

View File

@ -242,6 +242,11 @@ void FullCodeGenerator::Generate() {
}
}
Variable* home_object_var = scope()->home_object_var();
if (home_object_var != nullptr) {
__ Push(r1);
}
ArgumentsAccessStub::HasNewTarget has_new_target =
IsSubclassConstructor(info->function()->kind())
? ArgumentsAccessStub::HAS_NEW_TARGET
@ -307,6 +312,19 @@ void FullCodeGenerator::Generate() {
SetVar(arguments, r0, r1, r2);
}
// Possibly set up a local binding to the [[HomeObject]].
if (home_object_var != nullptr) {
Comment cmnt(masm_, "[ Home object");
__ Pop(LoadDescriptor::ReceiverRegister());
Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
__ Move(LoadDescriptor::NameRegister(), home_object_symbol);
__ Move(LoadDescriptor::SlotRegister(),
Operand(SmiFromSlot(function()->HomeObjectFeedbackSlot())));
CallLoadIC(NOT_CONTEXTUAL);
SetVar(home_object_var, r0, r1, r2);
}
if (FLAG_trace) {
__ CallRuntime(Runtime::kTraceEnter, 0);
}
@ -1325,27 +1343,6 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
}
void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
Comment cnmt(masm_, "[ SuperReference ");
__ ldr(LoadDescriptor::ReceiverRegister(),
MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
__ Move(LoadDescriptor::NameRegister(), home_object_symbol);
__ mov(LoadDescriptor::SlotRegister(),
Operand(SmiFromSlot(expr->HomeObjectFeedbackSlot())));
CallLoadIC(NOT_CONTEXTUAL);
__ cmp(r0, Operand(isolate()->factory()->undefined_value()));
Label done;
__ b(ne, &done);
__ CallRuntime(Runtime::kThrowNonMethodError, 0);
__ bind(&done);
}
void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
int offset) {
if (NeedsHomeObject(initializer)) {
@ -1980,7 +1977,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
break;
case NAMED_SUPER_PROPERTY:
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(property->obj()->AsSuperReference());
VisitForAccumulatorValue(
property->obj()->AsSuperReference()->home_object_var());
__ Push(result_register());
if (expr->is_compound()) {
const Register scratch = r1;
@ -1991,8 +1989,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
break;
case KEYED_SUPER_PROPERTY:
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(property->obj()->AsSuperReference());
__ Push(result_register());
VisitForStackValue(
property->obj()->AsSuperReference()->home_object_var());
VisitForAccumulatorValue(property->key());
__ Push(result_register());
if (expr->is_compound()) {
@ -2634,7 +2632,8 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
case NAMED_SUPER_PROPERTY: {
__ Push(r0);
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
VisitForAccumulatorValue(
prop->obj()->AsSuperReference()->home_object_var());
// stack: value, this; r0: home_object
Register scratch = r2;
Register scratch2 = r3;
@ -2650,8 +2649,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
case KEYED_SUPER_PROPERTY: {
__ Push(r0);
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
__ Push(result_register());
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
VisitForAccumulatorValue(prop->key());
Register scratch = r2;
Register scratch2 = r3;
@ -2863,8 +2861,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
EmitNamedPropertyLoad(expr);
} else {
VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(expr->obj()->AsSuperReference());
__ Push(result_register());
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
EmitNamedSuperPropertyLoad(expr);
}
} else {
@ -2876,8 +2873,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
EmitKeyedPropertyLoad(expr);
} else {
VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(expr->obj()->AsSuperReference());
__ Push(result_register());
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
VisitForStackValue(expr->key());
EmitKeyedSuperPropertyLoad(expr);
}
@ -2943,8 +2939,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
// Load the function from the receiver.
const Register scratch = r1;
SuperReference* super_ref = prop->obj()->AsSuperReference();
EmitLoadHomeObject(super_ref);
__ Push(r0);
VisitForStackValue(super_ref->home_object_var());
VisitForAccumulatorValue(super_ref->this_var());
__ Push(r0);
__ Push(r0);
@ -3004,8 +2999,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
// Load the function from the receiver.
const Register scratch = r1;
SuperReference* super_ref = prop->obj()->AsSuperReference();
EmitLoadHomeObject(super_ref);
__ Push(r0);
VisitForStackValue(super_ref->home_object_var());
VisitForAccumulatorValue(super_ref->this_var());
__ Push(r0);
__ Push(r0);
@ -4847,7 +4841,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case NAMED_SUPER_PROPERTY: {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
VisitForAccumulatorValue(
prop->obj()->AsSuperReference()->home_object_var());
__ Push(result_register());
const Register scratch = r1;
__ ldr(scratch, MemOperand(sp, kPointerSize));
@ -4859,8 +4854,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case KEYED_SUPER_PROPERTY: {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
__ Push(result_register());
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
VisitForAccumulatorValue(prop->key());
__ Push(result_register());
const Register scratch = r1;

View File

@ -243,6 +243,11 @@ void FullCodeGenerator::Generate() {
}
}
Variable* home_object_var = scope()->home_object_var();
if (home_object_var != nullptr) {
__ Push(x1);
}
ArgumentsAccessStub::HasNewTarget has_new_target =
IsSubclassConstructor(info->function()->kind())
? ArgumentsAccessStub::HAS_NEW_TARGET
@ -307,11 +312,23 @@ void FullCodeGenerator::Generate() {
SetVar(arguments, x0, x1, x2);
}
// Possibly set up a local binding to the [[HomeObject]].
if (home_object_var != nullptr) {
Comment cmnt(masm_, "[ Home object");
__ Pop(LoadDescriptor::ReceiverRegister());
Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
__ Mov(LoadDescriptor::NameRegister(), home_object_symbol);
__ Mov(LoadDescriptor::SlotRegister(),
SmiFromSlot(function()->HomeObjectFeedbackSlot()));
CallLoadIC(NOT_CONTEXTUAL);
SetVar(home_object_var, x0, x1, x2);
}
if (FLAG_trace) {
__ CallRuntime(Runtime::kTraceEnter, 0);
}
// Visit the declarations and body unless there is an illegal
// redeclaration.
if (scope()->HasIllegalRedeclaration()) {
@ -1310,28 +1327,6 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
}
void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
Comment cnmt(masm_, "[ SuperReference ");
__ ldr(LoadDescriptor::ReceiverRegister(),
MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
__ Mov(LoadDescriptor::NameRegister(), Operand(home_object_symbol));
__ Mov(LoadDescriptor::SlotRegister(),
SmiFromSlot(expr->HomeObjectFeedbackSlot()));
CallLoadIC(NOT_CONTEXTUAL);
__ Mov(x10, Operand(isolate()->factory()->undefined_value()));
__ cmp(x0, x10);
Label done;
__ b(&done, ne);
__ CallRuntime(Runtime::kThrowNonMethodError, 0);
__ bind(&done);
}
void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
int offset) {
if (NeedsHomeObject(initializer)) {
@ -1951,7 +1946,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
break;
case NAMED_SUPER_PROPERTY:
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(property->obj()->AsSuperReference());
VisitForAccumulatorValue(
property->obj()->AsSuperReference()->home_object_var());
__ Push(result_register());
if (expr->is_compound()) {
const Register scratch = x10;
@ -1961,8 +1957,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
break;
case KEYED_SUPER_PROPERTY:
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(property->obj()->AsSuperReference());
__ Push(result_register());
VisitForStackValue(
property->obj()->AsSuperReference()->home_object_var());
VisitForAccumulatorValue(property->key());
__ Push(result_register());
if (expr->is_compound()) {
@ -2318,7 +2314,8 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
case NAMED_SUPER_PROPERTY: {
__ Push(x0);
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
VisitForAccumulatorValue(
prop->obj()->AsSuperReference()->home_object_var());
// stack: value, this; x0: home_object
Register scratch = x10;
Register scratch2 = x11;
@ -2334,8 +2331,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
case KEYED_SUPER_PROPERTY: {
__ Push(x0);
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
__ Push(result_register());
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
VisitForAccumulatorValue(prop->key());
Register scratch = x10;
Register scratch2 = x11;
@ -2550,8 +2546,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
EmitNamedPropertyLoad(expr);
} else {
VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(expr->obj()->AsSuperReference());
__ Push(result_register());
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
EmitNamedSuperPropertyLoad(expr);
}
} else {
@ -2563,8 +2558,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
EmitKeyedPropertyLoad(expr);
} else {
VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(expr->obj()->AsSuperReference());
__ Push(result_register());
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
VisitForStackValue(expr->key());
EmitKeyedSuperPropertyLoad(expr);
}
@ -2633,8 +2627,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
// Load the function from the receiver.
const Register scratch = x10;
SuperReference* super_ref = callee->AsProperty()->obj()->AsSuperReference();
EmitLoadHomeObject(super_ref);
__ Push(x0);
VisitForStackValue(super_ref->home_object_var());
VisitForAccumulatorValue(super_ref->this_var());
__ Push(x0);
__ Peek(scratch, kPointerSize);
@ -2693,8 +2686,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
// Load the function from the receiver.
const Register scratch = x10;
SuperReference* super_ref = callee->AsProperty()->obj()->AsSuperReference();
EmitLoadHomeObject(super_ref);
__ Push(x0);
VisitForStackValue(super_ref->home_object_var());
VisitForAccumulatorValue(super_ref->this_var());
__ Push(x0);
__ Peek(scratch, kPointerSize);
@ -4530,7 +4522,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case NAMED_SUPER_PROPERTY: {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
VisitForAccumulatorValue(
prop->obj()->AsSuperReference()->home_object_var());
__ Push(result_register());
const Register scratch = x10;
__ Peek(scratch, kPointerSize);
@ -4541,8 +4534,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case KEYED_SUPER_PROPERTY: {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
__ Push(result_register());
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
VisitForAccumulatorValue(prop->key());
__ Push(result_register());
const Register scratch1 = x10;

View File

@ -174,6 +174,7 @@ void AstNumberingVisitor::VisitSuperReference(SuperReference* node) {
ReserveFeedbackSlots(node);
node->set_base_id(ReserveIdRange(SuperReference::num_ids()));
Visit(node->this_var());
Visit(node->home_object_var());
}
@ -525,6 +526,8 @@ bool AstNumberingVisitor::Renumber(FunctionLiteral* node) {
DisableCrankshaft(kContextAllocatedArguments);
}
ReserveFeedbackSlots(node);
VisitDeclarations(scope->declarations());
if (scope->is_function_scope() && scope->function() != NULL) {
// Visit the name of the named function expression.

View File

@ -248,6 +248,7 @@ class AstValue : public ZoneObject {
F(empty, "") \
F(eval, "eval") \
F(get_template_callsite, "$getTemplateCallSite") \
F(home_object, ".home_object") \
F(initialize_const_global, "initializeConstGlobal") \
F(initialize_var_global, "initializeVarGlobal") \
F(is_construct_call, "_IsConstructCall") \

View File

@ -179,7 +179,7 @@ LanguageMode FunctionLiteral::language_mode() const {
bool FunctionLiteral::uses_super_property() const {
DCHECK_NOT_NULL(scope());
return scope()->uses_super_property() || scope()->inner_uses_super_property();
return scope()->uses_super_property();
}

View File

@ -2539,6 +2539,26 @@ class FunctionLiteral final : public Expression {
dont_optimize_reason_ = reason;
}
static int num_ids() { return parent_num_ids() + 1; }
TypeFeedbackId HomeObjectFeedbackId() { return TypeFeedbackId(local_id(0)); }
// Type feedback information.
virtual FeedbackVectorRequirements ComputeFeedbackRequirements(
Isolate* isolate, const ICSlotCache* cache) override {
return FeedbackVectorRequirements(0, 1);
}
void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot,
ICSlotCache* cache) override {
DCHECK(!slot.IsInvalid());
home_object_feedback_slot_ = slot;
}
Code::Kind FeedbackICSlotKind(int index) override { return Code::LOAD_IC; }
FeedbackVectorICSlot HomeObjectFeedbackSlot() {
DCHECK(!home_object_feedback_slot_.IsInvalid());
return home_object_feedback_slot_;
}
protected:
FunctionLiteral(Zone* zone, const AstRawString* name,
AstValueFactory* ast_value_factory, Scope* scope,
@ -2560,7 +2580,8 @@ class FunctionLiteral final : public Expression {
expected_property_count_(expected_property_count),
handler_count_(handler_count),
parameter_count_(parameter_count),
function_token_position_(RelocInfo::kNoPosition) {
function_token_position_(RelocInfo::kNoPosition),
home_object_feedback_slot_(FeedbackVectorICSlot::Invalid()) {
bitfield_ = IsExpression::encode(function_type != DECLARATION) |
IsAnonymous::encode(function_type == ANONYMOUS_EXPRESSION) |
Pretenure::encode(false) |
@ -2572,6 +2593,8 @@ class FunctionLiteral final : public Expression {
DCHECK(IsValidFunctionKind(kind));
}
static int parent_num_ids() { return Expression::num_ids(); }
private:
const AstRawString* raw_name_;
Handle<String> name_;
@ -2589,6 +2612,9 @@ class FunctionLiteral final : public Expression {
int parameter_count_;
int function_token_position_;
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
FeedbackVectorICSlot home_object_feedback_slot_;
unsigned bitfield_;
class IsExpression : public BitField<bool, 0, 1> {};
class IsAnonymous : public BitField<bool, 1, 1> {};
@ -2690,37 +2716,21 @@ class SuperReference final : public Expression {
DECLARE_NODE_TYPE(SuperReference)
VariableProxy* this_var() const { return this_var_; }
static int num_ids() { return parent_num_ids(); }
// Type feedback information.
virtual FeedbackVectorRequirements ComputeFeedbackRequirements(
Isolate* isolate, const ICSlotCache* cache) override {
return FeedbackVectorRequirements(0, 1);
}
void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot,
ICSlotCache* cache) override {
homeobject_feedback_slot_ = slot;
}
Code::Kind FeedbackICSlotKind(int index) override { return Code::LOAD_IC; }
FeedbackVectorICSlot HomeObjectFeedbackSlot() {
DCHECK(!homeobject_feedback_slot_.IsInvalid());
return homeobject_feedback_slot_;
}
VariableProxy* home_object_var() const { return home_object_var_; }
protected:
SuperReference(Zone* zone, VariableProxy* this_var, int pos)
SuperReference(Zone* zone, VariableProxy* this_var,
VariableProxy* home_object_var, int pos)
: Expression(zone, pos),
this_var_(this_var),
homeobject_feedback_slot_(FeedbackVectorICSlot::Invalid()) {
home_object_var_(home_object_var) {
DCHECK(this_var->is_this());
DCHECK(home_object_var->raw_name()->IsOneByteEqualTo(".home_object"));
}
static int parent_num_ids() { return Expression::num_ids(); }
private:
VariableProxy* this_var_;
FeedbackVectorICSlot homeobject_feedback_slot_;
VariableProxy* home_object_var_;
};
@ -3491,8 +3501,9 @@ class AstNodeFactory final BASE_EMBEDDED {
return new (zone_) ThisFunction(zone_, pos);
}
SuperReference* NewSuperReference(VariableProxy* this_var, int pos) {
return new (zone_) SuperReference(zone_, this_var, pos);
SuperReference* NewSuperReference(VariableProxy* this_var,
VariableProxy* home_object_var, int pos) {
return new (zone_) SuperReference(zone_, this_var, home_object_var, pos);
}
private:

View File

@ -2225,6 +2225,13 @@ void AstGraphBuilder::VisitThrow(Throw* expr) {
void AstGraphBuilder::VisitProperty(Property* expr) {
if (expr->obj()->IsSuperReference()) {
// TODO(turbofan): Implement super here.
SetStackOverflow();
ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
return;
}
Node* value;
VectorSlotPair pair = CreateVectorSlotPair(expr->PropertyFeedbackSlot());
if (expr->key()->IsPropertyName()) {

View File

@ -676,8 +676,6 @@ class FullCodeGenerator: public AstVisitor {
// accumulator.
void EmitKeyedPropertyAssignment(Assignment* expr);
void EmitLoadHomeObject(SuperReference* expr);
static bool NeedsHomeObject(Expression* expr) {
return FunctionLiteral::NeedsHomeObject(expr);
}

View File

@ -238,6 +238,11 @@ void FullCodeGenerator::Generate() {
}
}
Variable* home_object_var = scope()->home_object_var();
if (home_object_var != nullptr) {
__ push(edi);
}
ArgumentsAccessStub::HasNewTarget has_new_target =
IsSubclassConstructor(info->function()->kind())
? ArgumentsAccessStub::HAS_NEW_TARGET
@ -303,6 +308,19 @@ void FullCodeGenerator::Generate() {
SetVar(arguments, eax, ebx, edx);
}
// Possibly set up a local binding to the [[HomeObject]].
if (home_object_var != nullptr) {
Comment cmnt(masm_, "[ Home object");
__ pop(LoadDescriptor::ReceiverRegister());
Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
__ mov(LoadDescriptor::NameRegister(), Immediate(home_object_symbol));
__ mov(LoadDescriptor::SlotRegister(),
Immediate(SmiFromSlot(function()->HomeObjectFeedbackSlot())));
CallLoadIC(NOT_CONTEXTUAL);
SetVar(home_object_var, eax, ebx, edx);
}
if (FLAG_trace) {
__ CallRuntime(Runtime::kTraceEnter, 0);
}
@ -1251,27 +1269,6 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
}
void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
Comment cnmt(masm_, "[ SuperReference ");
__ mov(LoadDescriptor::ReceiverRegister(),
Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
__ mov(LoadDescriptor::NameRegister(), home_object_symbol);
__ mov(LoadDescriptor::SlotRegister(),
Immediate(SmiFromSlot(expr->HomeObjectFeedbackSlot())));
CallLoadIC(NOT_CONTEXTUAL);
__ cmp(eax, isolate()->factory()->undefined_value());
Label done;
__ j(not_equal, &done);
__ CallRuntime(Runtime::kThrowNonMethodError, 0);
__ bind(&done);
}
void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
int offset) {
if (NeedsHomeObject(initializer)) {
@ -1898,7 +1895,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
break;
case NAMED_SUPER_PROPERTY:
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(property->obj()->AsSuperReference());
VisitForAccumulatorValue(
property->obj()->AsSuperReference()->home_object_var());
__ push(result_register());
if (expr->is_compound()) {
__ push(MemOperand(esp, kPointerSize));
@ -1916,8 +1914,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
break;
case KEYED_SUPER_PROPERTY:
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(property->obj()->AsSuperReference());
__ Push(result_register());
VisitForStackValue(
property->obj()->AsSuperReference()->home_object_var());
VisitForAccumulatorValue(property->key());
__ Push(result_register());
if (expr->is_compound()) {
@ -2540,7 +2538,8 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
case NAMED_SUPER_PROPERTY: {
__ push(eax);
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
VisitForAccumulatorValue(
prop->obj()->AsSuperReference()->home_object_var());
// stack: value, this; eax: home_object
Register scratch = ecx;
Register scratch2 = edx;
@ -2556,8 +2555,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
case KEYED_SUPER_PROPERTY: {
__ push(eax);
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
__ push(result_register());
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
VisitForAccumulatorValue(prop->key());
Register scratch = ecx;
Register scratch2 = edx;
@ -2768,8 +2766,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
EmitNamedPropertyLoad(expr);
} else {
VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(expr->obj()->AsSuperReference());
__ push(result_register());
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
EmitNamedSuperPropertyLoad(expr);
}
} else {
@ -2781,8 +2778,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
EmitKeyedPropertyLoad(expr);
} else {
VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(expr->obj()->AsSuperReference());
__ push(result_register());
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
VisitForStackValue(expr->key());
EmitKeyedSuperPropertyLoad(expr);
}
@ -2841,8 +2837,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
DCHECK(!key->value()->IsSmi());
// Load the function from the receiver.
SuperReference* super_ref = callee->AsProperty()->obj()->AsSuperReference();
EmitLoadHomeObject(super_ref);
__ push(eax);
VisitForStackValue(super_ref->home_object_var());
VisitForAccumulatorValue(super_ref->this_var());
__ push(eax);
__ push(eax);
@ -2898,8 +2893,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
SetSourcePosition(prop->position());
// Load the function from the receiver.
SuperReference* super_ref = callee->AsProperty()->obj()->AsSuperReference();
EmitLoadHomeObject(super_ref);
__ push(eax);
VisitForStackValue(super_ref->home_object_var());
VisitForAccumulatorValue(super_ref->this_var());
__ push(eax);
__ push(eax);
@ -4771,7 +4765,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case NAMED_SUPER_PROPERTY: {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
VisitForAccumulatorValue(
prop->obj()->AsSuperReference()->home_object_var());
__ push(result_register());
__ push(MemOperand(esp, kPointerSize));
__ push(result_register());
@ -4781,8 +4776,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case KEYED_SUPER_PROPERTY: {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
__ push(result_register());
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
VisitForAccumulatorValue(prop->key());
__ push(result_register());
__ push(MemOperand(esp, 2 * kPointerSize));

View File

@ -251,6 +251,11 @@ void FullCodeGenerator::Generate() {
}
}
Variable* home_object_var = scope()->home_object_var();
if (home_object_var != nullptr) {
__ Push(a1);
}
ArgumentsAccessStub::HasNewTarget has_new_target =
IsSubclassConstructor(info->function()->kind())
? ArgumentsAccessStub::HAS_NEW_TARGET
@ -317,6 +322,19 @@ void FullCodeGenerator::Generate() {
SetVar(arguments, v0, a1, a2);
}
// Possibly set up a local binding to the [[HomeObject]].
if (home_object_var != nullptr) {
Comment cmnt(masm_, "[ Home object");
__ Pop(LoadDescriptor::ReceiverRegister());
Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
__ li(LoadDescriptor::NameRegister(), Operand(home_object_symbol));
__ li(LoadDescriptor::SlotRegister(),
Operand(SmiFromSlot(function()->HomeObjectFeedbackSlot())));
CallLoadIC(NOT_CONTEXTUAL);
SetVar(home_object_var, v0, a1, a2);
}
if (FLAG_trace) {
__ CallRuntime(Runtime::kTraceEnter, 0);
}
@ -1313,26 +1331,6 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
}
void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
Comment cnmt(masm_, "[ SuperReference ");
__ lw(LoadDescriptor::ReceiverRegister(),
MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
__ li(LoadDescriptor::NameRegister(), home_object_symbol);
__ li(LoadDescriptor::SlotRegister(),
Operand(SmiFromSlot(expr->HomeObjectFeedbackSlot())));
CallLoadIC(NOT_CONTEXTUAL);
Label done;
__ Branch(&done, ne, v0, Operand(isolate()->factory()->undefined_value()));
__ CallRuntime(Runtime::kThrowNonMethodError, 0);
__ bind(&done);
}
void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
int offset) {
if (NeedsHomeObject(initializer)) {
@ -1966,7 +1964,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
break;
case NAMED_SUPER_PROPERTY:
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(property->obj()->AsSuperReference());
VisitForAccumulatorValue(
property->obj()->AsSuperReference()->home_object_var());
__ Push(result_register());
if (expr->is_compound()) {
const Register scratch = a1;
@ -1977,7 +1976,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
case KEYED_SUPER_PROPERTY: {
const Register scratch = a1;
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(property->obj()->AsSuperReference());
VisitForAccumulatorValue(
property->obj()->AsSuperReference()->home_object_var());
__ Move(scratch, result_register());
VisitForAccumulatorValue(property->key());
__ Push(scratch, result_register());
@ -2610,7 +2610,8 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
case NAMED_SUPER_PROPERTY: {
__ Push(v0);
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
VisitForAccumulatorValue(
prop->obj()->AsSuperReference()->home_object_var());
// stack: value, this; v0: home_object
Register scratch = a2;
Register scratch2 = a3;
@ -2626,8 +2627,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
case KEYED_SUPER_PROPERTY: {
__ Push(v0);
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
__ Push(result_register());
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
VisitForAccumulatorValue(prop->key());
Register scratch = a2;
Register scratch2 = a3;
@ -2844,8 +2844,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
EmitNamedPropertyLoad(expr);
} else {
VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(expr->obj()->AsSuperReference());
__ Push(result_register());
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
EmitNamedSuperPropertyLoad(expr);
}
} else {
@ -2857,8 +2856,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
EmitKeyedPropertyLoad(expr);
} else {
VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(expr->obj()->AsSuperReference());
__ Push(result_register());
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
VisitForStackValue(expr->key());
EmitKeyedSuperPropertyLoad(expr);
}
@ -2921,7 +2919,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
// Load the function from the receiver.
const Register scratch = a1;
SuperReference* super_ref = prop->obj()->AsSuperReference();
EmitLoadHomeObject(super_ref);
VisitForAccumulatorValue(super_ref->home_object_var());
__ mov(scratch, v0);
VisitForAccumulatorValue(super_ref->this_var());
__ Push(scratch, v0, v0, scratch);
@ -2979,7 +2977,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
// Load the function from the receiver.
const Register scratch = a1;
SuperReference* super_ref = prop->obj()->AsSuperReference();
EmitLoadHomeObject(super_ref);
VisitForAccumulatorValue(super_ref->home_object_var());
__ Move(scratch, v0);
VisitForAccumulatorValue(super_ref->this_var());
__ Push(scratch, v0, v0, scratch);
@ -4851,7 +4849,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case NAMED_SUPER_PROPERTY: {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
VisitForAccumulatorValue(
prop->obj()->AsSuperReference()->home_object_var());
__ Push(result_register());
const Register scratch = a1;
__ lw(scratch, MemOperand(sp, kPointerSize));
@ -4862,7 +4861,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case KEYED_SUPER_PROPERTY: {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
VisitForAccumulatorValue(
prop->obj()->AsSuperReference()->home_object_var());
const Register scratch = a1;
const Register scratch1 = t0;
__ Move(scratch, result_register());

View File

@ -248,6 +248,11 @@ void FullCodeGenerator::Generate() {
}
}
Variable* home_object_var = scope()->home_object_var();
if (home_object_var != nullptr) {
__ Push(a1);
}
ArgumentsAccessStub::HasNewTarget has_new_target =
IsSubclassConstructor(info->function()->kind())
? ArgumentsAccessStub::HAS_NEW_TARGET
@ -314,6 +319,19 @@ void FullCodeGenerator::Generate() {
SetVar(arguments, v0, a1, a2);
}
// Possibly set up a local binding to the [[HomeObject]].
if (home_object_var != nullptr) {
Comment cmnt(masm_, "[ Home object");
__ pop(LoadDescriptor::ReceiverRegister());
Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
__ li(LoadDescriptor::NameRegister(), home_object_symbol);
__ li(LoadDescriptor::SlotRegister(),
Operand(SmiFromSlot(function()->HomeObjectFeedbackSlot())));
CallLoadIC(NOT_CONTEXTUAL);
SetVar(home_object_var, v0, a1, a2);
}
if (FLAG_trace) {
__ CallRuntime(Runtime::kTraceEnter, 0);
}
@ -1310,26 +1328,6 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
}
void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
Comment cnmt(masm_, "[ SuperReference ");
__ ld(LoadDescriptor::ReceiverRegister(),
MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
__ li(LoadDescriptor::NameRegister(), home_object_symbol);
__ li(LoadDescriptor::SlotRegister(),
Operand(SmiFromSlot(expr->HomeObjectFeedbackSlot())));
CallLoadIC(NOT_CONTEXTUAL);
Label done;
__ Branch(&done, ne, v0, Operand(isolate()->factory()->undefined_value()));
__ CallRuntime(Runtime::kThrowNonMethodError, 0);
__ bind(&done);
}
void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
int offset) {
if (NeedsHomeObject(initializer)) {
@ -1965,7 +1963,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
break;
case NAMED_SUPER_PROPERTY:
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(property->obj()->AsSuperReference());
VisitForAccumulatorValue(
property->obj()->AsSuperReference()->home_object_var());
__ Push(result_register());
if (expr->is_compound()) {
const Register scratch = a1;
@ -1976,7 +1975,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
case KEYED_SUPER_PROPERTY: {
const Register scratch = a1;
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(property->obj()->AsSuperReference());
VisitForAccumulatorValue(
property->obj()->AsSuperReference()->home_object_var());
__ Move(scratch, result_register());
VisitForAccumulatorValue(property->key());
__ Push(scratch, result_register());
@ -2609,7 +2609,8 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
case NAMED_SUPER_PROPERTY: {
__ Push(v0);
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
VisitForAccumulatorValue(
prop->obj()->AsSuperReference()->home_object_var());
// stack: value, this; v0: home_object
Register scratch = a2;
Register scratch2 = a3;
@ -2625,8 +2626,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
case KEYED_SUPER_PROPERTY: {
__ Push(v0);
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
__ Push(result_register());
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
VisitForAccumulatorValue(prop->key());
Register scratch = a2;
Register scratch2 = a3;
@ -2847,8 +2847,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
EmitNamedPropertyLoad(expr);
} else {
VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(expr->obj()->AsSuperReference());
__ Push(result_register());
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
EmitNamedSuperPropertyLoad(expr);
}
} else {
@ -2860,8 +2859,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
EmitKeyedPropertyLoad(expr);
} else {
VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(expr->obj()->AsSuperReference());
__ Push(result_register());
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
VisitForStackValue(expr->key());
EmitKeyedSuperPropertyLoad(expr);
}
@ -2924,7 +2922,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
// Load the function from the receiver.
const Register scratch = a1;
SuperReference* super_ref = prop->obj()->AsSuperReference();
EmitLoadHomeObject(super_ref);
VisitForAccumulatorValue(super_ref->home_object_var());
__ mov(scratch, v0);
VisitForAccumulatorValue(super_ref->this_var());
__ Push(scratch, v0, v0, scratch);
@ -2982,7 +2980,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
// Load the function from the receiver.
const Register scratch = a1;
SuperReference* super_ref = prop->obj()->AsSuperReference();
EmitLoadHomeObject(super_ref);
VisitForAccumulatorValue(super_ref->home_object_var());
__ Move(scratch, v0);
VisitForAccumulatorValue(super_ref->this_var());
__ Push(scratch, v0, v0, scratch);
@ -4854,7 +4852,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case NAMED_SUPER_PROPERTY: {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
VisitForAccumulatorValue(
prop->obj()->AsSuperReference()->home_object_var());
__ Push(result_register());
const Register scratch = a1;
__ ld(scratch, MemOperand(sp, kPointerSize));
@ -4865,7 +4864,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case KEYED_SUPER_PROPERTY: {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
VisitForAccumulatorValue(
prop->obj()->AsSuperReference()->home_object_var());
const Register scratch = a1;
const Register scratch1 = a4;
__ Move(scratch, result_register());

View File

@ -749,8 +749,13 @@ Expression* ParserTraits::ThisExpression(Scope* scope, AstNodeFactory* factory,
Expression* ParserTraits::SuperReference(Scope* scope, AstNodeFactory* factory,
int pos) {
// TODO(arv): Split into SuperProperty and SuperCall?
VariableProxy* home_object_proxy = scope->NewUnresolved(
factory, parser_->ast_value_factory()->home_object_string(),
Variable::NORMAL, pos);
return factory->NewSuperReference(
ThisExpression(scope, factory, pos)->AsVariableProxy(),
ThisExpression(scope, factory, pos)->AsVariableProxy(), home_object_proxy,
pos);
}
@ -1138,7 +1143,8 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info,
bool ok = true;
if (shared_info->is_arrow()) {
Scope* scope = NewScope(scope_, ARROW_SCOPE);
Scope* scope =
NewScope(scope_, ARROW_SCOPE, FunctionKind::kArrowFunction);
scope->set_start_position(shared_info->start_position());
ExpressionClassifier formals_classifier;
bool has_rest = false;

View File

@ -724,8 +724,7 @@ class ParserTraits {
Expression* ThisExpression(Scope* scope, AstNodeFactory* factory,
int pos = RelocInfo::kNoPosition);
Expression* SuperReference(Scope* scope, AstNodeFactory* factory,
int pos = RelocInfo::kNoPosition);
Expression* SuperReference(Scope* scope, AstNodeFactory* factory, int pos);
Expression* DefaultConstructor(bool call_super, Scope* scope, int pos,
int end_pos);
Literal* ExpressionFromLiteral(Token::Value token, int pos, Scanner* scanner,

View File

@ -110,7 +110,7 @@ PreParser::PreParseResult PreParser::PreParseLazyFunction(
FunctionState top_state(&function_state_, &scope_, top_scope, kNormalFunction,
&top_factory);
scope_->SetLanguageMode(language_mode);
Scope* function_scope = NewScope(scope_, FUNCTION_SCOPE);
Scope* function_scope = NewScope(scope_, FUNCTION_SCOPE, kind);
PreParserFactory function_factory(NULL);
FunctionState function_state(&function_state_, &scope_, function_scope, kind,
&function_factory);
@ -1028,7 +1028,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
// Parse function body.
bool outer_is_script_scope = scope_->is_script_scope();
Scope* function_scope = NewScope(scope_, FUNCTION_SCOPE);
Scope* function_scope = NewScope(scope_, FUNCTION_SCOPE, kind);
PreParserFactory factory(NULL);
FunctionState function_state(&function_state_, &scope_, function_scope, kind,
&factory);

View File

@ -339,12 +339,17 @@ class ParserBase : public Traits {
Mode old_mode_;
};
Scope* NewScope(Scope* parent, ScopeType scope_type,
FunctionKind kind = kNormalFunction) {
Scope* NewScope(Scope* parent, ScopeType scope_type) {
// Must always pass the function kind for FUNCTION_SCOPE and ARROW_SCOPE.
DCHECK(scope_type != FUNCTION_SCOPE);
DCHECK(scope_type != ARROW_SCOPE);
return NewScope(parent, scope_type, kNormalFunction);
}
Scope* NewScope(Scope* parent, ScopeType scope_type, FunctionKind kind) {
DCHECK(ast_value_factory());
DCHECK(scope_type != MODULE_SCOPE || allow_harmony_modules());
DCHECK((scope_type == FUNCTION_SCOPE && IsValidFunctionKind(kind)) ||
kind == kNormalFunction);
DCHECK(scope_type != ARROW_SCOPE || IsArrowFunction(kind));
Scope* result = new (zone())
Scope(zone(), parent, scope_type, ast_value_factory(), kind);
result->Initialize();
@ -1711,7 +1716,8 @@ class PreParserTraits {
}
static PreParserExpression SuperReference(Scope* scope,
PreParserFactory* factory) {
PreParserFactory* factory,
int pos) {
return PreParserExpression::Default();
}
@ -2393,7 +2399,8 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier,
classifier->RecordBindingPatternError(scanner()->location(),
MessageTemplate::kUnexpectedToken,
Token::String(Token::RPAREN));
Scope* scope = this->NewScope(scope_, ARROW_SCOPE);
Scope* scope =
this->NewScope(scope_, ARROW_SCOPE, FunctionKind::kArrowFunction);
scope->set_start_position(beg_pos);
ExpressionClassifier args_classifier;
bool has_rest = false;
@ -2920,7 +2927,8 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN,
CHECK_OK);
Scanner::Location loc(lhs_location.beg_pos, scanner()->location().end_pos);
bool has_rest = false;
Scope* scope = this->NewScope(scope_, ARROW_SCOPE);
Scope* scope =
this->NewScope(scope_, ARROW_SCOPE, FunctionKind::kArrowFunction);
scope->set_start_position(lhs_location.beg_pos);
Scanner::Location duplicate_loc = Scanner::Location::invalid();
this->ParseArrowFunctionFormalParameters(scope, expression, loc, &has_rest,
@ -3507,7 +3515,7 @@ ParserBase<Traits>::ParseStrongSuperCallExpression(
Consume(Token::SUPER);
int pos = position();
Scanner::Location super_loc = scanner()->location();
ExpressionT expr = this->SuperReference(scope_, factory());
ExpressionT expr = this->SuperReference(scope_, factory(), pos);
if (peek() != Token::LPAREN) {
ReportMessage(MessageTemplate::kStrongConstructorSuper);
@ -3556,21 +3564,23 @@ typename ParserBase<Traits>::ExpressionT
ParserBase<Traits>::ParseSuperExpression(bool is_new,
ExpressionClassifier* classifier,
bool* ok) {
int pos = position();
Expect(Token::SUPER, CHECK_OK);
// TODO(wingo): Does this actually work with lazily compiled arrows?
FunctionState* function_state = function_state_;
while (IsArrowFunction(function_state->kind())) {
function_state = function_state->outer();
}
// TODO(arv): Handle eval scopes similarly.
Scope* scope = scope_->DeclarationScope();
FunctionKind kind = function_state->kind();
while (scope->is_eval_scope() || scope->is_arrow_scope()) {
scope = scope->outer_scope();
DCHECK_NOT_NULL(scope);
scope = scope->DeclarationScope();
}
FunctionKind kind = scope->function_kind();
if (IsConciseMethod(kind) || IsAccessorFunction(kind) ||
i::IsConstructor(kind)) {
if (peek() == Token::PERIOD || peek() == Token::LBRACK) {
scope_->RecordSuperPropertyUsage();
return this->SuperReference(scope_, factory());
scope->RecordSuperPropertyUsage();
return this->SuperReference(scope_, factory(), pos);
}
// new super() is never allowed.
// super() is only allowed in derived constructor
@ -3582,8 +3592,10 @@ ParserBase<Traits>::ParseSuperExpression(bool is_new,
*ok = false;
return this->EmptyExpression();
}
function_state->set_super_location(scanner()->location());
return this->SuperReference(scope_, factory());
// TODO(rossberg): This might not be the correct FunctionState for the
// method here.
function_state_->set_super_location(scanner()->location());
return this->SuperReference(scope_, factory(), pos);
}
}

View File

@ -154,12 +154,13 @@ void Scope::SetDefaults(ScopeType scope_type, Scope* outer_scope,
function_kind_ = function_kind;
block_scope_is_class_scope_ = false;
scope_name_ = ast_value_factory_->empty_string();
dynamics_ = NULL;
receiver_ = NULL;
dynamics_ = nullptr;
receiver_ = nullptr;
new_target_ = nullptr;
function_ = NULL;
arguments_ = NULL;
illegal_redecl_ = NULL;
function_ = nullptr;
arguments_ = nullptr;
home_object_ = nullptr;
illegal_redecl_ = nullptr;
scope_inside_with_ = false;
scope_contains_with_ = false;
scope_calls_eval_ = false;
@ -172,7 +173,6 @@ void Scope::SetDefaults(ScopeType scope_type, Scope* outer_scope,
outer_scope_calls_sloppy_eval_ = false;
inner_scope_calls_eval_ = false;
inner_scope_uses_arguments_ = false;
inner_scope_uses_super_property_ = false;
force_eager_compilation_ = false;
force_context_allocation_ = (outer_scope != NULL && !is_function_scope())
? outer_scope->has_forced_context_allocation() : false;
@ -337,6 +337,17 @@ void Scope::Initialize() {
Variable::ARGUMENTS,
kCreatedInitialized);
}
if (is_function_scope() &&
(IsConciseMethod(function_kind_) || IsConstructor(function_kind_) ||
IsAccessorFunction(function_kind_))) {
DCHECK(!is_arrow_scope());
// Declare '.home_object' variable which exists in all methods.
// Note that it might never be accessed, in which case it won't be
// allocated during variable allocation.
variables_.Declare(this, ast_value_factory_->home_object_string(), VAR,
Variable::NORMAL, kCreatedInitialized);
}
}
@ -929,8 +940,6 @@ void Scope::Print(int n) {
if (inner_scope_uses_arguments_) {
Indent(n1, "// inner scope uses 'arguments'\n");
}
if (inner_scope_uses_super_property_)
Indent(n1, "// inner scope uses 'super' property\n");
if (outer_scope_calls_sloppy_eval_) {
Indent(n1, "// outer scope calls 'eval' in sloppy context\n");
}
@ -1287,10 +1296,6 @@ void Scope::PropagateScopeInfo(bool outer_scope_calls_sloppy_eval ) {
if (inner->scope_uses_arguments_ || inner->inner_scope_uses_arguments_) {
inner_scope_uses_arguments_ = true;
}
if (inner->scope_uses_super_property_ ||
inner->inner_scope_uses_super_property_) {
inner_scope_uses_super_property_ = true;
}
}
if (inner->force_eager_compilation_) {
force_eager_compilation_ = true;
@ -1398,6 +1403,18 @@ void Scope::AllocateParameterLocals(Isolate* isolate) {
rest_parameter_ = NULL;
}
Variable* home_object_var =
LookupLocal(ast_value_factory_->home_object_string());
if (home_object_var != nullptr && uses_super_property() &&
MustAllocate(home_object_var)) {
// TODO(arv): super() uses a SuperReference so it generates a VariableProxy
// for the .home_object which makes it look like we need to allocate the
// home_object_var.
// Consider splitting the AST node into 2 different nodes since the
// semantics is just so different.
home_object_ = home_object_var;
}
// The same parameter may occur multiple times in the parameters_ list.
// If it does, and if it is not copied into the context object, it must
// receive the highest parameter index for that parameter; thus iteration

View File

@ -409,6 +409,16 @@ class Scope: public ZoneObject {
return arguments_;
}
// A local variable to the [[HomeObject]] used by methods if we need to
// allocate it; NULL otherwise.
Variable* home_object_var() const {
DCHECK(home_object_ == nullptr ||
(is_function_scope() && (IsConciseMethod(function_kind()) ||
IsAccessorFunction(function_kind()) ||
IsConstructor(function_kind()))));
return home_object_;
}
// Declarations list.
ZoneList<Declaration*>* declarations() { return &decls_; }
@ -567,6 +577,8 @@ class Scope: public ZoneObject {
Variable* new_target_;
// Convenience variable; function scopes only.
Variable* arguments_;
// Convenience variable; method scopes only.
Variable* home_object_;
// Module descriptor; module scopes only.
ModuleDescriptor* module_descriptor_;

View File

@ -234,6 +234,11 @@ void FullCodeGenerator::Generate() {
}
}
Variable* home_object_var = scope()->home_object_var();
if (home_object_var != nullptr) {
__ Push(rdi);
}
ArgumentsAccessStub::HasNewTarget has_new_target =
IsSubclassConstructor(info->function()->kind())
? ArgumentsAccessStub::HAS_NEW_TARGET
@ -301,6 +306,20 @@ void FullCodeGenerator::Generate() {
SetVar(arguments, rax, rbx, rdx);
}
// Possibly set up a local binding to the [[HomeObject]].
// Variable* home_object_var = scope()->home_object_var();
if (home_object_var != nullptr) {
Comment cmnt(masm_, "[ Home object");
__ Pop(LoadDescriptor::ReceiverRegister());
Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
__ Move(LoadDescriptor::NameRegister(), home_object_symbol);
__ Move(LoadDescriptor::SlotRegister(),
SmiFromSlot(function()->HomeObjectFeedbackSlot()));
CallLoadIC(NOT_CONTEXTUAL);
SetVar(home_object_var, rax, rbx, rdx);
}
if (FLAG_trace) {
__ CallRuntime(Runtime::kTraceEnter, 0);
}
@ -1285,27 +1304,6 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
}
void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
Comment cnmt(masm_, "[ SuperReference ");
__ movp(LoadDescriptor::ReceiverRegister(),
Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
__ Move(LoadDescriptor::NameRegister(), home_object_symbol);
__ Move(LoadDescriptor::SlotRegister(),
SmiFromSlot(expr->HomeObjectFeedbackSlot()));
CallLoadIC(NOT_CONTEXTUAL);
__ Cmp(rax, isolate()->factory()->undefined_value());
Label done;
__ j(not_equal, &done);
__ CallRuntime(Runtime::kThrowNonMethodError, 0);
__ bind(&done);
}
void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
int offset) {
if (NeedsHomeObject(initializer)) {
@ -1939,7 +1937,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
break;
case NAMED_SUPER_PROPERTY:
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(property->obj()->AsSuperReference());
VisitForAccumulatorValue(
property->obj()->AsSuperReference()->home_object_var());
__ Push(result_register());
if (expr->is_compound()) {
__ Push(MemOperand(rsp, kPointerSize));
@ -1948,8 +1947,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
break;
case KEYED_SUPER_PROPERTY:
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(property->obj()->AsSuperReference());
__ Push(result_register());
VisitForStackValue(
property->obj()->AsSuperReference()->home_object_var());
VisitForAccumulatorValue(property->key());
__ Push(result_register());
if (expr->is_compound()) {
@ -2540,7 +2539,8 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
case NAMED_SUPER_PROPERTY: {
__ Push(rax);
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
VisitForAccumulatorValue(
prop->obj()->AsSuperReference()->home_object_var());
// stack: value, this; rax: home_object
Register scratch = rcx;
Register scratch2 = rdx;
@ -2556,8 +2556,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
case KEYED_SUPER_PROPERTY: {
__ Push(rax);
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
__ Push(result_register());
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
VisitForAccumulatorValue(prop->key());
Register scratch = rcx;
Register scratch2 = rdx;
@ -2765,8 +2764,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
EmitNamedPropertyLoad(expr);
} else {
VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(expr->obj()->AsSuperReference());
__ Push(result_register());
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
EmitNamedSuperPropertyLoad(expr);
}
} else {
@ -2778,8 +2776,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
EmitKeyedPropertyLoad(expr);
} else {
VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(expr->obj()->AsSuperReference());
__ Push(result_register());
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
VisitForStackValue(expr->key());
EmitKeyedSuperPropertyLoad(expr);
}
@ -2838,8 +2835,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
DCHECK(!key->value()->IsSmi());
// Load the function from the receiver.
SuperReference* super_ref = prop->obj()->AsSuperReference();
EmitLoadHomeObject(super_ref);
__ Push(rax);
VisitForStackValue(super_ref->home_object_var());
VisitForAccumulatorValue(super_ref->this_var());
__ Push(rax);
__ Push(rax);
@ -2896,8 +2892,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
SetSourcePosition(prop->position());
// Load the function from the receiver.
SuperReference* super_ref = prop->obj()->AsSuperReference();
EmitLoadHomeObject(super_ref);
__ Push(rax);
VisitForStackValue(super_ref->home_object_var());
VisitForAccumulatorValue(super_ref->this_var());
__ Push(rax);
__ Push(rax);
@ -4791,7 +4786,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case NAMED_SUPER_PROPERTY: {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
VisitForAccumulatorValue(
prop->obj()->AsSuperReference()->home_object_var());
__ Push(result_register());
__ Push(MemOperand(rsp, kPointerSize));
__ Push(result_register());
@ -4801,8 +4797,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case KEYED_SUPER_PROPERTY: {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
EmitLoadHomeObject(prop->obj()->AsSuperReference());
__ Push(result_register());
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
VisitForAccumulatorValue(prop->key());
__ Push(result_register());
__ Push(MemOperand(rsp, 2 * kPointerSize));

View File

@ -310,10 +310,10 @@ TEST(FeedbackVectorPreservedAcrossRecompiles) {
// Verify that we gathered feedback.
int expected_slots = 0;
int expected_ic_slots = 1;
int expected_ic_slots = 2;
CHECK_EQ(expected_slots, feedback_vector->Slots());
CHECK_EQ(expected_ic_slots, feedback_vector->ICSlots());
FeedbackVectorICSlot slot_for_a(0);
FeedbackVectorICSlot slot_for_a(1);
Object* object = feedback_vector->Get(slot_for_a);
CHECK(object->IsWeakCell() &&
WeakCell::cast(object)->value()->IsJSFunction());
@ -362,7 +362,7 @@ TEST(FeedbackVectorUnaffectedByScopeChanges) {
// Now a feedback vector is allocated.
CHECK(f->shared()->is_compiled());
int expected_slots = 0;
int expected_ic_slots = 2;
int expected_ic_slots = 3;
CHECK_EQ(expected_slots, f->shared()->feedback_vector()->Slots());
CHECK_EQ(expected_ic_slots, f->shared()->feedback_vector()->ICSlots());
}

View File

@ -173,7 +173,7 @@ TEST(VectorICProfilerStatistics) {
CHECK_EQ(0, feedback_info->ic_generic_count());
Handle<TypeFeedbackVector> feedback_vector =
handle(f->shared()->feedback_vector(), isolate);
int ic_slot = 0;
int ic_slot = 1;
CallICNexus nexus(feedback_vector, FeedbackVectorICSlot(ic_slot));
CHECK_EQ(1, feedback_vector->ic_with_type_info_count());
CHECK_EQ(0, feedback_vector->ic_generic_count());
@ -222,7 +222,7 @@ TEST(VectorCallICStates) {
// There should be one IC.
Handle<TypeFeedbackVector> feedback_vector =
Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate);
FeedbackVectorICSlot slot(0);
FeedbackVectorICSlot slot(1);
CallICNexus nexus(feedback_vector, slot);
CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
// CallIC doesn't return map feedback.
@ -264,7 +264,7 @@ TEST(VectorLoadICStates) {
// There should be one IC.
Handle<TypeFeedbackVector> feedback_vector =
Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate);
FeedbackVectorICSlot slot(0);
FeedbackVectorICSlot slot(1);
LoadICNexus nexus(feedback_vector, slot);
CHECK_EQ(PREMONOMORPHIC, nexus.StateFromFeedback());
@ -322,8 +322,8 @@ TEST(VectorLoadICSlotSharing) {
// There should be one IC slot.
Handle<TypeFeedbackVector> feedback_vector =
Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate);
CHECK_EQ(1, feedback_vector->ICSlots());
FeedbackVectorICSlot slot(0);
CHECK_EQ(2, feedback_vector->ICSlots());
FeedbackVectorICSlot slot(1);
LoadICNexus nexus(feedback_vector, slot);
CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
}
@ -346,7 +346,7 @@ TEST(VectorLoadICOnSmi) {
// There should be one IC.
Handle<TypeFeedbackVector> feedback_vector =
Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate);
FeedbackVectorICSlot slot(0);
FeedbackVectorICSlot slot(1);
LoadICNexus nexus(feedback_vector, slot);
CHECK_EQ(PREMONOMORPHIC, nexus.StateFromFeedback());

View File

@ -3322,10 +3322,10 @@ TEST(IncrementalMarkingPreservesMonomorphicCallIC) {
Handle<TypeFeedbackVector> feedback_vector(f->shared()->feedback_vector());
int expected_slots = 2;
int expected_slots = 3;
CHECK_EQ(expected_slots, feedback_vector->ICSlots());
int slot1 = 0;
int slot2 = 1;
int slot1 = 1;
int slot2 = 2;
CHECK(feedback_vector->Get(FeedbackVectorICSlot(slot1))->IsWeakCell());
CHECK(feedback_vector->Get(FeedbackVectorICSlot(slot2))->IsWeakCell());
@ -3448,14 +3448,14 @@ TEST(IncrementalMarkingPreservesMonomorphicIC) {
CcTest::global()->Get(v8_str("f"))));
Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
CheckVectorIC(f, 0, MONOMORPHIC);
CheckVectorIC(f, 1, MONOMORPHIC);
CHECK(ic_before->ic_state() == DEFAULT);
SimulateIncrementalMarking(CcTest::heap());
CcTest::heap()->CollectAllGarbage();
Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
CheckVectorIC(f, 0, MONOMORPHIC);
CheckVectorIC(f, 1, MONOMORPHIC);
CHECK(ic_after->ic_state() == DEFAULT);
}
@ -3480,7 +3480,7 @@ TEST(IncrementalMarkingClearsMonomorphicIC) {
*v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f"))));
Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
CheckVectorIC(f, 0, MONOMORPHIC);
CheckVectorIC(f, 1, MONOMORPHIC);
CHECK(ic_before->ic_state() == DEFAULT);
// Fire context dispose notification.
@ -3489,7 +3489,7 @@ TEST(IncrementalMarkingClearsMonomorphicIC) {
CcTest::heap()->CollectAllGarbage();
Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
CheckVectorICCleared(f, 0);
CheckVectorICCleared(f, 1);
CHECK(ic_after->ic_state() == DEFAULT);
}
@ -3521,7 +3521,7 @@ TEST(IncrementalMarkingPreservesPolymorphicIC) {
*v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f"))));
Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
CheckVectorIC(f, 0, POLYMORPHIC);
CheckVectorIC(f, 1, POLYMORPHIC);
CHECK(ic_before->ic_state() == DEFAULT);
// Fire context dispose notification.
@ -3529,7 +3529,7 @@ TEST(IncrementalMarkingPreservesPolymorphicIC) {
CcTest::heap()->CollectAllGarbage();
Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
CheckVectorIC(f, 0, POLYMORPHIC);
CheckVectorIC(f, 1, POLYMORPHIC);
CHECK(ic_after->ic_state() == DEFAULT);
}
@ -3561,7 +3561,7 @@ TEST(IncrementalMarkingClearsPolymorphicIC) {
*v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f"))));
Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
CheckVectorIC(f, 0, POLYMORPHIC);
CheckVectorIC(f, 1, POLYMORPHIC);
CHECK(ic_before->ic_state() == DEFAULT);
// Fire context dispose notification.
@ -3569,7 +3569,7 @@ TEST(IncrementalMarkingClearsPolymorphicIC) {
SimulateIncrementalMarking(CcTest::heap());
CcTest::heap()->CollectAllGarbage();
CheckVectorICCleared(f, 0);
CheckVectorICCleared(f, 1);
CHECK(ic_before->ic_state() == DEFAULT);
}
@ -4719,12 +4719,12 @@ TEST(MonomorphicStaysMonomorphicAfterGC) {
CompileRun("(testIC())");
}
heap->CollectAllGarbage();
CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 0, MONOMORPHIC);
CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 1, MONOMORPHIC);
{
v8::HandleScope scope(CcTest::isolate());
CompileRun("(testIC())");
}
CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 0, MONOMORPHIC);
CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 1, MONOMORPHIC);
}
@ -4755,12 +4755,12 @@ TEST(PolymorphicStaysPolymorphicAfterGC) {
CompileRun("(testIC())");
}
heap->CollectAllGarbage();
CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 0, POLYMORPHIC);
CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 1, POLYMORPHIC);
{
v8::HandleScope scope(CcTest::isolate());
CompileRun("(testIC())");
}
CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 0, POLYMORPHIC);
CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 1, POLYMORPHIC);
}

View File

@ -976,9 +976,9 @@ TEST(ScopeUsesArgumentsSuperThis) {
SUPER_PROPERTY = 1 << 1,
THIS = 1 << 2,
INNER_ARGUMENTS = 1 << 3,
INNER_SUPER_PROPERTY = 1 << 4,
};
// clang-format off
static const struct {
const char* body;
int expected;
@ -992,7 +992,7 @@ TEST(ScopeUsesArgumentsSuperThis) {
{"return this + arguments[0] + super.x",
ARGUMENTS | SUPER_PROPERTY | THIS},
{"return x => this + x", THIS},
{"return x => super.f() + x", INNER_SUPER_PROPERTY},
{"return x => super.f() + x", SUPER_PROPERTY},
{"this.foo = 42;", THIS},
{"this.foo();", THIS},
{"if (foo()) { this.f() }", THIS},
@ -1018,15 +1018,15 @@ TEST(ScopeUsesArgumentsSuperThis) {
{"\"use strict\"; while (true) { let x; this, arguments; }",
INNER_ARGUMENTS | THIS},
{"\"use strict\"; while (true) { let x; this, super.f(), arguments; }",
INNER_ARGUMENTS | INNER_SUPER_PROPERTY | THIS},
INNER_ARGUMENTS | SUPER_PROPERTY | THIS},
{"\"use strict\"; if (foo()) { let x; this.f() }", THIS},
{"\"use strict\"; if (foo()) { let x; super.f() }",
INNER_SUPER_PROPERTY},
{"\"use strict\"; if (foo()) { let x; super.f() }", SUPER_PROPERTY},
{"\"use strict\"; if (1) {"
" let x; return { m() { return this + super.m() + arguments } }"
"}",
NONE},
};
// clang-format on
i::Isolate* isolate = CcTest::i_isolate();
i::Factory* factory = isolate->factory();
@ -1042,7 +1042,6 @@ TEST(ScopeUsesArgumentsSuperThis) {
for (unsigned i = 0; i < arraysize(source_data); ++i) {
// Super property is only allowed in constructor and method.
if (((source_data[i].expected & SUPER_PROPERTY) ||
(source_data[i].expected & INNER_SUPER_PROPERTY) ||
(source_data[i].expected == NONE)) && j != 2) {
continue;
}
@ -1090,8 +1089,6 @@ TEST(ScopeUsesArgumentsSuperThis) {
}
CHECK_EQ((source_data[i].expected & INNER_ARGUMENTS) != 0,
scope->inner_uses_arguments());
CHECK_EQ((source_data[i].expected & INNER_SUPER_PROPERTY) != 0,
scope->inner_uses_super_property());
}
}
}

View File

@ -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-classes --allow-natives-syntax
// Flags: --harmony-classes --harmony-arrow-functions --allow-natives-syntax
(function TestHomeObject() {
@ -131,3 +131,42 @@
assertEquals(42, o.g().next().value);
})();
(function TestSuperPropertyInEval() {
var y = 3;
var p = {
m() { return 1; },
get x() { return 2; }
};
var o = {
__proto__: p,
eval() {
assertSame(super.x, eval('super.x'));
assertSame(super.m(), eval('super.m()'));
// Global eval.
assertThrows('super.x', SyntaxError);
assertThrows('super.m()', SyntaxError);
return eval('super.m()');
}
};
assertSame(1, o.eval());
})();
(function TestSuperPropertyInArrow() {
var y = 3;
var p = {
m() { return 1; },
get x() { return 2; }
};
var o = {
__proto__: p,
arrow() {
assertSame(super.x, (() => super.x)());
assertSame(super.m(), (() => super.m())());
return (() => super.m())();
}
};
assertSame(1, o.arrow());
})();

View File

@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-classes --allow-natives-syntax
// Flags: --harmony-classes --harmony-arrow-functions --allow-natives-syntax
(function TestSuperNamedLoads() {
function Base() { }
@ -2053,6 +2054,7 @@ TestKeyedSetterCreatingOwnPropertiesNonConfigurable(42, 43, 44);
assertInstanceof(f, Number);
}());
(function TestSuperCallErrorCases() {
'use strict';
class T extends Object {
@ -2064,3 +2066,44 @@ TestKeyedSetterCreatingOwnPropertiesNonConfigurable(42, 43, 44);
T.__proto__ = null;
assertThrows(function() { new T(); }, TypeError);
}());
(function TestSuperPropertyInEval() {
'use strict';
let y = 3;
class Base {
m() { return 1; }
get x() { return 2; }
}
class Derived extends Base {
eval() {
assertSame(super.x, eval('super.x'));
assertSame(super.m(), eval('super.m()'));
// Global eval.
assertThrows('super.x', SyntaxError);
assertThrows('super.m()', SyntaxError);
return eval('super.m()');
}
}
let d = new Derived();
assertSame(1, d.eval());
})();
(function TestSuperPropertyInArrow() {
'use strict';
let y = 3;
class Base {
m() { return 1; }
get x() { return 2; }
}
class Derived extends Base {
arrow() {
assertSame(super.x, (() => super.x)());
assertSame(super.m(), (() => super.m())());
return (() => super.m())();
}
}
let d = new Derived();
assertSame(1, d.arrow());
})();