Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(851)

Side by Side Diff: runtime/vm/opt_code_generator_ia32.cc

Issue 9297026: Use inlined double temporary object for unary operation, add tests. Fix disassembler crash. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 8 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/compiler.cc ('k') | tests/standalone/src/DeoptimizationTest.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 567 matching lines...) Expand 10 before | Expand all | Expand 10 after
578 } 578 }
579 579
580 580
581 void OptimizingCodeGenerator::VisitStoreLocalNode(StoreLocalNode* node) { 581 void OptimizingCodeGenerator::VisitStoreLocalNode(StoreLocalNode* node) {
582 if (FLAG_enable_type_checks) { 582 if (FLAG_enable_type_checks) {
583 CodeGenerator::VisitStoreLocalNode(node); 583 CodeGenerator::VisitStoreLocalNode(node);
584 classes_for_locals_->SetLocalType(node->local(), Class::ZoneHandle()); 584 classes_for_locals_->SetLocalType(node->local(), Class::ZoneHandle());
585 return; 585 return;
586 } 586 }
587 CodeGenInfo value_info(node->value()); 587 CodeGenInfo value_info(node->value());
588 value_info.set_allow_temp(true); 588 value_info.set_allow_temp(false);
589 value_info.set_request_result_in_eax(true); 589 value_info.set_request_result_in_eax(true);
590 node->value()->Visit(this); 590 node->value()->Visit(this);
591 if (value_info.is_temp()) { 591 if (!value_info.result_returned_in_eax()) {
592 if (value_info.IsClass(double_class_)) { 592 __ popl(EAX);
593 if (value_info.result_returned_in_eax()) {
594 __ pushl(EAX);
595 }
596 const Code& stub =
597 Code::Handle(StubCode::GetAllocationStubForClass(double_class_));
598 const ExternalLabel label(double_class_.ToCString(), stub.EntryPoint());
599 GenerateCall(node->token_index(), &label);
600 // New allocated object is in EAX; copy value from temporary object.
601 __ popl(EDX); // temporary object from value.
602 __ movsd(XMM0, FieldAddress(EDX, Double::value_offset()));
603 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0);
604 CodeGenerator::GenerateStoreVariable(node->local(), EAX, EDX);
605 } else {
606 UNIMPLEMENTED(); // Cannot handle other temporary types yet.
607 }
608 } else {
609 if (!value_info.result_returned_in_eax()) {
610 __ popl(EAX);
611 }
612 CodeGenerator::GenerateStoreVariable(node->local(), EAX, EDX);
613 } 593 }
594 CodeGenerator::GenerateStoreVariable(node->local(), EAX, EDX);
614 HandleResult(node, EAX); 595 HandleResult(node, EAX);
615 classes_for_locals_->SetLocalType(node->local(), *value_info.is_class()); 596 classes_for_locals_->SetLocalType(node->local(), *value_info.is_class());
616 } 597 }
617 598
618 599
619 static bool NodeHasBothReceiverClasses(AstNode* node, 600 static bool NodeHasBothReceiverClasses(AstNode* node,
620 const Class& cls1, 601 const Class& cls1,
621 const Class& cls2) { 602 const Class& cls2) {
622 ASSERT(node != NULL); 603 ASSERT(node != NULL);
623 ASSERT(!cls1.IsNull() && !cls2.IsNull()); 604 ASSERT(!cls1.IsNull() && !cls2.IsNull());
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
848 void OptimizingCodeGenerator::GenerateDoubleUnaryOp(UnaryOpNode* node) { 829 void OptimizingCodeGenerator::GenerateDoubleUnaryOp(UnaryOpNode* node) {
849 const Register kOperandRegister = ECX; 830 const Register kOperandRegister = ECX;
850 const Register kTempRegister = EBX; 831 const Register kTempRegister = EBX;
851 const Register kResultRegister = EAX; 832 const Register kResultRegister = EAX;
852 const ICData& ic_data = node->ICDataAtId(node->id()); 833 const ICData& ic_data = node->ICDataAtId(node->id());
853 DeoptReasonId deopt_reason_id = ic_data.NumberOfChecks() == 0 ? 834 DeoptReasonId deopt_reason_id = ic_data.NumberOfChecks() == 0 ?
854 kDeoptNoTypeFeedback : kDeoptUnaryOp; 835 kDeoptNoTypeFeedback : kDeoptUnaryOp;
855 DeoptimizationBlob* deopt_blob = 836 DeoptimizationBlob* deopt_blob =
856 AddDeoptimizationBlob(node, kOperandRegister, deopt_reason_id); 837 AddDeoptimizationBlob(node, kOperandRegister, deopt_reason_id);
857 CodeGenInfo info(node->operand()); 838 CodeGenInfo info(node->operand());
839 info.set_allow_temp(true);
858 VisitLoadOne(node->operand(), kOperandRegister); 840 VisitLoadOne(node->operand(), kOperandRegister);
859 if (ic_data.NumberOfChecks() == 0) { 841 if (ic_data.NumberOfChecks() == 0) {
860 // No type feedback. 842 // No type feedback.
861 __ jmp(deopt_blob->label()); 843 __ jmp(deopt_blob->label());
862 return; 844 return;
863 } 845 }
864 ASSERT(ic_data.NumberOfChecks() == 1); 846 ASSERT(ic_data.NumberOfChecks() == 1);
865 CheckIfDoubleOrSmi(kOperandRegister, 847 if (!info.IsClass(double_class_)) {
866 kTempRegister, 848 // Deoptimize if not double.
867 deopt_blob->label(), 849 CheckIfDoubleOrSmi(kOperandRegister,
868 deopt_blob->label()); 850 kTempRegister,
869 PropagateBackLocalClass(node->operand(), double_class_); 851 deopt_blob->label(),
870 // TODO(srdjan): check if we could reuse a temporary object instead of 852 deopt_blob->label());
871 // allocating a new one. 853 PropagateBackLocalClass(node->operand(), double_class_);
872 const Code& stub = 854 }
873 Code::Handle(StubCode::GetAllocationStubForClass(double_class_)); 855 const bool using_temp =
874 const ExternalLabel label(double_class_.ToCString(), stub.EntryPoint()); 856 (node->info() != NULL) && node->info()->allow_temp();
875 __ pushl(kOperandRegister); 857 if (!using_temp) {
876 GenerateCall(node->token_index(), &label); 858 const Code& stub =
877 ASSERT(kResultRegister == EAX); 859 Code::Handle(StubCode::GetAllocationStubForClass(double_class_));
878 __ popl(kOperandRegister); 860 const ExternalLabel label(double_class_.ToCString(), stub.EntryPoint());
861 __ pushl(kOperandRegister);
862 GenerateCall(node->token_index(), &label);
863 ASSERT(kResultRegister == EAX);
864 __ popl(kOperandRegister);
865 } else if (info.is_temp()) {
866 __ movl(kResultRegister, kOperandRegister);
867 } else {
868 const Double& double_object =
869 Double::ZoneHandle(Double::New(0.0, Heap::kOld));
870 __ LoadObject(kResultRegister, double_object);
871 }
879 __ movsd(XMM0, FieldAddress(kOperandRegister, Double::value_offset())); 872 __ movsd(XMM0, FieldAddress(kOperandRegister, Double::value_offset()));
880 __ xorps(XMM1, XMM1); // 0.0 -> XMM1. 873 __ xorps(XMM1, XMM1); // 0.0 -> XMM1.
874 ASSERT(node->kind() == Token::kSUB);
881 __ subsd(XMM1, XMM0); 875 __ subsd(XMM1, XMM0);
882 __ movsd(FieldAddress(kResultRegister, Double::value_offset()), XMM1); 876 __ movsd(FieldAddress(kResultRegister, Double::value_offset()), XMM1);
883 if (CodeGenerator::IsResultNeeded(node)) { 877 if (CodeGenerator::IsResultNeeded(node)) {
884 if (node->info() != NULL) { 878 if (node->info() != NULL) {
885 // TODO(srdjan): Enable once we use a temporary object. 879 node->info()->set_is_temp(using_temp);
886 // node->info()->set_is_temp(true);
887 node->info()->set_is_class(&double_class_); 880 node->info()->set_is_class(&double_class_);
888 } 881 }
889 HandleResult(node, kResultRegister); 882 HandleResult(node, kResultRegister);
890 } 883 }
891 } 884 }
892 885
893 886
894 // Handles only Smi & Smi. 887 // Handles only Smi & Smi.
895 // TODO(srdjan): Certain operations always overflow, and thus cause 888 // TODO(srdjan): Certain operations always overflow, and thus cause
896 // deoptimization. We need to mark those places and handle them. 889 // deoptimization. We need to mark those places and handle them.
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
1084 // - true if both nodes are LoadLocalNodes with the same index. 1077 // - true if both nodes are LoadLocalNodes with the same index.
1085 static bool AreNodesOfSameType(AstNode* a, AstNode* b) { 1078 static bool AreNodesOfSameType(AstNode* a, AstNode* b) {
1086 ASSERT((a != NULL) && (b != NULL)); 1079 ASSERT((a != NULL) && (b != NULL));
1087 if (a->IsLoadLocalNode() && b->IsLoadLocalNode()) { 1080 if (a->IsLoadLocalNode() && b->IsLoadLocalNode()) {
1088 return a->AsLoadLocalNode()->local().Equals(b->AsLoadLocalNode()->local()); 1081 return a->AsLoadLocalNode()->local().Equals(b->AsLoadLocalNode()->local());
1089 } 1082 }
1090 return false; 1083 return false;
1091 } 1084 }
1092 1085
1093 1086
1094 // If possible propagate node type back to the local. 1087 // If possible propagate node type back to the local, therefore next load
1088 // of local can use that class and eliminate type checks.
1095 void OptimizingCodeGenerator::PropagateBackLocalClass(AstNode* node, 1089 void OptimizingCodeGenerator::PropagateBackLocalClass(AstNode* node,
1096 const Class& cls) { 1090 const Class& cls) {
1097 if (node->IsLoadLocalNode()) { 1091 if (node->IsLoadLocalNode()) {
1098 LoadLocalNode* local_node = node->AsLoadLocalNode(); 1092 LoadLocalNode* local_node = node->AsLoadLocalNode();
1099 classes_for_locals_->SetLocalType(local_node->local(), cls); 1093 classes_for_locals_->SetLocalType(local_node->local(), cls);
1100 } 1094 }
1101 } 1095 }
1102 1096
1103 1097
1104 // 'reg' is not modified, 'temp' is trashed. 1098 // 'reg' is not modified, 'temp' is trashed.
(...skipping 2025 matching lines...) Expand 10 before | Expand all | Expand 10 after
3130 } 3124 }
3131 } 3125 }
3132 // TODO(srdjan): Implement unary kSUB (negate) Mint. 3126 // TODO(srdjan): Implement unary kSUB (negate) Mint.
3133 CodeGenerator::VisitUnaryOpNode(node); 3127 CodeGenerator::VisitUnaryOpNode(node);
3134 } 3128 }
3135 3129
3136 3130
3137 } // namespace dart 3131 } // namespace dart
3138 3132
3139 #endif // defined TARGET_ARCH_IA32 3133 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/compiler.cc ('k') | tests/standalone/src/DeoptimizationTest.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698