~ubuntu-branches/ubuntu/trusty/libv8-3.14/trusty

« back to all changes in this revision

Viewing changes to src/ppc/regexp-macro-assembler-ppc.cc

  • Committer: Package Import Robot
  • Author(s): Adam Conrad
  • Date: 2014-02-12 10:26:54 UTC
  • Revision ID: package-import@ubuntu.com-20140212102654-mh2oalg31ifhjs0g
Tags: 3.14.5.8-5ubuntu1
* 0099_powerpc_support.patch: Pull in Andrew Low's powerpc port.
* debian/rules: Enable powerpc/ppc64/ppc64el for package builds.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2012 the V8 project authors. All rights reserved.
 
2
//
 
3
// Copyright IBM Corp. 2012, 2013. All rights reserved.
 
4
//
 
5
// Redistribution and use in source and binary forms, with or without
 
6
// modification, are permitted provided that the following conditions are
 
7
// met:
 
8
//
 
9
//     * Redistributions of source code must retain the above copyright
 
10
//       notice, this list of conditions and the following disclaimer.
 
11
//     * Redistributions in binary form must reproduce the above
 
12
//       copyright notice, this list of conditions and the following
 
13
//       disclaimer in the documentation and/or other materials provided
 
14
//       with the distribution.
 
15
//     * Neither the name of Google Inc. nor the names of its
 
16
//       contributors may be used to endorse or promote products derived
 
17
//       from this software without specific prior written permission.
 
18
//
 
19
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
20
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
21
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
22
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 
23
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
24
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
25
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
26
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
27
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
28
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
29
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
30
 
 
31
#include "v8.h"
 
32
 
 
33
#if defined(V8_TARGET_ARCH_PPC)
 
34
 
 
35
#include "unicode.h"
 
36
#include "log.h"
 
37
#include "code-stubs.h"
 
38
#include "regexp-stack.h"
 
39
#include "macro-assembler.h"
 
40
#include "regexp-macro-assembler.h"
 
41
#include "ppc/regexp-macro-assembler-ppc.h"
 
42
 
 
43
namespace v8 {
 
44
namespace internal {
 
45
 
 
46
#ifndef V8_INTERPRETED_REGEXP
 
47
/*
 
48
 * This assembler uses the following register assignment convention
 
49
 * - r25: Temporarily stores the index of capture start after a matching pass
 
50
 *        for a global regexp.
 
51
 * - r26: Pointer to current code object (Code*) including heap object tag.
 
52
 * - r27: Current position in input, as negative offset from end of string.
 
53
 *        Please notice that this is the byte offset, not the character offset!
 
54
 * - r28: Currently loaded character. Must be loaded using
 
55
 *        LoadCurrentCharacter before using any of the dispatch methods.
 
56
 * - r29: Points to tip of backtrack stack
 
57
 * - r30: End of input (points to byte after last character in input).
 
58
 * - r31: Frame pointer. Used to access arguments, local variables and
 
59
 *         RegExp registers.
 
60
 * - r12: IP register, used by assembler. Very volatile.
 
61
 * - r1/sp : Points to tip of C stack.
 
62
 *
 
63
 * The remaining registers are free for computations.
 
64
 * Each call to a public method should retain this convention.
 
65
 *
 
66
 * The stack will have the following structure:
 
67
 *  - fp[44]  Isolate* isolate   (address of the current isolate)
 
68
 *  - fp[40]  secondary link/return address used by native call.
 
69
 *  - fp[36]  lr save area (currently unused)
 
70
 *  - fp[32]  backchain    (currently unused)
 
71
 *  --- sp when called ---
 
72
 *  - fp[28]  return address     (lr).
 
73
 *  - fp[24]  old frame pointer  (r31).
 
74
 *  - fp[0..20]  backup of registers r25..r30
 
75
 *  --- frame pointer ----
 
76
 *  - fp[-4]  direct_call        (if 1, direct call from JavaScript code,
 
77
 *                                if 0, call through the runtime system).
 
78
 *  - fp[-8]  stack_area_base    (high end of the memory area to use as
 
79
 *                                backtracking stack).
 
80
 *  - fp[-12] capture array size (may fit multiple sets of matches)
 
81
 *  - fp[-16] int* capture_array (int[num_saved_registers_], for output).
 
82
 *  - fp[-20] end of input       (address of end of string).
 
83
 *  - fp[-24] start of input     (address of first character in string).
 
84
 *  - fp[-28] start index        (character index of start).
 
85
 *  - fp[-32] void* input_string (location of a handle containing the string).
 
86
 *  - fp[-36] success counter    (only for global regexps to count matches).
 
87
 *  - fp[-40] Offset of location before start of input (effectively character
 
88
 *            position -1). Used to initialize capture registers to a
 
89
 *            non-position.
 
90
 *  - fp[-44] At start (if 1, we are starting at the start of the
 
91
 *    string, otherwise 0)
 
92
 *  - fp[-48] register 0         (Only positions must be stored in the first
 
93
 *  -         register 1          num_saved_registers_ registers)
 
94
 *  -         ...
 
95
 *  -         register num_registers-1
 
96
 *  --- sp ---
 
97
 *
 
98
 * The first num_saved_registers_ registers are initialized to point to
 
99
 * "character -1" in the string (i.e., char_size() bytes before the first
 
100
 * character of the string). The remaining registers start out as garbage.
 
101
 *
 
102
 * The data up to the return address must be placed there by the calling
 
103
 * code and the remaining arguments are passed in registers, e.g. by calling the
 
104
 * code entry as cast to a function with the signature:
 
105
 * int (*match)(String* input_string,
 
106
 *              int start_index,
 
107
 *              Address start,
 
108
 *              Address end,
 
109
 *              int* capture_output_array,
 
110
 *              byte* stack_area_base,
 
111
 *              Address secondary_return_address,  // Only used by native call.
 
112
 *              bool direct_call = false)
 
113
 * The call is performed by NativeRegExpMacroAssembler::Execute()
 
114
 * (in regexp-macro-assembler.cc) via the CALL_GENERATED_REGEXP_CODE macro
 
115
 * in ppc/simulator-ppc.h.
 
116
 * When calling as a non-direct call (i.e., from C++ code), the return address
 
117
 * area is overwritten with the LR register by the RegExp code. When doing a
 
118
 * direct call from generated code, the return address is placed there by
 
119
 * the calling code, as in a normal exit frame.
 
120
 */
 
121
 
 
122
#define __ ACCESS_MASM(masm_)
 
123
 
 
124
RegExpMacroAssemblerPPC::RegExpMacroAssemblerPPC(
 
125
    Mode mode,
 
126
    int registers_to_save,
 
127
    Zone* zone)
 
128
    : NativeRegExpMacroAssembler(zone),
 
129
      masm_(new MacroAssembler(Isolate::Current(), NULL, kRegExpCodeSize)),
 
130
      mode_(mode),
 
131
      num_registers_(registers_to_save),
 
132
      num_saved_registers_(registers_to_save),
 
133
      entry_label_(),
 
134
      start_label_(),
 
135
      success_label_(),
 
136
      backtrack_label_(),
 
137
      exit_label_(),
 
138
      internal_failure_label_() {
 
139
  ASSERT_EQ(0, registers_to_save % 2);
 
140
 
 
141
  // Called from C
 
142
#if ABI_USES_FUNCTION_DESCRIPTORS
 
143
  __ function_descriptor();
 
144
#endif
 
145
 
 
146
  __ b(&entry_label_);   // We'll write the entry code later.
 
147
  // If the code gets too big or corrupted, an internal exception will be
 
148
  // raised, and we will exit right away.
 
149
  __ bind(&internal_failure_label_);
 
150
  __ li(r3, Operand(FAILURE));
 
151
  __ Ret();
 
152
  __ bind(&start_label_);  // And then continue from here.
 
153
}
 
154
 
 
155
 
 
156
RegExpMacroAssemblerPPC::~RegExpMacroAssemblerPPC() {
 
157
  delete masm_;
 
158
  // Unuse labels in case we throw away the assembler without calling GetCode.
 
159
  entry_label_.Unuse();
 
160
  start_label_.Unuse();
 
161
  success_label_.Unuse();
 
162
  backtrack_label_.Unuse();
 
163
  exit_label_.Unuse();
 
164
  check_preempt_label_.Unuse();
 
165
  stack_overflow_label_.Unuse();
 
166
  internal_failure_label_.Unuse();
 
167
}
 
168
 
 
169
 
 
170
int RegExpMacroAssemblerPPC::stack_limit_slack()  {
 
171
  return RegExpStack::kStackLimitSlack;
 
172
}
 
173
 
 
174
 
 
175
void RegExpMacroAssemblerPPC::AdvanceCurrentPosition(int by) {
 
176
  if (by != 0) {
 
177
    __ addi(current_input_offset(),
 
178
            current_input_offset(), Operand(by * char_size()));
 
179
  }
 
180
}
 
181
 
 
182
 
 
183
void RegExpMacroAssemblerPPC::AdvanceRegister(int reg, int by) {
 
184
  ASSERT(reg >= 0);
 
185
  ASSERT(reg < num_registers_);
 
186
  if (by != 0) {
 
187
    __ LoadP(r3, register_location(reg), r0);
 
188
    __ mov(r0, Operand(by));
 
189
    __ add(r3, r3, r0);
 
190
    __ StoreP(r3, register_location(reg), r0);
 
191
  }
 
192
}
 
193
 
 
194
 
 
195
void RegExpMacroAssemblerPPC::Backtrack() {
 
196
  CheckPreemption();
 
197
  // Pop Code* offset from backtrack stack, add Code* and jump to location.
 
198
  Pop(r3);
 
199
  __ add(r3, r3, code_pointer());
 
200
  __ mtctr(r3);
 
201
  __ bcr();
 
202
}
 
203
 
 
204
 
 
205
void RegExpMacroAssemblerPPC::Bind(Label* label) {
 
206
  __ bind(label);
 
207
}
 
208
 
 
209
 
 
210
void RegExpMacroAssemblerPPC::CheckCharacter(uint32_t c, Label* on_equal) {
 
211
  __ Cmpli(current_character(), Operand(c), r0);
 
212
  BranchOrBacktrack(eq, on_equal);
 
213
}
 
214
 
 
215
 
 
216
void RegExpMacroAssemblerPPC::CheckCharacterGT(uc16 limit, Label* on_greater) {
 
217
  __ Cmpli(current_character(), Operand(limit), r0);
 
218
  BranchOrBacktrack(gt, on_greater);
 
219
}
 
220
 
 
221
 
 
222
void RegExpMacroAssemblerPPC::CheckAtStart(Label* on_at_start) {
 
223
  Label not_at_start;
 
224
  // Did we start the match at the start of the string at all?
 
225
  __ LoadP(r3, MemOperand(frame_pointer(), kStartIndex));
 
226
  __ cmpi(r3, Operand::Zero());
 
227
  BranchOrBacktrack(ne, &not_at_start);
 
228
 
 
229
  // If we did, are we still at the start of the input?
 
230
  __ LoadP(r4, MemOperand(frame_pointer(), kInputStart));
 
231
  __ mr(r0, current_input_offset());
 
232
  __ add(r3, end_of_input_address(), r0);
 
233
  __ cmp(r4, r3);
 
234
  BranchOrBacktrack(eq, on_at_start);
 
235
  __ bind(&not_at_start);
 
236
}
 
237
 
 
238
 
 
239
void RegExpMacroAssemblerPPC::CheckNotAtStart(Label* on_not_at_start) {
 
240
  // Did we start the match at the start of the string at all?
 
241
  __ LoadP(r3, MemOperand(frame_pointer(), kStartIndex));
 
242
  __ cmpi(r3, Operand::Zero());
 
243
  BranchOrBacktrack(ne, on_not_at_start);
 
244
  // If we did, are we still at the start of the input?
 
245
  __ LoadP(r4, MemOperand(frame_pointer(), kInputStart));
 
246
  __ add(r3, end_of_input_address(), current_input_offset());
 
247
  __ cmp(r3, r4);
 
248
  BranchOrBacktrack(ne, on_not_at_start);
 
249
}
 
250
 
 
251
 
 
252
void RegExpMacroAssemblerPPC::CheckCharacterLT(uc16 limit, Label* on_less) {
 
253
  __ Cmpli(current_character(), Operand(limit), r0);
 
254
  BranchOrBacktrack(lt, on_less);
 
255
}
 
256
 
 
257
 
 
258
void RegExpMacroAssemblerPPC::CheckCharacters(Vector<const uc16> str,
 
259
                                              int cp_offset,
 
260
                                              Label* on_failure,
 
261
                                              bool check_end_of_string) {
 
262
  if (on_failure == NULL) {
 
263
    // Instead of inlining a backtrack for each test, (re)use the global
 
264
    // backtrack target.
 
265
    on_failure = &backtrack_label_;
 
266
  }
 
267
 
 
268
  if (check_end_of_string) {
 
269
    // Is last character of required match inside string.
 
270
    CheckPosition(cp_offset + str.length() - 1, on_failure);
 
271
  }
 
272
 
 
273
  __ add(r3, end_of_input_address(), current_input_offset());
 
274
  if (cp_offset != 0) {
 
275
    int byte_offset = cp_offset * char_size();
 
276
    __ addi(r3, r3, Operand(byte_offset));
 
277
  }
 
278
 
 
279
  // r3 : Address of characters to match against str.
 
280
  int stored_high_byte = 0;
 
281
  for (int i = 0; i < str.length(); i++) {
 
282
    if (mode_ == ASCII) {
 
283
      __ lbz(r4, MemOperand(r3));
 
284
      __ addi(r3, r3, Operand(char_size()));
 
285
      ASSERT(str[i] <= String::kMaxAsciiCharCode);
 
286
      __ cmpi(r4, Operand(str[i]));
 
287
    } else {
 
288
      __ lhz(r4, MemOperand(r3));
 
289
      __ addi(r3, r3, Operand(char_size()));
 
290
      uc16 match_char = str[i];
 
291
      int match_high_byte = (match_char >> 8);
 
292
      if (match_high_byte == 0) {
 
293
        __ cmpi(r4, Operand(str[i]));
 
294
      } else {
 
295
        if (match_high_byte != stored_high_byte) {
 
296
          __ li(r5, Operand(match_high_byte));
 
297
          stored_high_byte = match_high_byte;
 
298
        }
 
299
        __ addi(r6, r5, Operand(match_char & 0xff));
 
300
        __ cmp(r4, r6);
 
301
      }
 
302
    }
 
303
    BranchOrBacktrack(ne, on_failure);
 
304
  }
 
305
}
 
306
 
 
307
 
 
308
void RegExpMacroAssemblerPPC::CheckGreedyLoop(Label* on_equal) {
 
309
  Label backtrack_non_equal;
 
310
  __ LoadP(r3, MemOperand(backtrack_stackpointer(), 0));
 
311
  __ cmp(current_input_offset(), r3);
 
312
  __ bne(&backtrack_non_equal);
 
313
  __ addi(backtrack_stackpointer(),
 
314
         backtrack_stackpointer(), Operand(kPointerSize));
 
315
 
 
316
  __ bind(&backtrack_non_equal);
 
317
  BranchOrBacktrack(eq, on_equal);
 
318
}
 
319
 
 
320
 
 
321
void RegExpMacroAssemblerPPC::CheckNotBackReferenceIgnoreCase(
 
322
    int start_reg,
 
323
    Label* on_no_match) {
 
324
  Label fallthrough;
 
325
  __ LoadP(r3, register_location(start_reg), r0);  // Index of start of capture
 
326
  __ LoadP(r4, register_location(start_reg + 1), r0);  // Index of end
 
327
  __ sub(r4, r4, r3, LeaveOE, SetRC);  // Length of capture.
 
328
 
 
329
  // If length is zero, either the capture is empty or it is not participating.
 
330
  // In either case succeed immediately.
 
331
  __ beq(&fallthrough, cr0);
 
332
 
 
333
  // Check that there are enough characters left in the input.
 
334
  __ add(r0, r4, current_input_offset(), LeaveOE, SetRC);
 
335
//  __ cmn(r1, Operand(current_input_offset()));
 
336
  BranchOrBacktrack(gt, on_no_match, cr0);
 
337
 
 
338
  if (mode_ == ASCII) {
 
339
    Label success;
 
340
    Label fail;
 
341
    Label loop_check;
 
342
 
 
343
    // r3 - offset of start of capture
 
344
    // r4 - length of capture
 
345
    __ add(r3, r3, end_of_input_address());
 
346
    __ add(r5, end_of_input_address(), current_input_offset());
 
347
    __ add(r4, r3, r4);
 
348
 
 
349
    // r3 - Address of start of capture.
 
350
    // r4 - Address of end of capture
 
351
    // r5 - Address of current input position.
 
352
 
 
353
    Label loop;
 
354
    __ bind(&loop);
 
355
    __ lbz(r6, MemOperand(r3));
 
356
    __ addi(r3, r3, Operand(char_size()));
 
357
    __ lbz(r25, MemOperand(r5));
 
358
    __ addi(r5, r5, Operand(char_size()));
 
359
    __ cmp(r25, r6);
 
360
    __ beq(&loop_check);
 
361
 
 
362
    // Mismatch, try case-insensitive match (converting letters to lower-case).
 
363
    __ ori(r6, r6, Operand(0x20));  // Convert capture character to lower-case.
 
364
    __ ori(r25, r25, Operand(0x20));  // Also convert input character.
 
365
    __ cmp(r25, r6);
 
366
    __ bne(&fail);
 
367
    __ subi(r6, r6, Operand('a'));
 
368
    __ cmpli(r6, Operand('z' - 'a'));  // Is r6 a lowercase letter?
 
369
    __ bgt(&fail);
 
370
 
 
371
 
 
372
    __ bind(&loop_check);
 
373
    __ cmp(r3, r4);
 
374
    __ blt(&loop);
 
375
    __ b(&success);
 
376
 
 
377
    __ bind(&fail);
 
378
    BranchOrBacktrack(al, on_no_match);
 
379
 
 
380
    __ bind(&success);
 
381
    // Compute new value of character position after the matched part.
 
382
    __ sub(current_input_offset(), r5, end_of_input_address());
 
383
  } else {
 
384
    ASSERT(mode_ == UC16);
 
385
    int argument_count = 4;
 
386
    __ PrepareCallCFunction(argument_count, r5);
 
387
 
 
388
    // r3 - offset of start of capture
 
389
    // r4 - length of capture
 
390
 
 
391
    // Put arguments into arguments registers.
 
392
    // Parameters are
 
393
    //   r3: Address byte_offset1 - Address captured substring's start.
 
394
    //   r4: Address byte_offset2 - Address of current character position.
 
395
    //   r5: size_t byte_length - length of capture in bytes(!)
 
396
    //   r6: Isolate* isolate
 
397
 
 
398
    // Address of start of capture.
 
399
    __ add(r3, r3, end_of_input_address());
 
400
    // Length of capture.
 
401
    __ mr(r5, r4);
 
402
    // Save length in callee-save register for use on return.
 
403
    __ mr(r25, r4);
 
404
    // Address of current input position.
 
405
    __ add(r4, current_input_offset(), end_of_input_address());
 
406
    // Isolate.
 
407
    __ mov(r6, Operand(ExternalReference::isolate_address()));
 
408
 
 
409
    {
 
410
      AllowExternalCallThatCantCauseGC scope(masm_);
 
411
      ExternalReference function =
 
412
          ExternalReference::re_case_insensitive_compare_uc16(masm_->isolate());
 
413
      __ CallCFunction(function, argument_count);
 
414
    }
 
415
 
 
416
    // Check if function returned non-zero for success or zero for failure.
 
417
    __ cmpi(r3, Operand::Zero());
 
418
    BranchOrBacktrack(eq, on_no_match);
 
419
    // On success, increment position by length of capture.
 
420
    __ add(current_input_offset(), current_input_offset(), r25);
 
421
  }
 
422
 
 
423
  __ bind(&fallthrough);
 
424
}
 
425
 
 
426
 
 
427
void RegExpMacroAssemblerPPC::CheckNotBackReference(
 
428
    int start_reg,
 
429
    Label* on_no_match) {
 
430
  Label fallthrough;
 
431
  Label success;
 
432
 
 
433
  // Find length of back-referenced capture.
 
434
  __ LoadP(r3, register_location(start_reg), r0);
 
435
  __ LoadP(r4, register_location(start_reg + 1), r0);
 
436
  __ sub(r4, r4, r3, LeaveOE, SetRC);  // Length to check.
 
437
  // Succeed on empty capture (including no capture).
 
438
  __ beq(&fallthrough, cr0);
 
439
 
 
440
  // Check that there are enough characters left in the input.
 
441
  __ add(r0, r4, current_input_offset(), LeaveOE, SetRC);
 
442
  BranchOrBacktrack(gt, on_no_match, cr0);
 
443
 
 
444
  // Compute pointers to match string and capture string
 
445
  __ add(r3, r3, end_of_input_address());
 
446
  __ add(r5, end_of_input_address(), current_input_offset());
 
447
  __ add(r4, r4, r3);
 
448
 
 
449
  Label loop;
 
450
  __ bind(&loop);
 
451
  if (mode_ == ASCII) {
 
452
    __ lbz(r6, MemOperand(r3));
 
453
    __ addi(r3, r3, Operand(char_size()));
 
454
    __ lbz(r25, MemOperand(r5));
 
455
    __ addi(r5, r5, Operand(char_size()));
 
456
  } else {
 
457
    ASSERT(mode_ == UC16);
 
458
    __ lhz(r6, MemOperand(r3));
 
459
    __ addi(r3, r3, Operand(char_size()));
 
460
    __ lhz(r25, MemOperand(r5));
 
461
    __ addi(r5, r5, Operand(char_size()));
 
462
  }
 
463
  __ cmp(r6, r25);
 
464
  BranchOrBacktrack(ne, on_no_match);
 
465
  __ cmp(r3, r4);
 
466
  __ blt(&loop);
 
467
 
 
468
  // Move current character position to position after match.
 
469
  __ sub(current_input_offset(), r5, end_of_input_address());
 
470
  __ bind(&fallthrough);
 
471
}
 
472
 
 
473
 
 
474
void RegExpMacroAssemblerPPC::CheckNotCharacter(unsigned c,
 
475
                                                Label* on_not_equal) {
 
476
  __ Cmpli(current_character(), Operand(c), r0);
 
477
  BranchOrBacktrack(ne, on_not_equal);
 
478
}
 
479
 
 
480
 
 
481
void RegExpMacroAssemblerPPC::CheckCharacterAfterAnd(uint32_t c,
 
482
                                                     uint32_t mask,
 
483
                                                     Label* on_equal) {
 
484
  __ mov(r0, Operand(mask));
 
485
  if (c == 0) {
 
486
    __ and_(r3, current_character(), r0, SetRC);
 
487
  } else {
 
488
    __ and_(r3, current_character(), r0);
 
489
    __ Cmpli(r3, Operand(c), r0, cr0);
 
490
  }
 
491
  BranchOrBacktrack(eq, on_equal, cr0);
 
492
}
 
493
 
 
494
 
 
495
void RegExpMacroAssemblerPPC::CheckNotCharacterAfterAnd(unsigned c,
 
496
                                                        unsigned mask,
 
497
                                                        Label* on_not_equal) {
 
498
  __ mov(r0, Operand(mask));
 
499
  if (c == 0) {
 
500
    __ and_(r3, current_character(), r0, SetRC);
 
501
  } else {
 
502
    __ and_(r3, current_character(), r0);
 
503
    __ Cmpli(r3, Operand(c), r0, cr0);
 
504
  }
 
505
  BranchOrBacktrack(ne, on_not_equal, cr0);
 
506
}
 
507
 
 
508
 
 
509
void RegExpMacroAssemblerPPC::CheckNotCharacterAfterMinusAnd(
 
510
    uc16 c,
 
511
    uc16 minus,
 
512
    uc16 mask,
 
513
    Label* on_not_equal) {
 
514
  ASSERT(minus < String::kMaxUtf16CodeUnit);
 
515
  __ subi(r3, current_character(), Operand(minus));
 
516
  __ mov(r0, Operand(mask));
 
517
  __ and_(r3, r3, r0);
 
518
  __ Cmpli(r3, Operand(c), r0);
 
519
  BranchOrBacktrack(ne, on_not_equal);
 
520
}
 
521
 
 
522
 
 
523
void RegExpMacroAssemblerPPC::CheckCharacterInRange(
 
524
    uc16 from,
 
525
    uc16 to,
 
526
    Label* on_in_range) {
 
527
  __ mov(r0, Operand(from));
 
528
  __ sub(r3, current_character(), r0);
 
529
  __ Cmpli(r3, Operand(to - from), r0);
 
530
  BranchOrBacktrack(le, on_in_range);  // Unsigned lower-or-same condition.
 
531
}
 
532
 
 
533
 
 
534
void RegExpMacroAssemblerPPC::CheckCharacterNotInRange(
 
535
    uc16 from,
 
536
    uc16 to,
 
537
    Label* on_not_in_range) {
 
538
  __ mov(r0, Operand(from));
 
539
  __ sub(r3, current_character(), r0);
 
540
  __ Cmpli(r3, Operand(to - from), r0);
 
541
  BranchOrBacktrack(gt, on_not_in_range);  // Unsigned higher condition.
 
542
}
 
543
 
 
544
 
 
545
void RegExpMacroAssemblerPPC::CheckBitInTable(
 
546
    Handle<ByteArray> table,
 
547
    Label* on_bit_set) {
 
548
  __ mov(r3, Operand(table));
 
549
  if (mode_ != ASCII || kTableMask != String::kMaxAsciiCharCode) {
 
550
    __ andi(r4, current_character(), Operand(kTableSize - 1));
 
551
    __ addi(r4, r4, Operand(ByteArray::kHeaderSize - kHeapObjectTag));
 
552
  } else {
 
553
    __ addi(r4,
 
554
            current_character(),
 
555
            Operand(ByteArray::kHeaderSize - kHeapObjectTag));
 
556
  }
 
557
  __ lbzx(r3, MemOperand(r3, r4));
 
558
  __ cmpi(r3, Operand::Zero());
 
559
  BranchOrBacktrack(ne, on_bit_set);
 
560
}
 
561
 
 
562
 
 
563
bool RegExpMacroAssemblerPPC::CheckSpecialCharacterClass(uc16 type,
 
564
                                                         Label* on_no_match) {
 
565
  // Range checks (c in min..max) are generally implemented by an unsigned
 
566
  // (c - min) <= (max - min) check
 
567
  switch (type) {
 
568
  case 's':
 
569
    // Match space-characters
 
570
    if (mode_ == ASCII) {
 
571
      // ASCII space characters are '\t'..'\r' and ' '.
 
572
      Label success;
 
573
      __ cmpi(current_character(), Operand(' '));
 
574
      __ beq(&success);
 
575
      // Check range 0x09..0x0d
 
576
      __ subi(r3, current_character(), Operand('\t'));
 
577
      __ cmpli(r3, Operand('\r' - '\t'));
 
578
      BranchOrBacktrack(gt, on_no_match);
 
579
      __ bind(&success);
 
580
      return true;
 
581
    }
 
582
    return false;
 
583
  case 'S':
 
584
    // Match non-space characters.
 
585
    if (mode_ == ASCII) {
 
586
      // ASCII space characters are '\t'..'\r' and ' '.
 
587
      __ cmpi(current_character(), Operand(' '));
 
588
      BranchOrBacktrack(eq, on_no_match);
 
589
      __ subi(r3, current_character(), Operand('\t'));
 
590
      __ cmpli(r3, Operand('\r' - '\t'));
 
591
      BranchOrBacktrack(le, on_no_match);
 
592
      return true;
 
593
    }
 
594
    return false;
 
595
  case 'd':
 
596
    // Match ASCII digits ('0'..'9')
 
597
    __ subi(r3, current_character(), Operand('0'));
 
598
    __ cmpli(current_character(), Operand('9' - '0'));
 
599
    BranchOrBacktrack(gt, on_no_match);
 
600
    return true;
 
601
  case 'D':
 
602
    // Match non ASCII-digits
 
603
    __ subi(r3, current_character(), Operand('0'));
 
604
    __ cmpli(r3, Operand('9' - '0'));
 
605
    BranchOrBacktrack(le, on_no_match);
 
606
    return true;
 
607
  case '.': {
 
608
    // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029)
 
609
    __ xori(r3, current_character(), Operand(0x01));
 
610
    // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c
 
611
    __ subi(r3, r3, Operand(0x0b));
 
612
    __ cmpli(r3, Operand(0x0c - 0x0b));
 
613
    BranchOrBacktrack(le, on_no_match);
 
614
    if (mode_ == UC16) {
 
615
      // Compare original value to 0x2028 and 0x2029, using the already
 
616
      // computed (current_char ^ 0x01 - 0x0b). I.e., check for
 
617
      // 0x201d (0x2028 - 0x0b) or 0x201e.
 
618
      __ subi(r3, r3, Operand(0x2028 - 0x0b));
 
619
      __ cmpli(r3, Operand(1));
 
620
      BranchOrBacktrack(le, on_no_match);
 
621
    }
 
622
    return true;
 
623
  }
 
624
  case 'n': {
 
625
    // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029)
 
626
    __ xori(r3, current_character(), Operand(0x01));
 
627
    // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c
 
628
    __ subi(r3, r3, Operand(0x0b));
 
629
    __ cmpli(r3, Operand(0x0c - 0x0b));
 
630
    if (mode_ == ASCII) {
 
631
      BranchOrBacktrack(gt, on_no_match);
 
632
    } else {
 
633
      Label done;
 
634
      __ ble(&done);
 
635
      // Compare original value to 0x2028 and 0x2029, using the already
 
636
      // computed (current_char ^ 0x01 - 0x0b). I.e., check for
 
637
      // 0x201d (0x2028 - 0x0b) or 0x201e.
 
638
      __ subi(r3, r3, Operand(0x2028 - 0x0b));
 
639
      __ cmpli(r3, Operand(1));
 
640
      BranchOrBacktrack(gt, on_no_match);
 
641
      __ bind(&done);
 
642
    }
 
643
    return true;
 
644
  }
 
645
  case 'w': {
 
646
    if (mode_ != ASCII) {
 
647
      // Table is 128 entries, so all ASCII characters can be tested.
 
648
      __ cmpi(current_character(), Operand('z'));
 
649
      BranchOrBacktrack(gt, on_no_match);
 
650
    }
 
651
    ExternalReference map = ExternalReference::re_word_character_map();
 
652
    __ mov(r3, Operand(map));
 
653
    __ lbzx(r3, MemOperand(r3, current_character()));
 
654
    __ cmpli(r3, Operand::Zero());
 
655
    BranchOrBacktrack(eq, on_no_match);
 
656
    return true;
 
657
  }
 
658
  case 'W': {
 
659
    Label done;
 
660
    if (mode_ != ASCII) {
 
661
      // Table is 128 entries, so all ASCII characters can be tested.
 
662
      __ cmpli(current_character(), Operand('z'));
 
663
      __ bgt(&done);
 
664
    }
 
665
    ExternalReference map = ExternalReference::re_word_character_map();
 
666
    __ mov(r3, Operand(map));
 
667
    __ lbzx(r3, MemOperand(r3, current_character()));
 
668
    __ cmpli(r3, Operand::Zero());
 
669
    BranchOrBacktrack(ne, on_no_match);
 
670
    if (mode_ != ASCII) {
 
671
      __ bind(&done);
 
672
    }
 
673
    return true;
 
674
  }
 
675
  case '*':
 
676
    // Match any character.
 
677
    return true;
 
678
  // No custom implementation (yet): s(UC16), S(UC16).
 
679
  default:
 
680
    return false;
 
681
  }
 
682
}
 
683
 
 
684
 
 
685
void RegExpMacroAssemblerPPC::Fail() {
 
686
  __ li(r3, Operand(FAILURE));
 
687
  __ b(&exit_label_);
 
688
}
 
689
 
 
690
 
 
691
Handle<HeapObject> RegExpMacroAssemblerPPC::GetCode(Handle<String> source) {
 
692
  Label return_r3;
 
693
 
 
694
  if (masm_->has_exception()) {
 
695
    // If the code gets corrupted due to long regular expressions and lack of
 
696
    // space on trampolines, an internal exception flag is set. If this case
 
697
    // is detected, we will jump into exit sequence right away.
 
698
    __ bind_to(&entry_label_, internal_failure_label_.pos());
 
699
  } else {
 
700
    // Finalize code - write the entry point code now we know how many
 
701
    // registers we need.
 
702
 
 
703
    // Entry code:
 
704
    __ bind(&entry_label_);
 
705
 
 
706
    // Tell the system that we have a stack frame.  Because the type
 
707
    // is MANUAL, no is generated.
 
708
    FrameScope scope(masm_, StackFrame::MANUAL);
 
709
 
 
710
    // Ensure register assigments are consistent with callee save mask
 
711
    ASSERT(r25.bit() & kRegExpCalleeSaved);
 
712
    ASSERT(code_pointer().bit() & kRegExpCalleeSaved);
 
713
    ASSERT(current_input_offset().bit() & kRegExpCalleeSaved);
 
714
    ASSERT(current_character().bit() & kRegExpCalleeSaved);
 
715
    ASSERT(backtrack_stackpointer().bit() & kRegExpCalleeSaved);
 
716
    ASSERT(end_of_input_address().bit() & kRegExpCalleeSaved);
 
717
    ASSERT(frame_pointer().bit() & kRegExpCalleeSaved);
 
718
 
 
719
    // Actually emit code to start a new stack frame.
 
720
    // Push arguments
 
721
    // Save callee-save registers.
 
722
    // Start new stack frame.
 
723
    // Store link register in existing stack-cell.
 
724
    // Order here should correspond to order of offset constants in header file.
 
725
    RegList registers_to_retain = kRegExpCalleeSaved;
 
726
    RegList argument_registers = r3.bit() | r4.bit() | r5.bit() | r6.bit() |
 
727
      r7.bit() | r8.bit() | r9.bit() | r10.bit();
 
728
    __ mflr(r0);
 
729
    __ push(r0);
 
730
    __ MultiPush(argument_registers | registers_to_retain);
 
731
    // Set frame pointer in space for it if this is not a direct call
 
732
    // from generated code.
 
733
    __ addi(frame_pointer(), sp, Operand(8 * kPointerSize));
 
734
    __ li(r3, Operand::Zero());
 
735
    __ push(r3);  // Make room for success counter and initialize it to 0.
 
736
    __ push(r3);  // Make room for "position - 1" constant (value is irrelevant)
 
737
    // Check if we have space on the stack for registers.
 
738
    Label stack_limit_hit;
 
739
    Label stack_ok;
 
740
 
 
741
    ExternalReference stack_limit =
 
742
      ExternalReference::address_of_stack_limit(masm_->isolate());
 
743
    __ mov(r3, Operand(stack_limit));
 
744
    __ LoadP(r3, MemOperand(r3));
 
745
    __ sub(r3, sp, r3, LeaveOE, SetRC);
 
746
    // Handle it if the stack pointer is already below the stack limit.
 
747
    __ ble(&stack_limit_hit, cr0);
 
748
    // Check if there is room for the variable number of registers above
 
749
    // the stack limit.
 
750
    __ Cmpli(r3, Operand(num_registers_ * kPointerSize), r0);
 
751
    __ bge(&stack_ok);
 
752
    // Exit with OutOfMemory exception. There is not enough space on the stack
 
753
    // for our working registers.
 
754
    __ li(r3, Operand(EXCEPTION));
 
755
    __ b(&return_r3);
 
756
 
 
757
    __ bind(&stack_limit_hit);
 
758
    CallCheckStackGuardState(r3);
 
759
    __ cmpi(r3, Operand::Zero());
 
760
    // If returned value is non-zero, we exit with the returned value as result.
 
761
    __ bne(&return_r3);
 
762
 
 
763
    __ bind(&stack_ok);
 
764
 
 
765
    // Allocate space on stack for registers.
 
766
    __ Add(sp, sp, -num_registers_ * kPointerSize, r0);
 
767
    // Load string end.
 
768
    __ LoadP(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd));
 
769
    // Load input start.
 
770
    __ LoadP(r3, MemOperand(frame_pointer(), kInputStart));
 
771
    // Find negative length (offset of start relative to end).
 
772
    __ sub(current_input_offset(), r3, end_of_input_address());
 
773
    // Set r3 to address of char before start of the input string
 
774
    // (effectively string position -1).
 
775
    __ LoadP(r4, MemOperand(frame_pointer(), kStartIndex));
 
776
    __ subi(r3, current_input_offset(), Operand(char_size()));
 
777
    if (mode_ == UC16) {
 
778
      __ ShiftLeftImm(r0, r4, Operand(1));
 
779
      __ sub(r3, r3, r0);
 
780
    } else {
 
781
      __ sub(r3, r3, r4);
 
782
    }
 
783
    // Store this value in a local variable, for use when clearing
 
784
    // position registers.
 
785
    __ StoreP(r3, MemOperand(frame_pointer(), kInputStartMinusOne));
 
786
 
 
787
    // Initialize code pointer register
 
788
    __ mov(code_pointer(), Operand(masm_->CodeObject()));
 
789
 
 
790
    Label load_char_start_regexp, start_regexp;
 
791
    // Load newline if index is at start, previous character otherwise.
 
792
    __ cmpi(r4, Operand::Zero());
 
793
    __ bne(&load_char_start_regexp);
 
794
    __ li(current_character(), Operand('\n'));
 
795
    __ b(&start_regexp);
 
796
 
 
797
    // Global regexp restarts matching here.
 
798
    __ bind(&load_char_start_regexp);
 
799
    // Load previous char as initial value of current character register.
 
800
    LoadCurrentCharacterUnchecked(-1, 1);
 
801
    __ bind(&start_regexp);
 
802
 
 
803
    // Initialize on-stack registers.
 
804
    if (num_saved_registers_ > 0) {  // Always is, if generated from a regexp.
 
805
      // Fill saved registers with initial value = start offset - 1
 
806
      if (num_saved_registers_ > 8) {
 
807
        // One slot beyond address of register 0.
 
808
        __ addi(r4, frame_pointer(), Operand(kRegisterZero + kPointerSize));
 
809
        __ li(r5, Operand(num_saved_registers_));
 
810
        __ mtctr(r5);
 
811
        Label init_loop;
 
812
        __ bind(&init_loop);
 
813
        __ StorePU(r3, MemOperand(r4, -kPointerSize));
 
814
        __ bdnz(&init_loop);
 
815
      } else {
 
816
        for (int i = 0; i < num_saved_registers_; i++) {
 
817
          __ StoreP(r3, register_location(i), r0);
 
818
        }
 
819
      }
 
820
    }
 
821
 
 
822
    // Initialize backtrack stack pointer.
 
823
    __ LoadP(backtrack_stackpointer(),
 
824
             MemOperand(frame_pointer(), kStackHighEnd));
 
825
 
 
826
    __ b(&start_label_);
 
827
 
 
828
    // Exit code:
 
829
    if (success_label_.is_linked()) {
 
830
      // Save captures when successful.
 
831
      __ bind(&success_label_);
 
832
      if (num_saved_registers_ > 0) {
 
833
        // copy captures to output
 
834
        __ LoadP(r4, MemOperand(frame_pointer(), kInputStart));
 
835
        __ LoadP(r3, MemOperand(frame_pointer(), kRegisterOutput));
 
836
        __ LoadP(r5, MemOperand(frame_pointer(), kStartIndex));
 
837
        __ sub(r4, end_of_input_address(), r4);
 
838
        // r4 is length of input in bytes.
 
839
        if (mode_ == UC16) {
 
840
          __ ShiftRightImm(r4, r4, Operand(1));
 
841
        }
 
842
        // r4 is length of input in characters.
 
843
        __ add(r4, r4, r5);
 
844
        // r4 is length of string in characters.
 
845
 
 
846
        ASSERT_EQ(0, num_saved_registers_ % 2);
 
847
        // Always an even number of capture registers. This allows us to
 
848
        // unroll the loop once to add an operation between a load of a register
 
849
        // and the following use of that register.
 
850
        for (int i = 0; i < num_saved_registers_; i += 2) {
 
851
          __ LoadP(r5, register_location(i), r0);
 
852
          __ LoadP(r6, register_location(i + 1), r0);
 
853
          if (i == 0 && global_with_zero_length_check()) {
 
854
            // Keep capture start in r25 for the zero-length check later.
 
855
            __ mr(r25, r5);
 
856
          }
 
857
          if (mode_ == UC16) {
 
858
            __ ShiftRightArithImm(r5, r5, 1);
 
859
            __ add(r5, r4, r5);
 
860
            __ ShiftRightArithImm(r6, r6, 1);
 
861
            __ add(r6, r4, r6);
 
862
          } else {
 
863
            __ add(r5, r4, r5);
 
864
            __ add(r6, r4, r6);
 
865
          }
 
866
          __ stw(r5, MemOperand(r3));
 
867
          __ addi(r3, r3, Operand(kIntSize));
 
868
          __ stw(r6, MemOperand(r3));
 
869
          __ addi(r3, r3, Operand(kIntSize));
 
870
        }
 
871
      }
 
872
 
 
873
      if (global()) {
 
874
        // Restart matching if the regular expression is flagged as global.
 
875
        __ LoadP(r3, MemOperand(frame_pointer(), kSuccessfulCaptures));
 
876
        __ LoadP(r4, MemOperand(frame_pointer(), kNumOutputRegisters));
 
877
        __ LoadP(r5, MemOperand(frame_pointer(), kRegisterOutput));
 
878
        // Increment success counter.
 
879
        __ addi(r3, r3, Operand(1));
 
880
        __ StoreP(r3, MemOperand(frame_pointer(), kSuccessfulCaptures));
 
881
        // Capture results have been stored, so the number of remaining global
 
882
        // output registers is reduced by the number of stored captures.
 
883
        __ subi(r4, r4, Operand(num_saved_registers_));
 
884
        // Check whether we have enough room for another set of capture results.
 
885
        __ cmpi(r4, Operand(num_saved_registers_));
 
886
        __ blt(&return_r3);
 
887
 
 
888
        __ StoreP(r4, MemOperand(frame_pointer(), kNumOutputRegisters));
 
889
        // Advance the location for output.
 
890
        __ addi(r5, r5, Operand(num_saved_registers_ * kIntSize));
 
891
        __ StoreP(r5, MemOperand(frame_pointer(), kRegisterOutput));
 
892
 
 
893
        // Prepare r3 to initialize registers with its value in the next run.
 
894
        __ LoadP(r3, MemOperand(frame_pointer(), kInputStartMinusOne));
 
895
 
 
896
        if (global_with_zero_length_check()) {
 
897
          // Special case for zero-length matches.
 
898
          // r25: capture start index
 
899
          __ cmp(current_input_offset(), r25);
 
900
          // Not a zero-length match, restart.
 
901
          __ bne(&load_char_start_regexp);
 
902
          // Offset from the end is zero if we already reached the end.
 
903
          __ cmpi(current_input_offset(), Operand::Zero());
 
904
          __ beq(&exit_label_);
 
905
          // Advance current position after a zero-length match.
 
906
          __ addi(current_input_offset(),
 
907
                  current_input_offset(),
 
908
                  Operand((mode_ == UC16) ? 2 : 1));
 
909
        }
 
910
 
 
911
        __ b(&load_char_start_regexp);
 
912
      } else {
 
913
        __ li(r3, Operand(SUCCESS));
 
914
      }
 
915
    }
 
916
 
 
917
    // Exit and return r3
 
918
    __ bind(&exit_label_);
 
919
    if (global()) {
 
920
      __ LoadP(r3, MemOperand(frame_pointer(), kSuccessfulCaptures));
 
921
    }
 
922
 
 
923
    __ bind(&return_r3);
 
924
    // Skip sp past regexp registers and local variables..
 
925
    __ mr(sp, frame_pointer());
 
926
    // Restore registers r25..r31 and return (restoring lr to pc).
 
927
    __ MultiPop(registers_to_retain);
 
928
    __ pop(r0);
 
929
    __ mtctr(r0);
 
930
    __ bcr();
 
931
 
 
932
    // Backtrack code (branch target for conditional backtracks).
 
933
    if (backtrack_label_.is_linked()) {
 
934
      __ bind(&backtrack_label_);
 
935
      Backtrack();
 
936
    }
 
937
 
 
938
    Label exit_with_exception;
 
939
 
 
940
    // Preempt-code
 
941
    if (check_preempt_label_.is_linked()) {
 
942
      SafeCallTarget(&check_preempt_label_);
 
943
 
 
944
      CallCheckStackGuardState(r3);
 
945
      __ cmpi(r3, Operand::Zero());
 
946
      // If returning non-zero, we should end execution with the given
 
947
      // result as return value.
 
948
      __ bne(&return_r3);
 
949
 
 
950
      // String might have moved: Reload end of string from frame.
 
951
      __ LoadP(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd));
 
952
      SafeReturn();
 
953
    }
 
954
 
 
955
    // Backtrack stack overflow code.
 
956
    if (stack_overflow_label_.is_linked()) {
 
957
      SafeCallTarget(&stack_overflow_label_);
 
958
      // Reached if the backtrack-stack limit has been hit.
 
959
      Label grow_failed;
 
960
 
 
961
      // Call GrowStack(backtrack_stackpointer(), &stack_base)
 
962
      static const int num_arguments = 3;
 
963
      __ PrepareCallCFunction(num_arguments, r3);
 
964
      __ mr(r3, backtrack_stackpointer());
 
965
      __ addi(r4, frame_pointer(), Operand(kStackHighEnd));
 
966
      __ mov(r5, Operand(ExternalReference::isolate_address()));
 
967
      ExternalReference grow_stack =
 
968
        ExternalReference::re_grow_stack(masm_->isolate());
 
969
      __ CallCFunction(grow_stack, num_arguments);
 
970
      // If return NULL, we have failed to grow the stack, and
 
971
      // must exit with a stack-overflow exception.
 
972
      __ cmpi(r3, Operand::Zero());
 
973
      __ beq(&exit_with_exception);
 
974
      // Otherwise use return value as new stack pointer.
 
975
      __ mr(backtrack_stackpointer(), r3);
 
976
      // Restore saved registers and continue.
 
977
      SafeReturn();
 
978
    }
 
979
 
 
980
    if (exit_with_exception.is_linked()) {
 
981
      // If any of the code above needed to exit with an exception.
 
982
      __ bind(&exit_with_exception);
 
983
      // Exit with Result EXCEPTION(-1) to signal thrown exception.
 
984
      __ li(r3, Operand(EXCEPTION));
 
985
      __ b(&return_r3);
 
986
    }
 
987
  }
 
988
 
 
989
  CodeDesc code_desc;
 
990
  masm_->GetCode(&code_desc);
 
991
  Handle<Code> code = FACTORY->NewCode(code_desc,
 
992
                                       Code::ComputeFlags(Code::REGEXP),
 
993
                                       masm_->CodeObject());
 
994
  PROFILE(Isolate::Current(), RegExpCodeCreateEvent(*code, *source));
 
995
  return Handle<HeapObject>::cast(code);
 
996
}
 
