Enable references and assignments to lookup slots in the toplevel code

generator.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3716 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 93f5cb2c
......@@ -674,9 +674,13 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
void FullCodeGenerator::EmitVariableLoad(Variable* var,
Expression::Context context) {
Expression* rewrite = var->rewrite();
if (rewrite == NULL) {
ASSERT(var->is_global());
// Four cases: non-this global variables, lookup slots, all other
// types of slots, and parameters that rewrite to explicit property
// accesses on the arguments object.
Slot* slot = var->slot();
Property* property = var->AsProperty();
if (var->is_global() && !var->is_this()) {
Comment cmnt(masm_, "Global variable");
// Use inline caching. Variable name is passed in r2 and the global
// object on the stack.
......@@ -686,34 +690,24 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var,
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
__ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
DropAndApply(1, context, r0);
} else if (rewrite->AsSlot() != NULL) {
Slot* slot = rewrite->AsSlot();
if (FLAG_debug_code) {
switch (slot->type()) {
case Slot::PARAMETER:
case Slot::LOCAL: {
Comment cmnt(masm_, "Stack slot");
break;
}
case Slot::CONTEXT: {
Comment cmnt(masm_, "Context slot");
break;
}
case Slot::LOOKUP:
UNIMPLEMENTED();
break;
}
}
} else if (slot != NULL && slot->type() == Slot::LOOKUP) {
Comment cmnt(masm_, "Lookup slot");
__ mov(r1, Operand(var->name()));
__ stm(db_w, sp, cp.bit() | r1.bit()); // Context and name.
__ CallRuntime(Runtime::kLoadContextSlot, 2);
Apply(context, r0);
} else if (slot != NULL) {
Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
? "Context slot"
: "Stack slot");
Apply(context, slot);
} else {
Comment cmnt(masm_, "Variable rewritten to property");
// A variable has been rewritten into an explicit access to an object
// property.
Property* property = rewrite->AsProperty();
Comment cmnt(masm_, "Rewritten parameter");
ASSERT_NOT_NULL(property);
// The only property expressions that can occur are of the form
// "slot[literal]".
// Rewritten parameter accesses are of the form "slot[literal]".
// Assert that the object is in a slot.
Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
......@@ -927,9 +921,15 @@ void FullCodeGenerator::EmitBinaryOp(Token::Value op,
void FullCodeGenerator::EmitVariableAssignment(Variable* var,
Expression::Context context) {
// Three main cases: global variables, lookup slots, and all other
// types of slots. Left-hand-side parameters that rewrite to
// explicit property accesses do not reach here.
ASSERT(var != NULL);
ASSERT(var->is_global() || var->slot() != NULL);
Slot* slot = var->slot();
if (var->is_global()) {
ASSERT(!var->is_this());
// Assignment to a global variable. Use inline caching for the
// assignment. Right-hand-side value is passed in r0, variable name in
// r2, and the global object on the stack.
......@@ -941,6 +941,13 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
// Overwrite the global object on the stack with the result if needed.
DropAndApply(1, context, r0);
} else if (slot != NULL && slot->type() == Slot::LOOKUP) {
__ push(result_register()); // Value.
__ mov(r1, Operand(var->name()));
__ stm(db_w, sp, cp.bit() | r1.bit()); // Context and name.
__ CallRuntime(Runtime::kStoreContextSlot, 3);
Apply(context, r0);
} else if (var->slot() != NULL) {
Slot* slot = var->slot();
switch (slot->type()) {
......@@ -967,6 +974,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
break;
}
Apply(context, result_register());
} else {
// Variables rewritten as properties are not treated as variables in
// assignments.
......
......@@ -133,7 +133,9 @@ void FullCodeGenSyntaxChecker::VisitContinueStatement(ContinueStatement* stmt) {
}
void FullCodeGenSyntaxChecker::VisitBreakStatement(BreakStatement* stmt) {}
void FullCodeGenSyntaxChecker::VisitBreakStatement(BreakStatement* stmt) {
// Supported.
}
void FullCodeGenSyntaxChecker::VisitReturnStatement(ReturnStatement* stmt) {
......@@ -241,30 +243,7 @@ void FullCodeGenSyntaxChecker::VisitSlot(Slot* expr) {
void FullCodeGenSyntaxChecker::VisitVariableProxy(VariableProxy* expr) {
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
// implementing unary typeof will become live.
if (type == Slot::LOOKUP) {
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
Property* property = var->AsProperty();
ASSERT_NOT_NULL(property);
Variable* object = property->obj()->AsVariableProxy()->AsVariable();
ASSERT_NOT_NULL(object);
ASSERT_NOT_NULL(object->slot());
ASSERT_NOT_NULL(property->key()->AsLiteral());
ASSERT(property->key()->AsLiteral()->handle()->IsSmi());
#endif
}
}
// Supported.
}
......@@ -313,8 +292,6 @@ void FullCodeGenSyntaxChecker::VisitCatchExtensionObject(
void FullCodeGenSyntaxChecker::VisitAssignment(Assignment* expr) {
// We support plain non-compound assignments to properties, parameters and
// non-context (stack-allocated) locals, and global variables.
Token::Value op = expr->op();
if (op == Token::INIT_CONST) BAILOUT("initialize constant");
......@@ -322,17 +299,8 @@ void FullCodeGenSyntaxChecker::VisitAssignment(Assignment* expr) {
Property* prop = expr->target()->AsProperty();
ASSERT(var == NULL || prop == NULL);
if (var != NULL) {
if (var->mode() == Variable::CONST) {
BAILOUT("Assignment to const");
}
// All global variables are supported.
if (!var->is_global()) {
ASSERT(var->slot() != NULL);
Slot::Type type = var->slot()->type();
if (type == Slot::LOOKUP) {
BAILOUT("Lookup slot");
}
}
if (var->mode() == Variable::CONST) BAILOUT("Assignment to const");
// All other variables are supported.
} else if (prop != NULL) {
Visit(prop->obj());
CHECK_BAILOUT;
......@@ -1079,6 +1047,7 @@ void FullCodeGenerator::VisitLiteral(Literal* expr) {
void FullCodeGenerator::VisitAssignment(Assignment* expr) {
Comment cmnt(masm_, "[ Assignment");
ASSERT(expr->op() != Token::INIT_CONST);
// 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 };
......@@ -1129,7 +1098,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
Expression* rhs = expr->value();
VisitForValue(rhs, kAccumulator);
// If we have a compount assignment: Apply operator.
// If we have a compound assignment: Apply operator.
if (expr->is_compound()) {
Location saved_location = location_;
location_ = kAccumulator;
......
......@@ -245,7 +245,10 @@ class FullCodeGenerator: public AstVisitor {
// or on top of the stack) into the result expected according to an
// expression context.
void Apply(Expression::Context context, Register reg);
// Slot cannot have type Slot::LOOKUP.
void Apply(Expression::Context context, Slot* slot);
void Apply(Expression::Context context, Literal* lit);
void ApplyTOS(Expression::Context context);
......
......@@ -787,9 +787,13 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
void FullCodeGenerator::EmitVariableLoad(Variable* var,
Expression::Context context) {
Expression* rewrite = var->rewrite();
if (rewrite == NULL) {
ASSERT(var->is_global());
// Four cases: non-this global variables, lookup slots, all other
// types of slots, and parameters that rewrite to explicit property
// accesses on the arguments object.
Slot* slot = var->slot();
Property* property = var->AsProperty();
if (var->is_global() && !var->is_this()) {
Comment cmnt(masm_, "Global variable");
// Use inline caching. Variable name is passed in ecx and the global
// object on the stack.
......@@ -803,34 +807,24 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var,
// (eg, push/pop elimination).
__ nop();
DropAndApply(1, context, eax);
} else if (rewrite->AsSlot() != NULL) {
Slot* slot = rewrite->AsSlot();
if (FLAG_debug_code) {
switch (slot->type()) {
case Slot::PARAMETER:
case Slot::LOCAL: {
Comment cmnt(masm_, "Stack slot");
break;
}
case Slot::CONTEXT: {
Comment cmnt(masm_, "Context slot");
break;
}
case Slot::LOOKUP:
UNIMPLEMENTED();
break;
}
}
} else if (slot != NULL && slot->type() == Slot::LOOKUP) {
Comment cmnt(masm_, "Lookup slot");
__ push(esi); // Context.
__ push(Immediate(var->name()));
__ CallRuntime(Runtime::kLoadContextSlot, 2);
Apply(context, eax);
} else if (slot != NULL) {
Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
? "Context slot"
: "Stack slot");
Apply(context, slot);
} else {
Comment cmnt(masm_, "Variable rewritten to property");
// A variable has been rewritten into an explicit access to an object
// property.
Property* property = rewrite->AsProperty();
Comment cmnt(masm_, "Rewritten parameter");
ASSERT_NOT_NULL(property);
// The only property expressions that can occur are of the form
// "slot[literal]".
// Rewritten parameter accesses are of the form "slot[literal]".
// Assert that the object is in a slot.
Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
......@@ -1039,9 +1033,15 @@ void FullCodeGenerator::EmitBinaryOp(Token::Value op,
void FullCodeGenerator::EmitVariableAssignment(Variable* var,
Expression::Context context) {
// Three main cases: global variables, lookup slots, and all other
// types of slots. Left-hand-side parameters that rewrite to
// explicit property accesses do not reach here.
ASSERT(var != NULL);
ASSERT(var->is_global() || var->slot() != NULL);
Slot* slot = var->slot();
if (var->is_global()) {
ASSERT(!var->is_this());
// Assignment to a global variable. Use inline caching for the
// assignment. Right-hand-side value is passed in eax, variable name in
// ecx, and the global object on the stack.
......@@ -1053,8 +1053,14 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
// Overwrite the receiver on the stack with the result if needed.
DropAndApply(1, context, eax);
} else if (var->slot() != NULL) {
Slot* slot = var->slot();
} else if (slot != NULL && slot->type() == Slot::LOOKUP) {
__ push(result_register()); // Value.
__ push(esi); // Context.
__ push(Immediate(var->name()));
__ CallRuntime(Runtime::kStoreContextSlot, 3);
Apply(context, eax);
} else if (slot != NULL) {
switch (slot->type()) {
case Slot::LOCAL:
case Slot::PARAMETER:
......
......@@ -790,9 +790,13 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
void FullCodeGenerator::EmitVariableLoad(Variable* var,
Expression::Context context) {
Expression* rewrite = var->rewrite();
if (rewrite == NULL) {
ASSERT(var->is_global());
// Four cases: non-this global variables, lookup slots, all other
// types of slots, and parameters that rewrite to explicit property
// accesses on the arguments object.
Slot* slot = var->slot();
Property* property = var->AsProperty();
if (var->is_global() && !var->is_this()) {
Comment cmnt(masm_, "Global variable");
// Use inline caching. Variable name is passed in rcx and the global
// object on the stack.
......@@ -805,34 +809,24 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var,
// is no test rax instruction here.
__ nop();
DropAndApply(1, context, rax);
} else if (rewrite->AsSlot() != NULL) {
Slot* slot = rewrite->AsSlot();
if (FLAG_debug_code) {
switch (slot->type()) {
case Slot::PARAMETER:
case Slot::LOCAL: {
Comment cmnt(masm_, "Stack slot");
break;
}
case Slot::CONTEXT: {
Comment cmnt(masm_, "Context slot");
break;
}
case Slot::LOOKUP:
UNIMPLEMENTED();
break;
}
}
} else if (slot != NULL && slot->type() == Slot::LOOKUP) {
Comment cmnt(masm_, "Lookup slot");
__ push(rsi); // Context.
__ Push(var->name());
__ CallRuntime(Runtime::kLoadContextSlot, 2);
Apply(context, rax);
} else if (slot != NULL) {
Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
? "Context slot"
: "Stack slot");
Apply(context, slot);
} else {
Comment cmnt(masm_, "Variable rewritten to property");
// A variable has been rewritten into an explicit access to an object
// property.
Property* property = rewrite->AsProperty();
Comment cmnt(masm_, "Rewritten parameter");
ASSERT_NOT_NULL(property);
// The only property expressions that can occur are of the form
// "slot[literal]".
// Rewritten parameter accesses are of the form "slot[literal]".
// Assert that the object is in a slot.
Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
......@@ -1041,9 +1035,14 @@ void FullCodeGenerator::EmitBinaryOp(Token::Value op,
void FullCodeGenerator::EmitVariableAssignment(Variable* var,
Expression::Context context) {
// Three main cases: non-this global variables, lookup slots, and
// all other types of slots. Left-hand-side parameters that rewrite
// to explicit property accesses do not reach here.
ASSERT(var != NULL);
ASSERT(var->is_global() || var->slot() != NULL);
Slot* slot = var->slot();
if (var->is_global()) {
ASSERT(!var->is_this());
// Assignment to a global variable. Use inline caching for the
// assignment. Right-hand-side value is passed in rax, variable name in
// rcx, and the global object on the stack.
......@@ -1054,8 +1053,14 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
// Overwrite the global object on the stack with the result if needed.
DropAndApply(1, context, rax);
} else if (slot != NULL && slot->type() == Slot::LOOKUP) {
__ push(result_register()); // Value.
__ push(rsi); // Context.
__ Push(var->name());
__ CallRuntime(Runtime::kStoreContextSlot, 3);
Apply(context, rax);
} else if (var->slot() != NULL) {
Slot* slot = var->slot();
switch (slot->type()) {
case Slot::LOCAL:
case Slot::PARAMETER:
......@@ -1078,6 +1083,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
break;
}
Apply(context, result_register());
} else {
// Variables rewritten as properties are not treated as variables in
// assignments.
......
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