Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(310)

Side by Side Diff: src/ppc/regexp-macro-assembler-ppc.cc

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

Powered by Google App Engine
This is Rietveld 408576698