| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_JSON_STRINGIFIER_H_ | 5 #ifndef V8_JSON_STRINGIFIER_H_ |
| 6 #define V8_JSON_STRINGIFIER_H_ | 6 #define V8_JSON_STRINGIFIER_H_ |
| 7 | 7 |
| 8 #include "src/v8.h" | 8 #include "src/v8.h" |
| 9 | 9 |
| 10 #include "src/conversions.h" | 10 #include "src/conversions.h" |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 enum Result { UNCHANGED, SUCCESS, EXCEPTION }; | 31 enum Result { UNCHANGED, SUCCESS, EXCEPTION }; |
| 32 | 32 |
| 33 void Accumulate(); | 33 void Accumulate(); |
| 34 | 34 |
| 35 void Extend(); | 35 void Extend(); |
| 36 | 36 |
| 37 void ChangeEncoding(); | 37 void ChangeEncoding(); |
| 38 | 38 |
| 39 INLINE(void ShrinkCurrentPart()); | 39 INLINE(void ShrinkCurrentPart()); |
| 40 | 40 |
| 41 template <bool is_ascii, typename Char> | 41 template <bool is_one_byte, typename Char> |
| 42 INLINE(void Append_(Char c)); | 42 INLINE(void Append_(Char c)); |
| 43 | 43 |
| 44 template <bool is_ascii, typename Char> | 44 template <bool is_one_byte, typename Char> |
| 45 INLINE(void Append_(const Char* chars)); | 45 INLINE(void Append_(const Char* chars)); |
| 46 | 46 |
| 47 INLINE(void Append(uint8_t c)) { | 47 INLINE(void Append(uint8_t c)) { |
| 48 if (is_ascii_) { | 48 if (is_one_byte_) { |
| 49 Append_<true>(c); | 49 Append_<true>(c); |
| 50 } else { | 50 } else { |
| 51 Append_<false>(c); | 51 Append_<false>(c); |
| 52 } | 52 } |
| 53 } | 53 } |
| 54 | 54 |
| 55 INLINE(void AppendAscii(const char* chars)) { | 55 INLINE(void AppendOneByte(const char* chars)) { |
| 56 if (is_ascii_) { | 56 if (is_one_byte_) { |
| 57 Append_<true>(reinterpret_cast<const uint8_t*>(chars)); | 57 Append_<true>(reinterpret_cast<const uint8_t*>(chars)); |
| 58 } else { | 58 } else { |
| 59 Append_<false>(reinterpret_cast<const uint8_t*>(chars)); | 59 Append_<false>(reinterpret_cast<const uint8_t*>(chars)); |
| 60 } | 60 } |
| 61 } | 61 } |
| 62 | 62 |
| 63 MUST_USE_RESULT MaybeHandle<Object> ApplyToJsonFunction( | 63 MUST_USE_RESULT MaybeHandle<Object> ApplyToJsonFunction( |
| 64 Handle<Object> object, | 64 Handle<Object> object, |
| 65 Handle<Object> key); | 65 Handle<Object> key); |
| 66 | 66 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 | 122 |
| 123 Result SerializeJSArraySlow(Handle<JSArray> object, uint32_t length); | 123 Result SerializeJSArraySlow(Handle<JSArray> object, uint32_t length); |
| 124 | 124 |
| 125 void SerializeString(Handle<String> object); | 125 void SerializeString(Handle<String> object); |
| 126 | 126 |
| 127 template <typename SrcChar, typename DestChar> | 127 template <typename SrcChar, typename DestChar> |
| 128 INLINE(static int SerializeStringUnchecked_(const SrcChar* src, | 128 INLINE(static int SerializeStringUnchecked_(const SrcChar* src, |
| 129 DestChar* dest, | 129 DestChar* dest, |
| 130 int length)); | 130 int length)); |
| 131 | 131 |
| 132 template <bool is_ascii, typename Char> | 132 template <bool is_one_byte, typename Char> |
| 133 INLINE(void SerializeString_(Handle<String> string)); | 133 INLINE(void SerializeString_(Handle<String> string)); |
| 134 | 134 |
| 135 template <typename Char> | 135 template <typename Char> |
| 136 INLINE(static bool DoNotEscape(Char c)); | 136 INLINE(static bool DoNotEscape(Char c)); |
| 137 | 137 |
| 138 template <typename Char> | 138 template <typename Char> |
| 139 INLINE(static Vector<const Char> GetCharVector(Handle<String> string)); | 139 INLINE(static Vector<const Char> GetCharVector(Handle<String> string)); |
| 140 | 140 |
| 141 Result StackPush(Handle<Object> object); | 141 Result StackPush(Handle<Object> object); |
| 142 void StackPop(); | 142 void StackPop(); |
| 143 | 143 |
| 144 INLINE(Handle<String> accumulator()) { | 144 INLINE(Handle<String> accumulator()) { |
| 145 return Handle<String>(String::cast(accumulator_store_->value()), isolate_); | 145 return Handle<String>(String::cast(accumulator_store_->value()), isolate_); |
| 146 } | 146 } |
| 147 | 147 |
| 148 INLINE(void set_accumulator(Handle<String> string)) { | 148 INLINE(void set_accumulator(Handle<String> string)) { |
| 149 return accumulator_store_->set_value(*string); | 149 return accumulator_store_->set_value(*string); |
| 150 } | 150 } |
| 151 | 151 |
| 152 Isolate* isolate_; | 152 Isolate* isolate_; |
| 153 Factory* factory_; | 153 Factory* factory_; |
| 154 // We use a value wrapper for the string accumulator to keep the | 154 // We use a value wrapper for the string accumulator to keep the |
| 155 // (indirect) handle to it in the outermost handle scope. | 155 // (indirect) handle to it in the outermost handle scope. |
| 156 Handle<JSValue> accumulator_store_; | 156 Handle<JSValue> accumulator_store_; |
| 157 Handle<String> current_part_; | 157 Handle<String> current_part_; |
| 158 Handle<String> tojson_string_; | 158 Handle<String> tojson_string_; |
| 159 Handle<JSArray> stack_; | 159 Handle<JSArray> stack_; |
| 160 int current_index_; | 160 int current_index_; |
| 161 int part_length_; | 161 int part_length_; |
| 162 bool is_ascii_; | 162 bool is_one_byte_; |
| 163 bool overflowed_; | 163 bool overflowed_; |
| 164 | 164 |
| 165 static const int kJsonEscapeTableEntrySize = 8; | 165 static const int kJsonEscapeTableEntrySize = 8; |
| 166 static const char* const JsonEscapeTable; | 166 static const char* const JsonEscapeTable; |
| 167 }; | 167 }; |
| 168 | 168 |
| 169 | 169 |
| 170 // Translation table to escape ASCII characters. | 170 // Translation table to escape Latin1 characters. |
| 171 // Table entries start at a multiple of 8 and are null-terminated. | 171 // Table entries start at a multiple of 8 and are null-terminated. |
| 172 const char* const BasicJsonStringifier::JsonEscapeTable = | 172 const char* const BasicJsonStringifier::JsonEscapeTable = |
| 173 "\\u0000\0 \\u0001\0 \\u0002\0 \\u0003\0 " | 173 "\\u0000\0 \\u0001\0 \\u0002\0 \\u0003\0 " |
| 174 "\\u0004\0 \\u0005\0 \\u0006\0 \\u0007\0 " | 174 "\\u0004\0 \\u0005\0 \\u0006\0 \\u0007\0 " |
| 175 "\\b\0 \\t\0 \\n\0 \\u000b\0 " | 175 "\\b\0 \\t\0 \\n\0 \\u000b\0 " |
| 176 "\\f\0 \\r\0 \\u000e\0 \\u000f\0 " | 176 "\\f\0 \\r\0 \\u000e\0 \\u000f\0 " |
| 177 "\\u0010\0 \\u0011\0 \\u0012\0 \\u0013\0 " | 177 "\\u0010\0 \\u0011\0 \\u0012\0 \\u0013\0 " |
| 178 "\\u0014\0 \\u0015\0 \\u0016\0 \\u0017\0 " | 178 "\\u0014\0 \\u0015\0 \\u0016\0 \\u0017\0 " |
| 179 "\\u0018\0 \\u0019\0 \\u001a\0 \\u001b\0 " | 179 "\\u0018\0 \\u0019\0 \\u001a\0 \\u001b\0 " |
| 180 "\\u001c\0 \\u001d\0 \\u001e\0 \\u001f\0 " | 180 "\\u001c\0 \\u001d\0 \\u001e\0 \\u001f\0 " |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 232 "\354\0 \355\0 \356\0 \357\0 " | 232 "\354\0 \355\0 \356\0 \357\0 " |
| 233 "\360\0 \361\0 \362\0 \363\0 " | 233 "\360\0 \361\0 \362\0 \363\0 " |
| 234 "\364\0 \365\0 \366\0 \367\0 " | 234 "\364\0 \365\0 \366\0 \367\0 " |
| 235 "\370\0 \371\0 \372\0 \373\0 " | 235 "\370\0 \371\0 \372\0 \373\0 " |
| 236 "\374\0 \375\0 \376\0 \377\0 "; | 236 "\374\0 \375\0 \376\0 \377\0 "; |
| 237 | 237 |
| 238 | 238 |
| 239 BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate) | 239 BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate) |
| 240 : isolate_(isolate), | 240 : isolate_(isolate), |
| 241 current_index_(0), | 241 current_index_(0), |
| 242 is_ascii_(true), | 242 is_one_byte_(true), |
| 243 overflowed_(false) { | 243 overflowed_(false) { |
| 244 factory_ = isolate_->factory(); | 244 factory_ = isolate_->factory(); |
| 245 accumulator_store_ = Handle<JSValue>::cast( | 245 accumulator_store_ = Handle<JSValue>::cast( |
| 246 Object::ToObject(isolate, factory_->empty_string()).ToHandleChecked()); | 246 Object::ToObject(isolate, factory_->empty_string()).ToHandleChecked()); |
| 247 part_length_ = kInitialPartLength; | 247 part_length_ = kInitialPartLength; |
| 248 current_part_ = factory_->NewRawOneByteString(part_length_).ToHandleChecked(); | 248 current_part_ = factory_->NewRawOneByteString(part_length_).ToHandleChecked(); |
| 249 tojson_string_ = factory_->toJSON_string(); | 249 tojson_string_ = factory_->toJSON_string(); |
| 250 stack_ = factory_->NewJSArray(8); | 250 stack_ = factory_->NewJSArray(8); |
| 251 } | 251 } |
| 252 | 252 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 ResultType* dest = ResultType::cast(*result); | 310 ResultType* dest = ResultType::cast(*result); |
| 311 dest->Set(final_size++, '\"'); | 311 dest->Set(final_size++, '\"'); |
| 312 final_size += SerializeStringUnchecked_(vector.start(), | 312 final_size += SerializeStringUnchecked_(vector.start(), |
| 313 dest->GetChars() + 1, | 313 dest->GetChars() + 1, |
| 314 vector.length()); | 314 vector.length()); |
| 315 dest->Set(final_size++, '\"'); | 315 dest->Set(final_size++, '\"'); |
| 316 return SeqString::Truncate(Handle<SeqString>::cast(result), final_size); | 316 return SeqString::Truncate(Handle<SeqString>::cast(result), final_size); |
| 317 } | 317 } |
| 318 | 318 |
| 319 | 319 |
| 320 template <bool is_ascii, typename Char> | 320 template <bool is_one_byte, typename Char> |
| 321 void BasicJsonStringifier::Append_(Char c) { | 321 void BasicJsonStringifier::Append_(Char c) { |
| 322 if (is_ascii) { | 322 if (is_one_byte) { |
| 323 SeqOneByteString::cast(*current_part_)->SeqOneByteStringSet( | 323 SeqOneByteString::cast(*current_part_)->SeqOneByteStringSet( |
| 324 current_index_++, c); | 324 current_index_++, c); |
| 325 } else { | 325 } else { |
| 326 SeqTwoByteString::cast(*current_part_)->SeqTwoByteStringSet( | 326 SeqTwoByteString::cast(*current_part_)->SeqTwoByteStringSet( |
| 327 current_index_++, c); | 327 current_index_++, c); |
| 328 } | 328 } |
| 329 if (current_index_ == part_length_) Extend(); | 329 if (current_index_ == part_length_) Extend(); |
| 330 } | 330 } |
| 331 | 331 |
| 332 | 332 |
| 333 template <bool is_ascii, typename Char> | 333 template <bool is_one_byte, typename Char> |
| 334 void BasicJsonStringifier::Append_(const Char* chars) { | 334 void BasicJsonStringifier::Append_(const Char* chars) { |
| 335 for ( ; *chars != '\0'; chars++) Append_<is_ascii, Char>(*chars); | 335 for (; *chars != '\0'; chars++) Append_<is_one_byte, Char>(*chars); |
| 336 } | 336 } |
| 337 | 337 |
| 338 | 338 |
| 339 MaybeHandle<Object> BasicJsonStringifier::ApplyToJsonFunction( | 339 MaybeHandle<Object> BasicJsonStringifier::ApplyToJsonFunction( |
| 340 Handle<Object> object, Handle<Object> key) { | 340 Handle<Object> object, Handle<Object> key) { |
| 341 LookupIterator it(object, tojson_string_, | 341 LookupIterator it(object, tojson_string_, |
| 342 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR); | 342 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR); |
| 343 Handle<Object> fun; | 343 Handle<Object> fun; |
| 344 ASSIGN_RETURN_ON_EXCEPTION(isolate_, fun, Object::GetProperty(&it), Object); | 344 ASSIGN_RETURN_ON_EXCEPTION(isolate_, fun, Object::GetProperty(&it), Object); |
| 345 if (!fun->IsJSFunction()) return object; | 345 if (!fun->IsJSFunction()) return object; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 409 | 409 |
| 410 switch (HeapObject::cast(*object)->map()->instance_type()) { | 410 switch (HeapObject::cast(*object)->map()->instance_type()) { |
| 411 case HEAP_NUMBER_TYPE: | 411 case HEAP_NUMBER_TYPE: |
| 412 case MUTABLE_HEAP_NUMBER_TYPE: | 412 case MUTABLE_HEAP_NUMBER_TYPE: |
| 413 if (deferred_string_key) SerializeDeferredKey(comma, key); | 413 if (deferred_string_key) SerializeDeferredKey(comma, key); |
| 414 return SerializeHeapNumber(Handle<HeapNumber>::cast(object)); | 414 return SerializeHeapNumber(Handle<HeapNumber>::cast(object)); |
| 415 case ODDBALL_TYPE: | 415 case ODDBALL_TYPE: |
| 416 switch (Oddball::cast(*object)->kind()) { | 416 switch (Oddball::cast(*object)->kind()) { |
| 417 case Oddball::kFalse: | 417 case Oddball::kFalse: |
| 418 if (deferred_string_key) SerializeDeferredKey(comma, key); | 418 if (deferred_string_key) SerializeDeferredKey(comma, key); |
| 419 AppendAscii("false"); | 419 AppendOneByte("false"); |
| 420 return SUCCESS; | 420 return SUCCESS; |
| 421 case Oddball::kTrue: | 421 case Oddball::kTrue: |
| 422 if (deferred_string_key) SerializeDeferredKey(comma, key); | 422 if (deferred_string_key) SerializeDeferredKey(comma, key); |
| 423 AppendAscii("true"); | 423 AppendOneByte("true"); |
| 424 return SUCCESS; | 424 return SUCCESS; |
| 425 case Oddball::kNull: | 425 case Oddball::kNull: |
| 426 if (deferred_string_key) SerializeDeferredKey(comma, key); | 426 if (deferred_string_key) SerializeDeferredKey(comma, key); |
| 427 AppendAscii("null"); | 427 AppendOneByte("null"); |
| 428 return SUCCESS; | 428 return SUCCESS; |
| 429 default: | 429 default: |
| 430 return UNCHANGED; | 430 return UNCHANGED; |
| 431 } | 431 } |
| 432 case JS_ARRAY_TYPE: | 432 case JS_ARRAY_TYPE: |
| 433 if (object->IsAccessCheckNeeded()) break; | 433 if (object->IsAccessCheckNeeded()) break; |
| 434 if (deferred_string_key) SerializeDeferredKey(comma, key); | 434 if (deferred_string_key) SerializeDeferredKey(comma, key); |
| 435 return SerializeJSArray(Handle<JSArray>::cast(object)); | 435 return SerializeJSArray(Handle<JSArray>::cast(object)); |
| 436 case JS_VALUE_TYPE: | 436 case JS_VALUE_TYPE: |
| 437 if (deferred_string_key) SerializeDeferredKey(comma, key); | 437 if (deferred_string_key) SerializeDeferredKey(comma, key); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 504 } else if (class_name == isolate_->heap()->Number_string()) { | 504 } else if (class_name == isolate_->heap()->Number_string()) { |
| 505 Handle<Object> value; | 505 Handle<Object> value; |
| 506 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 506 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 507 isolate_, value, Execution::ToNumber(isolate_, object), EXCEPTION); | 507 isolate_, value, Execution::ToNumber(isolate_, object), EXCEPTION); |
| 508 if (value->IsSmi()) return SerializeSmi(Smi::cast(*value)); | 508 if (value->IsSmi()) return SerializeSmi(Smi::cast(*value)); |
| 509 SerializeHeapNumber(Handle<HeapNumber>::cast(value)); | 509 SerializeHeapNumber(Handle<HeapNumber>::cast(value)); |
| 510 } else { | 510 } else { |
| 511 DCHECK(class_name == isolate_->heap()->Boolean_string()); | 511 DCHECK(class_name == isolate_->heap()->Boolean_string()); |
| 512 Object* value = JSValue::cast(*object)->value(); | 512 Object* value = JSValue::cast(*object)->value(); |
| 513 DCHECK(value->IsBoolean()); | 513 DCHECK(value->IsBoolean()); |
| 514 AppendAscii(value->IsTrue() ? "true" : "false"); | 514 AppendOneByte(value->IsTrue() ? "true" : "false"); |
| 515 } | 515 } |
| 516 return SUCCESS; | 516 return SUCCESS; |
| 517 } | 517 } |
| 518 | 518 |
| 519 | 519 |
| 520 BasicJsonStringifier::Result BasicJsonStringifier::SerializeSmi(Smi* object) { | 520 BasicJsonStringifier::Result BasicJsonStringifier::SerializeSmi(Smi* object) { |
| 521 static const int kBufferSize = 100; | 521 static const int kBufferSize = 100; |
| 522 char chars[kBufferSize]; | 522 char chars[kBufferSize]; |
| 523 Vector<char> buffer(chars, kBufferSize); | 523 Vector<char> buffer(chars, kBufferSize); |
| 524 AppendAscii(IntToCString(object->value(), buffer)); | 524 AppendOneByte(IntToCString(object->value(), buffer)); |
| 525 return SUCCESS; | 525 return SUCCESS; |
| 526 } | 526 } |
| 527 | 527 |
| 528 | 528 |
| 529 BasicJsonStringifier::Result BasicJsonStringifier::SerializeDouble( | 529 BasicJsonStringifier::Result BasicJsonStringifier::SerializeDouble( |
| 530 double number) { | 530 double number) { |
| 531 if (std::isinf(number) || std::isnan(number)) { | 531 if (std::isinf(number) || std::isnan(number)) { |
| 532 AppendAscii("null"); | 532 AppendOneByte("null"); |
| 533 return SUCCESS; | 533 return SUCCESS; |
| 534 } | 534 } |
| 535 static const int kBufferSize = 100; | 535 static const int kBufferSize = 100; |
| 536 char chars[kBufferSize]; | 536 char chars[kBufferSize]; |
| 537 Vector<char> buffer(chars, kBufferSize); | 537 Vector<char> buffer(chars, kBufferSize); |
| 538 AppendAscii(DoubleToCString(number, buffer)); | 538 AppendOneByte(DoubleToCString(number, buffer)); |
| 539 return SUCCESS; | 539 return SUCCESS; |
| 540 } | 540 } |
| 541 | 541 |
| 542 | 542 |
| 543 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray( | 543 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray( |
| 544 Handle<JSArray> object) { | 544 Handle<JSArray> object) { |
| 545 HandleScope handle_scope(isolate_); | 545 HandleScope handle_scope(isolate_); |
| 546 Result stack_push = StackPush(object); | 546 Result stack_push = StackPush(object); |
| 547 if (stack_push != SUCCESS) return stack_push; | 547 if (stack_push != SUCCESS) return stack_push; |
| 548 uint32_t length = 0; | 548 uint32_t length = 0; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 573 Handle<FixedArray> elements( | 573 Handle<FixedArray> elements( |
| 574 FixedArray::cast(object->elements()), isolate_); | 574 FixedArray::cast(object->elements()), isolate_); |
| 575 for (uint32_t i = 0; i < length; i++) { | 575 for (uint32_t i = 0; i < length; i++) { |
| 576 if (i > 0) Append(','); | 576 if (i > 0) Append(','); |
| 577 Result result = | 577 Result result = |
| 578 SerializeElement(isolate_, | 578 SerializeElement(isolate_, |
| 579 Handle<Object>(elements->get(i), isolate_), | 579 Handle<Object>(elements->get(i), isolate_), |
| 580 i); | 580 i); |
| 581 if (result == SUCCESS) continue; | 581 if (result == SUCCESS) continue; |
| 582 if (result == UNCHANGED) { | 582 if (result == UNCHANGED) { |
| 583 AppendAscii("null"); | 583 AppendOneByte("null"); |
| 584 } else { | 584 } else { |
| 585 return result; | 585 return result; |
| 586 } | 586 } |
| 587 } | 587 } |
| 588 break; | 588 break; |
| 589 } | 589 } |
| 590 // TODO(yangguo): The FAST_HOLEY_* cases could be handled in a faster way. | 590 // TODO(yangguo): The FAST_HOLEY_* cases could be handled in a faster way. |
| 591 // They resemble the non-holey cases except that a prototype chain lookup | 591 // They resemble the non-holey cases except that a prototype chain lookup |
| 592 // is necessary for holes. | 592 // is necessary for holes. |
| 593 default: { | 593 default: { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 606 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArraySlow( | 606 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArraySlow( |
| 607 Handle<JSArray> object, uint32_t length) { | 607 Handle<JSArray> object, uint32_t length) { |
| 608 for (uint32_t i = 0; i < length; i++) { | 608 for (uint32_t i = 0; i < length; i++) { |
| 609 if (i > 0) Append(','); | 609 if (i > 0) Append(','); |
| 610 Handle<Object> element; | 610 Handle<Object> element; |
| 611 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 611 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 612 isolate_, element, | 612 isolate_, element, |
| 613 Object::GetElement(isolate_, object, i), | 613 Object::GetElement(isolate_, object, i), |
| 614 EXCEPTION); | 614 EXCEPTION); |
| 615 if (element->IsUndefined()) { | 615 if (element->IsUndefined()) { |
| 616 AppendAscii("null"); | 616 AppendOneByte("null"); |
| 617 } else { | 617 } else { |
| 618 Result result = SerializeElement(isolate_, element, i); | 618 Result result = SerializeElement(isolate_, element, i); |
| 619 if (result == SUCCESS) continue; | 619 if (result == SUCCESS) continue; |
| 620 if (result == UNCHANGED) { | 620 if (result == UNCHANGED) { |
| 621 AppendAscii("null"); | 621 AppendOneByte("null"); |
| 622 } else { | 622 } else { |
| 623 return result; | 623 return result; |
| 624 } | 624 } |
| 625 } | 625 } |
| 626 } | 626 } |
| 627 return SUCCESS; | 627 return SUCCESS; |
| 628 } | 628 } |
| 629 | 629 |
| 630 | 630 |
| 631 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject( | 631 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject( |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 724 current_part_).ToHandleChecked()); | 724 current_part_).ToHandleChecked()); |
| 725 } | 725 } |
| 726 } | 726 } |
| 727 | 727 |
| 728 | 728 |
| 729 void BasicJsonStringifier::Extend() { | 729 void BasicJsonStringifier::Extend() { |
| 730 Accumulate(); | 730 Accumulate(); |
| 731 if (part_length_ <= kMaxPartLength / kPartLengthGrowthFactor) { | 731 if (part_length_ <= kMaxPartLength / kPartLengthGrowthFactor) { |
| 732 part_length_ *= kPartLengthGrowthFactor; | 732 part_length_ *= kPartLengthGrowthFactor; |
| 733 } | 733 } |
| 734 if (is_ascii_) { | 734 if (is_one_byte_) { |
| 735 current_part_ = | 735 current_part_ = |
| 736 factory_->NewRawOneByteString(part_length_).ToHandleChecked(); | 736 factory_->NewRawOneByteString(part_length_).ToHandleChecked(); |
| 737 } else { | 737 } else { |
| 738 current_part_ = | 738 current_part_ = |
| 739 factory_->NewRawTwoByteString(part_length_).ToHandleChecked(); | 739 factory_->NewRawTwoByteString(part_length_).ToHandleChecked(); |
| 740 } | 740 } |
| 741 DCHECK(!current_part_.is_null()); | 741 DCHECK(!current_part_.is_null()); |
| 742 current_index_ = 0; | 742 current_index_ = 0; |
| 743 } | 743 } |
| 744 | 744 |
| 745 | 745 |
| 746 void BasicJsonStringifier::ChangeEncoding() { | 746 void BasicJsonStringifier::ChangeEncoding() { |
| 747 ShrinkCurrentPart(); | 747 ShrinkCurrentPart(); |
| 748 Accumulate(); | 748 Accumulate(); |
| 749 current_part_ = | 749 current_part_ = |
| 750 factory_->NewRawTwoByteString(part_length_).ToHandleChecked(); | 750 factory_->NewRawTwoByteString(part_length_).ToHandleChecked(); |
| 751 DCHECK(!current_part_.is_null()); | 751 DCHECK(!current_part_.is_null()); |
| 752 current_index_ = 0; | 752 current_index_ = 0; |
| 753 is_ascii_ = false; | 753 is_one_byte_ = false; |
| 754 } | 754 } |
| 755 | 755 |
| 756 | 756 |
| 757 template <typename SrcChar, typename DestChar> | 757 template <typename SrcChar, typename DestChar> |
| 758 int BasicJsonStringifier::SerializeStringUnchecked_(const SrcChar* src, | 758 int BasicJsonStringifier::SerializeStringUnchecked_(const SrcChar* src, |
| 759 DestChar* dest, | 759 DestChar* dest, |
| 760 int length) { | 760 int length) { |
| 761 DestChar* dest_start = dest; | 761 DestChar* dest_start = dest; |
| 762 | 762 |
| 763 // Assert that uc16 character is not truncated down to 8 bit. | 763 // Assert that uc16 character is not truncated down to 8 bit. |
| 764 // The <uc16, char> version of this method must not be called. | 764 // The <uc16, char> version of this method must not be called. |
| 765 DCHECK(sizeof(*dest) >= sizeof(*src)); | 765 DCHECK(sizeof(*dest) >= sizeof(*src)); |
| 766 | 766 |
| 767 for (int i = 0; i < length; i++) { | 767 for (int i = 0; i < length; i++) { |
| 768 SrcChar c = src[i]; | 768 SrcChar c = src[i]; |
| 769 if (DoNotEscape(c)) { | 769 if (DoNotEscape(c)) { |
| 770 *(dest++) = static_cast<DestChar>(c); | 770 *(dest++) = static_cast<DestChar>(c); |
| 771 } else { | 771 } else { |
| 772 const uint8_t* chars = reinterpret_cast<const uint8_t*>( | 772 const uint8_t* chars = reinterpret_cast<const uint8_t*>( |
| 773 &JsonEscapeTable[c * kJsonEscapeTableEntrySize]); | 773 &JsonEscapeTable[c * kJsonEscapeTableEntrySize]); |
| 774 while (*chars != '\0') *(dest++) = *(chars++); | 774 while (*chars != '\0') *(dest++) = *(chars++); |
| 775 } | 775 } |
| 776 } | 776 } |
| 777 | 777 |
| 778 return static_cast<int>(dest - dest_start); | 778 return static_cast<int>(dest - dest_start); |
| 779 } | 779 } |
| 780 | 780 |
| 781 | 781 |
| 782 template <bool is_ascii, typename Char> | 782 template <bool is_one_byte, typename Char> |
| 783 void BasicJsonStringifier::SerializeString_(Handle<String> string) { | 783 void BasicJsonStringifier::SerializeString_(Handle<String> string) { |
| 784 int length = string->length(); | 784 int length = string->length(); |
| 785 Append_<is_ascii, char>('"'); | 785 Append_<is_one_byte, char>('"'); |
| 786 // We make a rough estimate to find out if the current string can be | 786 // We make a rough estimate to find out if the current string can be |
| 787 // serialized without allocating a new string part. The worst case length of | 787 // serialized without allocating a new string part. The worst case length of |
| 788 // an escaped character is 6. Shifting the remainin string length right by 3 | 788 // an escaped character is 6. Shifting the remainin string length right by 3 |
| 789 // is a more pessimistic estimate, but faster to calculate. | 789 // is a more pessimistic estimate, but faster to calculate. |
| 790 | 790 |
| 791 if (((part_length_ - current_index_) >> 3) > length) { | 791 if (((part_length_ - current_index_) >> 3) > length) { |
| 792 DisallowHeapAllocation no_gc; | 792 DisallowHeapAllocation no_gc; |
| 793 Vector<const Char> vector = GetCharVector<Char>(string); | 793 Vector<const Char> vector = GetCharVector<Char>(string); |
| 794 if (is_ascii) { | 794 if (is_one_byte) { |
| 795 current_index_ += SerializeStringUnchecked_( | 795 current_index_ += SerializeStringUnchecked_( |
| 796 vector.start(), | 796 vector.start(), |
| 797 SeqOneByteString::cast(*current_part_)->GetChars() + current_index_, | 797 SeqOneByteString::cast(*current_part_)->GetChars() + current_index_, |
| 798 length); | 798 length); |
| 799 } else { | 799 } else { |
| 800 current_index_ += SerializeStringUnchecked_( | 800 current_index_ += SerializeStringUnchecked_( |
| 801 vector.start(), | 801 vector.start(), |
| 802 SeqTwoByteString::cast(*current_part_)->GetChars() + current_index_, | 802 SeqTwoByteString::cast(*current_part_)->GetChars() + current_index_, |
| 803 length); | 803 length); |
| 804 } | 804 } |
| 805 } else { | 805 } else { |
| 806 String* string_location = NULL; | 806 String* string_location = NULL; |
| 807 Vector<const Char> vector(NULL, 0); | 807 Vector<const Char> vector(NULL, 0); |
| 808 for (int i = 0; i < length; i++) { | 808 for (int i = 0; i < length; i++) { |
| 809 // If GC moved the string, we need to refresh the vector. | 809 // If GC moved the string, we need to refresh the vector. |
| 810 if (*string != string_location) { | 810 if (*string != string_location) { |
| 811 DisallowHeapAllocation no_gc; | 811 DisallowHeapAllocation no_gc; |
| 812 // This does not actually prevent the string from being relocated later. | 812 // This does not actually prevent the string from being relocated later. |
| 813 vector = GetCharVector<Char>(string); | 813 vector = GetCharVector<Char>(string); |
| 814 string_location = *string; | 814 string_location = *string; |
| 815 } | 815 } |
| 816 Char c = vector[i]; | 816 Char c = vector[i]; |
| 817 if (DoNotEscape(c)) { | 817 if (DoNotEscape(c)) { |
| 818 Append_<is_ascii, Char>(c); | 818 Append_<is_one_byte, Char>(c); |
| 819 } else { | 819 } else { |
| 820 Append_<is_ascii, uint8_t>(reinterpret_cast<const uint8_t*>( | 820 Append_<is_one_byte, uint8_t>(reinterpret_cast<const uint8_t*>( |
| 821 &JsonEscapeTable[c * kJsonEscapeTableEntrySize])); | 821 &JsonEscapeTable[c * kJsonEscapeTableEntrySize])); |
| 822 } | 822 } |
| 823 } | 823 } |
| 824 } | 824 } |
| 825 | 825 |
| 826 Append_<is_ascii, uint8_t>('"'); | 826 Append_<is_one_byte, uint8_t>('"'); |
| 827 } | 827 } |
| 828 | 828 |
| 829 | 829 |
| 830 template <> | 830 template <> |
| 831 bool BasicJsonStringifier::DoNotEscape(uint8_t c) { | 831 bool BasicJsonStringifier::DoNotEscape(uint8_t c) { |
| 832 return c >= '#' && c <= '~' && c != '\\'; | 832 return c >= '#' && c <= '~' && c != '\\'; |
| 833 } | 833 } |
| 834 | 834 |
| 835 | 835 |
| 836 template <> | 836 template <> |
| 837 bool BasicJsonStringifier::DoNotEscape(uint16_t c) { | 837 bool BasicJsonStringifier::DoNotEscape(uint16_t c) { |
| 838 return c >= '#' && c != '\\' && c != 0x7f; | 838 return c >= '#' && c != '\\' && c != 0x7f; |
| 839 } | 839 } |
| 840 | 840 |
| 841 | 841 |
| 842 template <> | 842 template <> |
| 843 Vector<const uint8_t> BasicJsonStringifier::GetCharVector( | 843 Vector<const uint8_t> BasicJsonStringifier::GetCharVector( |
| 844 Handle<String> string) { | 844 Handle<String> string) { |
| 845 String::FlatContent flat = string->GetFlatContent(); | 845 String::FlatContent flat = string->GetFlatContent(); |
| 846 DCHECK(flat.IsAscii()); | 846 DCHECK(flat.IsOneByte()); |
| 847 return flat.ToOneByteVector(); | 847 return flat.ToOneByteVector(); |
| 848 } | 848 } |
| 849 | 849 |
| 850 | 850 |
| 851 template <> | 851 template <> |
| 852 Vector<const uc16> BasicJsonStringifier::GetCharVector(Handle<String> string) { | 852 Vector<const uc16> BasicJsonStringifier::GetCharVector(Handle<String> string) { |
| 853 String::FlatContent flat = string->GetFlatContent(); | 853 String::FlatContent flat = string->GetFlatContent(); |
| 854 DCHECK(flat.IsTwoByte()); | 854 DCHECK(flat.IsTwoByte()); |
| 855 return flat.ToUC16Vector(); | 855 return flat.ToUC16Vector(); |
| 856 } | 856 } |
| 857 | 857 |
| 858 | 858 |
| 859 void BasicJsonStringifier::SerializeString(Handle<String> object) { | 859 void BasicJsonStringifier::SerializeString(Handle<String> object) { |
| 860 object = String::Flatten(object); | 860 object = String::Flatten(object); |
| 861 if (is_ascii_) { | 861 if (is_one_byte_) { |
| 862 if (object->IsOneByteRepresentationUnderneath()) { | 862 if (object->IsOneByteRepresentationUnderneath()) { |
| 863 SerializeString_<true, uint8_t>(object); | 863 SerializeString_<true, uint8_t>(object); |
| 864 } else { | 864 } else { |
| 865 ChangeEncoding(); | 865 ChangeEncoding(); |
| 866 SerializeString(object); | 866 SerializeString(object); |
| 867 } | 867 } |
| 868 } else { | 868 } else { |
| 869 if (object->IsOneByteRepresentationUnderneath()) { | 869 if (object->IsOneByteRepresentationUnderneath()) { |
| 870 SerializeString_<false, uint8_t>(object); | 870 SerializeString_<false, uint8_t>(object); |
| 871 } else { | 871 } else { |
| 872 SerializeString_<false, uc16>(object); | 872 SerializeString_<false, uc16>(object); |
| 873 } | 873 } |
| 874 } | 874 } |
| 875 } | 875 } |
| 876 | 876 |
| 877 } } // namespace v8::internal | 877 } } // namespace v8::internal |
| 878 | 878 |
| 879 #endif // V8_JSON_STRINGIFIER_H_ | 879 #endif // V8_JSON_STRINGIFIER_H_ |
| OLD | NEW |