Revision: 5541
Author: [email protected]
Date: Tue Sep 28 00:50:32 2010
Log: Avoid logging preparse-data inside lazily compiled functions.
Reduces size of preparser data significantly when there are nested functions.
Also allows us to drop the "skip" fields of function entries,
that tells us how much preparse-data to skip when skipping the function source.

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

Modified:
 /branches/bleeding_edge/src/parser.cc
 /branches/bleeding_edge/src/parser.h
 /branches/bleeding_edge/src/scopes.cc
 /branches/bleeding_edge/src/scopes.h

=======================================
--- /branches/bleeding_edge/src/parser.cc       Fri Sep 24 01:25:31 2010
+++ /branches/bleeding_edge/src/parser.cc       Tue Sep 28 00:50:32 2010
@@ -877,12 +877,30 @@
   virtual int function_position() { return 0; }
   virtual int symbol_position() { return 0; }
   virtual int symbol_ids() { return 0; }
+  virtual void PauseRecording() {}
+  virtual void ResumeRecording() {}
   virtual Vector<unsigned> ExtractData() {
     return Vector<unsigned>();
   };
 };


+
+class ConditionalLogPauseScope {
+ public:
+  ConditionalLogPauseScope(bool pause, ParserLog* log)
+      : log_(log), pause_(pause) {
+    if (pause) log->PauseRecording();
+  }
+  ~ConditionalLogPauseScope() {
+    if (pause_) log_->ResumeRecording();
+  }
+ private:
+  ParserLog* log_;
+  bool pause_;
+};
+
+
 class AstBuildingParserFactory : public ParserFactory {
  public:
   explicit AstBuildingParserFactory(int expected_symbols)
@@ -969,16 +987,32 @@
     }
     return data;
   }
+
+  virtual void PauseRecording() {
+    pause_count_++;
+    is_recording_ = false;
+  }
+
+  virtual void ResumeRecording() {
+    ASSERT(pause_count_ > 0);
+    if (--pause_count_ == 0) is_recording_ = !has_error();
+  }

  protected:
   bool has_error() {
     return static_cast<bool>(preamble_[ScriptDataImpl::kHasErrorOffset]);
   }
+  bool is_recording() {
+    return is_recording_;
+  }

   void WriteString(Vector<const char> str);

   Collector<unsigned> function_store_;
   unsigned preamble_[ScriptDataImpl::kHeaderSize];
+  bool is_recording_;
+  int pause_count_;
+
 #ifdef DEBUG
   int prev_start;
 #endif
@@ -991,6 +1025,7 @@
   CompleteParserRecorder();

   virtual void LogSymbol(int start, Vector<const char> literal) {
+    if (!is_recording_) return;
     int hash = vector_hash(literal);
     HashMap::Entry* entry = symbol_table_.Lookup(&literal, hash, true);
     int id = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
@@ -1061,13 +1096,6 @@
 };


-void ScriptDataImpl::SkipFunctionEntry(int start) {
-  ASSERT(function_index_ + FunctionEntry::kSize <= store_.length());
-  ASSERT(static_cast<int>(store_[function_index_]) == start);
-  function_index_ += FunctionEntry::kSize;
-}
-
-
 FunctionEntry ScriptDataImpl::GetFunctionEntry(int start) {
   // The current pre-data entry must be a FunctionEntry with the given
   // start position.
@@ -1126,7 +1154,10 @@



-PartialParserRecorder::PartialParserRecorder() : function_store_(0) {
+PartialParserRecorder::PartialParserRecorder()
+    : function_store_(0),
+      is_recording_(true),
+      pause_count_(0) {
   preamble_[ScriptDataImpl::kMagicOffset] = ScriptDataImpl::kMagicNumber;
preamble_[ScriptDataImpl::kVersionOffset] = ScriptDataImpl::kCurrentVersion;
   preamble_[ScriptDataImpl::kHasErrorOffset] = false;
@@ -1202,6 +1233,7 @@
   for (int i = 0; i < args.length(); i++) {
     WriteString(CStrVector(args[i]));
   }
+  is_recording_ = false;
 }


@@ -1248,7 +1280,7 @@
   ASSERT(start > prev_start);
   prev_start = start;
 #endif
-  if (has_error()) return FunctionEntry();
+  if (!is_recording_) return FunctionEntry();
   FunctionEntry result(function_store_.AddBlock(FunctionEntry::kSize, 0));
   result.set_start_pos(start);
   return result;
@@ -1343,6 +1375,8 @@
                                bool inside_with) {
   ASSERT(parent != NULL);
   parent->type_ = type;
+ // Initialize function is hijacked by DummyScope to increment scope depth.
+  parent->Initialize(inside_with);
   return parent;
 }

@@ -1415,6 +1449,7 @@
   }

   ~LexicalScope() {
+    parser_->top_scope_->Leave();
     parser_->top_scope_ = prev_scope_;
     parser_->with_nesting_level_ = prev_level_;
   }
