| 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 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_IA32 | 7 #if V8_TARGET_ARCH_IA32 |
| 8 | 8 |
| 9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
| 10 #include "src/ic-inl.h" | 10 #include "src/ic-inl.h" |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 381 FixedArray::kHeaderSize); | 381 FixedArray::kHeaderSize); |
| 382 } | 382 } |
| 383 | 383 |
| 384 | 384 |
| 385 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 385 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
| 386 // ----------- S t a t e ------------- | 386 // ----------- S t a t e ------------- |
| 387 // -- ecx : key | 387 // -- ecx : key |
| 388 // -- edx : receiver | 388 // -- edx : receiver |
| 389 // -- esp[0] : return address | 389 // -- esp[0] : return address |
| 390 // ----------------------------------- | 390 // ----------------------------------- |
| 391 ASSERT(edx.is(ReceiverRegister())); |
| 392 ASSERT(ecx.is(NameRegister())); |
| 391 Label slow, check_name, index_smi, index_name, property_array_property; | 393 Label slow, check_name, index_smi, index_name, property_array_property; |
| 392 Label probe_dictionary, check_number_dictionary; | 394 Label probe_dictionary, check_number_dictionary; |
| 393 | 395 |
| 394 // Check that the key is a smi. | 396 // Check that the key is a smi. |
| 395 __ JumpIfNotSmi(ecx, &check_name); | 397 __ JumpIfNotSmi(ecx, &check_name); |
| 396 __ bind(&index_smi); | 398 __ bind(&index_smi); |
| 397 // Now the key is known to be a smi. This place is also jumped to from | 399 // Now the key is known to be a smi. This place is also jumped to from |
| 398 // where a numeric string is converted to a smi. | 400 // where a numeric string is converted to a smi. |
| 399 | 401 |
| 400 GenerateKeyedLoadReceiverCheck( | 402 GenerateKeyedLoadReceiverCheck( |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 553 __ IncrementCounter(counters->keyed_load_generic_symbol(), 1); | 555 __ IncrementCounter(counters->keyed_load_generic_symbol(), 1); |
| 554 __ ret(0); | 556 __ ret(0); |
| 555 | 557 |
| 556 __ bind(&index_name); | 558 __ bind(&index_name); |
| 557 __ IndexFromHash(ebx, ecx); | 559 __ IndexFromHash(ebx, ecx); |
| 558 // Now jump to the place where smi keys are handled. | 560 // Now jump to the place where smi keys are handled. |
| 559 __ jmp(&index_smi); | 561 __ jmp(&index_smi); |
| 560 } | 562 } |
| 561 | 563 |
| 562 | 564 |
| 565 // A register that isn't one of the parameters to the load ic. |
| 566 static const Register LoadIC_TempRegister() { return ebx; } |
| 567 |
| 568 |
| 569 // A register that isn't one of the parameters to the load ic. |
| 570 static const Register KeyedLoadIC_TempRegister() { |
| 571 return LoadIC_TempRegister(); |
| 572 } |
| 573 |
| 574 |
| 563 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { | 575 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { |
| 564 // ----------- S t a t e ------------- | 576 // Return address is on the stack. |
| 565 // -- ecx : key (index) | |
| 566 // -- edx : receiver | |
| 567 // -- esp[0] : return address | |
| 568 // ----------------------------------- | |
| 569 Label miss; | 577 Label miss; |
| 570 | 578 |
| 571 Register receiver = edx; | 579 Register receiver = ReceiverRegister(); |
| 572 Register index = ecx; | 580 Register index = NameRegister(); |
| 573 Register scratch = ebx; | 581 Register scratch = KeyedLoadIC_TempRegister(); |
| 574 Register result = eax; | 582 Register result = eax; |
| 583 ASSERT(!result.is(scratch)); |
| 575 | 584 |
| 576 StringCharAtGenerator char_at_generator(receiver, | 585 StringCharAtGenerator char_at_generator(receiver, |
| 577 index, | 586 index, |
| 578 scratch, | 587 scratch, |
| 579 result, | 588 result, |
| 580 &miss, // When not a string. | 589 &miss, // When not a string. |
| 581 &miss, // When not a number. | 590 &miss, // When not a number. |
| 582 &miss, // When index out of range. | 591 &miss, // When index out of range. |
| 583 STRING_INDEX_IS_ARRAY_INDEX); | 592 STRING_INDEX_IS_ARRAY_INDEX); |
| 584 char_at_generator.GenerateFast(masm); | 593 char_at_generator.GenerateFast(masm); |
| 585 __ ret(0); | 594 __ ret(0); |
| 586 | 595 |
| 587 StubRuntimeCallHelper call_helper; | 596 StubRuntimeCallHelper call_helper; |
| 588 char_at_generator.GenerateSlow(masm, call_helper); | 597 char_at_generator.GenerateSlow(masm, call_helper); |
| 589 | 598 |
| 590 __ bind(&miss); | 599 __ bind(&miss); |
| 591 GenerateMiss(masm); | 600 GenerateMiss(masm); |
| 592 } | 601 } |
| 593 | 602 |
| 594 | 603 |
| 595 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { | 604 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { |
| 596 // ----------- S t a t e ------------- | 605 // Return address is on the stack. |
| 597 // -- ecx : key | |
| 598 // -- edx : receiver | |
| 599 // -- esp[0] : return address | |
| 600 // ----------------------------------- | |
| 601 Label slow; | 606 Label slow; |
| 602 | 607 |
| 608 Register receiver = ReceiverRegister(); |
| 609 Register key = NameRegister(); |
| 610 Register scratch = eax; |
| 611 ASSERT(!scratch.is(receiver) && !scratch.is(key)); |
| 612 |
| 603 // Check that the receiver isn't a smi. | 613 // Check that the receiver isn't a smi. |
| 604 __ JumpIfSmi(edx, &slow); | 614 __ JumpIfSmi(receiver, &slow); |
| 605 | 615 |
| 606 // Check that the key is an array index, that is Uint32. | 616 // Check that the key is an array index, that is Uint32. |
| 607 __ test(ecx, Immediate(kSmiTagMask | kSmiSignMask)); | 617 __ test(key, Immediate(kSmiTagMask | kSmiSignMask)); |
| 608 __ j(not_zero, &slow); | 618 __ j(not_zero, &slow); |
| 609 | 619 |
| 610 // Get the map of the receiver. | 620 // Get the map of the receiver. |
| 611 __ mov(eax, FieldOperand(edx, HeapObject::kMapOffset)); | 621 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 612 | 622 |
| 613 // Check that it has indexed interceptor and access checks | 623 // Check that it has indexed interceptor and access checks |
| 614 // are not enabled for this object. | 624 // are not enabled for this object. |
| 615 __ movzx_b(eax, FieldOperand(eax, Map::kBitFieldOffset)); | 625 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); |
| 616 __ and_(eax, Immediate(kSlowCaseBitFieldMask)); | 626 __ and_(scratch, Immediate(kSlowCaseBitFieldMask)); |
| 617 __ cmp(eax, Immediate(1 << Map::kHasIndexedInterceptor)); | 627 __ cmp(scratch, Immediate(1 << Map::kHasIndexedInterceptor)); |
| 618 __ j(not_zero, &slow); | 628 __ j(not_zero, &slow); |
| 619 | 629 |
| 620 // Everything is fine, call runtime. | 630 // Everything is fine, call runtime. |
| 621 __ pop(eax); | 631 __ pop(scratch); |
| 622 __ push(edx); // receiver | 632 __ push(receiver); // receiver |
| 623 __ push(ecx); // key | 633 __ push(key); // key |
| 624 __ push(eax); // return address | 634 __ push(scratch); // return address |
| 625 | 635 |
| 626 // Perform tail call to the entry. | 636 // Perform tail call to the entry. |
| 627 ExternalReference ref = | 637 ExternalReference ref = |
| 628 ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor), | 638 ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor), |
| 629 masm->isolate()); | 639 masm->isolate()); |
| 630 __ TailCallExternalReference(ref, 2, 1); | 640 __ TailCallExternalReference(ref, 2, 1); |
| 631 | 641 |
| 632 __ bind(&slow); | 642 __ bind(&slow); |
| 633 GenerateMiss(masm); | 643 GenerateMiss(masm); |
| 634 } | 644 } |
| 635 | 645 |
| 636 | 646 |
| 637 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) { | 647 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) { |
| 638 // ----------- S t a t e ------------- | 648 // ----------- S t a t e ------------- |
| 639 // -- ecx : key | 649 // -- ecx : key |
| 640 // -- edx : receiver | 650 // -- edx : receiver |
| 641 // -- esp[0] : return address | 651 // -- esp[0] : return address |
| 642 // ----------------------------------- | 652 // ----------------------------------- |
| 653 ASSERT(edx.is(ReceiverRegister())); |
| 654 ASSERT(ecx.is(NameRegister())); |
| 643 Label slow, notin; | 655 Label slow, notin; |
| 644 Factory* factory = masm->isolate()->factory(); | 656 Factory* factory = masm->isolate()->factory(); |
| 645 Operand mapped_location = | 657 Operand mapped_location = |
| 646 GenerateMappedArgumentsLookup(masm, edx, ecx, ebx, eax, ¬in, &slow); | 658 GenerateMappedArgumentsLookup(masm, edx, ecx, ebx, eax, ¬in, &slow); |
| 647 __ mov(eax, mapped_location); | 659 __ mov(eax, mapped_location); |
| 648 __ Ret(); | 660 __ Ret(); |
| 649 __ bind(¬in); | 661 __ bind(¬in); |
| 650 // The unmapped lookup expects that the parameter map is in ebx. | 662 // The unmapped lookup expects that the parameter map is in ebx. |
| 651 Operand unmapped_location = | 663 Operand unmapped_location = |
| 652 GenerateUnmappedArgumentsLookup(masm, ecx, ebx, eax, &slow); | 664 GenerateUnmappedArgumentsLookup(masm, ecx, ebx, eax, &slow); |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 923 &slow, kDontCheckMap, kIncrementLength); | 935 &slow, kDontCheckMap, kIncrementLength); |
| 924 } | 936 } |
| 925 | 937 |
| 926 | 938 |
| 927 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { | 939 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { |
| 928 // ----------- S t a t e ------------- | 940 // ----------- S t a t e ------------- |
| 929 // -- ecx : name | 941 // -- ecx : name |
| 930 // -- edx : receiver | 942 // -- edx : receiver |
| 931 // -- esp[0] : return address | 943 // -- esp[0] : return address |
| 932 // ----------------------------------- | 944 // ----------------------------------- |
| 945 ASSERT(edx.is(ReceiverRegister())); |
| 946 ASSERT(ecx.is(NameRegister())); |
| 933 | 947 |
| 934 // Probe the stub cache. | 948 // Probe the stub cache. |
| 935 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); | 949 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); |
| 936 masm->isolate()->stub_cache()->GenerateProbe( | 950 masm->isolate()->stub_cache()->GenerateProbe( |
| 937 masm, flags, edx, ecx, ebx, eax); | 951 masm, flags, edx, ecx, ebx, eax); |
| 938 | 952 |
| 939 // Cache miss: Jump to runtime. | 953 // Cache miss: Jump to runtime. |
| 940 GenerateMiss(masm); | 954 GenerateMiss(masm); |
| 941 } | 955 } |
| 942 | 956 |
| 943 | 957 |
| 944 void LoadIC::GenerateNormal(MacroAssembler* masm) { | 958 void LoadIC::GenerateNormal(MacroAssembler* masm) { |
| 945 // ----------- S t a t e ------------- | 959 // ----------- S t a t e ------------- |
| 946 // -- ecx : name | 960 // -- ecx : name |
| 947 // -- edx : receiver | 961 // -- edx : receiver |
| 948 // -- esp[0] : return address | 962 // -- esp[0] : return address |
| 949 // ----------------------------------- | 963 // ----------------------------------- |
| 964 ASSERT(edx.is(ReceiverRegister())); |
| 965 ASSERT(ecx.is(NameRegister())); |
| 966 |
| 950 Label miss, slow; | 967 Label miss, slow; |
| 951 | 968 |
| 952 GenerateNameDictionaryReceiverCheck(masm, edx, eax, ebx, &miss); | 969 GenerateNameDictionaryReceiverCheck(masm, edx, eax, ebx, &miss); |
| 953 | 970 |
| 954 // eax: elements | 971 // eax: elements |
| 955 // Search the dictionary placing the result in eax. | 972 // Search the dictionary placing the result in eax. |
| 956 GenerateDictionaryLoad(masm, &slow, eax, ecx, edi, ebx, eax); | 973 GenerateDictionaryLoad(masm, &slow, eax, ecx, edi, ebx, eax); |
| 957 __ ret(0); | 974 __ ret(0); |
| 958 | 975 |
| 959 // Dictionary load failed, go slow (but don't miss). | 976 // Dictionary load failed, go slow (but don't miss). |
| 960 __ bind(&slow); | 977 __ bind(&slow); |
| 961 GenerateRuntimeGetProperty(masm); | 978 GenerateRuntimeGetProperty(masm); |
| 962 | 979 |
| 963 // Cache miss: Jump to runtime. | 980 // Cache miss: Jump to runtime. |
| 964 __ bind(&miss); | 981 __ bind(&miss); |
| 965 GenerateMiss(masm); | 982 GenerateMiss(masm); |
| 966 } | 983 } |
| 967 | 984 |
| 968 | 985 |
| 969 void LoadIC::GenerateMiss(MacroAssembler* masm) { | 986 void LoadIC::GenerateMiss(MacroAssembler* masm) { |
| 970 // ----------- S t a t e ------------- | 987 // Return address is on the stack. |
| 971 // -- ecx : name | |
| 972 // -- edx : receiver | |
| 973 // -- esp[0] : return address | |
| 974 // ----------------------------------- | |
| 975 | |
| 976 __ IncrementCounter(masm->isolate()->counters()->load_miss(), 1); | 988 __ IncrementCounter(masm->isolate()->counters()->load_miss(), 1); |
| 977 | 989 |
| 978 __ pop(ebx); | 990 __ pop(LoadIC_TempRegister()); |
| 979 __ push(edx); // receiver | 991 __ push(ReceiverRegister()); // receiver |
| 980 __ push(ecx); // name | 992 __ push(NameRegister()); // name |
| 981 __ push(ebx); // return address | 993 __ push(LoadIC_TempRegister()); // return address |
| 982 | 994 |
| 983 // Perform tail call to the entry. | 995 // Perform tail call to the entry. |
| 984 ExternalReference ref = | 996 ExternalReference ref = |
| 985 ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate()); | 997 ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate()); |
| 986 __ TailCallExternalReference(ref, 2, 1); | 998 __ TailCallExternalReference(ref, 2, 1); |
| 987 } | 999 } |
| 988 | 1000 |
| 989 | 1001 |
| 990 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { | 1002 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
| 991 // ----------- S t a t e ------------- | 1003 // Return address is on the stack. |
| 992 // -- ecx : key | 1004 __ pop(LoadIC_TempRegister()); |
| 993 // -- edx : receiver | 1005 __ push(ReceiverRegister()); // receiver |
| 994 // -- esp[0] : return address | 1006 __ push(NameRegister()); // name |
| 995 // ----------------------------------- | 1007 __ push(LoadIC_TempRegister()); // return address |
| 996 | |
| 997 __ pop(ebx); | |
| 998 __ push(edx); // receiver | |
| 999 __ push(ecx); // name | |
| 1000 __ push(ebx); // return address | |
| 1001 | 1008 |
| 1002 // Perform tail call to the entry. | 1009 // Perform tail call to the entry. |
| 1003 __ TailCallRuntime(Runtime::kGetProperty, 2, 1); | 1010 __ TailCallRuntime(Runtime::kGetProperty, 2, 1); |
| 1004 } | 1011 } |
| 1005 | 1012 |
| 1006 | 1013 |
| 1007 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { | 1014 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { |
| 1008 // ----------- S t a t e ------------- | 1015 // Return address is on the stack. |
| 1009 // -- ecx : key | |
| 1010 // -- edx : receiver | |
| 1011 // -- esp[0] : return address | |
| 1012 // ----------------------------------- | |
| 1013 | |
| 1014 __ IncrementCounter(masm->isolate()->counters()->keyed_load_miss(), 1); | 1016 __ IncrementCounter(masm->isolate()->counters()->keyed_load_miss(), 1); |
| 1015 | 1017 |
| 1016 __ pop(ebx); | 1018 __ pop(KeyedLoadIC_TempRegister()); |
| 1017 __ push(edx); // receiver | 1019 __ push(ReceiverRegister()); // receiver |
| 1018 __ push(ecx); // name | 1020 __ push(NameRegister()); // name |
| 1019 __ push(ebx); // return address | 1021 __ push(KeyedLoadIC_TempRegister()); // return address |
| 1020 | 1022 |
| 1021 // Perform tail call to the entry. | 1023 // Perform tail call to the entry. |
| 1022 ExternalReference ref = | 1024 ExternalReference ref = |
| 1023 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate()); | 1025 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate()); |
| 1024 __ TailCallExternalReference(ref, 2, 1); | 1026 __ TailCallExternalReference(ref, 2, 1); |
| 1025 } | 1027 } |
| 1026 | 1028 |
| 1027 | 1029 |
| 1028 // IC register specifications | 1030 // IC register specifications |
| 1029 const Register LoadIC::ReceiverRegister() { return edx; } | 1031 const Register LoadIC::ReceiverRegister() { return edx; } |
| 1030 const Register LoadIC::NameRegister() { return ecx; } | 1032 const Register LoadIC::NameRegister() { return ecx; } |
| 1031 | 1033 |
| 1032 | 1034 |
| 1033 const Register KeyedLoadIC::ReceiverRegister() { | 1035 const Register KeyedLoadIC::ReceiverRegister() { |
| 1034 return LoadIC::ReceiverRegister(); | 1036 return LoadIC::ReceiverRegister(); |
| 1035 } | 1037 } |
| 1036 | 1038 |
| 1037 | 1039 |
| 1038 const Register KeyedLoadIC::NameRegister() { return LoadIC::NameRegister(); } | 1040 const Register KeyedLoadIC::NameRegister() { return LoadIC::NameRegister(); } |
| 1039 | 1041 |
| 1040 | 1042 |
| 1041 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { | 1043 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
| 1042 // ----------- S t a t e ------------- | 1044 // Return address is on the stack. |
| 1043 // -- ecx : key | 1045 __ pop(KeyedLoadIC_TempRegister()); |
| 1044 // -- edx : receiver | 1046 __ push(ReceiverRegister()); // receiver |
| 1045 // -- esp[0] : return address | 1047 __ push(NameRegister()); // name |
| 1046 // ----------------------------------- | 1048 __ push(KeyedLoadIC_TempRegister()); // return address |
| 1047 | |
| 1048 __ pop(ebx); | |
| 1049 __ push(edx); // receiver | |
| 1050 __ push(ecx); // name | |
| 1051 __ push(ebx); // return address | |
| 1052 | 1049 |
| 1053 // Perform tail call to the entry. | 1050 // Perform tail call to the entry. |
| 1054 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); | 1051 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); |
| 1055 } | 1052 } |
| 1056 | 1053 |
| 1057 | 1054 |
| 1058 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { | 1055 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { |
| 1059 // ----------- S t a t e ------------- | 1056 // ----------- S t a t e ------------- |
| 1060 // -- eax : value | 1057 // -- eax : value |
| 1061 // -- ecx : name | 1058 // -- ecx : name |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1294 Condition cc = (check == ENABLE_INLINED_SMI_CHECK) | 1291 Condition cc = (check == ENABLE_INLINED_SMI_CHECK) |
| 1295 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) | 1292 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) |
| 1296 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); | 1293 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); |
| 1297 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 1294 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
| 1298 } | 1295 } |
| 1299 | 1296 |
| 1300 | 1297 |
| 1301 } } // namespace v8::internal | 1298 } } // namespace v8::internal |
| 1302 | 1299 |
| 1303 #endif // V8_TARGET_ARCH_IA32 | 1300 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |