OLD | NEW |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |