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