OLD | NEW |
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 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
8 | 8 |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 3116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3127 if (!result_.is(rax)) { | 3127 if (!result_.is(rax)) { |
3128 __ movp(result_, rax); | 3128 __ movp(result_, rax); |
3129 } | 3129 } |
3130 call_helper.AfterCall(masm); | 3130 call_helper.AfterCall(masm); |
3131 __ jmp(&exit_); | 3131 __ jmp(&exit_); |
3132 | 3132 |
3133 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); | 3133 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); |
3134 } | 3134 } |
3135 | 3135 |
3136 | 3136 |
3137 void StringHelper::GenerateCopyCharactersREP(MacroAssembler* masm, | 3137 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, |
3138 Register dest, | 3138 Register dest, |
3139 Register src, | 3139 Register src, |
3140 Register count, | 3140 Register count, |
3141 bool ascii) { | 3141 String::Encoding encoding) { |
3142 // Copy characters using rep movs of doublewords. Align destination on 4 byte | |
3143 // boundary before starting rep movs. Copy remaining characters after running | |
3144 // rep movs. | |
3145 // Count is positive int32, dest and src are character pointers. | |
3146 ASSERT(dest.is(rdi)); // rep movs destination | |
3147 ASSERT(src.is(rsi)); // rep movs source | |
3148 ASSERT(count.is(rcx)); // rep movs count | |
3149 | |
3150 // Nothing to do for zero characters. | 3142 // Nothing to do for zero characters. |
3151 Label done; | 3143 Label done; |
3152 __ testl(count, count); | 3144 __ testl(count, count); |
3153 __ j(zero, &done, Label::kNear); | 3145 __ j(zero, &done, Label::kNear); |
3154 | 3146 |
3155 // Make count the number of bytes to copy. | 3147 // Make count the number of bytes to copy. |
3156 if (!ascii) { | 3148 if (encoding == String::TWO_BYTE_ENCODING) { |
3157 STATIC_ASSERT(2 == sizeof(uc16)); | 3149 STATIC_ASSERT(2 == sizeof(uc16)); |
3158 __ addl(count, count); | 3150 __ addl(count, count); |
3159 } | 3151 } |
3160 | 3152 |
3161 // Don't enter the rep movs if there are less than 4 bytes to copy. | |
3162 Label last_bytes; | |
3163 __ testl(count, Immediate(~(kPointerSize - 1))); | |
3164 __ j(zero, &last_bytes, Label::kNear); | |
3165 | |
3166 // Copy from edi to esi using rep movs instruction. | |
3167 __ movl(kScratchRegister, count); | |
3168 // Number of doublewords to copy. | |
3169 __ shrl(count, Immediate(kPointerSizeLog2)); | |
3170 __ repmovsp(); | |
3171 | |
3172 // Find number of bytes left. | |
3173 __ movl(count, kScratchRegister); | |
3174 __ andp(count, Immediate(kPointerSize - 1)); | |
3175 | |
3176 // Check if there are more bytes to copy. | |
3177 __ bind(&last_bytes); | |
3178 __ testl(count, count); | |
3179 __ j(zero, &done, Label::kNear); | |
3180 | |
3181 // Copy remaining characters. | 3153 // Copy remaining characters. |
3182 Label loop; | 3154 Label loop; |
3183 __ bind(&loop); | 3155 __ bind(&loop); |
3184 __ movb(kScratchRegister, Operand(src, 0)); | 3156 __ movb(kScratchRegister, Operand(src, 0)); |
3185 __ movb(Operand(dest, 0), kScratchRegister); | 3157 __ movb(Operand(dest, 0), kScratchRegister); |
3186 __ incp(src); | 3158 __ incp(src); |
3187 __ incp(dest); | 3159 __ incp(dest); |
3188 __ decl(count); | 3160 __ decl(count); |
3189 __ j(not_zero, &loop); | 3161 __ j(not_zero, &loop); |
3190 | 3162 |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3408 __ bind(&sequential_string); | 3380 __ bind(&sequential_string); |
3409 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); | 3381 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); |
3410 __ testb(rbx, Immediate(kStringEncodingMask)); | 3382 __ testb(rbx, Immediate(kStringEncodingMask)); |
3411 __ j(zero, &two_byte_sequential); | 3383 __ j(zero, &two_byte_sequential); |
3412 | 3384 |
3413 // Allocate the result. | 3385 // Allocate the result. |
3414 __ AllocateAsciiString(rax, rcx, r11, r14, r15, &runtime); | 3386 __ AllocateAsciiString(rax, rcx, r11, r14, r15, &runtime); |
3415 | 3387 |
3416 // rax: result string | 3388 // rax: result string |
3417 // rcx: result string length | 3389 // rcx: result string length |
3418 __ movp(r14, rsi); // esi used by following code. | |
3419 { // Locate character of sub string start. | 3390 { // Locate character of sub string start. |
3420 SmiIndex smi_as_index = masm->SmiToIndex(rdx, rdx, times_1); | 3391 SmiIndex smi_as_index = masm->SmiToIndex(rdx, rdx, times_1); |
3421 __ leap(rsi, Operand(rdi, smi_as_index.reg, smi_as_index.scale, | 3392 __ leap(r14, Operand(rdi, smi_as_index.reg, smi_as_index.scale, |
3422 SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 3393 SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
3423 } | 3394 } |
3424 // Locate first character of result. | 3395 // Locate first character of result. |
3425 __ leap(rdi, FieldOperand(rax, SeqOneByteString::kHeaderSize)); | 3396 __ leap(rdi, FieldOperand(rax, SeqOneByteString::kHeaderSize)); |
3426 | 3397 |
3427 // rax: result string | 3398 // rax: result string |
3428 // rcx: result length | 3399 // rcx: result length |
3429 // rdi: first character of result | 3400 // r14: first character of result |
3430 // rsi: character of sub string start | 3401 // rsi: character of sub string start |
3431 // r14: original value of rsi | 3402 StringHelper::GenerateCopyCharacters( |
3432 StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, true); | 3403 masm, rdi, r14, rcx, String::ONE_BYTE_ENCODING); |
3433 __ movp(rsi, r14); // Restore rsi. | |
3434 __ IncrementCounter(counters->sub_string_native(), 1); | 3404 __ IncrementCounter(counters->sub_string_native(), 1); |
3435 __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize); | 3405 __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize); |
3436 | 3406 |
3437 __ bind(&two_byte_sequential); | 3407 __ bind(&two_byte_sequential); |
3438 // Allocate the result. | 3408 // Allocate the result. |
3439 __ AllocateTwoByteString(rax, rcx, r11, r14, r15, &runtime); | 3409 __ AllocateTwoByteString(rax, rcx, r11, r14, r15, &runtime); |
3440 | 3410 |
3441 // rax: result string | 3411 // rax: result string |
3442 // rcx: result string length | 3412 // rcx: result string length |
3443 __ movp(r14, rsi); // esi used by following code. | |
3444 { // Locate character of sub string start. | 3413 { // Locate character of sub string start. |
3445 SmiIndex smi_as_index = masm->SmiToIndex(rdx, rdx, times_2); | 3414 SmiIndex smi_as_index = masm->SmiToIndex(rdx, rdx, times_2); |
3446 __ leap(rsi, Operand(rdi, smi_as_index.reg, smi_as_index.scale, | 3415 __ leap(r14, Operand(rdi, smi_as_index.reg, smi_as_index.scale, |
3447 SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 3416 SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
3448 } | 3417 } |
3449 // Locate first character of result. | 3418 // Locate first character of result. |
3450 __ leap(rdi, FieldOperand(rax, SeqTwoByteString::kHeaderSize)); | 3419 __ leap(rdi, FieldOperand(rax, SeqTwoByteString::kHeaderSize)); |
3451 | 3420 |
3452 // rax: result string | 3421 // rax: result string |
3453 // rcx: result length | 3422 // rcx: result length |
3454 // rdi: first character of result | 3423 // rdi: first character of result |
3455 // rsi: character of sub string start | 3424 // r14: character of sub string start |
3456 // r14: original value of rsi | 3425 StringHelper::GenerateCopyCharacters( |
3457 StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, false); | 3426 masm, rdi, r14, rcx, String::TWO_BYTE_ENCODING); |
3458 __ movp(rsi, r14); // Restore esi. | |
3459 __ IncrementCounter(counters->sub_string_native(), 1); | 3427 __ IncrementCounter(counters->sub_string_native(), 1); |
3460 __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize); | 3428 __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize); |
3461 | 3429 |
3462 // Just jump to runtime to create the sub string. | 3430 // Just jump to runtime to create the sub string. |
3463 __ bind(&runtime); | 3431 __ bind(&runtime); |
3464 __ TailCallRuntime(Runtime::kHiddenSubString, 3, 1); | 3432 __ TailCallRuntime(Runtime::kHiddenSubString, 3, 1); |
3465 | 3433 |
3466 __ bind(&single_char); | 3434 __ bind(&single_char); |
3467 // rax: string | 3435 // rax: string |
3468 // rbx: instance type | 3436 // rbx: instance type |
(...skipping 1599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5068 return_value_operand, | 5036 return_value_operand, |
5069 NULL); | 5037 NULL); |
5070 } | 5038 } |
5071 | 5039 |
5072 | 5040 |
5073 #undef __ | 5041 #undef __ |
5074 | 5042 |
5075 } } // namespace v8::internal | 5043 } } // namespace v8::internal |
5076 | 5044 |
5077 #endif // V8_TARGET_ARCH_X64 | 5045 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |