From 9ad7a66f985ad4a7427f2235131577a049c4a0a9 Mon Sep 17 00:00:00 2001 From: "kmillikin@chromium.org" Date: Thu, 29 Oct 2009 10:35:29 +0000 Subject: [PATCH] Rename the kinds of locations to be consistent with the (codegen) context of the expressions they label. Introduce an "unintialized" location to catch failure to assign any location at all. Changed the object literal initialization on ARM to use a Store IC in the same cases where it did on the other platforms. This was required because the location of the literal property name is given an "unitialized" location. Review URL: http://codereview.chromium.org/339045 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3171 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/fast-codegen-arm.cc | 155 ++++++++++++++++++++-------------- src/ast.h | 2 +- src/compiler.cc | 10 +-- src/fast-codegen.cc | 23 +++-- src/ia32/fast-codegen-ia32.cc | 135 ++++++++++++++++------------- src/location.h | 11 +-- src/x64/fast-codegen-x64.cc | 137 +++++++++++++++++------------- 7 files changed, 272 insertions(+), 201 deletions(-) diff --git a/src/arm/fast-codegen-arm.cc b/src/arm/fast-codegen-arm.cc index 21ee6d7e0..49b25746b 100644 --- a/src/arm/fast-codegen-arm.cc +++ b/src/arm/fast-codegen-arm.cc @@ -119,9 +119,11 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) { 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; @@ -131,9 +133,11 @@ void FastCodeGenerator::Move(Location destination, Slot* source) { 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; @@ -143,9 +147,10 @@ void FastCodeGenerator::Move(Location destination, Literal* expr) { 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; @@ -155,10 +160,12 @@ void FastCodeGenerator::Move(Slot* destination, Location source) { 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; } @@ -239,6 +246,33 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { } +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; @@ -284,73 +318,62 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 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 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; @@ -400,7 +423,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 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. @@ -416,10 +439,12 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { } 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; } @@ -446,7 +471,7 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) { 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); } @@ -468,15 +493,17 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) { __ 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)); @@ -522,10 +549,12 @@ void FastCodeGenerator::VisitProperty(Property* expr) { __ 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(); } } @@ -546,7 +575,7 @@ void FastCodeGenerator::VisitCall(Call* expr) { 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()); @@ -567,7 +596,7 @@ void FastCodeGenerator::VisitCallNew(CallNew* node) { // 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()); @@ -577,7 +606,7 @@ void FastCodeGenerator::VisitCallNew(CallNew* node) { 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. } @@ -610,7 +639,7 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 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); @@ -636,11 +665,11 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { 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); } @@ -653,7 +682,7 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { __ 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()); diff --git a/src/ast.h b/src/ast.h index 9b7d9ddb0..be64dcb3c 100644 --- a/src/ast.h +++ b/src/ast.h @@ -162,7 +162,7 @@ class Statement: public AstNode { class Expression: public AstNode { public: - Expression() : location_(Location::Temporary()) {} + Expression() : location_(Location::Uninitialized()) {} virtual Expression* AsExpression() { return this; } diff --git a/src/compiler.cc b/src/compiler.cc index bad209e13..63bf2ecad 100644 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -48,7 +48,7 @@ class CodeGenSelector: public AstVisitor { CodeGenSelector() : has_supported_syntax_(true), - location_(Location::Nowhere()) { + location_(Location::Uninitialized()) { } CodeGenTag Select(FunctionLiteral* fun); @@ -514,11 +514,11 @@ void CodeGenSelector::VisitStatements(ZoneList* stmts) { 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; } @@ -526,11 +526,11 @@ void CodeGenSelector::VisitAsEffect(Expression* expr) { 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; } diff --git a/src/fast-codegen.cc b/src/fast-codegen.cc index 8655e97a8..20c17b33c 100644 --- a/src/fast-codegen.cc +++ b/src/fast-codegen.cc @@ -73,14 +73,18 @@ int FastCodeGenerator::SlotOffset(Slot* slot) { 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; @@ -92,9 +96,11 @@ void FastCodeGenerator::Move(Location destination, Location source) { // 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; } @@ -105,9 +111,10 @@ void FastCodeGenerator::Move(Location destination, Register source) { // 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); } } diff --git a/src/ia32/fast-codegen-ia32.cc b/src/ia32/fast-codegen-ia32.cc index 0d661c3b6..520fd077a 100644 --- a/src/ia32/fast-codegen-ia32.cc +++ b/src/ia32/fast-codegen-ia32.cc @@ -110,9 +110,11 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) { 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; } @@ -121,9 +123,11 @@ void FastCodeGenerator::Move(Location destination, Slot* source) { 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; } @@ -132,9 +136,10 @@ void FastCodeGenerator::Move(Location destination, Literal* expr) { 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; } @@ -143,10 +148,12 @@ void FastCodeGenerator::Move(Slot* destination, Location source) { 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; } @@ -231,6 +238,33 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { } +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; @@ -295,9 +329,9 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 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; @@ -305,12 +339,12 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 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; @@ -318,43 +352,18 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { } } 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; @@ -403,7 +412,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 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. @@ -417,10 +426,12 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { } 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; } @@ -446,7 +457,7 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) { if (rhs->AsLiteral() != NULL) { __ mov(eax, rhs->AsLiteral()->handle()); } else { - ASSERT(rhs->location().is_temporary()); + ASSERT(rhs->location().is_value()); Visit(rhs); __ pop(eax); } @@ -467,14 +478,16 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) { __ 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)); @@ -519,10 +532,12 @@ void FastCodeGenerator::VisitProperty(Property* expr) { __ 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; } @@ -542,7 +557,7 @@ void FastCodeGenerator::VisitCall(Call* expr) { 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()); @@ -564,7 +579,7 @@ void FastCodeGenerator::VisitCallNew(CallNew* node) { // 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()); @@ -574,7 +589,7 @@ void FastCodeGenerator::VisitCallNew(CallNew* node) { 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. } @@ -607,7 +622,7 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 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); @@ -635,17 +650,19 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { // 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)); @@ -677,7 +694,7 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { __ 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. diff --git a/src/location.h b/src/location.h index c4a77cb5d..7a11c4ab5 100644 --- a/src/location.h +++ b/src/location.h @@ -35,13 +35,14 @@ namespace internal { 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_; } diff --git a/src/x64/fast-codegen-x64.cc b/src/x64/fast-codegen-x64.cc index 53ee35758..2c9212b39 100644 --- a/src/x64/fast-codegen-x64.cc +++ b/src/x64/fast-codegen-x64.cc @@ -118,9 +118,11 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) { 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; } @@ -129,9 +131,11 @@ void FastCodeGenerator::Move(Location destination, Slot* source) { 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; } @@ -140,9 +144,10 @@ void FastCodeGenerator::Move(Location destination, Literal* expr) { 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; } @@ -151,10 +156,12 @@ void FastCodeGenerator::Move(Slot* destination, Location source) { 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; } @@ -246,6 +253,33 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { } +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; @@ -295,7 +329,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 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 ic(Builtins::builtin(Builtins::StoreIC_Initialize)); @@ -307,9 +341,9 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 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; @@ -317,12 +351,12 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 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; @@ -330,43 +364,18 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { } } 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; @@ -415,7 +424,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 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. @@ -429,10 +438,12 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { } 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; } @@ -459,7 +470,7 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) { if (rhs->AsLiteral() != NULL) { __ Move(rax, rhs->AsLiteral()->handle()); } else { - ASSERT(rhs->location().is_temporary()); + ASSERT(rhs->location().is_value()); Visit(rhs); __ pop(rax); } @@ -480,14 +491,16 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) { __ 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)); @@ -532,10 +545,12 @@ void FastCodeGenerator::VisitProperty(Property* expr) { __ 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; } @@ -555,7 +570,7 @@ void FastCodeGenerator::VisitCall(Call* expr) { 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()); @@ -577,7 +592,7 @@ void FastCodeGenerator::VisitCallNew(CallNew* node) { // 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). @@ -588,7 +603,7 @@ void FastCodeGenerator::VisitCallNew(CallNew* node) { 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. } @@ -621,7 +636,7 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 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); @@ -649,17 +664,19 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { // 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)); @@ -692,7 +709,7 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { __ 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. -- 2.34.1