997
 
 
998
 
 
999
void RegExpMacroAssemblerPPC::GoTo(Label* to) {
 
1000
  BranchOrBacktrack(al, to);
 
1001
}
 
1002
 
 
1003
 
 
1004
void RegExpMacroAssemblerPPC::IfRegisterGE(int reg,
 
1005
                                           int comparand,
 
1006
                                           Label* if_ge) {
 
1007
  __ LoadP(r3, register_location(reg), r0);
 
1008
  __ Cmpi(r3, Operand(comparand), r0);
 
1009
  BranchOrBacktrack(ge, if_ge);
 
1010
}
 
1011
 
 
1012
 
 
1013
void RegExpMacroAssemblerPPC::IfRegisterLT(int reg,
 
1014
                                           int comparand,
 
1015
                                           Label* if_lt) {
 
1016
  __ LoadP(r3, register_location(reg), r0);
 
1017
  __ Cmpi(r3, Operand(comparand), r0);
 
1018
  BranchOrBacktrack(lt, if_lt);
 
1019
}
 
1020
 
 
1021
 
 
1022
void RegExpMacroAssemblerPPC::IfRegisterEqPos(int reg,
 
1023
                                              Label* if_eq) {
 
1024
  __ LoadP(r3, register_location(reg), r0);
 
1025
  __ cmp(r3, current_input_offset());
 
1026
  BranchOrBacktrack(eq, if_eq);
 
1027
}
 
