| 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 17 matching lines...) Expand all Loading... |
| 28 // type: holds the receiver instance type on entry. | 28 // type: holds the receiver instance type on entry. |
| 29 __ cmp(type, JS_GLOBAL_OBJECT_TYPE); | 29 __ cmp(type, JS_GLOBAL_OBJECT_TYPE); |
| 30 __ j(equal, global_object); | 30 __ j(equal, global_object); |
| 31 __ cmp(type, JS_BUILTINS_OBJECT_TYPE); | 31 __ cmp(type, JS_BUILTINS_OBJECT_TYPE); |
| 32 __ j(equal, global_object); | 32 __ j(equal, global_object); |
| 33 __ cmp(type, JS_GLOBAL_PROXY_TYPE); | 33 __ cmp(type, JS_GLOBAL_PROXY_TYPE); |
| 34 __ j(equal, global_object); | 34 __ j(equal, global_object); |
| 35 } | 35 } |
| 36 | 36 |
| 37 | 37 |
| 38 // Generated code falls through if the receiver is a regular non-global | |
| 39 // JS object with slow properties and no interceptors. | |
| 40 static void GenerateNameDictionaryReceiverCheck(MacroAssembler* masm, | |
| 41 Register receiver, | |
| 42 Register r0, | |
| 43 Register r1, | |
| 44 Label* miss) { | |
| 45 // Register usage: | |
| 46 // receiver: holds the receiver on entry and is unchanged. | |
| 47 // r0: used to hold receiver instance type. | |
| 48 // Holds the property dictionary on fall through. | |
| 49 // r1: used to hold receivers map. | |
| 50 | |
| 51 // Check that the receiver isn't a smi. | |
| 52 __ JumpIfSmi(receiver, miss); | |
| 53 | |
| 54 // Check that the receiver is a valid JS object. | |
| 55 __ mov(r1, FieldOperand(receiver, HeapObject::kMapOffset)); | |
| 56 __ movzx_b(r0, FieldOperand(r1, Map::kInstanceTypeOffset)); | |
| 57 __ cmp(r0, FIRST_SPEC_OBJECT_TYPE); | |
| 58 __ j(below, miss); | |
| 59 | |
| 60 // If this assert fails, we have to check upper bound too. | |
| 61 STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE); | |
| 62 | |
| 63 GenerateGlobalInstanceTypeCheck(masm, r0, miss); | |
| 64 | |
| 65 // Check for non-global object that requires access check. | |
| 66 __ test_b(FieldOperand(r1, Map::kBitFieldOffset), | |
| 67 (1 << Map::kIsAccessCheckNeeded) | | |
| 68 (1 << Map::kHasNamedInterceptor)); | |
| 69 __ j(not_zero, miss); | |
| 70 | |
| 71 __ mov(r0, FieldOperand(receiver, JSObject::kPropertiesOffset)); | |
| 72 __ CheckMap(r0, masm->isolate()->factory()->hash_table_map(), miss, | |
| 73 DONT_DO_SMI_CHECK); | |
| 74 } | |
| 75 | |
| 76 | |
| 77 // Helper function used to load a property from a dictionary backing | 38 // Helper function used to load a property from a dictionary backing |
| 78 // storage. This function may fail to load a property even though it is | 39 // storage. This function may fail to load a property even though it is |
| 79 // in the dictionary, so code at miss_label must always call a backup | 40 // in the dictionary, so code at miss_label must always call a backup |
| 80 // property load that is complete. This function is safe to call if | 41 // property load that is complete. This function is safe to call if |
| 81 // name is not internalized, and will jump to the miss_label in that | 42 // name is not internalized, and will jump to the miss_label in that |
| 82 // case. The generated code assumes that the receiver has slow | 43 // case. The generated code assumes that the receiver has slow |
| 83 // properties, is not a global object and does not have interceptors. | 44 // properties, is not a global object and does not have interceptors. |
| 84 static void GenerateDictionaryLoad(MacroAssembler* masm, | 45 static void GenerateDictionaryLoad(MacroAssembler* masm, |
| 85 Label* miss_label, | 46 Label* miss_label, |
| 86 Register elements, | 47 Register elements, |
| (...skipping 846 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 933 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); | 894 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); |
| 934 masm->isolate()->stub_cache()->GenerateProbe( | 895 masm->isolate()->stub_cache()->GenerateProbe( |
| 935 masm, flags, receiver, name, ebx, eax); | 896 masm, flags, receiver, name, ebx, eax); |
| 936 | 897 |
| 937 // Cache miss: Jump to runtime. | 898 // Cache miss: Jump to runtime. |
| 938 GenerateMiss(masm); | 899 GenerateMiss(masm); |
| 939 } | 900 } |
| 940 | 901 |
| 941 | 902 |
| 942 void LoadIC::GenerateNormal(MacroAssembler* masm) { | 903 void LoadIC::GenerateNormal(MacroAssembler* masm) { |
| 943 // ----------- S t a t e ------------- | 904 Register dictionary = eax; |
| 944 // -- ecx : name | 905 ASSERT(!dictionary.is(ReceiverRegister())); |
| 945 // -- edx : receiver | 906 ASSERT(!dictionary.is(NameRegister())); |
| 946 // -- esp[0] : return address | |
| 947 // ----------------------------------- | |
| 948 ASSERT(edx.is(ReceiverRegister())); | |
| 949 ASSERT(ecx.is(NameRegister())); | |
| 950 | 907 |
| 951 Label miss, slow; | 908 Label slow; |
| 952 | 909 |
| 953 GenerateNameDictionaryReceiverCheck(masm, edx, eax, ebx, &miss); | 910 __ mov(dictionary, |
| 954 | 911 FieldOperand(ReceiverRegister(), JSObject::kPropertiesOffset)); |
| 955 // eax: elements | 912 GenerateDictionaryLoad(masm, &slow, dictionary, NameRegister(), edi, ebx, |
| 956 // Search the dictionary placing the result in eax. | 913 eax); |
| 957 GenerateDictionaryLoad(masm, &slow, eax, ecx, edi, ebx, eax); | |
| 958 __ ret(0); | 914 __ ret(0); |
| 959 | 915 |
| 960 // Dictionary load failed, go slow (but don't miss). | 916 // Dictionary load failed, go slow (but don't miss). |
| 961 __ bind(&slow); | 917 __ bind(&slow); |
| 962 GenerateRuntimeGetProperty(masm); | 918 GenerateRuntimeGetProperty(masm); |
| 963 | |
| 964 // Cache miss: Jump to runtime. | |
| 965 __ bind(&miss); | |
| 966 GenerateMiss(masm); | |
| 967 } | 919 } |
| 968 | 920 |
| 969 | 921 |
| 970 static void LoadIC_PushArgs(MacroAssembler* masm) { | 922 static void LoadIC_PushArgs(MacroAssembler* masm) { |
| 971 Register receiver = LoadIC::ReceiverRegister(); | 923 Register receiver = LoadIC::ReceiverRegister(); |
| 972 Register name = LoadIC::NameRegister(); | 924 Register name = LoadIC::NameRegister(); |
| 973 ASSERT(!ebx.is(receiver) && !ebx.is(name)); | 925 ASSERT(!ebx.is(receiver) && !ebx.is(name)); |
| 974 | 926 |
| 975 __ pop(ebx); | 927 __ pop(ebx); |
| 976 __ push(receiver); | 928 __ push(receiver); |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1080 StoreIC_PushArgs(masm); | 1032 StoreIC_PushArgs(masm); |
| 1081 | 1033 |
| 1082 // Perform tail call to the entry. | 1034 // Perform tail call to the entry. |
| 1083 ExternalReference ref = | 1035 ExternalReference ref = |
| 1084 ExternalReference(IC_Utility(kStoreIC_Miss), masm->isolate()); | 1036 ExternalReference(IC_Utility(kStoreIC_Miss), masm->isolate()); |
| 1085 __ TailCallExternalReference(ref, 3, 1); | 1037 __ TailCallExternalReference(ref, 3, 1); |
| 1086 } | 1038 } |
| 1087 | 1039 |
| 1088 | 1040 |
| 1089 void StoreIC::GenerateNormal(MacroAssembler* masm) { | 1041 void StoreIC::GenerateNormal(MacroAssembler* masm) { |
| 1090 // Return address is on the stack. | 1042 Label restore_miss; |
| 1091 Label miss, restore_miss; | |
| 1092 Register receiver = ReceiverRegister(); | 1043 Register receiver = ReceiverRegister(); |
| 1093 Register name = NameRegister(); | 1044 Register name = NameRegister(); |
| 1094 Register value = ValueRegister(); | 1045 Register value = ValueRegister(); |
| 1046 Register dictionary = ebx; |
| 1095 | 1047 |
| 1096 GenerateNameDictionaryReceiverCheck(masm, receiver, ebx, edi, &miss); | 1048 __ mov(dictionary, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
| 1097 | 1049 |
| 1098 // A lot of registers are needed for storing to slow case | 1050 // A lot of registers are needed for storing to slow case |
| 1099 // objects. Push and restore receiver but rely on | 1051 // objects. Push and restore receiver but rely on |
| 1100 // GenerateDictionaryStore preserving the value and name. | 1052 // GenerateDictionaryStore preserving the value and name. |
| 1101 __ push(receiver); | 1053 __ push(receiver); |
| 1102 GenerateDictionaryStore(masm, &restore_miss, ebx, name, value, receiver, edi); | 1054 GenerateDictionaryStore(masm, &restore_miss, dictionary, name, value, |
| 1055 receiver, edi); |
| 1103 __ Drop(1); | 1056 __ Drop(1); |
| 1104 Counters* counters = masm->isolate()->counters(); | 1057 Counters* counters = masm->isolate()->counters(); |
| 1105 __ IncrementCounter(counters->store_normal_hit(), 1); | 1058 __ IncrementCounter(counters->store_normal_hit(), 1); |
| 1106 __ ret(0); | 1059 __ ret(0); |
| 1107 | 1060 |
| 1108 __ bind(&restore_miss); | 1061 __ bind(&restore_miss); |
| 1109 __ pop(receiver); | 1062 __ pop(receiver); |
| 1110 | |
| 1111 __ bind(&miss); | |
| 1112 __ IncrementCounter(counters->store_normal_miss(), 1); | 1063 __ IncrementCounter(counters->store_normal_miss(), 1); |
| 1113 GenerateMiss(masm); | 1064 GenerateMiss(masm); |
| 1114 } | 1065 } |
| 1115 | 1066 |
| 1116 | 1067 |
| 1117 void StoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm, | 1068 void StoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm, |
| 1118 StrictMode strict_mode) { | 1069 StrictMode strict_mode) { |
| 1119 // Return address is on the stack. | 1070 // Return address is on the stack. |
| 1120 ASSERT(!ebx.is(ReceiverRegister()) && !ebx.is(NameRegister()) && | 1071 ASSERT(!ebx.is(ReceiverRegister()) && !ebx.is(NameRegister()) && |
| 1121 !ebx.is(ValueRegister())); | 1072 !ebx.is(ValueRegister())); |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1246 Condition cc = (check == ENABLE_INLINED_SMI_CHECK) | 1197 Condition cc = (check == ENABLE_INLINED_SMI_CHECK) |
| 1247 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) | 1198 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) |
| 1248 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); | 1199 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); |
| 1249 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 1200 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
| 1250 } | 1201 } |
| 1251 | 1202 |
| 1252 | 1203 |
| 1253 } } // namespace v8::internal | 1204 } } // namespace v8::internal |
| 1254 | 1205 |
| 1255 #endif // V8_TARGET_ARCH_IA32 | 1206 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |