28 #ifndef V8_JSON_PARSER_H_
29 #define V8_JSON_PARSER_H_
43 template <
bool seq_ascii>
47 return JsonParser(source).ParseJson();
50 static const int kEndOfString = -1;
55 source_length_(source->length()),
56 isolate_(source->
map()->GetHeap()->isolate()),
57 factory_(isolate_->factory()),
59 object_constructor_(isolate_->native_context()->object_function(),
74 inline void Advance() {
76 if (position_ >= source_length_) {
78 }
else if (seq_ascii) {
79 c0_ = seq_source_->SeqOneByteStringGet(position_);
81 c0_ = source_->Get(position_);
89 inline void AdvanceSkipWhitespace() {
92 }
while (c0_ ==
' ' || c0_ ==
'\t' || c0_ ==
'\n' || c0_ ==
'\r');
95 inline void SkipWhitespace() {
96 while (c0_ ==
' ' || c0_ ==
'\t' || c0_ ==
'\n' || c0_ ==
'\r') {
101 inline uc32 AdvanceGetChar() {
108 inline bool MatchSkipWhiteSpace(
uc32 c) {
110 AdvanceSkipWhitespace();
120 Handle<String> ParseJsonString() {
121 return ScanJsonString<false>();
124 bool ParseJsonString(Handle<String> expected) {
125 int length = expected->length();
126 if (source_->length() - position_ - 1 > length) {
128 String::FlatContent content = expected->GetFlatContent();
129 if (content.IsAscii()) {
131 const uint8_t* input_chars = seq_source_->GetChars() + position_ + 1;
132 const uint8_t* expected_chars = content.ToOneByteVector().start();
133 for (
int i = 0; i < length; i++) {
134 uint8_t c0 = input_chars[i];
135 if (c0 != expected_chars[i] ||
136 c0 ==
'"' || c0 < 0x20 || c0 ==
'\\') {
140 if (input_chars[length] ==
'"') {
141 position_ = position_ + length + 1;
142 AdvanceSkipWhitespace();
150 Handle<String> ParseJsonInternalizedString() {
151 return ScanJsonString<true>();
154 template <
bool is_
internalized>
155 Handle<String> ScanJsonString();
159 template <
typename StringType,
typename SinkChar>
160 Handle<String> SlowScanJsonString(Handle<String> prefix,
int start,
int end);
168 Handle<Object> ParseJsonNumber();
173 Handle<Object> ParseJsonValue();
181 Handle<Object> ParseJsonObject();
188 Handle<Object> ParseJsonArray();
193 inline Handle<Object> ReportUnexpectedCharacter() {
197 inline Isolate* isolate() {
return isolate_; }
198 inline Factory* factory() {
return factory_; }
199 inline Handle<JSFunction> object_constructor() {
return object_constructor_; }
201 static const int kInitialSpecialStringLength = 1024;
202 static const int kPretenureTreshold = 100 * 1024;
206 Zone* zone() {
return &zone_; }
208 Handle<String> source_;
210 Handle<SeqOneByteString> seq_source_;
216 Handle<JSFunction> object_constructor_;
221 template <
bool seq_ascii>
222 Handle<Object> JsonParser<seq_ascii>::ParseJson() {
224 AdvanceSkipWhitespace();
225 Handle<Object> result = ParseJsonValue();
226 if (result.is_null() || c0_ != kEndOfString) {
228 if (isolate_->has_pending_exception())
return Handle<Object>::null();
232 Factory* factory = this->factory();
233 Handle<JSArray> array;
237 message =
"unexpected_eos";
238 array = factory->NewJSArray(0);
251 message =
"unexpected_token_number";
252 array = factory->NewJSArray(0);
255 message =
"unexpected_token_string";
256 array = factory->NewJSArray(0);
259 message =
"unexpected_token";
260 Handle<Object>
name =
262 Handle<FixedArray> element = factory->NewFixedArray(1);
263 element->set(0, *name);
264 array = factory->NewJSArrayWithElements(element);
268 MessageLocation location(factory->NewScript(source_),
271 Handle<Object> result = factory->NewSyntaxError(message, array);
272 isolate()->Throw(*result, &location);
280 template <
bool seq_ascii>
281 Handle<Object> JsonParser<seq_ascii>::ParseJsonValue() {
282 StackLimitCheck stack_check(isolate_);
283 if (stack_check.HasOverflowed()) {
284 isolate_->StackOverflow();
288 if (c0_ ==
'"')
return ParseJsonString();
289 if ((c0_ >=
'0' && c0_ <=
'9') || c0_ ==
'-')
return ParseJsonNumber();
290 if (c0_ ==
'{')
return ParseJsonObject();
291 if (c0_ ==
'[')
return ParseJsonArray();
293 if (AdvanceGetChar() ==
'a' && AdvanceGetChar() ==
'l' &&
294 AdvanceGetChar() ==
's' && AdvanceGetChar() ==
'e') {
295 AdvanceSkipWhitespace();
296 return factory()->false_value();
298 return ReportUnexpectedCharacter();
301 if (AdvanceGetChar() ==
'r' && AdvanceGetChar() ==
'u' &&
302 AdvanceGetChar() ==
'e') {
303 AdvanceSkipWhitespace();
304 return factory()->true_value();
306 return ReportUnexpectedCharacter();
309 if (AdvanceGetChar() ==
'u' && AdvanceGetChar() ==
'l' &&
310 AdvanceGetChar() ==
'l') {
311 AdvanceSkipWhitespace();
312 return factory()->null_value();
314 return ReportUnexpectedCharacter();
316 return ReportUnexpectedCharacter();
321 template <
bool seq_ascii>
322 Handle<Object> JsonParser<seq_ascii>::ParseJsonObject() {
323 HandleScope scope(isolate());
324 Handle<JSObject> json_object =
325 factory()->NewJSObject(object_constructor(), pretenure_);
326 Handle<Map>
map(json_object->map());
327 ZoneList<Handle<Object> > properties(8, zone());
330 bool transitioning =
true;
332 AdvanceSkipWhitespace();
335 if (c0_ !=
'"')
return ReportUnexpectedCharacter();
337 int start_position = position_;
341 if (c0_ >=
'0' && c0_ <=
'9') {
349 if (index > 429496729
U - ((d > 5) ? 1 : 0))
break;
350 index = (index * 10) + d;
352 }
while (c0_ >=
'0' && c0_ <=
'9');
357 AdvanceSkipWhitespace();
359 if (c0_ !=
':')
return ReportUnexpectedCharacter();
360 AdvanceSkipWhitespace();
361 Handle<Object> value = ParseJsonValue();
362 if (value.is_null())
return ReportUnexpectedCharacter();
370 position_ = start_position;
376 Handle<Object> value;
383 bool follow_expected =
false;
387 follow_expected = !key.is_null() && ParseJsonString(key);
390 if (follow_expected) {
395 key = ParseJsonInternalizedString();
396 if (key.is_null())
return ReportUnexpectedCharacter();
400 transitioning = !target.is_null();
402 if (c0_ !=
':')
return ReportUnexpectedCharacter();
404 AdvanceSkipWhitespace();
405 value = ParseJsonValue();
406 if (value.is_null())
return ReportUnexpectedCharacter();
409 int descriptor =
map->NumberOfOwnDescriptors();
410 PropertyDetails details =
411 target->instance_descriptors()->GetDetails(descriptor);
412 Representation expected_representation = details.representation();
414 if (value->FitsRepresentation(expected_representation)) {
417 if (value->IsSmi() && expected_representation.IsDouble()) {
418 value = factory()->NewHeapNumber(
419 Handle<Smi>::cast(value)->value());
421 properties.Add(value, zone());
425 transitioning =
false;
431 int length = properties.length();
432 for (
int i = 0; i < length; i++) {
433 Handle<Object> value = properties[i];
434 json_object->FastPropertyAtPut(i, *value);
437 key = ParseJsonInternalizedString();
438 if (key.is_null() || c0_ !=
':')
return ReportUnexpectedCharacter();
440 AdvanceSkipWhitespace();
441 value = ParseJsonValue();
442 if (value.is_null())
return ReportUnexpectedCharacter();
446 json_object, key, value,
NONE);
447 }
while (MatchSkipWhiteSpace(
','));
449 return ReportUnexpectedCharacter();
455 int length = properties.length();
456 for (
int i = 0; i < length; i++) {
457 Handle<Object> value = properties[i];
458 json_object->FastPropertyAtPut(i, *value);
462 AdvanceSkipWhitespace();
463 return scope.CloseAndEscape(json_object);
467 template <
bool seq_ascii>
468 Handle<Object> JsonParser<seq_ascii>::ParseJsonArray() {
469 HandleScope scope(isolate());
470 ZoneList<Handle<Object> > elements(4, zone());
473 AdvanceSkipWhitespace();
476 Handle<Object> element = ParseJsonValue();
477 if (element.is_null())
return ReportUnexpectedCharacter();
478 elements.Add(element, zone());
479 }
while (MatchSkipWhiteSpace(
','));
481 return ReportUnexpectedCharacter();
484 AdvanceSkipWhitespace();
486 Handle<FixedArray> fast_elements =
487 factory()->NewFixedArray(elements.length(), pretenure_);
488 for (
int i = 0, n = elements.length(); i < n; i++) {
489 fast_elements->set(i, *elements[i]);
491 Handle<Object> json_array = factory()->NewJSArrayWithElements(
493 return scope.CloseAndEscape(json_array);
497 template <
bool seq_ascii>
498 Handle<Object> JsonParser<seq_ascii>::ParseJsonNumber() {
500 int beg_pos = position_;
509 if (
'0' <= c0_ && c0_ <=
'9')
return ReportUnexpectedCharacter();
513 if (c0_ < '1' || c0_ >
'9')
return ReportUnexpectedCharacter();
515 i = i * 10 + c0_ -
'0';
518 }
while (c0_ >=
'0' && c0_ <=
'9');
519 if (c0_ !=
'.' && c0_ !=
'e' && c0_ !=
'E' && digits < 10) {
521 return Handle<Smi>(
Smi::FromInt((negative ? -i : i)), isolate());
526 if (c0_ < '0' || c0_ >
'9')
return ReportUnexpectedCharacter();
529 }
while (c0_ >=
'0' && c0_ <=
'9');
533 if (c0_ ==
'-' || c0_ ==
'+') Advance();
534 if (c0_ < '0' || c0_ >
'9')
return ReportUnexpectedCharacter();
537 }
while (c0_ >=
'0' && c0_ <=
'9');
539 int length = position_ - beg_pos;
542 Vector<const uint8_t> chars(seq_source_->GetChars() + beg_pos, length);
550 Vector<const uint8_t> result =
551 Vector<const uint8_t>(buffer.start(), length);
560 return factory()->NewNumber(number, pretenure_);
564 template <
typename StringType>
569 seq_str->SeqTwoByteStringSet(i, c);
574 seq_str->SeqOneByteStringSet(i, c);
577 template <
typename StringType>
600 template <
bool seq_ascii>
601 template <
typename StringType,
typename SinkChar>
604 int count = end - start;
605 int max_length = count + source_length_ - position_;
606 int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count));
608 NewRawString<StringType>(factory(), length, pretenure_);
609 ASSERT(!seq_string.is_null());
611 SinkChar* dest = seq_string->GetChars();
617 if (count >= length) {
619 return SlowScanJsonString<StringType, SinkChar>(seq_string, 0, count);
633 return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0, count);
660 for (
int i = 0; i < 4; i++) {
666 value = value * 16 + digit;
676 return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string,
690 AdvanceSkipWhitespace();
697 template <
bool seq_ascii>
698 template <
bool is_
internalized>
699 Handle<String> JsonParser<seq_ascii>::ScanJsonString() {
703 AdvanceSkipWhitespace();
704 return factory()->empty_string();
707 if (seq_ascii && is_internalized) {
711 uint32_t running_hash = isolate()->heap()->HashSeed();
712 int position = position_;
717 int beg_pos = position_;
718 position_ = position;
719 return SlowScanJsonString<SeqOneByteString, uint8_t>(source_,
724 if (static_cast<uint32_t>(c0) >
727 StringHasher::AddCharacterCore(running_hash,
730 StringHasher::AddCharacterCore(running_hash,
733 running_hash = StringHasher::AddCharacterCore(running_hash, c0);
737 c0 = seq_source_->SeqOneByteStringGet(position);
739 int length = position - position_;
741 ? StringHasher::GetHashCore(running_hash) : length;
742 Vector<const uint8_t> string_vector(
743 seq_source_->GetChars() + position_, length);
744 StringTable* string_table = isolate()->heap()->string_table();
745 uint32_t capacity = string_table->Capacity();
748 Handle<String> result;
750 Object* element = string_table->KeyAt(entry);
751 if (element == isolate()->heap()->undefined_value()) {
753 result = factory()->InternalizeOneByteString(
754 seq_source_, position_, length);
757 if (element != isolate()->heap()->the_hole_value() &&
758 String::cast(element)->IsOneByteEqualTo(string_vector)) {
759 result = Handle<String>(
String::cast(element), isolate());
761 uint32_t hash_field =
763 ASSERT_EQ(static_cast<int>(result->Hash()),
770 position_ = position;
772 AdvanceSkipWhitespace();
776 int beg_pos = position_;
785 return SlowScanJsonString<SeqTwoByteString, uc16>(source_,
790 return SlowScanJsonString<SeqOneByteString, uint8_t>(source_,
794 }
while (c0_ !=
'"');
795 int length = position_ - beg_pos;
796 Handle<String> result = factory()->NewRawOneByteString(length, pretenure_);
797 ASSERT(!result.is_null());
803 AdvanceSkipWhitespace();
809 #endif // V8_JSON_PARSER_H_
void FlattenString(Handle< String > string)
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf map
static String * cast(Object *obj)
static Smi * FromInt(int value)
static Handle< T > cast(Handle< S > that)
static const int kMaxHashCalcLength
int AsciiAlphaToLower(uc32 c)
static uint16_t TrailSurrogate(uint32_t char_code)
kSerializedDataOffset Object
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage message
static SeqOneByteString * cast(Object *obj)
#define ASSERT(condition)
static Handle< Object > SetLocalPropertyIgnoreAttributes(Handle< JSObject > object, Handle< Name > key, Handle< Object > value, PropertyAttributes attributes, ValueType value_type=OPTIMAL_REPRESENTATION, StoreMode mode=ALLOW_AS_CONSTANT, ExtensibilityCheck extensibility_check=PERFORM_EXTENSIBILITY_CHECK)
static Handle< Map > ExpectedTransitionTarget(Handle< Map > map)
Handle< StringType > NewRawString(Factory *factory, int length, PretenureFlag pretenure)
static MUST_USE_RESULT Handle< String > Truncate(Handle< SeqString > string, int new_length)
double StringToDouble(UnicodeCache *unicode_cache, const char *str, int flags, double empty_string_val)
static Handle< String > ExpectedTransitionKey(Handle< Map > map)
Handle< SeqTwoByteString > NewRawTwoByteString(int length, PretenureFlag pretenure=NOT_TENURED)
static const uchar kMaxNonSurrogateCharCode
static uint16_t LeadSurrogate(uint32_t char_code)
static Handle< Map > FindTransitionToField(Handle< Map > map, Handle< Name > key)
static const int kIsNotArrayIndexMask
static Handle< Object > SetOwnElement(Handle< JSObject > object, uint32_t index, Handle< Object > value, StrictMode strict_mode)
static Vector< T > New(int length)
static void WriteToFlat(String *source, sinkchar *sink, int from, int to)
static double nan_value()
Handle< String > LookupSingleCharacterStringFromCode(Isolate *isolate, uint32_t index)
static Vector< const char > cast(Vector< S > input)
static void AllocateStorageForMap(Handle< JSObject > object, Handle< Map > map)
static Handle< T > null()
Handle< SeqOneByteString > NewRawOneByteString(int length, PretenureFlag pretenure=NOT_TENURED)
#define ASSERT_EQ(v1, v2)
static uint32_t NextProbe(uint32_t last, uint32_t number, uint32_t size)
PerThreadAssertScopeDebugOnly< HEAP_ALLOCATION_ASSERT, false > DisallowHeapAllocation
static Handle< Object > Parse(Handle< String > source)
static const int kHashShift
static uint32_t FirstProbe(uint32_t hash, uint32_t size)
void SeqStringSet(Handle< StringType > seq_str, int i, uc32 c)
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in name
static const int32_t kMaxOneByteCharCode