1028
 
 
1029
 
 
1030
RegExpMacroAssembler::IrregexpImplementation
 
1031
    RegExpMacroAssemblerPPC::Implementation() {
 
1032
  return kPPCImplementation;
 
1033
}
 
1034
 
 
1035
 
 
1036
void RegExpMacroAssemblerPPC::LoadCurrentCharacter(int cp_offset,
 
1037
                                                   Label* on_end_of_input,
 
1038
                                                   bool check_bounds,
 
1039
                                                   int characters) {
 
1040
  ASSERT(cp_offset >= -1);      // ^ and \b can look behind one character.
 
1041
  ASSERT(cp_offset < (1<<30));  // Be sane! (And ensure negation works)
 
1042
  if (check_bounds) {
 
1043
    CheckPosition(cp_offset + characters - 1, on_end_of_input);
 
1044
  }
 
1045
  LoadCurrentCharacterUnchecked(cp_offset, characters);
 
1046
}
 
1047
 
 
1048
 
 
1049
void RegExpMacroAssemblerPPC::PopCurrentPosition() {
 
1050
  Pop(current_input_offset());
 
1051
}
 
1052
 
 
1053
 
 
1054
void RegExpMacroAssemblerPPC::PopRegister(int register_index) {
 
1055
  Pop(r3);
 
1056
  __ StoreP(r3, register_location(register_index), r0);
 
1057
}
 
