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