First step of refactoring expression contexts in the toplevel code

generator.

Contexts are no longer stored in the AST but in the code generator's
state.  This means that the running the code generator selector is not
required to use the toplevel code generator (for instance, if we
already know that we can and should use it).

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3645 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 712d108e
......@@ -662,13 +662,13 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
__ mov(r0, Operand(boilerplate));
__ stm(db_w, sp, cp.bit() | r0.bit());
__ CallRuntime(Runtime::kNewClosure, 2);
Apply(expr->context(), r0);
Apply(context_, r0);
}
void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
Comment cmnt(masm_, "[ VariableProxy");
EmitVariableLoad(expr->var(), expr->context());
EmitVariableLoad(expr->var(), context_);
}
......@@ -768,7 +768,7 @@ void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
__ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit());
__ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
__ bind(&done);
Apply(expr->context(), r0);
Apply(context_, r0);
}
......@@ -840,9 +840,9 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
}
if (result_saved) {
ApplyTOS(expr->context());
ApplyTOS(context_);
} else {
Apply(expr->context(), r0);
Apply(context_, r0);
}
}
......@@ -893,9 +893,9 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
}
if (result_saved) {
ApplyTOS(expr->context());
ApplyTOS(context_);
} else {
Apply(expr->context(), r0);
Apply(context_, r0);
}
}
......@@ -1007,7 +1007,7 @@ void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
__ pop(r0);
}
DropAndApply(1, expr->context(), r0);
DropAndApply(1, context_, r0);
}
......@@ -1042,7 +1042,7 @@ void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
}
// Receiver and key are still on stack.
DropAndApply(2, expr->context(), r0);
DropAndApply(2, context_, r0);
}
......@@ -1056,12 +1056,12 @@ void FastCodeGenerator::VisitProperty(Property* expr) {
if (key->IsPropertyName()) {
EmitNamedPropertyLoad(expr);
// Drop receiver left on the stack by IC.
DropAndApply(1, expr->context(), r0);
DropAndApply(1, context_, r0);
} else {
VisitForValue(expr->key(), kStack);
EmitKeyedPropertyLoad(expr);
// Drop key and receiver left on the stack by IC.
DropAndApply(2, expr->context(), r0);
DropAndApply(2, context_, r0);
}
}
......@@ -1083,7 +1083,7 @@ void FastCodeGenerator::EmitCallWithIC(Call* expr,
// Restore context register.
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
// Discard the function left on TOS.
DropAndApply(1, expr->context(), r0);
DropAndApply(1, context_, r0);
}
......@@ -1101,7 +1101,7 @@ void FastCodeGenerator::EmitCallWithStub(Call* expr) {
// Restore context register.
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
// Discard the function left on TOS.
DropAndApply(1, expr->context(), r0);
DropAndApply(1, context_, r0);
}
......@@ -1207,7 +1207,7 @@ void FastCodeGenerator::VisitCallNew(CallNew* expr) {
__ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
// Replace function on TOS with result in r0, or pop it.
DropAndApply(1, expr->context(), r0);
DropAndApply(1, context_, r0);
}
......@@ -1237,11 +1237,11 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
// Restore context register.
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
// Discard the function left on TOS.
DropAndApply(1, expr->context(), r0);
DropAndApply(1, context_, r0);
} else {
// Call the C runtime function.
__ CallRuntime(expr->function(), arg_count);
Apply(expr->context(), r0);
Apply(context_, r0);
}
}
......@@ -1250,9 +1250,8 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
switch (expr->op()) {
case Token::VOID: {
Comment cmnt(masm_, "[ UnaryOperation (VOID)");
ASSERT_EQ(Expression::kEffect, expr->expression()->context());
Visit(expr->expression());
switch (expr->context()) {
VisitForEffect(expr->expression());
switch (context_) {
case Expression::kUninitialized:
UNREACHABLE();
break;
......@@ -1289,14 +1288,12 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
case Token::NOT: {
Comment cmnt(masm_, "[ UnaryOperation (NOT)");
ASSERT_EQ(Expression::kTest, expr->expression()->context());
Label materialize_true, materialize_false, done;
// Initially assume a pure test context. Notice that the labels are
// swapped.
Label* if_true = false_label_;
Label* if_false = true_label_;
switch (expr->context()) {
switch (context_) {
case Expression::kUninitialized:
UNREACHABLE();
break;
......@@ -1318,14 +1315,12 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
break;
}
VisitForControl(expr->expression(), if_true, if_false);
Apply(expr->context(), if_false, if_true); // Labels swapped.
Apply(context_, if_false, if_true); // Labels swapped.
break;
}
case Token::TYPEOF: {
Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
ASSERT_EQ(Expression::kValue, expr->expression()->context());
VariableProxy* proxy = expr->expression()->AsVariableProxy();
if (proxy != NULL &&
!proxy->var()->is_this() &&
......@@ -1352,7 +1347,7 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
}
__ CallRuntime(Runtime::kTypeof, 1);
Apply(expr->context(), r0);
Apply(context_, r0);
break;
}
......@@ -1373,9 +1368,8 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
// In case of a property we use the uninitialized expression context
// of the key to detect a named property.
if (prop != NULL) {
assign_type = (prop->key()->context() == Expression::kUninitialized)
? NAMED_PROPERTY
: KEYED_PROPERTY;
assign_type =
(prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
}
// Evaluate expression and get value.
......@@ -1388,8 +1382,7 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
location_ = saved_location;
} else {
// Reserve space for result of postfix operation.
if (expr->is_postfix() && expr->context() != Expression::kEffect) {
ASSERT(expr->context() != Expression::kUninitialized);
if (expr->is_postfix() && context_ != Expression::kEffect) {
__ mov(ip, Operand(Smi::FromInt(0)));
__ push(ip);
}
......@@ -1408,7 +1401,7 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
// Save result for postfix expressions.
if (expr->is_postfix()) {
switch (expr->context()) {
switch (context_) {
case Expression::kUninitialized:
UNREACHABLE();
case Expression::kEffect:
......@@ -1451,12 +1444,12 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
Expression::kEffect);
// For all contexts except kEffect: We have the result on
// top of the stack.
if (expr->context() != Expression::kEffect) {
ApplyTOS(expr->context());
if (context_ != Expression::kEffect) {
ApplyTOS(context_);
}
} else {
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
expr->context());
context_);
}
break;
case NAMED_PROPERTY: {
......@@ -1465,11 +1458,11 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
__ Call(ic, RelocInfo::CODE_TARGET);
if (expr->is_postfix()) {
__ Drop(1); // Result is on the stack under the receiver.
if (expr->context() != Expression::kEffect) {
ApplyTOS(expr->context());
if (context_ != Expression::kEffect) {
ApplyTOS(context_);
}
} else {
DropAndApply(1, expr->context(), r0);
DropAndApply(1, context_, r0);
}
break;
}
......@@ -1478,11 +1471,11 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
__ Call(ic, RelocInfo::CODE_TARGET);
if (expr->is_postfix()) {
__ Drop(2); // Result is on the stack under the key and the receiver.
if (expr->context() != Expression::kEffect) {
ApplyTOS(expr->context());
if (context_ != Expression::kEffect) {
ApplyTOS(context_);
}
} else {
DropAndApply(2, expr->context(), r0);
DropAndApply(2, context_, r0);
}
break;
}
......@@ -1494,9 +1487,7 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
Comment cmnt(masm_, "[ BinaryOperation");
switch (expr->op()) {
case Token::COMMA:
ASSERT_EQ(Expression::kEffect, expr->left()->context());
ASSERT_EQ(expr->context(), expr->right()->context());
Visit(expr->left());
VisitForEffect(expr->left());
Visit(expr->right());
break;
......@@ -1518,7 +1509,7 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
case Token::SAR:
VisitForValue(expr->left(), kStack);
VisitForValue(expr->right(), kAccumulator);
EmitBinaryOp(expr->op(), expr->context());
EmitBinaryOp(expr->op(), context_);
break;
default:
......@@ -1536,7 +1527,7 @@ void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
// Initially assume we are in a test context.
Label* if_true = true_label_;
Label* if_false = false_label_;
switch (expr->context()) {
switch (context_) {
case Expression::kUninitialized:
UNREACHABLE();
break;
......@@ -1638,13 +1629,13 @@ void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
// Convert the result of the comparison into one expected for this
// expression's context.
Apply(expr->context(), if_true, if_false);
Apply(context_, if_true, if_false);
}
void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) {
__ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
Apply(expr->context(), r0);
Apply(context_, r0);
}
......
......@@ -180,8 +180,6 @@ class Expression: public AstNode {
kTestValue
};
Expression() : context_(kUninitialized) {}
virtual Expression* AsExpression() { return this; }
virtual bool IsValidJSON() { return false; }
......@@ -200,12 +198,8 @@ class Expression: public AstNode {
// Static type information for this expression.
StaticType* type() { return &type_; }
Context context() { return context_; }
void set_context(Context context) { context_ = context; }
private:
StaticType type_;
Context context_;
};
......
......@@ -46,25 +46,11 @@ class CodeGenSelector: public AstVisitor {
public:
enum CodeGenTag { NORMAL, FAST };
CodeGenSelector()
: has_supported_syntax_(true),
context_(Expression::kUninitialized) {
}
CodeGenSelector() : has_supported_syntax_(true) {}
CodeGenTag Select(FunctionLiteral* fun);
private:
// Visit an expression in a given expression context.
void ProcessExpression(Expression* expr, Expression::Context context) {
ASSERT(expr->context() == Expression::kUninitialized ||
expr->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);
......@@ -75,9 +61,6 @@ class CodeGenSelector: public AstVisitor {
bool has_supported_syntax_;
// The desired expression context of the currently visited expression.
Expression::Context context_;
DISALLOW_COPY_AND_ASSIGN(CodeGenSelector);
};
......@@ -649,12 +632,12 @@ void CodeGenSelector::VisitStatements(ZoneList<Statement*>* stmts) {
void CodeGenSelector::VisitDeclaration(Declaration* decl) {
Property* prop = decl->proxy()->AsProperty();
if (prop != NULL) {
ProcessExpression(prop->obj(), Expression::kValue);
ProcessExpression(prop->key(), Expression::kValue);
Visit(prop->obj());
Visit(prop->key());
}
if (decl->fun() != NULL) {
ProcessExpression(decl->fun(), Expression::kValue);
Visit(decl->fun());
}
}
......@@ -665,17 +648,15 @@ void CodeGenSelector::VisitBlock(Block* stmt) {
void CodeGenSelector::VisitExpressionStatement(ExpressionStatement* stmt) {
ProcessExpression(stmt->expression(), Expression::kEffect);
Visit(stmt->expression());
}
void CodeGenSelector::VisitEmptyStatement(EmptyStatement* stmt) {
// EmptyStatement is supported.
}
void CodeGenSelector::VisitEmptyStatement(EmptyStatement* stmt) {}
void CodeGenSelector::VisitIfStatement(IfStatement* stmt) {
ProcessExpression(stmt->condition(), Expression::kTest);
Visit(stmt->condition());
CHECK_BAILOUT;
Visit(stmt->then_statement());
CHECK_BAILOUT;
......@@ -683,27 +664,23 @@ void CodeGenSelector::VisitIfStatement(IfStatement* stmt) {
}
void CodeGenSelector::VisitContinueStatement(ContinueStatement* stmt) {
}
void CodeGenSelector::VisitContinueStatement(ContinueStatement* stmt) {}
void CodeGenSelector::VisitBreakStatement(BreakStatement* stmt) {
}
void CodeGenSelector::VisitBreakStatement(BreakStatement* stmt) {}
void CodeGenSelector::VisitReturnStatement(ReturnStatement* stmt) {
ProcessExpression(stmt->expression(), Expression::kValue);
Visit(stmt->expression());
}
void CodeGenSelector::VisitWithEnterStatement(WithEnterStatement* stmt) {
ProcessExpression(stmt->expression(), Expression::kValue);
Visit(stmt->expression());
}
void CodeGenSelector::VisitWithExitStatement(WithExitStatement* stmt) {
// Supported.
}
void CodeGenSelector::VisitWithExitStatement(WithExitStatement* stmt) {}
void CodeGenSelector::VisitSwitchStatement(SwitchStatement* stmt) {
......@@ -712,18 +689,14 @@ void CodeGenSelector::VisitSwitchStatement(SwitchStatement* stmt) {
void CodeGenSelector::VisitDoWhileStatement(DoWhileStatement* stmt) {
// We do not handle loops with breaks or continue statements in their
// body. We will bailout when we hit those statements in the body.
ProcessExpression(stmt->cond(), Expression::kTest);
Visit(stmt->cond());
CHECK_BAILOUT;
Visit(stmt->body());
}
void CodeGenSelector::VisitWhileStatement(WhileStatement* stmt) {
// We do not handle loops with breaks or continue statements in their
// body. We will bailout when we hit those statements in the body.
ProcessExpression(stmt->cond(), Expression::kTest);
Visit(stmt->cond());
CHECK_BAILOUT;
Visit(stmt->body());
}
......@@ -753,14 +726,10 @@ void CodeGenSelector::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
}
void CodeGenSelector::VisitDebuggerStatement(DebuggerStatement* stmt) {
// Debugger statement is supported.
}
void CodeGenSelector::VisitDebuggerStatement(DebuggerStatement* stmt) {}
void CodeGenSelector::VisitFunctionLiteral(FunctionLiteral* expr) {
// Function literal is supported.
}
void CodeGenSelector::VisitFunctionLiteral(FunctionLiteral* expr) {}
void CodeGenSelector::VisitFunctionBoilerplateLiteral(
......@@ -770,11 +739,11 @@ void CodeGenSelector::VisitFunctionBoilerplateLiteral(
void CodeGenSelector::VisitConditional(Conditional* expr) {
ProcessExpression(expr->condition(), Expression::kTest);
Visit(expr->condition());
CHECK_BAILOUT;
ProcessExpression(expr->then_expression(), context_);
Visit(expr->then_expression());
CHECK_BAILOUT;
ProcessExpression(expr->else_expression(), context_);
Visit(expr->else_expression());
}
......@@ -784,11 +753,9 @@ void CodeGenSelector::VisitSlot(Slot* expr) {
void CodeGenSelector::VisitVariableProxy(VariableProxy* expr) {
Expression* rewrite = expr->var()->rewrite();
// A rewrite of NULL indicates a global variable.
if (rewrite != NULL) {
// Non-global.
Slot* slot = rewrite->AsSlot();
Variable* var = expr->var();
if (!var->is_global()) {
Slot* slot = var->slot();
if (slot != NULL) {
Slot::Type type = slot->type();
// When LOOKUP slots are enabled, some currently dead code
......@@ -797,10 +764,10 @@ void CodeGenSelector::VisitVariableProxy(VariableProxy* expr) {
BAILOUT("Lookup slot");
}
} else {
// If not global or a slot, it is a parameter rewritten to an explicit
// property reference on the (shadow) arguments object.
#ifdef DEBUG
// Only remaining possibility is a property where the object is
// a slotted variable and the key is a smi.
Property* property = rewrite->AsProperty();
Property* property = var->AsProperty();
ASSERT_NOT_NULL(property);
Variable* object = property->obj()->AsVariableProxy()->AsVariable();
ASSERT_NOT_NULL(object);
......@@ -813,14 +780,10 @@ void CodeGenSelector::VisitVariableProxy(VariableProxy* expr) {
}
void CodeGenSelector::VisitLiteral(Literal* expr) {
/* Nothing to do. */
}
void CodeGenSelector::VisitLiteral(Literal* expr) {}
void CodeGenSelector::VisitRegExpLiteral(RegExpLiteral* expr) {
/* Nothing to do. */
}
void CodeGenSelector::VisitRegExpLiteral(RegExpLiteral* expr) {}
void CodeGenSelector::VisitObjectLiteral(ObjectLiteral* expr) {
......@@ -829,31 +792,9 @@ void CodeGenSelector::VisitObjectLiteral(ObjectLiteral* expr) {
for (int i = 0, len = properties->length(); i < len; i++) {
ObjectLiteral::Property* property = properties->at(i);
if (property->IsCompileTimeValue()) continue;
switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT:
UNREACHABLE();
// For (non-compile-time) materialized literals and computed
// properties with symbolic keys we will use an IC and therefore not
// generate code for the key.
case ObjectLiteral::Property::COMPUTED: // Fall through.
case ObjectLiteral::Property::MATERIALIZED_LITERAL:
if (property->key()->handle()->IsSymbol()) {
break;
}
// Fall through.
// In all other cases we need the key's value on the stack
// for a runtime call. (Relies on TEMP meaning STACK.)
case ObjectLiteral::Property::GETTER: // Fall through.
case ObjectLiteral::Property::SETTER: // Fall through.
case ObjectLiteral::Property::PROTOTYPE:
ProcessExpression(property->key(), Expression::kValue);
CHECK_BAILOUT;
break;
}
ProcessExpression(property->value(), Expression::kValue);
Visit(property->key());
CHECK_BAILOUT;
Visit(property->value());
CHECK_BAILOUT;
}
}
......@@ -865,16 +806,16 @@ void CodeGenSelector::VisitArrayLiteral(ArrayLiteral* expr) {
Expression* subexpr = subexprs->at(i);
if (subexpr->AsLiteral() != NULL) continue;
if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
ProcessExpression(subexpr, Expression::kValue);
Visit(subexpr);
CHECK_BAILOUT;
}
}
void CodeGenSelector::VisitCatchExtensionObject(CatchExtensionObject* expr) {
ProcessExpression(expr->key(), Expression::kValue);
Visit(expr->key());
CHECK_BAILOUT;
ProcessExpression(expr->value(), Expression::kValue);
Visit(expr->value());
}
......@@ -900,33 +841,28 @@ void CodeGenSelector::VisitAssignment(Assignment* expr) {
}
}
} else if (prop != NULL) {
ProcessExpression(prop->obj(), Expression::kValue);
Visit(prop->obj());
CHECK_BAILOUT;
Visit(prop->key());
CHECK_BAILOUT;
// We will only visit the key during code generation for keyed property
// stores. Leave its expression context uninitialized for named
// property stores.
if (!prop->key()->IsPropertyName()) {
ProcessExpression(prop->key(), Expression::kValue);
CHECK_BAILOUT;
}
} else {
// This is a throw reference error.
BAILOUT("non-variable/non-property assignment");
}
ProcessExpression(expr->value(), Expression::kValue);
Visit(expr->value());
}
void CodeGenSelector::VisitThrow(Throw* expr) {
ProcessExpression(expr->exception(), Expression::kValue);
Visit(expr->exception());
}
void CodeGenSelector::VisitProperty(Property* expr) {
ProcessExpression(expr->obj(), Expression::kValue);
Visit(expr->obj());
CHECK_BAILOUT;
ProcessExpression(expr->key(), Expression::kValue);
Visit(expr->key());
}
......@@ -946,34 +882,29 @@ void CodeGenSelector::VisitCall(Call* expr) {
} else if (fun->AsProperty() != NULL) {
Property* prop = fun->AsProperty();
Literal* literal_key = prop->key()->AsLiteral();
if (literal_key != NULL && literal_key->handle()->IsSymbol()) {
ProcessExpression(prop->obj(), Expression::kValue);
CHECK_BAILOUT;
} else {
ProcessExpression(prop->obj(), Expression::kValue);
CHECK_BAILOUT;
ProcessExpression(prop->key(), Expression::kValue);
CHECK_BAILOUT;
}
Visit(prop->obj());
CHECK_BAILOUT;
Visit(prop->key());
CHECK_BAILOUT;
} else {
// Otherwise the call is supported if the function expression is.
ProcessExpression(fun, Expression::kValue);
Visit(fun);
}
// Check all arguments to the call.
for (int i = 0; i < args->length(); i++) {
ProcessExpression(args->at(i), Expression::kValue);
Visit(args->at(i));
CHECK_BAILOUT;
}
}
void CodeGenSelector::VisitCallNew(CallNew* expr) {
ProcessExpression(expr->expression(), Expression::kValue);
Visit(expr->expression());
CHECK_BAILOUT;
ZoneList<Expression*>* args = expr->arguments();
// Check all arguments to the call
for (int i = 0; i < args->length(); i++) {
ProcessExpression(args->at(i), Expression::kValue);
Visit(args->at(i));
CHECK_BAILOUT;
}
}
......@@ -987,7 +918,7 @@ 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++) {
ProcessExpression(expr->arguments()->at(i), Expression::kValue);
Visit(expr->arguments()->at(i));
CHECK_BAILOUT;
}
}
......@@ -996,16 +927,16 @@ void CodeGenSelector::VisitCallRuntime(CallRuntime* expr) {
void CodeGenSelector::VisitUnaryOperation(UnaryOperation* expr) {
switch (expr->op()) {
case Token::VOID:
ProcessExpression(expr->expression(), Expression::kEffect);
break;
case Token::NOT:
ProcessExpression(expr->expression(), Expression::kTest);
break;
case Token::TYPEOF:
ProcessExpression(expr->expression(), Expression::kValue);
Visit(expr->expression());
break;
case BIT_NOT:
BAILOUT("UnaryOperataion: BIT_NOT");
case DELETE:
BAILOUT("UnaryOperataion: DELETE");
default:
BAILOUT("UnaryOperation");
UNREACHABLE();
}
}
......@@ -1024,15 +955,10 @@ void CodeGenSelector::VisitCountOperation(CountOperation* expr) {
}
}
} else if (prop != NULL) {
ProcessExpression(prop->obj(), Expression::kValue);
Visit(prop->obj());
CHECK_BAILOUT;
Visit(prop->key());
CHECK_BAILOUT;
// We will only visit the key during code generation for keyed property
// stores. Leave its expression context uninitialized for named
// property stores.
if (!prop->key()->IsPropertyName()) {
ProcessExpression(prop->key(), Expression::kValue);
CHECK_BAILOUT;
}
} else {
// This is a throw reference error.
BAILOUT("CountOperation non-variable/non-property expression");
......@@ -1041,89 +967,20 @@ void CodeGenSelector::VisitCountOperation(CountOperation* expr) {
void CodeGenSelector::VisitBinaryOperation(BinaryOperation* expr) {
switch (expr->op()) {
case Token::COMMA:
ProcessExpression(expr->left(), Expression::kEffect);
CHECK_BAILOUT;
ProcessExpression(expr->right(), context_);
break;
case Token::OR:
switch (context_) {
case Expression::kUninitialized:
UNREACHABLE();
case Expression::kEffect: // Fall through.
case Expression::kTest: // Fall through.
case Expression::kTestValue:
// The left subexpression's value is not needed, it is in a pure
// test context.
ProcessExpression(expr->left(), Expression::kTest);
break;
case Expression::kValue: // Fall through.
case Expression::kValueTest:
// The left subexpression's value is needed, it is in a hybrid
// value/test context.
ProcessExpression(expr->left(), Expression::kValueTest);
break;
}
CHECK_BAILOUT;
ProcessExpression(expr->right(), context_);
break;
case Token::AND:
switch (context_) {
case Expression::kUninitialized:
UNREACHABLE();
case Expression::kEffect: // Fall through.
case Expression::kTest: // Fall through.
case Expression::kValueTest:
// The left subexpression's value is not needed, it is in a pure
// test context.
ProcessExpression(expr->left(), Expression::kTest);
break;
case Expression::kValue: // Fall through.
case Expression::kTestValue:
// The left subexpression's value is needed, it is in a hybrid
// test/value context.
ProcessExpression(expr->left(), Expression::kTestValue);
break;
}
CHECK_BAILOUT;
ProcessExpression(expr->right(), context_);
break;
case Token::ADD:
case Token::SUB:
case Token::DIV:
case Token::MOD:
case Token::MUL:
case Token::BIT_OR:
case Token::BIT_AND:
case Token::BIT_XOR:
case Token::SHL:
case Token::SHR:
case Token::SAR:
ProcessExpression(expr->left(), Expression::kValue);
CHECK_BAILOUT;
ProcessExpression(expr->right(), Expression::kValue);
break;
default:
BAILOUT("Unsupported binary operation");
}
Visit(expr->left());
CHECK_BAILOUT;
Visit(expr->right());
}
void CodeGenSelector::VisitCompareOperation(CompareOperation* expr) {
ProcessExpression(expr->left(), Expression::kValue);
Visit(expr->left());
CHECK_BAILOUT;
ProcessExpression(expr->right(), Expression::kValue);
Visit(expr->right());
}
void CodeGenSelector::VisitThisFunction(ThisFunction* expr) {
// ThisFunction is supported.
}
void CodeGenSelector::VisitThisFunction(ThisFunction* expr) {}
#undef BAILOUT
#undef CHECK_BAILOUT
......
......@@ -165,68 +165,65 @@ void FastCodeGenerator::SetSourcePosition(int pos) {
void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) {
#ifdef DEBUG
Expression::Context expected = Expression::kUninitialized;
switch (expr->context()) {
case Expression::kUninitialized:
UNREACHABLE();
case Expression::kEffect:
case Expression::kTest:
// The value of the left subexpression is not needed.
expected = Expression::kTest;
break;
case Expression::kValue:
// The value of the left subexpression is needed and its specific
// context depends on the operator.
expected = (expr->op() == Token::OR)
? Expression::kValueTest
: Expression::kTestValue;
break;
case Expression::kValueTest:
// The value of the left subexpression is needed for OR.
expected = (expr->op() == Token::OR)
? Expression::kValueTest
: Expression::kTest;
break;
case Expression::kTestValue:
// The value of the left subexpression is needed for AND.
expected = (expr->op() == Token::OR)
? Expression::kTest
: Expression::kTestValue;
break;
}
ASSERT_EQ(expected, expr->left()->context());
ASSERT_EQ(expr->context(), expr->right()->context());
#endif
Label eval_right, done;
// Set up the appropriate context for the left subexpression based
// on the operation and our own context. Initially assume we can
// inherit both true and false labels from our context.
Label* if_true = true_label_;
Label* if_false = false_label_;
if (expr->op() == Token::OR) {
// If we are not in some kind of a test context, we did not inherit a
// true label from our context. Use the end of the expression.
if (expr->context() == Expression::kEffect ||
expr->context() == Expression::kValue) {
if_true = &done;
switch (context_) {
case Expression::kUninitialized:
UNREACHABLE();
case Expression::kEffect:
VisitForControl(expr->left(), &done, &eval_right);
break;
case Expression::kValue:
VisitForValueControl(expr->left(),
location_,
&done,
&eval_right);
break;
case Expression::kTest:
VisitForControl(expr->left(), true_label_, &eval_right);
break;
case Expression::kValueTest:
VisitForValueControl(expr->left(),
location_,
true_label_,
&eval_right);
break;
case Expression::kTestValue:
VisitForControl(expr->left(), true_label_, &eval_right);
break;
}
// The false label is the label of the right subexpression.
if_false = &eval_right;
} else {
ASSERT_EQ(Token::AND, expr->op());
// The true label is the label of the right subexpression.
if_true = &eval_right;
// If we are not in some kind of a test context, we did not inherit a
// false label from our context. Use the end of the expression.
if (expr->context() == Expression::kEffect ||
expr->context() == Expression::kValue) {
if_false = &done;
switch (context_) {
case Expression::kUninitialized:
UNREACHABLE();
case Expression::kEffect:
VisitForControl(expr->left(), &eval_right, &done);
break;
case Expression::kValue:
VisitForControlValue(expr->left(),
location_,
&eval_right,
&done);
break;
case Expression::kTest:
VisitForControl(expr->left(), &eval_right, false_label_);
break;
case Expression::kValueTest:
VisitForControl(expr->left(), &eval_right, false_label_);
break;
case Expression::kTestValue:
VisitForControlValue(expr->left(),
location_,
&eval_right,
false_label_);
break;
}
}
VisitForControl(expr->left(), if_true, if_false);
__ bind(&eval_right);
Visit(expr->right());
......@@ -247,7 +244,7 @@ void FastCodeGenerator::VisitBlock(Block* stmt) {
void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
Comment cmnt(masm_, "[ ExpressionStatement");
SetStatementPosition(stmt);
Visit(stmt->expression());
VisitForEffect(stmt->expression());
}
......@@ -446,7 +443,6 @@ void FastCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
// that scope again afterwards.
Label try_handler_setup, catch_entry, done;
__ Call(&try_handler_setup);
// Try handler code, exception in result register.
......@@ -558,27 +554,20 @@ void FastCodeGenerator::VisitFunctionBoilerplateLiteral(
void FastCodeGenerator::VisitConditional(Conditional* expr) {
Comment cmnt(masm_, "[ Conditional");
ASSERT_EQ(Expression::kTest, expr->condition()->context());
ASSERT_EQ(expr->context(), expr->then_expression()->context());
ASSERT_EQ(expr->context(), expr->else_expression()->context());
Label true_case, false_case, done;
VisitForControl(expr->condition(), &true_case, &false_case);
__ bind(&true_case);
Visit(expr->then_expression());
// If control flow falls through Visit, jump to done.
if (expr->context() == Expression::kEffect ||
expr->context() == Expression::kValue) {
if (context_ == Expression::kEffect || context_ == Expression::kValue) {
__ jmp(&done);
}
__ bind(&false_case);
Visit(expr->else_expression());
// If control flow falls through Visit, merge it with true case here.
if (expr->context() == Expression::kEffect ||
expr->context() == Expression::kValue) {
if (context_ == Expression::kEffect || context_ == Expression::kValue) {
__ bind(&done);
}
}
......@@ -592,24 +581,20 @@ void FastCodeGenerator::VisitSlot(Slot* expr) {
void FastCodeGenerator::VisitLiteral(Literal* expr) {
Comment cmnt(masm_, "[ Literal");
Apply(expr->context(), expr);
Apply(context_, expr);
}
void FastCodeGenerator::VisitAssignment(Assignment* expr) {
Comment cmnt(masm_, "[ Assignment");
// Left-hand side can only be a property, a global or a (parameter or local)
// slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
LhsKind assign_type = VARIABLE;
Property* prop = expr->target()->AsProperty();
// In case of a property we use the uninitialized expression context
// of the key to detect a named property.
if (prop != NULL) {
assign_type = (prop->key()->context() == Expression::kUninitialized)
? NAMED_PROPERTY
: KEYED_PROPERTY;
assign_type =
(prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
}
// Evaluate LHS expression.
......@@ -667,7 +652,7 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
switch (assign_type) {
case VARIABLE:
EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
expr->context());
context_);
break;
case NAMED_PROPERTY:
EmitNamedPropertyAssignment(expr);
......@@ -683,14 +668,11 @@ void FastCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) {
// Call runtime routine to allocate the catch extension object and
// assign the exception value to the catch variable.
Comment cmnt(masm_, "[ CatchExtensionObject");
VisitForValue(expr->key(), kStack);
VisitForValue(expr->value(), kStack);
// Create catch extension object.
__ CallRuntime(Runtime::kCreateCatchExtensionObject, 2);
__ push(result_register());
Apply(context_, result_register());
}
......
......@@ -250,23 +250,70 @@ class FastCodeGenerator: public AstVisitor {
// register.
MemOperand EmitSlotSearch(Slot* slot, Register scratch);
void VisitForEffect(Expression* expr) {
Expression::Context saved_context = context_;
context_ = Expression::kEffect;
Visit(expr);
context_ = saved_context;
}
void VisitForValue(Expression* expr, Location where) {
ASSERT(expr->context() == Expression::kValue);
Expression::Context saved_context = context_;
Location saved_location = location_;
context_ = Expression::kValue;
location_ = where;
Visit(expr);
context_ = saved_context;
location_ = saved_location;
}
void VisitForControl(Expression* expr, Label* if_true, Label* if_false) {
ASSERT(expr->context() == Expression::kTest ||
expr->context() == Expression::kValueTest ||
expr->context() == Expression::kTestValue);
Expression::Context saved_context = context_;
Label* saved_true = true_label_;
Label* saved_false = false_label_;
context_ = Expression::kTest;
true_label_ = if_true;
false_label_ = if_false;
Visit(expr);
context_ = saved_context;
true_label_ = saved_true;
false_label_ = saved_false;
}
void VisitForValueControl(Expression* expr,
Location where,
Label* if_true,
Label* if_false) {
Expression::Context saved_context = context_;
Location saved_location = location_;
Label* saved_true = true_label_;
Label* saved_false = false_label_;
context_ = Expression::kValueTest;
location_ = where;
true_label_ = if_true;
false_label_ = if_false;
Visit(expr);
context_ = saved_context;
location_ = saved_location;
true_label_ = saved_true;
false_label_ = saved_false;
}
void VisitForControlValue(Expression* expr,
Location where,
Label* if_true,
Label* if_false) {
Expression::Context saved_context = context_;
Location saved_location = location_;
Label* saved_true = true_label_;
Label* saved_false = false_label_;
context_ = Expression::kTestValue;
location_ = where;
true_label_ = if_true;
false_label_ = if_false;
Visit(expr);
context_ = saved_context;
location_ = saved_location;
true_label_ = saved_true;
false_label_ = saved_false;
}
......@@ -356,6 +403,7 @@ class FastCodeGenerator: public AstVisitor {
NestedStatement* nesting_stack_;
int loop_depth_;
Expression::Context context_;
Location location_;
Label* true_label_;
Label* false_label_;
......
......@@ -775,13 +775,13 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
__ push(esi);
__ push(Immediate(boilerplate));
__ CallRuntime(Runtime::kNewClosure, 2);
Apply(expr->context(), eax);
Apply(context_, eax);
}
void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
Comment cmnt(masm_, "[ VariableProxy");
EmitVariableLoad(expr->var(), expr->context());
EmitVariableLoad(expr->var(), context_);
}
......@@ -885,7 +885,7 @@ void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
__ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
// Label done:
__ bind(&done);
Apply(expr->context(), eax);
Apply(context_, eax);
}
......@@ -951,9 +951,9 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
}
if (result_saved) {
ApplyTOS(expr->context());
ApplyTOS(context_);
} else {
Apply(expr->context(), eax);
Apply(context_, eax);
}
}
......@@ -1001,9 +1001,9 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
}
if (result_saved) {
ApplyTOS(expr->context());
ApplyTOS(context_);
} else {
Apply(expr->context(), eax);
Apply(context_, eax);
}
}
......@@ -1117,7 +1117,7 @@ void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
__ pop(eax);
}
DropAndApply(1, expr->context(), eax);
DropAndApply(1, context_, eax);
}
......@@ -1153,7 +1153,7 @@ void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
}
// Receiver and key are still on stack.
DropAndApply(2, expr->context(), eax);
DropAndApply(2, context_, eax);
}
......@@ -1167,12 +1167,12 @@ void FastCodeGenerator::VisitProperty(Property* expr) {
if (key->IsPropertyName()) {
EmitNamedPropertyLoad(expr);
// Drop receiver left on the stack by IC.
DropAndApply(1, expr->context(), eax);
DropAndApply(1, context_, eax);
} else {
VisitForValue(expr->key(), kStack);
EmitKeyedPropertyLoad(expr);
// Drop key and receiver left on the stack by IC.
DropAndApply(2, expr->context(), eax);
DropAndApply(2, context_, eax);
}
}
......@@ -1194,7 +1194,7 @@ void FastCodeGenerator::EmitCallWithIC(Call* expr,
__ call(ic, mode);
// Restore context register.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
Apply(expr->context(), eax);
Apply(context_, eax);
}
......@@ -1211,7 +1211,7 @@ void FastCodeGenerator::EmitCallWithStub(Call* expr) {
__ CallStub(&stub);
// Restore context register.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
DropAndApply(1, expr->context(), eax);
DropAndApply(1, context_, eax);
}
......@@ -1317,7 +1317,7 @@ void FastCodeGenerator::VisitCallNew(CallNew* expr) {
__ call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
// Replace function on TOS with result in eax, or pop it.
DropAndApply(1, expr->context(), eax);
DropAndApply(1, context_, eax);
}
......@@ -1349,7 +1349,7 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
// Call the C runtime function.
__ CallRuntime(expr->function(), arg_count);
}
Apply(expr->context(), eax);
Apply(context_, eax);
}
......@@ -1357,9 +1357,8 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
switch (expr->op()) {
case Token::VOID: {
Comment cmnt(masm_, "[ UnaryOperation (VOID)");
ASSERT_EQ(Expression::kEffect, expr->expression()->context());
Visit(expr->expression());
switch (expr->context()) {
VisitForEffect(expr->expression());
switch (context_) {
case Expression::kUninitialized:
UNREACHABLE();
break;
......@@ -1396,14 +1395,12 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
case Token::NOT: {
Comment cmnt(masm_, "[ UnaryOperation (NOT)");
ASSERT_EQ(Expression::kTest, expr->expression()->context());
Label materialize_true, materialize_false, done;
// Initially assume a pure test context. Notice that the labels are
// swapped.
Label* if_true = false_label_;
Label* if_false = true_label_;
switch (expr->context()) {
switch (context_) {
case Expression::kUninitialized:
UNREACHABLE();
break;
......@@ -1425,14 +1422,12 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
break;
}
VisitForControl(expr->expression(), if_true, if_false);
Apply(expr->context(), if_false, if_true); // Labels swapped.
Apply(context_, if_false, if_true); // Labels swapped.
break;
}
case Token::TYPEOF: {
Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
ASSERT_EQ(Expression::kValue, expr->expression()->context());
VariableProxy* proxy = expr->expression()->AsVariableProxy();
if (proxy != NULL &&
!proxy->var()->is_this() &&
......@@ -1458,7 +1453,7 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
}
__ CallRuntime(Runtime::kTypeof, 1);
Apply(expr->context(), eax);
Apply(context_, eax);
break;
}
......@@ -1479,9 +1474,8 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
// In case of a property we use the uninitialized expression context
// of the key to detect a named property.
if (prop != NULL) {
assign_type = (prop->key()->context() == Expression::kUninitialized)
? NAMED_PROPERTY
: KEYED_PROPERTY;
assign_type =
(prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
}
// Evaluate expression and get value.
......@@ -1494,8 +1488,7 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
location_ = saved_location;
} else {
// Reserve space for result of postfix operation.
if (expr->is_postfix() && expr->context() != Expression::kEffect) {
ASSERT(expr->context() != Expression::kUninitialized);
if (expr->is_postfix() && context_ != Expression::kEffect) {
__ push(Immediate(Smi::FromInt(0)));
}
VisitForValue(prop->obj(), kStack);
......@@ -1513,7 +1506,7 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
// Save result for postfix expressions.
if (expr->is_postfix()) {
switch (expr->context()) {
switch (context_) {
case Expression::kUninitialized:
UNREACHABLE();
case Expression::kEffect:
......@@ -1557,12 +1550,12 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
Expression::kEffect);
// For all contexts except kEffect: We have the result on
// top of the stack.
if (expr->context() != Expression::kEffect) {
ApplyTOS(expr->context());
if (context_ != Expression::kEffect) {
ApplyTOS(context_);
}
} else {
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
expr->context());
context_);
}
break;
case NAMED_PROPERTY: {
......@@ -1574,11 +1567,11 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
__ nop();
if (expr->is_postfix()) {
__ Drop(1); // Result is on the stack under the receiver.
if (expr->context() != Expression::kEffect) {
ApplyTOS(expr->context());
if (context_ != Expression::kEffect) {
ApplyTOS(context_);
}
} else {
DropAndApply(1, expr->context(), eax);
DropAndApply(1, context_, eax);
}
break;
}
......@@ -1590,11 +1583,11 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
__ nop();
if (expr->is_postfix()) {
__ Drop(2); // Result is on the stack under the key and the receiver.
if (expr->context() != Expression::kEffect) {
ApplyTOS(expr->context());
if (context_ != Expression::kEffect) {
ApplyTOS(context_);
}
} else {
DropAndApply(2, expr->context(), eax);
DropAndApply(2, context_, eax);
}
break;
}
......@@ -1606,9 +1599,7 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
Comment cmnt(masm_, "[ BinaryOperation");
switch (expr->op()) {
case Token::COMMA:
ASSERT_EQ(Expression::kEffect, expr->left()->context());
ASSERT_EQ(expr->context(), expr->right()->context());
Visit(expr->left());
VisitForEffect(expr->left());
Visit(expr->right());
break;
......@@ -1630,7 +1621,7 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
case Token::SAR:
VisitForValue(expr->left(), kStack);
VisitForValue(expr->right(), kAccumulator);
EmitBinaryOp(expr->op(), expr->context());
EmitBinaryOp(expr->op(), context_);
break;
default:
......@@ -1648,7 +1639,7 @@ void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
// Initially assume we are in a test context.
Label* if_true = true_label_;
Label* if_false = false_label_;
switch (expr->context()) {
switch (context_) {
case Expression::kUninitialized:
UNREACHABLE();
break;
......@@ -1750,13 +1741,13 @@ void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
// Convert the result of the comparison into one expected for this
// expression's context.
Apply(expr->context(), if_true, if_false);
Apply(context_, if_true, if_false);
}
void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) {
__ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
Apply(expr->context(), eax);
Apply(context_, eax);
}
......
......@@ -778,13 +778,13 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
__ push(rsi);
__ Push(boilerplate);
__ CallRuntime(Runtime::kNewClosure, 2);
Apply(expr->context(), rax);
Apply(context_, rax);
}
void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
Comment cmnt(masm_, "[ VariableProxy");
EmitVariableLoad(expr->var(), expr->context());
EmitVariableLoad(expr->var(), context_);
}
......@@ -886,7 +886,7 @@ void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
__ Push(expr->flags());
__ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
__ bind(&done);
Apply(expr->context(), rax);
Apply(context_, rax);
}
......@@ -953,9 +953,9 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
}
if (result_saved) {
ApplyTOS(expr->context());
ApplyTOS(context_);
} else {
Apply(expr->context(), rax);
Apply(context_, rax);
}
}
......@@ -1003,9 +1003,9 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
}
if (result_saved) {
ApplyTOS(expr->context());
ApplyTOS(context_);
} else {
Apply(expr->context(), rax);
Apply(context_, rax);
}
}
......@@ -1117,7 +1117,7 @@ void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
__ pop(rax);
}
DropAndApply(1, expr->context(), rax);
DropAndApply(1, context_, rax);
}
......@@ -1153,7 +1153,7 @@ void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
}
// Receiver and key are still on stack.
DropAndApply(2, expr->context(), rax);
DropAndApply(2, context_, rax);
}
......@@ -1167,12 +1167,12 @@ void FastCodeGenerator::VisitProperty(Property* expr) {
if (key->IsPropertyName()) {
EmitNamedPropertyLoad(expr);
// Drop receiver left on the stack by IC.
DropAndApply(1, expr->context(), rax);
DropAndApply(1, context_, rax);
} else {
VisitForValue(expr->key(), kStack);
EmitKeyedPropertyLoad(expr);
// Drop key and receiver left on the stack by IC.
DropAndApply(2, expr->context(), rax);
DropAndApply(2, context_, rax);
}
}
......@@ -1196,7 +1196,7 @@ void FastCodeGenerator::EmitCallWithIC(Call* expr,
// Restore context register.
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
// Discard the function left on TOS.
DropAndApply(1, expr->context(), rax);
DropAndApply(1, context_, rax);
}
......@@ -1214,7 +1214,7 @@ void FastCodeGenerator::EmitCallWithStub(Call* expr) {
// Restore context register.
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
// Discard the function left on TOS.
DropAndApply(1, expr->context(), rax);
DropAndApply(1, context_, rax);
}
......@@ -1323,7 +1323,7 @@ void FastCodeGenerator::VisitCallNew(CallNew* expr) {
__ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
// Replace function on TOS with result in rax, or pop it.
DropAndApply(1, expr->context(), rax);
DropAndApply(1, context_, rax);
}
......@@ -1352,10 +1352,10 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
// Restore context register.
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
// Discard the function left on TOS.
DropAndApply(1, expr->context(), rax);
DropAndApply(1, context_, rax);
} else {
__ CallRuntime(expr->function(), arg_count);
Apply(expr->context(), rax);
Apply(context_, rax);
}
}
......@@ -1364,9 +1364,8 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
switch (expr->op()) {
case Token::VOID: {
Comment cmnt(masm_, "[ UnaryOperation (VOID)");
ASSERT_EQ(Expression::kEffect, expr->expression()->context());
Visit(expr->expression());
switch (expr->context()) {
VisitForEffect(expr->expression());
switch (context_) {
case Expression::kUninitialized:
UNREACHABLE();
break;
......@@ -1403,14 +1402,12 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
case Token::NOT: {
Comment cmnt(masm_, "[ UnaryOperation (NOT)");
ASSERT_EQ(Expression::kTest, expr->expression()->context());
Label materialize_true, materialize_false, done;
// Initially assume a pure test context. Notice that the labels are
// swapped.
Label* if_true = false_label_;
Label* if_false = true_label_;
switch (expr->context()) {
switch (context_) {
case Expression::kUninitialized:
UNREACHABLE();
break;
......@@ -1432,14 +1429,12 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
break;
}
VisitForControl(expr->expression(), if_true, if_false);
Apply(expr->context(), if_false, if_true); // Labels swapped.
Apply(context_, if_false, if_true); // Labels swapped.
break;
}
case Token::TYPEOF: {
Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
ASSERT_EQ(Expression::kValue, expr->expression()->context());
VariableProxy* proxy = expr->expression()->AsVariableProxy();
if (proxy != NULL &&
!proxy->var()->is_this() &&
......@@ -1465,7 +1460,7 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
}
__ CallRuntime(Runtime::kTypeof, 1);
Apply(expr->context(), rax);
Apply(context_, rax);
break;
}
......@@ -1486,9 +1481,8 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
// In case of a property we use the uninitialized expression context
// of the key to detect a named property.
if (prop != NULL) {
assign_type = (prop->key()->context() == Expression::kUninitialized)
? NAMED_PROPERTY
: KEYED_PROPERTY;
assign_type =
(prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
}
// Evaluate expression and get value.
......@@ -1501,8 +1495,7 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
location_ = saved_location;
} else {
// Reserve space for result of postfix operation.
if (expr->is_postfix() && expr->context() != Expression::kEffect) {
ASSERT(expr->context() != Expression::kUninitialized);
if (expr->is_postfix() && context_ != Expression::kEffect) {
__ Push(Smi::FromInt(0));
}
VisitForValue(prop->obj(), kStack);
......@@ -1520,7 +1513,7 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
// Save result for postfix expressions.
if (expr->is_postfix()) {
switch (expr->context()) {
switch (context_) {
case Expression::kUninitialized:
UNREACHABLE();
case Expression::kEffect:
......@@ -1564,12 +1557,12 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
Expression::kEffect);
// For all contexts except kEffect: We have the result on
// top of the stack.
if (expr->context() != Expression::kEffect) {
ApplyTOS(expr->context());
if (context_ != Expression::kEffect) {
ApplyTOS(context_);
}
} else {
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
expr->context());
context_);
}
break;
case NAMED_PROPERTY: {
......@@ -1581,11 +1574,11 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
__ nop();
if (expr->is_postfix()) {
__ Drop(1); // Result is on the stack under the receiver.
if (expr->context() != Expression::kEffect) {
ApplyTOS(expr->context());
if (context_ != Expression::kEffect) {
ApplyTOS(context_);
}
} else {
DropAndApply(1, expr->context(), rax);
DropAndApply(1, context_, rax);
}
break;
}
......@@ -1597,11 +1590,11 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
__ nop();
if (expr->is_postfix()) {
__ Drop(2); // Result is on the stack under the key and the receiver.
if (expr->context() != Expression::kEffect) {
ApplyTOS(expr->context());
if (context_ != Expression::kEffect) {
ApplyTOS(context_);
}
} else {
DropAndApply(2, expr->context(), rax);
DropAndApply(2, context_, rax);
}
break;
}
......@@ -1612,9 +1605,7 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
Comment cmnt(masm_, "[ BinaryOperation");
switch (expr->op()) {
case Token::COMMA:
ASSERT_EQ(Expression::kEffect, expr->left()->context());
ASSERT_EQ(expr->context(), expr->right()->context());
Visit(expr->left());
VisitForEffect(expr->left());
Visit(expr->right());
break;
......@@ -1636,7 +1627,7 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
case Token::SAR:
VisitForValue(expr->left(), kStack);
VisitForValue(expr->right(), kAccumulator);
EmitBinaryOp(expr->op(), expr->context());
EmitBinaryOp(expr->op(), context_);
break;
default:
......@@ -1654,7 +1645,7 @@ void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
// Initially assume we are in a test context.
Label* if_true = true_label_;
Label* if_false = false_label_;
switch (expr->context()) {
switch (context_) {
case Expression::kUninitialized:
UNREACHABLE();
break;
......@@ -1753,13 +1744,13 @@ void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
// Convert the result of the comparison into one expected for this
// expression's context.
Apply(expr->context(), if_true, if_false);
Apply(context_, if_true, if_false);
}
void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) {
__ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
Apply(expr->context(), rax);
Apply(context_, rax);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment