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

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

Issue 6960009: Version 3.3.5 (Closed) Base URL: https://v8.googlecode.com/svn/trunk
Patch Set: Created 9 years, 7 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/ic-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 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 3883 matching lines...) Expand 10 before | Expand all | Expand 10 after
3894 // non-zero value, which indicates not equal, so just return. 3894 // non-zero value, which indicates not equal, so just return.
3895 __ ret(0); 3895 __ ret(0);
3896 } 3896 }
3897 3897
3898 __ bind(&check_for_strings); 3898 __ bind(&check_for_strings);
3899 3899
3900 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, 3900 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx,
3901 &check_unequal_objects); 3901 &check_unequal_objects);
3902 3902
3903 // Inline comparison of ascii strings. 3903 // Inline comparison of ascii strings.
3904 StringCompareStub::GenerateCompareFlatAsciiStrings(masm, 3904 if (cc_ == equal) {
3905 StringCompareStub::GenerateFlatAsciiStringEquals(masm,
3905 edx, 3906 edx,
3906 eax, 3907 eax,
3907 ecx, 3908 ecx,
3908 ebx, 3909 ebx);
3909 edi); 3910 } else {
3911 StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
3912 edx,
3913 eax,
3914 ecx,
3915 ebx,
3916 edi);
3917 }
3910 #ifdef DEBUG 3918 #ifdef DEBUG
3911 __ Abort("Unexpected fall-through from string comparison"); 3919 __ Abort("Unexpected fall-through from string comparison");
3912 #endif 3920 #endif
3913 3921
3914 __ bind(&check_unequal_objects); 3922 __ bind(&check_unequal_objects);
3915 if (cc_ == equal && !strict_) { 3923 if (cc_ == equal && !strict_) {
3916 // Non-strict equality. Objects are unequal if 3924 // Non-strict equality. Objects are unequal if
3917 // they are both JSObjects and not undetectable, 3925 // they are both JSObjects and not undetectable,
3918 // and their pointers are different. 3926 // and their pointers are different.
3919 NearLabel not_both_objects; 3927 NearLabel not_both_objects;
(...skipping 1675 matching lines...) Expand 10 before | Expand all | Expand 10 after
5595 __ bind(&return_eax); 5603 __ bind(&return_eax);
5596 __ IncrementCounter(counters->sub_string_native(), 1); 5604 __ IncrementCounter(counters->sub_string_native(), 1);
5597 __ ret(3 * kPointerSize); 5605 __ ret(3 * kPointerSize);
5598 5606
5599 // Just jump to runtime to create the sub string. 5607 // Just jump to runtime to create the sub string.
5600 __ bind(&runtime); 5608 __ bind(&runtime);
5601 __ TailCallRuntime(Runtime::kSubString, 3, 1); 5609 __ TailCallRuntime(Runtime::kSubString, 3, 1);
5602 } 5610 }
5603 5611
5604 5612
5613 void StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm,
5614 Register left,
5615 Register right,
5616 Register scratch1,
5617 Register scratch2) {
5618 Register length = scratch1;
5619
5620 // Compare lengths.
5621 NearLabel strings_not_equal, check_zero_length;
5622 __ mov(length, FieldOperand(left, String::kLengthOffset));
5623 __ cmp(length, FieldOperand(right, String::kLengthOffset));
5624 __ j(equal, &check_zero_length);
5625 __ bind(&strings_not_equal);
5626 __ Set(eax, Immediate(Smi::FromInt(NOT_EQUAL)));
5627 __ ret(0);
5628
5629 // Check if the length is zero.
5630 NearLabel compare_chars;
5631 __ bind(&check_zero_length);
5632 STATIC_ASSERT(kSmiTag == 0);
5633 __ test(length, Operand(length));
5634 __ j(not_zero, &compare_chars);
5635 __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
5636 __ ret(0);
5637
5638 // Compare characters.
5639 __ bind(&compare_chars);
5640 GenerateAsciiCharsCompareLoop(masm, left, right, length, scratch2,
5641 &strings_not_equal);
5642
5643 // Characters are equal.
5644 __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
5645 __ ret(0);
5646 }
5647
5648
5605 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, 5649 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
5606 Register left, 5650 Register left,
5607 Register right, 5651 Register right,
5608 Register scratch1, 5652 Register scratch1,
5609 Register scratch2, 5653 Register scratch2,
5610 Register scratch3) { 5654 Register scratch3) {
5611 Label result_not_equal;
5612 Label result_greater;
5613 Label compare_lengths;
5614
5615 Counters* counters = masm->isolate()->counters(); 5655 Counters* counters = masm->isolate()->counters();
5616 __ IncrementCounter(counters->string_compare_native(), 1); 5656 __ IncrementCounter(counters->string_compare_native(), 1);
5617 5657
5618 // Find minimum length. 5658 // Find minimum length.
5619 NearLabel left_shorter; 5659 NearLabel left_shorter;
5620 __ mov(scratch1, FieldOperand(left, String::kLengthOffset)); 5660 __ mov(scratch1, FieldOperand(left, String::kLengthOffset));
5621 __ mov(scratch3, scratch1); 5661 __ mov(scratch3, scratch1);
5622 __ sub(scratch3, FieldOperand(right, String::kLengthOffset)); 5662 __ sub(scratch3, FieldOperand(right, String::kLengthOffset));
5623 5663
5624 Register length_delta = scratch3; 5664 Register length_delta = scratch3;
5625 5665
5626 __ j(less_equal, &left_shorter); 5666 __ j(less_equal, &left_shorter);
5627 // Right string is shorter. Change scratch1 to be length of right string. 5667 // Right string is shorter. Change scratch1 to be length of right string.
5628 __ sub(scratch1, Operand(length_delta)); 5668 __ sub(scratch1, Operand(length_delta));
5629 __ bind(&left_shorter); 5669 __ bind(&left_shorter);
5630 5670
5631 Register min_length = scratch1; 5671 Register min_length = scratch1;
5632 5672
5633 // If either length is zero, just compare lengths. 5673 // If either length is zero, just compare lengths.
5674 NearLabel compare_lengths;
5634 __ test(min_length, Operand(min_length)); 5675 __ test(min_length, Operand(min_length));
5635 __ j(zero, &compare_lengths); 5676 __ j(zero, &compare_lengths);
5636 5677
5637 // Change index to run from -min_length to -1 by adding min_length 5678 // Compare characters.
5638 // to string start. This means that loop ends when index reaches zero, 5679 NearLabel result_not_equal;
5639 // which doesn't need an additional compare. 5680 GenerateAsciiCharsCompareLoop(masm, left, right, min_length, scratch2,
5640 __ SmiUntag(min_length); 5681 &result_not_equal);
5641 __ lea(left,
5642 FieldOperand(left,
5643 min_length, times_1,
5644 SeqAsciiString::kHeaderSize));
5645 __ lea(right,
5646 FieldOperand(right,
5647 min_length, times_1,
5648 SeqAsciiString::kHeaderSize));
5649 __ neg(min_length);
5650
5651 Register index = min_length; // index = -min_length;
5652
5653 {
5654 // Compare loop.
5655 NearLabel loop;
5656 __ bind(&loop);
5657 // Compare characters.
5658 __ mov_b(scratch2, Operand(left, index, times_1, 0));
5659 __ cmpb(scratch2, Operand(right, index, times_1, 0));
5660 __ j(not_equal, &result_not_equal);
5661 __ add(Operand(index), Immediate(1));
5662 __ j(not_zero, &loop);
5663 }
5664 5682
5665 // Compare lengths - strings up to min-length are equal. 5683 // Compare lengths - strings up to min-length are equal.
5666 __ bind(&compare_lengths); 5684 __ bind(&compare_lengths);
5667 __ test(length_delta, Operand(length_delta)); 5685 __ test(length_delta, Operand(length_delta));
5668 __ j(not_zero, &result_not_equal); 5686 __ j(not_zero, &result_not_equal);
5669 5687
5670 // Result is EQUAL. 5688 // Result is EQUAL.
5671 STATIC_ASSERT(EQUAL == 0); 5689 STATIC_ASSERT(EQUAL == 0);
5672 STATIC_ASSERT(kSmiTag == 0); 5690 STATIC_ASSERT(kSmiTag == 0);
5673 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); 5691 __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
5674 __ ret(0); 5692 __ ret(0);
5675 5693
5694 NearLabel result_greater;
5676 __ bind(&result_not_equal); 5695 __ bind(&result_not_equal);
5677 __ j(greater, &result_greater); 5696 __ j(greater, &result_greater);
5678 5697
5679 // Result is LESS. 5698 // Result is LESS.
5680 __ Set(eax, Immediate(Smi::FromInt(LESS))); 5699 __ Set(eax, Immediate(Smi::FromInt(LESS)));
5681 __ ret(0); 5700 __ ret(0);
5682 5701
5683 // Result is GREATER. 5702 // Result is GREATER.
5684 __ bind(&result_greater); 5703 __ bind(&result_greater);
5685 __ Set(eax, Immediate(Smi::FromInt(GREATER))); 5704 __ Set(eax, Immediate(Smi::FromInt(GREATER)));
5686 __ ret(0); 5705 __ ret(0);
5687 } 5706 }
5688 5707
5689 5708
5709 void StringCompareStub::GenerateAsciiCharsCompareLoop(
5710 MacroAssembler* masm,
5711 Register left,
5712 Register right,
5713 Register length,
5714 Register scratch,
5715 NearLabel* chars_not_equal) {
5716 // Change index to run from -length to -1 by adding length to string
5717 // start. This means that loop ends when index reaches zero, which
5718 // doesn't need an additional compare.
5719 __ SmiUntag(length);
5720 __ lea(left,
5721 FieldOperand(left, length, times_1, SeqAsciiString::kHeaderSize));
5722 __ lea(right,
5723 FieldOperand(right, length, times_1, SeqAsciiString::kHeaderSize));
5724 __ neg(length);
5725 Register index = length; // index = -length;
5726
5727 // Compare loop.
5728 NearLabel loop;
5729 __ bind(&loop);
5730 __ mov_b(scratch, Operand(left, index, times_1, 0));
5731 __ cmpb(scratch, Operand(right, index, times_1, 0));
5732 __ j(not_equal, chars_not_equal);
5733 __ add(Operand(index), Immediate(1));
5734 __ j(not_zero, &loop);
5735 }
5736
5737
5690 void StringCompareStub::Generate(MacroAssembler* masm) { 5738 void StringCompareStub::Generate(MacroAssembler* masm) {
5691 Label runtime; 5739 Label runtime;
5692 5740
5693 // Stack frame on entry. 5741 // Stack frame on entry.
5694 // esp[0]: return address 5742 // esp[0]: return address
5695 // esp[4]: right string 5743 // esp[4]: right string
5696 // esp[8]: left string 5744 // esp[8]: left string
5697 5745
5698 __ mov(edx, Operand(esp, 2 * kPointerSize)); // left 5746 __ mov(edx, Operand(esp, 2 * kPointerSize)); // left
5699 __ mov(eax, Operand(esp, 1 * kPointerSize)); // right 5747 __ mov(eax, Operand(esp, 1 * kPointerSize)); // right
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
5799 5847
5800 CompareStub stub(GetCondition(), strict(), NO_COMPARE_FLAGS); 5848 CompareStub stub(GetCondition(), strict(), NO_COMPARE_FLAGS);
5801 __ bind(&generic_stub); 5849 __ bind(&generic_stub);
5802 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); 5850 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET);
5803 5851
5804 __ bind(&miss); 5852 __ bind(&miss);
5805 GenerateMiss(masm); 5853 GenerateMiss(masm);
5806 } 5854 }
5807 5855
5808 5856
5857 void ICCompareStub::GenerateStrings(MacroAssembler* masm) {
5858 ASSERT(state_ == CompareIC::STRINGS);
5859 ASSERT(GetCondition() == equal);
5860 Label miss;
5861
5862 // Registers containing left and right operands respectively.
5863 Register left = edx;
5864 Register right = eax;
5865 Register tmp1 = ecx;
5866 Register tmp2 = ebx;
5867 Register tmp3 = edi;
5868
5869 // Check that both operands are heap objects.
5870 __ mov(tmp1, Operand(left));
5871 STATIC_ASSERT(kSmiTag == 0);
5872 __ and_(tmp1, Operand(right));
5873 __ test(tmp1, Immediate(kSmiTagMask));
5874 __ j(zero, &miss);
5875
5876 // Check that both operands are strings. This leaves the instance
5877 // types loaded in tmp1 and tmp2.
5878 __ mov(tmp1, FieldOperand(left, HeapObject::kMapOffset));
5879 __ mov(tmp2, FieldOperand(right, HeapObject::kMapOffset));
5880 __ movzx_b(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
5881 __ movzx_b(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset));
5882 __ mov(tmp3, tmp1);
5883 STATIC_ASSERT(kNotStringTag != 0);
5884 __ or_(tmp3, Operand(tmp2));
5885 __ test(tmp3, Immediate(kIsNotStringMask));
5886 __ j(not_zero, &miss);
5887
5888 // Fast check for identical strings.
5889 NearLabel not_same;
5890 __ cmp(left, Operand(right));
5891 __ j(not_equal, &not_same);
5892 STATIC_ASSERT(EQUAL == 0);
5893 STATIC_ASSERT(kSmiTag == 0);
5894 __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
5895 __ ret(0);
5896
5897 // Handle not identical strings.
5898 __ bind(&not_same);
5899
5900 // Check that both strings are symbols. If they are, we're done
5901 // because we already know they are not identical.
5902 NearLabel do_compare;
5903 STATIC_ASSERT(kSymbolTag != 0);
5904 __ and_(tmp1, Operand(tmp2));
5905 __ test(tmp1, Immediate(kIsSymbolMask));
5906 __ j(zero, &do_compare);
5907 // Make sure eax is non-zero. At this point input operands are
5908 // guaranteed to be non-zero.
5909 ASSERT(right.is(eax));
5910 __ ret(0);
5911
5912 // Check that both strings are sequential ASCII.
5913 Label runtime;
5914 __ bind(&do_compare);
5915 __ JumpIfNotBothSequentialAsciiStrings(left, right, tmp1, tmp2, &runtime);
5916
5917 // Compare flat ASCII strings. Returns when done.
5918 StringCompareStub::GenerateFlatAsciiStringEquals(
5919 masm, left, right, tmp1, tmp2);
5920
5921 // Handle more complex cases in runtime.
5922 __ bind(&runtime);
5923 __ pop(tmp1); // Return address.
5924 __ push(left);
5925 __ push(right);
5926 __ push(tmp1);
5927 __ TailCallRuntime(Runtime::kStringEquals, 2, 1);
5928
5929 __ bind(&miss);
5930 GenerateMiss(masm);
5931 }
5932
5933
5809 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { 5934 void ICCompareStub::GenerateObjects(MacroAssembler* masm) {
5810 ASSERT(state_ == CompareIC::OBJECTS); 5935 ASSERT(state_ == CompareIC::OBJECTS);
5811 NearLabel miss; 5936 NearLabel miss;
5812 __ mov(ecx, Operand(edx)); 5937 __ mov(ecx, Operand(edx));
5813 __ and_(ecx, Operand(eax)); 5938 __ and_(ecx, Operand(eax));
5814 __ test(ecx, Immediate(kSmiTagMask)); 5939 __ test(ecx, Immediate(kSmiTagMask));
5815 __ j(zero, &miss, not_taken); 5940 __ j(zero, &miss, not_taken);
5816 5941
5817 __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx); 5942 __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx);
5818 __ j(not_equal, &miss, not_taken); 5943 __ j(not_equal, &miss, not_taken);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
5852 __ pop(ecx); 5977 __ pop(ecx);
5853 __ pop(eax); 5978 __ pop(eax);
5854 __ pop(edx); 5979 __ pop(edx);
5855 __ push(ecx); 5980 __ push(ecx);
5856 5981
5857 // Do a tail call to the rewritten stub. 5982 // Do a tail call to the rewritten stub.
5858 __ jmp(Operand(edi)); 5983 __ jmp(Operand(edi));
5859 } 5984 }
5860 5985
5861 5986
5987 // Helper function used to check that the dictionary doesn't contain
5988 // the property. This function may return false negatives, so miss_label
5989 // must always call a backup property check that is complete.
5990 // This function is safe to call if the receiver has fast properties.
5991 // Name must be a symbol and receiver must be a heap object.
5992 void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
5993 Label* miss,
5994 Label* done,
5995 Register properties,
5996 String* name,
5997 Register r0) {
5998 ASSERT(name->IsSymbol());
5999
6000 // If names of slots in range from 1 to kProbes - 1 for the hash value are
6001 // not equal to the name and kProbes-th slot is not used (its name is the
6002 // undefined value), it guarantees the hash table doesn't contain the
6003 // property. It's true even if some slots represent deleted properties
6004 // (their names are the null value).
6005 for (int i = 0; i < kInlinedProbes; i++) {
6006 // Compute the masked index: (hash + i + i * i) & mask.
6007 Register index = r0;
6008 // Capacity is smi 2^n.
6009 __ mov(index, FieldOperand(properties, kCapacityOffset));
6010 __ dec(index);
6011 __ and_(Operand(index),
6012 Immediate(Smi::FromInt(name->Hash() +
6013 StringDictionary::GetProbeOffset(i))));
6014
6015 // Scale the index by multiplying by the entry size.
6016 ASSERT(StringDictionary::kEntrySize == 3);
6017 __ lea(index, Operand(index, index, times_2, 0)); // index *= 3.
6018 Register entity_name = r0;
6019 // Having undefined at this place means the name is not contained.
6020 ASSERT_EQ(kSmiTagSize, 1);
6021 __ mov(entity_name, Operand(properties, index, times_half_pointer_size,
6022 kElementsStartOffset - kHeapObjectTag));
6023 __ cmp(entity_name, masm->isolate()->factory()->undefined_value());
6024 __ j(equal, done, taken);
6025
6026 // Stop if found the property.
6027 __ cmp(entity_name, Handle<String>(name));
6028 __ j(equal, miss, not_taken);
6029
6030 // Check if the entry name is not a symbol.
6031 __ mov(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset));
6032 __ test_b(FieldOperand(entity_name, Map::kInstanceTypeOffset),
6033 kIsSymbolMask);
6034 __ j(zero, miss, not_taken);
6035 }
6036
6037 StringDictionaryLookupStub stub(properties,
6038 r0,
6039 r0,
6040 StringDictionaryLookupStub::NEGATIVE_LOOKUP);
6041 __ push(Immediate(Handle<Object>(name)));
6042 __ push(Immediate(name->Hash()));
6043 __ CallStub(&stub);
6044 __ test(r0, Operand(r0));
6045 __ j(not_zero, miss);
6046 __ jmp(done);
6047 }
6048
6049
6050 // Probe the string dictionary in the |elements| register. Jump to the
6051 // |done| label if a property with the given name is found leaving the
6052 // index into the dictionary in |r0|. Jump to the |miss| label
6053 // otherwise.
6054 void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
6055 Label* miss,
6056 Label* done,
6057 Register elements,
6058 Register name,
6059 Register r0,
6060 Register r1) {
6061 // Assert that name contains a string.
6062 if (FLAG_debug_code) __ AbortIfNotString(name);
6063
6064 __ mov(r1, FieldOperand(elements, kCapacityOffset));
6065 __ shr(r1, kSmiTagSize); // convert smi to int
6066 __ dec(r1);
6067
6068 // Generate an unrolled loop that performs a few probes before
6069 // giving up. Measurements done on Gmail indicate that 2 probes
6070 // cover ~93% of loads from dictionaries.
6071 for (int i = 0; i < kInlinedProbes; i++) {
6072 // Compute the masked index: (hash + i + i * i) & mask.
6073 __ mov(r0, FieldOperand(name, String::kHashFieldOffset));
6074 __ shr(r0, String::kHashShift);
6075 if (i > 0) {
6076 __ add(Operand(r0), Immediate(StringDictionary::GetProbeOffset(i)));
6077 }
6078 __ and_(r0, Operand(r1));
6079
6080 // Scale the index by multiplying by the entry size.
6081 ASSERT(StringDictionary::kEntrySize == 3);
6082 __ lea(r0, Operand(r0, r0, times_2, 0)); // r0 = r0 * 3
6083
6084 // Check if the key is identical to the name.
6085 __ cmp(name, Operand(elements,
6086 r0,
6087 times_4,
6088 kElementsStartOffset - kHeapObjectTag));
6089 __ j(equal, done, taken);
6090 }
6091
6092 StringDictionaryLookupStub stub(elements,
6093 r1,
6094 r0,
6095 POSITIVE_LOOKUP);
6096 __ push(name);
6097 __ mov(r0, FieldOperand(name, String::kHashFieldOffset));
6098 __ shr(r0, String::kHashShift);
6099 __ push(r0);
6100 __ CallStub(&stub);
6101
6102 __ test(r1, Operand(r1));
6103 __ j(zero, miss);
6104 __ jmp(done);
6105 }
6106
6107
6108 void StringDictionaryLookupStub::Generate(MacroAssembler* masm) {
6109 // Stack frame on entry:
6110 // esp[0 * kPointerSize]: return address.
6111 // esp[1 * kPointerSize]: key's hash.
6112 // esp[2 * kPointerSize]: key.
6113 // Registers:
6114 // dictionary_: StringDictionary to probe.
6115 // result_: used as scratch.
6116 // index_: will hold an index of entry if lookup is successful.
6117 // might alias with result_.
6118 // Returns:
6119 // result_ is zero if lookup failed, non zero otherwise.
6120
6121 Label in_dictionary, maybe_in_dictionary, not_in_dictionary;
6122
6123 Register scratch = result_;
6124
6125 __ mov(scratch, FieldOperand(dictionary_, kCapacityOffset));
6126 __ dec(scratch);
6127 __ SmiUntag(scratch);
6128 __ push(scratch);
6129
6130 // If names of slots in range from 1 to kProbes - 1 for the hash value are
6131 // not equal to the name and kProbes-th slot is not used (its name is the
6132 // undefined value), it guarantees the hash table doesn't contain the
6133 // property. It's true even if some slots represent deleted properties
6134 // (their names are the null value).
6135 for (int i = kInlinedProbes; i < kTotalProbes; i++) {
6136 // Compute the masked index: (hash + i + i * i) & mask.
6137 __ mov(scratch, Operand(esp, 2 * kPointerSize));
6138 if (i > 0) {
6139 __ add(Operand(scratch),
6140 Immediate(StringDictionary::GetProbeOffset(i)));
6141 }
6142 __ and_(scratch, Operand(esp, 0));
6143
6144 // Scale the index by multiplying by the entry size.
6145 ASSERT(StringDictionary::kEntrySize == 3);
6146 __ lea(index_, Operand(scratch, scratch, times_2, 0)); // index *= 3.
6147
6148 // Having undefined at this place means the name is not contained.
6149 ASSERT_EQ(kSmiTagSize, 1);
6150 __ mov(scratch, Operand(dictionary_,
6151 index_,
6152 times_pointer_size,
6153 kElementsStartOffset - kHeapObjectTag));
6154 __ cmp(scratch, masm->isolate()->factory()->undefined_value());
6155 __ j(equal, &not_in_dictionary);
6156
6157 // Stop if found the property.
6158 __ cmp(scratch, Operand(esp, 3 * kPointerSize));
6159 __ j(equal, &in_dictionary);
6160
6161 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) {
6162 // If we hit a non symbol key during negative lookup
6163 // we have to bailout as this key might be equal to the
6164 // key we are looking for.
6165
6166 // Check if the entry name is not a symbol.
6167 __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
6168 __ test_b(FieldOperand(scratch, Map::kInstanceTypeOffset),
6169 kIsSymbolMask);
6170 __ j(zero, &maybe_in_dictionary);
6171 }
6172 }
6173
6174 __ bind(&maybe_in_dictionary);
6175 // If we are doing negative lookup then probing failure should be
6176 // treated as a lookup success. For positive lookup probing failure
6177 // should be treated as lookup failure.
6178 if (mode_ == POSITIVE_LOOKUP) {
6179 __ mov(result_, Immediate(0));
6180 __ Drop(1);
6181 __ ret(2 * kPointerSize);
6182 }
6183
6184 __ bind(&in_dictionary);
6185 __ mov(result_, Immediate(1));
6186 __ Drop(1);
6187 __ ret(2 * kPointerSize);
6188
6189 __ bind(&not_in_dictionary);
6190 __ mov(result_, Immediate(0));
6191 __ Drop(1);
6192 __ ret(2 * kPointerSize);
6193 }
6194
6195
5862 #undef __ 6196 #undef __
5863 6197
5864 } } // namespace v8::internal 6198 } } // namespace v8::internal
5865 6199
5866 #endif // V8_TARGET_ARCH_IA32 6200 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/code-stubs-ia32.h ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698