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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/lib/convert_patch.dart
diff --git a/runtime/lib/convert_patch.dart b/runtime/lib/convert_patch.dart
index 93da46140cb3fac8b3477af430d4d278bd61a3d0..d5683e11f87ee093796388d968bb3e95a2f75da4 100644
--- a/runtime/lib/convert_patch.dart
+++ b/runtime/lib/convert_patch.dart
@@ -371,7 +371,8 @@ class _JsonParser {
return position + 5;
}
- /** Parses a "null" literal starting at [position].
+ /**
+ * Parses a "null" literal starting at [position].
*
* [:source[position]:] must be "n".
*/
@@ -387,33 +388,49 @@ class _JsonParser {
return position + 4;
}
+ /**
+ * Parses a string value.
+ *
+ * Initial [position] is right after the initial quote.
+ * Returned position right after the final quote.
+ */
int parseString(int position) {
// Format: '"'([^\x00-\x1f\\\"]|'\\'[bfnrt/\\"])*'"'
// Initial position is right after first '"'.
int start = position;
- int char;
- do {
- if (position == source.length) {
- fail(start - 1, "Unterminated string");
+ while (position < source.length) {
+ int char = source.codeUnitAt(position++);
+ // BACKSLASH is larger than QUOTE and SPACE.
+ if (char > BACKSLASH) {
+ continue;
+ }
+ if (char == BACKSLASH) {
+ return parseStringWithEscapes(start, position - 1);
}
- char = source.codeUnitAt(position);
if (char == QUOTE) {
- listener.handleString(source.substring(start, position));
- return position + 1;
+ listener.handleString(source.substring(start, position - 1));
+ return position;
}
if (char < SPACE) {
- fail(position, "Control character in string");
+ fail(position - 1, "Control character in string");
}
- position++;
- } while (char != BACKSLASH);
+ }
+ fail(start - 1, "Unterminated string");
+ }
+
+ int parseStringWithEscapes(start, position) {
// Backslash escape detected. Collect character codes for rest of string.
- int firstEscape = position - 1;
+ int firstEscape = position;
List<int> chars = <int>[];
+ for (int i = start; i < firstEscape; i++) {
+ chars.add(source.codeUnitAt(i));
+ }
+ position++;
while (true) {
if (position == source.length) {
fail(start - 1, "Unterminated string");
}
- char = source.codeUnitAt(position);
+ int char = source.codeUnitAt(position);
switch (char) {
case CHAR_b: char = BACKSPACE; break;
case CHAR_f: char = FORM_FEED; break;
@@ -458,9 +475,6 @@ class _JsonParser {
char = source.codeUnitAt(position);
if (char == QUOTE) {
String result = new String.fromCharCodes(chars);
- if (start < firstEscape) {
- result = "${source.substring(start, firstEscape)}$result";
- }
listener.handleString(result);
return position + 1;
}
@@ -472,74 +486,84 @@ class _JsonParser {
}
}
- int _handleLiteral(start, position, isDouble) {
- String literal = source.substring(start, position);
- // This correctly creates -0 for doubles.
- num value = (isDouble ? double.parse(literal) : int.parse(literal));
- listener.handleNumber(value);
- return position;
- }
-
int parseNumber(int char, int position) {
// Format:
// '-'?('0'|[1-9][0-9]*)('.'[0-9]+)?([eE][+-]?[0-9]+)?
int start = position;
int length = source.length;
+ int intValue = 0; // Collect int value while parsing.
+ int intSign = 1;
bool isDouble = false;
- if (char == MINUS) {
- position++;
- if (position == length) fail(position, "Missing expected digit");
- char = source.codeUnitAt(position);
- }
- if (char < CHAR_0 || char > CHAR_9) {
- fail(position, "Missing expected digit");
- }
- if (char == CHAR_0) {
- position++;
- if (position == length) return _handleLiteral(start, position, false);
- char = source.codeUnitAt(position);
- if (CHAR_0 <= char && char <= CHAR_9) {
- fail(position);
- }
- } else {
- do {
+ // Break this block when the end of the number literal is reached.
+ // At that time, position points to the next character, and isDouble
+ // is set if the literal contains a decimal point or an exponential.
+ parsing: {
+ if (char == MINUS) {
+ intSign = -1;
position++;
- if (position == length) return _handleLiteral(start, position, false);
+ if (position == length) fail(position, "Missing expected digit");
char = source.codeUnitAt(position);
- } while (CHAR_0 <= char && char <= CHAR_9);
- }
- if (char == DECIMALPOINT) {
- isDouble = true;
- position++;
- if (position == length) fail(position, "Missing expected digit");
- char = source.codeUnitAt(position);
- if (char < CHAR_0 || char > CHAR_9) fail(position);
- do {
+ }
+ if (char < CHAR_0 || char > CHAR_9) {
+ fail(position, "Missing expected digit");
+ }
+ if (char == CHAR_0) {
position++;
- if (position == length) return _handleLiteral(start, position, true);
+ if (position == length) break parsing;
char = source.codeUnitAt(position);
- } while (CHAR_0 <= char && char <= CHAR_9);
- }
- if (char == CHAR_e || char == CHAR_E) {
- isDouble = true;
- position++;
- if (position == length) fail(position, "Missing expected digit");
- char = source.codeUnitAt(position);
- if (char == PLUS || char == MINUS) {
+ if (CHAR_0 <= char && char <= CHAR_9) {
+ fail(position);
+ }
+ } else {
+ do {
+ intValue = intValue * 10 + (char - CHAR_0);
+ position++;
+ if (position == length) break parsing;
+ char = source.codeUnitAt(position);
+ } while (CHAR_0 <= char && char <= CHAR_9);
+ }
+ if (char == DECIMALPOINT) {
+ isDouble = true;
position++;
if (position == length) fail(position, "Missing expected digit");
char = source.codeUnitAt(position);
+ if (char < CHAR_0 || char > CHAR_9) fail(position);
+ do {
+ position++;
+ if (position == length) break parsing;
+ char = source.codeUnitAt(position);
+ } while (CHAR_0 <= char && char <= CHAR_9);
}
- if (char < CHAR_0 || char > CHAR_9) {
- fail(position, "Missing expected digit");
- }
- do {
+ if (char == CHAR_e || char == CHAR_E) {
+ isDouble = true;
position++;
- if (position == length) return _handleLiteral(start, position, true);
+ if (position == length) fail(position, "Missing expected digit");
char = source.codeUnitAt(position);
- } while (CHAR_0 <= char && char <= CHAR_9);
+ if (char == PLUS || char == MINUS) {
+ position++;
+ if (position == length) fail(position, "Missing expected digit");
+ char = source.codeUnitAt(position);
+ }
+ if (char < CHAR_0 || char > CHAR_9) {
+ fail(position, "Missing expected digit");
+ }
+ do {
+ position++;
+ if (position == length) break parsing;
+ char = source.codeUnitAt(position);
+ } while (CHAR_0 <= char && char <= CHAR_9);
+ }
}
- return _handleLiteral(start, position, isDouble);
+ if (!isDouble) {
+ listener.handleNumber(intSign * intValue);
+ return position;
+ }
+ // Consider whether we can have an int/double.parse that works on part of
+ // a string, to avoid creating the substring.
+ String literal = source.substring(start, position);
+ // This correctly creates -0.0 for doubles.
+ listener.handleNumber(double.parse(literal));
+ return position;
}
void fail(int position, [String message]) {
« 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