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