diff options
| author | Leon Clarke <leonclarke@google.com> | 2010-01-27 15:57:47 +0000 |
|---|---|---|
| committer | Leon Clarke <leonclarke@google.com> | 2010-01-27 15:57:47 +0000 |
| commit | 888f6729be6a6f6fbe246cb5a9f122e2dbe455b7 (patch) | |
| tree | 16f9ce250ef5d36e49a0fb0018e979002ed5b4fb /src/compiler.cc | |
| parent | 1471e9f5b6f291eea8447f441527cd2a85074a33 (diff) | |
| download | android_external_v8-888f6729be6a6f6fbe246cb5a9f122e2dbe455b7.tar.gz android_external_v8-888f6729be6a6f6fbe246cb5a9f122e2dbe455b7.tar.bz2 android_external_v8-888f6729be6a6f6fbe246cb5a9f122e2dbe455b7.zip | |
Pull from svn bleeding_edge@3716
Diffstat (limited to 'src/compiler.cc')
| -rw-r--r-- | src/compiler.cc | 459 |
1 files changed, 11 insertions, 448 deletions
diff --git a/src/compiler.cc b/src/compiler.cc index b7aaedf5..fe61571f 100644 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -32,7 +32,7 @@ #include "compilation-cache.h" #include "compiler.h" #include "debug.h" -#include "fast-codegen.h" +#include "full-codegen.h" #include "oprofile-agent.h" #include "rewriter.h" #include "scopes.h" @@ -42,29 +42,6 @@ namespace v8 { namespace internal { -class CodeGenSelector: public AstVisitor { - public: - enum CodeGenTag { NORMAL, FAST }; - - CodeGenSelector() : has_supported_syntax_(true) {} - - CodeGenTag Select(FunctionLiteral* fun); - - private: - void VisitDeclarations(ZoneList<Declaration*>* decls); - void VisitStatements(ZoneList<Statement*>* stmts); - - // AST node visit functions. -#define DECLARE_VISIT(type) virtual void Visit##type(type* node); - AST_NODE_LIST(DECLARE_VISIT) -#undef DECLARE_VISIT - - bool has_supported_syntax_; - - DISALLOW_COPY_AND_ASSIGN(CodeGenSelector); -}; - - static Handle<Code> MakeCode(FunctionLiteral* literal, Handle<Script> script, Handle<Context> context, @@ -117,12 +94,11 @@ static Handle<Code> MakeCode(FunctionLiteral* literal, !FLAG_always_fast_compiler) { if (FLAG_trace_bailout) PrintF("No hint to try fast\n"); } else { - CodeGenSelector selector; - CodeGenSelector::CodeGenTag code_gen = selector.Select(literal); - if (code_gen == CodeGenSelector::FAST) { - return FastCodeGenerator::MakeCode(literal, script, is_eval); + FullCodeGenSyntaxChecker checker; + checker.Check(literal); + if (checker.has_supported_syntax()) { + return FullCodeGenerator::MakeCode(literal, script, is_eval); } - ASSERT(code_gen == CodeGenSelector::NORMAL); } } return CodeGenerator::MakeCode(literal, script, is_eval); @@ -493,11 +469,12 @@ Handle<JSFunction> Compiler::BuildBoilerplate(FunctionLiteral* literal, // Generate code and return it. bool is_compiled = false; - if (FLAG_fast_compiler && literal->try_fast_codegen()) { - CodeGenSelector selector; - CodeGenSelector::CodeGenTag code_gen = selector.Select(literal); - if (code_gen == CodeGenSelector::FAST) { - code = FastCodeGenerator::MakeCode(literal, + if (FLAG_always_fast_compiler || + (FLAG_fast_compiler && literal->try_fast_codegen())) { + FullCodeGenSyntaxChecker checker; + checker.Check(literal); + if (checker.has_supported_syntax()) { + code = FullCodeGenerator::MakeCode(literal, script, false); // Not eval. is_compiled = true; @@ -571,418 +548,4 @@ void Compiler::SetFunctionInfo(Handle<JSFunction> fun, } -CodeGenSelector::CodeGenTag CodeGenSelector::Select(FunctionLiteral* fun) { - Scope* scope = fun->scope(); - - if (scope->num_heap_slots() > 0) { - // We support functions with a local context if they do not have - // parameters that need to be copied into the context. - for (int i = 0, len = scope->num_parameters(); i < len; i++) { - Slot* slot = scope->parameter(i)->slot(); - if (slot != NULL && slot->type() == Slot::CONTEXT) { - if (FLAG_trace_bailout) { - PrintF("Function has context-allocated parameters.\n"); - } - return NORMAL; - } - } - } - - has_supported_syntax_ = true; - VisitDeclarations(scope->declarations()); - if (!has_supported_syntax_) return NORMAL; - - VisitStatements(fun->body()); - return has_supported_syntax_ ? FAST : NORMAL; -} - - -#define BAILOUT(reason) \ - do { \ - if (FLAG_trace_bailout) { \ - PrintF("%s\n", reason); \ - } \ - has_supported_syntax_ = false; \ - return; \ - } while (false) - - -#define CHECK_BAILOUT \ - do { \ - if (!has_supported_syntax_) return; \ - } 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; - } -} - - -void CodeGenSelector::VisitDeclaration(Declaration* decl) { - Property* prop = decl->proxy()->AsProperty(); - if (prop != NULL) { - Visit(prop->obj()); - Visit(prop->key()); - } - - if (decl->fun() != NULL) { - Visit(decl->fun()); - } -} - - -void CodeGenSelector::VisitBlock(Block* stmt) { - VisitStatements(stmt->statements()); -} - - -void CodeGenSelector::VisitExpressionStatement(ExpressionStatement* stmt) { - Visit(stmt->expression()); -} - - -void CodeGenSelector::VisitEmptyStatement(EmptyStatement* stmt) {} - - -void CodeGenSelector::VisitIfStatement(IfStatement* stmt) { - Visit(stmt->condition()); - CHECK_BAILOUT; - Visit(stmt->then_statement()); - CHECK_BAILOUT; - Visit(stmt->else_statement()); -} - - -void CodeGenSelector::VisitContinueStatement(ContinueStatement* stmt) {} - - -void CodeGenSelector::VisitBreakStatement(BreakStatement* stmt) {} - - -void CodeGenSelector::VisitReturnStatement(ReturnStatement* stmt) { - Visit(stmt->expression()); -} - - -void CodeGenSelector::VisitWithEnterStatement(WithEnterStatement* stmt) { - Visit(stmt->expression()); -} - - -void CodeGenSelector::VisitWithExitStatement(WithExitStatement* stmt) {} - - -void CodeGenSelector::VisitSwitchStatement(SwitchStatement* stmt) { - BAILOUT("SwitchStatement"); -} - - -void CodeGenSelector::VisitDoWhileStatement(DoWhileStatement* stmt) { - Visit(stmt->cond()); - CHECK_BAILOUT; - Visit(stmt->body()); -} - - -void CodeGenSelector::VisitWhileStatement(WhileStatement* stmt) { - Visit(stmt->cond()); - CHECK_BAILOUT; - Visit(stmt->body()); -} - - -void CodeGenSelector::VisitForStatement(ForStatement* stmt) { - BAILOUT("ForStatement"); -} - - -void CodeGenSelector::VisitForInStatement(ForInStatement* stmt) { - BAILOUT("ForInStatement"); -} - - -void CodeGenSelector::VisitTryCatchStatement(TryCatchStatement* stmt) { - Visit(stmt->try_block()); - CHECK_BAILOUT; - Visit(stmt->catch_block()); -} - - -void CodeGenSelector::VisitTryFinallyStatement(TryFinallyStatement* stmt) { - Visit(stmt->try_block()); - CHECK_BAILOUT; - Visit(stmt->finally_block()); -} - - -void CodeGenSelector::VisitDebuggerStatement(DebuggerStatement* stmt) {} - - -void CodeGenSelector::VisitFunctionLiteral(FunctionLiteral* expr) {} - - -void CodeGenSelector::VisitFunctionBoilerplateLiteral( - FunctionBoilerplateLiteral* expr) { - BAILOUT("FunctionBoilerplateLiteral"); -} - - -void CodeGenSelector::VisitConditional(Conditional* expr) { - Visit(expr->condition()); - CHECK_BAILOUT; - Visit(expr->then_expression()); - CHECK_BAILOUT; - Visit(expr->else_expression()); -} - - -void CodeGenSelector::VisitSlot(Slot* expr) { - UNREACHABLE(); -} - - -void CodeGenSelector::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 - } - } -} - - -void CodeGenSelector::VisitLiteral(Literal* expr) {} - - -void CodeGenSelector::VisitRegExpLiteral(RegExpLiteral* expr) {} - - -void CodeGenSelector::VisitObjectLiteral(ObjectLiteral* expr) { - 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; - Visit(property->key()); - CHECK_BAILOUT; - Visit(property->value()); - CHECK_BAILOUT; - } -} - - -void CodeGenSelector::VisitArrayLiteral(ArrayLiteral* expr) { - ZoneList<Expression*>* subexprs = expr->values(); - for (int i = 0, len = subexprs->length(); i < len; i++) { - Expression* subexpr = subexprs->at(i); - if (subexpr->AsLiteral() != NULL) continue; - if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; - Visit(subexpr); - CHECK_BAILOUT; - } -} - - -void CodeGenSelector::VisitCatchExtensionObject(CatchExtensionObject* expr) { - Visit(expr->key()); - CHECK_BAILOUT; - Visit(expr->value()); -} - - -void CodeGenSelector::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"); - - Variable* var = expr->target()->AsVariableProxy()->AsVariable(); - 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"); - } - } - } else if (prop != NULL) { - Visit(prop->obj()); - CHECK_BAILOUT; - Visit(prop->key()); - CHECK_BAILOUT; - } else { - // This is a throw reference error. - BAILOUT("non-variable/non-property assignment"); - } - - Visit(expr->value()); -} - - -void CodeGenSelector::VisitThrow(Throw* expr) { - Visit(expr->exception()); -} - - -void CodeGenSelector::VisitProperty(Property* expr) { - Visit(expr->obj()); - CHECK_BAILOUT; - Visit(expr->key()); -} - - -void CodeGenSelector::VisitCall(Call* expr) { - 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 the identifier 'eval'"); - } else if (var != NULL && !var->is_this() && var->is_global()) { - // Calls to global variables are supported. - } else if (var != NULL && var->slot() != NULL && - var->slot()->type() == Slot::LOOKUP) { - BAILOUT("call to a lookup slot"); - } else if (fun->AsProperty() != NULL) { - Property* prop = fun->AsProperty(); - Visit(prop->obj()); - CHECK_BAILOUT; - Visit(prop->key()); - CHECK_BAILOUT; - } else { - // Otherwise the call is supported if the function expression is. - Visit(fun); - } - // Check all arguments to the call. - for (int i = 0; i < args->length(); i++) { - Visit(args->at(i)); - CHECK_BAILOUT; - } -} - - -void CodeGenSelector::VisitCallNew(CallNew* expr) { - Visit(expr->expression()); - CHECK_BAILOUT; - ZoneList<Expression*>* args = expr->arguments(); - // Check all arguments to the call - for (int i = 0; i < args->length(); i++) { - Visit(args->at(i)); - CHECK_BAILOUT; - } -} - - -void CodeGenSelector::VisitCallRuntime(CallRuntime* expr) { - // Check for inline runtime call - if (expr->name()->Get(0) == '_' && - CodeGenerator::FindInlineRuntimeLUT(expr->name()) != NULL) { - 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)); - CHECK_BAILOUT; - } -} - - -void CodeGenSelector::VisitUnaryOperation(UnaryOperation* expr) { - switch (expr->op()) { - case Token::VOID: - case Token::NOT: - case Token::TYPEOF: - Visit(expr->expression()); - break; - case Token::BIT_NOT: - BAILOUT("UnaryOperataion: BIT_NOT"); - case Token::DELETE: - BAILOUT("UnaryOperataion: DELETE"); - default: - BAILOUT("UnaryOperataion"); - } -} - - -void CodeGenSelector::VisitCountOperation(CountOperation* expr) { - Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); - Property* prop = expr->expression()->AsProperty(); - ASSERT(var == NULL || prop == NULL); - if (var != NULL) { - // All global variables are supported. - if (!var->is_global()) { - ASSERT(var->slot() != NULL); - Slot::Type type = var->slot()->type(); - if (type == Slot::LOOKUP) { - BAILOUT("CountOperation with lookup slot"); - } - } - } else if (prop != NULL) { - Visit(prop->obj()); - CHECK_BAILOUT; - Visit(prop->key()); - CHECK_BAILOUT; - } else { - // This is a throw reference error. - BAILOUT("CountOperation non-variable/non-property expression"); - } -} - - -void CodeGenSelector::VisitBinaryOperation(BinaryOperation* expr) { - Visit(expr->left()); - CHECK_BAILOUT; - Visit(expr->right()); -} - - -void CodeGenSelector::VisitCompareOperation(CompareOperation* expr) { - Visit(expr->left()); - CHECK_BAILOUT; - Visit(expr->right()); -} - - -void CodeGenSelector::VisitThisFunction(ThisFunction* expr) {} - -#undef BAILOUT -#undef CHECK_BAILOUT - - } } // namespace v8::internal |