1058
 
 
1059
 
 
1060
void RegExpMacroAssemblerPPC::PushBacktrack(Label* label) {
 
1061
  if (label->is_bound()) {
 
1062
    int target = label->pos();
 
1063
    __ mov(r3, Operand(target + Code::kHeaderSize - kHeapObjectTag));
 
1064
  } else {
 
1065
    Label after_constant;
 
1066
    __ b(&after_constant);
 
1067
    int offset = masm_->pc_offset();
 
1068
    int cp_offset = offset + Code::kHeaderSize - kHeapObjectTag;
 
1069
    __ emit(0);
 
1070
    masm_->label_at_put(label, offset);
 
1071
    __ bind(&after_constant);
 
1072
    __ LoadWord(r3, MemOperand(code_pointer(), cp_offset), r0);
 
1073
  }
 
1074
  Push(r3);
 
1075
  CheckStackLimit();
 
1076
}
 
1077
 
 
1078
 
 
1079
void RegExpMacroAssemblerPPC::PushCurrentPosition() {
 
1080
  Push(current_input_offset());
 
1081
}
 
1082
 
 
1083
 
 
1084
void RegExpMacroAssemblerPPC::PushRegister(int register_index,
 
1085
                                           StackCheckFlag check_stack_limit) {
 
1086
  __ LoadP(r3, register_location(register_index), r0);
 
1087
  Push(r3);
 
1088
  if (check_stack_limit) CheckStackLimit();
 
1089
}
 
