| 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 12 matching lines...) Expand all Loading... |
| 23 DECLARE_FLAG(bool, enable_type_checks); | 23 DECLARE_FLAG(bool, enable_type_checks); |
| 24 DECLARE_FLAG(bool, intrinsify); | 24 DECLARE_FLAG(bool, intrinsify); |
| 25 DECLARE_FLAG(bool, trace_functions); | 25 DECLARE_FLAG(bool, trace_functions); |
| 26 | 26 |
| 27 | 27 |
| 28 // Property list to be used in CodeGenInfo. Each property has a setter | 28 // Property list to be used in CodeGenInfo. Each property has a setter |
| 29 // and a getter of specified type and name. | 29 // and a getter of specified type and name. |
| 30 // (name, type, default) | 30 // (name, type, default) |
| 31 #define PROPERTY_LIST(V) \ | 31 #define PROPERTY_LIST(V) \ |
| 32 V(is_temp, bool, false) \ | 32 V(is_temp, bool, false) \ |
| 33 V(allow_temp, bool, false) \ |
| 33 V(true_label, Label*, NULL) \ | 34 V(true_label, Label*, NULL) \ |
| 34 V(false_label, Label*, NULL) \ | 35 V(false_label, Label*, NULL) \ |
| 35 V(labels_used, bool, false) \ | 36 V(labels_used, bool, false) \ |
| 36 V(request_result_in_eax, bool, false) \ | 37 V(request_result_in_eax, bool, false) \ |
| 37 V(result_returned_in_eax, bool, false) \ | 38 V(result_returned_in_eax, bool, false) \ |
| 38 V(fallthrough_label, Label*, NULL) \ | 39 V(fallthrough_label, Label*, NULL) \ |
| 39 V(is_class, const Class*, &Class::ZoneHandle()) \ | 40 V(is_class, const Class*, &Class::ZoneHandle()) \ |
| 40 | 41 |
| 41 | 42 |
| 42 // Class holding information being passed from source to destination. | 43 // Class holding information being passed from source to destination. |
| (...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 577 } | 578 } |
| 578 | 579 |
| 579 | 580 |
| 580 void OptimizingCodeGenerator::VisitStoreLocalNode(StoreLocalNode* node) { | 581 void OptimizingCodeGenerator::VisitStoreLocalNode(StoreLocalNode* node) { |
| 581 if (FLAG_enable_type_checks) { | 582 if (FLAG_enable_type_checks) { |
| 582 CodeGenerator::VisitStoreLocalNode(node); | 583 CodeGenerator::VisitStoreLocalNode(node); |
| 583 classes_for_locals_->SetLocalType(node->local(), Class::ZoneHandle()); | 584 classes_for_locals_->SetLocalType(node->local(), Class::ZoneHandle()); |
| 584 return; | 585 return; |
| 585 } | 586 } |
| 586 CodeGenInfo value_info(node->value()); | 587 CodeGenInfo value_info(node->value()); |
| 588 value_info.set_allow_temp(true); |
| 587 value_info.set_request_result_in_eax(true); | 589 value_info.set_request_result_in_eax(true); |
| 588 node->value()->Visit(this); | 590 node->value()->Visit(this); |
| 589 if (value_info.is_temp()) { | 591 if (value_info.is_temp()) { |
| 590 if (value_info.IsClass(double_class_)) { | 592 if (value_info.IsClass(double_class_)) { |
| 591 if (value_info.result_returned_in_eax()) { | 593 if (value_info.result_returned_in_eax()) { |
| 592 __ pushl(EAX); | 594 __ pushl(EAX); |
| 593 } | 595 } |
| 594 const Code& stub = | 596 const Code& stub = |
| 595 Code::Handle(StubCode::GetAllocationStubForClass(double_class_)); | 597 Code::Handle(StubCode::GetAllocationStubForClass(double_class_)); |
| 596 const ExternalLabel label(double_class_.ToCString(), stub.EntryPoint()); | 598 const ExternalLabel label(double_class_.ToCString(), stub.EntryPoint()); |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 873 __ pushl(kOperandRegister); | 875 __ pushl(kOperandRegister); |
| 874 GenerateCall(node->token_index(), &label); | 876 GenerateCall(node->token_index(), &label); |
| 875 ASSERT(kResultRegister == EAX); | 877 ASSERT(kResultRegister == EAX); |
| 876 __ popl(kOperandRegister); | 878 __ popl(kOperandRegister); |
| 877 __ movsd(XMM0, FieldAddress(kOperandRegister, Double::value_offset())); | 879 __ movsd(XMM0, FieldAddress(kOperandRegister, Double::value_offset())); |
| 878 __ xorps(XMM1, XMM1); // 0.0 -> XMM1. | 880 __ xorps(XMM1, XMM1); // 0.0 -> XMM1. |
| 879 __ subsd(XMM1, XMM0); | 881 __ subsd(XMM1, XMM0); |
| 880 __ movsd(FieldAddress(kResultRegister, Double::value_offset()), XMM1); | 882 __ movsd(FieldAddress(kResultRegister, Double::value_offset()), XMM1); |
| 881 if (CodeGenerator::IsResultNeeded(node)) { | 883 if (CodeGenerator::IsResultNeeded(node)) { |
| 882 if (node->info() != NULL) { | 884 if (node->info() != NULL) { |
| 883 node->info()->set_is_temp(true); | 885 // TODO(srdjan): Enable once we use a temporary object. |
| 886 // node->info()->set_is_temp(true); |
| 884 node->info()->set_is_class(&double_class_); | 887 node->info()->set_is_class(&double_class_); |
| 885 } | 888 } |
| 886 HandleResult(node, kResultRegister); | 889 HandleResult(node, kResultRegister); |
| 887 } | 890 } |
| 888 } | 891 } |
| 889 | 892 |
| 890 | 893 |
| 891 // Handles only Smi & Smi. | 894 // Handles only Smi & Smi. |
| 892 // TODO(srdjan): Certain operations always overflow, and thus cause | 895 // TODO(srdjan): Certain operations always overflow, and thus cause |
| 893 // deoptimization. We need to mark those places and handle them. | 896 // deoptimization. We need to mark those places and handle them. |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1130 (kind == Token::kMUL) || | 1133 (kind == Token::kMUL) || |
| 1131 (kind == Token::kDIV)) { | 1134 (kind == Token::kDIV)) { |
| 1132 TraceOpt(node, kOptMessage); | 1135 TraceOpt(node, kOptMessage); |
| 1133 // All four register below must be different. | 1136 // All four register below must be different. |
| 1134 const Register kLeftRegister = EAX; | 1137 const Register kLeftRegister = EAX; |
| 1135 const Register kRightRegister = EDX; | 1138 const Register kRightRegister = EDX; |
| 1136 const Register kAllocatedRegister = ECX; | 1139 const Register kAllocatedRegister = ECX; |
| 1137 const Register kTempRegister = EBX; | 1140 const Register kTempRegister = EBX; |
| 1138 CodeGenInfo left_info(node->left()); // Receiver. | 1141 CodeGenInfo left_info(node->left()); // Receiver. |
| 1139 CodeGenInfo right_info(node->right()); | 1142 CodeGenInfo right_info(node->right()); |
| 1143 left_info.set_allow_temp(true); |
| 1144 right_info.set_allow_temp(true); |
| 1140 VisitLoadTwo(node->left(), node->right(), kLeftRegister, kRightRegister); | 1145 VisitLoadTwo(node->left(), node->right(), kLeftRegister, kRightRegister); |
| 1141 // First allocate result object or specify an existing object as result. | 1146 // First allocate result object or specify an existing object as result. |
| 1142 Register result_register = kNoRegister; | 1147 Register result_register = kNoRegister; |
| 1143 if (node->info() == NULL) { | 1148 const bool using_temp = |
| 1149 (node->info() != NULL) && node->info()->allow_temp(); |
| 1150 if (!using_temp) { |
| 1144 // Parent node cannot handle a temporary double object, allocate one | 1151 // Parent node cannot handle a temporary double object, allocate one |
| 1145 // each time. | 1152 // each time. |
| 1146 result_register = kAllocatedRegister; | 1153 result_register = kAllocatedRegister; |
| 1147 const Code& stub = | 1154 const Code& stub = |
| 1148 Code::Handle(StubCode::GetAllocationStubForClass(double_class_)); | 1155 Code::Handle(StubCode::GetAllocationStubForClass(double_class_)); |
| 1149 const ExternalLabel label(double_class_.ToCString(), stub.EntryPoint()); | 1156 const ExternalLabel label(double_class_.ToCString(), stub.EntryPoint()); |
| 1150 __ pushl(kLeftRegister); | 1157 __ pushl(kLeftRegister); |
| 1151 __ pushl(kRightRegister); | 1158 __ pushl(kRightRegister); |
| 1152 GenerateCall(node->token_index(), &label); | 1159 GenerateCall(node->token_index(), &label); |
| 1153 __ movl(result_register, EAX); | 1160 __ movl(result_register, EAX); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1239 switch (kind) { | 1246 switch (kind) { |
| 1240 case Token::kADD: __ addsd(XMM0, XMM1); break; | 1247 case Token::kADD: __ addsd(XMM0, XMM1); break; |
| 1241 case Token::kSUB: __ subsd(XMM0, XMM1); break; | 1248 case Token::kSUB: __ subsd(XMM0, XMM1); break; |
| 1242 case Token::kMUL: __ mulsd(XMM0, XMM1); break; | 1249 case Token::kMUL: __ mulsd(XMM0, XMM1); break; |
| 1243 case Token::kDIV: __ divsd(XMM0, XMM1); break; | 1250 case Token::kDIV: __ divsd(XMM0, XMM1); break; |
| 1244 default: UNREACHABLE(); | 1251 default: UNREACHABLE(); |
| 1245 } | 1252 } |
| 1246 __ movsd(FieldAddress(result_register, Double::value_offset()), XMM0); | 1253 __ movsd(FieldAddress(result_register, Double::value_offset()), XMM0); |
| 1247 if (CodeGenerator::IsResultNeeded(node)) { | 1254 if (CodeGenerator::IsResultNeeded(node)) { |
| 1248 if (node->info() != NULL) { | 1255 if (node->info() != NULL) { |
| 1249 node->info()->set_is_temp(true); | 1256 node->info()->set_is_temp(using_temp); |
| 1250 node->info()->set_is_class(&double_class_); | 1257 node->info()->set_is_class(&double_class_); |
| 1251 } | 1258 } |
| 1252 HandleResult(node, result_register); | 1259 HandleResult(node, result_register); |
| 1253 } | 1260 } |
| 1254 return; | 1261 return; |
| 1255 } | 1262 } |
| 1256 | 1263 |
| 1257 TraceNotOpt(node, kOptMessage); | 1264 TraceNotOpt(node, kOptMessage); |
| 1258 CodeGenerator::VisitBinaryOpNode(node); | 1265 CodeGenerator::VisitBinaryOpNode(node); |
| 1259 } | 1266 } |
| (...skipping 1861 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3121 } | 3128 } |
| 3122 } | 3129 } |
| 3123 // TODO(srdjan): Implement unary kSUB (negate) Mint. | 3130 // TODO(srdjan): Implement unary kSUB (negate) Mint. |
| 3124 CodeGenerator::VisitUnaryOpNode(node); | 3131 CodeGenerator::VisitUnaryOpNode(node); |
| 3125 } | 3132 } |
| 3126 | 3133 |
| 3127 | 3134 |
| 3128 } // namespace dart | 3135 } // namespace dart |
| 3129 | 3136 |
| 3130 #endif // defined TARGET_ARCH_IA32 | 3137 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |