Revision: 22371
Author:   yang...@chromium.org
Date:     Mon Jul 14 11:22:03 2014 UTC
Log:      Serialize builtins by referencing canonical ones.

R=mvstan...@chromium.org

Review URL: https://codereview.chromium.org/383173002
http://code.google.com/p/v8/source/detail?r=22371

Modified:
 /branches/bleeding_edge/src/serialize.cc
 /branches/bleeding_edge/src/serialize.h
 /branches/bleeding_edge/test/cctest/test-compiler.cc
 /branches/bleeding_edge/test/cctest/test-serialize.cc

=======================================
--- /branches/bleeding_edge/src/serialize.cc    Fri Jul 11 07:04:51 2014 UTC
+++ /branches/bleeding_edge/src/serialize.cc    Mon Jul 14 11:22:03 2014 UTC
@@ -889,83 +889,88 @@
     STATIC_ASSERT((space_number & ~kSpaceMask) == 0);

#define CASE_BODY(where, how, within, space_number_if_any) \ - { \ - bool emit_write_barrier = false; \ - bool current_was_incremented = false; \ - int space_number = space_number_if_any == kAnyOldSpace ? \ - (data & kSpaceMask) : space_number_if_any; \ - if (where == kNewObject && how == kPlain && within == kStartOfObject) {\ - ReadObject(space_number, current); \ - emit_write_barrier = (space_number == NEW_SPACE); \ + { \ + bool emit_write_barrier = false; \ + bool current_was_incremented = false; \ + int space_number = space_number_if_any == kAnyOldSpace \ + ? (data & kSpaceMask) \ + : space_number_if_any; \ + if (where == kNewObject && how == kPlain && within == kStartOfObject) { \ + ReadObject(space_number, current); \ + emit_write_barrier = (space_number == NEW_SPACE); \ + } else { \ + Object* new_object = NULL; /* May not be a real Object pointer. */ \ + if (where == kNewObject) { \ + ReadObject(space_number, &new_object); \ + } else if (where == kRootArray) { \ + int root_id = source_->GetInt(); \ + new_object = isolate->heap()->roots_array_start()[root_id]; \ + emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ + } else if (where == kPartialSnapshotCache) { \ + int cache_index = source_->GetInt(); \ + new_object = isolate->serialize_partial_snapshot_cache()[cache_index]; \ + emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ + } else if (where == kExternalReference) { \ + int skip = source_->GetInt(); \ + current = reinterpret_cast<Object**>( \ + reinterpret_cast<Address>(current) + skip); \ + int reference_id = source_->GetInt(); \ + Address address = external_reference_decoder_->Decode(reference_id); \ + new_object = reinterpret_cast<Object*>(address); \ + } else if (where == kBackref) { \ + emit_write_barrier = (space_number == NEW_SPACE); \ + new_object = GetAddressFromEnd(data & kSpaceMask); \ + } else if (where == kBuiltin) { \ + int builtin_id = source_->GetInt(); \ + ASSERT_LE(0, builtin_id); \ + ASSERT_LT(builtin_id, Builtins::builtin_count); \ + Builtins::Name name = static_cast<Builtins::Name>(builtin_id); \ + new_object = isolate->builtins()->builtin(name); \ + emit_write_barrier = false; \ + PrintF("BUILTIN how within %d, %d\n", how, within); \ + } else { \ + ASSERT(where == kBackrefWithSkip); \ + int skip = source_->GetInt(); \ + current = reinterpret_cast<Object**>( \ + reinterpret_cast<Address>(current) + skip); \ + emit_write_barrier = (space_number == NEW_SPACE); \ + new_object = GetAddressFromEnd(data & kSpaceMask); \ + } \ + if (within == kInnerPointer) { \ + if (space_number != CODE_SPACE || new_object->IsCode()) { \ + Code* new_code_object = reinterpret_cast<Code*>(new_object); \ + new_object = \ + reinterpret_cast<Object*>(new_code_object->instruction_start()); \ } else { \ - Object* new_object = NULL; /* May not be a real Object pointer. */ \ - if (where == kNewObject) { \ - ReadObject(space_number, &new_object); \ - } else if (where == kRootArray) { \ - int root_id = source_->GetInt(); \ - new_object = isolate->heap()->roots_array_start()[root_id]; \ - emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ - } else if (where == kPartialSnapshotCache) { \ - int cache_index = source_->GetInt(); \ - new_object = isolate->serialize_partial_snapshot_cache() \ - [cache_index]; \ - emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ - } else if (where == kExternalReference) { \ - int skip = source_->GetInt(); \ - current = reinterpret_cast<Object**>(reinterpret_cast<Address>( \ - current) + skip); \ - int reference_id = source_->GetInt(); \ - Address address = external_reference_decoder_-> \ - Decode(reference_id); \ - new_object = reinterpret_cast<Object*>(address); \ - } else if (where == kBackref) { \ - emit_write_barrier = (space_number == NEW_SPACE); \ - new_object = GetAddressFromEnd(data & kSpaceMask); \ - } else { \ - ASSERT(where == kBackrefWithSkip); \ - int skip = source_->GetInt(); \ - current = reinterpret_cast<Object**>( \ - reinterpret_cast<Address>(current) + skip); \ - emit_write_barrier = (space_number == NEW_SPACE); \ - new_object = GetAddressFromEnd(data & kSpaceMask); \ - } \ - if (within == kInnerPointer) { \ - if (space_number != CODE_SPACE || new_object->IsCode()) { \ - Code* new_code_object = reinterpret_cast<Code*>(new_object); \ - new_object = reinterpret_cast<Object*>( \ - new_code_object->instruction_start()); \ - } else { \ - ASSERT(space_number == CODE_SPACE); \ - Cell* cell = Cell::cast(new_object); \ - new_object = reinterpret_cast<Object*>( \ - cell->ValueAddress()); \ - } \ - } \ - if (how == kFromCode) { \ - Address location_of_branch_data = \ - reinterpret_cast<Address>(current); \ - Assembler::deserialization_set_special_target_at( \ - location_of_branch_data, \ - Code::cast(HeapObject::FromAddress(current_object_address)), \ - reinterpret_cast<Address>(new_object)); \ - location_of_branch_data += Assembler::kSpecialTargetSize; \ - current = reinterpret_cast<Object**>(location_of_branch_data); \ - current_was_incremented = true; \ - } else { \ - *current = new_object; \ - } \ + ASSERT(space_number == CODE_SPACE); \ + Cell* cell = Cell::cast(new_object); \ + new_object = reinterpret_cast<Object*>(cell->ValueAddress()); \ } \ - if (emit_write_barrier && write_barrier_needed) { \ - Address current_address = reinterpret_cast<Address>(current); \ - isolate->heap()->RecordWrite( \ - current_object_address, \ - static_cast<int>(current_address - current_object_address)); \ - } \ - if (!current_was_incremented) { \ - current++; \ - } \ - break; \ } \ + if (how == kFromCode) { \ + Address location_of_branch_data = reinterpret_cast<Address>(current); \ + Assembler::deserialization_set_special_target_at( \ + location_of_branch_data, \ + Code::cast(HeapObject::FromAddress(current_object_address)), \ + reinterpret_cast<Address>(new_object)); \ + location_of_branch_data += Assembler::kSpecialTargetSize; \ + current = reinterpret_cast<Object**>(location_of_branch_data); \ + current_was_incremented = true; \ + } else { \ + *current = new_object; \ + } \ + } \ + if (emit_write_barrier && write_barrier_needed) { \ + Address current_address = reinterpret_cast<Address>(current); \ + isolate->heap()->RecordWrite( \ + current_object_address, \ + static_cast<int>(current_address - current_object_address)); \ + } \ + if (!current_was_incremented) { \ + current++; \ + } \ + break; \
+  }

// This generates a case and a body for the new space (which has to do extra
 // write barrier handling) and handles the other spaces with 8 fall-through
@@ -1161,6 +1166,12 @@
                 kFromCode,
                 kStartOfObject,
                 0)
+      // Find a builtin and write a pointer to it to the current object.
+      CASE_STATEMENT(kBuiltin, kPlain, kStartOfObject, 0)
+      CASE_BODY(kBuiltin, kPlain, kStartOfObject, 0)
+ // Find a builtin and write a pointer to it in the current code object.
+      CASE_STATEMENT(kBuiltin, kFromCode, kInnerPointer, 0)
+      CASE_BODY(kBuiltin, kFromCode, kInnerPointer, 0)

 #undef CASE_STATEMENT
 #undef CASE_BODY
@@ -1717,7 +1728,7 @@
   int up_to_offset = static_cast<int>(up_to - object_start);
   int to_skip = up_to_offset - bytes_processed_so_far_;
   int bytes_to_output = to_skip;
-  bytes_processed_so_far_ +=  to_skip;
+  bytes_processed_so_far_ += to_skip;
// This assert will fail if the reloc info gives us the target_address_address
   // locations in a non-ascending order.  Luckily that doesn't happen.
   ASSERT(to_skip >= 0);
@@ -1846,7 +1857,6 @@
     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
@@ -1854,6 +1864,14 @@
   // TODO(yangguo) We cannot deal with different hash seeds yet.
   ASSERT(!heap_object->IsHashTable());

