OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 StubCompiler::GenerateLoadFunctionPrototype(masm, eax, edx, ebx, &miss); | 299 StubCompiler::GenerateLoadFunctionPrototype(masm, eax, edx, ebx, &miss); |
300 __ bind(&miss); | 300 __ bind(&miss); |
301 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); | 301 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); |
302 } | 302 } |
303 | 303 |
304 | 304 |
305 // Checks the receiver for special cases (value type, slow case bits). | 305 // Checks the receiver for special cases (value type, slow case bits). |
306 // Falls through for regular JS object. | 306 // Falls through for regular JS object. |
307 static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, | 307 static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, |
308 Register receiver, | 308 Register receiver, |
309 Register r0, | 309 Register map, |
310 Label* slow) { | 310 Label* slow) { |
311 // Register use: | 311 // Register use: |
312 // receiver - holds the receiver and is unchanged. | 312 // receiver - holds the receiver and is unchanged. |
313 // Scratch registers: | 313 // Scratch registers: |
314 // r0 - used to hold the map of the receiver. | 314 // map - used to hold the map of the receiver. |
315 | 315 |
316 // Check that the object isn't a smi. | 316 // Check that the object isn't a smi. |
317 __ test(receiver, Immediate(kSmiTagMask)); | 317 __ test(receiver, Immediate(kSmiTagMask)); |
318 __ j(zero, slow, not_taken); | 318 __ j(zero, slow, not_taken); |
319 | 319 |
320 // Get the map of the receiver. | 320 // Get the map of the receiver. |
321 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); | 321 __ mov(map, FieldOperand(receiver, HeapObject::kMapOffset)); |
322 | 322 |
323 // Check bit field. | 323 // Check bit field. |
324 __ test_b(FieldOperand(r0, Map::kBitFieldOffset), | 324 __ test_b(FieldOperand(map, Map::kBitFieldOffset), |
325 KeyedLoadIC::kSlowCaseBitFieldMask); | 325 KeyedLoadIC::kSlowCaseBitFieldMask); |
326 __ j(not_zero, slow, not_taken); | 326 __ j(not_zero, slow, not_taken); |
327 // Check that the object is some kind of JS object EXCEPT JS Value type. | 327 // Check that the object is some kind of JS object EXCEPT JS Value type. |
328 // In the case that the object is a value-wrapper object, | 328 // In the case that the object is a value-wrapper object, |
329 // we enter the runtime system to make sure that indexing | 329 // we enter the runtime system to make sure that indexing |
330 // into string objects works as intended. | 330 // into string objects works as intended. |
331 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); | 331 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); |
332 | 332 |
333 __ CmpInstanceType(r0, JS_OBJECT_TYPE); | 333 __ CmpInstanceType(map, JS_OBJECT_TYPE); |
334 __ j(below, slow, not_taken); | 334 __ j(below, slow, not_taken); |
335 } | 335 } |
336 | 336 |
337 | 337 |
338 // Loads an indexed element from a fast case array. | 338 // Loads an indexed element from a fast case array. |
339 static void GenerateFastArrayLoad(MacroAssembler* masm, | 339 static void GenerateFastArrayLoad(MacroAssembler* masm, |
340 Register receiver, | 340 Register receiver, |
341 Register key, | 341 Register key, |
342 Register scratch, | 342 Register scratch, |
343 Register result, | 343 Register result, |
(...skipping 20 matching lines...) Expand all Loading... |
364 // In case the loaded value is the_hole we have to consult GetProperty | 364 // In case the loaded value is the_hole we have to consult GetProperty |
365 // to ensure the prototype chain is searched. | 365 // to ensure the prototype chain is searched. |
366 __ j(equal, out_of_range); | 366 __ j(equal, out_of_range); |
367 if (!result.is(scratch)) { | 367 if (!result.is(scratch)) { |
368 __ mov(result, scratch); | 368 __ mov(result, scratch); |
369 } | 369 } |
370 } | 370 } |
371 | 371 |
372 | 372 |
373 // Checks whether a key is an array index string or a symbol string. | 373 // Checks whether a key is an array index string or a symbol string. |
374 // Falls through if a key is a symbol. | 374 // Falls through if the key is a symbol. |
375 static void GenerateKeyStringCheck(MacroAssembler* masm, | 375 static void GenerateKeyStringCheck(MacroAssembler* masm, |
376 Register key, | 376 Register key, |
377 Register map, | 377 Register map, |
378 Register hash, | 378 Register hash, |
379 Label* index_string, | 379 Label* index_string, |
380 Label* not_symbol) { | 380 Label* not_symbol) { |
381 // Register use: | 381 // Register use: |
382 // key - holds the key and is unchanged. Assumed to be non-smi. | 382 // key - holds the key and is unchanged. Assumed to be non-smi. |
383 // Scratch registers: | 383 // Scratch registers: |
384 // map - used to hold the map of the key. | 384 // map - used to hold the map of the key. |
385 // hash - used to hold the hash of the key. | 385 // hash - used to hold the hash of the key. |
386 __ CmpObjectType(key, FIRST_NONSTRING_TYPE, map); | 386 __ CmpObjectType(key, FIRST_NONSTRING_TYPE, map); |
387 __ j(above_equal, not_symbol); | 387 __ j(above_equal, not_symbol); |
388 | 388 |
389 // Is the string an array index, with cached numeric value? | 389 // Is the string an array index, with cached numeric value? |
390 __ mov(hash, FieldOperand(key, String::kHashFieldOffset)); | 390 __ mov(hash, FieldOperand(key, String::kHashFieldOffset)); |
391 __ test(hash, Immediate(String::kContainsCachedArrayIndexMask)); | 391 __ test(hash, Immediate(String::kContainsCachedArrayIndexMask)); |
392 __ j(zero, index_string, not_taken); | 392 __ j(zero, index_string, not_taken); |
393 | 393 |
394 // Is the string a symbol? | 394 // Is the string a symbol? |
395 ASSERT(kSymbolTag != 0); | 395 ASSERT(kSymbolTag != 0); |
396 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsSymbolMask); | 396 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsSymbolMask); |
397 __ j(zero, not_symbol, not_taken); | 397 __ j(zero, not_symbol, not_taken); |
398 } | 398 } |
399 | 399 |
400 | 400 |
401 // Picks out an array index from the hash field. | 401 // Picks out an array index from the hash field. |
402 // The generated code never falls through. | |
403 static void GenerateIndexFromHash(MacroAssembler* masm, | 402 static void GenerateIndexFromHash(MacroAssembler* masm, |
404 Register key, | 403 Register key, |
405 Register hash, | 404 Register hash) { |
406 Label* index_smi) { | |
407 // Register use: | 405 // Register use: |
408 // key - holds the overwritten key on exit. | 406 // key - holds the overwritten key on exit. |
409 // hash - holds the key's hash. Clobbered. | 407 // hash - holds the key's hash. Clobbered. |
410 | 408 |
411 // The assert checks that the constants for the maximum number of digits | 409 // The assert checks that the constants for the maximum number of digits |
412 // for an array index cached in the hash field and the number of bits | 410 // for an array index cached in the hash field and the number of bits |
413 // reserved for it does not conflict. | 411 // reserved for it does not conflict. |
414 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < | 412 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < |
415 (1 << String::kArrayIndexValueBits)); | 413 (1 << String::kArrayIndexValueBits)); |
416 // We want the smi-tagged index in key. kArrayIndexValueMask has zeros in | 414 // We want the smi-tagged index in key. kArrayIndexValueMask has zeros in |
417 // the low kHashShift bits. | 415 // the low kHashShift bits. |
418 // key: string key | |
419 // ebx: hash field. | |
420 ASSERT(String::kHashShift >= kSmiTagSize); | 416 ASSERT(String::kHashShift >= kSmiTagSize); |
421 __ and_(hash, String::kArrayIndexValueMask); | 417 __ and_(hash, String::kArrayIndexValueMask); |
422 __ shr(hash, String::kHashShift - kSmiTagSize); | 418 __ shr(hash, String::kHashShift - kSmiTagSize); |
423 // Here we actually clobber the key which will be used if calling into | 419 // Here we actually clobber the key which will be used if calling into |
424 // runtime later. However as the new key is the numeric value of a string key | 420 // runtime later. However as the new key is the numeric value of a string key |
425 // there is no difference in using either key. | 421 // there is no difference in using either key. |
426 __ mov(key, hash); | 422 __ mov(key, hash); |
427 // Now jump to the place where smi keys are handled. | |
428 __ jmp(index_smi); | |
429 } | 423 } |
430 | 424 |
431 | 425 |
432 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 426 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
433 // ----------- S t a t e ------------- | 427 // ----------- S t a t e ------------- |
434 // -- eax : key | 428 // -- eax : key |
435 // -- edx : receiver | 429 // -- edx : receiver |
436 // -- esp[0] : return address | 430 // -- esp[0] : return address |
437 // ----------------------------------- | 431 // ----------------------------------- |
438 Label slow, check_string, index_smi, index_string; | 432 Label slow, check_string, index_smi, index_string; |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
567 eax, | 561 eax, |
568 ebx, | 562 ebx, |
569 ecx, | 563 ecx, |
570 edi, | 564 edi, |
571 eax, | 565 eax, |
572 DICTIONARY_CHECK_DONE); | 566 DICTIONARY_CHECK_DONE); |
573 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); | 567 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); |
574 __ ret(0); | 568 __ ret(0); |
575 | 569 |
576 __ bind(&index_string); | 570 __ bind(&index_string); |
577 GenerateIndexFromHash(masm, eax, ebx, &index_smi); | 571 GenerateIndexFromHash(masm, eax, ebx); |
| 572 // Now jump to the place where smi keys are handled. |
| 573 __ jmp(&index_smi); |
578 } | 574 } |
579 | 575 |
580 | 576 |
581 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { | 577 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { |
582 // ----------- S t a t e ------------- | 578 // ----------- S t a t e ------------- |
583 // -- eax : key (index) | 579 // -- eax : key (index) |
584 // -- edx : receiver | 580 // -- edx : receiver |
585 // -- esp[0] : return address | 581 // -- esp[0] : return address |
586 // ----------------------------------- | 582 // ----------------------------------- |
587 Label miss; | 583 Label miss; |
(...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1118 } | 1114 } |
1119 | 1115 |
1120 | 1116 |
1121 // Defined in ic.cc. | 1117 // Defined in ic.cc. |
1122 Object* CallIC_Miss(Arguments args); | 1118 Object* CallIC_Miss(Arguments args); |
1123 | 1119 |
1124 // The generated code does not accept smi keys. | 1120 // The generated code does not accept smi keys. |
1125 // The generated code falls through if both probes miss. | 1121 // The generated code falls through if both probes miss. |
1126 static void GenerateMonomorphicCacheProbe(MacroAssembler* masm, | 1122 static void GenerateMonomorphicCacheProbe(MacroAssembler* masm, |
1127 int argc, | 1123 int argc, |
1128 Code::Kind kind, | 1124 Code::Kind kind) { |
1129 Label* miss) { | |
1130 // ----------- S t a t e ------------- | 1125 // ----------- S t a t e ------------- |
1131 // -- ecx : name | 1126 // -- ecx : name |
1132 // -- edx : receiver | 1127 // -- edx : receiver |
1133 // ----------------------------------- | 1128 // ----------------------------------- |
1134 Label number, non_number, non_string, boolean, probe; | 1129 Label number, non_number, non_string, boolean, probe, miss; |
1135 | 1130 |
1136 // Probe the stub cache. | 1131 // Probe the stub cache. |
1137 Code::Flags flags = | 1132 Code::Flags flags = |
1138 Code::ComputeFlags(kind, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc); | 1133 Code::ComputeFlags(kind, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc); |
1139 StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, eax); | 1134 StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, eax); |
1140 | 1135 |
1141 // If the stub cache probing failed, the receiver might be a value. | 1136 // If the stub cache probing failed, the receiver might be a value. |
1142 // For value objects, we use the map of the prototype objects for | 1137 // For value objects, we use the map of the prototype objects for |
1143 // the corresponding JSValue for the cache and that is what we need | 1138 // the corresponding JSValue for the cache and that is what we need |
1144 // to probe. | 1139 // to probe. |
(...skipping 14 matching lines...) Expand all Loading... |
1159 __ j(above_equal, &non_string, taken); | 1154 __ j(above_equal, &non_string, taken); |
1160 StubCompiler::GenerateLoadGlobalFunctionPrototype( | 1155 StubCompiler::GenerateLoadGlobalFunctionPrototype( |
1161 masm, Context::STRING_FUNCTION_INDEX, edx); | 1156 masm, Context::STRING_FUNCTION_INDEX, edx); |
1162 __ jmp(&probe); | 1157 __ jmp(&probe); |
1163 | 1158 |
1164 // Check for boolean. | 1159 // Check for boolean. |
1165 __ bind(&non_string); | 1160 __ bind(&non_string); |
1166 __ cmp(edx, Factory::true_value()); | 1161 __ cmp(edx, Factory::true_value()); |
1167 __ j(equal, &boolean, not_taken); | 1162 __ j(equal, &boolean, not_taken); |
1168 __ cmp(edx, Factory::false_value()); | 1163 __ cmp(edx, Factory::false_value()); |
1169 __ j(not_equal, miss, taken); | 1164 __ j(not_equal, &miss, taken); |
1170 __ bind(&boolean); | 1165 __ bind(&boolean); |
1171 StubCompiler::GenerateLoadGlobalFunctionPrototype( | 1166 StubCompiler::GenerateLoadGlobalFunctionPrototype( |
1172 masm, Context::BOOLEAN_FUNCTION_INDEX, edx); | 1167 masm, Context::BOOLEAN_FUNCTION_INDEX, edx); |
1173 | 1168 |
1174 // Probe the stub cache for the value object. | 1169 // Probe the stub cache for the value object. |
1175 __ bind(&probe); | 1170 __ bind(&probe); |
1176 StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg); | 1171 StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg); |
| 1172 __ bind(&miss); |
1177 } | 1173 } |
1178 | 1174 |
1179 | 1175 |
1180 static void GenerateNormalHelper(MacroAssembler* masm, | 1176 static void GenerateNormalHelper(MacroAssembler* masm, |
1181 int argc, | 1177 int argc, |
1182 bool is_global_object, | 1178 bool is_global_object, |
1183 Label* miss) { | 1179 Label* miss) { |
1184 // ----------- S t a t e ------------- | 1180 // ----------- S t a t e ------------- |
1185 // -- ecx : name | 1181 // -- ecx : name |
1186 // -- edx : receiver | 1182 // -- edx : receiver |
(...skipping 20 matching lines...) Expand all Loading... |
1207 if (is_global_object) { | 1203 if (is_global_object) { |
1208 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 1204 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
1209 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 1205 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
1210 } | 1206 } |
1211 | 1207 |
1212 // Invoke the function. | 1208 // Invoke the function. |
1213 ParameterCount actual(argc); | 1209 ParameterCount actual(argc); |
1214 __ InvokeFunction(edi, actual, JUMP_FUNCTION); | 1210 __ InvokeFunction(edi, actual, JUMP_FUNCTION); |
1215 } | 1211 } |
1216 | 1212 |
1217 // The generated code never falls through. | 1213 // The generated code falls through if the call should be handled by runtime. |
1218 static void GenerateCallNormal(MacroAssembler* masm, int argc, Label* miss) { | 1214 static void GenerateCallNormal(MacroAssembler* masm, int argc) { |
1219 // ----------- S t a t e ------------- | 1215 // ----------- S t a t e ------------- |
1220 // -- ecx : name | 1216 // -- ecx : name |
1221 // -- esp[0] : return address | 1217 // -- esp[0] : return address |
1222 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1218 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1223 // -- ... | 1219 // -- ... |
1224 // -- esp[(argc + 1) * 4] : receiver | 1220 // -- esp[(argc + 1) * 4] : receiver |
1225 // ----------------------------------- | 1221 // ----------------------------------- |
1226 Label global_object, non_global_object; | 1222 Label miss, global_object, non_global_object; |
1227 | 1223 |
1228 // Get the receiver of the function from the stack; 1 ~ return address. | 1224 // Get the receiver of the function from the stack; 1 ~ return address. |
1229 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1225 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1230 | 1226 |
1231 // Check that the receiver isn't a smi. | 1227 // Check that the receiver isn't a smi. |
1232 __ test(edx, Immediate(kSmiTagMask)); | 1228 __ test(edx, Immediate(kSmiTagMask)); |
1233 __ j(zero, miss, not_taken); | 1229 __ j(zero, &miss, not_taken); |
1234 | 1230 |
1235 // Check that the receiver is a valid JS object. | 1231 // Check that the receiver is a valid JS object. |
1236 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); | 1232 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); |
1237 __ movzx_b(eax, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 1233 __ movzx_b(eax, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
1238 __ cmp(eax, FIRST_JS_OBJECT_TYPE); | 1234 __ cmp(eax, FIRST_JS_OBJECT_TYPE); |
1239 __ j(below, miss, not_taken); | 1235 __ j(below, &miss, not_taken); |
1240 | 1236 |
1241 // If this assert fails, we have to check upper bound too. | 1237 // If this assert fails, we have to check upper bound too. |
1242 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); | 1238 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); |
1243 | 1239 |
1244 // Check for access to global object. | 1240 // Check for access to global object. |
1245 __ cmp(eax, JS_GLOBAL_OBJECT_TYPE); | 1241 __ cmp(eax, JS_GLOBAL_OBJECT_TYPE); |
1246 __ j(equal, &global_object); | 1242 __ j(equal, &global_object); |
1247 __ cmp(eax, JS_BUILTINS_OBJECT_TYPE); | 1243 __ cmp(eax, JS_BUILTINS_OBJECT_TYPE); |
1248 __ j(not_equal, &non_global_object); | 1244 __ j(not_equal, &non_global_object); |
1249 | 1245 |
1250 // Accessing global object: Load and invoke. | 1246 // Accessing global object: Load and invoke. |
1251 __ bind(&global_object); | 1247 __ bind(&global_object); |
1252 // Check that the global object does not require access checks. | 1248 // Check that the global object does not require access checks. |
1253 __ test_b(FieldOperand(ebx, Map::kBitFieldOffset), | 1249 __ test_b(FieldOperand(ebx, Map::kBitFieldOffset), |
1254 1 << Map::kIsAccessCheckNeeded); | 1250 1 << Map::kIsAccessCheckNeeded); |
1255 __ j(not_equal, miss, not_taken); | 1251 __ j(not_equal, &miss, not_taken); |
1256 GenerateNormalHelper(masm, argc, true, miss); | 1252 GenerateNormalHelper(masm, argc, true, &miss); |
1257 | 1253 |
1258 // Accessing non-global object: Check for access to global proxy. | 1254 // Accessing non-global object: Check for access to global proxy. |
1259 Label global_proxy, invoke; | 1255 Label global_proxy, invoke; |
1260 __ bind(&non_global_object); | 1256 __ bind(&non_global_object); |
1261 __ cmp(eax, JS_GLOBAL_PROXY_TYPE); | 1257 __ cmp(eax, JS_GLOBAL_PROXY_TYPE); |
1262 __ j(equal, &global_proxy, not_taken); | 1258 __ j(equal, &global_proxy, not_taken); |
1263 // Check that the non-global, non-global-proxy object does not | 1259 // Check that the non-global, non-global-proxy object does not |
1264 // require access checks. | 1260 // require access checks. |
1265 __ test_b(FieldOperand(ebx, Map::kBitFieldOffset), | 1261 __ test_b(FieldOperand(ebx, Map::kBitFieldOffset), |
1266 1 << Map::kIsAccessCheckNeeded); | 1262 1 << Map::kIsAccessCheckNeeded); |
1267 __ j(not_equal, miss, not_taken); | 1263 __ j(not_equal, &miss, not_taken); |
1268 __ bind(&invoke); | 1264 __ bind(&invoke); |
1269 GenerateNormalHelper(masm, argc, false, miss); | 1265 GenerateNormalHelper(masm, argc, false, &miss); |
1270 | 1266 |
1271 // Global object proxy access: Check access rights. | 1267 // Global object proxy access: Check access rights. |
1272 __ bind(&global_proxy); | 1268 __ bind(&global_proxy); |
1273 __ CheckAccessGlobalProxy(edx, eax, miss); | 1269 __ CheckAccessGlobalProxy(edx, eax, &miss); |
1274 __ jmp(&invoke); | 1270 __ jmp(&invoke); |
| 1271 |
| 1272 __ bind(&miss); |
1275 } | 1273 } |
1276 | 1274 |
1277 | 1275 |
1278 static void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) { | 1276 static void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) { |
1279 // ----------- S t a t e ------------- | 1277 // ----------- S t a t e ------------- |
1280 // -- ecx : name | 1278 // -- ecx : name |
1281 // -- esp[0] : return address | 1279 // -- esp[0] : return address |
1282 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1280 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1283 // -- ... | 1281 // -- ... |
1284 // -- esp[(argc + 1) * 4] : receiver | 1282 // -- esp[(argc + 1) * 4] : receiver |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1330 | 1328 |
1331 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { | 1329 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { |
1332 // ----------- S t a t e ------------- | 1330 // ----------- S t a t e ------------- |
1333 // -- ecx : name | 1331 // -- ecx : name |
1334 // -- esp[0] : return address | 1332 // -- esp[0] : return address |
1335 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1333 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1336 // -- ... | 1334 // -- ... |
1337 // -- esp[(argc + 1) * 4] : receiver | 1335 // -- esp[(argc + 1) * 4] : receiver |
1338 // ----------------------------------- | 1336 // ----------------------------------- |
1339 | 1337 |
1340 Label miss; | |
1341 // Get the receiver of the function from the stack; 1 ~ return address. | 1338 // Get the receiver of the function from the stack; 1 ~ return address. |
1342 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1339 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1343 GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC, &miss); | 1340 GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC); |
1344 __ bind(&miss); | |
1345 GenerateMiss(masm, argc); | 1341 GenerateMiss(masm, argc); |
1346 } | 1342 } |
1347 | 1343 |
1348 | 1344 |
1349 void CallIC::GenerateNormal(MacroAssembler* masm, int argc) { | 1345 void CallIC::GenerateNormal(MacroAssembler* masm, int argc) { |
1350 Label miss; | 1346 // ----------- S t a t e ------------- |
1351 GenerateCallNormal(masm, argc, &miss); | 1347 // -- ecx : name |
1352 __ bind(&miss); | 1348 // -- esp[0] : return address |
| 1349 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1350 // -- ... |
| 1351 // -- esp[(argc + 1) * 4] : receiver |
| 1352 // ----------------------------------- |
| 1353 |
| 1354 GenerateCallNormal(masm, argc); |
1353 GenerateMiss(masm, argc); | 1355 GenerateMiss(masm, argc); |
1354 } | 1356 } |
1355 | 1357 |
1356 | 1358 |
1357 void CallIC::GenerateMiss(MacroAssembler* masm, int argc) { | 1359 void CallIC::GenerateMiss(MacroAssembler* masm, int argc) { |
| 1360 // ----------- S t a t e ------------- |
| 1361 // -- ecx : name |
| 1362 // -- esp[0] : return address |
| 1363 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1364 // -- ... |
| 1365 // -- esp[(argc + 1) * 4] : receiver |
| 1366 // ----------------------------------- |
| 1367 |
1358 GenerateCallMiss(masm, argc, IC::kCallIC_Miss); | 1368 GenerateCallMiss(masm, argc, IC::kCallIC_Miss); |
1359 } | 1369 } |
1360 | 1370 |
1361 | 1371 |
1362 void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { | 1372 void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { |
1363 // ----------- S t a t e ------------- | 1373 // ----------- S t a t e ------------- |
1364 // -- ecx : name | 1374 // -- ecx : name |
1365 // -- esp[0] : return address | 1375 // -- esp[0] : return address |
1366 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1376 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1367 // -- ... | 1377 // -- ... |
(...skipping 10 matching lines...) Expand all Loading... |
1378 // Check that the key is a smi. | 1388 // Check that the key is a smi. |
1379 __ test(ecx, Immediate(kSmiTagMask)); | 1389 __ test(ecx, Immediate(kSmiTagMask)); |
1380 __ j(not_zero, &check_string, not_taken); | 1390 __ j(not_zero, &check_string, not_taken); |
1381 | 1391 |
1382 __ bind(&index_smi); | 1392 __ bind(&index_smi); |
1383 // Now the key is known to be a smi. This place is also jumped to from | 1393 // Now the key is known to be a smi. This place is also jumped to from |
1384 // where a numeric string is converted to a smi. | 1394 // where a numeric string is converted to a smi. |
1385 | 1395 |
1386 GenerateKeyedLoadReceiverCheck(masm, edx, eax, &slow_call); | 1396 GenerateKeyedLoadReceiverCheck(masm, edx, eax, &slow_call); |
1387 | 1397 |
1388 GenerateFastArrayLoad(masm, | 1398 GenerateFastArrayLoad( |
1389 edx, | 1399 masm, edx, ecx, eax, edi, &check_number_dictionary, &slow_load); |
1390 ecx, | |
1391 eax, | |
1392 edi, | |
1393 &check_number_dictionary, | |
1394 &slow_load); | |
1395 __ IncrementCounter(&Counters::keyed_call_generic_smi_fast, 1); | 1400 __ IncrementCounter(&Counters::keyed_call_generic_smi_fast, 1); |
1396 | 1401 |
1397 __ bind(&do_call); | 1402 __ bind(&do_call); |
1398 // receiver in edx is not used after this point. | 1403 // receiver in edx is not used after this point. |
1399 // ecx: key | 1404 // ecx: key |
1400 // edi: function | 1405 // edi: function |
1401 | 1406 |
1402 // Check that the value in edi is a JavaScript function. | 1407 // Check that the value in edi is a JavaScript function. |
1403 __ test(edi, Immediate(kSmiTagMask)); | 1408 __ test(edi, Immediate(kSmiTagMask)); |
1404 __ j(zero, &slow_call, not_taken); | 1409 __ j(zero, &slow_call, not_taken); |
1405 __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax); | 1410 __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax); |
1406 __ j(not_equal, &slow_call, not_taken); | 1411 __ j(not_equal, &slow_call, not_taken); |
1407 // Invoke the function. | 1412 // Invoke the function. |
1408 ParameterCount actual(argc); | 1413 ParameterCount actual(argc); |
1409 __ InvokeFunction(edi, actual, JUMP_FUNCTION); | 1414 __ InvokeFunction(edi, actual, JUMP_FUNCTION); |
1410 | 1415 |
1411 __ bind(&check_number_dictionary); | 1416 __ bind(&check_number_dictionary); |
1412 // eax: elements | 1417 // eax: elements |
1413 // ecx: smi key | 1418 // ecx: smi key |
1414 // Check whether the elements is a number dictionary. | 1419 // Check whether the elements is a number dictionary. |
1415 __ CheckMap(eax, Factory::hash_table_map(), &slow_load, true); | 1420 __ CheckMap(eax, Factory::hash_table_map(), &slow_load, true); |
1416 __ mov(ebx, ecx); | 1421 __ mov(ebx, ecx); |
1417 __ SmiUntag(ebx); | 1422 __ SmiUntag(ebx); |
1418 // ebx: untagged index | 1423 // ebx: untagged index |
1419 // Receiver in edx will be clobbered, need to reload it on miss. | 1424 // Receiver in edx will be clobbered, need to reload it on miss. |
1420 GenerateNumberDictionaryLoad(masm, | 1425 GenerateNumberDictionaryLoad( |
1421 &slow_reload_receiver, | 1426 masm, &slow_reload_receiver, eax, ecx, ebx, edx, edi, edi); |
1422 eax, | |
1423 ecx, | |
1424 ebx, | |
1425 edx, | |
1426 edi, | |
1427 edi); | |
1428 __ IncrementCounter(&Counters::keyed_call_generic_smi_dict, 1); | 1427 __ IncrementCounter(&Counters::keyed_call_generic_smi_dict, 1); |
1429 __ jmp(&do_call); | 1428 __ jmp(&do_call); |
1430 | 1429 |
1431 __ bind(&slow_reload_receiver); | 1430 __ bind(&slow_reload_receiver); |
1432 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1431 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1433 | 1432 |
1434 __ bind(&slow_load); | 1433 __ bind(&slow_load); |
1435 // This branch is taken when calling KeyedCallIC_Miss is neither required | 1434 // This branch is taken when calling KeyedCallIC_Miss is neither required |
1436 // nor beneficial. | 1435 // nor beneficial. |
1437 __ IncrementCounter(&Counters::keyed_call_generic_slow_load, 1); | 1436 __ IncrementCounter(&Counters::keyed_call_generic_slow_load, 1); |
(...skipping 14 matching lines...) Expand all Loading... |
1452 // If the receiver is a regular JS object with slow properties then do | 1451 // If the receiver is a regular JS object with slow properties then do |
1453 // a quick inline probe of the receiver's dictionary. | 1452 // a quick inline probe of the receiver's dictionary. |
1454 // Otherwise do the monomorphic cache probe. | 1453 // Otherwise do the monomorphic cache probe. |
1455 GenerateKeyedLoadReceiverCheck(masm, edx, eax, &lookup_monomorphic_cache); | 1454 GenerateKeyedLoadReceiverCheck(masm, edx, eax, &lookup_monomorphic_cache); |
1456 | 1455 |
1457 __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset)); | 1456 __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset)); |
1458 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), | 1457 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), |
1459 Immediate(Factory::hash_table_map())); | 1458 Immediate(Factory::hash_table_map())); |
1460 __ j(not_equal, &lookup_monomorphic_cache, not_taken); | 1459 __ j(not_equal, &lookup_monomorphic_cache, not_taken); |
1461 | 1460 |
1462 GenerateDictionaryLoad(masm, | 1461 GenerateDictionaryLoad( |
1463 &slow_load, | 1462 masm, &slow_load, edx, ecx, ebx, eax, edi, edi, DICTIONARY_CHECK_DONE); |
1464 edx, | |
1465 ecx, | |
1466 ebx, | |
1467 eax, | |
1468 edi, | |
1469 edi, | |
1470 DICTIONARY_CHECK_DONE); | |
1471 __ IncrementCounter(&Counters::keyed_call_generic_lookup_dict, 1); | 1463 __ IncrementCounter(&Counters::keyed_call_generic_lookup_dict, 1); |
1472 __ jmp(&do_call); | 1464 __ jmp(&do_call); |
1473 | 1465 |
1474 __ bind(&lookup_monomorphic_cache); | 1466 __ bind(&lookup_monomorphic_cache); |
1475 __ IncrementCounter(&Counters::keyed_call_generic_lookup_cache, 1); | 1467 __ IncrementCounter(&Counters::keyed_call_generic_lookup_cache, 1); |
1476 GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC, &slow_call); | 1468 GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC); |
1477 // Fall through on miss. | 1469 // Fall through on miss. |
1478 | 1470 |
1479 __ bind(&slow_call); | 1471 __ bind(&slow_call); |
1480 // This branch is taken if: | 1472 // This branch is taken if: |
1481 // - the receiver requires boxing or access check, | 1473 // - the receiver requires boxing or access check, |
1482 // - the key is neither smi nor symbol, | 1474 // - the key is neither smi nor symbol, |
1483 // - the value loaded is not a function, | 1475 // - the value loaded is not a function, |
1484 // - there is hope that the runtime will create a monomorphic call stub | 1476 // - there is hope that the runtime will create a monomorphic call stub |
1485 // that will get fetched next time. | 1477 // that will get fetched next time. |
1486 __ IncrementCounter(&Counters::keyed_call_generic_slow, 1); | 1478 __ IncrementCounter(&Counters::keyed_call_generic_slow, 1); |
1487 GenerateMiss(masm, argc); | 1479 GenerateMiss(masm, argc); |
1488 | 1480 |
1489 __ bind(&index_string); | 1481 __ bind(&index_string); |
1490 GenerateIndexFromHash(masm, ecx, ebx, &index_smi); | 1482 GenerateIndexFromHash(masm, ecx, ebx); |
| 1483 // Now jump to the place where smi keys are handled. |
| 1484 __ jmp(&index_smi); |
1491 } | 1485 } |
1492 | 1486 |
1493 | 1487 |
1494 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { | 1488 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { |
1495 Label miss; | 1489 // ----------- S t a t e ------------- |
1496 GenerateCallNormal(masm, argc, &miss); | 1490 // -- ecx : name |
1497 __ bind(&miss); | 1491 // -- esp[0] : return address |
| 1492 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1493 // -- ... |
| 1494 // -- esp[(argc + 1) * 4] : receiver |
| 1495 // ----------------------------------- |
| 1496 |
| 1497 GenerateCallNormal(masm, argc); |
1498 GenerateMiss(masm, argc); | 1498 GenerateMiss(masm, argc); |
1499 } | 1499 } |
1500 | 1500 |
1501 | 1501 |
1502 void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) { | 1502 void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) { |
| 1503 // ----------- S t a t e ------------- |
| 1504 // -- ecx : name |
| 1505 // -- esp[0] : return address |
| 1506 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1507 // -- ... |
| 1508 // -- esp[(argc + 1) * 4] : receiver |
| 1509 // ----------------------------------- |
| 1510 |
1503 GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss); | 1511 GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss); |
1504 } | 1512 } |
1505 | 1513 |
1506 | 1514 |
1507 // Defined in ic.cc. | 1515 // Defined in ic.cc. |
1508 Object* LoadIC_Miss(Arguments args); | 1516 Object* LoadIC_Miss(Arguments args); |
1509 | 1517 |
1510 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { | 1518 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { |
1511 // ----------- S t a t e ------------- | 1519 // ----------- S t a t e ------------- |
1512 // -- eax : receiver | 1520 // -- eax : receiver |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1861 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); | 1869 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); |
1862 __ TailCallExternalReference(ref, 3, 1); | 1870 __ TailCallExternalReference(ref, 3, 1); |
1863 } | 1871 } |
1864 | 1872 |
1865 #undef __ | 1873 #undef __ |
1866 | 1874 |
1867 | 1875 |
1868 } } // namespace v8::internal | 1876 } } // namespace v8::internal |
1869 | 1877 |
1870 #endif // V8_TARGET_ARCH_IA32 | 1878 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |