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 |