+  if (heap_object->IsCode()) {
+    Code* code_object = Code::cast(heap_object);
+    if (code_object->kind() == Code::BUILTIN) {
+      SerializeBuiltin(code_object, how_to_code, where_to_point, skip);
+      return;
+    }
+  }
+
   if (address_mapper_.IsMapped(heap_object)) {
     int space = SpaceOfObject(heap_object);
     int address = address_mapper_.MappedTo(heap_object);
@@ -1871,6 +1889,27 @@
                               where_to_point);
   serializer.Serialize();
 }
+
+
+void CodeSerializer::SerializeBuiltin(Code* builtin, HowToCode how_to_code,
+ WhereToPoint where_to_point, int skip) {
+  if (skip != 0) {
+    sink_->Put(kSkip, "SkipFromSerializeBuiltin");
+    sink_->PutInt(skip, "SkipDistanceFromSerializeBuiltin");
+  }
+
+  ASSERT((how_to_code == kPlain && where_to_point == kStartOfObject) ||
+         (how_to_code == kFromCode && where_to_point == kInnerPointer));
+  int id = 0;
+  do {  // Look for existing builtins in the list.
+ Code* b = isolate()->builtins()->builtin(static_cast<Builtins::Name>(id));
+    if (builtin == b) break;
+  } while (++id < Builtins::builtin_count);
+  ASSERT(id < Builtins::builtin_count);  // We must have found a one.
+
+  sink_->Put(kBuiltin + how_to_code + where_to_point, "Builtin");
+  sink_->PutInt(id, "builtin_index");
+}


 Object* CodeSerializer::Deserialize(Isolate* isolate, ScriptData* data) {
=======================================
--- /branches/bleeding_edge/src/serialize.h     Thu Jul 10 10:28:05 2014 UTC
+++ /branches/bleeding_edge/src/serialize.h     Mon Jul 14 11:22:03 2014 UTC
@@ -148,17 +148,18 @@
  protected:
   // Where the pointed-to object can be found:
   enum Where {
-    kNewObject = 0,                 // Object is next in snapshot.
+    kNewObject = 0,  // Object is next in snapshot.
     // 1-6                             One per space.
-    kRootArray = 0x9,               // Object is found in root array.
-    kPartialSnapshotCache = 0xa,    // Object is in the cache.
-    kExternalReference = 0xb,       // Pointer to an external reference.
-    kSkip = 0xc,                    // Skip n bytes.
-    kNop = 0xd,                     // Does nothing, used to pad.
-    // 0xe-0xf                         Free.
-    kBackref = 0x10,                // Object is described relative to end.
+    kRootArray = 0x9,             // Object is found in root array.
+    kPartialSnapshotCache = 0xa,  // Object is in the cache.
+    kExternalReference = 0xb,     // Pointer to an external reference.
+    kSkip = 0xc,                  // Skip n bytes.
+    kBuiltin = 0xd,               // Builtin code object.
+    // 0xe                             Free.
+    kNop = 0xf,       // Does nothing, used to pad.
+    kBackref = 0x10,  // Object is described relative to end.
     // 0x11-0x16                       One per space.
-    kBackrefWithSkip = 0x18,        // Object is described relative to end.
+    kBackrefWithSkip = 0x18,  // Object is described relative to end.
     // 0x19-0x1e                       One per space.
     // 0x20-0x3f                       Used by misc. tags below.
     kPointedToMask = 0x3f
@@ -566,14 +567,9 @@

   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;
+ private:
+  void SerializeBuiltin(Code* builtin, HowToCode how_to_code,
+                        WhereToPoint where_to_point, int skip);
 };


=======================================
--- /branches/bleeding_edge/test/cctest/test-compiler.cc Tue Jul 8 14:13:50 2014 UTC +++ /branches/bleeding_edge/test/cctest/test-compiler.cc Mon Jul 14 11:22:03 2014 UTC
@@ -397,48 +397,6 @@
     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());
-
-  delete cache;
-}


 #ifdef ENABLE_DISASSEMBLER
=======================================
--- /branches/bleeding_edge/test/cctest/test-serialize.cc Thu Jul 10 10:28:05 2014 UTC +++ /branches/bleeding_edge/test/cctest/test-serialize.cc Mon Jul 14 11:22:03 2014 UTC
@@ -661,3 +661,62 @@
   bool ArtificialFailure2 = false;
   CHECK(ArtificialFailure2);
 }
+
+
+int CountBuiltins() {
+  // Check that we have not deserialized any additional builtin.
+  HeapIterator iterator(CcTest::heap());
+  DisallowHeapAllocation no_allocation;
+  int counter = 0;
+ for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { + if (obj->IsCode() && Code::cast(obj)->kind() == Code::BUILTIN) counter++;
+  }
+  return counter;
+}
+
+
+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);
+
+  int builtins_count = CountBuiltins();
+
+  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());
+
+  CHECK_EQ(builtins_count, CountBuiltins());
+
+  delete cache;
+}

--
--
v8-dev mailing list
v8-dev@googlegroups.com
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 v8-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to