Revision: 3744
Author: [email protected]
Date: Fri Jan 29 03:55:40 2010
Log: Introduce a stack-allocated structure to encapsulate compile-time information.

Use it to hold the possible shared function info, the possible
receiver, and the compilation loop nesting depth.  Remove loop nesting
from FunctionLiteral AST nodes.

Review URL: http://codereview.chromium.org/552232
http://code.google.com/p/v8/source/detail?r=3744

Modified:
 /branches/bleeding_edge/src/arm/codegen-arm.cc
 /branches/bleeding_edge/src/arm/codegen-arm.h
 /branches/bleeding_edge/src/ast.h
 /branches/bleeding_edge/src/codegen.cc
 /branches/bleeding_edge/src/compiler.cc
 /branches/bleeding_edge/src/compiler.h
 /branches/bleeding_edge/src/fast-codegen.cc
 /branches/bleeding_edge/src/fast-codegen.h
 /branches/bleeding_edge/src/handles.cc
 /branches/bleeding_edge/src/ia32/codegen-ia32.cc
 /branches/bleeding_edge/src/ia32/codegen-ia32.h
 /branches/bleeding_edge/src/x64/codegen-x64.cc
 /branches/bleeding_edge/src/x64/codegen-x64.h

=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.cc      Thu Jan 28 04:41:27 2010
+++ /branches/bleeding_edge/src/arm/codegen-arm.cc      Fri Jan 29 03:55:40 2010
@@ -142,7 +142,7 @@
 // r1: called JS function
 // cp: callee's context

