Chromium Code Reviews| Index: src/compiler.cc |
| =================================================================== |
| --- src/compiler.cc (revision 3152) |
| +++ src/compiler.cc (working copy) |
| @@ -46,7 +46,10 @@ |
| public: |
| enum CodeGenTag { NORMAL, FAST }; |
| - CodeGenSelector() : has_supported_syntax_(true) {} |
| + CodeGenSelector() |
| + : has_supported_syntax_(true), |
| + location_(Location::Nowhere()) { |
|
fschneider
2009/10/28 10:06:01
I'm not sure: Should this match the default locati
Kevin Millikin (Chromium)
2009/10/28 11:39:38
Possibly. I wanted it to be nowhere when not insi
|
| + } |
| CodeGenTag Select(FunctionLiteral* fun); |
| @@ -54,6 +57,14 @@ |
| 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) |
| @@ -61,6 +72,9 @@ |
| bool has_supported_syntax_; |
| + // The desired location of the currently visited expression. |
| + Location location_; |
| + |
| DISALLOW_COPY_AND_ASSIGN(CodeGenSelector); |
| }; |
| @@ -499,6 +513,30 @@ |
| } |
| +void CodeGenSelector::VisitAsEffect(Expression* expr) { |
| + if (location_.is_nowhere()) { |
| + Visit(expr); |
| + } else { |
| + Location saved = location_; |
| + location_ = Location::Nowhere(); |
| + Visit(expr); |
| + location_ = saved; |
| + } |
| +} |
| + |
| + |
| +void CodeGenSelector::VisitAsValue(Expression* expr) { |
| + if (location_.is_temporary()) { |
| + Visit(expr); |
| + } else { |
| + Location saved = location_; |
| + location_ = Location::Temporary(); |
| + Visit(expr); |
| + location_ = saved; |
| + } |
| +} |
| + |
| + |
| void CodeGenSelector::VisitDeclaration(Declaration* decl) { |
| Variable* var = decl->proxy()->var(); |
| if (!var->is_global() || var->mode() == Variable::CONST) { |
| @@ -513,10 +551,7 @@ |
| void CodeGenSelector::VisitExpressionStatement(ExpressionStatement* stmt) { |
| - Expression* expr = stmt->expression(); |
| - Visit(expr); |
| - CHECK_BAILOUT; |
| - expr->set_location(Location::Nowhere()); |
| + VisitAsEffect(stmt->expression()); |
| } |
| @@ -541,7 +576,7 @@ |
| void CodeGenSelector::VisitReturnStatement(ReturnStatement* stmt) { |
| - Visit(stmt->expression()); |
| + VisitAsValue(stmt->expression()); |
| } |
| @@ -599,6 +634,7 @@ |
| if (!expr->AllowsLazyCompilation()) { |
| BAILOUT("FunctionLiteral does not allow lazy compilation"); |
| } |
| + expr->set_location(location_); |
| } |
| @@ -614,37 +650,72 @@ |
| void CodeGenSelector::VisitSlot(Slot* expr) { |
| - Slot::Type type = expr->type(); |
| - if (type != Slot::PARAMETER && type != Slot::LOCAL) { |
| - BAILOUT("non-parameter/non-local slot reference"); |
| - } |
| + UNREACHABLE(); |
| } |
| void CodeGenSelector::VisitVariableProxy(VariableProxy* expr) { |
| Expression* rewrite = expr->var()->rewrite(); |
| - if (rewrite != NULL) Visit(rewrite); |
| + // A rewrite of NULL indicates a global variable. |
| + if (rewrite != NULL) { |
| + Slot* slot = rewrite->AsSlot(); |
| + if (slot != NULL) { |
| + Slot::Type type = slot->type(); |
| + if (type != Slot::PARAMETER && type != Slot::LOCAL) { |
| + BAILOUT("non-parameter/non-local slot reference"); |
| + } |
|
William Hesse
2009/10/28 10:28:54
Control flow is tricky here. Reversing sense of s
Kevin Millikin (Chromium)
2009/10/28 11:39:38
I see what you mean. I've changed it.
|
| + } else { |
| + BAILOUT("non-global/non-slot variable reference"); |
| + } |
| + } |
| + expr->set_location(location_); |
| } |
| void CodeGenSelector::VisitLiteral(Literal* expr) { |
| - // Literals are supported. |
| + expr->set_location(location_); |
| } |
| void CodeGenSelector::VisitRegExpLiteral(RegExpLiteral* expr) { |
| - // RegexpLiterals are supported. |
| + expr->set_location(location_); |
| } |
| void CodeGenSelector::VisitObjectLiteral(ObjectLiteral* expr) { |
| - for (int i = 0; i < expr->properties()->length(); i++) { |
| - ObjectLiteral::Property* property = expr->properties()->at(i); |
| - Visit(property->key()); |
| + ZoneList<ObjectLiteral::Property*>* properties = expr->properties(); |
| + |
| + 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: |
| + VisitAsValue(property->key()); |
| + CHECK_BAILOUT; |
| + break; |
| + } |
| + VisitAsValue(property->value()); |
| CHECK_BAILOUT; |
| - Visit(property->value()); |
| - CHECK_BAILOUT; |
| } |
| + expr->set_location(location_); |
| } |
| @@ -654,9 +725,10 @@ |
| Expression* subexpr = subexprs->at(i); |
| if (subexpr->AsLiteral() != NULL) continue; |
| if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; |
| - Visit(subexpr); |
| + VisitAsValue(subexpr); |
| CHECK_BAILOUT; |
| } |
| + expr->set_location(location_); |
| } |
| @@ -668,7 +740,10 @@ |
| void CodeGenSelector::VisitAssignment(Assignment* expr) { |
| // We support plain non-compound assignments to parameters and |
| // non-context (stack-allocated) locals. |
| - if (expr->starts_initialization_block()) BAILOUT("initialization block"); |
| + if (expr->starts_initialization_block() || |
| + expr->ends_initialization_block()) { |
| + BAILOUT("initialization block start"); |
| + } |
| Token::Value op = expr->op(); |
| if (op == Token::INIT_CONST) BAILOUT("initialize constant"); |
| @@ -687,7 +762,8 @@ |
| } |
| } |
| - Visit(expr->value()); |
| + VisitAsValue(expr->value()); |
| + expr->set_location(location_); |
| } |
| @@ -718,11 +794,12 @@ |
| } else { |
| BAILOUT("Call to a non-global function"); |
| } |
| - // Check all arguments to the call |
| + // Check all arguments to the call. (Relies on TEMP meaning STACK.) |
| for (int i = 0; i < args->length(); i++) { |
| - Visit(args->at(i)); |
| + VisitAsValue(args->at(i)); |
| CHECK_BAILOUT; |
| } |
| + expr->set_location(location_); |
| } |
| @@ -740,16 +817,18 @@ |
| void CodeGenSelector::VisitCallRuntime(CallRuntime* expr) { |
| // In case of JS runtime function bail out. |
| - if (expr->function() == NULL) BAILOUT("CallRuntime"); |
| + if (expr->function() == NULL) BAILOUT("call JS runtime function"); |
| // Check for inline runtime call |
| if (expr->name()->Get(0) == '_' && |
| CodeGenerator::FindInlineRuntimeLUT(expr->name()) != NULL) { |
| - BAILOUT("InlineRuntimeCall"); |
| + BAILOUT("inlined runtime call"); |
| } |
| + // Check all arguments to the call. (Relies on TEMP meaning STACK.) |
| for (int i = 0; i < expr->arguments()->length(); i++) { |
| - Visit(expr->arguments()->at(i)); |
| + VisitAsValue(expr->arguments()->at(i)); |
| CHECK_BAILOUT; |
| } |
| + expr->set_location(location_); |
| } |
| @@ -766,14 +845,17 @@ |
| void CodeGenSelector::VisitBinaryOperation(BinaryOperation* expr) { |
| switch (expr->op()) { |
| case Token::OR: |
| - Visit(expr->left()); |
| + VisitAsValue(expr->left()); |
| CHECK_BAILOUT; |
| + // The location for the right subexpression is the same as for the |
| + // whole expression. |
| Visit(expr->right()); |
| break; |
| default: |
| BAILOUT("Unsupported binary operation"); |
| } |
| + expr->set_location(location_); |
| } |