| 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 |