Revision: 22286
Author:   [email protected]
Date:     Wed Jul  9 00:05:10 2014 UTC
Log:      Version 3.28.18 (based on bleeding_edge revision r22279)

Reland "Postpone termination exceptions in debug scope." (issue 3408).

Performance and stability improvements on all platforms.
http://code.google.com/p/v8/source/detail?r=22286

Modified:
 /trunk/ChangeLog
 /trunk/src/assembler.h
 /trunk/src/compiler.cc
 /trunk/src/debug.cc
 /trunk/src/debug.h
 /trunk/src/flag-definitions.h
 /trunk/src/frames.cc
 /trunk/src/frames.h
 /trunk/src/full-codegen.cc
 /trunk/src/heap.cc
 /trunk/src/heap.h
 /trunk/src/ic.cc
 /trunk/src/ic.h
 /trunk/src/mark-compact.cc
 /trunk/src/mksnapshot.cc
 /trunk/src/objects-inl.h
 /trunk/src/objects.h
 /trunk/src/parser.cc
 /trunk/src/parser.h
 /trunk/src/serialize.cc
 /trunk/src/serialize.h
 /trunk/src/snapshot-source-sink.cc
 /trunk/src/snapshot-source-sink.h
 /trunk/src/spaces.cc
 /trunk/src/store-buffer.cc
 /trunk/src/store-buffer.h
 /trunk/src/version.cc
 /trunk/src/version.h
 /trunk/test/cctest/cctest.status
 /trunk/test/cctest/test-compiler.cc
 /trunk/test/cctest/test-debug.cc

=======================================
--- /trunk/ChangeLog    Tue Jul  8 06:57:45 2014 UTC
+++ /trunk/ChangeLog    Wed Jul  9 00:05:10 2014 UTC
@@ -1,3 +1,10 @@
+2014-07-09: Version 3.28.18
+
+ Reland "Postpone termination exceptions in debug scope." (issue 3408).
+
+        Performance and stability improvements on all platforms.
+
+
 2014-07-08: Version 3.28.17

         MIPS: Fix computed properties on object literals with a double as
=======================================
--- /trunk/src/assembler.h      Tue Jul  8 00:05:42 2014 UTC
+++ /trunk/src/assembler.h      Wed Jul  9 00:05:10 2014 UTC
@@ -66,6 +66,7 @@
   void set_emit_debug_code(bool value) { emit_debug_code_ = value; }

   bool serializer_enabled() const { return serializer_enabled_; }
+  void enable_serializer() { serializer_enabled_ = true; }

   bool predictable_code_size() const { return predictable_code_size_; }
void set_predictable_code_size(bool value) { predictable_code_size_ = value; }
=======================================
--- /trunk/src/compiler.cc      Tue Jul  1 11:58:10 2014 UTC
+++ /trunk/src/compiler.cc      Wed Jul  9 00:05:10 2014 UTC
@@ -933,9 +933,11 @@
     cached_data = NULL;
   } else if (cached_data_mode == PRODUCE_CACHED_DATA) {
     ASSERT(cached_data && !*cached_data);
+    ASSERT(extension == NULL);
   } else {
     ASSERT(cached_data_mode == CONSUME_CACHED_DATA);
     ASSERT(cached_data && *cached_data);
+    ASSERT(extension == NULL);
   }
   Isolate* isolate = source->GetIsolate();
   int source_length = source->length();
@@ -951,6 +953,11 @@
     maybe_result = compilation_cache->LookupScript(
         source, script_name, line_offset, column_offset,
         is_shared_cross_origin, context);
+    if (maybe_result.is_null() && FLAG_serialize_toplevel &&
+        cached_data_mode == CONSUME_CACHED_DATA) {
+      Object* des = CodeSerializer::Deserialize(isolate, *cached_data);
+      return handle(SharedFunctionInfo::cast(des), isolate);
+    }
   }

   if (!maybe_result.ToHandle(&result)) {
@@ -971,17 +978,21 @@
     // Compile the function and add it to the cache.
     CompilationInfoWithZone info(script);
     info.MarkAsGlobal();
+    info.SetCachedData(cached_data, cached_data_mode);
     info.SetExtension(extension);
-    info.SetCachedData(cached_data, cached_data_mode);
     info.SetContext(context);
     if (FLAG_use_strict) info.SetStrictMode(STRICT);
+
     result = CompileToplevel(&info);
     if (extension == NULL && !result.is_null() && !result->dont_cache()) {
       compilation_cache->PutScript(source, context, result);
+ if (FLAG_serialize_toplevel && cached_data_mode == PRODUCE_CACHED_DATA) {
+        *cached_data = CodeSerializer::Serialize(result);
+      }
     }
     if (result.is_null()) isolate->ReportPendingMessages();
   } else if (result->ic_age() != isolate->heap()->global_ic_age()) {
-      result->ResetForNewContext(isolate->heap()->global_ic_age());
+    result->ResetForNewContext(isolate->heap()->global_ic_age());
   }
   return result;
 }
=======================================
--- /trunk/src/debug.cc Mon Jul  7 00:05:07 2014 UTC
+++ /trunk/src/debug.cc Wed Jul  9 00:05:10 2014 UTC
@@ -3104,9 +3104,12 @@
 }


-DebugScope::DebugScope(Debug* debug) : debug_(debug),
-                                       prev_(debug->debugger_entry()),
-                                       save_(debug_->isolate_) {
+DebugScope::DebugScope(Debug* debug)
+    : debug_(debug),
+      prev_(debug->debugger_entry()),
+      save_(debug_->isolate_),
+      no_termination_exceptons_(debug_->isolate_,
+                                StackGuard::TERMINATE_EXECUTION) {
   // Link recursive debugger entry.
   debug_->thread_local_.current_debug_scope_ = this;

=======================================
--- /trunk/src/debug.h  Mon Jul  7 00:05:07 2014 UTC
+++ /trunk/src/debug.h  Wed Jul  9 00:05:10 2014 UTC
@@ -705,6 +705,7 @@
   int break_id_;                   // Previous break id.
   bool failed_;                    // Did the debug context fail to load?
   SaveContext save_;               // Saves previous context.
+  PostponeInterruptsScope no_termination_exceptons_;
 };


=======================================
--- /trunk/src/flag-definitions.h       Mon Jul  7 00:05:07 2014 UTC
+++ /trunk/src/flag-definitions.h       Wed Jul  9 00:05:10 2014 UTC
@@ -423,6 +423,8 @@
 DEFINE_BOOL(trace_stub_failures, false,
             "trace deoptimization of generated code stubs")

+DEFINE_BOOL(serialize_toplevel, false, "enable caching of toplevel scripts")
+
 // compiler.cc
 DEFINE_INT(min_preparse_length, 1024,
            "minimum length for automatic enable preparsing")
@@ -536,6 +538,7 @@
             "Use idle notification to reduce memory footprint.")
 // ic.cc
 DEFINE_BOOL(use_ic, true, "use inline caching")
