| // Copyright 2012 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "src/regexp/regexp-macro-assembler-tracer.h" |
| |
| #include "src/ast/ast.h" |
| #include "src/objects/objects-inl.h" |
| |
| namespace v8 { |
| namespace internal { |
| |
| RegExpMacroAssemblerTracer::RegExpMacroAssemblerTracer( |
| Isolate* isolate, RegExpMacroAssembler* assembler) |
| : RegExpMacroAssembler(isolate, assembler->zone()), assembler_(assembler) { |
| IrregexpImplementation type = assembler->Implementation(); |
| DCHECK_LT(type, 9); |
| const char* impl_names[] = {"IA32", "ARM", "ARM64", "MIPS", "S390", |
| "PPC", "X64", "X87", "Bytecode"}; |
| PrintF("RegExpMacroAssembler%s();\n", impl_names[type]); |
| } |
| |
| RegExpMacroAssemblerTracer::~RegExpMacroAssemblerTracer() = default; |
| |
| void RegExpMacroAssemblerTracer::AbortedCodeGeneration() { |
| PrintF(" AbortedCodeGeneration\n"); |
| assembler_->AbortedCodeGeneration(); |
| } |
| |
| |
| // This is used for printing out debugging information. It makes an integer |
| // that is closely related to the address of an object. |
| static int LabelToInt(Label* label) { |
| return static_cast<int>(reinterpret_cast<intptr_t>(label)); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::Bind(Label* label) { |
| PrintF("label[%08x]: (Bind)\n", LabelToInt(label)); |
| assembler_->Bind(label); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::AdvanceCurrentPosition(int by) { |
| PrintF(" AdvanceCurrentPosition(by=%d);\n", by); |
| assembler_->AdvanceCurrentPosition(by); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::CheckGreedyLoop(Label* label) { |
| PrintF(" CheckGreedyLoop(label[%08x]);\n\n", LabelToInt(label)); |
| assembler_->CheckGreedyLoop(label); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::PopCurrentPosition() { |
| PrintF(" PopCurrentPosition();\n"); |
| assembler_->PopCurrentPosition(); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::PushCurrentPosition() { |
| PrintF(" PushCurrentPosition();\n"); |
| assembler_->PushCurrentPosition(); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::Backtrack() { |
| PrintF(" Backtrack();\n"); |
| assembler_->Backtrack(); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::GoTo(Label* label) { |
| PrintF(" GoTo(label[%08x]);\n\n", LabelToInt(label)); |
| assembler_->GoTo(label); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::PushBacktrack(Label* label) { |
| PrintF(" PushBacktrack(label[%08x]);\n", LabelToInt(label)); |
| assembler_->PushBacktrack(label); |
| } |
| |
| |
| bool RegExpMacroAssemblerTracer::Succeed() { |
| bool restart = assembler_->Succeed(); |
| PrintF(" Succeed();%s\n", restart ? " [restart for global match]" : ""); |
| return restart; |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::Fail() { |
| PrintF(" Fail();"); |
| assembler_->Fail(); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::PopRegister(int register_index) { |
| PrintF(" PopRegister(register=%d);\n", register_index); |
| assembler_->PopRegister(register_index); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::PushRegister( |
| int register_index, |
| StackCheckFlag check_stack_limit) { |
| PrintF(" PushRegister(register=%d, %s);\n", |
| register_index, |
| check_stack_limit ? "check stack limit" : ""); |
| assembler_->PushRegister(register_index, check_stack_limit); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::AdvanceRegister(int reg, int by) { |
| PrintF(" AdvanceRegister(register=%d, by=%d);\n", reg, by); |
| assembler_->AdvanceRegister(reg, by); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::SetCurrentPositionFromEnd(int by) { |
| PrintF(" SetCurrentPositionFromEnd(by=%d);\n", by); |
| assembler_->SetCurrentPositionFromEnd(by); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::SetRegister(int register_index, int to) { |
| PrintF(" SetRegister(register=%d, to=%d);\n", register_index, to); |
| assembler_->SetRegister(register_index, to); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::WriteCurrentPositionToRegister(int reg, |
| int cp_offset) { |
| PrintF(" WriteCurrentPositionToRegister(register=%d,cp_offset=%d);\n", |
| reg, |
| cp_offset); |
| assembler_->WriteCurrentPositionToRegister(reg, cp_offset); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::ClearRegisters(int reg_from, int reg_to) { |
| PrintF(" ClearRegister(from=%d, to=%d);\n", reg_from, reg_to); |
| assembler_->ClearRegisters(reg_from, reg_to); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::ReadCurrentPositionFromRegister(int reg) { |
| PrintF(" ReadCurrentPositionFromRegister(register=%d);\n", reg); |
| assembler_->ReadCurrentPositionFromRegister(reg); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::WriteStackPointerToRegister(int reg) { |
| PrintF(" WriteStackPointerToRegister(register=%d);\n", reg); |
| assembler_->WriteStackPointerToRegister(reg); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::ReadStackPointerFromRegister(int reg) { |
| PrintF(" ReadStackPointerFromRegister(register=%d);\n", reg); |
| assembler_->ReadStackPointerFromRegister(reg); |
| } |
| |
| void RegExpMacroAssemblerTracer::LoadCurrentCharacterImpl( |
| int cp_offset, Label* on_end_of_input, bool check_bounds, int characters, |
| int eats_at_least) { |
| const char* check_msg = check_bounds ? "" : " (unchecked)"; |
| PrintF( |
| " LoadCurrentCharacter(cp_offset=%d, label[%08x]%s (%d chars) (eats at " |
| "least %d));\n", |
| cp_offset, LabelToInt(on_end_of_input), check_msg, characters, |
| eats_at_least); |
| assembler_->LoadCurrentCharacter(cp_offset, on_end_of_input, check_bounds, |
| characters, eats_at_least); |
| } |
| |
| class PrintablePrinter { |
| public: |
| explicit PrintablePrinter(uc16 character) : character_(character) { } |
| |
| const char* operator*() { |
| if (character_ >= ' ' && character_ <= '~') { |
| buffer_[0] = '('; |
| buffer_[1] = static_cast<char>(character_); |
| buffer_[2] = ')'; |
| buffer_[3] = '\0'; |
| } else { |
| buffer_[0] = '\0'; |
| } |
| return &buffer_[0]; |
| } |
| |
| private: |
| uc16 character_; |
| char buffer_[4]; |
| }; |
| |
| |
| void RegExpMacroAssemblerTracer::CheckCharacterLT(uc16 limit, Label* on_less) { |
| PrintablePrinter printable(limit); |
| PrintF(" CheckCharacterLT(c=0x%04x%s, label[%08x]);\n", |
| limit, |
| *printable, |
| LabelToInt(on_less)); |
| assembler_->CheckCharacterLT(limit, on_less); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::CheckCharacterGT(uc16 limit, |
| Label* on_greater) { |
| PrintablePrinter printable(limit); |
| PrintF(" CheckCharacterGT(c=0x%04x%s, label[%08x]);\n", |
| limit, |
| *printable, |
| LabelToInt(on_greater)); |
| assembler_->CheckCharacterGT(limit, on_greater); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::CheckCharacter(unsigned c, Label* on_equal) { |
| PrintablePrinter printable(c); |
| PrintF(" CheckCharacter(c=0x%04x%s, label[%08x]);\n", |
| c, |
| *printable, |
| LabelToInt(on_equal)); |
| assembler_->CheckCharacter(c, on_equal); |
| } |
| |
| void RegExpMacroAssemblerTracer::CheckAtStart(int cp_offset, |
| Label* on_at_start) { |
| PrintF(" CheckAtStart(cp_offset=%d, label[%08x]);\n", cp_offset, |
| LabelToInt(on_at_start)); |
| assembler_->CheckAtStart(cp_offset, on_at_start); |
| } |
| |
| void RegExpMacroAssemblerTracer::CheckNotAtStart(int cp_offset, |
| Label* on_not_at_start) { |
| PrintF(" CheckNotAtStart(cp_offset=%d, label[%08x]);\n", cp_offset, |
| LabelToInt(on_not_at_start)); |
| assembler_->CheckNotAtStart(cp_offset, on_not_at_start); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::CheckNotCharacter(unsigned c, |
| Label* on_not_equal) { |
| PrintablePrinter printable(c); |
| PrintF(" CheckNotCharacter(c=0x%04x%s, label[%08x]);\n", |
| c, |
| *printable, |
| LabelToInt(on_not_equal)); |
| assembler_->CheckNotCharacter(c, on_not_equal); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::CheckCharacterAfterAnd( |
| unsigned c, |
| unsigned mask, |
| Label* on_equal) { |
| PrintablePrinter printable(c); |
| PrintF(" CheckCharacterAfterAnd(c=0x%04x%s, mask=0x%04x, label[%08x]);\n", |
| c, |
| *printable, |
| mask, |
| LabelToInt(on_equal)); |
| assembler_->CheckCharacterAfterAnd(c, mask, on_equal); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::CheckNotCharacterAfterAnd( |
| unsigned c, |
| unsigned mask, |
| Label* on_not_equal) { |
| PrintablePrinter printable(c); |
| PrintF(" CheckNotCharacterAfterAnd(c=0x%04x%s, mask=0x%04x, label[%08x]);\n", |
| c, |
| *printable, |
| mask, |
| LabelToInt(on_not_equal)); |
| assembler_->CheckNotCharacterAfterAnd(c, mask, on_not_equal); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::CheckNotCharacterAfterMinusAnd( |
| uc16 c, |
| uc16 minus, |
| uc16 mask, |
| Label* on_not_equal) { |
| PrintF(" CheckNotCharacterAfterMinusAnd(c=0x%04x, minus=%04x, mask=0x%04x, " |
| "label[%08x]);\n", |
| c, |
| minus, |
| mask, |
| LabelToInt(on_not_equal)); |
| assembler_->CheckNotCharacterAfterMinusAnd(c, minus, mask, on_not_equal); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::CheckCharacterInRange( |
| uc16 from, |
| uc16 to, |
| Label* on_not_in_range) { |
| PrintablePrinter printable_from(from); |
| PrintablePrinter printable_to(to); |
| PrintF(" CheckCharacterInRange(from=0x%04x%s, to=0x%04x%s, label[%08x]);\n", |
| from, |
| *printable_from, |
| to, |
| *printable_to, |
| LabelToInt(on_not_in_range)); |
| assembler_->CheckCharacterInRange(from, to, on_not_in_range); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::CheckCharacterNotInRange( |
| uc16 from, |
| uc16 to, |
| Label* on_in_range) { |
| PrintablePrinter printable_from(from); |
| PrintablePrinter printable_to(to); |
| PrintF( |
| " CheckCharacterNotInRange(from=0x%04x%s," " to=%04x%s, label[%08x]);\n", |
| from, |
| *printable_from, |
| to, |
| *printable_to, |
| LabelToInt(on_in_range)); |
| assembler_->CheckCharacterNotInRange(from, to, on_in_range); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::CheckBitInTable( |
| Handle<ByteArray> table, Label* on_bit_set) { |
| PrintF(" CheckBitInTable(label[%08x] ", LabelToInt(on_bit_set)); |
| for (int i = 0; i < kTableSize; i++) { |
| PrintF("%c", table->get(i) != 0 ? 'X' : '.'); |
| if (i % 32 == 31 && i != kTableMask) { |
| PrintF("\n "); |
| } |
| } |
| PrintF(");\n"); |
| assembler_->CheckBitInTable(table, on_bit_set); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::CheckNotBackReference(int start_reg, |
| bool read_backward, |
| Label* on_no_match) { |
| PrintF(" CheckNotBackReference(register=%d, %s, label[%08x]);\n", start_reg, |
| read_backward ? "backward" : "forward", LabelToInt(on_no_match)); |
| assembler_->CheckNotBackReference(start_reg, read_backward, on_no_match); |
| } |
| |
| void RegExpMacroAssemblerTracer::CheckNotBackReferenceIgnoreCase( |
| int start_reg, bool read_backward, bool unicode, Label* on_no_match) { |
| PrintF(" CheckNotBackReferenceIgnoreCase(register=%d, %s %s, label[%08x]);\n", |
| start_reg, read_backward ? "backward" : "forward", |
| unicode ? "unicode" : "non-unicode", LabelToInt(on_no_match)); |
| assembler_->CheckNotBackReferenceIgnoreCase(start_reg, read_backward, unicode, |
| on_no_match); |
| } |
| |
| void RegExpMacroAssemblerTracer::CheckPosition(int cp_offset, |
| Label* on_outside_input) { |
| PrintF(" CheckPosition(cp_offset=%d, label[%08x]);\n", cp_offset, |
| LabelToInt(on_outside_input)); |
| assembler_->CheckPosition(cp_offset, on_outside_input); |
| } |
| |
| |
| bool RegExpMacroAssemblerTracer::CheckSpecialCharacterClass( |
| uc16 type, |
| Label* on_no_match) { |
| bool supported = assembler_->CheckSpecialCharacterClass(type, |
| on_no_match); |
| PrintF(" CheckSpecialCharacterClass(type='%c', label[%08x]): %s;\n", |
| type, |
| LabelToInt(on_no_match), |
| supported ? "true" : "false"); |
| return supported; |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::IfRegisterLT(int register_index, |
| int comparand, Label* if_lt) { |
| PrintF(" IfRegisterLT(register=%d, number=%d, label[%08x]);\n", |
| register_index, comparand, LabelToInt(if_lt)); |
| assembler_->IfRegisterLT(register_index, comparand, if_lt); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::IfRegisterEqPos(int register_index, |
| Label* if_eq) { |
| PrintF(" IfRegisterEqPos(register=%d, label[%08x]);\n", |
| register_index, LabelToInt(if_eq)); |
| assembler_->IfRegisterEqPos(register_index, if_eq); |
| } |
| |
| |
| void RegExpMacroAssemblerTracer::IfRegisterGE(int register_index, |
| int comparand, Label* if_ge) { |
| PrintF(" IfRegisterGE(register=%d, number=%d, label[%08x]);\n", |
| register_index, comparand, LabelToInt(if_ge)); |
| assembler_->IfRegisterGE(register_index, comparand, if_ge); |
| } |
| |
| |
| RegExpMacroAssembler::IrregexpImplementation |
| RegExpMacroAssemblerTracer::Implementation() { |
| return assembler_->Implementation(); |
| } |
| |
| |
| Handle<HeapObject> RegExpMacroAssemblerTracer::GetCode(Handle<String> source) { |
| PrintF(" GetCode(%s);\n", source->ToCString().get()); |
| return assembler_->GetCode(source); |
| } |
| |
| } // namespace internal |
| } // namespace v8 |