@@ -1480,7 +1515,8 @@
   NoHandleAllocation no_handle_allocation;
   scanner_.Initialize(source, stream, JAVASCRIPT);
   ASSERT(target_stack_ == NULL);
-  mode_ = PARSE_EAGERLY;
+  mode_ = FLAG_lazy ? PARSE_LAZILY : PARSE_EAGERLY;
+  if (allow_natives_syntax_ || extension_ != NULL) mode_ = PARSE_EAGERLY;
   DummyScope top_scope;
   LexicalScope scope(this, &top_scope);
   TemporaryScope temp_scope(this);
@@ -1658,7 +1694,10 @@


 Handle<String> Parser::GetSymbol(bool* ok) {
-  log()->LogSymbol(scanner_.location().beg_pos, scanner_.literal());
+  if (is_pre_parsing_) {
+    log()->LogSymbol(scanner_.location().beg_pos, scanner_.literal());
+    return Handle<String>::null();
+  }
   int symbol_id = -1;
   if (pre_data() != NULL) {
     symbol_id = pre_data()->GetSymbolIdentifier();
@@ -1971,7 +2010,7 @@
   }

   // Propagate the collected information on this property assignments.
-  if (top_scope_->is_function_scope()) {
+  if (!is_pre_parsing_ && top_scope_->is_function_scope()) {
     bool only_simple_this_property_assignments =
this_property_assignment_finder.only_simple_this_property_assignments()
         && top_scope_->declarations()->length() == 0;
@@ -4123,8 +4162,8 @@

   int num_parameters = 0;
   // Parse function body.
-  { Scope::Type type = Scope::FUNCTION_SCOPE;
-    Scope* scope = factory()->NewScope(top_scope_, type, inside_with());
+  { Scope* scope =
+ factory()->NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with());
     LexicalScope lexical_scope(this, scope);
     TemporaryScope temp_scope(this);
     top_scope_->SetScopeName(name);
@@ -4155,7 +4194,9 @@
     // NOTE: We create a proxy and resolve it here so that in the
     // future we can change the AST to only refer to VariableProxies
     // instead of Variables and Proxis as is the case now.
-    if (!function_name.is_null() && function_name->length() > 0) {
+    if (!is_pre_parsing_
+        && !function_name.is_null()
+        && function_name->length() > 0) {
       Variable* fvar = top_scope_->DeclareFunctionVar(function_name);
       VariableProxy* fproxy =
           top_scope_->NewUnresolved(function_name, inside_with());
@@ -4189,22 +4230,18 @@
       }
Counters::total_preparse_skipped.Increment(end_pos - function_block_pos);
       scanner_.SeekForward(end_pos);
-      pre_data()->Skip(entry.predata_function_skip(),
-                       entry.predata_symbol_skip());
       materialized_literal_count = entry.literal_count();
       expected_property_count = entry.property_count();
       only_simple_this_property_assignments = false;
       this_property_assignments = Factory::empty_fixed_array();
       Expect(Token::RBRACE, CHECK_OK);
     } else {
-      if (pre_data() != NULL) {
-        // Skip pre-data entry for non-lazily compiled function.
-        pre_data()->SkipFunctionEntry(function_block_pos);
-      }
-      FunctionEntry entry = log()->LogFunction(function_block_pos);
-      int predata_function_position_before = log()->function_position();
-      int predata_symbol_position_before = log()->symbol_position();
-      ParseSourceElements(&body, Token::RBRACE, CHECK_OK);
+      FunctionEntry entry;
+ if (is_lazily_compiled) entry = log()->LogFunction(function_block_pos);
+      {
+        ConditionalLogPauseScope pause_if(is_lazily_compiled, log());
+        ParseSourceElements(&body, Token::RBRACE, CHECK_OK);
+      }
       materialized_literal_count = temp_scope.materialized_literal_count();
       expected_property_count = temp_scope.expected_property_count();
       only_simple_this_property_assignments =
@@ -4214,13 +4251,11 @@
       Expect(Token::RBRACE, CHECK_OK);
       end_pos = scanner_.location().end_pos;
       if (entry.is_valid()) {
+        ASSERT(is_lazily_compiled);
+        ASSERT(is_pre_parsing_);
         entry.set_end_pos(end_pos);
         entry.set_literal_count(materialized_literal_count);
         entry.set_property_count(expected_property_count);
-        entry.set_predata_function_skip(
-            log()->function_position() - predata_function_position_before);
-        entry.set_predata_symbol_skip(
-            log()->symbol_position() - predata_symbol_position_before);
       }
     }

@@ -5624,9 +5659,7 @@
                        start_position, end_position, is_expression);
   return result;
 }
-

 #undef NEW

-
 } }  // namespace v8::internal
