Version 3.16.3
Improved GC performance when moving parts of a FixedArray (issue 2452).
Enabled readline on d8 while building a shared lib (issue 1781).
Fixed missing exception check in typed array constructor (Chromium issue 168545).
Check for read-only-ness when preparing for array sort (issue 2419).
Performance and stability improvements on all platforms.
git-svn-id: http://v8.googlecode.com/svn/trunk@13346 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/heap.cc b/src/heap.cc
index 401f4f7..013a18c 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -677,6 +677,29 @@
}
+void Heap::MoveElements(FixedArray* array,
+ int dst_index,
+ int src_index,
+ int len) {
+ if (len == 0) return;
+
+ ASSERT(array->map() != HEAP->fixed_cow_array_map());
+ Object** dst_objects = array->data_start() + dst_index;
+ memmove(dst_objects,
+ array->data_start() + src_index,
+ len * kPointerSize);
+ if (!InNewSpace(array)) {
+ for (int i = 0; i < len; i++) {
+ // TODO(hpayer): check store buffer for entries
+ if (InNewSpace(dst_objects[i])) {
+ RecordWrite(array->address(), array->OffsetOfElementAt(dst_index + i));
+ }
+ }
+ }
+ incremental_marking()->RecordWrites(array);
+}
+
+
#ifdef VERIFY_HEAP
// Helper class for verifying the symbol table.
class SymbolTableVerifier : public ObjectVisitor {
@@ -2785,7 +2808,7 @@
// hash code in place. The hash code for the hidden_symbol is zero to ensure
// that it will always be at the first entry in property descriptors.
{ MaybeObject* maybe_obj =
- AllocateSymbol(CStrVector(""), 0, String::kEmptyStringHash);
+ AllocateOneByteSymbol(OneByteVector("", 0), String::kEmptyStringHash);
if (!maybe_obj->ToObject(&obj)) return false;
}
hidden_symbol_ = String::cast(obj);
@@ -2838,9 +2861,9 @@
}
set_number_string_cache(FixedArray::cast(obj));
- // Allocate cache for single character ASCII strings.
+ // Allocate cache for single character one byte strings.
{ MaybeObject* maybe_obj =
- AllocateFixedArray(String::kMaxAsciiCharCode + 1, TENURED);
+ AllocateFixedArray(String::kMaxOneByteCharCode + 1, TENURED);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_single_character_string_cache(FixedArray::cast(obj));
@@ -3309,16 +3332,16 @@
return symbol;
// Now we know the length is 2, we might as well make use of that fact
// when building the new string.
- } else if (static_cast<unsigned>(c1 | c2) <= String::kMaxAsciiCharCodeU) {
+ } else if (static_cast<unsigned>(c1 | c2) <= String::kMaxOneByteCharCodeU) {
// We can do this.
- ASSERT(IsPowerOf2(String::kMaxAsciiCharCodeU + 1)); // because of this.
+ ASSERT(IsPowerOf2(String::kMaxOneByteCharCodeU + 1)); // because of this.
Object* result;
{ MaybeObject* maybe_result = heap->AllocateRawOneByteString(2);
if (!maybe_result->ToObject(&result)) return maybe_result;
}
- char* dest = SeqOneByteString::cast(result)->GetChars();
- dest[0] = static_cast<char>(c1);
- dest[1] = static_cast<char>(c2);
+ uint8_t* dest = SeqOneByteString::cast(result)->GetChars();
+ dest[0] = static_cast<uint8_t>(c1);
+ dest[1] = static_cast<uint8_t>(c2);
return result;
} else {
Object* result;
@@ -3355,19 +3378,18 @@
return MakeOrFindTwoCharacterString(this, c1, c2);
}
- bool first_is_ascii = first->IsOneByteRepresentation();
- bool second_is_ascii = second->IsOneByteRepresentation();
- bool is_ascii = first_is_ascii && second_is_ascii;
-
+ bool first_is_one_byte = first->IsOneByteRepresentation();
+ bool second_is_one_byte = second->IsOneByteRepresentation();
+ bool is_one_byte = first_is_one_byte && second_is_one_byte;
// Make sure that an out of memory exception is thrown if the length
// of the new cons string is too large.
if (length > String::kMaxLength || length < 0) {
isolate()->context()->mark_out_of_memory();
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0x4);
}
bool is_ascii_data_in_two_byte_string = false;
- if (!is_ascii) {
+ if (!is_one_byte) {
// At least one of the strings uses two-byte representation so we
// can't use the fast case code for short ASCII strings below, but
// we can try to save memory if all chars actually fit in ASCII.
@@ -3384,15 +3406,15 @@
STATIC_ASSERT(ConsString::kMinLength <= SlicedString::kMinLength);
ASSERT(first->IsFlat());
ASSERT(second->IsFlat());
- if (is_ascii) {
+ if (is_one_byte) {
Object* result;
{ MaybeObject* maybe_result = AllocateRawOneByteString(length);
if (!maybe_result->ToObject(&result)) return maybe_result;
}
// Copy the characters into the new object.
- char* dest = SeqOneByteString::cast(result)->GetChars();
+ uint8_t* dest = SeqOneByteString::cast(result)->GetChars();
// Copy first part.
- const char* src;
+ const uint8_t* src;
if (first->IsExternalString()) {
src = ExternalAsciiString::cast(first)->GetChars();
} else {
@@ -3414,7 +3436,7 @@
if (!maybe_result->ToObject(&result)) return maybe_result;
}
// Copy the characters into the new object.
- char* dest = SeqOneByteString::cast(result)->GetChars();
+ uint8_t* dest = SeqOneByteString::cast(result)->GetChars();
String::WriteToFlat(first, dest, 0, first_length);
String::WriteToFlat(second, dest + first_length, 0, second_length);
isolate_->counters()->string_add_runtime_ext_to_ascii()->Increment();
@@ -3433,7 +3455,7 @@
}
}
- Map* map = (is_ascii || is_ascii_data_in_two_byte_string) ?
+ Map* map = (is_one_byte || is_ascii_data_in_two_byte_string) ?
cons_ascii_string_map() : cons_string_map();
Object* result;
@@ -3481,17 +3503,17 @@
// WriteToFlat takes care of the case when an indirect string has a
// different encoding from its underlying string. These encodings may
// differ because of externalization.
- bool is_ascii = buffer->IsOneByteRepresentation();
- { MaybeObject* maybe_result = is_ascii
+ bool is_one_byte = buffer->IsOneByteRepresentation();
+ { MaybeObject* maybe_result = is_one_byte
? AllocateRawOneByteString(length, pretenure)
: AllocateRawTwoByteString(length, pretenure);
if (!maybe_result->ToObject(&result)) return maybe_result;
}
String* string_result = String::cast(result);
// Copy the characters into the new object.
- if (is_ascii) {
+ if (is_one_byte) {
ASSERT(string_result->IsOneByteRepresentation());
- char* dest = SeqOneByteString::cast(string_result)->GetChars();
+ uint8_t* dest = SeqOneByteString::cast(string_result)->GetChars();
String::WriteToFlat(buffer, dest, start, end);
} else {
ASSERT(string_result->IsTwoByteRepresentation());
@@ -3551,7 +3573,7 @@
size_t length = resource->length();
if (length > static_cast<size_t>(String::kMaxLength)) {
isolate()->context()->mark_out_of_memory();
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0x5);
}
ASSERT(String::IsAscii(resource->data(), static_cast<int>(length)));
@@ -3576,15 +3598,15 @@
size_t length = resource->length();
if (length > static_cast<size_t>(String::kMaxLength)) {
isolate()->context()->mark_out_of_memory();
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0x6);
}
// For small strings we check whether the resource contains only
- // ASCII characters. If yes, we use a different string map.
+ // one byte characters. If yes, we use a different string map.
static const size_t kAsciiCheckLengthLimit = 32;
- bool is_ascii = length <= kAsciiCheckLengthLimit &&
- String::IsAscii(resource->data(), static_cast<int>(length));
- Map* map = is_ascii ?
+ bool is_one_byte = length <= kAsciiCheckLengthLimit &&
+ String::IsOneByte(resource->data(), static_cast<int>(length));
+ Map* map = is_one_byte ?
external_string_with_ascii_data_map() : external_string_map();
Object* result;
{ MaybeObject* maybe_result = Allocate(map, NEW_SPACE);
@@ -3601,15 +3623,15 @@
MaybeObject* Heap::LookupSingleCharacterStringFromCode(uint16_t code) {
- if (code <= String::kMaxAsciiCharCode) {
+ if (code <= String::kMaxOneByteCharCode) {
Object* value = single_character_string_cache()->get(code);
if (value != undefined_value()) return value;
- char buffer[1];
- buffer[0] = static_cast<char>(code);
+ uint8_t buffer[1];
+ buffer[0] = static_cast<uint8_t>(code);
Object* result;
MaybeObject* maybe_result =
- LookupOneByteSymbol(Vector<const char>(buffer, 1));
+ LookupOneByteSymbol(Vector<const uint8_t>(buffer, 1));
if (!maybe_result->ToObject(&result)) return maybe_result;
single_character_string_cache()->set(code, result);
@@ -3628,7 +3650,7 @@
MaybeObject* Heap::AllocateByteArray(int length, PretenureFlag pretenure) {
if (length < 0 || length > ByteArray::kMaxLength) {
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0x7);
}
if (pretenure == NOT_TENURED) {
return AllocateByteArray(length);
@@ -3650,7 +3672,7 @@
MaybeObject* Heap::AllocateByteArray(int length) {
if (length < 0 || length > ByteArray::kMaxLength) {
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0x8);
}
int size = ByteArray::SizeFor(length);
AllocationSpace space =
@@ -4520,7 +4542,7 @@
}
-MaybeObject* Heap::AllocateStringFromOneByte(Vector<const char> string,
+MaybeObject* Heap::AllocateStringFromOneByte(Vector<const uint8_t> string,
PretenureFlag pretenure) {
int length = string.length();
if (length == 1) {
@@ -4533,7 +4555,9 @@
}
// Copy the characters into the new object.
- CopyChars(SeqOneByteString::cast(result)->GetChars(), string.start(), length);
+ CopyChars(SeqOneByteString::cast(result)->GetChars(),
+ string.start(),
+ length);
return result;
}
@@ -4579,11 +4603,11 @@
int length = string.length();
const uc16* start = string.start();
- if (String::IsAscii(start, length)) {
+ if (String::IsOneByte(start, length)) {
MaybeObject* maybe_result = AllocateRawOneByteString(length, pretenure);
if (!maybe_result->ToObject(&result)) return maybe_result;
CopyChars(SeqOneByteString::cast(result)->GetChars(), start, length);
- } else { // It's not an ASCII string.
+ } else { // It's not a one byte string.
MaybeObject* maybe_result = AllocateRawTwoByteString(length, pretenure);
if (!maybe_result->ToObject(&result)) return maybe_result;
CopyChars(SeqTwoByteString::cast(result)->GetChars(), start, length);
@@ -4630,7 +4654,7 @@
class AllocateInternalSymbolHelper< Vector<const char> > {
public:
static inline void WriteOneByteData(Vector<const char> vector,
- char* chars,
+ uint8_t* chars,
int len) {
// Only works for ascii.
ASSERT(vector.length() == len);
@@ -4672,7 +4696,7 @@
template<>
class AllocateInternalSymbolHelper<String*> {
public:
- static inline void WriteOneByteData(String* s, char* chars, int len) {
+ static inline void WriteOneByteData(String* s, uint8_t* chars, int len) {
ASSERT(s->length() == len);
String::WriteToFlat(s, chars, 0, len);
}
@@ -4699,13 +4723,13 @@
if (is_one_byte) {
if (chars > SeqOneByteString::kMaxLength) {
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0x9);
}
map = ascii_symbol_map();
size = SeqOneByteString::SizeFor(chars);
} else {
if (chars > SeqTwoByteString::kMaxLength) {
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0xa);
}
map = symbol_map();
size = SeqTwoByteString::SizeFor(chars);
@@ -4750,7 +4774,7 @@
MaybeObject* Heap::AllocateRawOneByteString(int length,
PretenureFlag pretenure) {
if (length < 0 || length > SeqOneByteString::kMaxLength) {
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0xb);
}
int size = SeqOneByteString::SizeFor(length);
@@ -4782,14 +4806,16 @@
String::cast(result)->set_hash_field(String::kEmptyHashField);
ASSERT_EQ(size, HeapObject::cast(result)->Size());
+#ifndef ENABLE_LATIN_1
#ifdef VERIFY_HEAP
if (FLAG_verify_heap) {
// Initialize string's content to ensure ASCII-ness (character range 0-127)
// as required when verifying the heap.
- char* dest = SeqOneByteString::cast(result)->GetChars();
+ uint8_t* dest = SeqOneByteString::cast(result)->GetChars();
memset(dest, 0x0F, length * kCharSize);
}
#endif
+#endif
return result;
}
@@ -4798,7 +4824,7 @@
MaybeObject* Heap::AllocateRawTwoByteString(int length,
PretenureFlag pretenure) {
if (length < 0 || length > SeqTwoByteString::kMaxLength) {
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0xc);
}
int size = SeqTwoByteString::SizeFor(length);
ASSERT(size <= SeqTwoByteString::kMaxSize);
@@ -4867,7 +4893,7 @@
MaybeObject* Heap::AllocateRawFixedArray(int length) {
if (length < 0 || length > FixedArray::kMaxLength) {
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0xd);
}
ASSERT(length > 0);
// Use the general function if we're forced to always allocate.
@@ -4943,7 +4969,7 @@
MaybeObject* Heap::AllocateRawFixedArray(int length, PretenureFlag pretenure) {
if (length < 0 || length > FixedArray::kMaxLength) {
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0xe);
}
AllocationSpace space =
@@ -5076,7 +5102,7 @@
MaybeObject* Heap::AllocateRawFixedDoubleArray(int length,
PretenureFlag pretenure) {
if (length < 0 || length > FixedDoubleArray::kMaxLength) {
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0xf);
}
AllocationSpace space =
@@ -5628,7 +5654,7 @@
}
-MaybeObject* Heap::LookupOneByteSymbol(Vector<const char> string) {
+MaybeObject* Heap::LookupOneByteSymbol(Vector<const uint8_t> string) {
Object* symbol = NULL;
Object* new_table;
{ MaybeObject* maybe_new_table =