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

Side by Side Diff: src/x87/code-stubs-x87.cc

Issue 2738413002: [regexp] Port RegExpExecStub to CSA (mostly) (Closed)
Patch Set: Rebase Created 3 years, 9 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/x64/interface-descriptors-x64.cc ('k') | src/x87/interface-descriptors-x87.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #if V8_TARGET_ARCH_X87 5 #if V8_TARGET_ARCH_X87
6 6
7 #include "src/code-stubs.h" 7 #include "src/code-stubs.h"
8 #include "src/api-arguments.h" 8 #include "src/api-arguments.h"
9 #include "src/base/bits.h" 9 #include "src/base/bits.h"
10 #include "src/bootstrapper.h" 10 #include "src/bootstrapper.h"
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 // Put the double_exponent parameter in call stack 275 // Put the double_exponent parameter in call stack
276 __ fstp_d(Operand(esp, 1 * kDoubleSize)); 276 __ fstp_d(Operand(esp, 1 * kDoubleSize));
277 __ CallCFunction(ExternalReference::power_double_double_function(isolate()), 277 __ CallCFunction(ExternalReference::power_double_double_function(isolate()),
278 4); 278 4);
279 } 279 }
280 // Return value is in st(0) on ia32. 280 // Return value is in st(0) on ia32.
281 __ ret(0); 281 __ ret(0);
282 } 282 }
283 283
284 void RegExpExecStub::Generate(MacroAssembler* masm) { 284 void RegExpExecStub::Generate(MacroAssembler* masm) {
285 // Just jump directly to runtime if native RegExp is not selected at compile
286 // time or if regexp entry in generated code is turned off runtime switch or
287 // at compilation.
288 #ifdef V8_INTERPRETED_REGEXP 285 #ifdef V8_INTERPRETED_REGEXP
289 __ TailCallRuntime(Runtime::kRegExpExec); 286 // This case is handled prior to the RegExpExecStub call.
287 __ Abort(kUnexpectedRegExpExecCall);
290 #else // V8_INTERPRETED_REGEXP 288 #else // V8_INTERPRETED_REGEXP
291
292 // Stack frame on entry.
293 // esp[0]: return address
294 // esp[4]: last_match_info (expected JSArray)
295 // esp[8]: previous index
296 // esp[12]: subject string
297 // esp[16]: JSRegExp object
298
299 static const int kLastMatchInfoOffset = 1 * kPointerSize;
300 static const int kPreviousIndexOffset = 2 * kPointerSize;
301 static const int kSubjectOffset = 3 * kPointerSize;
302 static const int kJSRegExpOffset = 4 * kPointerSize;
303
304 Label runtime;
305 Factory* factory = isolate()->factory();
306
307 // Ensure that a RegExp stack is allocated.
308 ExternalReference address_of_regexp_stack_memory_address =
309 ExternalReference::address_of_regexp_stack_memory_address(isolate());
310 ExternalReference address_of_regexp_stack_memory_size =
311 ExternalReference::address_of_regexp_stack_memory_size(isolate());
312 __ mov(ebx, Operand::StaticVariable(address_of_regexp_stack_memory_size));
313 __ test(ebx, ebx);
314 __ j(zero, &runtime);
315
316 // Check that the first argument is a JSRegExp object.
317 __ mov(eax, Operand(esp, kJSRegExpOffset));
318 STATIC_ASSERT(kSmiTag == 0);
319 __ JumpIfSmi(eax, &runtime);
320 __ CmpObjectType(eax, JS_REGEXP_TYPE, ecx);
321 __ j(not_equal, &runtime);
322
323 // Check that the RegExp has been compiled (data contains a fixed array).
324 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset));
325 if (FLAG_debug_code) {
326 __ test(ecx, Immediate(kSmiTagMask));
327 __ Check(not_zero, kUnexpectedTypeForRegExpDataFixedArrayExpected);
328 __ CmpObjectType(ecx, FIXED_ARRAY_TYPE, ebx);
329 __ Check(equal, kUnexpectedTypeForRegExpDataFixedArrayExpected);
330 }
331
332 // ecx: RegExp data (FixedArray)
333 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP.
334 __ mov(ebx, FieldOperand(ecx, JSRegExp::kDataTagOffset));
335 __ cmp(ebx, Immediate(Smi::FromInt(JSRegExp::IRREGEXP)));
336 __ j(not_equal, &runtime);
337
338 // ecx: RegExp data (FixedArray)
339 // Check that the number of captures fit in the static offsets vector buffer.
340 __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset));
341 // Check (number_of_captures + 1) * 2 <= offsets vector size
342 // Or number_of_captures * 2 <= offsets vector size - 2
343 // Multiplying by 2 comes for free since edx is smi-tagged.
344 STATIC_ASSERT(kSmiTag == 0);
345 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
346 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2);
347 __ cmp(edx, Isolate::kJSRegexpStaticOffsetsVectorSize - 2);
348 __ j(above, &runtime);
349
350 // Reset offset for possibly sliced string.
351 __ Move(edi, Immediate(0));
352 __ mov(eax, Operand(esp, kSubjectOffset));
353 __ JumpIfSmi(eax, &runtime);
354 __ mov(edx, eax); // Make a copy of the original subject string.
355
356 // eax: subject string
357 // edx: subject string
358 // ecx: RegExp data (FixedArray)
359 // Handle subject string according to its encoding and representation:
360 // (1) Sequential two byte? If yes, go to (9).
361 // (2) Sequential one byte? If yes, go to (5).
362 // (3) Sequential or cons? If not, go to (6).
363 // (4) Cons string. If the string is flat, replace subject with first string
364 // and go to (1). Otherwise bail out to runtime.
365 // (5) One byte sequential. Load regexp code for one byte.
366 // (E) Carry on.
367 /// [...]
368
369 // Deferred code at the end of the stub:
370 // (6) Long external string? If not, go to (10).
371 // (7) External string. Make it, offset-wise, look like a sequential string.
372 // (8) Is the external string one byte? If yes, go to (5).
373 // (9) Two byte sequential. Load regexp code for two byte. Go to (E).
374 // (10) Short external string or not a string? If yes, bail out to runtime.
375 // (11) Sliced or thin string. Replace subject with parent. Go to (1).
376
377 Label seq_one_byte_string /* 5 */, seq_two_byte_string /* 9 */,
378 external_string /* 7 */, check_underlying /* 1 */,
379 not_seq_nor_cons /* 6 */, check_code /* E */, not_long_external /* 10 */;
380
381 __ bind(&check_underlying);
382 // (1) Sequential two byte? If yes, go to (9).
383 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
384 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
385
386 __ and_(ebx, kIsNotStringMask |
387 kStringRepresentationMask |
388 kStringEncodingMask |
389 kShortExternalStringMask);
390 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0);
391 __ j(zero, &seq_two_byte_string); // Go to (9).
392
393 // (2) Sequential one byte? If yes, go to (5).
394 // Any other sequential string must be one byte.
395 __ and_(ebx, Immediate(kIsNotStringMask |
396 kStringRepresentationMask |
397 kShortExternalStringMask));
398 __ j(zero, &seq_one_byte_string, Label::kNear); // Go to (5).
399
400 // (3) Sequential or cons? If not, go to (6).
401 // We check whether the subject string is a cons, since sequential strings
402 // have already been covered.
403 STATIC_ASSERT(kConsStringTag < kExternalStringTag);
404 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
405 STATIC_ASSERT(kThinStringTag > kExternalStringTag);
406 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
407 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
408 __ cmp(ebx, Immediate(kExternalStringTag));
409 __ j(greater_equal, &not_seq_nor_cons); // Go to (6).
410
411 // (4) Cons string. Check that it's flat.
412 // Replace subject with first string and reload instance type.
413 __ cmp(FieldOperand(eax, ConsString::kSecondOffset), factory->empty_string());
414 __ j(not_equal, &runtime);
415 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset));
416 __ jmp(&check_underlying);
417
418 // eax: sequential subject string (or look-alike, external string)
419 // edx: original subject string
420 // ecx: RegExp data (FixedArray)
421 // (5) One byte sequential. Load regexp code for one byte.
422 __ bind(&seq_one_byte_string);
423 // Load previous index and check range before edx is overwritten. We have
424 // to use edx instead of eax here because it might have been only made to
425 // look like a sequential string when it actually is an external string.
426 __ mov(ebx, Operand(esp, kPreviousIndexOffset));
427 __ JumpIfNotSmi(ebx, &runtime);
428 __ cmp(ebx, FieldOperand(edx, String::kLengthOffset));
429 __ j(above_equal, &runtime);
430 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataOneByteCodeOffset));
431 __ Move(ecx, Immediate(1)); // Type is one byte.
432
433 // (E) Carry on. String handling is done.
434 __ bind(&check_code);
435 // edx: irregexp code
436 // Check that the irregexp code has been generated for the actual string
437 // encoding. If it has, the field contains a code object otherwise it contains
438 // a smi (code flushing support).
439 __ JumpIfSmi(edx, &runtime);
440
441 // eax: subject string
442 // ebx: previous index (smi)
443 // edx: code
444 // ecx: encoding of subject string (1 if one_byte, 0 if two_byte);
445 // All checks done. Now push arguments for native regexp code.
446 Counters* counters = isolate()->counters();
447 __ IncrementCounter(counters->regexp_entry_native(), 1);
448
449 // Isolates: note we add an additional parameter here (isolate pointer). 289 // Isolates: note we add an additional parameter here (isolate pointer).
450 static const int kRegExpExecuteArguments = 9; 290 static const int kRegExpExecuteArguments = 9;
451 __ EnterApiExitFrame(kRegExpExecuteArguments); 291 __ EnterApiExitFrame(kRegExpExecuteArguments);
452 292
453 // Argument 9: Pass current isolate address. 293 // Argument 9: Pass current isolate address.
454 __ mov(Operand(esp, 8 * kPointerSize), 294 __ mov(Operand(esp, 8 * kPointerSize),
455 Immediate(ExternalReference::isolate_address(isolate()))); 295 Immediate(ExternalReference::isolate_address(isolate())));
456 296
457 // Argument 8: Indicate that this is a direct call from JavaScript. 297 // Argument 8: Indicate that this is a direct call from JavaScript.
458 __ mov(Operand(esp, 7 * kPointerSize), Immediate(1)); 298 __ mov(Operand(esp, 7 * kPointerSize), Immediate(1));
459 299
460 // Argument 7: Start (high end) of backtracking stack memory area. 300 // Argument 7: Start (high end) of backtracking stack memory area.
301 ExternalReference address_of_regexp_stack_memory_address =
302 ExternalReference::address_of_regexp_stack_memory_address(isolate());
303 ExternalReference address_of_regexp_stack_memory_size =
304 ExternalReference::address_of_regexp_stack_memory_size(isolate());
461 __ mov(esi, Operand::StaticVariable(address_of_regexp_stack_memory_address)); 305 __ mov(esi, Operand::StaticVariable(address_of_regexp_stack_memory_address));
462 __ add(esi, Operand::StaticVariable(address_of_regexp_stack_memory_size)); 306 __ add(esi, Operand::StaticVariable(address_of_regexp_stack_memory_size));
463 __ mov(Operand(esp, 6 * kPointerSize), esi); 307 __ mov(Operand(esp, 6 * kPointerSize), esi);
464 308
465 // Argument 6: Set the number of capture registers to zero to force global 309 // Argument 6: Set the number of capture registers to zero to force global
466 // regexps to behave as non-global. This does not affect non-global regexps. 310 // regexps to behave as non-global. This does not affect non-global regexps.
467 __ mov(Operand(esp, 5 * kPointerSize), Immediate(0)); 311 __ mov(Operand(esp, 5 * kPointerSize), Immediate(0));
468 312
469 // Argument 5: static offsets vector buffer. 313 // Argument 5: static offsets vector buffer.
470 __ mov(Operand(esp, 4 * kPointerSize), 314 __ mov(Operand(esp, 4 * kPointerSize),
471 Immediate(ExternalReference::address_of_static_offsets_vector( 315 Immediate(ExternalReference::address_of_static_offsets_vector(
472 isolate()))); 316 isolate())));
473 317
318 // Argument 4: End of string data
319 // Argument 3: Start of string data
320 __ mov(Operand(esp, 3 * kPointerSize),
321 RegExpExecDescriptor::StringEndRegister());
322 __ mov(Operand(esp, 2 * kPointerSize),
323 RegExpExecDescriptor::StringStartRegister());
324
474 // Argument 2: Previous index. 325 // Argument 2: Previous index.
475 __ SmiUntag(ebx); 326 __ mov(Operand(esp, 1 * kPointerSize),
476 __ mov(Operand(esp, 1 * kPointerSize), ebx); 327 RegExpExecDescriptor::LastIndexRegister());
477 328
478 // Argument 1: Original subject string. 329 // Argument 1: Original subject string.
479 // The original subject is in the previous stack frame. Therefore we have to 330 __ mov(Operand(esp, 0 * kPointerSize),
480 // use ebp, which points exactly to one pointer size below the previous esp. 331 RegExpExecDescriptor::StringRegister());
481 // (Because creating a new stack frame pushes the previous ebp onto the stack
482 // and thereby moves up esp by one kPointerSize.)
483 __ mov(esi, Operand(ebp, kSubjectOffset + kPointerSize));
484 __ mov(Operand(esp, 0 * kPointerSize), esi);
485
486 // esi: original subject string
487 // eax: underlying subject string
488 // ebx: previous index
489 // ecx: encoding of subject string (1 if one_byte 0 if two_byte);
490 // edx: code
491 // Argument 4: End of string data
492 // Argument 3: Start of string data
493 // Prepare start and end index of the input.
494 // Load the length from the original sliced string if that is the case.
495 __ mov(esi, FieldOperand(esi, String::kLengthOffset));
496 __ add(esi, edi); // Calculate input end wrt offset.
497 __ SmiUntag(edi);
498 __ add(ebx, edi); // Calculate input start wrt offset.
499
500 // ebx: start index of the input string
501 // esi: end index of the input string
502 Label setup_two_byte, setup_rest;
503 __ test(ecx, ecx);
504 __ j(zero, &setup_two_byte, Label::kNear);
505 __ SmiUntag(esi);
506 __ lea(ecx, FieldOperand(eax, esi, times_1, SeqOneByteString::kHeaderSize));
507 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4.
508 __ lea(ecx, FieldOperand(eax, ebx, times_1, SeqOneByteString::kHeaderSize));
509 __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3.
510 __ jmp(&setup_rest, Label::kNear);
511
512 __ bind(&setup_two_byte);
513 STATIC_ASSERT(kSmiTag == 0);
514 STATIC_ASSERT(kSmiTagSize == 1); // esi is smi (powered by 2).
515 __ lea(ecx, FieldOperand(eax, esi, times_1, SeqTwoByteString::kHeaderSize));
516 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4.
517 __ lea(ecx, FieldOperand(eax, ebx, times_2, SeqTwoByteString::kHeaderSize));
518 __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3.
519
520 __ bind(&setup_rest);
521 332
522 // Locate the code entry and call it. 333 // Locate the code entry and call it.
523 __ add(edx, Immediate(Code::kHeaderSize - kHeapObjectTag)); 334 __ add(RegExpExecDescriptor::CodeRegister(),
524 __ call(edx); 335 Immediate(Code::kHeaderSize - kHeapObjectTag));
336 __ call(RegExpExecDescriptor::CodeRegister());
525 337
526 // Drop arguments and come back to JS mode. 338 // Drop arguments and come back to JS mode.
527 __ LeaveApiExitFrame(true); 339 __ LeaveApiExitFrame(true);
528 340
529 // Check the result. 341 // TODO(jgruber): Don't tag return value once this is supported by stubs.
530 Label success; 342 __ SmiTag(eax);
531 __ cmp(eax, 1); 343 __ ret(0 * kPointerSize);
532 // We expect exactly one result since we force the called regexp to behave
533 // as non-global.
534 __ j(equal, &success);
535 Label failure;
536 __ cmp(eax, NativeRegExpMacroAssembler::FAILURE);
537 __ j(equal, &failure);
538 __ cmp(eax, NativeRegExpMacroAssembler::EXCEPTION);
539 // If not exception it can only be retry. Handle that in the runtime system.
540 __ j(not_equal, &runtime);
541 // Result must now be exception. If there is no pending exception already a
542 // stack overflow (on the backtrack stack) was detected in RegExp code but
543 // haven't created the exception yet. Handle that in the runtime system.
544 // TODO(592): Rerunning the RegExp to get the stack overflow exception.
545 ExternalReference pending_exception(Isolate::kPendingExceptionAddress,
546 isolate());
547 __ mov(edx, Immediate(isolate()->factory()->the_hole_value()));
548 __ mov(eax, Operand::StaticVariable(pending_exception));
549 __ cmp(edx, eax);
550 __ j(equal, &runtime);
551
552 // For exception, throw the exception again.
553 __ TailCallRuntime(Runtime::kRegExpExecReThrow);
554
555 __ bind(&failure);
556 // For failure to match, return null.
557 __ mov(eax, factory->null_value());
558 __ ret(4 * kPointerSize);
559
560 // Load RegExp data.
561 __ bind(&success);
562 __ mov(eax, Operand(esp, kJSRegExpOffset));
563 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset));
564 __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset));
565 // Calculate number of capture registers (number_of_captures + 1) * 2.
566 STATIC_ASSERT(kSmiTag == 0);
567 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
568 __ add(edx, Immediate(2)); // edx was a smi.
569
570 // edx: Number of capture registers
571 // Check that the last match info is a FixedArray.
572 __ mov(ebx, Operand(esp, kLastMatchInfoOffset));
573 __ JumpIfSmi(ebx, &runtime);
574 // Check that the object has fast elements.
575 __ mov(eax, FieldOperand(ebx, HeapObject::kMapOffset));
576 __ cmp(eax, factory->fixed_array_map());
577 __ j(not_equal, &runtime);
578 // Check that the last match info has space for the capture registers and the
579 // additional information.
580 __ mov(eax, FieldOperand(ebx, FixedArray::kLengthOffset));
581 __ SmiUntag(eax);
582 __ sub(eax, Immediate(RegExpMatchInfo::kLastMatchOverhead));
583 __ cmp(edx, eax);
584 __ j(greater, &runtime);
585
586 // ebx: last_match_info backing store (FixedArray)
587 // edx: number of capture registers
588 // Store the capture count.
589 __ SmiTag(edx); // Number of capture registers to smi.
590 __ mov(FieldOperand(ebx, RegExpMatchInfo::kNumberOfCapturesOffset), edx);
591 __ SmiUntag(edx); // Number of capture registers back from smi.
592 // Store last subject and last input.
593 __ mov(eax, Operand(esp, kSubjectOffset));
594 __ mov(ecx, eax);
595 __ mov(FieldOperand(ebx, RegExpMatchInfo::kLastSubjectOffset), eax);
596 __ RecordWriteField(ebx, RegExpMatchInfo::kLastSubjectOffset, eax, edi,
597 kDontSaveFPRegs);
598 __ mov(eax, ecx);
599 __ mov(FieldOperand(ebx, RegExpMatchInfo::kLastInputOffset), eax);
600 __ RecordWriteField(ebx, RegExpMatchInfo::kLastInputOffset, eax, edi,
601 kDontSaveFPRegs);
602
603 // Get the static offsets vector filled by the native regexp code.
604 ExternalReference address_of_static_offsets_vector =
605 ExternalReference::address_of_static_offsets_vector(isolate());
606 __ mov(ecx, Immediate(address_of_static_offsets_vector));
607
608 // ebx: last_match_info backing store (FixedArray)
609 // ecx: offsets vector
610 // edx: number of capture registers
611 Label next_capture, done;
612 // Capture register counter starts from number of capture registers and
613 // counts down until wrapping after zero.
614 __ bind(&next_capture);
615 __ sub(edx, Immediate(1));
616 __ j(negative, &done, Label::kNear);
617 // Read the value from the static offsets vector buffer.
618 __ mov(edi, Operand(ecx, edx, times_int_size, 0));
619 __ SmiTag(edi);
620 // Store the smi value in the last match info.
621 __ mov(FieldOperand(ebx, edx, times_pointer_size,
622 RegExpMatchInfo::kFirstCaptureOffset),
623 edi);
624 __ jmp(&next_capture);
625 __ bind(&done);
626
627 // Return last match info.
628 __ mov(eax, ebx);
629 __ ret(4 * kPointerSize);
630
631 // Do the runtime call to execute the regexp.
632 __ bind(&runtime);
633 __ TailCallRuntime(Runtime::kRegExpExec);
634
635 // Deferred code for string handling.
636 // (6) Long external string? If not, go to (10).
637 __ bind(&not_seq_nor_cons);
638 // Compare flags are still set from (3).
639 __ j(greater, &not_long_external, Label::kNear); // Go to (10).
640
641 // (7) External string. Short external strings have been ruled out.
642 __ bind(&external_string);
643 // Reload instance type.
644 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
645 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
646 if (FLAG_debug_code) {
647 // Assert that we do not have a cons or slice (indirect strings) here.
648 // Sequential strings have already been ruled out.
649 __ test_b(ebx, Immediate(kIsIndirectStringMask));
650 __ Assert(zero, kExternalStringExpectedButNotFound);
651 }
652 __ mov(eax, FieldOperand(eax, ExternalString::kResourceDataOffset));
653 // Move the pointer so that offset-wise, it looks like a sequential string.
654 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
655 __ sub(eax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
656 STATIC_ASSERT(kTwoByteStringTag == 0);
657 // (8) Is the external string one byte? If yes, go to (5).
658 __ test_b(ebx, Immediate(kStringEncodingMask));
659 __ j(not_zero, &seq_one_byte_string); // Go to (5).
660
661 // eax: sequential subject string (or look-alike, external string)
662 // edx: original subject string
663 // ecx: RegExp data (FixedArray)
664 // (9) Two byte sequential. Load regexp code for two byte. Go to (E).
665 __ bind(&seq_two_byte_string);
666 // Load previous index and check range before edx is overwritten. We have
667 // to use edx instead of eax here because it might have been only made to
668 // look like a sequential string when it actually is an external string.
669 __ mov(ebx, Operand(esp, kPreviousIndexOffset));
670 __ JumpIfNotSmi(ebx, &runtime);
671 __ cmp(ebx, FieldOperand(edx, String::kLengthOffset));
672 __ j(above_equal, &runtime);
673 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataUC16CodeOffset));
674 __ Move(ecx, Immediate(0)); // Type is two byte.
675 __ jmp(&check_code); // Go to (E).
676
677 // (10) Not a string or a short external string? If yes, bail out to runtime.
678 __ bind(&not_long_external);
679 // Catch non-string subject or short external string.
680 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0);
681 __ test(ebx, Immediate(kIsNotStringMask | kShortExternalStringTag));
682 __ j(not_zero, &runtime);
683
684 // (11) Sliced or thin string. Replace subject with parent. Go to (1).
685 Label thin_string;
686 __ cmp(ebx, Immediate(kThinStringTag));
687 __ j(equal, &thin_string, Label::kNear);
688 // Load offset into edi and replace subject string with parent.
689 __ mov(edi, FieldOperand(eax, SlicedString::kOffsetOffset));
690 __ mov(eax, FieldOperand(eax, SlicedString::kParentOffset));
691 __ jmp(&check_underlying); // Go to (1).
692
693 __ bind(&thin_string);
694 __ mov(eax, FieldOperand(eax, ThinString::kActualOffset));
695 __ jmp(&check_underlying); // Go to (1).
696 #endif // V8_INTERPRETED_REGEXP 344 #endif // V8_INTERPRETED_REGEXP
697 } 345 }
698 346
699 347
700 static int NegativeComparisonResult(Condition cc) { 348 static int NegativeComparisonResult(Condition cc) {
701 DCHECK(cc != equal); 349 DCHECK(cc != equal);
702 DCHECK((cc == less) || (cc == less_equal) 350 DCHECK((cc == less) || (cc == less_equal)
703 || (cc == greater) || (cc == greater_equal)); 351 || (cc == greater) || (cc == greater_equal));
704 return (cc == greater || cc == greater_equal) ? LESS : GREATER; 352 return (cc == greater || cc == greater_equal) ? LESS : GREATER;
705 } 353 }
(...skipping 3190 matching lines...) Expand 10 before | Expand all | Expand 10 after
3896 kStackUnwindSpace, nullptr, return_value_operand, 3544 kStackUnwindSpace, nullptr, return_value_operand,
3897 NULL); 3545 NULL);
3898 } 3546 }
3899 3547
3900 #undef __ 3548 #undef __
3901 3549
3902 } // namespace internal 3550 } // namespace internal
3903 } // namespace v8 3551 } // namespace v8
3904 3552
3905 #endif // V8_TARGET_ARCH_X87 3553 #endif // V8_TARGET_ARCH_X87
OLDNEW
« no previous file with comments | « src/x64/interface-descriptors-x64.cc ('k') | src/x87/interface-descriptors-x87.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698