=======================================
--- /branches/bleeding_edge/src/parser.h        Fri Sep 17 05:55:27 2010
+++ /branches/bleeding_edge/src/parser.h        Tue Sep 28 00:50:32 2010
@@ -71,20 +71,10 @@
   void set_property_count(int value) {
     backing_[kPropertyCountOffset] = value;
   }
-
- int predata_function_skip() { return backing_[kPredataFunctionSkipOffset]; }
-  void set_predata_function_skip(int value) {
-    backing_[kPredataFunctionSkipOffset] = value;
-  }
-
-  int predata_symbol_skip() { return backing_[kPredataSymbolSkipOffset]; }
-  void set_predata_symbol_skip(int value) {
-    backing_[kPredataSymbolSkipOffset] = value;
-  }

   bool is_valid() { return backing_.length() > 0; }

-  static const int kSize = 6;
+  static const int kSize = 4;

  private:
   Vector<unsigned> backing_;
@@ -92,8 +82,6 @@
   static const int kEndPosOffset = 1;
   static const int kLiteralCountOffset = 2;
   static const int kPropertyCountOffset = 3;
-  static const int kPredataFunctionSkipOffset = 4;
-  static const int kPredataSymbolSkipOffset = 5;
 };


@@ -117,7 +105,6 @@

   FunctionEntry GetFunctionEntry(int start);
   int GetSymbolIdentifier();
-  void SkipFunctionEntry(int start);
   bool SanityCheck();

   Scanner::Location MessageLocation();
@@ -132,29 +119,9 @@
   bool has_error() { return store_[kHasErrorOffset]; }
   unsigned magic() { return store_[kMagicOffset]; }
   unsigned version() { return store_[kVersionOffset]; }
-
-  // Skip forward in the preparser data by the given number
-  // of unsigned ints of function entries and the given number of bytes of
-  // symbol id encoding.
-  void Skip(int function_entries, int symbol_entries) {
-    ASSERT(function_entries >= 0);
-    ASSERT(function_entries
-           <= (static_cast<int>(store_[kFunctionsSizeOffset])
-               - (function_index_ - kHeaderSize)));
-    ASSERT(symbol_entries >= 0);
-    ASSERT(symbol_entries <= symbol_data_end_ - symbol_data_);
-
-    unsigned max_function_skip = store_[kFunctionsSizeOffset] -
-        static_cast<unsigned>(function_index_ - kHeaderSize);
-    function_index_ +=
-        Min(static_cast<unsigned>(function_entries), max_function_skip);
-    symbol_data_ +=
-        Min(static_cast<unsigned>(symbol_entries),
-            static_cast<unsigned>(symbol_data_end_ - symbol_data_));
-  }

   static const unsigned kMagicNumber = 0xBadDead;
