OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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/flow_graph_type_propagator.h" | 5 #include "vm/flow_graph_type_propagator.h" |
6 | 6 |
| 7 #include "vm/bit_vector.h" |
7 #include "vm/cha.h" | 8 #include "vm/cha.h" |
8 #include "vm/bit_vector.h" | |
9 #include "vm/il_printer.h" | 9 #include "vm/il_printer.h" |
10 #include "vm/object_store.h" | 10 #include "vm/object_store.h" |
11 #include "vm/regexp_assembler.h" | 11 #include "vm/regexp_assembler.h" |
12 #include "vm/resolver.h" | 12 #include "vm/resolver.h" |
13 #include "vm/timeline.h" | 13 #include "vm/timeline.h" |
14 | 14 |
15 namespace dart { | 15 namespace dart { |
16 | 16 |
17 DEFINE_FLAG(bool, | 17 DEFINE_FLAG(bool, |
18 trace_type_propagation, | 18 trace_type_propagation, |
19 false, | 19 false, |
20 "Trace flow graph type propagation"); | 20 "Trace flow graph type propagation"); |
21 | 21 |
22 DECLARE_FLAG(bool, propagate_types); | 22 DECLARE_FLAG(bool, propagate_types); |
23 | 23 |
24 | |
25 void FlowGraphTypePropagator::Propagate(FlowGraph* flow_graph) { | 24 void FlowGraphTypePropagator::Propagate(FlowGraph* flow_graph) { |
26 #ifndef PRODUCT | 25 #ifndef PRODUCT |
27 Thread* thread = flow_graph->thread(); | 26 Thread* thread = flow_graph->thread(); |
28 TimelineStream* compiler_timeline = Timeline::GetCompilerStream(); | 27 TimelineStream* compiler_timeline = Timeline::GetCompilerStream(); |
29 TimelineDurationScope tds2(thread, compiler_timeline, | 28 TimelineDurationScope tds2(thread, compiler_timeline, |
30 "FlowGraphTypePropagator"); | 29 "FlowGraphTypePropagator"); |
31 #endif // !PRODUCT | 30 #endif // !PRODUCT |
32 FlowGraphTypePropagator propagator(flow_graph); | 31 FlowGraphTypePropagator propagator(flow_graph); |
33 propagator.Propagate(); | 32 propagator.Propagate(); |
34 } | 33 } |
35 | 34 |
36 | |
37 FlowGraphTypePropagator::FlowGraphTypePropagator(FlowGraph* flow_graph) | 35 FlowGraphTypePropagator::FlowGraphTypePropagator(FlowGraph* flow_graph) |
38 : FlowGraphVisitor(flow_graph->reverse_postorder()), | 36 : FlowGraphVisitor(flow_graph->reverse_postorder()), |
39 flow_graph_(flow_graph), | 37 flow_graph_(flow_graph), |
40 visited_blocks_(new (flow_graph->zone()) | 38 visited_blocks_(new (flow_graph->zone()) |
41 BitVector(flow_graph->zone(), | 39 BitVector(flow_graph->zone(), |
42 flow_graph->reverse_postorder().length())), | 40 flow_graph->reverse_postorder().length())), |
43 types_(flow_graph->current_ssa_temp_index()), | 41 types_(flow_graph->current_ssa_temp_index()), |
44 in_worklist_(NULL), | 42 in_worklist_(NULL), |
45 asserts_(NULL), | 43 asserts_(NULL), |
46 collected_asserts_(NULL) { | 44 collected_asserts_(NULL) { |
47 for (intptr_t i = 0; i < flow_graph->current_ssa_temp_index(); i++) { | 45 for (intptr_t i = 0; i < flow_graph->current_ssa_temp_index(); i++) { |
48 types_.Add(NULL); | 46 types_.Add(NULL); |
49 } | 47 } |
50 | 48 |
51 if (Isolate::Current()->type_checks()) { | 49 if (Isolate::Current()->type_checks()) { |
52 asserts_ = new ZoneGrowableArray<AssertAssignableInstr*>( | 50 asserts_ = new ZoneGrowableArray<AssertAssignableInstr*>( |
53 flow_graph->current_ssa_temp_index()); | 51 flow_graph->current_ssa_temp_index()); |
54 for (intptr_t i = 0; i < flow_graph->current_ssa_temp_index(); i++) { | 52 for (intptr_t i = 0; i < flow_graph->current_ssa_temp_index(); i++) { |
55 asserts_->Add(NULL); | 53 asserts_->Add(NULL); |
56 } | 54 } |
57 | 55 |
58 collected_asserts_ = new ZoneGrowableArray<intptr_t>(10); | 56 collected_asserts_ = new ZoneGrowableArray<intptr_t>(10); |
59 } | 57 } |
60 } | 58 } |
61 | 59 |
62 | |
63 void FlowGraphTypePropagator::Propagate() { | 60 void FlowGraphTypePropagator::Propagate() { |
64 if (FLAG_support_il_printer && FLAG_trace_type_propagation && | 61 if (FLAG_support_il_printer && FLAG_trace_type_propagation && |
65 FlowGraphPrinter::ShouldPrint(flow_graph_->function())) { | 62 FlowGraphPrinter::ShouldPrint(flow_graph_->function())) { |
66 FlowGraphPrinter::PrintGraph("Before type propagation", flow_graph_); | 63 FlowGraphPrinter::PrintGraph("Before type propagation", flow_graph_); |
67 } | 64 } |
68 | 65 |
69 // Walk the dominator tree and propagate reaching types to all Values. | 66 // Walk the dominator tree and propagate reaching types to all Values. |
70 // Collect all phis for a fixed point iteration. | 67 // Collect all phis for a fixed point iteration. |
71 PropagateRecursive(flow_graph_->graph_entry()); | 68 PropagateRecursive(flow_graph_->graph_entry()); |
72 | 69 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 } | 103 } |
107 } | 104 } |
108 } | 105 } |
109 | 106 |
110 if (FLAG_support_il_printer && FLAG_trace_type_propagation && | 107 if (FLAG_support_il_printer && FLAG_trace_type_propagation && |
111 FlowGraphPrinter::ShouldPrint(flow_graph_->function())) { | 108 FlowGraphPrinter::ShouldPrint(flow_graph_->function())) { |
112 FlowGraphPrinter::PrintGraph("After type propagation", flow_graph_); | 109 FlowGraphPrinter::PrintGraph("After type propagation", flow_graph_); |
113 } | 110 } |
114 } | 111 } |
115 | 112 |
116 | |
117 void FlowGraphTypePropagator::PropagateRecursive(BlockEntryInstr* block) { | 113 void FlowGraphTypePropagator::PropagateRecursive(BlockEntryInstr* block) { |
118 if (visited_blocks_->Contains(block->postorder_number())) { | 114 if (visited_blocks_->Contains(block->postorder_number())) { |
119 return; | 115 return; |
120 } | 116 } |
121 visited_blocks_->Add(block->postorder_number()); | 117 visited_blocks_->Add(block->postorder_number()); |
122 | 118 |
123 const intptr_t rollback_point = rollback_.length(); | 119 const intptr_t rollback_point = rollback_.length(); |
124 | 120 |
125 if (Isolate::Current()->type_checks()) { | 121 if (Isolate::Current()->type_checks()) { |
126 StrengthenAsserts(block); | 122 StrengthenAsserts(block); |
(...skipping 23 matching lines...) Expand all Loading... |
150 } | 146 } |
151 } | 147 } |
152 | 148 |
153 for (intptr_t i = 0; i < block->dominated_blocks().length(); ++i) { | 149 for (intptr_t i = 0; i < block->dominated_blocks().length(); ++i) { |
154 PropagateRecursive(block->dominated_blocks()[i]); | 150 PropagateRecursive(block->dominated_blocks()[i]); |
155 } | 151 } |
156 | 152 |
157 RollbackTo(rollback_point); | 153 RollbackTo(rollback_point); |
158 } | 154 } |
159 | 155 |
160 | |
161 void FlowGraphTypePropagator::RollbackTo(intptr_t rollback_point) { | 156 void FlowGraphTypePropagator::RollbackTo(intptr_t rollback_point) { |
162 for (intptr_t i = rollback_.length() - 1; i >= rollback_point; i--) { | 157 for (intptr_t i = rollback_.length() - 1; i >= rollback_point; i--) { |
163 types_[rollback_[i].index()] = rollback_[i].type(); | 158 types_[rollback_[i].index()] = rollback_[i].type(); |
164 } | 159 } |
165 rollback_.TruncateTo(rollback_point); | 160 rollback_.TruncateTo(rollback_point); |
166 } | 161 } |
167 | 162 |
168 | |
169 CompileType* FlowGraphTypePropagator::TypeOf(Definition* def) { | 163 CompileType* FlowGraphTypePropagator::TypeOf(Definition* def) { |
170 const intptr_t index = def->ssa_temp_index(); | 164 const intptr_t index = def->ssa_temp_index(); |
171 | 165 |
172 CompileType* type = types_[index]; | 166 CompileType* type = types_[index]; |
173 if (type == NULL) { | 167 if (type == NULL) { |
174 type = types_[index] = def->Type(); | 168 type = types_[index] = def->Type(); |
175 ASSERT(type != NULL); | 169 ASSERT(type != NULL); |
176 } | 170 } |
177 return type; | 171 return type; |
178 } | 172 } |
179 | 173 |
180 | |
181 void FlowGraphTypePropagator::SetTypeOf(Definition* def, CompileType* type) { | 174 void FlowGraphTypePropagator::SetTypeOf(Definition* def, CompileType* type) { |
182 const intptr_t index = def->ssa_temp_index(); | 175 const intptr_t index = def->ssa_temp_index(); |
183 rollback_.Add(RollbackEntry(index, types_[index])); | 176 rollback_.Add(RollbackEntry(index, types_[index])); |
184 types_[index] = type; | 177 types_[index] = type; |
185 } | 178 } |
186 | 179 |
187 | |
188 void FlowGraphTypePropagator::SetCid(Definition* def, intptr_t cid) { | 180 void FlowGraphTypePropagator::SetCid(Definition* def, intptr_t cid) { |
189 CompileType* current = TypeOf(def); | 181 CompileType* current = TypeOf(def); |
190 if (current->IsNone() || (current->ToCid() != cid)) { | 182 if (current->IsNone() || (current->ToCid() != cid)) { |
191 SetTypeOf(def, new CompileType(CompileType::FromCid(cid))); | 183 SetTypeOf(def, new CompileType(CompileType::FromCid(cid))); |
192 } | 184 } |
193 } | 185 } |
194 | 186 |
195 | |
196 void FlowGraphTypePropagator::VisitValue(Value* value) { | 187 void FlowGraphTypePropagator::VisitValue(Value* value) { |
197 CompileType* type = TypeOf(value->definition()); | 188 CompileType* type = TypeOf(value->definition()); |
198 value->SetReachingType(type); | 189 value->SetReachingType(type); |
199 | 190 |
200 if (FLAG_support_il_printer && FLAG_trace_type_propagation && | 191 if (FLAG_support_il_printer && FLAG_trace_type_propagation && |
201 FlowGraphPrinter::ShouldPrint(flow_graph_->function())) { | 192 FlowGraphPrinter::ShouldPrint(flow_graph_->function())) { |
202 THR_Print("reaching type to %s for v%" Pd " is %s\n", | 193 THR_Print("reaching type to %s for v%" Pd " is %s\n", |
203 value->instruction()->ToCString(), | 194 value->instruction()->ToCString(), |
204 value->definition()->ssa_temp_index(), type->ToCString()); | 195 value->definition()->ssa_temp_index(), type->ToCString()); |
205 } | 196 } |
206 } | 197 } |
207 | 198 |
208 | |
209 void FlowGraphTypePropagator::VisitJoinEntry(JoinEntryInstr* join) { | 199 void FlowGraphTypePropagator::VisitJoinEntry(JoinEntryInstr* join) { |
210 for (PhiIterator it(join); !it.Done(); it.Advance()) { | 200 for (PhiIterator it(join); !it.Done(); it.Advance()) { |
211 worklist_.Add(it.Current()); | 201 worklist_.Add(it.Current()); |
212 } | 202 } |
213 } | 203 } |
214 | 204 |
215 | |
216 void FlowGraphTypePropagator::VisitCheckSmi(CheckSmiInstr* check) { | 205 void FlowGraphTypePropagator::VisitCheckSmi(CheckSmiInstr* check) { |
217 SetCid(check->value()->definition(), kSmiCid); | 206 SetCid(check->value()->definition(), kSmiCid); |
218 } | 207 } |
219 | 208 |
220 | |
221 void FlowGraphTypePropagator::VisitCheckArrayBound( | 209 void FlowGraphTypePropagator::VisitCheckArrayBound( |
222 CheckArrayBoundInstr* check) { | 210 CheckArrayBoundInstr* check) { |
223 // Array bounds checks also test index for smi. | 211 // Array bounds checks also test index for smi. |
224 SetCid(check->index()->definition(), kSmiCid); | 212 SetCid(check->index()->definition(), kSmiCid); |
225 } | 213 } |
226 | 214 |
227 | |
228 void FlowGraphTypePropagator::VisitCheckClass(CheckClassInstr* check) { | 215 void FlowGraphTypePropagator::VisitCheckClass(CheckClassInstr* check) { |
229 if (!check->cids().IsMonomorphic()) { | 216 if (!check->cids().IsMonomorphic()) { |
230 return; | 217 return; |
231 } | 218 } |
232 | 219 |
233 if (!check->Dependencies().IsNone()) { | 220 if (!check->Dependencies().IsNone()) { |
234 // TODO(vegorov): If check is affected by side-effect we can still propagate | 221 // TODO(vegorov): If check is affected by side-effect we can still propagate |
235 // the type further but not the cid. | 222 // the type further but not the cid. |
236 return; | 223 return; |
237 } | 224 } |
238 | 225 |
239 SetCid(check->value()->definition(), check->cids().MonomorphicReceiverCid()); | 226 SetCid(check->value()->definition(), check->cids().MonomorphicReceiverCid()); |
240 } | 227 } |
241 | 228 |
242 | |
243 void FlowGraphTypePropagator::VisitCheckClassId(CheckClassIdInstr* check) { | 229 void FlowGraphTypePropagator::VisitCheckClassId(CheckClassIdInstr* check) { |
244 if (!check->Dependencies().IsNone()) { | 230 if (!check->Dependencies().IsNone()) { |
245 // TODO(vegorov): If check is affected by side-effect we can still propagate | 231 // TODO(vegorov): If check is affected by side-effect we can still propagate |
246 // the type further but not the cid. | 232 // the type further but not the cid. |
247 return; | 233 return; |
248 } | 234 } |
249 | 235 |
250 LoadClassIdInstr* load_cid = | 236 LoadClassIdInstr* load_cid = |
251 check->value()->definition()->OriginalDefinition()->AsLoadClassId(); | 237 check->value()->definition()->OriginalDefinition()->AsLoadClassId(); |
252 if (load_cid != NULL && check->cids().IsSingleCid()) { | 238 if (load_cid != NULL && check->cids().IsSingleCid()) { |
253 SetCid(load_cid->object()->definition(), check->cids().cid_start); | 239 SetCid(load_cid->object()->definition(), check->cids().cid_start); |
254 } | 240 } |
255 } | 241 } |
256 | 242 |
257 | |
258 void FlowGraphTypePropagator::CheckNonNullSelector( | 243 void FlowGraphTypePropagator::CheckNonNullSelector( |
259 Instruction* call, | 244 Instruction* call, |
260 Definition* receiver, | 245 Definition* receiver, |
261 const String& function_name) { | 246 const String& function_name) { |
262 if (!receiver->Type()->is_nullable()) { | 247 if (!receiver->Type()->is_nullable()) { |
263 // Nothing to do if type is already non-nullable. | 248 // Nothing to do if type is already non-nullable. |
264 return; | 249 return; |
265 } | 250 } |
266 const Class& null_class = | 251 const Class& null_class = |
267 Class::Handle(Isolate::Current()->object_store()->null_class()); | 252 Class::Handle(Isolate::Current()->object_store()->null_class()); |
(...skipping 11 matching lines...) Expand all Loading... |
279 if (redef != NULL) { | 264 if (redef != NULL) { |
280 for (intptr_t i = types_.length(); i <= redef->ssa_temp_index() + 1; | 265 for (intptr_t i = types_.length(); i <= redef->ssa_temp_index() + 1; |
281 ++i) { | 266 ++i) { |
282 types_.Add(NULL); | 267 types_.Add(NULL); |
283 } | 268 } |
284 } | 269 } |
285 } | 270 } |
286 } | 271 } |
287 } | 272 } |
288 | 273 |
289 | |
290 void FlowGraphTypePropagator::VisitInstanceCall(InstanceCallInstr* instr) { | 274 void FlowGraphTypePropagator::VisitInstanceCall(InstanceCallInstr* instr) { |
291 if (instr->has_unique_selector()) { | 275 if (instr->has_unique_selector()) { |
292 SetCid(instr->ArgumentAt(0), instr->ic_data()->GetReceiverClassIdAt(0)); | 276 SetCid(instr->ArgumentAt(0), instr->ic_data()->GetReceiverClassIdAt(0)); |
293 return; | 277 return; |
294 } | 278 } |
295 CheckNonNullSelector(instr, instr->ArgumentAt(0), instr->function_name()); | 279 CheckNonNullSelector(instr, instr->ArgumentAt(0), instr->function_name()); |
296 } | 280 } |
297 | 281 |
298 | |
299 void FlowGraphTypePropagator::VisitPolymorphicInstanceCall( | 282 void FlowGraphTypePropagator::VisitPolymorphicInstanceCall( |
300 PolymorphicInstanceCallInstr* instr) { | 283 PolymorphicInstanceCallInstr* instr) { |
301 if (instr->instance_call()->has_unique_selector()) { | 284 if (instr->instance_call()->has_unique_selector()) { |
302 SetCid(instr->ArgumentAt(0), instr->targets().MonomorphicReceiverCid()); | 285 SetCid(instr->ArgumentAt(0), instr->targets().MonomorphicReceiverCid()); |
303 return; | 286 return; |
304 } | 287 } |
305 CheckNonNullSelector(instr, instr->ArgumentAt(0), | 288 CheckNonNullSelector(instr, instr->ArgumentAt(0), |
306 instr->instance_call()->function_name()); | 289 instr->instance_call()->function_name()); |
307 } | 290 } |
308 | 291 |
309 | |
310 void FlowGraphTypePropagator::VisitGuardFieldClass( | 292 void FlowGraphTypePropagator::VisitGuardFieldClass( |
311 GuardFieldClassInstr* guard) { | 293 GuardFieldClassInstr* guard) { |
312 const intptr_t cid = guard->field().guarded_cid(); | 294 const intptr_t cid = guard->field().guarded_cid(); |
313 if ((cid == kIllegalCid) || (cid == kDynamicCid) || | 295 if ((cid == kIllegalCid) || (cid == kDynamicCid) || |
314 Field::IsExternalizableCid(cid)) { | 296 Field::IsExternalizableCid(cid)) { |
315 return; | 297 return; |
316 } | 298 } |
317 | 299 |
318 Definition* def = guard->value()->definition(); | 300 Definition* def = guard->value()->definition(); |
319 CompileType* current = TypeOf(def); | 301 CompileType* current = TypeOf(def); |
320 if (current->IsNone() || (current->ToCid() != cid) || | 302 if (current->IsNone() || (current->ToCid() != cid) || |
321 (current->is_nullable() && !guard->field().is_nullable())) { | 303 (current->is_nullable() && !guard->field().is_nullable())) { |
322 const bool is_nullable = | 304 const bool is_nullable = |
323 guard->field().is_nullable() && current->is_nullable(); | 305 guard->field().is_nullable() && current->is_nullable(); |
324 SetTypeOf(def, new CompileType(is_nullable, cid, NULL)); | 306 SetTypeOf(def, new CompileType(is_nullable, cid, NULL)); |
325 } | 307 } |
326 } | 308 } |
327 | 309 |
328 | |
329 void FlowGraphTypePropagator::VisitAssertAssignable( | 310 void FlowGraphTypePropagator::VisitAssertAssignable( |
330 AssertAssignableInstr* instr) { | 311 AssertAssignableInstr* instr) { |
331 SetTypeOf(instr->value()->definition(), | 312 SetTypeOf(instr->value()->definition(), |
332 new CompileType(instr->ComputeType())); | 313 new CompileType(instr->ComputeType())); |
333 } | 314 } |
334 | 315 |
335 | |
336 void FlowGraphTypePropagator::VisitBranch(BranchInstr* instr) { | 316 void FlowGraphTypePropagator::VisitBranch(BranchInstr* instr) { |
337 StrictCompareInstr* comparison = instr->comparison()->AsStrictCompare(); | 317 StrictCompareInstr* comparison = instr->comparison()->AsStrictCompare(); |
338 if (comparison == NULL) return; | 318 if (comparison == NULL) return; |
339 bool negated = comparison->kind() == Token::kNE_STRICT; | 319 bool negated = comparison->kind() == Token::kNE_STRICT; |
340 LoadClassIdInstr* load_cid = | 320 LoadClassIdInstr* load_cid = |
341 comparison->InputAt(0)->definition()->AsLoadClassId(); | 321 comparison->InputAt(0)->definition()->AsLoadClassId(); |
342 InstanceCallInstr* call = | 322 InstanceCallInstr* call = |
343 comparison->InputAt(0)->definition()->AsInstanceCall(); | 323 comparison->InputAt(0)->definition()->AsInstanceCall(); |
344 RedefinitionInstr* redef = NULL; | 324 RedefinitionInstr* redef = NULL; |
345 if (load_cid != NULL && comparison->InputAt(1)->BindsToConstant()) { | 325 if (load_cid != NULL && comparison->InputAt(1)->BindsToConstant()) { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
390 // TODO(fschneider): Add propagation for generic is-tests. | 370 // TODO(fschneider): Add propagation for generic is-tests. |
391 | 371 |
392 // Grow types array if a new redefinition was inserted. | 372 // Grow types array if a new redefinition was inserted. |
393 if (redef != NULL) { | 373 if (redef != NULL) { |
394 for (intptr_t i = types_.length(); i <= redef->ssa_temp_index() + 1; ++i) { | 374 for (intptr_t i = types_.length(); i <= redef->ssa_temp_index() + 1; ++i) { |
395 types_.Add(NULL); | 375 types_.Add(NULL); |
396 } | 376 } |
397 } | 377 } |
398 } | 378 } |
399 | 379 |
400 | |
401 void FlowGraphTypePropagator::AddToWorklist(Definition* defn) { | 380 void FlowGraphTypePropagator::AddToWorklist(Definition* defn) { |
402 if (defn->ssa_temp_index() == -1) { | 381 if (defn->ssa_temp_index() == -1) { |
403 return; | 382 return; |
404 } | 383 } |
405 | 384 |
406 const intptr_t index = defn->ssa_temp_index(); | 385 const intptr_t index = defn->ssa_temp_index(); |
407 if (!in_worklist_->Contains(index)) { | 386 if (!in_worklist_->Contains(index)) { |
408 worklist_.Add(defn); | 387 worklist_.Add(defn); |
409 in_worklist_->Add(index); | 388 in_worklist_->Add(index); |
410 } | 389 } |
411 } | 390 } |
412 | 391 |
413 | |
414 Definition* FlowGraphTypePropagator::RemoveLastFromWorklist() { | 392 Definition* FlowGraphTypePropagator::RemoveLastFromWorklist() { |
415 Definition* defn = worklist_.RemoveLast(); | 393 Definition* defn = worklist_.RemoveLast(); |
416 ASSERT(defn->ssa_temp_index() != -1); | 394 ASSERT(defn->ssa_temp_index() != -1); |
417 in_worklist_->Remove(defn->ssa_temp_index()); | 395 in_worklist_->Remove(defn->ssa_temp_index()); |
418 return defn; | 396 return defn; |
419 } | 397 } |
420 | 398 |
421 | |
422 // In the given block strengthen type assertions by hoisting first class or smi | 399 // In the given block strengthen type assertions by hoisting first class or smi |
423 // check over the same value up to the point before the assertion. This allows | 400 // check over the same value up to the point before the assertion. This allows |
424 // to eliminate type assertions that are postdominated by class or smi checks as | 401 // to eliminate type assertions that are postdominated by class or smi checks as |
425 // these checks are strongly stricter than type assertions. | 402 // these checks are strongly stricter than type assertions. |
426 void FlowGraphTypePropagator::StrengthenAsserts(BlockEntryInstr* block) { | 403 void FlowGraphTypePropagator::StrengthenAsserts(BlockEntryInstr* block) { |
427 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 404 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
428 Instruction* instr = it.Current(); | 405 Instruction* instr = it.Current(); |
429 | 406 |
430 if (instr->IsCheckSmi() || instr->IsCheckClass()) { | 407 if (instr->IsCheckSmi() || instr->IsCheckClass()) { |
431 StrengthenAssertWith(instr); | 408 StrengthenAssertWith(instr); |
(...skipping 10 matching lines...) Expand all Loading... |
442 } | 419 } |
443 } | 420 } |
444 | 421 |
445 for (intptr_t i = 0; i < collected_asserts_->length(); i++) { | 422 for (intptr_t i = 0; i < collected_asserts_->length(); i++) { |
446 (*asserts_)[(*collected_asserts_)[i]] = NULL; | 423 (*asserts_)[(*collected_asserts_)[i]] = NULL; |
447 } | 424 } |
448 | 425 |
449 collected_asserts_->TruncateTo(0); | 426 collected_asserts_->TruncateTo(0); |
450 } | 427 } |
451 | 428 |
452 | |
453 void FlowGraphTypePropagator::StrengthenAssertWith(Instruction* check) { | 429 void FlowGraphTypePropagator::StrengthenAssertWith(Instruction* check) { |
454 // Marker that is used to mark values that already had type assertion | 430 // Marker that is used to mark values that already had type assertion |
455 // strengthened. | 431 // strengthened. |
456 AssertAssignableInstr* kStrengthenedAssertMarker = | 432 AssertAssignableInstr* kStrengthenedAssertMarker = |
457 reinterpret_cast<AssertAssignableInstr*>(-1); | 433 reinterpret_cast<AssertAssignableInstr*>(-1); |
458 | 434 |
459 Definition* defn = check->InputAt(0)->definition()->OriginalDefinition(); | 435 Definition* defn = check->InputAt(0)->definition()->OriginalDefinition(); |
460 | 436 |
461 AssertAssignableInstr* assert = (*asserts_)[defn->ssa_temp_index()]; | 437 AssertAssignableInstr* assert = (*asserts_)[defn->ssa_temp_index()]; |
462 if ((assert == NULL) || (assert == kStrengthenedAssertMarker)) { | 438 if ((assert == NULL) || (assert == kStrengthenedAssertMarker)) { |
(...skipping 17 matching lines...) Expand all Loading... |
480 check->AsCheckClass()->licm_hoisted()); | 456 check->AsCheckClass()->licm_hoisted()); |
481 } | 457 } |
482 ASSERT(check_clone != NULL); | 458 ASSERT(check_clone != NULL); |
483 ASSERT(assert->deopt_id() == assert->env()->deopt_id()); | 459 ASSERT(assert->deopt_id() == assert->env()->deopt_id()); |
484 check_clone->InsertBefore(assert); | 460 check_clone->InsertBefore(assert); |
485 assert->env()->DeepCopyTo(zone(), check_clone); | 461 assert->env()->DeepCopyTo(zone(), check_clone); |
486 | 462 |
487 (*asserts_)[defn->ssa_temp_index()] = kStrengthenedAssertMarker; | 463 (*asserts_)[defn->ssa_temp_index()] = kStrengthenedAssertMarker; |
488 } | 464 } |
489 | 465 |
490 | |
491 void CompileType::Union(CompileType* other) { | 466 void CompileType::Union(CompileType* other) { |
492 if (other->IsNone()) { | 467 if (other->IsNone()) { |
493 return; | 468 return; |
494 } | 469 } |
495 | 470 |
496 if (IsNone()) { | 471 if (IsNone()) { |
497 *this = *other; | 472 *this = *other; |
498 return; | 473 return; |
499 } | 474 } |
500 | 475 |
(...skipping 21 matching lines...) Expand all Loading... |
522 type_ = other_compile_type; | 497 type_ = other_compile_type; |
523 } else if (other_compile_type->IsMoreSpecificThan(*compile_type, NULL, NULL, | 498 } else if (other_compile_type->IsMoreSpecificThan(*compile_type, NULL, NULL, |
524 Heap::kOld)) { | 499 Heap::kOld)) { |
525 // Nothing to do. | 500 // Nothing to do. |
526 } else { | 501 } else { |
527 // Can't unify. | 502 // Can't unify. |
528 type_ = &Object::dynamic_type(); | 503 type_ = &Object::dynamic_type(); |
529 } | 504 } |
530 } | 505 } |
531 | 506 |
532 | |
533 static bool IsNullableCid(intptr_t cid) { | 507 static bool IsNullableCid(intptr_t cid) { |
534 ASSERT(cid != kIllegalCid); | 508 ASSERT(cid != kIllegalCid); |
535 return cid == kNullCid || cid == kDynamicCid; | 509 return cid == kNullCid || cid == kDynamicCid; |
536 } | 510 } |
537 | 511 |
538 | |
539 CompileType CompileType::Create(intptr_t cid, const AbstractType& type) { | 512 CompileType CompileType::Create(intptr_t cid, const AbstractType& type) { |
540 return CompileType(IsNullableCid(cid), cid, &type); | 513 return CompileType(IsNullableCid(cid), cid, &type); |
541 } | 514 } |
542 | 515 |
543 | |
544 CompileType CompileType::FromAbstractType(const AbstractType& type, | 516 CompileType CompileType::FromAbstractType(const AbstractType& type, |
545 bool is_nullable) { | 517 bool is_nullable) { |
546 return CompileType(is_nullable, kIllegalCid, &type); | 518 return CompileType(is_nullable, kIllegalCid, &type); |
547 } | 519 } |
548 | 520 |
549 | |
550 CompileType CompileType::FromCid(intptr_t cid) { | 521 CompileType CompileType::FromCid(intptr_t cid) { |
551 return CompileType(IsNullableCid(cid), cid, NULL); | 522 return CompileType(IsNullableCid(cid), cid, NULL); |
552 } | 523 } |
553 | 524 |
554 | |
555 CompileType CompileType::Dynamic() { | 525 CompileType CompileType::Dynamic() { |
556 return Create(kDynamicCid, Object::dynamic_type()); | 526 return Create(kDynamicCid, Object::dynamic_type()); |
557 } | 527 } |
558 | 528 |
559 | |
560 CompileType CompileType::Null() { | 529 CompileType CompileType::Null() { |
561 return Create(kNullCid, Type::ZoneHandle(Type::NullType())); | 530 return Create(kNullCid, Type::ZoneHandle(Type::NullType())); |
562 } | 531 } |
563 | 532 |
564 | |
565 CompileType CompileType::Bool() { | 533 CompileType CompileType::Bool() { |
566 return Create(kBoolCid, Type::ZoneHandle(Type::BoolType())); | 534 return Create(kBoolCid, Type::ZoneHandle(Type::BoolType())); |
567 } | 535 } |
568 | 536 |
569 | |
570 CompileType CompileType::Int() { | 537 CompileType CompileType::Int() { |
571 return FromAbstractType(Type::ZoneHandle(Type::Int64Type()), kNonNullable); | 538 return FromAbstractType(Type::ZoneHandle(Type::Int64Type()), kNonNullable); |
572 } | 539 } |
573 | 540 |
574 | |
575 CompileType CompileType::Smi() { | 541 CompileType CompileType::Smi() { |
576 return Create(kSmiCid, Type::ZoneHandle(Type::SmiType())); | 542 return Create(kSmiCid, Type::ZoneHandle(Type::SmiType())); |
577 } | 543 } |
578 | 544 |
579 | |
580 CompileType CompileType::String() { | 545 CompileType CompileType::String() { |
581 return FromAbstractType(Type::ZoneHandle(Type::StringType()), kNonNullable); | 546 return FromAbstractType(Type::ZoneHandle(Type::StringType()), kNonNullable); |
582 } | 547 } |
583 | 548 |
584 | |
585 intptr_t CompileType::ToCid() { | 549 intptr_t CompileType::ToCid() { |
586 if ((cid_ == kNullCid) || (cid_ == kDynamicCid)) { | 550 if ((cid_ == kNullCid) || (cid_ == kDynamicCid)) { |
587 return cid_; | 551 return cid_; |
588 } | 552 } |
589 | 553 |
590 return is_nullable_ ? static_cast<intptr_t>(kDynamicCid) : ToNullableCid(); | 554 return is_nullable_ ? static_cast<intptr_t>(kDynamicCid) : ToNullableCid(); |
591 } | 555 } |
592 | 556 |
593 | |
594 intptr_t CompileType::ToNullableCid() { | 557 intptr_t CompileType::ToNullableCid() { |
595 if (cid_ == kIllegalCid) { | 558 if (cid_ == kIllegalCid) { |
596 if (type_ == NULL) { | 559 if (type_ == NULL) { |
597 // Type propagation is turned off or has not yet run. | 560 // Type propagation is turned off or has not yet run. |
598 return kDynamicCid; | 561 return kDynamicCid; |
599 } else if (type_->IsMalformed()) { | 562 } else if (type_->IsMalformed()) { |
600 cid_ = kDynamicCid; | 563 cid_ = kDynamicCid; |
601 } else if (type_->IsVoidType()) { | 564 } else if (type_->IsVoidType()) { |
602 cid_ = kDynamicCid; | 565 cid_ = kDynamicCid; |
603 } else if (type_->IsFunctionType() || type_->IsDartFunctionType()) { | 566 } else if (type_->IsFunctionType() || type_->IsDartFunctionType()) { |
(...skipping 25 matching lines...) Expand all Loading... |
629 cid_ = kDynamicCid; | 592 cid_ = kDynamicCid; |
630 } | 593 } |
631 } else { | 594 } else { |
632 cid_ = kDynamicCid; | 595 cid_ = kDynamicCid; |
633 } | 596 } |
634 } | 597 } |
635 | 598 |
636 return cid_; | 599 return cid_; |
637 } | 600 } |
638 | 601 |
639 | |
640 bool CompileType::HasDecidableNullability() { | 602 bool CompileType::HasDecidableNullability() { |
641 return !is_nullable_ || IsNull(); | 603 return !is_nullable_ || IsNull(); |
642 } | 604 } |
643 | 605 |
644 | |
645 bool CompileType::IsNull() { | 606 bool CompileType::IsNull() { |
646 return (ToCid() == kNullCid); | 607 return (ToCid() == kNullCid); |
647 } | 608 } |
648 | 609 |
649 | |
650 const AbstractType* CompileType::ToAbstractType() { | 610 const AbstractType* CompileType::ToAbstractType() { |
651 if (type_ == NULL) { | 611 if (type_ == NULL) { |
652 // Type propagation has not run. Return dynamic-type. | 612 // Type propagation has not run. Return dynamic-type. |
653 if (cid_ == kIllegalCid) { | 613 if (cid_ == kIllegalCid) { |
654 type_ = &Object::dynamic_type(); | 614 type_ = &Object::dynamic_type(); |
655 return type_; | 615 return type_; |
656 } | 616 } |
657 | 617 |
658 // VM-internal objects don't have a compile-type. Return dynamic-type | 618 // VM-internal objects don't have a compile-type. Return dynamic-type |
659 // in this case. | 619 // in this case. |
660 if (cid_ < kInstanceCid) { | 620 if (cid_ < kInstanceCid) { |
661 type_ = &Object::dynamic_type(); | 621 type_ = &Object::dynamic_type(); |
662 return type_; | 622 return type_; |
663 } | 623 } |
664 | 624 |
665 const Class& type_class = | 625 const Class& type_class = |
666 Class::Handle(Isolate::Current()->class_table()->At(cid_)); | 626 Class::Handle(Isolate::Current()->class_table()->At(cid_)); |
667 | 627 |
668 if (type_class.NumTypeArguments() > 0) { | 628 if (type_class.NumTypeArguments() > 0) { |
669 type_ = &Object::dynamic_type(); | 629 type_ = &Object::dynamic_type(); |
670 return type_; | 630 return type_; |
671 } | 631 } |
672 | 632 |
673 type_ = &Type::ZoneHandle(Type::NewNonParameterizedType(type_class)); | 633 type_ = &Type::ZoneHandle(Type::NewNonParameterizedType(type_class)); |
674 } | 634 } |
675 | 635 |
676 return type_; | 636 return type_; |
677 } | 637 } |
678 | 638 |
679 | |
680 bool CompileType::CanComputeIsInstanceOf(const AbstractType& type, | 639 bool CompileType::CanComputeIsInstanceOf(const AbstractType& type, |
681 bool is_nullable, | 640 bool is_nullable, |
682 bool* is_instance) { | 641 bool* is_instance) { |
683 ASSERT(is_instance != NULL); | 642 ASSERT(is_instance != NULL); |
684 // We cannot give an answer if the given type is malformed or malbounded. | 643 // We cannot give an answer if the given type is malformed or malbounded. |
685 if (type.IsMalformedOrMalbounded()) { | 644 if (type.IsMalformedOrMalbounded()) { |
686 return false; | 645 return false; |
687 } | 646 } |
688 | 647 |
689 if (type.IsDynamicType() || type.IsObjectType() || type.IsVoidType()) { | 648 if (type.IsDynamicType() || type.IsObjectType() || type.IsVoidType()) { |
(...skipping 25 matching lines...) Expand all Loading... |
715 // If the value can be null then we can't eliminate the | 674 // If the value can be null then we can't eliminate the |
716 // check unless null is allowed. | 675 // check unless null is allowed. |
717 if (is_nullable_ && !is_nullable) { | 676 if (is_nullable_ && !is_nullable) { |
718 return false; | 677 return false; |
719 } | 678 } |
720 | 679 |
721 *is_instance = compile_type.IsMoreSpecificThan(type, NULL, NULL, Heap::kOld); | 680 *is_instance = compile_type.IsMoreSpecificThan(type, NULL, NULL, Heap::kOld); |
722 return *is_instance; | 681 return *is_instance; |
723 } | 682 } |
724 | 683 |
725 | |
726 bool CompileType::IsMoreSpecificThan(const AbstractType& other) { | 684 bool CompileType::IsMoreSpecificThan(const AbstractType& other) { |
727 if (IsNone()) { | 685 if (IsNone()) { |
728 return false; | 686 return false; |
729 } | 687 } |
730 | 688 |
731 return ToAbstractType()->IsMoreSpecificThan(other, NULL, NULL, Heap::kOld); | 689 return ToAbstractType()->IsMoreSpecificThan(other, NULL, NULL, Heap::kOld); |
732 } | 690 } |
733 | 691 |
734 | |
735 CompileType* Value::Type() { | 692 CompileType* Value::Type() { |
736 if (reaching_type_ == NULL) { | 693 if (reaching_type_ == NULL) { |
737 reaching_type_ = definition()->Type(); | 694 reaching_type_ = definition()->Type(); |
738 } | 695 } |
739 return reaching_type_; | 696 return reaching_type_; |
740 } | 697 } |
741 | 698 |
742 | |
743 CompileType PhiInstr::ComputeType() const { | 699 CompileType PhiInstr::ComputeType() const { |
744 // Initially type of phis is unknown until type propagation is run | 700 // Initially type of phis is unknown until type propagation is run |
745 // for the first time. | 701 // for the first time. |
746 return CompileType::None(); | 702 return CompileType::None(); |
747 } | 703 } |
748 | 704 |
749 | |
750 bool PhiInstr::RecomputeType() { | 705 bool PhiInstr::RecomputeType() { |
751 CompileType result = CompileType::None(); | 706 CompileType result = CompileType::None(); |
752 for (intptr_t i = 0; i < InputCount(); i++) { | 707 for (intptr_t i = 0; i < InputCount(); i++) { |
753 if (FLAG_support_il_printer && FLAG_trace_type_propagation) { | 708 if (FLAG_support_il_printer && FLAG_trace_type_propagation) { |
754 THR_Print(" phi %" Pd " input %" Pd ": v%" Pd " has reaching type %s\n", | 709 THR_Print(" phi %" Pd " input %" Pd ": v%" Pd " has reaching type %s\n", |
755 ssa_temp_index(), i, InputAt(i)->definition()->ssa_temp_index(), | 710 ssa_temp_index(), i, InputAt(i)->definition()->ssa_temp_index(), |
756 InputAt(i)->Type()->ToCString()); | 711 InputAt(i)->Type()->ToCString()); |
757 } | 712 } |
758 result.Union(InputAt(i)->Type()); | 713 result.Union(InputAt(i)->Type()); |
759 } | 714 } |
760 | 715 |
761 if (result.IsNone()) { | 716 if (result.IsNone()) { |
762 ASSERT(Type()->IsNone()); | 717 ASSERT(Type()->IsNone()); |
763 return false; | 718 return false; |
764 } | 719 } |
765 | 720 |
766 return UpdateType(result); | 721 return UpdateType(result); |
767 } | 722 } |
768 | 723 |
769 | |
770 CompileType RedefinitionInstr::ComputeType() const { | 724 CompileType RedefinitionInstr::ComputeType() const { |
771 if (constrained_type_ != NULL) { | 725 if (constrained_type_ != NULL) { |
772 // Check if the type associated with this redefinition is more specific | 726 // Check if the type associated with this redefinition is more specific |
773 // than the type of its input. If yes, return it. Otherwise, fall back | 727 // than the type of its input. If yes, return it. Otherwise, fall back |
774 // to the input's type. | 728 // to the input's type. |
775 | 729 |
776 // If either type is non-nullable, the resulting type is non-nullable. | 730 // If either type is non-nullable, the resulting type is non-nullable. |
777 const bool is_nullable = | 731 const bool is_nullable = |
778 value()->Type()->is_nullable() && constrained_type_->is_nullable(); | 732 value()->Type()->is_nullable() && constrained_type_->is_nullable(); |
779 | 733 |
(...skipping 11 matching lines...) Expand all Loading... |
791 return is_nullable ? *value()->Type() | 745 return is_nullable ? *value()->Type() |
792 : value()->Type()->CopyNonNullable(); | 746 : value()->Type()->CopyNonNullable(); |
793 } else { | 747 } else { |
794 return is_nullable ? *constrained_type_ | 748 return is_nullable ? *constrained_type_ |
795 : constrained_type_->CopyNonNullable(); | 749 : constrained_type_->CopyNonNullable(); |
796 } | 750 } |
797 } | 751 } |
798 return *value()->Type(); | 752 return *value()->Type(); |
799 } | 753 } |
800 | 754 |
801 | |
802 bool RedefinitionInstr::RecomputeType() { | 755 bool RedefinitionInstr::RecomputeType() { |
803 return UpdateType(ComputeType()); | 756 return UpdateType(ComputeType()); |
804 } | 757 } |
805 | 758 |
806 | |
807 CompileType IfThenElseInstr::ComputeType() const { | 759 CompileType IfThenElseInstr::ComputeType() const { |
808 return CompileType::FromCid(kSmiCid); | 760 return CompileType::FromCid(kSmiCid); |
809 } | 761 } |
810 | 762 |
811 | |
812 CompileType ParameterInstr::ComputeType() const { | 763 CompileType ParameterInstr::ComputeType() const { |
813 // Note that returning the declared type of the formal parameter would be | 764 // Note that returning the declared type of the formal parameter would be |
814 // incorrect, because ParameterInstr is used as input to the type check | 765 // incorrect, because ParameterInstr is used as input to the type check |
815 // verifying the run time type of the passed-in parameter and this check would | 766 // verifying the run time type of the passed-in parameter and this check would |
816 // always be wrongly eliminated. | 767 // always be wrongly eliminated. |
817 // However there are parameters that are known to match their declared type: | 768 // However there are parameters that are known to match their declared type: |
818 // for example receiver. | 769 // for example receiver. |
819 GraphEntryInstr* graph_entry = block_->AsGraphEntry(); | 770 GraphEntryInstr* graph_entry = block_->AsGraphEntry(); |
820 if (graph_entry == NULL) { | 771 if (graph_entry == NULL) { |
821 graph_entry = block_->AsCatchBlockEntry()->graph_entry(); | 772 graph_entry = block_->AsCatchBlockEntry()->graph_entry(); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
886 } | 837 } |
887 } | 838 } |
888 } | 839 } |
889 | 840 |
890 return CompileType(CompileType::kNonNullable, cid, &type); | 841 return CompileType(CompileType::kNonNullable, cid, &type); |
891 } | 842 } |
892 | 843 |
893 return CompileType::Dynamic(); | 844 return CompileType::Dynamic(); |
894 } | 845 } |
895 | 846 |
896 | |
897 CompileType PushArgumentInstr::ComputeType() const { | 847 CompileType PushArgumentInstr::ComputeType() const { |
898 return CompileType::Dynamic(); | 848 return CompileType::Dynamic(); |
899 } | 849 } |
900 | 850 |
901 | |
902 CompileType ConstantInstr::ComputeType() const { | 851 CompileType ConstantInstr::ComputeType() const { |
903 if (value().IsNull()) { | 852 if (value().IsNull()) { |
904 return CompileType::Null(); | 853 return CompileType::Null(); |
905 } | 854 } |
906 | 855 |
907 intptr_t cid = value().GetClassId(); | 856 intptr_t cid = value().GetClassId(); |
908 if (Field::IsExternalizableCid(cid)) { | 857 if (Field::IsExternalizableCid(cid)) { |
909 cid = kDynamicCid; | 858 cid = kDynamicCid; |
910 } | 859 } |
911 | 860 |
912 if (value().IsInstance()) { | 861 if (value().IsInstance()) { |
913 // Allocate in old-space since this may be invoked from the | 862 // Allocate in old-space since this may be invoked from the |
914 // background compiler. | 863 // background compiler. |
915 return CompileType::Create( | 864 return CompileType::Create( |
916 cid, | 865 cid, |
917 AbstractType::ZoneHandle(Instance::Cast(value()).GetType(Heap::kOld))); | 866 AbstractType::ZoneHandle(Instance::Cast(value()).GetType(Heap::kOld))); |
918 } else { | 867 } else { |
919 // Type info for non-instance objects. | 868 // Type info for non-instance objects. |
920 return CompileType::FromCid(cid); | 869 return CompileType::FromCid(cid); |
921 } | 870 } |
922 } | 871 } |
923 | 872 |
924 | |
925 CompileType AssertAssignableInstr::ComputeType() const { | 873 CompileType AssertAssignableInstr::ComputeType() const { |
926 CompileType* value_type = value()->Type(); | 874 CompileType* value_type = value()->Type(); |
927 | 875 |
928 if (value_type->IsMoreSpecificThan(dst_type())) { | 876 if (value_type->IsMoreSpecificThan(dst_type())) { |
929 return *value_type; | 877 return *value_type; |
930 } | 878 } |
931 | 879 |
932 return CompileType::Create(value_type->ToCid(), dst_type()); | 880 return CompileType::Create(value_type->ToCid(), dst_type()); |
933 } | 881 } |
934 | 882 |
935 | |
936 bool AssertAssignableInstr::RecomputeType() { | 883 bool AssertAssignableInstr::RecomputeType() { |
937 return UpdateType(ComputeType()); | 884 return UpdateType(ComputeType()); |
938 } | 885 } |
939 | 886 |
940 | |
941 CompileType AssertBooleanInstr::ComputeType() const { | 887 CompileType AssertBooleanInstr::ComputeType() const { |
942 return CompileType::Bool(); | 888 return CompileType::Bool(); |
943 } | 889 } |
944 | 890 |
945 | |
946 CompileType BooleanNegateInstr::ComputeType() const { | 891 CompileType BooleanNegateInstr::ComputeType() const { |
947 return CompileType::Bool(); | 892 return CompileType::Bool(); |
948 } | 893 } |
949 | 894 |
950 | |
951 CompileType InstanceOfInstr::ComputeType() const { | 895 CompileType InstanceOfInstr::ComputeType() const { |
952 return CompileType::Bool(); | 896 return CompileType::Bool(); |
953 } | 897 } |
954 | 898 |
955 | |
956 CompileType StrictCompareInstr::ComputeType() const { | 899 CompileType StrictCompareInstr::ComputeType() const { |
957 return CompileType::Bool(); | 900 return CompileType::Bool(); |
958 } | 901 } |
959 | 902 |
960 | |
961 CompileType TestSmiInstr::ComputeType() const { | 903 CompileType TestSmiInstr::ComputeType() const { |
962 return CompileType::Bool(); | 904 return CompileType::Bool(); |
963 } | 905 } |
964 | 906 |
965 | |
966 CompileType TestCidsInstr::ComputeType() const { | 907 CompileType TestCidsInstr::ComputeType() const { |
967 return CompileType::Bool(); | 908 return CompileType::Bool(); |
968 } | 909 } |
969 | 910 |
970 | |
971 CompileType EqualityCompareInstr::ComputeType() const { | 911 CompileType EqualityCompareInstr::ComputeType() const { |
972 // Used for numeric comparisons only. | 912 // Used for numeric comparisons only. |
973 return CompileType::Bool(); | 913 return CompileType::Bool(); |
974 } | 914 } |
975 | 915 |
976 | |
977 CompileType RelationalOpInstr::ComputeType() const { | 916 CompileType RelationalOpInstr::ComputeType() const { |
978 // Used for numeric comparisons only. | 917 // Used for numeric comparisons only. |
979 return CompileType::Bool(); | 918 return CompileType::Bool(); |
980 } | 919 } |
981 | 920 |
982 | |
983 CompileType SpecialParameterInstr::ComputeType() const { | 921 CompileType SpecialParameterInstr::ComputeType() const { |
984 switch (kind()) { | 922 switch (kind()) { |
985 case kContext: | 923 case kContext: |
986 return CompileType::FromCid(kContextCid); | 924 return CompileType::FromCid(kContextCid); |
987 case kTypeArgs: | 925 case kTypeArgs: |
988 return CompileType::FromCid(kTypeArgumentsCid); | 926 return CompileType::FromCid(kTypeArgumentsCid); |
989 } | 927 } |
990 UNREACHABLE(); | 928 UNREACHABLE(); |
991 return CompileType::Dynamic(); | 929 return CompileType::Dynamic(); |
992 } | 930 } |
993 | 931 |
994 | |
995 CompileType CloneContextInstr::ComputeType() const { | 932 CompileType CloneContextInstr::ComputeType() const { |
996 return CompileType(CompileType::kNonNullable, kContextCid, | 933 return CompileType(CompileType::kNonNullable, kContextCid, |
997 &Object::dynamic_type()); | 934 &Object::dynamic_type()); |
998 } | 935 } |
999 | 936 |
1000 | |
1001 CompileType AllocateContextInstr::ComputeType() const { | 937 CompileType AllocateContextInstr::ComputeType() const { |
1002 return CompileType(CompileType::kNonNullable, kContextCid, | 938 return CompileType(CompileType::kNonNullable, kContextCid, |
1003 &Object::dynamic_type()); | 939 &Object::dynamic_type()); |
1004 } | 940 } |
1005 | 941 |
1006 | |
1007 CompileType AllocateUninitializedContextInstr::ComputeType() const { | 942 CompileType AllocateUninitializedContextInstr::ComputeType() const { |
1008 return CompileType(CompileType::kNonNullable, kContextCid, | 943 return CompileType(CompileType::kNonNullable, kContextCid, |
1009 &Object::dynamic_type()); | 944 &Object::dynamic_type()); |
1010 } | 945 } |
1011 | 946 |
1012 | |
1013 CompileType PolymorphicInstanceCallInstr::ComputeType() const { | 947 CompileType PolymorphicInstanceCallInstr::ComputeType() const { |
1014 if (!IsSureToCallSingleRecognizedTarget()) return CompileType::Dynamic(); | 948 if (!IsSureToCallSingleRecognizedTarget()) return CompileType::Dynamic(); |
1015 const Function& target = *targets_.TargetAt(0)->target; | 949 const Function& target = *targets_.TargetAt(0)->target; |
1016 return (target.recognized_kind() != MethodRecognizer::kUnknown) | 950 return (target.recognized_kind() != MethodRecognizer::kUnknown) |
1017 ? CompileType::FromCid(MethodRecognizer::ResultCid(target)) | 951 ? CompileType::FromCid(MethodRecognizer::ResultCid(target)) |
1018 : CompileType::Dynamic(); | 952 : CompileType::Dynamic(); |
1019 } | 953 } |
1020 | 954 |
1021 | |
1022 CompileType StaticCallInstr::ComputeType() const { | 955 CompileType StaticCallInstr::ComputeType() const { |
1023 if (result_cid_ != kDynamicCid) { | 956 if (result_cid_ != kDynamicCid) { |
1024 return CompileType::FromCid(result_cid_); | 957 return CompileType::FromCid(result_cid_); |
1025 } | 958 } |
1026 | 959 |
1027 if (Isolate::Current()->type_checks()) { | 960 if (Isolate::Current()->type_checks()) { |
1028 const AbstractType& result_type = | 961 const AbstractType& result_type = |
1029 AbstractType::ZoneHandle(function().result_type()); | 962 AbstractType::ZoneHandle(function().result_type()); |
1030 return CompileType::FromAbstractType(result_type); | 963 return CompileType::FromAbstractType(result_type); |
1031 } | 964 } |
1032 | 965 |
1033 return (function_.recognized_kind() != MethodRecognizer::kUnknown) | 966 return (function_.recognized_kind() != MethodRecognizer::kUnknown) |
1034 ? CompileType::FromCid(MethodRecognizer::ResultCid(function_)) | 967 ? CompileType::FromCid(MethodRecognizer::ResultCid(function_)) |
1035 : CompileType::Dynamic(); | 968 : CompileType::Dynamic(); |
1036 } | 969 } |
1037 | 970 |
1038 | |
1039 CompileType LoadLocalInstr::ComputeType() const { | 971 CompileType LoadLocalInstr::ComputeType() const { |
1040 if (Isolate::Current()->type_checks()) { | 972 if (Isolate::Current()->type_checks()) { |
1041 return CompileType::FromAbstractType(local().type()); | 973 return CompileType::FromAbstractType(local().type()); |
1042 } | 974 } |
1043 return CompileType::Dynamic(); | 975 return CompileType::Dynamic(); |
1044 } | 976 } |
1045 | 977 |
1046 | |
1047 CompileType DropTempsInstr::ComputeType() const { | 978 CompileType DropTempsInstr::ComputeType() const { |
1048 return *value()->Type(); | 979 return *value()->Type(); |
1049 } | 980 } |
1050 | 981 |
1051 | |
1052 CompileType StoreLocalInstr::ComputeType() const { | 982 CompileType StoreLocalInstr::ComputeType() const { |
1053 // Returns stored value. | 983 // Returns stored value. |
1054 return *value()->Type(); | 984 return *value()->Type(); |
1055 } | 985 } |
1056 | 986 |
1057 | |
1058 CompileType OneByteStringFromCharCodeInstr::ComputeType() const { | 987 CompileType OneByteStringFromCharCodeInstr::ComputeType() const { |
1059 return CompileType::FromCid(kOneByteStringCid); | 988 return CompileType::FromCid(kOneByteStringCid); |
1060 } | 989 } |
1061 | 990 |
1062 | |
1063 CompileType StringToCharCodeInstr::ComputeType() const { | 991 CompileType StringToCharCodeInstr::ComputeType() const { |
1064 return CompileType::FromCid(kSmiCid); | 992 return CompileType::FromCid(kSmiCid); |
1065 } | 993 } |
1066 | 994 |
1067 | |
1068 CompileType StringInterpolateInstr::ComputeType() const { | 995 CompileType StringInterpolateInstr::ComputeType() const { |
1069 // TODO(srdjan): Do better and determine if it is a one or two byte string. | 996 // TODO(srdjan): Do better and determine if it is a one or two byte string. |
1070 return CompileType::String(); | 997 return CompileType::String(); |
1071 } | 998 } |
1072 | 999 |
1073 | |
1074 CompileType LoadStaticFieldInstr::ComputeType() const { | 1000 CompileType LoadStaticFieldInstr::ComputeType() const { |
1075 bool is_nullable = CompileType::kNullable; | 1001 bool is_nullable = CompileType::kNullable; |
1076 intptr_t cid = kDynamicCid; | 1002 intptr_t cid = kDynamicCid; |
1077 AbstractType* abstract_type = NULL; | 1003 AbstractType* abstract_type = NULL; |
1078 const Field& field = this->StaticField(); | 1004 const Field& field = this->StaticField(); |
1079 if (Isolate::Current()->type_checks()) { | 1005 if (Isolate::Current()->type_checks()) { |
1080 cid = kIllegalCid; | 1006 cid = kIllegalCid; |
1081 abstract_type = &AbstractType::ZoneHandle(field.type()); | 1007 abstract_type = &AbstractType::ZoneHandle(field.type()); |
1082 } | 1008 } |
1083 ASSERT(field.is_static()); | 1009 ASSERT(field.is_static()); |
1084 if (field.is_final()) { | 1010 if (field.is_final()) { |
1085 if (!FLAG_fields_may_be_reset) { | 1011 if (!FLAG_fields_may_be_reset) { |
1086 const Instance& obj = Instance::Handle(field.StaticValue()); | 1012 const Instance& obj = Instance::Handle(field.StaticValue()); |
1087 if ((obj.raw() != Object::sentinel().raw()) && | 1013 if ((obj.raw() != Object::sentinel().raw()) && |
1088 (obj.raw() != Object::transition_sentinel().raw()) && !obj.IsNull()) { | 1014 (obj.raw() != Object::transition_sentinel().raw()) && !obj.IsNull()) { |
1089 is_nullable = CompileType::kNonNullable; | 1015 is_nullable = CompileType::kNonNullable; |
1090 cid = obj.GetClassId(); | 1016 cid = obj.GetClassId(); |
1091 } | 1017 } |
1092 } else if (field.guarded_cid() != kIllegalCid) { | 1018 } else if (field.guarded_cid() != kIllegalCid) { |
1093 cid = field.guarded_cid(); | 1019 cid = field.guarded_cid(); |
1094 if (!IsNullableCid(cid)) is_nullable = CompileType::kNonNullable; | 1020 if (!IsNullableCid(cid)) is_nullable = CompileType::kNonNullable; |
1095 } | 1021 } |
1096 } | 1022 } |
1097 if (Field::IsExternalizableCid(cid)) { | 1023 if (Field::IsExternalizableCid(cid)) { |
1098 cid = kDynamicCid; | 1024 cid = kDynamicCid; |
1099 } | 1025 } |
1100 return CompileType(is_nullable, cid, abstract_type); | 1026 return CompileType(is_nullable, cid, abstract_type); |
1101 } | 1027 } |
1102 | 1028 |
1103 | |
1104 CompileType CreateArrayInstr::ComputeType() const { | 1029 CompileType CreateArrayInstr::ComputeType() const { |
1105 // TODO(fschneider): Add abstract type and type arguments to the compile type. | 1030 // TODO(fschneider): Add abstract type and type arguments to the compile type. |
1106 return CompileType::FromCid(kArrayCid); | 1031 return CompileType::FromCid(kArrayCid); |
1107 } | 1032 } |
1108 | 1033 |
1109 | |
1110 CompileType AllocateObjectInstr::ComputeType() const { | 1034 CompileType AllocateObjectInstr::ComputeType() const { |
1111 if (!closure_function().IsNull()) { | 1035 if (!closure_function().IsNull()) { |
1112 ASSERT(cls().id() == kClosureCid); | 1036 ASSERT(cls().id() == kClosureCid); |
1113 return CompileType(CompileType::kNonNullable, kClosureCid, | 1037 return CompileType(CompileType::kNonNullable, kClosureCid, |
1114 &Type::ZoneHandle(closure_function().SignatureType())); | 1038 &Type::ZoneHandle(closure_function().SignatureType())); |
1115 } | 1039 } |
1116 // TODO(vegorov): Incorporate type arguments into the returned type. | 1040 // TODO(vegorov): Incorporate type arguments into the returned type. |
1117 return CompileType::FromCid(cls().id()); | 1041 return CompileType::FromCid(cls().id()); |
1118 } | 1042 } |
1119 | 1043 |
1120 | |
1121 CompileType LoadUntaggedInstr::ComputeType() const { | 1044 CompileType LoadUntaggedInstr::ComputeType() const { |
1122 return CompileType::Dynamic(); | 1045 return CompileType::Dynamic(); |
1123 } | 1046 } |
1124 | 1047 |
1125 | |
1126 CompileType LoadClassIdInstr::ComputeType() const { | 1048 CompileType LoadClassIdInstr::ComputeType() const { |
1127 return CompileType::FromCid(kSmiCid); | 1049 return CompileType::FromCid(kSmiCid); |
1128 } | 1050 } |
1129 | 1051 |
1130 | |
1131 CompileType LoadFieldInstr::ComputeType() const { | 1052 CompileType LoadFieldInstr::ComputeType() const { |
1132 // Type may be null if the field is a VM field, e.g. context parent. | 1053 // Type may be null if the field is a VM field, e.g. context parent. |
1133 // Keep it as null for debug purposes and do not return dynamic in production | 1054 // Keep it as null for debug purposes and do not return dynamic in production |
1134 // mode, since misuse of the type would remain undetected. | 1055 // mode, since misuse of the type would remain undetected. |
1135 if (type().IsNull()) { | 1056 if (type().IsNull()) { |
1136 return CompileType::Dynamic(); | 1057 return CompileType::Dynamic(); |
1137 } | 1058 } |
1138 | 1059 |
1139 const AbstractType* abstract_type = NULL; | 1060 const AbstractType* abstract_type = NULL; |
1140 if (Isolate::Current()->type_checks() && | 1061 if (Isolate::Current()->type_checks() && |
(...skipping 12 matching lines...) Expand all Loading... |
1153 // changed on the fly. | 1074 // changed on the fly. |
1154 field_cid = kDynamicCid; | 1075 field_cid = kDynamicCid; |
1155 } | 1076 } |
1156 return CompileType(is_nullable, field_cid, abstract_type); | 1077 return CompileType(is_nullable, field_cid, abstract_type); |
1157 } | 1078 } |
1158 | 1079 |
1159 ASSERT(!Field::IsExternalizableCid(result_cid_)); | 1080 ASSERT(!Field::IsExternalizableCid(result_cid_)); |
1160 return CompileType::Create(result_cid_, *abstract_type); | 1081 return CompileType::Create(result_cid_, *abstract_type); |
1161 } | 1082 } |
1162 | 1083 |
1163 | |
1164 CompileType LoadCodeUnitsInstr::ComputeType() const { | 1084 CompileType LoadCodeUnitsInstr::ComputeType() const { |
1165 switch (class_id()) { | 1085 switch (class_id()) { |
1166 case kOneByteStringCid: | 1086 case kOneByteStringCid: |
1167 case kExternalOneByteStringCid: | 1087 case kExternalOneByteStringCid: |
1168 case kTwoByteStringCid: | 1088 case kTwoByteStringCid: |
1169 case kExternalTwoByteStringCid: | 1089 case kExternalTwoByteStringCid: |
1170 return can_pack_into_smi() ? CompileType::FromCid(kSmiCid) | 1090 return can_pack_into_smi() ? CompileType::FromCid(kSmiCid) |
1171 : CompileType::Int(); | 1091 : CompileType::Int(); |
1172 default: | 1092 default: |
1173 UNIMPLEMENTED(); | 1093 UNIMPLEMENTED(); |
1174 return CompileType::Dynamic(); | 1094 return CompileType::Dynamic(); |
1175 } | 1095 } |
1176 } | 1096 } |
1177 | 1097 |
1178 | |
1179 CompileType BinaryInt32OpInstr::ComputeType() const { | 1098 CompileType BinaryInt32OpInstr::ComputeType() const { |
1180 // TODO(vegorov): range analysis information shall be used here. | 1099 // TODO(vegorov): range analysis information shall be used here. |
1181 return CompileType::Int(); | 1100 return CompileType::Int(); |
1182 } | 1101 } |
1183 | 1102 |
1184 | |
1185 CompileType BinarySmiOpInstr::ComputeType() const { | 1103 CompileType BinarySmiOpInstr::ComputeType() const { |
1186 return CompileType::FromCid(kSmiCid); | 1104 return CompileType::FromCid(kSmiCid); |
1187 } | 1105 } |
1188 | 1106 |
1189 | |
1190 CompileType UnarySmiOpInstr::ComputeType() const { | 1107 CompileType UnarySmiOpInstr::ComputeType() const { |
1191 return CompileType::FromCid(kSmiCid); | 1108 return CompileType::FromCid(kSmiCid); |
1192 } | 1109 } |
1193 | 1110 |
1194 | |
1195 CompileType UnaryDoubleOpInstr::ComputeType() const { | 1111 CompileType UnaryDoubleOpInstr::ComputeType() const { |
1196 return CompileType::FromCid(kDoubleCid); | 1112 return CompileType::FromCid(kDoubleCid); |
1197 } | 1113 } |
1198 | 1114 |
1199 | |
1200 CompileType DoubleToSmiInstr::ComputeType() const { | 1115 CompileType DoubleToSmiInstr::ComputeType() const { |
1201 return CompileType::FromCid(kSmiCid); | 1116 return CompileType::FromCid(kSmiCid); |
1202 } | 1117 } |
1203 | 1118 |
1204 | |
1205 CompileType ConstraintInstr::ComputeType() const { | 1119 CompileType ConstraintInstr::ComputeType() const { |
1206 return CompileType::FromCid(kSmiCid); | 1120 return CompileType::FromCid(kSmiCid); |
1207 } | 1121 } |
1208 | 1122 |
1209 // Note that MintOp may produce Smi-s as result of an | 1123 // Note that MintOp may produce Smi-s as result of an |
1210 // appended BoxInt64Instr node. | 1124 // appended BoxInt64Instr node. |
1211 CompileType BinaryMintOpInstr::ComputeType() const { | 1125 CompileType BinaryMintOpInstr::ComputeType() const { |
1212 return CompileType::Int(); | 1126 return CompileType::Int(); |
1213 } | 1127 } |
1214 | 1128 |
1215 | |
1216 CompileType ShiftMintOpInstr::ComputeType() const { | 1129 CompileType ShiftMintOpInstr::ComputeType() const { |
1217 return CompileType::Int(); | 1130 return CompileType::Int(); |
1218 } | 1131 } |
1219 | 1132 |
1220 | |
1221 CompileType UnaryMintOpInstr::ComputeType() const { | 1133 CompileType UnaryMintOpInstr::ComputeType() const { |
1222 return CompileType::Int(); | 1134 return CompileType::Int(); |
1223 } | 1135 } |
1224 | 1136 |
1225 | |
1226 CompileType BoxIntegerInstr::ComputeType() const { | 1137 CompileType BoxIntegerInstr::ComputeType() const { |
1227 return ValueFitsSmi() ? CompileType::FromCid(kSmiCid) : CompileType::Int(); | 1138 return ValueFitsSmi() ? CompileType::FromCid(kSmiCid) : CompileType::Int(); |
1228 } | 1139 } |
1229 | 1140 |
1230 | |
1231 bool BoxIntegerInstr::RecomputeType() { | 1141 bool BoxIntegerInstr::RecomputeType() { |
1232 return UpdateType(ComputeType()); | 1142 return UpdateType(ComputeType()); |
1233 } | 1143 } |
1234 | 1144 |
1235 | |
1236 CompileType UnboxIntegerInstr::ComputeType() const { | 1145 CompileType UnboxIntegerInstr::ComputeType() const { |
1237 return CompileType::Int(); | 1146 return CompileType::Int(); |
1238 } | 1147 } |
1239 | 1148 |
1240 | |
1241 CompileType DoubleToIntegerInstr::ComputeType() const { | 1149 CompileType DoubleToIntegerInstr::ComputeType() const { |
1242 return CompileType::Int(); | 1150 return CompileType::Int(); |
1243 } | 1151 } |
1244 | 1152 |
1245 | |
1246 CompileType BinaryDoubleOpInstr::ComputeType() const { | 1153 CompileType BinaryDoubleOpInstr::ComputeType() const { |
1247 return CompileType::FromCid(kDoubleCid); | 1154 return CompileType::FromCid(kDoubleCid); |
1248 } | 1155 } |
1249 | 1156 |
1250 | |
1251 CompileType DoubleTestOpInstr::ComputeType() const { | 1157 CompileType DoubleTestOpInstr::ComputeType() const { |
1252 return CompileType::FromCid(kBoolCid); | 1158 return CompileType::FromCid(kBoolCid); |
1253 } | 1159 } |
1254 | 1160 |
1255 | |
1256 CompileType BinaryFloat32x4OpInstr::ComputeType() const { | 1161 CompileType BinaryFloat32x4OpInstr::ComputeType() const { |
1257 return CompileType::FromCid(kFloat32x4Cid); | 1162 return CompileType::FromCid(kFloat32x4Cid); |
1258 } | 1163 } |
1259 | 1164 |
1260 | |
1261 CompileType Simd32x4ShuffleInstr::ComputeType() const { | 1165 CompileType Simd32x4ShuffleInstr::ComputeType() const { |
1262 if ((op_kind() == MethodRecognizer::kFloat32x4ShuffleX) || | 1166 if ((op_kind() == MethodRecognizer::kFloat32x4ShuffleX) || |
1263 (op_kind() == MethodRecognizer::kFloat32x4ShuffleY) || | 1167 (op_kind() == MethodRecognizer::kFloat32x4ShuffleY) || |
1264 (op_kind() == MethodRecognizer::kFloat32x4ShuffleZ) || | 1168 (op_kind() == MethodRecognizer::kFloat32x4ShuffleZ) || |
1265 (op_kind() == MethodRecognizer::kFloat32x4ShuffleW)) { | 1169 (op_kind() == MethodRecognizer::kFloat32x4ShuffleW)) { |
1266 return CompileType::FromCid(kDoubleCid); | 1170 return CompileType::FromCid(kDoubleCid); |
1267 } | 1171 } |
1268 if ((op_kind() == MethodRecognizer::kInt32x4Shuffle)) { | 1172 if ((op_kind() == MethodRecognizer::kInt32x4Shuffle)) { |
1269 return CompileType::FromCid(kInt32x4Cid); | 1173 return CompileType::FromCid(kInt32x4Cid); |
1270 } | 1174 } |
1271 ASSERT((op_kind() == MethodRecognizer::kFloat32x4Shuffle)); | 1175 ASSERT((op_kind() == MethodRecognizer::kFloat32x4Shuffle)); |
1272 return CompileType::FromCid(kFloat32x4Cid); | 1176 return CompileType::FromCid(kFloat32x4Cid); |
1273 } | 1177 } |
1274 | 1178 |
1275 | |
1276 CompileType Simd32x4ShuffleMixInstr::ComputeType() const { | 1179 CompileType Simd32x4ShuffleMixInstr::ComputeType() const { |
1277 if (op_kind() == MethodRecognizer::kInt32x4ShuffleMix) { | 1180 if (op_kind() == MethodRecognizer::kInt32x4ShuffleMix) { |
1278 return CompileType::FromCid(kInt32x4Cid); | 1181 return CompileType::FromCid(kInt32x4Cid); |
1279 } | 1182 } |
1280 ASSERT((op_kind() == MethodRecognizer::kFloat32x4ShuffleMix)); | 1183 ASSERT((op_kind() == MethodRecognizer::kFloat32x4ShuffleMix)); |
1281 return CompileType::FromCid(kFloat32x4Cid); | 1184 return CompileType::FromCid(kFloat32x4Cid); |
1282 } | 1185 } |
1283 | 1186 |
1284 | |
1285 CompileType Simd32x4GetSignMaskInstr::ComputeType() const { | 1187 CompileType Simd32x4GetSignMaskInstr::ComputeType() const { |
1286 return CompileType::Int(); | 1188 return CompileType::Int(); |
1287 } | 1189 } |
1288 | 1190 |
1289 | |
1290 CompileType Float32x4ConstructorInstr::ComputeType() const { | 1191 CompileType Float32x4ConstructorInstr::ComputeType() const { |
1291 return CompileType::FromCid(kFloat32x4Cid); | 1192 return CompileType::FromCid(kFloat32x4Cid); |
1292 } | 1193 } |
1293 | 1194 |
1294 | |
1295 CompileType Float32x4ZeroInstr::ComputeType() const { | 1195 CompileType Float32x4ZeroInstr::ComputeType() const { |
1296 return CompileType::FromCid(kFloat32x4Cid); | 1196 return CompileType::FromCid(kFloat32x4Cid); |
1297 } | 1197 } |
1298 | 1198 |
1299 | |
1300 CompileType Float32x4SplatInstr::ComputeType() const { | 1199 CompileType Float32x4SplatInstr::ComputeType() const { |
1301 return CompileType::FromCid(kFloat32x4Cid); | 1200 return CompileType::FromCid(kFloat32x4Cid); |
1302 } | 1201 } |
1303 | 1202 |
1304 | |
1305 CompileType Float32x4ComparisonInstr::ComputeType() const { | 1203 CompileType Float32x4ComparisonInstr::ComputeType() const { |
1306 return CompileType::FromCid(kInt32x4Cid); | 1204 return CompileType::FromCid(kInt32x4Cid); |
1307 } | 1205 } |
1308 | 1206 |
1309 | |
1310 CompileType Float32x4MinMaxInstr::ComputeType() const { | 1207 CompileType Float32x4MinMaxInstr::ComputeType() const { |
1311 return CompileType::FromCid(kFloat32x4Cid); | 1208 return CompileType::FromCid(kFloat32x4Cid); |
1312 } | 1209 } |
1313 | 1210 |
1314 | |
1315 CompileType Float32x4ScaleInstr::ComputeType() const { | 1211 CompileType Float32x4ScaleInstr::ComputeType() const { |
1316 return CompileType::FromCid(kFloat32x4Cid); | 1212 return CompileType::FromCid(kFloat32x4Cid); |
1317 } | 1213 } |
1318 | 1214 |
1319 | |
1320 CompileType Float32x4SqrtInstr::ComputeType() const { | 1215 CompileType Float32x4SqrtInstr::ComputeType() const { |
1321 return CompileType::FromCid(kFloat32x4Cid); | 1216 return CompileType::FromCid(kFloat32x4Cid); |
1322 } | 1217 } |
1323 | 1218 |
1324 | |
1325 CompileType Float32x4ZeroArgInstr::ComputeType() const { | 1219 CompileType Float32x4ZeroArgInstr::ComputeType() const { |
1326 return CompileType::FromCid(kFloat32x4Cid); | 1220 return CompileType::FromCid(kFloat32x4Cid); |
1327 } | 1221 } |
1328 | 1222 |
1329 | |
1330 CompileType Float32x4ClampInstr::ComputeType() const { | 1223 CompileType Float32x4ClampInstr::ComputeType() const { |
1331 return CompileType::FromCid(kFloat32x4Cid); | 1224 return CompileType::FromCid(kFloat32x4Cid); |
1332 } | 1225 } |
1333 | 1226 |
1334 | |
1335 CompileType Float32x4WithInstr::ComputeType() const { | 1227 CompileType Float32x4WithInstr::ComputeType() const { |
1336 return CompileType::FromCid(kFloat32x4Cid); | 1228 return CompileType::FromCid(kFloat32x4Cid); |
1337 } | 1229 } |
1338 | 1230 |
1339 | |
1340 CompileType Float32x4ToInt32x4Instr::ComputeType() const { | 1231 CompileType Float32x4ToInt32x4Instr::ComputeType() const { |
1341 return CompileType::FromCid(kInt32x4Cid); | 1232 return CompileType::FromCid(kInt32x4Cid); |
1342 } | 1233 } |
1343 | 1234 |
1344 | |
1345 CompileType Simd64x2ShuffleInstr::ComputeType() const { | 1235 CompileType Simd64x2ShuffleInstr::ComputeType() const { |
1346 if ((op_kind() == MethodRecognizer::kFloat64x2GetX) || | 1236 if ((op_kind() == MethodRecognizer::kFloat64x2GetX) || |
1347 (op_kind() == MethodRecognizer::kFloat64x2GetY)) { | 1237 (op_kind() == MethodRecognizer::kFloat64x2GetY)) { |
1348 return CompileType::FromCid(kDoubleCid); | 1238 return CompileType::FromCid(kDoubleCid); |
1349 } | 1239 } |
1350 UNREACHABLE(); | 1240 UNREACHABLE(); |
1351 return CompileType::FromCid(kDoubleCid); | 1241 return CompileType::FromCid(kDoubleCid); |
1352 } | 1242 } |
1353 | 1243 |
1354 | |
1355 CompileType Float64x2ZeroInstr::ComputeType() const { | 1244 CompileType Float64x2ZeroInstr::ComputeType() const { |
1356 return CompileType::FromCid(kFloat64x2Cid); | 1245 return CompileType::FromCid(kFloat64x2Cid); |
1357 } | 1246 } |
1358 | 1247 |
1359 | |
1360 CompileType Float64x2SplatInstr::ComputeType() const { | 1248 CompileType Float64x2SplatInstr::ComputeType() const { |
1361 return CompileType::FromCid(kFloat64x2Cid); | 1249 return CompileType::FromCid(kFloat64x2Cid); |
1362 } | 1250 } |
1363 | 1251 |
1364 | |
1365 CompileType Float64x2ConstructorInstr::ComputeType() const { | 1252 CompileType Float64x2ConstructorInstr::ComputeType() const { |
1366 return CompileType::FromCid(kFloat64x2Cid); | 1253 return CompileType::FromCid(kFloat64x2Cid); |
1367 } | 1254 } |
1368 | 1255 |
1369 | |
1370 CompileType Float32x4ToFloat64x2Instr::ComputeType() const { | 1256 CompileType Float32x4ToFloat64x2Instr::ComputeType() const { |
1371 return CompileType::FromCid(kFloat64x2Cid); | 1257 return CompileType::FromCid(kFloat64x2Cid); |
1372 } | 1258 } |
1373 | 1259 |
1374 | |
1375 CompileType Float64x2ToFloat32x4Instr::ComputeType() const { | 1260 CompileType Float64x2ToFloat32x4Instr::ComputeType() const { |
1376 return CompileType::FromCid(kFloat32x4Cid); | 1261 return CompileType::FromCid(kFloat32x4Cid); |
1377 } | 1262 } |
1378 | 1263 |
1379 | |
1380 CompileType Float64x2ZeroArgInstr::ComputeType() const { | 1264 CompileType Float64x2ZeroArgInstr::ComputeType() const { |
1381 if (op_kind() == MethodRecognizer::kFloat64x2GetSignMask) { | 1265 if (op_kind() == MethodRecognizer::kFloat64x2GetSignMask) { |
1382 return CompileType::Int(); | 1266 return CompileType::Int(); |
1383 } | 1267 } |
1384 return CompileType::FromCid(kFloat64x2Cid); | 1268 return CompileType::FromCid(kFloat64x2Cid); |
1385 } | 1269 } |
1386 | 1270 |
1387 | |
1388 CompileType Float64x2OneArgInstr::ComputeType() const { | 1271 CompileType Float64x2OneArgInstr::ComputeType() const { |
1389 return CompileType::FromCid(kFloat64x2Cid); | 1272 return CompileType::FromCid(kFloat64x2Cid); |
1390 } | 1273 } |
1391 | 1274 |
1392 | |
1393 CompileType Int32x4ConstructorInstr::ComputeType() const { | 1275 CompileType Int32x4ConstructorInstr::ComputeType() const { |
1394 return CompileType::FromCid(kInt32x4Cid); | 1276 return CompileType::FromCid(kInt32x4Cid); |
1395 } | 1277 } |
1396 | 1278 |
1397 | |
1398 CompileType Int32x4BoolConstructorInstr::ComputeType() const { | 1279 CompileType Int32x4BoolConstructorInstr::ComputeType() const { |
1399 return CompileType::FromCid(kInt32x4Cid); | 1280 return CompileType::FromCid(kInt32x4Cid); |
1400 } | 1281 } |
1401 | 1282 |
1402 | |
1403 CompileType Int32x4GetFlagInstr::ComputeType() const { | 1283 CompileType Int32x4GetFlagInstr::ComputeType() const { |
1404 return CompileType::FromCid(kBoolCid); | 1284 return CompileType::FromCid(kBoolCid); |
1405 } | 1285 } |
1406 | 1286 |
1407 | |
1408 CompileType Int32x4SelectInstr::ComputeType() const { | 1287 CompileType Int32x4SelectInstr::ComputeType() const { |
1409 return CompileType::FromCid(kFloat32x4Cid); | 1288 return CompileType::FromCid(kFloat32x4Cid); |
1410 } | 1289 } |
1411 | 1290 |
1412 | |
1413 CompileType Int32x4SetFlagInstr::ComputeType() const { | 1291 CompileType Int32x4SetFlagInstr::ComputeType() const { |
1414 return CompileType::FromCid(kInt32x4Cid); | 1292 return CompileType::FromCid(kInt32x4Cid); |
1415 } | 1293 } |
1416 | 1294 |
1417 | |
1418 CompileType Int32x4ToFloat32x4Instr::ComputeType() const { | 1295 CompileType Int32x4ToFloat32x4Instr::ComputeType() const { |
1419 return CompileType::FromCid(kFloat32x4Cid); | 1296 return CompileType::FromCid(kFloat32x4Cid); |
1420 } | 1297 } |
1421 | 1298 |
1422 | |
1423 CompileType BinaryInt32x4OpInstr::ComputeType() const { | 1299 CompileType BinaryInt32x4OpInstr::ComputeType() const { |
1424 return CompileType::FromCid(kInt32x4Cid); | 1300 return CompileType::FromCid(kInt32x4Cid); |
1425 } | 1301 } |
1426 | 1302 |
1427 | |
1428 CompileType BinaryFloat64x2OpInstr::ComputeType() const { | 1303 CompileType BinaryFloat64x2OpInstr::ComputeType() const { |
1429 return CompileType::FromCid(kFloat64x2Cid); | 1304 return CompileType::FromCid(kFloat64x2Cid); |
1430 } | 1305 } |
1431 | 1306 |
1432 | |
1433 CompileType MathUnaryInstr::ComputeType() const { | 1307 CompileType MathUnaryInstr::ComputeType() const { |
1434 return CompileType::FromCid(kDoubleCid); | 1308 return CompileType::FromCid(kDoubleCid); |
1435 } | 1309 } |
1436 | 1310 |
1437 | |
1438 CompileType MathMinMaxInstr::ComputeType() const { | 1311 CompileType MathMinMaxInstr::ComputeType() const { |
1439 return CompileType::FromCid(result_cid_); | 1312 return CompileType::FromCid(result_cid_); |
1440 } | 1313 } |
1441 | 1314 |
1442 | |
1443 CompileType CaseInsensitiveCompareUC16Instr::ComputeType() const { | 1315 CompileType CaseInsensitiveCompareUC16Instr::ComputeType() const { |
1444 return CompileType::FromCid(kBoolCid); | 1316 return CompileType::FromCid(kBoolCid); |
1445 } | 1317 } |
1446 | 1318 |
1447 | |
1448 CompileType UnboxInstr::ComputeType() const { | 1319 CompileType UnboxInstr::ComputeType() const { |
1449 switch (representation()) { | 1320 switch (representation()) { |
1450 case kUnboxedDouble: | 1321 case kUnboxedDouble: |
1451 return CompileType::FromCid(kDoubleCid); | 1322 return CompileType::FromCid(kDoubleCid); |
1452 | 1323 |
1453 case kUnboxedFloat32x4: | 1324 case kUnboxedFloat32x4: |
1454 return CompileType::FromCid(kFloat32x4Cid); | 1325 return CompileType::FromCid(kFloat32x4Cid); |
1455 | 1326 |
1456 case kUnboxedFloat64x2: | 1327 case kUnboxedFloat64x2: |
1457 return CompileType::FromCid(kFloat64x2Cid); | 1328 return CompileType::FromCid(kFloat64x2Cid); |
1458 | 1329 |
1459 case kUnboxedInt32x4: | 1330 case kUnboxedInt32x4: |
1460 return CompileType::FromCid(kInt32x4Cid); | 1331 return CompileType::FromCid(kInt32x4Cid); |
1461 | 1332 |
1462 case kUnboxedMint: | 1333 case kUnboxedMint: |
1463 return CompileType::Int(); | 1334 return CompileType::Int(); |
1464 | 1335 |
1465 default: | 1336 default: |
1466 UNREACHABLE(); | 1337 UNREACHABLE(); |
1467 return CompileType::Dynamic(); | 1338 return CompileType::Dynamic(); |
1468 } | 1339 } |
1469 } | 1340 } |
1470 | 1341 |
1471 | |
1472 CompileType BoxInstr::ComputeType() const { | 1342 CompileType BoxInstr::ComputeType() const { |
1473 switch (from_representation()) { | 1343 switch (from_representation()) { |
1474 case kUnboxedDouble: | 1344 case kUnboxedDouble: |
1475 return CompileType::FromCid(kDoubleCid); | 1345 return CompileType::FromCid(kDoubleCid); |
1476 | 1346 |
1477 case kUnboxedFloat32x4: | 1347 case kUnboxedFloat32x4: |
1478 return CompileType::FromCid(kFloat32x4Cid); | 1348 return CompileType::FromCid(kFloat32x4Cid); |
1479 | 1349 |
1480 case kUnboxedFloat64x2: | 1350 case kUnboxedFloat64x2: |
1481 return CompileType::FromCid(kFloat64x2Cid); | 1351 return CompileType::FromCid(kFloat64x2Cid); |
1482 | 1352 |
1483 case kUnboxedInt32x4: | 1353 case kUnboxedInt32x4: |
1484 return CompileType::FromCid(kInt32x4Cid); | 1354 return CompileType::FromCid(kInt32x4Cid); |
1485 | 1355 |
1486 default: | 1356 default: |
1487 UNREACHABLE(); | 1357 UNREACHABLE(); |
1488 return CompileType::Dynamic(); | 1358 return CompileType::Dynamic(); |
1489 } | 1359 } |
1490 } | 1360 } |
1491 | 1361 |
1492 | |
1493 CompileType Int32ToDoubleInstr::ComputeType() const { | 1362 CompileType Int32ToDoubleInstr::ComputeType() const { |
1494 return CompileType::FromCid(kDoubleCid); | 1363 return CompileType::FromCid(kDoubleCid); |
1495 } | 1364 } |
1496 | 1365 |
1497 | |
1498 CompileType SmiToDoubleInstr::ComputeType() const { | 1366 CompileType SmiToDoubleInstr::ComputeType() const { |
1499 return CompileType::FromCid(kDoubleCid); | 1367 return CompileType::FromCid(kDoubleCid); |
1500 } | 1368 } |
1501 | 1369 |
1502 | |
1503 CompileType MintToDoubleInstr::ComputeType() const { | 1370 CompileType MintToDoubleInstr::ComputeType() const { |
1504 return CompileType::FromCid(kDoubleCid); | 1371 return CompileType::FromCid(kDoubleCid); |
1505 } | 1372 } |
1506 | 1373 |
1507 | |
1508 CompileType DoubleToDoubleInstr::ComputeType() const { | 1374 CompileType DoubleToDoubleInstr::ComputeType() const { |
1509 return CompileType::FromCid(kDoubleCid); | 1375 return CompileType::FromCid(kDoubleCid); |
1510 } | 1376 } |
1511 | 1377 |
1512 | |
1513 CompileType FloatToDoubleInstr::ComputeType() const { | 1378 CompileType FloatToDoubleInstr::ComputeType() const { |
1514 return CompileType::FromCid(kDoubleCid); | 1379 return CompileType::FromCid(kDoubleCid); |
1515 } | 1380 } |
1516 | 1381 |
1517 | |
1518 CompileType DoubleToFloatInstr::ComputeType() const { | 1382 CompileType DoubleToFloatInstr::ComputeType() const { |
1519 // Type is double when converted back. | 1383 // Type is double when converted back. |
1520 return CompileType::FromCid(kDoubleCid); | 1384 return CompileType::FromCid(kDoubleCid); |
1521 } | 1385 } |
1522 | 1386 |
1523 | |
1524 CompileType InvokeMathCFunctionInstr::ComputeType() const { | 1387 CompileType InvokeMathCFunctionInstr::ComputeType() const { |
1525 return CompileType::FromCid(kDoubleCid); | 1388 return CompileType::FromCid(kDoubleCid); |
1526 } | 1389 } |
1527 | 1390 |
1528 | |
1529 CompileType TruncDivModInstr::ComputeType() const { | 1391 CompileType TruncDivModInstr::ComputeType() const { |
1530 return CompileType::Dynamic(); | 1392 return CompileType::Dynamic(); |
1531 } | 1393 } |
1532 | 1394 |
1533 | |
1534 CompileType ExtractNthOutputInstr::ComputeType() const { | 1395 CompileType ExtractNthOutputInstr::ComputeType() const { |
1535 return CompileType::FromCid(definition_cid_); | 1396 return CompileType::FromCid(definition_cid_); |
1536 } | 1397 } |
1537 | 1398 |
1538 } // namespace dart | 1399 } // namespace dart |
OLD | NEW |