| 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_X64 | 7 #if V8_TARGET_ARCH_X64 |
| 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 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 325 } | 325 } |
| 326 | 326 |
| 327 | 327 |
| 328 | 328 |
| 329 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 329 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
| 330 // ----------- S t a t e ------------- | 330 // ----------- S t a t e ------------- |
| 331 // -- rax : key | 331 // -- rax : key |
| 332 // -- rdx : receiver | 332 // -- rdx : receiver |
| 333 // -- rsp[0] : return address | 333 // -- rsp[0] : return address |
| 334 // ----------------------------------- | 334 // ----------------------------------- |
| 335 ASSERT(rdx.is(ReceiverRegister())); |
| 336 ASSERT(rax.is(NameRegister())); |
| 335 Label slow, check_name, index_smi, index_name, property_array_property; | 337 Label slow, check_name, index_smi, index_name, property_array_property; |
| 336 Label probe_dictionary, check_number_dictionary; | 338 Label probe_dictionary, check_number_dictionary; |
| 337 | 339 |
| 338 // Check that the key is a smi. | 340 // Check that the key is a smi. |
| 339 __ JumpIfNotSmi(rax, &check_name); | 341 __ JumpIfNotSmi(rax, &check_name); |
| 340 __ bind(&index_smi); | 342 __ bind(&index_smi); |
| 341 // Now the key is known to be a smi. This place is also jumped to from below | 343 // Now the key is known to be a smi. This place is also jumped to from below |
| 342 // where a numeric string is converted to a smi. | 344 // where a numeric string is converted to a smi. |
| 343 | 345 |
| 344 GenerateKeyedLoadReceiverCheck( | 346 GenerateKeyedLoadReceiverCheck( |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 483 __ IncrementCounter(counters->keyed_load_generic_symbol(), 1); | 485 __ IncrementCounter(counters->keyed_load_generic_symbol(), 1); |
| 484 __ ret(0); | 486 __ ret(0); |
| 485 | 487 |
| 486 __ bind(&index_name); | 488 __ bind(&index_name); |
| 487 __ IndexFromHash(rbx, rax); | 489 __ IndexFromHash(rbx, rax); |
| 488 __ jmp(&index_smi); | 490 __ jmp(&index_smi); |
| 489 } | 491 } |
| 490 | 492 |
| 491 | 493 |
| 492 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { | 494 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { |
| 493 // ----------- S t a t e ------------- | 495 // Return address is on the stack. |
| 494 // -- rax : key | |
| 495 // -- rdx : receiver | |
| 496 // -- rsp[0] : return address | |
| 497 // ----------------------------------- | |
| 498 Label miss; | 496 Label miss; |
| 499 | 497 |
| 500 Register receiver = rdx; | 498 Register receiver = ReceiverRegister(); |
| 501 Register index = rax; | 499 Register index = NameRegister(); |
| 502 Register scratch = rcx; | 500 Register scratch = rcx; |
| 503 Register result = rax; | 501 Register result = rax; |
| 502 ASSERT(!scratch.is(receiver) && !scratch.is(index)); |
| 504 | 503 |
| 505 StringCharAtGenerator char_at_generator(receiver, | 504 StringCharAtGenerator char_at_generator(receiver, |
| 506 index, | 505 index, |
| 507 scratch, | 506 scratch, |
| 508 result, | 507 result, |
| 509 &miss, // When not a string. | 508 &miss, // When not a string. |
| 510 &miss, // When not a number. | 509 &miss, // When not a number. |
| 511 &miss, // When index out of range. | 510 &miss, // When index out of range. |
| 512 STRING_INDEX_IS_ARRAY_INDEX); | 511 STRING_INDEX_IS_ARRAY_INDEX); |
| 513 char_at_generator.GenerateFast(masm); | 512 char_at_generator.GenerateFast(masm); |
| 514 __ ret(0); | 513 __ ret(0); |
| 515 | 514 |
| 516 StubRuntimeCallHelper call_helper; | 515 StubRuntimeCallHelper call_helper; |
| 517 char_at_generator.GenerateSlow(masm, call_helper); | 516 char_at_generator.GenerateSlow(masm, call_helper); |
| 518 | 517 |
| 519 __ bind(&miss); | 518 __ bind(&miss); |
| 520 GenerateMiss(masm); | 519 GenerateMiss(masm); |
| 521 } | 520 } |
| 522 | 521 |
| 523 | 522 |
| 524 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { | 523 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { |
| 525 // ----------- S t a t e ------------- | 524 // Return address is on the stack. |
| 526 // -- rax : key | |
| 527 // -- rdx : receiver | |
| 528 // -- rsp[0] : return address | |
| 529 // ----------------------------------- | |
| 530 Label slow; | 525 Label slow; |
| 531 | 526 |
| 527 Register receiver = ReceiverRegister(); |
| 528 Register key = NameRegister(); |
| 529 Register scratch = rcx; |
| 530 ASSERT(!scratch.is(receiver) && !scratch.is(key)); |
| 531 |
| 532 // Check that the receiver isn't a smi. | 532 // Check that the receiver isn't a smi. |
| 533 __ JumpIfSmi(rdx, &slow); | 533 __ JumpIfSmi(receiver, &slow); |
| 534 | 534 |
| 535 // Check that the key is an array index, that is Uint32. | 535 // Check that the key is an array index, that is Uint32. |
| 536 STATIC_ASSERT(kSmiValueSize <= 32); | 536 STATIC_ASSERT(kSmiValueSize <= 32); |
| 537 __ JumpUnlessNonNegativeSmi(rax, &slow); | 537 __ JumpUnlessNonNegativeSmi(key, &slow); |
| 538 | 538 |
| 539 // Get the map of the receiver. | 539 // Get the map of the receiver. |
| 540 __ movp(rcx, FieldOperand(rdx, HeapObject::kMapOffset)); | 540 __ movp(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 541 | 541 |
| 542 // Check that it has indexed interceptor and access checks | 542 // Check that it has indexed interceptor and access checks |
| 543 // are not enabled for this object. | 543 // are not enabled for this object. |
| 544 __ movb(rcx, FieldOperand(rcx, Map::kBitFieldOffset)); | 544 __ movb(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); |
| 545 __ andb(rcx, Immediate(kSlowCaseBitFieldMask)); | 545 __ andb(scratch, Immediate(kSlowCaseBitFieldMask)); |
| 546 __ cmpb(rcx, Immediate(1 << Map::kHasIndexedInterceptor)); | 546 __ cmpb(scratch, Immediate(1 << Map::kHasIndexedInterceptor)); |
| 547 __ j(not_zero, &slow); | 547 __ j(not_zero, &slow); |
| 548 | 548 |
| 549 // Everything is fine, call runtime. | 549 // Everything is fine, call runtime. |
| 550 __ PopReturnAddressTo(rcx); | 550 __ PopReturnAddressTo(scratch); |
| 551 __ Push(rdx); // receiver | 551 __ Push(receiver); // receiver |
| 552 __ Push(rax); // key | 552 __ Push(key); // key |
| 553 __ PushReturnAddressFrom(rcx); | 553 __ PushReturnAddressFrom(scratch); |
| 554 | 554 |
| 555 // Perform tail call to the entry. | 555 // Perform tail call to the entry. |
| 556 __ TailCallExternalReference( | 556 __ TailCallExternalReference( |
| 557 ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor), | 557 ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor), |
| 558 masm->isolate()), | 558 masm->isolate()), |
| 559 2, | 559 2, |
| 560 1); | 560 1); |
| 561 | 561 |
| 562 __ bind(&slow); | 562 __ bind(&slow); |
| 563 GenerateMiss(masm); | 563 GenerateMiss(masm); |
| (...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 885 FixedArray::kHeaderSize); | 885 FixedArray::kHeaderSize); |
| 886 } | 886 } |
| 887 | 887 |
| 888 | 888 |
| 889 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) { | 889 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) { |
| 890 // ----------- S t a t e ------------- | 890 // ----------- S t a t e ------------- |
| 891 // -- rax : key | 891 // -- rax : key |
| 892 // -- rdx : receiver | 892 // -- rdx : receiver |
| 893 // -- rsp[0] : return address | 893 // -- rsp[0] : return address |
| 894 // ----------------------------------- | 894 // ----------------------------------- |
| 895 ASSERT(rdx.is(ReceiverRegister())); |
| 896 ASSERT(rax.is(NameRegister())); |
| 895 Label slow, notin; | 897 Label slow, notin; |
| 896 Operand mapped_location = | 898 Operand mapped_location = |
| 897 GenerateMappedArgumentsLookup( | 899 GenerateMappedArgumentsLookup( |
| 898 masm, rdx, rax, rbx, rcx, rdi, ¬in, &slow); | 900 masm, rdx, rax, rbx, rcx, rdi, ¬in, &slow); |
| 899 __ movp(rax, mapped_location); | 901 __ movp(rax, mapped_location); |
| 900 __ Ret(); | 902 __ Ret(); |
| 901 __ bind(¬in); | 903 __ bind(¬in); |
| 902 // The unmapped lookup expects that the parameter map is in rbx. | 904 // The unmapped lookup expects that the parameter map is in rbx. |
| 903 Operand unmapped_location = | 905 Operand unmapped_location = |
| 904 GenerateUnmappedArgumentsLookup(masm, rax, rbx, rcx, &slow); | 906 GenerateUnmappedArgumentsLookup(masm, rax, rbx, rcx, &slow); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 949 GenerateMiss(masm); | 951 GenerateMiss(masm); |
| 950 } | 952 } |
| 951 | 953 |
| 952 | 954 |
| 953 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { | 955 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { |
| 954 // ----------- S t a t e ------------- | 956 // ----------- S t a t e ------------- |
| 955 // -- rax : receiver | 957 // -- rax : receiver |
| 956 // -- rcx : name | 958 // -- rcx : name |
| 957 // -- rsp[0] : return address | 959 // -- rsp[0] : return address |
| 958 // ----------------------------------- | 960 // ----------------------------------- |
| 961 ASSERT(rax.is(ReceiverRegister())); |
| 962 ASSERT(rcx.is(NameRegister())); |
| 959 | 963 |
| 960 // Probe the stub cache. | 964 // Probe the stub cache. |
| 961 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); | 965 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); |
| 962 masm->isolate()->stub_cache()->GenerateProbe( | 966 masm->isolate()->stub_cache()->GenerateProbe( |
| 963 masm, flags, rax, rcx, rbx, rdx); | 967 masm, flags, rax, rcx, rbx, rdx); |
| 964 | 968 |
| 965 GenerateMiss(masm); | 969 GenerateMiss(masm); |
| 966 } | 970 } |
| 967 | 971 |
| 968 | 972 |
| 969 void LoadIC::GenerateNormal(MacroAssembler* masm) { | 973 void LoadIC::GenerateNormal(MacroAssembler* masm) { |
| 970 // ----------- S t a t e ------------- | 974 // ----------- S t a t e ------------- |
| 971 // -- rax : receiver | 975 // -- rax : receiver |
| 972 // -- rcx : name | 976 // -- rcx : name |
| 973 // -- rsp[0] : return address | 977 // -- rsp[0] : return address |
| 974 // ----------------------------------- | 978 // ----------------------------------- |
| 979 ASSERT(rax.is(ReceiverRegister())); |
| 980 ASSERT(rcx.is(NameRegister())); |
| 975 Label miss, slow; | 981 Label miss, slow; |
| 976 | 982 |
| 977 GenerateNameDictionaryReceiverCheck(masm, rax, rdx, rbx, &miss); | 983 GenerateNameDictionaryReceiverCheck(masm, rax, rdx, rbx, &miss); |
| 978 | 984 |
| 979 // rdx: elements | 985 // rdx: elements |
| 980 // Search the dictionary placing the result in rax. | 986 // Search the dictionary placing the result in rax. |
| 981 GenerateDictionaryLoad(masm, &slow, rdx, rcx, rbx, rdi, rax); | 987 GenerateDictionaryLoad(masm, &slow, rdx, rcx, rbx, rdi, rax); |
| 982 __ ret(0); | 988 __ ret(0); |
| 983 | 989 |
| 984 // Dictionary load failed, go slow (but don't miss). | 990 // Dictionary load failed, go slow (but don't miss). |
| 985 __ bind(&slow); | 991 __ bind(&slow); |
| 986 GenerateRuntimeGetProperty(masm); | 992 GenerateRuntimeGetProperty(masm); |
| 987 | 993 |
| 988 // Cache miss: Jump to runtime. | 994 // Cache miss: Jump to runtime. |
| 989 __ bind(&miss); | 995 __ bind(&miss); |
| 990 GenerateMiss(masm); | 996 GenerateMiss(masm); |
| 991 } | 997 } |
| 992 | 998 |
| 993 | 999 |
| 1000 // A register that isn't one of the parameters to the load ic. |
| 1001 static const Register LoadIC_TempRegister() { return rbx; } |
| 1002 |
| 1003 |
| 1004 static const Register KeyedLoadIC_TempRegister() { |
| 1005 return rbx; |
| 1006 } |
| 1007 |
| 1008 |
| 994 void LoadIC::GenerateMiss(MacroAssembler* masm) { | 1009 void LoadIC::GenerateMiss(MacroAssembler* masm) { |
| 995 // ----------- S t a t e ------------- | 1010 // The return address is on the stack. |
| 996 // -- rax : receiver | |
| 997 // -- rcx : name | |
| 998 // -- rsp[0] : return address | |
| 999 // ----------------------------------- | |
| 1000 | 1011 |
| 1001 Counters* counters = masm->isolate()->counters(); | 1012 Counters* counters = masm->isolate()->counters(); |
| 1002 __ IncrementCounter(counters->load_miss(), 1); | 1013 __ IncrementCounter(counters->load_miss(), 1); |
| 1003 | 1014 |
| 1004 __ PopReturnAddressTo(rbx); | 1015 __ PopReturnAddressTo(LoadIC_TempRegister()); |
| 1005 __ Push(rax); // receiver | 1016 __ Push(ReceiverRegister()); // receiver |
| 1006 __ Push(rcx); // name | 1017 __ Push(NameRegister()); // name |
| 1007 __ PushReturnAddressFrom(rbx); | 1018 __ PushReturnAddressFrom(LoadIC_TempRegister()); |
| 1008 | 1019 |
| 1009 // Perform tail call to the entry. | 1020 // Perform tail call to the entry. |
| 1010 ExternalReference ref = | 1021 ExternalReference ref = |
| 1011 ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate()); | 1022 ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate()); |
| 1012 __ TailCallExternalReference(ref, 2, 1); | 1023 __ TailCallExternalReference(ref, 2, 1); |
| 1013 } | 1024 } |
| 1014 | 1025 |
| 1015 | 1026 |
| 1016 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { | 1027 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
| 1017 // ----------- S t a t e ------------- | 1028 // The return address is on the stack. |
| 1018 // -- rax : receiver | |
| 1019 // -- rcx : name | |
| 1020 // -- rsp[0] : return address | |
| 1021 // ----------------------------------- | |
| 1022 | 1029 |
| 1023 __ PopReturnAddressTo(rbx); | 1030 __ PopReturnAddressTo(LoadIC_TempRegister()); |
| 1024 __ Push(rax); // receiver | 1031 __ Push(ReceiverRegister()); // receiver |
| 1025 __ Push(rcx); // name | 1032 __ Push(NameRegister()); // name |
| 1026 __ PushReturnAddressFrom(rbx); | 1033 __ PushReturnAddressFrom(LoadIC_TempRegister()); |
| 1027 | 1034 |
| 1028 // Perform tail call to the entry. | 1035 // Perform tail call to the entry. |
| 1029 __ TailCallRuntime(Runtime::kGetProperty, 2, 1); | 1036 __ TailCallRuntime(Runtime::kGetProperty, 2, 1); |
| 1030 } | 1037 } |
| 1031 | 1038 |
| 1032 | 1039 |
| 1033 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { | 1040 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { |
| 1034 // ----------- S t a t e ------------- | 1041 // The return address is on the stack. |
| 1035 // -- rax : key | |
| 1036 // -- rdx : receiver | |
| 1037 // -- rsp[0] : return address | |
| 1038 // ----------------------------------- | |
| 1039 | |
| 1040 Counters* counters = masm->isolate()->counters(); | 1042 Counters* counters = masm->isolate()->counters(); |
| 1041 __ IncrementCounter(counters->keyed_load_miss(), 1); | 1043 __ IncrementCounter(counters->keyed_load_miss(), 1); |
| 1042 | 1044 |
| 1043 __ PopReturnAddressTo(rbx); | 1045 __ PopReturnAddressTo(KeyedLoadIC_TempRegister()); |
| 1044 __ Push(rdx); // receiver | 1046 __ Push(ReceiverRegister()); // receiver |
| 1045 __ Push(rax); // name | 1047 __ Push(NameRegister()); // name |
| 1046 __ PushReturnAddressFrom(rbx); | 1048 __ PushReturnAddressFrom(KeyedLoadIC_TempRegister()); |
| 1047 | 1049 |
| 1048 // Perform tail call to the entry. | 1050 // Perform tail call to the entry. |
| 1049 ExternalReference ref = | 1051 ExternalReference ref = |
| 1050 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate()); | 1052 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate()); |
| 1051 __ TailCallExternalReference(ref, 2, 1); | 1053 __ TailCallExternalReference(ref, 2, 1); |
| 1052 } | 1054 } |
| 1053 | 1055 |
| 1054 | 1056 |
| 1055 // IC register specifications | 1057 // IC register specifications |
| 1056 const Register LoadIC::ReceiverRegister() { return rax; } | 1058 const Register LoadIC::ReceiverRegister() { return rax; } |
| 1057 const Register LoadIC::NameRegister() { return rcx; } | 1059 const Register LoadIC::NameRegister() { return rcx; } |
| 1058 const Register KeyedLoadIC::ReceiverRegister() { return rdx; } | 1060 const Register KeyedLoadIC::ReceiverRegister() { return rdx; } |
| 1059 const Register KeyedLoadIC::NameRegister() { return rax; } | 1061 const Register KeyedLoadIC::NameRegister() { return rax; } |
| 1060 | 1062 |
| 1061 | 1063 |
| 1062 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { | 1064 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
| 1063 // ----------- S t a t e ------------- | 1065 // The return address is on the stack. |
| 1064 // -- rax : key | |
| 1065 // -- rdx : receiver | |
| 1066 // -- rsp[0] : return address | |
| 1067 // ----------------------------------- | |
| 1068 | 1066 |
| 1069 __ PopReturnAddressTo(rbx); | 1067 __ PopReturnAddressTo(KeyedLoadIC_TempRegister()); |
| 1070 __ Push(rdx); // receiver | 1068 __ Push(ReceiverRegister()); // receiver |
| 1071 __ Push(rax); // name | 1069 __ Push(NameRegister()); // name |
| 1072 __ PushReturnAddressFrom(rbx); | 1070 __ PushReturnAddressFrom(KeyedLoadIC_TempRegister()); |
| 1073 | 1071 |
| 1074 // Perform tail call to the entry. | 1072 // Perform tail call to the entry. |
| 1075 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); | 1073 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); |
| 1076 } | 1074 } |
| 1077 | 1075 |
| 1078 | 1076 |
| 1079 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { | 1077 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { |
| 1080 // ----------- S t a t e ------------- | 1078 // ----------- S t a t e ------------- |
| 1081 // -- rax : value | 1079 // -- rax : value |
| 1082 // -- rcx : name | 1080 // -- rcx : name |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1309 Condition cc = (check == ENABLE_INLINED_SMI_CHECK) | 1307 Condition cc = (check == ENABLE_INLINED_SMI_CHECK) |
| 1310 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) | 1308 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) |
| 1311 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); | 1309 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); |
| 1312 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 1310 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
| 1313 } | 1311 } |
| 1314 | 1312 |
| 1315 | 1313 |
| 1316 } } // namespace v8::internal | 1314 } } // namespace v8::internal |
| 1317 | 1315 |
| 1318 #endif // V8_TARGET_ARCH_X64 | 1316 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |