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

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

Issue 14872002: Improve load forwarding: (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698