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

Side by Side Diff: src/x64/code-stubs-x64.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/s390/interface-descriptors-s390.cc ('k') | src/x64/interface-descriptors-x64.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 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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_X64 5 #if V8_TARGET_ARCH_X64
6 6
7 #include "src/api-arguments.h" 7 #include "src/api-arguments.h"
8 #include "src/bootstrapper.h" 8 #include "src/bootstrapper.h"
9 #include "src/code-stubs.h" 9 #include "src/code-stubs.h"
10 #include "src/codegen.h" 10 #include "src/codegen.h"
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 2); 344 2);
345 } 345 }
346 // Return value is in xmm0. 346 // Return value is in xmm0.
347 __ Movsd(double_result, xmm0); 347 __ Movsd(double_result, xmm0);
348 348
349 __ bind(&done); 349 __ bind(&done);
350 __ ret(0); 350 __ ret(0);
351 } 351 }
352 352
353 void RegExpExecStub::Generate(MacroAssembler* masm) { 353 void RegExpExecStub::Generate(MacroAssembler* masm) {
354 // Just jump directly to runtime if native RegExp is not selected at compile
355 // time or if regexp entry in generated code is turned off runtime switch or
356 // at compilation.
357 #ifdef V8_INTERPRETED_REGEXP 354 #ifdef V8_INTERPRETED_REGEXP
358 __ TailCallRuntime(Runtime::kRegExpExec); 355 // This case is handled prior to the RegExpExecStub call.
356 __ Abort(kUnexpectedRegExpExecCall);
359 #else // V8_INTERPRETED_REGEXP 357 #else // V8_INTERPRETED_REGEXP
360
361 // Stack frame on entry.
362 // rsp[0] : return address
363 // rsp[8] : last_match_info (expected JSArray)
364 // rsp[16] : previous index
365 // rsp[24] : subject string
366 // rsp[32] : JSRegExp object
367
368 enum RegExpExecStubArgumentIndices {
369 JS_REG_EXP_OBJECT_ARGUMENT_INDEX,
370 SUBJECT_STRING_ARGUMENT_INDEX,
371 PREVIOUS_INDEX_ARGUMENT_INDEX,
372 LAST_MATCH_INFO_ARGUMENT_INDEX,
373 REG_EXP_EXEC_ARGUMENT_COUNT
374 };
375
376 StackArgumentsAccessor args(rsp, REG_EXP_EXEC_ARGUMENT_COUNT,
377 ARGUMENTS_DONT_CONTAIN_RECEIVER);
378 Label runtime;
379 // Ensure that a RegExp stack is allocated.
380 ExternalReference address_of_regexp_stack_memory_address =
381 ExternalReference::address_of_regexp_stack_memory_address(isolate());
382 ExternalReference address_of_regexp_stack_memory_size =
383 ExternalReference::address_of_regexp_stack_memory_size(isolate());
384 __ Load(kScratchRegister, address_of_regexp_stack_memory_size);
385 __ testp(kScratchRegister, kScratchRegister);
386 __ j(zero, &runtime);
387
388 // Check that the first argument is a JSRegExp object.
389 __ movp(rax, args.GetArgumentOperand(JS_REG_EXP_OBJECT_ARGUMENT_INDEX));
390 __ JumpIfSmi(rax, &runtime);
391 __ CmpObjectType(rax, JS_REGEXP_TYPE, kScratchRegister);
392 __ j(not_equal, &runtime);
393
394 // Check that the RegExp has been compiled (data contains a fixed array).
395 __ movp(rax, FieldOperand(rax, JSRegExp::kDataOffset));
396 if (FLAG_debug_code) {
397 Condition is_smi = masm->CheckSmi(rax);
398 __ Check(NegateCondition(is_smi),
399 kUnexpectedTypeForRegExpDataFixedArrayExpected);
400 __ CmpObjectType(rax, FIXED_ARRAY_TYPE, kScratchRegister);
401 __ Check(equal, kUnexpectedTypeForRegExpDataFixedArrayExpected);
402 }
403
404 // rax: RegExp data (FixedArray)
405 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP.
406 __ SmiToInteger32(rbx, FieldOperand(rax, JSRegExp::kDataTagOffset));
407 __ cmpl(rbx, Immediate(JSRegExp::IRREGEXP));
408 __ j(not_equal, &runtime);
409
410 // rax: RegExp data (FixedArray)
411 // Check that the number of captures fit in the static offsets vector buffer.
412 __ SmiToInteger32(rdx,
413 FieldOperand(rax, JSRegExp::kIrregexpCaptureCountOffset));
414 // Check (number_of_captures + 1) * 2 <= offsets vector size
415 // Or number_of_captures <= offsets vector size / 2 - 1
416 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2);
417 __ cmpl(rdx, Immediate(Isolate::kJSRegexpStaticOffsetsVectorSize / 2 - 1));
418 __ j(above, &runtime);
419
420 // Reset offset for possibly sliced string.
421 __ Set(r14, 0);
422 __ movp(rdi, args.GetArgumentOperand(SUBJECT_STRING_ARGUMENT_INDEX));
423 __ JumpIfSmi(rdi, &runtime);
424 __ movp(r15, rdi); // Make a copy of the original subject string.
425 // rax: RegExp data (FixedArray)
426 // rdi: subject string
427 // r15: subject string
428 // Handle subject string according to its encoding and representation:
429 // (1) Sequential two byte? If yes, go to (9).
430 // (2) Sequential one byte? If yes, go to (5).
431 // (3) Sequential or cons? If not, go to (6).
432 // (4) Cons string. If the string is flat, replace subject with first string
433 // and go to (1). Otherwise bail out to runtime.
434 // (5) One byte sequential. Load regexp code for one byte.
435 // (E) Carry on.
436 /// [...]
437
438 // Deferred code at the end of the stub:
439 // (6) Long external string? If not, go to (10).
440 // (7) External string. Make it, offset-wise, look like a sequential string.
441 // (8) Is the external string one byte? If yes, go to (5).
442 // (9) Two byte sequential. Load regexp code for two byte. Go to (E).
443 // (10) Short external string or not a string? If yes, bail out to runtime.
444 // (11) Sliced or thin string. Replace subject with parent. Go to (1).
445
446 Label seq_one_byte_string /* 5 */, seq_two_byte_string /* 9 */,
447 external_string /* 7 */, check_underlying /* 1 */,
448 not_seq_nor_cons /* 6 */, check_code /* E */, not_long_external /* 10 */;
449
450 __ bind(&check_underlying);
451 __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
452 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
453
454 // (1) Sequential two byte? If yes, go to (9).
455 __ andb(rbx, Immediate(kIsNotStringMask |
456 kStringRepresentationMask |
457 kStringEncodingMask |
458 kShortExternalStringMask));
459 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0);
460 __ j(zero, &seq_two_byte_string); // Go to (9).
461
462 // (2) Sequential one byte? If yes, go to (5).
463 // Any other sequential string must be one byte.
464 __ andb(rbx, Immediate(kIsNotStringMask |
465 kStringRepresentationMask |
466 kShortExternalStringMask));
467 __ j(zero, &seq_one_byte_string, Label::kNear); // Go to (5).
468
469 // (3) Sequential or cons? If not, go to (6).
470 // We check whether the subject string is a cons, since sequential strings
471 // have already been covered.
472 STATIC_ASSERT(kConsStringTag < kExternalStringTag);
473 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
474 STATIC_ASSERT(kThinStringTag > kExternalStringTag);
475 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
476 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
477 __ cmpp(rbx, Immediate(kExternalStringTag));
478 __ j(greater_equal, &not_seq_nor_cons); // Go to (6).
479
480 // (4) Cons string. Check that it's flat.
481 // Replace subject with first string and reload instance type.
482 __ CompareRoot(FieldOperand(rdi, ConsString::kSecondOffset),
483 Heap::kempty_stringRootIndex);
484 __ j(not_equal, &runtime);
485 __ movp(rdi, FieldOperand(rdi, ConsString::kFirstOffset));
486 __ jmp(&check_underlying);
487
488 // (5) One byte sequential. Load regexp code for one byte.
489 __ bind(&seq_one_byte_string);
490 // rax: RegExp data (FixedArray)
491 __ movp(r11, FieldOperand(rax, JSRegExp::kDataOneByteCodeOffset));
492 __ Set(rcx, 1); // Type is one byte.
493
494 // (E) Carry on. String handling is done.
495 __ bind(&check_code);
496 // r11: irregexp code
497 // Check that the irregexp code has been generated for the actual string
498 // encoding. If it has, the field contains a code object otherwise it contains
499 // smi (code flushing support)
500 __ JumpIfSmi(r11, &runtime);
501
502 // rdi: sequential subject string (or look-alike, external string)
503 // r15: original subject string
504 // rcx: encoding of subject string (1 if one_byte, 0 if two_byte);
505 // r11: code
506 // Load used arguments before starting to push arguments for call to native
507 // RegExp code to avoid handling changing stack height.
508 // We have to use r15 instead of rdi to load the length because rdi might
509 // have been only made to look like a sequential string when it actually
510 // is an external string.
511 __ movp(rbx, args.GetArgumentOperand(PREVIOUS_INDEX_ARGUMENT_INDEX));
512 __ JumpIfNotSmi(rbx, &runtime);
513 __ SmiCompare(rbx, FieldOperand(r15, String::kLengthOffset));
514 __ j(above_equal, &runtime);
515 __ SmiToInteger64(rbx, rbx);
516
517 // rdi: subject string
518 // rbx: previous index
519 // rcx: encoding of subject string (1 if one_byte 0 if two_byte);
520 // r11: code
521 // All checks done. Now push arguments for native regexp code.
522 Counters* counters = isolate()->counters();
523 __ IncrementCounter(counters->regexp_entry_native(), 1);
524
525 // Isolates: note we add an additional parameter here (isolate pointer). 358 // Isolates: note we add an additional parameter here (isolate pointer).
526 static const int kRegExpExecuteArguments = 9; 359 static const int kRegExpExecuteArguments = 9;
527 int argument_slots_on_stack = 360 int argument_slots_on_stack =
528 masm->ArgumentStackSlotsForCFunctionCall(kRegExpExecuteArguments); 361 masm->ArgumentStackSlotsForCFunctionCall(kRegExpExecuteArguments);
529 __ EnterApiExitFrame(argument_slots_on_stack); 362 __ EnterApiExitFrame(argument_slots_on_stack);
530 363
531 // Argument 9: Pass current isolate address. 364 // Argument 9: Pass current isolate address.
532 __ LoadAddress(kScratchRegister, 365 __ LoadAddress(kScratchRegister,
533 ExternalReference::isolate_address(isolate())); 366 ExternalReference::isolate_address(isolate()));
534 __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kRegisterSize), 367 __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kRegisterSize),
535 kScratchRegister); 368 kScratchRegister);
536 369
537 // Argument 8: Indicate that this is a direct call from JavaScript. 370 // Argument 8: Indicate that this is a direct call from JavaScript.
538 __ movq(Operand(rsp, (argument_slots_on_stack - 2) * kRegisterSize), 371 __ movq(Operand(rsp, (argument_slots_on_stack - 2) * kRegisterSize),
539 Immediate(1)); 372 Immediate(1));
540 373
541 // Argument 7: Start (high end) of backtracking stack memory area. 374 // Argument 7: Start (high end) of backtracking stack memory area.
375 ExternalReference address_of_regexp_stack_memory_address =
376 ExternalReference::address_of_regexp_stack_memory_address(isolate());
377 ExternalReference address_of_regexp_stack_memory_size =
378 ExternalReference::address_of_regexp_stack_memory_size(isolate());
542 __ Move(kScratchRegister, address_of_regexp_stack_memory_address); 379 __ Move(kScratchRegister, address_of_regexp_stack_memory_address);
543 __ movp(r9, Operand(kScratchRegister, 0)); 380 __ movp(r12, Operand(kScratchRegister, 0));
544 __ Move(kScratchRegister, address_of_regexp_stack_memory_size); 381 __ Move(kScratchRegister, address_of_regexp_stack_memory_size);
545 __ addp(r9, Operand(kScratchRegister, 0)); 382 __ addp(r12, Operand(kScratchRegister, 0));
546 __ movq(Operand(rsp, (argument_slots_on_stack - 3) * kRegisterSize), r9); 383 __ movq(Operand(rsp, (argument_slots_on_stack - 3) * kRegisterSize), r12);
547 384
548 // Argument 6: Set the number of capture registers to zero to force global 385 // Argument 6: Set the number of capture registers to zero to force global
549 // regexps to behave as non-global. This does not affect non-global regexps. 386 // regexps to behave as non-global. This does not affect non-global regexps.
550 // Argument 6 is passed in r9 on Linux and on the stack on Windows. 387 // Argument 6 is passed in r9 on Linux and on the stack on Windows.
551 #ifdef _WIN64 388 #ifdef _WIN64
552 __ movq(Operand(rsp, (argument_slots_on_stack - 4) * kRegisterSize), 389 __ movq(Operand(rsp, (argument_slots_on_stack - 4) * kRegisterSize),
553 Immediate(0)); 390 Immediate(0));
554 #else 391 #else
555 __ Set(r9, 0); 392 __ Set(r9, 0);
556 #endif 393 #endif
557 394
558 // Argument 5: static offsets vector buffer. 395 // Argument 5: static offsets vector buffer.
396 // Argument 5 passed in r8 on Linux and on the stack on Windows.
397 #ifdef _WIN64
398 __ LoadAddress(
399 r12, ExternalReference::address_of_static_offsets_vector(isolate()));
400 __ movq(Operand(rsp, (argument_slots_on_stack - 5) * kRegisterSize), r12);
401 #else // _WIN64
559 __ LoadAddress( 402 __ LoadAddress(
560 r8, ExternalReference::address_of_static_offsets_vector(isolate())); 403 r8, ExternalReference::address_of_static_offsets_vector(isolate()));
561 // Argument 5 passed in r8 on Linux and on the stack on Windows.
562 #ifdef _WIN64
563 __ movq(Operand(rsp, (argument_slots_on_stack - 5) * kRegisterSize), r8);
564 #endif 404 #endif
565 405
566 // rdi: subject string
567 // rbx: previous index
568 // rcx: encoding of subject string (1 if one_byte 0 if two_byte);
569 // r11: code
570 // r14: slice offset
571 // r15: original subject string
572
573 // Argument 2: Previous index. 406 // Argument 2: Previous index.
574 __ movp(arg_reg_2, rbx); 407 // TODO(jgruber): Ideally, LastIndexRegister would already equal arg_reg_2,
408 // but that makes register allocation fail.
409 __ movp(arg_reg_2, RegExpExecDescriptor::LastIndexRegister());
575 410
576 // Argument 4: End of string data 411 // Argument 4: End of string data
577 // Argument 3: Start of string data 412 // Argument 3: Start of string data
578 Label setup_two_byte, setup_rest, got_length, length_not_from_slice; 413 CHECK(arg_reg_4.is(RegExpExecDescriptor::StringEndRegister()));
579 // Prepare start and end index of the input. 414 CHECK(arg_reg_3.is(RegExpExecDescriptor::StringStartRegister()));
580 // Load the length from the original sliced string if that is the case.
581 __ addp(rbx, r14);
582 __ SmiToInteger32(arg_reg_3, FieldOperand(r15, String::kLengthOffset));
583 __ addp(r14, arg_reg_3); // Using arg3 as scratch.
584
585 // rbx: start index of the input
586 // r14: end index of the input
587 // r15: original subject string
588 __ testb(rcx, rcx); // Last use of rcx as encoding of subject string.
589 __ j(zero, &setup_two_byte, Label::kNear);
590 __ leap(arg_reg_4,
591 FieldOperand(rdi, r14, times_1, SeqOneByteString::kHeaderSize));
592 __ leap(arg_reg_3,
593 FieldOperand(rdi, rbx, times_1, SeqOneByteString::kHeaderSize));
594 __ jmp(&setup_rest, Label::kNear);
595 __ bind(&setup_two_byte);
596 __ leap(arg_reg_4,
597 FieldOperand(rdi, r14, times_2, SeqTwoByteString::kHeaderSize));
598 __ leap(arg_reg_3,
599 FieldOperand(rdi, rbx, times_2, SeqTwoByteString::kHeaderSize));
600 __ bind(&setup_rest);
601 415
602 // Argument 1: Original subject string. 416 // Argument 1: Original subject string.
603 // The original subject is in the previous stack frame. Therefore we have to 417 CHECK(arg_reg_1.is(RegExpExecDescriptor::StringRegister()));
604 // use rbp, which points exactly to one pointer size below the previous rsp.
605 // (Because creating a new stack frame pushes the previous rbp onto the stack
606 // and thereby moves up rsp by one kPointerSize.)
607 __ movp(arg_reg_1, r15);
608 418
609 // Locate the code entry and call it. 419 __ addp(RegExpExecDescriptor::CodeRegister(),
610 __ addp(r11, Immediate(Code::kHeaderSize - kHeapObjectTag)); 420 Immediate(Code::kHeaderSize - kHeapObjectTag));
611 __ call(r11); 421 __ call(RegExpExecDescriptor::CodeRegister());
612 422
613 __ LeaveApiExitFrame(true); 423 __ LeaveApiExitFrame(true);
614 424
615 // Check the result. 425 // TODO(jgruber): Don't tag return value once this is supported by stubs.
616 Label success; 426 __ Integer32ToSmi(rax, rax);
617 Label exception; 427 __ ret(0 * kPointerSize);
618 __ cmpl(rax, Immediate(1));
619 // We expect exactly one result since we force the called regexp to behave
620 // as non-global.
621 __ j(equal, &success, Label::kNear);
622 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::EXCEPTION));
623 __ j(equal, &exception);
624 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::FAILURE));
625 // If none of the above, it can only be retry.
626 // Handle that in the runtime system.
627 __ j(not_equal, &runtime);
628
629 // For failure return null.
630 __ LoadRoot(rax, Heap::kNullValueRootIndex);
631 __ ret(REG_EXP_EXEC_ARGUMENT_COUNT * kPointerSize);
632
633 // Load RegExp data.
634 __ bind(&success);
635 __ movp(rax, args.GetArgumentOperand(JS_REG_EXP_OBJECT_ARGUMENT_INDEX));
636 __ movp(rcx, FieldOperand(rax, JSRegExp::kDataOffset));
637 __ SmiToInteger32(rax,
638 FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset));
639 // Calculate number of capture registers (number_of_captures + 1) * 2.
640 __ leal(rdx, Operand(rax, rax, times_1, 2));
641
642 // rdx: Number of capture registers
643 // Check that the last match info is a FixedArray.
644 __ movp(rbx, args.GetArgumentOperand(LAST_MATCH_INFO_ARGUMENT_INDEX));
645 __ JumpIfSmi(rbx, &runtime);
646 // Check that the object has fast elements.
647 __ movp(rax, FieldOperand(rbx, HeapObject::kMapOffset));
648 __ CompareRoot(rax, Heap::kFixedArrayMapRootIndex);
649 __ j(not_equal, &runtime);
650 // Check that the last match info has space for the capture registers and the
651 // additional information. Ensure no overflow in add.
652 STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset);
653 __ SmiToInteger32(rax, FieldOperand(rbx, FixedArray::kLengthOffset));
654 __ subl(rax, Immediate(RegExpMatchInfo::kLastMatchOverhead));
655 __ cmpl(rdx, rax);
656 __ j(greater, &runtime);
657
658 // rbx: last_match_info (FixedArray)
659 // rdx: number of capture registers
660 // Store the capture count.
661 __ Integer32ToSmi(kScratchRegister, rdx);
662 __ movp(FieldOperand(rbx, RegExpMatchInfo::kNumberOfCapturesOffset),
663 kScratchRegister);
664 // Store last subject and last input.
665 __ movp(rax, args.GetArgumentOperand(SUBJECT_STRING_ARGUMENT_INDEX));
666 __ movp(FieldOperand(rbx, RegExpMatchInfo::kLastSubjectOffset), rax);
667 __ movp(rcx, rax);
668 __ RecordWriteField(rbx, RegExpMatchInfo::kLastSubjectOffset, rax, rdi,
669 kDontSaveFPRegs);
670 __ movp(rax, rcx);
671 __ movp(FieldOperand(rbx, RegExpMatchInfo::kLastInputOffset), rax);
672 __ RecordWriteField(rbx, RegExpMatchInfo::kLastInputOffset, rax, rdi,
673 kDontSaveFPRegs);
674
675 // Get the static offsets vector filled by the native regexp code.
676 __ LoadAddress(
677 rcx, ExternalReference::address_of_static_offsets_vector(isolate()));
678
679 // rbx: last_match_info (FixedArray)
680 // rcx: offsets vector
681 // rdx: number of capture registers
682 Label next_capture, done;
683 // Capture register counter starts from number of capture registers and
684 // counts down until wrapping after zero.
685 __ bind(&next_capture);
686 __ subp(rdx, Immediate(1));
687 __ j(negative, &done, Label::kNear);
688 // Read the value from the static offsets vector buffer and make it a smi.
689 __ movl(rdi, Operand(rcx, rdx, times_int_size, 0));
690 __ Integer32ToSmi(rdi, rdi);
691 // Store the smi value in the last match info.
692 __ movp(FieldOperand(rbx, rdx, times_pointer_size,
693 RegExpMatchInfo::kFirstCaptureOffset),
694 rdi);
695 __ jmp(&next_capture);
696 __ bind(&done);
697
698 // Return last match info.
699 __ movp(rax, rbx);
700 __ ret(REG_EXP_EXEC_ARGUMENT_COUNT * kPointerSize);
701
702 __ bind(&exception);
703 // Result must now be exception. If there is no pending exception already a
704 // stack overflow (on the backtrack stack) was detected in RegExp code but
705 // haven't created the exception yet. Handle that in the runtime system.
706 // TODO(592): Rerunning the RegExp to get the stack overflow exception.
707 ExternalReference pending_exception_address(
708 Isolate::kPendingExceptionAddress, isolate());
709 Operand pending_exception_operand =
710 masm->ExternalOperand(pending_exception_address, rbx);
711 __ movp(rax, pending_exception_operand);
712 __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex);
713 __ cmpp(rax, rdx);
714 __ j(equal, &runtime);
715
716 // For exception, throw the exception again.
717 __ TailCallRuntime(Runtime::kRegExpExecReThrow);
718
719 // Do the runtime call to execute the regexp.
720 __ bind(&runtime);
721 __ TailCallRuntime(Runtime::kRegExpExec);
722
723 // Deferred code for string handling.
724 // (6) Long external string? If not, go to (10).
725 __ bind(&not_seq_nor_cons);
726 // Compare flags are still set from (3).
727 __ j(greater, &not_long_external, Label::kNear); // Go to (10).
728
729 // (7) External string. Short external strings have been ruled out.
730 __ bind(&external_string);
731 __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
732 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
733 if (FLAG_debug_code) {
734 // Assert that we do not have a cons or slice (indirect strings) here.
735 // Sequential strings have already been ruled out.
736 __ testb(rbx, Immediate(kIsIndirectStringMask));
737 __ Assert(zero, kExternalStringExpectedButNotFound);
738 }
739 __ movp(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset));
740 // Move the pointer so that offset-wise, it looks like a sequential string.
741 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
742 __ subp(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
743 STATIC_ASSERT(kTwoByteStringTag == 0);
744 // (8) Is the external string one byte? If yes, go to (5).
745 __ testb(rbx, Immediate(kStringEncodingMask));
746 __ j(not_zero, &seq_one_byte_string); // Go to (5).
747
748 // rdi: subject string (flat two-byte)
749 // rax: RegExp data (FixedArray)
750 // (9) Two byte sequential. Load regexp code for two byte. Go to (E).
751 __ bind(&seq_two_byte_string);
752 __ movp(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset));
753 __ Set(rcx, 0); // Type is two byte.
754 __ jmp(&check_code); // Go to (E).
755
756 // (10) Not a string or a short external string? If yes, bail out to runtime.
757 __ bind(&not_long_external);
758 // Catch non-string subject or short external string.
759 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0);
760 __ testb(rbx, Immediate(kIsNotStringMask | kShortExternalStringMask));
761 __ j(not_zero, &runtime);
762
763 // (11) Sliced or thin string. Replace subject with parent. Go to (1).
764 Label thin_string;
765 __ cmpl(rbx, Immediate(kThinStringTag));
766 __ j(equal, &thin_string, Label::kNear);
767 // Load offset into r14 and replace subject string with parent.
768 __ SmiToInteger32(r14, FieldOperand(rdi, SlicedString::kOffsetOffset));
769 __ movp(rdi, FieldOperand(rdi, SlicedString::kParentOffset));
770 __ jmp(&check_underlying);
771
772 __ bind(&thin_string);
773 __ movp(rdi, FieldOperand(rdi, ThinString::kActualOffset));
774 __ jmp(&check_underlying);
775 #endif // V8_INTERPRETED_REGEXP 428 #endif // V8_INTERPRETED_REGEXP
776 } 429 }
777 430
778 431
779 static int NegativeComparisonResult(Condition cc) { 432 static int NegativeComparisonResult(Condition cc) {
780 DCHECK(cc != equal); 433 DCHECK(cc != equal);
781 DCHECK((cc == less) || (cc == less_equal) 434 DCHECK((cc == less) || (cc == less_equal)
782 || (cc == greater) || (cc == greater_equal)); 435 || (cc == greater) || (cc == greater_equal));
783 return (cc == greater || cc == greater_equal) ? LESS : GREATER; 436 return (cc == greater || cc == greater_equal) ? LESS : GREATER;
784 } 437 }
(...skipping 2537 matching lines...) Expand 10 before | Expand all | Expand 10 after
3322 kStackUnwindSpace, nullptr, return_value_operand, 2975 kStackUnwindSpace, nullptr, return_value_operand,
3323 NULL); 2976 NULL);
3324 } 2977 }
3325 2978
3326 #undef __ 2979 #undef __
3327 2980
3328 } // namespace internal 2981 } // namespace internal
3329 } // namespace v8 2982 } // namespace v8
3330 2983
3331 #endif // V8_TARGET_ARCH_X64 2984 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/s390/interface-descriptors-s390.cc ('k') | src/x64/interface-descriptors-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698