Index: src/heap.cc |
=================================================================== |
--- src/heap.cc (revision 766) |
+++ src/heap.cc (working copy) |
@@ -84,6 +84,8 @@ |
GCCallback Heap::global_gc_prologue_callback_ = NULL; |
GCCallback Heap::global_gc_epilogue_callback_ = NULL; |
+ExternalSymbolCallback Heap::global_external_symbol_callback_ = NULL; |
+ |
// Variables set based on semispace_size_ and old_generation_size_ in |
// ConfigureHeap. |
int Heap::young_generation_size_ = 0; // Will be 2 * semispace_size_. |
@@ -1535,6 +1537,29 @@ |
} |
+Object* Heap::AllocateExternalSymbolFromTwoByte( |
+ ExternalTwoByteString::Resource* resource) { |
+ Map* map; |
+ int length = resource->length(); |
+ if (length <= String::kMaxShortStringSize) { |
+ map = short_external_symbol_map(); |
+ } else if (length <= String::kMaxMediumStringSize) { |
+ map = medium_external_symbol_map(); |
+ } else { |
+ map = long_external_symbol_map(); |
+ } |
+ |
+ Object* result = Allocate(map, OLD_DATA_SPACE); |
+ if (result->IsFailure()) return result; |
+ |
+ ExternalTwoByteString* external_string = ExternalTwoByteString::cast(result); |
+ external_string->set_length(length); |
+ external_string->set_resource(resource); |
+ |
+ return result; |
+} |
+ |
+ |
Object* Heap::LookupSingleCharacterStringFromCode(uint16_t code) { |
if (code <= String::kMaxAsciiCharCode) { |
Object* value = Heap::single_character_string_cache()->get(code); |
@@ -2028,9 +2053,9 @@ |
} |
-Object* Heap::AllocateSymbol(unibrow::CharacterStream* buffer, |
- int chars, |
- uint32_t length_field) { |
+Object* Heap::AllocateInternalSymbol(unibrow::CharacterStream* buffer, |
+ int chars, |
+ uint32_t length_field) { |
// Ensure the chars matches the number of characters in the buffer. |
ASSERT(static_cast<unsigned>(chars) == buffer->Length()); |
// Determine whether the string is ascii. |
@@ -2086,6 +2111,42 @@ |
} |
+// External string resource that only contains a length field. These |
+// are used temporarily when allocating external symbols. |
+class DummyExternalStringResource |
+ : public v8::String::ExternalStringResource { |
+ public: |
+ explicit DummyExternalStringResource(size_t length) : length_(length) { } |
+ |
+ virtual const uint16_t* data() const { |
+ UNREACHABLE(); |
+ return NULL; |
+ } |
+ |
+ virtual size_t length() const { return length_; } |
+ private: |
+ size_t length_; |
+}; |
+ |
+ |
+Object* Heap::AllocateExternalSymbol(Vector<const char> string, int chars) { |
+ // Attempt to allocate the resulting external string first. Use a |
+ // dummy string resource that has the correct length so that we only |
+ // have to patch the external string resource after the callback. |
+ DummyExternalStringResource dummy_resource(chars); |
+ Object* obj = AllocateExternalSymbolFromTwoByte(&dummy_resource); |
+ if (obj->IsFailure()) return obj; |
+ // Perform callback. |
+ v8::String::ExternalStringResource* resource = |
+ global_external_symbol_callback_(string.start(), string.length()); |
+ // Patch the resource pointer of the result. |
+ ExternalTwoByteString* result = ExternalTwoByteString::cast(obj); |
+ result->set_resource(resource); |
+ ASSERT(result->IsEqualTo(string)); |
+ return result; |
+} |
+ |
+ |
Object* Heap::AllocateRawAsciiString(int length, PretenureFlag pretenure) { |
AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; |
int size = SeqAsciiString::SizeFor(length); |