| 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 |