Chromium Code Reviews| 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" // Needed here to get TARGET_ARCH_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 7 | 7 |
| 8 #include "vm/opt_code_generator.h" | 8 #include "vm/opt_code_generator.h" |
| 9 | 9 |
| 10 #include "vm/assembler_macros.h" | 10 #include "vm/assembler_macros.h" |
| (...skipping 965 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 976 VisitLoadTwo(node->left(), node->right(), EAX, EDX); | 976 VisitLoadTwo(node->left(), node->right(), EAX, EDX); |
| 977 __ testl(EDX, Immediate(kSmiTagMask)); | 977 __ testl(EDX, Immediate(kSmiTagMask)); |
| 978 __ j(NOT_ZERO, &slow_case); // Call operator if right is not Smi. | 978 __ j(NOT_ZERO, &slow_case); // Call operator if right is not Smi. |
| 979 __ cmpl(EDX, Immediate(0)); | 979 __ cmpl(EDX, Immediate(0)); |
| 980 __ j(LESS, &slow_case); // Result will not be Smi. | 980 __ j(LESS, &slow_case); // Result will not be Smi. |
| 981 | 981 |
| 982 // Test left. | 982 // Test left. |
| 983 __ testl(EAX, Immediate(kSmiTagMask)); | 983 __ testl(EAX, Immediate(kSmiTagMask)); |
| 984 __ j(ZERO, &is_smi); | 984 __ j(ZERO, &is_smi); |
| 985 | 985 |
| 986 __ movl(EBX, FieldAddress(EAX, Object::class_offset())); | 986 __ CompareClassOf(EAX, Class::Handle(object_store->mint_class()), EBX); |
| 987 __ CompareObject(EBX, Class::ZoneHandle(object_store->mint_class())); | |
| 988 __ j(NOT_EQUAL, deopt_blob->label()); | 987 __ j(NOT_EQUAL, deopt_blob->label()); |
| 989 | 988 |
| 990 // Load lower Mint word, convert to Smi. It is OK to loose bits. | 989 // Load lower Mint word, convert to Smi. It is OK to loose bits. |
| 991 __ movl(EAX, FieldAddress(EAX, Mint::value_offset())); | 990 __ movl(EAX, FieldAddress(EAX, Mint::value_offset())); |
| 992 __ SmiTag(EAX); | 991 __ SmiTag(EAX); |
| 993 | 992 |
| 994 __ Bind(&is_smi); | 993 __ Bind(&is_smi); |
| 995 __ andl(EAX, EDX); | 994 __ andl(EAX, EDX); |
| 996 __ jmp(&done); | 995 __ jmp(&done); |
| 997 __ Bind(&slow_case); | 996 __ Bind(&slow_case); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1042 | 1041 |
| 1043 // 'reg' is not modified, 'temp' is trashed. | 1042 // 'reg' is not modified, 'temp' is trashed. |
| 1044 // Fall through if double, jump to 'is_smi' if Smi and | 1043 // Fall through if double, jump to 'is_smi' if Smi and |
| 1045 // jump to 'not_double_or_smi' if neither double nor Smi. | 1044 // jump to 'not_double_or_smi' if neither double nor Smi. |
| 1046 void OptimizingCodeGenerator::CheckIfDoubleOrSmi(Register reg, | 1045 void OptimizingCodeGenerator::CheckIfDoubleOrSmi(Register reg, |
| 1047 Register temp, | 1046 Register temp, |
| 1048 Label* is_smi, | 1047 Label* is_smi, |
| 1049 Label* not_double_or_smi) { | 1048 Label* not_double_or_smi) { |
| 1050 __ testl(reg, Immediate(kSmiTagMask)); | 1049 __ testl(reg, Immediate(kSmiTagMask)); |
| 1051 __ j(ZERO, is_smi); | 1050 __ j(ZERO, is_smi); |
| 1052 __ movl(temp, FieldAddress(reg, Object::class_offset())); | 1051 __ CompareClassOf(reg, double_class_, temp); |
| 1053 __ CompareObject(temp, double_class_); | |
| 1054 __ j(NOT_EQUAL, not_double_or_smi); | 1052 __ j(NOT_EQUAL, not_double_or_smi); |
| 1055 } | 1053 } |
| 1056 | 1054 |
| 1057 | 1055 |
| 1058 // Result of the computation is a newly allocated double object or | 1056 // Result of the computation is a newly allocated double object or |
| 1059 // a temporary object if the parent node specifies a CodeGenInfo for this node | 1057 // a temporary object if the parent node specifies a CodeGenInfo for this node |
| 1060 // and therefore knows how to handle a temporary. A temporary object cannot | 1058 // and therefore knows how to handle a temporary. A temporary object cannot |
| 1061 // be used for long living values (e.g., the ones stored on stack or into other | 1059 // be used for long living values (e.g., the ones stored on stack or into other |
| 1062 // objects). | 1060 // objects). |
| 1063 // Implement for combinations: Double/Double, Double/Smi, Smi/Double, as | 1061 // Implement for combinations: Double/Double, Double/Smi, Smi/Double, as |
| (...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1410 // TODO(srdjan): Do not hardwire register. | 1408 // TODO(srdjan): Do not hardwire register. |
| 1411 UNIMPLEMENTED(); | 1409 UNIMPLEMENTED(); |
| 1412 } | 1410 } |
| 1413 DeoptimizationBlob* deopt_blob = | 1411 DeoptimizationBlob* deopt_blob = |
| 1414 AddDeoptimizationBlob(node, EBX, kDeoptInstanceGetterSameTarget); | 1412 AddDeoptimizationBlob(node, EBX, kDeoptInstanceGetterSameTarget); |
| 1415 if (NodeMayBeSmi(receiver)) { | 1413 if (NodeMayBeSmi(receiver)) { |
| 1416 __ testl(EBX, Immediate(kSmiTagMask)); | 1414 __ testl(EBX, Immediate(kSmiTagMask)); |
| 1417 __ j(ZERO, deopt_blob->label()); | 1415 __ j(ZERO, deopt_blob->label()); |
| 1418 } | 1416 } |
| 1419 | 1417 |
| 1420 __ movl(EAX, FieldAddress(EBX, Object::class_offset())); | 1418 __ LoadObjectClassId(EAX, EBX); |
| 1421 const ICData& ic_data = node->ic_data(); | 1419 const ICData& ic_data = node->ic_data(); |
| 1422 Function& target = Function::Handle(); | 1420 Function& target = Function::Handle(); |
| 1423 Label load_field; | 1421 Label load_field; |
| 1424 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 1422 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 1425 Class& cls = Class::ZoneHandle(); | 1423 Class& cls = Class::Handle(); |
| 1426 ic_data.GetOneClassCheckAt(i, &cls, &target); | 1424 ic_data.GetOneClassCheckAt(i, &cls, &target); |
| 1427 __ CompareObject(EAX, cls); | 1425 __ CompareClassId(EAX, cls); |
|
Ivan Posva
2012/05/26 04:34:46
Not sure about others, but I find this more readab
Vyacheslav Egorov (Google)
2012/05/26 16:48:22
ok. I will inline them. I agree that macros does n
| |
| 1428 if (i == (ic_data.NumberOfChecks() - 1)) { | 1426 if (i == (ic_data.NumberOfChecks() - 1)) { |
| 1429 __ j(NOT_EQUAL, deopt_blob->label()); | 1427 __ j(NOT_EQUAL, deopt_blob->label()); |
| 1430 } else { | 1428 } else { |
| 1431 __ j(EQUAL, &load_field); | 1429 __ j(EQUAL, &load_field); |
| 1432 } | 1430 } |
| 1433 } | 1431 } |
| 1434 Class& cls = Class::Handle(); | 1432 Class& cls = Class::Handle(); |
| 1435 ic_data.GetOneClassCheckAt(0, &cls, &target); | 1433 ic_data.GetOneClassCheckAt(0, &cls, &target); |
| 1436 | 1434 |
| 1437 __ Bind(&load_field); | 1435 __ Bind(&load_field); |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1620 } | 1618 } |
| 1621 } | 1619 } |
| 1622 // TODO(srdjan): sort classes/target by their invocation count. | 1620 // TODO(srdjan): sort classes/target by their invocation count. |
| 1623 DeoptimizationBlob* deopt_blob = AddDeoptimizationBlob( | 1621 DeoptimizationBlob* deopt_blob = AddDeoptimizationBlob( |
| 1624 node, recv_reg, value_reg, kDeoptInstanceSetterSameTarget); | 1622 node, recv_reg, value_reg, kDeoptInstanceSetterSameTarget); |
| 1625 // Deoptimize if Smi, since they do not have setters. | 1623 // Deoptimize if Smi, since they do not have setters. |
| 1626 if (NodeMayBeSmi(receiver)) { | 1624 if (NodeMayBeSmi(receiver)) { |
| 1627 __ testl(recv_reg, Immediate(kSmiTagMask)); | 1625 __ testl(recv_reg, Immediate(kSmiTagMask)); |
| 1628 __ j(ZERO, deopt_blob->label()); | 1626 __ j(ZERO, deopt_blob->label()); |
| 1629 } | 1627 } |
| 1630 __ movl(EBX, FieldAddress(recv_reg, Object::class_offset())); | 1628 __ LoadObjectClassId(EBX, recv_reg); |
| 1631 // Initialize setter arguments, but leave the class and target fields NULL. | 1629 // Initialize setter arguments, but leave the class and target fields NULL. |
| 1632 InstanceSetterArgs setter_args = | 1630 InstanceSetterArgs setter_args = |
| 1633 {NULL, NULL, &field_name, recv_reg, value_reg, | 1631 {NULL, NULL, &field_name, recv_reg, value_reg, |
| 1634 node->id(), node->token_index()}; | 1632 node->id(), node->token_index()}; |
| 1635 | 1633 |
| 1636 if (unique_target) { | 1634 if (unique_target) { |
| 1637 Label store_field; | 1635 Label store_field; |
| 1638 for (intptr_t i = 0; i < classes.length(); i++) { | 1636 for (intptr_t i = 0; i < classes.length(); i++) { |
| 1639 __ CompareObject(EBX, *classes[i]); | 1637 __ CompareClassId(EBX, *classes[i]); |
| 1640 if (i == (classes.length() - 1)) { | 1638 if (i == (classes.length() - 1)) { |
| 1641 __ j(NOT_EQUAL, deopt_blob->label()); | 1639 __ j(NOT_EQUAL, deopt_blob->label()); |
| 1642 } else { | 1640 } else { |
| 1643 __ j(EQUAL, &store_field); | 1641 __ j(EQUAL, &store_field); |
| 1644 } | 1642 } |
| 1645 } | 1643 } |
| 1646 __ Bind(&store_field); | 1644 __ Bind(&store_field); |
| 1647 setter_args.cls = classes[0]; | 1645 setter_args.cls = classes[0]; |
| 1648 setter_args.target = targets[0]; | 1646 setter_args.target = targets[0]; |
| 1649 GenerateInstanceSetter(setter_args); | 1647 GenerateInstanceSetter(setter_args); |
| (...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1983 DeoptimizationBlob* deopt_blob = | 1981 DeoptimizationBlob* deopt_blob = |
| 1984 AddDeoptimizationBlob(node, EAX, EDX, kDeoptEqualityNoFeedback); | 1982 AddDeoptimizationBlob(node, EAX, EDX, kDeoptEqualityNoFeedback); |
| 1985 __ j(NOT_EQUAL, deopt_blob->label()); | 1983 __ j(NOT_EQUAL, deopt_blob->label()); |
| 1986 } else { | 1984 } else { |
| 1987 DeoptimizationBlob* deopt_blob = | 1985 DeoptimizationBlob* deopt_blob = |
| 1988 AddDeoptimizationBlob(node, EAX, EDX, kDeoptEqualityClassCheck); | 1986 AddDeoptimizationBlob(node, EAX, EDX, kDeoptEqualityClassCheck); |
| 1989 __ j(EQUAL, &compare); | 1987 __ j(EQUAL, &compare); |
| 1990 // Smi causes deoptimization. | 1988 // Smi causes deoptimization. |
| 1991 __ testl(EAX, Immediate(kSmiTagMask)); | 1989 __ testl(EAX, Immediate(kSmiTagMask)); |
| 1992 __ j(ZERO, deopt_blob->label()); | 1990 __ j(ZERO, deopt_blob->label()); |
| 1993 __ movl(EBX, FieldAddress(EAX, Object::class_offset())); | 1991 __ LoadObjectClassId(EBX, EAX); |
| 1994 for (intptr_t i = 0; i < num_classes; i++) { | 1992 for (intptr_t i = 0; i < num_classes; i++) { |
| 1995 const Class& cls = *(*classes)[i]; | 1993 const Class& cls = *(*classes)[i]; |
| 1996 __ CompareObject(EBX, cls); | 1994 __ CompareClassId(EBX, cls); |
| 1997 if (i == (num_classes - 1)) { | 1995 if (i == (num_classes - 1)) { |
| 1998 __ j(NOT_EQUAL, deopt_blob->label()); | 1996 __ j(NOT_EQUAL, deopt_blob->label()); |
| 1999 } else { | 1997 } else { |
| 2000 __ j(EQUAL, &compare); | 1998 __ j(EQUAL, &compare); |
| 2001 } | 1999 } |
| 2002 } | 2000 } |
| 2003 } | 2001 } |
| 2004 __ Bind(&compare); | 2002 __ Bind(&compare); |
| 2005 __ cmpl(EAX, EDX); | 2003 __ cmpl(EAX, EDX); |
| 2006 if (NodeInfoHasLabels(node)) { | 2004 if (NodeInfoHasLabels(node)) { |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2164 CodeGenInfo index_info(node->index_expr()); | 2162 CodeGenInfo index_info(node->index_expr()); |
| 2165 VisitLoadTwo(node->array(), node->index_expr(), EBX, EDX); | 2163 VisitLoadTwo(node->array(), node->index_expr(), EBX, EDX); |
| 2166 DeoptimizationBlob* deopt_blob = | 2164 DeoptimizationBlob* deopt_blob = |
| 2167 AddDeoptimizationBlob(node, EBX, EDX, kDeoptLoadIndexedFixedArray); | 2165 AddDeoptimizationBlob(node, EBX, EDX, kDeoptLoadIndexedFixedArray); |
| 2168 const Class& test_class = NodeHasClassAt(node, object_array_class, 0) ? | 2166 const Class& test_class = NodeHasClassAt(node, object_array_class, 0) ? |
| 2169 object_array_class : immutable_object_array_class; | 2167 object_array_class : immutable_object_array_class; |
| 2170 // Type checks of array. | 2168 // Type checks of array. |
| 2171 if (!array_info.IsClass(test_class)) { | 2169 if (!array_info.IsClass(test_class)) { |
| 2172 __ testl(EBX, Immediate(kSmiTagMask)); // Deoptimize if Smi. | 2170 __ testl(EBX, Immediate(kSmiTagMask)); // Deoptimize if Smi. |
| 2173 __ j(ZERO, deopt_blob->label()); | 2171 __ j(ZERO, deopt_blob->label()); |
| 2174 __ movl(EAX, FieldAddress(EBX, Object::class_offset())); | 2172 __ CompareClassOf(EBX, test_class, EAX); |
| 2175 __ CompareObject(EAX, test_class); | |
| 2176 __ j(NOT_EQUAL, deopt_blob->label()); | 2173 __ j(NOT_EQUAL, deopt_blob->label()); |
| 2177 PropagateBackLocalClass(node->array(), test_class); | 2174 PropagateBackLocalClass(node->array(), test_class); |
| 2178 } | 2175 } |
| 2179 | 2176 |
| 2180 // Type check of index. | 2177 // Type check of index. |
| 2181 if (!index_info.IsClass(smi_class_)) { | 2178 if (!index_info.IsClass(smi_class_)) { |
| 2182 __ testl(EDX, Immediate(kSmiTagMask)); | 2179 __ testl(EDX, Immediate(kSmiTagMask)); |
| 2183 __ j(NOT_ZERO, deopt_blob->label()); | 2180 __ j(NOT_ZERO, deopt_blob->label()); |
| 2184 PropagateBackLocalClass(node->index_expr(), smi_class_); | 2181 PropagateBackLocalClass(node->index_expr(), smi_class_); |
| 2185 } | 2182 } |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 2202 AddDeoptimizationBlob(node, EDX, EAX, kDeoptLoadIndexedGrowableArray); | 2199 AddDeoptimizationBlob(node, EDX, EAX, kDeoptLoadIndexedGrowableArray); |
| 2203 // EAX: index, EDX: array. | 2200 // EAX: index, EDX: array. |
| 2204 if (!index_info.IsClass(smi_class_)) { | 2201 if (!index_info.IsClass(smi_class_)) { |
| 2205 __ testl(EAX, Immediate(kSmiTagMask)); | 2202 __ testl(EAX, Immediate(kSmiTagMask)); |
| 2206 __ j(NOT_ZERO, deopt_blob->label()); // Not Smi index. | 2203 __ j(NOT_ZERO, deopt_blob->label()); // Not Smi index. |
| 2207 PropagateBackLocalClass(node->index_expr(), smi_class_); | 2204 PropagateBackLocalClass(node->index_expr(), smi_class_); |
| 2208 } | 2205 } |
| 2209 if (!array_info.IsClass(growable_object_array_class_)) { | 2206 if (!array_info.IsClass(growable_object_array_class_)) { |
| 2210 __ testl(EDX, Immediate(kSmiTagMask)); | 2207 __ testl(EDX, Immediate(kSmiTagMask)); |
| 2211 __ j(ZERO, deopt_blob->label()); // Array is Smi. | 2208 __ j(ZERO, deopt_blob->label()); // Array is Smi. |
| 2212 __ movl(EBX, FieldAddress(EDX, Object::class_offset())); | 2209 __ CompareClassOf(EDX, growable_object_array_class_, EBX); |
| 2213 __ CompareObject(EBX, growable_object_array_class_); | |
| 2214 __ j(NOT_EQUAL, deopt_blob->label()); // Not GrowableObjectArray. | 2210 __ j(NOT_EQUAL, deopt_blob->label()); // Not GrowableObjectArray. |
| 2215 PropagateBackLocalClass(node->array(), growable_object_array_class_); | 2211 PropagateBackLocalClass(node->array(), growable_object_array_class_); |
| 2216 } | 2212 } |
| 2217 // Range check: deoptimize if out of bounds. | 2213 // Range check: deoptimize if out of bounds. |
| 2218 __ cmpl(EAX, FieldAddress(EDX, GrowableObjectArray::length_offset())); | 2214 __ cmpl(EAX, FieldAddress(EDX, GrowableObjectArray::length_offset())); |
| 2219 __ j(ABOVE_EQUAL, deopt_blob->label()); | 2215 __ j(ABOVE_EQUAL, deopt_blob->label()); |
| 2220 __ movl(EDX, FieldAddress(EDX, GrowableObjectArray::data_offset())); | 2216 __ movl(EDX, FieldAddress(EDX, GrowableObjectArray::data_offset())); |
| 2221 // Note that EAX is Smi, i.e, times 2. | 2217 // Note that EAX is Smi, i.e, times 2. |
| 2222 ASSERT(kSmiTagShift == 1); | 2218 ASSERT(kSmiTagShift == 1); |
| 2223 __ movl(EAX, FieldAddress(EDX, EAX, TIMES_2, sizeof(RawArray))); | 2219 __ movl(EAX, FieldAddress(EDX, EAX, TIMES_2, sizeof(RawArray))); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2270 VisitLoadOne(node->value(), ECX); | 2266 VisitLoadOne(node->value(), ECX); |
| 2271 DeoptimizationBlob* deopt_blob = | 2267 DeoptimizationBlob* deopt_blob = |
| 2272 AddDeoptimizationBlob(node, EAX, EBX, ECX, kDeoptStoreIndexed); | 2268 AddDeoptimizationBlob(node, EAX, EBX, ECX, kDeoptStoreIndexed); |
| 2273 __ popl(EBX); // index. | 2269 __ popl(EBX); // index. |
| 2274 __ popl(EAX); // array. | 2270 __ popl(EAX); // array. |
| 2275 // ECX: value, EBX:index, EAX: array. | 2271 // ECX: value, EBX:index, EAX: array. |
| 2276 // Check class of array. | 2272 // Check class of array. |
| 2277 if (class_of_this_array.raw() != object_array_class.raw()) { | 2273 if (class_of_this_array.raw() != object_array_class.raw()) { |
| 2278 __ testl(EAX, Immediate(kSmiTagMask)); | 2274 __ testl(EAX, Immediate(kSmiTagMask)); |
| 2279 __ j(ZERO, deopt_blob->label()); // Array is smi -> deopt. | 2275 __ j(ZERO, deopt_blob->label()); // Array is smi -> deopt. |
| 2280 __ movl(EDX, FieldAddress(EAX, Object::class_offset())); | 2276 __ CompareClassOf(EAX, object_array_class, EDX); |
| 2281 __ CompareObject(EDX, object_array_class); | |
| 2282 __ j(NOT_EQUAL, deopt_blob->label()); // Not ObjectArray -> deopt. | 2277 __ j(NOT_EQUAL, deopt_blob->label()); // Not ObjectArray -> deopt. |
| 2283 PropagateBackLocalClass(node->array(), object_array_class); | 2278 PropagateBackLocalClass(node->array(), object_array_class); |
| 2284 } | 2279 } |
| 2285 // Check class of index. | 2280 // Check class of index. |
| 2286 if (!index_is_smi) { | 2281 if (!index_is_smi) { |
| 2287 __ testl(EBX, Immediate(kSmiTagMask)); | 2282 __ testl(EBX, Immediate(kSmiTagMask)); |
| 2288 __ j(NOT_ZERO, deopt_blob->label()); // Index not Smi -> deopt. | 2283 __ j(NOT_ZERO, deopt_blob->label()); // Index not Smi -> deopt. |
| 2289 PropagateBackLocalClass(node->index_expr(), smi_class_); | 2284 PropagateBackLocalClass(node->index_expr(), smi_class_); |
| 2290 } | 2285 } |
| 2291 // Range check. | 2286 // Range check. |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 2311 VisitLoadOne(node->value(), ECX); | 2306 VisitLoadOne(node->value(), ECX); |
| 2312 DeoptimizationBlob* deopt_blob = | 2307 DeoptimizationBlob* deopt_blob = |
| 2313 AddDeoptimizationBlob(node, EAX, EBX, ECX, kDeoptStoreIndexed); | 2308 AddDeoptimizationBlob(node, EAX, EBX, ECX, kDeoptStoreIndexed); |
| 2314 __ popl(EBX); // index. | 2309 __ popl(EBX); // index. |
| 2315 __ popl(EAX); // array. | 2310 __ popl(EAX); // array. |
| 2316 // ECX: value, EBX:index, EAX: array, EDX: scratch. | 2311 // ECX: value, EBX:index, EAX: array, EDX: scratch. |
| 2317 // Check class of array. | 2312 // Check class of array. |
| 2318 if (class_of_this_array.raw() != growable_object_array_class_.raw()) { | 2313 if (class_of_this_array.raw() != growable_object_array_class_.raw()) { |
| 2319 __ testl(EAX, Immediate(kSmiTagMask)); | 2314 __ testl(EAX, Immediate(kSmiTagMask)); |
| 2320 __ j(ZERO, deopt_blob->label()); // Array is smi -> deopt. | 2315 __ j(ZERO, deopt_blob->label()); // Array is smi -> deopt. |
| 2321 __ movl(EDX, FieldAddress(EAX, Object::class_offset())); | 2316 __ CompareClassOf(EAX, growable_object_array_class_, EDX); |
| 2322 __ CompareObject(EDX, growable_object_array_class_); | |
| 2323 __ j(NOT_EQUAL, deopt_blob->label()); // Not GrowableObjectArray. | 2317 __ j(NOT_EQUAL, deopt_blob->label()); // Not GrowableObjectArray. |
| 2324 PropagateBackLocalClass(node->array(), growable_object_array_class_); | 2318 PropagateBackLocalClass(node->array(), growable_object_array_class_); |
| 2325 } | 2319 } |
| 2326 // Check class of index. | 2320 // Check class of index. |
| 2327 if (!index_is_smi) { | 2321 if (!index_is_smi) { |
| 2328 __ testl(EBX, Immediate(kSmiTagMask)); | 2322 __ testl(EBX, Immediate(kSmiTagMask)); |
| 2329 __ j(NOT_ZERO, deopt_blob->label()); // Index not Smi -> deopt. | 2323 __ j(NOT_ZERO, deopt_blob->label()); // Index not Smi -> deopt. |
| 2330 PropagateBackLocalClass(node->index_expr(), smi_class_); | 2324 PropagateBackLocalClass(node->index_expr(), smi_class_); |
| 2331 } | 2325 } |
| 2332 // Range check: deoptimize if out of bounds. | 2326 // Range check: deoptimize if out of bounds. |
| (...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2640 __ jmp(&done); | 2634 __ jmp(&done); |
| 2641 __ Bind(¬_smi); // Continue with other test below. | 2635 __ Bind(¬_smi); // Continue with other test below. |
| 2642 } else if (NodeMayBeSmi(receiver)) { | 2636 } else if (NodeMayBeSmi(receiver)) { |
| 2643 DeoptimizationBlob* deopt_blob = | 2637 DeoptimizationBlob* deopt_blob = |
| 2644 AddDeoptimizationBlob(node, kDeoptCheckedInstanceCallSmiFail); | 2638 AddDeoptimizationBlob(node, kDeoptCheckedInstanceCallSmiFail); |
| 2645 __ testl(EAX, Immediate(kSmiTagMask)); | 2639 __ testl(EAX, Immediate(kSmiTagMask)); |
| 2646 __ j(ZERO, deopt_blob->label()); | 2640 __ j(ZERO, deopt_blob->label()); |
| 2647 } else { | 2641 } else { |
| 2648 // Receiver cannot be Smi, no need to test it. | 2642 // Receiver cannot be Smi, no need to test it. |
| 2649 } | 2643 } |
| 2650 __ movl(EAX, FieldAddress(EAX, Object::class_offset())); // Receiver's class. | 2644 __ LoadObjectClassId(EAX, EAX); // Receiver's class. |
| 2651 for (intptr_t i = start_ix; i < classes.length(); i++) { | 2645 for (intptr_t i = start_ix; i < classes.length(); i++) { |
| 2652 const Class& cls = *classes[i]; | 2646 const Class& cls = *classes[i]; |
| 2653 const Function& target = *targets[i]; | 2647 const Function& target = *targets[i]; |
| 2654 __ CompareObject(EAX, cls); | 2648 __ CompareClassId(EAX, cls); |
| 2655 if (i == (classes.length() - 1)) { | 2649 if (i == (classes.length() - 1)) { |
| 2656 // Last check. | 2650 // Last check. |
| 2657 DeoptimizationBlob* deopt_blob = | 2651 DeoptimizationBlob* deopt_blob = |
| 2658 AddDeoptimizationBlob(node, kDeoptCheckedInstanceCallCheckFail); | 2652 AddDeoptimizationBlob(node, kDeoptCheckedInstanceCallCheckFail); |
| 2659 __ j(NOT_EQUAL, deopt_blob->label()); | 2653 __ j(NOT_EQUAL, deopt_blob->label()); |
| 2660 GenerateDirectCall(node->id(), | 2654 GenerateDirectCall(node->id(), |
| 2661 token_index, | 2655 token_index, |
| 2662 target, | 2656 target, |
| 2663 num_args, | 2657 num_args, |
| 2664 optional_arguments_names); | 2658 optional_arguments_names); |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2901 } | 2895 } |
| 2902 } | 2896 } |
| 2903 // TODO(srdjan): Implement unary kSUB (negate) Mint. | 2897 // TODO(srdjan): Implement unary kSUB (negate) Mint. |
| 2904 CodeGenerator::VisitUnaryOpNode(node); | 2898 CodeGenerator::VisitUnaryOpNode(node); |
| 2905 } | 2899 } |
| 2906 | 2900 |
| 2907 | 2901 |
| 2908 } // namespace dart | 2902 } // namespace dart |
| 2909 | 2903 |
| 2910 #endif // defined TARGET_ARCH_IA32 | 2904 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |