Update V8 to version 4.1.0.21
This is a cherry-pick of all commits up to and including the
4.1.0.21 cherry-pick in Chromium.
Original commit message:
Version 4.1.0.21 (cherry-pick)
Merged 206e9136bde0f2b5ae8cb77afbb1e7833e5bd412
Unlink pages from the space page list after evacuation.
BUG=430201
LOG=N
R=jkummerow@chromium.org
Review URL: https://codereview.chromium.org/953813002
Cr-Commit-Position: refs/branch-heads/4.1@{#22}
Cr-Branched-From: 2e08d2a7aa9d65d269d8c57aba82eb38a8cb0a18-refs/heads/candidates@{#25353}
---
FPIIM-449
Change-Id: I8c23c7bbb70772b4858fe8a47b64fa97ee0d1f8c
diff --git a/src/json-stringifier.h b/src/json-stringifier.h
index f89a19f..393551d 100644
--- a/src/json-stringifier.h
+++ b/src/json-stringifier.h
@@ -8,6 +8,7 @@
#include "src/v8.h"
#include "src/conversions.h"
+#include "src/string-builder.h"
#include "src/utils.h"
namespace v8 {
@@ -24,42 +25,8 @@
Handle<String> object));
private:
- static const int kInitialPartLength = 32;
- static const int kMaxPartLength = 16 * 1024;
- static const int kPartLengthGrowthFactor = 2;
-
enum Result { UNCHANGED, SUCCESS, EXCEPTION };
- void Accumulate();
-
- void Extend();
-
- void ChangeEncoding();
-
- INLINE(void ShrinkCurrentPart());
-
- template <bool is_one_byte, typename Char>
- INLINE(void Append_(Char c));
-
- template <bool is_one_byte, typename Char>
- INLINE(void Append_(const Char* chars));
-
- INLINE(void Append(uint8_t c)) {
- if (is_one_byte_) {
- Append_<true>(c);
- } else {
- Append_<false>(c);
- }
- }
-
- INLINE(void AppendOneByte(const char* chars)) {
- if (is_one_byte_) {
- Append_<true>(reinterpret_cast<const uint8_t*>(chars));
- } else {
- Append_<false>(reinterpret_cast<const uint8_t*>(chars));
- }
- }
-
MUST_USE_RESULT MaybeHandle<Object> ApplyToJsonFunction(
Handle<Object> object,
Handle<Object> key);
@@ -69,14 +36,9 @@
bool deferred_comma,
bool deferred_key);
- template <typename ResultType, typename Char>
- INLINE(static Handle<String> StringifyString_(Isolate* isolate,
- Vector<Char> vector,
- Handle<String> result));
-
// Entry point to serialize the object.
INLINE(Result SerializeObject(Handle<Object> obj)) {
- return Serialize_<false>(obj, false, factory_->empty_string());
+ return Serialize_<false>(obj, false, factory()->empty_string());
}
// Serialize an array element.
@@ -103,9 +65,9 @@
Result Serialize_(Handle<Object> object, bool comma, Handle<Object> key);
void SerializeDeferredKey(bool deferred_comma, Handle<Object> deferred_key) {
- if (deferred_comma) Append(',');
+ if (deferred_comma) builder_.AppendCharacter(',');
SerializeString(Handle<String>::cast(deferred_key));
- Append(':');
+ builder_.AppendCharacter(':');
}
Result SerializeSmi(Smi* object);
@@ -125,42 +87,25 @@
void SerializeString(Handle<String> object);
template <typename SrcChar, typename DestChar>
- INLINE(static int SerializeStringUnchecked_(const SrcChar* src,
- DestChar* dest,
- int length));
+ INLINE(static void SerializeStringUnchecked_(
+ Vector<const SrcChar> src,
+ IncrementalStringBuilder::NoExtend<DestChar>* dest));
- template <bool is_one_byte, typename Char>
+ template <typename SrcChar, typename DestChar>
INLINE(void SerializeString_(Handle<String> string));
template <typename Char>
INLINE(static bool DoNotEscape(Char c));
- template <typename Char>
- INLINE(static Vector<const Char> GetCharVector(Handle<String> string));
-
Result StackPush(Handle<Object> object);
void StackPop();
- INLINE(Handle<String> accumulator()) {
- return Handle<String>(String::cast(accumulator_store_->value()), isolate_);
- }
-
- INLINE(void set_accumulator(Handle<String> string)) {
- return accumulator_store_->set_value(*string);
- }
+ Factory* factory() { return isolate_->factory(); }
Isolate* isolate_;
- Factory* factory_;
- // We use a value wrapper for the string accumulator to keep the
- // (indirect) handle to it in the outermost handle scope.
- Handle<JSValue> accumulator_store_;
- Handle<String> current_part_;
+ IncrementalStringBuilder builder_;
Handle<String> tojson_string_;
Handle<JSArray> stack_;
- int current_index_;
- int part_length_;
- bool is_one_byte_;
- bool overflowed_;
static const int kJsonEscapeTableEntrySize = 8;
static const char* const JsonEscapeTable;
@@ -237,31 +182,16 @@
BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate)
- : isolate_(isolate),
- current_index_(0),
- is_one_byte_(true),
- overflowed_(false) {
- factory_ = isolate_->factory();
- accumulator_store_ = Handle<JSValue>::cast(
- Object::ToObject(isolate, factory_->empty_string()).ToHandleChecked());
- part_length_ = kInitialPartLength;
- current_part_ = factory_->NewRawOneByteString(part_length_).ToHandleChecked();
- tojson_string_ = factory_->toJSON_string();
- stack_ = factory_->NewJSArray(8);
+ : isolate_(isolate), builder_(isolate) {
+ tojson_string_ = factory()->toJSON_string();
+ stack_ = factory()->NewJSArray(8);
}
MaybeHandle<Object> BasicJsonStringifier::Stringify(Handle<Object> object) {
Result result = SerializeObject(object);
- if (result == UNCHANGED) return isolate_->factory()->undefined_value();
- if (result == SUCCESS) {
- ShrinkCurrentPart();
- Accumulate();
- if (overflowed_) {
- THROW_NEW_ERROR(isolate_, NewInvalidStringLengthError(), Object);
- }
- return accumulator();
- }
+ if (result == UNCHANGED) return factory()->undefined_value();
+ if (result == SUCCESS) return builder_.Finish();
DCHECK(result == EXCEPTION);
return MaybeHandle<Object>();
}
@@ -281,58 +211,29 @@
object = String::Flatten(object);
DCHECK(object->IsFlat());
+ Handle<SeqString> result;
if (object->IsOneByteRepresentationUnderneath()) {
- Handle<String> result = isolate->factory()->NewRawOneByteString(
- worst_case_length).ToHandleChecked();
- DisallowHeapAllocation no_gc;
- return StringifyString_<SeqOneByteString>(
- isolate,
- object->GetFlatContent().ToOneByteVector(),
- result);
+ result = isolate->factory()
+ ->NewRawOneByteString(worst_case_length)
+ .ToHandleChecked();
+ IncrementalStringBuilder::NoExtendString<uint8_t> no_extend(
+ result, worst_case_length);
+ no_extend.Append('\"');
+ SerializeStringUnchecked_(object->GetFlatContent().ToOneByteVector(),
+ &no_extend);
+ no_extend.Append('\"');
} else {
- Handle<String> result = isolate->factory()->NewRawTwoByteString(
- worst_case_length).ToHandleChecked();
- DisallowHeapAllocation no_gc;
- return StringifyString_<SeqTwoByteString>(
- isolate,
- object->GetFlatContent().ToUC16Vector(),
- result);
+ result = isolate->factory()
+ ->NewRawTwoByteString(worst_case_length)
+ .ToHandleChecked();
+ IncrementalStringBuilder::NoExtendString<uc16> no_extend(result,
+ worst_case_length);
+ no_extend.Append('\"');
+ SerializeStringUnchecked_(object->GetFlatContent().ToUC16Vector(),
+ &no_extend);
+ no_extend.Append('\"');
}
-}
-
-
-template <typename ResultType, typename Char>
-Handle<String> BasicJsonStringifier::StringifyString_(Isolate* isolate,
- Vector<Char> vector,
- Handle<String> result) {
- DisallowHeapAllocation no_gc;
- int final_size = 0;
- ResultType* dest = ResultType::cast(*result);
- dest->Set(final_size++, '\"');
- final_size += SerializeStringUnchecked_(vector.start(),
- dest->GetChars() + 1,
- vector.length());
- dest->Set(final_size++, '\"');
- return SeqString::Truncate(Handle<SeqString>::cast(result), final_size);
-}
-
-
-template <bool is_one_byte, typename Char>
-void BasicJsonStringifier::Append_(Char c) {
- if (is_one_byte) {
- SeqOneByteString::cast(*current_part_)->SeqOneByteStringSet(
- current_index_++, c);
- } else {
- SeqTwoByteString::cast(*current_part_)->SeqTwoByteStringSet(
- current_index_++, c);
- }
- if (current_index_ == part_length_) Extend();
-}
-
-
-template <bool is_one_byte, typename Char>
-void BasicJsonStringifier::Append_(const Char* chars) {
- for (; *chars != '\0'; chars++) Append_<is_one_byte, Char>(*chars);
+ return result;
}
@@ -345,7 +246,7 @@
if (!fun->IsJSFunction()) return object;
// Call toJSON function.
- if (key->IsSmi()) key = factory_->NumberToString(key);
+ if (key->IsSmi()) key = factory()->NumberToString(key);
Handle<Object> argv[] = { key };
HandleScope scope(isolate_);
ASSIGN_RETURN_ON_EXCEPTION(
@@ -372,7 +273,7 @@
if (elements->get(i) == *object) {
AllowHeapAllocation allow_to_return_error;
Handle<Object> error;
- MaybeHandle<Object> maybe_error = factory_->NewTypeError(
+ MaybeHandle<Object> maybe_error = factory()->NewTypeError(
"circular_structure", HandleVector<Object>(NULL, 0));
if (maybe_error.ToHandle(&error)) isolate_->Throw(*error);
return EXCEPTION;
@@ -416,15 +317,15 @@
switch (Oddball::cast(*object)->kind()) {
case Oddball::kFalse:
if (deferred_string_key) SerializeDeferredKey(comma, key);
- AppendOneByte("false");
+ builder_.AppendCString("false");
return SUCCESS;
case Oddball::kTrue:
if (deferred_string_key) SerializeDeferredKey(comma, key);
- AppendOneByte("true");
+ builder_.AppendCString("true");
return SUCCESS;
case Oddball::kNull:
if (deferred_string_key) SerializeDeferredKey(comma, key);
- AppendOneByte("null");
+ builder_.AppendCString("null");
return SUCCESS;
default:
return UNCHANGED;
@@ -472,23 +373,11 @@
EXCEPTION);
if (result->IsUndefined()) return UNCHANGED;
if (deferred_key) {
- if (key->IsSmi()) key = factory_->NumberToString(key);
+ if (key->IsSmi()) key = factory()->NumberToString(key);
SerializeDeferredKey(deferred_comma, key);
}
- Handle<String> result_string = Handle<String>::cast(result);
- // Shrink current part, attach it to the accumulator, also attach the result
- // string to the accumulator, and allocate a new part.
- ShrinkCurrentPart(); // Shrink.
- part_length_ = kInitialPartLength; // Allocate conservatively.
- Extend(); // Attach current part and allocate new part.
- // Attach result string to the accumulator.
- Handle<String> cons;
- ASSIGN_RETURN_ON_EXCEPTION_VALUE(
- isolate_, cons,
- factory_->NewConsString(accumulator(), result_string),
- EXCEPTION);
- set_accumulator(cons);
+ builder_.AppendString(Handle<String>::cast(result));
return SUCCESS;
}
@@ -511,7 +400,7 @@
DCHECK(class_name == isolate_->heap()->Boolean_string());
Object* value = JSValue::cast(*object)->value();
DCHECK(value->IsBoolean());
- AppendOneByte(value->IsTrue() ? "true" : "false");
+ builder_.AppendCString(value->IsTrue() ? "true" : "false");
}
return SUCCESS;
}
@@ -521,7 +410,7 @@
static const int kBufferSize = 100;
char chars[kBufferSize];
Vector<char> buffer(chars, kBufferSize);
- AppendOneByte(IntToCString(object->value(), buffer));
+ builder_.AppendCString(IntToCString(object->value(), buffer));
return SUCCESS;
}
@@ -529,13 +418,13 @@
BasicJsonStringifier::Result BasicJsonStringifier::SerializeDouble(
double number) {
if (std::isinf(number) || std::isnan(number)) {
- AppendOneByte("null");
+ builder_.AppendCString("null");
return SUCCESS;
}
static const int kBufferSize = 100;
char chars[kBufferSize];
Vector<char> buffer(chars, kBufferSize);
- AppendOneByte(DoubleToCString(number, buffer));
+ builder_.AppendCString(DoubleToCString(number, buffer));
return SUCCESS;
}
@@ -547,13 +436,13 @@
if (stack_push != SUCCESS) return stack_push;
uint32_t length = 0;
CHECK(object->length()->ToArrayIndex(&length));
- Append('[');
+ builder_.AppendCharacter('[');
switch (object->GetElementsKind()) {
case FAST_SMI_ELEMENTS: {
Handle<FixedArray> elements(
FixedArray::cast(object->elements()), isolate_);
for (uint32_t i = 0; i < length; i++) {
- if (i > 0) Append(',');
+ if (i > 0) builder_.AppendCharacter(',');
SerializeSmi(Smi::cast(elements->get(i)));
}
break;
@@ -564,7 +453,7 @@
Handle<FixedDoubleArray> elements(
FixedDoubleArray::cast(object->elements()), isolate_);
for (uint32_t i = 0; i < length; i++) {
- if (i > 0) Append(',');
+ if (i > 0) builder_.AppendCharacter(',');
SerializeDouble(elements->get_scalar(i));
}
break;
@@ -573,14 +462,14 @@
Handle<FixedArray> elements(
FixedArray::cast(object->elements()), isolate_);
for (uint32_t i = 0; i < length; i++) {
- if (i > 0) Append(',');
+ if (i > 0) builder_.AppendCharacter(',');
Result result =
SerializeElement(isolate_,
Handle<Object>(elements->get(i), isolate_),
i);
if (result == SUCCESS) continue;
if (result == UNCHANGED) {
- AppendOneByte("null");
+ builder_.AppendCString("null");
} else {
return result;
}
@@ -596,9 +485,8 @@
break;
}
}
- Append(']');
+ builder_.AppendCharacter(']');
StackPop();
- current_part_ = handle_scope.CloseAndEscape(current_part_);
return SUCCESS;
}
@@ -606,19 +494,19 @@
BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArraySlow(
Handle<JSArray> object, uint32_t length) {
for (uint32_t i = 0; i < length; i++) {
- if (i > 0) Append(',');
+ if (i > 0) builder_.AppendCharacter(',');
Handle<Object> element;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate_, element,
Object::GetElement(isolate_, object, i),
EXCEPTION);
if (element->IsUndefined()) {
- AppendOneByte("null");
+ builder_.AppendCString("null");
} else {
Result result = SerializeElement(isolate_, element, i);
if (result == SUCCESS) continue;
if (result == UNCHANGED) {
- AppendOneByte("null");
+ builder_.AppendCString("null");
} else {
return result;
}
@@ -635,7 +523,7 @@
if (stack_push != SUCCESS) return stack_push;
DCHECK(!object->IsJSGlobalProxy() && !object->IsGlobalObject());
- Append('{');
+ builder_.AppendCharacter('{');
bool comma = false;
if (object->HasFastProperties() &&
@@ -652,8 +540,15 @@
if (details.IsDontEnum()) continue;
Handle<Object> property;
if (details.type() == FIELD && *map == object->map()) {
- property = Handle<Object>(object->RawFastPropertyAt(
- FieldIndex::ForDescriptor(*map, i)), isolate_);
+ FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
+ Isolate* isolate = object->GetIsolate();
+ if (object->IsUnboxedDoubleField(field_index)) {
+ double value = object->RawFastDoublePropertyAt(field_index);
+ property = isolate->factory()->NewHeapNumber(value);
+
+ } else {
+ property = handle(object->RawFastPropertyAt(field_index), isolate);
+ }
} else {
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate_, property,
@@ -680,7 +575,7 @@
maybe_property = Object::GetPropertyOrElement(object, key_handle);
} else {
DCHECK(key->IsNumber());
- key_handle = factory_->NumberToString(Handle<Object>(key, isolate_));
+ key_handle = factory()->NumberToString(Handle<Object>(key, isolate_));
uint32_t index;
if (key->IsSmi()) {
maybe_property = Object::GetElement(
@@ -700,130 +595,59 @@
}
}
- Append('}');
+ builder_.AppendCharacter('}');
StackPop();
- current_part_ = handle_scope.CloseAndEscape(current_part_);
return SUCCESS;
}
-void BasicJsonStringifier::ShrinkCurrentPart() {
- DCHECK(current_index_ < part_length_);
- current_part_ = SeqString::Truncate(Handle<SeqString>::cast(current_part_),
- current_index_);
-}
+template <typename SrcChar, typename DestChar>
+void BasicJsonStringifier::SerializeStringUnchecked_(
+ Vector<const SrcChar> src,
+ IncrementalStringBuilder::NoExtend<DestChar>* dest) {
+ // Assert that uc16 character is not truncated down to 8 bit.
+ // The <uc16, char> version of this method must not be called.
+ DCHECK(sizeof(DestChar) >= sizeof(SrcChar));
-
-void BasicJsonStringifier::Accumulate() {
- if (accumulator()->length() + current_part_->length() > String::kMaxLength) {
- // Screw it. Simply set the flag and carry on. Throw exception at the end.
- set_accumulator(factory_->empty_string());
- overflowed_ = true;
- } else {
- set_accumulator(factory_->NewConsString(accumulator(),
- current_part_).ToHandleChecked());
+ for (int i = 0; i < src.length(); i++) {
+ SrcChar c = src[i];
+ if (DoNotEscape(c)) {
+ dest->Append(c);
+ } else {
+ dest->AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]);
+ }
}
}
-void BasicJsonStringifier::Extend() {
- Accumulate();
- if (part_length_ <= kMaxPartLength / kPartLengthGrowthFactor) {
- part_length_ *= kPartLengthGrowthFactor;
- }
- if (is_one_byte_) {
- current_part_ =
- factory_->NewRawOneByteString(part_length_).ToHandleChecked();
- } else {
- current_part_ =
- factory_->NewRawTwoByteString(part_length_).ToHandleChecked();
- }
- DCHECK(!current_part_.is_null());
- current_index_ = 0;
-}
-
-
-void BasicJsonStringifier::ChangeEncoding() {
- ShrinkCurrentPart();
- Accumulate();
- current_part_ =
- factory_->NewRawTwoByteString(part_length_).ToHandleChecked();
- DCHECK(!current_part_.is_null());
- current_index_ = 0;
- is_one_byte_ = false;
-}
-
-
template <typename SrcChar, typename DestChar>
-int BasicJsonStringifier::SerializeStringUnchecked_(const SrcChar* src,
- DestChar* dest,
- int length) {
- DestChar* dest_start = dest;
-
- // Assert that uc16 character is not truncated down to 8 bit.
- // The <uc16, char> version of this method must not be called.
- DCHECK(sizeof(*dest) >= sizeof(*src));
-
- for (int i = 0; i < length; i++) {
- SrcChar c = src[i];
- if (DoNotEscape(c)) {
- *(dest++) = static_cast<DestChar>(c);
- } else {
- const uint8_t* chars = reinterpret_cast<const uint8_t*>(
- &JsonEscapeTable[c * kJsonEscapeTableEntrySize]);
- while (*chars != '\0') *(dest++) = *(chars++);
- }
- }
-
- return static_cast<int>(dest - dest_start);
-}
-
-
-template <bool is_one_byte, typename Char>
void BasicJsonStringifier::SerializeString_(Handle<String> string) {
int length = string->length();
- Append_<is_one_byte, char>('"');
+ builder_.Append<uint8_t, DestChar>('"');
// We make a rough estimate to find out if the current string can be
// serialized without allocating a new string part. The worst case length of
// an escaped character is 6. Shifting the remainin string length right by 3
// is a more pessimistic estimate, but faster to calculate.
-
- if (((part_length_ - current_index_) >> 3) > length) {
+ int worst_case_length = length << 3;
+ if (builder_.CurrentPartCanFit(worst_case_length)) {
DisallowHeapAllocation no_gc;
- Vector<const Char> vector = GetCharVector<Char>(string);
- if (is_one_byte) {
- current_index_ += SerializeStringUnchecked_(
- vector.start(),
- SeqOneByteString::cast(*current_part_)->GetChars() + current_index_,
- length);
- } else {
- current_index_ += SerializeStringUnchecked_(
- vector.start(),
- SeqTwoByteString::cast(*current_part_)->GetChars() + current_index_,
- length);
- }
+ Vector<const SrcChar> vector = string->GetCharVector<SrcChar>();
+ IncrementalStringBuilder::NoExtendBuilder<DestChar> no_extend(
+ &builder_, worst_case_length);
+ SerializeStringUnchecked_(vector, &no_extend);
} else {
- String* string_location = NULL;
- Vector<const Char> vector(NULL, 0);
- for (int i = 0; i < length; i++) {
- // If GC moved the string, we need to refresh the vector.
- if (*string != string_location) {
- DisallowHeapAllocation no_gc;
- // This does not actually prevent the string from being relocated later.
- vector = GetCharVector<Char>(string);
- string_location = *string;
- }
- Char c = vector[i];
+ FlatStringReader reader(isolate_, string);
+ for (int i = 0; i < reader.length(); i++) {
+ SrcChar c = reader.Get<SrcChar>(i);
if (DoNotEscape(c)) {
- Append_<is_one_byte, Char>(c);
+ builder_.Append<SrcChar, DestChar>(c);
} else {
- Append_<is_one_byte, uint8_t>(reinterpret_cast<const uint8_t*>(
- &JsonEscapeTable[c * kJsonEscapeTableEntrySize]));
+ builder_.AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]);
}
}
}
- Append_<is_one_byte, uint8_t>('"');
+ builder_.Append<uint8_t, DestChar>('"');
}
@@ -839,37 +663,20 @@
}
-template <>
-Vector<const uint8_t> BasicJsonStringifier::GetCharVector(
- Handle<String> string) {
- String::FlatContent flat = string->GetFlatContent();
- DCHECK(flat.IsOneByte());
- return flat.ToOneByteVector();
-}
-
-
-template <>
-Vector<const uc16> BasicJsonStringifier::GetCharVector(Handle<String> string) {
- String::FlatContent flat = string->GetFlatContent();
- DCHECK(flat.IsTwoByte());
- return flat.ToUC16Vector();
-}
-
-
void BasicJsonStringifier::SerializeString(Handle<String> object) {
object = String::Flatten(object);
- if (is_one_byte_) {
+ if (builder_.CurrentEncoding() == String::ONE_BYTE_ENCODING) {
if (object->IsOneByteRepresentationUnderneath()) {
- SerializeString_<true, uint8_t>(object);
+ SerializeString_<uint8_t, uint8_t>(object);
} else {
- ChangeEncoding();
+ builder_.ChangeEncoding();
SerializeString(object);
}
} else {
if (object->IsOneByteRepresentationUnderneath()) {
- SerializeString_<false, uint8_t>(object);
+ SerializeString_<uint8_t, uc16>(object);
} else {
- SerializeString_<false, uc16>(object);
+ SerializeString_<uc16, uc16>(object);
}
}
}