| Index: src/compiler.cc
|
| ===================================================================
|
| --- src/compiler.cc (revision 3095)
|
| +++ src/compiler.cc (working copy)
|
| @@ -51,6 +51,7 @@
|
| CodeGenTag Select(FunctionLiteral* fun);
|
|
|
| private:
|
| + void VisitDeclarations(ZoneList<Declaration*>* decls);
|
| void VisitStatements(ZoneList<Statement*>* stmts);
|
|
|
| // AST node visit functions.
|
| @@ -107,7 +108,7 @@
|
| CodeGenSelector selector;
|
| CodeGenSelector::CodeGenTag code_gen = selector.Select(literal);
|
| if (code_gen == CodeGenSelector::FAST) {
|
| - return FastCodeGenerator::MakeCode(literal, script);
|
| + return FastCodeGenerator::MakeCode(literal, script, is_eval);
|
| }
|
| ASSERT(code_gen == CodeGenSelector::NORMAL);
|
| }
|
| @@ -450,14 +451,22 @@
|
| CodeGenSelector::CodeGenTag CodeGenSelector::Select(FunctionLiteral* fun) {
|
| Scope* scope = fun->scope();
|
|
|
| - if (!scope->is_global_scope()) return NORMAL;
|
| + if (!scope->is_global_scope()) {
|
| + if (FLAG_trace_bailout) PrintF("Non-global scope\n");
|
| + return NORMAL;
|
| + }
|
| ASSERT(scope->num_heap_slots() == 0);
|
| ASSERT(scope->arguments() == NULL);
|
|
|
| - if (!scope->declarations()->is_empty()) return NORMAL;
|
| - if (fun->materialized_literal_count() > 0) return NORMAL;
|
| + if (fun->materialized_literal_count() > 0) {
|
| + if (FLAG_trace_bailout) PrintF("Unsupported literal\n");
|
| + return NORMAL;
|
| + }
|
|
|
| has_supported_syntax_ = true;
|
| + VisitDeclarations(fun->scope()->declarations());
|
| + if (!has_supported_syntax_) return NORMAL;
|
| +
|
| VisitStatements(fun->body());
|
| return has_supported_syntax_ ? FAST : NORMAL;
|
| }
|
| @@ -479,21 +488,32 @@
|
| } while (false)
|
|
|
|
|
| +void CodeGenSelector::VisitDeclarations(ZoneList<Declaration*>* decls) {
|
| + for (int i = 0; i < decls->length(); i++) {
|
| + Visit(decls->at(i));
|
| + CHECK_BAILOUT;
|
| + }
|
| +}
|
| +
|
| +
|
| void CodeGenSelector::VisitStatements(ZoneList<Statement*>* stmts) {
|
| for (int i = 0, len = stmts->length(); i < len; i++) {
|
| + Visit(stmts->at(i));
|
| CHECK_BAILOUT;
|
| - Visit(stmts->at(i));
|
| }
|
| }
|
|
|
|
|
| void CodeGenSelector::VisitDeclaration(Declaration* decl) {
|
| - BAILOUT("Declaration");
|
| + Variable* var = decl->proxy()->var();
|
| + if (!var->is_global() || var->mode() == Variable::CONST) {
|
| + BAILOUT("Non-global declaration");
|
| + }
|
| }
|
|
|
|
|
| void CodeGenSelector::VisitBlock(Block* stmt) {
|
| - BAILOUT("Block");
|
| + VisitStatements(stmt->statements());
|
| }
|
|
|
|
|
| @@ -581,7 +601,9 @@
|
|
|
|
|
| void CodeGenSelector::VisitFunctionLiteral(FunctionLiteral* expr) {
|
| - BAILOUT("FunctionLiteral");
|
| + if (!expr->AllowsLazyCompilation()) {
|
| + BAILOUT("FunctionLiteral does not allow lazy compilation");
|
| + }
|
| }
|
|
|
|
|
| @@ -674,7 +696,25 @@
|
|
|
|
|
| void CodeGenSelector::VisitCall(Call* expr) {
|
| - BAILOUT("Call");
|
| + Expression* fun = expr->expression();
|
| + ZoneList<Expression*>* args = expr->arguments();
|
| + Variable* var = fun->AsVariableProxy()->AsVariable();
|
| +
|
| + // Check for supported calls
|
| + if (var != NULL && var->is_possibly_eval()) {
|
| + BAILOUT("Call to a function named 'eval'");
|
| + } else if (var != NULL && !var->is_this() && var->is_global()) {
|
| + // ----------------------------------
|
| + // JavaScript example: 'foo(1, 2, 3)' // foo is global
|
| + // ----------------------------------
|
| + } else {
|
| + BAILOUT("Call to a non-global function");
|
| + }
|
| + // Check all arguments to the call
|
| + for (int i = 0; i < args->length(); i++) {
|
| + Visit(args->at(i));
|
| + CHECK_BAILOUT;
|
| + }
|
| }
|
|
|
|
|
| @@ -684,7 +724,17 @@
|
|
|
|
|
| void CodeGenSelector::VisitCallRuntime(CallRuntime* expr) {
|
| - BAILOUT("CallRuntime");
|
| + // In case of JS runtime function bail out.
|
| + if (expr->function() == NULL) BAILOUT("CallRuntime");
|
| + // Check for inline runtime call
|
| + if (expr->name()->Get(0) == '_' &&
|
| + CodeGenerator::FindInlineRuntimeLUT(expr->name()) != NULL) {
|
| + BAILOUT("InlineRuntimeCall");
|
| + }
|
| + for (int i = 0; i < expr->arguments()->length(); i++) {
|
| + Visit(expr->arguments()->at(i));
|
| + CHECK_BAILOUT;
|
| + }
|
| }
|
|
|
|
|
|
|