1// Copyright 2012 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29#include "ast.h"
30#include "regexp-macro-assembler.h"
31#include "regexp-macro-assembler-tracer.h"
32
33namespace v8 {
34namespace internal {
35
36RegExpMacroAssemblerTracer::RegExpMacroAssemblerTracer(
37    RegExpMacroAssembler* assembler) :
38  RegExpMacroAssembler(assembler->zone()),
39  assembler_(assembler) {
40  unsigned int type = assembler->Implementation();
41  ASSERT(type < 5);
42  const char* impl_names[] = {"IA32", "ARM", "MIPS", "X64", "Bytecode"};
43  PrintF("RegExpMacroAssembler%s();\n", impl_names[type]);
44}
45
46
47RegExpMacroAssemblerTracer::~RegExpMacroAssemblerTracer() {
48}
49
50
51// This is used for printing out debugging information.  It makes an integer
52// that is closely related to the address of an object.
53static int LabelToInt(Label* label) {
54  return static_cast<int>(reinterpret_cast<intptr_t>(label));
55}
56
57
58void RegExpMacroAssemblerTracer::Bind(Label* label) {
59  PrintF("label[%08x]: (Bind)\n", LabelToInt(label));
60  assembler_->Bind(label);
61}
62
63
64void RegExpMacroAssemblerTracer::AdvanceCurrentPosition(int by) {
65  PrintF(" AdvanceCurrentPosition(by=%d);\n", by);
66  assembler_->AdvanceCurrentPosition(by);
67}
68
69
70void RegExpMacroAssemblerTracer::CheckGreedyLoop(Label* label) {
71  PrintF(" CheckGreedyLoop(label[%08x]);\n\n", LabelToInt(label));
72  assembler_->CheckGreedyLoop(label);
73}
74
75
76void RegExpMacroAssemblerTracer::PopCurrentPosition() {
77  PrintF(" PopCurrentPosition();\n");
78  assembler_->PopCurrentPosition();
79}
80
81
82void RegExpMacroAssemblerTracer::PushCurrentPosition() {
83  PrintF(" PushCurrentPosition();\n");
84  assembler_->PushCurrentPosition();
85}
86
87
88void RegExpMacroAssemblerTracer::Backtrack() {
89  PrintF(" Backtrack();\n");
90  assembler_->Backtrack();
91}
92
93
94void RegExpMacroAssemblerTracer::GoTo(Label* label) {
95  PrintF(" GoTo(label[%08x]);\n\n", LabelToInt(label));
96  assembler_->GoTo(label);
97}
98
99
100void RegExpMacroAssemblerTracer::PushBacktrack(Label* label) {
101  PrintF(" PushBacktrack(label[%08x]);\n", LabelToInt(label));
102  assembler_->PushBacktrack(label);
103}
104
105
106bool RegExpMacroAssemblerTracer::Succeed() {
107  bool restart = assembler_->Succeed();
108  PrintF(" Succeed();%s\n", restart ? " [restart for global match]" : "");
109  return restart;
110}
111
112
113void RegExpMacroAssemblerTracer::Fail() {
114  PrintF(" Fail();");
115  assembler_->Fail();
116}
117
118
119void RegExpMacroAssemblerTracer::PopRegister(int register_index) {
120  PrintF(" PopRegister(register=%d);\n", register_index);
121  assembler_->PopRegister(register_index);
122}
123
124
125void RegExpMacroAssemblerTracer::PushRegister(
126    int register_index,
127    StackCheckFlag check_stack_limit) {
128  PrintF(" PushRegister(register=%d, %s);\n",
129         register_index,
130         check_stack_limit ? "check stack limit" : "");
131  assembler_->PushRegister(register_index, check_stack_limit);
132}
133
134
135void RegExpMacroAssemblerTracer::AdvanceRegister(int reg, int by) {
136  PrintF(" AdvanceRegister(register=%d, by=%d);\n", reg, by);
137  assembler_->AdvanceRegister(reg, by);
138}
139
140
141void RegExpMacroAssemblerTracer::SetCurrentPositionFromEnd(int by) {
142  PrintF(" SetCurrentPositionFromEnd(by=%d);\n", by);
143  assembler_->SetCurrentPositionFromEnd(by);
144}
145
146
147void RegExpMacroAssemblerTracer::SetRegister(int register_index, int to) {
148  PrintF(" SetRegister(register=%d, to=%d);\n", register_index, to);
149  assembler_->SetRegister(register_index, to);
150}
151
152
153void RegExpMacroAssemblerTracer::WriteCurrentPositionToRegister(int reg,
154                                                                int cp_offset) {
155  PrintF(" WriteCurrentPositionToRegister(register=%d,cp_offset=%d);\n",
156         reg,
157         cp_offset);
158  assembler_->WriteCurrentPositionToRegister(reg, cp_offset);
159}
160
161
162void RegExpMacroAssemblerTracer::ClearRegisters(int reg_from, int reg_to) {
163  PrintF(" ClearRegister(from=%d, to=%d);\n", reg_from, reg_to);
164  assembler_->ClearRegisters(reg_from, reg_to);
165}
166
167
168void RegExpMacroAssemblerTracer::ReadCurrentPositionFromRegister(int reg) {
169  PrintF(" ReadCurrentPositionFromRegister(register=%d);\n", reg);
170  assembler_->ReadCurrentPositionFromRegister(reg);
171}
172
173
174void RegExpMacroAssemblerTracer::WriteStackPointerToRegister(int reg) {
175  PrintF(" WriteStackPointerToRegister(register=%d);\n", reg);
176  assembler_->WriteStackPointerToRegister(reg);
177}
178
179
180void RegExpMacroAssemblerTracer::ReadStackPointerFromRegister(int reg) {
181  PrintF(" ReadStackPointerFromRegister(register=%d);\n", reg);
182  assembler_->ReadStackPointerFromRegister(reg);
183}
184
185
186void RegExpMacroAssemblerTracer::LoadCurrentCharacter(int cp_offset,
187                                                      Label* on_end_of_input,
188                                                      bool check_bounds,
189                                                      int characters) {
190  const char* check_msg = check_bounds ? "" : " (unchecked)";
191  PrintF(" LoadCurrentCharacter(cp_offset=%d, label[%08x]%s (%d chars));\n",
192         cp_offset,
193         LabelToInt(on_end_of_input),
194         check_msg,
195         characters);
196  assembler_->LoadCurrentCharacter(cp_offset,
197                                   on_end_of_input,
198                                   check_bounds,
199                                   characters);
200}
201
202
203class PrintablePrinter {
204 public:
205  explicit PrintablePrinter(uc16 character) : character_(character) { }
206
207  const char* operator*() {
208    if (character_ >= ' ' && character_ <= '~') {
209      buffer_[0] = '(';
210      buffer_[1] = static_cast<char>(character_);
211      buffer_[2] = ')';
212      buffer_[3] = '\0';
213    } else {
214      buffer_[0] = '\0';
215    }
216    return &buffer_[0];
217  };
218
219 private:
220  uc16 character_;
221  char buffer_[4];
222};
223
224
225void RegExpMacroAssemblerTracer::CheckCharacterLT(uc16 limit, Label* on_less) {
226  PrintablePrinter printable(limit);
227  PrintF(" CheckCharacterLT(c=0x%04x%s, label[%08x]);\n",
228         limit,
229         *printable,
230         LabelToInt(on_less));
231  assembler_->CheckCharacterLT(limit, on_less);
232}
233
234
235void RegExpMacroAssemblerTracer::CheckCharacterGT(uc16 limit,
236                                                  Label* on_greater) {
237  PrintablePrinter printable(limit);
238  PrintF(" CheckCharacterGT(c=0x%04x%s, label[%08x]);\n",
239         limit,
240         *printable,
241         LabelToInt(on_greater));
242  assembler_->CheckCharacterGT(limit, on_greater);
243}
244
245
246void RegExpMacroAssemblerTracer::CheckCharacter(unsigned c, Label* on_equal) {
247  PrintablePrinter printable(c);
248  PrintF(" CheckCharacter(c=0x%04x%s, label[%08x]);\n",
249         c,
250         *printable,
251         LabelToInt(on_equal));
252  assembler_->CheckCharacter(c, on_equal);
253}
254
255
256void RegExpMacroAssemblerTracer::CheckAtStart(Label* on_at_start) {
257  PrintF(" CheckAtStart(label[%08x]);\n", LabelToInt(on_at_start));
258  assembler_->CheckAtStart(on_at_start);
259}
260
261
262void RegExpMacroAssemblerTracer::CheckNotAtStart(Label* on_not_at_start) {
263  PrintF(" CheckNotAtStart(label[%08x]);\n", LabelToInt(on_not_at_start));
264  assembler_->CheckNotAtStart(on_not_at_start);
265}
266
267
268void RegExpMacroAssemblerTracer::CheckNotCharacter(unsigned c,
269                                                   Label* on_not_equal) {
270  PrintablePrinter printable(c);
271  PrintF(" CheckNotCharacter(c=0x%04x%s, label[%08x]);\n",
272         c,
273         *printable,
274         LabelToInt(on_not_equal));
275  assembler_->CheckNotCharacter(c, on_not_equal);
276}
277
278
279void RegExpMacroAssemblerTracer::CheckCharacterAfterAnd(
280    unsigned c,
281    unsigned mask,
282    Label* on_equal) {
283  PrintablePrinter printable(c);
284  PrintF(" CheckCharacterAfterAnd(c=0x%04x%s, mask=0x%04x, label[%08x]);\n",
285         c,
286         *printable,
287         mask,
288         LabelToInt(on_equal));
289  assembler_->CheckCharacterAfterAnd(c, mask, on_equal);
290}
291
292
293void RegExpMacroAssemblerTracer::CheckNotCharacterAfterAnd(
294    unsigned c,
295    unsigned mask,
296    Label* on_not_equal) {
297  PrintablePrinter printable(c);
298  PrintF(" CheckNotCharacterAfterAnd(c=0x%04x%s, mask=0x%04x, label[%08x]);\n",
299         c,
300         *printable,
301         mask,
302         LabelToInt(on_not_equal));
303  assembler_->CheckNotCharacterAfterAnd(c, mask, on_not_equal);
304}
305
306
307void RegExpMacroAssemblerTracer::CheckNotCharacterAfterMinusAnd(
308    uc16 c,
309    uc16 minus,
310    uc16 mask,
311    Label* on_not_equal) {
312  PrintF(" CheckNotCharacterAfterMinusAnd(c=0x%04x, minus=%04x, mask=0x%04x, "
313             "label[%08x]);\n",
314         c,
315         minus,
316         mask,
317         LabelToInt(on_not_equal));
318  assembler_->CheckNotCharacterAfterMinusAnd(c, minus, mask, on_not_equal);
319}
320
321
322void RegExpMacroAssemblerTracer::CheckCharacterInRange(
323    uc16 from,
324    uc16 to,
325    Label* on_not_in_range) {
326  PrintablePrinter printable_from(from);
327  PrintablePrinter printable_to(to);
328  PrintF(" CheckCharacterInRange(from=0x%04x%s, to=0x%04x%s, label[%08x]);\n",
329         from,
330         *printable_from,
331         to,
332         *printable_to,
333         LabelToInt(on_not_in_range));
334  assembler_->CheckCharacterInRange(from, to, on_not_in_range);
335}
336
337
338void RegExpMacroAssemblerTracer::CheckCharacterNotInRange(
339    uc16 from,
340    uc16 to,
341    Label* on_in_range) {
342  PrintablePrinter printable_from(from);
343  PrintablePrinter printable_to(to);
344  PrintF(
345      " CheckCharacterNotInRange(from=0x%04x%s," " to=%04x%s, label[%08x]);\n",
346      from,
347      *printable_from,
348      to,
349      *printable_to,
350      LabelToInt(on_in_range));
351  assembler_->CheckCharacterNotInRange(from, to, on_in_range);
352}
353
354
355void RegExpMacroAssemblerTracer::CheckBitInTable(
356    Handle<ByteArray> table, Label* on_bit_set) {
357  PrintF(" CheckBitInTable(label[%08x] ", LabelToInt(on_bit_set));
358  for (int i = 0; i < kTableSize; i++) {
359    PrintF("%c", table->get(i) != 0 ? 'X' : '.');
360    if (i % 32 == 31 && i != kTableMask) {
361      PrintF("\n                                 ");
362    }
363  }
364  PrintF(");\n");
365  assembler_->CheckBitInTable(table, on_bit_set);
366}
367
368
369void RegExpMacroAssemblerTracer::CheckNotBackReference(int start_reg,
370                                                       Label* on_no_match) {
371  PrintF(" CheckNotBackReference(register=%d, label[%08x]);\n", start_reg,
372         LabelToInt(on_no_match));
373  assembler_->CheckNotBackReference(start_reg, on_no_match);
374}
375
376
377void RegExpMacroAssemblerTracer::CheckNotBackReferenceIgnoreCase(
378    int start_reg,
379    Label* on_no_match) {
380  PrintF(" CheckNotBackReferenceIgnoreCase(register=%d, label[%08x]);\n",
381         start_reg, LabelToInt(on_no_match));
382  assembler_->CheckNotBackReferenceIgnoreCase(start_reg, on_no_match);
383}
384
385
386bool RegExpMacroAssemblerTracer::CheckSpecialCharacterClass(
387    uc16 type,
388    Label* on_no_match) {
389  bool supported = assembler_->CheckSpecialCharacterClass(type,
390                                                          on_no_match);
391  PrintF(" CheckSpecialCharacterClass(type='%c', label[%08x]): %s;\n",
392         type,
393         LabelToInt(on_no_match),
394         supported ? "true" : "false");
395  return supported;
396}
397
398
399void RegExpMacroAssemblerTracer::IfRegisterLT(int register_index,
400                                              int comparand, Label* if_lt) {
401  PrintF(" IfRegisterLT(register=%d, number=%d, label[%08x]);\n",
402         register_index, comparand, LabelToInt(if_lt));
403  assembler_->IfRegisterLT(register_index, comparand, if_lt);
404}
405
406
407void RegExpMacroAssemblerTracer::IfRegisterEqPos(int register_index,
408                                                 Label* if_eq) {
409  PrintF(" IfRegisterEqPos(register=%d, label[%08x]);\n",
410         register_index, LabelToInt(if_eq));
411  assembler_->IfRegisterEqPos(register_index, if_eq);
412}
413
414
415void RegExpMacroAssemblerTracer::IfRegisterGE(int register_index,
416                                              int comparand, Label* if_ge) {
417  PrintF(" IfRegisterGE(register=%d, number=%d, label[%08x]);\n",
418         register_index, comparand, LabelToInt(if_ge));
419  assembler_->IfRegisterGE(register_index, comparand, if_ge);
420}
421
422
423RegExpMacroAssembler::IrregexpImplementation
424    RegExpMacroAssemblerTracer::Implementation() {
425  return assembler_->Implementation();
426}
427
428
429Handle<HeapObject> RegExpMacroAssemblerTracer::GetCode(Handle<String> source) {
430  PrintF(" GetCode(%s);\n", *(source->ToCString()));
431  return assembler_->GetCode(source);
432}
433
434}}  // namespace v8::internal
435