1090
 
 
1091
 
 
1092
void RegExpMacroAssemblerPPC::ReadCurrentPositionFromRegister(int reg) {
 
1093
  __ LoadP(current_input_offset(), register_location(reg), r0);
 
1094
}
 
1095
 
 
1096
 
 
1097
void RegExpMacroAssemblerPPC::ReadStackPointerFromRegister(int reg) {
 
1098
  __ LoadP(backtrack_stackpointer(), register_location(reg), r0);
 
1099
  __ LoadP(r3, MemOperand(frame_pointer(), kStackHighEnd));
 
1100
  __ add(backtrack_stackpointer(), backtrack_stackpointer(), r3);
 
1101
}
 
1102
 
 
1103
 
 
1104
void RegExpMacroAssemblerPPC::SetCurrentPositionFromEnd(int by) {
 
1105
  Label after_position;
 
1106
  __ Cmpi(current_input_offset(), Operand(-by * char_size()), r0);
 
1107
  __ bge(&after_position);
 
1108
  __ mov(current_input_offset(), Operand(-by * char_size()));
 
1109
  // On RegExp code entry (where this operation is used), the character before
 
1110
  // the current position is expected to be already loaded.
 
1111
  // We have advanced the position, so it's safe to read backwards.
 
1112
  LoadCurrentCharacterUnchecked(-1, 1);
 
1113
  __ bind(&after_position);
 
1114
}
 
1115
 
 
1116
 
 
1117
void RegExpMacroAssemblerPPC::SetRegister(int register_index, int to) {
 
1118
  ASSERT(register_index >= num_saved_registers_);  // Reserved for positions!
 
1119
  __ mov(r3, Operand(to));
 
1120
  __ StoreP(r3, register_location(register_index), r0);
 
1121
}
 
1122
 
 
1123
 
 
1124
bool RegExpMacroAssemblerPPC::Succeed() {
 
1125
  __ b(&success_label_);
 
1126
  return global();
 
1127
}
 
1128
 
 
1129
 
 
1130
void RegExpMacroAssemblerPPC::WriteCurrentPositionToRegister(int reg,
 
1131
                                                             int cp_offset) {
 
1132
  if (cp_offset == 0) {
 
1133
    __ StoreP(current_input_offset(), register_location(reg), r0);
 
1134
  } else {
 
1135
    __ mov(r0, Operand(cp_offset * char_size()));
 
1136
    __ add(r3, current_input_offset(), r0);
 
1137
    __ StoreP(r3, register_location(reg), r0);
 
1138
  }
 
1139
}
 
1140
 
 
1141
 
 
1142
void RegExpMacroAssemblerPPC::ClearRegisters(int reg_from, int reg_to) {
 
1143
  ASSERT(reg_from <= reg_to);
 
1144
  __ LoadP(r3, MemOperand(frame_pointer(), kInputStartMinusOne));
 
1145
  for (int reg = reg_from; reg <= reg_to; reg++) {
 
1146
    __ StoreP(r3, register_location(reg), r0);
 
1147
  }
 
1148
}
 
1149
 
 
1150
 
 
1151
void RegExpMacroAssemblerPPC::WriteStackPointerToRegister(int reg) {
 
1152
  __ LoadP(r4, MemOperand(frame_pointer(), kStackHighEnd));
 
1153
  __ sub(r3, backtrack_stackpointer(), r4);
 
1154
  __ StoreP(r3, register_location(reg), r0);
 
1155
}
 
1156
 
 
1157
 
 
1158
// Private methods:
 
1159
 
 
1160
void RegExpMacroAssemblerPPC::CallCheckStackGuardState(Register scratch) {
 
1161
  static const int num_arguments = 3;
 
1162
  __ PrepareCallCFunction(num_arguments, scratch);
 
1163
  // RegExp code frame pointer.
 
1164
  __ mr(r5, frame_pointer());
 
1165
  // Code* of self.
 
1166
  __ mov(r4, Operand(masm_->CodeObject()));
 
1167
  // r3 becomes return address pointer.
 
1168
  ExternalReference stack_guard_check =
 
1169
      ExternalReference::re_check_stack_guard_state(masm_->isolate());
 
1170
  CallCFunctionUsingStub(stack_guard_check, num_arguments);
 
1171
}
 
1172
 
 
1173
 
 
1174
// Helper function for reading a value out of a stack frame.
 
1175
template <typename T>
 
1176
static T& frame_entry(Address re_frame, int frame_offset) {
 
1177
  return reinterpret_cast<T&>(Memory::int32_at(re_frame + frame_offset));
 
1178
}
 
1179
 
 
1180
 
 
1181
int RegExpMacroAssemblerPPC::CheckStackGuardState(Address* return_address,
 
1182
                                                  Code* re_code,
 
1183
                                                  Address re_frame) {
 
1184
  Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate);
 
1185
  ASSERT(isolate == Isolate::Current());
 
1186
  if (isolate->stack_guard()->IsStackOverflow()) {
 
1187
    isolate->StackOverflow();
 
1188
    return EXCEPTION;
 
1189
  }
 
1190
 
 
1191
  // If not real stack overflow the stack guard was used to interrupt
 
1192
  // execution for another purpose.
 
1193
 
 
1194
  // If this is a direct call from JavaScript retry the RegExp forcing the call
 
1195
  // through the runtime system. Currently the direct call cannot handle a GC.
 
1196
  if (frame_entry<int>(re_frame, kDirectCall) == 1) {
 
1197
    return RETRY;
 
1198
  }
 
1199
 
 
1200
  // Prepare for possible GC.
 
1201
  HandleScope handles(isolate);
 
1202
  Handle<Code> code_handle(re_code);
 
1203
 
 
1204
  Handle<String> subject(frame_entry<String*>(re_frame, kInputString));
 
1205
 
 
1206
  // Current string.
 
1207
  bool is_ascii = subject->IsAsciiRepresentationUnderneath();
 
1208
 
 
1209
  ASSERT(re_code->instruction_start() <= *return_address);
 
1210
  ASSERT(*return_address <=
 
1211
      re_code->instruction_start() + re_code->instruction_size());
 
1212
 
 
1213
  MaybeObject* result = Execution::HandleStackGuardInterrupt(isolate);
 
1214
 
 
1215
  if (*code_handle != re_code) {  // Return address no longer valid
 
1216
    int delta = code_handle->address() - re_code->address();
 
1217
    // Overwrite the return address on the stack.
 
1218
    *return_address += delta;
 
1219
  }
 
1220
 
 
1221
  if (result->IsException()) {
 
1222
    return EXCEPTION;
 
1223
  }
 
1224
 
 
1225
  Handle<String> subject_tmp = subject;
 
1226
  int slice_offset = 0;
 
1227
 
 
1228
  // Extract the underlying string and the slice offset.
 
1229
  if (StringShape(*subject_tmp).IsCons()) {
 
1230
    subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first());
 
1231
  } else if (StringShape(*subject_tmp).IsSliced()) {
 
1232
    SlicedString* slice = SlicedString::cast(*subject_tmp);
 
1233
    subject_tmp = Handle<String>(slice->parent());
 
1234
    slice_offset = slice->offset();
 
1235
  }
 
1236
 
 
1237
  // String might have changed.
 
1238
  if (subject_tmp->IsAsciiRepresentation() != is_ascii) {
 
1239
    // If we changed between an ASCII and an UC16 string, the specialized
 
1240
    // code cannot be used, and we need to restart regexp matching from
 
1241
    // scratch (including, potentially, compiling a new version of the code).
 
1242
    return RETRY;
 
1243
  }
 
1244
 
 
1245
  // Otherwise, the content of the string might have moved. It must still
 
1246
  // be a sequential or external string with the same content.
 
1247
  // Update the start and end pointers in the stack frame to the current
 
1248
  // location (whether it has actually moved or not).
 
1249
  ASSERT(StringShape(*subject_tmp).IsSequential() ||
 
1250
      StringShape(*subject_tmp).IsExternal());
 
1251
 
 
1252
  // The original start address of the characters to match.
 
1253
  const byte* start_address = frame_entry<const byte*>(re_frame, kInputStart);
 
1254
 
 
1255
  // Find the current start address of the same character at the current string
 
1256
  // position.
 
1257
  int start_index = frame_entry<intptr_t>(re_frame, kStartIndex);
 
1258
  const byte* new_address = StringCharacterPosition(*subject_tmp,
 
1259
                                                    start_index + slice_offset);
 
1260
 
 
1261
  if (start_address != new_address) {
 
1262
    // If there is a difference, update the object pointer and start and end
 
1263
    // addresses in the RegExp stack frame to match the new value.
 
1264
    const byte* end_address = frame_entry<const byte* >(re_frame, kInputEnd);
 
1265
    int byte_length = static_cast<int>(end_address - start_address);
 
1266
    frame_entry<const String*>(re_frame, kInputString) = *subject;
 
1267
    frame_entry<const byte*>(re_frame, kInputStart) = new_address;
 
1268
    frame_entry<const byte*>(re_frame, kInputEnd) = new_address + byte_length;
 
1269
  } else if (frame_entry<const String*>(re_frame, kInputString) != *subject) {
 
1270
    // Subject string might have been a ConsString that underwent
 
1271
    // short-circuiting during GC. That will not change start_address but
 
1272
    // will change pointer inside the subject handle.
 
1273
    frame_entry<const String*>(re_frame, kInputString) = *subject;
 
1274
  }
 
1275
 
 
1276
  return 0;
 
1277
}
 
