| 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 948 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 959 } | 959 } |
| 960 | 960 |
| 961 | 961 |
| 962 // Supports some mixed Smi/Mint operations. | 962 // Supports some mixed Smi/Mint operations. |
| 963 // For BIT_AND operation with right operand being Smi, we can throw away | 963 // For BIT_AND operation with right operand being Smi, we can throw away |
| 964 // any Mint bits above the Smi range as long as the right operand is positive. | 964 // any Mint bits above the Smi range as long as the right operand is positive. |
| 965 // 'allow_smi' is true if Smi and Mint classes have been encountered. | 965 // 'allow_smi' is true if Smi and Mint classes have been encountered. |
| 966 void OptimizingCodeGenerator::GenerateMintBinaryOp(BinaryOpNode* node, | 966 void OptimizingCodeGenerator::GenerateMintBinaryOp(BinaryOpNode* node, |
| 967 bool allow_smi) { | 967 bool allow_smi) { |
| 968 const char* kOptMessage = "Inline Mint binop."; | 968 const char* kOptMessage = "Inline Mint binop."; |
| 969 ObjectStore* object_store = Isolate::Current()->object_store(); | |
| 970 const Token::Kind kind = node->kind(); | 969 const Token::Kind kind = node->kind(); |
| 971 if (kind == Token::kBIT_AND) { | 970 if (kind == Token::kBIT_AND) { |
| 972 TraceOpt(node, kOptMessage); | 971 TraceOpt(node, kOptMessage); |
| 973 Label is_smi, slow_case, done; | 972 Label is_smi, slow_case, done; |
| 974 DeoptimizationBlob* deopt_blob = | 973 DeoptimizationBlob* deopt_blob = |
| 975 AddDeoptimizationBlob(node, EAX, EDX, kDeoptMintBinaryOp); | 974 AddDeoptimizationBlob(node, EAX, EDX, kDeoptMintBinaryOp); |
| 976 VisitLoadTwo(node->left(), node->right(), EAX, EDX); | 975 VisitLoadTwo(node->left(), node->right(), EAX, EDX); |
| 977 __ testl(EDX, Immediate(kSmiTagMask)); | 976 __ testl(EDX, Immediate(kSmiTagMask)); |
| 978 __ j(NOT_ZERO, &slow_case); // Call operator if right is not Smi. | 977 __ j(NOT_ZERO, &slow_case); // Call operator if right is not Smi. |
| 979 __ cmpl(EDX, Immediate(0)); | 978 __ cmpl(EDX, Immediate(0)); |
| 980 __ j(LESS, &slow_case); // Result will not be Smi. | 979 __ j(LESS, &slow_case); // Result will not be Smi. |
| 981 | 980 |
| 982 // Test left. | 981 // Test left. |
| 983 __ testl(EAX, Immediate(kSmiTagMask)); | 982 __ testl(EAX, Immediate(kSmiTagMask)); |
| 984 __ j(ZERO, &is_smi); | 983 __ j(ZERO, &is_smi); |
| 985 | 984 |
| 986 __ CompareClassOfObject(EAX, | 985 __ CompareClassId(EAX, kMint, EBX); |
| 987 Class::Handle(object_store->mint_class()), | |
| 988 EBX); | |
| 989 __ j(NOT_EQUAL, deopt_blob->label()); | 986 __ j(NOT_EQUAL, deopt_blob->label()); |
| 990 | 987 |
| 991 // Load lower Mint word, convert to Smi. It is OK to loose bits. | 988 // Load lower Mint word, convert to Smi. It is OK to loose bits. |
| 992 __ movl(EAX, FieldAddress(EAX, Mint::value_offset())); | 989 __ movl(EAX, FieldAddress(EAX, Mint::value_offset())); |
| 993 __ SmiTag(EAX); | 990 __ SmiTag(EAX); |
| 994 | 991 |
| 995 __ Bind(&is_smi); | 992 __ Bind(&is_smi); |
| 996 __ andl(EAX, EDX); | 993 __ andl(EAX, EDX); |
| 997 __ jmp(&done); | 994 __ jmp(&done); |
| 998 __ Bind(&slow_case); | 995 __ Bind(&slow_case); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1043 | 1040 |
| 1044 // 'reg' is not modified, 'temp' is trashed. | 1041 // 'reg' is not modified, 'temp' is trashed. |
| 1045 // Fall through if double, jump to 'is_smi' if Smi and | 1042 // Fall through if double, jump to 'is_smi' if Smi and |
| 1046 // jump to 'not_double_or_smi' if neither double nor Smi. | 1043 // jump to 'not_double_or_smi' if neither double nor Smi. |
| 1047 void OptimizingCodeGenerator::CheckIfDoubleOrSmi(Register reg, | 1044 void OptimizingCodeGenerator::CheckIfDoubleOrSmi(Register reg, |
| 1048 Register temp, | 1045 Register temp, |
| 1049 Label* is_smi, | 1046 Label* is_smi, |
| 1050 Label* not_double_or_smi) { | 1047 Label* not_double_or_smi) { |
| 1051 __ testl(reg, Immediate(kSmiTagMask)); | 1048 __ testl(reg, Immediate(kSmiTagMask)); |
| 1052 __ j(ZERO, is_smi); | 1049 __ j(ZERO, is_smi); |
| 1053 __ CompareClassOfObject(reg, double_class_, temp); | 1050 __ CompareClassId(reg, kDouble, temp); |
| 1054 __ j(NOT_EQUAL, not_double_or_smi); | 1051 __ j(NOT_EQUAL, not_double_or_smi); |
| 1055 } | 1052 } |
| 1056 | 1053 |
| 1057 | 1054 |
| 1058 // Result of the computation is a newly allocated double object or | 1055 // 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 | 1056 // 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 | 1057 // 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 | 1058 // be used for long living values (e.g., the ones stored on stack or into other |
| 1062 // objects). | 1059 // objects). |
| 1063 // Implement for combinations: Double/Double, Double/Smi, Smi/Double, as | 1060 // 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. | 1407 // TODO(srdjan): Do not hardwire register. |
| 1411 UNIMPLEMENTED(); | 1408 UNIMPLEMENTED(); |
| 1412 } | 1409 } |
| 1413 DeoptimizationBlob* deopt_blob = | 1410 DeoptimizationBlob* deopt_blob = |
| 1414 AddDeoptimizationBlob(node, EBX, kDeoptInstanceGetterSameTarget); | 1411 AddDeoptimizationBlob(node, EBX, kDeoptInstanceGetterSameTarget); |
| 1415 if (NodeMayBeSmi(receiver)) { | 1412 if (NodeMayBeSmi(receiver)) { |
| 1416 __ testl(EBX, Immediate(kSmiTagMask)); | 1413 __ testl(EBX, Immediate(kSmiTagMask)); |
| 1417 __ j(ZERO, deopt_blob->label()); | 1414 __ j(ZERO, deopt_blob->label()); |
| 1418 } | 1415 } |
| 1419 | 1416 |
| 1420 __ LoadClassIndexOfObject(EAX, EBX); | 1417 __ LoadClassId(EAX, EBX); |
| 1421 const ICData& ic_data = node->ic_data(); | 1418 const ICData& ic_data = node->ic_data(); |
| 1422 Function& target = Function::Handle(); | 1419 Function& target = Function::Handle(); |
| 1423 Label load_field; | 1420 Label load_field; |
| 1424 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 1421 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 1425 Class& cls = Class::Handle(); | 1422 Class& cls = Class::Handle(); |
| 1426 ic_data.GetOneClassCheckAt(i, &cls, &target); | 1423 ic_data.GetOneClassCheckAt(i, &cls, &target); |
| 1427 __ cmpl(EAX, Immediate(cls.index())); | 1424 __ cmpl(EAX, Immediate(cls.index())); |
| 1428 if (i == (ic_data.NumberOfChecks() - 1)) { | 1425 if (i == (ic_data.NumberOfChecks() - 1)) { |
| 1429 __ j(NOT_EQUAL, deopt_blob->label()); | 1426 __ j(NOT_EQUAL, deopt_blob->label()); |
| 1430 } else { | 1427 } else { |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1620 } | 1617 } |
| 1621 } | 1618 } |
| 1622 // TODO(srdjan): sort classes/target by their invocation count. | 1619 // TODO(srdjan): sort classes/target by their invocation count. |
| 1623 DeoptimizationBlob* deopt_blob = AddDeoptimizationBlob( | 1620 DeoptimizationBlob* deopt_blob = AddDeoptimizationBlob( |
| 1624 node, recv_reg, value_reg, kDeoptInstanceSetterSameTarget); | 1621 node, recv_reg, value_reg, kDeoptInstanceSetterSameTarget); |
| 1625 // Deoptimize if Smi, since they do not have setters. | 1622 // Deoptimize if Smi, since they do not have setters. |
| 1626 if (NodeMayBeSmi(receiver)) { | 1623 if (NodeMayBeSmi(receiver)) { |
| 1627 __ testl(recv_reg, Immediate(kSmiTagMask)); | 1624 __ testl(recv_reg, Immediate(kSmiTagMask)); |
| 1628 __ j(ZERO, deopt_blob->label()); | 1625 __ j(ZERO, deopt_blob->label()); |
| 1629 } | 1626 } |
| 1630 __ LoadClassIndexOfObject(EBX, recv_reg); | 1627 __ LoadClassId(EBX, recv_reg); |
| 1631 // Initialize setter arguments, but leave the class and target fields NULL. | 1628 // Initialize setter arguments, but leave the class and target fields NULL. |
| 1632 InstanceSetterArgs setter_args = | 1629 InstanceSetterArgs setter_args = |
| 1633 {NULL, NULL, &field_name, recv_reg, value_reg, | 1630 {NULL, NULL, &field_name, recv_reg, value_reg, |
| 1634 node->id(), node->token_index()}; | 1631 node->id(), node->token_index()}; |
| 1635 | 1632 |
| 1636 if (unique_target) { | 1633 if (unique_target) { |
| 1637 Label store_field; | 1634 Label store_field; |
| 1638 for (intptr_t i = 0; i < classes.length(); i++) { | 1635 for (intptr_t i = 0; i < classes.length(); i++) { |
| 1639 __ cmpl(EBX, Immediate(classes[i]->index())); | 1636 __ cmpl(EBX, Immediate(classes[i]->index())); |
| 1640 if (i == (classes.length() - 1)) { | 1637 if (i == (classes.length() - 1)) { |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1983 DeoptimizationBlob* deopt_blob = | 1980 DeoptimizationBlob* deopt_blob = |
| 1984 AddDeoptimizationBlob(node, EAX, EDX, kDeoptEqualityNoFeedback); | 1981 AddDeoptimizationBlob(node, EAX, EDX, kDeoptEqualityNoFeedback); |
| 1985 __ j(NOT_EQUAL, deopt_blob->label()); | 1982 __ j(NOT_EQUAL, deopt_blob->label()); |
| 1986 } else { | 1983 } else { |
| 1987 DeoptimizationBlob* deopt_blob = | 1984 DeoptimizationBlob* deopt_blob = |
| 1988 AddDeoptimizationBlob(node, EAX, EDX, kDeoptEqualityClassCheck); | 1985 AddDeoptimizationBlob(node, EAX, EDX, kDeoptEqualityClassCheck); |
| 1989 __ j(EQUAL, &compare); | 1986 __ j(EQUAL, &compare); |
| 1990 // Smi causes deoptimization. | 1987 // Smi causes deoptimization. |
| 1991 __ testl(EAX, Immediate(kSmiTagMask)); | 1988 __ testl(EAX, Immediate(kSmiTagMask)); |
| 1992 __ j(ZERO, deopt_blob->label()); | 1989 __ j(ZERO, deopt_blob->label()); |
| 1993 __ LoadClassIndexOfObject(EBX, EAX); | 1990 __ LoadClassId(EBX, EAX); |
| 1994 for (intptr_t i = 0; i < num_classes; i++) { | 1991 for (intptr_t i = 0; i < num_classes; i++) { |
| 1995 const Class& cls = *(*classes)[i]; | 1992 const Class& cls = *(*classes)[i]; |
| 1996 __ cmpl(EBX, Immediate(cls.index())); | 1993 __ cmpl(EBX, Immediate(cls.index())); |
| 1997 if (i == (num_classes - 1)) { | 1994 if (i == (num_classes - 1)) { |
| 1998 __ j(NOT_EQUAL, deopt_blob->label()); | 1995 __ j(NOT_EQUAL, deopt_blob->label()); |
| 1999 } else { | 1996 } else { |
| 2000 __ j(EQUAL, &compare); | 1997 __ j(EQUAL, &compare); |
| 2001 } | 1998 } |
| 2002 } | 1999 } |
| 2003 } | 2000 } |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2164 CodeGenInfo index_info(node->index_expr()); | 2161 CodeGenInfo index_info(node->index_expr()); |
| 2165 VisitLoadTwo(node->array(), node->index_expr(), EBX, EDX); | 2162 VisitLoadTwo(node->array(), node->index_expr(), EBX, EDX); |
| 2166 DeoptimizationBlob* deopt_blob = | 2163 DeoptimizationBlob* deopt_blob = |
| 2167 AddDeoptimizationBlob(node, EBX, EDX, kDeoptLoadIndexedFixedArray); | 2164 AddDeoptimizationBlob(node, EBX, EDX, kDeoptLoadIndexedFixedArray); |
| 2168 const Class& test_class = NodeHasClassAt(node, object_array_class, 0) ? | 2165 const Class& test_class = NodeHasClassAt(node, object_array_class, 0) ? |
| 2169 object_array_class : immutable_object_array_class; | 2166 object_array_class : immutable_object_array_class; |
| 2170 // Type checks of array. | 2167 // Type checks of array. |
| 2171 if (!array_info.IsClass(test_class)) { | 2168 if (!array_info.IsClass(test_class)) { |
| 2172 __ testl(EBX, Immediate(kSmiTagMask)); // Deoptimize if Smi. | 2169 __ testl(EBX, Immediate(kSmiTagMask)); // Deoptimize if Smi. |
| 2173 __ j(ZERO, deopt_blob->label()); | 2170 __ j(ZERO, deopt_blob->label()); |
| 2174 __ CompareClassOfObject(EBX, test_class, EAX); | 2171 __ CompareClassId(EBX, test_class.index(), EAX); |
| 2175 __ j(NOT_EQUAL, deopt_blob->label()); | 2172 __ j(NOT_EQUAL, deopt_blob->label()); |
| 2176 PropagateBackLocalClass(node->array(), test_class); | 2173 PropagateBackLocalClass(node->array(), test_class); |
| 2177 } | 2174 } |
| 2178 | 2175 |
| 2179 // Type check of index. | 2176 // Type check of index. |
| 2180 if (!index_info.IsClass(smi_class_)) { | 2177 if (!index_info.IsClass(smi_class_)) { |
| 2181 __ testl(EDX, Immediate(kSmiTagMask)); | 2178 __ testl(EDX, Immediate(kSmiTagMask)); |
| 2182 __ j(NOT_ZERO, deopt_blob->label()); | 2179 __ j(NOT_ZERO, deopt_blob->label()); |
| 2183 PropagateBackLocalClass(node->index_expr(), smi_class_); | 2180 PropagateBackLocalClass(node->index_expr(), smi_class_); |
| 2184 } | 2181 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2201 AddDeoptimizationBlob(node, EDX, EAX, kDeoptLoadIndexedGrowableArray); | 2198 AddDeoptimizationBlob(node, EDX, EAX, kDeoptLoadIndexedGrowableArray); |
| 2202 // EAX: index, EDX: array. | 2199 // EAX: index, EDX: array. |
| 2203 if (!index_info.IsClass(smi_class_)) { | 2200 if (!index_info.IsClass(smi_class_)) { |
| 2204 __ testl(EAX, Immediate(kSmiTagMask)); | 2201 __ testl(EAX, Immediate(kSmiTagMask)); |
| 2205 __ j(NOT_ZERO, deopt_blob->label()); // Not Smi index. | 2202 __ j(NOT_ZERO, deopt_blob->label()); // Not Smi index. |
| 2206 PropagateBackLocalClass(node->index_expr(), smi_class_); | 2203 PropagateBackLocalClass(node->index_expr(), smi_class_); |
| 2207 } | 2204 } |
| 2208 if (!array_info.IsClass(growable_object_array_class_)) { | 2205 if (!array_info.IsClass(growable_object_array_class_)) { |
| 2209 __ testl(EDX, Immediate(kSmiTagMask)); | 2206 __ testl(EDX, Immediate(kSmiTagMask)); |
| 2210 __ j(ZERO, deopt_blob->label()); // Array is Smi. | 2207 __ j(ZERO, deopt_blob->label()); // Array is Smi. |
| 2211 __ CompareClassOfObject(EDX, growable_object_array_class_, EBX); | 2208 __ CompareClassId(EDX, kGrowableObjectArray, EBX); |
| 2212 __ j(NOT_EQUAL, deopt_blob->label()); // Not GrowableObjectArray. | 2209 __ j(NOT_EQUAL, deopt_blob->label()); // Not GrowableObjectArray. |
| 2213 PropagateBackLocalClass(node->array(), growable_object_array_class_); | 2210 PropagateBackLocalClass(node->array(), growable_object_array_class_); |
| 2214 } | 2211 } |
| 2215 // Range check: deoptimize if out of bounds. | 2212 // Range check: deoptimize if out of bounds. |
| 2216 __ cmpl(EAX, FieldAddress(EDX, GrowableObjectArray::length_offset())); | 2213 __ cmpl(EAX, FieldAddress(EDX, GrowableObjectArray::length_offset())); |
| 2217 __ j(ABOVE_EQUAL, deopt_blob->label()); | 2214 __ j(ABOVE_EQUAL, deopt_blob->label()); |
| 2218 __ movl(EDX, FieldAddress(EDX, GrowableObjectArray::data_offset())); | 2215 __ movl(EDX, FieldAddress(EDX, GrowableObjectArray::data_offset())); |
| 2219 // Note that EAX is Smi, i.e, times 2. | 2216 // Note that EAX is Smi, i.e, times 2. |
| 2220 ASSERT(kSmiTagShift == 1); | 2217 ASSERT(kSmiTagShift == 1); |
| 2221 __ movl(EAX, FieldAddress(EDX, EAX, TIMES_2, sizeof(RawArray))); | 2218 __ movl(EAX, FieldAddress(EDX, EAX, TIMES_2, sizeof(RawArray))); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2268 VisitLoadOne(node->value(), ECX); | 2265 VisitLoadOne(node->value(), ECX); |
| 2269 DeoptimizationBlob* deopt_blob = | 2266 DeoptimizationBlob* deopt_blob = |
| 2270 AddDeoptimizationBlob(node, EAX, EBX, ECX, kDeoptStoreIndexed); | 2267 AddDeoptimizationBlob(node, EAX, EBX, ECX, kDeoptStoreIndexed); |
| 2271 __ popl(EBX); // index. | 2268 __ popl(EBX); // index. |
| 2272 __ popl(EAX); // array. | 2269 __ popl(EAX); // array. |
| 2273 // ECX: value, EBX:index, EAX: array. | 2270 // ECX: value, EBX:index, EAX: array. |
| 2274 // Check class of array. | 2271 // Check class of array. |
| 2275 if (class_of_this_array.raw() != object_array_class.raw()) { | 2272 if (class_of_this_array.raw() != object_array_class.raw()) { |
| 2276 __ testl(EAX, Immediate(kSmiTagMask)); | 2273 __ testl(EAX, Immediate(kSmiTagMask)); |
| 2277 __ j(ZERO, deopt_blob->label()); // Array is smi -> deopt. | 2274 __ j(ZERO, deopt_blob->label()); // Array is smi -> deopt. |
| 2278 __ CompareClassOfObject(EAX, object_array_class, EDX); | 2275 __ CompareClassId(EAX, kArray, EDX); |
| 2279 __ j(NOT_EQUAL, deopt_blob->label()); // Not ObjectArray -> deopt. | 2276 __ j(NOT_EQUAL, deopt_blob->label()); // Not ObjectArray -> deopt. |
| 2280 PropagateBackLocalClass(node->array(), object_array_class); | 2277 PropagateBackLocalClass(node->array(), object_array_class); |
| 2281 } | 2278 } |
| 2282 // Check class of index. | 2279 // Check class of index. |
| 2283 if (!index_is_smi) { | 2280 if (!index_is_smi) { |
| 2284 __ testl(EBX, Immediate(kSmiTagMask)); | 2281 __ testl(EBX, Immediate(kSmiTagMask)); |
| 2285 __ j(NOT_ZERO, deopt_blob->label()); // Index not Smi -> deopt. | 2282 __ j(NOT_ZERO, deopt_blob->label()); // Index not Smi -> deopt. |
| 2286 PropagateBackLocalClass(node->index_expr(), smi_class_); | 2283 PropagateBackLocalClass(node->index_expr(), smi_class_); |
| 2287 } | 2284 } |
| 2288 // Range check. | 2285 // Range check. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2308 VisitLoadOne(node->value(), ECX); | 2305 VisitLoadOne(node->value(), ECX); |
| 2309 DeoptimizationBlob* deopt_blob = | 2306 DeoptimizationBlob* deopt_blob = |
| 2310 AddDeoptimizationBlob(node, EAX, EBX, ECX, kDeoptStoreIndexed); | 2307 AddDeoptimizationBlob(node, EAX, EBX, ECX, kDeoptStoreIndexed); |
| 2311 __ popl(EBX); // index. | 2308 __ popl(EBX); // index. |
| 2312 __ popl(EAX); // array. | 2309 __ popl(EAX); // array. |
| 2313 // ECX: value, EBX:index, EAX: array, EDX: scratch. | 2310 // ECX: value, EBX:index, EAX: array, EDX: scratch. |
| 2314 // Check class of array. | 2311 // Check class of array. |
| 2315 if (class_of_this_array.raw() != growable_object_array_class_.raw()) { | 2312 if (class_of_this_array.raw() != growable_object_array_class_.raw()) { |
| 2316 __ testl(EAX, Immediate(kSmiTagMask)); | 2313 __ testl(EAX, Immediate(kSmiTagMask)); |
| 2317 __ j(ZERO, deopt_blob->label()); // Array is smi -> deopt. | 2314 __ j(ZERO, deopt_blob->label()); // Array is smi -> deopt. |
| 2318 __ CompareClassOfObject(EAX, growable_object_array_class_, EDX); | 2315 __ CompareClassId(EAX, kGrowableObjectArray, EDX); |
| 2319 __ j(NOT_EQUAL, deopt_blob->label()); // Not GrowableObjectArray. | 2316 __ j(NOT_EQUAL, deopt_blob->label()); // Not GrowableObjectArray. |
| 2320 PropagateBackLocalClass(node->array(), growable_object_array_class_); | 2317 PropagateBackLocalClass(node->array(), growable_object_array_class_); |
| 2321 } | 2318 } |
| 2322 // Check class of index. | 2319 // Check class of index. |
| 2323 if (!index_is_smi) { | 2320 if (!index_is_smi) { |
| 2324 __ testl(EBX, Immediate(kSmiTagMask)); | 2321 __ testl(EBX, Immediate(kSmiTagMask)); |
| 2325 __ j(NOT_ZERO, deopt_blob->label()); // Index not Smi -> deopt. | 2322 __ j(NOT_ZERO, deopt_blob->label()); // Index not Smi -> deopt. |
| 2326 PropagateBackLocalClass(node->index_expr(), smi_class_); | 2323 PropagateBackLocalClass(node->index_expr(), smi_class_); |
| 2327 } | 2324 } |
| 2328 // Range check: deoptimize if out of bounds. | 2325 // Range check: deoptimize if out of bounds. |
| (...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2636 __ jmp(&done); | 2633 __ jmp(&done); |
| 2637 __ Bind(¬_smi); // Continue with other test below. | 2634 __ Bind(¬_smi); // Continue with other test below. |
| 2638 } else if (NodeMayBeSmi(receiver)) { | 2635 } else if (NodeMayBeSmi(receiver)) { |
| 2639 DeoptimizationBlob* deopt_blob = | 2636 DeoptimizationBlob* deopt_blob = |
| 2640 AddDeoptimizationBlob(node, kDeoptCheckedInstanceCallSmiFail); | 2637 AddDeoptimizationBlob(node, kDeoptCheckedInstanceCallSmiFail); |
| 2641 __ testl(EAX, Immediate(kSmiTagMask)); | 2638 __ testl(EAX, Immediate(kSmiTagMask)); |
| 2642 __ j(ZERO, deopt_blob->label()); | 2639 __ j(ZERO, deopt_blob->label()); |
| 2643 } else { | 2640 } else { |
| 2644 // Receiver cannot be Smi, no need to test it. | 2641 // Receiver cannot be Smi, no need to test it. |
| 2645 } | 2642 } |
| 2646 __ LoadClassIndexOfObject(EAX, EAX); // Receiver's class. | 2643 __ LoadClassId(EAX, EAX); // Receiver's class id. |
| 2647 for (intptr_t i = start_ix; i < classes.length(); i++) { | 2644 for (intptr_t i = start_ix; i < classes.length(); i++) { |
| 2648 const Class& cls = *classes[i]; | 2645 const Class& cls = *classes[i]; |
| 2649 const Function& target = *targets[i]; | 2646 const Function& target = *targets[i]; |
| 2650 __ cmpl(EAX, Immediate(cls.index())); | 2647 __ cmpl(EAX, Immediate(cls.index())); |
| 2651 if (i == (classes.length() - 1)) { | 2648 if (i == (classes.length() - 1)) { |
| 2652 // Last check. | 2649 // Last check. |
| 2653 DeoptimizationBlob* deopt_blob = | 2650 DeoptimizationBlob* deopt_blob = |
| 2654 AddDeoptimizationBlob(node, kDeoptCheckedInstanceCallCheckFail); | 2651 AddDeoptimizationBlob(node, kDeoptCheckedInstanceCallCheckFail); |
| 2655 __ j(NOT_EQUAL, deopt_blob->label()); | 2652 __ j(NOT_EQUAL, deopt_blob->label()); |
| 2656 GenerateDirectCall(node->id(), | 2653 GenerateDirectCall(node->id(), |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2897 } | 2894 } |
| 2898 } | 2895 } |
| 2899 // TODO(srdjan): Implement unary kSUB (negate) Mint. | 2896 // TODO(srdjan): Implement unary kSUB (negate) Mint. |
| 2900 CodeGenerator::VisitUnaryOpNode(node); | 2897 CodeGenerator::VisitUnaryOpNode(node); |
| 2901 } | 2898 } |
| 2902 | 2899 |
| 2903 | 2900 |
| 2904 } // namespace dart | 2901 } // namespace dart |
| 2905 | 2902 |
| 2906 #endif // defined TARGET_ARCH_IA32 | 2903 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |