| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #if V8_TARGET_ARCH_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
| 6 | 6 |
| 7 #include "src/codegen.h" | 7 #include "src/codegen.h" |
| 8 #include "src/ic/ic.h" | 8 #include "src/ic/ic.h" |
| 9 #include "src/ic/ic-compiler.h" | 9 #include "src/ic/ic-compiler.h" |
| 10 #include "src/ic/stub-cache.h" | 10 #include "src/ic/stub-cache.h" |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 | 160 |
| 161 __ CmpInstanceType(map, JS_OBJECT_TYPE); | 161 __ CmpInstanceType(map, JS_OBJECT_TYPE); |
| 162 __ j(below, slow); | 162 __ j(below, slow); |
| 163 } | 163 } |
| 164 | 164 |
| 165 | 165 |
| 166 // Loads an indexed element from a fast case array. | 166 // Loads an indexed element from a fast case array. |
| 167 static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, | 167 static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, |
| 168 Register key, Register scratch, | 168 Register key, Register scratch, |
| 169 Register scratch2, Register result, | 169 Register scratch2, Register result, |
| 170 Label* slow, LanguageMode language_mode) { | 170 Label* slow) { |
| 171 // Register use: | 171 // Register use: |
| 172 // receiver - holds the receiver and is unchanged. | 172 // receiver - holds the receiver and is unchanged. |
| 173 // key - holds the key and is unchanged (must be a smi). | 173 // key - holds the key and is unchanged (must be a smi). |
| 174 // Scratch registers: | 174 // Scratch registers: |
| 175 // scratch - used to hold elements of the receiver and the loaded value. | 175 // scratch - used to hold elements of the receiver and the loaded value. |
| 176 // scratch2 - holds maps and prototypes during prototype chain check. | 176 // scratch2 - holds maps and prototypes during prototype chain check. |
| 177 // result - holds the result on exit if the load succeeds and | 177 // result - holds the result on exit if the load succeeds and |
| 178 // we fall through. | 178 // we fall through. |
| 179 Label check_prototypes, check_next_prototype; | 179 Label check_prototypes, check_next_prototype; |
| 180 Label done, in_bounds, absent; | 180 Label done, in_bounds, absent; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 204 __ j(below, slow); | 204 __ j(below, slow); |
| 205 __ test_b( | 205 __ test_b( |
| 206 FieldOperand(scratch2, Map::kBitFieldOffset), | 206 FieldOperand(scratch2, Map::kBitFieldOffset), |
| 207 (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor)); | 207 (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor)); |
| 208 __ j(not_zero, slow); | 208 __ j(not_zero, slow); |
| 209 __ cmp(scratch, masm->isolate()->factory()->empty_fixed_array()); | 209 __ cmp(scratch, masm->isolate()->factory()->empty_fixed_array()); |
| 210 __ j(not_equal, slow); | 210 __ j(not_equal, slow); |
| 211 __ jmp(&check_next_prototype); | 211 __ jmp(&check_next_prototype); |
| 212 | 212 |
| 213 __ bind(&absent); | 213 __ bind(&absent); |
| 214 if (is_strong(language_mode)) { | 214 __ mov(result, masm->isolate()->factory()->undefined_value()); |
| 215 // Strong mode accesses must throw in this case, so call the runtime. | 215 __ jmp(&done); |
| 216 __ jmp(slow); | |
| 217 } else { | |
| 218 __ mov(result, masm->isolate()->factory()->undefined_value()); | |
| 219 __ jmp(&done); | |
| 220 } | |
| 221 | 216 |
| 222 __ bind(&in_bounds); | 217 __ bind(&in_bounds); |
| 223 // Fast case: Do the load. | 218 // Fast case: Do the load. |
| 224 STATIC_ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0)); | 219 STATIC_ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0)); |
| 225 __ mov(scratch, FieldOperand(scratch, key, times_2, FixedArray::kHeaderSize)); | 220 __ mov(scratch, FieldOperand(scratch, key, times_2, FixedArray::kHeaderSize)); |
| 226 __ cmp(scratch, Immediate(masm->isolate()->factory()->the_hole_value())); | 221 __ cmp(scratch, Immediate(masm->isolate()->factory()->the_hole_value())); |
| 227 // In case the loaded value is the_hole we have to check the prototype chain. | 222 // In case the loaded value is the_hole we have to check the prototype chain. |
| 228 __ j(equal, &check_prototypes); | 223 __ j(equal, &check_prototypes); |
| 229 __ Move(result, scratch); | 224 __ Move(result, scratch); |
| 230 __ bind(&done); | 225 __ bind(&done); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 255 // Is the string internalized? We already know it's a string so a single | 250 // Is the string internalized? We already know it's a string so a single |
| 256 // bit test is enough. | 251 // bit test is enough. |
| 257 STATIC_ASSERT(kNotInternalizedTag != 0); | 252 STATIC_ASSERT(kNotInternalizedTag != 0); |
| 258 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), | 253 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), |
| 259 kIsNotInternalizedMask); | 254 kIsNotInternalizedMask); |
| 260 __ j(not_zero, not_unique); | 255 __ j(not_zero, not_unique); |
| 261 | 256 |
| 262 __ bind(&unique); | 257 __ bind(&unique); |
| 263 } | 258 } |
| 264 | 259 |
| 265 | 260 void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { |
| 266 void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm, | |
| 267 LanguageMode language_mode) { | |
| 268 // The return address is on the stack. | 261 // The return address is on the stack. |
| 269 Label slow, check_name, index_smi, index_name, property_array_property; | 262 Label slow, check_name, index_smi, index_name, property_array_property; |
| 270 Label probe_dictionary, check_number_dictionary; | 263 Label probe_dictionary, check_number_dictionary; |
| 271 | 264 |
| 272 Register receiver = LoadDescriptor::ReceiverRegister(); | 265 Register receiver = LoadDescriptor::ReceiverRegister(); |
| 273 Register key = LoadDescriptor::NameRegister(); | 266 Register key = LoadDescriptor::NameRegister(); |
| 274 DCHECK(receiver.is(edx)); | 267 DCHECK(receiver.is(edx)); |
| 275 DCHECK(key.is(ecx)); | 268 DCHECK(key.is(ecx)); |
| 276 | 269 |
| 277 // Check that the key is a smi. | 270 // Check that the key is a smi. |
| 278 __ JumpIfNotSmi(key, &check_name); | 271 __ JumpIfNotSmi(key, &check_name); |
| 279 __ bind(&index_smi); | 272 __ bind(&index_smi); |
| 280 // Now the key is known to be a smi. This place is also jumped to from | 273 // Now the key is known to be a smi. This place is also jumped to from |
| 281 // where a numeric string is converted to a smi. | 274 // where a numeric string is converted to a smi. |
| 282 | 275 |
| 283 GenerateKeyedLoadReceiverCheck(masm, receiver, eax, | 276 GenerateKeyedLoadReceiverCheck(masm, receiver, eax, |
| 284 Map::kHasIndexedInterceptor, &slow); | 277 Map::kHasIndexedInterceptor, &slow); |
| 285 | 278 |
| 286 // Check the receiver's map to see if it has fast elements. | 279 // Check the receiver's map to see if it has fast elements. |
| 287 __ CheckFastElements(eax, &check_number_dictionary); | 280 __ CheckFastElements(eax, &check_number_dictionary); |
| 288 | 281 |
| 289 GenerateFastArrayLoad(masm, receiver, key, eax, ebx, eax, &slow, | 282 GenerateFastArrayLoad(masm, receiver, key, eax, ebx, eax, &slow); |
| 290 language_mode); | |
| 291 Isolate* isolate = masm->isolate(); | 283 Isolate* isolate = masm->isolate(); |
| 292 Counters* counters = isolate->counters(); | 284 Counters* counters = isolate->counters(); |
| 293 __ IncrementCounter(counters->ic_keyed_load_generic_smi(), 1); | 285 __ IncrementCounter(counters->ic_keyed_load_generic_smi(), 1); |
| 294 __ ret(0); | 286 __ ret(0); |
| 295 | 287 |
| 296 __ bind(&check_number_dictionary); | 288 __ bind(&check_number_dictionary); |
| 297 __ mov(ebx, key); | 289 __ mov(ebx, key); |
| 298 __ SmiUntag(ebx); | 290 __ SmiUntag(ebx); |
| 299 __ mov(eax, FieldOperand(receiver, JSObject::kElementsOffset)); | 291 __ mov(eax, FieldOperand(receiver, JSObject::kElementsOffset)); |
| 300 | 292 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 312 __ pop(receiver); | 304 __ pop(receiver); |
| 313 __ ret(0); | 305 __ ret(0); |
| 314 | 306 |
| 315 __ bind(&slow_pop_receiver); | 307 __ bind(&slow_pop_receiver); |
| 316 // Pop the receiver from the stack and jump to runtime. | 308 // Pop the receiver from the stack and jump to runtime. |
| 317 __ pop(receiver); | 309 __ pop(receiver); |
| 318 | 310 |
| 319 __ bind(&slow); | 311 __ bind(&slow); |
| 320 // Slow case: jump to runtime. | 312 // Slow case: jump to runtime. |
| 321 __ IncrementCounter(counters->ic_keyed_load_generic_slow(), 1); | 313 __ IncrementCounter(counters->ic_keyed_load_generic_slow(), 1); |
| 322 GenerateRuntimeGetProperty(masm, language_mode); | 314 GenerateRuntimeGetProperty(masm); |
| 323 | 315 |
| 324 __ bind(&check_name); | 316 __ bind(&check_name); |
| 325 GenerateKeyNameCheck(masm, key, eax, ebx, &index_name, &slow); | 317 GenerateKeyNameCheck(masm, key, eax, ebx, &index_name, &slow); |
| 326 | 318 |
| 327 GenerateKeyedLoadReceiverCheck(masm, receiver, eax, Map::kHasNamedInterceptor, | 319 GenerateKeyedLoadReceiverCheck(masm, receiver, eax, Map::kHasNamedInterceptor, |
| 328 &slow); | 320 &slow); |
| 329 | 321 |
| 330 // If the receiver is a fast-case object, check the stub cache. Otherwise | 322 // If the receiver is a fast-case object, check the stub cache. Otherwise |
| 331 // probe the dictionary. | 323 // probe the dictionary. |
| 332 __ mov(ebx, FieldOperand(receiver, JSObject::kPropertiesOffset)); | 324 __ mov(ebx, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 621 KeyedStoreGenerateMegamorphicHelper(masm, &fast_object, &fast_double, &slow, | 613 KeyedStoreGenerateMegamorphicHelper(masm, &fast_object, &fast_double, &slow, |
| 622 kCheckMap, kDontIncrementLength); | 614 kCheckMap, kDontIncrementLength); |
| 623 KeyedStoreGenerateMegamorphicHelper(masm, &fast_object_grow, | 615 KeyedStoreGenerateMegamorphicHelper(masm, &fast_object_grow, |
| 624 &fast_double_grow, &slow, kDontCheckMap, | 616 &fast_double_grow, &slow, kDontCheckMap, |
| 625 kIncrementLength); | 617 kIncrementLength); |
| 626 | 618 |
| 627 __ bind(&miss); | 619 __ bind(&miss); |
| 628 GenerateMiss(masm); | 620 GenerateMiss(masm); |
| 629 } | 621 } |
| 630 | 622 |
| 631 | 623 void LoadIC::GenerateNormal(MacroAssembler* masm) { |
| 632 void LoadIC::GenerateNormal(MacroAssembler* masm, LanguageMode language_mode) { | |
| 633 Register dictionary = eax; | 624 Register dictionary = eax; |
| 634 DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister())); | 625 DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister())); |
| 635 DCHECK(!dictionary.is(LoadDescriptor::NameRegister())); | 626 DCHECK(!dictionary.is(LoadDescriptor::NameRegister())); |
| 636 | 627 |
| 637 Label slow; | 628 Label slow; |
| 638 | 629 |
| 639 __ mov(dictionary, FieldOperand(LoadDescriptor::ReceiverRegister(), | 630 __ mov(dictionary, FieldOperand(LoadDescriptor::ReceiverRegister(), |
| 640 JSObject::kPropertiesOffset)); | 631 JSObject::kPropertiesOffset)); |
| 641 GenerateDictionaryLoad(masm, &slow, dictionary, | 632 GenerateDictionaryLoad(masm, &slow, dictionary, |
| 642 LoadDescriptor::NameRegister(), edi, ebx, eax); | 633 LoadDescriptor::NameRegister(), edi, ebx, eax); |
| 643 __ ret(0); | 634 __ ret(0); |
| 644 | 635 |
| 645 // Dictionary load failed, go slow (but don't miss). | 636 // Dictionary load failed, go slow (but don't miss). |
| 646 __ bind(&slow); | 637 __ bind(&slow); |
| 647 GenerateRuntimeGetProperty(masm, language_mode); | 638 GenerateRuntimeGetProperty(masm); |
| 648 } | 639 } |
| 649 | 640 |
| 650 | 641 |
| 651 static void LoadIC_PushArgs(MacroAssembler* masm) { | 642 static void LoadIC_PushArgs(MacroAssembler* masm) { |
| 652 Register receiver = LoadDescriptor::ReceiverRegister(); | 643 Register receiver = LoadDescriptor::ReceiverRegister(); |
| 653 Register name = LoadDescriptor::NameRegister(); | 644 Register name = LoadDescriptor::NameRegister(); |
| 654 | 645 |
| 655 Register slot = LoadDescriptor::SlotRegister(); | 646 Register slot = LoadDescriptor::SlotRegister(); |
| 656 Register vector = LoadWithVectorDescriptor::VectorRegister(); | 647 Register vector = LoadWithVectorDescriptor::VectorRegister(); |
| 657 DCHECK(!edi.is(receiver) && !edi.is(name) && !edi.is(slot) && | 648 DCHECK(!edi.is(receiver) && !edi.is(name) && !edi.is(slot) && |
| (...skipping 10 matching lines...) Expand all Loading... |
| 668 | 659 |
| 669 void LoadIC::GenerateMiss(MacroAssembler* masm) { | 660 void LoadIC::GenerateMiss(MacroAssembler* masm) { |
| 670 // Return address is on the stack. | 661 // Return address is on the stack. |
| 671 __ IncrementCounter(masm->isolate()->counters()->ic_load_miss(), 1); | 662 __ IncrementCounter(masm->isolate()->counters()->ic_load_miss(), 1); |
| 672 LoadIC_PushArgs(masm); | 663 LoadIC_PushArgs(masm); |
| 673 | 664 |
| 674 // Perform tail call to the entry. | 665 // Perform tail call to the entry. |
| 675 __ TailCallRuntime(Runtime::kLoadIC_Miss); | 666 __ TailCallRuntime(Runtime::kLoadIC_Miss); |
| 676 } | 667 } |
| 677 | 668 |
| 678 | 669 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
| 679 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm, | |
| 680 LanguageMode language_mode) { | |
| 681 // Return address is on the stack. | 670 // Return address is on the stack. |
| 682 Register receiver = LoadDescriptor::ReceiverRegister(); | 671 Register receiver = LoadDescriptor::ReceiverRegister(); |
| 683 Register name = LoadDescriptor::NameRegister(); | 672 Register name = LoadDescriptor::NameRegister(); |
| 684 DCHECK(!ebx.is(receiver) && !ebx.is(name)); | 673 DCHECK(!ebx.is(receiver) && !ebx.is(name)); |
| 685 | 674 |
| 686 __ pop(ebx); | 675 __ pop(ebx); |
| 687 __ push(receiver); | 676 __ push(receiver); |
| 688 __ push(name); | 677 __ push(name); |
| 689 __ push(ebx); | 678 __ push(ebx); |
| 690 | 679 |
| 691 // Do tail-call to runtime routine. | 680 // Do tail-call to runtime routine. |
| 692 __ TailCallRuntime(is_strong(language_mode) ? Runtime::kGetPropertyStrong | 681 __ TailCallRuntime(Runtime::kGetProperty); |
| 693 : Runtime::kGetProperty); | |
| 694 } | 682 } |
| 695 | 683 |
| 696 | 684 |
| 697 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { | 685 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { |
| 698 // Return address is on the stack. | 686 // Return address is on the stack. |
| 699 __ IncrementCounter(masm->isolate()->counters()->ic_keyed_load_miss(), 1); | 687 __ IncrementCounter(masm->isolate()->counters()->ic_keyed_load_miss(), 1); |
| 700 | 688 |
| 701 LoadIC_PushArgs(masm); | 689 LoadIC_PushArgs(masm); |
| 702 | 690 |
| 703 // Perform tail call to the entry. | 691 // Perform tail call to the entry. |
| 704 __ TailCallRuntime(Runtime::kKeyedLoadIC_Miss); | 692 __ TailCallRuntime(Runtime::kKeyedLoadIC_Miss); |
| 705 } | 693 } |
| 706 | 694 |
| 707 | 695 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
| 708 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm, | |
| 709 LanguageMode language_mode) { | |
| 710 // Return address is on the stack. | 696 // Return address is on the stack. |
| 711 Register receiver = LoadDescriptor::ReceiverRegister(); | 697 Register receiver = LoadDescriptor::ReceiverRegister(); |
| 712 Register name = LoadDescriptor::NameRegister(); | 698 Register name = LoadDescriptor::NameRegister(); |
| 713 DCHECK(!ebx.is(receiver) && !ebx.is(name)); | 699 DCHECK(!ebx.is(receiver) && !ebx.is(name)); |
| 714 | 700 |
| 715 __ pop(ebx); | 701 __ pop(ebx); |
| 716 __ push(receiver); | 702 __ push(receiver); |
| 717 __ push(name); | 703 __ push(name); |
| 718 __ push(ebx); | 704 __ push(ebx); |
| 719 | 705 |
| 720 // Do tail-call to runtime routine. | 706 // Do tail-call to runtime routine. |
| 721 __ TailCallRuntime(is_strong(language_mode) ? Runtime::kKeyedGetPropertyStrong | 707 __ TailCallRuntime(Runtime::kKeyedGetProperty); |
| 722 : Runtime::kKeyedGetProperty); | |
| 723 } | 708 } |
| 724 | 709 |
| 725 | 710 |
| 726 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { | 711 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { |
| 727 // This shouldn't be called. | 712 // This shouldn't be called. |
| 728 // TODO(mvstanton): remove this method. | 713 // TODO(mvstanton): remove this method. |
| 729 __ int3(); | 714 __ int3(); |
| 730 return; | 715 return; |
| 731 } | 716 } |
| 732 | 717 |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 866 Condition cc = | 851 Condition cc = |
| 867 (check == ENABLE_INLINED_SMI_CHECK) | 852 (check == ENABLE_INLINED_SMI_CHECK) |
| 868 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) | 853 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) |
| 869 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); | 854 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); |
| 870 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 855 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
| 871 } | 856 } |
| 872 } // namespace internal | 857 } // namespace internal |
| 873 } // namespace v8 | 858 } // namespace v8 |
| 874 | 859 |
| 875 #endif // V8_TARGET_ARCH_IA32 | 860 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |