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

Side by Side Diff: src/ia32/code-stubs-ia32.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/ia32/code-stubs-ia32.h ('k') | src/ia32/full-codegen-ia32.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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 Isolate* isolate, 346 Isolate* isolate,
347 CodeStubInterfaceDescriptor* descriptor) { 347 CodeStubInterfaceDescriptor* descriptor) {
348 static Register registers[] = { ecx, edx, eax }; 348 static Register registers[] = { ecx, edx, eax };
349 descriptor->register_param_count_ = 3; 349 descriptor->register_param_count_ = 3;
350 descriptor->register_params_ = registers; 350 descriptor->register_params_ = registers;
351 descriptor->deoptimization_handler_ = 351 descriptor->deoptimization_handler_ =
352 FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite); 352 FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite);
353 } 353 }
354 354
355 355
356 void NewStringAddStub::InitializeInterfaceDescriptor( 356 void StringAddStub::InitializeInterfaceDescriptor(
357 Isolate* isolate, 357 Isolate* isolate,
358 CodeStubInterfaceDescriptor* descriptor) { 358 CodeStubInterfaceDescriptor* descriptor) {
359 static Register registers[] = { edx, eax }; 359 static Register registers[] = { edx, eax };
360 descriptor->register_param_count_ = 2; 360 descriptor->register_param_count_ = 2;
361 descriptor->register_params_ = registers; 361 descriptor->register_params_ = registers;
362 descriptor->deoptimization_handler_ = 362 descriptor->deoptimization_handler_ =
363 Runtime::FunctionForId(Runtime::kStringAdd)->entry; 363 Runtime::FunctionForId(Runtime::kStringAdd)->entry;
364 } 364 }
365 365
366 366
(...skipping 3003 matching lines...) Expand 10 before | Expand all | Expand 10 after
3370 if (!result_.is(eax)) { 3370 if (!result_.is(eax)) {
3371 __ mov(result_, eax); 3371 __ mov(result_, eax);
3372 } 3372 }
3373 call_helper.AfterCall(masm); 3373 call_helper.AfterCall(masm);
3374 __ jmp(&exit_); 3374 __ jmp(&exit_);
3375 3375
3376 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); 3376 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
3377 } 3377 }
3378 3378
3379 3379
3380 void StringAddStub::Generate(MacroAssembler* masm) {
3381 Label call_runtime, call_builtin;
3382 Builtins::JavaScript builtin_id = Builtins::ADD;
3383
3384 // Load the two arguments.
3385 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument.
3386 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument.
3387
3388 // Make sure that both arguments are strings if not known in advance.
3389 // Otherwise, at least one of the arguments is definitely a string,
3390 // and we convert the one that is not known to be a string.
3391 if ((flags_ & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) {
3392 ASSERT((flags_ & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT);
3393 ASSERT((flags_ & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT);
3394 __ JumpIfSmi(eax, &call_runtime);
3395 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ebx);
3396 __ j(above_equal, &call_runtime);
3397
3398 // First argument is a a string, test second.
3399 __ JumpIfSmi(edx, &call_runtime);
3400 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, ebx);
3401 __ j(above_equal, &call_runtime);
3402 } else if ((flags_ & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) {
3403 ASSERT((flags_ & STRING_ADD_CHECK_RIGHT) == 0);
3404 GenerateConvertArgument(masm, 2 * kPointerSize, eax, ebx, ecx, edi,
3405 &call_builtin);
3406 builtin_id = Builtins::STRING_ADD_RIGHT;
3407 } else if ((flags_ & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) {
3408 ASSERT((flags_ & STRING_ADD_CHECK_LEFT) == 0);
3409 GenerateConvertArgument(masm, 1 * kPointerSize, edx, ebx, ecx, edi,
3410 &call_builtin);
3411 builtin_id = Builtins::STRING_ADD_LEFT;
3412 }
3413
3414 // Both arguments are strings.
3415 // eax: first string
3416 // edx: second string
3417 // Check if either of the strings are empty. In that case return the other.
3418 Label second_not_zero_length, both_not_zero_length;
3419 __ mov(ecx, FieldOperand(edx, String::kLengthOffset));
3420 STATIC_ASSERT(kSmiTag == 0);
3421 __ test(ecx, ecx);
3422 __ j(not_zero, &second_not_zero_length, Label::kNear);
3423 // Second string is empty, result is first string which is already in eax.
3424 Counters* counters = masm->isolate()->counters();
3425 __ IncrementCounter(counters->string_add_native(), 1);
3426 __ ret(2 * kPointerSize);
3427 __ bind(&second_not_zero_length);
3428 __ mov(ebx, FieldOperand(eax, String::kLengthOffset));
3429 STATIC_ASSERT(kSmiTag == 0);
3430 __ test(ebx, ebx);
3431 __ j(not_zero, &both_not_zero_length, Label::kNear);
3432 // First string is empty, result is second string which is in edx.
3433 __ mov(eax, edx);
3434 __ IncrementCounter(counters->string_add_native(), 1);
3435 __ ret(2 * kPointerSize);
3436
3437 // Both strings are non-empty.
3438 // eax: first string
3439 // ebx: length of first string as a smi
3440 // ecx: length of second string as a smi
3441 // edx: second string
3442 // Look at the length of the result of adding the two strings.
3443 Label string_add_flat_result, longer_than_two;
3444 __ bind(&both_not_zero_length);
3445 __ add(ebx, ecx);
3446 STATIC_ASSERT(Smi::kMaxValue == String::kMaxLength);
3447 // Handle exceptionally long strings in the runtime system.
3448 __ j(overflow, &call_runtime);
3449 // Use the string table when adding two one character strings, as it
3450 // helps later optimizations to return an internalized string here.
3451 __ cmp(ebx, Immediate(Smi::FromInt(2)));
3452 __ j(not_equal, &longer_than_two);
3453
3454 // Check that both strings are non-external ASCII strings.
3455 __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx, &call_runtime);
3456
3457 // Get the two characters forming the new string.
3458 __ movzx_b(ebx, FieldOperand(eax, SeqOneByteString::kHeaderSize));
3459 __ movzx_b(ecx, FieldOperand(edx, SeqOneByteString::kHeaderSize));
3460
3461 // Try to lookup two character string in string table. If it is not found
3462 // just allocate a new one.
3463 Label make_two_character_string, make_two_character_string_no_reload;
3464 StringHelper::GenerateTwoCharacterStringTableProbe(
3465 masm, ebx, ecx, eax, edx, edi,
3466 &make_two_character_string_no_reload, &make_two_character_string);
3467 __ IncrementCounter(counters->string_add_native(), 1);
3468 __ ret(2 * kPointerSize);
3469
3470 // Allocate a two character string.
3471 __ bind(&make_two_character_string);
3472 // Reload the arguments.
3473 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument.
3474 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument.
3475 // Get the two characters forming the new string.
3476 __ movzx_b(ebx, FieldOperand(eax, SeqOneByteString::kHeaderSize));
3477 __ movzx_b(ecx, FieldOperand(edx, SeqOneByteString::kHeaderSize));
3478 __ bind(&make_two_character_string_no_reload);
3479 __ IncrementCounter(counters->string_add_make_two_char(), 1);
3480 __ AllocateAsciiString(eax, 2, edi, edx, &call_runtime);
3481 // Pack both characters in ebx.
3482 __ shl(ecx, kBitsPerByte);
3483 __ or_(ebx, ecx);
3484 // Set the characters in the new string.
3485 __ mov_w(FieldOperand(eax, SeqOneByteString::kHeaderSize), ebx);
3486 __ IncrementCounter(counters->string_add_native(), 1);
3487 __ ret(2 * kPointerSize);
3488
3489 __ bind(&longer_than_two);
3490 // Check if resulting string will be flat.
3491 __ cmp(ebx, Immediate(Smi::FromInt(ConsString::kMinLength)));
3492 __ j(below, &string_add_flat_result);
3493
3494 // If result is not supposed to be flat allocate a cons string object. If both
3495 // strings are ASCII the result is an ASCII cons string.
3496 Label non_ascii, allocated, ascii_data;
3497 __ mov(edi, FieldOperand(eax, HeapObject::kMapOffset));
3498 __ movzx_b(ecx, FieldOperand(edi, Map::kInstanceTypeOffset));
3499 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
3500 __ movzx_b(edi, FieldOperand(edi, Map::kInstanceTypeOffset));
3501 __ and_(ecx, edi);
3502 STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0);
3503 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
3504 __ test(ecx, Immediate(kStringEncodingMask));
3505 __ j(zero, &non_ascii);
3506 __ bind(&ascii_data);
3507 // Allocate an ASCII cons string.
3508 __ AllocateAsciiConsString(ecx, edi, no_reg, &call_runtime);
3509 __ bind(&allocated);
3510 // Fill the fields of the cons string.
3511 __ AssertSmi(ebx);
3512 __ mov(FieldOperand(ecx, ConsString::kLengthOffset), ebx);
3513 __ mov(FieldOperand(ecx, ConsString::kHashFieldOffset),
3514 Immediate(String::kEmptyHashField));
3515
3516 Label skip_write_barrier, after_writing;
3517 ExternalReference high_promotion_mode = ExternalReference::
3518 new_space_high_promotion_mode_active_address(masm->isolate());
3519 __ test(Operand::StaticVariable(high_promotion_mode), Immediate(1));
3520 __ j(zero, &skip_write_barrier);
3521
3522 __ mov(FieldOperand(ecx, ConsString::kFirstOffset), eax);
3523 __ RecordWriteField(ecx,
3524 ConsString::kFirstOffset,
3525 eax,
3526 ebx,
3527 kDontSaveFPRegs);
3528 __ mov(FieldOperand(ecx, ConsString::kSecondOffset), edx);
3529 __ RecordWriteField(ecx,
3530 ConsString::kSecondOffset,
3531 edx,
3532 ebx,
3533 kDontSaveFPRegs);
3534 __ jmp(&after_writing);
3535
3536 __ bind(&skip_write_barrier);
3537 __ mov(FieldOperand(ecx, ConsString::kFirstOffset), eax);
3538 __ mov(FieldOperand(ecx, ConsString::kSecondOffset), edx);
3539
3540 __ bind(&after_writing);
3541
3542 __ mov(eax, ecx);
3543 __ IncrementCounter(counters->string_add_native(), 1);
3544 __ ret(2 * kPointerSize);
3545 __ bind(&non_ascii);
3546 // At least one of the strings is two-byte. Check whether it happens
3547 // to contain only one byte characters.
3548 // ecx: first instance type AND second instance type.
3549 // edi: second instance type.
3550 __ test(ecx, Immediate(kOneByteDataHintMask));
3551 __ j(not_zero, &ascii_data);
3552 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
3553 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
3554 __ xor_(edi, ecx);
3555 STATIC_ASSERT(kOneByteStringTag != 0 && kOneByteDataHintTag != 0);
3556 __ and_(edi, kOneByteStringTag | kOneByteDataHintTag);
3557 __ cmp(edi, kOneByteStringTag | kOneByteDataHintTag);
3558 __ j(equal, &ascii_data);
3559 // Allocate a two byte cons string.
3560 __ AllocateTwoByteConsString(ecx, edi, no_reg, &call_runtime);
3561 __ jmp(&allocated);
3562
3563 // We cannot encounter sliced strings or cons strings here since:
3564 STATIC_ASSERT(SlicedString::kMinLength >= ConsString::kMinLength);
3565 // Handle creating a flat result from either external or sequential strings.
3566 // Locate the first characters' locations.
3567 // eax: first string
3568 // ebx: length of resulting flat string as a smi
3569 // edx: second string
3570 Label first_prepared, second_prepared;
3571 Label first_is_sequential, second_is_sequential;
3572 __ bind(&string_add_flat_result);
3573 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
3574 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
3575 // ecx: instance type of first string
3576 STATIC_ASSERT(kSeqStringTag == 0);
3577 __ test_b(ecx, kStringRepresentationMask);
3578 __ j(zero, &first_is_sequential, Label::kNear);
3579 // Rule out short external string and load string resource.
3580 STATIC_ASSERT(kShortExternalStringTag != 0);
3581 __ test_b(ecx, kShortExternalStringMask);
3582 __ j(not_zero, &call_runtime);
3583 __ mov(eax, FieldOperand(eax, ExternalString::kResourceDataOffset));
3584 STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize);
3585 __ jmp(&first_prepared, Label::kNear);
3586 __ bind(&first_is_sequential);
3587 __ add(eax, Immediate(SeqOneByteString::kHeaderSize - kHeapObjectTag));
3588 __ bind(&first_prepared);
3589
3590 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
3591 __ movzx_b(edi, FieldOperand(edi, Map::kInstanceTypeOffset));
3592 // Check whether both strings have same encoding.
3593 // edi: instance type of second string
3594 __ xor_(ecx, edi);
3595 __ test_b(ecx, kStringEncodingMask);
3596 __ j(not_zero, &call_runtime);
3597 STATIC_ASSERT(kSeqStringTag == 0);
3598 __ test_b(edi, kStringRepresentationMask);
3599 __ j(zero, &second_is_sequential, Label::kNear);
3600 // Rule out short external string and load string resource.
3601 STATIC_ASSERT(kShortExternalStringTag != 0);
3602 __ test_b(edi, kShortExternalStringMask);
3603 __ j(not_zero, &call_runtime);
3604 __ mov(edx, FieldOperand(edx, ExternalString::kResourceDataOffset));
3605 STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize);
3606 __ jmp(&second_prepared, Label::kNear);
3607 __ bind(&second_is_sequential);
3608 __ add(edx, Immediate(SeqOneByteString::kHeaderSize - kHeapObjectTag));
3609 __ bind(&second_prepared);
3610
3611 // Push the addresses of both strings' first characters onto the stack.
3612 __ push(edx);
3613 __ push(eax);
3614
3615 Label non_ascii_string_add_flat_result, call_runtime_drop_two;
3616 // edi: instance type of second string
3617 // First string and second string have the same encoding.
3618 STATIC_ASSERT(kTwoByteStringTag == 0);
3619 __ test_b(edi, kStringEncodingMask);
3620 __ j(zero, &non_ascii_string_add_flat_result);
3621
3622 // Both strings are ASCII strings.
3623 // ebx: length of resulting flat string as a smi
3624 __ SmiUntag(ebx);
3625 __ AllocateAsciiString(eax, ebx, ecx, edx, edi, &call_runtime_drop_two);
3626 // eax: result string
3627 __ mov(ecx, eax);
3628 // Locate first character of result.
3629 __ add(ecx, Immediate(SeqOneByteString::kHeaderSize - kHeapObjectTag));
3630 // Load first argument's length and first character location. Account for
3631 // values currently on the stack when fetching arguments from it.
3632 __ mov(edx, Operand(esp, 4 * kPointerSize));
3633 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
3634 __ SmiUntag(edi);
3635 __ pop(edx);
3636 // eax: result string
3637 // ecx: first character of result
3638 // edx: first char of first argument
3639 // edi: length of first argument
3640 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true);
3641 // Load second argument's length and first character location. Account for
3642 // values currently on the stack when fetching arguments from it.
3643 __ mov(edx, Operand(esp, 2 * kPointerSize));
3644 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
3645 __ SmiUntag(edi);
3646 __ pop(edx);
3647 // eax: result string
3648 // ecx: next character of result
3649 // edx: first char of second argument
3650 // edi: length of second argument
3651 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true);
3652 __ IncrementCounter(counters->string_add_native(), 1);
3653 __ ret(2 * kPointerSize);
3654
3655 // Handle creating a flat two byte result.
3656 // eax: first string - known to be two byte
3657 // ebx: length of resulting flat string as a smi
3658 // edx: second string
3659 __ bind(&non_ascii_string_add_flat_result);
3660 // Both strings are two byte strings.
3661 __ SmiUntag(ebx);
3662 __ AllocateTwoByteString(eax, ebx, ecx, edx, edi, &call_runtime_drop_two);
3663 // eax: result string
3664 __ mov(ecx, eax);
3665 // Locate first character of result.
3666 __ add(ecx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
3667 // Load second argument's length and first character location. Account for
3668 // values currently on the stack when fetching arguments from it.
3669 __ mov(edx, Operand(esp, 4 * kPointerSize));
3670 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
3671 __ SmiUntag(edi);
3672 __ pop(edx);
3673 // eax: result string
3674 // ecx: first character of result
3675 // edx: first char of first argument
3676 // edi: length of first argument
3677 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false);
3678 // Load second argument's length and first character location. Account for
3679 // values currently on the stack when fetching arguments from it.
3680 __ mov(edx, Operand(esp, 2 * kPointerSize));
3681 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
3682 __ SmiUntag(edi);
3683 __ pop(edx);
3684 // eax: result string
3685 // ecx: next character of result
3686 // edx: first char of second argument
3687 // edi: length of second argument
3688 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false);
3689 __ IncrementCounter(counters->string_add_native(), 1);
3690 __ ret(2 * kPointerSize);
3691
3692 // Recover stack pointer before jumping to runtime.
3693 __ bind(&call_runtime_drop_two);
3694 __ Drop(2);
3695 // Just jump to runtime to add the two strings.
3696 __ bind(&call_runtime);
3697 __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
3698
3699 if (call_builtin.is_linked()) {
3700 __ bind(&call_builtin);
3701 __ InvokeBuiltin(builtin_id, JUMP_FUNCTION);
3702 }
3703 }
3704
3705
3706 void StringAddStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
3707 __ push(eax);
3708 __ push(edx);
3709 }
3710
3711
3712 void StringAddStub::GenerateRegisterArgsPop(MacroAssembler* masm,
3713 Register temp) {
3714 __ pop(temp);
3715 __ pop(edx);
3716 __ pop(eax);
3717 __ push(temp);
3718 }
3719
3720
3721 void StringAddStub::GenerateConvertArgument(MacroAssembler* masm,
3722 int stack_offset,
3723 Register arg,
3724 Register scratch1,
3725 Register scratch2,
3726 Register scratch3,
3727 Label* slow) {
3728 // First check if the argument is already a string.
3729 Label not_string, done;
3730 __ JumpIfSmi(arg, &not_string);
3731 __ CmpObjectType(arg, FIRST_NONSTRING_TYPE, scratch1);
3732 __ j(below, &done);
3733
3734 // Check the number to string cache.
3735 __ bind(&not_string);
3736 // Puts the cached result into scratch1.
3737 __ LookupNumberStringCache(arg, scratch1, scratch2, scratch3, slow);
3738 __ mov(arg, scratch1);
3739 __ mov(Operand(esp, stack_offset), arg);
3740 __ bind(&done);
3741 }
3742
3743
3744 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm,
3745 Register dest,
3746 Register src,
3747 Register count,
3748 Register scratch,
3749 bool ascii) {
3750 Label loop;
3751 __ bind(&loop);
3752 // This loop just copies one character at a time, as it is only used for very
3753 // short strings.
3754 if (ascii) {
3755 __ mov_b(scratch, Operand(src, 0));
3756 __ mov_b(Operand(dest, 0), scratch);
3757 __ add(src, Immediate(1));
3758 __ add(dest, Immediate(1));
3759 } else {
3760 __ mov_w(scratch, Operand(src, 0));
3761 __ mov_w(Operand(dest, 0), scratch);
3762 __ add(src, Immediate(2));
3763 __ add(dest, Immediate(2));
3764 }
3765 __ sub(count, Immediate(1));
3766 __ j(not_zero, &loop);
3767 }
3768
3769
3770 void StringHelper::GenerateCopyCharactersREP(MacroAssembler* masm, 3380 void StringHelper::GenerateCopyCharactersREP(MacroAssembler* masm,
3771 Register dest, 3381 Register dest,
3772 Register src, 3382 Register src,
3773 Register count, 3383 Register count,
3774 Register scratch, 3384 Register scratch,
3775 bool ascii) { 3385 bool ascii) {
3776 // Copy characters using rep movs of doublewords. 3386 // Copy characters using rep movs of doublewords.
3777 // The destination is aligned on a 4 byte boundary because we are 3387 // The destination is aligned on a 4 byte boundary because we are
3778 // copying to the beginning of a newly allocated string. 3388 // copying to the beginning of a newly allocated string.
3779 ASSERT(dest.is(edi)); // rep movs destination 3389 ASSERT(dest.is(edi)); // rep movs destination
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
3820 __ mov_b(Operand(dest, 0), scratch); 3430 __ mov_b(Operand(dest, 0), scratch);
3821 __ add(src, Immediate(1)); 3431 __ add(src, Immediate(1));
3822 __ add(dest, Immediate(1)); 3432 __ add(dest, Immediate(1));
3823 __ sub(count, Immediate(1)); 3433 __ sub(count, Immediate(1));
3824 __ j(not_zero, &loop); 3434 __ j(not_zero, &loop);
3825 3435
3826 __ bind(&done); 3436 __ bind(&done);
3827 } 3437 }
3828 3438
3829 3439
3830 void StringHelper::GenerateTwoCharacterStringTableProbe(MacroAssembler* masm,
3831 Register c1,
3832 Register c2,
3833 Register scratch1,
3834 Register scratch2,
3835 Register scratch3,
3836 Label* not_probed,
3837 Label* not_found) {
3838 // Register scratch3 is the general scratch register in this function.
3839 Register scratch = scratch3;
3840
3841 // Make sure that both characters are not digits as such strings has a
3842 // different hash algorithm. Don't try to look for these in the string table.
3843 Label not_array_index;
3844 __ mov(scratch, c1);
3845 __ sub(scratch, Immediate(static_cast<int>('0')));
3846 __ cmp(scratch, Immediate(static_cast<int>('9' - '0')));
3847 __ j(above, &not_array_index, Label::kNear);
3848 __ mov(scratch, c2);
3849 __ sub(scratch, Immediate(static_cast<int>('0')));
3850 __ cmp(scratch, Immediate(static_cast<int>('9' - '0')));
3851 __ j(below_equal, not_probed);
3852
3853 __ bind(&not_array_index);
3854 // Calculate the two character string hash.
3855 Register hash = scratch1;
3856 GenerateHashInit(masm, hash, c1, scratch);
3857 GenerateHashAddCharacter(masm, hash, c2, scratch);
3858 GenerateHashGetHash(masm, hash, scratch);
3859
3860 // Collect the two characters in a register.
3861 Register chars = c1;
3862 __ shl(c2, kBitsPerByte);
3863 __ or_(chars, c2);
3864
3865 // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
3866 // hash: hash of two character string.
3867
3868 // Load the string table.
3869 Register string_table = c2;
3870 __ LoadRoot(string_table, Heap::kStringTableRootIndex);
3871
3872 // Calculate capacity mask from the string table capacity.
3873 Register mask = scratch2;
3874 __ mov(mask, FieldOperand(string_table, StringTable::kCapacityOffset));
3875 __ SmiUntag(mask);
3876 __ sub(mask, Immediate(1));
3877
3878 // Registers
3879 // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
3880 // hash: hash of two character string
3881 // string_table: string table
3882 // mask: capacity mask
3883 // scratch: -
3884
3885 // Perform a number of probes in the string table.
3886 static const int kProbes = 4;
3887 Label found_in_string_table;
3888 Label next_probe[kProbes], next_probe_pop_mask[kProbes];
3889 Register candidate = scratch; // Scratch register contains candidate.
3890 for (int i = 0; i < kProbes; i++) {
3891 // Calculate entry in string table.
3892 __ mov(scratch, hash);
3893 if (i > 0) {
3894 __ add(scratch, Immediate(StringTable::GetProbeOffset(i)));
3895 }
3896 __ and_(scratch, mask);
3897
3898 // Load the entry from the string table.
3899 STATIC_ASSERT(StringTable::kEntrySize == 1);
3900 __ mov(candidate,
3901 FieldOperand(string_table,
3902 scratch,
3903 times_pointer_size,
3904 StringTable::kElementsStartOffset));
3905
3906 // If entry is undefined no string with this hash can be found.
3907 Factory* factory = masm->isolate()->factory();
3908 __ cmp(candidate, factory->undefined_value());
3909 __ j(equal, not_found);
3910 __ cmp(candidate, factory->the_hole_value());
3911 __ j(equal, &next_probe[i]);
3912
3913 // If length is not 2 the string is not a candidate.
3914 __ cmp(FieldOperand(candidate, String::kLengthOffset),
3915 Immediate(Smi::FromInt(2)));
3916 __ j(not_equal, &next_probe[i]);
3917
3918 // As we are out of registers save the mask on the stack and use that
3919 // register as a temporary.
3920 __ push(mask);
3921 Register temp = mask;
3922
3923 // Check that the candidate is a non-external ASCII string.
3924 __ mov(temp, FieldOperand(candidate, HeapObject::kMapOffset));
3925 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
3926 __ JumpIfInstanceTypeIsNotSequentialAscii(
3927 temp, temp, &next_probe_pop_mask[i]);
3928
3929 // Check if the two characters match.
3930 __ mov(temp, FieldOperand(candidate, SeqOneByteString::kHeaderSize));
3931 __ and_(temp, 0x0000ffff);
3932 __ cmp(chars, temp);
3933 __ j(equal, &found_in_string_table);
3934 __ bind(&next_probe_pop_mask[i]);
3935 __ pop(mask);
3936 __ bind(&next_probe[i]);
3937 }
3938
3939 // No matching 2 character string found by probing.
3940 __ jmp(not_found);
3941
3942 // Scratch register contains result when we fall through to here.
3943 Register result = candidate;
3944 __ bind(&found_in_string_table);
3945 __ pop(mask); // Pop saved mask from the stack.
3946 if (!result.is(eax)) {
3947 __ mov(eax, result);
3948 }
3949 }
3950
3951
3952 void StringHelper::GenerateHashInit(MacroAssembler* masm, 3440 void StringHelper::GenerateHashInit(MacroAssembler* masm,
3953 Register hash, 3441 Register hash,
3954 Register character, 3442 Register character,
3955 Register scratch) { 3443 Register scratch) {
3956 // hash = (seed + character) + ((seed + character) << 10); 3444 // hash = (seed + character) + ((seed + character) << 10);
3957 if (Serializer::enabled()) { 3445 if (Serializer::enabled()) {
3958 __ LoadRoot(scratch, Heap::kHashSeedRootIndex); 3446 __ LoadRoot(scratch, Heap::kHashSeedRootIndex);
3959 __ SmiUntag(scratch); 3447 __ SmiUntag(scratch);
3960 __ add(scratch, character); 3448 __ add(scratch, character);
3961 __ mov(hash, scratch); 3449 __ mov(hash, scratch);
(...skipping 1949 matching lines...) Expand 10 before | Expand all | Expand 10 after
5911 __ bind(&fast_elements_case); 5399 __ bind(&fast_elements_case);
5912 GenerateCase(masm, FAST_ELEMENTS); 5400 GenerateCase(masm, FAST_ELEMENTS);
5913 } 5401 }
5914 5402
5915 5403
5916 #undef __ 5404 #undef __
5917 5405
5918 } } // namespace v8::internal 5406 } } // namespace v8::internal
5919 5407
5920 #endif // V8_TARGET_ARCH_IA32 5408 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/code-stubs-ia32.h ('k') | src/ia32/full-codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698