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