| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" | 5 #include "vm/globals.h" |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/assembler_macros.h" | 9 #include "vm/assembler_macros.h" |
| 10 #include "vm/code_generator.h" | 10 #include "vm/code_generator.h" |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 // Total number of args is the first Smi in args descriptor array (EDX). | 288 // Total number of args is the first Smi in args descriptor array (EDX). |
| 289 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 289 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 290 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // Get receiver. EAX is a Smi. | 290 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // Get receiver. EAX is a Smi. |
| 291 // TODO(srdjan): Remove the special casing below for null receiver, once | 291 // TODO(srdjan): Remove the special casing below for null receiver, once |
| 292 // NullClass is implemented. | 292 // NullClass is implemented. |
| 293 __ cmpl(EAX, raw_null); | 293 __ cmpl(EAX, raw_null); |
| 294 // Use Object class if receiver is null. | 294 // Use Object class if receiver is null. |
| 295 __ j(EQUAL, &null_receiver, Assembler::kNearJump); | 295 __ j(EQUAL, &null_receiver, Assembler::kNearJump); |
| 296 __ testl(EAX, Immediate(kSmiTagMask)); | 296 __ testl(EAX, Immediate(kSmiTagMask)); |
| 297 __ j(ZERO, &smi_receiver, Assembler::kNearJump); | 297 __ j(ZERO, &smi_receiver, Assembler::kNearJump); |
| 298 __ movl(EAX, FieldAddress(EAX, Object::class_offset())); | 298 __ GetClassOf(EAX, EAX, EDI); |
| 299 __ jmp(&class_in_eax, Assembler::kNearJump); | 299 __ jmp(&class_in_eax, Assembler::kNearJump); |
| 300 __ Bind(&smi_receiver); | 300 __ Bind(&smi_receiver); |
| 301 // For Smis we need to get the class from the isolate. | 301 // For Smis we need to get the class from the isolate. |
| 302 // Load current Isolate pointer from Context structure into EAX. | 302 // Load current Isolate pointer from Context structure into EAX. |
| 303 __ movl(EAX, FieldAddress(CTX, Context::isolate_offset())); | 303 __ movl(EAX, FieldAddress(CTX, Context::isolate_offset())); |
| 304 __ movl(EAX, Address(EAX, Isolate::object_store_offset())); | 304 __ movl(EAX, Address(EAX, Isolate::object_store_offset())); |
| 305 __ movl(EAX, Address(EAX, ObjectStore::smi_class_offset())); | 305 __ movl(EAX, Address(EAX, ObjectStore::smi_class_offset())); |
| 306 __ jmp(&class_in_eax, Assembler::kNearJump); | 306 __ jmp(&class_in_eax, Assembler::kNearJump); |
| 307 __ Bind(&null_receiver); | 307 __ Bind(&null_receiver); |
| 308 __ movl(EAX, FieldAddress(CTX, Context::isolate_offset())); | 308 __ movl(EAX, FieldAddress(CTX, Context::isolate_offset())); |
| (...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 666 // Store the type argument field. | 666 // Store the type argument field. |
| 667 __ StoreIntoObject(EAX, | 667 __ StoreIntoObject(EAX, |
| 668 FieldAddress(EAX, Array::type_arguments_offset()), | 668 FieldAddress(EAX, Array::type_arguments_offset()), |
| 669 ECX); | 669 ECX); |
| 670 | 670 |
| 671 // Set the length field. | 671 // Set the length field. |
| 672 __ StoreIntoObject(EAX, | 672 __ StoreIntoObject(EAX, |
| 673 FieldAddress(EAX, Array::length_offset()), | 673 FieldAddress(EAX, Array::length_offset()), |
| 674 EDX); | 674 EDX); |
| 675 | 675 |
| 676 // EAX: new object start as a tagged pointer. | |
| 677 // EBX: new object end address. | |
| 678 // EDX: Array length as Smi. | |
| 679 // Store class value for array. | |
| 680 __ movl(ECX, FieldAddress(CTX, Context::isolate_offset())); | |
| 681 __ movl(ECX, Address(ECX, Isolate::object_store_offset())); | |
| 682 __ movl(ECX, Address(ECX, ObjectStore::array_class_offset())); | |
| 683 __ StoreIntoObject(EAX, | |
| 684 FieldAddress(EAX, Array::class_offset()), | |
| 685 ECX); | |
| 686 // Calculate the size tag. | 676 // Calculate the size tag. |
| 687 // EAX: new object start as a tagged pointer. | 677 // EAX: new object start as a tagged pointer. |
| 688 // EBX: new object end address. | 678 // EBX: new object end address. |
| 689 // EDX: Array length as Smi. | 679 // EDX: Array length as Smi. |
| 690 { | 680 { |
| 691 Label size_tag_overflow, done; | 681 Label size_tag_overflow, done; |
| 692 __ leal(ECX, Address(EDX, TIMES_2, fixed_size)); // EDX is Smi. | 682 __ leal(ECX, Address(EDX, TIMES_2, fixed_size)); // EDX is Smi. |
| 693 ASSERT(kSmiTagShift == 1); | 683 ASSERT(kSmiTagShift == 1); |
| 694 __ andl(ECX, Immediate(-kObjectAlignment)); | 684 __ andl(ECX, Immediate(-kObjectAlignment)); |
| 695 __ cmpl(ECX, Immediate(RawObject::SizeTag::kMaxSizeTag)); | 685 __ cmpl(ECX, Immediate(RawObject::SizeTag::kMaxSizeTag)); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 765 | 755 |
| 766 // Verify that EDI is a closure by checking its class. | 756 // Verify that EDI is a closure by checking its class. |
| 767 Label not_closure; | 757 Label not_closure; |
| 768 __ cmpl(EDI, raw_null); | 758 __ cmpl(EDI, raw_null); |
| 769 // Not a closure, but null object. | 759 // Not a closure, but null object. |
| 770 __ j(EQUAL, ¬_closure, Assembler::kNearJump); | 760 __ j(EQUAL, ¬_closure, Assembler::kNearJump); |
| 771 __ testl(EDI, Immediate(kSmiTagMask)); | 761 __ testl(EDI, Immediate(kSmiTagMask)); |
| 772 __ j(ZERO, ¬_closure, Assembler::kNearJump); // Not a closure, but a smi. | 762 __ j(ZERO, ¬_closure, Assembler::kNearJump); // Not a closure, but a smi. |
| 773 // Verify that the class of the object is a closure class by checking that | 763 // Verify that the class of the object is a closure class by checking that |
| 774 // class.signature_function() is not null. | 764 // class.signature_function() is not null. |
| 775 __ movl(EAX, FieldAddress(EDI, Object::class_offset())); | 765 __ GetClassOf(EAX, EDI, ECX); |
| 776 __ movl(EAX, FieldAddress(EAX, Class::signature_function_offset())); | 766 __ movl(EAX, FieldAddress(EAX, Class::signature_function_offset())); |
| 777 __ cmpl(EAX, raw_null); | 767 __ cmpl(EAX, raw_null); |
| 778 // Actual class is not a closure class. | 768 // Actual class is not a closure class. |
| 779 __ j(EQUAL, ¬_closure, Assembler::kNearJump); | 769 __ j(EQUAL, ¬_closure, Assembler::kNearJump); |
| 780 | 770 |
| 781 // EAX is just the signature function. Load the actual closure function. | 771 // EAX is just the signature function. Load the actual closure function. |
| 782 __ movl(ECX, FieldAddress(EDI, Closure::function_offset())); | 772 __ movl(ECX, FieldAddress(EDI, Closure::function_offset())); |
| 783 | 773 |
| 784 // Load closure context in CTX; note that CTX has already been preserved. | 774 // Load closure context in CTX; note that CTX has already been preserved. |
| 785 __ movl(CTX, FieldAddress(EDI, Closure::context_offset())); | 775 __ movl(CTX, FieldAddress(EDI, Closure::context_offset())); |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 997 } | 987 } |
| 998 | 988 |
| 999 // Successfully allocated the object, now update top to point to | 989 // Successfully allocated the object, now update top to point to |
| 1000 // next object start and initialize the object. | 990 // next object start and initialize the object. |
| 1001 // EAX: new object. | 991 // EAX: new object. |
| 1002 // EBX: next object start. | 992 // EBX: next object start. |
| 1003 // EDX: number of context variables. | 993 // EDX: number of context variables. |
| 1004 __ movl(Address::Absolute(heap->TopAddress()), EBX); | 994 __ movl(Address::Absolute(heap->TopAddress()), EBX); |
| 1005 __ addl(EAX, Immediate(kHeapObjectTag)); | 995 __ addl(EAX, Immediate(kHeapObjectTag)); |
| 1006 | 996 |
| 1007 // Initialize the class field in the context object. | |
| 1008 // EAX: new object. | |
| 1009 // EDX: number of context variables. | |
| 1010 __ LoadObject(EBX, context_class); // Load up class field of context. | |
| 1011 __ StoreIntoObject(EAX, | |
| 1012 FieldAddress(EAX, Context::class_offset()), | |
| 1013 EBX); | |
| 1014 // Calculate the size tag. | 997 // Calculate the size tag. |
| 1015 // EAX: new object. | 998 // EAX: new object. |
| 1016 // EDX: number of context variables. | 999 // EDX: number of context variables. |
| 1017 { | 1000 { |
| 1018 Label size_tag_overflow, done; | 1001 Label size_tag_overflow, done; |
| 1019 __ leal(EBX, Address(EDX, TIMES_4, fixed_size)); | 1002 __ leal(EBX, Address(EDX, TIMES_4, fixed_size)); |
| 1020 __ andl(EBX, Immediate(-kObjectAlignment)); | 1003 __ andl(EBX, Immediate(-kObjectAlignment)); |
| 1021 __ cmpl(EBX, Immediate(RawObject::SizeTag::kMaxSizeTag)); | 1004 __ cmpl(EBX, Immediate(RawObject::SizeTag::kMaxSizeTag)); |
| 1022 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); | 1005 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); |
| 1023 __ shll(EBX, Immediate(RawObject::kSizeTagBit - kObjectAlignmentLog2)); | 1006 __ shll(EBX, Immediate(RawObject::kSizeTagBit - kObjectAlignmentLog2)); |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1162 // Initialize InstantiatedTypeArguments object at ECX. | 1145 // Initialize InstantiatedTypeArguments object at ECX. |
| 1163 __ movl(Address(ECX, | 1146 __ movl(Address(ECX, |
| 1164 InstantiatedTypeArguments::uninstantiated_type_arguments_offset()), | 1147 InstantiatedTypeArguments::uninstantiated_type_arguments_offset()), |
| 1165 EDI); | 1148 EDI); |
| 1166 __ movl(EDX, Address(ESP, kInstantiatorTypeArgumentsOffset)); | 1149 __ movl(EDX, Address(ESP, kInstantiatorTypeArgumentsOffset)); |
| 1167 __ movl(Address(ECX, | 1150 __ movl(Address(ECX, |
| 1168 InstantiatedTypeArguments::instantiator_type_arguments_offset()), | 1151 InstantiatedTypeArguments::instantiator_type_arguments_offset()), |
| 1169 EDX); | 1152 EDX); |
| 1170 const Class& ita_cls = | 1153 const Class& ita_cls = |
| 1171 Class::ZoneHandle(Object::instantiated_type_arguments_class()); | 1154 Class::ZoneHandle(Object::instantiated_type_arguments_class()); |
| 1172 __ LoadObject(EDX, ita_cls); | |
| 1173 __ movl(Address(ECX, Instance::class_offset()), EDX); // Set its class. | |
| 1174 // Set the tags. | 1155 // Set the tags. |
| 1175 uword tags = 0; | 1156 uword tags = 0; |
| 1176 tags = RawObject::SizeTag::update(type_args_size, tags); | 1157 tags = RawObject::SizeTag::update(type_args_size, tags); |
| 1177 tags = RawObject::ClassTag::update(ita_cls.index(), tags); | 1158 tags = RawObject::ClassTag::update(ita_cls.index(), tags); |
| 1178 __ movl(Address(ECX, Instance::tags_offset()), Immediate(tags)); | 1159 __ movl(Address(ECX, Instance::tags_offset()), Immediate(tags)); |
| 1179 // Set the new InstantiatedTypeArguments object (ECX) as the type | 1160 // Set the new InstantiatedTypeArguments object (ECX) as the type |
| 1180 // arguments (EDI) of the new object (EAX). | 1161 // arguments (EDI) of the new object (EAX). |
| 1181 __ movl(EDI, ECX); | 1162 __ movl(EDI, ECX); |
| 1182 __ addl(EDI, Immediate(kHeapObjectTag)); | 1163 __ addl(EDI, Immediate(kHeapObjectTag)); |
| 1183 // Set EBX to new object end. | 1164 // Set EBX to new object end. |
| 1184 __ movl(EBX, ECX); | 1165 __ movl(EBX, ECX); |
| 1185 __ Bind(&type_arguments_ready); | 1166 __ Bind(&type_arguments_ready); |
| 1186 // EAX: new object. | 1167 // EAX: new object. |
| 1187 // EDI: new object type arguments. | 1168 // EDI: new object type arguments. |
| 1188 } | 1169 } |
| 1189 | 1170 |
| 1190 // Initialize the class field in the object. | 1171 // Initialize the class field in the object. |
| 1191 // EAX: new object start. | 1172 // EAX: new object start. |
| 1192 // EBX: next object start. | 1173 // EBX: next object start. |
| 1193 // EDI: new object type arguments (if is_cls_parameterized). | 1174 // EDI: new object type arguments (if is_cls_parameterized). |
| 1194 __ LoadObject(EDX, cls); // Load class of object to be allocated. | 1175 __ LoadObject(EDX, cls); // Load class of object to be allocated. |
| 1195 __ movl(Address(EAX, Instance::class_offset()), EDX); | |
| 1196 // Set the tags. | 1176 // Set the tags. |
| 1197 uword tags = 0; | 1177 uword tags = 0; |
| 1198 tags = RawObject::SizeTag::update(instance_size, tags); | 1178 tags = RawObject::SizeTag::update(instance_size, tags); |
| 1199 ASSERT(cls.index() != kIllegalObjectKind); | 1179 ASSERT(cls.index() != kIllegalObjectKind); |
| 1200 tags = RawObject::ClassTag::update(cls.index(), tags); | 1180 tags = RawObject::ClassTag::update(cls.index(), tags); |
| 1201 __ movl(Address(EAX, Instance::tags_offset()), Immediate(tags)); | 1181 __ movl(Address(EAX, Instance::tags_offset()), Immediate(tags)); |
| 1202 | 1182 |
| 1203 // Initialize the remaining words of the object. | 1183 // Initialize the remaining words of the object. |
| 1204 const Immediate raw_null = | 1184 const Immediate raw_null = |
| 1205 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1185 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1335 if (FLAG_use_slow_path) { | 1315 if (FLAG_use_slow_path) { |
| 1336 __ jmp(&slow_case); | 1316 __ jmp(&slow_case); |
| 1337 } else { | 1317 } else { |
| 1338 __ j(ABOVE_EQUAL, &slow_case, Assembler::kNearJump); | 1318 __ j(ABOVE_EQUAL, &slow_case, Assembler::kNearJump); |
| 1339 } | 1319 } |
| 1340 | 1320 |
| 1341 // Successfully allocated the object, now update top to point to | 1321 // Successfully allocated the object, now update top to point to |
| 1342 // next object start and initialize the object. | 1322 // next object start and initialize the object. |
| 1343 __ movl(Address::Absolute(heap->TopAddress()), EBX); | 1323 __ movl(Address::Absolute(heap->TopAddress()), EBX); |
| 1344 | 1324 |
| 1345 // Initialize the class field in the object. | |
| 1346 // EAX: new closure object. | 1325 // EAX: new closure object. |
| 1347 // ECX: new context object (only if is_implicit_closure). | 1326 // ECX: new context object (only if is_implicit_closure). |
| 1348 __ LoadObject(EDX, cls); // Load signature class of closure. | |
| 1349 __ movl(Address(EAX, Closure::class_offset()), EDX); | |
| 1350 // Set the tags. | 1327 // Set the tags. |
| 1351 uword tags = 0; | 1328 uword tags = 0; |
| 1352 tags = RawObject::SizeTag::update(closure_size, tags); | 1329 tags = RawObject::SizeTag::update(closure_size, tags); |
| 1353 tags = RawObject::ClassTag::update(cls.index(), tags); | 1330 tags = RawObject::ClassTag::update(cls.index(), tags); |
| 1354 __ movl(Address(EAX, Closure::tags_offset()), Immediate(tags)); | 1331 __ movl(Address(EAX, Closure::tags_offset()), Immediate(tags)); |
| 1355 | 1332 |
| 1356 // Initialize the function field in the object. | 1333 // Initialize the function field in the object. |
| 1357 // EAX: new closure object. | 1334 // EAX: new closure object. |
| 1358 // ECX: new context object (only if is_implicit_closure). | 1335 // ECX: new context object (only if is_implicit_closure). |
| 1359 // EBX: next object start. | 1336 // EBX: next object start. |
| 1360 __ LoadObject(EDX, func); // Load function of closure to be allocated. | 1337 __ LoadObject(EDX, func); // Load function of closure to be allocated. |
| 1361 __ movl(Address(EAX, Closure::function_offset()), EDX); | 1338 __ movl(Address(EAX, Closure::function_offset()), EDX); |
| 1362 | 1339 |
| 1363 // Setup the context for this closure. | 1340 // Setup the context for this closure. |
| 1364 if (is_implicit_static_closure) { | 1341 if (is_implicit_static_closure) { |
| 1365 ObjectStore* object_store = Isolate::Current()->object_store(); | 1342 ObjectStore* object_store = Isolate::Current()->object_store(); |
| 1366 ASSERT(object_store != NULL); | 1343 ASSERT(object_store != NULL); |
| 1367 const Context& empty_context = | 1344 const Context& empty_context = |
| 1368 Context::ZoneHandle(object_store->empty_context()); | 1345 Context::ZoneHandle(object_store->empty_context()); |
| 1369 __ LoadObject(EDX, empty_context); | 1346 __ LoadObject(EDX, empty_context); |
| 1370 __ movl(Address(EAX, Closure::context_offset()), EDX); | 1347 __ movl(Address(EAX, Closure::context_offset()), EDX); |
| 1371 } else if (is_implicit_instance_closure) { | 1348 } else if (is_implicit_instance_closure) { |
| 1372 // Initialize the new context capturing the receiver. | 1349 // Initialize the new context capturing the receiver. |
| 1373 | 1350 |
| 1374 // Set the class field to the Context class. | |
| 1375 const Class& context_class = Class::ZoneHandle(Object::context_class()); | 1351 const Class& context_class = Class::ZoneHandle(Object::context_class()); |
| 1376 __ LoadObject(EBX, context_class); | |
| 1377 __ movl(Address(ECX, Context::class_offset()), EBX); | |
| 1378 // Set the tags. | 1352 // Set the tags. |
| 1379 uword tags = 0; | 1353 uword tags = 0; |
| 1380 tags = RawObject::SizeTag::update(context_size, tags); | 1354 tags = RawObject::SizeTag::update(context_size, tags); |
| 1381 tags = RawObject::ClassTag::update(context_class.index(), tags); | 1355 tags = RawObject::ClassTag::update(context_class.index(), tags); |
| 1382 __ movl(Address(ECX, Context::tags_offset()), Immediate(tags)); | 1356 __ movl(Address(ECX, Context::tags_offset()), Immediate(tags)); |
| 1383 | 1357 |
| 1384 // Set number of variables field to 1 (for captured receiver). | 1358 // Set number of variables field to 1 (for captured receiver). |
| 1385 __ movl(Address(ECX, Context::num_variables_offset()), Immediate(1)); | 1359 __ movl(Address(ECX, Context::num_variables_offset()), Immediate(1)); |
| 1386 | 1360 |
| 1387 // Set isolate field to isolate of current context. | 1361 // Set isolate field to isolate of current context. |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1569 __ Bind(¬_yet_hot); | 1543 __ Bind(¬_yet_hot); |
| 1570 } | 1544 } |
| 1571 | 1545 |
| 1572 ASSERT(num_args > 0); | 1546 ASSERT(num_args > 0); |
| 1573 // Get receiver (first read number of arguments from argument descriptor array | 1547 // Get receiver (first read number of arguments from argument descriptor array |
| 1574 // and then access the receiver from the stack). | 1548 // and then access the receiver from the stack). |
| 1575 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1549 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 1576 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX (argument_count) is Smi. | 1550 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX (argument_count) is Smi. |
| 1577 | 1551 |
| 1578 Label get_class, ic_miss; | 1552 Label get_class, ic_miss; |
| 1579 __ call(&get_class); | |
| 1580 // EAX: receiver's class | |
| 1581 // ECX: IC data array. | 1553 // ECX: IC data array. |
| 1582 | 1554 |
| 1583 #if defined(DEBUG) | 1555 #if defined(DEBUG) |
| 1584 { Label ok; | 1556 { Label ok; |
| 1585 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. | 1557 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. |
| 1586 // 'num_args_tested' is stored as an untagged int. | 1558 // 'num_args_tested' is stored as an untagged int. |
| 1587 __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset())); | 1559 __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset())); |
| 1588 __ cmpl(EBX, Immediate(num_args)); | 1560 __ cmpl(EBX, Immediate(num_args)); |
| 1589 __ j(EQUAL, &ok, Assembler::kNearJump); | 1561 __ j(EQUAL, &ok, Assembler::kNearJump); |
| 1590 __ Stop("Incorrect stub for IC data"); | 1562 __ Stop("Incorrect stub for IC data"); |
| 1591 __ Bind(&ok); | 1563 __ Bind(&ok); |
| 1592 } | 1564 } |
| 1593 #endif // DEBUG | 1565 #endif // DEBUG |
| 1594 | 1566 |
| 1595 // Loop that checks if there is an IC data match. | 1567 // Loop that checks if there is an IC data match. |
| 1596 // EAX: receiver's class. | 1568 // EAX: receiver's class. |
| 1597 // ECX: IC data object (preserved). | 1569 // ECX: IC data object (preserved). |
| 1598 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); | 1570 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); |
| 1599 // EBX: ic_data_array with check entries: classes and target functions. | 1571 // EBX: ic_data_array with check entries: classes and target functions. |
| 1600 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); | 1572 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); |
| 1601 // EBX: points directly to the first ic data array element. | 1573 // EBX: points directly to the first ic data array element. |
| 1602 Label loop, found; | 1574 Label loop, found; |
| 1603 if (num_args == 1) { | 1575 if (num_args == 1) { |
| 1576 __ call(&get_class); |
| 1577 // EAX: receiver's class |
| 1604 __ Bind(&loop); | 1578 __ Bind(&loop); |
| 1605 __ movl(EDI, Address(EBX, 0)); // Get class to check. | 1579 __ movl(EDI, Address(EBX, 0)); // Get class to check. |
| 1606 __ cmpl(EAX, EDI); // Match? | 1580 __ cmpl(EAX, EDI); // Match? |
| 1607 __ j(EQUAL, &found, Assembler::kNearJump); | 1581 __ j(EQUAL, &found, Assembler::kNearJump); |
| 1608 __ addl(EBX, Immediate(kWordSize * 2)); // Next element (class + target). | 1582 __ addl(EBX, Immediate(kWordSize * 2)); // Next element (class + target). |
| 1609 __ cmpl(EDI, raw_null); // Done? | 1583 __ cmpl(EDI, raw_null); // Done? |
| 1610 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1584 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1611 } else if (num_args == 2) { | 1585 } else if (num_args == 2) { |
| 1612 // EDI: class to check. | 1586 // EDI: class to check. |
| 1613 Label no_match; | 1587 Label no_match; |
| 1614 __ Bind(&loop); | 1588 __ Bind(&loop); |
| 1615 // Get class from IC data to check. | 1589 // Get class from IC data to check. |
| 1616 __ movl(EDI, Address(EBX, 0)); | |
| 1617 // Get receiver using argument descriptor in EDX. | 1590 // Get receiver using argument descriptor in EDX. |
| 1618 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1591 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 1619 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX (arg. count) is Smi. | 1592 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX (arg. count) is Smi. |
| 1620 __ call(&get_class); | 1593 __ call(&get_class); |
| 1594 // TODO(vegorov): is it possible to switch this code to use class ids? |
| 1595 __ movl(EDI, Address(EBX, 0)); |
| 1621 __ cmpl(EAX, EDI); // Match? | 1596 __ cmpl(EAX, EDI); // Match? |
| 1622 __ j(NOT_EQUAL, &no_match, Assembler::kNearJump); | 1597 __ j(NOT_EQUAL, &no_match, Assembler::kNearJump); |
| 1623 // Check second class/argument. | 1598 // Check second class/argument. |
| 1624 // Get class from IC data to check. | 1599 // Get class from IC data to check. |
| 1625 __ movl(EDI, Address(EBX, kWordSize)); | |
| 1626 // Get next argument. | 1600 // Get next argument. |
| 1627 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1601 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 1628 __ movl(EAX, Address(ESP, EAX, TIMES_2, -kWordSize)); | 1602 __ movl(EAX, Address(ESP, EAX, TIMES_2, -kWordSize)); |
| 1629 // EAX (argument count) is Smi. | 1603 // EAX (argument count) is Smi. |
| 1630 __ call(&get_class); | 1604 __ call(&get_class); |
| 1605 __ movl(EDI, Address(EBX, kWordSize)); |
| 1631 __ cmpl(EAX, EDI); // Match? | 1606 __ cmpl(EAX, EDI); // Match? |
| 1632 __ j(EQUAL, &found, Assembler::kNearJump); | 1607 __ j(EQUAL, &found, Assembler::kNearJump); |
| 1633 __ Bind(&no_match); | 1608 __ Bind(&no_match); |
| 1634 // Each test entry has (1 + num_args) array elements. | 1609 // Each test entry has (1 + num_args) array elements. |
| 1635 __ addl(EBX, Immediate(kWordSize * (1 + num_args))); // Next element. | 1610 __ addl(EBX, Immediate(kWordSize * (1 + num_args))); // Next element. |
| 1636 __ cmpl(EDI, raw_null); // Done? | 1611 __ cmpl(EDI, raw_null); // Done? |
| 1637 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1612 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1638 } | 1613 } |
| 1639 | 1614 |
| 1640 __ Bind(&ic_miss); | 1615 __ Bind(&ic_miss); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1689 Label not_smi; | 1664 Label not_smi; |
| 1690 // Test if Smi -> load Smi class for comparison. | 1665 // Test if Smi -> load Smi class for comparison. |
| 1691 __ testl(EAX, Immediate(kSmiTagMask)); | 1666 __ testl(EAX, Immediate(kSmiTagMask)); |
| 1692 __ j(NOT_ZERO, ¬_smi, Assembler::kNearJump); | 1667 __ j(NOT_ZERO, ¬_smi, Assembler::kNearJump); |
| 1693 const Class& smi_class = | 1668 const Class& smi_class = |
| 1694 Class::ZoneHandle(Isolate::Current()->object_store()->smi_class()); | 1669 Class::ZoneHandle(Isolate::Current()->object_store()->smi_class()); |
| 1695 __ LoadObject(EAX, smi_class); | 1670 __ LoadObject(EAX, smi_class); |
| 1696 __ ret(); | 1671 __ ret(); |
| 1697 | 1672 |
| 1698 __ Bind(¬_smi); | 1673 __ Bind(¬_smi); |
| 1699 __ movl(EAX, FieldAddress(EAX, Object::class_offset())); | 1674 __ GetClassOf(EAX, EAX, EDI); |
| 1700 __ ret(); | 1675 __ ret(); |
| 1701 } | 1676 } |
| 1702 | 1677 |
| 1703 | 1678 |
| 1704 // Use inline cache data array to invoke the target or continue in inline | 1679 // Use inline cache data array to invoke the target or continue in inline |
| 1705 // cache miss handler. Stub for 1-argument check (receiver class). | 1680 // cache miss handler. Stub for 1-argument check (receiver class). |
| 1706 // ECX: Inline cache data array | 1681 // ECX: Inline cache data array |
| 1707 // EDX: Arguments array | 1682 // EDX: Arguments array |
| 1708 // TOS(0): return address | 1683 // TOS(0): return address |
| 1709 // Inline cache data array structure: | 1684 // Inline cache data array structure: |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1795 // TOS + 3: SubtypeTestCache. | 1770 // TOS + 3: SubtypeTestCache. |
| 1796 // Result in ECX: null -> not found, otherwise result (true or false). | 1771 // Result in ECX: null -> not found, otherwise result (true or false). |
| 1797 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { | 1772 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { |
| 1798 ASSERT((1 <= n) && (n <= 3)); | 1773 ASSERT((1 <= n) && (n <= 3)); |
| 1799 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize; | 1774 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize; |
| 1800 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize; | 1775 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize; |
| 1801 const intptr_t kCacheOffsetInBytes = 3 * kWordSize; | 1776 const intptr_t kCacheOffsetInBytes = 3 * kWordSize; |
| 1802 const Immediate raw_null = | 1777 const Immediate raw_null = |
| 1803 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1778 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1804 __ movl(EAX, Address(ESP, kInstanceOffsetInBytes)); | 1779 __ movl(EAX, Address(ESP, kInstanceOffsetInBytes)); |
| 1805 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); | 1780 __ GetClassOf(ECX, EAX, EBX); |
| 1806 // EAX: instance, ECX: instance-class. | 1781 // EAX: instance, ECX: instance-class. |
| 1807 // Get instance type arguments | 1782 // Get instance type arguments |
| 1808 if (n > 1) { | 1783 if (n > 1) { |
| 1809 // Compute instance type arguments into EBX. | 1784 // Compute instance type arguments into EBX. |
| 1810 Label has_no_type_arguments; | 1785 Label has_no_type_arguments; |
| 1811 __ movl(EBX, raw_null); | 1786 __ movl(EBX, raw_null); |
| 1812 __ movl(EDI, FieldAddress(ECX, | 1787 __ movl(EDI, FieldAddress(ECX, |
| 1813 Class::type_arguments_instance_field_offset_offset())); | 1788 Class::type_arguments_instance_field_offset_offset())); |
| 1814 __ cmpl(EDI, Immediate(Class::kNoTypeArguments)); | 1789 __ cmpl(EDI, Immediate(Class::kNoTypeArguments)); |
| 1815 __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump); | 1790 __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1891 // TOS + 2: instance. | 1866 // TOS + 2: instance. |
| 1892 // TOS + 3: cache array. | 1867 // TOS + 3: cache array. |
| 1893 // Result in ECX: null -> not found, otherwise result (true or false). | 1868 // Result in ECX: null -> not found, otherwise result (true or false). |
| 1894 void StubCode::GenerateSubtype3TestCacheStub(Assembler* assembler) { | 1869 void StubCode::GenerateSubtype3TestCacheStub(Assembler* assembler) { |
| 1895 GenerateSubtypeNTestCacheStub(assembler, 3); | 1870 GenerateSubtypeNTestCacheStub(assembler, 3); |
| 1896 } | 1871 } |
| 1897 | 1872 |
| 1898 } // namespace dart | 1873 } // namespace dart |
| 1899 | 1874 |
| 1900 #endif // defined TARGET_ARCH_IA32 | 1875 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |