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

Side by Side Diff: runtime/lib/convert_patch.dart

Issue 183193002: Optimize VM parsing of JSON String and number literals. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Tweaks Created 6 years, 9 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 import "dart:typed_data"; 5 import "dart:typed_data";
6 6
7 // JSON conversion. 7 // JSON conversion.
8 8
9 patch _parseJson(String json, reviver(var key, var value)) { 9 patch _parseJson(String json, reviver(var key, var value)) {
10 _BuildJsonListener listener; 10 _BuildJsonListener listener;
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 if (source.codeUnitAt(position + 1) != CHAR_a || 364 if (source.codeUnitAt(position + 1) != CHAR_a ||
365 source.codeUnitAt(position + 2) != CHAR_l || 365 source.codeUnitAt(position + 2) != CHAR_l ||
366 source.codeUnitAt(position + 3) != CHAR_s || 366 source.codeUnitAt(position + 3) != CHAR_s ||
367 source.codeUnitAt(position + 4) != CHAR_e) { 367 source.codeUnitAt(position + 4) != CHAR_e) {
368 fail(position); 368 fail(position);
369 } 369 }
370 listener.handleBool(false); 370 listener.handleBool(false);
371 return position + 5; 371 return position + 5;
372 } 372 }
373 373
374 /** Parses a "null" literal starting at [position]. 374 /**
375 * Parses a "null" literal starting at [position].
375 * 376 *
376 * [:source[position]:] must be "n". 377 * [:source[position]:] must be "n".
377 */ 378 */
378 int parseNull(int position) { 379 int parseNull(int position) {
379 assert(source.codeUnitAt(position) == CHAR_n); 380 assert(source.codeUnitAt(position) == CHAR_n);
380 if (source.length < position + 4) fail(position, "Unexpected identifier"); 381 if (source.length < position + 4) fail(position, "Unexpected identifier");
381 if (source.codeUnitAt(position + 1) != CHAR_u || 382 if (source.codeUnitAt(position + 1) != CHAR_u ||
382 source.codeUnitAt(position + 2) != CHAR_l || 383 source.codeUnitAt(position + 2) != CHAR_l ||
383 source.codeUnitAt(position + 3) != CHAR_l) { 384 source.codeUnitAt(position + 3) != CHAR_l) {
384 fail(position); 385 fail(position);
385 } 386 }
386 listener.handleNull(); 387 listener.handleNull();
387 return position + 4; 388 return position + 4;
388 } 389 }
389 390
391 /**
392 * Parses a string value.
393 *
394 * Initial [position] is right after the initial quote.
395 * Returned position right after the final quote.
396 */
390 int parseString(int position) { 397 int parseString(int position) {
391 // Format: '"'([^\x00-\x1f\\\"]|'\\'[bfnrt/\\"])*'"' 398 // Format: '"'([^\x00-\x1f\\\"]|'\\'[bfnrt/\\"])*'"'
392 // Initial position is right after first '"'. 399 // Initial position is right after first '"'.
393 int start = position; 400 int start = position;
394 int char; 401 while (position < source.length) {
395 do { 402 int char = source.codeUnitAt(position++);
396 if (position == source.length) { 403 // BACKSLASH is larger than QUOTE and SPACE.
397 fail(start - 1, "Unterminated string"); 404 if (char > BACKSLASH) {
405 continue;
398 } 406 }
399 char = source.codeUnitAt(position); 407 if (char == BACKSLASH) {
408 return parseStringWithEscapes(start, position - 1);
409 }
400 if (char == QUOTE) { 410 if (char == QUOTE) {
401 listener.handleString(source.substring(start, position)); 411 listener.handleString(source.substring(start, position - 1));
402 return position + 1; 412 return position;
403 } 413 }
404 if (char < SPACE) { 414 if (char < SPACE) {
405 fail(position, "Control character in string"); 415 fail(position - 1, "Control character in string");
406 } 416 }
407 position++; 417 }
408 } while (char != BACKSLASH); 418 fail(start - 1, "Unterminated string");
419 }
420
421 int parseStringWithEscapes(start, position) {
409 // Backslash escape detected. Collect character codes for rest of string. 422 // Backslash escape detected. Collect character codes for rest of string.
410 int firstEscape = position - 1; 423 int firstEscape = position;
411 List<int> chars = <int>[]; 424 List<int> chars = <int>[];
425 for (int i = start; i < firstEscape; i++) {
426 chars.add(source.codeUnitAt(i));
427 }
428 position++;
412 while (true) { 429 while (true) {
413 if (position == source.length) { 430 if (position == source.length) {
414 fail(start - 1, "Unterminated string"); 431 fail(start - 1, "Unterminated string");
415 } 432 }
416 char = source.codeUnitAt(position); 433 int char = source.codeUnitAt(position);
417 switch (char) { 434 switch (char) {
418 case CHAR_b: char = BACKSPACE; break; 435 case CHAR_b: char = BACKSPACE; break;
419 case CHAR_f: char = FORM_FEED; break; 436 case CHAR_f: char = FORM_FEED; break;
420 case CHAR_n: char = NEWLINE; break; 437 case CHAR_n: char = NEWLINE; break;
421 case CHAR_r: char = CARRIAGE_RETURN; break; 438 case CHAR_r: char = CARRIAGE_RETURN; break;
422 case CHAR_t: char = TAB; break; 439 case CHAR_t: char = TAB; break;
423 case SLASH: 440 case SLASH:
424 case BACKSLASH: 441 case BACKSLASH:
425 case QUOTE: 442 case QUOTE:
426 break; 443 break;
(...skipping 24 matching lines...) Expand all
451 if (char < SPACE) fail(position, "Control character in string"); 468 if (char < SPACE) fail(position, "Control character in string");
452 fail(position, "Unrecognized string escape"); 469 fail(position, "Unrecognized string escape");
453 } 470 }
454 do { 471 do {
455 chars.add(char); 472 chars.add(char);
456 position++; 473 position++;
457 if (position == source.length) fail(start - 1, "Unterminated string"); 474 if (position == source.length) fail(start - 1, "Unterminated string");
458 char = source.codeUnitAt(position); 475 char = source.codeUnitAt(position);
459 if (char == QUOTE) { 476 if (char == QUOTE) {
460 String result = new String.fromCharCodes(chars); 477 String result = new String.fromCharCodes(chars);
461 if (start < firstEscape) {
462 result = "${source.substring(start, firstEscape)}$result";
463 }
464 listener.handleString(result); 478 listener.handleString(result);
465 return position + 1; 479 return position + 1;
466 } 480 }
467 if (char < SPACE) { 481 if (char < SPACE) {
468 fail(position, "Control character in string"); 482 fail(position, "Control character in string");
469 } 483 }
470 } while (char != BACKSLASH); 484 } while (char != BACKSLASH);
471 position++; 485 position++;
472 } 486 }
473 } 487 }
474 488
475 int _handleLiteral(start, position, isDouble) {
476 String literal = source.substring(start, position);
477 // This correctly creates -0 for doubles.
478 num value = (isDouble ? double.parse(literal) : int.parse(literal));
479 listener.handleNumber(value);
480 return position;
481 }
482
483 int parseNumber(int char, int position) { 489 int parseNumber(int char, int position) {
484 // Format: 490 // Format:
485 // '-'?('0'|[1-9][0-9]*)('.'[0-9]+)?([eE][+-]?[0-9]+)? 491 // '-'?('0'|[1-9][0-9]*)('.'[0-9]+)?([eE][+-]?[0-9]+)?
486 int start = position; 492 int start = position;
487 int length = source.length; 493 int length = source.length;
494 int intValue = 0; // Collect int value while parsing.
495 int intSign = 1;
488 bool isDouble = false; 496 bool isDouble = false;
489 if (char == MINUS) { 497 // Break this block when the end of the number literal is reached.
490 position++; 498 // At that time, position points to the next character, and isDouble
491 if (position == length) fail(position, "Missing expected digit"); 499 // is set if the literal contains a decimal point or an exponential.
492 char = source.codeUnitAt(position); 500 parsing: {
493 } 501 if (char == MINUS) {
494 if (char < CHAR_0 || char > CHAR_9) { 502 intSign = -1;
495 fail(position, "Missing expected digit");
496 }
497 if (char == CHAR_0) {
498 position++;
499 if (position == length) return _handleLiteral(start, position, false);
500 char = source.codeUnitAt(position);
501 if (CHAR_0 <= char && char <= CHAR_9) {
502 fail(position);
503 }
504 } else {
505 do {
506 position++;
507 if (position == length) return _handleLiteral(start, position, false);
508 char = source.codeUnitAt(position);
509 } while (CHAR_0 <= char && char <= CHAR_9);
510 }
511 if (char == DECIMALPOINT) {
512 isDouble = true;
513 position++;
514 if (position == length) fail(position, "Missing expected digit");
515 char = source.codeUnitAt(position);
516 if (char < CHAR_0 || char > CHAR_9) fail(position);
517 do {
518 position++;
519 if (position == length) return _handleLiteral(start, position, true);
520 char = source.codeUnitAt(position);
521 } while (CHAR_0 <= char && char <= CHAR_9);
522 }
523 if (char == CHAR_e || char == CHAR_E) {
524 isDouble = true;
525 position++;
526 if (position == length) fail(position, "Missing expected digit");
527 char = source.codeUnitAt(position);
528 if (char == PLUS || char == MINUS) {
529 position++; 503 position++;
530 if (position == length) fail(position, "Missing expected digit"); 504 if (position == length) fail(position, "Missing expected digit");
531 char = source.codeUnitAt(position); 505 char = source.codeUnitAt(position);
532 } 506 }
533 if (char < CHAR_0 || char > CHAR_9) { 507 if (char < CHAR_0 || char > CHAR_9) {
534 fail(position, "Missing expected digit"); 508 fail(position, "Missing expected digit");
535 } 509 }
536 do { 510 if (char == CHAR_0) {
537 position++; 511 position++;
538 if (position == length) return _handleLiteral(start, position, true); 512 if (position == length) break parsing;
539 char = source.codeUnitAt(position); 513 char = source.codeUnitAt(position);
540 } while (CHAR_0 <= char && char <= CHAR_9); 514 if (CHAR_0 <= char && char <= CHAR_9) {
515 fail(position);
516 }
517 } else {
518 do {
519 intValue = intValue * 10 + (char - CHAR_0);
520 position++;
521 if (position == length) break parsing;
522 char = source.codeUnitAt(position);
523 } while (CHAR_0 <= char && char <= CHAR_9);
524 }
525 if (char == DECIMALPOINT) {
526 isDouble = true;
527 position++;
528 if (position == length) fail(position, "Missing expected digit");
529 char = source.codeUnitAt(position);
530 if (char < CHAR_0 || char > CHAR_9) fail(position);
531 do {
532 position++;
533 if (position == length) break parsing;
534 char = source.codeUnitAt(position);
535 } while (CHAR_0 <= char && char <= CHAR_9);
536 }
537 if (char == CHAR_e || char == CHAR_E) {
538 isDouble = true;
539 position++;
540 if (position == length) fail(position, "Missing expected digit");
541 char = source.codeUnitAt(position);
542 if (char == PLUS || char == MINUS) {
543 position++;
544 if (position == length) fail(position, "Missing expected digit");
545 char = source.codeUnitAt(position);
546 }
547 if (char < CHAR_0 || char > CHAR_9) {
548 fail(position, "Missing expected digit");
549 }
550 do {
551 position++;
552 if (position == length) break parsing;
553 char = source.codeUnitAt(position);
554 } while (CHAR_0 <= char && char <= CHAR_9);
555 }
541 } 556 }
542 return _handleLiteral(start, position, isDouble); 557 if (!isDouble) {
558 listener.handleNumber(intSign * intValue);
559 return position;
560 }
561 // Consider whether we can have an int/double.parse that works on part of
562 // a string, to avoid creating the substring.
563 String literal = source.substring(start, position);
564 // This correctly creates -0.0 for doubles.
565 listener.handleNumber(double.parse(literal));
566 return position;
543 } 567 }
544 568
545 void fail(int position, [String message]) { 569 void fail(int position, [String message]) {
546 if (message == null) message = "Unexpected character"; 570 if (message == null) message = "Unexpected character";
547 listener.fail(source, position, message); 571 listener.fail(source, position, message);
548 // If the listener didn't throw, do it here. 572 // If the listener didn't throw, do it here.
549 String slice; 573 String slice;
550 int sliceEnd = position + 20; 574 int sliceEnd = position + 20;
551 if (sliceEnd > source.length) { 575 if (sliceEnd > source.length) {
552 slice = "'${source.substring(position)}'"; 576 slice = "'${source.substring(position)}'";
553 } else { 577 } else {
554 slice = "'${source.substring(position, sliceEnd)}...'"; 578 slice = "'${source.substring(position, sliceEnd)}...'";
555 } 579 }
556 throw new FormatException("Unexpected character at $position: $slice"); 580 throw new FormatException("Unexpected character at $position: $slice");
557 } 581 }
558 } 582 }
559 583
560 // UTF-8 conversion. 584 // UTF-8 conversion.
561 585
562 patch class _Utf8Encoder { 586 patch class _Utf8Encoder {
563 /* patch */ static List<int> _createBuffer(int size) => new Uint8List(size); 587 /* patch */ static List<int> _createBuffer(int size) => new Uint8List(size);
564 } 588 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698