Reviewers: mvstanton,

Description:
Correctly hook up back references to internalized strings in code deserializer.

[email protected]

Please review this at https://codereview.chromium.org/411483002/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files (+54, -7 lines):
  M src/objects.h
  M src/objects-inl.h
  M src/serialize.h
  M src/serialize.cc
  A + test/mjsunit/deserialize-reference.js


Index: src/objects-inl.h
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 0aca5cfcdb488b0718af22d18c95afc69a17da19..4cbd65a4985d1811ff9d131436c6edae4119c694 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -6580,6 +6580,30 @@ bool String::AsArrayIndex(uint32_t* index) {
 }


+void String::SetForwardedInternalizedString(String* canonical) {
+  ASSERT(IsInternalizedString());
+  ASSERT(canonical->IsInternalizedString());
+  ASSERT(SlowEquals(canonical));
+  ASSERT(HasHashCode());
+  ASSERT(canonical->HasHashCode());
+  WRITE_FIELD(this, kHashFieldOffset, canonical);
+ // With canonical being a string, the LSB is set. Interpreted as hash code, + // this means that the hash code uninitialized. We use this for distinction.
+  ASSERT(!HasHashCode());
+}
+
+
+String* String::GetForwardedInternalizedString() {
+  ASSERT(IsInternalizedString());
+  if (HasHashCode()) return this;
+  String* canonical = String::cast(READ_FIELD(this, kHashFieldOffset));
+  ASSERT(canonical->IsInternalizedString());
+  ASSERT(SlowEquals(canonical));
+  ASSERT(canonical->HasHashCode());
+  return canonical;
+}
+
+
 Object* JSReceiver::GetConstructor() {
   return map()->constructor();
 }
Index: src/objects.h
diff --git a/src/objects.h b/src/objects.h
index e7f5a598d99be6c65283da8067b9152db35f333e..b049dbf8c094b109a422a37e5b3825ab584d36c7 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -9325,6 +9325,11 @@ class String: public Name {
   static Handle<FixedArray> CalculateLineEnds(Handle<String> string,
                                               bool include_ending_line);

+  // Use the hash field to forward to the canonical internalized string
+  // when deserializing an internalized string.
+  inline void SetForwardedInternalizedString(String* string);
+  inline String* GetForwardedInternalizedString();
+
  private:
   friend class Name;
   friend class StringTableInsertionKey;
Index: src/serialize.cc
diff --git a/src/serialize.cc b/src/serialize.cc
index c35464e2f8e37954f753e7129ac61e82349fd1e2..08c9cd145983305f17a1b9e989e4a2bfe04fe93b 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -867,7 +867,7 @@ class StringTableInsertionKey : public HashTableKey {
 };


-HeapObject* Deserializer::ProcessObjectFromSerializedCode(HeapObject* obj) { +HeapObject* Deserializer::ProcessNewObjectFromSerializedCode(HeapObject* obj) {
   if (obj->IsString()) {
     String* string = String::cast(obj);
     // Uninitialize hash field as the hash seed may have changed.
@@ -876,13 +876,23 @@ HeapObject* Deserializer::ProcessObjectFromSerializedCode(HeapObject* obj) {
       DisallowHeapAllocation no_gc;
       HandleScope scope(isolate_);
       StringTableInsertionKey key(string);
-      return *StringTable::LookupKey(isolate_, &key);
+      String* canonical = *StringTable::LookupKey(isolate_, &key);
+      string->SetForwardedInternalizedString(canonical);
+      return canonical;
     }
   }
   return obj;
 }


+Object* Deserializer::ProcessBackRefInSerializedCode(Object* obj) {
+  if (obj->IsInternalizedString()) {
+    return String::cast(obj)->GetForwardedInternalizedString();
+  }
+  return obj;
+}
+
+
 // This routine writes the new object into the pointer provided and then
 // returns true if the new object was in young space and false otherwise.
 // The reason for this strange interface is that otherwise the object is
@@ -907,7 +917,7 @@ void Deserializer::ReadObject(int space_number,
if (obj->IsAllocationSite()) RelinkAllocationSite(AllocationSite::cast(obj));

   // Fix up strings from serialized user code.
- if (deserializing_user_code()) obj = ProcessObjectFromSerializedCode(obj); + if (deserializing_user_code()) obj = ProcessNewObjectFromSerializedCode(obj);

   *write_back = obj;
 #ifdef DEBUG
@@ -972,6 +982,9 @@ void Deserializer::ReadChunk(Object** current,
} else if (where == kBackref) { \ emit_write_barrier = (space_number == NEW_SPACE); \ new_object = GetAddressFromEnd(data & kSpaceMask); \ + if (deserializing_user_code()) { \ + new_object = ProcessBackRefInSerializedCode(new_object); \ + } \ } else if (where == kBuiltin) { \ ASSERT(deserializing_user_code()); \ int builtin_id = source_->GetInt(); \
@@ -992,6 +1005,9 @@ void Deserializer::ReadChunk(Object** current,
reinterpret_cast<Address>(current) + skip); \ emit_write_barrier = (space_number == NEW_SPACE); \ new_object = GetAddressFromEnd(data & kSpaceMask); \ + if (deserializing_user_code()) { \ + new_object = ProcessBackRefInSerializedCode(new_object); \ + } \ } \ if (within == kInnerPointer) { \ if (space_number != CODE_SPACE || new_object->IsCode()) { \
Index: src/serialize.h
diff --git a/src/serialize.h b/src/serialize.h
index 0676c39ed139ded0ff490378c584a35404341356..c9805678e274a8dd230529b5693fbd4cbcddaf4c 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -280,7 +280,9 @@ class Deserializer: public SerializerDeserializer {
       Object** start, Object** end, int space, Address object_address);
   void ReadObject(int space_number, Object** write_back);

-  HeapObject* ProcessObjectFromSerializedCode(HeapObject* obj);
+ // Special handling for serialized code like hooking up internalized strings.
+  HeapObject* ProcessNewObjectFromSerializedCode(HeapObject* obj);
+  Object* ProcessBackRefInSerializedCode(Object* obj);

   // This routine both allocates a new object, and also keeps
   // track of where objects have been allocated so that we can
Index: test/mjsunit/deserialize-reference.js
diff --git a/test/mjsunit/regress/regress-debug-context-load.js b/test/mjsunit/deserialize-reference.js
similarity index 67%
copy from test/mjsunit/regress/regress-debug-context-load.js
copy to test/mjsunit/deserialize-reference.js
index 0b3c275f99b016825cd563a700772bbddb7e4bad..b03201315932eab59e38c135d219192e6dcdf0eb 100644
--- a/test/mjsunit/regress/regress-debug-context-load.js
+++ b/test/mjsunit/deserialize-reference.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.

-// Flags: --expose-debug-as debug
+// Flags: --cache=code --serialize-toplevel

-Debug = debug.Debug;
-Debug.setListener(null);
+var a = "123";
+assertEquals(a, "123");


--
--
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