1278
 
 
1279
 
 
1280
MemOperand RegExpMacroAssemblerPPC::register_location(int register_index) {
 
1281
  ASSERT(register_index < (1<<30));
 
1282
  if (num_registers_ <= register_index) {
 
1283
    num_registers_ = register_index + 1;
 
1284
  }
 
1285
  return MemOperand(frame_pointer(),
 
1286
                    kRegisterZero - register_index * kPointerSize);
 
1287
}
 
1288
 
 
1289
 
 
1290
void RegExpMacroAssemblerPPC::CheckPosition(int cp_offset,
 
1291
                                            Label* on_outside_input) {
 
1292
  __ Cmpi(current_input_offset(), Operand(-cp_offset * char_size()), r0);
 
1293
  BranchOrBacktrack(ge, on_outside_input);
 
1294
}
 
1295
 
 
1296
 
 
1297
void RegExpMacroAssemblerPPC::BranchOrBacktrack(Condition condition,
 
1298
                                                Label* to,
 
1299
                                                CRegister cr) {
 
1300
  if (condition == al) {  // Unconditional.
 
1301
    if (to == NULL) {
 
1302
      Backtrack();
 
1303
      return;
 
1304
    }
 
1305
    __ b(to);
 
1306
    return;
 
1307
  }
 
1308
  if (to == NULL) {
 
1309
    __ b(condition, &backtrack_label_, cr);
 
1310
    return;
 
1311
  }
 
1312
  __ b(condition, to, cr);
 
1313
}
 
1314
 
 
1315
 
 
1316
void RegExpMacroAssemblerPPC::SafeCall(Label* to, Condition cond,
 
1317
                                       CRegister cr) {
 
1318
  __ b(cond, to, cr, SetLK);
 
1319
}
 
1320
 
 
1321
 
 
1322
void RegExpMacroAssemblerPPC::SafeReturn() {
 
1323
  __ pop(r0);
 
1324
  __ mov(ip, Operand(masm_->CodeObject()));
 
1325
  __ add(r0, r0, ip);
 
1326
  __ mtlr(r0);
 
1327
  __ blr();
 
1328
}
 
1329
 
 
1330
 
 
1331
void RegExpMacroAssemblerPPC::SafeCallTarget(Label* name) {
 
1332
  __ bind(name);
 
1333
  __ mflr(r0);
 
1334
  __ mov(ip, Operand(masm_->CodeObject()));
 
1335
  __ sub(r0, r0, ip);
 
1336
  __ push(r0);
 
1337
}
 
1338
 
 
1339
 
 
1340
void RegExpMacroAssemblerPPC::Push(Register source) {
 
1341
  ASSERT(!source.is(backtrack_stackpointer()));
 
1342
  __ StorePU(source, MemOperand(backtrack_stackpointer(), -kPointerSize));
 
1343
}
 
1344
 
 
1345
 
 
1346
void RegExpMacroAssemblerPPC::Pop(Register target) {
 
1347
  ASSERT(!target.is(backtrack_stackpointer()));
 
1348
  __ LoadP(target, MemOperand(backtrack_stackpointer()));
 
1349
  __ addi(backtrack_stackpointer(), backtrack_stackpointer(),
 
1350
          Operand(kPointerSize));
 
1351
}
 
1352
 
 
1353
 
 
1354
void RegExpMacroAssemblerPPC::CheckPreemption() {
 
1355
  // Check for preemption.
 
1356
  ExternalReference stack_limit =
 
1357
      ExternalReference::address_of_stack_limit(masm_->isolate());
 
1358
  __ mov(r3, Operand(stack_limit));
 
1359
  __ LoadP(r3, MemOperand(r3));
 
1360
  __ cmpl(sp, r3);
 
1361
  SafeCall(&check_preempt_label_, le);
 
1362
}
 
1363
 
 
1364
 
 
1365
void RegExpMacroAssemblerPPC::CheckStackLimit() {
 
1366
  ExternalReference stack_limit =
 
1367
      ExternalReference::address_of_regexp_stack_limit(masm_->isolate());
 
1368
  __ mov(r3, Operand(stack_limit));
 
1369
  __ LoadP(r3, MemOperand(r3));
 
1370
  __ cmpl(backtrack_stackpointer(), r3);
 
1371
  SafeCall(&stack_overflow_label_, le);
 
1372
}
 
1373
 
 
1374
 
 
1375
void RegExpMacroAssemblerPPC::CallCFunctionUsingStub(
 
1376
    ExternalReference function,
 
1377
    int num_arguments) {
 
1378
  // Must pass all arguments in registers. The stub pushes on the stack.
 
1379
  ASSERT(num_arguments <= 8);
 
1380
  __ mov(code_pointer(), Operand(function));
 
1381
  RegExpCEntryStub stub;
 
1382
  __ CallStub(&stub);
 
1383
  if (OS::ActivationFrameAlignment() > kPointerSize) {
 
1384
    __ LoadP(sp, MemOperand(sp, 0));
 
1385
  } else {
 
1386
    __ addi(sp, sp, Operand(kNumRequiredStackFrameSlots * kPointerSize));
 
1387
  }
 
1388
  __ mov(code_pointer(), Operand(masm_->CodeObject()));
 
1389
}
 
1390
 
 
1391
 
 
1392
bool RegExpMacroAssemblerPPC::CanReadUnaligned() {
 
1393
  return CpuFeatures::IsSupported(UNALIGNED_ACCESSES) && !slow_safe();
 
1394
}
 
1395
 
 
1396
 
 
1397
void RegExpMacroAssemblerPPC::LoadCurrentCharacterUnchecked(int cp_offset,
 
1398
                                                            int characters) {
 
1399
  Register offset = current_input_offset();
 
1400
  if (cp_offset != 0) {
 
1401
    // r25 is not being used to store the capture start index at this point.
 
1402
    __ addi(r25, current_input_offset(), Operand(cp_offset * char_size()));
 
1403
    offset = r25;
 
1404
  }
 
1405
  // The lwz, stw, lhz, sth instructions can do unaligned accesses, if the CPU
 
1406
  // and the operating system running on the target allow it.
 
1407
  // We assume we don't want to do unaligned loads on PPC, so this function
 
1408
  // must only be used to load a single character at a time.
 
1409
 
 
1410
  ASSERT(characters == 1);
 
1411
  __ add(current_character(), end_of_input_address(), offset);
 
1412
  if (mode_ == ASCII) {
 
1413
    __ lbz(current_character(), MemOperand(current_character()));
 
1414
  } else {
 
1415
    ASSERT(mode_ == UC16);
 
1416
    __ lhz(current_character(), MemOperand(current_character()));
 
1417
  }
 
1418
}
 
1419
 
 
1420
 
 
1421
void RegExpCEntryStub::Generate(MacroAssembler* masm_) {
 
1422
  int stack_alignment = OS::ActivationFrameAlignment();
 
1423
  if (stack_alignment < kPointerSize) stack_alignment = kPointerSize;
 
1424
 
 
1425
  // Stack is already aligned for call, so decrement by alignment
 
1426
  // to make room for storing the return address.
 
1427
  int extra_stack_slots = stack_alignment >> kPointerSizeLog2;
 
1428
 
 
1429
  __ addi(r3, sp, Operand(-stack_alignment));
 
1430
  __ mflr(r0);
 
1431
  __ StoreP(r0, MemOperand(r3, 0));
 
1432
 
 
1433
  // PPC LINUX ABI:
 
1434
  extra_stack_slots += kNumRequiredStackFrameSlots;
 
1435
  __ addi(sp, sp, Operand(-extra_stack_slots * kPointerSize));
 
1436
 
 
1437
#if ABI_USES_FUNCTION_DESCRIPTORS && !defined(USE_SIMULATOR)
 
1438
  // Native AIX/PPC64 Linux use a function descriptor.
 
1439
  __ LoadP(ToRegister(2), MemOperand(r26, kPointerSize));  // TOC
 
1440
  __ LoadP(ip, MemOperand(r26, 0));  // Instruction address
 
1441
  Register target = ip;
 
1442
#elif ABI_TOC_ADDRESSABILITY_VIA_IP
 
1443
  Register target = ip;
 
1444
  __ Move(target, r26);
 
1445
#else
 
1446
  Register target = r26;
 
1447
#endif
 
1448
 
 
1449
  __ Call(target);
 
1450
 
 
1451
  __ addi(sp, sp, Operand(extra_stack_slots * kPointerSize));
 
1452
 
 
1453
  __ LoadP(r0, MemOperand(sp, -stack_alignment));
 
1454
  __ mtlr(r0);
 
1455
  __ blr();
 
1456
}
 
1457
 
 
1458
#undef __
 
1459
 
 
1460
#endif  // V8_INTERPRETED_REGEXP
 
1461
 
 
1462
}}  // namespace v8::internal
 
1463
 
 
1464
#endif  // V8_TARGET_ARCH_PPC