Index: src/json-stringifier.h |
diff --git a/src/json-stringifier.h b/src/json-stringifier.h |
index 1b4ab9a0faa9f8a9e803c85575f994359dadc4da..728575bdb982a87524a451978da96492ece47410 100644 |
--- a/src/json-stringifier.h |
+++ b/src/json-stringifier.h |
@@ -48,7 +48,7 @@ class BasicJsonStringifier BASE_EMBEDDED { |
enum Result { UNCHANGED, SUCCESS, EXCEPTION, CIRCULAR, STACK_OVERFLOW }; |
- template <bool is_ascii> void Extend(); |
+ void Extend(); |
void ChangeEncoding(); |
@@ -82,9 +82,14 @@ class BasicJsonStringifier BASE_EMBEDDED { |
Handle<Object> ApplyToJsonFunction(Handle<Object> object, |
Handle<Object> key); |
+ Result SerializeGeneric(Handle<Object> object, |
+ Handle<Object> key, |
+ bool deferred_comma, |
+ bool deferred_key); |
+ |
// Entry point to serialize the object. |
INLINE(Result SerializeObject(Handle<Object> obj)) { |
- return Serialize_<false>(obj, false, isolate_->factory()->empty_string()); |
+ return Serialize_<false>(obj, false, factory_->empty_string()); |
} |
// Serialize an array element. |
@@ -147,7 +152,7 @@ class BasicJsonStringifier BASE_EMBEDDED { |
void StackPop(); |
INLINE(Handle<String> accumulator()) { |
- return Handle<String>(String::cast(accumulator_store_->value())); |
+ return Handle<String>(String::cast(accumulator_store_->value()), isolate_); |
} |
INLINE(void set_accumulator(Handle<String> string)) { |
@@ -155,6 +160,7 @@ class BasicJsonStringifier BASE_EMBEDDED { |
} |
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_; |
@@ -209,13 +215,13 @@ const char* const BasicJsonStringifier::JsonEscapeTable = |
BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate) |
: isolate_(isolate), current_index_(0), is_ascii_(true) { |
+ factory_ = isolate_->factory(); |
accumulator_store_ = Handle<JSValue>::cast( |
- isolate_->factory()->ToObject(isolate_->factory()->empty_string())); |
+ factory_->ToObject(factory_->empty_string())); |
part_length_ = kInitialPartLength; |
- current_part_ = |
- isolate_->factory()->NewRawAsciiString(kInitialPartLength); |
- tojson_symbol_ = isolate_->factory()->LookupAsciiSymbol("toJSON"); |
- stack_ = isolate_->factory()->NewJSArray(8); |
+ current_part_ = factory_->NewRawAsciiString(kInitialPartLength); |
+ tojson_symbol_ = factory_->LookupAsciiSymbol("toJSON"); |
+ stack_ = factory_->NewJSArray(8); |
} |
@@ -225,9 +231,9 @@ MaybeObject* BasicJsonStringifier::Stringify(Handle<Object> object) { |
return isolate_->heap()->undefined_value(); |
case SUCCESS: |
ShrinkCurrentPart(); |
- return *isolate_->factory()->NewConsString(accumulator(), current_part_); |
+ return *factory_->NewConsString(accumulator(), current_part_); |
case CIRCULAR: |
- return isolate_->Throw(*isolate_->factory()->NewTypeError( |
+ return isolate_->Throw(*factory_->NewTypeError( |
"circular_structure", HandleVector<Object>(NULL, 0))); |
case STACK_OVERFLOW: |
return isolate_->StackOverflow(); |
@@ -246,7 +252,7 @@ void BasicJsonStringifier::Append_(Char c) { |
SeqTwoByteString::cast(*current_part_)->SeqTwoByteStringSet( |
current_index_++, c); |
} |
- if (current_index_ == part_length_) Extend<is_ascii>(); |
+ if (current_index_ == part_length_) Extend(); |
} |
@@ -260,20 +266,20 @@ Handle<Object> BasicJsonStringifier::GetProperty(Handle<JSObject> object, |
Handle<String> key) { |
LookupResult lookup(isolate_); |
object->LocalLookupRealNamedProperty(*key, &lookup); |
- if (!lookup.IsProperty()) return isolate_->factory()->undefined_value(); |
+ if (!lookup.IsProperty()) return factory_->undefined_value(); |
switch (lookup.type()) { |
case NORMAL: { |
Object* value = lookup.holder()->GetNormalizedProperty(&lookup); |
ASSERT(!value->IsTheHole()); |
- return Handle<Object>(value); |
+ return Handle<Object>(value, isolate_); |
} |
case FIELD: { |
Object* value = lookup.holder()->FastPropertyAt(lookup.GetFieldIndex()); |
ASSERT(!value->IsTheHole()); |
- return Handle<Object>(value); |
+ return Handle<Object>(value, isolate_); |
} |
case CONSTANT_FUNCTION: |
- return Handle<Object>(lookup.GetConstantFunction()); |
+ return Handle<Object>(lookup.GetConstantFunction(), isolate_); |
default: { |
PropertyAttributes attr; |
return Object::GetProperty(object, object, &lookup, key, &attr); |
@@ -294,7 +300,7 @@ Handle<Object> BasicJsonStringifier::ApplyToJsonFunction( |
if (!fun->IsJSFunction()) return object; |
// Call toJSON function. |
- if (key->IsSmi()) key = isolate_->factory()->NumberToString(key); |
+ if (key->IsSmi()) key = factory_->NumberToString(key); |
Handle<Object> argv[] = { key }; |
bool has_exception = false; |
HandleScope scope(isolate_); |
@@ -338,47 +344,84 @@ BasicJsonStringifier::Result BasicJsonStringifier::Serialize_( |
if (object.is_null()) return EXCEPTION; |
} |
- if (object->IsJSObject()) { |
- if (object->IsJSFunction()) return UNCHANGED; |
+ if (object->IsSmi()) { |
if (deferred_string_key) SerializeDeferredKey(comma, key); |
- if (object->IsJSArray()) { |
- return SerializeJSArray(Handle<JSArray>::cast(object)); |
- } else if (object->IsJSValue()) { |
- return SerializeJSValue(Handle<JSValue>::cast(object)); |
- } else { |
- return SerializeJSObject(Handle<JSObject>::cast(object)); |
- } |
+ return SerializeSmi(Smi::cast(*object)); |
} |
- // Handle non-JSObject. |
- if (object->IsString()) { |
- if (deferred_string_key) SerializeDeferredKey(comma, key); |
- SerializeString(Handle<String>::cast(object)); |
- return SUCCESS; |
- } else if (object->IsSmi()) { |
- if (deferred_string_key) SerializeDeferredKey(comma, key); |
- return SerializeSmi(Smi::cast(*object)); |
- } else if (object->IsHeapNumber()) { |
- if (deferred_string_key) SerializeDeferredKey(comma, key); |
- return SerializeHeapNumber(Handle<HeapNumber>::cast(object)); |
- } else if (object->IsOddball()) { |
- switch (Oddball::cast(*object)->kind()) { |
- case Oddball::kFalse: |
- if (deferred_string_key) SerializeDeferredKey(comma, key); |
- Append("false"); |
- return SUCCESS; |
- case Oddball::kTrue: |
+ switch (HeapObject::cast(*object)->map()->instance_type()) { |
+ case HEAP_NUMBER_TYPE: |
+ if (deferred_string_key) SerializeDeferredKey(comma, key); |
+ return SerializeHeapNumber(Handle<HeapNumber>::cast(object)); |
+ case ODDBALL_TYPE: |
+ switch (Oddball::cast(*object)->kind()) { |
+ case Oddball::kFalse: |
+ if (deferred_string_key) SerializeDeferredKey(comma, key); |
+ Append("false"); |
+ return SUCCESS; |
+ case Oddball::kTrue: |
+ if (deferred_string_key) SerializeDeferredKey(comma, key); |
+ Append("true"); |
+ return SUCCESS; |
+ case Oddball::kNull: |
+ if (deferred_string_key) SerializeDeferredKey(comma, key); |
+ Append("null"); |
+ return SUCCESS; |
+ default: |
+ return UNCHANGED; |
+ } |
+ case JS_ARRAY_TYPE: |
+ if (deferred_string_key) SerializeDeferredKey(comma, key); |
+ return SerializeJSArray(Handle<JSArray>::cast(object)); |
+ case JS_VALUE_TYPE: |
+ if (deferred_string_key) SerializeDeferredKey(comma, key); |
+ return SerializeJSValue(Handle<JSValue>::cast(object)); |
+ case JS_FUNCTION_TYPE: |
+ return UNCHANGED; |
+ default: |
+ if (object->IsString()) { |
if (deferred_string_key) SerializeDeferredKey(comma, key); |
- Append("true"); |
+ SerializeString(Handle<String>::cast(object)); |
return SUCCESS; |
- case Oddball::kNull: |
+ } else if (object->IsJSObject()) { |
if (deferred_string_key) SerializeDeferredKey(comma, key); |
- Append("null"); |
- return SUCCESS; |
- } |
+ return SerializeJSObject(Handle<JSObject>::cast(object)); |
+ } else { |
+ return SerializeGeneric(object, key, comma, deferred_string_key); |
+ } |
} |
+} |
+ |
- return UNCHANGED; |
+BasicJsonStringifier::Result BasicJsonStringifier::SerializeGeneric( |
+ Handle<Object> object, |
+ Handle<Object> key, |
+ bool deferred_comma, |
+ bool deferred_key) { |
+ Handle<JSObject> builtins(isolate_->native_context()->builtins()); |
+ Handle<JSFunction> builtin = Handle<JSFunction>::cast( |
+ v8::internal::GetProperty(builtins, "JSONSerializeAdapter")); |
+ |
+ Handle<Object> argv[] = { key, object }; |
+ bool has_exception = false; |
+ Handle<Object> result = |
+ Execution::Call(builtin, object, 2, argv, &has_exception); |
+ if (has_exception) return EXCEPTION; |
+ if (result->IsUndefined()) return UNCHANGED; |
+ if (deferred_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. |
+ set_accumulator(factory_->NewConsString(accumulator(), result_string)); |
+ return SUCCESS; |
} |
@@ -437,7 +480,8 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray( |
Append('['); |
switch (object->GetElementsKind()) { |
case FAST_SMI_ELEMENTS: { |
- Handle<FixedArray> elements(FixedArray::cast(object->elements())); |
+ Handle<FixedArray> elements( |
+ FixedArray::cast(object->elements()), isolate_); |
for (int i = 0; i < length; i++) { |
if (i > 0) Append(','); |
SerializeSmi(Smi::cast(elements->get(i))); |
@@ -446,7 +490,7 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray( |
} |
case FAST_DOUBLE_ELEMENTS: { |
Handle<FixedDoubleArray> elements( |
- FixedDoubleArray::cast(object->elements())); |
+ FixedDoubleArray::cast(object->elements()), isolate_); |
for (int i = 0; i < length; i++) { |
if (i > 0) Append(','); |
SerializeDouble(elements->get_scalar(i)); |
@@ -454,10 +498,12 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray( |
break; |
} |
case FAST_ELEMENTS: { |
- Handle<FixedArray> elements(FixedArray::cast(object->elements())); |
+ Handle<FixedArray> elements( |
+ FixedArray::cast(object->elements()), isolate_); |
for (int i = 0; i < length; i++) { |
if (i > 0) Append(','); |
- Result result = SerializeElement(Handle<Object>(elements->get(i)), i); |
+ Result result = |
+ SerializeElement(Handle<Object>(elements->get(i), isolate_), i); |
if (result == SUCCESS) continue; |
if (result == UNCHANGED) { |
Append("null"); |
@@ -510,7 +556,8 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject( |
Result stack_push = StackPush(object); |
if (stack_push != SUCCESS) return stack_push; |
if (object->IsJSGlobalProxy()) { |
- object = Handle<JSObject>(JSObject::cast(object->GetPrototype())); |
+ object = Handle<JSObject>( |
+ JSObject::cast(object->GetPrototype()), isolate_); |
ASSERT(object->IsGlobalObject()); |
} |
bool has_exception = false; |
@@ -524,11 +571,11 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject( |
Handle<String> key_handle; |
Handle<Object> property; |
if (key->IsString()) { |
- key_handle = Handle<String>(String::cast(key)); |
+ key_handle = Handle<String>(String::cast(key), isolate_); |
property = GetProperty(object, key_handle); |
} else { |
ASSERT(key->IsNumber()); |
- key_handle = isolate_->factory()->NumberToString(Handle<Object>(key)); |
+ key_handle = factory_->NumberToString(Handle<Object>(key, isolate_)); |
uint32_t index; |
if (key->IsSmi()) { |
property = Object::GetElement(object, Smi::cast(key)->value()); |
@@ -553,7 +600,7 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject( |
void BasicJsonStringifier::ShrinkCurrentPart() { |
ASSERT(current_index_ < part_length_); |
if (current_index_ == 0) { |
- current_part_ = isolate_->factory()->empty_string(); |
+ current_part_ = factory_->empty_string(); |
return; |
} |
@@ -580,19 +627,15 @@ void BasicJsonStringifier::ShrinkCurrentPart() { |
} |
-template <bool is_ascii> |
void BasicJsonStringifier::Extend() { |
- set_accumulator( |
- isolate_->factory()->NewConsString(accumulator(), current_part_)); |
+ set_accumulator(factory_->NewConsString(accumulator(), current_part_)); |
if (part_length_ <= kMaxPartLength / kPartLengthGrowthFactor) { |
part_length_ *= kPartLengthGrowthFactor; |
} |
- if (is_ascii) { |
- current_part_ = |
- isolate_->factory()->NewRawAsciiString(part_length_); |
+ if (is_ascii_) { |
+ current_part_ = factory_->NewRawAsciiString(part_length_); |
} else { |
- current_part_ = |
- isolate_->factory()->NewRawTwoByteString(part_length_); |
+ current_part_ = factory_->NewRawTwoByteString(part_length_); |
} |
current_index_ = 0; |
} |
@@ -600,10 +643,8 @@ void BasicJsonStringifier::Extend() { |
void BasicJsonStringifier::ChangeEncoding() { |
ShrinkCurrentPart(); |
- set_accumulator( |
- isolate_->factory()->NewConsString(accumulator(), current_part_)); |
- current_part_ = |
- isolate_->factory()->NewRawTwoByteString(part_length_); |
+ set_accumulator(factory_->NewConsString(accumulator(), current_part_)); |
+ current_part_ = factory_->NewRawTwoByteString(part_length_); |
current_index_ = 0; |
is_ascii_ = false; |
} |