OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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_PARSER_H_ | 5 #ifndef V8_JSON_PARSER_H_ |
6 #define V8_JSON_PARSER_H_ | 6 #define V8_JSON_PARSER_H_ |
7 | 7 |
8 #include "src/v8.h" | 8 #include "src/v8.h" |
9 | 9 |
10 #include "src/char-predicates-inl.h" | 10 #include "src/char-predicates-inl.h" |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 inline Factory* factory() { return factory_; } | 175 inline Factory* factory() { return factory_; } |
176 inline Handle<JSFunction> object_constructor() { return object_constructor_; } | 176 inline Handle<JSFunction> object_constructor() { return object_constructor_; } |
177 | 177 |
178 static const int kInitialSpecialStringLength = 1024; | 178 static const int kInitialSpecialStringLength = 1024; |
179 static const int kPretenureTreshold = 100 * 1024; | 179 static const int kPretenureTreshold = 100 * 1024; |
180 | 180 |
181 | 181 |
182 private: | 182 private: |
183 Zone* zone() { return &zone_; } | 183 Zone* zone() { return &zone_; } |
184 | 184 |
| 185 void CommitStateToJsonObject(Handle<JSObject> json_object, Handle<Map> map, |
| 186 ZoneList<Handle<Object> >* properties); |
| 187 |
185 Handle<String> source_; | 188 Handle<String> source_; |
186 int source_length_; | 189 int source_length_; |
187 Handle<SeqOneByteString> seq_source_; | 190 Handle<SeqOneByteString> seq_source_; |
188 | 191 |
189 PretenureFlag pretenure_; | 192 PretenureFlag pretenure_; |
190 Isolate* isolate_; | 193 Isolate* isolate_; |
191 Factory* factory_; | 194 Factory* factory_; |
192 Zone zone_; | 195 Zone zone_; |
193 Handle<JSFunction> object_constructor_; | 196 Handle<JSFunction> object_constructor_; |
194 uc32 c0_; | 197 uc32 c0_; |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 descriptor)->NowContains(value)); | 406 descriptor)->NowContains(value)); |
404 properties.Add(value, zone()); | 407 properties.Add(value, zone()); |
405 map = target; | 408 map = target; |
406 continue; | 409 continue; |
407 } else { | 410 } else { |
408 transitioning = false; | 411 transitioning = false; |
409 } | 412 } |
410 } | 413 } |
411 | 414 |
412 // Commit the intermediate state to the object and stop transitioning. | 415 // Commit the intermediate state to the object and stop transitioning. |
413 JSObject::AllocateStorageForMap(json_object, map); | 416 CommitStateToJsonObject(json_object, map, &properties); |
414 int length = properties.length(); | |
415 for (int i = 0; i < length; i++) { | |
416 Handle<Object> value = properties[i]; | |
417 FieldIndex index = FieldIndex::ForPropertyIndex(*map, i); | |
418 json_object->FastPropertyAtPut(index, *value); | |
419 } | |
420 } else { | 417 } else { |
421 key = ParseJsonInternalizedString(); | 418 key = ParseJsonInternalizedString(); |
422 if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter(); | 419 if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter(); |
423 | 420 |
424 AdvanceSkipWhitespace(); | 421 AdvanceSkipWhitespace(); |
425 value = ParseJsonValue(); | 422 value = ParseJsonValue(); |
426 if (value.is_null()) return ReportUnexpectedCharacter(); | 423 if (value.is_null()) return ReportUnexpectedCharacter(); |
427 } | 424 } |
428 | 425 |
429 Runtime::DefineObjectProperty(json_object, key, value, NONE).Check(); | 426 Runtime::DefineObjectProperty(json_object, key, value, NONE).Check(); |
430 } while (MatchSkipWhiteSpace(',')); | 427 } while (MatchSkipWhiteSpace(',')); |
431 if (c0_ != '}') { | 428 if (c0_ != '}') { |
432 return ReportUnexpectedCharacter(); | 429 return ReportUnexpectedCharacter(); |
433 } | 430 } |
434 | 431 |
435 // If we transitioned until the very end, transition the map now. | 432 // If we transitioned until the very end, transition the map now. |
436 if (transitioning) { | 433 if (transitioning) { |
437 JSObject::AllocateStorageForMap(json_object, map); | 434 CommitStateToJsonObject(json_object, map, &properties); |
438 int length = properties.length(); | |
439 for (int i = 0; i < length; i++) { | |
440 Handle<Object> value = properties[i]; | |
441 FieldIndex index = FieldIndex::ForPropertyIndex(*map, i); | |
442 json_object->FastPropertyAtPut(index, *value); | |
443 } | |
444 } | 435 } |
445 } | 436 } |
446 AdvanceSkipWhitespace(); | 437 AdvanceSkipWhitespace(); |
447 return scope.CloseAndEscape(json_object); | 438 return scope.CloseAndEscape(json_object); |
448 } | 439 } |
449 | 440 |
| 441 |
| 442 template <bool seq_one_byte> |
| 443 void JsonParser<seq_one_byte>::CommitStateToJsonObject( |
| 444 Handle<JSObject> json_object, Handle<Map> map, |
| 445 ZoneList<Handle<Object> >* properties) { |
| 446 JSObject::AllocateStorageForMap(json_object, map); |
| 447 DCHECK(!json_object->map()->is_dictionary_map()); |
| 448 |
| 449 DisallowHeapAllocation no_gc; |
| 450 Factory* factory = isolate()->factory(); |
| 451 // If the |json_object|'s map is exactly the same as |map| then the |
| 452 // |properties| values correspond to the |map| and nothing more has to be |
| 453 // done. But if the |json_object|'s map is different then we have to |
| 454 // iterate descriptors to ensure that properties still correspond to the |
| 455 // map. |
| 456 bool slow_case = json_object->map() != *map; |
| 457 DescriptorArray* descriptors = NULL; |
| 458 |
| 459 int length = properties->length(); |
| 460 if (slow_case) { |
| 461 descriptors = json_object->map()->instance_descriptors(); |
| 462 DCHECK(json_object->map()->NumberOfOwnDescriptors() == length); |
| 463 } |
| 464 for (int i = 0; i < length; i++) { |
| 465 Handle<Object> value = (*properties)[i]; |
| 466 if (slow_case && value->IsMutableHeapNumber() && |
| 467 !descriptors->GetDetails(i).representation().IsDouble()) { |
| 468 // Turn mutable heap numbers into immutable if the field representation |
| 469 // is not double. |
| 470 HeapNumber::cast(*value)->set_map(*factory->heap_number_map()); |
| 471 } |
| 472 FieldIndex index = FieldIndex::ForPropertyIndex(*map, i); |
| 473 json_object->FastPropertyAtPut(index, *value); |
| 474 } |
| 475 } |
| 476 |
| 477 |
450 // Parse a JSON array. Position must be right at '['. | 478 // Parse a JSON array. Position must be right at '['. |
451 template <bool seq_one_byte> | 479 template <bool seq_one_byte> |
452 Handle<Object> JsonParser<seq_one_byte>::ParseJsonArray() { | 480 Handle<Object> JsonParser<seq_one_byte>::ParseJsonArray() { |
453 HandleScope scope(isolate()); | 481 HandleScope scope(isolate()); |
454 ZoneList<Handle<Object> > elements(4, zone()); | 482 ZoneList<Handle<Object> > elements(4, zone()); |
455 DCHECK_EQ(c0_, '['); | 483 DCHECK_EQ(c0_, '['); |
456 | 484 |
457 AdvanceSkipWhitespace(); | 485 AdvanceSkipWhitespace(); |
458 if (c0_ != ']') { | 486 if (c0_ != ']') { |
459 do { | 487 do { |
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
783 | 811 |
784 DCHECK_EQ('"', c0_); | 812 DCHECK_EQ('"', c0_); |
785 // Advance past the last '"'. | 813 // Advance past the last '"'. |
786 AdvanceSkipWhitespace(); | 814 AdvanceSkipWhitespace(); |
787 return result; | 815 return result; |
788 } | 816 } |
789 | 817 |
790 } } // namespace v8::internal | 818 } } // namespace v8::internal |
791 | 819 |
792 #endif // V8_JSON_PARSER_H_ | 820 #endif // V8_JSON_PARSER_H_ |
OLD | NEW |