| 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 | 
|---|