| 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_optimizer.h" | 5 #include "vm/flow_graph_optimizer.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
| 9 #include "vm/flow_graph_builder.h" | 9 #include "vm/flow_graph_builder.h" |
| 10 #include "vm/flow_graph_compiler.h" | 10 #include "vm/flow_graph_compiler.h" |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 OS::Print("Removing %s\n", current->DebugName()); | 295 OS::Print("Removing %s\n", current->DebugName()); |
| 296 } else { | 296 } else { |
| 297 ASSERT(!current_defn->HasUses()); | 297 ASSERT(!current_defn->HasUses()); |
| 298 OS::Print("Removing v%"Pd".\n", current_defn->ssa_temp_index()); | 298 OS::Print("Removing v%"Pd".\n", current_defn->ssa_temp_index()); |
| 299 } | 299 } |
| 300 } | 300 } |
| 301 iterator->RemoveCurrentFromGraph(); | 301 iterator->RemoveCurrentFromGraph(); |
| 302 } | 302 } |
| 303 | 303 |
| 304 | 304 |
| 305 void FlowGraphOptimizer::Canonicalize() { | 305 bool FlowGraphOptimizer::Canonicalize() { |
| 306 bool changed = false; |
| 306 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 307 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| 307 BlockEntryInstr* entry = block_order_[i]; | 308 BlockEntryInstr* entry = block_order_[i]; |
| 308 entry->Accept(this); | 309 entry->Accept(this); |
| 309 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { | 310 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { |
| 310 Instruction* current = it.Current(); | 311 Instruction* current = it.Current(); |
| 311 Instruction* replacement = current->Canonicalize(this); | 312 Instruction* replacement = current->Canonicalize(this); |
| 312 if (replacement != current) { | 313 if (replacement != current) { |
| 313 // For non-definitions Canonicalize should return either NULL or | 314 // For non-definitions Canonicalize should return either NULL or |
| 314 // this. | 315 // this. |
| 315 ASSERT((replacement == NULL) || current->IsDefinition()); | 316 ASSERT((replacement == NULL) || current->IsDefinition()); |
| 316 ReplaceCurrentInstruction(&it, current, replacement, flow_graph_); | 317 ReplaceCurrentInstruction(&it, current, replacement, flow_graph_); |
| 318 changed = true; |
| 317 } | 319 } |
| 318 } | 320 } |
| 319 } | 321 } |
| 322 return changed; |
| 320 } | 323 } |
| 321 | 324 |
| 322 | 325 |
| 323 void FlowGraphOptimizer::InsertConversion(Representation from, | 326 void FlowGraphOptimizer::InsertConversion(Representation from, |
| 324 Representation to, | 327 Representation to, |
| 325 Value* use, | 328 Value* use, |
| 326 Instruction* insert_before, | 329 Instruction* insert_before, |
| 327 Instruction* deopt_target) { | 330 Instruction* deopt_target) { |
| 328 Definition* converted = NULL; | 331 Definition* converted = NULL; |
| 329 if ((from == kTagged) && (to == kUnboxedMint)) { | 332 if ((from == kTagged) && (to == kUnboxedMint)) { |
| (...skipping 903 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1233 callee_receiver->IsParameter() && | 1236 callee_receiver->IsParameter() && |
| 1234 (callee_receiver->AsParameter()->index() == 0)) { | 1237 (callee_receiver->AsParameter()->index() == 0)) { |
| 1235 const String& field_name = | 1238 const String& field_name = |
| 1236 String::Handle(Field::NameFromGetter(call->function_name())); | 1239 String::Handle(Field::NameFromGetter(call->function_name())); |
| 1237 return CHA::HasOverride(Class::Handle(function.Owner()), field_name); | 1240 return CHA::HasOverride(Class::Handle(function.Owner()), field_name); |
| 1238 } | 1241 } |
| 1239 return true; | 1242 return true; |
| 1240 } | 1243 } |
| 1241 | 1244 |
| 1242 | 1245 |
| 1243 void FlowGraphOptimizer::AddToGuardedFields(Field* field) { | 1246 void FlowGraphOptimizer::AddToGuardedFields(const Field& field) { |
| 1244 if ((field->guarded_cid() == kDynamicCid) || | 1247 if ((field.guarded_cid() == kDynamicCid) || |
| 1245 (field->guarded_cid() == kIllegalCid)) { | 1248 (field.guarded_cid() == kIllegalCid)) { |
| 1246 return; | 1249 return; |
| 1247 } | 1250 } |
| 1248 for (intptr_t j = 0; j < guarded_fields_->length(); j++) { | 1251 for (intptr_t j = 0; j < guarded_fields_->length(); j++) { |
| 1249 if ((*guarded_fields_)[j]->raw() == field->raw()) { | 1252 if ((*guarded_fields_)[j]->raw() == field.raw()) { |
| 1250 return; | 1253 return; |
| 1251 } | 1254 } |
| 1252 } | 1255 } |
| 1253 guarded_fields_->Add(field); | 1256 guarded_fields_->Add(&field); |
| 1254 } | 1257 } |
| 1255 | 1258 |
| 1256 | 1259 |
| 1257 void FlowGraphOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call) { | 1260 void FlowGraphOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call) { |
| 1258 ASSERT(call->HasICData()); | 1261 ASSERT(call->HasICData()); |
| 1259 const ICData& ic_data = *call->ic_data(); | 1262 const ICData& ic_data = *call->ic_data(); |
| 1260 Function& target = Function::Handle(); | 1263 Function& target = Function::Handle(); |
| 1261 GrowableArray<intptr_t> class_ids; | 1264 GrowableArray<intptr_t> class_ids; |
| 1262 ic_data.GetCheckAt(0, &class_ids, &target); | 1265 ic_data.GetCheckAt(0, &class_ids, &target); |
| 1263 ASSERT(class_ids.length() == 1); | 1266 ASSERT(class_ids.length() == 1); |
| 1264 // Inline implicit instance getter. | 1267 // Inline implicit instance getter. |
| 1265 const String& field_name = | 1268 const String& field_name = |
| 1266 String::Handle(Field::NameFromGetter(call->function_name())); | 1269 String::Handle(Field::NameFromGetter(call->function_name())); |
| 1267 const Field& field = Field::Handle(GetField(class_ids[0], field_name)); | 1270 const Field& field = Field::ZoneHandle(GetField(class_ids[0], field_name)); |
| 1268 ASSERT(!field.IsNull()); | 1271 ASSERT(!field.IsNull()); |
| 1269 | 1272 |
| 1270 if (InstanceCallNeedsClassCheck(call)) { | 1273 if (InstanceCallNeedsClassCheck(call)) { |
| 1271 AddReceiverCheck(call); | 1274 AddReceiverCheck(call); |
| 1272 } | 1275 } |
| 1273 LoadFieldInstr* load = new LoadFieldInstr( | 1276 LoadFieldInstr* load = new LoadFieldInstr( |
| 1274 new Value(call->ArgumentAt(0)), | 1277 new Value(call->ArgumentAt(0)), |
| 1275 field.Offset(), | 1278 field.Offset(), |
| 1276 AbstractType::ZoneHandle(field.type()), | 1279 AbstractType::ZoneHandle(field.type()), |
| 1277 field.is_final()); | 1280 field.is_final()); |
| 1281 load->set_field(&field); |
| 1278 if (field.guarded_cid() != kIllegalCid) { | 1282 if (field.guarded_cid() != kIllegalCid) { |
| 1279 if (!field.is_nullable() || (field.guarded_cid() == kNullCid)) { | 1283 if (!field.is_nullable() || (field.guarded_cid() == kNullCid)) { |
| 1280 load->set_result_cid(field.guarded_cid()); | 1284 load->set_result_cid(field.guarded_cid()); |
| 1281 } | 1285 } |
| 1282 Field* the_field = &Field::ZoneHandle(field.raw()); | 1286 AddToGuardedFields(field); |
| 1283 load->set_field(the_field); | |
| 1284 AddToGuardedFields(the_field); | |
| 1285 } | 1287 } |
| 1286 load->set_field_name(String::Handle(field.name()).ToCString()); | 1288 load->set_field_name(String::Handle(field.name()).ToCString()); |
| 1287 | 1289 |
| 1288 // Discard the environment from the original instruction because the load | 1290 // Discard the environment from the original instruction because the load |
| 1289 // can't deoptimize. | 1291 // can't deoptimize. |
| 1290 call->RemoveEnvironment(); | 1292 call->RemoveEnvironment(); |
| 1291 ReplaceCall(call, load); | 1293 ReplaceCall(call, load); |
| 1292 | 1294 |
| 1293 if (load->result_cid() != kDynamicCid) { | 1295 if (load->result_cid() != kDynamicCid) { |
| 1294 // Reset value types if guarded_cid was used. | 1296 // Reset value types if guarded_cid was used. |
| (...skipping 1988 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3283 public: | 3285 public: |
| 3284 Alias(const Alias& other) : ValueObject(), alias_(other.alias_) { } | 3286 Alias(const Alias& other) : ValueObject(), alias_(other.alias_) { } |
| 3285 | 3287 |
| 3286 // All indexed load/stores alias each other. | 3288 // All indexed load/stores alias each other. |
| 3287 // TODO(vegorov): incorporate type of array into alias to disambiguate | 3289 // TODO(vegorov): incorporate type of array into alias to disambiguate |
| 3288 // different typed data and normal arrays. | 3290 // different typed data and normal arrays. |
| 3289 static Alias Indexes() { | 3291 static Alias Indexes() { |
| 3290 return Alias(kIndexesAlias); | 3292 return Alias(kIndexesAlias); |
| 3291 } | 3293 } |
| 3292 | 3294 |
| 3293 // Field load/stores alias each other when field offset matches. | 3295 // Field load/stores alias each other only when they access the same field. |
| 3294 // TODO(vegorov): use field information to disambiguate load/stores into | 3296 // AliasedSet assigns ids to a combination of instance and field during |
| 3295 // different fields that by accident share offset. | 3297 // the optimization phase. |
| 3296 static Alias Field(intptr_t offset_in_bytes) { | 3298 static Alias Field(intptr_t id) { |
| 3299 ASSERT(id >= kFirstFieldAlias); |
| 3300 return Alias(id * 2 + 1); |
| 3301 } |
| 3302 |
| 3303 // VMField load/stores alias each other when field offset matches. |
| 3304 // TODO(vegorov) storing a context variable does not alias loading array |
| 3305 // length. |
| 3306 static Alias VMField(intptr_t offset_in_bytes) { |
| 3297 const intptr_t idx = offset_in_bytes / kWordSize; | 3307 const intptr_t idx = offset_in_bytes / kWordSize; |
| 3298 ASSERT(idx >= kFirstFieldAlias); | 3308 ASSERT(idx >= kFirstFieldAlias); |
| 3299 return Alias(idx * 2); | 3309 return Alias(idx * 2); |
| 3300 } | 3310 } |
| 3301 | 3311 |
| 3302 // Static field load/stores alias each other. | |
| 3303 // AliasedSet assigns ids to static fields during optimization phase. | |
| 3304 static Alias StaticField(intptr_t id) { | |
| 3305 ASSERT(id >= kFirstFieldAlias); | |
| 3306 return Alias(id * 2 + 1); | |
| 3307 } | |
| 3308 | |
| 3309 // Current context load/stores alias each other. | 3312 // Current context load/stores alias each other. |
| 3310 static Alias CurrentContext() { | 3313 static Alias CurrentContext() { |
| 3311 return Alias(kCurrentContextAlias); | 3314 return Alias(kCurrentContextAlias); |
| 3312 } | 3315 } |
| 3313 | 3316 |
| 3314 // Operation does not alias anything. | 3317 // Operation does not alias anything. |
| 3315 static Alias None() { | 3318 static Alias None() { |
| 3316 return Alias(kNoneAlias); | 3319 return Alias(kNoneAlias); |
| 3317 } | 3320 } |
| 3318 | 3321 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3351 max_field_id_(0) { } | 3354 max_field_id_(0) { } |
| 3352 | 3355 |
| 3353 Alias ComputeAliasForLoad(Definition* defn) { | 3356 Alias ComputeAliasForLoad(Definition* defn) { |
| 3354 if (defn->IsLoadIndexed()) { | 3357 if (defn->IsLoadIndexed()) { |
| 3355 // We are assuming that LoadField is never used to load the first word. | 3358 // We are assuming that LoadField is never used to load the first word. |
| 3356 return Alias::Indexes(); | 3359 return Alias::Indexes(); |
| 3357 } | 3360 } |
| 3358 | 3361 |
| 3359 LoadFieldInstr* load_field = defn->AsLoadField(); | 3362 LoadFieldInstr* load_field = defn->AsLoadField(); |
| 3360 if (load_field != NULL) { | 3363 if (load_field != NULL) { |
| 3361 return Alias::Field(load_field->offset_in_bytes()); | 3364 if (load_field->field() != NULL) { |
| 3365 Definition* instance = load_field->instance()->definition(); |
| 3366 return Alias::Field(GetInstanceFieldId(instance, *load_field->field())); |
| 3367 } else { |
| 3368 return Alias::VMField(load_field->offset_in_bytes()); |
| 3369 } |
| 3362 } | 3370 } |
| 3363 | 3371 |
| 3364 if (defn->IsCurrentContext()) { | 3372 if (defn->IsCurrentContext()) { |
| 3365 return Alias::CurrentContext(); | 3373 return Alias::CurrentContext(); |
| 3366 } | 3374 } |
| 3367 | 3375 |
| 3368 LoadStaticFieldInstr* load_static_field = defn->AsLoadStaticField(); | 3376 LoadStaticFieldInstr* load_static_field = defn->AsLoadStaticField(); |
| 3369 if (load_static_field != NULL) { | 3377 if (load_static_field != NULL) { |
| 3370 return Alias::StaticField(GetFieldId(load_static_field->field())); | 3378 return Alias::Field(GetFieldId(kAnyInstance, load_static_field->field())); |
| 3371 } | 3379 } |
| 3372 | 3380 |
| 3373 UNREACHABLE(); | 3381 UNREACHABLE(); |
| 3374 return Alias::None(); | 3382 return Alias::None(); |
| 3375 } | 3383 } |
| 3376 | 3384 |
| 3377 Alias ComputeAliasForStore(Instruction* instr) { | 3385 Alias ComputeAliasForStore(Instruction* instr) { |
| 3378 if (instr->IsStoreIndexed()) { | 3386 if (instr->IsStoreIndexed()) { |
| 3379 return Alias::Indexes(); | 3387 return Alias::Indexes(); |
| 3380 } | 3388 } |
| 3381 | 3389 |
| 3382 StoreInstanceFieldInstr* store_instance_field = | 3390 StoreInstanceFieldInstr* store_instance_field = |
| 3383 instr->AsStoreInstanceField(); | 3391 instr->AsStoreInstanceField(); |
| 3384 if (store_instance_field != NULL) { | 3392 if (store_instance_field != NULL) { |
| 3385 return Alias::Field(store_instance_field->field().Offset()); | 3393 Definition* instance = store_instance_field->instance()->definition(); |
| 3394 return Alias::Field(GetInstanceFieldId(instance, |
| 3395 store_instance_field->field())); |
| 3386 } | 3396 } |
| 3387 | 3397 |
| 3388 StoreVMFieldInstr* store_vm_field = instr->AsStoreVMField(); | 3398 StoreVMFieldInstr* store_vm_field = instr->AsStoreVMField(); |
| 3389 if (store_vm_field != NULL) { | 3399 if (store_vm_field != NULL) { |
| 3390 return Alias::Field(store_vm_field->offset_in_bytes()); | 3400 return Alias::VMField(store_vm_field->offset_in_bytes()); |
| 3391 } | 3401 } |
| 3392 | 3402 |
| 3393 if (instr->IsStoreContext() || instr->IsChainContext()) { | 3403 if (instr->IsStoreContext() || instr->IsChainContext()) { |
| 3394 return Alias::CurrentContext(); | 3404 return Alias::CurrentContext(); |
| 3395 } | 3405 } |
| 3396 | 3406 |
| 3397 StoreStaticFieldInstr* store_static_field = instr->AsStoreStaticField(); | 3407 StoreStaticFieldInstr* store_static_field = instr->AsStoreStaticField(); |
| 3398 if (store_static_field != NULL) { | 3408 if (store_static_field != NULL) { |
| 3399 return Alias::StaticField(GetFieldId(store_static_field->field())); | 3409 return Alias::Field(GetStaticFieldId(store_static_field->field())); |
| 3400 } | 3410 } |
| 3401 | 3411 |
| 3402 return Alias::None(); | 3412 return Alias::None(); |
| 3403 } | 3413 } |
| 3404 | 3414 |
| 3405 bool Contains(const Alias alias) { | 3415 bool Contains(const Alias alias) { |
| 3406 const intptr_t idx = alias.ToIndex(); | 3416 const intptr_t idx = alias.ToIndex(); |
| 3407 return (idx < sets_.length()) && (sets_[idx] != NULL); | 3417 return (idx < sets_.length()) && (sets_[idx] != NULL); |
| 3408 } | 3418 } |
| 3409 | 3419 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 3431 | 3441 |
| 3432 private: | 3442 private: |
| 3433 const intptr_t max_expr_id_; | 3443 const intptr_t max_expr_id_; |
| 3434 | 3444 |
| 3435 // Maps alias index to a set of ssa indexes corresponding to loads with the | 3445 // Maps alias index to a set of ssa indexes corresponding to loads with the |
| 3436 // given alias. | 3446 // given alias. |
| 3437 GrowableArray<BitVector*> sets_; | 3447 GrowableArray<BitVector*> sets_; |
| 3438 | 3448 |
| 3439 // Get id assigned to the given field. Assign a new id if the field is seen | 3449 // Get id assigned to the given field. Assign a new id if the field is seen |
| 3440 // for the first time. | 3450 // for the first time. |
| 3441 intptr_t GetFieldId(const Field& field) { | 3451 intptr_t GetFieldId(intptr_t instance_id, const Field& field) { |
| 3442 intptr_t id = field_ids_.Lookup(&field); | 3452 intptr_t id = field_ids_.Lookup(FieldIdPair::Key(instance_id, &field)); |
| 3443 if (id == 0) { | 3453 if (id == 0) { |
| 3444 id = ++max_field_id_; | 3454 id = ++max_field_id_; |
| 3445 field_ids_.Insert(FieldIdPair(&field, id)); | 3455 field_ids_.Insert(FieldIdPair(FieldIdPair::Key(instance_id, &field), id)); |
| 3446 } | 3456 } |
| 3447 return id; | 3457 return id; |
| 3448 } | 3458 } |
| 3449 | 3459 |
| 3460 enum { |
| 3461 kAnyInstance = -1 |
| 3462 }; |
| 3463 |
| 3464 // Get or create an identifier for an instance field belonging to the |
| 3465 // given instance. |
| 3466 // The space of identifiers assigned to instance fields is split into |
| 3467 // parts based on the instance that contains the field. |
| 3468 // If compiler can prove that instance has a single SSA name in the compiled |
| 3469 // function then we use that SSA name to distinguish fields of this object |
| 3470 // from the same fields in other objects. |
| 3471 // If multiple SSA names can point to the same object then we use |
| 3472 // kAnyInstance instead of a concrete SSA name. |
| 3473 intptr_t GetInstanceFieldId(Definition* defn, const Field& field) { |
| 3474 ASSERT(!field.is_static()); |
| 3475 |
| 3476 intptr_t instance_id = kAnyInstance; |
| 3477 |
| 3478 AllocateObjectInstr* alloc = defn->AsAllocateObject(); |
| 3479 if ((alloc != NULL) && !CanBeAliased(alloc)) { |
| 3480 instance_id = alloc->ssa_temp_index(); |
| 3481 ASSERT(instance_id != kAnyInstance); |
| 3482 } |
| 3483 |
| 3484 return GetFieldId(instance_id, field); |
| 3485 } |
| 3486 |
| 3487 // Get or create an identifier for a static field. |
| 3488 intptr_t GetStaticFieldId(const Field& field) { |
| 3489 ASSERT(field.is_static()); |
| 3490 return GetFieldId(kAnyInstance, field); |
| 3491 } |
| 3492 |
| 3493 // Returns true if the result of AllocateObject can be aliased by some |
| 3494 // other SSA variable and false otherwise. Currently simply checks if |
| 3495 // this value is stored in a field, escapes to another function or |
| 3496 // participates in a phi. |
| 3497 bool CanBeAliased(AllocateObjectInstr* alloc) { |
| 3498 if (alloc->identity() == AllocateObjectInstr::kUnknown) { |
| 3499 bool escapes = false; |
| 3500 for (Value* use = alloc->input_use_list(); |
| 3501 use != NULL; |
| 3502 use = use->next_use()) { |
| 3503 Instruction* instr = use->instruction(); |
| 3504 if (instr->IsPushArgument() || |
| 3505 (instr->IsStoreVMField() && (use->use_index() != 0)) || |
| 3506 (instr->IsStoreInstanceField() && (use->use_index() != 0)) || |
| 3507 (instr->IsStoreStaticField()) || |
| 3508 (instr->IsPhi())) { |
| 3509 escapes = true; |
| 3510 break; |
| 3511 } |
| 3512 |
| 3513 alloc->set_identity(escapes ? AllocateObjectInstr::kAliased |
| 3514 : AllocateObjectInstr::kNotAliased); |
| 3515 } |
| 3516 } |
| 3517 |
| 3518 return alloc->identity() != AllocateObjectInstr::kNotAliased; |
| 3519 } |
| 3520 |
| 3450 class FieldIdPair { | 3521 class FieldIdPair { |
| 3451 public: | 3522 public: |
| 3452 typedef const Field* Key; | 3523 struct Key { |
| 3524 Key(intptr_t instance_id, const Field* field) |
| 3525 : instance_id_(instance_id), field_(field) { } |
| 3526 |
| 3527 intptr_t instance_id_; |
| 3528 const Field* field_; |
| 3529 }; |
| 3530 |
| 3453 typedef intptr_t Value; | 3531 typedef intptr_t Value; |
| 3454 typedef FieldIdPair Pair; | 3532 typedef FieldIdPair Pair; |
| 3455 | 3533 |
| 3456 FieldIdPair(Key key, Value value) : key_(key), value_(value) { } | 3534 FieldIdPair(Key key, Value value) : key_(key), value_(value) { } |
| 3457 | 3535 |
| 3458 static Key KeyOf(Pair kv) { | 3536 static Key KeyOf(Pair kv) { |
| 3459 return kv.key_; | 3537 return kv.key_; |
| 3460 } | 3538 } |
| 3461 | 3539 |
| 3462 static Value ValueOf(Pair kv) { | 3540 static Value ValueOf(Pair kv) { |
| 3463 return kv.value_; | 3541 return kv.value_; |
| 3464 } | 3542 } |
| 3465 | 3543 |
| 3466 static intptr_t Hashcode(Key key) { | 3544 static intptr_t Hashcode(Key key) { |
| 3467 return String::Handle(key->name()).Hash(); | 3545 return String::Handle(key.field_->name()).Hash(); |
| 3468 } | 3546 } |
| 3469 | 3547 |
| 3470 static inline bool IsKeyEqual(Pair kv, Key key) { | 3548 static inline bool IsKeyEqual(Pair kv, Key key) { |
| 3471 return KeyOf(kv)->raw() == key->raw(); | 3549 return (KeyOf(kv).field_->raw() == key.field_->raw()) && |
| 3550 (KeyOf(kv).instance_id_ == key.instance_id_); |
| 3472 } | 3551 } |
| 3473 | 3552 |
| 3474 private: | 3553 private: |
| 3475 Key key_; | 3554 Key key_; |
| 3476 Value value_; | 3555 Value value_; |
| 3477 }; | 3556 }; |
| 3478 | 3557 |
| 3479 // Table mapping static field to their id used during optimization pass. | 3558 // Table mapping static field to their id used during optimization pass. |
| 3480 DirectChainedHashMap<FieldIdPair> field_ids_; | 3559 DirectChainedHashMap<FieldIdPair> field_ids_; |
| 3481 intptr_t max_field_id_; | 3560 intptr_t max_field_id_; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3534 if (key->IsLoadIndexed()) { | 3613 if (key->IsLoadIndexed()) { |
| 3535 LoadIndexedInstr* load_indexed = key->AsLoadIndexed(); | 3614 LoadIndexedInstr* load_indexed = key->AsLoadIndexed(); |
| 3536 object = load_indexed->array()->definition()->ssa_temp_index(); | 3615 object = load_indexed->array()->definition()->ssa_temp_index(); |
| 3537 location = load_indexed->index()->definition()->ssa_temp_index(); | 3616 location = load_indexed->index()->definition()->ssa_temp_index(); |
| 3538 } else if (key->IsStoreIndexed()) { | 3617 } else if (key->IsStoreIndexed()) { |
| 3539 StoreIndexedInstr* store_indexed = key->AsStoreIndexed(); | 3618 StoreIndexedInstr* store_indexed = key->AsStoreIndexed(); |
| 3540 object = store_indexed->array()->definition()->ssa_temp_index(); | 3619 object = store_indexed->array()->definition()->ssa_temp_index(); |
| 3541 location = store_indexed->index()->definition()->ssa_temp_index(); | 3620 location = store_indexed->index()->definition()->ssa_temp_index(); |
| 3542 } else if (key->IsLoadField()) { | 3621 } else if (key->IsLoadField()) { |
| 3543 LoadFieldInstr* load_field = key->AsLoadField(); | 3622 LoadFieldInstr* load_field = key->AsLoadField(); |
| 3544 object = load_field->value()->definition()->ssa_temp_index(); | 3623 object = load_field->instance()->definition()->ssa_temp_index(); |
| 3545 location = load_field->offset_in_bytes(); | 3624 location = load_field->offset_in_bytes(); |
| 3546 } else if (key->IsStoreInstanceField()) { | 3625 } else if (key->IsStoreInstanceField()) { |
| 3547 StoreInstanceFieldInstr* store_field = key->AsStoreInstanceField(); | 3626 StoreInstanceFieldInstr* store_field = key->AsStoreInstanceField(); |
| 3548 object = store_field->instance()->definition()->ssa_temp_index(); | 3627 object = store_field->instance()->definition()->ssa_temp_index(); |
| 3549 location = store_field->field().Offset(); | 3628 location = store_field->field().Offset(); |
| 3550 } else if (key->IsStoreVMField()) { | 3629 } else if (key->IsStoreVMField()) { |
| 3551 StoreVMFieldInstr* store_field = key->AsStoreVMField(); | 3630 StoreVMFieldInstr* store_field = key->AsStoreVMField(); |
| 3552 object = store_field->dest()->definition()->ssa_temp_index(); | 3631 object = store_field->dest()->definition()->ssa_temp_index(); |
| 3553 location = store_field->offset_in_bytes(); | 3632 location = store_field->offset_in_bytes(); |
| 3554 } else if (key->IsLoadStaticField()) { | 3633 } else if (key->IsLoadStaticField()) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3590 } | 3669 } |
| 3591 | 3670 |
| 3592 if (kv->IsCurrentContext()) { | 3671 if (kv->IsCurrentContext()) { |
| 3593 return key->IsStoreContext() || key->IsChainContext(); | 3672 return key->IsStoreContext() || key->IsChainContext(); |
| 3594 } | 3673 } |
| 3595 | 3674 |
| 3596 ASSERT(kv->IsLoadField()); | 3675 ASSERT(kv->IsLoadField()); |
| 3597 LoadFieldInstr* load_field = kv->AsLoadField(); | 3676 LoadFieldInstr* load_field = kv->AsLoadField(); |
| 3598 if (key->IsStoreVMField()) { | 3677 if (key->IsStoreVMField()) { |
| 3599 StoreVMFieldInstr* store_field = key->AsStoreVMField(); | 3678 StoreVMFieldInstr* store_field = key->AsStoreVMField(); |
| 3600 return load_field->value()->Equals(store_field->dest()) && | 3679 return load_field->instance()->Equals(store_field->dest()) && |
| 3601 (load_field->offset_in_bytes() == store_field->offset_in_bytes()); | 3680 (load_field->offset_in_bytes() == store_field->offset_in_bytes()); |
| 3602 } else if (key->IsStoreInstanceField()) { | 3681 } else if (key->IsStoreInstanceField()) { |
| 3603 StoreInstanceFieldInstr* store_field = key->AsStoreInstanceField(); | 3682 StoreInstanceFieldInstr* store_field = key->AsStoreInstanceField(); |
| 3604 return load_field->value()->Equals(store_field->instance()) && | 3683 return load_field->instance()->Equals(store_field->instance()) && |
| 3605 (load_field->offset_in_bytes() == store_field->field().Offset()); | 3684 (load_field->offset_in_bytes() == store_field->field().Offset()); |
| 3606 } | 3685 } |
| 3607 | 3686 |
| 3608 return false; | 3687 return false; |
| 3609 } | 3688 } |
| 3610 }; | 3689 }; |
| 3611 | 3690 |
| 3612 | 3691 |
| 3613 static AliasedSet* NumberLoadExpressions( | 3692 static AliasedSet* NumberLoadExpressions( |
| 3614 FlowGraph* graph, | 3693 FlowGraph* graph, |
| (...skipping 1105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4720 } | 4799 } |
| 4721 | 4800 |
| 4722 | 4801 |
| 4723 void ConstantPropagator::VisitLoadUntagged(LoadUntaggedInstr* instr) { | 4802 void ConstantPropagator::VisitLoadUntagged(LoadUntaggedInstr* instr) { |
| 4724 SetValue(instr, non_constant_); | 4803 SetValue(instr, non_constant_); |
| 4725 } | 4804 } |
| 4726 | 4805 |
| 4727 | 4806 |
| 4728 void ConstantPropagator::VisitLoadField(LoadFieldInstr* instr) { | 4807 void ConstantPropagator::VisitLoadField(LoadFieldInstr* instr) { |
| 4729 if ((instr->recognized_kind() == MethodRecognizer::kObjectArrayLength) && | 4808 if ((instr->recognized_kind() == MethodRecognizer::kObjectArrayLength) && |
| 4730 (instr->value()->definition()->IsCreateArray())) { | 4809 (instr->instance()->definition()->IsCreateArray())) { |
| 4731 const intptr_t length = | 4810 const intptr_t length = |
| 4732 instr->value()->definition()->AsCreateArray()->num_elements(); | 4811 instr->instance()->definition()->AsCreateArray()->num_elements(); |
| 4733 const Object& result = Smi::ZoneHandle(Smi::New(length)); | 4812 const Object& result = Smi::ZoneHandle(Smi::New(length)); |
| 4734 SetValue(instr, result); | 4813 SetValue(instr, result); |
| 4735 return; | 4814 return; |
| 4736 } | 4815 } |
| 4737 | 4816 |
| 4738 if (instr->IsImmutableLengthLoad()) { | 4817 if (instr->IsImmutableLengthLoad()) { |
| 4739 ConstantInstr* constant = instr->value()->definition()->AsConstant(); | 4818 ConstantInstr* constant = instr->instance()->definition()->AsConstant(); |
| 4740 if (constant != NULL) { | 4819 if (constant != NULL) { |
| 4741 if (constant->value().IsString()) { | 4820 if (constant->value().IsString()) { |
| 4742 SetValue(instr, Smi::ZoneHandle( | 4821 SetValue(instr, Smi::ZoneHandle( |
| 4743 Smi::New(String::Cast(constant->value()).Length()))); | 4822 Smi::New(String::Cast(constant->value()).Length()))); |
| 4744 return; | 4823 return; |
| 4745 } | 4824 } |
| 4746 if (constant->value().IsArray()) { | 4825 if (constant->value().IsArray()) { |
| 4747 SetValue(instr, Smi::ZoneHandle( | 4826 SetValue(instr, Smi::ZoneHandle( |
| 4748 Smi::New(Array::Cast(constant->value()).Length()))); | 4827 Smi::New(Array::Cast(constant->value()).Length()))); |
| 4749 return; | 4828 return; |
| (...skipping 922 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5672 if (changed) { | 5751 if (changed) { |
| 5673 // We may have changed the block order and the dominator tree. | 5752 // We may have changed the block order and the dominator tree. |
| 5674 flow_graph->DiscoverBlocks(); | 5753 flow_graph->DiscoverBlocks(); |
| 5675 GrowableArray<BitVector*> dominance_frontier; | 5754 GrowableArray<BitVector*> dominance_frontier; |
| 5676 flow_graph->ComputeDominators(&dominance_frontier); | 5755 flow_graph->ComputeDominators(&dominance_frontier); |
| 5677 } | 5756 } |
| 5678 } | 5757 } |
| 5679 | 5758 |
| 5680 | 5759 |
| 5681 } // namespace dart | 5760 } // namespace dart |
| OLD | NEW |