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

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

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

Powered by Google App Engine
This is Rietveld 408576698