| 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 |