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/transitions.h"
17 : #include "src/unicode-cache.h"
18 :
19 : namespace v8 {
20 : namespace internal {
21 :
22 218 : MaybeHandle<Object> JsonParseInternalizer::Internalize(Isolate* isolate,
23 : Handle<Object> object,
24 : Handle<Object> reviver) {
25 : DCHECK(reviver->IsCallable());
26 : JsonParseInternalizer internalizer(isolate,
27 : Handle<JSReceiver>::cast(reviver));
28 : Handle<JSObject> holder =
29 218 : isolate->factory()->NewJSObject(isolate->object_function());
30 : Handle<String> name = isolate->factory()->empty_string();
31 218 : JSObject::AddProperty(holder, name, object, NONE);
32 218 : return internalizer.InternalizeJsonProperty(holder, name);
33 : }
34 :
35 68579 : MaybeHandle<Object> JsonParseInternalizer::InternalizeJsonProperty(
36 : Handle<JSReceiver> holder, Handle<String> name) {
37 68579 : HandleScope outer_scope(isolate_);
38 : Handle<Object> value;
39 137158 : ASSIGN_RETURN_ON_EXCEPTION(
40 : isolate_, value, Object::GetPropertyOrElement(holder, name), Object);
41 68579 : if (value->IsJSReceiver()) {
42 : Handle<JSReceiver> object = Handle<JSReceiver>::cast(value);
43 34174 : Maybe<bool> is_array = Object::IsArray(object);
44 68042 : if (is_array.IsNothing()) return MaybeHandle<Object>();
45 34174 : if (is_array.FromJust()) {
46 : Handle<Object> length_object;
47 67936 : ASSIGN_RETURN_ON_EXCEPTION(
48 : isolate_, length_object,
49 : Object::GetLengthFromArrayLike(isolate_, object), Object);
50 : double length = length_object->Number();
51 68080 : for (double i = 0; i < length; i++) {
52 67980 : HandleScope inner_scope(isolate_);
53 67980 : Handle<Object> index = isolate_->factory()->NewNumber(i);
54 67980 : Handle<String> name = isolate_->factory()->NumberToString(index);
55 67980 : if (!RecurseAndApply(object, name)) return MaybeHandle<Object>();
56 : }
57 : } else {
58 : Handle<FixedArray> contents;
59 412 : ASSIGN_RETURN_ON_EXCEPTION(
60 : isolate_, contents,
61 : KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly,
62 : ENUMERABLE_STRINGS,
63 : GetKeysConversion::kConvertToString),
64 : Object);
65 968 : for (int i = 0; i < contents->length(); i++) {
66 381 : HandleScope inner_scope(isolate_);
67 381 : Handle<String> name(String::cast(contents->get(i)), isolate_);
68 381 : if (!RecurseAndApply(object, name)) return MaybeHandle<Object>();
69 : }
70 : }
71 : }
72 34711 : Handle<Object> argv[] = {name, value};
73 : Handle<Object> result;
74 69422 : ASSIGN_RETURN_ON_EXCEPTION(
75 : isolate_, result, Execution::Call(isolate_, reviver_, holder, 2, argv),
76 : Object);
77 34697 : return outer_scope.CloseAndEscape(result);
78 : }
79 :
80 68361 : bool JsonParseInternalizer::RecurseAndApply(Handle<JSReceiver> holder,
81 : Handle<String> name) {
82 : Handle<Object> result;
83 136722 : ASSIGN_RETURN_ON_EXCEPTION_VALUE(
84 : isolate_, result, InternalizeJsonProperty(holder, name), false);
85 : Maybe<bool> change_result = Nothing<bool>();
86 68986 : if (result->IsUndefined(isolate_)) {
87 146 : change_result = JSReceiver::DeletePropertyOrElement(holder, name, SLOPPY);
88 : } else {
89 : PropertyDescriptor desc;
90 : desc.set_value(result);
91 : desc.set_configurable(true);
92 : desc.set_enumerable(true);
93 : desc.set_writable(true);
94 : change_result = JSReceiver::DefineOwnProperty(isolate_, holder, name, &desc,
95 34347 : Object::DONT_THROW);
96 : }
97 34493 : MAYBE_RETURN(change_result, false);
98 34493 : return true;
99 : }
100 :
101 : template <bool seq_one_byte>
102 692509 : JsonParser<seq_one_byte>::JsonParser(Isolate* isolate, Handle<String> source)
103 : : source_(source),
104 : source_length_(source->length()),
105 : isolate_(isolate),
106 692509 : factory_(isolate_->factory()),
107 : zone_(isolate_->allocator(), ZONE_NAME),
108 692509 : object_constructor_(isolate_->native_context()->object_function(),
109 : isolate_),
110 4155054 : position_(-1) {
111 692509 : source_ = String::Flatten(source_);
112 692509 : pretenure_ = (source_length_ >= kPretenureTreshold) ? TENURED : NOT_TENURED;
113 :
114 : // Optimized fast case where we only have Latin1 characters.
115 : if (seq_one_byte) {
116 692456 : seq_source_ = Handle<SeqOneByteString>::cast(source_);
117 : }
118 692509 : }
119 :
120 : template <bool seq_one_byte>
121 692509 : MaybeHandle<Object> JsonParser<seq_one_byte>::ParseJson() {
122 : // Advance to the first character (possibly EOS)
123 : AdvanceSkipWhitespace();
124 692509 : Handle<Object> result = ParseJsonValue();
125 692509 : if (result.is_null() || c0_ != kEndOfString) {
126 : // Some exception (for example stack overflow) is already pending.
127 1068 : if (isolate_->has_pending_exception()) return Handle<Object>::null();
128 :
129 : // Parse failed. Current character is the unexpected token.
130 : Factory* factory = this->factory();
131 : MessageTemplate::Template message;
132 1024 : Handle<Object> arg1 = Handle<Smi>(Smi::FromInt(position_), isolate());
133 : Handle<Object> arg2;
134 :
135 1024 : switch (c0_) {
136 : case kEndOfString:
137 : message = MessageTemplate::kJsonParseUnexpectedEOS;
138 : break;
139 : case '-':
140 : case '0':
141 : case '1':
142 : case '2':
143 : case '3':
144 : case '4':
145 : case '5':
146 : case '6':
147 : case '7':
148 : case '8':
149 : case '9':
150 : message = MessageTemplate::kJsonParseUnexpectedTokenNumber;
151 150 : break;
152 : case '"':
153 : message = MessageTemplate::kJsonParseUnexpectedTokenString;
154 195 : break;
155 : default:
156 : message = MessageTemplate::kJsonParseUnexpectedToken;
157 484 : arg2 = arg1;
158 484 : arg1 = factory->LookupSingleCharacterStringFromCode(c0_);
159 484 : break;
160 : }
161 :
162 1024 : Handle<Script> script(factory->NewScript(source_));
163 : // We should sent compile error event because we compile JSON object in
164 : // separated source file.
165 1024 : isolate()->debug()->OnCompileError(script);
166 1024 : MessageLocation location(script, position_, position_ + 1);
167 1024 : Handle<Object> error = factory->NewSyntaxError(message, arg1, arg2);
168 : return isolate()->template Throw<Object>(error, &location);
169 : }
170 : return result;
171 : }
172 :
173 : MaybeHandle<Object> InternalizeJsonProperty(Handle<JSObject> holder,
174 : Handle<String> key);
175 :
176 : template <bool seq_one_byte>
177 0 : void JsonParser<seq_one_byte>::Advance() {
178 1763647465 : position_++;
179 1763647465 : if (position_ >= source_length_) {
180 691621 : c0_ = kEndOfString;
181 : } else if (seq_one_byte) {
182 1755638267 : c0_ = seq_source_->SeqOneByteStringGet(position_);
183 : } else {
184 7317577 : c0_ = source_->Get(position_);
185 : }
186 0 : }
187 :
188 : template <bool seq_one_byte>
189 0 : void JsonParser<seq_one_byte>::AdvanceSkipWhitespace() {
190 184128639 : do {
191 : Advance();
192 : } while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r');
193 0 : }
194 :
195 : template <bool seq_one_byte>
196 0 : void JsonParser<seq_one_byte>::SkipWhitespace() {
197 4064299 : while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r') {
198 : Advance();
199 : }
200 0 : }
201 :
202 : template <bool seq_one_byte>
203 0 : uc32 JsonParser<seq_one_byte>::AdvanceGetChar() {
204 : Advance();
205 45006525 : return c0_;
206 : }
207 :
208 : template <bool seq_one_byte>
209 0 : bool JsonParser<seq_one_byte>::MatchSkipWhiteSpace(uc32 c) {
210 49105181 : if (c0_ == c) {
211 : AdvanceSkipWhitespace();
212 : return true;
213 : }
214 : return false;
215 : }
216 :
217 : template <bool seq_one_byte>
218 28264531 : bool JsonParser<seq_one_byte>::ParseJsonString(Handle<String> expected) {
219 : int length = expected->length();
220 28264531 : if (source_->length() - position_ - 1 > length) {
221 : DisallowHeapAllocation no_gc;
222 28264531 : String::FlatContent content = expected->GetFlatContent();
223 28264531 : if (content.IsOneByte()) {
224 : DCHECK_EQ('"', c0_);
225 28264531 : const uint8_t* input_chars = seq_source_->GetChars() + position_ + 1;
226 28264531 : const uint8_t* expected_chars = content.ToOneByteVector().start();
227 273124829 : for (int i = 0; i < length; i++) {
228 244867361 : uint8_t c0 = input_chars[i];
229 244867361 : if (c0 != expected_chars[i] || c0 == '"' || c0 < 0x20 || c0 == '\\') {
230 28264525 : return false;
231 : }
232 : }
233 28257468 : if (input_chars[length] == '"') {
234 28257462 : position_ = position_ + length + 1;
235 : AdvanceSkipWhitespace();
236 : return true;
237 : }
238 : }
239 : }
240 : return false;
241 : }
242 :
243 : // Parse any JSON value.
244 : template <bool seq_one_byte>
245 49876556 : Handle<Object> JsonParser<seq_one_byte>::ParseJsonValue() {
246 49876556 : StackLimitCheck stack_check(isolate_);
247 49876556 : if (stack_check.HasOverflowed()) {
248 44 : isolate_->StackOverflow();
249 : return Handle<Object>::null();
250 : }
251 :
252 49876706 : if (stack_check.InterruptRequested() &&
253 194 : isolate_->stack_guard()->HandleInterrupts()->IsException(isolate_)) {
254 : return Handle<Object>::null();
255 : }
256 :
257 71301489 : if (c0_ == '"') return ParseJsonString();
258 28451535 : if ((c0_ >= '0' && c0_ <= '9') || c0_ == '-') return ParseJsonNumber();
259 24678771 : if (c0_ == '{') return ParseJsonObject();
260 14588392 : if (c0_ == '[') return ParseJsonArray();
261 13992559 : if (c0_ == 'f') {
262 12116939 : if (AdvanceGetChar() == 'a' && AdvanceGetChar() == 'l' &&
263 : AdvanceGetChar() == 's' && AdvanceGetChar() == 'e') {
264 : AdvanceSkipWhitespace();
265 3029231 : return factory()->false_value();
266 : }
267 : return ReportUnexpectedCharacter();
268 : }
269 10963313 : if (c0_ == 't') {
270 32878947 : if (AdvanceGetChar() == 'r' && AdvanceGetChar() == 'u' &&
271 : AdvanceGetChar() == 'e') {
272 : AdvanceSkipWhitespace();
273 10959649 : return factory()->true_value();
274 : }
275 : return ReportUnexpectedCharacter();
276 : }
277 3664 : if (c0_ == 'n') {
278 10639 : if (AdvanceGetChar() == 'u' && AdvanceGetChar() == 'l' &&
279 : AdvanceGetChar() == 'l') {
280 : AdvanceSkipWhitespace();
281 3546 : return factory()->null_value();
282 : }
283 : return ReportUnexpectedCharacter();
284 : }
285 : return ReportUnexpectedCharacter();
286 : }
287 :
288 : template <bool seq_one_byte>
289 264494 : ParseElementResult JsonParser<seq_one_byte>::ParseElement(
290 : Handle<JSObject> json_object) {
291 : uint32_t index = 0;
292 : // Maybe an array index, try to parse it.
293 264494 : if (c0_ == '0') {
294 : // With a leading zero, the string has to be "0" only to be an index.
295 : Advance();
296 : } else {
297 584055 : do {
298 584070 : int d = c0_ - '0';
299 584070 : if (index > 429496729U - ((d + 3) >> 3)) break;
300 584055 : index = (index * 10) + d;
301 : Advance();
302 584055 : } while (IsDecimalDigit(c0_));
303 : }
304 :
305 264494 : if (c0_ == '"') {
306 : // Successfully parsed index, parse and store element.
307 : AdvanceSkipWhitespace();
308 :
309 264419 : if (c0_ == ':') {
310 : AdvanceSkipWhitespace();
311 264419 : Handle<Object> value = ParseJsonValue();
312 264419 : if (!value.is_null()) {
313 : JSObject::SetOwnElementIgnoreAttributes(json_object, index, value, NONE)
314 264404 : .Assert();
315 264404 : return kElementFound;
316 : } else {
317 : return kNullHandle;
318 : }
319 : }
320 : }
321 : return kElementNotFound;
322 : }
323 :
324 : // Parse a JSON object. Position must be right at '{'.
325 : template <bool seq_one_byte>
326 10090379 : Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() {
327 : HandleScope scope(isolate());
328 : Handle<JSObject> json_object =
329 20180758 : factory()->NewJSObject(object_constructor(), pretenure_);
330 : Handle<Map> map(json_object->map());
331 : int descriptor = 0;
332 10090379 : ZoneList<Handle<Object> > properties(8, zone());
333 : DCHECK_EQ(c0_, '{');
334 :
335 : bool transitioning = true;
336 :
337 : AdvanceSkipWhitespace();
338 10090379 : if (c0_ != '}') {
339 86536444 : do {
340 43341622 : if (c0_ != '"') return ReportUnexpectedCharacter();
341 :
342 43341210 : int start_position = position_;
343 : Advance();
344 :
345 86682420 : if (IsDecimalDigit(c0_)) {
346 264494 : ParseElementResult element_result = ParseElement(json_object);
347 264494 : if (element_result == kNullHandle) return Handle<Object>::null();
348 43459855 : if (element_result == kElementFound) continue;
349 : }
350 : // Not an index, fallback to the slow path.
351 :
352 43076791 : position_ = start_position;
353 : #ifdef DEBUG
354 : c0_ = '"';
355 : #endif
356 :
357 : Handle<String> key;
358 : Handle<Object> value;
359 :
360 : // Try to follow existing transitions as long as possible. Once we stop
361 : // transitioning, no transition can be found anymore.
362 : DCHECK(transitioning);
363 : // First check whether there is a single expected transition. If so, try
364 : // to parse it first.
365 : bool follow_expected = false;
366 : Handle<Map> target;
367 : if (seq_one_byte) {
368 42976723 : key = TransitionArray::ExpectedTransitionKey(map);
369 42976723 : follow_expected = !key.is_null() && ParseJsonString(key);
370 : }
371 : // If the expected transition hits, follow it.
372 42976723 : if (follow_expected) {
373 28257462 : target = TransitionArray::ExpectedTransitionTarget(map);
374 : } else {
375 : // If the expected transition failed, parse an internalized string and
376 : // try to find a matching transition.
377 14819329 : key = ParseJsonInternalizedString();
378 14819329 : if (key.is_null()) return ReportUnexpectedCharacter();
379 :
380 14819224 : target = TransitionArray::FindTransitionToField(map, key);
381 : // If a transition was found, follow it and continue.
382 14819224 : transitioning = !target.is_null();
383 : }
384 43076686 : if (c0_ != ':') return ReportUnexpectedCharacter();
385 :
386 : AdvanceSkipWhitespace();
387 43076686 : value = ParseJsonValue();
388 43076686 : if (value.is_null()) return ReportUnexpectedCharacter();
389 :
390 43076664 : if (transitioning) {
391 : PropertyDetails details =
392 42935249 : target->instance_descriptors()->GetDetails(descriptor);
393 : Representation expected_representation = details.representation();
394 :
395 42935249 : if (value->FitsRepresentation(expected_representation)) {
396 83492391 : if (expected_representation.IsHeapObject() &&
397 : !target->instance_descriptors()
398 : ->GetFieldType(descriptor)
399 40561419 : ->NowContains(value)) {
400 : Handle<FieldType> value_type(
401 18742 : value->OptimalType(isolate(), expected_representation));
402 18742 : Map::GeneralizeField(target, descriptor, details.constness(),
403 : expected_representation, value_type);
404 : }
405 : DCHECK(target->instance_descriptors()
406 : ->GetFieldType(descriptor)
407 : ->NowContains(value));
408 : properties.Add(value, zone());
409 42930972 : map = target;
410 42930972 : descriptor++;
411 : continue;
412 : } else {
413 : transitioning = false;
414 : }
415 : }
416 :
417 : DCHECK(!transitioning);
418 :
419 : // Commit the intermediate state to the object and stop transitioning.
420 145692 : CommitStateToJsonObject(json_object, map, &properties);
421 :
422 : JSObject::DefinePropertyOrElementIgnoreAttributes(json_object, key, value)
423 291384 : .Check();
424 : } while (transitioning && MatchSkipWhiteSpace(','));
425 :
426 : // If we transitioned until the very end, transition the map now.
427 9944865 : if (transitioning) {
428 9799173 : CommitStateToJsonObject(json_object, map, &properties);
429 : } else {
430 527958 : while (MatchSkipWhiteSpace(',')) {
431 : HandleScope local_scope(isolate());
432 382266 : if (c0_ != '"') return ReportUnexpectedCharacter();
433 :
434 382266 : int start_position = position_;
435 : Advance();
436 :
437 764532 : if (IsDecimalDigit(c0_)) {
438 0 : ParseElementResult element_result = ParseElement(json_object);
439 0 : if (element_result == kNullHandle) return Handle<Object>::null();
440 0 : if (element_result == kElementFound) continue;
441 : }
442 : // Not an index, fallback to the slow path.
443 :
444 382266 : position_ = start_position;
445 : #ifdef DEBUG
446 : c0_ = '"';
447 : #endif
448 :
449 : Handle<String> key;
450 : Handle<Object> value;
451 :
452 382266 : key = ParseJsonInternalizedString();
453 382266 : if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter();
454 :
455 : AdvanceSkipWhitespace();
456 382266 : value = ParseJsonValue();
457 382266 : if (value.is_null()) return ReportUnexpectedCharacter();
458 :
459 : JSObject::DefinePropertyOrElementIgnoreAttributes(json_object, key,
460 : value)
461 764532 : .Check();
462 : }
463 : }
464 :
465 9944865 : if (c0_ != '}') {
466 : return ReportUnexpectedCharacter();
467 : }
468 : }
469 : AdvanceSkipWhitespace();
470 10090087 : return scope.CloseAndEscape(json_object);
471 : }
472 :
473 : template <bool seq_one_byte>
474 9944865 : void JsonParser<seq_one_byte>::CommitStateToJsonObject(
475 : Handle<JSObject> json_object, Handle<Map> map,
476 : ZoneList<Handle<Object> >* properties) {
477 9944865 : JSObject::AllocateStorageForMap(json_object, map);
478 : DCHECK(!json_object->map()->is_dictionary_map());
479 :
480 : DisallowHeapAllocation no_gc;
481 : DescriptorArray* descriptors = json_object->map()->instance_descriptors();
482 52875813 : int length = properties->length();
483 52875813 : for (int i = 0; i < length; i++) {
484 42930948 : Handle<Object> value = (*properties)[i];
485 : // Initializing store.
486 85861896 : json_object->WriteToField(i, descriptors->GetDetails(i), *value);
487 : }
488 9944865 : }
489 :
490 : // Parse a JSON array. Position must be right at '['.
491 : template <bool seq_one_byte>
492 595833 : Handle<Object> JsonParser<seq_one_byte>::ParseJsonArray() {
493 : HandleScope scope(isolate());
494 595833 : ZoneList<Handle<Object> > elements(4, zone());
495 : DCHECK_EQ(c0_, '[');
496 :
497 : AdvanceSkipWhitespace();
498 595833 : if (c0_ != ']') {
499 5381847 : do {
500 5460676 : Handle<Object> element = ParseJsonValue();
501 5460676 : if (element.is_null()) return ReportUnexpectedCharacter();
502 : elements.Add(element, zone());
503 : } while (MatchSkipWhiteSpace(','));
504 438675 : if (c0_ != ']') {
505 : return ReportUnexpectedCharacter();
506 : }
507 : }
508 : AdvanceSkipWhitespace();
509 : // Allocate a fixed array with all the elements.
510 : Handle<FixedArray> fast_elements =
511 1033978 : factory()->NewFixedArray(elements.length(), pretenure_);
512 5820085 : for (int i = 0, n = elements.length(); i < n; i++) {
513 10606192 : fast_elements->set(i, *elements[i]);
514 : }
515 : Handle<Object> json_array = factory()->NewJSArrayWithElements(
516 516989 : fast_elements, FAST_ELEMENTS, pretenure_);
517 516989 : return scope.CloseAndEscape(json_array);
518 : }
519 :
520 : template <bool seq_one_byte>
521 3772764 : Handle<Object> JsonParser<seq_one_byte>::ParseJsonNumber() {
522 : bool negative = false;
523 3772764 : int beg_pos = position_;
524 3772764 : if (c0_ == '-') {
525 : Advance();
526 : negative = true;
527 : }
528 3772764 : if (c0_ == '0') {
529 : Advance();
530 : // Prefix zero is only allowed if it's the only digit before
531 : // a decimal point or exponent.
532 1551238 : if (IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
533 : } else {
534 : int i = 0;
535 : int digits = 0;
536 2997145 : if (c0_ < '1' || c0_ > '9') return ReportUnexpectedCharacter();
537 6350546 : do {
538 6350546 : i = i * 10 + c0_ - '0';
539 6350546 : digits++;
540 : Advance();
541 6350546 : } while (IsDecimalDigit(c0_));
542 2997100 : if (c0_ != '.' && c0_ != 'e' && c0_ != 'E' && digits < 10) {
543 : SkipWhitespace();
544 5939800 : return Handle<Smi>(Smi::FromInt((negative ? -i : i)), isolate());
545 : }
546 : }
547 802804 : if (c0_ == '.') {
548 : Advance();
549 354676 : if (!IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
550 207995 : do {
551 : Advance();
552 207995 : } while (IsDecimalDigit(c0_));
553 : }
554 1605518 : if (AsciiAlphaToLower(c0_) == 'e') {
555 : Advance();
556 165 : if (c0_ == '-' || c0_ == '+') Advance();
557 330 : if (!IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
558 90 : do {
559 : Advance();
560 90 : } while (IsDecimalDigit(c0_));
561 : }
562 802684 : int length = position_ - beg_pos;
563 : double number;
564 : if (seq_one_byte) {
565 730157 : Vector<const uint8_t> chars(seq_source_->GetChars() + beg_pos, length);
566 730157 : number = StringToDouble(isolate()->unicode_cache(), chars,
567 : NO_FLAGS, // Hex, octal or trailing junk.
568 730157 : std::numeric_limits<double>::quiet_NaN());
569 : } else {
570 : Vector<uint8_t> buffer = Vector<uint8_t>::New(length);
571 145054 : String::WriteToFlat(*source_, buffer.start(), beg_pos, position_);
572 : Vector<const uint8_t> result =
573 : Vector<const uint8_t>(buffer.start(), length);
574 72527 : number = StringToDouble(isolate()->unicode_cache(), result,
575 : NO_FLAGS, // Hex, octal or trailing junk.
576 72527 : 0.0);
577 : buffer.Dispose();
578 : }
579 : SkipWhitespace();
580 1605368 : return factory()->NewNumber(number, pretenure_);
581 : }
582 :
583 : template <typename StringType>
584 : inline void SeqStringSet(Handle<StringType> seq_str, int i, uc32 c);
585 :
586 : template <>
587 : inline void SeqStringSet(Handle<SeqTwoByteString> seq_str, int i, uc32 c) {
588 571509 : seq_str->SeqTwoByteStringSet(i, c);
589 : }
590 :
591 : template <>
592 : inline void SeqStringSet(Handle<SeqOneByteString> seq_str, int i, uc32 c) {
593 1128083910 : seq_str->SeqOneByteStringSet(i, c);
594 : }
595 :
596 : template <typename StringType>
597 : inline Handle<StringType> NewRawString(Factory* factory, int length,
598 : PretenureFlag pretenure);
599 :
600 : template <>
601 50057 : inline Handle<SeqTwoByteString> NewRawString(Factory* factory, int length,
602 : PretenureFlag pretenure) {
603 100114 : return factory->NewRawTwoByteString(length, pretenure).ToHandleChecked();
604 : }
605 :
606 : template <>
607 9251255 : inline Handle<SeqOneByteString> NewRawString(Factory* factory, int length,
608 : PretenureFlag pretenure) {
609 18502510 : return factory->NewRawOneByteString(length, pretenure).ToHandleChecked();
610 : }
611 :
612 : // Scans the rest of a JSON string starting from position_ and writes
613 : // prefix[start..end] along with the scanned characters into a
614 : // sequential string of type StringType.
615 : template <bool seq_one_byte>
616 : template <typename StringType, typename SinkChar>
617 9301312 : Handle<String> JsonParser<seq_one_byte>::SlowScanJsonString(
618 : Handle<String> prefix, int start, int end) {
619 9301312 : int count = end - start;
620 9301312 : int max_length = count + source_length_ - position_;
621 9301312 : int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count));
622 : Handle<StringType> seq_string =
623 18602624 : NewRawString<StringType>(factory(), length, pretenure_);
624 : // Copy prefix into seq_str.
625 9301312 : SinkChar* dest = seq_string->GetChars();
626 9301312 : String::WriteToFlat(*prefix, dest, start, end);
627 :
628 1179031199 : while (c0_ != '"') {
629 : // Check for control character (0x00-0x1f) or unterminated string (<0).
630 1164701115 : if (c0_ < 0x20) return Handle<String>::null();
631 1164701040 : if (count >= length) {
632 : // We need to create a longer sequential string for the result.
633 4272339 : return SlowScanJsonString<StringType, SinkChar>(seq_string, 0, count);
634 : }
635 1160428701 : if (c0_ != '\\') {
636 : // If the sink can contain UC16 characters, or source_ contains only
637 : // Latin1 characters, there's no need to test whether we can store the
638 : // character. Otherwise check whether the UC16 source character can fit
639 : // in the Latin1 sink.
640 78273 : if (sizeof(SinkChar) == kUC16Size || seq_one_byte ||
641 : c0_ <= String::kMaxOneByteCharCode) {
642 1103468998 : SeqStringSet(seq_string, count++, c0_);
643 : Advance();
644 : } else {
645 : // StringType is SeqOneByteString and we just read a non-Latin1 char.
646 15 : return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0, count);
647 : }
648 : } else {
649 : Advance(); // Advance past the \.
650 56959688 : switch (c0_) {
651 : case '"':
652 : case '\\':
653 : case '/':
654 22771529 : SeqStringSet(seq_string, count++, c0_);
655 : break;
656 : case 'b':
657 21 : SeqStringSet(seq_string, count++, '\x08');
658 : break;
659 : case 'f':
660 15 : SeqStringSet(seq_string, count++, '\x0c');
661 : break;
662 : case 'n':
663 31773084 : SeqStringSet(seq_string, count++, '\x0a');
664 : break;
665 : case 'r':
666 21 : SeqStringSet(seq_string, count++, '\x0d');
667 : break;
668 : case 't':
669 15 : SeqStringSet(seq_string, count++, '\x09');
670 : break;
671 : case 'u': {
672 : uc32 value = 0;
673 9659697 : for (int i = 0; i < 4; i++) {
674 : Advance();
675 9659712 : int digit = HexValue(c0_);
676 9659712 : if (digit < 0) {
677 : return Handle<String>::null();
678 : }
679 9659697 : value = value * 16 + digit;
680 : }
681 2414880 : if (sizeof(SinkChar) == kUC16Size ||
682 : value <= String::kMaxOneByteCharCode) {
683 2414892 : SeqStringSet(seq_string, count++, value);
684 : break;
685 : } else {
686 : // StringType is SeqOneByteString and we just read a non-Latin1
687 : // char.
688 21 : position_ -= 6; // Rewind position_ to \ in \uxxxx.
689 : Advance();
690 21 : return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0,
691 21 : count);
692 : }
693 : }
694 : default:
695 : return Handle<String>::null();
696 : }
697 : Advance();
698 : }
699 : }
700 :
701 : DCHECK_EQ('"', c0_);
702 : // Advance past the last '"'.
703 : AdvanceSkipWhitespace();
704 :
705 : // Shrink seq_string length to count and return.
706 5028772 : return SeqString::Truncate(seq_string, count);
707 : }
708 :
709 : template <bool seq_one_byte>
710 : template <bool is_internalized>
711 36626572 : Handle<String> JsonParser<seq_one_byte>::ScanJsonString() {
712 : DCHECK_EQ('"', c0_);
713 : Advance();
714 36626572 : if (c0_ == '"') {
715 : AdvanceSkipWhitespace();
716 : return factory()->empty_string();
717 : }
718 :
719 : if (seq_one_byte && is_internalized) {
720 : // Fast path for existing internalized strings. If the the string being
721 : // parsed is not a known internalized string, contains backslashes or
722 : // unexpectedly reaches the end of string, return with an empty handle.
723 :
724 : // We intentionally use local variables instead of fields, compute hash
725 : // while we are iterating a string and manually inline StringTable lookup
726 : // here.
727 : uint32_t running_hash = isolate()->heap()->HashSeed();
728 15051436 : int position = position_;
729 : uc32 c0 = c0_;
730 90004030 : do {
731 90004120 : if (c0 == '\\') {
732 45 : c0_ = c0;
733 : int beg_pos = position_;
734 45 : position_ = position;
735 : return SlowScanJsonString<SeqOneByteString, uint8_t>(source_, beg_pos,
736 45 : position_);
737 : }
738 90004075 : if (c0 < 0x20) {
739 30 : c0_ = c0;
740 30 : position_ = position;
741 : return Handle<String>::null();
742 : }
743 : running_hash = StringHasher::AddCharacterCore(running_hash,
744 90004045 : static_cast<uint16_t>(c0));
745 90004045 : position++;
746 90004045 : if (position >= source_length_) {
747 15 : c0_ = kEndOfString;
748 15 : position_ = position;
749 : return Handle<String>::null();
750 : }
751 90004030 : c0 = seq_source_->SeqOneByteStringGet(position);
752 : } while (c0 != '"');
753 15051346 : int length = position - position_;
754 : uint32_t hash = (length <= String::kMaxHashCalcLength)
755 : ? StringHasher::GetHashCore(running_hash)
756 15051346 : : static_cast<uint32_t>(length);
757 15051346 : Vector<const uint8_t> string_vector(seq_source_->GetChars() + position_,
758 15051346 : length);
759 15051346 : StringTable* string_table = isolate()->heap()->string_table();
760 15051346 : uint32_t capacity = string_table->Capacity();
761 : uint32_t entry = StringTable::FirstProbe(hash, capacity);
762 : uint32_t count = 1;
763 : Handle<String> result;
764 : while (true) {
765 21037592 : Object* element = string_table->KeyAt(entry);
766 21037592 : if (element->IsUndefined(isolate())) {
767 : // Lookup failure.
768 230098 : result =
769 : factory()->InternalizeOneByteString(seq_source_, position_, length);
770 115049 : break;
771 : }
772 41662995 : if (!element->IsTheHole(isolate()) &&
773 20740452 : String::cast(element)->IsOneByteEqualTo(string_vector)) {
774 : result = Handle<String>(String::cast(element), isolate());
775 : #ifdef DEBUG
776 : uint32_t hash_field =
777 : (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
778 : DCHECK_EQ(static_cast<int>(result->Hash()),
779 : static_cast<int>(hash_field >> String::kHashShift));
780 : #endif
781 14936297 : break;
782 : }
783 5986246 : entry = StringTable::NextProbe(entry, count++, capacity);
784 : }
785 15051346 : position_ = position;
786 : // Advance past the last '"'.
787 : AdvanceSkipWhitespace();
788 21037592 : return result;
789 : }
790 :
791 21428065 : int beg_pos = position_;
792 : // Fast case for Latin1 only without escape characters.
793 218611541 : do {
794 : // Check for control character (0x00-0x1f) or unterminated string (<0).
795 223640478 : if (c0_ < 0x20) return Handle<String>::null();
796 223640433 : if (c0_ != '\\') {
797 969864 : if (seq_one_byte || c0_ <= String::kMaxOneByteCharCode) {
798 : Advance();
799 : } else {
800 50021 : return SlowScanJsonString<SeqTwoByteString, uc16>(source_, beg_pos,
801 50021 : position_);
802 : }
803 : } else {
804 4978871 : return SlowScanJsonString<SeqOneByteString, uint8_t>(source_, beg_pos,
805 4978871 : position_);
806 : }
807 : } while (c0_ != '"');
808 16399128 : int length = position_ - beg_pos;
809 : Handle<String> result =
810 49197384 : factory()->NewRawOneByteString(length, pretenure_).ToHandleChecked();
811 16399128 : uint8_t* dest = SeqOneByteString::cast(*result)->GetChars();
812 32798256 : String::WriteToFlat(*source_, dest, beg_pos, position_);
813 :
814 : DCHECK_EQ('"', c0_);
815 : // Advance past the last '"'.
816 : AdvanceSkipWhitespace();
817 16399128 : return result;
818 : }
819 :
820 : // Explicit instantiation.
821 : template class JsonParser<true>;
822 : template class JsonParser<false>;
823 :
824 : } // namespace internal
825 : } // namespace v8
|