| 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" |
| 11 #include "src/string-builder.h" |
| 11 #include "src/utils.h" | 12 #include "src/utils.h" |
| 12 | 13 |
| 13 namespace v8 { | 14 namespace v8 { |
| 14 namespace internal { | 15 namespace internal { |
| 15 | 16 |
| 16 class BasicJsonStringifier BASE_EMBEDDED { | 17 class BasicJsonStringifier BASE_EMBEDDED { |
| 17 public: | 18 public: |
| 18 explicit BasicJsonStringifier(Isolate* isolate); | 19 explicit BasicJsonStringifier(Isolate* isolate); |
| 19 | 20 |
| 20 MUST_USE_RESULT MaybeHandle<Object> Stringify(Handle<Object> object); | 21 MUST_USE_RESULT MaybeHandle<Object> Stringify(Handle<Object> object); |
| 21 | 22 |
| 22 MUST_USE_RESULT INLINE(static MaybeHandle<Object> StringifyString( | 23 MUST_USE_RESULT INLINE(static MaybeHandle<Object> StringifyString( |
| 23 Isolate* isolate, | 24 Isolate* isolate, |
| 24 Handle<String> object)); | 25 Handle<String> object)); |
| 25 | 26 |
| 26 private: | 27 private: |
| 27 static const int kInitialPartLength = 32; | |
| 28 static const int kMaxPartLength = 16 * 1024; | |
| 29 static const int kPartLengthGrowthFactor = 2; | |
| 30 | |
| 31 enum Result { UNCHANGED, SUCCESS, EXCEPTION }; | 28 enum Result { UNCHANGED, SUCCESS, EXCEPTION }; |
| 32 | 29 |
| 33 void Accumulate(); | |
| 34 | |
| 35 void Extend(); | |
| 36 | |
| 37 void ChangeEncoding(); | |
| 38 | |
| 39 INLINE(void ShrinkCurrentPart()); | |
| 40 | |
| 41 template <bool is_one_byte, typename Char> | |
| 42 INLINE(void Append_(Char c)); | |
| 43 | |
| 44 template <bool is_one_byte, typename Char> | |
| 45 INLINE(void Append_(const Char* chars)); | |
| 46 | |
| 47 INLINE(void Append(uint8_t c)) { | |
| 48 if (is_one_byte_) { | |
| 49 Append_<true>(c); | |
| 50 } else { | |
| 51 Append_<false>(c); | |
| 52 } | |
| 53 } | |
| 54 | |
| 55 INLINE(void AppendOneByte(const char* chars)) { | |
| 56 if (is_one_byte_) { | |
| 57 Append_<true>(reinterpret_cast<const uint8_t*>(chars)); | |
| 58 } else { | |
| 59 Append_<false>(reinterpret_cast<const uint8_t*>(chars)); | |
| 60 } | |
| 61 } | |
| 62 | |
| 63 MUST_USE_RESULT MaybeHandle<Object> ApplyToJsonFunction( | 30 MUST_USE_RESULT MaybeHandle<Object> ApplyToJsonFunction( |
| 64 Handle<Object> object, | 31 Handle<Object> object, |
| 65 Handle<Object> key); | 32 Handle<Object> key); |
| 66 | 33 |
| 67 Result SerializeGeneric(Handle<Object> object, | 34 Result SerializeGeneric(Handle<Object> object, |
| 68 Handle<Object> key, | 35 Handle<Object> key, |
| 69 bool deferred_comma, | 36 bool deferred_comma, |
| 70 bool deferred_key); | 37 bool deferred_key); |
| 71 | 38 |
| 72 template <typename ResultType, typename Char> | |
| 73 INLINE(static Handle<String> StringifyString_(Isolate* isolate, | |
| 74 Vector<Char> vector, | |
| 75 Handle<String> result)); | |
| 76 | |
| 77 // Entry point to serialize the object. | 39 // Entry point to serialize the object. |
| 78 INLINE(Result SerializeObject(Handle<Object> obj)) { | 40 INLINE(Result SerializeObject(Handle<Object> obj)) { |
| 79 return Serialize_<false>(obj, false, factory_->empty_string()); | 41 return Serialize_<false>(obj, false, factory()->empty_string()); |
| 80 } | 42 } |
| 81 | 43 |
| 82 // Serialize an array element. | 44 // Serialize an array element. |
| 83 // The index may serve as argument for the toJSON function. | 45 // The index may serve as argument for the toJSON function. |
| 84 INLINE(Result SerializeElement(Isolate* isolate, | 46 INLINE(Result SerializeElement(Isolate* isolate, |
| 85 Handle<Object> object, | 47 Handle<Object> object, |
| 86 int i)) { | 48 int i)) { |
| 87 return Serialize_<false>(object, | 49 return Serialize_<false>(object, |
| 88 false, | 50 false, |
| 89 Handle<Object>(Smi::FromInt(i), isolate)); | 51 Handle<Object>(Smi::FromInt(i), isolate)); |
| 90 } | 52 } |
| 91 | 53 |
| 92 // Serialize a object property. | 54 // Serialize a object property. |
| 93 // The key may or may not be serialized depending on the property. | 55 // The key may or may not be serialized depending on the property. |
| 94 // The key may also serve as argument for the toJSON function. | 56 // The key may also serve as argument for the toJSON function. |
| 95 INLINE(Result SerializeProperty(Handle<Object> object, | 57 INLINE(Result SerializeProperty(Handle<Object> object, |
| 96 bool deferred_comma, | 58 bool deferred_comma, |
| 97 Handle<String> deferred_key)) { | 59 Handle<String> deferred_key)) { |
| 98 DCHECK(!deferred_key.is_null()); | 60 DCHECK(!deferred_key.is_null()); |
| 99 return Serialize_<true>(object, deferred_comma, deferred_key); | 61 return Serialize_<true>(object, deferred_comma, deferred_key); |
| 100 } | 62 } |
| 101 | 63 |
| 102 template <bool deferred_string_key> | 64 template <bool deferred_string_key> |
| 103 Result Serialize_(Handle<Object> object, bool comma, Handle<Object> key); | 65 Result Serialize_(Handle<Object> object, bool comma, Handle<Object> key); |
| 104 | 66 |
| 105 void SerializeDeferredKey(bool deferred_comma, Handle<Object> deferred_key) { | 67 void SerializeDeferredKey(bool deferred_comma, Handle<Object> deferred_key) { |
| 106 if (deferred_comma) Append(','); | 68 if (deferred_comma) builder_.AppendCharacter(','); |
| 107 SerializeString(Handle<String>::cast(deferred_key)); | 69 SerializeString(Handle<String>::cast(deferred_key)); |
| 108 Append(':'); | 70 builder_.AppendCharacter(':'); |
| 109 } | 71 } |
| 110 | 72 |
| 111 Result SerializeSmi(Smi* object); | 73 Result SerializeSmi(Smi* object); |
| 112 | 74 |
| 113 Result SerializeDouble(double number); | 75 Result SerializeDouble(double number); |
| 114 INLINE(Result SerializeHeapNumber(Handle<HeapNumber> object)) { | 76 INLINE(Result SerializeHeapNumber(Handle<HeapNumber> object)) { |
| 115 return SerializeDouble(object->value()); | 77 return SerializeDouble(object->value()); |
| 116 } | 78 } |
| 117 | 79 |
| 118 Result SerializeJSValue(Handle<JSValue> object); | 80 Result SerializeJSValue(Handle<JSValue> object); |
| 119 | 81 |
| 120 INLINE(Result SerializeJSArray(Handle<JSArray> object)); | 82 INLINE(Result SerializeJSArray(Handle<JSArray> object)); |
| 121 INLINE(Result SerializeJSObject(Handle<JSObject> object)); | 83 INLINE(Result SerializeJSObject(Handle<JSObject> object)); |
| 122 | 84 |
| 123 Result SerializeJSArraySlow(Handle<JSArray> object, uint32_t length); | 85 Result SerializeJSArraySlow(Handle<JSArray> object, uint32_t length); |
| 124 | 86 |
| 125 void SerializeString(Handle<String> object); | 87 void SerializeString(Handle<String> object); |
| 126 | 88 |
| 127 template <typename SrcChar, typename DestChar> | 89 template <typename SrcChar, typename DestChar> |
| 128 INLINE(static int SerializeStringUnchecked_(const SrcChar* src, | 90 INLINE(static void SerializeStringUnchecked_( |
| 129 DestChar* dest, | 91 Vector<const SrcChar> src, |
| 130 int length)); | 92 IncrementalStringBuilder::NoExtend<DestChar>* dest)); |
| 131 | 93 |
| 132 template <bool is_one_byte, typename Char> | 94 template <typename SrcChar, typename DestChar> |
| 133 INLINE(void SerializeString_(Handle<String> string)); | 95 INLINE(void SerializeString_(Handle<String> string)); |
| 134 | 96 |
| 135 template <typename Char> | 97 template <typename Char> |
| 136 INLINE(static bool DoNotEscape(Char c)); | 98 INLINE(static bool DoNotEscape(Char c)); |
| 137 | 99 |
| 138 template <typename Char> | 100 template <typename Char> |
| 139 INLINE(static Vector<const Char> GetCharVector(Handle<String> string)); | 101 INLINE(static Vector<const Char> GetCharVector(Handle<String> string)); |
| 140 | 102 |
| 141 Result StackPush(Handle<Object> object); | 103 Result StackPush(Handle<Object> object); |
| 142 void StackPop(); | 104 void StackPop(); |
| 143 | 105 |
| 144 INLINE(Handle<String> accumulator()) { | 106 Factory* factory() { return isolate_->factory(); } |
| 145 return Handle<String>(String::cast(accumulator_store_->value()), isolate_); | |
| 146 } | |
| 147 | |
| 148 INLINE(void set_accumulator(Handle<String> string)) { | |
| 149 return accumulator_store_->set_value(*string); | |
| 150 } | |
| 151 | 107 |
| 152 Isolate* isolate_; | 108 Isolate* isolate_; |
| 153 Factory* factory_; | 109 IncrementalStringBuilder builder_; |
| 154 // We use a value wrapper for the string accumulator to keep the | |
| 155 // (indirect) handle to it in the outermost handle scope. | |
| 156 Handle<JSValue> accumulator_store_; | |
| 157 Handle<String> current_part_; | |
| 158 Handle<String> tojson_string_; | 110 Handle<String> tojson_string_; |
| 159 Handle<JSArray> stack_; | 111 Handle<JSArray> stack_; |
| 160 int current_index_; | |
| 161 int part_length_; | |
| 162 bool is_one_byte_; | |
| 163 bool overflowed_; | |
| 164 | 112 |
| 165 static const int kJsonEscapeTableEntrySize = 8; | 113 static const int kJsonEscapeTableEntrySize = 8; |
| 166 static const char* const JsonEscapeTable; | 114 static const char* const JsonEscapeTable; |
| 167 }; | 115 }; |
| 168 | 116 |
| 169 | 117 |
| 170 // Translation table to escape Latin1 characters. | 118 // Translation table to escape Latin1 characters. |
| 171 // Table entries start at a multiple of 8 and are null-terminated. | 119 // Table entries start at a multiple of 8 and are null-terminated. |
| 172 const char* const BasicJsonStringifier::JsonEscapeTable = | 120 const char* const BasicJsonStringifier::JsonEscapeTable = |
| 173 "\\u0000\0 \\u0001\0 \\u0002\0 \\u0003\0 " | 121 "\\u0000\0 \\u0001\0 \\u0002\0 \\u0003\0 " |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 "\344\0 \345\0 \346\0 \347\0 " | 178 "\344\0 \345\0 \346\0 \347\0 " |
| 231 "\350\0 \351\0 \352\0 \353\0 " | 179 "\350\0 \351\0 \352\0 \353\0 " |
| 232 "\354\0 \355\0 \356\0 \357\0 " | 180 "\354\0 \355\0 \356\0 \357\0 " |
| 233 "\360\0 \361\0 \362\0 \363\0 " | 181 "\360\0 \361\0 \362\0 \363\0 " |
| 234 "\364\0 \365\0 \366\0 \367\0 " | 182 "\364\0 \365\0 \366\0 \367\0 " |
| 235 "\370\0 \371\0 \372\0 \373\0 " | 183 "\370\0 \371\0 \372\0 \373\0 " |
| 236 "\374\0 \375\0 \376\0 \377\0 "; | 184 "\374\0 \375\0 \376\0 \377\0 "; |
| 237 | 185 |
| 238 | 186 |
| 239 BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate) | 187 BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate) |
| 240 : isolate_(isolate), | 188 : isolate_(isolate), builder_(isolate) { |
| 241 current_index_(0), | 189 tojson_string_ = factory()->toJSON_string(); |
| 242 is_one_byte_(true), | 190 stack_ = factory()->NewJSArray(8); |
| 243 overflowed_(false) { | |
| 244 factory_ = isolate_->factory(); | |
| 245 accumulator_store_ = Handle<JSValue>::cast( | |
| 246 Object::ToObject(isolate, factory_->empty_string()).ToHandleChecked()); | |
| 247 part_length_ = kInitialPartLength; | |
| 248 current_part_ = factory_->NewRawOneByteString(part_length_).ToHandleChecked(); | |
| 249 tojson_string_ = factory_->toJSON_string(); | |
| 250 stack_ = factory_->NewJSArray(8); | |
| 251 } | 191 } |
| 252 | 192 |
| 253 | 193 |
| 254 MaybeHandle<Object> BasicJsonStringifier::Stringify(Handle<Object> object) { | 194 MaybeHandle<Object> BasicJsonStringifier::Stringify(Handle<Object> object) { |
| 255 Result result = SerializeObject(object); | 195 Result result = SerializeObject(object); |
| 256 if (result == UNCHANGED) return isolate_->factory()->undefined_value(); | 196 if (result == UNCHANGED) return factory()->undefined_value(); |
| 257 if (result == SUCCESS) { | 197 if (result == SUCCESS) return builder_.Finish(); |
| 258 ShrinkCurrentPart(); | |
| 259 Accumulate(); | |
| 260 if (overflowed_) { | |
| 261 THROW_NEW_ERROR(isolate_, NewInvalidStringLengthError(), Object); | |
| 262 } | |
| 263 return accumulator(); | |
| 264 } | |
| 265 DCHECK(result == EXCEPTION); | 198 DCHECK(result == EXCEPTION); |
| 266 return MaybeHandle<Object>(); | 199 return MaybeHandle<Object>(); |
| 267 } | 200 } |
| 268 | 201 |
| 269 | 202 |
| 270 MaybeHandle<Object> BasicJsonStringifier::StringifyString( | 203 MaybeHandle<Object> BasicJsonStringifier::StringifyString( |
| 271 Isolate* isolate, Handle<String> object) { | 204 Isolate* isolate, Handle<String> object) { |
| 272 static const int kJsonQuoteWorstCaseBlowup = 6; | 205 static const int kJsonQuoteWorstCaseBlowup = 6; |
| 273 static const int kSpaceForQuotes = 2; | 206 static const int kSpaceForQuotes = 2; |
| 274 int worst_case_length = | 207 int worst_case_length = |
| 275 object->length() * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes; | 208 object->length() * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes; |
| 276 | 209 |
| 277 if (worst_case_length > 32 * KB) { // Slow path if too large. | 210 if (worst_case_length > 32 * KB) { // Slow path if too large. |
| 278 BasicJsonStringifier stringifier(isolate); | 211 BasicJsonStringifier stringifier(isolate); |
| 279 return stringifier.Stringify(object); | 212 return stringifier.Stringify(object); |
| 280 } | 213 } |
| 281 | 214 |
| 282 object = String::Flatten(object); | 215 object = String::Flatten(object); |
| 283 DCHECK(object->IsFlat()); | 216 DCHECK(object->IsFlat()); |
| 217 Handle<SeqString> result; |
| 284 if (object->IsOneByteRepresentationUnderneath()) { | 218 if (object->IsOneByteRepresentationUnderneath()) { |
| 285 Handle<String> result = isolate->factory()->NewRawOneByteString( | 219 result = isolate->factory() |
| 286 worst_case_length).ToHandleChecked(); | 220 ->NewRawOneByteString(worst_case_length) |
| 287 DisallowHeapAllocation no_gc; | 221 .ToHandleChecked(); |
| 288 return StringifyString_<SeqOneByteString>( | 222 IncrementalStringBuilder::NoExtendString<uint8_t> no_extend( |
| 289 isolate, | 223 result, worst_case_length); |
| 290 object->GetFlatContent().ToOneByteVector(), | 224 no_extend.Append('\"'); |
| 291 result); | 225 SerializeStringUnchecked_(object->GetFlatContent().ToOneByteVector(), |
| 226 &no_extend); |
| 227 no_extend.Append('\"'); |
| 292 } else { | 228 } else { |
| 293 Handle<String> result = isolate->factory()->NewRawTwoByteString( | 229 result = isolate->factory() |
| 294 worst_case_length).ToHandleChecked(); | 230 ->NewRawTwoByteString(worst_case_length) |
| 295 DisallowHeapAllocation no_gc; | 231 .ToHandleChecked(); |
| 296 return StringifyString_<SeqTwoByteString>( | 232 IncrementalStringBuilder::NoExtendString<uc16> no_extend(result, |
| 297 isolate, | 233 worst_case_length); |
| 298 object->GetFlatContent().ToUC16Vector(), | 234 no_extend.Append('\"'); |
| 299 result); | 235 SerializeStringUnchecked_(object->GetFlatContent().ToUC16Vector(), |
| 236 &no_extend); |
| 237 no_extend.Append('\"'); |
| 300 } | 238 } |
| 239 return result; |
| 301 } | 240 } |
| 302 | 241 |
| 303 | 242 |
| 304 template <typename ResultType, typename Char> | |
| 305 Handle<String> BasicJsonStringifier::StringifyString_(Isolate* isolate, | |
| 306 Vector<Char> vector, | |
| 307 Handle<String> result) { | |
| 308 DisallowHeapAllocation no_gc; | |
| 309 int final_size = 0; | |
| 310 ResultType* dest = ResultType::cast(*result); | |
| 311 dest->Set(final_size++, '\"'); | |
| 312 final_size += SerializeStringUnchecked_(vector.start(), | |
| 313 dest->GetChars() + 1, | |
| 314 vector.length()); | |
| 315 dest->Set(final_size++, '\"'); | |
| 316 return SeqString::Truncate(Handle<SeqString>::cast(result), final_size); | |
| 317 } | |
| 318 | |
| 319 | |
| 320 template <bool is_one_byte, typename Char> | |
| 321 void BasicJsonStringifier::Append_(Char c) { | |
| 322 if (is_one_byte) { | |
| 323 SeqOneByteString::cast(*current_part_)->SeqOneByteStringSet( | |
| 324 current_index_++, c); | |
| 325 } else { | |
| 326 SeqTwoByteString::cast(*current_part_)->SeqTwoByteStringSet( | |
| 327 current_index_++, c); | |
| 328 } | |
| 329 if (current_index_ == part_length_) Extend(); | |
| 330 } | |
| 331 | |
| 332 | |
| 333 template <bool is_one_byte, typename Char> | |
| 334 void BasicJsonStringifier::Append_(const Char* chars) { | |
| 335 for (; *chars != '\0'; chars++) Append_<is_one_byte, Char>(*chars); | |
| 336 } | |
| 337 | |
| 338 | |
| 339 MaybeHandle<Object> BasicJsonStringifier::ApplyToJsonFunction( | 243 MaybeHandle<Object> BasicJsonStringifier::ApplyToJsonFunction( |
| 340 Handle<Object> object, Handle<Object> key) { | 244 Handle<Object> object, Handle<Object> key) { |
| 341 LookupIterator it(object, tojson_string_, | 245 LookupIterator it(object, tojson_string_, |
| 342 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR); | 246 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR); |
| 343 Handle<Object> fun; | 247 Handle<Object> fun; |
| 344 ASSIGN_RETURN_ON_EXCEPTION(isolate_, fun, Object::GetProperty(&it), Object); | 248 ASSIGN_RETURN_ON_EXCEPTION(isolate_, fun, Object::GetProperty(&it), Object); |
| 345 if (!fun->IsJSFunction()) return object; | 249 if (!fun->IsJSFunction()) return object; |
| 346 | 250 |
| 347 // Call toJSON function. | 251 // Call toJSON function. |
| 348 if (key->IsSmi()) key = factory_->NumberToString(key); | 252 if (key->IsSmi()) key = factory()->NumberToString(key); |
| 349 Handle<Object> argv[] = { key }; | 253 Handle<Object> argv[] = { key }; |
| 350 HandleScope scope(isolate_); | 254 HandleScope scope(isolate_); |
| 351 ASSIGN_RETURN_ON_EXCEPTION( | 255 ASSIGN_RETURN_ON_EXCEPTION( |
| 352 isolate_, object, | 256 isolate_, object, |
| 353 Execution::Call(isolate_, fun, object, 1, argv), | 257 Execution::Call(isolate_, fun, object, 1, argv), |
| 354 Object); | 258 Object); |
| 355 return scope.CloseAndEscape(object); | 259 return scope.CloseAndEscape(object); |
| 356 } | 260 } |
| 357 | 261 |
| 358 | 262 |
| 359 BasicJsonStringifier::Result BasicJsonStringifier::StackPush( | 263 BasicJsonStringifier::Result BasicJsonStringifier::StackPush( |
| 360 Handle<Object> object) { | 264 Handle<Object> object) { |
| 361 StackLimitCheck check(isolate_); | 265 StackLimitCheck check(isolate_); |
| 362 if (check.HasOverflowed()) { | 266 if (check.HasOverflowed()) { |
| 363 isolate_->StackOverflow(); | 267 isolate_->StackOverflow(); |
| 364 return EXCEPTION; | 268 return EXCEPTION; |
| 365 } | 269 } |
| 366 | 270 |
| 367 int length = Smi::cast(stack_->length())->value(); | 271 int length = Smi::cast(stack_->length())->value(); |
| 368 { | 272 { |
| 369 DisallowHeapAllocation no_allocation; | 273 DisallowHeapAllocation no_allocation; |
| 370 FixedArray* elements = FixedArray::cast(stack_->elements()); | 274 FixedArray* elements = FixedArray::cast(stack_->elements()); |
| 371 for (int i = 0; i < length; i++) { | 275 for (int i = 0; i < length; i++) { |
| 372 if (elements->get(i) == *object) { | 276 if (elements->get(i) == *object) { |
| 373 AllowHeapAllocation allow_to_return_error; | 277 AllowHeapAllocation allow_to_return_error; |
| 374 Handle<Object> error; | 278 Handle<Object> error; |
| 375 MaybeHandle<Object> maybe_error = factory_->NewTypeError( | 279 MaybeHandle<Object> maybe_error = factory()->NewTypeError( |
| 376 "circular_structure", HandleVector<Object>(NULL, 0)); | 280 "circular_structure", HandleVector<Object>(NULL, 0)); |
| 377 if (maybe_error.ToHandle(&error)) isolate_->Throw(*error); | 281 if (maybe_error.ToHandle(&error)) isolate_->Throw(*error); |
| 378 return EXCEPTION; | 282 return EXCEPTION; |
| 379 } | 283 } |
| 380 } | 284 } |
| 381 } | 285 } |
| 382 JSArray::EnsureSize(stack_, length + 1); | 286 JSArray::EnsureSize(stack_, length + 1); |
| 383 FixedArray::cast(stack_->elements())->set(length, *object); | 287 FixedArray::cast(stack_->elements())->set(length, *object); |
| 384 stack_->set_length(Smi::FromInt(length + 1)); | 288 stack_->set_length(Smi::FromInt(length + 1)); |
| 385 return SUCCESS; | 289 return SUCCESS; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 409 | 313 |
| 410 switch (HeapObject::cast(*object)->map()->instance_type()) { | 314 switch (HeapObject::cast(*object)->map()->instance_type()) { |
| 411 case HEAP_NUMBER_TYPE: | 315 case HEAP_NUMBER_TYPE: |
| 412 case MUTABLE_HEAP_NUMBER_TYPE: | 316 case MUTABLE_HEAP_NUMBER_TYPE: |
| 413 if (deferred_string_key) SerializeDeferredKey(comma, key); | 317 if (deferred_string_key) SerializeDeferredKey(comma, key); |
| 414 return SerializeHeapNumber(Handle<HeapNumber>::cast(object)); | 318 return SerializeHeapNumber(Handle<HeapNumber>::cast(object)); |
| 415 case ODDBALL_TYPE: | 319 case ODDBALL_TYPE: |
| 416 switch (Oddball::cast(*object)->kind()) { | 320 switch (Oddball::cast(*object)->kind()) { |
| 417 case Oddball::kFalse: | 321 case Oddball::kFalse: |
| 418 if (deferred_string_key) SerializeDeferredKey(comma, key); | 322 if (deferred_string_key) SerializeDeferredKey(comma, key); |
| 419 AppendOneByte("false"); | 323 builder_.AppendCString("false"); |
| 420 return SUCCESS; | 324 return SUCCESS; |
| 421 case Oddball::kTrue: | 325 case Oddball::kTrue: |
| 422 if (deferred_string_key) SerializeDeferredKey(comma, key); | 326 if (deferred_string_key) SerializeDeferredKey(comma, key); |
| 423 AppendOneByte("true"); | 327 builder_.AppendCString("true"); |
| 424 return SUCCESS; | 328 return SUCCESS; |
| 425 case Oddball::kNull: | 329 case Oddball::kNull: |
| 426 if (deferred_string_key) SerializeDeferredKey(comma, key); | 330 if (deferred_string_key) SerializeDeferredKey(comma, key); |
| 427 AppendOneByte("null"); | 331 builder_.AppendCString("null"); |
| 428 return SUCCESS; | 332 return SUCCESS; |
| 429 default: | 333 default: |
| 430 return UNCHANGED; | 334 return UNCHANGED; |
| 431 } | 335 } |
| 432 case JS_ARRAY_TYPE: | 336 case JS_ARRAY_TYPE: |
| 433 if (object->IsAccessCheckNeeded()) break; | 337 if (object->IsAccessCheckNeeded()) break; |
| 434 if (deferred_string_key) SerializeDeferredKey(comma, key); | 338 if (deferred_string_key) SerializeDeferredKey(comma, key); |
| 435 return SerializeJSArray(Handle<JSArray>::cast(object)); | 339 return SerializeJSArray(Handle<JSArray>::cast(object)); |
| 436 case JS_VALUE_TYPE: | 340 case JS_VALUE_TYPE: |
| 437 if (deferred_string_key) SerializeDeferredKey(comma, key); | 341 if (deferred_string_key) SerializeDeferredKey(comma, key); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 465 isolate_, builtins, "JSONSerializeAdapter").ToHandleChecked()); | 369 isolate_, builtins, "JSONSerializeAdapter").ToHandleChecked()); |
| 466 | 370 |
| 467 Handle<Object> argv[] = { key, object }; | 371 Handle<Object> argv[] = { key, object }; |
| 468 Handle<Object> result; | 372 Handle<Object> result; |
| 469 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 373 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 470 isolate_, result, | 374 isolate_, result, |
| 471 Execution::Call(isolate_, builtin, object, 2, argv), | 375 Execution::Call(isolate_, builtin, object, 2, argv), |
| 472 EXCEPTION); | 376 EXCEPTION); |
| 473 if (result->IsUndefined()) return UNCHANGED; | 377 if (result->IsUndefined()) return UNCHANGED; |
| 474 if (deferred_key) { | 378 if (deferred_key) { |
| 475 if (key->IsSmi()) key = factory_->NumberToString(key); | 379 if (key->IsSmi()) key = factory()->NumberToString(key); |
| 476 SerializeDeferredKey(deferred_comma, key); | 380 SerializeDeferredKey(deferred_comma, key); |
| 477 } | 381 } |
| 478 | 382 |
| 479 Handle<String> result_string = Handle<String>::cast(result); | 383 builder_.AppendString(Handle<String>::cast(result)); |
| 480 // Shrink current part, attach it to the accumulator, also attach the result | |
| 481 // string to the accumulator, and allocate a new part. | |
| 482 ShrinkCurrentPart(); // Shrink. | |
| 483 part_length_ = kInitialPartLength; // Allocate conservatively. | |
| 484 Extend(); // Attach current part and allocate new part. | |
| 485 // Attach result string to the accumulator. | |
| 486 Handle<String> cons; | |
| 487 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | |
| 488 isolate_, cons, | |
| 489 factory_->NewConsString(accumulator(), result_string), | |
| 490 EXCEPTION); | |
| 491 set_accumulator(cons); | |
| 492 return SUCCESS; | 384 return SUCCESS; |
| 493 } | 385 } |
| 494 | 386 |
| 495 | 387 |
| 496 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSValue( | 388 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSValue( |
| 497 Handle<JSValue> object) { | 389 Handle<JSValue> object) { |
| 498 String* class_name = object->class_name(); | 390 String* class_name = object->class_name(); |
| 499 if (class_name == isolate_->heap()->String_string()) { | 391 if (class_name == isolate_->heap()->String_string()) { |
| 500 Handle<Object> value; | 392 Handle<Object> value; |
| 501 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 393 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 502 isolate_, value, Execution::ToString(isolate_, object), EXCEPTION); | 394 isolate_, value, Execution::ToString(isolate_, object), EXCEPTION); |
| 503 SerializeString(Handle<String>::cast(value)); | 395 SerializeString(Handle<String>::cast(value)); |
| 504 } else if (class_name == isolate_->heap()->Number_string()) { | 396 } else if (class_name == isolate_->heap()->Number_string()) { |
| 505 Handle<Object> value; | 397 Handle<Object> value; |
| 506 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 398 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 507 isolate_, value, Execution::ToNumber(isolate_, object), EXCEPTION); | 399 isolate_, value, Execution::ToNumber(isolate_, object), EXCEPTION); |
| 508 if (value->IsSmi()) return SerializeSmi(Smi::cast(*value)); | 400 if (value->IsSmi()) return SerializeSmi(Smi::cast(*value)); |
| 509 SerializeHeapNumber(Handle<HeapNumber>::cast(value)); | 401 SerializeHeapNumber(Handle<HeapNumber>::cast(value)); |
| 510 } else { | 402 } else { |
| 511 DCHECK(class_name == isolate_->heap()->Boolean_string()); | 403 DCHECK(class_name == isolate_->heap()->Boolean_string()); |
| 512 Object* value = JSValue::cast(*object)->value(); | 404 Object* value = JSValue::cast(*object)->value(); |
| 513 DCHECK(value->IsBoolean()); | 405 DCHECK(value->IsBoolean()); |
| 514 AppendOneByte(value->IsTrue() ? "true" : "false"); | 406 builder_.AppendCString(value->IsTrue() ? "true" : "false"); |
| 515 } | 407 } |
| 516 return SUCCESS; | 408 return SUCCESS; |
| 517 } | 409 } |
| 518 | 410 |
| 519 | 411 |
| 520 BasicJsonStringifier::Result BasicJsonStringifier::SerializeSmi(Smi* object) { | 412 BasicJsonStringifier::Result BasicJsonStringifier::SerializeSmi(Smi* object) { |
| 521 static const int kBufferSize = 100; | 413 static const int kBufferSize = 100; |
| 522 char chars[kBufferSize]; | 414 char chars[kBufferSize]; |
| 523 Vector<char> buffer(chars, kBufferSize); | 415 Vector<char> buffer(chars, kBufferSize); |
| 524 AppendOneByte(IntToCString(object->value(), buffer)); | 416 builder_.AppendCString(IntToCString(object->value(), buffer)); |
| 525 return SUCCESS; | 417 return SUCCESS; |
| 526 } | 418 } |
| 527 | 419 |
| 528 | 420 |
| 529 BasicJsonStringifier::Result BasicJsonStringifier::SerializeDouble( | 421 BasicJsonStringifier::Result BasicJsonStringifier::SerializeDouble( |
| 530 double number) { | 422 double number) { |
| 531 if (std::isinf(number) || std::isnan(number)) { | 423 if (std::isinf(number) || std::isnan(number)) { |
| 532 AppendOneByte("null"); | 424 builder_.AppendCString("null"); |
| 533 return SUCCESS; | 425 return SUCCESS; |
| 534 } | 426 } |
| 535 static const int kBufferSize = 100; | 427 static const int kBufferSize = 100; |
| 536 char chars[kBufferSize]; | 428 char chars[kBufferSize]; |
| 537 Vector<char> buffer(chars, kBufferSize); | 429 Vector<char> buffer(chars, kBufferSize); |
| 538 AppendOneByte(DoubleToCString(number, buffer)); | 430 builder_.AppendCString(DoubleToCString(number, buffer)); |
| 539 return SUCCESS; | 431 return SUCCESS; |
| 540 } | 432 } |
| 541 | 433 |
| 542 | 434 |
| 543 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray( | 435 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray( |
| 544 Handle<JSArray> object) { | 436 Handle<JSArray> object) { |
| 545 HandleScope handle_scope(isolate_); | 437 HandleScope handle_scope(isolate_); |
| 546 Result stack_push = StackPush(object); | 438 Result stack_push = StackPush(object); |
| 547 if (stack_push != SUCCESS) return stack_push; | 439 if (stack_push != SUCCESS) return stack_push; |
| 548 uint32_t length = 0; | 440 uint32_t length = 0; |
| 549 CHECK(object->length()->ToArrayIndex(&length)); | 441 CHECK(object->length()->ToArrayIndex(&length)); |
| 550 Append('['); | 442 builder_.AppendCharacter('['); |
| 551 switch (object->GetElementsKind()) { | 443 switch (object->GetElementsKind()) { |
| 552 case FAST_SMI_ELEMENTS: { | 444 case FAST_SMI_ELEMENTS: { |
| 553 Handle<FixedArray> elements( | 445 Handle<FixedArray> elements( |
| 554 FixedArray::cast(object->elements()), isolate_); | 446 FixedArray::cast(object->elements()), isolate_); |
| 555 for (uint32_t i = 0; i < length; i++) { | 447 for (uint32_t i = 0; i < length; i++) { |
| 556 if (i > 0) Append(','); | 448 if (i > 0) builder_.AppendCharacter(','); |
| 557 SerializeSmi(Smi::cast(elements->get(i))); | 449 SerializeSmi(Smi::cast(elements->get(i))); |
| 558 } | 450 } |
| 559 break; | 451 break; |
| 560 } | 452 } |
| 561 case FAST_DOUBLE_ELEMENTS: { | 453 case FAST_DOUBLE_ELEMENTS: { |
| 562 // Empty array is FixedArray but not FixedDoubleArray. | 454 // Empty array is FixedArray but not FixedDoubleArray. |
| 563 if (length == 0) break; | 455 if (length == 0) break; |
| 564 Handle<FixedDoubleArray> elements( | 456 Handle<FixedDoubleArray> elements( |
| 565 FixedDoubleArray::cast(object->elements()), isolate_); | 457 FixedDoubleArray::cast(object->elements()), isolate_); |
| 566 for (uint32_t i = 0; i < length; i++) { | 458 for (uint32_t i = 0; i < length; i++) { |
| 567 if (i > 0) Append(','); | 459 if (i > 0) builder_.AppendCharacter(','); |
| 568 SerializeDouble(elements->get_scalar(i)); | 460 SerializeDouble(elements->get_scalar(i)); |
| 569 } | 461 } |
| 570 break; | 462 break; |
| 571 } | 463 } |
| 572 case FAST_ELEMENTS: { | 464 case FAST_ELEMENTS: { |
| 573 Handle<FixedArray> elements( | 465 Handle<FixedArray> elements( |
| 574 FixedArray::cast(object->elements()), isolate_); | 466 FixedArray::cast(object->elements()), isolate_); |
| 575 for (uint32_t i = 0; i < length; i++) { | 467 for (uint32_t i = 0; i < length; i++) { |
| 576 if (i > 0) Append(','); | 468 if (i > 0) builder_.AppendCharacter(','); |
| 577 Result result = | 469 Result result = |
| 578 SerializeElement(isolate_, | 470 SerializeElement(isolate_, |
| 579 Handle<Object>(elements->get(i), isolate_), | 471 Handle<Object>(elements->get(i), isolate_), |
| 580 i); | 472 i); |
| 581 if (result == SUCCESS) continue; | 473 if (result == SUCCESS) continue; |
| 582 if (result == UNCHANGED) { | 474 if (result == UNCHANGED) { |
| 583 AppendOneByte("null"); | 475 builder_.AppendCString("null"); |
| 584 } else { | 476 } else { |
| 585 return result; | 477 return result; |
| 586 } | 478 } |
| 587 } | 479 } |
| 588 break; | 480 break; |
| 589 } | 481 } |
| 590 // TODO(yangguo): The FAST_HOLEY_* cases could be handled in a faster way. | 482 // 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 | 483 // They resemble the non-holey cases except that a prototype chain lookup |
| 592 // is necessary for holes. | 484 // is necessary for holes. |
| 593 default: { | 485 default: { |
| 594 Result result = SerializeJSArraySlow(object, length); | 486 Result result = SerializeJSArraySlow(object, length); |
| 595 if (result != SUCCESS) return result; | 487 if (result != SUCCESS) return result; |
| 596 break; | 488 break; |
| 597 } | 489 } |
| 598 } | 490 } |
| 599 Append(']'); | 491 builder_.AppendCharacter(']'); |
| 600 StackPop(); | 492 StackPop(); |
| 601 current_part_ = handle_scope.CloseAndEscape(current_part_); | |
| 602 return SUCCESS; | 493 return SUCCESS; |
| 603 } | 494 } |
| 604 | 495 |
| 605 | 496 |
| 606 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArraySlow( | 497 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArraySlow( |
| 607 Handle<JSArray> object, uint32_t length) { | 498 Handle<JSArray> object, uint32_t length) { |
| 608 for (uint32_t i = 0; i < length; i++) { | 499 for (uint32_t i = 0; i < length; i++) { |
| 609 if (i > 0) Append(','); | 500 if (i > 0) builder_.AppendCharacter(','); |
| 610 Handle<Object> element; | 501 Handle<Object> element; |
| 611 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 502 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 612 isolate_, element, | 503 isolate_, element, |
| 613 Object::GetElement(isolate_, object, i), | 504 Object::GetElement(isolate_, object, i), |
| 614 EXCEPTION); | 505 EXCEPTION); |
| 615 if (element->IsUndefined()) { | 506 if (element->IsUndefined()) { |
| 616 AppendOneByte("null"); | 507 builder_.AppendCString("null"); |
| 617 } else { | 508 } else { |
| 618 Result result = SerializeElement(isolate_, element, i); | 509 Result result = SerializeElement(isolate_, element, i); |
| 619 if (result == SUCCESS) continue; | 510 if (result == SUCCESS) continue; |
| 620 if (result == UNCHANGED) { | 511 if (result == UNCHANGED) { |
| 621 AppendOneByte("null"); | 512 builder_.AppendCString("null"); |
| 622 } else { | 513 } else { |
| 623 return result; | 514 return result; |
| 624 } | 515 } |
| 625 } | 516 } |
| 626 } | 517 } |
| 627 return SUCCESS; | 518 return SUCCESS; |
| 628 } | 519 } |
| 629 | 520 |
| 630 | 521 |
| 631 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject( | 522 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject( |
| 632 Handle<JSObject> object) { | 523 Handle<JSObject> object) { |
| 633 HandleScope handle_scope(isolate_); | 524 HandleScope handle_scope(isolate_); |
| 634 Result stack_push = StackPush(object); | 525 Result stack_push = StackPush(object); |
| 635 if (stack_push != SUCCESS) return stack_push; | 526 if (stack_push != SUCCESS) return stack_push; |
| 636 DCHECK(!object->IsJSGlobalProxy() && !object->IsGlobalObject()); | 527 DCHECK(!object->IsJSGlobalProxy() && !object->IsGlobalObject()); |
| 637 | 528 |
| 638 Append('{'); | 529 builder_.AppendCharacter('{'); |
| 639 bool comma = false; | 530 bool comma = false; |
| 640 | 531 |
| 641 if (object->HasFastProperties() && | 532 if (object->HasFastProperties() && |
| 642 !object->HasIndexedInterceptor() && | 533 !object->HasIndexedInterceptor() && |
| 643 !object->HasNamedInterceptor() && | 534 !object->HasNamedInterceptor() && |
| 644 object->elements()->length() == 0) { | 535 object->elements()->length() == 0) { |
| 645 Handle<Map> map(object->map()); | 536 Handle<Map> map(object->map()); |
| 646 for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) { | 537 for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) { |
| 647 Handle<Name> name(map->instance_descriptors()->GetKey(i), isolate_); | 538 Handle<Name> name(map->instance_descriptors()->GetKey(i), isolate_); |
| 648 // TODO(rossberg): Should this throw? | 539 // TODO(rossberg): Should this throw? |
| (...skipping 24 matching lines...) Expand all Loading... |
| 673 | 564 |
| 674 for (int i = 0; i < contents->length(); i++) { | 565 for (int i = 0; i < contents->length(); i++) { |
| 675 Object* key = contents->get(i); | 566 Object* key = contents->get(i); |
| 676 Handle<String> key_handle; | 567 Handle<String> key_handle; |
| 677 MaybeHandle<Object> maybe_property; | 568 MaybeHandle<Object> maybe_property; |
| 678 if (key->IsString()) { | 569 if (key->IsString()) { |
| 679 key_handle = Handle<String>(String::cast(key), isolate_); | 570 key_handle = Handle<String>(String::cast(key), isolate_); |
| 680 maybe_property = Object::GetPropertyOrElement(object, key_handle); | 571 maybe_property = Object::GetPropertyOrElement(object, key_handle); |
| 681 } else { | 572 } else { |
| 682 DCHECK(key->IsNumber()); | 573 DCHECK(key->IsNumber()); |
| 683 key_handle = factory_->NumberToString(Handle<Object>(key, isolate_)); | 574 key_handle = factory()->NumberToString(Handle<Object>(key, isolate_)); |
| 684 uint32_t index; | 575 uint32_t index; |
| 685 if (key->IsSmi()) { | 576 if (key->IsSmi()) { |
| 686 maybe_property = Object::GetElement( | 577 maybe_property = Object::GetElement( |
| 687 isolate_, object, Smi::cast(key)->value()); | 578 isolate_, object, Smi::cast(key)->value()); |
| 688 } else if (key_handle->AsArrayIndex(&index)) { | 579 } else if (key_handle->AsArrayIndex(&index)) { |
| 689 maybe_property = Object::GetElement(isolate_, object, index); | 580 maybe_property = Object::GetElement(isolate_, object, index); |
| 690 } else { | 581 } else { |
| 691 maybe_property = Object::GetPropertyOrElement(object, key_handle); | 582 maybe_property = Object::GetPropertyOrElement(object, key_handle); |
| 692 } | 583 } |
| 693 } | 584 } |
| 694 Handle<Object> property; | 585 Handle<Object> property; |
| 695 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 586 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 696 isolate_, property, maybe_property, EXCEPTION); | 587 isolate_, property, maybe_property, EXCEPTION); |
| 697 Result result = SerializeProperty(property, comma, key_handle); | 588 Result result = SerializeProperty(property, comma, key_handle); |
| 698 if (!comma && result == SUCCESS) comma = true; | 589 if (!comma && result == SUCCESS) comma = true; |
| 699 if (result == EXCEPTION) return result; | 590 if (result == EXCEPTION) return result; |
| 700 } | 591 } |
| 701 } | 592 } |
| 702 | 593 |
| 703 Append('}'); | 594 builder_.AppendCharacter('}'); |
| 704 StackPop(); | 595 StackPop(); |
| 705 current_part_ = handle_scope.CloseAndEscape(current_part_); | |
| 706 return SUCCESS; | 596 return SUCCESS; |
| 707 } | 597 } |
| 708 | 598 |
| 709 | 599 |
| 710 void BasicJsonStringifier::ShrinkCurrentPart() { | 600 template <typename SrcChar, typename DestChar> |
| 711 DCHECK(current_index_ < part_length_); | 601 void BasicJsonStringifier::SerializeStringUnchecked_( |
| 712 current_part_ = SeqString::Truncate(Handle<SeqString>::cast(current_part_), | 602 Vector<const SrcChar> src, |
| 713 current_index_); | 603 IncrementalStringBuilder::NoExtend<DestChar>* dest) { |
| 714 } | 604 // Assert that uc16 character is not truncated down to 8 bit. |
| 605 // The <uc16, char> version of this method must not be called. |
| 606 DCHECK(sizeof(DestChar) >= sizeof(SrcChar)); |
| 715 | 607 |
| 716 | 608 for (int i = 0; i < src.length(); i++) { |
| 717 void BasicJsonStringifier::Accumulate() { | 609 SrcChar c = src[i]; |
| 718 if (accumulator()->length() + current_part_->length() > String::kMaxLength) { | 610 if (DoNotEscape(c)) { |
| 719 // Screw it. Simply set the flag and carry on. Throw exception at the end. | 611 dest->Append(c); |
| 720 set_accumulator(factory_->empty_string()); | 612 } else { |
| 721 overflowed_ = true; | 613 dest->AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]); |
| 722 } else { | 614 } |
| 723 set_accumulator(factory_->NewConsString(accumulator(), | |
| 724 current_part_).ToHandleChecked()); | |
| 725 } | 615 } |
| 726 } | 616 } |
| 727 | 617 |
| 728 | 618 |
| 729 void BasicJsonStringifier::Extend() { | |
| 730 Accumulate(); | |
| 731 if (part_length_ <= kMaxPartLength / kPartLengthGrowthFactor) { | |
| 732 part_length_ *= kPartLengthGrowthFactor; | |
| 733 } | |
| 734 if (is_one_byte_) { | |
| 735 current_part_ = | |
| 736 factory_->NewRawOneByteString(part_length_).ToHandleChecked(); | |
| 737 } else { | |
| 738 current_part_ = | |
| 739 factory_->NewRawTwoByteString(part_length_).ToHandleChecked(); | |
| 740 } | |
| 741 DCHECK(!current_part_.is_null()); | |
| 742 current_index_ = 0; | |
| 743 } | |
| 744 | |
| 745 | |
| 746 void BasicJsonStringifier::ChangeEncoding() { | |
| 747 ShrinkCurrentPart(); | |
| 748 Accumulate(); | |
| 749 current_part_ = | |
| 750 factory_->NewRawTwoByteString(part_length_).ToHandleChecked(); | |
| 751 DCHECK(!current_part_.is_null()); | |
| 752 current_index_ = 0; | |
| 753 is_one_byte_ = false; | |
| 754 } | |
| 755 | |
| 756 | |
| 757 template <typename SrcChar, typename DestChar> | 619 template <typename SrcChar, typename DestChar> |
| 758 int BasicJsonStringifier::SerializeStringUnchecked_(const SrcChar* src, | |
| 759 DestChar* dest, | |
| 760 int length) { | |
| 761 DestChar* dest_start = dest; | |
| 762 | |
| 763 // Assert that uc16 character is not truncated down to 8 bit. | |
| 764 // The <uc16, char> version of this method must not be called. | |
| 765 DCHECK(sizeof(*dest) >= sizeof(*src)); | |
| 766 | |
| 767 for (int i = 0; i < length; i++) { | |
| 768 SrcChar c = src[i]; | |
| 769 if (DoNotEscape(c)) { | |
| 770 *(dest++) = static_cast<DestChar>(c); | |
| 771 } else { | |
| 772 const uint8_t* chars = reinterpret_cast<const uint8_t*>( | |
| 773 &JsonEscapeTable[c * kJsonEscapeTableEntrySize]); | |
| 774 while (*chars != '\0') *(dest++) = *(chars++); | |
| 775 } | |
| 776 } | |
| 777 | |
| 778 return static_cast<int>(dest - dest_start); | |
| 779 } | |
| 780 | |
| 781 | |
| 782 template <bool is_one_byte, typename Char> | |
| 783 void BasicJsonStringifier::SerializeString_(Handle<String> string) { | 620 void BasicJsonStringifier::SerializeString_(Handle<String> string) { |
| 784 int length = string->length(); | 621 int length = string->length(); |
| 785 Append_<is_one_byte, char>('"'); | 622 builder_.Append<uint8_t, DestChar>('"'); |
| 786 // We make a rough estimate to find out if the current string can be | 623 // 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 | 624 // 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 | 625 // an escaped character is 6. Shifting the remainin string length right by 3 |
| 789 // is a more pessimistic estimate, but faster to calculate. | 626 // is a more pessimistic estimate, but faster to calculate. |
| 790 | 627 int worst_case_length = length << 3; |
| 791 if (((part_length_ - current_index_) >> 3) > length) { | 628 if (builder_.CurrentPartCanFit(worst_case_length)) { |
| 792 DisallowHeapAllocation no_gc; | 629 DisallowHeapAllocation no_gc; |
| 793 Vector<const Char> vector = GetCharVector<Char>(string); | 630 Vector<const SrcChar> vector = GetCharVector<SrcChar>(string); |
| 794 if (is_one_byte) { | 631 IncrementalStringBuilder::NoExtendBuilder<DestChar> no_extend( |
| 795 current_index_ += SerializeStringUnchecked_( | 632 &builder_, worst_case_length); |
| 796 vector.start(), | 633 SerializeStringUnchecked_(vector, &no_extend); |
| 797 SeqOneByteString::cast(*current_part_)->GetChars() + current_index_, | |
| 798 length); | |
| 799 } else { | |
| 800 current_index_ += SerializeStringUnchecked_( | |
| 801 vector.start(), | |
| 802 SeqTwoByteString::cast(*current_part_)->GetChars() + current_index_, | |
| 803 length); | |
| 804 } | |
| 805 } else { | 634 } else { |
| 806 String* string_location = NULL; | 635 String* string_location = NULL; |
| 807 Vector<const Char> vector(NULL, 0); | 636 Vector<const SrcChar> vector(NULL, 0); |
| 808 for (int i = 0; i < length; i++) { | 637 for (int i = 0; i < length; i++) { |
| 809 // If GC moved the string, we need to refresh the vector. | 638 // If GC moved the string, we need to refresh the vector. |
| 810 if (*string != string_location) { | 639 if (*string != string_location) { |
| 811 DisallowHeapAllocation no_gc; | 640 DisallowHeapAllocation no_gc; |
| 812 // This does not actually prevent the string from being relocated later. | 641 // This does not actually prevent the string from being relocated later. |
| 813 vector = GetCharVector<Char>(string); | 642 vector = GetCharVector<SrcChar>(string); |
| 814 string_location = *string; | 643 string_location = *string; |
| 815 } | 644 } |
| 816 Char c = vector[i]; | 645 SrcChar c = vector[i]; |
| 817 if (DoNotEscape(c)) { | 646 if (DoNotEscape(c)) { |
| 818 Append_<is_one_byte, Char>(c); | 647 builder_.Append<SrcChar, DestChar>(c); |
| 819 } else { | 648 } else { |
| 820 Append_<is_one_byte, uint8_t>(reinterpret_cast<const uint8_t*>( | 649 builder_.AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]); |
| 821 &JsonEscapeTable[c * kJsonEscapeTableEntrySize])); | |
| 822 } | 650 } |
| 823 } | 651 } |
| 824 } | 652 } |
| 825 | 653 |
| 826 Append_<is_one_byte, uint8_t>('"'); | 654 builder_.Append<uint8_t, DestChar>('"'); |
| 827 } | 655 } |
| 828 | 656 |
| 829 | 657 |
| 830 template <> | 658 template <> |
| 831 bool BasicJsonStringifier::DoNotEscape(uint8_t c) { | 659 bool BasicJsonStringifier::DoNotEscape(uint8_t c) { |
| 832 return c >= '#' && c <= '~' && c != '\\'; | 660 return c >= '#' && c <= '~' && c != '\\'; |
| 833 } | 661 } |
| 834 | 662 |
| 835 | 663 |
| 836 template <> | 664 template <> |
| (...skipping 14 matching lines...) Expand all Loading... |
| 851 template <> | 679 template <> |
| 852 Vector<const uc16> BasicJsonStringifier::GetCharVector(Handle<String> string) { | 680 Vector<const uc16> BasicJsonStringifier::GetCharVector(Handle<String> string) { |
| 853 String::FlatContent flat = string->GetFlatContent(); | 681 String::FlatContent flat = string->GetFlatContent(); |
| 854 DCHECK(flat.IsTwoByte()); | 682 DCHECK(flat.IsTwoByte()); |
| 855 return flat.ToUC16Vector(); | 683 return flat.ToUC16Vector(); |
| 856 } | 684 } |
| 857 | 685 |
| 858 | 686 |
| 859 void BasicJsonStringifier::SerializeString(Handle<String> object) { | 687 void BasicJsonStringifier::SerializeString(Handle<String> object) { |
| 860 object = String::Flatten(object); | 688 object = String::Flatten(object); |
| 861 if (is_one_byte_) { | 689 if (builder_.CurrentEncoding() == String::ONE_BYTE_ENCODING) { |
| 862 if (object->IsOneByteRepresentationUnderneath()) { | 690 if (object->IsOneByteRepresentationUnderneath()) { |
| 863 SerializeString_<true, uint8_t>(object); | 691 SerializeString_<uint8_t, uint8_t>(object); |
| 864 } else { | 692 } else { |
| 865 ChangeEncoding(); | 693 builder_.ChangeEncoding(); |
| 866 SerializeString(object); | 694 SerializeString(object); |
| 867 } | 695 } |
| 868 } else { | 696 } else { |
| 869 if (object->IsOneByteRepresentationUnderneath()) { | 697 if (object->IsOneByteRepresentationUnderneath()) { |
| 870 SerializeString_<false, uint8_t>(object); | 698 SerializeString_<uint8_t, uc16>(object); |
| 871 } else { | 699 } else { |
| 872 SerializeString_<false, uc16>(object); | 700 SerializeString_<uc16, uc16>(object); |
| 873 } | 701 } |
| 874 } | 702 } |
| 875 } | 703 } |
| 876 | 704 |
| 877 } } // namespace v8::internal | 705 } } // namespace v8::internal |
| 878 | 706 |
| 879 #endif // V8_JSON_STRINGIFIER_H_ | 707 #endif // V8_JSON_STRINGIFIER_H_ |
| OLD | NEW |