1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/regexp/regexp-macro-assembler-tracer.h"
6 
7 #include "src/objects/fixed-array-inl.h"
8 #include "src/objects/string.h"
9 
10 namespace v8 {
11 namespace internal {
12 
RegExpMacroAssemblerTracer( Isolate* isolate, RegExpMacroAssembler* assembler)13 RegExpMacroAssemblerTracer::RegExpMacroAssemblerTracer(
14     Isolate* isolate, RegExpMacroAssembler* assembler)
15     : RegExpMacroAssembler(isolate, assembler->zone()), assembler_(assembler) {
16   PrintF("RegExpMacroAssembler%s();\n",
17          ImplementationToString(assembler->Implementation()));
18 }
19 
20 RegExpMacroAssemblerTracer::~RegExpMacroAssemblerTracer() = default;
21 
AbortedCodeGeneration()22 void RegExpMacroAssemblerTracer::AbortedCodeGeneration() {
23   PrintF(" AbortedCodeGeneration\n");
24   assembler_->AbortedCodeGeneration();
25 }
26 
27 
28 // This is used for printing out debugging information.  It makes an integer
29 // that is closely related to the address of an object.
LabelToInt(Label* label)30 static int LabelToInt(Label* label) {
31   return static_cast<int>(reinterpret_cast<intptr_t>(label));
32 }
33 
34 
Bind(Label* label)35 void RegExpMacroAssemblerTracer::Bind(Label* label) {
36   PrintF("label[%08x]: (Bind)\n", LabelToInt(label));
37   assembler_->Bind(label);
38 }
39 
40 
AdvanceCurrentPosition(int by)41 void RegExpMacroAssemblerTracer::AdvanceCurrentPosition(int by) {
42   PrintF(" AdvanceCurrentPosition(by=%d);\n", by);
43   assembler_->AdvanceCurrentPosition(by);
44 }
45 
46 
CheckGreedyLoop(Label* label)47 void RegExpMacroAssemblerTracer::CheckGreedyLoop(Label* label) {
48   PrintF(" CheckGreedyLoop(label[%08x]);\n\n", LabelToInt(label));
49   assembler_->CheckGreedyLoop(label);
50 }
51 
52 
PopCurrentPosition()53 void RegExpMacroAssemblerTracer::PopCurrentPosition() {
54   PrintF(" PopCurrentPosition();\n");
55   assembler_->PopCurrentPosition();
56 }
57 
58 
PushCurrentPosition()59 void RegExpMacroAssemblerTracer::PushCurrentPosition() {
60   PrintF(" PushCurrentPosition();\n");
61   assembler_->PushCurrentPosition();
62 }
63 
64 
Backtrack()65 void RegExpMacroAssemblerTracer::Backtrack() {
66   PrintF(" Backtrack();\n");
67   assembler_->Backtrack();
68 }
69 
70 
GoTo(Label* label)71 void RegExpMacroAssemblerTracer::GoTo(Label* label) {
72   PrintF(" GoTo(label[%08x]);\n\n", LabelToInt(label));
73   assembler_->GoTo(label);
74 }
75 
76 
PushBacktrack(Label* label)77 void RegExpMacroAssemblerTracer::PushBacktrack(Label* label) {
78   PrintF(" PushBacktrack(label[%08x]);\n", LabelToInt(label));
79   assembler_->PushBacktrack(label);
80 }
81 
82 
Succeed()83 bool RegExpMacroAssemblerTracer::Succeed() {
84   bool restart = assembler_->Succeed();
85   PrintF(" Succeed();%s\n", restart ? " [restart for global match]" : "");
86   return restart;
87 }
88 
89 
Fail()90 void RegExpMacroAssemblerTracer::Fail() {
91   PrintF(" Fail();");
92   assembler_->Fail();
93 }
94 
95 
PopRegister(int register_index)96 void RegExpMacroAssemblerTracer::PopRegister(int register_index) {
97   PrintF(" PopRegister(register=%d);\n", register_index);
98   assembler_->PopRegister(register_index);
99 }
100 
101 
PushRegister( int register_index, StackCheckFlag check_stack_limit)102 void RegExpMacroAssemblerTracer::PushRegister(
103     int register_index,
104     StackCheckFlag check_stack_limit) {
105   PrintF(" PushRegister(register=%d, %s);\n",
106          register_index,
107          check_stack_limit ? "check stack limit" : "");
108   assembler_->PushRegister(register_index, check_stack_limit);
109 }
110 
111 
AdvanceRegister(int reg, int by)112 void RegExpMacroAssemblerTracer::AdvanceRegister(int reg, int by) {
113   PrintF(" AdvanceRegister(register=%d, by=%d);\n", reg, by);
114   assembler_->AdvanceRegister(reg, by);
115 }
116 
117 
SetCurrentPositionFromEnd(int by)118 void RegExpMacroAssemblerTracer::SetCurrentPositionFromEnd(int by) {
119   PrintF(" SetCurrentPositionFromEnd(by=%d);\n", by);
120   assembler_->SetCurrentPositionFromEnd(by);
121 }
122 
123 
SetRegister(int register_index, int to)124 void RegExpMacroAssemblerTracer::SetRegister(int register_index, int to) {
125   PrintF(" SetRegister(register=%d, to=%d);\n", register_index, to);
126   assembler_->SetRegister(register_index, to);
127 }
128 
129 
WriteCurrentPositionToRegister(int reg, int cp_offset)130 void RegExpMacroAssemblerTracer::WriteCurrentPositionToRegister(int reg,
131                                                                 int cp_offset) {
132   PrintF(" WriteCurrentPositionToRegister(register=%d,cp_offset=%d);\n",
133          reg,
134          cp_offset);
135   assembler_->WriteCurrentPositionToRegister(reg, cp_offset);
136 }
137 
138 
ClearRegisters(int reg_from, int reg_to)139 void RegExpMacroAssemblerTracer::ClearRegisters(int reg_from, int reg_to) {
140   PrintF(" ClearRegister(from=%d, to=%d);\n", reg_from, reg_to);
141   assembler_->ClearRegisters(reg_from, reg_to);
142 }
143 
144 
ReadCurrentPositionFromRegister(int reg)145 void RegExpMacroAssemblerTracer::ReadCurrentPositionFromRegister(int reg) {
146   PrintF(" ReadCurrentPositionFromRegister(register=%d);\n", reg);
147   assembler_->ReadCurrentPositionFromRegister(reg);
148 }
149 
150 
WriteStackPointerToRegister(int reg)151 void RegExpMacroAssemblerTracer::WriteStackPointerToRegister(int reg) {
152   PrintF(" WriteStackPointerToRegister(register=%d);\n", reg);
153   assembler_->WriteStackPointerToRegister(reg);
154 }
155 
156 
ReadStackPointerFromRegister(int reg)157 void RegExpMacroAssemblerTracer::ReadStackPointerFromRegister(int reg) {
158   PrintF(" ReadStackPointerFromRegister(register=%d);\n", reg);
159   assembler_->ReadStackPointerFromRegister(reg);
160 }
161 
LoadCurrentCharacterImpl( int cp_offset, Label* on_end_of_input, bool check_bounds, int characters, int eats_at_least)162 void RegExpMacroAssemblerTracer::LoadCurrentCharacterImpl(
163     int cp_offset, Label* on_end_of_input, bool check_bounds, int characters,
164     int eats_at_least) {
165   const char* check_msg = check_bounds ? "" : " (unchecked)";
166   PrintF(
167       " LoadCurrentCharacter(cp_offset=%d, label[%08x]%s (%d chars) (eats at "
168       "least %d));\n",
169       cp_offset, LabelToInt(on_end_of_input), check_msg, characters,
170       eats_at_least);
171   assembler_->LoadCurrentCharacter(cp_offset, on_end_of_input, check_bounds,
172                                    characters, eats_at_least);
173 }
174 
175 namespace {
176 
177 class PrintablePrinter {
178  public:
PrintablePrinter(base::uc16 character)179   explicit PrintablePrinter(base::uc16 character) : character_(character) {}
180 
operator *()181   const char* operator*() {
182     if (character_ >= ' ' && character_ <= '~') {
183       buffer_[0] = '(';
184       buffer_[1] = static_cast<char>(character_);
185       buffer_[2] = ')';
186       buffer_[3] = '\0';
187     } else {
188       buffer_[0] = '\0';
189     }
190     return &buffer_[0];
191   }
192 
193  private:
194   base::uc16 character_;
195   char buffer_[4];
196 };
197 
198 }  // namespace
199 
CheckCharacterLT(base::uc16 limit, Label* on_less)200 void RegExpMacroAssemblerTracer::CheckCharacterLT(base::uc16 limit,
201                                                   Label* on_less) {
202   PrintablePrinter printable(limit);
203   PrintF(" CheckCharacterLT(c=0x%04x%s, label[%08x]);\n",
204          limit,
205          *printable,
206          LabelToInt(on_less));
207   assembler_->CheckCharacterLT(limit, on_less);
208 }
209 
CheckCharacterGT(base::uc16 limit, Label* on_greater)210 void RegExpMacroAssemblerTracer::CheckCharacterGT(base::uc16 limit,
211                                                   Label* on_greater) {
212   PrintablePrinter printable(limit);
213   PrintF(" CheckCharacterGT(c=0x%04x%s, label[%08x]);\n",
214          limit,
215          *printable,
216          LabelToInt(on_greater));
217   assembler_->CheckCharacterGT(limit, on_greater);
218 }
219 
CheckCharacter(unsigned c, Label* on_equal)220 void RegExpMacroAssemblerTracer::CheckCharacter(unsigned c, Label* on_equal) {
221   PrintablePrinter printable(c);
222   PrintF(" CheckCharacter(c=0x%04x%s, label[%08x]);\n",
223          c,
224          *printable,
225          LabelToInt(on_equal));
226   assembler_->CheckCharacter(c, on_equal);
227 }
228 
CheckAtStart(int cp_offset, Label* on_at_start)229 void RegExpMacroAssemblerTracer::CheckAtStart(int cp_offset,
230                                               Label* on_at_start) {
231   PrintF(" CheckAtStart(cp_offset=%d, label[%08x]);\n", cp_offset,
232          LabelToInt(on_at_start));
233   assembler_->CheckAtStart(cp_offset, on_at_start);
234 }
235 
CheckNotAtStart(int cp_offset, Label* on_not_at_start)236 void RegExpMacroAssemblerTracer::CheckNotAtStart(int cp_offset,
237                                                  Label* on_not_at_start) {
238   PrintF(" CheckNotAtStart(cp_offset=%d, label[%08x]);\n", cp_offset,
239          LabelToInt(on_not_at_start));
240   assembler_->CheckNotAtStart(cp_offset, on_not_at_start);
241 }
242 
243 
CheckNotCharacter(unsigned c, Label* on_not_equal)244 void RegExpMacroAssemblerTracer::CheckNotCharacter(unsigned c,
245                                                    Label* on_not_equal) {
246   PrintablePrinter printable(c);
247   PrintF(" CheckNotCharacter(c=0x%04x%s, label[%08x]);\n",
248          c,
249          *printable,
250          LabelToInt(on_not_equal));
251   assembler_->CheckNotCharacter(c, on_not_equal);
252 }
253 
254 
CheckCharacterAfterAnd( unsigned c, unsigned mask, Label* on_equal)255 void RegExpMacroAssemblerTracer::CheckCharacterAfterAnd(
256     unsigned c,
257     unsigned mask,
258     Label* on_equal) {
259   PrintablePrinter printable(c);
260   PrintF(" CheckCharacterAfterAnd(c=0x%04x%s, mask=0x%04x, label[%08x]);\n",
261          c,
262          *printable,
263          mask,
264          LabelToInt(on_equal));
265   assembler_->CheckCharacterAfterAnd(c, mask, on_equal);
266 }
267 
268 
CheckNotCharacterAfterAnd( unsigned c, unsigned mask, Label* on_not_equal)269 void RegExpMacroAssemblerTracer::CheckNotCharacterAfterAnd(
270     unsigned c,
271     unsigned mask,
272     Label* on_not_equal) {
273   PrintablePrinter printable(c);
274   PrintF(" CheckNotCharacterAfterAnd(c=0x%04x%s, mask=0x%04x, label[%08x]);\n",
275          c,
276          *printable,
277          mask,
278          LabelToInt(on_not_equal));
279   assembler_->CheckNotCharacterAfterAnd(c, mask, on_not_equal);
280 }
281 
CheckNotCharacterAfterMinusAnd( base::uc16 c, base::uc16 minus, base::uc16 mask, Label* on_not_equal)282 void RegExpMacroAssemblerTracer::CheckNotCharacterAfterMinusAnd(
283     base::uc16 c, base::uc16 minus, base::uc16 mask, Label* on_not_equal) {
284   PrintF(" CheckNotCharacterAfterMinusAnd(c=0x%04x, minus=%04x, mask=0x%04x, "
285              "label[%08x]);\n",
286          c,
287          minus,
288          mask,
289          LabelToInt(on_not_equal));
290   assembler_->CheckNotCharacterAfterMinusAnd(c, minus, mask, on_not_equal);
291 }
292 
CheckCharacterInRange(base::uc16 from, base::uc16 to, Label* on_not_in_range)293 void RegExpMacroAssemblerTracer::CheckCharacterInRange(base::uc16 from,
294                                                        base::uc16 to,
295                                                        Label* on_not_in_range) {
296   PrintablePrinter printable_from(from);
297   PrintablePrinter printable_to(to);
298   PrintF(" CheckCharacterInRange(from=0x%04x%s, to=0x%04x%s, label[%08x]);\n",
299          from,
300          *printable_from,
301          to,
302          *printable_to,
303          LabelToInt(on_not_in_range));
304   assembler_->CheckCharacterInRange(from, to, on_not_in_range);
305 }
306 
CheckCharacterNotInRange(base::uc16 from, base::uc16 to, Label* on_in_range)307 void RegExpMacroAssemblerTracer::CheckCharacterNotInRange(base::uc16 from,
308                                                           base::uc16 to,
309                                                           Label* on_in_range) {
310   PrintablePrinter printable_from(from);
311   PrintablePrinter printable_to(to);
312   PrintF(
313       " CheckCharacterNotInRange(from=0x%04x%s," " to=%04x%s, label[%08x]);\n",
314       from,
315       *printable_from,
316       to,
317       *printable_to,
318       LabelToInt(on_in_range));
319   assembler_->CheckCharacterNotInRange(from, to, on_in_range);
320 }
321 
322 namespace {
323 
PrintRangeArray(const ZoneList<CharacterRange>* ranges)324 void PrintRangeArray(const ZoneList<CharacterRange>* ranges) {
325   for (int i = 0; i < ranges->length(); i++) {
326     base::uc16 from = ranges->at(i).from();
327     base::uc16 to = ranges->at(i).to();
328     PrintablePrinter printable_from(from);
329     PrintablePrinter printable_to(to);
330     PrintF("        [from=0x%04x%s, to=%04x%s],\n", from, *printable_from, to,
331            *printable_to);
332   }
333 }
334 
335 }  // namespace
336 
CheckCharacterInRangeArray( const ZoneList<CharacterRange>* ranges, Label* on_in_range)337 bool RegExpMacroAssemblerTracer::CheckCharacterInRangeArray(
338     const ZoneList<CharacterRange>* ranges, Label* on_in_range) {
339   PrintF(
340       " CheckCharacterInRangeArray(\n"
341       "        label[%08x]);\n",
342       LabelToInt(on_in_range));
343   PrintRangeArray(ranges);
344   return assembler_->CheckCharacterInRangeArray(ranges, on_in_range);
345 }
346 
CheckCharacterNotInRangeArray( const ZoneList<CharacterRange>* ranges, Label* on_not_in_range)347 bool RegExpMacroAssemblerTracer::CheckCharacterNotInRangeArray(
348     const ZoneList<CharacterRange>* ranges, Label* on_not_in_range) {
349   PrintF(
350       " CheckCharacterNotInRangeArray(\n"
351       "        label[%08x]);\n",
352       LabelToInt(on_not_in_range));
353   PrintRangeArray(ranges);
354   return assembler_->CheckCharacterNotInRangeArray(ranges, on_not_in_range);
355 }
356 
CheckBitInTable( Handle<ByteArray> table, Label* on_bit_set)357 void RegExpMacroAssemblerTracer::CheckBitInTable(
358     Handle<ByteArray> table, Label* on_bit_set) {
359   PrintF(" CheckBitInTable(label[%08x] ", LabelToInt(on_bit_set));
360   for (int i = 0; i < kTableSize; i++) {
361     PrintF("%c", table->get(i) != 0 ? 'X' : '.');
362     if (i % 32 == 31 && i != kTableMask) {
363       PrintF("\n                                 ");
364     }
365   }
366   PrintF(");\n");
367   assembler_->CheckBitInTable(table, on_bit_set);
368 }
369 
370 
CheckNotBackReference(int start_reg, bool read_backward, Label* on_no_match)371 void RegExpMacroAssemblerTracer::CheckNotBackReference(int start_reg,
372                                                        bool read_backward,
373                                                        Label* on_no_match) {
374   PrintF(" CheckNotBackReference(register=%d, %s, label[%08x]);\n", start_reg,
375          read_backward ? "backward" : "forward", LabelToInt(on_no_match));
376   assembler_->CheckNotBackReference(start_reg, read_backward, on_no_match);
377 }
378 
CheckNotBackReferenceIgnoreCase( int start_reg, bool read_backward, bool unicode, Label* on_no_match)379 void RegExpMacroAssemblerTracer::CheckNotBackReferenceIgnoreCase(
380     int start_reg, bool read_backward, bool unicode, Label* on_no_match) {
381   PrintF(" CheckNotBackReferenceIgnoreCase(register=%d, %s %s, label[%08x]);\n",
382          start_reg, read_backward ? "backward" : "forward",
383          unicode ? "unicode" : "non-unicode", LabelToInt(on_no_match));
384   assembler_->CheckNotBackReferenceIgnoreCase(start_reg, read_backward, unicode,
385                                               on_no_match);
386 }
387 
CheckPosition(int cp_offset, Label* on_outside_input)388 void RegExpMacroAssemblerTracer::CheckPosition(int cp_offset,
389                                                Label* on_outside_input) {
390   PrintF(" CheckPosition(cp_offset=%d, label[%08x]);\n", cp_offset,
391          LabelToInt(on_outside_input));
392   assembler_->CheckPosition(cp_offset, on_outside_input);
393 }
394 
CheckSpecialCharacterClass( StandardCharacterSet type, Label* on_no_match)395 bool RegExpMacroAssemblerTracer::CheckSpecialCharacterClass(
396     StandardCharacterSet type, Label* on_no_match) {
397   bool supported = assembler_->CheckSpecialCharacterClass(type,
398                                                           on_no_match);
399   PrintF(" CheckSpecialCharacterClass(type='%c', label[%08x]): %s;\n",
400          static_cast<char>(type), LabelToInt(on_no_match),
401          supported ? "true" : "false");
402   return supported;
403 }
404 
IfRegisterLT(int register_index, int comparand, Label* if_lt)405 void RegExpMacroAssemblerTracer::IfRegisterLT(int register_index,
406                                               int comparand, Label* if_lt) {
407   PrintF(" IfRegisterLT(register=%d, number=%d, label[%08x]);\n",
408          register_index, comparand, LabelToInt(if_lt));
409   assembler_->IfRegisterLT(register_index, comparand, if_lt);
410 }
411 
412 
IfRegisterEqPos(int register_index, Label* if_eq)413 void RegExpMacroAssemblerTracer::IfRegisterEqPos(int register_index,
414                                                  Label* if_eq) {
415   PrintF(" IfRegisterEqPos(register=%d, label[%08x]);\n",
416          register_index, LabelToInt(if_eq));
417   assembler_->IfRegisterEqPos(register_index, if_eq);
418 }
419 
420 
IfRegisterGE(int register_index, int comparand, Label* if_ge)421 void RegExpMacroAssemblerTracer::IfRegisterGE(int register_index,
422                                               int comparand, Label* if_ge) {
423   PrintF(" IfRegisterGE(register=%d, number=%d, label[%08x]);\n",
424          register_index, comparand, LabelToInt(if_ge));
425   assembler_->IfRegisterGE(register_index, comparand, if_ge);
426 }
427 
428 
429 RegExpMacroAssembler::IrregexpImplementation
Implementation()430     RegExpMacroAssemblerTracer::Implementation() {
431   return assembler_->Implementation();
432 }
433 
434 
GetCode(Handle<String> source)435 Handle<HeapObject> RegExpMacroAssemblerTracer::GetCode(Handle<String> source) {
436   PrintF(" GetCode(%s);\n", source->ToCString().get());
437   return assembler_->GetCode(source);
438 }
439 
440 }  // namespace internal
441 }  // namespace v8
442