Move the Location class into the AST Expression class as a member.

Since it is (currently) only an enum, change it to an enum (for now).

Review URL: http://codereview.chromium.org/342035

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3181 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
kmillikin@chromium.org 2009-10-30 08:36:46 +00:00
parent 143b4b87b4
commit d92fa03eca
11 changed files with 281 additions and 423 deletions

View File

@ -117,13 +117,13 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) {
}
void FastCodeGenerator::Move(Location destination, Slot* source) {
switch (destination.type()) {
case Location::kUninitialized:
void FastCodeGenerator::Move(Expression::Context context, Slot* source) {
switch (context) {
case Expression::kUninitialized:
UNREACHABLE();
case Location::kEffect:
case Expression::kEffect:
break;
case Location::kValue:
case Expression::kValue:
__ ldr(ip, MemOperand(fp, SlotOffset(source)));
__ push(ip);
break;
@ -131,13 +131,13 @@ void FastCodeGenerator::Move(Location destination, Slot* source) {
}
void FastCodeGenerator::Move(Location destination, Literal* expr) {
switch (destination.type()) {
case Location::kUninitialized:
void FastCodeGenerator::Move(Expression::Context context, Literal* expr) {
switch (context) {
case Expression::kUninitialized:
UNREACHABLE();
case Location::kEffect:
case Expression::kEffect:
break;
case Location::kValue:
case Expression::kValue:
__ mov(ip, Operand(expr->handle()));
__ push(ip);
break;
@ -145,27 +145,15 @@ void FastCodeGenerator::Move(Location destination, Literal* expr) {
}
void FastCodeGenerator::Move(Slot* destination, Location source) {
switch (source.type()) {
case Location::kUninitialized: // Fall through.
case Location::kEffect:
void FastCodeGenerator::DropAndMove(Expression::Context context,
Register source) {
switch (context) {
case Expression::kUninitialized:
UNREACHABLE();
case Location::kValue:
__ pop(ip);
__ str(ip, MemOperand(fp, SlotOffset(destination)));
break;
}
}
void FastCodeGenerator::DropAndMove(Location destination, Register source) {
switch (destination.type()) {
case Location::kUninitialized:
UNREACHABLE();
case Location::kEffect:
case Expression::kEffect:
__ pop();
break;
case Location::kValue:
case Expression::kValue:
__ str(source, MemOperand(sp));
break;
}
@ -191,8 +179,9 @@ void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
if (expr->AsLiteral() != NULL) {
__ mov(r0, Operand(expr->AsLiteral()->handle()));
} else {
ASSERT_EQ(Expression::kValue, expr->context());
Visit(expr);
Move(r0, expr->location());
__ pop(r0);
}
if (FLAG_trace) {
@ -222,7 +211,7 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
__ mov(r0, Operand(boilerplate));
__ stm(db_w, sp, cp.bit() | r0.bit());
__ CallRuntime(Runtime::kNewClosure, 2);
Move(expr->location(), r0);
Move(expr->context(), r0);
}
@ -238,10 +227,10 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
__ mov(r2, Operand(expr->name()));
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
__ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
DropAndMove(expr->location(), r0);
DropAndMove(expr->context(), r0);
} else {
Comment cmnt(masm_, "Stack slot");
Move(expr->location(), rewrite->AsSlot());
Move(expr->context(), rewrite->AsSlot());
}
}
@ -269,7 +258,7 @@ void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
__ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit());
__ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
__ bind(&done);
Move(expr->location(), r0);
Move(expr->context(), r0);
}
@ -326,7 +315,8 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::COMPUTED:
if (key->handle()->IsSymbol()) {
Visit(value);
Move(r0, value->location());
ASSERT_EQ(Expression::kValue, value->context());
__ pop(r0);
__ mov(r2, Operand(key->handle()));
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
__ Call(ic, RelocInfo::CODE_TARGET);
@ -338,9 +328,9 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::PROTOTYPE:
__ push(r0);
Visit(key);
ASSERT(key->location().is_value());
ASSERT_EQ(Expression::kValue, key->context());
Visit(value);
ASSERT(value->location().is_value());
ASSERT_EQ(Expression::kValue, value->context());
__ CallRuntime(Runtime::kSetProperty, 3);
__ ldr(r0, MemOperand(sp)); // Restore result into r0
break;
@ -349,25 +339,25 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::SETTER:
__ push(r0);
Visit(key);
ASSERT(key->location().is_value());
ASSERT_EQ(Expression::kValue, key->context());
__ mov(r1, Operand(property->kind() == ObjectLiteral::Property::SETTER ?
Smi::FromInt(1) :
Smi::FromInt(0)));
__ push(r1);
Visit(value);
ASSERT(value->location().is_value());
ASSERT_EQ(Expression::kValue, value->context());
__ CallRuntime(Runtime::kDefineAccessor, 4);
__ ldr(r0, MemOperand(sp)); // Restore result into r0
break;
}
}
switch (expr->location().type()) {
case Location::kUninitialized:
switch (expr->context()) {
case Expression::kUninitialized:
UNREACHABLE();
case Location::kEffect:
case Expression::kEffect:
if (result_saved) __ pop();
break;
case Location::kValue:
case Expression::kValue:
if (!result_saved) __ push(r0);
break;
}
@ -423,7 +413,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
result_saved = true;
}
Visit(subexpr);
ASSERT(subexpr->location().is_value());
ASSERT_EQ(Expression::kValue, subexpr->context());
// Store the subexpression value in the array's elements.
__ pop(r0); // Subexpression value.
@ -438,13 +428,13 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
__ RecordWrite(r1, r2, r0);
}
switch (expr->location().type()) {
case Location::kUninitialized:
switch (expr->context()) {
case Expression::kUninitialized:
UNREACHABLE();
case Location::kEffect:
case Expression::kEffect:
if (result_saved) __ pop();
break;
case Location::kValue:
case Expression::kValue:
if (!result_saved) __ push(r0);
break;
}
@ -474,7 +464,8 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
!String::cast(*(literal_key->handle()))->AsArrayIndex(&dummy)) {
// NAMED property assignment
Visit(rhs);
Move(r0, rhs->location());
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);
@ -482,14 +473,15 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
// KEYED property assignment
Visit(prop->key());
Visit(rhs);
Move(r0, rhs->location());
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->location(), r0);
DropAndMove(expr->context(), r0);
} else 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
@ -499,7 +491,7 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
if (rhs->AsLiteral() != NULL) {
__ mov(r0, Operand(rhs->AsLiteral()->handle()));
} else {
ASSERT(rhs->location().is_value());
ASSERT_EQ(Expression::kValue, rhs->context());
Visit(rhs);
__ pop(r0);
}
@ -509,7 +501,7 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
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->location(), r0);
DropAndMove(expr->context(), r0);
} else {
// Local or parameter assignment.
@ -519,19 +511,19 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
// discarded result. Always perform the assignment.
__ mov(ip, Operand(rhs->AsLiteral()->handle()));
__ str(ip, MemOperand(fp, SlotOffset(var->slot())));
Move(expr->location(), ip);
Move(expr->context(), ip);
} else {
ASSERT(rhs->location().is_value());
ASSERT_EQ(Expression::kValue, rhs->context());
Visit(rhs);
// Load right-hand side into ip.
switch (expr->location().type()) {
case Location::kUninitialized:
switch (expr->context()) {
case Expression::kUninitialized:
UNREACHABLE();
case Location::kEffect:
case Expression::kEffect:
// Case 'var = temp'. Discard right-hand-side temporary.
__ pop(ip);
break;
case Location::kValue:
case Expression::kValue:
// Case 'temp1 <- (var = temp0)'. Preserve right-hand-side
// temporary on the stack.
__ ldr(ip, MemOperand(sp));
@ -570,7 +562,7 @@ void FastCodeGenerator::VisitProperty(Property* expr) {
// Drop key and receiver left on the stack by IC.
__ pop();
}
DropAndMove(expr->location(), r0);
DropAndMove(expr->context(), r0);
}
@ -589,7 +581,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_value());
ASSERT_EQ(Expression::kValue, args->at(i)->context());
}
// Record source position for debugger
SetSourcePosition(expr->position());
@ -599,35 +591,35 @@ void FastCodeGenerator::VisitCall(Call* expr) {
__ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
// Restore context register.
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
DropAndMove(expr->location(), r0);
DropAndMove(expr->context(), r0);
}
void FastCodeGenerator::VisitCallNew(CallNew* node) {
void FastCodeGenerator::VisitCallNew(CallNew* expr) {
Comment cmnt(masm_, "[ CallNew");
// According to ECMA-262, section 11.2.2, page 44, the function
// expression in new calls must be evaluated before the
// arguments.
// Push function on the stack.
Visit(node->expression());
ASSERT(node->expression()->location().is_value());
Visit(expr->expression());
ASSERT_EQ(Expression::kValue, expr->expression()->context());
// Push global object (receiver).
__ ldr(r0, CodeGenerator::GlobalObject());
__ push(r0);
// Push the arguments ("left-to-right") on the stack.
ZoneList<Expression*>* args = node->arguments();
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
Visit(args->at(i));
ASSERT(args->at(i)->location().is_value());
ASSERT_EQ(Expression::kValue, args->at(i)->context());
// If location is value, it is already on the stack,
// so nothing to do here.
}
// Call the construct call builtin that handles allocation and
// constructor invocation.
SetSourcePosition(node->position());
SetSourcePosition(expr->position());
// Load function, arg_count into r1 and r0.
__ mov(r0, Operand(arg_count));
@ -638,7 +630,7 @@ void FastCodeGenerator::VisitCallNew(CallNew* node) {
__ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
// Replace function on TOS with result in r0, or pop it.
DropAndMove(node->location(), r0);
DropAndMove(expr->context(), r0);
}
@ -653,19 +645,19 @@ 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_value());
ASSERT_EQ(Expression::kValue, args->at(i)->context());
}
__ CallRuntime(function, arg_count);
Move(expr->location(), r0);
Move(expr->context(), r0);
}
void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
switch (expr->op()) {
case Token::COMMA:
ASSERT(expr->left()->location().is_effect());
ASSERT_EQ(expr->right()->location().type(), expr->location().type());
ASSERT_EQ(Expression::kEffect, expr->left()->context());
ASSERT_EQ(expr->context(), expr->right()->context());
Visit(expr->left());
Visit(expr->right());
break;
@ -686,8 +678,8 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
case Token::SHL:
case Token::SHR:
case Token::SAR: {
ASSERT(expr->left()->location().is_value());
ASSERT(expr->right()->location().is_value());
ASSERT_EQ(Expression::kValue, expr->left()->context());
ASSERT_EQ(Expression::kValue, expr->right()->context());
Visit(expr->left());
Visit(expr->right());
@ -696,7 +688,7 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
GenericBinaryOpStub stub(expr->op(),
NO_OVERWRITE);
__ CallStub(&stub);
Move(expr->location(), r0);
Move(expr->context(), r0);
break;
}
@ -715,7 +707,7 @@ void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) {
// (let (temp = e0) !temp ? temp : e1).
Label done;
Location destination = expr->location();
Expression::Context context = expr->context();
Expression* left = expr->left();
Expression* right = expr->right();
@ -725,11 +717,11 @@ void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) {
if (left->AsLiteral() != NULL) {
__ mov(r0, Operand(left->AsLiteral()->handle()));
__ push(r0);
if (destination.is_value()) __ push(r0);
if (context == Expression::kValue) __ push(r0);
} else {
Visit(left);
ASSERT(left->location().is_value());
if (destination.is_value()) {
ASSERT_EQ(Expression::kValue, left->context());
if (context == Expression::kValue) {
__ ldr(r0, MemOperand(sp));
__ push(r0);
}
@ -746,10 +738,10 @@ void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) {
__ b(eq, &done);
// Discard the left-hand value if present on the stack.
if (destination.is_value()) __ pop();
if (context == Expression::kValue) __ pop();
// Save or discard the right-hand value as needed.
Visit(right);
ASSERT_EQ(destination.type(), right->location().type());
ASSERT_EQ(context, right->context());
__ bind(&done);
}

View File

@ -28,7 +28,6 @@
#ifndef V8_AST_H_
#define V8_AST_H_
#include "location.h"
#include "execution.h"
#include "factory.h"
#include "jsregexp.h"
@ -162,7 +161,13 @@ class Statement: public AstNode {
class Expression: public AstNode {
public:
Expression() : location_(Location::Uninitialized()) {}
enum Context {
kUninitialized,
kEffect,
kValue
};
Expression() : context_(kUninitialized) {}
virtual Expression* AsExpression() { return this; }
@ -177,12 +182,12 @@ class Expression: public AstNode {
// Static type information for this expression.
SmiAnalysis* type() { return &type_; }
Location location() { return location_; }
void set_location(Location loc) { location_ = loc; }
Context context() { return context_; }
void set_context(Context context) { context_ = context; }
private:
SmiAnalysis type_;
Location location_;
Context context_;
};

View File

@ -48,23 +48,24 @@ class CodeGenSelector: public AstVisitor {
CodeGenSelector()
: has_supported_syntax_(true),
location_(Location::Uninitialized()) {
context_(Expression::kUninitialized) {
}
CodeGenTag Select(FunctionLiteral* fun);
private:
// Visit an expression in a given expression context.
void ProcessExpression(Expression* expr, Expression::Context context) {
Expression::Context saved = context_;
context_ = context;
Visit(expr);
expr->set_context(context);
context_ = saved;
}
void VisitDeclarations(ZoneList<Declaration*>* decls);
void VisitStatements(ZoneList<Statement*>* stmts);
// Visit an expression in effect context with a desired location of
// nowhere.
void VisitAsEffect(Expression* expr);
// Visit an expression in value context with a desired location of
// temporary.
void VisitAsValue(Expression* expr);
// AST node visit functions.
#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
AST_NODE_LIST(DECLARE_VISIT)
@ -72,8 +73,8 @@ class CodeGenSelector: public AstVisitor {
bool has_supported_syntax_;
// The desired location of the currently visited expression.
Location location_;
// The desired expression context of the currently visited expression.
Expression::Context context_;
DISALLOW_COPY_AND_ASSIGN(CodeGenSelector);
};
@ -513,30 +514,6 @@ void CodeGenSelector::VisitStatements(ZoneList<Statement*>* stmts) {
}
void CodeGenSelector::VisitAsEffect(Expression* expr) {
if (location_.is_effect()) {
Visit(expr);
} else {
Location saved = location_;
location_ = Location::Effect();
Visit(expr);
location_ = saved;
}
}
void CodeGenSelector::VisitAsValue(Expression* expr) {
if (location_.is_value()) {
Visit(expr);
} else {
Location saved = location_;
location_ = Location::Value();
Visit(expr);
location_ = saved;
}
}
void CodeGenSelector::VisitDeclaration(Declaration* decl) {
Variable* var = decl->proxy()->var();
if (!var->is_global() || var->mode() == Variable::CONST) {
@ -551,7 +528,7 @@ void CodeGenSelector::VisitBlock(Block* stmt) {
void CodeGenSelector::VisitExpressionStatement(ExpressionStatement* stmt) {
VisitAsEffect(stmt->expression());
ProcessExpression(stmt->expression(), Expression::kEffect);
}
@ -576,7 +553,7 @@ void CodeGenSelector::VisitBreakStatement(BreakStatement* stmt) {
void CodeGenSelector::VisitReturnStatement(ReturnStatement* stmt) {
VisitAsValue(stmt->expression());
ProcessExpression(stmt->expression(), Expression::kValue);
}
@ -634,7 +611,6 @@ void CodeGenSelector::VisitFunctionLiteral(FunctionLiteral* expr) {
if (!expr->AllowsLazyCompilation()) {
BAILOUT("FunctionLiteral does not allow lazy compilation");
}
expr->set_location(location_);
}
@ -671,17 +647,16 @@ void CodeGenSelector::VisitVariableProxy(VariableProxy* expr) {
BAILOUT("non-parameter/non-local slot reference");
}
}
expr->set_location(location_);
}
void CodeGenSelector::VisitLiteral(Literal* expr) {
expr->set_location(location_);
/* Nothing to do. */
}
void CodeGenSelector::VisitRegExpLiteral(RegExpLiteral* expr) {
expr->set_location(location_);
/* Nothing to do. */
}
@ -711,14 +686,13 @@ void CodeGenSelector::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::GETTER: // Fall through.
case ObjectLiteral::Property::SETTER: // Fall through.
case ObjectLiteral::Property::PROTOTYPE:
VisitAsValue(property->key());
ProcessExpression(property->key(), Expression::kValue);
CHECK_BAILOUT;
break;
}
VisitAsValue(property->value());
ProcessExpression(property->value(), Expression::kValue);
CHECK_BAILOUT;
}
expr->set_location(location_);
}
@ -728,10 +702,9 @@ void CodeGenSelector::VisitArrayLiteral(ArrayLiteral* expr) {
Expression* subexpr = subexprs->at(i);
if (subexpr->AsLiteral() != NULL) continue;
if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
VisitAsValue(subexpr);
ProcessExpression(subexpr, Expression::kValue);
CHECK_BAILOUT;
}
expr->set_location(location_);
}
@ -758,9 +731,9 @@ void CodeGenSelector::VisitAssignment(Assignment* expr) {
if (var == NULL) {
Property* prop = expr->target()->AsProperty();
if (prop == NULL) BAILOUT("non-variable, non-property assignment");
VisitAsValue(prop->obj());
ProcessExpression(prop->obj(), Expression::kValue);
CHECK_BAILOUT;
VisitAsValue(prop->key());
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();
@ -769,8 +742,7 @@ void CodeGenSelector::VisitAssignment(Assignment* expr) {
}
}
VisitAsValue(expr->value());
expr->set_location(location_);
ProcessExpression(expr->value(), Expression::kValue);
}
@ -780,10 +752,9 @@ void CodeGenSelector::VisitThrow(Throw* expr) {
void CodeGenSelector::VisitProperty(Property* expr) {
VisitAsValue(expr->obj());
ProcessExpression(expr->obj(), Expression::kValue);
CHECK_BAILOUT;
VisitAsValue(expr->key());
expr->set_location(location_);
ProcessExpression(expr->key(), Expression::kValue);
}
@ -804,23 +775,21 @@ void CodeGenSelector::VisitCall(Call* expr) {
}
// Check all arguments to the call. (Relies on TEMP meaning STACK.)
for (int i = 0; i < args->length(); i++) {
VisitAsValue(args->at(i));
ProcessExpression(args->at(i), Expression::kValue);
CHECK_BAILOUT;
}
expr->set_location(location_);
}
void CodeGenSelector::VisitCallNew(CallNew* expr) {
VisitAsValue(expr->expression());
ProcessExpression(expr->expression(), Expression::kValue);
CHECK_BAILOUT;
ZoneList<Expression*>* args = expr->arguments();
// Check all arguments to the call
for (int i = 0; i < args->length(); i++) {
VisitAsValue(args->at(i));
ProcessExpression(args->at(i), Expression::kValue);
CHECK_BAILOUT;
}
expr->set_location(location_);
}
@ -834,10 +803,9 @@ void CodeGenSelector::VisitCallRuntime(CallRuntime* expr) {
}
// Check all arguments to the call. (Relies on TEMP meaning STACK.)
for (int i = 0; i < expr->arguments()->length(); i++) {
VisitAsValue(expr->arguments()->at(i));
ProcessExpression(expr->arguments()->at(i), Expression::kValue);
CHECK_BAILOUT;
}
expr->set_location(location_);
}
@ -854,17 +822,15 @@ void CodeGenSelector::VisitCountOperation(CountOperation* expr) {
void CodeGenSelector::VisitBinaryOperation(BinaryOperation* expr) {
switch (expr->op()) {
case Token::COMMA:
VisitAsEffect(expr->left());
ProcessExpression(expr->left(), Expression::kEffect);
CHECK_BAILOUT;
Visit(expr->right()); // Location is the same as the parent location.
ProcessExpression(expr->right(), context_);
break;
case Token::OR:
VisitAsValue(expr->left());
ProcessExpression(expr->left(), Expression::kValue);
CHECK_BAILOUT;
// The location for the right subexpression is the same as for the
// whole expression so we call Visit directly.
Visit(expr->right());
ProcessExpression(expr->right(), context_);
break;
case Token::ADD:
@ -878,15 +844,14 @@ void CodeGenSelector::VisitBinaryOperation(BinaryOperation* expr) {
case Token::SHL:
case Token::SHR:
case Token::SAR:
VisitAsValue(expr->left());
ProcessExpression(expr->left(), Expression::kValue);
CHECK_BAILOUT;
VisitAsValue(expr->right());
ProcessExpression(expr->right(), Expression::kValue);
break;
default:
BAILOUT("Unsupported binary operation");
}
expr->set_location(location_);
}

View File

@ -73,32 +73,19 @@ int FastCodeGenerator::SlotOffset(Slot* slot) {
// All platform macro assemblers in {ia32,x64,arm} have a push(Register)
// function.
void FastCodeGenerator::Move(Location destination, Register source) {
switch (destination.type()) {
case Location::kUninitialized:
void FastCodeGenerator::Move(Expression::Context context, Register source) {
switch (context) {
case Expression::kUninitialized:
UNREACHABLE();
case Location::kEffect:
case Expression::kEffect:
break;
case Location::kValue:
case Expression::kValue:
masm_->push(source);
break;
}
}
// All platform macro assemblers in {ia32,x64,arm} have a pop(Register)
// function.
void FastCodeGenerator::Move(Register destination, Location source) {
switch (source.type()) {
case Location::kUninitialized: // Fall through.
case Location::kEffect:
UNREACHABLE();
case Location::kValue:
masm_->pop(destination);
}
}
void FastCodeGenerator::VisitDeclarations(
ZoneList<Declaration*>* declarations) {
int length = declarations->length();
@ -323,7 +310,7 @@ void FastCodeGenerator::VisitSlot(Slot* expr) {
void FastCodeGenerator::VisitLiteral(Literal* expr) {
Move(expr->location(), expr);
Move(expr->context(), expr);
}

View File

@ -51,16 +51,13 @@ class FastCodeGenerator: public AstVisitor {
private:
int SlotOffset(Slot* slot);
void Move(Location destination, Register source);
void Move(Location destination, Slot* source);
void Move(Location destination, Literal* source);
void Move(Register destination, Location source);
void Move(Slot* destination, Location source);
void Move(Expression::Context destination, Register source);
void Move(Expression::Context destination, Slot* source);
void Move(Expression::Context destination, Literal* source);
// Drop the TOS, and store source to destination.
// If destination is TOS, just overwrite TOS with source.
void DropAndMove(Location destination, Register source);
void DropAndMove(Expression::Context destination, Register source);
void VisitDeclarations(ZoneList<Declaration*>* declarations);
Handle<JSFunction> BuildBoilerplate(FunctionLiteral* fun);

View File

@ -108,52 +108,41 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) {
}
void FastCodeGenerator::Move(Location destination, Slot* source) {
switch (destination.type()) {
case Location::kUninitialized:
void FastCodeGenerator::Move(Expression::Context context, Slot* source) {
switch (context) {
case Expression::kUninitialized:
UNREACHABLE();
case Location::kEffect:
case Expression::kEffect:
break;
case Location::kValue:
case Expression::kValue:
__ push(Operand(ebp, SlotOffset(source)));
break;
}
}
void FastCodeGenerator::Move(Location destination, Literal* expr) {
switch (destination.type()) {
case Location::kUninitialized:
void FastCodeGenerator::Move(Expression::Context context, Literal* expr) {
switch (context) {
case Expression::kUninitialized:
UNREACHABLE();
case Location::kEffect:
case Expression::kEffect:
break;
case Location::kValue:
case Expression::kValue:
__ push(Immediate(expr->handle()));
break;
}
}
void FastCodeGenerator::Move(Slot* destination, Location source) {
switch (source.type()) {
case Location::kUninitialized: // Fall through.
case Location::kEffect:
void FastCodeGenerator::DropAndMove(Expression::Context context,
Register source) {
switch (context) {
case Expression::kUninitialized:
UNREACHABLE();
case Location::kValue:
__ pop(Operand(ebp, SlotOffset(destination)));
break;
}
}
void FastCodeGenerator::DropAndMove(Location destination, Register source) {
switch (destination.type()) {
case Location::kUninitialized:
UNREACHABLE();
case Location::kEffect:
case Expression::kEffect:
__ add(Operand(esp), Immediate(kPointerSize));
break;
case Location::kValue:
case Expression::kValue:
__ mov(Operand(esp, 0), source);
break;
}
@ -174,12 +163,12 @@ void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
Comment cmnt(masm_, "[ ReturnStatement");
SetStatementPosition(stmt);
Expression* expr = stmt->expression();
// Complete the statement based on the type of the subexpression.
if (expr->AsLiteral() != NULL) {
__ mov(eax, expr->AsLiteral()->handle());
} else {
ASSERT_EQ(Expression::kValue, expr->context());
Visit(expr);
Move(eax, expr->location());
__ pop(eax);
}
if (FLAG_trace) {
@ -209,7 +198,7 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
__ push(esi);
__ push(Immediate(boilerplate));
__ CallRuntime(Runtime::kNewClosure, 2);
Move(expr->location(), eax);
Move(expr->context(), eax);
}
@ -230,10 +219,10 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
// (eg, push/pop elimination).
__ nop();
DropAndMove(expr->location(), eax);
DropAndMove(expr->context(), eax);
} else {
Comment cmnt(masm_, "Stack slot");
Move(expr->location(), rewrite->AsSlot());
Move(expr->context(), rewrite->AsSlot());
}
}
@ -261,7 +250,7 @@ void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
__ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
// Label done:
__ bind(&done);
Move(expr->location(), eax);
Move(expr->context(), eax);
}
@ -318,7 +307,8 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::COMPUTED:
if (key->handle()->IsSymbol()) {
Visit(value);
Move(eax, value->location());
ASSERT_EQ(Expression::kValue, value->context());
__ pop(eax);
__ mov(ecx, Immediate(key->handle()));
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
__ call(ic, RelocInfo::CODE_TARGET);
@ -329,9 +319,9 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::PROTOTYPE:
__ push(eax);
Visit(key);
ASSERT(key->location().is_value());
ASSERT_EQ(Expression::kValue, key->context());
Visit(value);
ASSERT(value->location().is_value());
ASSERT_EQ(Expression::kValue, value->context());
__ CallRuntime(Runtime::kSetProperty, 3);
__ mov(eax, Operand(esp, 0)); // Restore result into eax.
break;
@ -339,25 +329,25 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::GETTER:
__ push(eax);
Visit(key);
ASSERT(key->location().is_value());
ASSERT_EQ(Expression::kValue, key->context());
__ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ?
Smi::FromInt(1) :
Smi::FromInt(0)));
Visit(value);
ASSERT(value->location().is_value());
ASSERT_EQ(Expression::kValue, value->context());
__ CallRuntime(Runtime::kDefineAccessor, 4);
__ mov(eax, Operand(esp, 0)); // Restore result into eax.
break;
default: UNREACHABLE();
}
}
switch (expr->location().type()) {
case Location::kUninitialized:
switch (expr->context()) {
case Expression::kUninitialized:
UNREACHABLE();
case Location::kEffect:
case Expression::kEffect:
if (result_saved) __ add(Operand(esp), Immediate(kPointerSize));
break;
case Location::kValue:
case Expression::kValue:
if (!result_saved) __ push(eax);
break;
}
@ -412,7 +402,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
result_saved = true;
}
Visit(subexpr);
ASSERT(subexpr->location().is_value());
ASSERT_EQ(Expression::kValue, subexpr->context());
// Store the subexpression value in the array's elements.
__ pop(eax); // Subexpression value.
@ -425,13 +415,13 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
__ RecordWrite(ebx, offset, eax, ecx);
}
switch (expr->location().type()) {
case Location::kUninitialized:
switch (expr->context()) {
case Expression::kUninitialized:
UNREACHABLE();
case Location::kEffect:
case Expression::kEffect:
if (result_saved) __ add(Operand(esp), Immediate(kPointerSize));
break;
case Location::kValue:
case Expression::kValue:
if (!result_saved) __ push(eax);
break;
}
@ -461,7 +451,8 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
!String::cast(*(literal_key->handle()))->AsArrayIndex(&dummy)) {
// NAMED property assignment
Visit(rhs);
Move(eax, rhs->location());
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);
@ -470,7 +461,8 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
// KEYED property assignment
Visit(prop->key());
Visit(rhs);
Move(eax, rhs->location());
ASSERT_EQ(Expression::kValue, rhs->context());
__ pop(eax);
Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
__ call(ic, RelocInfo::CODE_TARGET);
__ nop();
@ -478,7 +470,7 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
__ add(Operand(esp), Immediate(kPointerSize));
}
// Overwrite the receiver on the stack with the result if needed.
DropAndMove(expr->location(), eax);
DropAndMove(expr->context(), eax);
} else 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
@ -488,7 +480,7 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
if (rhs->AsLiteral() != NULL) {
__ mov(eax, rhs->AsLiteral()->handle());
} else {
ASSERT(rhs->location().is_value());
ASSERT_EQ(Expression::kValue, rhs->context());
Visit(rhs);
__ pop(eax);
}
@ -497,7 +489,7 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
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->location(), eax);
DropAndMove(expr->context(), eax);
} else {
// Local or parameter assignment.
ASSERT(var->slot() != NULL);
@ -508,18 +500,18 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
// discarded result. Always perform the assignment.
__ mov(eax, rhs->AsLiteral()->handle());
__ mov(Operand(ebp, SlotOffset(var->slot())), eax);
Move(expr->location(), eax);
Move(expr->context(), eax);
} else {
ASSERT(rhs->location().is_value());
ASSERT_EQ(Expression::kValue, rhs->context());
Visit(rhs);
switch (expr->location().type()) {
case Location::kUninitialized:
switch (expr->context()) {
case Expression::kUninitialized:
UNREACHABLE();
case Location::kEffect:
case Expression::kEffect:
// Case 'var = temp'. Discard right-hand-side temporary.
Move(var->slot(), rhs->location());
__ pop(Operand(ebp, SlotOffset(var->slot())));
break;
case Location::kValue:
case Expression::kValue:
// Case 'temp1 <- (var = temp0)'. Preserve right-hand-side
// temporary on the stack.
__ mov(eax, Operand(esp, 0));
@ -562,7 +554,7 @@ void FastCodeGenerator::VisitProperty(Property* expr) {
// Drop key left on the stack by IC.
__ add(Operand(esp), Immediate(kPointerSize));
}
DropAndMove(expr->location(), eax);
DropAndMove(expr->context(), eax);
}
@ -579,7 +571,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_value());
ASSERT_EQ(Expression::kValue, args->at(i)->context());
}
// Record source position for debugger
SetSourcePosition(expr->position());
@ -590,35 +582,35 @@ void FastCodeGenerator::VisitCall(Call* expr) {
// Restore context register.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
// Discard the function left on TOS.
DropAndMove(expr->location(), eax);
DropAndMove(expr->context(), eax);
}
void FastCodeGenerator::VisitCallNew(CallNew* node) {
void FastCodeGenerator::VisitCallNew(CallNew* expr) {
Comment cmnt(masm_, "[ CallNew");
// According to ECMA-262, section 11.2.2, page 44, the function
// expression in new calls must be evaluated before the
// arguments.
// Push function on the stack.
Visit(node->expression());
ASSERT(node->expression()->location().is_value());
Visit(expr->expression());
ASSERT_EQ(Expression::kValue, expr->expression()->context());
// Push global object (receiver).
__ push(CodeGenerator::GlobalObject());
// Push the arguments ("left-to-right") on the stack.
ZoneList<Expression*>* args = node->arguments();
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
Visit(args->at(i));
ASSERT(args->at(i)->location().is_value());
ASSERT_EQ(Expression::kValue, args->at(i)->context());
// If location is value, it is already on the stack,
// so nothing to do here.
}
// Call the construct call builtin that handles allocation and
// constructor invocation.
SetSourcePosition(node->position());
SetSourcePosition(expr->position());
// Load function, arg_count into edi and eax.
__ Set(eax, Immediate(arg_count));
@ -629,7 +621,7 @@ void FastCodeGenerator::VisitCallNew(CallNew* node) {
__ call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
// Replace function on TOS with result in eax, or pop it.
DropAndMove(node->location(), eax);
DropAndMove(expr->context(), eax);
}
@ -644,19 +636,19 @@ 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_value());
ASSERT_EQ(Expression::kValue, args->at(i)->context());
}
__ CallRuntime(function, arg_count);
Move(expr->location(), eax);
Move(expr->context(), eax);
}
void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
switch (expr->op()) {
case Token::COMMA:
ASSERT(expr->left()->location().is_effect());
ASSERT_EQ(expr->right()->location().type(), expr->location().type());
ASSERT_EQ(Expression::kValue, expr->left()->context());
ASSERT_EQ(expr->context(), expr->right()->context());
Visit(expr->left());
Visit(expr->right());
break;
@ -677,8 +669,8 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
case Token::SHL:
case Token::SHR:
case Token::SAR: {
ASSERT(expr->left()->location().is_value());
ASSERT(expr->right()->location().is_value());
ASSERT_EQ(Expression::kValue, expr->left()->context());
ASSERT_EQ(Expression::kValue, expr->right()->context());
Visit(expr->left());
Visit(expr->right());
@ -686,7 +678,7 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
NO_OVERWRITE,
NO_GENERIC_BINARY_FLAGS);
__ CallStub(&stub);
Move(expr->location(), eax);
Move(expr->context(), eax);
break;
}
@ -711,7 +703,7 @@ void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) {
left_true = &eval_right;
left_false = &done;
}
Location destination = expr->location();
Expression::Context context = expr->context();
Expression* left = expr->left();
Expression* right = expr->right();
@ -723,19 +715,19 @@ void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) {
// need it as the value of the whole expression.
if (left->AsLiteral() != NULL) {
__ mov(eax, left->AsLiteral()->handle());
if (destination.is_value()) __ push(eax);
if (context == Expression::kValue) __ push(eax);
} else {
Visit(left);
ASSERT(left->location().is_value());
switch (destination.type()) {
case Location::kUninitialized:
ASSERT_EQ(Expression::kValue, left->context());
switch (context) {
case Expression::kUninitialized:
UNREACHABLE();
case Location::kEffect:
case Expression::kEffect:
// Pop the left-hand value into eax because we will not need it as the
// final result.
__ pop(eax);
break;
case Location::kValue:
case Expression::kValue:
// Copy the left-hand value into eax because we may need it as the
// final result.
__ mov(eax, Operand(esp, 0));
@ -752,7 +744,7 @@ void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) {
__ j(equal, left_true);
__ cmp(eax, Factory::false_value()); // False is false.
__ j(equal, left_false);
ASSERT(kSmiTag == 0);
ASSERT_EQ(0, kSmiTag);
__ test(eax, Operand(eax)); // The smi zero is false.
__ j(zero, left_false);
__ test(eax, Immediate(kSmiTagMask)); // All other smis are true.
@ -771,12 +763,12 @@ void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) {
__ bind(&eval_right);
// Discard the left-hand value if present on the stack.
if (destination.is_value()) {
if (context == Expression::kValue) {
__ add(Operand(esp), Immediate(kPointerSize));
}
// Save or discard the right-hand value as needed.
Visit(right);
ASSERT_EQ(destination.type(), right->location().type());
ASSERT_EQ(context, right->context());
__ bind(&done);
}

View File

@ -1,62 +0,0 @@
// Copyright 2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef V8_LOCATION_H_
#define V8_LOCATION_H_
#include "utils.h"
namespace v8 {
namespace internal {
class Location BASE_EMBEDDED {
public:
enum Type {
kUninitialized,
kEffect,
kValue
};
static Location Uninitialized() { return Location(kUninitialized); }
static Location Effect() { return Location(kEffect); }
static Location Value() { return Location(kValue); }
bool is_effect() { return type_ == kEffect; }
bool is_value() { return type_ == kValue; }
Type type() { return type_; }
private:
explicit Location(Type type) : type_(type) {}
Type type_;
};
} } // namespace v8::internal
#endif // V8_LOCATION_H_

View File

@ -116,52 +116,41 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) {
}
void FastCodeGenerator::Move(Location destination, Slot* source) {
switch (destination.type()) {
case Location::kUninitialized:
void FastCodeGenerator::Move(Expression::Context context, Slot* source) {
switch (context) {
case Expression::kUninitialized:
UNREACHABLE();
case Location::kEffect:
case Expression::kEffect:
break;
case Location::kValue:
case Expression::kValue:
__ push(Operand(rbp, SlotOffset(source)));
break;
}
}
void FastCodeGenerator::Move(Location destination, Literal* expr) {
switch (destination.type()) {
case Location::kUninitialized:
void FastCodeGenerator::Move(Expression::Context context, Literal* expr) {
switch (context) {
case Expression::kUninitialized:
UNREACHABLE();
case Location::kEffect:
case Expression::kEffect:
break;
case Location::kValue:
case Expression::kValue:
__ Push(expr->handle());
break;
}
}
void FastCodeGenerator::Move(Slot* destination, Location source) {
switch (source.type()) {
case Location::kUninitialized: // Fall through.
case Location::kEffect:
void FastCodeGenerator::DropAndMove(Expression::Context context,
Register source) {
switch (context) {
case Expression::kUninitialized:
UNREACHABLE();
case Location::kValue:
__ pop(Operand(rbp, SlotOffset(destination)));
break;
}
}
void FastCodeGenerator::DropAndMove(Location destination, Register source) {
switch (destination.type()) {
case Location::kUninitialized:
UNREACHABLE();
case Location::kEffect:
case Expression::kEffect:
__ addq(rsp, Immediate(kPointerSize));
break;
case Location::kValue:
case Expression::kValue:
__ movq(Operand(rsp, 0), source);
break;
}
@ -182,12 +171,12 @@ void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
Comment cmnt(masm_, "[ ReturnStatement");
SetStatementPosition(stmt);
Expression* expr = stmt->expression();
// Complete the statement based on the type of the subexpression.
if (expr->AsLiteral() != NULL) {
__ Move(rax, expr->AsLiteral()->handle());
} else {
Visit(expr);
Move(rax, expr->location());
ASSERT_EQ(Expression::kValue, expr->context());
__ pop(rax);
}
if (FLAG_trace) {
@ -226,7 +215,7 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
__ push(rsi);
__ Push(boilerplate);
__ CallRuntime(Runtime::kNewClosure, 2);
Move(expr->location(), rax);
Move(expr->context(), rax);
}
@ -245,10 +234,10 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
// A test rax instruction following the call is used by the IC to
// indicate that the inobject property case was inlined. Ensure there
// is no test rax instruction here.
DropAndMove(expr->location(), rax);
DropAndMove(expr->context(), rax);
} else {
Comment cmnt(masm_, "Stack slot");
Move(expr->location(), rewrite->AsSlot());
Move(expr->context(), rewrite->AsSlot());
}
}
@ -276,7 +265,7 @@ void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
__ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
// Label done:
__ bind(&done);
Move(expr->location(), rax);
Move(expr->context(), rax);
}
@ -329,7 +318,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::COMPUTED:
if (key->handle()->IsSymbol()) {
Visit(value);
ASSERT(value->location().is_value());
ASSERT_EQ(Expression::kValue, value->context());
__ pop(rax);
__ Move(rcx, key->handle());
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
@ -341,9 +330,9 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::PROTOTYPE:
__ push(rax);
Visit(key);
ASSERT(key->location().is_value());
ASSERT_EQ(Expression::kValue, key->context());
Visit(value);
ASSERT(value->location().is_value());
ASSERT_EQ(Expression::kValue, value->context());
__ CallRuntime(Runtime::kSetProperty, 3);
__ movq(rax, Operand(rsp, 0)); // Restore result into rax.
break;
@ -351,25 +340,25 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::GETTER:
__ push(rax);
Visit(key);
ASSERT(key->location().is_value());
ASSERT_EQ(Expression::kValue, key->context());
__ Push(property->kind() == ObjectLiteral::Property::SETTER ?
Smi::FromInt(1) :
Smi::FromInt(0));
Visit(value);
ASSERT(value->location().is_value());
ASSERT_EQ(Expression::kValue, value->context());
__ CallRuntime(Runtime::kDefineAccessor, 4);
__ movq(rax, Operand(rsp, 0)); // Restore result into rax.
break;
default: UNREACHABLE();
}
}
switch (expr->location().type()) {
case Location::kUninitialized:
switch (expr->context()) {
case Expression::kUninitialized:
UNREACHABLE();
case Location::kEffect:
case Expression::kEffect:
if (result_saved) __ addq(rsp, Immediate(kPointerSize));
break;
case Location::kValue:
case Expression::kValue:
if (!result_saved) __ push(rax);
break;
}
@ -424,7 +413,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
result_saved = true;
}
Visit(subexpr);
ASSERT(subexpr->location().is_value());
ASSERT_EQ(Expression::kValue, subexpr->context());
// Store the subexpression value in the array's elements.
__ pop(rax); // Subexpression value.
@ -437,13 +426,13 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
__ RecordWrite(rbx, offset, rax, rcx);
}
switch (expr->location().type()) {
case Location::kUninitialized:
switch (expr->context()) {
case Expression::kUninitialized:
UNREACHABLE();
case Location::kEffect:
case Expression::kEffect:
if (result_saved) __ addq(rsp, Immediate(kPointerSize));
break;
case Location::kValue:
case Expression::kValue:
if (!result_saved) __ push(rax);
break;
}
@ -473,7 +462,8 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
!String::cast(*(literal_key->handle()))->AsArrayIndex(&dummy)) {
// NAMED property assignment
Visit(rhs);
Move(rax, rhs->location());
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);
@ -482,7 +472,8 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
// KEYED property assignment
Visit(prop->key());
Visit(rhs);
Move(rax, rhs->location());
ASSERT_EQ(Expression::kValue, rhs->context());
__ pop(rax);
Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
__ call(ic, RelocInfo::CODE_TARGET);
__ nop();
@ -490,7 +481,7 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
__ addq(rsp, Immediate(kPointerSize));
}
// Overwrite the receiver on the stack with the result if needed.
DropAndMove(expr->location(), rax);
DropAndMove(expr->context(), rax);
} else 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
@ -500,7 +491,7 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
if (rhs->AsLiteral() != NULL) {
__ Move(rax, rhs->AsLiteral()->handle());
} else {
ASSERT(rhs->location().is_value());
ASSERT_EQ(Expression::kValue, rhs->context());
Visit(rhs);
__ pop(rax);
}
@ -509,7 +500,7 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
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->location(), rax);
DropAndMove(expr->context(), rax);
} else {
// Local or parameter assignment.
@ -519,18 +510,18 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
// discarded result. Always perform the assignment.
__ Move(kScratchRegister, rhs->AsLiteral()->handle());
__ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister);
Move(expr->location(), kScratchRegister);
Move(expr->context(), kScratchRegister);
} else {
ASSERT(rhs->location().is_value());
ASSERT_EQ(Expression::kValue, rhs->context());
Visit(rhs);
switch (expr->location().type()) {
case Location::kUninitialized:
switch (expr->context()) {
case Expression::kUninitialized:
UNREACHABLE();
case Location::kEffect:
case Expression::kEffect:
// Case 'var = temp'. Discard right-hand-side temporary.
Move(var->slot(), rhs->location());
__ pop(Operand(rbp, SlotOffset(var->slot())));
break;
case Location::kValue:
case Expression::kValue:
// Case 'temp1 <- (var = temp0)'. Preserve right-hand-side
// temporary on the stack.
__ movq(kScratchRegister, Operand(rsp, 0));
@ -574,7 +565,7 @@ void FastCodeGenerator::VisitProperty(Property* expr) {
// Drop key left on the stack by IC.
__ addq(rsp, Immediate(kPointerSize));
}
DropAndMove(expr->location(), rax);
DropAndMove(expr->context(), rax);
}
@ -591,7 +582,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_value());
ASSERT_EQ(Expression::kValue, args->at(i)->context());
}
// Record source position for debugger
SetSourcePosition(expr->position());
@ -602,36 +593,36 @@ void FastCodeGenerator::VisitCall(Call* expr) {
// Restore context register.
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
// Discard the function left on TOS.
DropAndMove(expr->location(), rax);
DropAndMove(expr->context(), rax);
}
void FastCodeGenerator::VisitCallNew(CallNew* node) {
void FastCodeGenerator::VisitCallNew(CallNew* expr) {
Comment cmnt(masm_, "[ CallNew");
// According to ECMA-262, section 11.2.2, page 44, the function
// expression in new calls must be evaluated before the
// arguments.
// Push function on the stack.
Visit(node->expression());
ASSERT(node->expression()->location().is_value());
Visit(expr->expression());
ASSERT_EQ(Expression::kValue, expr->expression()->context());
// If location is value, already on the stack,
// Push global object (receiver).
__ push(CodeGenerator::GlobalObject());
// Push the arguments ("left-to-right") on the stack.
ZoneList<Expression*>* args = node->arguments();
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
Visit(args->at(i));
ASSERT(args->at(i)->location().is_value());
ASSERT_EQ(Expression::kValue, args->at(i)->context());
// If location is value, it is already on the stack,
// so nothing to do here.
}
// Call the construct call builtin that handles allocation and
// constructor invocation.
SetSourcePosition(node->position());
SetSourcePosition(expr->position());
// Load function, arg_count into rdi and rax.
__ Set(rax, arg_count);
@ -642,7 +633,7 @@ void FastCodeGenerator::VisitCallNew(CallNew* node) {
__ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
// Replace function on TOS with result in rax, or pop it.
DropAndMove(node->location(), rax);
DropAndMove(expr->context(), rax);
}
@ -657,19 +648,19 @@ 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_value());
ASSERT_EQ(Expression::kValue, args->at(i)->context());
}
__ CallRuntime(function, arg_count);
Move(expr->location(), rax);
Move(expr->context(), rax);
}
void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
switch (expr->op()) {
case Token::COMMA:
ASSERT(expr->left()->location().is_effect());
ASSERT_EQ(expr->right()->location().type(), expr->location().type());
ASSERT_EQ(Expression::kEffect, expr->left()->context());
ASSERT_EQ(expr->context(), expr->right()->context());
Visit(expr->left());
Visit(expr->right());
break;
@ -690,8 +681,8 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
case Token::SHL:
case Token::SHR:
case Token::SAR: {
ASSERT(expr->left()->location().is_value());
ASSERT(expr->right()->location().is_value());
ASSERT_EQ(Expression::kValue, expr->left()->context());
ASSERT_EQ(Expression::kValue, expr->right()->context());
Visit(expr->left());
Visit(expr->right());
@ -699,7 +690,7 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
NO_OVERWRITE,
NO_GENERIC_BINARY_FLAGS);
__ CallStub(&stub);
Move(expr->location(), rax);
Move(expr->context(), rax);
break;
}
@ -726,7 +717,7 @@ void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) {
left_true = &eval_right;
left_false = &done;
}
Location destination = expr->location();
Expression::Context context = expr->context();
Expression* left = expr->left();
Expression* right = expr->right();
@ -738,19 +729,19 @@ void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) {
// need it as the value of the whole expression.
if (left->AsLiteral() != NULL) {
__ Move(rax, left->AsLiteral()->handle());
if (destination.is_value()) __ push(rax);
if (context == Expression::kValue) __ push(rax);
} else {
Visit(left);
ASSERT(left->location().is_value());
switch (destination.type()) {
case Location::kUninitialized:
ASSERT_EQ(Expression::kValue, left->context());
switch (context) {
case Expression::kUninitialized:
UNREACHABLE();
case Location::kEffect:
case Expression::kEffect:
// Pop the left-hand value into rax because we will not need it as the
// final result.
__ pop(rax);
break;
case Location::kValue:
case Expression::kValue:
// Copy the left-hand value into rax because we may need it as the
// final result.
__ movq(rax, Operand(rsp, 0));
@ -787,12 +778,12 @@ void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) {
__ bind(&eval_right);
// Discard the left-hand value if present on the stack.
if (destination.is_value()) {
if (context == Expression::kValue) {
__ addq(rsp, Immediate(kPointerSize));
}
// Save or discard the right-hand value as needed.
Visit(right);
ASSERT_EQ(destination.type(), right->location().type());
ASSERT_EQ(context, right->context());
__ bind(&done);
}

View File

@ -293,7 +293,6 @@
'../../src/jsregexp.h',
'../../src/list-inl.h',
'../../src/list.h',
'../../src/location.h',
'../../src/log-inl.h',
'../../src/log-utils.cc',
'../../src/log-utils.h',

View File

@ -556,10 +556,6 @@
RelativePath="..\..\src\list.h"
>
</File>
<File
RelativePath="..\..\src\location.h"
>
</File>
<File
RelativePath="..\..\src\log.cc"
>

View File

@ -560,10 +560,6 @@
RelativePath="..\..\src\list.h"
>
</File>
<File
RelativePath="..\..\src\location.h"
>
</File>
<File
RelativePath="..\..\src\log.cc"
>