Introduce short external strings without pointer cache.
BUG= TEST= Review URL: http://codereview.chromium.org/8635011 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10049 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
46f0a651cc
commit
21edc7c30b
@ -4556,12 +4556,9 @@ bool v8::String::CanMakeExternal() {
|
|||||||
i::Handle<i::String> obj = Utils::OpenHandle(this);
|
i::Handle<i::String> obj = Utils::OpenHandle(this);
|
||||||
i::Isolate* isolate = obj->GetIsolate();
|
i::Isolate* isolate = obj->GetIsolate();
|
||||||
if (IsDeadCheck(isolate, "v8::String::CanMakeExternal()")) return false;
|
if (IsDeadCheck(isolate, "v8::String::CanMakeExternal()")) return false;
|
||||||
if (isolate->string_tracker()->IsFreshUnusedString(obj)) {
|
if (isolate->string_tracker()->IsFreshUnusedString(obj)) return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
int size = obj->Size(); // Byte size of the original string.
|
int size = obj->Size(); // Byte size of the original string.
|
||||||
if (size < i::ExternalString::kSize)
|
if (size < i::ExternalString::kShortSize) return false;
|
||||||
return false;
|
|
||||||
i::StringShape shape(*obj);
|
i::StringShape shape(*obj);
|
||||||
return !shape.IsExternal();
|
return !shape.IsExternal();
|
||||||
}
|
}
|
||||||
|
@ -255,16 +255,11 @@ void Heap::FinalizeExternalString(String* string) {
|
|||||||
ExternalString::kResourceOffset -
|
ExternalString::kResourceOffset -
|
||||||
kHeapObjectTag);
|
kHeapObjectTag);
|
||||||
|
|
||||||
// Clear pointer cache.
|
|
||||||
ExternalString::cast(string)->clear_data_cache();
|
|
||||||
|
|
||||||
// Dispose of the C++ object if it has not already been disposed.
|
// Dispose of the C++ object if it has not already been disposed.
|
||||||
if (*resource_addr != NULL) {
|
if (*resource_addr != NULL) {
|
||||||
(*resource_addr)->Dispose();
|
(*resource_addr)->Dispose();
|
||||||
}
|
|
||||||
|
|
||||||
// Clear the resource pointer in the string.
|
|
||||||
*resource_addr = NULL;
|
*resource_addr = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3997,6 +3997,15 @@ Map* Heap::SymbolMapForString(String* string) {
|
|||||||
if (map == external_string_with_ascii_data_map()) {
|
if (map == external_string_with_ascii_data_map()) {
|
||||||
return external_symbol_with_ascii_data_map();
|
return external_symbol_with_ascii_data_map();
|
||||||
}
|
}
|
||||||
|
if (map == short_external_string_map()) {
|
||||||
|
return short_external_symbol_map();
|
||||||
|
}
|
||||||
|
if (map == short_external_ascii_string_map()) {
|
||||||
|
return short_external_ascii_symbol_map();
|
||||||
|
}
|
||||||
|
if (map == short_external_string_with_ascii_data_map()) {
|
||||||
|
return short_external_symbol_with_ascii_data_map();
|
||||||
|
}
|
||||||
|
|
||||||
// No match found.
|
// No match found.
|
||||||
return NULL;
|
return NULL;
|
||||||
|
10
src/heap.h
10
src/heap.h
@ -110,6 +110,16 @@ inline Heap* _inline_get_heap_();
|
|||||||
V(Map, external_string_map, ExternalStringMap) \
|
V(Map, external_string_map, ExternalStringMap) \
|
||||||
V(Map, external_string_with_ascii_data_map, ExternalStringWithAsciiDataMap) \
|
V(Map, external_string_with_ascii_data_map, ExternalStringWithAsciiDataMap) \
|
||||||
V(Map, external_ascii_string_map, ExternalAsciiStringMap) \
|
V(Map, external_ascii_string_map, ExternalAsciiStringMap) \
|
||||||
|
V(Map, short_external_symbol_map, ShortExternalSymbolMap) \
|
||||||
|
V(Map, \
|
||||||
|
short_external_symbol_with_ascii_data_map, \
|
||||||
|
ShortExternalSymbolWithAsciiDataMap) \
|
||||||
|
V(Map, short_external_ascii_symbol_map, ShortExternalAsciiSymbolMap) \
|
||||||
|
V(Map, short_external_string_map, ShortExternalStringMap) \
|
||||||
|
V(Map, \
|
||||||
|
short_external_string_with_ascii_data_map, \
|
||||||
|
ShortExternalStringWithAsciiDataMap) \
|
||||||
|
V(Map, short_external_ascii_string_map, ShortExternalAsciiStringMap) \
|
||||||
V(Map, undetectable_string_map, UndetectableStringMap) \
|
V(Map, undetectable_string_map, UndetectableStringMap) \
|
||||||
V(Map, undetectable_ascii_string_map, UndetectableAsciiStringMap) \
|
V(Map, undetectable_ascii_string_map, UndetectableAsciiStringMap) \
|
||||||
V(Map, external_pixel_array_map, ExternalPixelArrayMap) \
|
V(Map, external_pixel_array_map, ExternalPixelArrayMap) \
|
||||||
|
@ -563,15 +563,17 @@ void StringCharLoadGenerator::Generate(MacroAssembler* masm,
|
|||||||
__ Assert(zero, "external string expected, but not found");
|
__ Assert(zero, "external string expected, but not found");
|
||||||
}
|
}
|
||||||
__ mov(result, FieldOperand(string, ExternalString::kResourceDataOffset));
|
__ mov(result, FieldOperand(string, ExternalString::kResourceDataOffset));
|
||||||
// Assert that the external string has not been finalized yet.
|
|
||||||
__ test(result, result);
|
|
||||||
__ j(zero, call_runtime);
|
|
||||||
Register scratch = string;
|
Register scratch = string;
|
||||||
__ mov(scratch, FieldOperand(string, HeapObject::kMapOffset));
|
__ mov(scratch, FieldOperand(string, HeapObject::kMapOffset));
|
||||||
__ cmp(scratch, Immediate(factory->external_ascii_string_map()));
|
__ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
|
||||||
__ j(equal, &ascii_external, Label::kNear);
|
// Rule out short external strings.
|
||||||
__ cmp(scratch, Immediate(factory->external_ascii_symbol_map()));
|
STATIC_CHECK(kShortExternalStringTag != 0);
|
||||||
__ j(equal, &ascii_external, Label::kNear);
|
__ test_b(scratch, kShortExternalStringMask);
|
||||||
|
__ j(not_zero, call_runtime);
|
||||||
|
// Check encoding.
|
||||||
|
STATIC_ASSERT(kTwoByteStringTag == 0);
|
||||||
|
__ test_b(scratch, kStringEncodingMask);
|
||||||
|
__ j(not_equal, &ascii_external, Label::kNear);
|
||||||
// Two-byte string.
|
// Two-byte string.
|
||||||
__ movzx_w(result, Operand(result, index, times_2, 0));
|
__ movzx_w(result, Operand(result, index, times_2, 0));
|
||||||
__ jmp(&done);
|
__ jmp(&done);
|
||||||
|
@ -2297,8 +2297,9 @@ void ConsString::set_second(String* value, WriteBarrierMode mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ExternalString::clear_data_cache() {
|
bool ExternalString::is_short() {
|
||||||
WRITE_INTPTR_FIELD(this, kResourceDataOffset, 0);
|
InstanceType type = map()->instance_type();
|
||||||
|
return (type & kShortExternalStringMask) == kShortExternalStringTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2307,19 +2308,24 @@ const ExternalAsciiString::Resource* ExternalAsciiString::resource() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ExternalAsciiString::update_data_cache() {
|
||||||
|
if (is_short()) return;
|
||||||
|
const char** data_field =
|
||||||
|
reinterpret_cast<const char**>(FIELD_ADDR(this, kResourceDataOffset));
|
||||||
|
*data_field = resource()->data();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ExternalAsciiString::set_resource(
|
void ExternalAsciiString::set_resource(
|
||||||
const ExternalAsciiString::Resource* resource) {
|
const ExternalAsciiString::Resource* resource) {
|
||||||
*reinterpret_cast<const Resource**>(
|
*reinterpret_cast<const Resource**>(
|
||||||
FIELD_ADDR(this, kResourceOffset)) = resource;
|
FIELD_ADDR(this, kResourceOffset)) = resource;
|
||||||
clear_data_cache();
|
if (resource != NULL) update_data_cache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char* ExternalAsciiString::GetChars() {
|
const char* ExternalAsciiString::GetChars() {
|
||||||
const char** data_field =
|
return resource()->data();
|
||||||
reinterpret_cast<const char**>(FIELD_ADDR(this, kResourceDataOffset));
|
|
||||||
if (*data_field == NULL) *data_field = resource()->data();
|
|
||||||
return *data_field;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2334,19 +2340,24 @@ const ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ExternalTwoByteString::update_data_cache() {
|
||||||
|
if (is_short()) return;
|
||||||
|
const uint16_t** data_field =
|
||||||
|
reinterpret_cast<const uint16_t**>(FIELD_ADDR(this, kResourceDataOffset));
|
||||||
|
*data_field = resource()->data();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ExternalTwoByteString::set_resource(
|
void ExternalTwoByteString::set_resource(
|
||||||
const ExternalTwoByteString::Resource* resource) {
|
const ExternalTwoByteString::Resource* resource) {
|
||||||
*reinterpret_cast<const Resource**>(
|
*reinterpret_cast<const Resource**>(
|
||||||
FIELD_ADDR(this, kResourceOffset)) = resource;
|
FIELD_ADDR(this, kResourceOffset)) = resource;
|
||||||
clear_data_cache();
|
if (resource != NULL) update_data_cache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const uint16_t* ExternalTwoByteString::GetChars() {
|
const uint16_t* ExternalTwoByteString::GetChars() {
|
||||||
const uint16_t** data_field =
|
return resource()->data();
|
||||||
reinterpret_cast<const uint16_t**>(FIELD_ADDR(this, kResourceDataOffset));
|
|
||||||
if (*data_field == NULL) *data_field = resource()->data();
|
|
||||||
return *data_field;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -446,6 +446,9 @@ static const char* TypeToString(InstanceType type) {
|
|||||||
case EXTERNAL_ASCII_SYMBOL_TYPE:
|
case EXTERNAL_ASCII_SYMBOL_TYPE:
|
||||||
case EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE:
|
case EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE:
|
||||||
case EXTERNAL_SYMBOL_TYPE: return "EXTERNAL_SYMBOL";
|
case EXTERNAL_SYMBOL_TYPE: return "EXTERNAL_SYMBOL";
|
||||||
|
case SHORT_EXTERNAL_ASCII_SYMBOL_TYPE:
|
||||||
|
case SHORT_EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE:
|
||||||
|
case SHORT_EXTERNAL_SYMBOL_TYPE: return "SHORT_EXTERNAL_SYMBOL";
|
||||||
case ASCII_STRING_TYPE: return "ASCII_STRING";
|
case ASCII_STRING_TYPE: return "ASCII_STRING";
|
||||||
case STRING_TYPE: return "TWO_BYTE_STRING";
|
case STRING_TYPE: return "TWO_BYTE_STRING";
|
||||||
case CONS_STRING_TYPE:
|
case CONS_STRING_TYPE:
|
||||||
@ -453,6 +456,9 @@ static const char* TypeToString(InstanceType type) {
|
|||||||
case EXTERNAL_ASCII_STRING_TYPE:
|
case EXTERNAL_ASCII_STRING_TYPE:
|
||||||
case EXTERNAL_STRING_WITH_ASCII_DATA_TYPE:
|
case EXTERNAL_STRING_WITH_ASCII_DATA_TYPE:
|
||||||
case EXTERNAL_STRING_TYPE: return "EXTERNAL_STRING";
|
case EXTERNAL_STRING_TYPE: return "EXTERNAL_STRING";
|
||||||
|
case SHORT_EXTERNAL_ASCII_STRING_TYPE:
|
||||||
|
case SHORT_EXTERNAL_STRING_WITH_ASCII_DATA_TYPE:
|
||||||
|
case SHORT_EXTERNAL_STRING_TYPE: return "SHORT_EXTERNAL_STRING";
|
||||||
case FIXED_ARRAY_TYPE: return "FIXED_ARRAY";
|
case FIXED_ARRAY_TYPE: return "FIXED_ARRAY";
|
||||||
case BYTE_ARRAY_TYPE: return "BYTE_ARRAY";
|
case BYTE_ARRAY_TYPE: return "BYTE_ARRAY";
|
||||||
case FREE_SPACE_TYPE: return "FREE_SPACE";
|
case FREE_SPACE_TYPE: return "FREE_SPACE";
|
||||||
|
@ -64,7 +64,7 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId(
|
|||||||
case kExternalStringTag:
|
case kExternalStringTag:
|
||||||
return GetVisitorIdForSize(kVisitDataObject,
|
return GetVisitorIdForSize(kVisitDataObject,
|
||||||
kVisitDataObjectGeneric,
|
kVisitDataObjectGeneric,
|
||||||
ExternalString::kSize);
|
instance_size);
|
||||||
}
|
}
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
@ -952,33 +952,32 @@ bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
|
|||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
Heap* heap = GetHeap();
|
Heap* heap = GetHeap();
|
||||||
int size = this->Size(); // Byte size of the original string.
|
int size = this->Size(); // Byte size of the original string.
|
||||||
if (size < ExternalString::kSize) {
|
if (size < ExternalString::kShortSize) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ASSERT(size >= ExternalString::kSize);
|
|
||||||
bool is_ascii = this->IsAsciiRepresentation();
|
bool is_ascii = this->IsAsciiRepresentation();
|
||||||
bool is_symbol = this->IsSymbol();
|
bool is_symbol = this->IsSymbol();
|
||||||
int length = this->length();
|
|
||||||
int hash_field = this->hash_field();
|
|
||||||
|
|
||||||
// Morph the object to an external string by adjusting the map and
|
// Morph the object to an external string by adjusting the map and
|
||||||
// reinitializing the fields.
|
// reinitializing the fields.
|
||||||
this->set_map(is_ascii ?
|
if (size >= ExternalString::kSize) {
|
||||||
heap->external_string_with_ascii_data_map() :
|
this->set_map(
|
||||||
heap->external_string_map());
|
is_symbol
|
||||||
ExternalTwoByteString* self = ExternalTwoByteString::cast(this);
|
? (is_ascii ? heap->external_symbol_with_ascii_data_map()
|
||||||
self->set_length(length);
|
: heap->external_symbol_map())
|
||||||
self->set_hash_field(hash_field);
|
: (is_ascii ? heap->external_string_with_ascii_data_map()
|
||||||
self->set_resource(resource);
|
: heap->external_string_map()));
|
||||||
// Additionally make the object into an external symbol if the original string
|
} else {
|
||||||
// was a symbol to start with.
|
this->set_map(
|
||||||
if (is_symbol) {
|
is_symbol
|
||||||
self->Hash(); // Force regeneration of the hash value.
|
? (is_ascii ? heap->short_external_symbol_with_ascii_data_map()
|
||||||
// Now morph this external string into a external symbol.
|
: heap->short_external_symbol_map())
|
||||||
this->set_map(is_ascii ?
|
: (is_ascii ? heap->short_external_string_with_ascii_data_map()
|
||||||
heap->external_symbol_with_ascii_data_map() :
|
: heap->short_external_string_map()));
|
||||||
heap->external_symbol_map());
|
|
||||||
}
|
}
|
||||||
|
ExternalTwoByteString* self = ExternalTwoByteString::cast(this);
|
||||||
|
self->set_resource(resource);
|
||||||
|
if (is_symbol) self->Hash(); // Force regeneration of the hash value.
|
||||||
|
|
||||||
// Fill the remainder of the string with dead wood.
|
// Fill the remainder of the string with dead wood.
|
||||||
int new_size = this->Size(); // Byte size of the external String object.
|
int new_size = this->Size(); // Byte size of the external String object.
|
||||||
@ -1004,28 +1003,23 @@ bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) {
|
|||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
Heap* heap = GetHeap();
|
Heap* heap = GetHeap();
|
||||||
int size = this->Size(); // Byte size of the original string.
|
int size = this->Size(); // Byte size of the original string.
|
||||||
if (size < ExternalString::kSize) {
|
if (size < ExternalString::kShortSize) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ASSERT(size >= ExternalString::kSize);
|
|
||||||
bool is_symbol = this->IsSymbol();
|
bool is_symbol = this->IsSymbol();
|
||||||
int length = this->length();
|
|
||||||
int hash_field = this->hash_field();
|
|
||||||
|
|
||||||
// Morph the object to an external string by adjusting the map and
|
// Morph the object to an external string by adjusting the map and
|
||||||
// reinitializing the fields.
|
// reinitializing the fields. Use short version if space is limited.
|
||||||
this->set_map(heap->external_ascii_string_map());
|
if (size >= ExternalString::kSize) {
|
||||||
ExternalAsciiString* self = ExternalAsciiString::cast(this);
|
this->set_map(is_symbol ? heap->external_ascii_symbol_map()
|
||||||
self->set_length(length);
|
: heap->external_ascii_string_map());
|
||||||
self->set_hash_field(hash_field);
|
} else {
|
||||||
self->set_resource(resource);
|
this->set_map(is_symbol ? heap->short_external_ascii_symbol_map()
|
||||||
// Additionally make the object into an external symbol if the original string
|
: heap->short_external_ascii_string_map());
|
||||||
// was a symbol to start with.
|
|
||||||
if (is_symbol) {
|
|
||||||
self->Hash(); // Force regeneration of the hash value.
|
|
||||||
// Now morph this external string into a external symbol.
|
|
||||||
this->set_map(heap->external_ascii_symbol_map());
|
|
||||||
}
|
}
|
||||||
|
ExternalAsciiString* self = ExternalAsciiString::cast(this);
|
||||||
|
self->set_resource(resource);
|
||||||
|
if (is_symbol) self->Hash(); // Force regeneration of the hash value.
|
||||||
|
|
||||||
// Fill the remainder of the string with dead wood.
|
// Fill the remainder of the string with dead wood.
|
||||||
int new_size = this->Size(); // Byte size of the external String object.
|
int new_size = this->Size(); // Byte size of the external String object.
|
||||||
@ -1033,7 +1027,6 @@ bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) {
|
|||||||
if (Marking::IsBlack(Marking::MarkBitFrom(this))) {
|
if (Marking::IsBlack(Marking::MarkBitFrom(this))) {
|
||||||
MemoryChunk::IncrementLiveBytes(this->address(), new_size - size);
|
MemoryChunk::IncrementLiveBytes(this->address(), new_size - size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,6 +232,9 @@ static const int kVariableSizeSentinel = 0;
|
|||||||
V(EXTERNAL_SYMBOL_TYPE) \
|
V(EXTERNAL_SYMBOL_TYPE) \
|
||||||
V(EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE) \
|
V(EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE) \
|
||||||
V(EXTERNAL_ASCII_SYMBOL_TYPE) \
|
V(EXTERNAL_ASCII_SYMBOL_TYPE) \
|
||||||
|
V(SHORT_EXTERNAL_SYMBOL_TYPE) \
|
||||||
|
V(SHORT_EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE) \
|
||||||
|
V(SHORT_EXTERNAL_ASCII_SYMBOL_TYPE) \
|
||||||
V(STRING_TYPE) \
|
V(STRING_TYPE) \
|
||||||
V(ASCII_STRING_TYPE) \
|
V(ASCII_STRING_TYPE) \
|
||||||
V(CONS_STRING_TYPE) \
|
V(CONS_STRING_TYPE) \
|
||||||
@ -240,6 +243,9 @@ static const int kVariableSizeSentinel = 0;
|
|||||||
V(EXTERNAL_STRING_TYPE) \
|
V(EXTERNAL_STRING_TYPE) \
|
||||||
V(EXTERNAL_STRING_WITH_ASCII_DATA_TYPE) \
|
V(EXTERNAL_STRING_WITH_ASCII_DATA_TYPE) \
|
||||||
V(EXTERNAL_ASCII_STRING_TYPE) \
|
V(EXTERNAL_ASCII_STRING_TYPE) \
|
||||||
|
V(SHORT_EXTERNAL_STRING_TYPE) \
|
||||||
|
V(SHORT_EXTERNAL_STRING_WITH_ASCII_DATA_TYPE) \
|
||||||
|
V(SHORT_EXTERNAL_ASCII_STRING_TYPE) \
|
||||||
V(PRIVATE_EXTERNAL_ASCII_STRING_TYPE) \
|
V(PRIVATE_EXTERNAL_ASCII_STRING_TYPE) \
|
||||||
\
|
\
|
||||||
V(MAP_TYPE) \
|
V(MAP_TYPE) \
|
||||||
@ -340,6 +346,18 @@ static const int kVariableSizeSentinel = 0;
|
|||||||
ExternalAsciiString::kSize, \
|
ExternalAsciiString::kSize, \
|
||||||
external_ascii_symbol, \
|
external_ascii_symbol, \
|
||||||
ExternalAsciiSymbol) \
|
ExternalAsciiSymbol) \
|
||||||
|
V(SHORT_EXTERNAL_SYMBOL_TYPE, \
|
||||||
|
ExternalTwoByteString::kShortSize, \
|
||||||
|
short_external_symbol, \
|
||||||
|
ShortExternalSymbol) \
|
||||||
|
V(SHORT_EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE, \
|
||||||
|
ExternalTwoByteString::kShortSize, \
|
||||||
|
short_external_symbol_with_ascii_data, \
|
||||||
|
ShortExternalSymbolWithAsciiData) \
|
||||||
|
V(SHORT_EXTERNAL_ASCII_SYMBOL_TYPE, \
|
||||||
|
ExternalAsciiString::kShortSize, \
|
||||||
|
short_external_ascii_symbol, \
|
||||||
|
ShortExternalAsciiSymbol) \
|
||||||
V(STRING_TYPE, \
|
V(STRING_TYPE, \
|
||||||
kVariableSizeSentinel, \
|
kVariableSizeSentinel, \
|
||||||
string, \
|
string, \
|
||||||
@ -375,7 +393,19 @@ static const int kVariableSizeSentinel = 0;
|
|||||||
V(EXTERNAL_ASCII_STRING_TYPE, \
|
V(EXTERNAL_ASCII_STRING_TYPE, \
|
||||||
ExternalAsciiString::kSize, \
|
ExternalAsciiString::kSize, \
|
||||||
external_ascii_string, \
|
external_ascii_string, \
|
||||||
ExternalAsciiString)
|
ExternalAsciiString) \
|
||||||
|
V(SHORT_EXTERNAL_STRING_TYPE, \
|
||||||
|
ExternalTwoByteString::kShortSize, \
|
||||||
|
short_external_string, \
|
||||||
|
ShortExternalString) \
|
||||||
|
V(SHORT_EXTERNAL_STRING_WITH_ASCII_DATA_TYPE, \
|
||||||
|
ExternalTwoByteString::kShortSize, \
|
||||||
|
short_external_string_with_ascii_data, \
|
||||||
|
ShortExternalStringWithAsciiData) \
|
||||||
|
V(SHORT_EXTERNAL_ASCII_STRING_TYPE, \
|
||||||
|
ExternalAsciiString::kShortSize, \
|
||||||
|
short_external_ascii_string, \
|
||||||
|
ShortExternalAsciiString)
|
||||||
|
|
||||||
// A struct is a simple object a set of object-valued fields. Including an
|
// A struct is a simple object a set of object-valued fields. Including an
|
||||||
// object type in this causes the compiler to generate most of the boilerplate
|
// object type in this causes the compiler to generate most of the boilerplate
|
||||||
@ -459,6 +489,11 @@ STATIC_ASSERT(IS_POWER_OF_TWO(kSlicedNotConsMask) && kSlicedNotConsMask != 0);
|
|||||||
const uint32_t kAsciiDataHintMask = 0x08;
|
const uint32_t kAsciiDataHintMask = 0x08;
|
||||||
const uint32_t kAsciiDataHintTag = 0x08;
|
const uint32_t kAsciiDataHintTag = 0x08;
|
||||||
|
|
||||||
|
// If bit 7 is clear and string representation indicates an external string,
|
||||||
|
// then bit 4 indicates whether the data pointer is cached.
|
||||||
|
const uint32_t kShortExternalStringMask = 0x10;
|
||||||
|
const uint32_t kShortExternalStringTag = 0x10;
|
||||||
|
|
||||||
|
|
||||||
// A ConsString with an empty string as the right side is a candidate
|
// A ConsString with an empty string as the right side is a candidate
|
||||||
// for being shortcut by the garbage collector unless it is a
|
// for being shortcut by the garbage collector unless it is a
|
||||||
@ -478,6 +513,13 @@ enum InstanceType {
|
|||||||
ASCII_SYMBOL_TYPE = kAsciiStringTag | kSymbolTag | kSeqStringTag,
|
ASCII_SYMBOL_TYPE = kAsciiStringTag | kSymbolTag | kSeqStringTag,
|
||||||
CONS_SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag | kConsStringTag,
|
CONS_SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag | kConsStringTag,
|
||||||
CONS_ASCII_SYMBOL_TYPE = kAsciiStringTag | kSymbolTag | kConsStringTag,
|
CONS_ASCII_SYMBOL_TYPE = kAsciiStringTag | kSymbolTag | kConsStringTag,
|
||||||
|
SHORT_EXTERNAL_SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag |
|
||||||
|
kExternalStringTag | kShortExternalStringTag,
|
||||||
|
SHORT_EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE =
|
||||||
|
kTwoByteStringTag | kSymbolTag | kExternalStringTag |
|
||||||
|
kAsciiDataHintTag | kShortExternalStringTag,
|
||||||
|
SHORT_EXTERNAL_ASCII_SYMBOL_TYPE = kAsciiStringTag | kExternalStringTag |
|
||||||
|
kSymbolTag | kShortExternalStringTag,
|
||||||
EXTERNAL_SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag | kExternalStringTag,
|
EXTERNAL_SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag | kExternalStringTag,
|
||||||
EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE =
|
EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE =
|
||||||
kTwoByteStringTag | kSymbolTag | kExternalStringTag | kAsciiDataHintTag,
|
kTwoByteStringTag | kSymbolTag | kExternalStringTag | kAsciiDataHintTag,
|
||||||
@ -489,6 +531,13 @@ enum InstanceType {
|
|||||||
CONS_ASCII_STRING_TYPE = kAsciiStringTag | kConsStringTag,
|
CONS_ASCII_STRING_TYPE = kAsciiStringTag | kConsStringTag,
|
||||||
SLICED_STRING_TYPE = kTwoByteStringTag | kSlicedStringTag,
|
SLICED_STRING_TYPE = kTwoByteStringTag | kSlicedStringTag,
|
||||||
SLICED_ASCII_STRING_TYPE = kAsciiStringTag | kSlicedStringTag,
|
SLICED_ASCII_STRING_TYPE = kAsciiStringTag | kSlicedStringTag,
|
||||||
|
SHORT_EXTERNAL_STRING_TYPE =
|
||||||
|
kTwoByteStringTag | kExternalStringTag | kShortExternalStringTag,
|
||||||
|
SHORT_EXTERNAL_STRING_WITH_ASCII_DATA_TYPE =
|
||||||
|
kTwoByteStringTag | kExternalStringTag |
|
||||||
|
kAsciiDataHintTag | kShortExternalStringTag,
|
||||||
|
SHORT_EXTERNAL_ASCII_STRING_TYPE =
|
||||||
|
kAsciiStringTag | kExternalStringTag | kShortExternalStringTag,
|
||||||
EXTERNAL_STRING_TYPE = kTwoByteStringTag | kExternalStringTag,
|
EXTERNAL_STRING_TYPE = kTwoByteStringTag | kExternalStringTag,
|
||||||
EXTERNAL_STRING_WITH_ASCII_DATA_TYPE =
|
EXTERNAL_STRING_WITH_ASCII_DATA_TYPE =
|
||||||
kTwoByteStringTag | kExternalStringTag | kAsciiDataHintTag,
|
kTwoByteStringTag | kExternalStringTag | kAsciiDataHintTag,
|
||||||
@ -6755,12 +6804,12 @@ class ExternalString: public String {
|
|||||||
|
|
||||||
// Layout description.
|
// Layout description.
|
||||||
static const int kResourceOffset = POINTER_SIZE_ALIGN(String::kSize);
|
static const int kResourceOffset = POINTER_SIZE_ALIGN(String::kSize);
|
||||||
|
static const int kShortSize = kResourceOffset + kPointerSize;
|
||||||
static const int kResourceDataOffset = kResourceOffset + kPointerSize;
|
static const int kResourceDataOffset = kResourceOffset + kPointerSize;
|
||||||
static const int kSize = kResourceDataOffset + kPointerSize;
|
static const int kSize = kResourceDataOffset + kPointerSize;
|
||||||
|
|
||||||
// Clear the cached pointer to the character array provided by the resource.
|
// Return whether external string is short (data pointer is not cached).
|
||||||
// This cache is updated the first time the character array is accessed.
|
inline bool is_short();
|
||||||
inline void clear_data_cache();
|
|
||||||
|
|
||||||
STATIC_CHECK(kResourceOffset == Internals::kStringResourceOffset);
|
STATIC_CHECK(kResourceOffset == Internals::kStringResourceOffset);
|
||||||
|
|
||||||
@ -6781,6 +6830,12 @@ class ExternalAsciiString: public ExternalString {
|
|||||||
inline const Resource* resource();
|
inline const Resource* resource();
|
||||||
inline void set_resource(const Resource* buffer);
|
inline void set_resource(const Resource* buffer);
|
||||||
|
|
||||||
|
// Update the pointer cache to the external character array.
|
||||||
|
// The cached pointer is always valid, as the external character array does =
|
||||||
|
// not move during lifetime. Deserialization is the only exception, after
|
||||||
|
// which the pointer cache has to be refreshed.
|
||||||
|
inline void update_data_cache();
|
||||||
|
|
||||||
inline const char* GetChars();
|
inline const char* GetChars();
|
||||||
|
|
||||||
// Dispatched behavior.
|
// Dispatched behavior.
|
||||||
@ -6820,6 +6875,12 @@ class ExternalTwoByteString: public ExternalString {
|
|||||||
inline const Resource* resource();
|
inline const Resource* resource();
|
||||||
inline void set_resource(const Resource* buffer);
|
inline void set_resource(const Resource* buffer);
|
||||||
|
|
||||||
|
// Update the pointer cache to the external character array.
|
||||||
|
// The cached pointer is always valid, as the external character array does =
|
||||||
|
// not move during lifetime. Deserialization is the only exception, after
|
||||||
|
// which the pointer cache has to be refreshed.
|
||||||
|
inline void update_data_cache();
|
||||||
|
|
||||||
inline const uint16_t* GetChars();
|
inline const uint16_t* GetChars();
|
||||||
|
|
||||||
// Dispatched behavior.
|
// Dispatched behavior.
|
||||||
|
@ -669,6 +669,14 @@ void Deserializer::Deserialize() {
|
|||||||
|
|
||||||
isolate_->heap()->set_global_contexts_list(
|
isolate_->heap()->set_global_contexts_list(
|
||||||
isolate_->heap()->undefined_value());
|
isolate_->heap()->undefined_value());
|
||||||
|
|
||||||
|
// Update data pointers to the external strings containing natives sources.
|
||||||
|
for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
|
||||||
|
Object* source = isolate_->heap()->natives_source_cache()->get(i);
|
||||||
|
if (!source->IsUndefined()) {
|
||||||
|
ExternalAsciiString::cast(source)->update_data_cache();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1564,7 +1572,6 @@ void Serializer::ObjectSerializer::VisitExternalAsciiString(
|
|||||||
sink_->Put(kNativesStringResource, "NativesStringResource");
|
sink_->Put(kNativesStringResource, "NativesStringResource");
|
||||||
sink_->PutSection(i, "NativesStringResourceEnd");
|
sink_->PutSection(i, "NativesStringResourceEnd");
|
||||||
bytes_processed_so_far_ += sizeof(resource);
|
bytes_processed_so_far_ += sizeof(resource);
|
||||||
string->clear_data_cache();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -491,7 +491,7 @@ TEST(MakingExternalStringConditions) {
|
|||||||
HEAP->CollectGarbage(i::NEW_SPACE);
|
HEAP->CollectGarbage(i::NEW_SPACE);
|
||||||
HEAP->CollectGarbage(i::NEW_SPACE);
|
HEAP->CollectGarbage(i::NEW_SPACE);
|
||||||
|
|
||||||
uint16_t* two_byte_string = AsciiToTwoByteString("abcdefghi");
|
uint16_t* two_byte_string = AsciiToTwoByteString("s1");
|
||||||
Local<String> small_string = String::New(two_byte_string);
|
Local<String> small_string = String::New(two_byte_string);
|
||||||
i::DeleteArray(two_byte_string);
|
i::DeleteArray(two_byte_string);
|
||||||
|
|
||||||
@ -503,7 +503,7 @@ TEST(MakingExternalStringConditions) {
|
|||||||
// Old space strings should be accepted.
|
// Old space strings should be accepted.
|
||||||
CHECK(small_string->CanMakeExternal());
|
CHECK(small_string->CanMakeExternal());
|
||||||
|
|
||||||
two_byte_string = AsciiToTwoByteString("abcdefghi");
|
two_byte_string = AsciiToTwoByteString("small string 2");
|
||||||
small_string = String::New(two_byte_string);
|
small_string = String::New(two_byte_string);
|
||||||
i::DeleteArray(two_byte_string);
|
i::DeleteArray(two_byte_string);
|
||||||
|
|
||||||
@ -537,7 +537,7 @@ TEST(MakingExternalAsciiStringConditions) {
|
|||||||
HEAP->CollectGarbage(i::NEW_SPACE);
|
HEAP->CollectGarbage(i::NEW_SPACE);
|
||||||
HEAP->CollectGarbage(i::NEW_SPACE);
|
HEAP->CollectGarbage(i::NEW_SPACE);
|
||||||
|
|
||||||
Local<String> small_string = String::New("abcdefghi");
|
Local<String> small_string = String::New("s1");
|
||||||
// We should refuse to externalize newly created small string.
|
// We should refuse to externalize newly created small string.
|
||||||
CHECK(!small_string->CanMakeExternal());
|
CHECK(!small_string->CanMakeExternal());
|
||||||
// Trigger GCs so that the newly allocated string moves to old gen.
|
// Trigger GCs so that the newly allocated string moves to old gen.
|
||||||
@ -546,7 +546,7 @@ TEST(MakingExternalAsciiStringConditions) {
|
|||||||
// Old space strings should be accepted.
|
// Old space strings should be accepted.
|
||||||
CHECK(small_string->CanMakeExternal());
|
CHECK(small_string->CanMakeExternal());
|
||||||
|
|
||||||
small_string = String::New("abcdefghi");
|
small_string = String::New("small string 2");
|
||||||
// We should refuse externalizing newly created small string.
|
// We should refuse externalizing newly created small string.
|
||||||
CHECK(!small_string->CanMakeExternal());
|
CHECK(!small_string->CanMakeExternal());
|
||||||
for (int i = 0; i < 100; i++) {
|
for (int i = 0; i < 100; i++) {
|
||||||
|
@ -39,7 +39,7 @@ function test() {
|
|||||||
assertTrue(isAsciiString(str));
|
assertTrue(isAsciiString(str));
|
||||||
|
|
||||||
var twoByteExternalWithAsciiData =
|
var twoByteExternalWithAsciiData =
|
||||||
"AAAAAAAA" + (function() { return "A"; })();
|
"AA" + (function() { return "A"; })();
|
||||||
externalizeString(twoByteExternalWithAsciiData, true /* force two-byte */);
|
externalizeString(twoByteExternalWithAsciiData, true /* force two-byte */);
|
||||||
assertFalse(isAsciiString(twoByteExternalWithAsciiData));
|
assertFalse(isAsciiString(twoByteExternalWithAsciiData));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user