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

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

Issue 7860035: Merge bleeding edge up to 9192 into the GC branch. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/gc
Patch Set: Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/builtins-x64.cc ('k') | src/x64/full-codegen-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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 2373 matching lines...) Expand 10 before | Expand all | Expand 10 after
2384 // Ensure that a RegExp stack is allocated. 2384 // Ensure that a RegExp stack is allocated.
2385 Isolate* isolate = masm->isolate(); 2385 Isolate* isolate = masm->isolate();
2386 ExternalReference address_of_regexp_stack_memory_address = 2386 ExternalReference address_of_regexp_stack_memory_address =
2387 ExternalReference::address_of_regexp_stack_memory_address(isolate); 2387 ExternalReference::address_of_regexp_stack_memory_address(isolate);
2388 ExternalReference address_of_regexp_stack_memory_size = 2388 ExternalReference address_of_regexp_stack_memory_size =
2389 ExternalReference::address_of_regexp_stack_memory_size(isolate); 2389 ExternalReference::address_of_regexp_stack_memory_size(isolate);
2390 __ Load(kScratchRegister, address_of_regexp_stack_memory_size); 2390 __ Load(kScratchRegister, address_of_regexp_stack_memory_size);
2391 __ testq(kScratchRegister, kScratchRegister); 2391 __ testq(kScratchRegister, kScratchRegister);
2392 __ j(zero, &runtime); 2392 __ j(zero, &runtime);
2393 2393
2394
2395 // Check that the first argument is a JSRegExp object. 2394 // Check that the first argument is a JSRegExp object.
2396 __ movq(rax, Operand(rsp, kJSRegExpOffset)); 2395 __ movq(rax, Operand(rsp, kJSRegExpOffset));
2397 __ JumpIfSmi(rax, &runtime); 2396 __ JumpIfSmi(rax, &runtime);
2398 __ CmpObjectType(rax, JS_REGEXP_TYPE, kScratchRegister); 2397 __ CmpObjectType(rax, JS_REGEXP_TYPE, kScratchRegister);
2399 __ j(not_equal, &runtime); 2398 __ j(not_equal, &runtime);
2400 // Check that the RegExp has been compiled (data contains a fixed array). 2399 // Check that the RegExp has been compiled (data contains a fixed array).
2401 __ movq(rax, FieldOperand(rax, JSRegExp::kDataOffset)); 2400 __ movq(rax, FieldOperand(rax, JSRegExp::kDataOffset));
2402 if (FLAG_debug_code) { 2401 if (FLAG_debug_code) {
2403 Condition is_smi = masm->CheckSmi(rax); 2402 Condition is_smi = masm->CheckSmi(rax);
2404 __ Check(NegateCondition(is_smi), 2403 __ Check(NegateCondition(is_smi),
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
2455 Heap::kFixedArrayMapRootIndex); 2454 Heap::kFixedArrayMapRootIndex);
2456 __ j(not_equal, &runtime); 2455 __ j(not_equal, &runtime);
2457 // Check that the last match info has space for the capture registers and the 2456 // Check that the last match info has space for the capture registers and the
2458 // additional information. Ensure no overflow in add. 2457 // additional information. Ensure no overflow in add.
2459 STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset); 2458 STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset);
2460 __ SmiToInteger32(rdi, FieldOperand(rbx, FixedArray::kLengthOffset)); 2459 __ SmiToInteger32(rdi, FieldOperand(rbx, FixedArray::kLengthOffset));
2461 __ addl(rdx, Immediate(RegExpImpl::kLastMatchOverhead)); 2460 __ addl(rdx, Immediate(RegExpImpl::kLastMatchOverhead));
2462 __ cmpl(rdx, rdi); 2461 __ cmpl(rdx, rdi);
2463 __ j(greater, &runtime); 2462 __ j(greater, &runtime);
2464 2463
2464 // Reset offset for possibly sliced string.
2465 __ Set(r14, 0);
2465 // rax: RegExp data (FixedArray) 2466 // rax: RegExp data (FixedArray)
2466 // Check the representation and encoding of the subject string. 2467 // Check the representation and encoding of the subject string.
2467 Label seq_ascii_string, seq_two_byte_string, check_code; 2468 Label seq_ascii_string, seq_two_byte_string, check_code;
2468 __ movq(rdi, Operand(rsp, kSubjectOffset)); 2469 __ movq(rdi, Operand(rsp, kSubjectOffset));
2470 // Make a copy of the original subject string.
2471 __ movq(r15, rdi);
2469 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); 2472 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
2470 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); 2473 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
2471 // First check for flat two byte string. 2474 // First check for flat two byte string.
2472 __ andb(rbx, Immediate( 2475 __ andb(rbx, Immediate(
2473 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask)); 2476 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask));
2474 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); 2477 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0);
2475 __ j(zero, &seq_two_byte_string, Label::kNear); 2478 __ j(zero, &seq_two_byte_string, Label::kNear);
2476 // Any other flat string must be a flat ascii string. 2479 // Any other flat string must be a flat ascii string.
2477 __ testb(rbx, Immediate(kIsNotStringMask | kStringRepresentationMask)); 2480 __ andb(rbx, Immediate(kIsNotStringMask | kStringRepresentationMask));
2478 __ j(zero, &seq_ascii_string, Label::kNear); 2481 __ j(zero, &seq_ascii_string, Label::kNear);
2479 2482
2480 // Check for flat cons string. 2483 // Check for flat cons string or sliced string.
2481 // A flat cons string is a cons string where the second part is the empty 2484 // A flat cons string is a cons string where the second part is the empty
2482 // string. In that case the subject string is just the first part of the cons 2485 // string. In that case the subject string is just the first part of the cons
2483 // string. Also in this case the first part of the cons string is known to be 2486 // string. Also in this case the first part of the cons string is known to be
2484 // a sequential string or an external string. 2487 // a sequential string or an external string.
2485 STATIC_ASSERT(kExternalStringTag !=0); 2488 // In the case of a sliced string its offset has to be taken into account.
2486 STATIC_ASSERT((kConsStringTag & kExternalStringTag) == 0); 2489 Label cons_string, check_encoding;
2487 __ testb(rbx, Immediate(kIsNotStringMask | kExternalStringTag)); 2490 STATIC_ASSERT(kConsStringTag < kExternalStringTag);
2488 __ j(not_zero, &runtime); 2491 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
2489 // String is a cons string. 2492 __ cmpq(rbx, Immediate(kExternalStringTag));
2493 __ j(less, &cons_string, Label::kNear);
2494 __ j(equal, &runtime);
2495
2496 // String is sliced.
2497 __ SmiToInteger32(r14, FieldOperand(rdi, SlicedString::kOffsetOffset));
2498 __ movq(rdi, FieldOperand(rdi, SlicedString::kParentOffset));
2499 // r14: slice offset
2500 // r15: original subject string
2501 // rdi: parent string
2502 __ jmp(&check_encoding, Label::kNear);
2503 // String is a cons string, check whether it is flat.
2504 __ bind(&cons_string);
2490 __ CompareRoot(FieldOperand(rdi, ConsString::kSecondOffset), 2505 __ CompareRoot(FieldOperand(rdi, ConsString::kSecondOffset),
2491 Heap::kEmptyStringRootIndex); 2506 Heap::kEmptyStringRootIndex);
2492 __ j(not_equal, &runtime); 2507 __ j(not_equal, &runtime);
2493 __ movq(rdi, FieldOperand(rdi, ConsString::kFirstOffset)); 2508 __ movq(rdi, FieldOperand(rdi, ConsString::kFirstOffset));
2509 // rdi: first part of cons string or parent of sliced string.
2510 // rbx: map of first part of cons string or map of parent of sliced string.
2511 // Is first part of cons or parent of slice a flat two byte string?
2512 __ bind(&check_encoding);
2494 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); 2513 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
2495 // String is a cons string with empty second part.
2496 // rdi: first part of cons string.
2497 // rbx: map of first part of cons string.
2498 // Is first part a flat two byte string?
2499 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset), 2514 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset),
2500 Immediate(kStringRepresentationMask | kStringEncodingMask)); 2515 Immediate(kStringRepresentationMask | kStringEncodingMask));
2501 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); 2516 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0);
2502 __ j(zero, &seq_two_byte_string, Label::kNear); 2517 __ j(zero, &seq_two_byte_string, Label::kNear);
2503 // Any other flat string must be ascii. 2518 // Any other flat string must be ascii.
2504 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset), 2519 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset),
2505 Immediate(kStringRepresentationMask)); 2520 Immediate(kStringRepresentationMask));
2506 __ j(not_zero, &runtime); 2521 __ j(not_zero, &runtime);
2507 2522
2508 __ bind(&seq_ascii_string); 2523 __ bind(&seq_ascii_string);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
2585 Register arg3 = rdx; 2600 Register arg3 = rdx;
2586 Register arg2 = rsi; 2601 Register arg2 = rsi;
2587 Register arg1 = rdi; 2602 Register arg1 = rdi;
2588 #endif 2603 #endif
2589 2604
2590 // Keep track on aliasing between argX defined above and the registers used. 2605 // Keep track on aliasing between argX defined above and the registers used.
2591 // rdi: subject string 2606 // rdi: subject string
2592 // rbx: previous index 2607 // rbx: previous index
2593 // rcx: encoding of subject string (1 if ascii 0 if two_byte); 2608 // rcx: encoding of subject string (1 if ascii 0 if two_byte);
2594 // r11: code 2609 // r11: code
2610 // r14: slice offset
2611 // r15: original subject string
2612
2613 // Argument 2: Previous index.
2614 __ movq(arg2, rbx);
2595 2615
2596 // Argument 4: End of string data 2616 // Argument 4: End of string data
2597 // Argument 3: Start of string data 2617 // Argument 3: Start of string data
2598 Label setup_two_byte, setup_rest; 2618 Label setup_two_byte, setup_rest, got_length, length_not_from_slice;
2619 // Prepare start and end index of the input.
2620 // Load the length from the original sliced string if that is the case.
2621 __ addq(rbx, r14);
2622 __ SmiToInteger32(arg3, FieldOperand(r15, String::kLengthOffset));
2623 __ addq(r14, arg3); // Using arg3 as scratch.
2624
2625 // rbx: start index of the input
2626 // r14: end index of the input
2627 // r15: original subject string
2599 __ testb(rcx, rcx); // Last use of rcx as encoding of subject string. 2628 __ testb(rcx, rcx); // Last use of rcx as encoding of subject string.
2600 __ j(zero, &setup_two_byte, Label::kNear); 2629 __ j(zero, &setup_two_byte, Label::kNear);
2601 __ SmiToInteger32(rcx, FieldOperand(rdi, String::kLengthOffset)); 2630 __ lea(arg4, FieldOperand(rdi, r14, times_1, SeqAsciiString::kHeaderSize));
2602 __ lea(arg4, FieldOperand(rdi, rcx, times_1, SeqAsciiString::kHeaderSize));
2603 __ lea(arg3, FieldOperand(rdi, rbx, times_1, SeqAsciiString::kHeaderSize)); 2631 __ lea(arg3, FieldOperand(rdi, rbx, times_1, SeqAsciiString::kHeaderSize));
2604 __ jmp(&setup_rest, Label::kNear); 2632 __ jmp(&setup_rest, Label::kNear);
2605 __ bind(&setup_two_byte); 2633 __ bind(&setup_two_byte);
2606 __ SmiToInteger32(rcx, FieldOperand(rdi, String::kLengthOffset)); 2634 __ lea(arg4, FieldOperand(rdi, r14, times_2, SeqTwoByteString::kHeaderSize));
2607 __ lea(arg4, FieldOperand(rdi, rcx, times_2, SeqTwoByteString::kHeaderSize));
2608 __ lea(arg3, FieldOperand(rdi, rbx, times_2, SeqTwoByteString::kHeaderSize)); 2635 __ lea(arg3, FieldOperand(rdi, rbx, times_2, SeqTwoByteString::kHeaderSize));
2636 __ bind(&setup_rest);
2609 2637
2610 __ bind(&setup_rest); 2638 // Argument 1: Original subject string.
2611 // Argument 2: Previous index. 2639 // The original subject is in the previous stack frame. Therefore we have to
2612 __ movq(arg2, rbx); 2640 // use rbp, which points exactly to one pointer size below the previous rsp.
2613 2641 // (Because creating a new stack frame pushes the previous rbp onto the stack
2614 // Argument 1: Subject string. 2642 // and thereby moves up rsp by one kPointerSize.)
2615 #ifdef _WIN64 2643 __ movq(arg1, r15);
2616 __ movq(arg1, rdi);
2617 #else
2618 // Already there in AMD64 calling convention.
2619 ASSERT(arg1.is(rdi));
2620 USE(arg1);
2621 #endif
2622 2644
2623 // Locate the code entry and call it. 2645 // Locate the code entry and call it.
2624 __ addq(r11, Immediate(Code::kHeaderSize - kHeapObjectTag)); 2646 __ addq(r11, Immediate(Code::kHeaderSize - kHeapObjectTag));
2625 __ call(r11); 2647 __ call(r11);
2626 2648
2627 __ LeaveApiExitFrame(); 2649 __ LeaveApiExitFrame();
2628 2650
2629 // Check the result. 2651 // Check the result.
2630 Label success; 2652 Label success;
2631 Label exception; 2653 Label exception;
(...skipping 1240 matching lines...) Expand 10 before | Expand all | Expand 10 after
3872 } 3894 }
3873 3895
3874 3896
3875 // ------------------------------------------------------------------------- 3897 // -------------------------------------------------------------------------
3876 // StringCharCodeAtGenerator 3898 // StringCharCodeAtGenerator
3877 3899
3878 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { 3900 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
3879 Label flat_string; 3901 Label flat_string;
3880 Label ascii_string; 3902 Label ascii_string;
3881 Label got_char_code; 3903 Label got_char_code;
3904 Label sliced_string;
3882 3905
3883 // If the receiver is a smi trigger the non-string case. 3906 // If the receiver is a smi trigger the non-string case.
3884 __ JumpIfSmi(object_, receiver_not_string_); 3907 __ JumpIfSmi(object_, receiver_not_string_);
3885 3908
3886 // Fetch the instance type of the receiver into result register. 3909 // Fetch the instance type of the receiver into result register.
3887 __ movq(result_, FieldOperand(object_, HeapObject::kMapOffset)); 3910 __ movq(result_, FieldOperand(object_, HeapObject::kMapOffset));
3888 __ movzxbl(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); 3911 __ movzxbl(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
3889 // If the receiver is not a string trigger the non-string case. 3912 // If the receiver is not a string trigger the non-string case.
3890 __ testb(result_, Immediate(kIsNotStringMask)); 3913 __ testb(result_, Immediate(kIsNotStringMask));
3891 __ j(not_zero, receiver_not_string_); 3914 __ j(not_zero, receiver_not_string_);
3892 3915
3893 // If the index is non-smi trigger the non-smi case. 3916 // If the index is non-smi trigger the non-smi case.
3894 __ JumpIfNotSmi(index_, &index_not_smi_); 3917 __ JumpIfNotSmi(index_, &index_not_smi_);
3895 3918
3896 // Put smi-tagged index into scratch register. 3919 // Put smi-tagged index into scratch register.
3897 __ movq(scratch_, index_); 3920 __ movq(scratch_, index_);
3898 __ bind(&got_smi_index_); 3921 __ bind(&got_smi_index_);
3899 3922
3900 // Check for index out of range. 3923 // Check for index out of range.
3901 __ SmiCompare(scratch_, FieldOperand(object_, String::kLengthOffset)); 3924 __ SmiCompare(scratch_, FieldOperand(object_, String::kLengthOffset));
3902 __ j(above_equal, index_out_of_range_); 3925 __ j(above_equal, index_out_of_range_);
3903 3926
3904 // We need special handling for non-flat strings. 3927 // We need special handling for non-flat strings.
3905 STATIC_ASSERT(kSeqStringTag == 0); 3928 STATIC_ASSERT(kSeqStringTag == 0);
3906 __ testb(result_, Immediate(kStringRepresentationMask)); 3929 __ testb(result_, Immediate(kStringRepresentationMask));
3907 __ j(zero, &flat_string); 3930 __ j(zero, &flat_string);
3908 3931
3909 // Handle non-flat strings. 3932 // Handle non-flat strings.
3910 __ testb(result_, Immediate(kIsConsStringMask)); 3933 __ and_(result_, Immediate(kStringRepresentationMask));
3911 __ j(zero, &call_runtime_); 3934 STATIC_ASSERT(kConsStringTag < kExternalStringTag);
3935 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
3936 __ cmpb(result_, Immediate(kExternalStringTag));
3937 __ j(greater, &sliced_string);
3938 __ j(equal, &call_runtime_);
3912 3939
3913 // ConsString. 3940 // ConsString.
3914 // Check whether the right hand side is the empty string (i.e. if 3941 // Check whether the right hand side is the empty string (i.e. if
3915 // this is really a flat string in a cons string). If that is not 3942 // this is really a flat string in a cons string). If that is not
3916 // the case we would rather go to the runtime system now to flatten 3943 // the case we would rather go to the runtime system now to flatten
3917 // the string. 3944 // the string.
3945 Label assure_seq_string;
3918 __ CompareRoot(FieldOperand(object_, ConsString::kSecondOffset), 3946 __ CompareRoot(FieldOperand(object_, ConsString::kSecondOffset),
3919 Heap::kEmptyStringRootIndex); 3947 Heap::kEmptyStringRootIndex);
3920 __ j(not_equal, &call_runtime_); 3948 __ j(not_equal, &call_runtime_);
3921 // Get the first of the two strings and load its instance type. 3949 // Get the first of the two strings and load its instance type.
3922 __ movq(object_, FieldOperand(object_, ConsString::kFirstOffset)); 3950 __ movq(object_, FieldOperand(object_, ConsString::kFirstOffset));
3951 __ jmp(&assure_seq_string, Label::kNear);
3952
3953 // SlicedString, unpack and add offset.
3954 __ bind(&sliced_string);
3955 __ addq(scratch_, FieldOperand(object_, SlicedString::kOffsetOffset));
3956 __ movq(object_, FieldOperand(object_, SlicedString::kParentOffset));
3957
3958 __ bind(&assure_seq_string);
3923 __ movq(result_, FieldOperand(object_, HeapObject::kMapOffset)); 3959 __ movq(result_, FieldOperand(object_, HeapObject::kMapOffset));
3924 __ movzxbl(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); 3960 __ movzxbl(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
3925 // If the first cons component is also non-flat, then go to runtime. 3961 // If the first cons component is also non-flat, then go to runtime.
3926 STATIC_ASSERT(kSeqStringTag == 0); 3962 STATIC_ASSERT(kSeqStringTag == 0);
3927 __ testb(result_, Immediate(kStringRepresentationMask)); 3963 __ testb(result_, Immediate(kStringRepresentationMask));
3928 __ j(not_zero, &call_runtime_); 3964 __ j(not_zero, &call_runtime_);
3965 __ jmp(&flat_string);
3929 3966
3930 // Check for 1-byte or 2-byte string. 3967 // Check for 1-byte or 2-byte string.
3931 __ bind(&flat_string); 3968 __ bind(&flat_string);
3932 STATIC_ASSERT(kAsciiStringTag != 0); 3969 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
3970 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
3933 __ testb(result_, Immediate(kStringEncodingMask)); 3971 __ testb(result_, Immediate(kStringEncodingMask));
3934 __ j(not_zero, &ascii_string); 3972 __ j(not_zero, &ascii_string);
3935 3973
3936 // 2-byte string. 3974 // 2-byte string.
3937 // Load the 2-byte character code into the result register. 3975 // Load the 2-byte character code into the result register.
3938 __ SmiToInteger32(scratch_, scratch_); 3976 __ SmiToInteger32(scratch_, scratch_);
3939 __ movzxwl(result_, FieldOperand(object_, 3977 __ movzxwl(result_, FieldOperand(object_,
3940 scratch_, times_2, 3978 scratch_, times_2,
3941 SeqTwoByteString::kHeaderSize)); 3979 SeqTwoByteString::kHeaderSize));
3942 __ jmp(&got_char_code); 3980 __ jmp(&got_char_code);
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
4179 // If result is not supposed to be flat, allocate a cons string object. If 4217 // If result is not supposed to be flat, allocate a cons string object. If
4180 // both strings are ascii the result is an ascii cons string. 4218 // both strings are ascii the result is an ascii cons string.
4181 // rax: first string 4219 // rax: first string
4182 // rbx: length of resulting flat string 4220 // rbx: length of resulting flat string
4183 // rdx: second string 4221 // rdx: second string
4184 // r8: instance type of first string 4222 // r8: instance type of first string
4185 // r9: instance type of second string 4223 // r9: instance type of second string
4186 Label non_ascii, allocated, ascii_data; 4224 Label non_ascii, allocated, ascii_data;
4187 __ movl(rcx, r8); 4225 __ movl(rcx, r8);
4188 __ and_(rcx, r9); 4226 __ and_(rcx, r9);
4189 STATIC_ASSERT(kStringEncodingMask == kAsciiStringTag); 4227 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
4190 __ testl(rcx, Immediate(kAsciiStringTag)); 4228 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
4229 __ testl(rcx, Immediate(kStringEncodingMask));
4191 __ j(zero, &non_ascii); 4230 __ j(zero, &non_ascii);
4192 __ bind(&ascii_data); 4231 __ bind(&ascii_data);
4193 // Allocate an acsii cons string. 4232 // Allocate an acsii cons string.
4194 __ AllocateAsciiConsString(rcx, rdi, no_reg, &string_add_runtime); 4233 __ AllocateAsciiConsString(rcx, rdi, no_reg, &string_add_runtime);
4195 __ bind(&allocated); 4234 __ bind(&allocated);
4196 // Fill the fields of the cons string. 4235 // Fill the fields of the cons string.
4197 __ movq(FieldOperand(rcx, ConsString::kLengthOffset), rbx); 4236 __ movq(FieldOperand(rcx, ConsString::kLengthOffset), rbx);
4198 __ movq(FieldOperand(rcx, ConsString::kHashFieldOffset), 4237 __ movq(FieldOperand(rcx, ConsString::kHashFieldOffset),
4199 Immediate(String::kEmptyHashField)); 4238 Immediate(String::kEmptyHashField));
4200 __ movq(FieldOperand(rcx, ConsString::kFirstOffset), rax); 4239 __ movq(FieldOperand(rcx, ConsString::kFirstOffset), rax);
4201 __ movq(FieldOperand(rcx, ConsString::kSecondOffset), rdx); 4240 __ movq(FieldOperand(rcx, ConsString::kSecondOffset), rdx);
4202 __ movq(rax, rcx); 4241 __ movq(rax, rcx);
4203 __ IncrementCounter(counters->string_add_native(), 1); 4242 __ IncrementCounter(counters->string_add_native(), 1);
4204 __ ret(2 * kPointerSize); 4243 __ ret(2 * kPointerSize);
4205 __ bind(&non_ascii); 4244 __ bind(&non_ascii);
4206 // At least one of the strings is two-byte. Check whether it happens 4245 // At least one of the strings is two-byte. Check whether it happens
4207 // to contain only ascii characters. 4246 // to contain only ascii characters.
4208 // rcx: first instance type AND second instance type. 4247 // rcx: first instance type AND second instance type.
4209 // r8: first instance type. 4248 // r8: first instance type.
4210 // r9: second instance type. 4249 // r9: second instance type.
4211 __ testb(rcx, Immediate(kAsciiDataHintMask)); 4250 __ testb(rcx, Immediate(kAsciiDataHintMask));
4212 __ j(not_zero, &ascii_data); 4251 __ j(not_zero, &ascii_data);
4213 __ xor_(r8, r9); 4252 __ xor_(r8, r9);
4214 STATIC_ASSERT(kAsciiStringTag != 0 && kAsciiDataHintTag != 0); 4253 STATIC_ASSERT(kAsciiStringTag != 0 && kAsciiDataHintTag != 0);
4215 __ andb(r8, Immediate(kAsciiStringTag | kAsciiDataHintTag)); 4254 __ andb(r8, Immediate(kAsciiStringTag | kAsciiDataHintTag));
4216 __ cmpb(r8, Immediate(kAsciiStringTag | kAsciiDataHintTag)); 4255 __ cmpb(r8, Immediate(kAsciiStringTag | kAsciiDataHintTag));
4217 __ j(equal, &ascii_data); 4256 __ j(equal, &ascii_data);
4218 // Allocate a two byte cons string. 4257 // Allocate a two byte cons string.
4219 __ AllocateConsString(rcx, rdi, no_reg, &string_add_runtime); 4258 __ AllocateTwoByteConsString(rcx, rdi, no_reg, &string_add_runtime);
4220 __ jmp(&allocated); 4259 __ jmp(&allocated);
4221 4260
4222 // Handle creating a flat result. First check that both strings are not 4261 // Handle creating a flat result. First check that both strings are not
4223 // external strings. 4262 // external strings.
4224 // rax: first string 4263 // rax: first string
4225 // rbx: length of resulting flat string as smi 4264 // rbx: length of resulting flat string as smi
4226 // rdx: second string 4265 // rdx: second string
4227 // r8: instance type of first string 4266 // r8: instance type of first string
4228 // r9: instance type of first string 4267 // r9: instance type of first string
4229 __ bind(&string_add_flat_result); 4268 __ bind(&string_add_flat_result);
4230 __ SmiToInteger32(rbx, rbx); 4269 __ SmiToInteger32(rbx, rbx);
4231 __ movl(rcx, r8); 4270 __ movl(rcx, r8);
4232 __ and_(rcx, Immediate(kStringRepresentationMask)); 4271 __ and_(rcx, Immediate(kStringRepresentationMask));
4233 __ cmpl(rcx, Immediate(kExternalStringTag)); 4272 __ cmpl(rcx, Immediate(kExternalStringTag));
4234 __ j(equal, &string_add_runtime); 4273 __ j(equal, &string_add_runtime);
4235 __ movl(rcx, r9); 4274 __ movl(rcx, r9);
4236 __ and_(rcx, Immediate(kStringRepresentationMask)); 4275 __ and_(rcx, Immediate(kStringRepresentationMask));
4237 __ cmpl(rcx, Immediate(kExternalStringTag)); 4276 __ cmpl(rcx, Immediate(kExternalStringTag));
4238 __ j(equal, &string_add_runtime); 4277 __ j(equal, &string_add_runtime);
4278 // We cannot encounter sliced strings here since:
4279 STATIC_ASSERT(SlicedString::kMinLength >= String::kMinNonFlatLength);
4239 // Now check if both strings are ascii strings. 4280 // Now check if both strings are ascii strings.
4240 // rax: first string 4281 // rax: first string
4241 // rbx: length of resulting flat string 4282 // rbx: length of resulting flat string
4242 // rdx: second string 4283 // rdx: second string
4243 // r8: instance type of first string 4284 // r8: instance type of first string
4244 // r9: instance type of second string 4285 // r9: instance type of second string
4245 Label non_ascii_string_add_flat_result; 4286 Label non_ascii_string_add_flat_result;
4246 STATIC_ASSERT(kStringEncodingMask == kAsciiStringTag); 4287 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
4247 __ testl(r8, Immediate(kAsciiStringTag)); 4288 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
4289 __ testl(r8, Immediate(kStringEncodingMask));
4248 __ j(zero, &non_ascii_string_add_flat_result); 4290 __ j(zero, &non_ascii_string_add_flat_result);
4249 __ testl(r9, Immediate(kAsciiStringTag)); 4291 __ testl(r9, Immediate(kStringEncodingMask));
4250 __ j(zero, &string_add_runtime); 4292 __ j(zero, &string_add_runtime);
4251 4293
4252 __ bind(&make_flat_ascii_string); 4294 __ bind(&make_flat_ascii_string);
4253 // Both strings are ascii strings. As they are short they are both flat. 4295 // Both strings are ascii strings. As they are short they are both flat.
4254 __ AllocateAsciiString(rcx, rbx, rdi, r14, r11, &string_add_runtime); 4296 __ AllocateAsciiString(rcx, rbx, rdi, r14, r11, &string_add_runtime);
4255 // rcx: result string 4297 // rcx: result string
4256 __ movq(rbx, rcx); 4298 __ movq(rbx, rcx);
4257 // Locate first character of result. 4299 // Locate first character of result.
4258 __ addq(rcx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 4300 __ addq(rcx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
4259 // Locate first character of first argument 4301 // Locate first character of first argument
(...skipping 17 matching lines...) Expand all
4277 __ IncrementCounter(counters->string_add_native(), 1); 4319 __ IncrementCounter(counters->string_add_native(), 1);
4278 __ ret(2 * kPointerSize); 4320 __ ret(2 * kPointerSize);
4279 4321
4280 // Handle creating a flat two byte result. 4322 // Handle creating a flat two byte result.
4281 // rax: first string - known to be two byte 4323 // rax: first string - known to be two byte
4282 // rbx: length of resulting flat string 4324 // rbx: length of resulting flat string
4283 // rdx: second string 4325 // rdx: second string
4284 // r8: instance type of first string 4326 // r8: instance type of first string
4285 // r9: instance type of first string 4327 // r9: instance type of first string
4286 __ bind(&non_ascii_string_add_flat_result); 4328 __ bind(&non_ascii_string_add_flat_result);
4287 __ and_(r9, Immediate(kAsciiStringTag)); 4329 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
4330 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
4331 __ and_(r9, Immediate(kStringEncodingMask));
4288 __ j(not_zero, &string_add_runtime); 4332 __ j(not_zero, &string_add_runtime);
4289 // Both strings are two byte strings. As they are short they are both 4333 // Both strings are two byte strings. As they are short they are both
4290 // flat. 4334 // flat.
4291 __ AllocateTwoByteString(rcx, rbx, rdi, r14, r11, &string_add_runtime); 4335 __ AllocateTwoByteString(rcx, rbx, rdi, r14, r11, &string_add_runtime);
4292 // rcx: result string 4336 // rcx: result string
4293 __ movq(rbx, rcx); 4337 __ movq(rbx, rcx);
4294 // Locate first character of result. 4338 // Locate first character of result.
4295 __ addq(rcx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 4339 __ addq(rcx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
4296 // Locate first character of first argument. 4340 // Locate first character of first argument.
4297 __ SmiToInteger32(rdi, FieldOperand(rax, String::kLengthOffset)); 4341 __ SmiToInteger32(rdi, FieldOperand(rax, String::kLengthOffset));
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after
4686 masm, rbx, rcx, rax, rdx, rdi, r14, &make_two_character_string); 4730 masm, rbx, rcx, rax, rdx, rdi, r14, &make_two_character_string);
4687 __ ret(3 * kPointerSize); 4731 __ ret(3 * kPointerSize);
4688 4732
4689 __ bind(&make_two_character_string); 4733 __ bind(&make_two_character_string);
4690 // Setup registers for allocating the two character string. 4734 // Setup registers for allocating the two character string.
4691 __ movq(rax, Operand(rsp, kStringOffset)); 4735 __ movq(rax, Operand(rsp, kStringOffset));
4692 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 4736 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
4693 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); 4737 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
4694 __ Set(rcx, 2); 4738 __ Set(rcx, 2);
4695 4739
4696 __ bind(&result_longer_than_two); 4740 if (FLAG_string_slices) {
4741 Label copy_routine;
4742 // If coming from the make_two_character_string path, the string
4743 // is too short to be sliced anyways.
4744 STATIC_ASSERT(2 < SlicedString::kMinLength);
4745 __ jmp(&copy_routine);
4746 __ bind(&result_longer_than_two);
4747
4748 // rax: string
4749 // rbx: instance type
4750 // rcx: sub string length
4751 // rdx: from index (smi)
4752 Label allocate_slice, sliced_string, seq_string;
4753 __ cmpq(rcx, Immediate(SlicedString::kMinLength));
4754 // Short slice. Copy instead of slicing.
4755 __ j(less, &copy_routine);
4756 STATIC_ASSERT(kSeqStringTag == 0);
4757 __ testb(rbx, Immediate(kStringRepresentationMask));
4758 __ j(zero, &seq_string, Label::kNear);
4759 STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag));
4760 STATIC_ASSERT(kIsIndirectStringMask != 0);
4761 __ testb(rbx, Immediate(kIsIndirectStringMask));
4762 // External string. Jump to runtime.
4763 __ j(zero, &runtime);
4764
4765 __ testb(rbx, Immediate(kSlicedNotConsMask));
4766 __ j(not_zero, &sliced_string, Label::kNear);
4767 // Cons string. Check whether it is flat, then fetch first part.
4768 __ CompareRoot(FieldOperand(rax, ConsString::kSecondOffset),
4769 Heap::kEmptyStringRootIndex);
4770 __ j(not_equal, &runtime);
4771 __ movq(rdi, FieldOperand(rax, ConsString::kFirstOffset));
4772 __ jmp(&allocate_slice, Label::kNear);
4773
4774 __ bind(&sliced_string);
4775 // Sliced string. Fetch parent and correct start index by offset.
4776 __ addq(rdx, FieldOperand(rax, SlicedString::kOffsetOffset));
4777 __ movq(rdi, FieldOperand(rax, SlicedString::kParentOffset));
4778 __ jmp(&allocate_slice, Label::kNear);
4779
4780 __ bind(&seq_string);
4781 // Sequential string. Just move string to the right register.
4782 __ movq(rdi, rax);
4783
4784 __ bind(&allocate_slice);
4785 // edi: underlying subject string
4786 // ebx: instance type of original subject string
4787 // edx: offset
4788 // ecx: length
4789 // Allocate new sliced string. At this point we do not reload the instance
4790 // type including the string encoding because we simply rely on the info
4791 // provided by the original string. It does not matter if the original
4792 // string's encoding is wrong because we always have to recheck encoding of
4793 // the newly created string's parent anyways due to externalized strings.
4794 Label two_byte_slice, set_slice_header;
4795 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
4796 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
4797 __ testb(rbx, Immediate(kStringEncodingMask));
4798 __ j(zero, &two_byte_slice, Label::kNear);
4799 __ AllocateAsciiSlicedString(rax, rbx, no_reg, &runtime);
4800 __ jmp(&set_slice_header, Label::kNear);
4801 __ bind(&two_byte_slice);
4802 __ AllocateTwoByteSlicedString(rax, rbx, no_reg, &runtime);
4803 __ bind(&set_slice_header);
4804 __ movq(FieldOperand(rax, SlicedString::kOffsetOffset), rdx);
4805 __ Integer32ToSmi(rcx, rcx);
4806 __ movq(FieldOperand(rax, SlicedString::kLengthOffset), rcx);
4807 __ movq(FieldOperand(rax, SlicedString::kParentOffset), rdi);
4808 __ movq(FieldOperand(rax, SlicedString::kHashFieldOffset),
4809 Immediate(String::kEmptyHashField));
4810 __ jmp(&return_rax);
4811
4812 __ bind(&copy_routine);
4813 } else {
4814 __ bind(&result_longer_than_two);
4815 }
4697 4816
4698 // rax: string 4817 // rax: string
4699 // rbx: instance type 4818 // rbx: instance type
4700 // rcx: result string length 4819 // rcx: result string length
4701 // Check for flat ascii string 4820 // Check for flat ascii string
4702 Label non_ascii_flat; 4821 Label non_ascii_flat;
4703 __ JumpIfInstanceTypeIsNotSequentialAscii(rbx, rbx, &non_ascii_flat); 4822 __ JumpIfInstanceTypeIsNotSequentialAscii(rbx, rbx, &non_ascii_flat);
4704 4823
4705 // Allocate the result. 4824 // Allocate the result.
4706 __ AllocateAsciiString(rax, rcx, rbx, rdx, rdi, &runtime); 4825 __ AllocateAsciiString(rax, rcx, rbx, rdx, rdi, &runtime);
(...skipping 866 matching lines...) Expand 10 before | Expand all | Expand 10 after
5573 5692
5574 // Fall through when we need to inform the incremental marker. 5693 // Fall through when we need to inform the incremental marker.
5575 } 5694 }
5576 5695
5577 5696
5578 #undef __ 5697 #undef __
5579 5698
5580 } } // namespace v8::internal 5699 } } // namespace v8::internal
5581 5700
5582 #endif // V8_TARGET_ARCH_X64 5701 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/builtins-x64.cc ('k') | src/x64/full-codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698