5 #ifndef V8_JSON_PARSER_H_
6 #define V8_JSON_PARSER_H_
20 template <
bool seq_one_
byte>
24 return JsonParser(source).ParseJson();
27 static const int kEndOfString = -1;
32 source_length_(source->length()),
33 isolate_(source->
map()->GetHeap()->isolate()),
34 factory_(isolate_->factory()),
36 object_constructor_(isolate_->native_context()->object_function(),
53 if (position_ >= source_length_) {
55 }
else if (seq_one_byte) {
56 c0_ = seq_source_->SeqOneByteStringGet(position_);
58 c0_ = source_->Get(position_);
69 }
while (c0_ ==
' ' || c0_ ==
'\t' || c0_ ==
'\n' || c0_ ==
'\r');
73 while (c0_ ==
' ' || c0_ ==
'\t' || c0_ ==
'\n' || c0_ ==
'\r') {
87 AdvanceSkipWhitespace();
98 return ScanJsonString<false>();
102 int length = expected->length();
103 if (source_->length() - position_ - 1 > length) {
108 const uint8_t* input_chars = seq_source_->GetChars() + position_ + 1;
110 for (
int i = 0;
i < length;
i++) {
111 uint8_t c0 = input_chars[
i];
112 if (c0 != expected_chars[
i] ||
113 c0 ==
'"' || c0 < 0x20 || c0 ==
'\\') {
117 if (input_chars[length] ==
'"') {
118 position_ = position_ + length + 1;
119 AdvanceSkipWhitespace();
128 return ScanJsonString<true>();
131 template <
bool is_
internalized>
136 template <
typename StringType,
typename SinkChar>
175 inline Factory*
factory() {
return factory_; }
178 static const int kInitialSpecialStringLength = 1024;
179 static const int kPretenureTreshold = 100 * 1024;
198 template <
bool seq_one_
byte>
201 AdvanceSkipWhitespace();
203 if (result.
is_null() || c0_ != kEndOfString) {
209 Factory* factory = this->factory();
214 message =
"unexpected_eos";
215 array = factory->NewJSArray(0);
228 message =
"unexpected_token_number";
229 array = factory->NewJSArray(0);
232 message =
"unexpected_token_string";
233 array = factory->NewJSArray(0);
236 message =
"unexpected_token";
239 element->set(0, *
name);
240 array = factory->NewJSArrayWithElements(element);
249 factory->NewSyntaxError(message, array),
Object);
250 return isolate()->template Throw<Object>(error, &location);
257 template <
bool seq_one_
byte>
258 Handle<Object> JsonParser<seq_one_byte>::ParseJsonValue() {
259 StackLimitCheck stack_check(isolate_);
260 if (stack_check.HasOverflowed()) {
261 isolate_->StackOverflow();
265 if (c0_ ==
'"')
return ParseJsonString();
266 if ((c0_ >=
'0' && c0_ <=
'9') || c0_ ==
'-')
return ParseJsonNumber();
267 if (c0_ ==
'{')
return ParseJsonObject();
268 if (c0_ ==
'[')
return ParseJsonArray();
270 if (AdvanceGetChar() ==
'a' && AdvanceGetChar() ==
'l' &&
271 AdvanceGetChar() ==
's' && AdvanceGetChar() ==
'e') {
272 AdvanceSkipWhitespace();
273 return factory()->false_value();
275 return ReportUnexpectedCharacter();
278 if (AdvanceGetChar() ==
'r' && AdvanceGetChar() ==
'u' &&
279 AdvanceGetChar() ==
'e') {
280 AdvanceSkipWhitespace();
281 return factory()->true_value();
283 return ReportUnexpectedCharacter();
286 if (AdvanceGetChar() ==
'u' && AdvanceGetChar() ==
'l' &&
287 AdvanceGetChar() ==
'l') {
288 AdvanceSkipWhitespace();
289 return factory()->null_value();
291 return ReportUnexpectedCharacter();
293 return ReportUnexpectedCharacter();
298 template <
bool seq_one_
byte>
299 Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() {
300 HandleScope scope(isolate());
301 Handle<JSObject> json_object =
302 factory()->NewJSObject(object_constructor(), pretenure_);
303 Handle<Map>
map(json_object->map());
304 ZoneList<Handle<Object> > properties(8, zone());
307 bool transitioning =
true;
309 AdvanceSkipWhitespace();
312 if (c0_ !=
'"')
return ReportUnexpectedCharacter();
314 int start_position = position_;
318 if (c0_ >=
'0' && c0_ <=
'9') {
326 if (index > 429496729U - ((d > 5) ? 1 : 0))
break;
327 index = (index * 10) + d;
329 }
while (c0_ >=
'0' && c0_ <=
'9');
334 AdvanceSkipWhitespace();
336 if (c0_ !=
':')
return ReportUnexpectedCharacter();
337 AdvanceSkipWhitespace();
338 Handle<Object> value = ParseJsonValue();
339 if (value.is_null())
return ReportUnexpectedCharacter();
347 position_ = start_position;
353 Handle<Object> value;
360 bool follow_expected =
false;
364 follow_expected = !key.is_null() && ParseJsonString(key);
367 if (follow_expected) {
372 key = ParseJsonInternalizedString();
373 if (key.is_null())
return ReportUnexpectedCharacter();
377 transitioning = !target.is_null();
379 if (c0_ !=
':')
return ReportUnexpectedCharacter();
381 AdvanceSkipWhitespace();
382 value = ParseJsonValue();
383 if (value.is_null())
return ReportUnexpectedCharacter();
386 int descriptor =
map->NumberOfOwnDescriptors();
387 PropertyDetails details =
388 target->instance_descriptors()->GetDetails(descriptor);
389 Representation expected_representation = details.representation();
391 if (value->FitsRepresentation(expected_representation)) {
392 if (expected_representation.IsDouble()) {
394 expected_representation);
395 }
else if (expected_representation.IsHeapObject() &&
396 !target->instance_descriptors()->GetFieldType(
397 descriptor)->NowContains(value)) {
398 Handle<HeapType> value_type(value->OptimalType(
399 isolate(), expected_representation));
402 DCHECK(target->instance_descriptors()->GetFieldType(
403 descriptor)->NowContains(value));
404 properties.Add(value, zone());
408 transitioning =
false;
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);
421 key = ParseJsonInternalizedString();
422 if (key.is_null() || c0_ !=
':')
return ReportUnexpectedCharacter();
424 AdvanceSkipWhitespace();
425 value = ParseJsonValue();
426 if (value.is_null())
return ReportUnexpectedCharacter();
430 }
while (MatchSkipWhiteSpace(
','));
432 return ReportUnexpectedCharacter();
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);
446 AdvanceSkipWhitespace();
447 return scope.CloseAndEscape(json_object);
451 template <
bool seq_one_
byte>
452 Handle<Object> JsonParser<seq_one_byte>::ParseJsonArray() {
453 HandleScope scope(isolate());
454 ZoneList<Handle<Object> > elements(4, zone());
457 AdvanceSkipWhitespace();
460 Handle<Object> element = ParseJsonValue();
461 if (element.is_null())
return ReportUnexpectedCharacter();
462 elements.Add(element, zone());
463 }
while (MatchSkipWhiteSpace(
','));
465 return ReportUnexpectedCharacter();
468 AdvanceSkipWhitespace();
470 Handle<FixedArray> fast_elements =
471 factory()->NewFixedArray(elements.length(), pretenure_);
472 for (
int i = 0, n = elements.length();
i < n;
i++) {
473 fast_elements->set(
i, *elements[
i]);
475 Handle<Object> json_array = factory()->NewJSArrayWithElements(
477 return scope.CloseAndEscape(json_array);
481 template <
bool seq_one_
byte>
482 Handle<Object> JsonParser<seq_one_byte>::ParseJsonNumber() {
484 int beg_pos = position_;
493 if (
'0' <= c0_ && c0_ <=
'9')
return ReportUnexpectedCharacter();
497 if (c0_ < '1' || c0_ >
'9')
return ReportUnexpectedCharacter();
499 i =
i * 10 + c0_ -
'0';
502 }
while (c0_ >=
'0' && c0_ <=
'9');
503 if (c0_ !=
'.' && c0_ !=
'e' && c0_ !=
'E' && digits < 10) {
510 if (c0_ < '0' || c0_ >
'9')
return ReportUnexpectedCharacter();
513 }
while (c0_ >=
'0' && c0_ <=
'9');
517 if (c0_ ==
'-' || c0_ ==
'+') Advance();
518 if (c0_ < '0' || c0_ >
'9')
return ReportUnexpectedCharacter();
521 }
while (c0_ >=
'0' && c0_ <=
'9');
523 int length = position_ - beg_pos;
526 Vector<const uint8_t> chars(seq_source_->GetChars() + beg_pos, length);
534 Vector<const uint8_t> result =
535 Vector<const uint8_t>(buffer.start(), length);
543 return factory()->NewNumber(number, pretenure_);
547 template <
typename StringType>
552 seq_str->SeqTwoByteStringSet(
i, c);
557 seq_str->SeqOneByteStringSet(
i, c);
560 template <
typename StringType>
569 return factory->NewRawTwoByteString(length, pretenure).ToHandleChecked();
576 return factory->NewRawOneByteString(length, pretenure).ToHandleChecked();
583 template <
bool seq_one_
byte>
584 template <
typename StringType,
typename SinkChar>
585 Handle<String> JsonParser<seq_one_byte>::SlowScanJsonString(
586 Handle<String> prefix,
int start,
int end) {
587 int count = end - start;
588 int max_length = count + source_length_ - position_;
589 int length =
Min(max_length,
Max(kInitialSpecialStringLength, 2 * count));
590 Handle<StringType> seq_string =
591 NewRawString<StringType>(factory(), length, pretenure_);
593 SinkChar* dest = seq_string->GetChars();
599 if (count >= length) {
601 return SlowScanJsonString<StringType, SinkChar>(seq_string, 0, count);
608 if (
sizeof(SinkChar) ==
kUC16Size || seq_one_byte ||
614 return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0, count);
641 for (
int i = 0;
i < 4;
i++) {
647 value = value * 16 + digit;
658 return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string,
672 AdvanceSkipWhitespace();
679 template <
bool seq_one_
byte>
680 template <
bool is_
internalized>
681 Handle<String> JsonParser<seq_one_byte>::ScanJsonString() {
685 AdvanceSkipWhitespace();
686 return factory()->empty_string();
689 if (seq_one_byte && is_internalized) {
693 uint32_t running_hash = isolate()->heap()->HashSeed();
694 int position = position_;
699 int beg_pos = position_;
700 position_ = position;
701 return SlowScanJsonString<SeqOneByteString, uint8_t>(source_,
709 StringHasher::AddCharacterCore(running_hash,
712 StringHasher::AddCharacterCore(running_hash,
715 running_hash = StringHasher::AddCharacterCore(running_hash, c0);
719 c0 = seq_source_->SeqOneByteStringGet(position);
721 int length = position - position_;
723 ? StringHasher::GetHashCore(running_hash)
725 Vector<const uint8_t> string_vector(
726 seq_source_->GetChars() + position_, length);
727 StringTable* string_table = isolate()->heap()->string_table();
728 uint32_t capacity = string_table->Capacity();
731 Handle<String> result;
733 Object* element = string_table->KeyAt(entry);
734 if (element == isolate()->heap()->undefined_value()) {
736 result = factory()->InternalizeOneByteString(
737 seq_source_, position_, length);
740 if (element != isolate()->heap()->the_hole_value() &&
741 String::cast(element)->IsOneByteEqualTo(string_vector)) {
742 result = Handle<String>(String::cast(element), isolate());
746 DCHECK_EQ(
static_cast<int>(result->Hash()),
753 position_ = position;
755 AdvanceSkipWhitespace();
759 int beg_pos = position_;
768 return SlowScanJsonString<SeqTwoByteString, uc16>(source_,
773 return SlowScanJsonString<SeqOneByteString, uint8_t>(source_,
777 }
while (c0_ !=
'"');
778 int length = position_ - beg_pos;
779 Handle<String> result =
780 factory()->NewRawOneByteString(length, pretenure_).ToHandleChecked();
781 uint8_t* dest = SeqOneByteString::cast(*result)->GetChars();
786 AdvanceSkipWhitespace();
static uint16_t LeadSurrogate(uint32_t char_code)
static const uchar kMaxNonSurrogateCharCode
static uint16_t TrailSurrogate(uint32_t char_code)
An object reference managed by the v8 garbage collector.
static double nan_value()
bool ParseJsonString(Handle< String > expected)
Handle< Object > ParseJsonValue()
MaybeHandle< Object > ParseJson()
Handle< String > ParseJsonString()
bool MatchSkipWhiteSpace(uc32 c)
Handle< Object > ParseJsonNumber()
Handle< SeqOneByteString > seq_source_
Handle< String > ScanJsonString()
Handle< JSFunction > object_constructor()
Handle< Object > ReportUnexpectedCharacter()
Handle< Object > ParseJsonObject()
JsonParser(Handle< String > source)
Handle< Object > ParseJsonArray()
Handle< String > SlowScanJsonString(Handle< String > prefix, int start, int end)
Handle< JSFunction > object_constructor_
static MUST_USE_RESULT MaybeHandle< Object > Parse(Handle< String > source)
void AdvanceSkipWhitespace()
Handle< String > ParseJsonInternalizedString()
static Handle< T > cast(Handle< S > that)
static Handle< T > null()
static uint32_t NextProbe(uint32_t last, uint32_t number, uint32_t size)
static uint32_t FirstProbe(uint32_t hash, uint32_t size)
static void AllocateStorageForMap(Handle< JSObject > object, Handle< Map > map)
static MUST_USE_RESULT MaybeHandle< Object > SetOwnElement(Handle< JSObject > object, uint32_t index, Handle< Object > value, StrictMode strict_mode)
static MUST_USE_RESULT Handle< HeapType > GeneralizeFieldType(Handle< HeapType > type1, Handle< HeapType > type2, Isolate *isolate)
static Handle< String > ExpectedTransitionKey(Handle< Map > map)
static Handle< Map > FindTransitionToField(Handle< Map > map, Handle< Name > key)
static Handle< Map > ExpectedTransitionTarget(Handle< Map > map)
static const int kHashShift
static const int kIsNotArrayIndexMask
static Handle< Object > NewStorageFor(Isolate *isolate, Handle< Object > object, Representation representation)
static MUST_USE_RESULT MaybeHandle< Object > DefineObjectProperty(Handle< JSObject > object, Handle< Object > key, Handle< Object > value, PropertyAttributes attr)
static MUST_USE_RESULT Handle< String > Truncate(Handle< SeqString > string, int new_length)
static Smi * FromInt(int value)
Vector< const uint8_t > ToOneByteVector()
static void WriteToFlat(String *source, sinkchar *sink, int from, int to)
static const int32_t kMaxOneByteCharCode
static const int kMaxHashCalcLength
static Handle< String > Flatten(Handle< String > string, PretenureFlag pretenure=NOT_TENURED)
static Vector< T > New(int length)
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf map
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS 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 enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in name
#define ASSIGN_RETURN_ON_EXCEPTION(isolate, dst, call, T)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
void SeqStringSet(Handle< StringType > seq_str, int i, uc32 c)
Handle< StringType > NewRawString(Factory *factory, int length, PretenureFlag pretenure)
static LifetimePosition Min(LifetimePosition a, LifetimePosition b)
kSerializedDataOffset Object
static LifetimePosition Max(LifetimePosition a, LifetimePosition b)
int AsciiAlphaToLower(uc32 c)
double StringToDouble(UnicodeCache *unicode_cache, const char *str, int flags, double empty_string_val)
Debugger support for the V8 JavaScript engine.