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

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

Issue 10949019: Turn definitions that do not produce results (e.g. Checks) into instructions. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address Florian's comments Created 8 years, 3 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') | no next file » | 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_allocator.h" 9 #include "vm/flow_graph_allocator.h"
10 #include "vm/flow_graph_builder.h" 10 #include "vm/flow_graph_builder.h"
11 #include "vm/flow_graph_compiler.h" 11 #include "vm/flow_graph_compiler.h"
12 #include "vm/locations.h" 12 #include "vm/locations.h"
13 #include "vm/object.h" 13 #include "vm/object.h"
14 #include "vm/object_store.h" 14 #include "vm/object_store.h"
15 #include "vm/os.h" 15 #include "vm/os.h"
16 #include "vm/scopes.h" 16 #include "vm/scopes.h"
17 #include "vm/stub_code.h" 17 #include "vm/stub_code.h"
18 #include "vm/symbols.h" 18 #include "vm/symbols.h"
19 19
20 namespace dart { 20 namespace dart {
21 21
22 DECLARE_FLAG(bool, enable_type_checks); 22 DECLARE_FLAG(bool, enable_type_checks);
23 23
24 24
25 intptr_t Definition::Hashcode() const { 25 intptr_t Instruction::Hashcode() const {
26 intptr_t result = tag(); 26 intptr_t result = tag();
27 for (intptr_t i = 0; i < InputCount(); ++i) { 27 for (intptr_t i = 0; i < InputCount(); ++i) {
28 Value* value = InputAt(i); 28 Value* value = InputAt(i);
29 intptr_t j = value->definition()->ssa_temp_index(); 29 intptr_t j = value->definition()->ssa_temp_index();
30 result = result * 31 + j; 30 result = result * 31 + j;
31 } 31 }
32 return result; 32 return result;
33 } 33 }
34 34
35 35
36 bool Definition::Equals(Definition* other) const { 36 bool Instruction::Equals(Instruction* other) const {
37 if (tag() != other->tag()) return false; 37 if (tag() != other->tag()) return false;
38 for (intptr_t i = 0; i < InputCount(); ++i) { 38 for (intptr_t i = 0; i < InputCount(); ++i) {
39 if (!InputAt(i)->Equals(other->InputAt(i))) return false; 39 if (!InputAt(i)->Equals(other->InputAt(i))) return false;
40 } 40 }
41 return AttributesEqual(other); 41 return AttributesEqual(other);
42 } 42 }
43 43
44 44
45 bool Value::Equals(Value* other) const { 45 bool Value::Equals(Value* other) const {
46 return definition() == other->definition(); 46 return definition() == other->definition();
47 } 47 }
48 48
49 49
50 bool CheckClassInstr::AttributesEqual(Definition* other) const { 50 bool CheckClassInstr::AttributesEqual(Instruction* other) const {
51 CheckClassInstr* other_check = other->AsCheckClass(); 51 CheckClassInstr* other_check = other->AsCheckClass();
52 ASSERT(other_check != NULL); 52 ASSERT(other_check != NULL);
53 if (unary_checks().NumberOfChecks() != 53 if (unary_checks().NumberOfChecks() !=
54 other_check->unary_checks().NumberOfChecks()) { 54 other_check->unary_checks().NumberOfChecks()) {
55 return false; 55 return false;
56 } 56 }
57 for (intptr_t i = 0; i < unary_checks().NumberOfChecks(); ++i) { 57 for (intptr_t i = 0; i < unary_checks().NumberOfChecks(); ++i) {
58 // TODO(fschneider): Make sure ic_data are sorted to hit more cases. 58 // TODO(fschneider): Make sure ic_data are sorted to hit more cases.
59 if (unary_checks().GetReceiverClassIdAt(i) != 59 if (unary_checks().GetReceiverClassIdAt(i) !=
60 other_check->unary_checks().GetReceiverClassIdAt(i)) { 60 other_check->unary_checks().GetReceiverClassIdAt(i)) {
61 return false; 61 return false;
62 } 62 }
63 } 63 }
64 return true; 64 return true;
65 } 65 }
66 66
67 67
68 bool CheckArrayBoundInstr::AttributesEqual(Definition* other) const { 68 bool CheckArrayBoundInstr::AttributesEqual(Instruction* other) const {
69 CheckArrayBoundInstr* other_check = other->AsCheckArrayBound(); 69 CheckArrayBoundInstr* other_check = other->AsCheckArrayBound();
70 ASSERT(other_check != NULL); 70 ASSERT(other_check != NULL);
71 return array_type() == other_check->array_type(); 71 return array_type() == other_check->array_type();
72 } 72 }
73 73
74 74
75 bool StrictCompareInstr::AttributesEqual(Definition* other) const { 75 bool StrictCompareInstr::AttributesEqual(Instruction* other) const {
76 StrictCompareInstr* other_op = other->AsStrictCompare(); 76 StrictCompareInstr* other_op = other->AsStrictCompare();
77 ASSERT(other_op != NULL); 77 ASSERT(other_op != NULL);
78 return kind() == other_op->kind(); 78 return kind() == other_op->kind();
79 } 79 }
80 80
81 81
82 bool BinarySmiOpInstr::AttributesEqual(Definition* other) const { 82 bool BinarySmiOpInstr::AttributesEqual(Instruction* other) const {
83 BinarySmiOpInstr* other_op = other->AsBinarySmiOp(); 83 BinarySmiOpInstr* other_op = other->AsBinarySmiOp();
84 ASSERT(other_op != NULL); 84 ASSERT(other_op != NULL);
85 return op_kind() == other_op->op_kind(); 85 return op_kind() == other_op->op_kind();
86 } 86 }
87 87
88 88
89 bool LoadFieldInstr::AttributesEqual(Definition* other) const { 89 bool LoadFieldInstr::AttributesEqual(Instruction* other) const {
90 LoadFieldInstr* other_load = other->AsLoadField(); 90 LoadFieldInstr* other_load = other->AsLoadField();
91 ASSERT(other_load != NULL); 91 ASSERT(other_load != NULL);
92 ASSERT((offset_in_bytes() != other_load->offset_in_bytes()) || 92 ASSERT((offset_in_bytes() != other_load->offset_in_bytes()) ||
93 ((immutable_ == other_load->immutable_) && 93 ((immutable_ == other_load->immutable_) &&
94 (ResultCid() == other_load->ResultCid()))); 94 (ResultCid() == other_load->ResultCid())));
95 return offset_in_bytes() == other_load->offset_in_bytes(); 95 return offset_in_bytes() == other_load->offset_in_bytes();
96 } 96 }
97 97
98 98
99 bool LoadStaticFieldInstr::AttributesEqual(Definition* other) const { 99 bool LoadStaticFieldInstr::AttributesEqual(Instruction* other) const {
100 LoadStaticFieldInstr* other_load = other->AsLoadStaticField(); 100 LoadStaticFieldInstr* other_load = other->AsLoadStaticField();
101 ASSERT(other_load != NULL); 101 ASSERT(other_load != NULL);
102 // Assert that the field is initialized. 102 // Assert that the field is initialized.
103 ASSERT(field().value() != Object::sentinel()); 103 ASSERT(field().value() != Object::sentinel());
104 ASSERT(field().value() != Object::transition_sentinel()); 104 ASSERT(field().value() != Object::transition_sentinel());
105 return field().raw() == other_load->field().raw(); 105 return field().raw() == other_load->field().raw();
106 } 106 }
107 107
108 108
109 bool ConstantInstr::AttributesEqual(Definition* other) const { 109 bool ConstantInstr::AttributesEqual(Instruction* other) const {
110 ConstantInstr* other_constant = other->AsConstant(); 110 ConstantInstr* other_constant = other->AsConstant();
111 ASSERT(other_constant != NULL); 111 ASSERT(other_constant != NULL);
112 return (value().raw() == other_constant->value().raw()); 112 return (value().raw() == other_constant->value().raw());
113 } 113 }
114 114
115 115
116 // Returns true if the value represents a constant. 116 // Returns true if the value represents a constant.
117 bool Value::BindsToConstant() const { 117 bool Value::BindsToConstant() const {
118 return definition()->IsConstant(); 118 return definition()->IsConstant();
119 } 119 }
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 prev_instr->set_next(next_instr); 218 prev_instr->set_next(next_instr);
219 next_instr->set_previous(prev_instr); 219 next_instr->set_previous(prev_instr);
220 // Reset successor and previous instruction to indicate 220 // Reset successor and previous instruction to indicate
221 // that the instruction is removed from the graph. 221 // that the instruction is removed from the graph.
222 set_previous(NULL); 222 set_previous(NULL);
223 set_next(NULL); 223 set_next(NULL);
224 return return_previous ? prev_instr : next_instr; 224 return return_previous ? prev_instr : next_instr;
225 } 225 }
226 226
227 227
228 void Definition::InsertBefore(Instruction* next) { 228 void Instruction::InsertBefore(Instruction* next) {
229 ASSERT(previous_ == NULL); 229 ASSERT(previous_ == NULL);
230 ASSERT(next_ == NULL); 230 ASSERT(next_ == NULL);
231 next_ = next; 231 next_ = next;
232 previous_ = next->previous_; 232 previous_ = next->previous_;
233 next->previous_ = this; 233 next->previous_ = this;
234 previous_->next_ = this; 234 previous_->next_ = this;
235 } 235 }
236 236
237 237
238 void Definition::InsertAfter(Instruction* prev) { 238 void Instruction::InsertAfter(Instruction* prev) {
239 ASSERT(previous_ == NULL); 239 ASSERT(previous_ == NULL);
240 ASSERT(next_ == NULL); 240 ASSERT(next_ == NULL);
241 previous_ = prev; 241 previous_ = prev;
242 next_ = prev->next_; 242 next_ = prev->next_;
243 next_->previous_ = this; 243 next_->previous_ = this;
244 previous_->next_ = this; 244 previous_->next_ = this;
245 } 245 }
246 246
247 247
248 BlockEntryInstr* Definition::GetBlock() const { 248 BlockEntryInstr* Instruction::GetBlock() const {
249 // TODO(fschneider): Implement a faster way to get the block of an 249 // TODO(fschneider): Implement a faster way to get the block of an
250 // instruction. 250 // instruction.
251 ASSERT(previous() != NULL); 251 ASSERT(previous() != NULL);
252 Instruction* result = previous(); 252 Instruction* result = previous();
253 while (!result->IsBlockEntry()) result = result->previous(); 253 while (!result->IsBlockEntry()) result = result->previous();
254 return result->AsBlockEntry(); 254 return result->AsBlockEntry();
255 } 255 }
256 256
257 257
258 void ForwardInstructionIterator::RemoveCurrentFromGraph() { 258 void ForwardInstructionIterator::RemoveCurrentFromGraph() {
(...skipping 934 matching lines...) Expand 10 before | Expand all | Expand 10 after
1193 RawAbstractType* CheckArrayBoundInstr::CompileType() const { 1193 RawAbstractType* CheckArrayBoundInstr::CompileType() const {
1194 return AbstractType::null(); 1194 return AbstractType::null();
1195 } 1195 }
1196 1196
1197 1197
1198 RawAbstractType* CheckEitherNonSmiInstr::CompileType() const { 1198 RawAbstractType* CheckEitherNonSmiInstr::CompileType() const {
1199 return AbstractType::null(); 1199 return AbstractType::null();
1200 } 1200 }
1201 1201
1202 1202
1203 // Optimizations that eliminate or simplify individual computations. 1203 // Optimizations that eliminate or simplify individual instructions.
1204 Instruction* Instruction::Canonicalize() {
1205 return this;
1206 }
1207
1208
1204 Definition* Definition::Canonicalize() { 1209 Definition* Definition::Canonicalize() {
1205 return this; 1210 return this;
1206 } 1211 }
1207 1212
1208 1213
1209 Definition* StrictCompareInstr::Canonicalize() { 1214 Definition* StrictCompareInstr::Canonicalize() {
1210 if (!right()->BindsToConstant()) return this; 1215 if (!right()->BindsToConstant()) return this;
1211 const Object& right_constant = right()->BoundConstant(); 1216 const Object& right_constant = right()->BoundConstant();
1212 Definition* left_defn = left()->definition(); 1217 Definition* left_defn = left()->definition();
1213 // TODO(fschneider): Handle other cases: e === false and e !== true/false. 1218 // TODO(fschneider): Handle other cases: e === false and e !== true/false.
1214 // Handles e === true. 1219 // Handles e === true.
1215 if ((kind() == Token::kEQ_STRICT) && 1220 if ((kind() == Token::kEQ_STRICT) &&
1216 (right_constant.raw() == Bool::True()) && 1221 (right_constant.raw() == Bool::True()) &&
1217 (left()->ResultCid() == kBoolCid)) { 1222 (left()->ResultCid() == kBoolCid)) {
1218 // Return left subexpression as the replacement for this instruction. 1223 // Return left subexpression as the replacement for this instruction.
1219 return left_defn; 1224 return left_defn;
1220 } 1225 }
1221 return this; 1226 return this;
1222 } 1227 }
1223 1228
1224 1229
1225 Definition* CheckClassInstr::Canonicalize() { 1230 Instruction* CheckClassInstr::Canonicalize() {
1226 const intptr_t v_cid = value()->ResultCid(); 1231 const intptr_t v_cid = value()->ResultCid();
1227 const intptr_t num_checks = unary_checks().NumberOfChecks(); 1232 const intptr_t num_checks = unary_checks().NumberOfChecks();
1228 if ((num_checks == 1) && 1233 if ((num_checks == 1) &&
1229 (v_cid == unary_checks().GetReceiverClassIdAt(0))) { 1234 (v_cid == unary_checks().GetReceiverClassIdAt(0))) {
1230 // No checks needed. 1235 // No checks needed.
1231 return NULL; 1236 return NULL;
1232 } 1237 }
1233 return this; 1238 return this;
1234 } 1239 }
1235 1240
1236 1241
1237 Definition* CheckSmiInstr::Canonicalize() { 1242 Instruction* CheckSmiInstr::Canonicalize() {
1238 return (value()->ResultCid() == kSmiCid) ? NULL : this; 1243 return (value()->ResultCid() == kSmiCid) ? NULL : this;
1239 } 1244 }
1240 1245
1241 1246
1242 Definition* CheckEitherNonSmiInstr::Canonicalize() { 1247 Instruction* CheckEitherNonSmiInstr::Canonicalize() {
1243 if ((left()->ResultCid() == kDoubleCid) || 1248 if ((left()->ResultCid() == kDoubleCid) ||
1244 (right()->ResultCid() == kDoubleCid)) { 1249 (right()->ResultCid() == kDoubleCid)) {
1245 return NULL; // Remove from the graph. 1250 return NULL; // Remove from the graph.
1246 } 1251 }
1247 return this; 1252 return this;
1248 } 1253 }
1249 1254
1250 1255
1251 // Shared code generation methods (EmitNativeCode, MakeLocationSummary, and 1256 // Shared code generation methods (EmitNativeCode, MakeLocationSummary, and
1252 // PrepareEntry). Only assembly code that can be shared across all architectures 1257 // PrepareEntry). Only assembly code that can be shared across all architectures
(...skipping 495 matching lines...) Expand 10 before | Expand all | Expand 10 after
1748 value->set_use_index(use_index++); 1753 value->set_use_index(use_index++);
1749 value->AddToEnvUseList(); 1754 value->AddToEnvUseList();
1750 } 1755 }
1751 instr->env()->outer_ = copy; 1756 instr->env()->outer_ = copy;
1752 } 1757 }
1753 1758
1754 1759
1755 #undef __ 1760 #undef __
1756 1761
1757 } // namespace dart 1762 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698