Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(622)

Side by Side Diff: src/ia32/ic-ia32.cc

Issue 148223002: Remove CallICs (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Update test262 status file Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/full-codegen-ia32.cc ('k') | src/ia32/lithium-codegen-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 929 matching lines...) Expand 10 before | Expand all | Expand 10 after
940 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. 940 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis.
941 __ j(above_equal, &extra); 941 __ j(above_equal, &extra);
942 942
943 KeyedStoreGenerateGenericHelper(masm, &fast_object, &fast_double, 943 KeyedStoreGenerateGenericHelper(masm, &fast_object, &fast_double,
944 &slow, kCheckMap, kDontIncrementLength); 944 &slow, kCheckMap, kDontIncrementLength);
945 KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow, 945 KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow,
946 &slow, kDontCheckMap, kIncrementLength); 946 &slow, kDontCheckMap, kIncrementLength);
947 } 947 }
948 948
949 949
950 // The generated code does not accept smi keys. 950 void LoadIC::GenerateMegamorphic(MacroAssembler* masm,
951 // The generated code falls through if both probes miss.
952 void CallICBase::GenerateMonomorphicCacheProbe(MacroAssembler* masm,
953 int argc,
954 Code::Kind kind,
955 ExtraICState extra_state) {
956 // ----------- S t a t e -------------
957 // -- ecx : name
958 // -- edx : receiver
959 // -----------------------------------
960 Label number, non_number, non_string, boolean, probe, miss;
961
962 // Probe the stub cache.
963 Code::Flags flags = Code::ComputeFlags(kind,
964 MONOMORPHIC,
965 extra_state,
966 Code::NORMAL,
967 argc);
968 Isolate* isolate = masm->isolate();
969 isolate->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx, eax);
970
971 // If the stub cache probing failed, the receiver might be a value.
972 // For value objects, we use the map of the prototype objects for
973 // the corresponding JSValue for the cache and that is what we need
974 // to probe.
975 //
976 // Check for number.
977 __ JumpIfSmi(edx, &number);
978 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ebx);
979 __ j(not_equal, &non_number);
980 __ bind(&number);
981 StubCompiler::GenerateLoadGlobalFunctionPrototype(
982 masm, Context::NUMBER_FUNCTION_INDEX, edx);
983 __ jmp(&probe);
984
985 // Check for string.
986 __ bind(&non_number);
987 __ CmpInstanceType(ebx, FIRST_NONSTRING_TYPE);
988 __ j(above_equal, &non_string);
989 StubCompiler::GenerateLoadGlobalFunctionPrototype(
990 masm, Context::STRING_FUNCTION_INDEX, edx);
991 __ jmp(&probe);
992
993 // Check for boolean.
994 __ bind(&non_string);
995 __ cmp(edx, isolate->factory()->true_value());
996 __ j(equal, &boolean);
997 __ cmp(edx, isolate->factory()->false_value());
998 __ j(not_equal, &miss);
999 __ bind(&boolean);
1000 StubCompiler::GenerateLoadGlobalFunctionPrototype(
1001 masm, Context::BOOLEAN_FUNCTION_INDEX, edx);
1002
1003 // Probe the stub cache for the value object.
1004 __ bind(&probe);
1005 isolate->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx, no_reg);
1006 __ bind(&miss);
1007 }
1008
1009
1010 static void GenerateFunctionTailCall(MacroAssembler* masm,
1011 int argc,
1012 Label* miss) {
1013 // ----------- S t a t e -------------
1014 // -- ecx : name
1015 // -- edi : function
1016 // -- esp[0] : return address
1017 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1018 // -- ...
1019 // -- esp[(argc + 1) * 4] : receiver
1020 // -----------------------------------
1021
1022 // Check that the result is not a smi.
1023 __ JumpIfSmi(edi, miss);
1024
1025 // Check that the value is a JavaScript function, fetching its map into eax.
1026 __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax);
1027 __ j(not_equal, miss);
1028
1029 // Invoke the function.
1030 ParameterCount actual(argc);
1031 __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper());
1032 }
1033
1034
1035 // The generated code falls through if the call should be handled by runtime.
1036 void CallICBase::GenerateNormal(MacroAssembler* masm, int argc) {
1037 // ----------- S t a t e -------------
1038 // -- ecx : name
1039 // -- esp[0] : return address
1040 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1041 // -- ...
1042 // -- esp[(argc + 1) * 4] : receiver
1043 // -----------------------------------
1044 Label miss;
1045
1046 // Get the receiver of the function from the stack; 1 ~ return address.
1047 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1048
1049 GenerateNameDictionaryReceiverCheck(masm, edx, eax, ebx, &miss);
1050
1051 // eax: elements
1052 // Search the dictionary placing the result in edi.
1053 GenerateDictionaryLoad(masm, &miss, eax, ecx, edi, ebx, edi);
1054 GenerateFunctionTailCall(masm, argc, &miss);
1055
1056 __ bind(&miss);
1057 }
1058
1059
1060 void CallICBase::GenerateMiss(MacroAssembler* masm,
1061 int argc,
1062 IC::UtilityId id,
1063 ExtraICState extra_state) {
1064 // ----------- S t a t e -------------
1065 // -- ecx : name
1066 // -- esp[0] : return address
1067 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1068 // -- ...
1069 // -- esp[(argc + 1) * 4] : receiver
1070 // -----------------------------------
1071
1072 Counters* counters = masm->isolate()->counters();
1073 if (id == IC::kCallIC_Miss) {
1074 __ IncrementCounter(counters->call_miss(), 1);
1075 } else {
1076 __ IncrementCounter(counters->keyed_call_miss(), 1);
1077 }
1078
1079 // Get the receiver of the function from the stack; 1 ~ return address.
1080 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1081
1082 {
1083 FrameScope scope(masm, StackFrame::INTERNAL);
1084
1085 // Push the receiver and the name of the function.
1086 __ push(edx);
1087 __ push(ecx);
1088
1089 // Call the entry.
1090 CEntryStub stub(1);
1091 __ mov(eax, Immediate(2));
1092 __ mov(ebx, Immediate(ExternalReference(IC_Utility(id), masm->isolate())));
1093 __ CallStub(&stub);
1094
1095 // Move result to edi and exit the internal frame.
1096 __ mov(edi, eax);
1097 }
1098
1099 // Check if the receiver is a global object of some sort.
1100 // This can happen only for regular CallIC but not KeyedCallIC.
1101 if (id == IC::kCallIC_Miss) {
1102 Label invoke, global;
1103 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); // receiver
1104 __ JumpIfSmi(edx, &invoke, Label::kNear);
1105 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
1106 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
1107 __ cmp(ebx, JS_GLOBAL_OBJECT_TYPE);
1108 __ j(equal, &global, Label::kNear);
1109 __ cmp(ebx, JS_BUILTINS_OBJECT_TYPE);
1110 __ j(not_equal, &invoke, Label::kNear);
1111
1112 // Patch the receiver on the stack.
1113 __ bind(&global);
1114 __ mov(Operand(esp, (argc + 1) * kPointerSize),
1115 masm->isolate()->factory()->undefined_value());
1116
1117 __ bind(&invoke);
1118 }
1119
1120 // Invoke the function.
1121 ParameterCount actual(argc);
1122 __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper());
1123 }
1124
1125
1126 void CallIC::GenerateMegamorphic(MacroAssembler* masm,
1127 int argc,
1128 ExtraICState extra_state) { 951 ExtraICState extra_state) {
1129 // ----------- S t a t e ------------- 952 // ----------- S t a t e -------------
1130 // -- ecx : name
1131 // -- esp[0] : return address
1132 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1133 // -- ...
1134 // -- esp[(argc + 1) * 4] : receiver
1135 // -----------------------------------
1136
1137 // Get the receiver of the function from the stack; 1 ~ return address.
1138 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1139 CallICBase::GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC,
1140 extra_state);
1141
1142 GenerateMiss(masm, argc, extra_state);
1143 }
1144
1145
1146 void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
1147 // ----------- S t a t e -------------
1148 // -- ecx : name
1149 // -- esp[0] : return address
1150 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1151 // -- ...
1152 // -- esp[(argc + 1) * 4] : receiver
1153 // -----------------------------------
1154
1155 // Get the receiver of the function from the stack; 1 ~ return address.
1156 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1157
1158 Label do_call, slow_call, slow_load, slow_reload_receiver;
1159 Label check_number_dictionary, check_name, lookup_monomorphic_cache;
1160 Label index_smi, index_name;
1161
1162 // Check that the key is a smi.
1163 __ JumpIfNotSmi(ecx, &check_name);
1164
1165 __ bind(&index_smi);
1166 // Now the key is known to be a smi. This place is also jumped to from
1167 // where a numeric string is converted to a smi.
1168
1169 GenerateKeyedLoadReceiverCheck(
1170 masm, edx, eax, Map::kHasIndexedInterceptor, &slow_call);
1171
1172 GenerateFastArrayLoad(
1173 masm, edx, ecx, eax, edi, &check_number_dictionary, &slow_load);
1174 Isolate* isolate = masm->isolate();
1175 Counters* counters = isolate->counters();
1176 __ IncrementCounter(counters->keyed_call_generic_smi_fast(), 1);
1177
1178 __ bind(&do_call);
1179 // receiver in edx is not used after this point.
1180 // ecx: key
1181 // edi: function
1182 GenerateFunctionTailCall(masm, argc, &slow_call);
1183
1184 __ bind(&check_number_dictionary);
1185 // eax: elements
1186 // ecx: smi key
1187 // Check whether the elements is a number dictionary.
1188 __ CheckMap(eax,
1189 isolate->factory()->hash_table_map(),
1190 &slow_load,
1191 DONT_DO_SMI_CHECK);
1192 __ mov(ebx, ecx);
1193 __ SmiUntag(ebx);
1194 // ebx: untagged index
1195 // Receiver in edx will be clobbered, need to reload it on miss.
1196 __ LoadFromNumberDictionary(
1197 &slow_reload_receiver, eax, ecx, ebx, edx, edi, edi);
1198 __ IncrementCounter(counters->keyed_call_generic_smi_dict(), 1);
1199 __ jmp(&do_call);
1200
1201 __ bind(&slow_reload_receiver);
1202 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1203
1204 __ bind(&slow_load);
1205 // This branch is taken when calling KeyedCallIC_Miss is neither required
1206 // nor beneficial.
1207 __ IncrementCounter(counters->keyed_call_generic_slow_load(), 1);
1208
1209 {
1210 FrameScope scope(masm, StackFrame::INTERNAL);
1211 __ push(ecx); // save the key
1212 __ push(edx); // pass the receiver
1213 __ push(ecx); // pass the key
1214 __ CallRuntime(Runtime::kKeyedGetProperty, 2);
1215 __ pop(ecx); // restore the key
1216 // Leave the internal frame.
1217 }
1218
1219 __ mov(edi, eax);
1220 __ jmp(&do_call);
1221
1222 __ bind(&check_name);
1223 GenerateKeyNameCheck(masm, ecx, eax, ebx, &index_name, &slow_call);
1224
1225 // The key is known to be a unique name.
1226 // If the receiver is a regular JS object with slow properties then do
1227 // a quick inline probe of the receiver's dictionary.
1228 // Otherwise do the monomorphic cache probe.
1229 GenerateKeyedLoadReceiverCheck(
1230 masm, edx, eax, Map::kHasNamedInterceptor, &lookup_monomorphic_cache);
1231
1232 __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset));
1233 __ CheckMap(ebx,
1234 isolate->factory()->hash_table_map(),
1235 &lookup_monomorphic_cache,
1236 DONT_DO_SMI_CHECK);
1237
1238 GenerateDictionaryLoad(masm, &slow_load, ebx, ecx, eax, edi, edi);
1239 __ IncrementCounter(counters->keyed_call_generic_lookup_dict(), 1);
1240 __ jmp(&do_call);
1241
1242 __ bind(&lookup_monomorphic_cache);
1243 __ IncrementCounter(counters->keyed_call_generic_lookup_cache(), 1);
1244 CallICBase::GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC,
1245 kNoExtraICState);
1246 // Fall through on miss.
1247
1248 __ bind(&slow_call);
1249 // This branch is taken if:
1250 // - the receiver requires boxing or access check,
1251 // - the key is neither smi nor a unique name,
1252 // - the value loaded is not a function,
1253 // - there is hope that the runtime will create a monomorphic call stub
1254 // that will get fetched next time.
1255 __ IncrementCounter(counters->keyed_call_generic_slow(), 1);
1256 GenerateMiss(masm, argc);
1257
1258 __ bind(&index_name);
1259 __ IndexFromHash(ebx, ecx);
1260 // Now jump to the place where smi keys are handled.
1261 __ jmp(&index_smi);
1262 }
1263
1264
1265 void KeyedCallIC::GenerateNonStrictArguments(MacroAssembler* masm,
1266 int argc) {
1267 // ----------- S t a t e -------------
1268 // -- ecx : name
1269 // -- esp[0] : return address
1270 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1271 // -- ...
1272 // -- esp[(argc + 1) * 4] : receiver
1273 // -----------------------------------
1274 Label slow, notin;
1275 Factory* factory = masm->isolate()->factory();
1276 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1277 Operand mapped_location =
1278 GenerateMappedArgumentsLookup(masm, edx, ecx, ebx, eax, &notin, &slow);
1279 __ mov(edi, mapped_location);
1280 GenerateFunctionTailCall(masm, argc, &slow);
1281 __ bind(&notin);
1282 // The unmapped lookup expects that the parameter map is in ebx.
1283 Operand unmapped_location =
1284 GenerateUnmappedArgumentsLookup(masm, ecx, ebx, eax, &slow);
1285 __ cmp(unmapped_location, factory->the_hole_value());
1286 __ j(equal, &slow);
1287 __ mov(edi, unmapped_location);
1288 GenerateFunctionTailCall(masm, argc, &slow);
1289 __ bind(&slow);
1290 GenerateMiss(masm, argc);
1291 }
1292
1293
1294 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) {
1295 // ----------- S t a t e -------------
1296 // -- ecx : name
1297 // -- esp[0] : return address
1298 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1299 // -- ...
1300 // -- esp[(argc + 1) * 4] : receiver
1301 // -----------------------------------
1302
1303 // Check if the name is really a name.
1304 Label miss;
1305 __ JumpIfSmi(ecx, &miss);
1306 Condition cond = masm->IsObjectNameType(ecx, eax, eax);
1307 __ j(NegateCondition(cond), &miss);
1308 CallICBase::GenerateNormal(masm, argc);
1309 __ bind(&miss);
1310 GenerateMiss(masm, argc);
1311 }
1312
1313
1314 void LoadIC::GenerateMegamorphic(MacroAssembler* masm, ContextualMode mode) {
1315 // ----------- S t a t e -------------
1316 // -- ecx : name 953 // -- ecx : name
1317 // -- edx : receiver 954 // -- edx : receiver
1318 // -- esp[0] : return address 955 // -- esp[0] : return address
1319 // ----------------------------------- 956 // -----------------------------------
1320 957
1321 // Probe the stub cache. 958 // Probe the stub cache.
1322 ExtraICState extra_ic_state = LoadIC::ComputeExtraICState(mode);
1323 Code::Flags flags = Code::ComputeFlags( 959 Code::Flags flags = Code::ComputeFlags(
1324 Code::HANDLER, MONOMORPHIC, extra_ic_state, 960 Code::HANDLER, MONOMORPHIC, extra_state,
1325 Code::NORMAL, Code::LOAD_IC); 961 Code::NORMAL, Code::LOAD_IC);
1326 masm->isolate()->stub_cache()->GenerateProbe( 962 masm->isolate()->stub_cache()->GenerateProbe(
1327 masm, flags, edx, ecx, ebx, eax); 963 masm, flags, edx, ecx, ebx, eax);
1328 964
1329 // Cache miss: Jump to runtime. 965 // Cache miss: Jump to runtime.
1330 GenerateMiss(masm); 966 GenerateMiss(masm);
1331 } 967 }
1332 968
1333 969
1334 void LoadIC::GenerateNormal(MacroAssembler* masm) { 970 void LoadIC::GenerateNormal(MacroAssembler* masm) {
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
1670 Condition cc = (check == ENABLE_INLINED_SMI_CHECK) 1306 Condition cc = (check == ENABLE_INLINED_SMI_CHECK)
1671 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) 1307 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero)
1672 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); 1308 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry);
1673 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); 1309 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc);
1674 } 1310 }
1675 1311
1676 1312
1677 } } // namespace v8::internal 1313 } } // namespace v8::internal
1678 1314
1679 #endif // V8_TARGET_ARCH_IA32 1315 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/full-codegen-ia32.cc ('k') | src/ia32/lithium-codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698