Line data Source code
1 : // Copyright 2016 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/json-parser.h"
6 :
7 : #include "src/char-predicates-inl.h"
8 : #include "src/conversions.h"
9 : #include "src/debug/debug.h"
10 : #include "src/factory.h"
11 : #include "src/field-type.h"
12 : #include "src/messages.h"
13 : #include "src/objects-inl.h"
14 : #include "src/parsing/token.h"
15 : #include "src/property-descriptor.h"
16 : #include "src/string-hasher.h"
17 : #include "src/transitions.h"
18 : #include "src/unicode-cache.h"
19 :
20 : namespace v8 {
21 : namespace internal {
22 :
23 153 : MaybeHandle<Object> JsonParseInternalizer::Internalize(Isolate* isolate,
24 : Handle<Object> object,
25 : Handle<Object> reviver) {
26 : DCHECK(reviver->IsCallable());
27 : JsonParseInternalizer internalizer(isolate,
28 : Handle<JSReceiver>::cast(reviver));
29 : Handle<JSObject> holder =
30 153 : isolate->factory()->NewJSObject(isolate->object_function());
31 : Handle<String> name = isolate->factory()->empty_string();
32 153 : JSObject::AddProperty(holder, name, object, NONE);
33 153 : return internalizer.InternalizeJsonProperty(holder, name);
34 : }
35 :
36 68353 : MaybeHandle<Object> JsonParseInternalizer::InternalizeJsonProperty(
37 : Handle<JSReceiver> holder, Handle<String> name) {
38 68353 : HandleScope outer_scope(isolate_);
39 : Handle<Object> value;
40 136706 : ASSIGN_RETURN_ON_EXCEPTION(
41 : isolate_, value, Object::GetPropertyOrElement(holder, name), Object);
42 68353 : if (value->IsJSReceiver()) {
43 : Handle<JSReceiver> object = Handle<JSReceiver>::cast(value);
44 : Maybe<bool> is_array = Object::IsArray(object);
45 46201 : if (is_array.IsNothing()) return MaybeHandle<Object>();
46 46201 : if (is_array.FromJust()) {
47 : Handle<Object> length_object;
48 43710 : ASSIGN_RETURN_ON_EXCEPTION(
49 : isolate_, length_object,
50 : Object::GetLengthFromArrayLike(isolate_, object), Object);
51 : double length = length_object->Number();
52 43804 : for (double i = 0; i < length; i++) {
53 43739 : HandleScope inner_scope(isolate_);
54 43739 : Handle<Object> index = isolate_->factory()->NewNumber(i);
55 43739 : Handle<String> name = isolate_->factory()->NumberToString(index);
56 43739 : if (!RecurseAndApply(object, name)) return MaybeHandle<Object>();
57 : }
58 : } else {
59 : Handle<FixedArray> contents;
60 48692 : ASSIGN_RETURN_ON_EXCEPTION(
61 : isolate_, contents,
62 : KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly,
63 : ENUMERABLE_STRINGS,
64 : GetKeysConversion::kConvertToString),
65 : Object);
66 24868 : for (int i = 0; i < contents->length(); i++) {
67 24471 : HandleScope inner_scope(isolate_);
68 24471 : Handle<String> name(String::cast(contents->get(i)), isolate_);
69 24471 : if (!RecurseAndApply(object, name)) return MaybeHandle<Object>();
70 : }
71 : }
72 : }
73 22353 : Handle<Object> argv[] = {name, value};
74 : Handle<Object> result;
75 44706 : ASSIGN_RETURN_ON_EXCEPTION(
76 : isolate_, result, Execution::Call(isolate_, reviver_, holder, 2, argv),
77 : Object);
78 22344 : return outer_scope.CloseAndEscape(result);
79 : }
80 :
81 68210 : bool JsonParseInternalizer::RecurseAndApply(Handle<JSReceiver> holder,
82 : Handle<String> name) {
83 136420 : STACK_CHECK(isolate_, false);
84 :
85 : Handle<Object> result;
86 136400 : ASSIGN_RETURN_ON_EXCEPTION_VALUE(
87 : isolate_, result, InternalizeJsonProperty(holder, name), false);
88 : Maybe<bool> change_result = Nothing<bool>();
89 44420 : if (result->IsUndefined(isolate_)) {
90 : change_result = JSReceiver::DeletePropertyOrElement(holder, name,
91 116 : LanguageMode::kSloppy);
92 : } else {
93 : PropertyDescriptor desc;
94 : desc.set_value(result);
95 : desc.set_configurable(true);
96 : desc.set_enumerable(true);
97 : desc.set_writable(true);
98 : change_result = JSReceiver::DefineOwnProperty(isolate_, holder, name, &desc,
99 22094 : Object::DONT_THROW);
100 : }
101 22210 : MAYBE_RETURN(change_result, false);
102 22210 : return true;
103 : }
104 :
105 : template <bool seq_one_byte>
106 481563 : JsonParser<seq_one_byte>::JsonParser(Isolate* isolate, Handle<String> source)
107 : : source_(source),
108 : source_length_(source->length()),
109 : isolate_(isolate),
110 481563 : factory_(isolate_->factory()),
111 : zone_(isolate_->allocator(), ZONE_NAME),
112 481563 : object_constructor_(isolate_->native_context()->object_function(),
113 : isolate_),
114 2889378 : position_(-1) {
115 481563 : source_ = String::Flatten(source_);
116 481563 : pretenure_ = (source_length_ >= kPretenureTreshold) ? TENURED : NOT_TENURED;
117 :
118 : // Optimized fast case where we only have Latin1 characters.
119 : if (seq_one_byte) {
120 481526 : seq_source_ = Handle<SeqOneByteString>::cast(source_);
121 : }
122 481563 : }
123 :
124 : template <bool seq_one_byte>
125 481563 : MaybeHandle<Object> JsonParser<seq_one_byte>::ParseJson() {
126 : // Advance to the first character (possibly EOS)
127 : AdvanceSkipWhitespace();
128 481563 : Handle<Object> result = ParseJsonValue();
129 481563 : if (result.is_null() || c0_ != kEndOfString) {
130 : // Some exception (for example stack overflow) is already pending.
131 715 : if (isolate_->has_pending_exception()) return Handle<Object>::null();
132 :
133 : // Parse failed. Current character is the unexpected token.
134 : Factory* factory = this->factory();
135 : MessageTemplate::Template message;
136 : Handle<Object> arg1 = Handle<Smi>(Smi::FromInt(position_), isolate());
137 : Handle<Object> arg2;
138 :
139 686 : switch (c0_) {
140 : case kEndOfString:
141 : message = MessageTemplate::kJsonParseUnexpectedEOS;
142 : break;
143 : case '-':
144 : case '0':
145 : case '1':
146 : case '2':
147 : case '3':
148 : case '4':
149 : case '5':
150 : case '6':
151 : case '7':
152 : case '8':
153 : case '9':
154 : message = MessageTemplate::kJsonParseUnexpectedTokenNumber;
155 100 : break;
156 : case '"':
157 : message = MessageTemplate::kJsonParseUnexpectedTokenString;
158 130 : break;
159 : default:
160 : message = MessageTemplate::kJsonParseUnexpectedToken;
161 326 : arg2 = arg1;
162 326 : arg1 = factory->LookupSingleCharacterStringFromCode(c0_);
163 326 : break;
164 : }
165 :
166 686 : Handle<Script> script(factory->NewScript(source_));
167 : // We should sent compile error event because we compile JSON object in
168 : // separated source file.
169 686 : isolate()->debug()->OnCompileError(script);
170 686 : MessageLocation location(script, position_, position_ + 1);
171 686 : Handle<Object> error = factory->NewSyntaxError(message, arg1, arg2);
172 : return isolate()->template Throw<Object>(error, &location);
173 : }
174 480848 : return result;
175 : }
176 :
177 : MaybeHandle<Object> InternalizeJsonProperty(Handle<JSObject> holder,
178 : Handle<String> key);
179 :
180 : template <bool seq_one_byte>
181 0 : void JsonParser<seq_one_byte>::Advance() {
182 1216451132 : position_++;
183 1216451132 : if (position_ >= source_length_) {
184 480968 : c0_ = kEndOfString;
185 : } else if (seq_one_byte) {
186 1209991316 : c0_ = seq_source_->SeqOneByteStringGet(position_);
187 : } else {
188 5978848 : c0_ = source_->Get(position_);
189 : }
190 0 : }
191 :
192 : template <bool seq_one_byte>
193 0 : void JsonParser<seq_one_byte>::AdvanceSkipWhitespace() {
194 130254778 : do {
195 : Advance();
196 : } while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r');
197 0 : }
198 :
199 : template <bool seq_one_byte>
200 0 : void JsonParser<seq_one_byte>::SkipWhitespace() {
201 6429185 : while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r') {
202 : Advance();
203 : }
204 0 : }
205 :
206 : template <bool seq_one_byte>
207 0 : uc32 JsonParser<seq_one_byte>::AdvanceGetChar() {
208 : Advance();
209 30743053 : return c0_;
210 : }
211 :
212 : template <bool seq_one_byte>
213 0 : bool JsonParser<seq_one_byte>::MatchSkipWhiteSpace(uc32 c) {
214 36760437 : if (c0_ == c) {
215 : AdvanceSkipWhitespace();
216 : return true;
217 : }
218 : return false;
219 : }
220 :
221 : template <bool seq_one_byte>
222 19497701 : bool JsonParser<seq_one_byte>::ParseJsonString(Handle<String> expected) {
223 : int length = expected->length();
224 19497701 : if (source_->length() - position_ - 1 > length) {
225 : DisallowHeapAllocation no_gc;
226 19497514 : String::FlatContent content = expected->GetFlatContent();
227 19497514 : if (content.IsOneByte()) {
228 : DCHECK_EQ('"', c0_);
229 19497514 : const uint8_t* input_chars = seq_source_->GetChars() + position_ + 1;
230 19497514 : const uint8_t* expected_chars = content.ToOneByteVector().start();
231 187733758 : for (int i = 0; i < length; i++) {
232 168244948 : uint8_t c0 = input_chars[i];
233 168244948 : if (c0 != expected_chars[i] || c0 == '"' || c0 < 0x20 || c0 == '\\') {
234 19497500 : return false;
235 : }
236 : }
237 19488810 : if (input_chars[length] == '"') {
238 19488796 : position_ = position_ + length + 1;
239 : AdvanceSkipWhitespace();
240 : return true;
241 : }
242 : }
243 : }
244 : return false;
245 : }
246 :
247 : // Parse any JSON value.
248 : template <bool seq_one_byte>
249 37290563 : Handle<Object> JsonParser<seq_one_byte>::ParseJsonValue() {
250 37290563 : StackLimitCheck stack_check(isolate_);
251 37290563 : if (stack_check.HasOverflowed()) {
252 29 : isolate_->StackOverflow();
253 : return Handle<Object>::null();
254 : }
255 :
256 37290642 : if (stack_check.InterruptRequested() &&
257 108 : isolate_->stack_guard()->HandleInterrupts()->IsException(isolate_)) {
258 : return Handle<Object>::null();
259 : }
260 :
261 52149486 : if (c0_ == '"') return ParseJsonString();
262 22431582 : if ((c0_ >= '0' && c0_ <= '9') || c0_ == '-') return ParseJsonNumber();
263 16982082 : if (c0_ == '{') return ParseJsonObject();
264 9994600 : if (c0_ == '[') return ParseJsonArray();
265 9561029 : if (c0_ == 'f') {
266 8240922 : if (AdvanceGetChar() == 'a' && AdvanceGetChar() == 'l' &&
267 : AdvanceGetChar() == 's' && AdvanceGetChar() == 'e') {
268 : AdvanceSkipWhitespace();
269 2060228 : return factory()->false_value();
270 : }
271 : return ReportUnexpectedCharacter();
272 : }
273 7500791 : if (c0_ == 't') {
274 22494294 : if (AdvanceGetChar() == 'r' && AdvanceGetChar() == 'u' &&
275 : AdvanceGetChar() == 'e') {
276 : AdvanceSkipWhitespace();
277 7498098 : return factory()->true_value();
278 : }
279 : return ReportUnexpectedCharacter();
280 : }
281 2693 : if (c0_ == 'n') {
282 7837 : if (AdvanceGetChar() == 'u' && AdvanceGetChar() == 'l' &&
283 : AdvanceGetChar() == 'l') {
284 : AdvanceSkipWhitespace();
285 2612 : return factory()->null_value();
286 : }
287 : return ReportUnexpectedCharacter();
288 : }
289 : return ReportUnexpectedCharacter();
290 : }
291 :
292 : template <bool seq_one_byte>
293 173537 : ParseElementResult JsonParser<seq_one_byte>::ParseElement(
294 : Handle<JSObject> json_object) {
295 : uint32_t index = 0;
296 : // Maybe an array index, try to parse it.
297 173537 : if (c0_ == '0') {
298 : // With a leading zero, the string has to be "0" only to be an index.
299 : Advance();
300 : } else {
301 389370 : do {
302 389380 : int d = c0_ - '0';
303 389380 : if (index > 429496729U - ((d + 3) >> 3)) break;
304 389370 : index = (index * 10) + d;
305 : Advance();
306 389370 : } while (IsDecimalDigit(c0_));
307 : }
308 :
309 173537 : if (c0_ == '"') {
310 : // Successfully parsed index, parse and store element.
311 : AdvanceSkipWhitespace();
312 :
313 173487 : if (c0_ == ':') {
314 : AdvanceSkipWhitespace();
315 173487 : Handle<Object> value = ParseJsonValue();
316 173487 : if (!value.is_null()) {
317 : JSObject::SetOwnElementIgnoreAttributes(json_object, index, value, NONE)
318 173477 : .Assert();
319 173477 : return kElementFound;
320 : } else {
321 : return kNullHandle;
322 : }
323 : }
324 : }
325 : return kElementNotFound;
326 : }
327 :
328 : // Parse a JSON object. Position must be right at '{'.
329 : template <bool seq_one_byte>
330 6987482 : Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() {
331 : HandleScope scope(isolate());
332 : Handle<JSObject> json_object =
333 13974964 : factory()->NewJSObject(object_constructor(), pretenure_);
334 : Handle<Map> map(json_object->map());
335 : int descriptor = 0;
336 6987482 : ZoneList<Handle<Object> > properties(8, zone());
337 : DCHECK_EQ(c0_, '{');
338 :
339 : bool transitioning = true;
340 :
341 : AdvanceSkipWhitespace();
342 6987482 : if (c0_ != '}') {
343 59819759 : do {
344 29961135 : if (c0_ != '"') return ReportUnexpectedCharacter();
345 :
346 29960852 : int start_position = position_;
347 : Advance();
348 :
349 59921704 : if (IsDecimalDigit(c0_)) {
350 173537 : ParseElementResult element_result = ParseElement(json_object);
351 173537 : if (element_result == kNullHandle) return Handle<Object>::null();
352 30032537 : if (element_result == kElementFound) continue;
353 : }
354 : // Not an index, fallback to the slow path.
355 :
356 29787365 : position_ = start_position;
357 : #ifdef DEBUG
358 : c0_ = '"';
359 : #endif
360 :
361 : Handle<String> key;
362 : Handle<Object> value;
363 :
364 : // Try to follow existing transitions as long as possible. Once we stop
365 : // transitioning, no transition can be found anymore.
366 : DCHECK(transitioning);
367 : // First check whether there is a single expected transition. If so, try
368 : // to parse it first.
369 : bool follow_expected = false;
370 : Handle<Map> target;
371 : if (seq_one_byte) {
372 : DisallowHeapAllocation no_gc;
373 : TransitionsAccessor transitions(*map, &no_gc);
374 29687315 : key = transitions.ExpectedTransitionKey();
375 29687315 : follow_expected = !key.is_null() && ParseJsonString(key);
376 : // If the expected transition hits, follow it.
377 29687315 : if (follow_expected) {
378 19488796 : target = transitions.ExpectedTransitionTarget();
379 : }
380 : }
381 29687315 : if (!follow_expected) {
382 : // If the expected transition failed, parse an internalized string and
383 : // try to find a matching transition.
384 10298569 : key = ParseJsonInternalizedString();
385 10298569 : if (key.is_null()) return ReportUnexpectedCharacter();
386 :
387 10298499 : target = TransitionsAccessor(map).FindTransitionToField(key);
388 : // If a transition was found, follow it and continue.
389 10298499 : transitioning = !target.is_null();
390 : }
391 29787295 : if (c0_ != ':') return ReportUnexpectedCharacter();
392 :
393 : AdvanceSkipWhitespace();
394 29787295 : value = ParseJsonValue();
395 29787295 : if (value.is_null()) return ReportUnexpectedCharacter();
396 :
397 29787272 : if (transitioning) {
398 : PropertyDetails details =
399 29688480 : target->instance_descriptors()->GetDetails(descriptor);
400 : Representation expected_representation = details.representation();
401 :
402 29688480 : if (value->FitsRepresentation(expected_representation)) {
403 57626659 : if (expected_representation.IsHeapObject() &&
404 : !target->instance_descriptors()
405 : ->GetFieldType(descriptor)
406 27941126 : ->NowContains(value)) {
407 : Handle<FieldType> value_type(
408 13122 : value->OptimalType(isolate(), expected_representation));
409 13122 : Map::GeneralizeField(target, descriptor, details.constness(),
410 : expected_representation, value_type);
411 : }
412 : DCHECK(target->instance_descriptors()
413 : ->GetFieldType(descriptor)
414 : ->NowContains(value));
415 29685533 : properties.Add(value, zone());
416 : map = target;
417 29685533 : descriptor++;
418 : continue;
419 : } else {
420 : transitioning = false;
421 : }
422 : }
423 :
424 : DCHECK(!transitioning);
425 :
426 : // Commit the intermediate state to the object and stop transitioning.
427 101739 : CommitStateToJsonObject(json_object, map, &properties);
428 :
429 101739 : JSObject::DefinePropertyOrElementIgnoreAttributes(json_object, key, value)
430 203478 : .Check();
431 : } while (transitioning && MatchSkipWhiteSpace(','));
432 :
433 : // If we transitioned until the very end, transition the map now.
434 6882590 : if (transitioning) {
435 6780851 : CommitStateToJsonObject(json_object, map, &properties);
436 : } else {
437 388730 : while (MatchSkipWhiteSpace(',')) {
438 : HandleScope local_scope(isolate());
439 286991 : if (c0_ != '"') return ReportUnexpectedCharacter();
440 :
441 286991 : int start_position = position_;
442 : Advance();
443 :
444 573982 : if (IsDecimalDigit(c0_)) {
445 0 : ParseElementResult element_result = ParseElement(json_object);
446 0 : if (element_result == kNullHandle) return Handle<Object>::null();
447 0 : if (element_result == kElementFound) continue;
448 : }
449 : // Not an index, fallback to the slow path.
450 :
451 286991 : position_ = start_position;
452 : #ifdef DEBUG
453 : c0_ = '"';
454 : #endif
455 :
456 : Handle<String> key;
457 : Handle<Object> value;
458 :
459 286991 : key = ParseJsonInternalizedString();
460 286991 : if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter();
461 :
462 : AdvanceSkipWhitespace();
463 286991 : value = ParseJsonValue();
464 286991 : if (value.is_null()) return ReportUnexpectedCharacter();
465 :
466 : JSObject::DefinePropertyOrElementIgnoreAttributes(json_object, key,
467 286991 : value)
468 573982 : .Check();
469 : }
470 : }
471 :
472 6882590 : if (c0_ != '}') {
473 : return ReportUnexpectedCharacter();
474 : }
475 : }
476 : AdvanceSkipWhitespace();
477 6987279 : return scope.CloseAndEscape(json_object);
478 : }
479 :
480 : template <bool seq_one_byte>
481 6882590 : void JsonParser<seq_one_byte>::CommitStateToJsonObject(
482 : Handle<JSObject> json_object, Handle<Map> map,
483 36568109 : ZoneList<Handle<Object> >* properties) {
484 6882590 : JSObject::AllocateStorageForMap(json_object, map);
485 : DCHECK(!json_object->map()->is_dictionary_map());
486 :
487 : DisallowHeapAllocation no_gc;
488 : DescriptorArray* descriptors = json_object->map()->instance_descriptors();
489 : int length = properties->length();
490 36568109 : for (int i = 0; i < length; i++) {
491 29685519 : Handle<Object> value = (*properties)[i];
492 : // Initializing store.
493 59371038 : json_object->WriteToField(i, descriptors->GetDetails(i), *value);
494 : }
495 6882590 : }
496 :
497 : class ElementKindLattice {
498 : private:
499 : enum {
500 : SMI_ELEMENTS,
501 : NUMBER_ELEMENTS,
502 : OBJECT_ELEMENTS,
503 : };
504 :
505 : public:
506 433571 : ElementKindLattice() : value_(SMI_ELEMENTS) {}
507 :
508 6512697 : void Update(Handle<Object> o) {
509 6512697 : if (o->IsSmi()) {
510 6512697 : return;
511 2995072 : } else if (o->IsHeapNumber()) {
512 44 : if (value_ < NUMBER_ELEMENTS) value_ = NUMBER_ELEMENTS;
513 : } else {
514 : DCHECK(!o->IsNumber());
515 2995028 : value_ = OBJECT_ELEMENTS;
516 : }
517 : }
518 :
519 385031 : ElementsKind GetElementsKind() const {
520 385031 : switch (value_) {
521 : case SMI_ELEMENTS:
522 : return PACKED_SMI_ELEMENTS;
523 : case NUMBER_ELEMENTS:
524 22 : return PACKED_DOUBLE_ELEMENTS;
525 : case OBJECT_ELEMENTS:
526 331199 : return PACKED_ELEMENTS;
527 : default:
528 0 : UNREACHABLE();
529 : return PACKED_ELEMENTS;
530 : }
531 : }
532 :
533 : private:
534 : int value_;
535 : };
536 :
537 : // Parse a JSON array. Position must be right at '['.
538 : template <bool seq_one_byte>
539 433571 : Handle<Object> JsonParser<seq_one_byte>::ParseJsonArray() {
540 : HandleScope scope(isolate());
541 433571 : ZoneList<Handle<Object> > elements(4, zone());
542 : DCHECK_EQ(c0_, '[');
543 :
544 : ElementKindLattice lattice;
545 :
546 : AdvanceSkipWhitespace();
547 433571 : if (c0_ != ']') {
548 6512697 : do {
549 6561227 : Handle<Object> element = ParseJsonValue();
550 6561227 : if (element.is_null()) return ReportUnexpectedCharacter();
551 6512697 : elements.Add(element, zone());
552 6512697 : lattice.Update(element);
553 : } while (MatchSkipWhiteSpace(','));
554 332540 : if (c0_ != ']') {
555 : return ReportUnexpectedCharacter();
556 : }
557 : }
558 : AdvanceSkipWhitespace();
559 :
560 : // Allocate a fixed array with all the elements.
561 :
562 : Handle<Object> json_array;
563 385031 : const ElementsKind kind = lattice.GetElementsKind();
564 :
565 385031 : switch (kind) {
566 : case PACKED_ELEMENTS:
567 : case PACKED_SMI_ELEMENTS: {
568 : Handle<FixedArray> elems =
569 770018 : factory()->NewFixedArray(elements.length(), pretenure_);
570 6849180 : for (int i = 0; i < elements.length(); i++) elems->set(i, *elements[i]);
571 770018 : json_array = factory()->NewJSArrayWithElements(elems, kind, pretenure_);
572 : break;
573 : }
574 : case PACKED_DOUBLE_ELEMENTS: {
575 : Handle<FixedDoubleArray> elems = Handle<FixedDoubleArray>::cast(
576 44 : factory()->NewFixedDoubleArray(elements.length(), pretenure_));
577 68 : for (int i = 0; i < elements.length(); i++) {
578 46 : elems->set(i, elements[i]->Number());
579 : }
580 44 : json_array = factory()->NewJSArrayWithElements(elems, kind, pretenure_);
581 : break;
582 : }
583 : default:
584 0 : UNREACHABLE();
585 : }
586 :
587 385031 : return scope.CloseAndEscape(json_array);
588 : }
589 :
590 : template <bool seq_one_byte>
591 5449500 : Handle<Object> JsonParser<seq_one_byte>::ParseJsonNumber() {
592 : bool negative = false;
593 5449500 : int beg_pos = position_;
594 5449500 : if (c0_ == '-') {
595 : Advance();
596 : negative = true;
597 : }
598 5449500 : if (c0_ == '0') {
599 : Advance();
600 : // Prefix zero is only allowed if it's the only digit before
601 : // a decimal point or exponent.
602 1505008 : if (IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
603 : } else {
604 : int i = 0;
605 : int digits = 0;
606 4696996 : if (c0_ < '1' || c0_ > '9') return ReportUnexpectedCharacter();
607 11701357 : do {
608 11701357 : i = i * 10 + c0_ - '0';
609 11701357 : digits++;
610 : Advance();
611 11701357 : } while (IsDecimalDigit(c0_));
612 4696966 : if (c0_ != '.' && c0_ != 'e' && c0_ != 'E' && digits < 10) {
613 : SkipWhitespace();
614 9345534 : return Handle<Smi>(Smi::FromInt((negative ? -i : i)), isolate());
615 : }
616 : }
617 776693 : if (c0_ == '.') {
618 : Advance();
619 248574 : if (!IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
620 156820 : do {
621 : Advance();
622 156820 : } while (IsDecimalDigit(c0_));
623 : }
624 1553326 : if (AsciiAlphaToLower(c0_) == 'e') {
625 : Advance();
626 120 : if (c0_ == '-' || c0_ == '+') Advance();
627 240 : if (!IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
628 80 : do {
629 : Advance();
630 80 : } while (IsDecimalDigit(c0_));
631 : }
632 776613 : int length = position_ - beg_pos;
633 : double number;
634 : if (seq_one_byte) {
635 1448554 : Vector<const uint8_t> chars(seq_source_->GetChars() + beg_pos, length);
636 724277 : number = StringToDouble(isolate()->unicode_cache(), chars,
637 : NO_FLAGS, // Hex, octal or trailing junk.
638 724277 : std::numeric_limits<double>::quiet_NaN());
639 : } else {
640 : Vector<uint8_t> buffer = Vector<uint8_t>::New(length);
641 104672 : String::WriteToFlat(*source_, buffer.start(), beg_pos, position_);
642 : Vector<const uint8_t> result =
643 : Vector<const uint8_t>(buffer.start(), length);
644 52336 : number = StringToDouble(isolate()->unicode_cache(), result,
645 : NO_FLAGS, // Hex, octal or trailing junk.
646 52336 : 0.0);
647 : buffer.Dispose();
648 : }
649 : SkipWhitespace();
650 1553226 : return factory()->NewNumber(number, pretenure_);
651 : }
652 :
653 : template <typename StringType>
654 : inline void SeqStringSet(Handle<StringType> seq_str, int i, uc32 c);
655 :
656 : template <>
657 : inline void SeqStringSet(Handle<SeqTwoByteString> seq_str, int i, uc32 c) {
658 572721 : seq_str->SeqTwoByteStringSet(i, c);
659 : }
660 :
661 : template <>
662 : inline void SeqStringSet(Handle<SeqOneByteString> seq_str, int i, uc32 c) {
663 750893747 : seq_str->SeqOneByteStringSet(i, c);
664 : }
665 :
666 : template <typename StringType>
667 : inline Handle<StringType> NewRawString(Factory* factory, int length,
668 : PretenureFlag pretenure);
669 :
670 : template <>
671 50121 : inline Handle<SeqTwoByteString> NewRawString(Factory* factory, int length,
672 : PretenureFlag pretenure) {
673 100242 : return factory->NewRawTwoByteString(length, pretenure).ToHandleChecked();
674 : }
675 :
676 : template <>
677 6416746 : inline Handle<SeqOneByteString> NewRawString(Factory* factory, int length,
678 : PretenureFlag pretenure) {
679 12833492 : return factory->NewRawOneByteString(length, pretenure).ToHandleChecked();
680 : }
681 :
682 : // Scans the rest of a JSON string starting from position_ and writes
683 : // prefix[start..end] along with the scanned characters into a
684 : // sequential string of type StringType.
685 : template <bool seq_one_byte>
686 : template <typename StringType, typename SinkChar>
687 6466867 : Handle<String> JsonParser<seq_one_byte>::SlowScanJsonString(
688 : Handle<String> prefix, int start, int end) {
689 6466867 : int count = end - start;
690 6466867 : int max_length = count + source_length_ - position_;
691 6466867 : int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count));
692 : Handle<StringType> seq_string =
693 12933734 : NewRawString<StringType>(factory(), length, pretenure_);
694 : // Copy prefix into seq_str.
695 6466867 : SinkChar* dest = seq_string->GetChars();
696 6466867 : String::WriteToFlat(*prefix, dest, start, end);
697 :
698 786581230 : while (c0_ != '"') {
699 : // Check for control character (0x00-0x1f) or unterminated string (<0).
700 776682319 : if (c0_ < 0x20) return Handle<String>::null();
701 776682269 : if (count >= length) {
702 : // We need to create a longer sequential string for the result.
703 3034608 : return SlowScanJsonString<StringType, SinkChar>(seq_string, 0, count);
704 : }
705 773647661 : if (c0_ != '\\') {
706 : // If the sink can contain UC16 characters, or source_ contains only
707 : // Latin1 characters, there's no need to test whether we can store the
708 : // character. Otherwise check whether the UC16 source character can fit
709 : // in the Latin1 sink.
710 38670 : if (sizeof(SinkChar) == kUC16Size || seq_one_byte ||
711 : c0_ <= String::kMaxOneByteCharCode) {
712 736103983 : SeqStringSet(seq_string, count++, c0_);
713 : Advance();
714 : } else {
715 : // StringType is SeqOneByteString and we just read a non-Latin1 char.
716 10 : return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0, count);
717 : }
718 : } else {
719 : Advance(); // Advance past the \.
720 37543668 : switch (c0_) {
721 : case '"':
722 : case '\\':
723 : case '/':
724 15362325 : SeqStringSet(seq_string, count++, c0_);
725 : break;
726 : case 'b':
727 15 : SeqStringSet(seq_string, count++, '\x08');
728 : break;
729 : case 'f':
730 10 : SeqStringSet(seq_string, count++, '\x0c');
731 : break;
732 : case 'n':
733 22180978 : SeqStringSet(seq_string, count++, '\x0a');
734 : break;
735 : case 'r':
736 15 : SeqStringSet(seq_string, count++, '\x0d');
737 : break;
738 : case 't':
739 10 : SeqStringSet(seq_string, count++, '\x09');
740 : break;
741 : case 'u': {
742 : uc32 value = 0;
743 1050 : for (int i = 0; i < 4; i++) {
744 : Advance();
745 1060 : int digit = HexValue(c0_);
746 1060 : if (digit < 0) {
747 : return Handle<String>::null();
748 : }
749 1050 : value = value * 16 + digit;
750 : }
751 110 : if (sizeof(SinkChar) == kUC16Size ||
752 : value <= String::kMaxOneByteCharCode) {
753 160 : SeqStringSet(seq_string, count++, value);
754 : break;
755 : } else {
756 : // StringType is SeqOneByteString and we just read a non-Latin1
757 : // char.
758 95 : position_ -= 6; // Rewind position_ to \ in \uxxxx.
759 : Advance();
760 95 : return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0,
761 95 : count);
762 : }
763 : }
764 : default:
765 : return Handle<String>::null();
766 : }
767 : Advance();
768 : }
769 : }
770 :
771 : DCHECK_EQ('"', c0_);
772 : // Advance past the last '"'.
773 : AdvanceSkipWhitespace();
774 :
775 : // Shrink seq_string length to count and return.
776 3432044 : return SeqString::Truncate(seq_string, count);
777 : }
778 :
779 : template <bool seq_one_byte>
780 : template <bool is_internalized>
781 25444512 : Handle<String> JsonParser<seq_one_byte>::ScanJsonString() {
782 : DCHECK_EQ('"', c0_);
783 : Advance();
784 25444512 : if (c0_ == '"') {
785 : AdvanceSkipWhitespace();
786 : return factory()->empty_string();
787 : }
788 :
789 : if (seq_one_byte && is_internalized) {
790 : // Fast path for existing internalized strings. If the the string being
791 : // parsed is not a known internalized string, contains backslashes or
792 : // unexpectedly reaches the end of string, return with an empty handle.
793 :
794 : // We intentionally use local variables instead of fields, compute hash
795 : // while we are iterating a string and manually inline StringTable lookup
796 : // here.
797 : uint32_t running_hash = isolate()->heap()->HashSeed();
798 10435434 : int position = position_;
799 : uc32 c0 = c0_;
800 62497943 : do {
801 62498003 : if (c0 == '\\') {
802 30 : c0_ = c0;
803 : int beg_pos = position_;
804 30 : position_ = position;
805 : return SlowScanJsonString<SeqOneByteString, uint8_t>(source_, beg_pos,
806 30 : position_);
807 : }
808 62497973 : if (c0 < 0x20) {
809 20 : c0_ = c0;
810 20 : position_ = position;
811 : return Handle<String>::null();
812 : }
813 : running_hash = StringHasher::AddCharacterCore(running_hash,
814 62497953 : static_cast<uint16_t>(c0));
815 62497953 : position++;
816 62497953 : if (position >= source_length_) {
817 10 : c0_ = kEndOfString;
818 10 : position_ = position;
819 : return Handle<String>::null();
820 : }
821 62497943 : c0 = seq_source_->SeqOneByteStringGet(position);
822 : } while (c0 != '"');
823 10435374 : int length = position - position_;
824 : uint32_t hash = (length <= String::kMaxHashCalcLength)
825 : ? StringHasher::GetHashCore(running_hash)
826 10435374 : : static_cast<uint32_t>(length);
827 10435374 : Vector<const uint8_t> string_vector(seq_source_->GetChars() + position_,
828 20870748 : length);
829 10435374 : StringTable* string_table = isolate()->heap()->string_table();
830 10435374 : uint32_t capacity = string_table->Capacity();
831 : uint32_t entry = StringTable::FirstProbe(hash, capacity);
832 : uint32_t count = 1;
833 : Handle<String> result;
834 : while (true) {
835 12623873 : Object* element = string_table->KeyAt(entry);
836 12623873 : if (element->IsUndefined(isolate())) {
837 : // Lookup failure.
838 224008 : result =
839 : factory()->InternalizeOneByteString(seq_source_, position_, length);
840 112004 : break;
841 : }
842 24839538 : if (!element->IsTheHole(isolate()) &&
843 12327669 : String::cast(element)->IsOneByteEqualTo(string_vector)) {
844 : result = Handle<String>(String::cast(element), isolate());
845 : #ifdef DEBUG
846 : uint32_t hash_field =
847 : (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
848 : DCHECK_EQ(static_cast<int>(result->Hash()),
849 : static_cast<int>(hash_field >> String::kHashShift));
850 : #endif
851 10323370 : break;
852 : }
853 2188499 : entry = StringTable::NextProbe(entry, count++, capacity);
854 : }
855 10435374 : position_ = position;
856 : // Advance past the last '"'.
857 : AdvanceSkipWhitespace();
858 12623873 : return result;
859 : }
860 :
861 14874594 : int beg_pos = position_;
862 : // Fast case for Latin1 only without escape characters.
863 174389816 : do {
864 : // Check for control character (0x00-0x1f) or unterminated string (<0).
865 177821970 : if (c0_ < 0x20) return Handle<String>::null();
866 177821940 : if (c0_ != '\\') {
867 890015 : if (seq_one_byte || c0_ <= String::kMaxOneByteCharCode) {
868 : Advance();
869 : } else {
870 50016 : return SlowScanJsonString<SeqTwoByteString, uc16>(source_, beg_pos,
871 50016 : position_);
872 : }
873 : } else {
874 3382108 : return SlowScanJsonString<SeqOneByteString, uint8_t>(source_, beg_pos,
875 3382108 : position_);
876 : }
877 : } while (c0_ != '"');
878 11442440 : int length = position_ - beg_pos;
879 : Handle<String> result =
880 34327320 : factory()->NewRawOneByteString(length, pretenure_).ToHandleChecked();
881 11442440 : uint8_t* dest = SeqOneByteString::cast(*result)->GetChars();
882 22884880 : String::WriteToFlat(*source_, dest, beg_pos, position_);
883 :
884 : DCHECK_EQ('"', c0_);
885 : // Advance past the last '"'.
886 : AdvanceSkipWhitespace();
887 11442440 : return result;
888 : }
889 :
890 : // Explicit instantiation.
891 : template class JsonParser<true>;
892 : template class JsonParser<false>;
893 :
894 : } // namespace internal
895 : } // namespace v8
|