void FastCodeGenerator::Move(Location destination, Slot* source) {
switch (destination.type()) {
- case Location::NOWHERE:
+ case Location::UNINITIALIZED:
+ UNREACHABLE();
+ case Location::EFFECT:
break;
- case Location::TEMP:
+ case Location::VALUE:
__ ldr(ip, MemOperand(fp, SlotOffset(source)));
__ push(ip);
break;
void FastCodeGenerator::Move(Location destination, Literal* expr) {
switch (destination.type()) {
- case Location::NOWHERE:
+ case Location::UNINITIALIZED:
+ UNREACHABLE();
+ case Location::EFFECT:
break;
- case Location::TEMP:
+ case Location::VALUE:
__ mov(ip, Operand(expr->handle()));
__ push(ip);
break;
void FastCodeGenerator::Move(Slot* destination, Location source) {
switch (source.type()) {
- case Location::NOWHERE:
+ case Location::UNINITIALIZED: // Fall through.
+ case Location::EFFECT:
UNREACHABLE();
- case Location::TEMP:
+ case Location::VALUE:
__ pop(ip);
__ str(ip, MemOperand(fp, SlotOffset(destination)));
break;
void FastCodeGenerator::DropAndMove(Location destination, Register source) {
switch (destination.type()) {
- case Location::NOWHERE:
+ case Location::UNINITIALIZED:
+ UNREACHABLE();
+ case Location::EFFECT:
__ pop();
break;
- case Location::TEMP:
+ case Location::VALUE:
__ str(source, MemOperand(sp));
break;
}
}
+void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
+ Comment cmnt(masm_, "[ RegExp Literal");
+ Label done;
+ // Registers will be used as follows:
+ // r4 = JS function, literals array
+ // r3 = literal index
+ // r2 = RegExp pattern
+ // r1 = RegExp flags
+ // r0 = temp + return value (RegExp literal)
+ __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+ __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset));
+ int literal_offset =
+ FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
+ __ ldr(r0, FieldMemOperand(r4, literal_offset));
+ __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
+ __ cmp(r0, ip);
+ __ b(ne, &done);
+ __ mov(r3, Operand(Smi::FromInt(expr->literal_index())));
+ __ mov(r2, Operand(expr->pattern()));
+ __ mov(r1, Operand(expr->flags()));
+ __ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit());
+ __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
+ __ bind(&done);
+ Move(expr->location(), r0);
+}
+
+
void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
Comment cmnt(masm_, "[ ObjectLiteral");
Label boilerplate_exists;
result_saved = true;
}
switch (property->kind()) {
- case ObjectLiteral::Property::MATERIALIZED_LITERAL: // fall through
+ case ObjectLiteral::Property::CONSTANT:
+ UNREACHABLE();
+
+ case ObjectLiteral::Property::MATERIALIZED_LITERAL: // Fall through.
ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value()));
- case ObjectLiteral::Property::COMPUTED: // fall through
+ case ObjectLiteral::Property::COMPUTED:
+ if (key->handle()->IsSymbol()) {
+ Visit(value);
+ Move(r0, value->location());
+ __ mov(r2, Operand(key->handle()));
+ Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+ __ Call(ic, RelocInfo::CODE_TARGET);
+ // StoreIC leaves the receiver on the stack.
+ break;
+ }
+ // Fall through.
+
case ObjectLiteral::Property::PROTOTYPE:
__ push(r0);
Visit(key);
- ASSERT(key->location().is_temporary());
+ ASSERT(key->location().is_value());
Visit(value);
- ASSERT(value->location().is_temporary());
+ ASSERT(value->location().is_value());
__ CallRuntime(Runtime::kSetProperty, 3);
__ ldr(r0, MemOperand(sp)); // Restore result into r0
break;
- case ObjectLiteral::Property::SETTER: // fall through
- case ObjectLiteral::Property::GETTER:
+
+ case ObjectLiteral::Property::GETTER: // Fall through.
+ case ObjectLiteral::Property::SETTER:
__ push(r0);
Visit(key);
- ASSERT(key->location().is_temporary());
+ ASSERT(key->location().is_value());
__ mov(r1, Operand(property->kind() == ObjectLiteral::Property::SETTER ?
Smi::FromInt(1) :
Smi::FromInt(0)));
__ push(r1);
Visit(value);
- ASSERT(value->location().is_temporary());
+ ASSERT(value->location().is_value());
__ CallRuntime(Runtime::kDefineAccessor, 4);
__ ldr(r0, MemOperand(sp)); // Restore result into r0
break;
- default: UNREACHABLE();
}
}
switch (expr->location().type()) {
- case Location::NOWHERE:
+ case Location::UNINITIALIZED:
+ UNREACHABLE();
+ case Location::EFFECT:
if (result_saved) __ pop();
break;
- case Location::TEMP:
+ case Location::VALUE:
if (!result_saved) __ push(r0);
break;
}
}
-void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
- Comment cmnt(masm_, "[ RegExp Literal");
- Label done;
- // Registers will be used as follows:
- // r4 = JS function, literals array
- // r3 = literal index
- // r2 = RegExp pattern
- // r1 = RegExp flags
- // r0 = temp + return value (RegExp literal)
- __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
- __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset));
- int literal_offset =
- FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
- __ ldr(r0, FieldMemOperand(r4, literal_offset));
- __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
- __ cmp(r0, ip);
- __ b(ne, &done);
- __ mov(r3, Operand(Smi::FromInt(expr->literal_index())));
- __ mov(r2, Operand(expr->pattern()));
- __ mov(r1, Operand(expr->flags()));
- __ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit());
- __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
- __ bind(&done);
- Move(expr->location(), r0);
-}
-
-
void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
Comment cmnt(masm_, "[ ArrayLiteral");
Label make_clone;
result_saved = true;
}
Visit(subexpr);
- ASSERT(subexpr->location().is_temporary());
+ ASSERT(subexpr->location().is_value());
// Store the subexpression value in the array's elements.
__ pop(r0); // Subexpression value.
}
switch (expr->location().type()) {
- case Location::NOWHERE:
+ case Location::UNINITIALIZED:
+ UNREACHABLE();
+ case Location::EFFECT:
if (result_saved) __ pop();
break;
- case Location::TEMP:
+ case Location::VALUE:
if (!result_saved) __ push(r0);
break;
}
if (rhs->AsLiteral() != NULL) {
__ mov(r0, Operand(rhs->AsLiteral()->handle()));
} else {
- ASSERT(rhs->location().is_temporary());
+ ASSERT(rhs->location().is_value());
Visit(rhs);
__ pop(r0);
}
__ str(ip, MemOperand(fp, SlotOffset(var->slot())));
Move(expr->location(), ip);
} else {
- ASSERT(rhs->location().is_temporary());
+ ASSERT(rhs->location().is_value());
Visit(rhs);
// Load right-hand side into ip.
switch (expr->location().type()) {
- case Location::NOWHERE:
+ case Location::UNINITIALIZED:
+ UNREACHABLE();
+ case Location::EFFECT:
// Case 'var = temp'. Discard right-hand-side temporary.
__ pop(ip);
break;
- case Location::TEMP:
+ case Location::VALUE:
// Case 'temp1 <- (var = temp0)'. Preserve right-hand-side
// temporary on the stack.
__ ldr(ip, MemOperand(sp));
__ pop();
}
switch (expr->location().type()) {
- case Location::TEMP:
+ case Location::UNINITIALIZED:
+ UNREACHABLE();
+ case Location::VALUE:
__ str(r0, MemOperand(sp));
break;
- case Location::NOWHERE:
+ case Location::EFFECT:
__ pop();
}
}
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
Visit(args->at(i));
- ASSERT(args->at(i)->location().is_temporary());
+ ASSERT(args->at(i)->location().is_value());
}
// Record source position for debugger
SetSourcePosition(expr->position());
// arguments.
// Push function on the stack.
Visit(node->expression());
- ASSERT(node->expression()->location().is_temporary());
+ ASSERT(node->expression()->location().is_value());
// Push global object (receiver).
__ ldr(r0, CodeGenerator::GlobalObject());
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
Visit(args->at(i));
- ASSERT(args->at(i)->location().is_temporary());
+ ASSERT(args->at(i)->location().is_value());
// If location is temporary, it is already on the stack,
// so nothing to do here.
}
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
Visit(args->at(i));
- ASSERT(args->at(i)->location().is_temporary());
+ ASSERT(args->at(i)->location().is_value());
}
__ CallRuntime(function, arg_count);
if (left->AsLiteral() != NULL) {
__ mov(r0, Operand(left->AsLiteral()->handle()));
__ push(r0);
- if (destination.is_temporary()) __ push(r0);
+ if (destination.is_value()) __ push(r0);
} else {
Visit(left);
- ASSERT(left->location().is_temporary());
- if (destination.is_temporary()) {
+ ASSERT(left->location().is_value());
+ if (destination.is_value()) {
__ ldr(r0, MemOperand(sp));
__ push(r0);
}
__ b(eq, &done);
// Discard the left-hand value if present on the stack.
- if (destination.is_temporary()) __ pop();
+ if (destination.is_value()) __ pop();
// Save or discard the right-hand value as needed.
if (right->AsLiteral() != NULL) {
Move(destination, right->AsLiteral());
class Expression: public AstNode {
public:
- Expression() : location_(Location::Temporary()) {}
+ Expression() : location_(Location::Uninitialized()) {}
virtual Expression* AsExpression() { return this; }
CodeGenSelector()
: has_supported_syntax_(true),
- location_(Location::Nowhere()) {
+ location_(Location::Uninitialized()) {
}
CodeGenTag Select(FunctionLiteral* fun);
void CodeGenSelector::VisitAsEffect(Expression* expr) {
- if (location_.is_nowhere()) {
+ if (location_.is_effect()) {
Visit(expr);
} else {
Location saved = location_;
- location_ = Location::Nowhere();
+ location_ = Location::Effect();
Visit(expr);
location_ = saved;
}
void CodeGenSelector::VisitAsValue(Expression* expr) {
- if (location_.is_temporary()) {
+ if (location_.is_value()) {
Visit(expr);
} else {
Location saved = location_;
- location_ = Location::Temporary();
+ location_ = Location::Value();
Visit(expr);
location_ = saved;
}
void FastCodeGenerator::Move(Location destination, Location source) {
switch (destination.type()) {
- case Location::NOWHERE:
+ case Location::UNINITIALIZED:
+ UNREACHABLE();
+
+ case Location::EFFECT:
break;
- case Location::TEMP:
+ case Location::VALUE:
switch (source.type()) {
- case Location::NOWHERE:
+ case Location::UNINITIALIZED: // Fall through.
+ case Location::EFFECT:
UNREACHABLE();
- case Location::TEMP:
+ case Location::VALUE:
break;
}
break;
// function.
void FastCodeGenerator::Move(Location destination, Register source) {
switch (destination.type()) {
- case Location::NOWHERE:
+ case Location::UNINITIALIZED:
+ UNREACHABLE();
+ case Location::EFFECT:
break;
- case Location::TEMP:
+ case Location::VALUE:
masm_->push(source);
break;
}
// function.
void FastCodeGenerator::Move(Register destination, Location source) {
switch (source.type()) {
- case Location::NOWHERE:
+ case Location::UNINITIALIZED: // Fall through.
+ case Location::EFFECT:
UNREACHABLE();
- case Location::TEMP:
+ case Location::VALUE:
masm_->pop(destination);
}
}
void FastCodeGenerator::Move(Location destination, Slot* source) {
switch (destination.type()) {
- case Location::NOWHERE:
+ case Location::UNINITIALIZED:
+ UNREACHABLE();
+ case Location::EFFECT:
break;
- case Location::TEMP:
+ case Location::VALUE:
__ push(Operand(ebp, SlotOffset(source)));
break;
}
void FastCodeGenerator::Move(Location destination, Literal* expr) {
switch (destination.type()) {
- case Location::NOWHERE:
+ case Location::UNINITIALIZED:
+ UNREACHABLE();
+ case Location::EFFECT:
break;
- case Location::TEMP:
+ case Location::VALUE:
__ push(Immediate(expr->handle()));
break;
}
void FastCodeGenerator::Move(Slot* destination, Location source) {
switch (source.type()) {
- case Location::NOWHERE:
+ case Location::UNINITIALIZED: // Fall through.
+ case Location::EFFECT:
UNREACHABLE();
- case Location::TEMP:
+ case Location::VALUE:
__ pop(Operand(ebp, SlotOffset(destination)));
break;
}
void FastCodeGenerator::DropAndMove(Location destination, Register source) {
switch (destination.type()) {
- case Location::NOWHERE:
+ case Location::UNINITIALIZED:
+ UNREACHABLE();
+ case Location::EFFECT:
__ add(Operand(esp), Immediate(kPointerSize));
break;
- case Location::TEMP:
+ case Location::VALUE:
__ mov(Operand(esp, 0), source);
break;
}
}
+void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
+ Comment cmnt(masm_, "[ RegExp Literal");
+ Label done;
+ // Registers will be used as follows:
+ // edi = JS function.
+ // ebx = literals array.
+ // eax = regexp literal.
+ __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
+ __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset));
+ int literal_offset =
+ FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
+ __ mov(eax, FieldOperand(ebx, literal_offset));
+ __ cmp(eax, Factory::undefined_value());
+ __ j(not_equal, &done);
+ // Create regexp literal using runtime function
+ // Result will be in eax.
+ __ push(ebx);
+ __ push(Immediate(Smi::FromInt(expr->literal_index())));
+ __ push(Immediate(expr->pattern()));
+ __ push(Immediate(expr->flags()));
+ __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
+ // Label done:
+ __ bind(&done);
+ Move(expr->location(), eax);
+}
+
+
void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
Comment cmnt(masm_, "[ ObjectLiteral");
Label exists;
case ObjectLiteral::Property::PROTOTYPE:
__ push(eax);
Visit(key);
- ASSERT(key->location().is_temporary());
+ ASSERT(key->location().is_value());
Visit(value);
- ASSERT(value->location().is_temporary());
+ ASSERT(value->location().is_value());
__ CallRuntime(Runtime::kSetProperty, 3);
__ mov(eax, Operand(esp, 0)); // Restore result into eax.
break;
case ObjectLiteral::Property::GETTER:
__ push(eax);
Visit(key);
- ASSERT(key->location().is_temporary());
+ ASSERT(key->location().is_value());
__ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ?
Smi::FromInt(1) :
Smi::FromInt(0)));
Visit(value);
- ASSERT(value->location().is_temporary());
+ ASSERT(value->location().is_value());
__ CallRuntime(Runtime::kDefineAccessor, 4);
__ mov(eax, Operand(esp, 0)); // Restore result into eax.
break;
}
}
switch (expr->location().type()) {
- case Location::NOWHERE:
+ case Location::UNINITIALIZED:
+ UNREACHABLE();
+ case Location::EFFECT:
if (result_saved) __ add(Operand(esp), Immediate(kPointerSize));
break;
- case Location::TEMP:
+ case Location::VALUE:
if (!result_saved) __ push(eax);
break;
}
}
-void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
- Comment cmnt(masm_, "[ RegExp Literal");
- Label done;
- // Registers will be used as follows:
- // edi = JS function.
- // ebx = literals array.
- // eax = regexp literal.
- __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
- __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset));
- int literal_offset =
- FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
- __ mov(eax, FieldOperand(ebx, literal_offset));
- __ cmp(eax, Factory::undefined_value());
- __ j(not_equal, &done);
- // Create regexp literal using runtime function
- // Result will be in eax.
- __ push(ebx);
- __ push(Immediate(Smi::FromInt(expr->literal_index())));
- __ push(Immediate(expr->pattern()));
- __ push(Immediate(expr->flags()));
- __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
- // Label done:
- __ bind(&done);
- Move(expr->location(), eax);
-}
-
-
void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
Comment cmnt(masm_, "[ ArrayLiteral");
Label make_clone;
result_saved = true;
}
Visit(subexpr);
- ASSERT(subexpr->location().is_temporary());
+ ASSERT(subexpr->location().is_value());
// Store the subexpression value in the array's elements.
__ pop(eax); // Subexpression value.
}
switch (expr->location().type()) {
- case Location::NOWHERE:
+ case Location::UNINITIALIZED:
+ UNREACHABLE();
+ case Location::EFFECT:
if (result_saved) __ add(Operand(esp), Immediate(kPointerSize));
break;
- case Location::TEMP:
+ case Location::VALUE:
if (!result_saved) __ push(eax);
break;
}
if (rhs->AsLiteral() != NULL) {
__ mov(eax, rhs->AsLiteral()->handle());
} else {
- ASSERT(rhs->location().is_temporary());
+ ASSERT(rhs->location().is_value());
Visit(rhs);
__ pop(eax);
}
__ mov(Operand(ebp, SlotOffset(var->slot())), eax);
Move(expr->location(), eax);
} else {
- ASSERT(rhs->location().is_temporary());
+ ASSERT(rhs->location().is_value());
Visit(rhs);
switch (expr->location().type()) {
- case Location::NOWHERE:
+ case Location::UNINITIALIZED:
+ UNREACHABLE();
+ case Location::EFFECT:
// Case 'var = temp'. Discard right-hand-side temporary.
Move(var->slot(), rhs->location());
break;
- case Location::TEMP:
+ case Location::VALUE:
// Case 'temp1 <- (var = temp0)'. Preserve right-hand-side
// temporary on the stack.
__ mov(eax, Operand(esp, 0));
__ add(Operand(esp), Immediate(kPointerSize));
}
switch (expr->location().type()) {
- case Location::TEMP:
+ case Location::UNINITIALIZED:
+ UNREACHABLE();
+ case Location::VALUE:
__ mov(Operand(esp, 0), eax);
break;
- case Location::NOWHERE:
+ case Location::EFFECT:
__ add(Operand(esp), Immediate(kPointerSize));
break;
}
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
Visit(args->at(i));
- ASSERT(args->at(i)->location().is_temporary());
+ ASSERT(args->at(i)->location().is_value());
}
// Record source position for debugger
SetSourcePosition(expr->position());
// arguments.
// Push function on the stack.
Visit(node->expression());
- ASSERT(node->expression()->location().is_temporary());
+ ASSERT(node->expression()->location().is_value());
// Push global object (receiver).
__ push(CodeGenerator::GlobalObject());
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
Visit(args->at(i));
- ASSERT(args->at(i)->location().is_temporary());
+ ASSERT(args->at(i)->location().is_value());
// If location is temporary, it is already on the stack,
// so nothing to do here.
}
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
Visit(args->at(i));
- ASSERT(args->at(i)->location().is_temporary());
+ ASSERT(args->at(i)->location().is_value());
}
__ CallRuntime(function, arg_count);
// need it as the value of the whole expression.
if (left->AsLiteral() != NULL) {
__ mov(eax, left->AsLiteral()->handle());
- if (destination.is_temporary()) __ push(eax);
+ if (destination.is_value()) __ push(eax);
} else {
Visit(left);
- ASSERT(left->location().is_temporary());
+ ASSERT(left->location().is_value());
switch (destination.type()) {
- case Location::NOWHERE:
+ case Location::UNINITIALIZED:
+ UNREACHABLE();
+ case Location::EFFECT:
// Pop the left-hand value into eax because we will not need it as the
// final result.
__ pop(eax);
break;
- case Location::TEMP:
+ case Location::VALUE:
// Copy the left-hand value into eax because we may need it as the
// final result.
__ mov(eax, Operand(esp, 0));
__ bind(&eval_right);
// Discard the left-hand value if present on the stack.
- if (destination.is_temporary()) {
+ if (destination.is_value()) {
__ add(Operand(esp), Immediate(kPointerSize));
}
// Save or discard the right-hand value as needed.
class Location BASE_EMBEDDED {
public:
- enum Type { NOWHERE, TEMP };
+ enum Type { UNINITIALIZED, EFFECT, VALUE };
- static Location Temporary() { return Location(TEMP); }
- static Location Nowhere() { return Location(NOWHERE); }
+ static Location Uninitialized() { return Location(UNINITIALIZED); }
+ static Location Effect() { return Location(EFFECT); }
+ static Location Value() { return Location(VALUE); }
- bool is_temporary() { return type_ == TEMP; }
- bool is_nowhere() { return type_ == NOWHERE; }
+ bool is_effect() { return type_ == EFFECT; }
+ bool is_value() { return type_ == VALUE; }
Type type() { return type_; }
void FastCodeGenerator::Move(Location destination, Slot* source) {
switch (destination.type()) {
- case Location::NOWHERE:
+ case Location::UNINITIALIZED:
+ UNREACHABLE();
+ case Location::EFFECT:
break;
- case Location::TEMP:
+ case Location::VALUE:
__ push(Operand(rbp, SlotOffset(source)));
break;
}
void FastCodeGenerator::Move(Location destination, Literal* expr) {
switch (destination.type()) {
- case Location::NOWHERE:
+ case Location::UNINITIALIZED:
+ UNREACHABLE();
+ case Location::EFFECT:
break;
- case Location::TEMP:
+ case Location::VALUE:
__ Push(expr->handle());
break;
}
void FastCodeGenerator::Move(Slot* destination, Location source) {
switch (source.type()) {
- case Location::NOWHERE:
+ case Location::UNINITIALIZED: // Fall through.
+ case Location::EFFECT:
UNREACHABLE();
- case Location::TEMP:
+ case Location::VALUE:
__ pop(Operand(rbp, SlotOffset(destination)));
break;
}
void FastCodeGenerator::DropAndMove(Location destination, Register source) {
switch (destination.type()) {
- case Location::NOWHERE:
+ case Location::UNINITIALIZED:
+ UNREACHABLE();
+ case Location::EFFECT:
__ addq(rsp, Immediate(kPointerSize));
break;
- case Location::TEMP:
+ case Location::VALUE:
__ movq(Operand(rsp, 0), source);
break;
}
}
+void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
+ Comment cmnt(masm_, "[ RegExp Literal");
+ Label done;
+ // Registers will be used as follows:
+ // rdi = JS function.
+ // rbx = literals array.
+ // rax = regexp literal.
+ __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
+ __ movq(rbx, FieldOperand(rdi, JSFunction::kLiteralsOffset));
+ int literal_offset =
+ FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
+ __ movq(rax, FieldOperand(rbx, literal_offset));
+ __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
+ __ j(not_equal, &done);
+ // Create regexp literal using runtime function
+ // Result will be in rax.
+ __ push(rbx);
+ __ Push(Smi::FromInt(expr->literal_index()));
+ __ Push(expr->pattern());
+ __ Push(expr->flags());
+ __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
+ // Label done:
+ __ bind(&done);
+ Move(expr->location(), rax);
+}
+
+
void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
Comment cmnt(masm_, "[ ObjectLiteral");
Label boilerplate_exists;
case ObjectLiteral::Property::COMPUTED:
if (key->handle()->IsSymbol()) {
Visit(value);
- ASSERT(value->location().is_temporary());
+ ASSERT(value->location().is_value());
__ pop(rax);
__ Move(rcx, key->handle());
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
case ObjectLiteral::Property::PROTOTYPE:
__ push(rax);
Visit(key);
- ASSERT(key->location().is_temporary());
+ ASSERT(key->location().is_value());
Visit(value);
- ASSERT(value->location().is_temporary());
+ ASSERT(value->location().is_value());
__ CallRuntime(Runtime::kSetProperty, 3);
__ movq(rax, Operand(rsp, 0)); // Restore result into rax.
break;
case ObjectLiteral::Property::GETTER:
__ push(rax);
Visit(key);
- ASSERT(key->location().is_temporary());
+ ASSERT(key->location().is_value());
__ Push(property->kind() == ObjectLiteral::Property::SETTER ?
Smi::FromInt(1) :
Smi::FromInt(0));
Visit(value);
- ASSERT(value->location().is_temporary());
+ ASSERT(value->location().is_value());
__ CallRuntime(Runtime::kDefineAccessor, 4);
__ movq(rax, Operand(rsp, 0)); // Restore result into rax.
break;
}
}
switch (expr->location().type()) {
- case Location::NOWHERE:
+ case Location::UNINITIALIZED:
+ UNREACHABLE();
+ case Location::EFFECT:
if (result_saved) __ addq(rsp, Immediate(kPointerSize));
break;
- case Location::TEMP:
+ case Location::VALUE:
if (!result_saved) __ push(rax);
break;
}
}
-void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
- Comment cmnt(masm_, "[ RegExp Literal");
- Label done;
- // Registers will be used as follows:
- // rdi = JS function.
- // rbx = literals array.
- // rax = regexp literal.
- __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
- __ movq(rbx, FieldOperand(rdi, JSFunction::kLiteralsOffset));
- int literal_offset =
- FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
- __ movq(rax, FieldOperand(rbx, literal_offset));
- __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
- __ j(not_equal, &done);
- // Create regexp literal using runtime function
- // Result will be in rax.
- __ push(rbx);
- __ Push(Smi::FromInt(expr->literal_index()));
- __ Push(expr->pattern());
- __ Push(expr->flags());
- __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
- // Label done:
- __ bind(&done);
- Move(expr->location(), rax);
-}
-
-
void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
Comment cmnt(masm_, "[ ArrayLiteral");
Label make_clone;
result_saved = true;
}
Visit(subexpr);
- ASSERT(subexpr->location().is_temporary());
+ ASSERT(subexpr->location().is_value());
// Store the subexpression value in the array's elements.
__ pop(rax); // Subexpression value.
}
switch (expr->location().type()) {
- case Location::NOWHERE:
+ case Location::UNINITIALIZED:
+ UNREACHABLE();
+ case Location::EFFECT:
if (result_saved) __ addq(rsp, Immediate(kPointerSize));
break;
- case Location::TEMP:
+ case Location::VALUE:
if (!result_saved) __ push(rax);
break;
}
if (rhs->AsLiteral() != NULL) {
__ Move(rax, rhs->AsLiteral()->handle());
} else {
- ASSERT(rhs->location().is_temporary());
+ ASSERT(rhs->location().is_value());
Visit(rhs);
__ pop(rax);
}
__ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister);
Move(expr->location(), kScratchRegister);
} else {
- ASSERT(rhs->location().is_temporary());
+ ASSERT(rhs->location().is_value());
Visit(rhs);
switch (expr->location().type()) {
- case Location::NOWHERE:
+ case Location::UNINITIALIZED:
+ UNREACHABLE();
+ case Location::EFFECT:
// Case 'var = temp'. Discard right-hand-side temporary.
Move(var->slot(), rhs->location());
break;
- case Location::TEMP:
+ case Location::VALUE:
// Case 'temp1 <- (var = temp0)'. Preserve right-hand-side
// temporary on the stack.
__ movq(kScratchRegister, Operand(rsp, 0));
__ addq(rsp, Immediate(kPointerSize));
}
switch (expr->location().type()) {
- case Location::TEMP:
+ case Location::UNINITIALIZED:
+ UNREACHABLE();
+ case Location::VALUE:
__ movq(Operand(rsp, 0), rax);
break;
- case Location::NOWHERE:
+ case Location::EFFECT:
__ addq(rsp, Immediate(kPointerSize));
break;
}
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
Visit(args->at(i));
- ASSERT(args->at(i)->location().is_temporary());
+ ASSERT(args->at(i)->location().is_value());
}
// Record source position for debugger
SetSourcePosition(expr->position());
// arguments.
// Push function on the stack.
Visit(node->expression());
- ASSERT(node->expression()->location().is_temporary());
+ ASSERT(node->expression()->location().is_value());
// If location is temporary, already on the stack,
// Push global object (receiver).
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
Visit(args->at(i));
- ASSERT(args->at(i)->location().is_temporary());
+ ASSERT(args->at(i)->location().is_value());
// If location is temporary, it is already on the stack,
// so nothing to do here.
}
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
Visit(args->at(i));
- ASSERT(args->at(i)->location().is_temporary());
+ ASSERT(args->at(i)->location().is_value());
}
__ CallRuntime(function, arg_count);
// need it as the value of the whole expression.
if (left->AsLiteral() != NULL) {
__ Move(rax, left->AsLiteral()->handle());
- if (destination.is_temporary()) __ push(rax);
+ if (destination.is_value()) __ push(rax);
} else {
Visit(left);
- ASSERT(left->location().is_temporary());
+ ASSERT(left->location().is_value());
switch (destination.type()) {
- case Location::NOWHERE:
+ case Location::UNINITIALIZED:
+ UNREACHABLE();
+ case Location::EFFECT:
// Pop the left-hand value into rax because we will not need it as the
// final result.
__ pop(rax);
break;
- case Location::TEMP:
+ case Location::VALUE:
// Copy the left-hand value into rax because we may need it as the
// final result.
__ movq(rax, Operand(rsp, 0));
__ bind(&eval_right);
// Discard the left-hand value if present on the stack.
- if (destination.is_temporary()) {
+ if (destination.is_value()) {
__ addq(rsp, Immediate(kPointerSize));
}
// Save or discard the right-hand value as needed.