Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index 41703b90abaf4022bf3861db79699b3c10ce600d..48d77db4580cb9462380d045ac6fa2e63fbfc868 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -1273,27 +1273,37 @@ bool String::MakeExternal(v8::String::ExternalStringResource* resource) { |
bool is_ascii = this->IsOneByteRepresentation(); |
bool is_internalized = this->IsInternalizedString(); |
- // Morph the object to an external string by adjusting the map and |
- // reinitializing the fields. |
- if (size >= ExternalString::kSize) { |
+ // Morph the string to an external string by replacing the map and |
+ // reinitializing the fields. This won't work if |
+ // - the space the existing string occupies is too small for a regular |
+ // external string. |
+ // - the existing string is in old pointer space and the backing store of |
+ // the external string is not aligned. The GC cannot deal with fields |
+ // containing an unaligned address that points to outside of V8's heap. |
+ // In either case we resort to a short external string instead, omitting |
+ // the field caching the address of the backing store. When we encounter |
+ // short external strings in generated code, we need to bailout to runtime. |
+ if (size < ExternalString::kSize || |
+ (!IsAligned(reinterpret_cast<intptr_t>(resource->data()), kPointerSize) && |
+ heap->old_pointer_space()->Contains(this))) { |
this->set_map_no_write_barrier( |
is_internalized |
? (is_ascii |
- ? heap->external_internalized_string_with_one_byte_data_map() |
- : heap->external_internalized_string_map()) |
+ ? heap-> |
+ short_external_internalized_string_with_one_byte_data_map() |
+ : heap->short_external_internalized_string_map()) |
: (is_ascii |
- ? heap->external_string_with_one_byte_data_map() |
- : heap->external_string_map())); |
+ ? heap->short_external_string_with_one_byte_data_map() |
+ : heap->short_external_string_map())); |
} else { |
this->set_map_no_write_barrier( |
is_internalized |
- ? (is_ascii |
- ? heap-> |
- short_external_internalized_string_with_one_byte_data_map() |
- : heap->short_external_internalized_string_map()) |
- : (is_ascii |
- ? heap->short_external_string_with_one_byte_data_map() |
- : heap->short_external_string_map())); |
+ ? (is_ascii |
+ ? heap->external_internalized_string_with_one_byte_data_map() |
+ : heap->external_internalized_string_map()) |
+ : (is_ascii |
+ ? heap->external_string_with_one_byte_data_map() |
+ : heap->external_string_map())); |
} |
ExternalTwoByteString* self = ExternalTwoByteString::cast(this); |
self->set_resource(resource); |
@@ -1334,16 +1344,26 @@ bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) { |
} |
bool is_internalized = this->IsInternalizedString(); |
- // Morph the object to an external string by adjusting the map and |
- // reinitializing the fields. Use short version if space is limited. |
- if (size >= ExternalString::kSize) { |
- this->set_map_no_write_barrier( |
- is_internalized ? heap->external_ascii_internalized_string_map() |
- : heap->external_ascii_string_map()); |
- } else { |
+ // Morph the string to an external string by replacing the map and |
+ // reinitializing the fields. This won't work if |
+ // - the space the existing string occupies is too small for a regular |
+ // external string. |
+ // - the existing string is in old pointer space and the backing store of |
+ // the external string is not aligned. The GC cannot deal with fields |
+ // containing an unaligned address that points to outside of V8's heap. |
+ // In either case we resort to a short external string instead, omitting |
+ // the field caching the address of the backing store. When we encounter |
+ // short external strings in generated code, we need to bailout to runtime. |
+ if (size < ExternalString::kSize || |
+ (!IsAligned(reinterpret_cast<intptr_t>(resource->data()), kPointerSize) && |
+ heap->old_pointer_space()->Contains(this))) { |
this->set_map_no_write_barrier( |
is_internalized ? heap->short_external_ascii_internalized_string_map() |
: heap->short_external_ascii_string_map()); |
+ } else { |
+ this->set_map_no_write_barrier( |
+ is_internalized ? heap->external_ascii_internalized_string_map() |
+ : heap->external_ascii_string_map()); |
} |
ExternalAsciiString* self = ExternalAsciiString::cast(this); |
self->set_resource(resource); |