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