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:
parent
143b4b87b4
commit
d92fa03eca
@ -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);
|
||||
}
|
||||
|
15
src/ast.h
15
src/ast.h
@ -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_;
|
||||
};
|
||||
|
||||
|
||||
|
103
src/compiler.cc
103
src/compiler.cc
@ -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_);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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_
|
@ -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);
|
||||
}
|
||||
|
@ -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',
|
||||
|
@ -556,10 +556,6 @@
|
||||
RelativePath="..\..\src\list.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\location.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\log.cc"
|
||||
>
|
||||
|
@ -560,10 +560,6 @@
|
||||
RelativePath="..\..\src\list.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\location.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\log.cc"
|
||||
>
|
||||
|
Loading…
Reference in New Issue
Block a user