-  static const unsigned kCurrentVersion = 3;
+  static const unsigned kCurrentVersion = 4;

   static const int kMagicOffset = 0;
   static const int kVersionOffset = 1;
=======================================
--- /branches/bleeding_edge/src/scopes.cc       Fri Sep 24 00:53:59 2010
+++ /branches/bleeding_edge/src/scopes.cc       Tue Sep 28 00:50:32 2010
@@ -199,7 +199,6 @@
                        true, Variable::ARGUMENTS);
   }
 }
-


 Variable* Scope::LocalLookup(Handle<String> name) {
=======================================
--- /branches/bleeding_edge/src/scopes.h        Fri Sep 24 01:25:31 2010
+++ /branches/bleeding_edge/src/scopes.h        Tue Sep 28 00:50:32 2010
@@ -34,7 +34,6 @@
 namespace v8 {
 namespace internal {

-
 // A hash map to support fast variable declaration and lookup.
 class VariableMap: public HashMap {
  public:
@@ -100,8 +99,12 @@
   // The scope name is only used for printing/debugging.
void SetScopeName(Handle<String> scope_name) { scope_name_ = scope_name; }

-  void Initialize(bool inside_with);
-
+  virtual void Initialize(bool inside_with);
+
+  // Called just before leaving a scope.
+  virtual void Leave() {
+    // No cleanup or fixup necessary.
+  }

// ---------------------------------------------------------------------------
   // Declarations
@@ -272,7 +275,7 @@
   bool AllowsLazyCompilation() const;

   // True if the outer context of this scope is always the global context.
-  bool HasTrivialOuterContext() const;
+  virtual bool HasTrivialOuterContext() const;

   // The number of contexts between this and scope; zero if this == scope.
   int ContextChainLength(Scope* scope);
@@ -378,20 +381,53 @@
 };


+// Scope used during pre-parsing.
 class DummyScope : public Scope {
  public:
-  DummyScope() : Scope(GLOBAL_SCOPE) {
+  DummyScope()
+      : Scope(GLOBAL_SCOPE),
+        nesting_level_(1),  // Allows us to Leave the initial scope.
+        inside_with_level_(kNotInsideWith) {
     outer_scope_ = this;
+    scope_inside_with_ = false;
   }

-  virtual Variable* Lookup(Handle<String> name)  { return NULL; }
-  virtual Variable* Declare(Handle<String> name, Variable::Mode mode) {
-    return NULL;
-  }
+  virtual void Initialize(bool inside_with) {
+    nesting_level_++;
+    if (inside_with && inside_with_level_ == kNotInsideWith) {
+      inside_with_level_ = nesting_level_;
+    }
+    ASSERT(inside_with_level_ <= nesting_level_);
+  }
+
+  virtual void Leave() {
+    nesting_level_--;
+    ASSERT(nesting_level_ >= 0);
+    if (nesting_level_ < inside_with_level_) {
+      inside_with_level_ = kNotInsideWith;
+    }
+    ASSERT(inside_with_level_ <= nesting_level_);
+  }
+
+  virtual Variable* Lookup(Handle<String> name)  { return NULL; }
+
virtual VariableProxy* NewUnresolved(Handle<String> name, bool inside_with) {
     return NULL;
   }
+
virtual VariableProxy* NewTemporary(Handle<String> name) { return NULL; }
+
+  virtual bool HasTrivialOuterContext() const {
+    return (nesting_level_ == 0 || inside_with_level_ <= 0);
+  }
+
+ private:
+  static const int kNotInsideWith = -1;
+  // Number of surrounding scopes of the current scope.
+  int nesting_level_;
+ // Nesting level of outermost scope that is contained in a with statement,
+  // or kNotInsideWith if there are no with's around the current scope.
+  int inside_with_level_;
 };


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

Reply via email to