}
}
+ 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
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);
}
}
-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)) {
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;
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()) {
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;
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;
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 {
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);
}
// 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);
// 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);
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));
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;
}
}
+ 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
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()) {
}
-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)) {
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;
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()) {
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;
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;
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 {
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);
}
// 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);
// 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);
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);
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;
ReserveFeedbackSlots(node);
node->set_base_id(ReserveIdRange(SuperReference::num_ids()));
Visit(node->this_var());
+ Visit(node->home_object_var());
}
DisableCrankshaft(kContextAllocatedArguments);
}
+ ReserveFeedbackSlots(node);
+
VisitDeclarations(scope->declarations());
if (scope->is_function_scope() && scope->function() != NULL) {
// Visit the name of the named function expression.
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") \
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();
}
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,
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) |
DCHECK(IsValidFunctionKind(kind));
}
+ static int parent_num_ids() { return Expression::num_ids(); }
+
private:
const AstRawString* raw_name_;
Handle<String> name_;
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> {};
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_;
};
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:
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()) {
// accumulator.
void EmitKeyedPropertyAssignment(Assignment* expr);
- void EmitLoadHomeObject(SuperReference* expr);
-
static bool NeedsHomeObject(Expression* expr) {
return FunctionLiteral::NeedsHomeObject(expr);
}
}
}
+ 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
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);
}
}
-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)) {
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));
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()) {
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;
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;
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 {
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);
}
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);
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);
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());
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));
}
}
+ 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
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);
}
}
-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)) {
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;
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());
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;
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;
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 {
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);
}
// 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);
// 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);
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));
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());
}
}
+ 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
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);
}
}
-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)) {
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;
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());
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;
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;
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 {
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);
}
// 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);
// 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);
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));
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());
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);
}
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;
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,
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);
// 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);
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();
}
static PreParserExpression SuperReference(Scope* scope,
- PreParserFactory* factory) {
+ PreParserFactory* factory,
+ int pos) {
return PreParserExpression::Default();
}
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;
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,
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);
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();
+ Scope* scope = scope_->DeclarationScope();
+
+ while (scope->is_eval_scope() || scope->is_arrow_scope()) {
+ scope = scope->outer_scope();
+ DCHECK_NOT_NULL(scope);
+ scope = scope->DeclarationScope();
}
- // TODO(arv): Handle eval scopes similarly.
- FunctionKind kind = function_state->kind();
+ 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
*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);
}
}
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;
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;
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);
+ }
}
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");
}
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;
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
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_; }
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_;
}
}
+ 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
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);
}
}
-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)) {
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));
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()) {
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;
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;
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 {
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);
}
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);
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);
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());
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));
// 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());
// 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());
}
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());
// 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.
// 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());
// 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());
}
// 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());
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());
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);
}
*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.
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);
}
*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.
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);
}
*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.
SimulateIncrementalMarking(CcTest::heap());
CcTest::heap()->CollectAllGarbage();
- CheckVectorICCleared(f, 0);
+ CheckVectorICCleared(f, 1);
CHECK(ic_before->ic_state() == DEFAULT);
}
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);
}
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);
}
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;
{"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},
{"\"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();
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;
}
}
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());
}
}
}
// 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() {
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());
+})();
// 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() { }
assertInstanceof(f, Number);
}());
+
(function TestSuperCallErrorCases() {
'use strict';
class T extends Object {
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());
+})();