Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(379)

Side by Side Diff: src/json-parser.h

Issue 1052593002: Revert of Fix JSON parser Handle leak (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/heap/heap.cc ('k') | test/mjsunit/regress/regress-3976.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef V8_JSON_PARSER_H_ 5 #ifndef V8_JSON_PARSER_H_
6 #define V8_JSON_PARSER_H_ 6 #define V8_JSON_PARSER_H_
7 7
8 #include "src/v8.h" 8 #include "src/v8.h"
9 9
10 #include "src/char-predicates-inl.h" 10 #include "src/char-predicates-inl.h"
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
148 Handle<Object> ParseJsonValue(); 148 Handle<Object> ParseJsonValue();
149 149
150 // Parse a JSON object literal (grammar production JSONObject). 150 // Parse a JSON object literal (grammar production JSONObject).
151 // An object literal is a squiggly-braced and comma separated sequence 151 // An object literal is a squiggly-braced and comma separated sequence
152 // (possibly empty) of key/value pairs, where the key is a JSON string 152 // (possibly empty) of key/value pairs, where the key is a JSON string
153 // literal, the value is a JSON value, and the two are separated by a colon. 153 // literal, the value is a JSON value, and the two are separated by a colon.
154 // A JSON array doesn't allow numbers and identifiers as keys, like a 154 // A JSON array doesn't allow numbers and identifiers as keys, like a
155 // JavaScript array. 155 // JavaScript array.
156 Handle<Object> ParseJsonObject(); 156 Handle<Object> ParseJsonObject();
157 157
158 // Helper for ParseJsonObject. Parses the form "123": obj, which is recorded
159 // as an element, not a property.
160 bool ParseElement(Handle<JSObject> json_object);
161
162 // Parses a JSON array literal (grammar production JSONArray). An array 158 // Parses a JSON array literal (grammar production JSONArray). An array
163 // literal is a square-bracketed and comma separated sequence (possibly empty) 159 // literal is a square-bracketed and comma separated sequence (possibly empty)
164 // of JSON values. 160 // of JSON values.
165 // A JSON array doesn't allow leaving out values from the sequence, nor does 161 // A JSON array doesn't allow leaving out values from the sequence, nor does
166 // it allow a terminal comma, like a JavaScript array does. 162 // it allow a terminal comma, like a JavaScript array does.
167 Handle<Object> ParseJsonArray(); 163 Handle<Object> ParseJsonArray();
168 164
169 165
170 // Mark that a parsing error has happened at the current token, and 166 // Mark that a parsing error has happened at the current token, and
171 // return a null handle. Primarily for readability. 167 // return a null handle. Primarily for readability.
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 AdvanceGetChar() == 'l') { 292 AdvanceGetChar() == 'l') {
297 AdvanceSkipWhitespace(); 293 AdvanceSkipWhitespace();
298 return factory()->null_value(); 294 return factory()->null_value();
299 } 295 }
300 return ReportUnexpectedCharacter(); 296 return ReportUnexpectedCharacter();
301 } 297 }
302 return ReportUnexpectedCharacter(); 298 return ReportUnexpectedCharacter();
303 } 299 }
304 300
305 301
306 template <bool seq_one_byte>
307 bool JsonParser<seq_one_byte>::ParseElement(Handle<JSObject> json_object) {
308 uint32_t index = 0;
309 // Maybe an array index, try to parse it.
310 if (c0_ == '0') {
311 // With a leading zero, the string has to be "0" only to be an index.
312 Advance();
313 } else {
314 do {
315 int d = c0_ - '0';
316 if (index > 429496729U - ((d > 5) ? 1 : 0)) break;
317 index = (index * 10) + d;
318 Advance();
319 } while (IsDecimalDigit(c0_));
320 }
321
322 if (c0_ == '"') {
323 // Successfully parsed index, parse and store element.
324 AdvanceSkipWhitespace();
325
326 if (c0_ == ':') {
327 AdvanceSkipWhitespace();
328 Handle<Object> value = ParseJsonValue();
329 if (!value.is_null()) {
330 JSObject::SetOwnElement(json_object, index, value, SLOPPY).Assert();
331 return true;
332 }
333 }
334 }
335 return false;
336 }
337
338 // Parse a JSON object. Position must be right at '{'. 302 // Parse a JSON object. Position must be right at '{'.
339 template <bool seq_one_byte> 303 template <bool seq_one_byte>
340 Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() { 304 Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() {
341 HandleScope scope(isolate()); 305 HandleScope scope(isolate());
342 Handle<JSObject> json_object = 306 Handle<JSObject> json_object =
343 factory()->NewJSObject(object_constructor(), pretenure_); 307 factory()->NewJSObject(object_constructor(), pretenure_);
344 Handle<Map> map(json_object->map()); 308 Handle<Map> map(json_object->map());
345 int descriptor = 0; 309 int descriptor = 0;
346 ZoneList<Handle<Object> > properties(8, zone()); 310 ZoneList<Handle<Object> > properties(8, zone());
347 DCHECK_EQ(c0_, '{'); 311 DCHECK_EQ(c0_, '{');
348 312
349 bool transitioning = true; 313 bool transitioning = true;
350 314
351 AdvanceSkipWhitespace(); 315 AdvanceSkipWhitespace();
352 if (c0_ != '}') { 316 if (c0_ != '}') {
353 do { 317 do {
354 if (c0_ != '"') return ReportUnexpectedCharacter(); 318 if (c0_ != '"') return ReportUnexpectedCharacter();
355 319
356 int start_position = position_; 320 int start_position = position_;
357 Advance(); 321 Advance();
358 322
323 uint32_t index = 0;
359 if (IsDecimalDigit(c0_)) { 324 if (IsDecimalDigit(c0_)) {
360 if (ParseElement(json_object)) continue; 325 // Maybe an array index, try to parse it.
326 if (c0_ == '0') {
327 // With a leading zero, the string has to be "0" only to be an index.
328 Advance();
329 } else {
330 do {
331 int d = c0_ - '0';
332 if (index > 429496729U - ((d > 5) ? 1 : 0)) break;
333 index = (index * 10) + d;
334 Advance();
335 } while (IsDecimalDigit(c0_));
336 }
337
338 if (c0_ == '"') {
339 // Successfully parsed index, parse and store element.
340 AdvanceSkipWhitespace();
341
342 if (c0_ != ':') return ReportUnexpectedCharacter();
343 AdvanceSkipWhitespace();
344 Handle<Object> value = ParseJsonValue();
345 if (value.is_null()) return ReportUnexpectedCharacter();
346
347 JSObject::SetOwnElement(json_object, index, value, SLOPPY).Assert();
348 continue;
349 }
350 // Not an index, fallback to the slow path.
361 } 351 }
362 // Not an index, fallback to the slow path.
363 352
364 position_ = start_position; 353 position_ = start_position;
365 #ifdef DEBUG 354 #ifdef DEBUG
366 c0_ = '"'; 355 c0_ = '"';
367 #endif 356 #endif
368 357
369 Handle<String> key; 358 Handle<String> key;
370 Handle<Object> value; 359 Handle<Object> value;
371 360
372 // Try to follow existing transitions as long as possible. Once we stop 361 // Try to follow existing transitions as long as possible. Once we stop
373 // transitioning, no transition can be found anymore. 362 // transitioning, no transition can be found anymore.
374 DCHECK(transitioning); 363 if (transitioning) {
375 // First check whether there is a single expected transition. If so, try 364 // First check whether there is a single expected transition. If so, try
376 // to parse it first. 365 // to parse it first.
377 bool follow_expected = false; 366 bool follow_expected = false;
378 Handle<Map> target; 367 Handle<Map> target;
379 if (seq_one_byte) { 368 if (seq_one_byte) {
380 key = TransitionArray::ExpectedTransitionKey(map); 369 key = TransitionArray::ExpectedTransitionKey(map);
381 follow_expected = !key.is_null() && ParseJsonString(key); 370 follow_expected = !key.is_null() && ParseJsonString(key);
382 } 371 }
383 // If the expected transition hits, follow it. 372 // If the expected transition hits, follow it.
384 if (follow_expected) { 373 if (follow_expected) {
385 target = TransitionArray::ExpectedTransitionTarget(map); 374 target = TransitionArray::ExpectedTransitionTarget(map);
375 } else {
376 // If the expected transition failed, parse an internalized string and
377 // try to find a matching transition.
378 key = ParseJsonInternalizedString();
379 if (key.is_null()) return ReportUnexpectedCharacter();
380
381 target = TransitionArray::FindTransitionToField(map, key);
382 // If a transition was found, follow it and continue.
383 transitioning = !target.is_null();
384 }
385 if (c0_ != ':') return ReportUnexpectedCharacter();
386
387 AdvanceSkipWhitespace();
388 value = ParseJsonValue();
389 if (value.is_null()) return ReportUnexpectedCharacter();
390
391 if (transitioning) {
392 PropertyDetails details =
393 target->instance_descriptors()->GetDetails(descriptor);
394 Representation expected_representation = details.representation();
395
396 if (value->FitsRepresentation(expected_representation)) {
397 if (expected_representation.IsHeapObject() &&
398 !target->instance_descriptors()
399 ->GetFieldType(descriptor)
400 ->NowContains(value)) {
401 Handle<HeapType> value_type(value->OptimalType(
402 isolate(), expected_representation));
403 Map::GeneralizeFieldType(target, descriptor,
404 expected_representation, value_type);
405 }
406 DCHECK(target->instance_descriptors()->GetFieldType(
407 descriptor)->NowContains(value));
408 properties.Add(value, zone());
409 map = target;
410 descriptor++;
411 continue;
412 } else {
413 transitioning = false;
414 }
415 }
416
417 // Commit the intermediate state to the object and stop transitioning.
418 CommitStateToJsonObject(json_object, map, &properties);
386 } else { 419 } else {
387 // If the expected transition failed, parse an internalized string and
388 // try to find a matching transition.
389 key = ParseJsonInternalizedString();
390 if (key.is_null()) return ReportUnexpectedCharacter();
391
392 target = TransitionArray::FindTransitionToField(map, key);
393 // If a transition was found, follow it and continue.
394 transitioning = !target.is_null();
395 }
396 if (c0_ != ':') return ReportUnexpectedCharacter();
397
398 AdvanceSkipWhitespace();
399 value = ParseJsonValue();
400 if (value.is_null()) return ReportUnexpectedCharacter();
401
402 if (transitioning) {
403 PropertyDetails details =
404 target->instance_descriptors()->GetDetails(descriptor);
405 Representation expected_representation = details.representation();
406
407 if (value->FitsRepresentation(expected_representation)) {
408 if (expected_representation.IsHeapObject() &&
409 !target->instance_descriptors()
410 ->GetFieldType(descriptor)
411 ->NowContains(value)) {
412 Handle<HeapType> value_type(
413 value->OptimalType(isolate(), expected_representation));
414 Map::GeneralizeFieldType(target, descriptor,
415 expected_representation, value_type);
416 }
417 DCHECK(target->instance_descriptors()
418 ->GetFieldType(descriptor)
419 ->NowContains(value));
420 properties.Add(value, zone());
421 map = target;
422 descriptor++;
423 continue;
424 } else {
425 transitioning = false;
426 }
427 }
428
429 DCHECK(!transitioning);
430
431 // Commit the intermediate state to the object and stop transitioning.
432 CommitStateToJsonObject(json_object, map, &properties);
433
434 Runtime::DefineObjectProperty(json_object, key, value, NONE).Check();
435 } while (transitioning && MatchSkipWhiteSpace(','));
436
437 // If we transitioned until the very end, transition the map now.
438 if (transitioning) {
439 CommitStateToJsonObject(json_object, map, &properties);
440 } else {
441 while (MatchSkipWhiteSpace(',')) {
442 HandleScope local_scope(isolate());
443 if (c0_ != '"') return ReportUnexpectedCharacter();
444
445 int start_position = position_;
446 Advance();
447
448 if (IsDecimalDigit(c0_)) {
449 if (ParseElement(json_object)) continue;
450 }
451 // Not an index, fallback to the slow path.
452
453 position_ = start_position;
454 #ifdef DEBUG
455 c0_ = '"';
456 #endif
457
458 Handle<String> key;
459 Handle<Object> value;
460
461 key = ParseJsonInternalizedString(); 420 key = ParseJsonInternalizedString();
462 if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter(); 421 if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter();
463 422
464 AdvanceSkipWhitespace(); 423 AdvanceSkipWhitespace();
465 value = ParseJsonValue(); 424 value = ParseJsonValue();
466 if (value.is_null()) return ReportUnexpectedCharacter(); 425 if (value.is_null()) return ReportUnexpectedCharacter();
426 }
467 427
468 Runtime::DefineObjectProperty(json_object, key, value, NONE).Check(); 428 Runtime::DefineObjectProperty(json_object, key, value, NONE).Check();
469 } 429 } while (MatchSkipWhiteSpace(','));
470 }
471
472 if (c0_ != '}') { 430 if (c0_ != '}') {
473 return ReportUnexpectedCharacter(); 431 return ReportUnexpectedCharacter();
474 } 432 }
433
434 // If we transitioned until the very end, transition the map now.
435 if (transitioning) {
436 CommitStateToJsonObject(json_object, map, &properties);
437 }
475 } 438 }
476 AdvanceSkipWhitespace(); 439 AdvanceSkipWhitespace();
477 return scope.CloseAndEscape(json_object); 440 return scope.CloseAndEscape(json_object);
478 } 441 }
479 442
480 443
481 template <bool seq_one_byte> 444 template <bool seq_one_byte>
482 void JsonParser<seq_one_byte>::CommitStateToJsonObject( 445 void JsonParser<seq_one_byte>::CommitStateToJsonObject(
483 Handle<JSObject> json_object, Handle<Map> map, 446 Handle<JSObject> json_object, Handle<Map> map,
484 ZoneList<Handle<Object> >* properties) { 447 ZoneList<Handle<Object> >* properties) {
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
830 793
831 DCHECK_EQ('"', c0_); 794 DCHECK_EQ('"', c0_);
832 // Advance past the last '"'. 795 // Advance past the last '"'.
833 AdvanceSkipWhitespace(); 796 AdvanceSkipWhitespace();
834 return result; 797 return result;
835 } 798 }
836 799
837 } } // namespace v8::internal 800 } } // namespace v8::internal
838 801
839 #endif // V8_JSON_PARSER_H_ 802 #endif // V8_JSON_PARSER_H_
OLDNEW
« no previous file with comments | « src/heap/heap.cc ('k') | test/mjsunit/regress/regress-3976.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698