| Index: src/compiler.cc
|
| ===================================================================
|
| --- src/compiler.cc (revision 3062)
|
| +++ src/compiler.cc (working copy)
|
| @@ -32,6 +32,7 @@
|
| #include "compilation-cache.h"
|
| #include "compiler.h"
|
| #include "debug.h"
|
| +#include "fast-codegen.h"
|
| #include "oprofile-agent.h"
|
| #include "rewriter.h"
|
| #include "scopes.h"
|
| @@ -40,6 +41,32 @@
|
| namespace v8 {
|
| namespace internal {
|
|
|
| +#ifdef V8_TARGET_ARCH_IA32
|
| +
|
| +class CodeGenSelector: public AstVisitor {
|
| + public:
|
| + enum CodeGenTag { NORMAL, FAST };
|
| +
|
| + CodeGenSelector() : has_supported_syntax_(true) {}
|
| +
|
| + CodeGenTag Select(FunctionLiteral* fun);
|
| +
|
| + private:
|
| + 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);
|
| +};
|
| +
|
| +#endif
|
| +
|
| +
|
| static Handle<Code> MakeCode(FunctionLiteral* literal,
|
| Handle<Script> script,
|
| Handle<Context> context,
|
| @@ -79,8 +106,18 @@
|
| }
|
|
|
| // Generate code and return it.
|
| - Handle<Code> result = CodeGenerator::MakeCode(literal, script, is_eval);
|
| - return result;
|
| +#ifdef V8_TARGET_ARCH_IA32
|
| + if (FLAG_fast_compiler) {
|
| + CodeGenSelector selector;
|
| + CodeGenSelector::CodeGenTag code_gen = selector.Select(literal);
|
| + if (code_gen == CodeGenSelector::FAST) {
|
| + return FastCodeGenerator::MakeCode(literal, script);
|
| + }
|
| + ASSERT(code_gen == CodeGenSelector::NORMAL);
|
| + }
|
| +#endif
|
| +
|
| + return CodeGenerator::MakeCode(literal, script, is_eval);
|
| }
|
|
|
|
|
| @@ -416,4 +453,272 @@
|
| }
|
|
|
|
|
| +#ifdef V8_TARGET_ARCH_IA32
|
| +
|
| +CodeGenSelector::CodeGenTag CodeGenSelector::Select(FunctionLiteral* fun) {
|
| + Scope* scope = fun->scope();
|
| +
|
| + if (!scope->is_global_scope()) 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->body()->is_empty()) return NORMAL;
|
| +
|
| + has_supported_syntax_ = true;
|
| + 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::VisitStatements(ZoneList<Statement*>* stmts) {
|
| + for (int i = 0, len = stmts->length(); i < len; i++) {
|
| + CHECK_BAILOUT;
|
| + Visit(stmts->at(i));
|
| + }
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitDeclaration(Declaration* decl) {
|
| + BAILOUT("Declaration");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitBlock(Block* stmt) {
|
| + BAILOUT("Block");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitExpressionStatement(ExpressionStatement* stmt) {
|
| + Visit(stmt->expression());
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitEmptyStatement(EmptyStatement* stmt) {
|
| + BAILOUT("EmptyStatement");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitIfStatement(IfStatement* stmt) {
|
| + BAILOUT("IfStatement");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitContinueStatement(ContinueStatement* stmt) {
|
| + BAILOUT("ContinueStatement");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitBreakStatement(BreakStatement* stmt) {
|
| + BAILOUT("BreakStatement");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitReturnStatement(ReturnStatement* stmt) {
|
| + Visit(stmt->expression());
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitWithEnterStatement(WithEnterStatement* stmt) {
|
| + BAILOUT("WithEnterStatement");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitWithExitStatement(WithExitStatement* stmt) {
|
| + BAILOUT("WithExitStatement");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitSwitchStatement(SwitchStatement* stmt) {
|
| + BAILOUT("SwitchStatement");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitDoWhileStatement(DoWhileStatement* stmt) {
|
| + BAILOUT("DoWhileStatement");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitWhileStatement(WhileStatement* stmt) {
|
| + BAILOUT("WhileStatement");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitForStatement(ForStatement* stmt) {
|
| + BAILOUT("ForStatement");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitForInStatement(ForInStatement* stmt) {
|
| + BAILOUT("ForInStatement");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitTryCatchStatement(TryCatchStatement* stmt) {
|
| + BAILOUT("TryCatchStatement");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
|
| + BAILOUT("TryFinallyStatement");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitDebuggerStatement(DebuggerStatement* stmt) {
|
| + BAILOUT("DebuggerStatement");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitFunctionLiteral(FunctionLiteral* expr) {
|
| + BAILOUT("FunctionLiteral");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitFunctionBoilerplateLiteral(
|
| + FunctionBoilerplateLiteral* expr) {
|
| + BAILOUT("FunctionBoilerplateLiteral");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitConditional(Conditional* expr) {
|
| + BAILOUT("Conditional");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitSlot(Slot* expr) {
|
| + Slot::Type type = expr->type();
|
| + if (type != Slot::PARAMETER && type != Slot::LOCAL) {
|
| + BAILOUT("non-parameter/non-local slot reference");
|
| + }
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitVariableProxy(VariableProxy* expr) {
|
| + Expression* rewrite = expr->var()->rewrite();
|
| + if (rewrite == NULL) BAILOUT("global variable reference");
|
| + Visit(rewrite);
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitLiteral(Literal* expr) {
|
| + // All literals are supported.
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitRegExpLiteral(RegExpLiteral* expr) {
|
| + BAILOUT("RegExpLiteral");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitObjectLiteral(ObjectLiteral* expr) {
|
| + BAILOUT("ObjectLiteral");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitArrayLiteral(ArrayLiteral* expr) {
|
| + BAILOUT("ArrayLiteral");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitCatchExtensionObject(CatchExtensionObject* expr) {
|
| + BAILOUT("CatchExtensionObject");
|
| +}
|
| +
|
| +
|
| +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");
|
| +
|
| + Token::Value op = expr->op();
|
| + if (op == Token::INIT_CONST) BAILOUT("initialize constant");
|
| + if (op != Token::ASSIGN && op != Token::INIT_VAR) {
|
| + BAILOUT("compound assignment");
|
| + }
|
| +
|
| + Variable* var = expr->target()->AsVariableProxy()->AsVariable();
|
| + if (var == NULL || var->is_global()) BAILOUT("non-variable assignment");
|
| +
|
| + ASSERT(var->slot() != NULL);
|
| + Slot::Type type = var->slot()->type();
|
| + if (type != Slot::PARAMETER && type != Slot::LOCAL) {
|
| + BAILOUT("non-parameter/non-local slot assignment");
|
| + }
|
| +
|
| + Visit(expr->value());
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitThrow(Throw* expr) {
|
| + BAILOUT("Throw");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitProperty(Property* expr) {
|
| + BAILOUT("Property");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitCall(Call* expr) {
|
| + BAILOUT("Call");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitCallNew(CallNew* expr) {
|
| + BAILOUT("CallNew");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitCallRuntime(CallRuntime* expr) {
|
| + BAILOUT("CallRuntime");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitUnaryOperation(UnaryOperation* expr) {
|
| + BAILOUT("UnaryOperation");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitCountOperation(CountOperation* expr) {
|
| + BAILOUT("CountOperation");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitBinaryOperation(BinaryOperation* expr) {
|
| + BAILOUT("BinaryOperation");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitCompareOperation(CompareOperation* expr) {
|
| + BAILOUT("CompareOperation");
|
| +}
|
| +
|
| +
|
| +void CodeGenSelector::VisitThisFunction(ThisFunction* expr) {
|
| + BAILOUT("ThisFunction");
|
| +}
|
| +
|
| +#undef BAILOUT
|
| +#undef CHECK_BAILOUT
|
| +
|
| +#endif // V8_TARGET_ARCH_IA32
|
| +
|
| +
|
| } } // namespace v8::internal
|
|
|