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

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

Issue 144023009: Get rid of the unused native code StringAddStub. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Remove obsolete StringHelper methods. Created 6 years, 11 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/code-stubs-x64.h ('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 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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 332 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 Isolate* isolate, 343 Isolate* isolate,
344 CodeStubInterfaceDescriptor* descriptor) { 344 CodeStubInterfaceDescriptor* descriptor) {
345 static Register registers[] = { rcx, rdx, rax }; 345 static Register registers[] = { rcx, rdx, rax };
346 descriptor->register_param_count_ = 3; 346 descriptor->register_param_count_ = 3;
347 descriptor->register_params_ = registers; 347 descriptor->register_params_ = registers;
348 descriptor->deoptimization_handler_ = 348 descriptor->deoptimization_handler_ =
349 FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite); 349 FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite);
350 } 350 }
351 351
352 352
353 void NewStringAddStub::InitializeInterfaceDescriptor( 353 void StringAddStub::InitializeInterfaceDescriptor(
354 Isolate* isolate, 354 Isolate* isolate,
355 CodeStubInterfaceDescriptor* descriptor) { 355 CodeStubInterfaceDescriptor* descriptor) {
356 static Register registers[] = { rdx, rax }; 356 static Register registers[] = { rdx, rax };
357 descriptor->register_param_count_ = 2; 357 descriptor->register_param_count_ = 2;
358 descriptor->register_params_ = registers; 358 descriptor->register_params_ = registers;
359 descriptor->deoptimization_handler_ = 359 descriptor->deoptimization_handler_ =
360 Runtime::FunctionForId(Runtime::kStringAdd)->entry; 360 Runtime::FunctionForId(Runtime::kStringAdd)->entry;
361 } 361 }
362 362
363 363
(...skipping 2873 matching lines...) Expand 10 before | Expand all | Expand 10 after
3237 if (!result_.is(rax)) { 3237 if (!result_.is(rax)) {
3238 __ movp(result_, rax); 3238 __ movp(result_, rax);
3239 } 3239 }
3240 call_helper.AfterCall(masm); 3240 call_helper.AfterCall(masm);
3241 __ jmp(&exit_); 3241 __ jmp(&exit_);
3242 3242
3243 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); 3243 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
3244 } 3244 }
3245 3245
3246 3246
3247 void StringAddStub::Generate(MacroAssembler* masm) {
3248 Label call_runtime, call_builtin;
3249 Builtins::JavaScript builtin_id = Builtins::ADD;
3250
3251 // Load the two arguments.
3252 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER);
3253 __ movp(rax, args.GetArgumentOperand(0)); // First argument (left).
3254 __ movp(rdx, args.GetArgumentOperand(1)); // Second argument (right).
3255
3256 // Make sure that both arguments are strings if not known in advance.
3257 // Otherwise, at least one of the arguments is definitely a string,
3258 // and we convert the one that is not known to be a string.
3259 if ((flags_ & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) {
3260 ASSERT((flags_ & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT);
3261 ASSERT((flags_ & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT);
3262 __ JumpIfSmi(rax, &call_runtime);
3263 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, r8);
3264 __ j(above_equal, &call_runtime);
3265
3266 // First argument is a a string, test second.
3267 __ JumpIfSmi(rdx, &call_runtime);
3268 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, r9);
3269 __ j(above_equal, &call_runtime);
3270 } else if ((flags_ & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) {
3271 ASSERT((flags_ & STRING_ADD_CHECK_RIGHT) == 0);
3272 GenerateConvertArgument(masm, 2 * kPointerSize, rax, rbx, rcx, rdi,
3273 &call_builtin);
3274 builtin_id = Builtins::STRING_ADD_RIGHT;
3275 } else if ((flags_ & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) {
3276 ASSERT((flags_ & STRING_ADD_CHECK_LEFT) == 0);
3277 GenerateConvertArgument(masm, 1 * kPointerSize, rdx, rbx, rcx, rdi,
3278 &call_builtin);
3279 builtin_id = Builtins::STRING_ADD_LEFT;
3280 }
3281
3282 // Both arguments are strings.
3283 // rax: first string
3284 // rdx: second string
3285 // Check if either of the strings are empty. In that case return the other.
3286 Label second_not_zero_length, both_not_zero_length;
3287 __ movp(rcx, FieldOperand(rdx, String::kLengthOffset));
3288 __ SmiTest(rcx);
3289 __ j(not_zero, &second_not_zero_length, Label::kNear);
3290 // Second string is empty, result is first string which is already in rax.
3291 Counters* counters = masm->isolate()->counters();
3292 __ IncrementCounter(counters->string_add_native(), 1);
3293 __ ret(2 * kPointerSize);
3294 __ bind(&second_not_zero_length);
3295 __ movp(rbx, FieldOperand(rax, String::kLengthOffset));
3296 __ SmiTest(rbx);
3297 __ j(not_zero, &both_not_zero_length, Label::kNear);
3298 // First string is empty, result is second string which is in rdx.
3299 __ movp(rax, rdx);
3300 __ IncrementCounter(counters->string_add_native(), 1);
3301 __ ret(2 * kPointerSize);
3302
3303 // Both strings are non-empty.
3304 // rax: first string
3305 // rbx: length of first string
3306 // rcx: length of second string
3307 // rdx: second string
3308 // r8: map of first string (if flags_ == NO_STRING_ADD_FLAGS)
3309 // r9: map of second string (if flags_ == NO_STRING_ADD_FLAGS)
3310 Label string_add_flat_result, longer_than_two;
3311 __ bind(&both_not_zero_length);
3312
3313 // If arguments where known to be strings, maps are not loaded to r8 and r9
3314 // by the code above.
3315 if ((flags_ & STRING_ADD_CHECK_BOTH) != STRING_ADD_CHECK_BOTH) {
3316 __ movp(r8, FieldOperand(rax, HeapObject::kMapOffset));
3317 __ movp(r9, FieldOperand(rdx, HeapObject::kMapOffset));
3318 }
3319 // Get the instance types of the two strings as they will be needed soon.
3320 __ movzxbl(r8, FieldOperand(r8, Map::kInstanceTypeOffset));
3321 __ movzxbl(r9, FieldOperand(r9, Map::kInstanceTypeOffset));
3322
3323 // Look at the length of the result of adding the two strings.
3324 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue / 2);
3325 __ SmiAdd(rbx, rbx, rcx);
3326 // Use the string table when adding two one character strings, as it
3327 // helps later optimizations to return an internalized string here.
3328 __ SmiCompare(rbx, Smi::FromInt(2));
3329 __ j(not_equal, &longer_than_two);
3330
3331 // Check that both strings are non-external ASCII strings.
3332 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r8, r9, rbx, rcx,
3333 &call_runtime);
3334
3335 // Get the two characters forming the sub string.
3336 __ movzxbq(rbx, FieldOperand(rax, SeqOneByteString::kHeaderSize));
3337 __ movzxbq(rcx, FieldOperand(rdx, SeqOneByteString::kHeaderSize));
3338
3339 // Try to lookup two character string in string table. If it is not found
3340 // just allocate a new one.
3341 Label make_two_character_string, make_flat_ascii_string;
3342 StringHelper::GenerateTwoCharacterStringTableProbe(
3343 masm, rbx, rcx, r14, r11, rdi, r15, &make_two_character_string);
3344 __ IncrementCounter(counters->string_add_native(), 1);
3345 __ ret(2 * kPointerSize);
3346
3347 __ bind(&make_two_character_string);
3348 __ Set(rdi, 2);
3349 __ AllocateAsciiString(rax, rdi, r8, r9, r11, &call_runtime);
3350 // rbx - first byte: first character
3351 // rbx - second byte: *maybe* second character
3352 // Make sure that the second byte of rbx contains the second character.
3353 __ movzxbq(rcx, FieldOperand(rdx, SeqOneByteString::kHeaderSize));
3354 __ shll(rcx, Immediate(kBitsPerByte));
3355 __ orl(rbx, rcx);
3356 // Write both characters to the new string.
3357 __ movw(FieldOperand(rax, SeqOneByteString::kHeaderSize), rbx);
3358 __ IncrementCounter(counters->string_add_native(), 1);
3359 __ ret(2 * kPointerSize);
3360
3361 __ bind(&longer_than_two);
3362 // Check if resulting string will be flat.
3363 __ SmiCompare(rbx, Smi::FromInt(ConsString::kMinLength));
3364 __ j(below, &string_add_flat_result);
3365 // Handle exceptionally long strings in the runtime system.
3366 STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0);
3367 __ SmiCompare(rbx, Smi::FromInt(String::kMaxLength));
3368 __ j(above, &call_runtime);
3369
3370 // If result is not supposed to be flat, allocate a cons string object. If
3371 // both strings are ASCII the result is an ASCII cons string.
3372 // rax: first string
3373 // rbx: length of resulting flat string
3374 // rdx: second string
3375 // r8: instance type of first string
3376 // r9: instance type of second string
3377 Label non_ascii, allocated, ascii_data;
3378 __ movl(rcx, r8);
3379 __ and_(rcx, r9);
3380 STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0);
3381 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
3382 __ testl(rcx, Immediate(kStringEncodingMask));
3383 __ j(zero, &non_ascii);
3384 __ bind(&ascii_data);
3385 // Allocate an ASCII cons string.
3386 __ AllocateAsciiConsString(rcx, rdi, no_reg, &call_runtime);
3387 __ bind(&allocated);
3388 // Fill the fields of the cons string.
3389 __ movp(FieldOperand(rcx, ConsString::kLengthOffset), rbx);
3390 __ movp(FieldOperand(rcx, ConsString::kHashFieldOffset),
3391 Immediate(String::kEmptyHashField));
3392
3393 Label skip_write_barrier, after_writing;
3394 ExternalReference high_promotion_mode = ExternalReference::
3395 new_space_high_promotion_mode_active_address(masm->isolate());
3396 __ Load(rbx, high_promotion_mode);
3397 __ testb(rbx, Immediate(1));
3398 __ j(zero, &skip_write_barrier);
3399
3400 __ movp(FieldOperand(rcx, ConsString::kFirstOffset), rax);
3401 __ RecordWriteField(rcx,
3402 ConsString::kFirstOffset,
3403 rax,
3404 rbx,
3405 kDontSaveFPRegs);
3406 __ movp(FieldOperand(rcx, ConsString::kSecondOffset), rdx);
3407 __ RecordWriteField(rcx,
3408 ConsString::kSecondOffset,
3409 rdx,
3410 rbx,
3411 kDontSaveFPRegs);
3412 __ jmp(&after_writing);
3413
3414 __ bind(&skip_write_barrier);
3415 __ movp(FieldOperand(rcx, ConsString::kFirstOffset), rax);
3416 __ movp(FieldOperand(rcx, ConsString::kSecondOffset), rdx);
3417
3418 __ bind(&after_writing);
3419
3420 __ movp(rax, rcx);
3421 __ IncrementCounter(counters->string_add_native(), 1);
3422 __ ret(2 * kPointerSize);
3423 __ bind(&non_ascii);
3424 // At least one of the strings is two-byte. Check whether it happens
3425 // to contain only one byte characters.
3426 // rcx: first instance type AND second instance type.
3427 // r8: first instance type.
3428 // r9: second instance type.
3429 __ testb(rcx, Immediate(kOneByteDataHintMask));
3430 __ j(not_zero, &ascii_data);
3431 __ xor_(r8, r9);
3432 STATIC_ASSERT(kOneByteStringTag != 0 && kOneByteDataHintTag != 0);
3433 __ andb(r8, Immediate(kOneByteStringTag | kOneByteDataHintTag));
3434 __ cmpb(r8, Immediate(kOneByteStringTag | kOneByteDataHintTag));
3435 __ j(equal, &ascii_data);
3436 // Allocate a two byte cons string.
3437 __ AllocateTwoByteConsString(rcx, rdi, no_reg, &call_runtime);
3438 __ jmp(&allocated);
3439
3440 // We cannot encounter sliced strings or cons strings here since:
3441 STATIC_ASSERT(SlicedString::kMinLength >= ConsString::kMinLength);
3442 // Handle creating a flat result from either external or sequential strings.
3443 // Locate the first characters' locations.
3444 // rax: first string
3445 // rbx: length of resulting flat string as smi
3446 // rdx: second string
3447 // r8: instance type of first string
3448 // r9: instance type of first string
3449 Label first_prepared, second_prepared;
3450 Label first_is_sequential, second_is_sequential;
3451 __ bind(&string_add_flat_result);
3452
3453 __ SmiToInteger32(r14, FieldOperand(rax, SeqString::kLengthOffset));
3454 // r14: length of first string
3455 STATIC_ASSERT(kSeqStringTag == 0);
3456 __ testb(r8, Immediate(kStringRepresentationMask));
3457 __ j(zero, &first_is_sequential, Label::kNear);
3458 // Rule out short external string and load string resource.
3459 STATIC_ASSERT(kShortExternalStringTag != 0);
3460 __ testb(r8, Immediate(kShortExternalStringMask));
3461 __ j(not_zero, &call_runtime);
3462 __ movp(rcx, FieldOperand(rax, ExternalString::kResourceDataOffset));
3463 __ jmp(&first_prepared, Label::kNear);
3464 __ bind(&first_is_sequential);
3465 STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize);
3466 __ lea(rcx, FieldOperand(rax, SeqOneByteString::kHeaderSize));
3467 __ bind(&first_prepared);
3468
3469 // Check whether both strings have same encoding.
3470 __ xorl(r8, r9);
3471 __ testb(r8, Immediate(kStringEncodingMask));
3472 __ j(not_zero, &call_runtime);
3473
3474 __ SmiToInteger32(r15, FieldOperand(rdx, SeqString::kLengthOffset));
3475 // r15: length of second string
3476 STATIC_ASSERT(kSeqStringTag == 0);
3477 __ testb(r9, Immediate(kStringRepresentationMask));
3478 __ j(zero, &second_is_sequential, Label::kNear);
3479 // Rule out short external string and load string resource.
3480 STATIC_ASSERT(kShortExternalStringTag != 0);
3481 __ testb(r9, Immediate(kShortExternalStringMask));
3482 __ j(not_zero, &call_runtime);
3483 __ movp(rdx, FieldOperand(rdx, ExternalString::kResourceDataOffset));
3484 __ jmp(&second_prepared, Label::kNear);
3485 __ bind(&second_is_sequential);
3486 STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize);
3487 __ lea(rdx, FieldOperand(rdx, SeqOneByteString::kHeaderSize));
3488 __ bind(&second_prepared);
3489
3490 Label non_ascii_string_add_flat_result;
3491 // r9: instance type of second string
3492 // First string and second string have the same encoding.
3493 STATIC_ASSERT(kTwoByteStringTag == 0);
3494 __ SmiToInteger32(rbx, rbx);
3495 __ testb(r9, Immediate(kStringEncodingMask));
3496 __ j(zero, &non_ascii_string_add_flat_result);
3497
3498 __ bind(&make_flat_ascii_string);
3499 // Both strings are ASCII strings. As they are short they are both flat.
3500 __ AllocateAsciiString(rax, rbx, rdi, r8, r9, &call_runtime);
3501 // rax: result string
3502 // Locate first character of result.
3503 __ lea(rbx, FieldOperand(rax, SeqOneByteString::kHeaderSize));
3504 // rcx: first char of first string
3505 // rbx: first character of result
3506 // r14: length of first string
3507 StringHelper::GenerateCopyCharacters(masm, rbx, rcx, r14, true);
3508 // rbx: next character of result
3509 // rdx: first char of second string
3510 // r15: length of second string
3511 StringHelper::GenerateCopyCharacters(masm, rbx, rdx, r15, true);
3512 __ IncrementCounter(counters->string_add_native(), 1);
3513 __ ret(2 * kPointerSize);
3514
3515 __ bind(&non_ascii_string_add_flat_result);
3516 // Both strings are ASCII strings. As they are short they are both flat.
3517 __ AllocateTwoByteString(rax, rbx, rdi, r8, r9, &call_runtime);
3518 // rax: result string
3519 // Locate first character of result.
3520 __ lea(rbx, FieldOperand(rax, SeqTwoByteString::kHeaderSize));
3521 // rcx: first char of first string
3522 // rbx: first character of result
3523 // r14: length of first string
3524 StringHelper::GenerateCopyCharacters(masm, rbx, rcx, r14, false);
3525 // rbx: next character of result
3526 // rdx: first char of second string
3527 // r15: length of second string
3528 StringHelper::GenerateCopyCharacters(masm, rbx, rdx, r15, false);
3529 __ IncrementCounter(counters->string_add_native(), 1);
3530 __ ret(2 * kPointerSize);
3531
3532 // Just jump to runtime to add the two strings.
3533 __ bind(&call_runtime);
3534 __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
3535
3536 if (call_builtin.is_linked()) {
3537 __ bind(&call_builtin);
3538 __ InvokeBuiltin(builtin_id, JUMP_FUNCTION);
3539 }
3540 }
3541
3542
3543 void StringAddStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
3544 __ push(rax);
3545 __ push(rdx);
3546 }
3547
3548
3549 void StringAddStub::GenerateRegisterArgsPop(MacroAssembler* masm,
3550 Register temp) {
3551 __ PopReturnAddressTo(temp);
3552 __ pop(rdx);
3553 __ pop(rax);
3554 __ PushReturnAddressFrom(temp);
3555 }
3556
3557
3558 void StringAddStub::GenerateConvertArgument(MacroAssembler* masm,
3559 int stack_offset,
3560 Register arg,
3561 Register scratch1,
3562 Register scratch2,
3563 Register scratch3,
3564 Label* slow) {
3565 // First check if the argument is already a string.
3566 Label not_string, done;
3567 __ JumpIfSmi(arg, &not_string);
3568 __ CmpObjectType(arg, FIRST_NONSTRING_TYPE, scratch1);
3569 __ j(below, &done);
3570
3571 // Check the number to string cache.
3572 __ bind(&not_string);
3573 // Puts the cached result into scratch1.
3574 __ LookupNumberStringCache(arg, scratch1, scratch2, scratch3, slow);
3575 __ movp(arg, scratch1);
3576 __ movp(Operand(rsp, stack_offset), arg);
3577 __ bind(&done);
3578 }
3579
3580
3581 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm,
3582 Register dest,
3583 Register src,
3584 Register count,
3585 bool ascii) {
3586 Label loop;
3587 __ bind(&loop);
3588 // This loop just copies one character at a time, as it is only used for very
3589 // short strings.
3590 if (ascii) {
3591 __ movb(kScratchRegister, Operand(src, 0));
3592 __ movb(Operand(dest, 0), kScratchRegister);
3593 __ incq(src);
3594 __ incq(dest);
3595 } else {
3596 __ movzxwl(kScratchRegister, Operand(src, 0));
3597 __ movw(Operand(dest, 0), kScratchRegister);
3598 __ addq(src, Immediate(2));
3599 __ addq(dest, Immediate(2));
3600 }
3601 __ decl(count);
3602 __ j(not_zero, &loop);
3603 }
3604
3605
3606 void StringHelper::GenerateCopyCharactersREP(MacroAssembler* masm, 3247 void StringHelper::GenerateCopyCharactersREP(MacroAssembler* masm,
3607 Register dest, 3248 Register dest,
3608 Register src, 3249 Register src,
3609 Register count, 3250 Register count,
3610 bool ascii) { 3251 bool ascii) {
3611 // Copy characters using rep movs of doublewords. Align destination on 4 byte 3252 // Copy characters using rep movs of doublewords. Align destination on 4 byte
3612 // boundary before starting rep movs. Copy remaining characters after running 3253 // boundary before starting rep movs. Copy remaining characters after running
3613 // rep movs. 3254 // rep movs.
3614 // Count is positive int32, dest and src are character pointers. 3255 // Count is positive int32, dest and src are character pointers.
3615 ASSERT(dest.is(rdi)); // rep movs destination 3256 ASSERT(dest.is(rdi)); // rep movs destination
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
3652 __ movb(kScratchRegister, Operand(src, 0)); 3293 __ movb(kScratchRegister, Operand(src, 0));
3653 __ movb(Operand(dest, 0), kScratchRegister); 3294 __ movb(Operand(dest, 0), kScratchRegister);
3654 __ incq(src); 3295 __ incq(src);
3655 __ incq(dest); 3296 __ incq(dest);
3656 __ decl(count); 3297 __ decl(count);
3657 __ j(not_zero, &loop); 3298 __ j(not_zero, &loop);
3658 3299
3659 __ bind(&done); 3300 __ bind(&done);
3660 } 3301 }
3661 3302
3662 void StringHelper::GenerateTwoCharacterStringTableProbe(MacroAssembler* masm,
3663 Register c1,
3664 Register c2,
3665 Register scratch1,
3666 Register scratch2,
3667 Register scratch3,
3668 Register scratch4,
3669 Label* not_found) {
3670 // Register scratch3 is the general scratch register in this function.
3671 Register scratch = scratch3;
3672
3673 // Make sure that both characters are not digits as such strings has a
3674 // different hash algorithm. Don't try to look for these in the string table.
3675 Label not_array_index;
3676 __ leal(scratch, Operand(c1, -'0'));
3677 __ cmpl(scratch, Immediate(static_cast<int>('9' - '0')));
3678 __ j(above, &not_array_index, Label::kNear);
3679 __ leal(scratch, Operand(c2, -'0'));
3680 __ cmpl(scratch, Immediate(static_cast<int>('9' - '0')));
3681 __ j(below_equal, not_found);
3682
3683 __ bind(&not_array_index);
3684 // Calculate the two character string hash.
3685 Register hash = scratch1;
3686 GenerateHashInit(masm, hash, c1, scratch);
3687 GenerateHashAddCharacter(masm, hash, c2, scratch);
3688 GenerateHashGetHash(masm, hash, scratch);
3689
3690 // Collect the two characters in a register.
3691 Register chars = c1;
3692 __ shl(c2, Immediate(kBitsPerByte));
3693 __ orl(chars, c2);
3694
3695 // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
3696 // hash: hash of two character string.
3697
3698 // Load the string table.
3699 Register string_table = c2;
3700 __ LoadRoot(string_table, Heap::kStringTableRootIndex);
3701
3702 // Calculate capacity mask from the string table capacity.
3703 Register mask = scratch2;
3704 __ SmiToInteger32(mask,
3705 FieldOperand(string_table, StringTable::kCapacityOffset));
3706 __ decl(mask);
3707
3708 Register map = scratch4;
3709
3710 // Registers
3711 // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
3712 // hash: hash of two character string (32-bit int)
3713 // string_table: string table
3714 // mask: capacity mask (32-bit int)
3715 // map: -
3716 // scratch: -
3717
3718 // Perform a number of probes in the string table.
3719 static const int kProbes = 4;
3720 Label found_in_string_table;
3721 Label next_probe[kProbes];
3722 Register candidate = scratch; // Scratch register contains candidate.
3723 for (int i = 0; i < kProbes; i++) {
3724 // Calculate entry in string table.
3725 __ movl(scratch, hash);
3726 if (i > 0) {
3727 __ addl(scratch, Immediate(StringTable::GetProbeOffset(i)));
3728 }
3729 __ andl(scratch, mask);
3730
3731 // Load the entry from the string table.
3732 STATIC_ASSERT(StringTable::kEntrySize == 1);
3733 __ movp(candidate,
3734 FieldOperand(string_table,
3735 scratch,
3736 times_pointer_size,
3737 StringTable::kElementsStartOffset));
3738
3739 // If entry is undefined no string with this hash can be found.
3740 Label is_string;
3741 __ CmpObjectType(candidate, ODDBALL_TYPE, map);
3742 __ j(not_equal, &is_string, Label::kNear);
3743
3744 __ CompareRoot(candidate, Heap::kUndefinedValueRootIndex);
3745 __ j(equal, not_found);
3746 // Must be the hole (deleted entry).
3747 if (FLAG_debug_code) {
3748 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
3749 __ cmpq(kScratchRegister, candidate);
3750 __ Assert(equal, kOddballInStringTableIsNotUndefinedOrTheHole);
3751 }
3752 __ jmp(&next_probe[i]);
3753
3754 __ bind(&is_string);
3755
3756 // If length is not 2 the string is not a candidate.
3757 __ SmiCompare(FieldOperand(candidate, String::kLengthOffset),
3758 Smi::FromInt(2));
3759 __ j(not_equal, &next_probe[i]);
3760
3761 // We use kScratchRegister as a temporary register in assumption that
3762 // JumpIfInstanceTypeIsNotSequentialAscii does not use it implicitly
3763 Register temp = kScratchRegister;
3764
3765 // Check that the candidate is a non-external ASCII string.
3766 __ movzxbl(temp, FieldOperand(map, Map::kInstanceTypeOffset));
3767 __ JumpIfInstanceTypeIsNotSequentialAscii(
3768 temp, temp, &next_probe[i]);
3769
3770 // Check if the two characters match.
3771 __ movl(temp, FieldOperand(candidate, SeqOneByteString::kHeaderSize));
3772 __ andl(temp, Immediate(0x0000ffff));
3773 __ cmpl(chars, temp);
3774 __ j(equal, &found_in_string_table);
3775 __ bind(&next_probe[i]);
3776 }
3777
3778 // No matching 2 character string found by probing.
3779 __ jmp(not_found);
3780
3781 // Scratch register contains result when we fall through to here.
3782 Register result = candidate;
3783 __ bind(&found_in_string_table);
3784 if (!result.is(rax)) {
3785 __ movp(rax, result);
3786 }
3787 }
3788
3789 3303
3790 void StringHelper::GenerateHashInit(MacroAssembler* masm, 3304 void StringHelper::GenerateHashInit(MacroAssembler* masm,
3791 Register hash, 3305 Register hash,
3792 Register character, 3306 Register character,
3793 Register scratch) { 3307 Register scratch) {
3794 // hash = (seed + character) + ((seed + character) << 10); 3308 // hash = (seed + character) + ((seed + character) << 10);
3795 __ LoadRoot(scratch, Heap::kHashSeedRootIndex); 3309 __ LoadRoot(scratch, Heap::kHashSeedRootIndex);
3796 __ SmiToInteger32(scratch, scratch); 3310 __ SmiToInteger32(scratch, scratch);
3797 __ addl(scratch, character); 3311 __ addl(scratch, character);
3798 __ movl(hash, scratch); 3312 __ movl(hash, scratch);
(...skipping 1925 matching lines...) Expand 10 before | Expand all | Expand 10 after
5724 __ bind(&fast_elements_case); 5238 __ bind(&fast_elements_case);
5725 GenerateCase(masm, FAST_ELEMENTS); 5239 GenerateCase(masm, FAST_ELEMENTS);
5726 } 5240 }
5727 5241
5728 5242
5729 #undef __ 5243 #undef __
5730 5244
5731 } } // namespace v8::internal 5245 } } // namespace v8::internal
5732 5246
5733 #endif // V8_TARGET_ARCH_X64 5247 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/code-stubs-x64.h ('k') | src/x64/full-codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698