}
-void FastCodeGenerator::VisitAssignment(Assignment* expr) {
- Comment cmnt(masm_, "[ Assignment");
- ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR);
-
- // Record the source position for the assignment.
- SetSourcePosition(expr->position());
-
- // Left-hand side can only be a property, a global or
- // a (parameter or local) slot.
- Variable* var = expr->target()->AsVariableProxy()->AsVariable();
- Expression* rhs = expr->value();
- if (var == NULL) {
- // Assignment to a property.
- ASSERT(expr->target()->AsProperty() != NULL);
- Property* prop = expr->target()->AsProperty();
- Visit(prop->obj());
- Literal* literal_key = prop->key()->AsLiteral();
- uint32_t dummy;
- if (literal_key != NULL &&
- literal_key->handle()->IsSymbol() &&
- !String::cast(*(literal_key->handle()))->AsArrayIndex(&dummy)) {
- // NAMED property assignment
- Visit(rhs);
- ASSERT_EQ(Expression::kValue, rhs->context());
- __ pop(r0);
- __ mov(r2, Operand(literal_key->handle()));
- Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
- __ Call(ic, RelocInfo::CODE_TARGET);
- } else {
- // KEYED property assignment
- Visit(prop->key());
- Visit(rhs);
- ASSERT_EQ(Expression::kValue, rhs->context());
- __ pop(r0);
- Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
- __ Call(ic, RelocInfo::CODE_TARGET);
- // Drop key from the stack
- __ pop();
- }
- // Overwrite the receiver on the stack with the result if needed.
- DropAndMove(expr->context(), r0);
- } else if (var->is_global()) {
+void FastCodeGenerator::EmitVariableAssignment(Expression::Context context,
+ Variable* var) {
+ if (var->is_global()) {
// Assignment to a global variable, use inline caching. Right-hand-side
- // value is passed in r0, variable name in r2, and the global object on
- // the stack.
-
- // Code for the right-hand-side expression depends on its type.
- if (rhs->AsLiteral() != NULL) {
- __ mov(r0, Operand(rhs->AsLiteral()->handle()));
- } else {
- ASSERT_EQ(Expression::kValue, rhs->context());
- Visit(rhs);
- __ pop(r0);
- }
+ // value is passed in r0, variable name in r2, and the global object
+ // on the stack.
+ __ pop(r0);
__ mov(r2, Operand(var->name()));
__ ldr(ip, CodeGenerator::GlobalObject());
__ push(ip);
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
__ Call(ic, RelocInfo::CODE_TARGET);
// Overwrite the global object on the stack with the result if needed.
- DropAndMove(expr->context(), r0);
+ DropAndMove(context, r0);
} else {
- // Local or parameter assignment.
-
- // Code for the right-hand side expression depends on its type.
- if (rhs->AsLiteral() != NULL) {
- // Two cases: 'temp <- (var = constant)', or 'var = constant' with a
- // discarded result. Always perform the assignment.
- __ mov(ip, Operand(rhs->AsLiteral()->handle()));
- __ str(ip, MemOperand(fp, SlotOffset(var->slot())));
- Move(expr->context(), ip);
- } else {
- ASSERT_EQ(Expression::kValue, rhs->context());
- Visit(rhs);
- // Load right-hand side into ip.
- switch (expr->context()) {
- case Expression::kUninitialized:
- UNREACHABLE();
- case Expression::kEffect:
- // Case 'var = temp'. Discard right-hand-side temporary.
- __ pop(r0);
- __ str(r0, MemOperand(fp, SlotOffset(var->slot())));
- break;
- case Expression::kValue:
- // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side
- // temporary on the stack.
- __ ldr(r0, MemOperand(sp));
- __ str(r0, MemOperand(fp, SlotOffset(var->slot())));
- break;
- case Expression::kTest:
- // Case 'if (var = temp) ...'.
- __ pop(r0);
- __ str(r0, MemOperand(fp, SlotOffset(var->slot())));
- TestAndBranch(r0, true_label_, false_label_);
- break;
- case Expression::kValueTest: {
- // Case '(var = temp) || ...' in value context.
- Label discard;
- __ ldr(r0, MemOperand(sp));
- __ str(r0, MemOperand(fp, SlotOffset(var->slot())));
- TestAndBranch(r0, true_label_, &discard);
- __ bind(&discard);
- __ pop();
- __ jmp(false_label_);
- break;
- }
- case Expression::kTestValue: {
- // Case '(var = temp) && ...' in value context.
- Label discard;
- __ ldr(r0, MemOperand(sp));
- __ str(r0, MemOperand(fp, SlotOffset(var->slot())));
- TestAndBranch(r0, &discard, false_label_);
- __ bind(&discard);
- __ pop();
- __ jmp(true_label_);
- break;
- }
+ switch (context) {
+ case Expression::kUninitialized:
+ UNREACHABLE();
+ case Expression::kEffect:
+ // Perform assignment and discard value.
+ __ pop(r0);
+ __ str(r0, MemOperand(fp, SlotOffset(var->slot())));
+ break;
+ case Expression::kValue:
+ // Perform assignment and preserve value.
+ __ ldr(r0, MemOperand(sp));
+ __ str(r0, MemOperand(fp, SlotOffset(var->slot())));
+ break;
+ case Expression::kTest:
+ // Perform assignment and test (and discard) value.
+ __ pop(r0);
+ __ str(r0, MemOperand(fp, SlotOffset(var->slot())));
+ TestAndBranch(r0, true_label_, false_label_);
+ break;
+ case Expression::kValueTest: {
+ Label discard;
+ __ ldr(r0, MemOperand(sp));
+ __ str(r0, MemOperand(fp, SlotOffset(var->slot())));
+ TestAndBranch(r0, true_label_, &discard);
+ __ bind(&discard);
+ __ pop();
+ __ jmp(false_label_);
+ break;
+ }
+ case Expression::kTestValue: {
+ Label discard;
+ __ ldr(r0, MemOperand(sp));
+ __ str(r0, MemOperand(fp, SlotOffset(var->slot())));
+ TestAndBranch(r0, &discard, false_label_);
+ __ bind(&discard);
+ __ pop();
+ __ jmp(true_label_);
+ break;
}
}
}
}
+void FastCodeGenerator::EmitNamedPropertyAssignment(
+ Expression::Context context,
+ Handle<Object> name) {
+ __ pop(r0);
+ __ mov(r2, Operand(name));
+ Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+ __ Call(ic, RelocInfo::CODE_TARGET);
+ DropAndMove(context, r0);
+}
+
+
+void FastCodeGenerator::EmitKeyedPropertyAssignment(
+ Expression::Context context) {
+ __ pop(r0);
+ Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+ __ Call(ic, RelocInfo::CODE_TARGET);
+ // Receiver and key are still on stack.
+ __ add(sp, sp, Operand(2 * kPointerSize));
+ Move(context, r0);
+}
+
+
void FastCodeGenerator::VisitProperty(Property* expr) {
Comment cmnt(masm_, "[ Property");
Expression* key = expr->key();
}
Variable* var = expr->target()->AsVariableProxy()->AsVariable();
- if (var == NULL) {
- Property* prop = expr->target()->AsProperty();
- if (prop == NULL) BAILOUT("non-variable, non-property assignment");
+ Property* prop = expr->target()->AsProperty();
+ if (var != NULL) {
+ // All global variables are supported.
+ if (!var->is_global()) {
+ if (var->slot() == NULL) {
+ // This is a parameter that has rewritten to an arguments access.
+ BAILOUT("non-global/non-slot assignment");
+ }
+ Slot::Type type = var->slot()->type();
+ if (type != Slot::PARAMETER && type != Slot::LOCAL) {
+ BAILOUT("non-parameter/non-local slot assignment");
+ }
+ }
+ } else if (prop != NULL) {
ProcessExpression(prop->obj(), Expression::kValue);
CHECK_BAILOUT;
- ProcessExpression(prop->key(), Expression::kValue);
- } else if (!var->is_global()) {
- if (var->slot() == NULL) BAILOUT("Assigment with an unsupported LHS.");
- Slot::Type type = var->slot()->type();
- if (type != Slot::PARAMETER && type != Slot::LOCAL) {
- BAILOUT("non-parameter/non-local slot assignment");
+ // We will only visit the key during code generation for keyed property
+ // stores. Leave its expression context uninitialized for named
+ // property stores.
+ Literal* lit = prop->key()->AsLiteral();
+ uint32_t ignored;
+ if (lit == NULL ||
+ !lit->handle()->IsSymbol() ||
+ String::cast(*(lit->handle()))->AsArrayIndex(&ignored)) {
+ ProcessExpression(prop->key(), Expression::kValue);
+ CHECK_BAILOUT;
}
+ } else {
+ // This is a throw reference error.
+ BAILOUT("non-variable/non-property assignment");
}
ProcessExpression(expr->value(), Expression::kValue);
}
+void FastCodeGenerator::VisitAssignment(Assignment* expr) {
+ Comment cmnt(masm_, "[ Assignment");
+ ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR);
+
+ // Record source code position of the (possible) IC call.
+ SetSourcePosition(expr->position());
+
+ Expression* rhs = expr->value();
+ // Left-hand side can only be a property, a global or a (parameter or
+ // local) slot.
+ Variable* var = expr->target()->AsVariableProxy()->AsVariable();
+ Property* prop = expr->target()->AsProperty();
+ if (var != NULL) {
+ Visit(rhs);
+ ASSERT_EQ(Expression::kValue, rhs->context());
+ EmitVariableAssignment(expr->context(), var);
+ } else if (prop != NULL) {
+ // Assignment to a property.
+ Visit(prop->obj());
+ ASSERT_EQ(Expression::kValue, prop->obj()->context());
+ // Use the expression context of the key subexpression to detect whether
+ // we have decided to us a named or keyed IC.
+ if (prop->key()->context() == Expression::kUninitialized) {
+ ASSERT(prop->key()->AsLiteral() != NULL);
+ Visit(rhs);
+ ASSERT_EQ(Expression::kValue, rhs->context());
+ EmitNamedPropertyAssignment(expr->context(),
+ prop->key()->AsLiteral()->handle());
+ } else {
+ Visit(prop->key());
+ ASSERT_EQ(Expression::kValue, prop->key()->context());
+ Visit(rhs);
+ ASSERT_EQ(Expression::kValue, rhs->context());
+ EmitKeyedPropertyAssignment(expr->context());
+ }
+ } else {
+ UNREACHABLE();
+ }
+}
+
+
void FastCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) {
UNREACHABLE();
}
void EmitCallWithStub(Call* expr);
void EmitCallWithIC(Call* expr, RelocInfo::Mode reloc_info);
+ // Platform-specific support for compiling assignments.
+
+ // Complete a variable assignment. The right-hand-side value are expected
+ // on top of the stack.
+ void EmitVariableAssignment(Expression::Context context, Variable* var);
+
+ // Complete a named property assignment. The receiver and right-hand-side
+ // value are expected on top of the stack.
+ void EmitNamedPropertyAssignment(Expression::Context context,
+ Handle<Object> name);
+
+ // Complete a keyed property assignment. The reciever, key, and
+ // right-hand-side value are expected on top of the stack.
+ void EmitKeyedPropertyAssignment(Expression::Context context);
+
void SetFunctionPosition(FunctionLiteral* fun);
void SetReturnPosition(FunctionLiteral* fun);
void SetStatementPosition(Statement* stmt);
}
-void FastCodeGenerator::VisitAssignment(Assignment* expr) {
- Comment cmnt(masm_, "[ Assignment");
- ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR);
-
- // Record the source position for the assignment.
- SetSourcePosition(expr->position());
-
- // Left-hand side can only be a property, a global or
- // a (parameter or local) slot.
- Variable* var = expr->target()->AsVariableProxy()->AsVariable();
- Expression* rhs = expr->value();
- if (var == NULL) {
- // Assignment to a property.
- ASSERT(expr->target()->AsProperty() != NULL);
- Property* prop = expr->target()->AsProperty();
- Visit(prop->obj());
- Literal* literal_key = prop->key()->AsLiteral();
- uint32_t dummy;
- if (literal_key != NULL &&
- literal_key->handle()->IsSymbol() &&
- !String::cast(*(literal_key->handle()))->AsArrayIndex(&dummy)) {
- // NAMED property assignment
- Visit(rhs);
- ASSERT_EQ(Expression::kValue, rhs->context());
- __ pop(eax);
- __ mov(ecx, Immediate(literal_key->handle()));
- Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
- __ call(ic, RelocInfo::CODE_TARGET);
- __ nop();
- } else {
- // KEYED property assignment
- Visit(prop->key());
- Visit(rhs);
- ASSERT_EQ(Expression::kValue, rhs->context());
- __ pop(eax);
- Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
- __ call(ic, RelocInfo::CODE_TARGET);
- __ nop();
- // Drop key from the stack
- __ add(Operand(esp), Immediate(kPointerSize));
- }
- // Overwrite the receiver on the stack with the result if needed.
- DropAndMove(expr->context(), eax);
- } else if (var->is_global()) {
+void FastCodeGenerator::EmitVariableAssignment(Expression::Context context,
+ Variable* var) {
+ if (var->is_global()) {
// Assignment to a global variable, use inline caching. Right-hand-side
// value is passed in eax, variable name in ecx, and the global object
// on the stack.
-
- // Code for the right-hand-side expression depends on its type.
- if (rhs->AsLiteral() != NULL) {
- __ mov(eax, rhs->AsLiteral()->handle());
- } else {
- ASSERT_EQ(Expression::kValue, rhs->context());
- Visit(rhs);
- __ pop(eax);
- }
- // Record position for debugger.
- SetSourcePosition(expr->position());
+ __ pop(eax);
__ mov(ecx, var->name());
__ push(CodeGenerator::GlobalObject());
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
__ call(ic, RelocInfo::CODE_TARGET);
// Overwrite the global object on the stack with the result if needed.
- DropAndMove(expr->context(), eax);
+ DropAndMove(context, eax);
} else {
- // Local or parameter assignment.
- ASSERT(var->slot() != NULL);
-
- // Code for the right-hand side expression depends on its type.
- if (rhs->AsLiteral() != NULL) {
- // Two cases: 'temp <- (var = constant)', or 'var = constant' with a
- // discarded result. Always perform the assignment.
- __ mov(eax, rhs->AsLiteral()->handle());
- __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
- Move(expr->context(), eax);
- } else {
- ASSERT_EQ(Expression::kValue, rhs->context());
- Visit(rhs);
- switch (expr->context()) {
- case Expression::kUninitialized:
- UNREACHABLE();
- case Expression::kEffect:
- // Case 'var = temp'. Discard right-hand-side temporary.
- __ pop(Operand(ebp, SlotOffset(var->slot())));
- break;
- case Expression::kValue:
- // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side
- // temporary on the stack.
- __ mov(eax, Operand(esp, 0));
- __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
- break;
- case Expression::kTest:
- // Case 'if (var = temp) ...'.
- __ pop(eax);
- __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
- TestAndBranch(eax, true_label_, false_label_);
- break;
- case Expression::kValueTest: {
- // Case '(var = temp) || ...' in value context.
- Label discard;
- __ mov(eax, Operand(esp, 0));
- __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
- TestAndBranch(eax, true_label_, &discard);
- __ bind(&discard);
- __ add(Operand(esp), Immediate(kPointerSize));
- __ jmp(false_label_);
- break;
- }
- case Expression::kTestValue: {
- // Case '(var = temp) && ...' in value context.
- Label discard;
- __ mov(eax, Operand(esp, 0));
- __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
- TestAndBranch(eax, &discard, false_label_);
- __ bind(&discard);
- __ add(Operand(esp), Immediate(kPointerSize));
- __ jmp(true_label_);
- break;
- }
+ switch (context) {
+ case Expression::kUninitialized:
+ UNREACHABLE();
+ case Expression::kEffect:
+ // Perform assignment and discard value.
+ __ pop(Operand(ebp, SlotOffset(var->slot())));
+ break;
+ case Expression::kValue:
+ // Perform assignment and preserve value.
+ __ mov(eax, Operand(esp, 0));
+ __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
+ break;
+ case Expression::kTest:
+ // Perform assignment and test (and discard) value.
+ __ pop(eax);
+ __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
+ TestAndBranch(eax, true_label_, false_label_);
+ break;
+ case Expression::kValueTest: {
+ Label discard;
+ __ mov(eax, Operand(esp, 0));
+ __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
+ TestAndBranch(eax, true_label_, &discard);
+ __ bind(&discard);
+ __ add(Operand(esp), Immediate(kPointerSize));
+ __ jmp(false_label_);
+ break;
+ }
+ case Expression::kTestValue: {
+ Label discard;
+ __ mov(eax, Operand(esp, 0));
+ __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
+ TestAndBranch(eax, &discard, false_label_);
+ __ bind(&discard);
+ __ add(Operand(esp), Immediate(kPointerSize));
+ __ jmp(true_label_);
+ break;
}
}
}
}
+void FastCodeGenerator::EmitNamedPropertyAssignment(
+ Expression::Context context,
+ Handle<Object> name) {
+ __ pop(eax);
+ __ mov(ecx, name);
+ Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+ __ call(ic, RelocInfo::CODE_TARGET);
+ DropAndMove(context, eax);
+}
+
+
+void FastCodeGenerator::EmitKeyedPropertyAssignment(
+ Expression::Context context) {
+ __ pop(eax);
+ Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+ __ call(ic, RelocInfo::CODE_TARGET);
+ // This nop signals to the IC that there is no inlined code at the call
+ // site for it to patch.
+ __ nop();
+ // Receiver and key are still on stack.
+ __ add(Operand(esp), Immediate(2 * kPointerSize));
+ Move(context, eax);
+}
+
+
void FastCodeGenerator::VisitProperty(Property* expr) {
Comment cmnt(masm_, "[ Property");
Expression* key = expr->key();
}
-void FastCodeGenerator::VisitAssignment(Assignment* expr) {
- Comment cmnt(masm_, "[ Assignment");
- ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR);
-
- // Record the source position for the assignment.
- SetSourcePosition(expr->position());
-
- // Left-hand side can only be a property, a global or
- // a (parameter or local) slot.
- Variable* var = expr->target()->AsVariableProxy()->AsVariable();
- Expression* rhs = expr->value();
- if (var == NULL) {
- // Assignment to a property.
- ASSERT(expr->target()->AsProperty() != NULL);
- Property* prop = expr->target()->AsProperty();
- Visit(prop->obj());
- Literal* literal_key = prop->key()->AsLiteral();
- uint32_t dummy;
- if (literal_key != NULL &&
- literal_key->handle()->IsSymbol() &&
- !String::cast(*(literal_key->handle()))->AsArrayIndex(&dummy)) {
- // NAMED property assignment
- Visit(rhs);
- ASSERT_EQ(Expression::kValue, rhs->context());
- __ pop(rax);
- __ Move(rcx, literal_key->handle());
- Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
- __ call(ic, RelocInfo::CODE_TARGET);
- __ nop();
- } else {
- // KEYED property assignment
- Visit(prop->key());
- Visit(rhs);
- ASSERT_EQ(Expression::kValue, rhs->context());
- __ pop(rax);
- Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
- __ call(ic, RelocInfo::CODE_TARGET);
- __ nop();
- // Drop key from the stack
- __ addq(rsp, Immediate(kPointerSize));
- }
- // Overwrite the receiver on the stack with the result if needed.
- DropAndMove(expr->context(), rax);
- } else if (var->is_global()) {
+void FastCodeGenerator::EmitVariableAssignment(Expression::Context context,
+ Variable* var) {
+ if (var->is_global()) {
// Assignment to a global variable, use inline caching. Right-hand-side
// value is passed in rax, variable name in rcx, and the global object
// on the stack.
-
- // Code for the right-hand-side expression depends on its type.
- if (rhs->AsLiteral() != NULL) {
- __ Move(rax, rhs->AsLiteral()->handle());
- } else {
- ASSERT_EQ(Expression::kValue, rhs->context());
- Visit(rhs);
- __ pop(rax);
- }
- // Record position for debugger.
- SetSourcePosition(expr->position());
+ __ pop(rax);
__ Move(rcx, var->name());
__ push(CodeGenerator::GlobalObject());
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
__ Call(ic, RelocInfo::CODE_TARGET);
// Overwrite the global object on the stack with the result if needed.
- DropAndMove(expr->context(), rax);
+ DropAndMove(context, rax);
} else {
- // Local or parameter assignment.
-
- // Code for the right-hand-side expression depends on its type.
- if (rhs->AsLiteral() != NULL) {
- // Two cases: 'temp <- (var = constant)', or 'var = constant' with a
- // discarded result. Always perform the assignment.
- __ Move(kScratchRegister, rhs->AsLiteral()->handle());
- __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister);
- Move(expr->context(), kScratchRegister);
- } else {
- ASSERT_EQ(Expression::kValue, rhs->context());
- Visit(rhs);
- switch (expr->context()) {
- case Expression::kUninitialized:
- UNREACHABLE();
- case Expression::kEffect:
- // Case 'var = temp'. Discard right-hand-side temporary.
- __ pop(Operand(rbp, SlotOffset(var->slot())));
- break;
- case Expression::kValue:
- // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side
- // temporary on the stack.
- __ movq(kScratchRegister, Operand(rsp, 0));
- __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister);
- break;
- case Expression::kTest:
- // Case 'if (var = temp) ...'.
- __ pop(rax);
- __ movq(Operand(rbp, SlotOffset(var->slot())), rax);
- TestAndBranch(rax, true_label_, false_label_);
- break;
- case Expression::kValueTest: {
- // Case '(var = temp) || ...' in value context.
- Label discard;
- __ movq(rax, Operand(rsp, 0));
- __ movq(Operand(rbp, SlotOffset(var->slot())), rax);
- TestAndBranch(rax, true_label_, &discard);
- __ bind(&discard);
- __ addq(rsp, Immediate(kPointerSize));
- __ jmp(false_label_);
- break;
- }
- case Expression::kTestValue: {
- // Case '(var = temp) && ...' in value context.
- Label discard;
- __ movq(rax, Operand(rsp, 0));
- __ movq(Operand(rbp, SlotOffset(var->slot())), rax);
- TestAndBranch(rax, &discard, false_label_);
- __ bind(&discard);
- __ addq(rsp, Immediate(kPointerSize));
- __ jmp(true_label_);
- break;
- }
+ switch (context) {
+ case Expression::kUninitialized:
+ UNREACHABLE();
+ case Expression::kEffect:
+ // Perform assignment and discard value.
+ __ pop(Operand(rbp, SlotOffset(var->slot())));
+ break;
+ case Expression::kValue:
+ // Perform assignment and preserve value.
+ __ movq(rax, Operand(rsp, 0));
+ __ movq(Operand(rbp, SlotOffset(var->slot())), rax);
+ break;
+ case Expression::kTest:
+ // Perform assignment and test (and discard) value.
+ __ pop(rax);
+ __ movq(Operand(rbp, SlotOffset(var->slot())), rax);
+ TestAndBranch(rax, true_label_, false_label_);
+ break;
+ case Expression::kValueTest: {
+ Label discard;
+ __ movq(rax, Operand(rsp, 0));
+ __ movq(Operand(rbp, SlotOffset(var->slot())), rax);
+ TestAndBranch(rax, true_label_, &discard);
+ __ bind(&discard);
+ __ addq(rsp, Immediate(kPointerSize));
+ __ jmp(false_label_);
+ break;
+ }
+ case Expression::kTestValue: {
+ Label discard;
+ __ movq(rax, Operand(rsp, 0));
+ __ movq(Operand(rbp, SlotOffset(var->slot())), rax);
+ TestAndBranch(rax, &discard, false_label_);
+ __ bind(&discard);
+ __ addq(rsp, Immediate(kPointerSize));
+ __ jmp(true_label_);
+ break;
}
}
}
}
+void FastCodeGenerator::EmitNamedPropertyAssignment(
+ Expression::Context context,
+ Handle<Object> name) {
+ __ pop(rax);
+ __ Move(rcx, name);
+ Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+ __ Call(ic, RelocInfo::CODE_TARGET);
+ DropAndMove(context, rax);
+}
+
+
+void FastCodeGenerator::EmitKeyedPropertyAssignment(
+ Expression::Context context) {
+ __ pop(rax);
+ Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+ __ Call(ic, RelocInfo::CODE_TARGET);
+ // This nop signals to the IC that there is no inlined code at the call
+ // site for it to patch.
+ __ nop();
+ // Receiver and key are still on stack.
+ __ addq(rsp, Immediate(2 * kPointerSize));
+ Move(context, rax);
+}
+
+
void FastCodeGenerator::VisitProperty(Property* expr) {
Comment cmnt(masm_, "[ Property");
Expression* key = expr->key();