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

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

Issue 11237002: Micro-optimizing the json parser (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed comment Created 8 years, 2 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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 Handle<Object> ParseJsonArray(); 142 Handle<Object> ParseJsonArray();
143 143
144 144
145 // Mark that a parsing error has happened at the current token, and 145 // Mark that a parsing error has happened at the current token, and
146 // return a null handle. Primarily for readability. 146 // return a null handle. Primarily for readability.
147 inline Handle<Object> ReportUnexpectedCharacter() { 147 inline Handle<Object> ReportUnexpectedCharacter() {
148 return Handle<Object>::null(); 148 return Handle<Object>::null();
149 } 149 }
150 150
151 inline Isolate* isolate() { return isolate_; } 151 inline Isolate* isolate() { return isolate_; }
152 inline Factory* factory() { return factory_; }
153 inline Handle<JSFunction> object_constructor() { return object_constructor_; }
152 inline Zone* zone() const { return zone_; } 154 inline Zone* zone() const { return zone_; }
153 155
154 static const int kInitialSpecialStringLength = 1024; 156 static const int kInitialSpecialStringLength = 1024;
155 157
156 158
157 private: 159 private:
158 Handle<String> source_; 160 Handle<String> source_;
159 int source_length_; 161 int source_length_;
160 Handle<SeqAsciiString> seq_source_; 162 Handle<SeqAsciiString> seq_source_;
161 163
162 Isolate* isolate_; 164 Isolate* isolate_;
165 Factory* factory_;
166 Handle<JSFunction> object_constructor_;
163 uc32 c0_; 167 uc32 c0_;
164 int position_; 168 int position_;
165 Zone* zone_; 169 Zone* zone_;
166 }; 170 };
167 171
168 template <bool seq_ascii> 172 template <bool seq_ascii>
169 Handle<Object> JsonParser<seq_ascii>::ParseJson(Handle<String> source, 173 Handle<Object> JsonParser<seq_ascii>::ParseJson(Handle<String> source,
170 Zone* zone) { 174 Zone* zone) {
171 isolate_ = source->map()->GetHeap()->isolate(); 175 isolate_ = source->map()->GetHeap()->isolate();
176 factory_ = isolate_->factory();
177 object_constructor_ =
178 Handle<JSFunction>(isolate()->native_context()->object_function());
172 zone_ = zone; 179 zone_ = zone;
173 FlattenString(source); 180 FlattenString(source);
174 source_ = source; 181 source_ = source;
175 source_length_ = source_->length(); 182 source_length_ = source_->length();
176 183
177 // Optimized fast case where we only have ASCII characters. 184 // Optimized fast case where we only have ASCII characters.
178 if (seq_ascii) { 185 if (seq_ascii) {
179 seq_source_ = Handle<SeqAsciiString>::cast(source_); 186 seq_source_ = Handle<SeqAsciiString>::cast(source_);
180 } 187 }
181 188
182 // Set initial position right before the string. 189 // Set initial position right before the string.
183 position_ = -1; 190 position_ = -1;
184 // Advance to the first character (possibly EOS) 191 // Advance to the first character (possibly EOS)
185 AdvanceSkipWhitespace(); 192 AdvanceSkipWhitespace();
186 Handle<Object> result = ParseJsonValue(); 193 Handle<Object> result = ParseJsonValue();
187 if (result.is_null() || c0_ != kEndOfString) { 194 if (result.is_null() || c0_ != kEndOfString) {
188 // Parse failed. Current character is the unexpected token. 195 // Parse failed. Current character is the unexpected token.
189 196
190 const char* message; 197 const char* message;
191 Factory* factory = isolate()->factory(); 198 Factory* factory = this->factory();
192 Handle<JSArray> array; 199 Handle<JSArray> array;
193 200
194 switch (c0_) { 201 switch (c0_) {
195 case kEndOfString: 202 case kEndOfString:
196 message = "unexpected_eos"; 203 message = "unexpected_eos";
197 array = factory->NewJSArray(0); 204 array = factory->NewJSArray(0);
198 break; 205 break;
199 case '-': 206 case '-':
200 case '0': 207 case '0':
201 case '1': 208 case '1':
(...skipping 28 matching lines...) Expand all
230 isolate()->Throw(*result, &location); 237 isolate()->Throw(*result, &location);
231 return Handle<Object>::null(); 238 return Handle<Object>::null();
232 } 239 }
233 return result; 240 return result;
234 } 241 }
235 242
236 243
237 // Parse any JSON value. 244 // Parse any JSON value.
238 template <bool seq_ascii> 245 template <bool seq_ascii>
239 Handle<Object> JsonParser<seq_ascii>::ParseJsonValue() { 246 Handle<Object> JsonParser<seq_ascii>::ParseJsonValue() {
240 switch (c0_) { 247 if (c0_ == '"') return ParseJsonString();
241 case '"': 248 if ((c0_ >= '0' && c0_ <= '9') || c0_ == '-') return ParseJsonNumber();
242 return ParseJsonString(); 249 if (c0_ == '{') return ParseJsonObject();
243 case '-': 250 if (c0_ == '[') return ParseJsonArray();
244 case '0': 251 if (c0_ == 'f') {
245 case '1': 252 if (AdvanceGetChar() == 'a' && AdvanceGetChar() == 'l' &&
246 case '2': 253 AdvanceGetChar() == 's' && AdvanceGetChar() == 'e') {
247 case '3': 254 AdvanceSkipWhitespace();
248 case '4': 255 return factory()->false_value();
249 case '5': 256 }
250 case '6': 257 return ReportUnexpectedCharacter();
251 case '7':
252 case '8':
253 case '9':
254 return ParseJsonNumber();
255 case 'f':
256 if (AdvanceGetChar() == 'a' && AdvanceGetChar() == 'l' &&
257 AdvanceGetChar() == 's' && AdvanceGetChar() == 'e') {
258 AdvanceSkipWhitespace();
259 return isolate()->factory()->false_value();
260 } else {
261 return ReportUnexpectedCharacter();
262 }
263 case 't':
264 if (AdvanceGetChar() == 'r' && AdvanceGetChar() == 'u' &&
265 AdvanceGetChar() == 'e') {
266 AdvanceSkipWhitespace();
267 return isolate()->factory()->true_value();
268 } else {
269 return ReportUnexpectedCharacter();
270 }
271 case 'n':
272 if (AdvanceGetChar() == 'u' && AdvanceGetChar() == 'l' &&
273 AdvanceGetChar() == 'l') {
274 AdvanceSkipWhitespace();
275 return isolate()->factory()->null_value();
276 } else {
277 return ReportUnexpectedCharacter();
278 }
279 case '{':
280 return ParseJsonObject();
281 case '[':
282 return ParseJsonArray();
283 default:
284 return ReportUnexpectedCharacter();
285 } 258 }
259 if (c0_ == 't') {
260 if (AdvanceGetChar() == 'r' && AdvanceGetChar() == 'u' &&
261 AdvanceGetChar() == 'e') {
262 AdvanceSkipWhitespace();
263 return factory()->true_value();
264 }
265 return ReportUnexpectedCharacter();
266 }
267 if (c0_ == 'n') {
268 if (AdvanceGetChar() == 'u' && AdvanceGetChar() == 'l' &&
269 AdvanceGetChar() == 'l') {
270 AdvanceSkipWhitespace();
271 return factory()->null_value();
272 }
273 return ReportUnexpectedCharacter();
274 }
275 return ReportUnexpectedCharacter();
286 } 276 }
287 277
288 278
289 // Parse a JSON object. Position must be right at '{'. 279 // Parse a JSON object. Position must be right at '{'.
290 template <bool seq_ascii> 280 template <bool seq_ascii>
291 Handle<Object> JsonParser<seq_ascii>::ParseJsonObject() { 281 Handle<Object> JsonParser<seq_ascii>::ParseJsonObject() {
292 Handle<Object> prototype; 282 Handle<Object> prototype;
293 Handle<JSFunction> object_constructor(
294 isolate()->native_context()->object_function());
295 Handle<JSObject> json_object = 283 Handle<JSObject> json_object =
296 isolate()->factory()->NewJSObject(object_constructor); 284 factory()->NewJSObject(object_constructor());
297 ASSERT_EQ(c0_, '{'); 285 ASSERT_EQ(c0_, '{');
298 286
299 AdvanceSkipWhitespace(); 287 AdvanceSkipWhitespace();
300 if (c0_ != '}') { 288 if (c0_ != '}') {
301 do { 289 do {
302 if (c0_ != '"') return ReportUnexpectedCharacter(); 290 if (c0_ != '"') return ReportUnexpectedCharacter();
303 291
304 int start_position = position_; 292 int start_position = position_;
305 Advance(); 293 Advance();
306 294
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 if (element.is_null()) return ReportUnexpectedCharacter(); 358 if (element.is_null()) return ReportUnexpectedCharacter();
371 elements.Add(element, zone()); 359 elements.Add(element, zone());
372 } while (MatchSkipWhiteSpace(',')); 360 } while (MatchSkipWhiteSpace(','));
373 if (c0_ != ']') { 361 if (c0_ != ']') {
374 return ReportUnexpectedCharacter(); 362 return ReportUnexpectedCharacter();
375 } 363 }
376 } 364 }
377 AdvanceSkipWhitespace(); 365 AdvanceSkipWhitespace();
378 // Allocate a fixed array with all the elements. 366 // Allocate a fixed array with all the elements.
379 Handle<FixedArray> fast_elements = 367 Handle<FixedArray> fast_elements =
380 isolate()->factory()->NewFixedArray(elements.length()); 368 factory()->NewFixedArray(elements.length());
381 for (int i = 0, n = elements.length(); i < n; i++) { 369 for (int i = 0, n = elements.length(); i < n; i++) {
382 fast_elements->set(i, *elements[i]); 370 fast_elements->set(i, *elements[i]);
383 } 371 }
384 return isolate()->factory()->NewJSArrayWithElements(fast_elements); 372 return factory()->NewJSArrayWithElements(fast_elements);
385 } 373 }
386 374
387 375
388 template <bool seq_ascii> 376 template <bool seq_ascii>
389 Handle<Object> JsonParser<seq_ascii>::ParseJsonNumber() { 377 Handle<Object> JsonParser<seq_ascii>::ParseJsonNumber() {
390 bool negative = false; 378 bool negative = false;
391 int beg_pos = position_; 379 int beg_pos = position_;
392 if (c0_ == '-') { 380 if (c0_ == '-') {
393 Advance(); 381 Advance();
394 negative = true; 382 negative = true;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
441 Vector<const char> result = 429 Vector<const char> result =
442 Vector<const char>(reinterpret_cast<const char*>(buffer.start()), 430 Vector<const char>(reinterpret_cast<const char*>(buffer.start()),
443 length); 431 length);
444 number = StringToDouble(isolate()->unicode_cache(), 432 number = StringToDouble(isolate()->unicode_cache(),
445 result, 433 result,
446 NO_FLAGS, // Hex, octal or trailing junk. 434 NO_FLAGS, // Hex, octal or trailing junk.
447 0.0); 435 0.0);
448 buffer.Dispose(); 436 buffer.Dispose();
449 } 437 }
450 SkipWhitespace(); 438 SkipWhitespace();
451 return isolate()->factory()->NewNumber(number); 439 return factory()->NewNumber(number);
452 } 440 }
453 441
454 442
455 template <typename StringType> 443 template <typename StringType>
456 inline void SeqStringSet(Handle<StringType> seq_str, int i, uc32 c); 444 inline void SeqStringSet(Handle<StringType> seq_str, int i, uc32 c);
457 445
458 template <> 446 template <>
459 inline void SeqStringSet(Handle<SeqTwoByteString> seq_str, int i, uc32 c) { 447 inline void SeqStringSet(Handle<SeqTwoByteString> seq_str, int i, uc32 c) {
460 seq_str->SeqTwoByteStringSet(i, c); 448 seq_str->SeqTwoByteStringSet(i, c);
461 } 449 }
(...skipping 20 matching lines...) Expand all
482 // Scans the rest of a JSON string starting from position_ and writes 470 // Scans the rest of a JSON string starting from position_ and writes
483 // prefix[start..end] along with the scanned characters into a 471 // prefix[start..end] along with the scanned characters into a
484 // sequential string of type StringType. 472 // sequential string of type StringType.
485 template <bool seq_ascii> 473 template <bool seq_ascii>
486 template <typename StringType, typename SinkChar> 474 template <typename StringType, typename SinkChar>
487 Handle<String> JsonParser<seq_ascii>::SlowScanJsonString( 475 Handle<String> JsonParser<seq_ascii>::SlowScanJsonString(
488 Handle<String> prefix, int start, int end) { 476 Handle<String> prefix, int start, int end) {
489 int count = end - start; 477 int count = end - start;
490 int max_length = count + source_length_ - position_; 478 int max_length = count + source_length_ - position_;
491 int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count)); 479 int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count));
492 Handle<StringType> seq_str = NewRawString<StringType>(isolate()->factory(), 480 Handle<StringType> seq_str = NewRawString<StringType>(factory(), length);
493 length);
494 // Copy prefix into seq_str. 481 // Copy prefix into seq_str.
495 SinkChar* dest = seq_str->GetChars(); 482 SinkChar* dest = seq_str->GetChars();
496 String::WriteToFlat(*prefix, dest, start, end); 483 String::WriteToFlat(*prefix, dest, start, end);
497 484
498 while (c0_ != '"') { 485 while (c0_ != '"') {
499 // Check for control character (0x00-0x1f) or unterminated string (<0). 486 // Check for control character (0x00-0x1f) or unterminated string (<0).
500 if (c0_ < 0x20) return Handle<String>::null(); 487 if (c0_ < 0x20) return Handle<String>::null();
501 if (count >= length) { 488 if (count >= length) {
502 // We need to create a longer sequential string for the result. 489 // We need to create a longer sequential string for the result.
503 return SlowScanJsonString<StringType, SinkChar>(seq_str, 0, count); 490 return SlowScanJsonString<StringType, SinkChar>(seq_str, 0, count);
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
661 } 648 }
662 } else { 649 } else {
663 return SlowScanJsonString<SeqAsciiString, char>(source_, 650 return SlowScanJsonString<SeqAsciiString, char>(source_,
664 beg_pos, 651 beg_pos,
665 position_); 652 position_);
666 } 653 }
667 } while (c0_ != '"'); 654 } while (c0_ != '"');
668 int length = position_ - beg_pos; 655 int length = position_ - beg_pos;
669 Handle<String> result; 656 Handle<String> result;
670 if (seq_ascii && is_symbol) { 657 if (seq_ascii && is_symbol) {
671 result = isolate()->factory()->LookupAsciiSymbol(seq_source_, 658 result = factory()->LookupAsciiSymbol(seq_source_,
672 beg_pos, 659 beg_pos,
673 length); 660 length);
674 } else { 661 } else {
675 result = isolate()->factory()->NewRawAsciiString(length); 662 result = factory()->NewRawAsciiString(length);
676 char* dest = SeqAsciiString::cast(*result)->GetChars(); 663 char* dest = SeqAsciiString::cast(*result)->GetChars();
677 String::WriteToFlat(*source_, dest, beg_pos, position_); 664 String::WriteToFlat(*source_, dest, beg_pos, position_);
678 } 665 }
679 ASSERT_EQ('"', c0_); 666 ASSERT_EQ('"', c0_);
680 // Advance past the last '"'. 667 // Advance past the last '"'.
681 AdvanceSkipWhitespace(); 668 AdvanceSkipWhitespace();
682 return result; 669 return result;
683 } 670 }
684 671
685 } } // namespace v8::internal 672 } } // namespace v8::internal
686 673
687 #endif // V8_JSON_PARSER_H_ 674 #endif // V8_JSON_PARSER_H_
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