Introduce a stack-allocated structure to encapsulate compile-time information.
authorkmillikin@chromium.org <kmillikin@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 29 Jan 2010 11:55:40 +0000 (11:55 +0000)
committerkmillikin@chromium.org <kmillikin@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 29 Jan 2010 11:55:40 +0000 (11:55 +0000)
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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3744 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

13 files changed:
src/arm/codegen-arm.cc
src/arm/codegen-arm.h
src/ast.h
src/codegen.cc
src/compiler.cc
src/compiler.h
src/fast-codegen.cc
src/fast-codegen.h
src/handles.cc
src/ia32/codegen-ia32.cc
src/ia32/codegen-ia32.h
src/x64/codegen-x64.cc
src/x64/codegen-x64.h

index 381e37fb311388a9d122dfdab67c84439c34d66b..e4977bab805aa463f1c0572135d486f5f07f45a1 100644 (file)
@@ -142,7 +142,7 @@ CodeGenerator::CodeGenerator(int buffer_size, Handle<Script> script,
 // 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);
 
index ccca2e9ec521153ef9469529f2cfdaffca765107..da5ff76f1d8be7e1288c624105590acba2a1626f 100644 (file)
@@ -32,6 +32,7 @@ namespace v8 {
 namespace internal {
 
 // Forward declarations
+class CompilationInfo;
 class DeferredCode;
 class RegisterAllocator;
 class RegisterFile;
@@ -153,7 +154,8 @@ class CodeGenerator: public AstVisitor {
   // 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 @@ class CodeGenerator: public AstVisitor {
   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);
index 808bfc6979859f5e1016a464f5b0546e12468608..11a12d0aa5a0294913c7cfd4fb698ab88ef8b225 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -1331,7 +1331,6 @@ class FunctionLiteral: public Expression {
         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) {
@@ -1366,9 +1365,6 @@ class FunctionLiteral: public Expression {
 
   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) {
     inferred_name_ = inferred_name;
@@ -1396,7 +1392,6 @@ class FunctionLiteral: public Expression {
   int start_position_;
   int end_position_;
   bool is_expression_;
-  int loop_nesting_;
   int function_token_position_;
   Handle<String> inferred_name_;
   bool try_full_codegen_;
index aa2a2b82dffc79e2344859e7d63b99e4a80fbe13..ba88d7318c2bd82a8c3be011fd75416a0d09ee69 100644 (file)
@@ -216,7 +216,8 @@ Handle<Code> CodeGenerator::MakeCodeEpilogue(FunctionLiteral* fun,
 // 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 @@ Handle<Code> CodeGenerator::MakeCode(FunctionLiteral* fun,
   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();
index 86716403cf55d06758b9d75549449a39b43f2128..604af2c0c99a2a114408c0952aec53d7d0160bc4 100644 (file)
@@ -48,8 +48,7 @@ static Handle<Code> MakeCode(FunctionLiteral* literal,
                              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 @@ static Handle<Code> MakeCode(FunctionLiteral* literal,
   // 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 @@ static Handle<Code> MakeCode(FunctionLiteral* literal,
     }
   } 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 @@ static Handle<Code> MakeCode(FunctionLiteral* literal,
     // Does not yet generate code.
   }
 
-  return CodeGenerator::MakeCode(literal, script, is_eval);
+  return CodeGenerator::MakeCode(literal, script, is_eval, info);
 }
 
 
@@ -204,12 +204,10 @@ static Handle<JSFunction> MakeFunction(bool is_global,
   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 @@ Handle<JSFunction> Compiler::CompileEval(Handle<String> source,
 }
 
 
-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 @@ bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared,
   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()));
 
@@ -402,9 +399,6 @@ bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared,
     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
   // lazy parsing statistics.
@@ -415,8 +409,7 @@ bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared,
                                script,
                                Handle<Context>::null(),
                                false,
-                               shared,
-                               receiver);
+                               info);
 
   // Check for stack-overflow exception.
   if (code.is_null()) {
@@ -497,6 +490,10 @@ Handle<JSFunction> Compiler::BuildBoilerplate(FunctionLiteral* literal,
     // 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 @@ Handle<JSFunction> Compiler::BuildBoilerplate(FunctionLiteral* literal,
                (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 @@ Handle<JSFunction> Compiler::BuildBoilerplate(FunctionLiteral* literal,
       // 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.
index 74c7ffb1719dfa202c7478593749521d1b006f19..0661f348027ac366c79b56aec45f3e4a1a2c94e2 100644 (file)
 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 @@ class Compiler : public AllStatic {
   // 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
index adca9908064d52eee0981cec09cf6281aa221d7b..5a8c09e6e280dc2c48352577e9df97490f0cf6b5 100644 (file)
@@ -49,9 +49,10 @@ namespace internal {
   } 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 @@ void FastCodeGenSyntaxChecker::VisitAssignment(Assignment* expr) {
   // 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();
index 1ac60aceb5683ba7b7d7eeb49b63abde83f7f4f3..4f2628d7c31b7ddf38cf98684027e9fa02adfdd0 100644 (file)
 #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);
+  void Check(FunctionLiteral* fun, CompilationInfo* info);
 
-  Handle<Object> receiver() { return receiver_; }
+  CompilationInfo* info() { return info_; }
   bool has_supported_syntax() { return has_supported_syntax_; }
 
  private:
@@ -55,7 +56,7 @@ class FastCodeGenSyntaxChecker: public AstVisitor {
   AST_NODE_LIST(DECLARE_VISIT)
 #undef DECLARE_VISIT
 
-  Handle<Object> receiver_;
+  CompilationInfo* info_;
   bool has_supported_syntax_;
 
   DISALLOW_COPY_AND_ASSIGN(FastCodeGenSyntaxChecker);
index cfe4dd74a6c5e8bef7cdb06ff6e3218629a29f19..c66056ebbc2ba31342d94acc48671678dcfe1f48 100644 (file)
@@ -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 @@ bool EnsureCompiled(Handle<SharedFunctionInfo> shared,
 }
 
 
-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 @@ static bool CompileLazyHelper(Handle<SharedFunctionInfo> shared,
 
 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 CompileLazy(Handle<JSFunction> function,
 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;
 }
index f2e37d1a39315b5bcbafa41489bb8b1ee43dfd6e..e19067c97979c646255800802b0d44e8296f926a 100644 (file)
@@ -126,7 +126,7 @@ CodeGenerator::CodeGenerator(int buffer_size,
 // 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 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
   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 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
   }
 
   // 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);
index a81a7d1d8fb7c9235928d3b991f89e0cb4f9277d..a842244f605b1a1a3c90fb7f9ce760e9545299c6 100644 (file)
@@ -32,6 +32,7 @@ namespace v8 {
 namespace internal {
 
 // Forward declarations
+class CompilationInfo;
 class DeferredCode;
 class RegisterAllocator;
 class RegisterFile;
@@ -297,7 +298,8 @@ class CodeGenerator: public AstVisitor {
   // 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 @@ class CodeGenerator: public AstVisitor {
   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
index 31afdc860c8f1c4f9e3600f4dd16fdf20147b14d..6f93d2afb255f66896728cf626742c8635d42ac6 100644 (file)
@@ -278,7 +278,7 @@ void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
 }
 
 
-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 @@ void CodeGenerator::GenCode(FunctionLiteral* function) {
   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 @@ void CodeGenerator::GenCode(FunctionLiteral* function) {
   }
 
   // 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);
index 2c2c29fabc52372c9d836be89e5791178a06bbfc..5f04b3fbbb4a794139067af93438d0ae9daacee7 100644 (file)
@@ -32,6 +32,7 @@ namespace v8 {
 namespace internal {
 
 // Forward declarations
+class CompilationInfo;
 class DeferredCode;
 class RegisterAllocator;
 class RegisterFile;
@@ -297,7 +298,8 @@ class CodeGenerator: public AstVisitor {
   // 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 @@ class CodeGenerator: public AstVisitor {
   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