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

Side by Side Diff: runtime/vm/regexp_assembler_bytecode.cc

Issue 2510783002: VM: Optimize RegExp.matchAsPrefix(...) by generating a sticky RegExp specialization. (Closed)
Patch Set: Done Created 4 years, 1 month 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 | « runtime/vm/regexp_assembler_bytecode.h ('k') | runtime/vm/regexp_assembler_ir.h » ('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 (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 #include "vm/regexp_assembler_bytecode.h" 5 #include "vm/regexp_assembler_bytecode.h"
6 6
7 #include "vm/regexp_assembler_bytecode_inl.h" 7 #include "vm/regexp_assembler_bytecode_inl.h"
8 #include "vm/exceptions.h" 8 #include "vm/exceptions.h"
9 #include "vm/object_store.h" 9 #include "vm/object_store.h"
10 #include "vm/regexp_bytecodes.h" 10 #include "vm/regexp_bytecodes.h"
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 buffer_->Add(0); 450 buffer_->Add(0);
451 buffer_->Add(0); 451 buffer_->Add(0);
452 intptr_t x = buffer_->length(); 452 intptr_t x = buffer_->length();
453 for (intptr_t i = 0; i < x; i++) 453 for (intptr_t i = 0; i < x; i++)
454 buffer_->Add(0); 454 buffer_->Add(0);
455 } 455 }
456 456
457 457
458 static intptr_t Prepare(const RegExp& regexp, 458 static intptr_t Prepare(const RegExp& regexp,
459 const String& subject, 459 const String& subject,
460 bool sticky,
460 Zone* zone) { 461 Zone* zone) {
461 bool is_one_byte = 462 bool is_one_byte =
462 subject.IsOneByteString() || subject.IsExternalOneByteString(); 463 subject.IsOneByteString() || subject.IsExternalOneByteString();
463 464
464 if (regexp.bytecode(is_one_byte) == TypedData::null()) { 465 if (regexp.bytecode(is_one_byte, sticky) == TypedData::null()) {
465 const String& pattern = String::Handle(zone, regexp.pattern()); 466 const String& pattern = String::Handle(zone, regexp.pattern());
466 #if !defined(PRODUCT) 467 #if !defined(PRODUCT)
467 TimelineDurationScope tds(Thread::Current(), Timeline::GetCompilerStream(), 468 TimelineDurationScope tds(Thread::Current(), Timeline::GetCompilerStream(),
468 "CompileIrregexpBytecode"); 469 "CompileIrregexpBytecode");
469 if (tds.enabled()) { 470 if (tds.enabled()) {
470 tds.SetNumArguments(1); 471 tds.SetNumArguments(1);
471 tds.CopyArgument(0, "pattern", pattern.ToCString()); 472 tds.CopyArgument(0, "pattern", pattern.ToCString());
472 } 473 }
473 #endif // !defined(PRODUCT) 474 #endif // !defined(PRODUCT)
474 475
475 const bool multiline = regexp.is_multi_line(); 476 const bool multiline = regexp.is_multi_line();
476 RegExpCompileData* compile_data = new (zone) RegExpCompileData(); 477 RegExpCompileData* compile_data = new (zone) RegExpCompileData();
477 if (!RegExpParser::ParseRegExp(pattern, multiline, compile_data)) { 478 if (!RegExpParser::ParseRegExp(pattern, multiline, compile_data)) {
478 // Parsing failures are handled in the RegExp factory constructor. 479 // Parsing failures are handled in the RegExp factory constructor.
479 UNREACHABLE(); 480 UNREACHABLE();
480 } 481 }
481 482
482 regexp.set_num_bracket_expressions(compile_data->capture_count); 483 regexp.set_num_bracket_expressions(compile_data->capture_count);
483 if (compile_data->simple) { 484 if (compile_data->simple) {
484 regexp.set_is_simple(); 485 regexp.set_is_simple();
485 } else { 486 } else {
486 regexp.set_is_complex(); 487 regexp.set_is_complex();
487 } 488 }
488 489
489 RegExpEngine::CompilationResult result = 490 RegExpEngine::CompilationResult result = RegExpEngine::CompileBytecode(
490 RegExpEngine::CompileBytecode(compile_data, regexp, is_one_byte, zone); 491 compile_data, regexp, is_one_byte, sticky, zone);
491 ASSERT(result.bytecode != NULL); 492 ASSERT(result.bytecode != NULL);
492 ASSERT((regexp.num_registers() == -1) || 493 ASSERT((regexp.num_registers() == -1) ||
493 (regexp.num_registers() == result.num_registers)); 494 (regexp.num_registers() == result.num_registers));
494 regexp.set_num_registers(result.num_registers); 495 regexp.set_num_registers(result.num_registers);
495 regexp.set_bytecode(is_one_byte, *(result.bytecode)); 496 regexp.set_bytecode(is_one_byte, sticky, *(result.bytecode));
496 } 497 }
497 498
498 ASSERT(regexp.num_registers() != -1); 499 ASSERT(regexp.num_registers() != -1);
499 500
500 return regexp.num_registers() + 501 return regexp.num_registers() +
501 (Smi::Value(regexp.num_bracket_expressions()) + 1) * 2; 502 (Smi::Value(regexp.num_bracket_expressions()) + 1) * 2;
502 } 503 }
503 504
504 505
505 static IrregexpInterpreter::IrregexpResult ExecRaw(const RegExp& regexp, 506 static IrregexpInterpreter::IrregexpResult ExecRaw(const RegExp& regexp,
506 const String& subject, 507 const String& subject,
507 intptr_t index, 508 intptr_t index,
509 bool sticky,
508 int32_t* output, 510 int32_t* output,
509 intptr_t output_size, 511 intptr_t output_size,
510 Zone* zone) { 512 Zone* zone) {
511 bool is_one_byte = 513 bool is_one_byte =
512 subject.IsOneByteString() || subject.IsExternalOneByteString(); 514 subject.IsOneByteString() || subject.IsExternalOneByteString();
513 515
514 ASSERT(regexp.num_bracket_expressions() != Smi::null()); 516 ASSERT(regexp.num_bracket_expressions() != Smi::null());
515 517
516 // We must have done EnsureCompiledIrregexp, so we can get the number of 518 // We must have done EnsureCompiledIrregexp, so we can get the number of
517 // registers. 519 // registers.
518 int number_of_capture_registers = 520 int number_of_capture_registers =
519 (Smi::Value(regexp.num_bracket_expressions()) + 1) * 2; 521 (Smi::Value(regexp.num_bracket_expressions()) + 1) * 2;
520 int32_t* raw_output = &output[number_of_capture_registers]; 522 int32_t* raw_output = &output[number_of_capture_registers];
521 523
522 // We do not touch the actual capture result registers until we know there 524 // We do not touch the actual capture result registers until we know there
523 // has been a match so that we can use those capture results to set the 525 // has been a match so that we can use those capture results to set the
524 // last match info. 526 // last match info.
525 for (int i = number_of_capture_registers - 1; i >= 0; i--) { 527 for (int i = number_of_capture_registers - 1; i >= 0; i--) {
526 raw_output[i] = -1; 528 raw_output[i] = -1;
527 } 529 }
528 530
529 const TypedData& bytecode = 531 const TypedData& bytecode =
530 TypedData::Handle(zone, regexp.bytecode(is_one_byte)); 532 TypedData::Handle(zone, regexp.bytecode(is_one_byte, sticky));
531 ASSERT(!bytecode.IsNull()); 533 ASSERT(!bytecode.IsNull());
532 IrregexpInterpreter::IrregexpResult result = 534 IrregexpInterpreter::IrregexpResult result =
533 IrregexpInterpreter::Match(bytecode, subject, raw_output, index, zone); 535 IrregexpInterpreter::Match(bytecode, subject, raw_output, index, zone);
534 536
535 if (result == IrregexpInterpreter::RE_SUCCESS) { 537 if (result == IrregexpInterpreter::RE_SUCCESS) {
536 // Copy capture results to the start of the registers array. 538 // Copy capture results to the start of the registers array.
537 memmove(output, raw_output, number_of_capture_registers * sizeof(int32_t)); 539 memmove(output, raw_output, number_of_capture_registers * sizeof(int32_t));
538 } 540 }
539 if (result == IrregexpInterpreter::RE_EXCEPTION) { 541 if (result == IrregexpInterpreter::RE_EXCEPTION) {
540 Thread* thread = Thread::Current(); 542 Thread* thread = Thread::Current();
541 Isolate* isolate = thread->isolate(); 543 Isolate* isolate = thread->isolate();
542 const Instance& exception = 544 const Instance& exception =
543 Instance::Handle(isolate->object_store()->stack_overflow()); 545 Instance::Handle(isolate->object_store()->stack_overflow());
544 Exceptions::Throw(thread, exception); 546 Exceptions::Throw(thread, exception);
545 UNREACHABLE(); 547 UNREACHABLE();
546 } 548 }
547 return result; 549 return result;
548 } 550 }
549 551
550 552
551 RawInstance* BytecodeRegExpMacroAssembler::Interpret(const RegExp& regexp, 553 RawInstance* BytecodeRegExpMacroAssembler::Interpret(const RegExp& regexp,
552 const String& subject, 554 const String& subject,
553 const Smi& start_index, 555 const Smi& start_index,
556 bool sticky,
554 Zone* zone) { 557 Zone* zone) {
555 intptr_t required_registers = Prepare(regexp, subject, zone); 558 intptr_t required_registers = Prepare(regexp, subject, sticky, zone);
556 if (required_registers < 0) { 559 if (required_registers < 0) {
557 // Compiling failed with an exception. 560 // Compiling failed with an exception.
558 UNREACHABLE(); 561 UNREACHABLE();
559 } 562 }
560 563
561 // V8 uses a shared copy on the isolate when smaller than some threshold. 564 // V8 uses a shared copy on the isolate when smaller than some threshold.
562 int32_t* output_registers = zone->Alloc<int32_t>(required_registers); 565 int32_t* output_registers = zone->Alloc<int32_t>(required_registers);
563 566
564 IrregexpInterpreter::IrregexpResult result = 567 IrregexpInterpreter::IrregexpResult result =
565 ExecRaw(regexp, subject, start_index.Value(), output_registers, 568 ExecRaw(regexp, subject, start_index.Value(), sticky, output_registers,
566 required_registers, zone); 569 required_registers, zone);
567 570
568 if (result == IrregexpInterpreter::RE_SUCCESS) { 571 if (result == IrregexpInterpreter::RE_SUCCESS) {
569 intptr_t capture_count = Smi::Value(regexp.num_bracket_expressions()); 572 intptr_t capture_count = Smi::Value(regexp.num_bracket_expressions());
570 intptr_t capture_register_count = (capture_count + 1) * 2; 573 intptr_t capture_register_count = (capture_count + 1) * 2;
571 ASSERT(required_registers >= capture_register_count); 574 ASSERT(required_registers >= capture_register_count);
572 575
573 const TypedData& result = TypedData::Handle( 576 const TypedData& result = TypedData::Handle(
574 TypedData::New(kTypedDataInt32ArrayCid, capture_register_count)); 577 TypedData::New(kTypedDataInt32ArrayCid, capture_register_count));
575 { 578 {
(...skipping 15 matching lines...) Expand all
591 } 594 }
592 if (result == IrregexpInterpreter::RE_EXCEPTION) { 595 if (result == IrregexpInterpreter::RE_EXCEPTION) {
593 UNREACHABLE(); 596 UNREACHABLE();
594 } 597 }
595 ASSERT(result == IrregexpInterpreter::RE_FAILURE); 598 ASSERT(result == IrregexpInterpreter::RE_FAILURE);
596 return Instance::null(); 599 return Instance::null();
597 } 600 }
598 601
599 602
600 } // namespace dart 603 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/regexp_assembler_bytecode.h ('k') | runtime/vm/regexp_assembler_ir.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698