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
-~----------~----~----~----~------~----~------~--~---

Reply via email to