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

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

Issue 10830109: Add type propagation phase in optimizing compiler (work in progress). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 4 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/intermediate_language.h ('k') | runtime/vm/isolate.h » ('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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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/intermediate_language.h" 5 #include "vm/intermediate_language.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/dart_entry.h" 8 #include "vm/dart_entry.h"
9 #include "vm/flow_graph_builder.h" 9 #include "vm/flow_graph_builder.h"
10 #include "vm/flow_graph_compiler.h" 10 #include "vm/flow_graph_compiler.h"
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 for (intptr_t i = 0; i < block_order_.length(); ++i) { 109 for (intptr_t i = 0; i < block_order_.length(); ++i) {
110 BlockEntryInstr* entry = block_order_[i]; 110 BlockEntryInstr* entry = block_order_[i];
111 entry->Accept(this); 111 entry->Accept(this);
112 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { 112 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
113 it.Current()->Accept(this); 113 it.Current()->Accept(this);
114 } 114 }
115 } 115 }
116 } 116 }
117 117
118 118
119 // Returns true if the static type of this value is more specific than the
120 // given dst_type.
121 // TODO(regis): Should we support a set of static types?
122 bool Value::StaticTypeIsMoreSpecificThan(const AbstractType& dst_type) const {
123 ASSERT(!dst_type.IsMalformed()); // Should be tested by caller.
124 ASSERT(!dst_type.IsDynamicType()); // Should be tested by caller.
125 ASSERT(!dst_type.IsObjectType()); // Should be tested by caller.
126
127 // If the value is the null constant, its type (NullType) is more specific
128 // than the destination type, even if the destination type is the void type,
129 // since a void function is allowed to return null.
130 if (IsConstant() && AsConstant()->value().IsNull()) {
131 return true;
132 }
133
134 // Functions that do not explicitly return a value, implicitly return null,
135 // except generative constructors, which return the object being constructed.
136 // It is therefore acceptable for void functions to return null.
137 // In case of a null constant, we have already returned true above, else we
138 // return false here.
139 if (dst_type.IsVoidType()) {
140 return false;
141 }
142
143 // Consider the static type of the value.
144 const AbstractType& static_type = AbstractType::Handle(StaticType());
145 ASSERT(!static_type.IsMalformed());
146
147 // If the static type of the value is void, we are type checking the result of
148 // a void function, which was checked to be null at the return statement
149 // inside the function.
150 if (static_type.IsVoidType()) {
151 return true;
152 }
153
154 // If the static type of the value is NullType, the type test is eliminated.
155 // There are only three instances that can be of Class Null:
156 // Object::null(), Object::sentinel(), and Object::transition_sentinel().
157 // The inline code and run time code performing the type check will never
158 // encounter the 2 sentinel values. The type check of a sentinel value
159 // will always be eliminated here, because these sentinel values can only
160 // be encountered as constants, never as actual value of a heap object
161 // being type checked.
162 if (static_type.IsNullType()) {
163 return true;
164 }
165
166 // The run time type of the value is guaranteed to be a subtype of the
167 // compile time static type of the value. However, establishing here that
168 // the static type is a subtype of the destination type does not guarantee
169 // that the run time type will also be a subtype of the destination type,
170 // because the subtype relation is not transitive.
171 // However, the 'more specific than' relation is transitive and is used
172 // here. In other words, if the static type of the value is more specific
173 // than the destination type, the run time type of the value, which is
174 // guaranteed to be a subtype of the static type, is also guaranteed to be
175 // a subtype of the destination type and the type check can therefore be
176 // eliminated.
177 return static_type.IsMoreSpecificThan(dst_type, NULL);
178 }
179
180
119 intptr_t AllocateObjectComp::InputCount() const { 181 intptr_t AllocateObjectComp::InputCount() const {
120 return arguments().length(); 182 return arguments().length();
121 } 183 }
122 184
123 185
124 intptr_t AllocateObjectWithBoundsCheckComp::InputCount() const { 186 intptr_t AllocateObjectWithBoundsCheckComp::InputCount() const {
125 return arguments().length(); 187 return arguments().length();
126 } 188 }
127 189
128 190
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 } 382 }
321 383
322 384
323 void PhiInstr::SetInputAt(intptr_t i, Value* value) { 385 void PhiInstr::SetInputAt(intptr_t i, Value* value) {
324 inputs_[i] = value; 386 inputs_[i] = value;
325 } 387 }
326 388
327 389
328 RawAbstractType* PhiInstr::StaticType() const { 390 RawAbstractType* PhiInstr::StaticType() const {
329 // TODO(regis): Return the least upper bound of the input static types. 391 // TODO(regis): Return the least upper bound of the input static types.
330 return Type::DynamicType(); 392 // It is much simpler to compute the least specific of the input static types,
393 // and it may be good enough in practice.
394 // Even better: we could keep the set of the input static types intact.
395 AbstractType& least_specific_type =
396 AbstractType::Handle(InputAt(0)->StaticType());
397 AbstractType& input_type = AbstractType::Handle();
398 for (intptr_t i = 1; i < InputCount(); i++) {
399 input_type = InputAt(i)->StaticType();
400 if (input_type.IsMoreSpecificThan(least_specific_type, NULL)) {
401 // Type least_specific_type is less specific than input_type. No change.
402 } else if (least_specific_type.IsMoreSpecificThan(input_type, NULL)) {
403 // Type input_type is less specific than the current least_specific_type.
404 least_specific_type = input_type.raw();
405 } else {
406 // The types are unrelated. No need to continue.
407 least_specific_type = Type::ObjectType();
408 break;
409 }
410 }
411 return least_specific_type.raw();
331 } 412 }
332 413
333 414
334 intptr_t ParameterInstr::InputCount() const { 415 intptr_t ParameterInstr::InputCount() const {
335 return 0; 416 return 0;
336 } 417 }
337 418
338 419
339 Value* ParameterInstr::InputAt(intptr_t i) const { 420 Value* ParameterInstr::InputAt(intptr_t i) const {
340 UNREACHABLE(); 421 UNREACHABLE();
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after
818 899
819 900
820 RawAbstractType* CreateClosureComp::StaticType() const { 901 RawAbstractType* CreateClosureComp::StaticType() const {
821 const Function& fun = function(); 902 const Function& fun = function();
822 const Class& signature_class = Class::Handle(fun.signature_class()); 903 const Class& signature_class = Class::Handle(fun.signature_class());
823 return signature_class.SignatureType(); 904 return signature_class.SignatureType();
824 } 905 }
825 906
826 907
827 RawAbstractType* AllocateObjectComp::StaticType() const { 908 RawAbstractType* AllocateObjectComp::StaticType() const {
828 UNREACHABLE(); 909 // TODO(regis): Be more specific.
829 return AbstractType::null(); 910 return Type::DynamicType();
830 } 911 }
831 912
832 913
833 RawAbstractType* AllocateObjectWithBoundsCheckComp::StaticType() const { 914 RawAbstractType* AllocateObjectWithBoundsCheckComp::StaticType() const {
834 UNREACHABLE(); 915 UNREACHABLE();
835 return AbstractType::null(); 916 return AbstractType::null();
836 } 917 }
837 918
838 919
839 RawAbstractType* LoadVMFieldComp::StaticType() const { 920 RawAbstractType* LoadVMFieldComp::StaticType() const {
(...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after
1359 if (compiler->is_ssa()) { 1440 if (compiler->is_ssa()) {
1360 ASSERT(locs()->in(0).IsRegister()); 1441 ASSERT(locs()->in(0).IsRegister());
1361 __ PushRegister(locs()->in(0).reg()); 1442 __ PushRegister(locs()->in(0).reg());
1362 } 1443 }
1363 } 1444 }
1364 1445
1365 1446
1366 #undef __ 1447 #undef __
1367 1448
1368 } // namespace dart 1449 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language.h ('k') | runtime/vm/isolate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698