-void CodeGenerator::GenCode(FunctionLiteral* fun) {
+void CodeGenerator::GenCode(FunctionLiteral* fun, CompilationInfo* info) {
   // Record the position for debugging purposes.
   CodeForFunctionPosition(fun);

=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.h       Wed Jan 27 06:07:12 2010
+++ /branches/bleeding_edge/src/arm/codegen-arm.h       Fri Jan 29 03:55:40 2010
@@ -32,6 +32,7 @@
 namespace internal {

 // Forward declarations
+class CompilationInfo;
 class DeferredCode;
 class RegisterAllocator;
 class RegisterFile;
@@ -153,7 +154,8 @@
   // be called by compiler.cc.
   static Handle<Code> MakeCode(FunctionLiteral* fun,
                                Handle<Script> script,
-                               bool is_eval);
+                               bool is_eval,
+                               CompilationInfo* info);

   // Printing of AST, etc. as requested by flags.
   static void MakeCodePrologue(FunctionLiteral* fun);
@@ -239,7 +241,7 @@
   inline void VisitStatementsAndSpill(ZoneList<Statement*>* statements);

   // Main code generation function
-  void GenCode(FunctionLiteral* fun);
+  void GenCode(FunctionLiteral* fun, CompilationInfo* info);

   // The following are used by class Reference.
   void LoadReference(Reference* ref);
=======================================
--- /branches/bleeding_edge/src/ast.h   Fri Jan 29 01:42:13 2010
+++ /branches/bleeding_edge/src/ast.h   Fri Jan 29 03:55:40 2010
@@ -1331,7 +1331,6 @@
         start_position_(start_position),
         end_position_(end_position),
         is_expression_(is_expression),
-        loop_nesting_(0),
         function_token_position_(RelocInfo::kNoPosition),
         inferred_name_(Heap::empty_string()),
         try_full_codegen_(false) {
@@ -1365,9 +1364,6 @@
   int num_parameters() { return num_parameters_; }

   bool AllowsLazyCompilation();
-
-  bool loop_nesting() const { return loop_nesting_; }
-  void set_loop_nesting(int nesting) { loop_nesting_ = nesting; }

   Handle<String> inferred_name() const  { return inferred_name_; }
   void set_inferred_name(Handle<String> inferred_name) {
@@ -1396,7 +1392,6 @@
   int start_position_;
   int end_position_;
   bool is_expression_;
-  int loop_nesting_;
   int function_token_position_;
   Handle<String> inferred_name_;
   bool try_full_codegen_;
=======================================
--- /branches/bleeding_edge/src/codegen.cc      Wed Jan 27 03:08:32 2010
+++ /branches/bleeding_edge/src/codegen.cc      Fri Jan 29 03:55:40 2010
@@ -216,7 +216,8 @@
 // the compiler.cc code.
 Handle<Code> CodeGenerator::MakeCode(FunctionLiteral* fun,
                                      Handle<Script> script,
-                                     bool is_eval) {
+                                     bool is_eval,
+                                     CompilationInfo* info) {
   if (!script->IsUndefined() && !script->source()->IsUndefined()) {
     int len = String::cast(script->source())->length();
     Counters::total_old_codegen_source_size.Increment(len);
@@ -226,7 +227,7 @@
   const int kInitialBufferSize = 4 * KB;
   CodeGenerator cgen(kInitialBufferSize, script, is_eval);
   CodeGeneratorScope scope(&cgen);
-  cgen.GenCode(fun);
+  cgen.GenCode(fun, info);
   if (cgen.HasStackOverflow()) {
     ASSERT(!Top::has_pending_exception());
     return Handle<Code>::null();
=======================================
--- /branches/bleeding_edge/src/compiler.cc     Fri Jan 29 01:52:51 2010
+++ /branches/bleeding_edge/src/compiler.cc     Fri Jan 29 03:55:40 2010
@@ -48,8 +48,7 @@
                              Handle<Script> script,
                              Handle<Context> context,
                              bool is_eval,
-                             Handle<SharedFunctionInfo> shared,
-                             Handle<Object> receiver) {
+                             CompilationInfo* info) {
   ASSERT(literal != NULL);

   // Rewrite the AST by introducing .result assignments where needed.
@@ -98,6 +97,7 @@
   // incompatible.
   CHECK(!FLAG_always_full_compiler || !FLAG_always_fast_compiler);

+  Handle<SharedFunctionInfo> shared = info->shared_info();
   bool is_run_once = (shared.is_null())
       ? literal->scope()->is_global_scope()
       : (shared->is_toplevel() || shared->try_full_codegen());
@@ -110,8 +110,8 @@
     }
   } else if (FLAG_always_fast_compiler ||
              (FLAG_fast_compiler && !is_run_once)) {
-    FastCodeGenSyntaxChecker checker(receiver);
-    checker.Check(literal);
+    FastCodeGenSyntaxChecker checker;
+    checker.Check(literal, info);
     if (checker.has_supported_syntax()) {
       AstLabeler labeler;
       labeler.Label(literal);
@@ -119,7 +119,7 @@
     // Does not yet generate code.
   }

-  return CodeGenerator::MakeCode(literal, script, is_eval);
+  return CodeGenerator::MakeCode(literal, script, is_eval, info);
 }


@@ -204,12 +204,10 @@
   HistogramTimerScope timer(rate);

   // Compile the code.
-  Handle<Code> code = MakeCode(lit,
-                               script,
-                               context,
-                               is_eval,
-                               Handle<SharedFunctionInfo>::null(),
-                               Handle<Object>::null());  // No receiver.
+  CompilationInfo info(Handle<SharedFunctionInfo>::null(),
+                       Handle<Object>::null(),  // No receiver.
+                       0);  // Not nested in a loop.
+  Handle<Code> code = MakeCode(lit, script, context, is_eval, &info);

   // Check for stack-overflow exceptions.
   if (code.is_null()) {
@@ -370,9 +368,7 @@
 }


-bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared,
-                           Handle<Object> receiver,
-                           int loop_nesting) {
+bool Compiler::CompileLazy(CompilationInfo* info) {
   CompilationZoneScope zone_scope(DELETE_ON_EXIT);

   // The VM is in the COMPILER state until exiting this function.
@@ -381,6 +377,7 @@
   PostponeInterruptsScope postpone;

   // Compute name, source code and script data.
+  Handle<SharedFunctionInfo> shared = info->shared_info();
   Handle<String> name(String::cast(shared->name()));
   Handle<Script> script(Script::cast(shared->script()));

@@ -401,9 +398,6 @@
     ASSERT(Top::has_pending_exception());
     return false;
   }
-
-  // Update the loop nesting in the function literal.
-  lit->set_loop_nesting(loop_nesting);

   // Measure how long it takes to do the lazy compilation; only take
   // the rest of the function into account to avoid overlap with the
@@ -415,8 +409,7 @@
                                script,
                                Handle<Context>::null(),
                                false,
-                               shared,
-                               receiver);
+                               info);

   // Check for stack-overflow exception.
   if (code.is_null()) {
@@ -497,6 +490,10 @@
     // Generate code and return it.  The way that the compilation mode
     // is controlled by the command-line flags is described in
     // the static helper function MakeCode.
+    CompilationInfo info(Handle<SharedFunctionInfo>::null(),
+                         Handle<Object>::null(),  // No receiver.
+                         0);  // Not nested in a loop.
+
     CHECK(!FLAG_always_full_compiler || !FLAG_always_fast_compiler);
     bool is_run_once = literal->try_full_codegen();
     bool is_compiled = false;
@@ -513,8 +510,8 @@
                (FLAG_fast_compiler && !is_run_once)) {
       // Since we are not lazily compiling we do not have a receiver to
       // specialize for.
-      FastCodeGenSyntaxChecker checker(Handle<Object>::null());
-      checker.Check(literal);
+      FastCodeGenSyntaxChecker checker;
+      checker.Check(literal, &info);
       if (checker.has_supported_syntax()) {
         AstLabeler label_nodes;
         label_nodes.Label(literal);
@@ -526,7 +523,8 @@
       // We fall back to the classic V8 code generator.
       code = CodeGenerator::MakeCode(literal,
                                      script,
-                                     false);  // Not eval.
+                                     false,  // Not eval.
+                                     &info);
     }

     // Check for stack-overflow exception.
=======================================
--- /branches/bleeding_edge/src/compiler.h      Fri Jan 29 01:52:51 2010
+++ /branches/bleeding_edge/src/compiler.h      Fri Jan 29 03:55:40 2010
@@ -35,6 +35,31 @@
 namespace v8 {
 namespace internal {

+// CompilationInfo encapsulates some information known at compile time.
+class CompilationInfo BASE_EMBEDDED {
+ public:
+  CompilationInfo(Handle<SharedFunctionInfo> shared_info,
+                  Handle<Object> receiver,
+                  int loop_nesting)
+      : shared_info_(shared_info),
+        receiver_(receiver_),
+        loop_nesting_(loop_nesting) {
+  }
+
+  Handle<SharedFunctionInfo> shared_info() { return shared_info_; }
+
+  bool has_receiver() { return !receiver_.is_null(); }
+  Handle<Object> receiver() { return receiver_; }
+
+  int loop_nesting() { return loop_nesting_; }
+
+ private:
+  Handle<SharedFunctionInfo> shared_info_;
+  Handle<Object> receiver_;
+  int loop_nesting_;
+};
+
+
 // The V8 compiler
 //
// General strategy: Source code is translated into an anonymous function w/o
@@ -70,9 +95,7 @@
   // Compile from function info (used for lazy compilation). Returns
   // true on success and false if the compilation resulted in a stack
   // overflow.
-  static bool CompileLazy(Handle<SharedFunctionInfo> shared,
-                          Handle<Object> receiver,
-                          int loop_nesting);
+  static bool CompileLazy(CompilationInfo* info);

   // Compile a function boilerplate object (the function is possibly
   // lazily compiled). Called recursively from a backend code
=======================================
--- /branches/bleeding_edge/src/fast-codegen.cc Fri Jan 29 01:52:51 2010
+++ /branches/bleeding_edge/src/fast-codegen.cc Fri Jan 29 03:55:40 2010
@@ -49,9 +49,10 @@
   } while (false)


-void FastCodeGenSyntaxChecker::Check(FunctionLiteral* fun) {
+void FastCodeGenSyntaxChecker::Check(FunctionLiteral* fun,
+                                     CompilationInfo* info) {
   // We do not specialize if we do not have a receiver.
-  if (receiver().is_null()) BAILOUT("No receiver");
+  if (!info->has_receiver()) BAILOUT("No receiver");

   // We do not support stack or heap slots (both of which require
   // allocation).
@@ -253,10 +254,11 @@
   // symbol but we do not assume that.
   Literal* key = prop->key()->AsLiteral();
   if (key != NULL && key->handle()->IsString()) {
+    Handle<Object> receiver = info()->receiver();
     Handle<String> name = Handle<String>::cast(key->handle());
     LookupResult lookup;
-    receiver()->Lookup(*name, &lookup);
- if (lookup.holder() != *receiver()) BAILOUT("Non-own property assignment");
+    receiver->Lookup(*name, &lookup);
+ if (lookup.holder() != *receiver) BAILOUT("Non-own property assignment");
     if (!lookup.type() == FIELD) BAILOUT("Non-field property assignment");
   } else {
     UNREACHABLE();
=======================================
--- /branches/bleeding_edge/src/fast-codegen.h  Fri Jan 29 01:52:51 2010
+++ /branches/bleeding_edge/src/fast-codegen.h  Fri Jan 29 03:55:40 2010
@@ -31,19 +31,20 @@
 #include "v8.h"

 #include "ast.h"
+#include "compiler.h"

 namespace v8 {
 namespace internal {

 class FastCodeGenSyntaxChecker: public AstVisitor {
  public:
-  explicit FastCodeGenSyntaxChecker(Handle<Object> receiver)
-      : receiver_(receiver), has_supported_syntax_(true) {
+  explicit FastCodeGenSyntaxChecker()
+      : info_(NULL), has_supported_syntax_(true) {
   }

-  void Check(FunctionLiteral* fun);
-
-  Handle<Object> receiver() { return receiver_; }
+  void Check(FunctionLiteral* fun, CompilationInfo* info);
+
+  CompilationInfo* info() { return info_; }
   bool has_supported_syntax() { return has_supported_syntax_; }

  private:
@@ -55,7 +56,7 @@
   AST_NODE_LIST(DECLARE_VISIT)
 #undef DECLARE_VISIT

-  Handle<Object> receiver_;
+  CompilationInfo* info_;
   bool has_supported_syntax_;

   DISALLOW_COPY_AND_ASSIGN(FastCodeGenSyntaxChecker);
=======================================
--- /branches/bleeding_edge/src/handles.cc      Fri Jan 29 01:52:51 2010
+++ /branches/bleeding_edge/src/handles.cc      Fri Jan 29 03:55:40 2010
@@ -31,6 +31,7 @@
 #include "api.h"
 #include "arguments.h"
 #include "bootstrapper.h"
+#include "codegen.h"
 #include "compiler.h"
 #include "debug.h"
 #include "execution.h"
@@ -672,13 +673,11 @@
 }


-static bool CompileLazyHelper(Handle<SharedFunctionInfo> shared,
-                              Handle<Object> receiver,
-                              ClearExceptionFlag flag,
-                              int loop_nesting) {
+static bool CompileLazyHelper(CompilationInfo* info,
+                              ClearExceptionFlag flag) {
   // Compile the source information to a code object.
-  ASSERT(!shared->is_compiled());
-  bool result = Compiler::CompileLazy(shared, receiver, loop_nesting);
+  ASSERT(!info->shared_info()->is_compiled());
+  bool result = Compiler::CompileLazy(info);
   ASSERT(result != Top::has_pending_exception());
   if (!result && flag == CLEAR_EXCEPTION) Top::clear_pending_exception();
   return result;
@@ -687,16 +686,17 @@

 bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
                        ClearExceptionFlag flag) {
-  return CompileLazyHelper(shared, Handle<Object>::null(), flag, 0);
+  CompilationInfo info(shared, Handle<Object>::null(), 0);
+  return CompileLazyHelper(&info, flag);
 }


 bool CompileLazy(Handle<JSFunction> function,
                  Handle<Object> receiver,
                  ClearExceptionFlag flag) {
-  // Compile the source information to a code object.
   Handle<SharedFunctionInfo> shared(function->shared());
-  bool result = CompileLazyHelper(shared, receiver, flag, 0);
+  CompilationInfo info(shared, receiver, 0);
+  bool result = CompileLazyHelper(&info, flag);
   LOG(FunctionCreateEvent(*function));
   return result;
 }
@@ -705,9 +705,9 @@
 bool CompileLazyInLoop(Handle<JSFunction> function,
                        Handle<Object> receiver,
                        ClearExceptionFlag flag) {
-  // Compile the source information to a code object.
   Handle<SharedFunctionInfo> shared(function->shared());
-  bool result = CompileLazyHelper(shared, receiver, flag, 1);
+  CompilationInfo info(shared, receiver, 1);
+  bool result = CompileLazyHelper(&info, flag);
   LOG(FunctionCreateEvent(*function));
   return result;
 }
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Fri Jan 29 03:34:37 2010 +++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Fri Jan 29 03:55:40 2010
@@ -126,7 +126,7 @@
 // edi: called JS function
 // esi: callee's context

-void CodeGenerator::GenCode(FunctionLiteral* fun) {
+void CodeGenerator::GenCode(FunctionLiteral* fun, CompilationInfo* info) {
   // Record the position for debugging purposes.
   CodeForFunctionPosition(fun);

@@ -143,7 +143,7 @@
   set_in_spilled_code(false);

   // Adjust for function-level loop nesting.
-  loop_nesting_ += fun->loop_nesting();
+  loop_nesting_ += info->loop_nesting();

   JumpTarget::set_compiling_deferred_code(false);

@@ -321,7 +321,7 @@
   }

   // Adjust for function-level loop nesting.
-  loop_nesting_ -= fun->loop_nesting();
+  loop_nesting_ -= info->loop_nesting();

   // Code generation state must be reset.
   ASSERT(state_ == NULL);
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.h     Wed Jan 27 06:07:12 2010
+++ /branches/bleeding_edge/src/ia32/codegen-ia32.h     Fri Jan 29 03:55:40 2010
@@ -32,6 +32,7 @@
 namespace internal {

 // Forward declarations
+class CompilationInfo;
 class DeferredCode;
 class RegisterAllocator;
 class RegisterFile;
@@ -297,7 +298,8 @@
   // be called by compiler.cc.
   static Handle<Code> MakeCode(FunctionLiteral* fun,
                                Handle<Script> script,
-                               bool is_eval);
+                               bool is_eval,
+                               CompilationInfo* info);

   // Printing of AST, etc. as requested by flags.
   static void MakeCodePrologue(FunctionLiteral* fun);
@@ -378,7 +380,7 @@
   void VisitStatementsAndSpill(ZoneList<Statement*>* statements);

   // Main code generation function
-  void GenCode(FunctionLiteral* fun);
+  void GenCode(FunctionLiteral* fun, CompilationInfo* info);

   // Generate the return sequence code.  Should be called no more than
   // once per compiled function, immediately after binding the return
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc      Fri Jan 29 03:34:37 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.cc      Fri Jan 29 03:55:40 2010
@@ -278,7 +278,7 @@
 }


-void CodeGenerator::GenCode(FunctionLiteral* function) {
+void CodeGenerator::GenCode(FunctionLiteral* function, CompilationInfo* info) {
   // Record the position for debugging purposes.
   CodeForFunctionPosition(function);
   ZoneList<Statement*>* body = function->body();
@@ -294,7 +294,7 @@
   set_in_spilled_code(false);

   // Adjust for function-level loop nesting.
-  loop_nesting_ += function->loop_nesting();
+  loop_nesting_ += info->loop_nesting();

   JumpTarget::set_compiling_deferred_code(false);

@@ -472,7 +472,7 @@
   }

   // Adjust for function-level loop nesting.
-  loop_nesting_ -= function->loop_nesting();
+  loop_nesting_ -= info->loop_nesting();

   // Code generation state must be reset.
   ASSERT(state_ == NULL);
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.h       Thu Jan 28 04:45:14 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.h       Fri Jan 29 03:55:40 2010
@@ -32,6 +32,7 @@
 namespace internal {

 // Forward declarations
+class CompilationInfo;
 class DeferredCode;
 class RegisterAllocator;
 class RegisterFile;
@@ -297,7 +298,8 @@
   // be called by compiler.cc.
   static Handle<Code> MakeCode(FunctionLiteral* fun,
                                Handle<Script> script,
-                               bool is_eval);
+                               bool is_eval,
+                               CompilationInfo* info);

   // Printing of AST, etc. as requested by flags.
   static void MakeCodePrologue(FunctionLiteral* fun);
@@ -380,7 +382,7 @@
   void VisitStatementsAndSpill(ZoneList<Statement*>* statements);

   // Main code generation function
-  void GenCode(FunctionLiteral* fun);
+  void GenCode(FunctionLiteral* fun, CompilationInfo* info);

   // Generate the return sequence code.  Should be called no more than
   // once per compiled function, immediately after binding the return

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to