+DEFINE_BOOL(trace_ic, false, "trace inline cache state transitions")

 // macro-assembler-ia32.cc
 DEFINE_BOOL(native_code_counters, false,
@@ -724,9 +727,6 @@
 DEFINE_BOOL(print_handles, false, "report handles after GC")
 DEFINE_BOOL(print_global_handles, false, "report global handles after GC")

-// ic.cc
-DEFINE_BOOL(trace_ic, false, "trace inline cache state transitions")
-
 // interface.cc
 DEFINE_BOOL(print_interfaces, false, "print interfaces")
DEFINE_BOOL(print_interface_details, false, "print interface inference details")
=======================================
--- /trunk/src/frames.cc        Tue Jul  8 00:05:42 2014 UTC
+++ /trunk/src/frames.cc        Wed Jul  9 00:05:10 2014 UTC
@@ -777,9 +777,37 @@
 }


-void JavaScriptFrame::PrintTop(Isolate* isolate,
-                               FILE* file,
-                               bool print_args,
+void JavaScriptFrame::PrintFunctionAndOffset(JSFunction* function, Code* code,
+                                             Address pc, FILE* file,
+                                             bool print_line_number) {
+  PrintF(file, "%s", function->IsOptimized() ? "*" : "~");
+  function->PrintName(file);
+  int code_offset = static_cast<int>(pc - code->instruction_start());
+  PrintF(file, "+%d", code_offset);
+  if (print_line_number) {
+    SharedFunctionInfo* shared = function->shared();
+    int source_pos = code->SourcePosition(pc);
+    Object* maybe_script = shared->script();
+    if (maybe_script->IsScript()) {
+      Script* script = Script::cast(maybe_script);
+      int line = script->GetLineNumber(source_pos) + 1;
+      Object* script_name_raw = script->name();
+      if (script_name_raw->IsString()) {
+        String* script_name = String::cast(script->name());
+        SmartArrayPointer<char> c_script_name =
+ script_name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+        PrintF(file, " at %s:%d", c_script_name.get(), line);
+      } else {
+        PrintF(file, " at <unknown>:%d", line);
+      }
+    } else {
+      PrintF(file, " at <unknown>:<unknown>");
+    }
+  }
+}
+
+
+void JavaScriptFrame::PrintTop(Isolate* isolate, FILE* file, bool print_args,
                                bool print_line_number) {
   // constructor calls
   DisallowHeapAllocation no_allocation;
@@ -788,37 +816,8 @@
     if (it.frame()->is_java_script()) {
       JavaScriptFrame* frame = it.frame();
       if (frame->IsConstructor()) PrintF(file, "new ");
-      // function name
-      JSFunction* fun = frame->function();
-      fun->PrintName();
-      Code* js_code = frame->unchecked_code();
-      Address pc = frame->pc();
-      int code_offset =
-          static_cast<int>(pc - js_code->instruction_start());
-      PrintF("+%d", code_offset);
-      SharedFunctionInfo* shared = fun->shared();
-      if (print_line_number) {
-        Code* code = Code::cast(isolate->FindCodeObject(pc));
-        int source_pos = code->SourcePosition(pc);
-        Object* maybe_script = shared->script();
-        if (maybe_script->IsScript()) {
-          Script* script = Script::cast(maybe_script);
-          int line = script->GetLineNumber(source_pos) + 1;
-          Object* script_name_raw = script->name();
-          if (script_name_raw->IsString()) {
-            String* script_name = String::cast(script->name());
-            SmartArrayPointer<char> c_script_name =
-                script_name->ToCString(DISALLOW_NULLS,
-                                       ROBUST_STRING_TRAVERSAL);
-            PrintF(file, " at %s:%d", c_script_name.get(), line);
-          } else {
-            PrintF(file, " at <unknown>:%d", line);
-          }
-        } else {
-          PrintF(file, " at <unknown>:<unknown>");
-        }
-      }
-
+      PrintFunctionAndOffset(frame->function(), frame->unchecked_code(),
+                             frame->pc(), file, print_line_number);
       if (print_args) {
         // function arguments
         // (we are intentionally only printing the actually
=======================================
--- /trunk/src/frames.h Wed Jun  4 00:06:13 2014 UTC
+++ /trunk/src/frames.h Wed Jul  9 00:05:10 2014 UTC
@@ -614,9 +614,11 @@
     return static_cast<JavaScriptFrame*>(frame);
   }

-  static void PrintTop(Isolate* isolate,
-                       FILE* file,
-                       bool print_args,
+  static void PrintFunctionAndOffset(JSFunction* function, Code* code,
+                                     Address pc, FILE* file,
+                                     bool print_line_number);
+
+  static void PrintTop(Isolate* isolate, FILE* file, bool print_args,
                        bool print_line_number);

  protected:
=======================================
--- /trunk/src/full-codegen.cc  Thu Jun 26 08:57:53 2014 UTC
+++ /trunk/src/full-codegen.cc  Wed Jul  9 00:05:10 2014 UTC
@@ -301,6 +301,11 @@
   CodeGenerator::MakeCodePrologue(info, "full");
   const int kInitialBufferSize = 4 * KB;
   MacroAssembler masm(info->isolate(), NULL, kInitialBufferSize);
+  if (FLAG_serialize_toplevel &&
+ info->cached_data_mode() == PRODUCE_CACHED_DATA && info->is_global()) {
+    masm.enable_serializer();
+  }
+
 #ifdef ENABLE_GDB_JIT_INTERFACE
   masm.positions_recorder()->StartGDBJITLineInfoRecording();
 #endif
=======================================
--- /trunk/src/heap.cc  Tue Jul  8 00:05:42 2014 UTC
+++ /trunk/src/heap.cc  Wed Jul  9 00:05:10 2014 UTC
@@ -404,7 +404,7 @@
 }


-void Heap::GarbageCollectionPrologue() {
+void Heap::GarbageCollectionPrologue(GarbageCollector collector) {
   {  AllowHeapAllocation for_the_first_part_of_prologue;
     ClearJSFunctionResultCaches();
     gc_count_++;
@@ -435,7 +435,7 @@
   ReportStatisticsBeforeGC();
 #endif  // DEBUG

-  store_buffer()->GCPrologue();
+  store_buffer()->GCPrologue(collector == MARK_COMPACTOR);

   if (isolate()->concurrent_osr_enabled()) {
     isolate()->optimizing_compiler_thread()->AgeBufferedOsrJobs();
@@ -833,7 +833,7 @@
   { GCTracer tracer(this, gc_reason, collector_reason);
     ASSERT(AllowHeapAllocation::IsAllowed());
     DisallowHeapAllocation no_allocation_during_gc;
-    GarbageCollectionPrologue();
+    GarbageCollectionPrologue(collector);
     // The GC count was incremented in the prologue.  Tell the tracer about
     // it.
     tracer.set_gc_count(gc_count_);
=======================================
--- /trunk/src/heap.h   Tue Jul  8 00:05:42 2014 UTC
+++ /trunk/src/heap.h   Wed Jul  9 00:05:10 2014 UTC
@@ -1698,7 +1698,7 @@

   // Code that should be run before and after each GC.  Includes some
   // reporting/verification activities when compiled with DEBUG set.
-  void GarbageCollectionPrologue();
+  void GarbageCollectionPrologue(GarbageCollector collector);
   void GarbageCollectionEpilogue();

   // Pretenuring decisions are made based on feedback collected during new
=======================================
--- /trunk/src/ic.cc    Tue Jul  8 00:05:42 2014 UTC
+++ /trunk/src/ic.cc    Wed Jul  9 00:05:10 2014 UTC
@@ -17,7 +17,6 @@
 namespace v8 {
 namespace internal {

-#ifdef DEBUG
 char IC::TransitionMarkFromState(IC::State state) {
   switch (state) {
     case UNINITIALIZED: return '0';
@@ -48,25 +47,43 @@
 }


-void IC::TraceIC(const char* type,
-                 Handle<Object> name) {
+#ifdef DEBUG
+
+#define TRACE_GENERIC_IC(isolate, type, reason)                \
+  do {                                                         \
+    if (FLAG_trace_ic) {                                       \
+      PrintF("[%s patching generic stub in ", type);           \
+      JavaScriptFrame::PrintTop(isolate, stdout, false, true); \
+      PrintF(" (%s)]\n", reason);                              \
+    }                                                          \
+  } while (false)
+
+#else
+
+#define TRACE_GENERIC_IC(isolate, type, reason)
+
+#endif  // DEBUG
+
+void IC::TraceIC(const char* type, Handle<Object> name) {
   if (FLAG_trace_ic) {
     Code* new_target = raw_target();
     State new_state = new_target->ic_state();
     PrintF("[%s%s in ", new_target->is_keyed_stub() ? "Keyed" : "", type);
-    StackFrameIterator it(isolate());
-    while (it.frame()->fp() != this->fp()) it.Advance();
-    StackFrame* raw_frame = it.frame();
-    if (raw_frame->is_internal()) {
-      Code* apply_builtin = isolate()->builtins()->builtin(
-          Builtins::kFunctionApply);
-      if (raw_frame->unchecked_code() == apply_builtin) {
-        PrintF("apply from ");
-        it.Advance();
-        raw_frame = it.frame();
-      }
+
+    // TODO(jkummerow): Add support for "apply". The logic is roughly:
+    // marker = [fp_ + kMarkerOffset];
+    // if marker is smi and marker.value == INTERNAL and
+    //     the frame's code == builtin(Builtins::kFunctionApply):
+    // then print "apply from" and advance one frame
+
+    Object* maybe_function =
+        Memory::Object_at(fp_ + JavaScriptFrameConstants::kFunctionOffset);
+    if (maybe_function->IsJSFunction()) {
+      JSFunction* function = JSFunction::cast(maybe_function);
+ JavaScriptFrame::PrintFunctionAndOffset(function, function->code(), pc(),
+                                              stdout, true);
     }
-    JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
+
     ExtraICState extra_state = new_target->extra_ic_state();
     const char* modifier = "";
     if (new_target->kind() == Code::KEYED_STORE_IC) {
@@ -77,27 +94,18 @@
            TransitionMarkFromState(state()),
            TransitionMarkFromState(new_state),
            modifier);
+#ifdef OBJECT_PRINT
     OFStream os(stdout);
     name->Print(os);
+#else
+    name->ShortPrint(stdout);
+#endif
     PrintF("]\n");
   }
 }

-#define TRACE_GENERIC_IC(isolate, type, reason)                 \
-  do {                                                          \
-    if (FLAG_trace_ic) {                                        \
-      PrintF("[%s patching generic stub in ", type);            \
-      JavaScriptFrame::PrintTop(isolate, stdout, false, true);  \
-      PrintF(" (%s)]\n", reason);                               \
-    }                                                           \
-  } while (false)
+#define TRACE_IC(type, name) TraceIC(type, name)

-#else
-#define TRACE_GENERIC_IC(isolate, type, reason)
-#endif  // DEBUG
-
-#define TRACE_IC(type, name)             \
-  ASSERT((TraceIC(type, name), true))

 IC::IC(FrameDepth depth, Isolate* isolate)
     : isolate_(isolate),
@@ -599,9 +607,11 @@
       } else if (state() == PREMONOMORPHIC) {
         FunctionPrototypeStub function_prototype_stub(isolate(), kind());
         stub = function_prototype_stub.GetCode();
-      } else if (state() != MEGAMORPHIC) {
+ } else if (!FLAG_compiled_keyed_generic_loads && state() != MEGAMORPHIC) {
         ASSERT(state() != GENERIC);
         stub = megamorphic_stub();
+      } else if (FLAG_compiled_keyed_generic_loads && state() != GENERIC) {
+        stub = generic_stub();
       }
       if (!stub.is_null()) {
         set_target(*stub);
@@ -616,7 +626,11 @@
   uint32_t index;
   if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) {
     // Rewrite to the generic keyed load stub.
-    if (FLAG_use_ic) set_target(*generic_stub());
+    if (FLAG_use_ic) {
+      set_target(*generic_stub());
+      TRACE_IC("LoadIC", name);
+      TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index");
+    }
     Handle<Object> result;
     ASSIGN_RETURN_ON_EXCEPTION(
         isolate(),
@@ -822,6 +836,10 @@
         if (UpdatePolymorphicIC(type, name, code)) break;
         CopyICToMegamorphicCache(name);
       }
+      if (FLAG_compiled_keyed_generic_loads && (kind() == Code::LOAD_IC)) {
+        set_target(*generic_stub());
+        break;
+      }
       set_target(*megamorphic_stub());
       // Fall through.
     case MEGAMORPHIC:
@@ -851,6 +869,11 @@
 Handle<Code> LoadIC::megamorphic_stub() {
return isolate()->stub_cache()->ComputeLoad(MEGAMORPHIC, extra_ic_state());
 }
+
+
+Handle<Code> LoadIC::generic_stub() const {
+  return KeyedLoadGenericElementStub(isolate()).GetCode();
+}


 Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) {
=======================================
--- /trunk/src/ic.h     Mon Jul  7 00:05:07 2014 UTC
+++ /trunk/src/ic.h     Wed Jul  9 00:05:10 2014 UTC
@@ -170,11 +170,8 @@

   bool is_target_set() { return target_set_; }

-#ifdef DEBUG
   char TransitionMarkFromState(IC::State state);
-
   void TraceIC(const char* type, Handle<Object> name);
-#endif

   MaybeHandle<Object> TypeError(const char* type,
                                 Handle<Object> object,
@@ -467,6 +464,7 @@
   }

   virtual Handle<Code> megamorphic_stub();
+  virtual Handle<Code> generic_stub() const;

   // Update the inline cache and the global stub cache based on the
   // lookup result.
=======================================
--- /trunk/src/mark-compact.cc  Mon Jul  7 00:05:07 2014 UTC
+++ /trunk/src/mark-compact.cc  Wed Jul  9 00:05:10 2014 UTC
@@ -4146,12 +4146,23 @@
           pages_swept++;
           parallel_sweeping_active = true;
         } else {
-          if (FLAG_gc_verbose) {
- PrintF("Sweeping 0x%" V8PRIxPTR " conservatively in parallel.\n",
-                   reinterpret_cast<intptr_t>(p));
+          if (p->scan_on_scavenge()) {
+ SweepPrecisely<SWEEP_ONLY, IGNORE_SKIP_LIST, IGNORE_FREE_SPACE>(
+                space, p, NULL);
+            pages_swept++;
+            if (FLAG_gc_verbose) {
+              PrintF("Sweeping 0x%" V8PRIxPTR
+                  " scan on scavenge page precisely.\n",
+                  reinterpret_cast<intptr_t>(p));
+            }
+          } else {
+            if (FLAG_gc_verbose) {
+ PrintF("Sweeping 0x%" V8PRIxPTR " conservatively in parallel.\n",
+                  reinterpret_cast<intptr_t>(p));
+            }
+ p->set_parallel_sweeping(MemoryChunk::PARALLEL_SWEEPING_PENDING);
+            space->IncreaseUnsweptFreeBytes(p);
           }
-          p->set_parallel_sweeping(MemoryChunk::PARALLEL_SWEEPING_PENDING);
-          space->IncreaseUnsweptFreeBytes(p);
         }
         space->set_end_of_unswept_pages(p);
         break;
=======================================
--- /trunk/src/mksnapshot.cc    Mon Jul  7 00:05:07 2014 UTC
+++ /trunk/src/mksnapshot.cc    Wed Jul  9 00:05:10 2014 UTC
@@ -32,17 +32,6 @@
 };


-class ListSnapshotSink : public i::SnapshotByteSink {
- public:
-  explicit ListSnapshotSink(i::List<char>* data) : data_(data) { }
-  virtual ~ListSnapshotSink() {}
-  virtual void Put(int byte, const char* description) { data_->Add(byte); }
-  virtual int Position() { return data_->length(); }
- private:
-  i::List<char>* data_;
-};
-
-
 class SnapshotWriter {
  public:
   explicit SnapshotWriter(const char* snapshot_file)
@@ -93,7 +82,7 @@
       return;

     i::List<char> startup_blob;
-    ListSnapshotSink sink(&startup_blob);
+    i::ListSnapshotSink sink(&startup_blob);

     int spaces[] = {
i::NEW_SPACE, i::OLD_POINTER_SPACE, i::OLD_DATA_SPACE, i::CODE_SPACE,
@@ -417,12 +406,12 @@
// This results in a somewhat smaller snapshot, probably because it gets
     // rid of some things that are cached between garbage collections.
     i::List<char> snapshot_data;
-    ListSnapshotSink snapshot_sink(&snapshot_data);
+    i::ListSnapshotSink snapshot_sink(&snapshot_data);
     i::StartupSerializer ser(internal_isolate, &snapshot_sink);
     ser.SerializeStrongReferences();

     i::List<char> context_data;
-    ListSnapshotSink contex_sink(&context_data);
+    i::ListSnapshotSink contex_sink(&context_data);
     i::PartialSerializer context_ser(internal_isolate, &ser, &contex_sink);
     context_ser.Serialize(&raw_context);
     ser.SerializeWeakReferences();
=======================================
--- /trunk/src/objects-inl.h    Tue Jul  8 00:05:42 2014 UTC
+++ /trunk/src/objects-inl.h    Wed Jul  9 00:05:10 2014 UTC
@@ -1478,6 +1478,22 @@
 int HeapObject::Size() {
   return SizeFromMap(map());
 }
+
+
+bool HeapObject::ContainsPointers() {
+  InstanceType type = map()->instance_type();
+  if (type <= LAST_NAME_TYPE) {
+    if (type == SYMBOL_TYPE) {
+      return true;
+    }
+    ASSERT(type < FIRST_NONSTRING_TYPE);
+    // There are four string representations: sequential strings, external
+    // strings, cons strings, and sliced strings.
+    // Only the latter two contain non-map-word pointers to heap objects.
+    return ((type & kIsIndirectStringMask) == kIsIndirectStringTag);
+  }
+  return (type > LAST_DATA_TYPE);
+}


 void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
=======================================
--- /trunk/src/objects.h        Tue Jul  8 00:05:42 2014 UTC
+++ /trunk/src/objects.h        Wed Jul  9 00:05:10 2014 UTC
@@ -714,6 +714,7 @@
   FIXED_UINT8_CLAMPED_ARRAY_TYPE,  // LAST_FIXED_TYPED_ARRAY_TYPE

   FIXED_DOUBLE_ARRAY_TYPE,
+  CONSTANT_POOL_ARRAY_TYPE,
   FILLER_TYPE,  // LAST_DATA_TYPE

   // Structs.
@@ -740,7 +741,6 @@
   BREAK_POINT_INFO_TYPE,

   FIXED_ARRAY_TYPE,
-  CONSTANT_POOL_ARRAY_TYPE,
   SHARED_FUNCTION_INFO_TYPE,

// All the following types are subtypes of JSReceiver, which corresponds to
@@ -1557,15 +1557,15 @@
   // Prints this object without details to a message accumulator.
   void ShortPrint(StringStream* accumulator);

-  // For our gdb macros, we should perhaps change these in the future.
-  void Print();
-
   DECLARE_CAST(Object)

   // Layout description.
   static const int kHeaderSize = 0;  // Object does not take up any space.

 #ifdef OBJECT_PRINT
+  // For our gdb macros, we should perhaps change these in the future.
+  void Print();
+
   // Prints this object with details.
   void Print(OStream& os);  // NOLINT
 #endif
@@ -1716,6 +1716,10 @@
   // Returns the heap object's size in bytes
   inline int Size();

+  // Returns true if this heap object contains only references to other
+  // heap objects.
+  inline bool ContainsPointers();
+
   // Given a heap object's map pointer, returns the heap size in bytes
   // Useful when the map pointer field is used for other purposes.
   // GC internal.
=======================================
--- /trunk/src/parser.cc        Tue Jul  8 00:05:42 2014 UTC
+++ /trunk/src/parser.cc        Wed Jul  9 00:05:10 2014 UTC
@@ -182,7 +182,7 @@
 }


-ScriptData* ScriptData::New(const char* data, int length) {
+ScriptData* ScriptData::New(const char* data, int length, bool owns_store) {
   // The length is obviously invalid.
   if (length % sizeof(unsigned) != 0) {
     return NULL;
@@ -190,7 +190,8 @@

   int deserialized_data_length = length / sizeof(unsigned);
   unsigned* deserialized_data;
- bool owns_store = reinterpret_cast<intptr_t>(data) % sizeof(unsigned) != 0;
+  owns_store =
+ owns_store || reinterpret_cast<intptr_t>(data) % sizeof(unsigned) != 0;
   if (owns_store) {
     // Copy the data to align it.
     deserialized_data = i::NewArray<unsigned>(deserialized_data_length);
=======================================
--- /trunk/src/parser.h Mon Jul  7 00:05:07 2014 UTC
+++ /trunk/src/parser.h Wed Jul  9 00:05:10 2014 UTC
@@ -72,7 +72,7 @@
// The created ScriptData won't take ownership of the data. If the alignment // is not correct, this will copy the data (and the created ScriptData will
   // take ownership of the copy).
-  static ScriptData* New(const char* data, int length);
+ static ScriptData* New(const char* data, int length, bool owns_store = false);

   virtual ~ScriptData();
   virtual int Length();
=======================================
--- /trunk/src/serialize.cc     Tue Jul  1 11:58:10 2014 UTC
+++ /trunk/src/serialize.cc     Wed Jul  9 00:05:10 2014 UTC
@@ -19,6 +19,7 @@
 #include "src/snapshot-source-sink.h"
 #include "src/stub-cache.h"
 #include "src/v8threads.h"
+#include "src/version.h"

 namespace v8 {
 namespace internal {
@@ -1794,14 +1795,15 @@
     return Page::kPageSize - Page::kObjectStartOffset;
   }
 }
+
+
+void Serializer::PadByte() { sink_->Put(kNop, "Padding"); }


 void Serializer::Pad() {
   // The non-branching GetInt will read up to 3 bytes too far, so we need
   // to pad the snapshot to make sure we don't read over the end.
-  for (unsigned i = 0; i < sizeof(int32_t) - 1; i++) {
-    sink_->Put(kNop, "Padding");
-  }
+  for (unsigned i = 0; i < sizeof(int32_t) - 1; i++) PadByte();
 }


@@ -1811,4 +1813,101 @@
 }


+ScriptData* CodeSerializer::Serialize(Handle<SharedFunctionInfo> info) {
+  // Serialize code object.
+  List<char> payload;
+  ListSnapshotSink listsink(&payload);
+  CodeSerializer ser(info->GetIsolate(), &listsink);
+  DisallowHeapAllocation no_gc;
+  Object** location = Handle<Object>::cast(info).location();
+  ser.VisitPointer(location);
+  ser.Pad();
+
+  // Allocate storage.  The payload length may not be aligned.  Round up.
+  // TODO(yangguo) replace ScriptData with a more generic super class.
+  int payload_length = payload.length();
+  int raw_length = payload_length / sizeof(unsigned) + kHeaderSize;
+  if (!IsAligned(payload_length, sizeof(unsigned))) raw_length++;
+  unsigned* raw_data = i::NewArray<unsigned>(raw_length);
+  char* payload_data = reinterpret_cast<char*>(raw_data + kHeaderSize);
+
+  // Write header.
+  raw_data[kVersionHashOffset] = Version::Hash();
+  raw_data[kPayloadLengthOffset] = payload_length;
+  STATIC_ASSERT(NEW_SPACE == 0);
+  for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) {
+    raw_data[kReservationsOffset + i] = ser.CurrentAllocationAddress(i);
+  }
+
+ CopyBytes(payload_data, payload.begin(), static_cast<size_t>(payload_length));
+
+  return new ScriptData(Vector<unsigned>(raw_data, raw_length), true);
+}
+
+
+void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
+ WhereToPoint where_to_point, int skip) {
+  CHECK(o->IsHeapObject());
+  HeapObject* heap_object = HeapObject::cast(o);
+
+  // The code-caches link to context-specific code objects, which
+  // the startup and context serializes cannot currently handle.
+  ASSERT(!heap_object->IsMap() ||
+         Map::cast(heap_object)->code_cache() ==
+             heap_object->GetHeap()->empty_fixed_array());
+
+  int root_index;
+ if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) {
+    PutRoot(root_index, heap_object, how_to_code, where_to_point, skip);
+    return;
+  }
+
+  // TODO(yangguo) wire up builtins.
+  // TODO(yangguo) wire up stubs from stub cache.
+  // TODO(yangguo) wire up script source.
+  // TODO(yangguo) wire up internalized strings
+  ASSERT(!heap_object->IsInternalizedString());
+  // TODO(yangguo) We cannot deal with different hash seeds yet.
+  ASSERT(!heap_object->IsHashTable());
+
+  if (address_mapper_.IsMapped(heap_object)) {
+    int space = SpaceOfObject(heap_object);
+    int address = address_mapper_.MappedTo(heap_object);
+    SerializeReferenceToPreviousObject(space, address, how_to_code,
+                                       where_to_point, skip);
+    return;
+  }
+
+  if (skip != 0) {
+    sink_->Put(kSkip, "SkipFromSerializeObject");
+    sink_->PutInt(skip, "SkipDistanceFromSerializeObject");
+  }
+  // Object has not yet been serialized.  Serialize it here.
+  ObjectSerializer serializer(this, heap_object, sink_, how_to_code,
+                              where_to_point);
+  serializer.Serialize();
+}
+
+
+Object* CodeSerializer::Deserialize(Isolate* isolate, ScriptData* data) {
+ const unsigned* raw_data = reinterpret_cast<const unsigned*>(data->Data());
+  CHECK_EQ(Version::Hash(), raw_data[kVersionHashOffset]);
+  int payload_length = raw_data[kPayloadLengthOffset];
+  const byte* payload_data =
+      reinterpret_cast<const byte*>(raw_data + kHeaderSize);
+  ASSERT_LE(payload_length, data->Length() - kHeaderSize);
+
+  SnapshotByteSource payload(payload_data, payload_length);
+  Deserializer deserializer(&payload);
+  STATIC_ASSERT(NEW_SPACE == 0);
+  // TODO(yangguo) what happens if remaining new space is too small?
+  for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) {
+    deserializer.set_reservation(
+        i, raw_data[CodeSerializer::kReservationsOffset + i]);
+  }
+  Object* root;
+  deserializer.DeserializePartial(isolate, &root);
+  ASSERT(root->IsSharedFunctionInfo());
+  return root;
+}
 } }  // namespace v8::internal
=======================================
--- /trunk/src/serialize.h      Tue Jun 24 00:06:56 2014 UTC
+++ /trunk/src/serialize.h      Wed Jul  9 00:05:10 2014 UTC
@@ -8,6 +8,7 @@
 #include "src/hashmap.h"
 #include "src/heap-profiler.h"
 #include "src/isolate.h"
+#include "src/parser.h"
 #include "src/snapshot-source-sink.h"

 namespace v8 {
@@ -469,6 +470,7 @@
   SerializationAddressMapper address_mapper_;
   intptr_t root_index_wave_front_;
   void Pad();
+  void PadByte();

   friend class ObjectSerializer;
   friend class Deserializer;
@@ -551,6 +553,29 @@
 };


+class CodeSerializer : public Serializer {
+ public:
+  CodeSerializer(Isolate* isolate, SnapshotByteSink* sink)
+      : Serializer(isolate, sink) {
+    set_root_index_wave_front(Heap::kStrongRootListLength);
+    InitializeCodeAddressMap();
+  }
+
+  static ScriptData* Serialize(Handle<SharedFunctionInfo> info);
+  virtual void SerializeObject(Object* o, HowToCode how_to_code,
+                               WhereToPoint where_to_point, int skip);
+
+  static Object* Deserialize(Isolate* isolate, ScriptData* data);
+
+  // The data header consists of int-sized entries:
+  // [0] version hash
+  // [1] length in bytes
+ // [2..8] reservation sizes for spaces from NEW_SPACE to PROPERTY_CELL_SPACE.
+  static const int kHeaderSize = 9;
+  static const int kVersionHashOffset = 0;
+  static const int kPayloadLengthOffset = 1;
+  static const int kReservationsOffset = 2;
+};
 } }  // namespace v8::internal

 #endif  // V8_SERIALIZE_H_
=======================================
--- /trunk/src/snapshot-source-sink.cc  Tue Jul  1 11:58:10 2014 UTC
+++ /trunk/src/snapshot-source-sink.cc  Wed Jul  9 00:05:10 2014 UTC
@@ -90,6 +90,12 @@
     return false;
   }
 }
+
+
+void DebugSnapshotSink::Put(int byte, const char* description) {
+  PrintF("%24s: %x\n", description, byte);
+  sink_->Put(byte, description);
+}

 }  // namespace v8::internal
 }  // namespace v8
=======================================
--- /trunk/src/snapshot-source-sink.h   Tue Jul  1 11:58:10 2014 UTC
+++ /trunk/src/snapshot-source-sink.h   Wed Jul  9 00:05:10 2014 UTC
@@ -82,6 +82,42 @@
 };


+class DummySnapshotSink : public SnapshotByteSink {
+ public:
+  DummySnapshotSink() : length_(0) {}
+  virtual ~DummySnapshotSink() {}
+  virtual void Put(int byte, const char* description) { length_++; }
+  virtual int Position() { return length_; }
+
+ private:
+  int length_;
+};
+
+
+// Wrap a SnapshotByteSink into a DebugSnapshotSink to get debugging output.
+class DebugSnapshotSink : public SnapshotByteSink {
+ public:
+  explicit DebugSnapshotSink(SnapshotByteSink* chained) : sink_(chained) {}
+  virtual void Put(int byte, const char* description) V8_OVERRIDE;
+  virtual int Position() V8_OVERRIDE { return sink_->Position(); }
+
+ private:
+  SnapshotByteSink* sink_;
+};
+
+
+class ListSnapshotSink : public i::SnapshotByteSink {
+ public:
+  explicit ListSnapshotSink(i::List<char>* data) : data_(data) {}
+  virtual void Put(int byte, const char* description) V8_OVERRIDE {
+    data_->Add(byte);
+  }
+  virtual int Position() V8_OVERRIDE { return data_->length(); }
+
+ private:
+  i::List<char>* data_;
+};
+
 }  // namespace v8::internal
 }  // namespace v8

=======================================
--- /trunk/src/spaces.cc        Tue Jul  8 00:05:42 2014 UTC
+++ /trunk/src/spaces.cc        Wed Jul  9 00:05:10 2014 UTC
@@ -18,6 +18,9 @@
 // HeapObjectIterator

 HeapObjectIterator::HeapObjectIterator(PagedSpace* space) {
+  // Check that we actually can iterate this space.
+  ASSERT(space->is_iterable());
+
// You can't actually iterate over the anchor page. It is not a real page, // just an anchor for the double linked page list. Initialize as if we have // reached the end of the anchor page, then the first iteration will move on
@@ -32,6 +35,9 @@

 HeapObjectIterator::HeapObjectIterator(PagedSpace* space,
                                        HeapObjectCallback size_func) {
+  // Check that we actually can iterate this space.
+  ASSERT(space->is_iterable());
+
// You can't actually iterate over the anchor page. It is not a real page, // just an anchor for the double linked page list. Initialize the current
   // address and end as NULL, then the first iteration will move on
@@ -66,9 +72,6 @@
                                     Address cur, Address end,
                                     HeapObjectIterator::PageMode mode,
                                     HeapObjectCallback size_f) {
-  // Check that we actually can iterate this space.
-  ASSERT(space->is_iterable());
-
   space_ = space;
   cur_addr_ = cur;
   cur_end_ = end;
=======================================
--- /trunk/src/store-buffer.cc  Tue Jul  8 00:05:42 2014 UTC
+++ /trunk/src/store-buffer.cc  Wed Jul  9 00:05:10 2014 UTC
@@ -11,6 +11,7 @@
 #include "src/base/atomicops.h"
 #include "src/counters.h"
 #include "src/store-buffer-inl.h"
+#include "src/utils.h"

 namespace v8 {
 namespace internal {
@@ -22,10 +23,13 @@
       old_start_(NULL),
       old_limit_(NULL),
       old_top_(NULL),
+      old_regular_limit_(NULL),
       old_reserved_limit_(NULL),
+      old_virtual_memory_(NULL),
+      old_store_buffer_length_(0),
       old_buffer_is_sorted_(false),
       old_buffer_is_filtered_(false),
-      during_gc_(false),
+      allow_overflow_(false),
       store_buffer_rebuilding_enabled_(false),
       callback_(NULL),
       may_move_store_buffer_entries_(true),
@@ -44,8 +48,16 @@
reinterpret_cast<Address*>(RoundUp(start_as_int, kStoreBufferSize * 2));
   limit_ = start_ + (kStoreBufferSize / kPointerSize);

+ // We set the maximum store buffer size to the maximum size of a semi-space. + // The store buffer may reach this limit during a full garbage collection. + // Note that half of the semi-space should be good enough since half of the
+  // memory in the semi-space are not object pointers.
+  old_store_buffer_length_ =
+      Max(static_cast<int>(heap_->MaxSemiSpaceSize() / sizeof(Address)),
+          kOldRegularStoreBufferLength);
+
   old_virtual_memory_ =
-      new base::VirtualMemory(kOldStoreBufferLength * kPointerSize);
+      new base::VirtualMemory(old_store_buffer_length_ * kPointerSize);
   old_top_ = old_start_ =
       reinterpret_cast<Address*>(old_virtual_memory_->address());
// Don't know the alignment requirements of the OS, but it is certainly not
@@ -54,9 +66,12 @@
   int initial_length =
       static_cast<int>(base::OS::CommitPageSize() / kPointerSize);
   ASSERT(initial_length > 0);
-  ASSERT(initial_length <= kOldStoreBufferLength);
+  ASSERT(initial_length <= kOldRegularStoreBufferLength);
+  ASSERT(initial_length <= old_store_buffer_length_);
+  ASSERT(kOldRegularStoreBufferLength <= old_store_buffer_length_);
   old_limit_ = old_start_ + initial_length;
-  old_reserved_limit_ = old_start_ + kOldStoreBufferLength;
+  old_regular_limit_ = old_start_ + kOldRegularStoreBufferLength;
+  old_reserved_limit_ = old_start_ + old_store_buffer_length_;

   CHECK(old_virtual_memory_->Commit(
             reinterpret_cast<void*>(old_start_),
@@ -93,8 +108,13 @@
   delete old_virtual_memory_;
   delete[] hash_set_1_;
   delete[] hash_set_2_;
-  old_start_ = old_top_ = old_limit_ = old_reserved_limit_ = NULL;
-  start_ = limit_ = NULL;
+  old_start_ = NULL;
+  old_top_ = NULL;
+  old_limit_ = NULL;
+  old_reserved_limit_ = NULL;
+  old_regular_limit_ = NULL;
+  start_ = NULL;
+  limit_ = NULL;
   heap_->public_set_store_buffer_top(start_);
 }

@@ -126,11 +146,37 @@
 bool StoreBuffer::SpaceAvailable(intptr_t space_needed) {
   return old_limit_ - old_top_ >= space_needed;
 }
+
+
+template<StoreBuffer::ExemptPopularPagesMode mode>
+void StoreBuffer::IterativelyExemptPopularPages(intptr_t space_needed) {
+ // Sample 1 entry in 97 and filter out the pages where we estimate that more
+  // than 1 in 8 pointers are to new space.
+  static const int kSampleFinenesses = 5;
+  static const struct Samples {
+    int prime_sample_step;
+    int threshold;
+  } samples[kSampleFinenesses] =  {
+    { 97, ((Page::kPageSize / kPointerSize) / 97) / 8 },
+    { 23, ((Page::kPageSize / kPointerSize) / 23) / 16 },
+    { 7, ((Page::kPageSize / kPointerSize) / 7) / 32 },
+    { 3, ((Page::kPageSize / kPointerSize) / 3) / 256 },
+    { 1, 0}
+  };
+  for (int i = 0; i < kSampleFinenesses; i++) {
+    ExemptPopularPages(samples[i].prime_sample_step, samples[i].threshold);
+ // As a last resort we mark all pages as being exempt from the store buffer.
+    ASSERT(i != (kSampleFinenesses - 1) || old_top_ == old_start_);
+    if (mode == ENSURE_SPACE && SpaceAvailable(space_needed)) return;
+ else if (mode == SHRINK_TO_REGULAR_SIZE && old_top_ < old_limit_) return;
+  }
+}


 void StoreBuffer::EnsureSpace(intptr_t space_needed) {
   while (old_limit_ - old_top_ < space_needed &&
-         old_limit_ < old_reserved_limit_) {
+      ((!allow_overflow_ && old_limit_ < old_regular_limit_) ||
+          (allow_overflow_ && old_limit_ < old_reserved_limit_))) {
     size_t grow = old_limit_ - old_start_;  // Double size.
     CHECK(old_virtual_memory_->Commit(reinterpret_cast<void*>(old_limit_),
                                       grow * kPointerSize,
@@ -162,26 +208,8 @@

   if (SpaceAvailable(space_needed)) return;

- // Sample 1 entry in 97 and filter out the pages where we estimate that more
-  // than 1 in 8 pointers are to new space.
-  static const int kSampleFinenesses = 5;
-  static const struct Samples {
-    int prime_sample_step;
-    int threshold;
-  } samples[kSampleFinenesses] =  {
-    { 97, ((Page::kPageSize / kPointerSize) / 97) / 8 },
-    { 23, ((Page::kPageSize / kPointerSize) / 23) / 16 },
-    { 7, ((Page::kPageSize / kPointerSize) / 7) / 32 },
-    { 3, ((Page::kPageSize / kPointerSize) / 3) / 256 },
-    { 1, 0}
-  };
-  for (int i = 0; i < kSampleFinenesses; i++) {
-    ExemptPopularPages(samples[i].prime_sample_step, samples[i].threshold);
- // As a last resort we mark all pages as being exempt from the store buffer.
-    ASSERT(i != (kSampleFinenesses - 1) || old_top_ == old_start_);
-    if (SpaceAvailable(space_needed)) return;
-  }
-  UNREACHABLE();
+  IterativelyExemptPopularPages<ENSURE_SPACE>(space_needed);
+  ASSERT(SpaceAvailable(space_needed));
 }


@@ -328,9 +356,9 @@
 }


-void StoreBuffer::GCPrologue() {
+void StoreBuffer::GCPrologue(bool allow_overflow) {
   ClearFilteringHashSets();
-  during_gc_ = true;
+  allow_overflow_ = allow_overflow;
 }


@@ -366,7 +394,13 @@


 void StoreBuffer::GCEpilogue() {
-  during_gc_ = false;
+  if (allow_overflow_ && old_limit_ > old_regular_limit_) {
+    IterativelyExemptPopularPages<SHRINK_TO_REGULAR_SIZE>(0);
+    ASSERT(old_limit_ < old_regular_limit_);
+ old_virtual_memory_->Uncommit(old_limit_, old_regular_limit_ - old_limit_);
+  }
+
+  allow_overflow_ = false;
 #ifdef VERIFY_HEAP
   if (FLAG_verify_heap) {
     Verify();
@@ -488,25 +522,22 @@
FindPointersToNewSpaceInRegion(start, end, slot_callback, clear_maps);
         } else {
           Page* page = reinterpret_cast<Page*>(chunk);
-          PagedSpace* owner = reinterpret_cast<PagedSpace*>(page->owner());
-          Address start = page->area_start();
-          Address end = page->area_end();
-          if (owner == heap_->map_space()) {
-            ASSERT(page->WasSweptPrecisely());
-            HeapObjectIterator iterator(page, NULL);
- for (HeapObject* heap_object = iterator.Next(); heap_object != NULL;
-                 heap_object = iterator.Next()) {
-              // We skip free space objects.
-              if (!heap_object->IsFiller()) {
-                FindPointersToNewSpaceInRegion(
-                    heap_object->address() + HeapObject::kHeaderSize,
- heap_object->address() + heap_object->Size(), slot_callback,
-                    clear_maps);
-              }
+          ASSERT(page->owner() == heap_->map_space() ||
+                 page->owner() == heap_->old_pointer_space());
+          CHECK(!page->WasSweptConservatively());
+
+          HeapObjectIterator iterator(page, NULL);
+          for (HeapObject* heap_object = iterator.Next();
+               heap_object != NULL;
+               heap_object = iterator.Next()) {
+            // We iterate over objects that contain pointers only.
+            if (heap_object->ContainsPointers()) {
+              FindPointersToNewSpaceInRegion(
+                  heap_object->address() + HeapObject::kHeaderSize,
+                  heap_object->address() + heap_object->Size(),
+                  slot_callback,
+                  clear_maps);
             }
-          } else {
-            FindPointersToNewSpaceInRegion(
-                start, end, slot_callback, clear_maps);
           }
         }
       }
=======================================
--- /trunk/src/store-buffer.h   Mon Jul  7 00:05:07 2014 UTC
+++ /trunk/src/store-buffer.h   Wed Jul  9 00:05:10 2014 UTC
@@ -19,11 +19,6 @@

 typedef void (*ObjectSlotCallback)(HeapObject** from, HeapObject* to);

-typedef void (StoreBuffer::*RegionCallback)(Address start,
-                                            Address end,
- ObjectSlotCallback slot_callback,
-                                            bool clear_maps);
-
 // Used to implement the write barrier by collecting addresses of pointers
 // between spaces.
 class StoreBuffer {
@@ -68,13 +63,13 @@
   static const int kStoreBufferOverflowBit = 1 << (14 + kPointerSizeLog2);
   static const int kStoreBufferSize = kStoreBufferOverflowBit;
   static const int kStoreBufferLength = kStoreBufferSize / sizeof(Address);
-  static const int kOldStoreBufferLength = kStoreBufferLength * 16;
+  static const int kOldRegularStoreBufferLength = kStoreBufferLength * 16;
   static const int kHashSetLengthLog2 = 12;
   static const int kHashSetLength = 1 << kHashSetLengthLog2;

   void Compact();

-  void GCPrologue();
+  void GCPrologue(bool allow_overflow);
   void GCEpilogue();

   Object*** Limit() { return reinterpret_cast<Object***>(old_limit_); }
@@ -118,12 +113,27 @@
   Address* old_start_;
   Address* old_limit_;
   Address* old_top_;
+
+  // The regular limit specifies how big the store buffer may become during
+  // mutator execution or while scavenging.
+  Address* old_regular_limit_;
+
+ // The reserved limit is bigger then the regular limit. It should be the size + // of a semi-space to avoid new scan-on-scavenge during new space evacuation
+  // after sweeping in a full garbage collection.
   Address* old_reserved_limit_;
+
   base::VirtualMemory* old_virtual_memory_;
+  int old_store_buffer_length_;

   bool old_buffer_is_sorted_;
   bool old_buffer_is_filtered_;
-  bool during_gc_;
+
+  // If allow_overflow_ is set, we allow the store buffer to grow until
+ // old_reserved_limit_. But we will shrink the store buffer in the epilogue to
+  // stay within the old_regular_limit_.
+  bool allow_overflow_;
+
// The garbage collector iterates over many pointers to new space that are not
   // handled by the store buffer.  This flag indicates whether the pointers
   // found by the callbacks should be added to the store buffer or not.
@@ -146,6 +156,14 @@
   void Uniq();
   void ExemptPopularPages(int prime_sample_step, int threshold);

+  enum ExemptPopularPagesMode {
+    ENSURE_SPACE,
+    SHRINK_TO_REGULAR_SIZE
+  };
+
+  template <ExemptPopularPagesMode mode>
+  void IterativelyExemptPopularPages(intptr_t space_needed);
+
   // Set the map field of the object to NULL if contains a map.
   inline void ClearDeadObject(HeapObject *object);

@@ -156,17 +174,6 @@
                                       ObjectSlotCallback slot_callback,
                                       bool clear_maps);

-  // For each region of pointers on a page in use from an old space call
-  // visit_pointer_region callback.
-  // If either visit_pointer_region or callback can cause an allocation
-  // in old space and changes in allocation watermark then
-  // can_preallocate_during_iteration should be set to true.
-  void IteratePointersOnPage(
-      PagedSpace* space,
-      Page* page,
-      RegionCallback region_callback,
-      ObjectSlotCallback slot_callback);
-
   void IteratePointersInStoreBuffer(ObjectSlotCallback slot_callback,
                                     bool clear_maps);

=======================================
--- /trunk/src/version.cc       Tue Jul  8 06:57:45 2014 UTC
+++ /trunk/src/version.cc       Wed Jul  9 00:05:10 2014 UTC
@@ -34,7 +34,7 @@
 // system so their names cannot be changed without changing the scripts.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     28
-#define BUILD_NUMBER      17
+#define BUILD_NUMBER      18
 #define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
=======================================
--- /trunk/src/version.h        Tue Apr 29 16:30:47 2014 UTC
+++ /trunk/src/version.h        Wed Jul  9 00:05:10 2014 UTC
@@ -16,6 +16,7 @@
   static int GetBuild() { return build_; }
   static int GetPatch() { return patch_; }
   static bool IsCandidate() { return candidate_; }
+  static int Hash() { return (major_ << 20) ^ (minor_ << 10) ^ patch_; }

   // Calculate the V8 version string.
   static void GetString(Vector<char> str);
=======================================
--- /trunk/test/cctest/cctest.status    Tue Jul  1 11:58:10 2014 UTC
+++ /trunk/test/cctest/cctest.status    Wed Jul  9 00:05:10 2014 UTC
@@ -75,6 +75,9 @@
   # BUG(3287). (test-cpu-profiler/SampleWhenFrameIsNotSetup)
   'test-cpu-profiler/*': [PASS, FLAKY],

+  # TODO(yangguo): Temporarily disable code serializer test
+  'test-compiler/SerializeToplevel': [SKIP],
+
############################################################################
   # Slow tests.
   'test-api/Threading1': [PASS, ['mode == debug', SLOW]],
=======================================
--- /trunk/test/cctest/test-compiler.cc Mon Jun 30 00:04:54 2014 UTC
+++ /trunk/test/cctest/test-compiler.cc Wed Jul  9 00:05:10 2014 UTC
@@ -32,6 +32,7 @@

 #include "src/compiler.h"
 #include "src/disasm.h"
+#include "src/parser.h"
 #include "test/cctest/cctest.h"

 using namespace v8::internal;
@@ -396,6 +397,46 @@
     CHECK_EQ(fun1->code(), fun2->code());
   }
 }
+
+
+TEST(SerializeToplevel) {
+  FLAG_serialize_toplevel = true;
+  v8::HandleScope scope(CcTest::isolate());
+  v8::Local<v8::Context> context = CcTest::NewContext(PRINT_EXTENSION);
+  v8::Context::Scope context_scope(context);
+
+  const char* source1 = "1 + 1";
+ const char* source2 = "1 + 2"; // Use alternate string to verify caching.
+
+  Isolate* isolate = CcTest::i_isolate();
+  Handle<String> source1_string = isolate->factory()
+ ->NewStringFromUtf8(CStrVector(source1))
+                                      .ToHandleChecked();
+  Handle<String> source2_string = isolate->factory()
+ ->NewStringFromUtf8(CStrVector(source2))
+                                      .ToHandleChecked();
+
+  ScriptData* cache = NULL;
+
+  Handle<SharedFunctionInfo> orig =
+ Compiler::CompileScript(source1_string, Handle<String>(), 0, 0, false, + Handle<Context>(isolate->native_context()), NULL, + &cache, PRODUCE_CACHED_DATA, NOT_NATIVES_CODE);
+
+  Handle<SharedFunctionInfo> info =
+ Compiler::CompileScript(source2_string, Handle<String>(), 0, 0, false, + Handle<Context>(isolate->native_context()), NULL, + &cache, CONSUME_CACHED_DATA, NOT_NATIVES_CODE);
+
+  CHECK_NE(*orig, *info);
+  Handle<JSFunction> fun =
+      isolate->factory()->NewFunctionFromSharedFunctionInfo(
+          info, isolate->native_context());
+  Handle<JSObject> global(isolate->context()->global_object());
+  Handle<Object> result =
+      Execution::Call(isolate, fun, global, 0, NULL).ToHandleChecked();
+  CHECK_EQ(2, Handle<Smi>::cast(result)->value());
+}


 #ifdef ENABLE_DISASSEMBLER
=======================================
--- /trunk/test/cctest/test-debug.cc    Mon Jul  7 00:05:07 2014 UTC
+++ /trunk/test/cctest/test-debug.cc    Wed Jul  9 00:05:10 2014 UTC
@@ -7374,9 +7374,6 @@
   // Wait for at most 2 seconds for the terminate request.
CHECK(terminate_fired_semaphore.WaitFor(v8::base::TimeDelta::FromSeconds(2)));
   terminate_already_fired = true;
-  v8::internal::Isolate* isolate =
- v8::Utils::OpenHandle(*event_details.GetEventContext())->GetIsolate();
-  CHECK(isolate->stack_guard()->CheckTerminateExecution());
 }


@@ -7403,6 +7400,8 @@
   v8::Debug::SetDebugEventListener(DebugBreakTriggerTerminate);
   TerminationThread terminator(isolate);
   terminator.Start();
+  v8::TryCatch try_catch;
   v8::Debug::DebugBreak(isolate);
   CompileRun("while (true);");
+  CHECK(try_catch.HasTerminated());
 }

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to