| 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 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 558 const Class* cls = NULL; | 558 const Class* cls = NULL; |
| 559 classes_for_locals_->GetLocalClass(node->local(), &cls); | 559 classes_for_locals_->GetLocalClass(node->local(), &cls); |
| 560 if (cls != NULL) { | 560 if (cls != NULL) { |
| 561 node->info()->set_is_class(cls); | 561 node->info()->set_is_class(cls); |
| 562 } | 562 } |
| 563 } | 563 } |
| 564 } | 564 } |
| 565 | 565 |
| 566 | 566 |
| 567 void OptimizingCodeGenerator::HandleResult(AstNode* node, Register result_reg) { | 567 void OptimizingCodeGenerator::HandleResult(AstNode* node, Register result_reg) { |
| 568 if (CodeGenerator::IsResultNeeded(node)) { | 568 if (IsResultNeeded(node)) { |
| 569 if (IsResultInEaxRequested(node)) { | 569 if (IsResultInEaxRequested(node)) { |
| 570 if (result_reg != EAX) { | 570 if (result_reg != EAX) { |
| 571 __ movl(EAX, result_reg); | 571 __ movl(EAX, result_reg); |
| 572 } | 572 } |
| 573 node->info()->set_result_returned_in_eax(true); | 573 node->info()->set_result_returned_in_eax(true); |
| 574 } else { | 574 } else { |
| 575 __ pushl(result_reg); | 575 __ pushl(result_reg); |
| 576 } | 576 } |
| 577 } | 577 } |
| 578 } | 578 } |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 866 __ movl(kResultRegister, kOperandRegister); | 866 __ movl(kResultRegister, kOperandRegister); |
| 867 } else { | 867 } else { |
| 868 const Double& double_object = | 868 const Double& double_object = |
| 869 Double::ZoneHandle(Double::New(0.0, Heap::kOld)); | 869 Double::ZoneHandle(Double::New(0.0, Heap::kOld)); |
| 870 __ LoadObject(kResultRegister, double_object); | 870 __ LoadObject(kResultRegister, double_object); |
| 871 } | 871 } |
| 872 __ movsd(XMM0, FieldAddress(kOperandRegister, Double::value_offset())); | 872 __ movsd(XMM0, FieldAddress(kOperandRegister, Double::value_offset())); |
| 873 ASSERT(node->kind() == Token::kSUB); | 873 ASSERT(node->kind() == Token::kSUB); |
| 874 __ DoubleNegate(XMM0); | 874 __ DoubleNegate(XMM0); |
| 875 __ movsd(FieldAddress(kResultRegister, Double::value_offset()), XMM0); | 875 __ movsd(FieldAddress(kResultRegister, Double::value_offset()), XMM0); |
| 876 if (CodeGenerator::IsResultNeeded(node)) { | 876 if (IsResultNeeded(node)) { |
| 877 if (node->info() != NULL) { | 877 if (node->info() != NULL) { |
| 878 node->info()->set_is_temp(using_temp); | 878 node->info()->set_is_temp(using_temp); |
| 879 node->info()->set_is_class(&double_class_); | 879 node->info()->set_is_class(&double_class_); |
| 880 } | 880 } |
| 881 HandleResult(node, kResultRegister); | 881 HandleResult(node, kResultRegister); |
| 882 } | 882 } |
| 883 } | 883 } |
| 884 | 884 |
| 885 | 885 |
| 886 // Handles only Smi & Smi. | 886 // Handles only Smi & Smi. |
| (...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1239 } | 1239 } |
| 1240 | 1240 |
| 1241 switch (kind) { | 1241 switch (kind) { |
| 1242 case Token::kADD: __ addsd(XMM0, XMM1); break; | 1242 case Token::kADD: __ addsd(XMM0, XMM1); break; |
| 1243 case Token::kSUB: __ subsd(XMM0, XMM1); break; | 1243 case Token::kSUB: __ subsd(XMM0, XMM1); break; |
| 1244 case Token::kMUL: __ mulsd(XMM0, XMM1); break; | 1244 case Token::kMUL: __ mulsd(XMM0, XMM1); break; |
| 1245 case Token::kDIV: __ divsd(XMM0, XMM1); break; | 1245 case Token::kDIV: __ divsd(XMM0, XMM1); break; |
| 1246 default: UNREACHABLE(); | 1246 default: UNREACHABLE(); |
| 1247 } | 1247 } |
| 1248 __ movsd(FieldAddress(result_register, Double::value_offset()), XMM0); | 1248 __ movsd(FieldAddress(result_register, Double::value_offset()), XMM0); |
| 1249 if (CodeGenerator::IsResultNeeded(node)) { | 1249 if (IsResultNeeded(node)) { |
| 1250 if (node->info() != NULL) { | 1250 if (node->info() != NULL) { |
| 1251 node->info()->set_is_temp(using_temp); | 1251 node->info()->set_is_temp(using_temp); |
| 1252 node->info()->set_is_class(&double_class_); | 1252 node->info()->set_is_class(&double_class_); |
| 1253 } | 1253 } |
| 1254 HandleResult(node, result_register); | 1254 HandleResult(node, result_register); |
| 1255 } | 1255 } |
| 1256 return; | 1256 return; |
| 1257 } | 1257 } |
| 1258 | 1258 |
| 1259 TraceNotOpt(node, kOptMessage); | 1259 TraceNotOpt(node, kOptMessage); |
| (...skipping 739 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1999 // Right operand can be Smi or null, otherwise call operator on Smi (e.g, | 1999 // Right operand can be Smi or null, otherwise call operator on Smi (e.g, |
| 2000 // when compared with double). | 2000 // when compared with double). |
| 2001 // This code will be more optimized once we collect types for two arguments. | 2001 // This code will be more optimized once we collect types for two arguments. |
| 2002 void OptimizingCodeGenerator::GenerateSmiEquality(ComparisonNode* node) { | 2002 void OptimizingCodeGenerator::GenerateSmiEquality(ComparisonNode* node) { |
| 2003 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 2003 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 2004 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | 2004 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
| 2005 ASSERT((node->kind() == Token::kEQ) || (node->kind() == Token::kNE)); | 2005 ASSERT((node->kind() == Token::kEQ) || (node->kind() == Token::kNE)); |
| 2006 CodeGenInfo left_info(node->left()); | 2006 CodeGenInfo left_info(node->left()); |
| 2007 CodeGenInfo right_info(node->right()); | 2007 CodeGenInfo right_info(node->right()); |
| 2008 VisitLoadTwo(node->left(), node->right(), EAX, EDX); | 2008 VisitLoadTwo(node->left(), node->right(), EAX, EDX); |
| 2009 if (!CodeGenerator::IsResultNeeded(node)) { | 2009 if (!IsResultNeeded(node)) { |
| 2010 return; | 2010 return; |
| 2011 } | 2011 } |
| 2012 const Immediate raw_null = | 2012 const Immediate raw_null = |
| 2013 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 2013 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 2014 Label evaluate_comparison; | 2014 Label evaluate_comparison; |
| 2015 if (!left_info.IsClass(smi_class_)) { | 2015 if (!left_info.IsClass(smi_class_)) { |
| 2016 DeoptimizationBlob* deopt_blob = | 2016 DeoptimizationBlob* deopt_blob = |
| 2017 AddDeoptimizationBlob(node, EAX, EDX, kDeoptSmiEquality); | 2017 AddDeoptimizationBlob(node, EAX, EDX, kDeoptSmiEquality); |
| 2018 Label left_not_null; | 2018 Label left_not_null; |
| 2019 __ cmpl(EAX, raw_null); | 2019 __ cmpl(EAX, raw_null); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2092 } | 2092 } |
| 2093 Condition condition; | 2093 Condition condition; |
| 2094 if (!SupportedTokenKindToSmiCondition(node->kind(), &condition)) { | 2094 if (!SupportedTokenKindToSmiCondition(node->kind(), &condition)) { |
| 2095 return false; | 2095 return false; |
| 2096 } | 2096 } |
| 2097 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 2097 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 2098 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | 2098 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
| 2099 CodeGenInfo left_info(node->left()); | 2099 CodeGenInfo left_info(node->left()); |
| 2100 CodeGenInfo right_info(node->right()); | 2100 CodeGenInfo right_info(node->right()); |
| 2101 VisitLoadTwo(node->left(), node->right(), EAX, EDX); | 2101 VisitLoadTwo(node->left(), node->right(), EAX, EDX); |
| 2102 if (!CodeGenerator::IsResultNeeded(node)) { | 2102 if (!IsResultNeeded(node)) { |
| 2103 return true; | 2103 return true; |
| 2104 } | 2104 } |
| 2105 if (left_info.IsClass(smi_class_) && right_info.IsClass(smi_class_)) { | 2105 if (left_info.IsClass(smi_class_) && right_info.IsClass(smi_class_)) { |
| 2106 __ cmpl(EAX, EDX); | 2106 __ cmpl(EAX, EDX); |
| 2107 } else if (left_info.IsClass(smi_class_) || right_info.IsClass(smi_class_)) { | 2107 } else if (left_info.IsClass(smi_class_) || right_info.IsClass(smi_class_)) { |
| 2108 // One is Smi. | 2108 // One is Smi. |
| 2109 DeoptimizationBlob* deopt_blob = | 2109 DeoptimizationBlob* deopt_blob = |
| 2110 AddDeoptimizationBlob(node, EAX, EDX, kDeoptSmiCompareSmis); | 2110 AddDeoptimizationBlob(node, EAX, EDX, kDeoptSmiCompareSmis); |
| 2111 Register reg_to_test = left_info.IsClass(smi_class_) ? EDX : EAX; | 2111 Register reg_to_test = left_info.IsClass(smi_class_) ? EDX : EAX; |
| 2112 __ testl(reg_to_test, Immediate(kSmiTagMask)); | 2112 __ testl(reg_to_test, Immediate(kSmiTagMask)); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2198 if (cls.raw() == smi_class_.raw()) { | 2198 if (cls.raw() == smi_class_.raw()) { |
| 2199 // TODO(srdjan): implement mixed smi/non-smi comparison, for the moment | 2199 // TODO(srdjan): implement mixed smi/non-smi comparison, for the moment |
| 2200 // bail out. | 2200 // bail out. |
| 2201 TraceNotOpt(node, "Equality comparison, mixed with Smi"); | 2201 TraceNotOpt(node, "Equality comparison, mixed with Smi"); |
| 2202 return false; | 2202 return false; |
| 2203 } | 2203 } |
| 2204 } | 2204 } |
| 2205 | 2205 |
| 2206 // All targets are Object.==, i.e., '==='. Smi is not among the classes. | 2206 // All targets are Object.==, i.e., '==='. Smi is not among the classes. |
| 2207 VisitLoadTwo(node->left(), node->right(), EAX, EDX); | 2207 VisitLoadTwo(node->left(), node->right(), EAX, EDX); |
| 2208 if (!CodeGenerator::IsResultNeeded(node)) { | 2208 if (!IsResultNeeded(node)) { |
| 2209 return true; | 2209 return true; |
| 2210 } | 2210 } |
| 2211 Label compare; | 2211 Label compare; |
| 2212 // Comparison with NULL is "===". | 2212 // Comparison with NULL is "===". |
| 2213 const Immediate raw_null = | 2213 const Immediate raw_null = |
| 2214 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 2214 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 2215 __ cmpl(EAX, raw_null); | 2215 __ cmpl(EAX, raw_null); |
| 2216 if (num_classes == 0) { | 2216 if (num_classes == 0) { |
| 2217 DeoptimizationBlob* deopt_blob = | 2217 DeoptimizationBlob* deopt_blob = |
| 2218 AddDeoptimizationBlob(node, EAX, EDX, kDeoptEqualityNoFeedback); | 2218 AddDeoptimizationBlob(node, EAX, EDX, kDeoptEqualityNoFeedback); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2292 __ comisd(XMM0, XMM1); | 2292 __ comisd(XMM0, XMM1); |
| 2293 if (NodeInfoHasLabels(node)) { | 2293 if (NodeInfoHasLabels(node)) { |
| 2294 __ j(PARITY_EVEN, node->info()->false_label()); // NaN -> false; | 2294 __ j(PARITY_EVEN, node->info()->false_label()); // NaN -> false; |
| 2295 GenerateConditionalJumps(*(node->info()), true_condition); | 2295 GenerateConditionalJumps(*(node->info()), true_condition); |
| 2296 node->info()->set_labels_used(true); | 2296 node->info()->set_labels_used(true); |
| 2297 } else { | 2297 } else { |
| 2298 Label is_false, is_true, done; | 2298 Label is_false, is_true, done; |
| 2299 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false; | 2299 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false; |
| 2300 __ j(true_condition, &is_true, Assembler::kNearJump); | 2300 __ j(true_condition, &is_true, Assembler::kNearJump); |
| 2301 __ Bind(&is_false); | 2301 __ Bind(&is_false); |
| 2302 if (CodeGenerator::IsResultNeeded(node)) { | 2302 if (IsResultNeeded(node)) { |
| 2303 __ PushObject(bool_false); | 2303 __ PushObject(bool_false); |
| 2304 } | 2304 } |
| 2305 __ jmp(&done); | 2305 __ jmp(&done); |
| 2306 __ Bind(&is_true); | 2306 __ Bind(&is_true); |
| 2307 if (CodeGenerator::IsResultNeeded(node)) { | 2307 if (IsResultNeeded(node)) { |
| 2308 __ PushObject(bool_true); | 2308 __ PushObject(bool_true); |
| 2309 } | 2309 } |
| 2310 __ Bind(&done); | 2310 __ Bind(&done); |
| 2311 } | 2311 } |
| 2312 return true; | 2312 return true; |
| 2313 } | 2313 } |
| 2314 | 2314 |
| 2315 | 2315 |
| 2316 // IS, ISNOT are handled in class CodeGenerator. | 2316 // IS, ISNOT are handled in class CodeGenerator. |
| 2317 void OptimizingCodeGenerator::VisitComparisonNode(ComparisonNode* node) { | 2317 void OptimizingCodeGenerator::VisitComparisonNode(ComparisonNode* node) { |
| 2318 if ((node->kind() == Token::kEQ_STRICT) || | 2318 if ((node->kind() == Token::kEQ_STRICT) || |
| 2319 (node->kind() == Token::kNE_STRICT)) { | 2319 (node->kind() == Token::kNE_STRICT)) { |
| 2320 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 2320 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 2321 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | 2321 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
| 2322 // Note that evaluation of right may cause deoptimization, therefore left | 2322 // Note that evaluation of right may cause deoptimization, therefore left |
| 2323 // must be on stack when evaluating right. | 2323 // must be on stack when evaluating right. |
| 2324 if (node->right()->IsLiteralNode()) { | 2324 if (node->right()->IsLiteralNode()) { |
| 2325 VisitLoadOne(node->left(), EAX); | 2325 VisitLoadOne(node->left(), EAX); |
| 2326 __ CompareObject(EAX, node->right()->AsLiteralNode()->literal()); | 2326 __ CompareObject(EAX, node->right()->AsLiteralNode()->literal()); |
| 2327 } else { | 2327 } else { |
| 2328 VisitLoadTwo(node->left(), node->right(), EAX, EDX); | 2328 VisitLoadTwo(node->left(), node->right(), EAX, EDX); |
| 2329 __ cmpl(EAX, EDX); | 2329 __ cmpl(EAX, EDX); |
| 2330 } | 2330 } |
| 2331 if (!CodeGenerator::IsResultNeeded(node)) { | 2331 if (!IsResultNeeded(node)) { |
| 2332 return; | 2332 return; |
| 2333 } | 2333 } |
| 2334 Condition condition = node->kind() == Token::kEQ_STRICT ? EQUAL : NOT_EQUAL; | 2334 Condition condition = node->kind() == Token::kEQ_STRICT ? EQUAL : NOT_EQUAL; |
| 2335 if (NodeInfoHasLabels(node)) { | 2335 if (NodeInfoHasLabels(node)) { |
| 2336 GenerateConditionalJumps(*(node->info()), condition); | 2336 GenerateConditionalJumps(*(node->info()), condition); |
| 2337 node->info()->set_labels_used(true); | 2337 node->info()->set_labels_used(true); |
| 2338 } else { | 2338 } else { |
| 2339 Label done, is_true; | 2339 Label done, is_true; |
| 2340 __ j(condition, &is_true); | 2340 __ j(condition, &is_true); |
| 2341 __ PushObject(bool_false); | 2341 __ PushObject(bool_false); |
| (...skipping 748 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3090 | 3090 |
| 3091 | 3091 |
| 3092 void OptimizingCodeGenerator::VisitStoreInstanceFieldNode( | 3092 void OptimizingCodeGenerator::VisitStoreInstanceFieldNode( |
| 3093 StoreInstanceFieldNode* node) { | 3093 StoreInstanceFieldNode* node) { |
| 3094 if (FLAG_enable_type_checks) { | 3094 if (FLAG_enable_type_checks) { |
| 3095 CodeGenerator::VisitStoreInstanceFieldNode(node); | 3095 CodeGenerator::VisitStoreInstanceFieldNode(node); |
| 3096 return; | 3096 return; |
| 3097 } | 3097 } |
| 3098 VisitLoadTwo(node->instance(), node->value(), EDX, EAX); | 3098 VisitLoadTwo(node->instance(), node->value(), EDX, EAX); |
| 3099 __ StoreIntoObject(EDX, FieldAddress(EDX, node->field().Offset()), EAX); | 3099 __ StoreIntoObject(EDX, FieldAddress(EDX, node->field().Offset()), EAX); |
| 3100 // The result is the input value. | 3100 ASSERT(!IsResultNeeded(node)); |
| 3101 HandleResult(node, EAX); | |
| 3102 } | 3101 } |
| 3103 | 3102 |
| 3104 | 3103 |
| 3105 void OptimizingCodeGenerator::VisitCatchClauseNode(CatchClauseNode* node) { | 3104 void OptimizingCodeGenerator::VisitCatchClauseNode(CatchClauseNode* node) { |
| 3106 // TODO(srdjan): Set classes for locals. | 3105 // TODO(srdjan): Set classes for locals. |
| 3107 classes_for_locals_->Clear(); | 3106 classes_for_locals_->Clear(); |
| 3108 CodeGenerator::VisitCatchClauseNode(node); | 3107 CodeGenerator::VisitCatchClauseNode(node); |
| 3109 } | 3108 } |
| 3110 | 3109 |
| 3111 | 3110 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3153 } | 3152 } |
| 3154 } | 3153 } |
| 3155 // TODO(srdjan): Implement unary kSUB (negate) Mint. | 3154 // TODO(srdjan): Implement unary kSUB (negate) Mint. |
| 3156 CodeGenerator::VisitUnaryOpNode(node); | 3155 CodeGenerator::VisitUnaryOpNode(node); |
| 3157 } | 3156 } |
| 3158 | 3157 |
| 3159 | 3158 |
| 3160 } // namespace dart | 3159 } // namespace dart |
| 3161 | 3160 |
| 3162 #endif // defined TARGET_ARCH_IA32 | 3161 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |