OLD | NEW |
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 3263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3274 | 3274 |
3275 void ArrayLengthStub::Generate(MacroAssembler* masm) { | 3275 void ArrayLengthStub::Generate(MacroAssembler* masm) { |
3276 // ----------- S t a t e ------------- | 3276 // ----------- S t a t e ------------- |
3277 // -- ecx : name | 3277 // -- ecx : name |
3278 // -- edx : receiver | 3278 // -- edx : receiver |
3279 // -- esp[0] : return address | 3279 // -- esp[0] : return address |
3280 // ----------------------------------- | 3280 // ----------------------------------- |
3281 Label miss; | 3281 Label miss; |
3282 | 3282 |
3283 if (kind() == Code::KEYED_LOAD_IC) { | 3283 if (kind() == Code::KEYED_LOAD_IC) { |
3284 __ cmp(ecx, Immediate(masm->isolate()->factory()->length_symbol())); | 3284 __ cmp(ecx, Immediate(masm->isolate()->factory()->length_string())); |
3285 __ j(not_equal, &miss); | 3285 __ j(not_equal, &miss); |
3286 } | 3286 } |
3287 | 3287 |
3288 StubCompiler::GenerateLoadArrayLength(masm, edx, eax, &miss); | 3288 StubCompiler::GenerateLoadArrayLength(masm, edx, eax, &miss); |
3289 __ bind(&miss); | 3289 __ bind(&miss); |
3290 StubCompiler::GenerateLoadMiss(masm, kind()); | 3290 StubCompiler::GenerateLoadMiss(masm, kind()); |
3291 } | 3291 } |
3292 | 3292 |
3293 | 3293 |
3294 void FunctionPrototypeStub::Generate(MacroAssembler* masm) { | 3294 void FunctionPrototypeStub::Generate(MacroAssembler* masm) { |
3295 // ----------- S t a t e ------------- | 3295 // ----------- S t a t e ------------- |
3296 // -- ecx : name | 3296 // -- ecx : name |
3297 // -- edx : receiver | 3297 // -- edx : receiver |
3298 // -- esp[0] : return address | 3298 // -- esp[0] : return address |
3299 // ----------------------------------- | 3299 // ----------------------------------- |
3300 Label miss; | 3300 Label miss; |
3301 | 3301 |
3302 if (kind() == Code::KEYED_LOAD_IC) { | 3302 if (kind() == Code::KEYED_LOAD_IC) { |
3303 __ cmp(ecx, Immediate(masm->isolate()->factory()->prototype_symbol())); | 3303 __ cmp(ecx, Immediate(masm->isolate()->factory()->prototype_string())); |
3304 __ j(not_equal, &miss); | 3304 __ j(not_equal, &miss); |
3305 } | 3305 } |
3306 | 3306 |
3307 StubCompiler::GenerateLoadFunctionPrototype(masm, edx, eax, ebx, &miss); | 3307 StubCompiler::GenerateLoadFunctionPrototype(masm, edx, eax, ebx, &miss); |
3308 __ bind(&miss); | 3308 __ bind(&miss); |
3309 StubCompiler::GenerateLoadMiss(masm, kind()); | 3309 StubCompiler::GenerateLoadMiss(masm, kind()); |
3310 } | 3310 } |
3311 | 3311 |
3312 | 3312 |
3313 void StringLengthStub::Generate(MacroAssembler* masm) { | 3313 void StringLengthStub::Generate(MacroAssembler* masm) { |
3314 // ----------- S t a t e ------------- | 3314 // ----------- S t a t e ------------- |
3315 // -- ecx : name | 3315 // -- ecx : name |
3316 // -- edx : receiver | 3316 // -- edx : receiver |
3317 // -- esp[0] : return address | 3317 // -- esp[0] : return address |
3318 // ----------------------------------- | 3318 // ----------------------------------- |
3319 Label miss; | 3319 Label miss; |
3320 | 3320 |
3321 if (kind() == Code::KEYED_LOAD_IC) { | 3321 if (kind() == Code::KEYED_LOAD_IC) { |
3322 __ cmp(ecx, Immediate(masm->isolate()->factory()->length_symbol())); | 3322 __ cmp(ecx, Immediate(masm->isolate()->factory()->length_string())); |
3323 __ j(not_equal, &miss); | 3323 __ j(not_equal, &miss); |
3324 } | 3324 } |
3325 | 3325 |
3326 StubCompiler::GenerateLoadStringLength(masm, edx, eax, ebx, &miss, | 3326 StubCompiler::GenerateLoadStringLength(masm, edx, eax, ebx, &miss, |
3327 support_wrapper_); | 3327 support_wrapper_); |
3328 __ bind(&miss); | 3328 __ bind(&miss); |
3329 StubCompiler::GenerateLoadMiss(masm, kind()); | 3329 StubCompiler::GenerateLoadMiss(masm, kind()); |
3330 } | 3330 } |
3331 | 3331 |
3332 | 3332 |
(...skipping 10 matching lines...) Expand all Loading... |
3343 // elements of FixedArray type). Value must be a number, but only smis are | 3343 // elements of FixedArray type). Value must be a number, but only smis are |
3344 // accepted as the most common case. | 3344 // accepted as the most common case. |
3345 | 3345 |
3346 Label miss; | 3346 Label miss; |
3347 | 3347 |
3348 Register receiver = edx; | 3348 Register receiver = edx; |
3349 Register value = eax; | 3349 Register value = eax; |
3350 Register scratch = ebx; | 3350 Register scratch = ebx; |
3351 | 3351 |
3352 if (kind() == Code::KEYED_LOAD_IC) { | 3352 if (kind() == Code::KEYED_LOAD_IC) { |
3353 __ cmp(ecx, Immediate(masm->isolate()->factory()->length_symbol())); | 3353 __ cmp(ecx, Immediate(masm->isolate()->factory()->length_string())); |
3354 __ j(not_equal, &miss); | 3354 __ j(not_equal, &miss); |
3355 } | 3355 } |
3356 | 3356 |
3357 // Check that the receiver isn't a smi. | 3357 // Check that the receiver isn't a smi. |
3358 __ JumpIfSmi(receiver, &miss); | 3358 __ JumpIfSmi(receiver, &miss); |
3359 | 3359 |
3360 // Check that the object is a JS array. | 3360 // Check that the object is a JS array. |
3361 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); | 3361 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); |
3362 __ j(not_equal, &miss); | 3362 __ j(not_equal, &miss); |
3363 | 3363 |
(...skipping 1069 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4433 Label* fail) { | 4433 Label* fail) { |
4434 Label ok; | 4434 Label ok; |
4435 if (expected == CompareIC::SMI) { | 4435 if (expected == CompareIC::SMI) { |
4436 __ JumpIfNotSmi(input, fail); | 4436 __ JumpIfNotSmi(input, fail); |
4437 } else if (expected == CompareIC::HEAP_NUMBER) { | 4437 } else if (expected == CompareIC::HEAP_NUMBER) { |
4438 __ JumpIfSmi(input, &ok); | 4438 __ JumpIfSmi(input, &ok); |
4439 __ cmp(FieldOperand(input, HeapObject::kMapOffset), | 4439 __ cmp(FieldOperand(input, HeapObject::kMapOffset), |
4440 Immediate(masm->isolate()->factory()->heap_number_map())); | 4440 Immediate(masm->isolate()->factory()->heap_number_map())); |
4441 __ j(not_equal, fail); | 4441 __ j(not_equal, fail); |
4442 } | 4442 } |
4443 // We could be strict about symbol/string here, but as long as | 4443 // We could be strict about internalized/non-internalized here, but as long as |
4444 // hydrogen doesn't care, the stub doesn't have to care either. | 4444 // hydrogen doesn't care, the stub doesn't have to care either. |
4445 __ bind(&ok); | 4445 __ bind(&ok); |
4446 } | 4446 } |
4447 | 4447 |
4448 | 4448 |
4449 static void BranchIfNonSymbol(MacroAssembler* masm, | 4449 static void BranchIfNotInternalizedString(MacroAssembler* masm, |
4450 Label* label, | 4450 Label* label, |
4451 Register object, | 4451 Register object, |
4452 Register scratch) { | 4452 Register scratch) { |
4453 __ JumpIfSmi(object, label); | 4453 __ JumpIfSmi(object, label); |
4454 __ mov(scratch, FieldOperand(object, HeapObject::kMapOffset)); | 4454 __ mov(scratch, FieldOperand(object, HeapObject::kMapOffset)); |
4455 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); | 4455 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); |
4456 __ and_(scratch, kIsSymbolMask | kIsNotStringMask); | 4456 __ and_(scratch, kIsInternalizedMask | kIsNotStringMask); |
4457 __ cmp(scratch, kSymbolTag | kStringTag); | 4457 __ cmp(scratch, kInternalizedTag | kStringTag); |
4458 __ j(not_equal, label); | 4458 __ j(not_equal, label); |
4459 } | 4459 } |
4460 | 4460 |
4461 | 4461 |
4462 void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { | 4462 void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { |
4463 Label check_unequal_objects; | 4463 Label check_unequal_objects; |
4464 Condition cc = GetCondition(); | 4464 Condition cc = GetCondition(); |
4465 | 4465 |
4466 Label miss; | 4466 Label miss; |
4467 CheckInputType(masm, edx, left_, &miss); | 4467 CheckInputType(masm, edx, left_, &miss); |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4675 if (cc == less || cc == less_equal) { | 4675 if (cc == less || cc == less_equal) { |
4676 __ mov(eax, Immediate(Smi::FromInt(1))); | 4676 __ mov(eax, Immediate(Smi::FromInt(1))); |
4677 } else { | 4677 } else { |
4678 __ mov(eax, Immediate(Smi::FromInt(-1))); | 4678 __ mov(eax, Immediate(Smi::FromInt(-1))); |
4679 } | 4679 } |
4680 __ ret(0); | 4680 __ ret(0); |
4681 | 4681 |
4682 // The number comparison code did not provide a valid result. | 4682 // The number comparison code did not provide a valid result. |
4683 __ bind(&non_number_comparison); | 4683 __ bind(&non_number_comparison); |
4684 | 4684 |
4685 // Fast negative check for symbol-to-symbol equality. | 4685 // Fast negative check for internalized-to-internalized equality. |
4686 Label check_for_strings; | 4686 Label check_for_strings; |
4687 if (cc == equal) { | 4687 if (cc == equal) { |
4688 BranchIfNonSymbol(masm, &check_for_strings, eax, ecx); | 4688 BranchIfNotInternalizedString(masm, &check_for_strings, eax, ecx); |
4689 BranchIfNonSymbol(masm, &check_for_strings, edx, ecx); | 4689 BranchIfNotInternalizedString(masm, &check_for_strings, edx, ecx); |
4690 | 4690 |
4691 // We've already checked for object identity, so if both operands | 4691 // We've already checked for object identity, so if both operands |
4692 // are symbols they aren't equal. Register eax already holds a | 4692 // are internalized they aren't equal. Register eax already holds a |
4693 // non-zero value, which indicates not equal, so just return. | 4693 // non-zero value, which indicates not equal, so just return. |
4694 __ ret(0); | 4694 __ ret(0); |
4695 } | 4695 } |
4696 | 4696 |
4697 __ bind(&check_for_strings); | 4697 __ bind(&check_for_strings); |
4698 | 4698 |
4699 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, | 4699 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, |
4700 &check_unequal_objects); | 4700 &check_unequal_objects); |
4701 | 4701 |
4702 // Inline comparison of ASCII strings. | 4702 // Inline comparison of ASCII strings. |
(...skipping 1060 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5763 // ebx: length of first string as a smi | 5763 // ebx: length of first string as a smi |
5764 // ecx: length of second string as a smi | 5764 // ecx: length of second string as a smi |
5765 // edx: second string | 5765 // edx: second string |
5766 // Look at the length of the result of adding the two strings. | 5766 // Look at the length of the result of adding the two strings. |
5767 Label string_add_flat_result, longer_than_two; | 5767 Label string_add_flat_result, longer_than_two; |
5768 __ bind(&both_not_zero_length); | 5768 __ bind(&both_not_zero_length); |
5769 __ add(ebx, ecx); | 5769 __ add(ebx, ecx); |
5770 STATIC_ASSERT(Smi::kMaxValue == String::kMaxLength); | 5770 STATIC_ASSERT(Smi::kMaxValue == String::kMaxLength); |
5771 // Handle exceptionally long strings in the runtime system. | 5771 // Handle exceptionally long strings in the runtime system. |
5772 __ j(overflow, &call_runtime); | 5772 __ j(overflow, &call_runtime); |
5773 // Use the symbol table when adding two one character strings, as it | 5773 // Use the string table when adding two one character strings, as it |
5774 // helps later optimizations to return a symbol here. | 5774 // helps later optimizations to return an internalized string here. |
5775 __ cmp(ebx, Immediate(Smi::FromInt(2))); | 5775 __ cmp(ebx, Immediate(Smi::FromInt(2))); |
5776 __ j(not_equal, &longer_than_two); | 5776 __ j(not_equal, &longer_than_two); |
5777 | 5777 |
5778 // Check that both strings are non-external ASCII strings. | 5778 // Check that both strings are non-external ASCII strings. |
5779 __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx, &call_runtime); | 5779 __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx, &call_runtime); |
5780 | 5780 |
5781 // Get the two characters forming the new string. | 5781 // Get the two characters forming the new string. |
5782 __ movzx_b(ebx, FieldOperand(eax, SeqOneByteString::kHeaderSize)); | 5782 __ movzx_b(ebx, FieldOperand(eax, SeqOneByteString::kHeaderSize)); |
5783 __ movzx_b(ecx, FieldOperand(edx, SeqOneByteString::kHeaderSize)); | 5783 __ movzx_b(ecx, FieldOperand(edx, SeqOneByteString::kHeaderSize)); |
5784 | 5784 |
5785 // Try to lookup two character string in symbol table. If it is not found | 5785 // Try to lookup two character string in string table. If it is not found |
5786 // just allocate a new one. | 5786 // just allocate a new one. |
5787 Label make_two_character_string, make_two_character_string_no_reload; | 5787 Label make_two_character_string, make_two_character_string_no_reload; |
5788 StringHelper::GenerateTwoCharacterSymbolTableProbe( | 5788 StringHelper::GenerateTwoCharacterStringTableProbe( |
5789 masm, ebx, ecx, eax, edx, edi, | 5789 masm, ebx, ecx, eax, edx, edi, |
5790 &make_two_character_string_no_reload, &make_two_character_string); | 5790 &make_two_character_string_no_reload, &make_two_character_string); |
5791 __ IncrementCounter(counters->string_add_native(), 1); | 5791 __ IncrementCounter(counters->string_add_native(), 1); |
5792 __ ret(2 * kPointerSize); | 5792 __ ret(2 * kPointerSize); |
5793 | 5793 |
5794 // Allocate a two character string. | 5794 // Allocate a two character string. |
5795 __ bind(&make_two_character_string); | 5795 __ bind(&make_two_character_string); |
5796 // Reload the arguments. | 5796 // Reload the arguments. |
5797 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument. | 5797 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument. |
5798 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument. | 5798 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument. |
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6124 __ mov_b(Operand(dest, 0), scratch); | 6124 __ mov_b(Operand(dest, 0), scratch); |
6125 __ add(src, Immediate(1)); | 6125 __ add(src, Immediate(1)); |
6126 __ add(dest, Immediate(1)); | 6126 __ add(dest, Immediate(1)); |
6127 __ sub(count, Immediate(1)); | 6127 __ sub(count, Immediate(1)); |
6128 __ j(not_zero, &loop); | 6128 __ j(not_zero, &loop); |
6129 | 6129 |
6130 __ bind(&done); | 6130 __ bind(&done); |
6131 } | 6131 } |
6132 | 6132 |
6133 | 6133 |
6134 void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm, | 6134 void StringHelper::GenerateTwoCharacterStringTableProbe(MacroAssembler* masm, |
6135 Register c1, | 6135 Register c1, |
6136 Register c2, | 6136 Register c2, |
6137 Register scratch1, | 6137 Register scratch1, |
6138 Register scratch2, | 6138 Register scratch2, |
6139 Register scratch3, | 6139 Register scratch3, |
6140 Label* not_probed, | 6140 Label* not_probed, |
6141 Label* not_found) { | 6141 Label* not_found) { |
6142 // Register scratch3 is the general scratch register in this function. | 6142 // Register scratch3 is the general scratch register in this function. |
6143 Register scratch = scratch3; | 6143 Register scratch = scratch3; |
6144 | 6144 |
6145 // Make sure that both characters are not digits as such strings has a | 6145 // Make sure that both characters are not digits as such strings has a |
6146 // different hash algorithm. Don't try to look for these in the symbol table. | 6146 // different hash algorithm. Don't try to look for these in the string table. |
6147 Label not_array_index; | 6147 Label not_array_index; |
6148 __ mov(scratch, c1); | 6148 __ mov(scratch, c1); |
6149 __ sub(scratch, Immediate(static_cast<int>('0'))); | 6149 __ sub(scratch, Immediate(static_cast<int>('0'))); |
6150 __ cmp(scratch, Immediate(static_cast<int>('9' - '0'))); | 6150 __ cmp(scratch, Immediate(static_cast<int>('9' - '0'))); |
6151 __ j(above, ¬_array_index, Label::kNear); | 6151 __ j(above, ¬_array_index, Label::kNear); |
6152 __ mov(scratch, c2); | 6152 __ mov(scratch, c2); |
6153 __ sub(scratch, Immediate(static_cast<int>('0'))); | 6153 __ sub(scratch, Immediate(static_cast<int>('0'))); |
6154 __ cmp(scratch, Immediate(static_cast<int>('9' - '0'))); | 6154 __ cmp(scratch, Immediate(static_cast<int>('9' - '0'))); |
6155 __ j(below_equal, not_probed); | 6155 __ j(below_equal, not_probed); |
6156 | 6156 |
6157 __ bind(¬_array_index); | 6157 __ bind(¬_array_index); |
6158 // Calculate the two character string hash. | 6158 // Calculate the two character string hash. |
6159 Register hash = scratch1; | 6159 Register hash = scratch1; |
6160 GenerateHashInit(masm, hash, c1, scratch); | 6160 GenerateHashInit(masm, hash, c1, scratch); |
6161 GenerateHashAddCharacter(masm, hash, c2, scratch); | 6161 GenerateHashAddCharacter(masm, hash, c2, scratch); |
6162 GenerateHashGetHash(masm, hash, scratch); | 6162 GenerateHashGetHash(masm, hash, scratch); |
6163 | 6163 |
6164 // Collect the two characters in a register. | 6164 // Collect the two characters in a register. |
6165 Register chars = c1; | 6165 Register chars = c1; |
6166 __ shl(c2, kBitsPerByte); | 6166 __ shl(c2, kBitsPerByte); |
6167 __ or_(chars, c2); | 6167 __ or_(chars, c2); |
6168 | 6168 |
6169 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. | 6169 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. |
6170 // hash: hash of two character string. | 6170 // hash: hash of two character string. |
6171 | 6171 |
6172 // Load the symbol table. | 6172 // Load the string table. |
6173 Register symbol_table = c2; | 6173 Register string_table = c2; |
6174 ExternalReference roots_array_start = | 6174 ExternalReference roots_array_start = |
6175 ExternalReference::roots_array_start(masm->isolate()); | 6175 ExternalReference::roots_array_start(masm->isolate()); |
6176 __ mov(scratch, Immediate(Heap::kSymbolTableRootIndex)); | 6176 __ mov(scratch, Immediate(Heap::kStringTableRootIndex)); |
6177 __ mov(symbol_table, | 6177 __ mov(string_table, |
6178 Operand::StaticArray(scratch, times_pointer_size, roots_array_start)); | 6178 Operand::StaticArray(scratch, times_pointer_size, roots_array_start)); |
6179 | 6179 |
6180 // Calculate capacity mask from the symbol table capacity. | 6180 // Calculate capacity mask from the string table capacity. |
6181 Register mask = scratch2; | 6181 Register mask = scratch2; |
6182 __ mov(mask, FieldOperand(symbol_table, SymbolTable::kCapacityOffset)); | 6182 __ mov(mask, FieldOperand(string_table, StringTable::kCapacityOffset)); |
6183 __ SmiUntag(mask); | 6183 __ SmiUntag(mask); |
6184 __ sub(mask, Immediate(1)); | 6184 __ sub(mask, Immediate(1)); |
6185 | 6185 |
6186 // Registers | 6186 // Registers |
6187 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. | 6187 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. |
6188 // hash: hash of two character string | 6188 // hash: hash of two character string |
6189 // symbol_table: symbol table | 6189 // string_table: string table |
6190 // mask: capacity mask | 6190 // mask: capacity mask |
6191 // scratch: - | 6191 // scratch: - |
6192 | 6192 |
6193 // Perform a number of probes in the symbol table. | 6193 // Perform a number of probes in the string table. |
6194 static const int kProbes = 4; | 6194 static const int kProbes = 4; |
6195 Label found_in_symbol_table; | 6195 Label found_in_string_table; |
6196 Label next_probe[kProbes], next_probe_pop_mask[kProbes]; | 6196 Label next_probe[kProbes], next_probe_pop_mask[kProbes]; |
6197 Register candidate = scratch; // Scratch register contains candidate. | 6197 Register candidate = scratch; // Scratch register contains candidate. |
6198 for (int i = 0; i < kProbes; i++) { | 6198 for (int i = 0; i < kProbes; i++) { |
6199 // Calculate entry in symbol table. | 6199 // Calculate entry in string table. |
6200 __ mov(scratch, hash); | 6200 __ mov(scratch, hash); |
6201 if (i > 0) { | 6201 if (i > 0) { |
6202 __ add(scratch, Immediate(SymbolTable::GetProbeOffset(i))); | 6202 __ add(scratch, Immediate(StringTable::GetProbeOffset(i))); |
6203 } | 6203 } |
6204 __ and_(scratch, mask); | 6204 __ and_(scratch, mask); |
6205 | 6205 |
6206 // Load the entry from the symbol table. | 6206 // Load the entry from the string table. |
6207 STATIC_ASSERT(SymbolTable::kEntrySize == 1); | 6207 STATIC_ASSERT(StringTable::kEntrySize == 1); |
6208 __ mov(candidate, | 6208 __ mov(candidate, |
6209 FieldOperand(symbol_table, | 6209 FieldOperand(string_table, |
6210 scratch, | 6210 scratch, |
6211 times_pointer_size, | 6211 times_pointer_size, |
6212 SymbolTable::kElementsStartOffset)); | 6212 StringTable::kElementsStartOffset)); |
6213 | 6213 |
6214 // If entry is undefined no string with this hash can be found. | 6214 // If entry is undefined no string with this hash can be found. |
6215 Factory* factory = masm->isolate()->factory(); | 6215 Factory* factory = masm->isolate()->factory(); |
6216 __ cmp(candidate, factory->undefined_value()); | 6216 __ cmp(candidate, factory->undefined_value()); |
6217 __ j(equal, not_found); | 6217 __ j(equal, not_found); |
6218 __ cmp(candidate, factory->the_hole_value()); | 6218 __ cmp(candidate, factory->the_hole_value()); |
6219 __ j(equal, &next_probe[i]); | 6219 __ j(equal, &next_probe[i]); |
6220 | 6220 |
6221 // If length is not 2 the string is not a candidate. | 6221 // If length is not 2 the string is not a candidate. |
6222 __ cmp(FieldOperand(candidate, String::kLengthOffset), | 6222 __ cmp(FieldOperand(candidate, String::kLengthOffset), |
6223 Immediate(Smi::FromInt(2))); | 6223 Immediate(Smi::FromInt(2))); |
6224 __ j(not_equal, &next_probe[i]); | 6224 __ j(not_equal, &next_probe[i]); |
6225 | 6225 |
6226 // As we are out of registers save the mask on the stack and use that | 6226 // As we are out of registers save the mask on the stack and use that |
6227 // register as a temporary. | 6227 // register as a temporary. |
6228 __ push(mask); | 6228 __ push(mask); |
6229 Register temp = mask; | 6229 Register temp = mask; |
6230 | 6230 |
6231 // Check that the candidate is a non-external ASCII string. | 6231 // Check that the candidate is a non-external ASCII string. |
6232 __ mov(temp, FieldOperand(candidate, HeapObject::kMapOffset)); | 6232 __ mov(temp, FieldOperand(candidate, HeapObject::kMapOffset)); |
6233 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); | 6233 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); |
6234 __ JumpIfInstanceTypeIsNotSequentialAscii( | 6234 __ JumpIfInstanceTypeIsNotSequentialAscii( |
6235 temp, temp, &next_probe_pop_mask[i]); | 6235 temp, temp, &next_probe_pop_mask[i]); |
6236 | 6236 |
6237 // Check if the two characters match. | 6237 // Check if the two characters match. |
6238 __ mov(temp, FieldOperand(candidate, SeqOneByteString::kHeaderSize)); | 6238 __ mov(temp, FieldOperand(candidate, SeqOneByteString::kHeaderSize)); |
6239 __ and_(temp, 0x0000ffff); | 6239 __ and_(temp, 0x0000ffff); |
6240 __ cmp(chars, temp); | 6240 __ cmp(chars, temp); |
6241 __ j(equal, &found_in_symbol_table); | 6241 __ j(equal, &found_in_string_table); |
6242 __ bind(&next_probe_pop_mask[i]); | 6242 __ bind(&next_probe_pop_mask[i]); |
6243 __ pop(mask); | 6243 __ pop(mask); |
6244 __ bind(&next_probe[i]); | 6244 __ bind(&next_probe[i]); |
6245 } | 6245 } |
6246 | 6246 |
6247 // No matching 2 character string found by probing. | 6247 // No matching 2 character string found by probing. |
6248 __ jmp(not_found); | 6248 __ jmp(not_found); |
6249 | 6249 |
6250 // Scratch register contains result when we fall through to here. | 6250 // Scratch register contains result when we fall through to here. |
6251 Register result = candidate; | 6251 Register result = candidate; |
6252 __ bind(&found_in_symbol_table); | 6252 __ bind(&found_in_string_table); |
6253 __ pop(mask); // Pop saved mask from the stack. | 6253 __ pop(mask); // Pop saved mask from the stack. |
6254 if (!result.is(eax)) { | 6254 if (!result.is(eax)) { |
6255 __ mov(eax, result); | 6255 __ mov(eax, result); |
6256 } | 6256 } |
6257 } | 6257 } |
6258 | 6258 |
6259 | 6259 |
6260 void StringHelper::GenerateHashInit(MacroAssembler* masm, | 6260 void StringHelper::GenerateHashInit(MacroAssembler* masm, |
6261 Register hash, | 6261 Register hash, |
6262 Register character, | 6262 Register character, |
(...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6840 if (Token::IsOrderedRelationalCompareOp(op_)) { | 6840 if (Token::IsOrderedRelationalCompareOp(op_)) { |
6841 __ cmp(edx, Immediate(masm->isolate()->factory()->undefined_value())); | 6841 __ cmp(edx, Immediate(masm->isolate()->factory()->undefined_value())); |
6842 __ j(equal, &unordered); | 6842 __ j(equal, &unordered); |
6843 } | 6843 } |
6844 | 6844 |
6845 __ bind(&miss); | 6845 __ bind(&miss); |
6846 GenerateMiss(masm); | 6846 GenerateMiss(masm); |
6847 } | 6847 } |
6848 | 6848 |
6849 | 6849 |
6850 void ICCompareStub::GenerateSymbols(MacroAssembler* masm) { | 6850 void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) { |
6851 ASSERT(state_ == CompareIC::SYMBOL); | 6851 ASSERT(state_ == CompareIC::INTERNALIZED_STRING); |
6852 ASSERT(GetCondition() == equal); | 6852 ASSERT(GetCondition() == equal); |
6853 | 6853 |
6854 // Registers containing left and right operands respectively. | 6854 // Registers containing left and right operands respectively. |
6855 Register left = edx; | 6855 Register left = edx; |
6856 Register right = eax; | 6856 Register right = eax; |
6857 Register tmp1 = ecx; | 6857 Register tmp1 = ecx; |
6858 Register tmp2 = ebx; | 6858 Register tmp2 = ebx; |
6859 | 6859 |
6860 // Check that both operands are heap objects. | 6860 // Check that both operands are heap objects. |
6861 Label miss; | 6861 Label miss; |
6862 __ mov(tmp1, left); | 6862 __ mov(tmp1, left); |
6863 STATIC_ASSERT(kSmiTag == 0); | 6863 STATIC_ASSERT(kSmiTag == 0); |
6864 __ and_(tmp1, right); | 6864 __ and_(tmp1, right); |
6865 __ JumpIfSmi(tmp1, &miss, Label::kNear); | 6865 __ JumpIfSmi(tmp1, &miss, Label::kNear); |
6866 | 6866 |
6867 // Check that both operands are symbols. | 6867 // Check that both operands are internalized strings. |
6868 __ mov(tmp1, FieldOperand(left, HeapObject::kMapOffset)); | 6868 __ mov(tmp1, FieldOperand(left, HeapObject::kMapOffset)); |
6869 __ mov(tmp2, FieldOperand(right, HeapObject::kMapOffset)); | 6869 __ mov(tmp2, FieldOperand(right, HeapObject::kMapOffset)); |
6870 __ movzx_b(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); | 6870 __ movzx_b(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); |
6871 __ movzx_b(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); | 6871 __ movzx_b(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); |
6872 STATIC_ASSERT(kSymbolTag != 0); | 6872 STATIC_ASSERT(kInternalizedTag != 0); |
6873 __ and_(tmp1, tmp2); | 6873 __ and_(tmp1, tmp2); |
6874 __ test(tmp1, Immediate(kIsSymbolMask)); | 6874 __ test(tmp1, Immediate(kIsInternalizedMask)); |
6875 __ j(zero, &miss, Label::kNear); | 6875 __ j(zero, &miss, Label::kNear); |
6876 | 6876 |
6877 // Symbols are compared by identity. | 6877 // Internalized strings are compared by identity. |
6878 Label done; | 6878 Label done; |
6879 __ cmp(left, right); | 6879 __ cmp(left, right); |
6880 // Make sure eax is non-zero. At this point input operands are | 6880 // Make sure eax is non-zero. At this point input operands are |
6881 // guaranteed to be non-zero. | 6881 // guaranteed to be non-zero. |
6882 ASSERT(right.is(eax)); | 6882 ASSERT(right.is(eax)); |
6883 __ j(not_equal, &done, Label::kNear); | 6883 __ j(not_equal, &done, Label::kNear); |
6884 STATIC_ASSERT(EQUAL == 0); | 6884 STATIC_ASSERT(EQUAL == 0); |
6885 STATIC_ASSERT(kSmiTag == 0); | 6885 STATIC_ASSERT(kSmiTag == 0); |
6886 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); | 6886 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); |
6887 __ bind(&done); | 6887 __ bind(&done); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6928 __ cmp(left, right); | 6928 __ cmp(left, right); |
6929 __ j(not_equal, ¬_same, Label::kNear); | 6929 __ j(not_equal, ¬_same, Label::kNear); |
6930 STATIC_ASSERT(EQUAL == 0); | 6930 STATIC_ASSERT(EQUAL == 0); |
6931 STATIC_ASSERT(kSmiTag == 0); | 6931 STATIC_ASSERT(kSmiTag == 0); |
6932 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); | 6932 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); |
6933 __ ret(0); | 6933 __ ret(0); |
6934 | 6934 |
6935 // Handle not identical strings. | 6935 // Handle not identical strings. |
6936 __ bind(¬_same); | 6936 __ bind(¬_same); |
6937 | 6937 |
6938 // Check that both strings are symbols. If they are, we're done | 6938 // Check that both strings are internalized. If they are, we're done |
6939 // because we already know they are not identical. But in the case of | 6939 // because we already know they are not identical. But in the case of |
6940 // non-equality compare, we still need to determine the order. | 6940 // non-equality compare, we still need to determine the order. |
6941 if (equality) { | 6941 if (equality) { |
6942 Label do_compare; | 6942 Label do_compare; |
6943 STATIC_ASSERT(kSymbolTag != 0); | 6943 STATIC_ASSERT(kInternalizedTag != 0); |
6944 __ and_(tmp1, tmp2); | 6944 __ and_(tmp1, tmp2); |
6945 __ test(tmp1, Immediate(kIsSymbolMask)); | 6945 __ test(tmp1, Immediate(kIsInternalizedMask)); |
6946 __ j(zero, &do_compare, Label::kNear); | 6946 __ j(zero, &do_compare, Label::kNear); |
6947 // Make sure eax is non-zero. At this point input operands are | 6947 // Make sure eax is non-zero. At this point input operands are |
6948 // guaranteed to be non-zero. | 6948 // guaranteed to be non-zero. |
6949 ASSERT(right.is(eax)); | 6949 ASSERT(right.is(eax)); |
6950 __ ret(0); | 6950 __ ret(0); |
6951 __ bind(&do_compare); | 6951 __ bind(&do_compare); |
6952 } | 6952 } |
6953 | 6953 |
6954 // Check that both strings are sequential ASCII. | 6954 // Check that both strings are sequential ASCII. |
6955 Label runtime; | 6955 Label runtime; |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7043 | 7043 |
7044 // Do a tail call to the rewritten stub. | 7044 // Do a tail call to the rewritten stub. |
7045 __ jmp(edi); | 7045 __ jmp(edi); |
7046 } | 7046 } |
7047 | 7047 |
7048 | 7048 |
7049 // Helper function used to check that the dictionary doesn't contain | 7049 // Helper function used to check that the dictionary doesn't contain |
7050 // the property. This function may return false negatives, so miss_label | 7050 // the property. This function may return false negatives, so miss_label |
7051 // must always call a backup property check that is complete. | 7051 // must always call a backup property check that is complete. |
7052 // This function is safe to call if the receiver has fast properties. | 7052 // This function is safe to call if the receiver has fast properties. |
7053 // Name must be a symbol and receiver must be a heap object. | 7053 // Name must be an internalized string and receiver must be a heap object. |
7054 void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, | 7054 void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, |
7055 Label* miss, | 7055 Label* miss, |
7056 Label* done, | 7056 Label* done, |
7057 Register properties, | 7057 Register properties, |
7058 Handle<String> name, | 7058 Handle<String> name, |
7059 Register r0) { | 7059 Register r0) { |
7060 ASSERT(name->IsSymbol()); | 7060 ASSERT(name->IsInternalizedString()); |
7061 | 7061 |
7062 // If names of slots in range from 1 to kProbes - 1 for the hash value are | 7062 // If names of slots in range from 1 to kProbes - 1 for the hash value are |
7063 // not equal to the name and kProbes-th slot is not used (its name is the | 7063 // not equal to the name and kProbes-th slot is not used (its name is the |
7064 // undefined value), it guarantees the hash table doesn't contain the | 7064 // undefined value), it guarantees the hash table doesn't contain the |
7065 // property. It's true even if some slots represent deleted properties | 7065 // property. It's true even if some slots represent deleted properties |
7066 // (their names are the hole value). | 7066 // (their names are the hole value). |
7067 for (int i = 0; i < kInlinedProbes; i++) { | 7067 for (int i = 0; i < kInlinedProbes; i++) { |
7068 // Compute the masked index: (hash + i + i * i) & mask. | 7068 // Compute the masked index: (hash + i + i * i) & mask. |
7069 Register index = r0; | 7069 Register index = r0; |
7070 // Capacity is smi 2^n. | 7070 // Capacity is smi 2^n. |
(...skipping 16 matching lines...) Expand all Loading... |
7087 | 7087 |
7088 // Stop if found the property. | 7088 // Stop if found the property. |
7089 __ cmp(entity_name, Handle<String>(name)); | 7089 __ cmp(entity_name, Handle<String>(name)); |
7090 __ j(equal, miss); | 7090 __ j(equal, miss); |
7091 | 7091 |
7092 Label the_hole; | 7092 Label the_hole; |
7093 // Check for the hole and skip. | 7093 // Check for the hole and skip. |
7094 __ cmp(entity_name, masm->isolate()->factory()->the_hole_value()); | 7094 __ cmp(entity_name, masm->isolate()->factory()->the_hole_value()); |
7095 __ j(equal, &the_hole, Label::kNear); | 7095 __ j(equal, &the_hole, Label::kNear); |
7096 | 7096 |
7097 // Check if the entry name is not a symbol. | 7097 // Check if the entry name is not an internalized string. |
7098 __ mov(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset)); | 7098 __ mov(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset)); |
7099 __ test_b(FieldOperand(entity_name, Map::kInstanceTypeOffset), | 7099 __ test_b(FieldOperand(entity_name, Map::kInstanceTypeOffset), |
7100 kIsSymbolMask); | 7100 kIsInternalizedMask); |
7101 __ j(zero, miss); | 7101 __ j(zero, miss); |
7102 __ bind(&the_hole); | 7102 __ bind(&the_hole); |
7103 } | 7103 } |
7104 | 7104 |
7105 StringDictionaryLookupStub stub(properties, | 7105 StringDictionaryLookupStub stub(properties, |
7106 r0, | 7106 r0, |
7107 r0, | 7107 r0, |
7108 StringDictionaryLookupStub::NEGATIVE_LOOKUP); | 7108 StringDictionaryLookupStub::NEGATIVE_LOOKUP); |
7109 __ push(Immediate(Handle<Object>(name))); | 7109 __ push(Immediate(Handle<Object>(name))); |
7110 __ push(Immediate(name->Hash())); | 7110 __ push(Immediate(name->Hash())); |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7225 times_pointer_size, | 7225 times_pointer_size, |
7226 kElementsStartOffset - kHeapObjectTag)); | 7226 kElementsStartOffset - kHeapObjectTag)); |
7227 __ cmp(scratch, masm->isolate()->factory()->undefined_value()); | 7227 __ cmp(scratch, masm->isolate()->factory()->undefined_value()); |
7228 __ j(equal, ¬_in_dictionary); | 7228 __ j(equal, ¬_in_dictionary); |
7229 | 7229 |
7230 // Stop if found the property. | 7230 // Stop if found the property. |
7231 __ cmp(scratch, Operand(esp, 3 * kPointerSize)); | 7231 __ cmp(scratch, Operand(esp, 3 * kPointerSize)); |
7232 __ j(equal, &in_dictionary); | 7232 __ j(equal, &in_dictionary); |
7233 | 7233 |
7234 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) { | 7234 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) { |
7235 // If we hit a non symbol key during negative lookup | 7235 // If we hit a key that is not an internalized string during negative |
7236 // we have to bailout as this key might be equal to the | 7236 // lookup we have to bailout as this key might be equal to the |
7237 // key we are looking for. | 7237 // key we are looking for. |
7238 | 7238 |
7239 // Check if the entry name is not a symbol. | 7239 // Check if the entry name is not an internalized string. |
7240 __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); | 7240 __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); |
7241 __ test_b(FieldOperand(scratch, Map::kInstanceTypeOffset), | 7241 __ test_b(FieldOperand(scratch, Map::kInstanceTypeOffset), |
7242 kIsSymbolMask); | 7242 kIsInternalizedMask); |
7243 __ j(zero, &maybe_in_dictionary); | 7243 __ j(zero, &maybe_in_dictionary); |
7244 } | 7244 } |
7245 } | 7245 } |
7246 | 7246 |
7247 __ bind(&maybe_in_dictionary); | 7247 __ bind(&maybe_in_dictionary); |
7248 // If we are doing negative lookup then probing failure should be | 7248 // If we are doing negative lookup then probing failure should be |
7249 // treated as a lookup success. For positive lookup probing failure | 7249 // treated as a lookup success. For positive lookup probing failure |
7250 // should be treated as lookup failure. | 7250 // should be treated as lookup failure. |
7251 if (mode_ == POSITIVE_LOOKUP) { | 7251 if (mode_ == POSITIVE_LOOKUP) { |
7252 __ mov(result_, Immediate(0)); | 7252 __ mov(result_, Immediate(0)); |
(...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7687 // Restore ecx. | 7687 // Restore ecx. |
7688 __ pop(ecx); | 7688 __ pop(ecx); |
7689 __ ret(0); | 7689 __ ret(0); |
7690 } | 7690 } |
7691 | 7691 |
7692 #undef __ | 7692 #undef __ |
7693 | 7693 |
7694 } } // namespace v8::internal | 7694 } } // namespace v8::internal |
7695 | 7695 |
7696 #endif // V8_TARGET_ARCH_IA32 | 7696 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |