Revision: 3206 Author: [email protected] Date: Tue Nov 3 06:48:59 2009 Log: Begin using the top-level code generator for code that is inside directly-applied function literals that are themselves compiled with the top-level code generator.
The choice is guarded by a test that the function is anonymous (thus not expected to be recursive) and not in a loop. A compilation hint is set in the shared function info and used to make the choice. Review URL: http://codereview.chromium.org/341081 http://code.google.com/p/v8/source/detail?r=3206 Modified: /branches/bleeding_edge/src/arm/fast-codegen-arm.cc /branches/bleeding_edge/src/ast.h /branches/bleeding_edge/src/codegen.cc /branches/bleeding_edge/src/compiler.cc /branches/bleeding_edge/src/fast-codegen.cc /branches/bleeding_edge/src/fast-codegen.h /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc /branches/bleeding_edge/src/objects-inl.h /branches/bleeding_edge/src/objects.h /branches/bleeding_edge/src/x64/fast-codegen-x64.cc ======================================= --- /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Tue Nov 3 04:47:19 2009 +++ /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Tue Nov 3 06:48:59 2009 @@ -92,7 +92,9 @@ } { Comment cmnt(masm_, "[ Body"); + ASSERT(loop_depth() == 0); VisitStatements(fun->body()); + ASSERT(loop_depth() == 0); } { Comment cmnt(masm_, "[ return <undefined>;"); @@ -323,7 +325,7 @@ void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { - Comment cmnt(masm_, "[ RegExp Literal"); + Comment cmnt(masm_, "[ RegExpLiteral"); Label done; // Registers will be used as follows: // r4 = JS function, literals array @@ -818,8 +820,16 @@ EmitCallWithStub(expr); } } else { - // Call to some other function expression. - Visit(expr->expression()); + // Call to some other expression. If the expression is an anonymous + // function literal not called in a loop, mark it as one that should + // also use the fast code generator. + FunctionLiteral* lit = fun->AsFunctionLiteral(); + if (lit != NULL && + lit->name()->Equals(Heap::empty_string()) && + loop_depth() == 0) { + lit->set_try_fast_codegen(true); + } + Visit(fun); // Load global receiver object. __ ldr(r1, CodeGenerator::GlobalObject()); __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); @@ -890,7 +900,6 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { Comment cmnt(masm_, "[ UnaryOperation"); - switch (expr->op()) { case Token::VOID: Visit(expr->expression()); @@ -988,12 +997,12 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { - VariableProxy* v = expr->expression()->AsVariableProxy(); - ASSERT(v->AsVariable() != NULL); - ASSERT(v->AsVariable()->is_global()); - - Visit(v); - + Comment cmnt(masm_, "[ CountOperation"); + VariableProxy* proxy = expr->expression()->AsVariableProxy(); + ASSERT(proxy->AsVariable() != NULL); + ASSERT(proxy->AsVariable()->is_global()); + + Visit(proxy); __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS); switch (expr->context()) { @@ -1020,7 +1029,7 @@ __ CallRuntime(Runtime::kNumberSub, 2); } // Call Store IC. - __ mov(r2, Operand(v->AsVariable()->name())); + __ mov(r2, Operand(proxy->AsVariable()->name())); __ ldr(ip, CodeGenerator::GlobalObject()); __ push(ip); Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); @@ -1063,6 +1072,7 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { + Comment cmnt(masm_, "[ BinaryOperation"); switch (expr->op()) { case Token::COMMA: ASSERT_EQ(Expression::kEffect, expr->left()->context()); @@ -1108,6 +1118,7 @@ void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { + Comment cmnt(masm_, "[ CompareOperation"); ASSERT_EQ(Expression::kValue, expr->left()->context()); ASSERT_EQ(Expression::kValue, expr->right()->context()); Visit(expr->left()); ======================================= --- /branches/bleeding_edge/src/ast.h Fri Oct 30 07:06:48 2009 +++ /branches/bleeding_edge/src/ast.h Tue Nov 3 06:48:59 2009 @@ -1302,7 +1302,8 @@ is_expression_(is_expression), loop_nesting_(0), function_token_position_(RelocInfo::kNoPosition), - inferred_name_(Heap::empty_string()) { + inferred_name_(Heap::empty_string()), + try_fast_codegen_(false) { #ifdef DEBUG already_compiled_ = false; #endif @@ -1344,6 +1345,9 @@ void set_inferred_name(Handle<String> inferred_name) { inferred_name_ = inferred_name; } + + bool try_fast_codegen() { return try_fast_codegen_; } + void set_try_fast_codegen(bool flag) { try_fast_codegen_ = flag; } #ifdef DEBUG void mark_as_compiled() { @@ -1368,6 +1372,7 @@ int loop_nesting_; int function_token_position_; Handle<String> inferred_name_; + bool try_fast_codegen_; #ifdef DEBUG bool already_compiled_; #endif ======================================= --- /branches/bleeding_edge/src/codegen.cc Thu Oct 29 06:17:11 2009 +++ /branches/bleeding_edge/src/codegen.cc Tue Nov 3 06:48:59 2009 @@ -271,6 +271,7 @@ lit->has_only_this_property_assignments(), lit->has_only_simple_this_property_assignments(), *lit->this_property_assignments()); + fun->shared()->set_try_fast_codegen(lit->try_fast_codegen()); } ======================================= --- /branches/bleeding_edge/src/compiler.cc Tue Nov 3 04:47:19 2009 +++ /branches/bleeding_edge/src/compiler.cc Tue Nov 3 06:48:59 2009 @@ -83,7 +83,8 @@ static Handle<Code> MakeCode(FunctionLiteral* literal, Handle<Script> script, Handle<Context> context, - bool is_eval) { + bool is_eval, + Handle<SharedFunctionInfo> shared) { ASSERT(literal != NULL); // Rewrite the AST by introducing .result assignments where needed. @@ -120,12 +121,21 @@ // Generate code and return it. if (FLAG_fast_compiler) { - CodeGenSelector selector; - CodeGenSelector::CodeGenTag code_gen = selector.Select(literal); - if (code_gen == CodeGenSelector::FAST) { - return FastCodeGenerator::MakeCode(literal, script, is_eval); - } - ASSERT(code_gen == CodeGenSelector::NORMAL); + // If there is no shared function info, try the fast code + // generator for code in the global scope. Otherwise obey the + // explicit hint in the shared function info. + if (shared.is_null() && !literal->scope()->is_global_scope()) { + if (FLAG_trace_bailout) PrintF("Non-global scope\n"); + } else if (!shared.is_null() && !shared->try_fast_codegen()) { + 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); + } + ASSERT(code_gen == CodeGenSelector::NORMAL); + } } return CodeGenerator::MakeCode(literal, script, is_eval); } @@ -210,7 +220,8 @@ HistogramTimerScope timer(rate); // Compile the code. - Handle<Code> code = MakeCode(lit, script, context, is_eval); + Handle<Code> code = MakeCode(lit, script, context, is_eval, + Handle<SharedFunctionInfo>::null()); // Check for stack-overflow exceptions. if (code.is_null()) { @@ -411,7 +422,8 @@ HistogramTimerScope timer(&Counters::compile_lazy); // Compile the code. - Handle<Code> code = MakeCode(lit, script, Handle<Context>::null(), false); + Handle<Code> code = MakeCode(lit, script, Handle<Context>::null(), false, + shared); // Check for stack-overflow exception. if (code.is_null()) { @@ -465,16 +477,17 @@ CodeGenSelector::CodeGenTag CodeGenSelector::Select(FunctionLiteral* fun) { Scope* scope = fun->scope(); - - if (!scope->is_global_scope()) { - if (FLAG_trace_bailout) PrintF("Non-global scope\n"); + if (scope->num_heap_slots() != 0) { + if (FLAG_trace_bailout) PrintF("function has context slots\n"); return NORMAL; } - ASSERT(scope->num_heap_slots() == 0); - ASSERT(scope->arguments() == NULL); + if (scope->arguments() != NULL) { + if (FLAG_trace_bailout) PrintF("function uses 'arguments'\n"); + return NORMAL; + } has_supported_syntax_ = true; - VisitDeclarations(fun->scope()->declarations()); + VisitDeclarations(scope->declarations()); if (!has_supported_syntax_) return NORMAL; VisitStatements(fun->body()); ======================================= --- /branches/bleeding_edge/src/fast-codegen.cc Mon Nov 2 07:01:06 2009 +++ /branches/bleeding_edge/src/fast-codegen.cc Tue Nov 3 06:48:59 2009 @@ -75,6 +75,7 @@ void FastCodeGenerator::VisitDeclarations( ZoneList<Declaration*>* declarations) { + Comment cmnt(masm_, "[ Declarations"); int length = declarations->length(); int globals = 0; for (int i = 0; i < length; i++) { @@ -289,6 +290,7 @@ void FastCodeGenerator::VisitIfStatement(IfStatement* stmt) { + Comment cmnt(masm_, "[ IfStatement"); // Expressions cannot recursively enter statements, there are no labels in // the state. ASSERT_EQ(NULL, true_label_); @@ -350,9 +352,11 @@ void FastCodeGenerator::VisitForStatement(ForStatement* stmt) { + Comment cmnt(masm_, "[ ForStatement"); Label test, body, exit; if (stmt->init() != NULL) Visit(stmt->init()); + increment_loop_depth(); // Emit the test at the bottom of the loop (even if empty). __ jmp(&test); __ bind(&body); @@ -377,6 +381,7 @@ } __ bind(&exit); + decrement_loop_depth(); } @@ -407,6 +412,7 @@ void FastCodeGenerator::VisitConditional(Conditional* expr) { + Comment cmnt(masm_, "[ Conditional"); ASSERT_EQ(Expression::kTest, expr->condition()->context()); ASSERT_EQ(expr->context(), expr->then_expression()->context()); ASSERT_EQ(expr->context(), expr->else_expression()->context()); @@ -447,6 +453,7 @@ void FastCodeGenerator::VisitLiteral(Literal* expr) { + Comment cmnt(masm_, "[ Literal"); Move(expr->context(), expr); } ======================================= --- /branches/bleeding_edge/src/fast-codegen.h Mon Nov 2 05:30:24 2009 +++ /branches/bleeding_edge/src/fast-codegen.h Tue Nov 3 06:48:59 2009 @@ -43,6 +43,7 @@ function_(NULL), script_(script), is_eval_(is_eval), + loop_depth_(0), true_label_(NULL), false_label_(NULL) { } @@ -93,6 +94,13 @@ void SetReturnPosition(FunctionLiteral* fun); void SetStatementPosition(Statement* stmt); void SetSourcePosition(int pos); + + int loop_depth() { return loop_depth_; } + void increment_loop_depth() { loop_depth_++; } + void decrement_loop_depth() { + ASSERT(loop_depth_ > 0); + loop_depth_--; + } // AST node visit functions. #define DECLARE_VISIT(type) virtual void Visit##type(type* node); @@ -107,6 +115,7 @@ Handle<Script> script_; bool is_eval_; Label return_label_; + int loop_depth_; Label* true_label_; Label* false_label_; ======================================= --- /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc Tue Nov 3 04:47:19 2009 +++ /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc Tue Nov 3 06:48:59 2009 @@ -85,7 +85,9 @@ } { Comment cmnt(masm_, "[ Body"); + ASSERT(loop_depth() == 0); VisitStatements(fun->body()); + ASSERT(loop_depth() == 0); } { Comment cmnt(masm_, "[ return <undefined>;"); @@ -342,7 +344,7 @@ void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { - Comment cmnt(masm_, "[ RegExp Literal"); + Comment cmnt(masm_, "[ RegExpLiteral"); Label done; // Registers will be used as follows: // edi = JS function. @@ -840,8 +842,16 @@ EmitCallWithStub(expr); } } else { - // Call to some other function expression. - Visit(expr->expression()); + // Call to some other expression. If the expression is an anonymous + // function literal not called in a loop, mark it as one that should + // also use the fast code generator. + FunctionLiteral* lit = fun->AsFunctionLiteral(); + if (lit != NULL && + lit->name()->Equals(Heap::empty_string()) && + loop_depth() == 0) { + lit->set_try_fast_codegen(true); + } + Visit(fun); // Load global receiver object. __ mov(ebx, CodeGenerator::GlobalObject()); __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); @@ -849,6 +859,7 @@ EmitCallWithStub(expr); } } + void FastCodeGenerator::VisitCallNew(CallNew* expr) { Comment cmnt(masm_, "[ CallNew"); @@ -910,7 +921,6 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { Comment cmnt(masm_, "[ UnaryOperation"); - switch (expr->op()) { case Token::VOID: Visit(expr->expression()); @@ -1003,12 +1013,12 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { - VariableProxy* v = expr->expression()->AsVariableProxy(); - ASSERT(v->AsVariable() != NULL); - ASSERT(v->AsVariable()->is_global()); - - Visit(v); - + Comment cmnt(masm_, "[ CountOperation"); + VariableProxy* proxy = expr->expression()->AsVariableProxy(); + ASSERT(proxy->AsVariable() != NULL); + ASSERT(proxy->AsVariable()->is_global()); + + Visit(proxy); __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); switch (expr->context()) { @@ -1034,7 +1044,7 @@ __ CallRuntime(Runtime::kNumberSub, 2); } // Call Store IC. - __ mov(ecx, v->AsVariable()->name()); + __ mov(ecx, proxy->AsVariable()->name()); __ push(CodeGenerator::GlobalObject()); Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); __ call(ic, RelocInfo::CODE_TARGET); @@ -1076,6 +1086,7 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { + Comment cmnt(masm_, "[ BinaryOperation"); switch (expr->op()) { case Token::COMMA: ASSERT_EQ(Expression::kEffect, expr->left()->context()); @@ -1120,6 +1131,7 @@ void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { + Comment cmnt(masm_, "[ CompareOperation"); ASSERT_EQ(Expression::kValue, expr->left()->context()); ASSERT_EQ(Expression::kValue, expr->right()->context()); Visit(expr->left()); ======================================= --- /branches/bleeding_edge/src/objects-inl.h Thu Oct 29 06:17:11 2009 +++ /branches/bleeding_edge/src/objects-inl.h Tue Nov 3 06:48:59 2009 @@ -2538,7 +2538,10 @@ BOOL_GETTER(SharedFunctionInfo, compiler_hints, has_only_simple_this_property_assignments, kHasOnlySimpleThisPropertyAssignments) - +BOOL_ACCESSORS(SharedFunctionInfo, + compiler_hints, + try_fast_codegen, + kTryFastCodegen) INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset) INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count, ======================================= --- /branches/bleeding_edge/src/objects.h Thu Oct 29 06:17:11 2009 +++ /branches/bleeding_edge/src/objects.h Tue Nov 3 06:48:59 2009 @@ -3386,6 +3386,9 @@ // this.x = y; where y is either a constant or refers to an argument. inline bool has_only_simple_this_property_assignments(); + inline bool try_fast_codegen(); + inline void set_try_fast_codegen(bool flag); + // For functions which only contains this property assignments this provides // access to the names for the properties assigned. DECL_ACCESSORS(this_property_assignments, Object) @@ -3466,6 +3469,7 @@ // Bit positions in compiler_hints. static const int kHasOnlyThisPropertyAssignments = 0; static const int kHasOnlySimpleThisPropertyAssignments = 1; + static const int kTryFastCodegen = 2; DISALLOW_IMPLICIT_CONSTRUCTORS(SharedFunctionInfo); }; ======================================= --- /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Tue Nov 3 04:47:19 2009 +++ /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Tue Nov 3 06:48:59 2009 @@ -84,7 +84,9 @@ } { Comment cmnt(masm_, "[ Body"); + ASSERT(loop_depth() == 0); VisitStatements(fun->body()); + ASSERT(loop_depth() == 0); } { Comment cmnt(masm_, "[ return <undefined>;"); @@ -360,7 +362,7 @@ void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { - Comment cmnt(masm_, "[ RegExp Literal"); + Comment cmnt(masm_, "[ RegExpLiteral"); Label done; // Registers will be used as follows: // rdi = JS function. @@ -855,8 +857,16 @@ EmitCallWithStub(expr); } } else { - // Call to some other function expression. - Visit(expr->expression()); + // Call to some other expression. If the expression is an anonymous + // function literal not called in a loop, mark it as one that should + // also use the fast code generator. + FunctionLiteral* lit = fun->AsFunctionLiteral(); + if (lit != NULL && + lit->name()->Equals(Heap::empty_string()) && + loop_depth() == 0) { + lit->set_try_fast_codegen(true); + } + Visit(fun); // Load global receiver object. __ movq(rbx, CodeGenerator::GlobalObject()); __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); @@ -925,12 +935,12 @@ } void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { - VariableProxy* v = expr->expression()->AsVariableProxy(); - ASSERT(v->AsVariable() != NULL); - ASSERT(v->AsVariable()->is_global()); - - Visit(v); - + Comment cmnt(masm_, "[ CountOperation"); + VariableProxy* proxy = expr->expression()->AsVariableProxy(); + ASSERT(proxy->AsVariable() != NULL); + ASSERT(proxy->AsVariable()->is_global()); + + Visit(proxy); __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); switch (expr->context()) { @@ -956,7 +966,7 @@ __ CallRuntime(Runtime::kNumberSub, 2); } // Call Store IC. - __ Move(rcx, v->AsVariable()->name()); + __ Move(rcx, proxy->AsVariable()->name()); __ push(CodeGenerator::GlobalObject()); Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); __ call(ic, RelocInfo::CODE_TARGET); @@ -999,7 +1009,6 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { Comment cmnt(masm_, "[ UnaryOperation"); - switch (expr->op()) { case Token::VOID: Visit(expr->expression()); @@ -1092,6 +1101,7 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { + Comment cmnt(masm_, "[ BinaryOperation"); switch (expr->op()) { case Token::COMMA: ASSERT_EQ(Expression::kEffect, expr->left()->context()); @@ -1136,6 +1146,7 @@ void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { + Comment cmnt(masm_, "[ CompareOperation"); ASSERT_EQ(Expression::kValue, expr->left()->context()); ASSERT_EQ(Expression::kValue, expr->right()->context()); Visit(expr->left()); --~--~---------~--~----~------------~-------~--~----~ v8-dev mailing list [email protected] http://groups.google.com/group/v8-dev -~----------~----~----~----~------~----~------~--~---
