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/field-type.h"
11 : #include "src/message-template.h"
12 : #include "src/objects-inl.h"
13 : #include "src/objects/hash-table-inl.h"
14 : #include "src/property-descriptor.h"
15 : #include "src/string-hasher.h"
16 : #include "src/transitions.h"
17 :
18 : namespace v8 {
19 : namespace internal {
20 :
21 : namespace {
22 :
23 : // A vector-like data structure that uses a larger vector for allocation, and
24 : // provides limited utility access. The original vector must not be used for the
25 : // duration, and it may even be reallocated. This allows vector storage to be
26 : // reused for the properties of sibling objects.
27 : template <typename Container>
28 : class VectorSegment {
29 : public:
30 : using value_type = typename Container::value_type;
31 :
32 : explicit VectorSegment(Container* container)
33 7795909 : : container_(*container), begin_(container->size()) {}
34 7795909 : ~VectorSegment() { container_.resize(begin_); }
35 :
36 : Vector<const value_type> GetVector() const {
37 : return VectorOf(container_) + begin_;
38 : }
39 :
40 : template <typename T>
41 : void push_back(T&& value) {
42 33125960 : container_.push_back(std::forward<T>(value));
43 : }
44 :
45 : private:
46 : Container& container_;
47 : const typename Container::size_type begin_;
48 : };
49 :
50 : } // namespace
51 :
52 144 : MaybeHandle<Object> JsonParseInternalizer::Internalize(Isolate* isolate,
53 : Handle<Object> object,
54 : Handle<Object> reviver) {
55 : DCHECK(reviver->IsCallable());
56 : JsonParseInternalizer internalizer(isolate,
57 144 : Handle<JSReceiver>::cast(reviver));
58 : Handle<JSObject> holder =
59 144 : isolate->factory()->NewJSObject(isolate->object_function());
60 : Handle<String> name = isolate->factory()->empty_string();
61 144 : JSObject::AddProperty(isolate, holder, name, object, NONE);
62 144 : return internalizer.InternalizeJsonProperty(holder, name);
63 : }
64 :
65 63441 : MaybeHandle<Object> JsonParseInternalizer::InternalizeJsonProperty(
66 : Handle<JSReceiver> holder, Handle<String> name) {
67 63441 : HandleScope outer_scope(isolate_);
68 : Handle<Object> value;
69 126882 : ASSIGN_RETURN_ON_EXCEPTION(
70 : isolate_, value, Object::GetPropertyOrElement(isolate_, holder, name),
71 : Object);
72 126882 : if (value->IsJSReceiver()) {
73 42129 : Handle<JSReceiver> object = Handle<JSReceiver>::cast(value);
74 : Maybe<bool> is_array = Object::IsArray(object);
75 42129 : if (is_array.IsNothing()) return MaybeHandle<Object>();
76 42129 : if (is_array.FromJust()) {
77 : Handle<Object> length_object;
78 42066 : ASSIGN_RETURN_ON_EXCEPTION(
79 : isolate_, length_object,
80 : Object::GetLengthFromArrayLike(isolate_, object), Object);
81 21033 : double length = length_object->Number();
82 42156 : for (double i = 0; i < length; i++) {
83 42093 : HandleScope inner_scope(isolate_);
84 42093 : Handle<Object> index = isolate_->factory()->NewNumber(i);
85 42093 : Handle<String> name = isolate_->factory()->NumberToString(index);
86 42093 : if (!RecurseAndApply(object, name)) return MaybeHandle<Object>();
87 : }
88 : } else {
89 : Handle<FixedArray> contents;
90 42192 : ASSIGN_RETURN_ON_EXCEPTION(
91 : isolate_, contents,
92 : KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly,
93 : ENUMERABLE_STRINGS,
94 : GetKeysConversion::kConvertToString),
95 : Object);
96 21582 : for (int i = 0; i < contents->length(); i++) {
97 21213 : HandleScope inner_scope(isolate_);
98 21213 : Handle<String> name(String::cast(contents->get(i)), isolate_);
99 21213 : if (!RecurseAndApply(object, name)) return MaybeHandle<Object>();
100 : }
101 : }
102 : }
103 21501 : Handle<Object> argv[] = {name, value};
104 : Handle<Object> result;
105 43002 : ASSIGN_RETURN_ON_EXCEPTION(
106 : isolate_, result, Execution::Call(isolate_, reviver_, holder, 2, argv),
107 : Object);
108 21492 : return outer_scope.CloseAndEscape(result);
109 : }
110 :
111 63306 : bool JsonParseInternalizer::RecurseAndApply(Handle<JSReceiver> holder,
112 : Handle<String> name) {
113 126612 : STACK_CHECK(isolate_, false);
114 :
115 : Handle<Object> result;
116 126594 : ASSIGN_RETURN_ON_EXCEPTION_VALUE(
117 : isolate_, result, InternalizeJsonProperty(holder, name), false);
118 : Maybe<bool> change_result = Nothing<bool>();
119 64098 : if (result->IsUndefined(isolate_)) {
120 : change_result = JSReceiver::DeletePropertyOrElement(holder, name,
121 108 : LanguageMode::kSloppy);
122 : } else {
123 : PropertyDescriptor desc;
124 : desc.set_value(result);
125 : desc.set_configurable(true);
126 : desc.set_enumerable(true);
127 : desc.set_writable(true);
128 : change_result = JSReceiver::DefineOwnProperty(isolate_, holder, name, &desc,
129 21258 : kDontThrow);
130 : }
131 21366 : MAYBE_RETURN(change_result, false);
132 21366 : return true;
133 : }
134 :
135 : template <bool seq_one_byte>
136 561360 : JsonParser<seq_one_byte>::JsonParser(Isolate* isolate, Handle<String> source)
137 : : source_(source),
138 : source_length_(source->length()),
139 : isolate_(isolate),
140 : zone_(isolate_->allocator(), ZONE_NAME),
141 1684083 : object_constructor_(isolate_->native_context()->object_function(),
142 : isolate_),
143 : position_(-1),
144 2806802 : properties_(&zone_) {
145 561361 : source_ = String::Flatten(isolate, source_);
146 561360 : pretenure_ = (source_length_ >= kPretenureTreshold) ? TENURED : NOT_TENURED;
147 :
148 : // Optimized fast case where we only have Latin1 characters.
149 : if (seq_one_byte) {
150 561311 : seq_source_ = Handle<SeqOneByteString>::cast(source_);
151 : }
152 561360 : }
153 :
154 : template <bool seq_one_byte>
155 561360 : MaybeHandle<Object> JsonParser<seq_one_byte>::ParseJson() {
156 : // Advance to the first character (possibly EOS)
157 : AdvanceSkipWhitespace();
158 561360 : Handle<Object> result = ParseJsonValue();
159 561362 : if (result.is_null() || c0_ != kEndOfString) {
160 : // Some exception (for example stack overflow) is already pending.
161 5659 : if (isolate_->has_pending_exception()) return Handle<Object>::null();
162 :
163 : // Parse failed. Current character is the unexpected token.
164 : Factory* factory = this->factory();
165 : MessageTemplate message;
166 5624 : Handle<Object> arg1 = Handle<Smi>(Smi::FromInt(position_), isolate());
167 : Handle<Object> arg2;
168 :
169 5624 : switch (c0_) {
170 : case kEndOfString:
171 : message = MessageTemplate::kJsonParseUnexpectedEOS;
172 : break;
173 : case '-':
174 : case '0':
175 : case '1':
176 : case '2':
177 : case '3':
178 : case '4':
179 : case '5':
180 : case '6':
181 : case '7':
182 : case '8':
183 : case '9':
184 : message = MessageTemplate::kJsonParseUnexpectedTokenNumber;
185 90 : break;
186 : case '"':
187 : message = MessageTemplate::kJsonParseUnexpectedTokenString;
188 117 : break;
189 : default:
190 : message = MessageTemplate::kJsonParseUnexpectedToken;
191 5300 : arg2 = arg1;
192 5300 : arg1 = factory->LookupSingleCharacterStringFromCode(c0_);
193 5300 : break;
194 : }
195 :
196 5624 : Handle<Script> script(factory->NewScript(source_));
197 5624 : if (isolate()->NeedsSourcePositionsForProfiling()) {
198 5020 : Script::InitLineEnds(script);
199 : }
200 : // We should sent compile error event because we compile JSON object in
201 : // separated source file.
202 5624 : isolate()->debug()->OnCompileError(script);
203 5624 : MessageLocation location(script, position_, position_ + 1);
204 5624 : Handle<Object> error = factory->NewSyntaxError(message, arg1, arg2);
205 5624 : return isolate()->template Throw<Object>(error, &location);
206 : }
207 555703 : return result;
208 : }
209 :
210 : MaybeHandle<Object> InternalizeJsonProperty(Handle<JSObject> holder,
211 : Handle<String> key);
212 :
213 : template <bool seq_one_byte>
214 0 : void JsonParser<seq_one_byte>::Advance() {
215 1064072798 : position_++;
216 1064072798 : if (position_ >= source_length_) {
217 555793 : c0_ = kEndOfString;
218 : } else if (seq_one_byte) {
219 1057741878 : c0_ = seq_source_->SeqOneByteStringGet(position_);
220 : } else {
221 11550254 : c0_ = source_->Get(position_);
222 : }
223 0 : }
224 :
225 : template <bool seq_one_byte>
226 0 : void JsonParser<seq_one_byte>::AdvanceSkipWhitespace() {
227 143146817 : do {
228 : Advance();
229 : } while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r');
230 0 : }
231 :
232 : template <bool seq_one_byte>
233 0 : void JsonParser<seq_one_byte>::SkipWhitespace() {
234 5575739 : while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r') {
235 : Advance();
236 : }
237 0 : }
238 :
239 : template <bool seq_one_byte>
240 0 : uc32 JsonParser<seq_one_byte>::AdvanceGetChar() {
241 : Advance();
242 32892001 : return c0_;
243 : }
244 :
245 : template <bool seq_one_byte>
246 0 : bool JsonParser<seq_one_byte>::MatchSkipWhiteSpace(uc32 c) {
247 39388336 : if (c0_ == c) {
248 : AdvanceSkipWhitespace();
249 : return true;
250 : }
251 : return false;
252 : }
253 :
254 : template <bool seq_one_byte>
255 21723716 : bool JsonParser<seq_one_byte>::ParseJsonString(Handle<String> expected) {
256 : int length = expected->length();
257 21723716 : if (source_->length() - position_ - 1 > length) {
258 : DisallowHeapAllocation no_gc;
259 21723681 : String::FlatContent content = expected->GetFlatContent(no_gc);
260 21723681 : if (content.IsOneByte()) {
261 : DCHECK_EQ('"', c0_);
262 21723681 : const uint8_t* input_chars = seq_source_->GetChars(no_gc) + position_ + 1;
263 21723681 : const uint8_t* expected_chars = content.ToOneByteVector().start();
264 210017087 : for (int i = 0; i < length; i++) {
265 188303918 : uint8_t c0 = input_chars[i];
266 188303918 : if (c0 != expected_chars[i] || c0 == '"' || c0 < 0x20 || c0 == '\\') {
267 21723657 : return false;
268 : }
269 : }
270 21713169 : if (input_chars[length] == '"') {
271 21713145 : position_ = position_ + length + 1;
272 : AdvanceSkipWhitespace();
273 : return true;
274 : }
275 : }
276 : }
277 : return false;
278 : }
279 :
280 : // Parse any JSON value.
281 : template <bool seq_one_byte>
282 39983128 : Handle<Object> JsonParser<seq_one_byte>::ParseJsonValue() {
283 39983128 : StackLimitCheck stack_check(isolate_);
284 39983132 : if (stack_check.HasOverflowed()) {
285 35 : isolate_->StackOverflow();
286 : return Handle<Object>::null();
287 : }
288 :
289 119949339 : if (stack_check.InterruptRequested() &&
290 39983289 : isolate_->stack_guard()->HandleInterrupts()->IsException(isolate_)) {
291 : return Handle<Object>::null();
292 : }
293 :
294 39983121 : if (c0_ == '"') return ParseJsonString();
295 23423066 : if ((c0_ >= '0' && c0_ <= '9') || c0_ == '-') return ParseJsonNumber();
296 18484871 : if (c0_ == '{') return ParseJsonObject();
297 10688962 : if (c0_ == '[') return ParseJsonArray();
298 10196487 : if (c0_ == 'f') {
299 9271185 : if (AdvanceGetChar() == 'a' && AdvanceGetChar() == 'l' &&
300 : AdvanceGetChar() == 's' && AdvanceGetChar() == 'e') {
301 : AdvanceSkipWhitespace();
302 2317794 : return factory()->false_value();
303 : }
304 : return ReportUnexpectedCharacter();
305 : }
306 7878684 : if (c0_ == 't') {
307 23612418 : if (AdvanceGetChar() == 'r' && AdvanceGetChar() == 'u' &&
308 : AdvanceGetChar() == 'e') {
309 : AdvanceSkipWhitespace();
310 7870806 : return factory()->true_value();
311 : }
312 : return ReportUnexpectedCharacter();
313 : }
314 7878 : if (c0_ == 'n') {
315 8398 : if (AdvanceGetChar() == 'u' && AdvanceGetChar() == 'l' &&
316 : AdvanceGetChar() == 'l') {
317 : AdvanceSkipWhitespace();
318 2799 : return factory()->null_value();
319 : }
320 : return ReportUnexpectedCharacter();
321 : }
322 : return ReportUnexpectedCharacter();
323 : }
324 :
325 : template <bool seq_one_byte>
326 154145 : ParseElementResult JsonParser<seq_one_byte>::ParseElement(
327 : Handle<JSObject> json_object) {
328 : uint32_t index = 0;
329 : // Maybe an array index, try to parse it.
330 154145 : if (c0_ == '0') {
331 : // With a leading zero, the string has to be "0" only to be an index.
332 : Advance();
333 : } else {
334 350438 : do {
335 350447 : int d = c0_ - '0';
336 350447 : if (index > 429496729U - ((d + 3) >> 3)) break;
337 350438 : index = (index * 10) + d;
338 : Advance();
339 350438 : } while (IsDecimalDigit(c0_));
340 : }
341 :
342 154145 : if (c0_ == '"') {
343 : // Successfully parsed index, parse and store element.
344 : AdvanceSkipWhitespace();
345 :
346 154100 : if (c0_ == ':') {
347 : AdvanceSkipWhitespace();
348 154100 : Handle<Object> value = ParseJsonValue();
349 154100 : if (!value.is_null()) {
350 : JSObject::SetOwnElementIgnoreAttributes(json_object, index, value, NONE)
351 154091 : .Assert();
352 154091 : return kElementFound;
353 : } else {
354 : return kNullHandle;
355 : }
356 : }
357 : }
358 : return kElementNotFound;
359 : }
360 :
361 : // Parse a JSON object. Position must be right at '{'.
362 : template <bool seq_one_byte>
363 7795909 : Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() {
364 : HandleScope scope(isolate());
365 : Handle<JSObject> json_object =
366 15591818 : factory()->NewJSObject(object_constructor(), pretenure_);
367 : Handle<Map> map(json_object->map(), isolate());
368 : int descriptor = 0;
369 7795909 : VectorSegment<ZoneVector<Handle<Object>>> properties(&properties_);
370 : DCHECK_EQ(c0_, '{');
371 :
372 : bool transitioning = true;
373 :
374 : AdvanceSkipWhitespace();
375 7795909 : if (c0_ != '}') {
376 66675571 : do {
377 33395904 : if (c0_ != '"') return ReportUnexpectedCharacter();
378 :
379 33395631 : int start_position = position_;
380 : Advance();
381 :
382 66791262 : if (IsDecimalDigit(c0_)) {
383 154145 : ParseElementResult element_result = ParseElement(json_object);
384 154145 : if (element_result == kNullHandle) return Handle<Object>::null();
385 33434187 : if (element_result == kElementFound) continue;
386 : }
387 : // Not an index, fallback to the slow path.
388 :
389 33241531 : position_ = start_position;
390 : #ifdef DEBUG
391 : c0_ = '"';
392 : #endif
393 :
394 : Handle<String> key;
395 : Handle<Object> value;
396 :
397 : // Try to follow existing transitions as long as possible. Once we stop
398 : // transitioning, no transition can be found anymore.
399 : DCHECK(transitioning);
400 : // First check whether there is a single expected transition. If so, try
401 : // to parse it first.
402 : bool follow_expected = false;
403 : Handle<Map> target;
404 : if (seq_one_byte) {
405 : DisallowHeapAllocation no_gc;
406 : TransitionsAccessor transitions(isolate(), *map, &no_gc);
407 33141249 : key = transitions.ExpectedTransitionKey();
408 33141249 : follow_expected = !key.is_null() && ParseJsonString(key);
409 : // If the expected transition hits, follow it.
410 33141249 : if (follow_expected) {
411 21713145 : target = transitions.ExpectedTransitionTarget();
412 : }
413 : }
414 33141249 : if (!follow_expected) {
415 : // If the expected transition failed, parse an internalized string and
416 : // try to find a matching transition.
417 11528386 : key = ParseJsonString();
418 11528386 : if (key.is_null()) return ReportUnexpectedCharacter();
419 :
420 : // If a transition was found, follow it and continue.
421 : transitioning = TransitionsAccessor(isolate(), map)
422 23056646 : .FindTransitionToField(key)
423 : .ToHandle(&target);
424 : }
425 33241468 : if (c0_ != ':') return ReportUnexpectedCharacter();
426 :
427 : AdvanceSkipWhitespace();
428 33241468 : value = ParseJsonValue();
429 33241468 : if (value.is_null()) return ReportUnexpectedCharacter();
430 :
431 33241429 : if (transitioning) {
432 : PropertyDetails details =
433 33129279 : target->instance_descriptors()->GetDetails(descriptor);
434 : Representation expected_representation = details.representation();
435 :
436 33129279 : if (value->FitsRepresentation(expected_representation)) {
437 99377880 : if (expected_representation.IsHeapObject() &&
438 94579060 : !target->instance_descriptors()
439 63852510 : ->GetFieldType(descriptor)
440 63852510 : ->NowContains(value)) {
441 : Handle<FieldType> value_type(
442 15869 : value->OptimalType(isolate(), expected_representation));
443 15869 : Map::GeneralizeField(isolate(), target, descriptor,
444 : details.constness(), expected_representation,
445 : value_type);
446 : }
447 : DCHECK(target->instance_descriptors()
448 : ->GetFieldType(descriptor)
449 : ->NowContains(value));
450 : properties.push_back(value);
451 100235 : map = target;
452 33125960 : descriptor++;
453 : continue;
454 : } else {
455 : transitioning = false;
456 : }
457 : }
458 :
459 : DCHECK(!transitioning);
460 :
461 : // Commit the intermediate state to the object and stop transitioning.
462 115469 : CommitStateToJsonObject(json_object, map, properties.GetVector());
463 :
464 115469 : JSObject::DefinePropertyOrElementIgnoreAttributes(json_object, key, value)
465 230938 : .Check();
466 : } while (transitioning && MatchSkipWhiteSpace(','));
467 :
468 : // If we transitioned until the very end, transition the map now.
469 7681532 : if (transitioning) {
470 7566063 : CommitStateToJsonObject(json_object, map, properties.GetVector());
471 : } else {
472 424233 : while (MatchSkipWhiteSpace(',')) {
473 : HandleScope local_scope(isolate());
474 308764 : if (c0_ != '"') return ReportUnexpectedCharacter();
475 :
476 308764 : int start_position = position_;
477 : Advance();
478 :
479 617528 : if (IsDecimalDigit(c0_)) {
480 0 : ParseElementResult element_result = ParseElement(json_object);
481 0 : if (element_result == kNullHandle) return Handle<Object>::null();
482 0 : if (element_result == kElementFound) continue;
483 : }
484 : // Not an index, fallback to the slow path.
485 :
486 308764 : position_ = start_position;
487 : #ifdef DEBUG
488 : c0_ = '"';
489 : #endif
490 :
491 : Handle<String> key;
492 : Handle<Object> value;
493 :
494 308764 : key = ParseJsonString();
495 308764 : if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter();
496 :
497 : AdvanceSkipWhitespace();
498 308764 : value = ParseJsonValue();
499 308764 : if (value.is_null()) return ReportUnexpectedCharacter();
500 :
501 : JSObject::DefinePropertyOrElementIgnoreAttributes(json_object, key,
502 308764 : value)
503 617528 : .Check();
504 : }
505 : }
506 :
507 7681532 : if (c0_ != '}') {
508 : return ReportUnexpectedCharacter();
509 : }
510 : }
511 : AdvanceSkipWhitespace();
512 7795708 : return scope.CloseAndEscape(json_object);
513 : }
514 :
515 : template <bool seq_one_byte>
516 7681532 : void JsonParser<seq_one_byte>::CommitStateToJsonObject(
517 : Handle<JSObject> json_object, Handle<Map> map,
518 : Vector<const Handle<Object>> properties) {
519 7681532 : JSObject::AllocateStorageForMap(json_object, map);
520 : DCHECK(!json_object->map()->is_dictionary_map());
521 :
522 : DisallowHeapAllocation no_gc;
523 7681532 : DescriptorArray descriptors = json_object->map()->instance_descriptors();
524 81614844 : for (int i = 0; i < properties.length(); i++) {
525 66251780 : Handle<Object> value = properties[i];
526 : // Initializing store.
527 66251780 : json_object->WriteToField(i, descriptors->GetDetails(i), *value);
528 : }
529 7681532 : }
530 :
531 : class ElementKindLattice {
532 : private:
533 : enum {
534 : SMI_ELEMENTS,
535 : NUMBER_ELEMENTS,
536 : OBJECT_ELEMENTS,
537 : };
538 :
539 : public:
540 492475 : ElementKindLattice() : value_(SMI_ELEMENTS) {}
541 :
542 5684052 : void Update(Handle<Object> o) {
543 11368104 : if (o->IsSmi()) {
544 5684052 : return;
545 6638308 : } else if (o->IsHeapNumber()) {
546 42 : if (value_ < NUMBER_ELEMENTS) value_ = NUMBER_ELEMENTS;
547 : } else {
548 : DCHECK(!o->IsNumber());
549 3319112 : value_ = OBJECT_ELEMENTS;
550 : }
551 : }
552 :
553 459056 : ElementsKind GetElementsKind() const {
554 459056 : switch (value_) {
555 : case SMI_ELEMENTS:
556 : return PACKED_SMI_ELEMENTS;
557 : case NUMBER_ELEMENTS:
558 21 : return PACKED_DOUBLE_ELEMENTS;
559 : case OBJECT_ELEMENTS:
560 399381 : return PACKED_ELEMENTS;
561 : default:
562 0 : UNREACHABLE();
563 : return PACKED_ELEMENTS;
564 : }
565 : }
566 :
567 : private:
568 : int value_;
569 : };
570 :
571 : // Parse a JSON array. Position must be right at '['.
572 : template <bool seq_one_byte>
573 492475 : Handle<Object> JsonParser<seq_one_byte>::ParseJsonArray() {
574 : HandleScope scope(isolate());
575 492475 : ZoneVector<Handle<Object>> elements(zone());
576 : DCHECK_EQ(c0_, '[');
577 :
578 : ElementKindLattice lattice;
579 :
580 : AdvanceSkipWhitespace();
581 492475 : if (c0_ != ']') {
582 5684052 : do {
583 5717462 : Handle<Object> element = ParseJsonValue();
584 5717462 : if (element.is_null()) return ReportUnexpectedCharacter();
585 5684052 : elements.push_back(element);
586 5684052 : lattice.Update(element);
587 : } while (MatchSkipWhiteSpace(','));
588 400726 : if (c0_ != ']') {
589 : return ReportUnexpectedCharacter();
590 : }
591 : }
592 : AdvanceSkipWhitespace();
593 :
594 : // Allocate a fixed array with all the elements.
595 :
596 : Handle<Object> json_array;
597 459056 : const ElementsKind kind = lattice.GetElementsKind();
598 918112 : int elements_size = static_cast<int>(elements.size());
599 :
600 459056 : switch (kind) {
601 : case PACKED_ELEMENTS:
602 : case PACKED_SMI_ELEMENTS: {
603 : Handle<FixedArray> elems =
604 918070 : factory()->NewFixedArray(elements_size, pretenure_);
605 6109679 : for (int i = 0; i < elements_size; i++) elems->set(i, *elements[i]);
606 918070 : json_array = factory()->NewJSArrayWithElements(elems, kind, pretenure_);
607 : break;
608 : }
609 : case PACKED_DOUBLE_ELEMENTS: {
610 : Handle<FixedDoubleArray> elems = Handle<FixedDoubleArray>::cast(
611 42 : factory()->NewFixedDoubleArray(elements_size, pretenure_));
612 66 : for (int i = 0; i < elements_size; i++) {
613 180 : elems->set(i, elements[i]->Number());
614 : }
615 42 : json_array = factory()->NewJSArrayWithElements(elems, kind, pretenure_);
616 : break;
617 : }
618 : default:
619 0 : UNREACHABLE();
620 : }
621 :
622 459056 : return scope.CloseAndEscape(json_array);
623 : }
624 :
625 : template <bool seq_one_byte>
626 4938195 : Handle<Object> JsonParser<seq_one_byte>::ParseJsonNumber() {
627 : bool negative = false;
628 4938195 : int beg_pos = position_;
629 4938195 : if (c0_ == '-') {
630 : Advance();
631 : negative = true;
632 : }
633 4938195 : if (c0_ == '0') {
634 : Advance();
635 : // Prefix zero is only allowed if it's the only digit before
636 : // a decimal point or exponent.
637 2064942 : if (IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
638 : } else {
639 : uint32_t i = 0;
640 : int digits = 0;
641 3905724 : if (c0_ < '1' || c0_ > '9') return ReportUnexpectedCharacter();
642 9386366 : do {
643 : // This can overflow. That's OK, the "digits < 10" check below
644 : // will discard overflown results.
645 9386366 : i = i * 10 + c0_ - '0';
646 9386366 : digits++;
647 : Advance();
648 9386366 : } while (IsDecimalDigit(c0_));
649 3905697 : if (c0_ != '.' && c0_ != 'e' && c0_ != 'E' && digits < 10) {
650 : SkipWhitespace();
651 : return Handle<Smi>(Smi::FromInt((negative ? -static_cast<int>(i) : i)),
652 7762982 : isolate());
653 : }
654 : }
655 1056668 : if (c0_ == '.') {
656 : Advance();
657 228264 : if (!IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
658 146305 : do {
659 : Advance();
660 146305 : } while (IsDecimalDigit(c0_));
661 : }
662 2113282 : if (AsciiAlphaToLower(c0_) == 'e') {
663 : Advance();
664 109 : if (c0_ == '-' || c0_ == '+') Advance();
665 218 : if (!IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
666 74 : do {
667 : Advance();
668 74 : } while (IsDecimalDigit(c0_));
669 : }
670 1056596 : int length = position_ - beg_pos;
671 : double number;
672 : if (seq_one_byte) {
673 : DisallowHeapAllocation no_gc;
674 1997222 : Vector<const uint8_t> chars(seq_source_->GetChars(no_gc) + beg_pos, length);
675 998611 : number = StringToDouble(chars,
676 : NO_FLAGS, // Hex, octal or trailing junk.
677 : std::numeric_limits<double>::quiet_NaN());
678 : } else {
679 : Vector<uint8_t> buffer = Vector<uint8_t>::New(length);
680 115970 : String::WriteToFlat(*source_, buffer.start(), beg_pos, position_);
681 : Vector<const uint8_t> result =
682 : Vector<const uint8_t>(buffer.start(), length);
683 57985 : number = StringToDouble(result,
684 : NO_FLAGS, // Hex, octal or trailing junk.
685 : 0.0);
686 : buffer.Dispose();
687 : }
688 : SkipWhitespace();
689 2113192 : return factory()->NewNumber(number, pretenure_);
690 : }
691 :
692 : template <typename StringType>
693 : inline void SeqStringSet(Handle<StringType> seq_str, int i, uc32 c);
694 :
695 : template <>
696 574344 : inline void SeqStringSet(Handle<SeqTwoByteString> seq_str, int i, uc32 c) {
697 574344 : seq_str->SeqTwoByteStringSet(i, c);
698 574344 : }
699 :
700 : template <>
701 : inline void SeqStringSet(Handle<SeqOneByteString> seq_str, int i, uc32 c) {
702 750451939 : seq_str->SeqOneByteStringSet(i, c);
703 : }
704 :
705 : template <typename StringType>
706 : inline Handle<StringType> NewRawString(Factory* factory, int length,
707 : PretenureFlag pretenure);
708 :
709 : template <>
710 50198 : inline Handle<SeqTwoByteString> NewRawString(Factory* factory, int length,
711 : PretenureFlag pretenure) {
712 100396 : return factory->NewRawTwoByteString(length, pretenure).ToHandleChecked();
713 : }
714 :
715 : template <>
716 7037164 : inline Handle<SeqOneByteString> NewRawString(Factory* factory, int length,
717 : PretenureFlag pretenure) {
718 14074328 : return factory->NewRawOneByteString(length, pretenure).ToHandleChecked();
719 : }
720 :
721 : // Scans the rest of a JSON string starting from position_ and writes
722 : // prefix[start..end] along with the scanned characters into a
723 : // sequential string of type StringType.
724 : template <bool seq_one_byte>
725 : template <typename StringType, typename SinkChar>
726 7087362 : Handle<String> JsonParser<seq_one_byte>::SlowScanJsonString(
727 : Handle<String> prefix, int start, int end) {
728 7087362 : int count = end - start;
729 7087362 : int max_length = count + source_length_ - position_;
730 7087362 : int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count));
731 : Handle<StringType> seq_string =
732 14174724 : NewRawString<StringType>(factory(), length, pretenure_);
733 :
734 : {
735 : DisallowHeapAllocation no_gc;
736 : // Copy prefix into seq_str.
737 : SinkChar* dest = seq_string->GetChars(no_gc);
738 7087362 : String::WriteToFlat(*prefix, dest, start, end);
739 : }
740 :
741 786868606 : while (c0_ != '"') {
742 : // Check for control character (0x00-0x1F) or unterminated string (<0).
743 776093683 : if (c0_ < 0x20) return Handle<String>::null();
744 776093638 : if (count >= length) {
745 : // We need to create a longer sequential string for the result.
746 3399539 : return SlowScanJsonString<StringType, SinkChar>(seq_string, 0, count);
747 : }
748 772694099 : if (c0_ != '\\') {
749 : // If the sink can contain UC16 characters, or source_ contains only
750 : // Latin1 characters, there's no need to test whether we can store the
751 : // character. Otherwise check whether the UC16 source character can fit
752 : // in the Latin1 sink.
753 5414 : if (sizeof(SinkChar) == kUC16Size || seq_one_byte ||
754 : c0_ <= String::kMaxOneByteCharCode) {
755 732465096 : SeqStringSet(seq_string, count++, c0_);
756 : Advance();
757 : } else {
758 : // StringType is SeqOneByteString and we just read a non-Latin1 char.
759 9 : return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0, count);
760 : }
761 : } else {
762 : Advance(); // Advance past the \.
763 40228994 : switch (c0_) {
764 : case '"':
765 : case '\\':
766 : case '/':
767 18560959 : SeqStringSet(seq_string, count++, c0_);
768 18 : break;
769 : case 'b':
770 14 : SeqStringSet(seq_string, count++, '\x08');
771 0 : break;
772 : case 'f':
773 9 : SeqStringSet(seq_string, count++, '\x0C');
774 0 : break;
775 : case 'n':
776 21667563 : SeqStringSet(seq_string, count++, '\x0A');
777 10 : break;
778 : case 'r':
779 14 : SeqStringSet(seq_string, count++, '\x0D');
780 0 : break;
781 : case 't':
782 9 : SeqStringSet(seq_string, count++, '\x09');
783 0 : break;
784 : case 'u': {
785 : uc32 value = 0;
786 1515 : for (int i = 0; i < 4; i++) {
787 : Advance();
788 1524 : int digit = HexValue(c0_);
789 1524 : if (digit < 0) {
790 : return Handle<String>::null();
791 : }
792 1515 : value = value * 16 + digit;
793 : }
794 168 : if (sizeof(SinkChar) == kUC16Size ||
795 : value <= String::kMaxOneByteCharCode) {
796 218 : SeqStringSet(seq_string, count++, value);
797 204 : break;
798 : } else {
799 : // StringType is SeqOneByteString and we just read a non-Latin1
800 : // char.
801 154 : position_ -= 6; // Rewind position_ to \ in \uxxxx.
802 : Advance();
803 154 : return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0,
804 154 : count);
805 : }
806 : }
807 : default:
808 : return Handle<String>::null();
809 : }
810 : Advance();
811 : }
812 : }
813 :
814 : DCHECK_EQ('"', c0_);
815 : // Advance past the last '"'.
816 : AdvanceSkipWhitespace();
817 :
818 : // Shrink seq_string length to count and return.
819 3687561 : return SeqString::Truncate(seq_string, count);
820 : }
821 :
822 : template <bool seq_one_byte>
823 28397205 : Handle<String> JsonParser<seq_one_byte>::ScanJsonString() {
824 : DCHECK_EQ('"', c0_);
825 : Advance();
826 28397205 : if (c0_ == '"') {
827 : AdvanceSkipWhitespace();
828 : return factory()->empty_string();
829 : }
830 :
831 : if (seq_one_byte) {
832 : // Fast path for existing internalized strings. If the the string being
833 : // parsed is not a known internalized string, contains backslashes or
834 : // unexpectedly reaches the end of string, return with an empty handle.
835 :
836 : // We intentionally use local variables instead of fields, compute hash
837 : // while we are iterating a string and manually inline StringTable lookup
838 : // here.
839 :
840 27994344 : int position = position_;
841 : uc32 c0 = c0_;
842 : uint32_t running_hash =
843 27994344 : static_cast<uint32_t>(isolate()->heap()->HashSeed());
844 : uint32_t index = 0;
845 : bool is_array_index = true;
846 :
847 271969478 : do {
848 275607094 : if (c0 == '\\') {
849 3637571 : c0_ = c0;
850 3637571 : int beg_pos = position_;
851 3637571 : position_ = position;
852 : return SlowScanJsonString<SeqOneByteString, uint8_t>(source_, beg_pos,
853 3637571 : position_);
854 : }
855 271969523 : if (c0 < 0x20) {
856 18 : c0_ = c0;
857 18 : position_ = position;
858 : return Handle<String>::null();
859 : }
860 271969505 : if (is_array_index) {
861 : // With leading zero, the string has to be "0" to be a valid index.
862 28706654 : if (!IsDecimalDigit(c0) || (position > position_ && index == 0)) {
863 : is_array_index = false;
864 : } else {
865 1631085 : int d = c0 - '0';
866 1631085 : is_array_index = index <= 429496729U - ((d + 3) >> 3);
867 1631085 : index = (index * 10) + d;
868 : }
869 : }
870 : running_hash = StringHasher::AddCharacterCore(running_hash,
871 271969505 : static_cast<uint16_t>(c0));
872 271969505 : position++;
873 271969505 : if (position >= source_length_) {
874 27 : c0_ = kEndOfString;
875 27 : position_ = position;
876 : return Handle<String>::null();
877 : }
878 271969478 : c0 = seq_source_->SeqOneByteStringGet(position);
879 : } while (c0 != '"');
880 24356728 : int length = position - position_;
881 : uint32_t hash;
882 24356728 : if (is_array_index) {
883 917955 : hash =
884 917955 : StringHasher::MakeArrayIndexHash(index, length) >> String::kHashShift;
885 23438773 : } else if (length <= String::kMaxHashCalcLength) {
886 : hash = StringHasher::GetHashCore(running_hash);
887 : } else {
888 25 : hash = static_cast<uint32_t>(length);
889 : }
890 24356728 : StringTable string_table = isolate()->heap()->string_table();
891 24356728 : uint32_t capacity = string_table->Capacity();
892 : uint32_t entry = StringTable::FirstProbe(hash, capacity);
893 : uint32_t count = 1;
894 : Handle<String> result;
895 : while (true) {
896 33031977 : Object element = string_table->KeyAt(entry);
897 33031977 : if (element->IsUndefined(isolate())) {
898 : // Lookup failure.
899 947368 : result =
900 : factory()->InternalizeOneByteString(seq_source_, position_, length);
901 24830412 : break;
902 : }
903 32558293 : if (!element->IsTheHole(isolate())) {
904 : DisallowHeapAllocation no_gc;
905 : Vector<const uint8_t> string_vector(
906 64251018 : seq_source_->GetChars(no_gc) + position_, length);
907 32125509 : if (String::cast(element)->IsOneByteEqualTo(string_vector)) {
908 : result = Handle<String>(String::cast(element), isolate());
909 : DCHECK_EQ(result->Hash(),
910 : (hash << String::kHashShift) >> String::kHashShift);
911 23883044 : break;
912 : }
913 : }
914 8675249 : entry = StringTable::NextProbe(entry, count++, capacity);
915 : }
916 24356728 : position_ = position;
917 : // Advance past the last '"'.
918 : AdvanceSkipWhitespace();
919 33031977 : return result;
920 : }
921 :
922 184003 : int beg_pos = position_;
923 : // Fast case for Latin1 only without escape characters.
924 1263706 : do {
925 : // Check for control character (0x00-0x1F) or unterminated string (<0).
926 1313804 : if (c0_ < 0x20) return Handle<String>::null();
927 1313795 : if (c0_ != '\\') {
928 1313741 : if (seq_one_byte || c0_ <= String::kMaxOneByteCharCode) {
929 : Advance();
930 : } else {
931 50035 : return SlowScanJsonString<SeqTwoByteString, uc16>(source_, beg_pos,
932 50035 : position_);
933 : }
934 : } else {
935 54 : return SlowScanJsonString<SeqOneByteString, uint8_t>(source_, beg_pos,
936 54 : position_);
937 : }
938 : } while (c0_ != '"');
939 133905 : int length = position_ - beg_pos;
940 : Handle<String> result =
941 401715 : factory()->NewRawOneByteString(length, pretenure_).ToHandleChecked();
942 : DisallowHeapAllocation no_gc;
943 : uint8_t* dest = SeqOneByteString::cast(*result)->GetChars(no_gc);
944 267810 : String::WriteToFlat(*source_, dest, beg_pos, position_);
945 :
946 : DCHECK_EQ('"', c0_);
947 : // Advance past the last '"'.
948 : AdvanceSkipWhitespace();
949 133905 : return result;
950 : }
951 :
952 : // Explicit instantiation.
953 : template class JsonParser<true>;
954 : template class JsonParser<false>;
955 :
956 : } // namespace internal
957 183867 : } // namespace v8
|