From: kmillikin@chromium.org Date: Wed, 27 Jan 2010 12:14:26 +0000 (+0000) Subject: Enable references and assignments to lookup slots in the toplevel code X-Git-Tag: upstream/4.7.83~22603 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f866a574aef89f4405458c28d2a9748cad5d1de9;p=platform%2Fupstream%2Fv8.git 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 --- diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc index 9c178aed4..1844c285e 100644 --- a/src/arm/full-codegen-arm.cc +++ b/src/arm/full-codegen-arm.cc @@ -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 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. diff --git a/src/full-codegen.cc b/src/full-codegen.cc index 4bda3648e..0477ab906 100644 --- a/src/full-codegen.cc +++ b/src/full-codegen.cc @@ -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; diff --git a/src/full-codegen.h b/src/full-codegen.h index acb9d5256..35ed25f13 100644 --- a/src/full-codegen.h +++ b/src/full-codegen.h @@ -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); diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc index 74de4b97e..fbeec3f51 100644 --- a/src/ia32/full-codegen-ia32.cc +++ b/src/ia32/full-codegen-ia32.cc @@ -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: diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc index 002840aea..a5085cac7 100644 --- a/src/x64/full-codegen-x64.cc +++ b/src/x64/full-codegen-x64.cc @@ -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.