Reviewers: Michael Starzinger,

Description:
Do not allow external strings in old pointer space.

[email protected]
BUG=

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

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

Affected files:
  M src/api.cc
  M test/cctest/test-api.cc


Index: src/api.cc
diff --git a/src/api.cc b/src/api.cc
index 5978ed270e34d51d8a5de093310ba023d0810a55..3f5a0793b21a5e53d68070494f18e28d79c57cf2 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -5930,6 +5930,23 @@ i::Handle<i::String> NewExternalAsciiStringHandle(i::Isolate* isolate,
 }


+bool RedirectToExternalString(i::Isolate* isolate,
+                              i::Handle<i::String> parent,
+                              i::Handle<i::String> external) {
+  if (parent->IsConsString()) {
+    i::Handle<i::ConsString> cons = i::Handle<i::ConsString>::cast(parent);
+    cons->set_first(*external);
+    cons->set_second(isolate->heap()->empty_string());
+  } else {
+    ASSERT(parent->IsSlicedString());
+ i::Handle<i::SlicedString> slice = i::Handle<i::SlicedString>::cast(parent);
+    slice->set_parent(*external);
+    slice->set_offset(0);
+  }
+  return true;
+}
+
+
 Local<String> v8::String::NewExternal(
       v8::String::ExternalStringResource* resource) {
   i::Isolate* isolate = i::Isolate::Current();
@@ -5958,9 +5975,23 @@ bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
     return false;
   }
   CHECK(resource && resource->data());
-  bool result = obj->MakeExternal(resource);
-  if (result && !obj->IsInternalizedString()) {
-    isolate->heap()->external_string_table()->AddString(*obj);
+
+  bool result;
+  i::Handle<i::String> external;
+  if (isolate->heap()->old_pointer_space()->Contains(*obj)) {
+ // We do not allow external strings in the old pointer space. Instead of
+    // converting the string in-place, we keep the cons/sliced string and
+    // point it to a newly-allocated external string.
+    external = NewExternalStringHandle(isolate, resource);
+    result = RedirectToExternalString(isolate, obj, external);
+  } else {
+    result = obj->MakeExternal(resource);
+    external = obj;
+  }
+
+  ASSERT(external->IsExternalString());
+  if (result && !external->IsInternalizedString()) {
+    isolate->heap()->external_string_table()->AddString(*external);
   }
   return result;
 }
@@ -5995,9 +6026,23 @@ bool v8::String::MakeExternal(
     return false;
   }
   CHECK(resource && resource->data());
-  bool result = obj->MakeExternal(resource);
-  if (result && !obj->IsInternalizedString()) {
-    isolate->heap()->external_string_table()->AddString(*obj);
+
+  bool result;
+  i::Handle<i::String> external;
+  if (isolate->heap()->old_pointer_space()->Contains(*obj)) {
+ // We do not allow external strings in the old pointer space. Instead of
+    // converting the string in-place, we keep the cons/sliced string and
+    // point it to a newly-allocated external string.
+    external = NewExternalAsciiStringHandle(isolate, resource);
+    result = RedirectToExternalString(isolate, obj, external);
+  } else {
+    result = obj->MakeExternal(resource);
+    external = obj;
+  }
+
+  ASSERT(external->IsExternalString());
+  if (result && !external->IsInternalizedString()) {
+    isolate->heap()->external_string_table()->AddString(*external);
   }
   return result;
 }
Index: test/cctest/test-api.cc
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 724eb6a2fc2793f10fa8fbf341d0f67c6e42b316..7cb3c04087b69d5238b904861e20d4aaf75fc3fa 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -625,10 +625,14 @@ TEST(MakingExternalUnalignedAsciiString) {
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());

+  CompileRun("function cons(a, b) { return a + b; }"
+             "function slice(a) { return a.substring(1); }");
   // Create a cons string that will land in old pointer space.
-  Local<String> string = Local<String>::Cast(CompileRun(
-      "function cons(a, b) { return a + b; }"
+  Local<String> cons = Local<String>::Cast(CompileRun(
       "cons('abcdefghijklm', 'nopqrstuvwxyz');"));
+  // Create a sliced string that will land in old pointer space.
+  Local<String> slice = Local<String>::Cast(CompileRun(
+      "slice('abcdefghijklmnopqrstuvwxyz');"));

   // Trigger GCs so that the newly allocated string moves to old gen.
   SimulateFullSpace(HEAP->old_pointer_space());
@@ -637,9 +641,13 @@ TEST(MakingExternalUnalignedAsciiString) {

   // Turn into external string with unaligned resource data.
   int dispose_count = 0;
-  const char* c_source = "_abcdefghijklmnopqrstuvwxyz";
-  bool success = string->MakeExternal(
-      new TestAsciiResource(i::StrDup(c_source) + 1, &dispose_count));
+  const char* c_cons = "_abcdefghijklmnopqrstuvwxyz";
+  bool success = cons->MakeExternal(
+      new TestAsciiResource(i::StrDup(c_cons) + 1, &dispose_count));
+  CHECK(success);
+  const char* c_slice = "_bcdefghijklmnopqrstuvwxyz";
+  success = slice->MakeExternal(
+      new TestAsciiResource(i::StrDup(c_slice) + 1, &dispose_count));
   CHECK(success);

   // Trigger GCs and force evacuation.


--
--
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/groups/opt_out.


Reply via email to