Chromium Code Reviews| 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 938 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Field* the_field = &Field::ZoneHandle(field.raw()); | |
| 1282 load->set_field(the_field); | |
| 1278 if (field.guarded_cid() != kIllegalCid) { | 1283 if (field.guarded_cid() != kIllegalCid) { |
| 1279 if (!field.is_nullable() || (field.guarded_cid() == kNullCid)) { | 1284 if (!field.is_nullable() || (field.guarded_cid() == kNullCid)) { |
| 1280 load->set_result_cid(field.guarded_cid()); | 1285 load->set_result_cid(field.guarded_cid()); |
| 1281 } | 1286 } |
| 1282 Field* the_field = &Field::ZoneHandle(field.raw()); | |
| 1283 load->set_field(the_field); | |
| 1284 AddToGuardedFields(the_field); | 1287 AddToGuardedFields(the_field); |
| 1285 } | 1288 } |
| 1286 load->set_field_name(String::Handle(field.name()).ToCString()); | 1289 load->set_field_name(String::Handle(field.name()).ToCString()); |
| 1287 | 1290 |
| 1288 // Discard the environment from the original instruction because the load | 1291 // Discard the environment from the original instruction because the load |
| 1289 // can't deoptimize. | 1292 // can't deoptimize. |
| 1290 call->RemoveEnvironment(); | 1293 call->RemoveEnvironment(); |
| 1291 ReplaceCall(call, load); | 1294 ReplaceCall(call, load); |
| 1292 | 1295 |
| 1293 if (load->result_cid() != kDynamicCid) { | 1296 if (load->result_cid() != kDynamicCid) { |
| (...skipping 1989 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3283 public: | 3286 public: |
| 3284 Alias(const Alias& other) : ValueObject(), alias_(other.alias_) { } | 3287 Alias(const Alias& other) : ValueObject(), alias_(other.alias_) { } |
| 3285 | 3288 |
| 3286 // All indexed load/stores alias each other. | 3289 // All indexed load/stores alias each other. |
| 3287 // TODO(vegorov): incorporate type of array into alias to disambiguate | 3290 // TODO(vegorov): incorporate type of array into alias to disambiguate |
| 3288 // different typed data and normal arrays. | 3291 // different typed data and normal arrays. |
| 3289 static Alias Indexes() { | 3292 static Alias Indexes() { |
| 3290 return Alias(kIndexesAlias); | 3293 return Alias(kIndexesAlias); |
| 3291 } | 3294 } |
| 3292 | 3295 |
| 3293 // Field load/stores alias each other when field offset matches. | 3296 // Field load/stores alias each other only when they access the same field. |
| 3294 // TODO(vegorov): use field information to disambiguate load/stores into | 3297 // AliasedSet assigns ids to a combination of instance and field during |
| 3295 // different fields that by accident share offset. | 3298 // the optimization phase. |
| 3296 static Alias Field(intptr_t offset_in_bytes) { | 3299 static Alias Field(intptr_t id) { |
| 3300 ASSERT(id >= kFirstFieldAlias); | |
| 3301 return Alias(id * 2 + 1); | |
| 3302 } | |
| 3303 | |
| 3304 // VMField load/stores alias each other when field offset matches. | |
| 3305 // TODO(vegorov) storing a context variable does not alias loading array | |
| 3306 // length. | |
| 3307 static Alias VMField(intptr_t offset_in_bytes) { | |
| 3297 const intptr_t idx = offset_in_bytes / kWordSize; | 3308 const intptr_t idx = offset_in_bytes / kWordSize; |
| 3298 ASSERT(idx >= kFirstFieldAlias); | 3309 ASSERT(idx >= kFirstFieldAlias); |
| 3299 return Alias(idx * 2); | 3310 return Alias(idx * 2); |
| 3300 } | 3311 } |
| 3301 | 3312 |
| 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. | 3313 // Current context load/stores alias each other. |
| 3310 static Alias CurrentContext() { | 3314 static Alias CurrentContext() { |
| 3311 return Alias(kCurrentContextAlias); | 3315 return Alias(kCurrentContextAlias); |
| 3312 } | 3316 } |
| 3313 | 3317 |
| 3314 // Operation does not alias anything. | 3318 // Operation does not alias anything. |
| 3315 static Alias None() { | 3319 static Alias None() { |
| 3316 return Alias(kNoneAlias); | 3320 return Alias(kNoneAlias); |
| 3317 } | 3321 } |
| 3318 | 3322 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3351 max_field_id_(0) { } | 3355 max_field_id_(0) { } |
| 3352 | 3356 |
| 3353 Alias ComputeAliasForLoad(Definition* defn) { | 3357 Alias ComputeAliasForLoad(Definition* defn) { |
| 3354 if (defn->IsLoadIndexed()) { | 3358 if (defn->IsLoadIndexed()) { |
| 3355 // We are assuming that LoadField is never used to load the first word. | 3359 // We are assuming that LoadField is never used to load the first word. |
| 3356 return Alias::Indexes(); | 3360 return Alias::Indexes(); |
| 3357 } | 3361 } |
| 3358 | 3362 |
| 3359 LoadFieldInstr* load_field = defn->AsLoadField(); | 3363 LoadFieldInstr* load_field = defn->AsLoadField(); |
| 3360 if (load_field != NULL) { | 3364 if (load_field != NULL) { |
| 3361 return Alias::Field(load_field->offset_in_bytes()); | 3365 if (load_field->field() != NULL) { |
| 3366 Definition* instance = load_field->instance()->definition(); | |
| 3367 return Alias::Field(GetInstanceFieldId(instance, *load_field->field())); | |
| 3368 } else { | |
| 3369 return Alias::VMField(load_field->offset_in_bytes()); | |
| 3370 } | |
| 3362 } | 3371 } |
| 3363 | 3372 |
| 3364 if (defn->IsCurrentContext()) { | 3373 if (defn->IsCurrentContext()) { |
| 3365 return Alias::CurrentContext(); | 3374 return Alias::CurrentContext(); |
| 3366 } | 3375 } |
| 3367 | 3376 |
| 3368 LoadStaticFieldInstr* load_static_field = defn->AsLoadStaticField(); | 3377 LoadStaticFieldInstr* load_static_field = defn->AsLoadStaticField(); |
| 3369 if (load_static_field != NULL) { | 3378 if (load_static_field != NULL) { |
| 3370 return Alias::StaticField(GetFieldId(load_static_field->field())); | 3379 return Alias::Field(GetFieldId(kAnyInstance, load_static_field->field())); |
| 3371 } | 3380 } |
| 3372 | 3381 |
| 3373 UNREACHABLE(); | 3382 UNREACHABLE(); |
| 3374 return Alias::None(); | 3383 return Alias::None(); |
| 3375 } | 3384 } |
| 3376 | 3385 |
| 3377 Alias ComputeAliasForStore(Instruction* instr) { | 3386 Alias ComputeAliasForStore(Instruction* instr) { |
| 3378 if (instr->IsStoreIndexed()) { | 3387 if (instr->IsStoreIndexed()) { |
| 3379 return Alias::Indexes(); | 3388 return Alias::Indexes(); |
| 3380 } | 3389 } |
| 3381 | 3390 |
| 3382 StoreInstanceFieldInstr* store_instance_field = | 3391 StoreInstanceFieldInstr* store_instance_field = |
| 3383 instr->AsStoreInstanceField(); | 3392 instr->AsStoreInstanceField(); |
| 3384 if (store_instance_field != NULL) { | 3393 if (store_instance_field != NULL) { |
| 3385 return Alias::Field(store_instance_field->field().Offset()); | 3394 Definition* instance = store_instance_field->instance()->definition(); |
| 3395 return Alias::Field(GetInstanceFieldId(instance, | |
| 3396 store_instance_field->field())); | |
| 3386 } | 3397 } |
| 3387 | 3398 |
| 3388 StoreVMFieldInstr* store_vm_field = instr->AsStoreVMField(); | 3399 StoreVMFieldInstr* store_vm_field = instr->AsStoreVMField(); |
| 3389 if (store_vm_field != NULL) { | 3400 if (store_vm_field != NULL) { |
| 3390 return Alias::Field(store_vm_field->offset_in_bytes()); | 3401 return Alias::VMField(store_vm_field->offset_in_bytes()); |
| 3391 } | 3402 } |
| 3392 | 3403 |
| 3393 if (instr->IsStoreContext() || instr->IsChainContext()) { | 3404 if (instr->IsStoreContext() || instr->IsChainContext()) { |
| 3394 return Alias::CurrentContext(); | 3405 return Alias::CurrentContext(); |
| 3395 } | 3406 } |
| 3396 | 3407 |
| 3397 StoreStaticFieldInstr* store_static_field = instr->AsStoreStaticField(); | 3408 StoreStaticFieldInstr* store_static_field = instr->AsStoreStaticField(); |
| 3398 if (store_static_field != NULL) { | 3409 if (store_static_field != NULL) { |
| 3399 return Alias::StaticField(GetFieldId(store_static_field->field())); | 3410 return Alias::Field(GetStaticFieldId(store_static_field->field())); |
| 3400 } | 3411 } |
| 3401 | 3412 |
| 3402 return Alias::None(); | 3413 return Alias::None(); |
| 3403 } | 3414 } |
| 3404 | 3415 |
| 3405 bool Contains(const Alias alias) { | 3416 bool Contains(const Alias alias) { |
| 3406 const intptr_t idx = alias.ToIndex(); | 3417 const intptr_t idx = alias.ToIndex(); |
| 3407 return (idx < sets_.length()) && (sets_[idx] != NULL); | 3418 return (idx < sets_.length()) && (sets_[idx] != NULL); |
| 3408 } | 3419 } |
| 3409 | 3420 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 3431 | 3442 |
| 3432 private: | 3443 private: |
| 3433 const intptr_t max_expr_id_; | 3444 const intptr_t max_expr_id_; |
| 3434 | 3445 |
| 3435 // Maps alias index to a set of ssa indexes corresponding to loads with the | 3446 // Maps alias index to a set of ssa indexes corresponding to loads with the |
| 3436 // given alias. | 3447 // given alias. |
| 3437 GrowableArray<BitVector*> sets_; | 3448 GrowableArray<BitVector*> sets_; |
| 3438 | 3449 |
| 3439 // Get id assigned to the given field. Assign a new id if the field is seen | 3450 // Get id assigned to the given field. Assign a new id if the field is seen |
| 3440 // for the first time. | 3451 // for the first time. |
| 3441 intptr_t GetFieldId(const Field& field) { | 3452 intptr_t GetFieldId(intptr_t instance_id, const Field& field) { |
| 3442 intptr_t id = field_ids_.Lookup(&field); | 3453 intptr_t id = field_ids_.Lookup(FieldIdPair::Key(instance_id, &field)); |
| 3443 if (id == 0) { | 3454 if (id == 0) { |
| 3444 id = ++max_field_id_; | 3455 id = ++max_field_id_; |
| 3445 field_ids_.Insert(FieldIdPair(&field, id)); | 3456 field_ids_.Insert(FieldIdPair(FieldIdPair::Key(instance_id, &field), id)); |
| 3446 } | 3457 } |
| 3447 return id; | 3458 return id; |
| 3448 } | 3459 } |
| 3449 | 3460 |
| 3461 enum { | |
| 3462 kAnyInstance = -1 | |
| 3463 }; | |
| 3464 | |
| 3465 intptr_t GetInstanceFieldId(Definition* defn, const Field& field) { | |
| 3466 intptr_t instance_id = kAnyInstance; | |
| 3467 | |
| 3468 AllocateObjectInstr* alloc = defn->AsAllocateObject(); | |
| 3469 if ((alloc != NULL) && !CanBeAliased(alloc)) { | |
| 3470 instance_id = alloc->ssa_temp_index(); | |
| 3471 ASSERT(instance_id != kAnyInstance); | |
| 3472 } | |
| 3473 | |
| 3474 return GetFieldId(instance_id, field); | |
| 3475 } | |
| 3476 | |
| 3477 intptr_t GetStaticFieldId(const Field& field) { | |
| 3478 return GetFieldId(kAnyInstance, field); | |
| 3479 } | |
| 3480 | |
| 3481 intptr_t CanBeAliased(AllocateObjectInstr* alloc) { | |
| 3482 if (alloc->identity() == AllocateObjectInstr::kUnknown) { | |
| 3483 bool escapes = false; | |
| 3484 for (Value* use = alloc->input_use_list(); | |
| 3485 use != NULL; | |
| 3486 use = use->next_use()) { | |
| 3487 Instruction* instr = use->instruction(); | |
| 3488 if (instr->IsPushArgument() || | |
| 3489 (instr->IsStoreVMField() && use->use_index() != 0) || | |
| 3490 (instr->IsStoreInstanceField() && use->use_index() != 0) || | |
|
srdjan
2013/05/02 21:00:54
Some more parentheses, please.
Vyacheslav Egorov (Google)
2013/05/02 21:20:25
Done.
| |
| 3491 (instr->IsStoreStaticField()) || | |
| 3492 (instr->IsPhi())) { | |
| 3493 escapes = true; | |
| 3494 break; | |
| 3495 } | |
| 3496 | |
| 3497 alloc->set_identity(escapes ? AllocateObjectInstr::kAliased | |
| 3498 : AllocateObjectInstr::kNotAliased); | |
| 3499 } | |
| 3500 } | |
| 3501 return alloc->identity() != AllocateObjectInstr::kNotAliased; | |
| 3502 } | |
| 3503 | |
| 3450 class FieldIdPair { | 3504 class FieldIdPair { |
| 3451 public: | 3505 public: |
| 3452 typedef const Field* Key; | 3506 struct Key { |
| 3507 Key(intptr_t instance_id, const Field* field) | |
| 3508 : instance_id_(instance_id), field_(field) { } | |
| 3509 | |
| 3510 intptr_t instance_id_; | |
| 3511 const Field* field_; | |
| 3512 }; | |
| 3513 | |
| 3453 typedef intptr_t Value; | 3514 typedef intptr_t Value; |
| 3454 typedef FieldIdPair Pair; | 3515 typedef FieldIdPair Pair; |
| 3455 | 3516 |
| 3456 FieldIdPair(Key key, Value value) : key_(key), value_(value) { } | 3517 FieldIdPair(Key key, Value value) : key_(key), value_(value) { } |
| 3457 | 3518 |
| 3458 static Key KeyOf(Pair kv) { | 3519 static Key KeyOf(Pair kv) { |
| 3459 return kv.key_; | 3520 return kv.key_; |
| 3460 } | 3521 } |
| 3461 | 3522 |
| 3462 static Value ValueOf(Pair kv) { | 3523 static Value ValueOf(Pair kv) { |
| 3463 return kv.value_; | 3524 return kv.value_; |
| 3464 } | 3525 } |
| 3465 | 3526 |
| 3466 static intptr_t Hashcode(Key key) { | 3527 static intptr_t Hashcode(Key key) { |
| 3467 return String::Handle(key->name()).Hash(); | 3528 return String::Handle(key.field_->name()).Hash(); |
| 3468 } | 3529 } |
| 3469 | 3530 |
| 3470 static inline bool IsKeyEqual(Pair kv, Key key) { | 3531 static inline bool IsKeyEqual(Pair kv, Key key) { |
| 3471 return KeyOf(kv)->raw() == key->raw(); | 3532 return (KeyOf(kv).field_->raw() == key.field_->raw()) && |
| 3533 (KeyOf(kv).instance_id_ == key.instance_id_); | |
| 3472 } | 3534 } |
| 3473 | 3535 |
| 3474 private: | 3536 private: |
| 3475 Key key_; | 3537 Key key_; |
| 3476 Value value_; | 3538 Value value_; |
| 3477 }; | 3539 }; |
| 3478 | 3540 |
| 3479 // Table mapping static field to their id used during optimization pass. | 3541 // Table mapping static field to their id used during optimization pass. |
| 3480 DirectChainedHashMap<FieldIdPair> field_ids_; | 3542 DirectChainedHashMap<FieldIdPair> field_ids_; |
| 3481 intptr_t max_field_id_; | 3543 intptr_t max_field_id_; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3534 if (key->IsLoadIndexed()) { | 3596 if (key->IsLoadIndexed()) { |
| 3535 LoadIndexedInstr* load_indexed = key->AsLoadIndexed(); | 3597 LoadIndexedInstr* load_indexed = key->AsLoadIndexed(); |
| 3536 object = load_indexed->array()->definition()->ssa_temp_index(); | 3598 object = load_indexed->array()->definition()->ssa_temp_index(); |
| 3537 location = load_indexed->index()->definition()->ssa_temp_index(); | 3599 location = load_indexed->index()->definition()->ssa_temp_index(); |
| 3538 } else if (key->IsStoreIndexed()) { | 3600 } else if (key->IsStoreIndexed()) { |
| 3539 StoreIndexedInstr* store_indexed = key->AsStoreIndexed(); | 3601 StoreIndexedInstr* store_indexed = key->AsStoreIndexed(); |
| 3540 object = store_indexed->array()->definition()->ssa_temp_index(); | 3602 object = store_indexed->array()->definition()->ssa_temp_index(); |
| 3541 location = store_indexed->index()->definition()->ssa_temp_index(); | 3603 location = store_indexed->index()->definition()->ssa_temp_index(); |
| 3542 } else if (key->IsLoadField()) { | 3604 } else if (key->IsLoadField()) { |
| 3543 LoadFieldInstr* load_field = key->AsLoadField(); | 3605 LoadFieldInstr* load_field = key->AsLoadField(); |
| 3544 object = load_field->value()->definition()->ssa_temp_index(); | 3606 object = load_field->instance()->definition()->ssa_temp_index(); |
| 3545 location = load_field->offset_in_bytes(); | 3607 location = load_field->offset_in_bytes(); |
| 3546 } else if (key->IsStoreInstanceField()) { | 3608 } else if (key->IsStoreInstanceField()) { |
| 3547 StoreInstanceFieldInstr* store_field = key->AsStoreInstanceField(); | 3609 StoreInstanceFieldInstr* store_field = key->AsStoreInstanceField(); |
| 3548 object = store_field->instance()->definition()->ssa_temp_index(); | 3610 object = store_field->instance()->definition()->ssa_temp_index(); |
| 3549 location = store_field->field().Offset(); | 3611 location = store_field->field().Offset(); |
| 3550 } else if (key->IsStoreVMField()) { | 3612 } else if (key->IsStoreVMField()) { |
| 3551 StoreVMFieldInstr* store_field = key->AsStoreVMField(); | 3613 StoreVMFieldInstr* store_field = key->AsStoreVMField(); |
| 3552 object = store_field->dest()->definition()->ssa_temp_index(); | 3614 object = store_field->dest()->definition()->ssa_temp_index(); |
| 3553 location = store_field->offset_in_bytes(); | 3615 location = store_field->offset_in_bytes(); |
| 3554 } else if (key->IsLoadStaticField()) { | 3616 } else if (key->IsLoadStaticField()) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3590 } | 3652 } |
| 3591 | 3653 |
| 3592 if (kv->IsCurrentContext()) { | 3654 if (kv->IsCurrentContext()) { |
| 3593 return key->IsStoreContext() || key->IsChainContext(); | 3655 return key->IsStoreContext() || key->IsChainContext(); |
| 3594 } | 3656 } |
| 3595 | 3657 |
| 3596 ASSERT(kv->IsLoadField()); | 3658 ASSERT(kv->IsLoadField()); |
| 3597 LoadFieldInstr* load_field = kv->AsLoadField(); | 3659 LoadFieldInstr* load_field = kv->AsLoadField(); |
| 3598 if (key->IsStoreVMField()) { | 3660 if (key->IsStoreVMField()) { |
| 3599 StoreVMFieldInstr* store_field = key->AsStoreVMField(); | 3661 StoreVMFieldInstr* store_field = key->AsStoreVMField(); |
| 3600 return load_field->value()->Equals(store_field->dest()) && | 3662 return load_field->instance()->Equals(store_field->dest()) && |
| 3601 (load_field->offset_in_bytes() == store_field->offset_in_bytes()); | 3663 (load_field->offset_in_bytes() == store_field->offset_in_bytes()); |
| 3602 } else if (key->IsStoreInstanceField()) { | 3664 } else if (key->IsStoreInstanceField()) { |
| 3603 StoreInstanceFieldInstr* store_field = key->AsStoreInstanceField(); | 3665 StoreInstanceFieldInstr* store_field = key->AsStoreInstanceField(); |
| 3604 return load_field->value()->Equals(store_field->instance()) && | 3666 return load_field->instance()->Equals(store_field->instance()) && |
| 3605 (load_field->offset_in_bytes() == store_field->field().Offset()); | 3667 (load_field->offset_in_bytes() == store_field->field().Offset()); |
| 3606 } | 3668 } |
| 3607 | 3669 |
| 3608 return false; | 3670 return false; |
| 3609 } | 3671 } |
| 3610 }; | 3672 }; |
| 3611 | 3673 |
| 3612 | 3674 |
| 3613 static AliasedSet* NumberLoadExpressions( | 3675 static AliasedSet* NumberLoadExpressions( |
| 3614 FlowGraph* graph, | 3676 FlowGraph* graph, |
| (...skipping 1105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4720 } | 4782 } |
| 4721 | 4783 |
| 4722 | 4784 |
| 4723 void ConstantPropagator::VisitLoadUntagged(LoadUntaggedInstr* instr) { | 4785 void ConstantPropagator::VisitLoadUntagged(LoadUntaggedInstr* instr) { |
| 4724 SetValue(instr, non_constant_); | 4786 SetValue(instr, non_constant_); |
| 4725 } | 4787 } |
| 4726 | 4788 |
| 4727 | 4789 |
| 4728 void ConstantPropagator::VisitLoadField(LoadFieldInstr* instr) { | 4790 void ConstantPropagator::VisitLoadField(LoadFieldInstr* instr) { |
| 4729 if ((instr->recognized_kind() == MethodRecognizer::kObjectArrayLength) && | 4791 if ((instr->recognized_kind() == MethodRecognizer::kObjectArrayLength) && |
| 4730 (instr->value()->definition()->IsCreateArray())) { | 4792 (instr->instance()->definition()->IsCreateArray())) { |
| 4731 const intptr_t length = | 4793 const intptr_t length = |
| 4732 instr->value()->definition()->AsCreateArray()->num_elements(); | 4794 instr->instance()->definition()->AsCreateArray()->num_elements(); |
| 4733 const Object& result = Smi::ZoneHandle(Smi::New(length)); | 4795 const Object& result = Smi::ZoneHandle(Smi::New(length)); |
| 4734 SetValue(instr, result); | 4796 SetValue(instr, result); |
| 4735 return; | 4797 return; |
| 4736 } | 4798 } |
| 4737 | 4799 |
| 4738 if (instr->IsImmutableLengthLoad()) { | 4800 if (instr->IsImmutableLengthLoad()) { |
| 4739 ConstantInstr* constant = instr->value()->definition()->AsConstant(); | 4801 ConstantInstr* constant = instr->instance()->definition()->AsConstant(); |
| 4740 if (constant != NULL) { | 4802 if (constant != NULL) { |
| 4741 if (constant->value().IsString()) { | 4803 if (constant->value().IsString()) { |
| 4742 SetValue(instr, Smi::ZoneHandle( | 4804 SetValue(instr, Smi::ZoneHandle( |
| 4743 Smi::New(String::Cast(constant->value()).Length()))); | 4805 Smi::New(String::Cast(constant->value()).Length()))); |
| 4744 return; | 4806 return; |
| 4745 } | 4807 } |
| 4746 if (constant->value().IsArray()) { | 4808 if (constant->value().IsArray()) { |
| 4747 SetValue(instr, Smi::ZoneHandle( | 4809 SetValue(instr, Smi::ZoneHandle( |
| 4748 Smi::New(Array::Cast(constant->value()).Length()))); | 4810 Smi::New(Array::Cast(constant->value()).Length()))); |
| 4749 return; | 4811 return; |
| (...skipping 922 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5672 if (changed) { | 5734 if (changed) { |
| 5673 // We may have changed the block order and the dominator tree. | 5735 // We may have changed the block order and the dominator tree. |
| 5674 flow_graph->DiscoverBlocks(); | 5736 flow_graph->DiscoverBlocks(); |
| 5675 GrowableArray<BitVector*> dominance_frontier; | 5737 GrowableArray<BitVector*> dominance_frontier; |
| 5676 flow_graph->ComputeDominators(&dominance_frontier); | 5738 flow_graph->ComputeDominators(&dominance_frontier); |
| 5677 } | 5739 } |
| 5678 } | 5740 } |
| 5679 | 5741 |
| 5680 | 5742 |
| 5681 } // namespace dart | 5743 } // namespace dart |
| OLD | NEW |