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

Side by Side Diff: src/compiler/load-elimination.cc

Issue 2431563002: [turbofan] Track multiple maps for LoadElimination. (Closed)
Patch Set: Created 4 years, 2 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
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/load-elimination.h" 5 #include "src/compiler/load-elimination.h"
6 6
7 #include "src/compiler/common-operator.h" 7 #include "src/compiler/common-operator.h"
8 #include "src/compiler/js-graph.h" 8 #include "src/compiler/js-graph.h"
9 #include "src/compiler/node-properties.h" 9 #include "src/compiler/node-properties.h"
10 #include "src/compiler/simplified-operator.h" 10 #include "src/compiler/simplified-operator.h"
11 #include "src/factory.h"
12 #include "src/objects-inl.h"
11 13
12 namespace v8 { 14 namespace v8 {
13 namespace internal { 15 namespace internal {
14 namespace compiler { 16 namespace compiler {
15 17
16 namespace { 18 namespace {
17 19
18 enum Aliasing { kNoAlias, kMayAlias, kMustAlias }; 20 enum Aliasing { kNoAlias, kMayAlias, kMustAlias };
19 21
20 Aliasing QueryAlias(Node* a, Node* b) { 22 Aliasing QueryAlias(Node* a, Node* b) {
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 } 315 }
314 316
315 void LoadElimination::AbstractField::Print() const { 317 void LoadElimination::AbstractField::Print() const {
316 for (auto pair : info_for_node_) { 318 for (auto pair : info_for_node_) {
317 PrintF(" #%d:%s -> #%d:%s\n", pair.first->id(), 319 PrintF(" #%d:%s -> #%d:%s\n", pair.first->id(),
318 pair.first->op()->mnemonic(), pair.second->id(), 320 pair.first->op()->mnemonic(), pair.second->id(),
319 pair.second->op()->mnemonic()); 321 pair.second->op()->mnemonic());
320 } 322 }
321 } 323 }
322 324
325 ZoneHandleSet<Map> LoadElimination::AbstractMaps::Lookup(Node* object) const {
326 for (auto pair : info_for_node_) {
327 if (MustAlias(object, pair.first)) return pair.second;
328 }
329 return ZoneHandleSet<Map>();
330 }
331
332 LoadElimination::AbstractMaps const* LoadElimination::AbstractMaps::Kill(
333 Node* object, Zone* zone) const {
334 for (auto pair : this->info_for_node_) {
335 if (MayAlias(object, pair.first)) {
336 AbstractMaps* that = new (zone) AbstractMaps(zone);
337 for (auto pair : this->info_for_node_) {
338 if (!MayAlias(object, pair.first)) that->info_for_node_.insert(pair);
339 }
340 return that;
341 }
342 }
343 return this;
344 }
345
346 void LoadElimination::AbstractMaps::Print() const {
347 for (auto pair : info_for_node_) {
348 PrintF(" #%d:%s\n", pair.first->id(),
349 pair.first->op()->mnemonic());
350 OFStream os(stdout);
351 ZoneHandleSet<Map> const& maps = pair.second;
352 for (size_t i = 0; i < maps.size(); ++i) {
353 os << " - " << Brief(*maps[i]) << "\n";
354 }
355 }
356 }
357
323 bool LoadElimination::AbstractState::Equals(AbstractState const* that) const { 358 bool LoadElimination::AbstractState::Equals(AbstractState const* that) const {
324 if (this->checks_) { 359 if (this->checks_) {
325 if (!that->checks_ || !that->checks_->Equals(this->checks_)) { 360 if (!that->checks_ || !that->checks_->Equals(this->checks_)) {
326 return false; 361 return false;
327 } 362 }
328 } else if (that->checks_) { 363 } else if (that->checks_) {
329 return false; 364 return false;
330 } 365 }
331 if (this->elements_) { 366 if (this->elements_) {
332 if (!that->elements_ || !that->elements_->Equals(this->elements_)) { 367 if (!that->elements_ || !that->elements_->Equals(this->elements_)) {
333 return false; 368 return false;
334 } 369 }
335 } else if (that->elements_) { 370 } else if (that->elements_) {
336 return false; 371 return false;
337 } 372 }
338 for (size_t i = 0u; i < arraysize(fields_); ++i) { 373 for (size_t i = 0u; i < arraysize(fields_); ++i) {
339 AbstractField const* this_field = this->fields_[i]; 374 AbstractField const* this_field = this->fields_[i];
340 AbstractField const* that_field = that->fields_[i]; 375 AbstractField const* that_field = that->fields_[i];
341 if (this_field) { 376 if (this_field) {
342 if (!that_field || !that_field->Equals(this_field)) return false; 377 if (!that_field || !that_field->Equals(this_field)) return false;
343 } else if (that_field) { 378 } else if (that_field) {
344 return false; 379 return false;
345 } 380 }
346 } 381 }
382 if (this->maps_) {
383 if (!that->maps_ || !that->maps_->Equals(this->maps_)) {
384 return false;
385 }
386 } else if (that->maps_) {
387 return false;
388 }
347 return true; 389 return true;
348 } 390 }
349 391
350 void LoadElimination::AbstractState::Merge(AbstractState const* that, 392 void LoadElimination::AbstractState::Merge(AbstractState const* that,
351 Zone* zone) { 393 Zone* zone) {
352 // Merge the information we have about the checks. 394 // Merge the information we have about the checks.
353 if (this->checks_) { 395 if (this->checks_) {
354 this->checks_ = 396 this->checks_ =
355 that->checks_ ? that->checks_->Merge(this->checks_, zone) : nullptr; 397 that->checks_ ? that->checks_->Merge(this->checks_, zone) : nullptr;
356 } 398 }
357 399
358 // Merge the information we have about the elements. 400 // Merge the information we have about the elements.
359 if (this->elements_) { 401 if (this->elements_) {
360 this->elements_ = that->elements_ 402 this->elements_ = that->elements_
361 ? that->elements_->Merge(this->elements_, zone) 403 ? that->elements_->Merge(this->elements_, zone)
362 : nullptr; 404 : nullptr;
363 } 405 }
364 406
365 // Merge the information we have about the fields. 407 // Merge the information we have about the fields.
366 for (size_t i = 0; i < arraysize(fields_); ++i) { 408 for (size_t i = 0; i < arraysize(fields_); ++i) {
367 if (this->fields_[i]) { 409 if (this->fields_[i]) {
368 if (that->fields_[i]) { 410 if (that->fields_[i]) {
369 this->fields_[i] = this->fields_[i]->Merge(that->fields_[i], zone); 411 this->fields_[i] = this->fields_[i]->Merge(that->fields_[i], zone);
370 } else { 412 } else {
371 this->fields_[i] = nullptr; 413 this->fields_[i] = nullptr;
372 } 414 }
373 } 415 }
374 } 416 }
417
418 // Merge the information we have about the maps.
419 if (this->maps_) {
420 this->maps_ = that->maps_ ? that->maps_->Merge(this->maps_, zone) : nullptr;
421 }
375 } 422 }
376 423
377 Node* LoadElimination::AbstractState::LookupCheck(Node* node) const { 424 Node* LoadElimination::AbstractState::LookupCheck(Node* node) const {
378 return this->checks_ ? this->checks_->Lookup(node) : nullptr; 425 return this->checks_ ? this->checks_->Lookup(node) : nullptr;
379 } 426 }
380 427
381 LoadElimination::AbstractState const* LoadElimination::AbstractState::AddCheck( 428 LoadElimination::AbstractState const* LoadElimination::AbstractState::AddCheck(
382 Node* node, Zone* zone) const { 429 Node* node, Zone* zone) const {
383 AbstractState* that = new (zone) AbstractState(*this); 430 AbstractState* that = new (zone) AbstractState(*this);
384 if (that->checks_) { 431 if (that->checks_) {
385 that->checks_ = that->checks_->Extend(node, zone); 432 that->checks_ = that->checks_->Extend(node, zone);
386 } else { 433 } else {
387 that->checks_ = new (zone) AbstractChecks(node, zone); 434 that->checks_ = new (zone) AbstractChecks(node, zone);
388 } 435 }
389 return that; 436 return that;
390 } 437 }
391 438
439 ZoneHandleSet<Map> LoadElimination::AbstractState::LookupMaps(
440 Node* object) const {
441 if (this->maps_) {
442 return this->maps_->Lookup(object);
443 }
444 return ZoneHandleSet<Map>();
445 }
446
447 LoadElimination::AbstractState const* LoadElimination::AbstractState::AddMaps(
448 Node* object, ZoneHandleSet<Map> maps, Zone* zone) const {
449 AbstractState* that = new (zone) AbstractState(*this);
450 if (that->maps_) {
451 that->maps_ = that->maps_->Extend(object, maps, zone);
452 } else {
453 that->maps_ = new (zone) AbstractMaps(object, maps, zone);
454 }
455 return that;
456 }
457
458 LoadElimination::AbstractState const* LoadElimination::AbstractState::KillMaps(
459 Node* object, Zone* zone) const {
460 if (this->maps_) {
461 AbstractMaps const* that_maps = this->maps_->Kill(object, zone);
462 if (this->maps_ != that_maps) {
463 AbstractState* that = new (zone) AbstractState(*this);
464 that->maps_ = that_maps;
465 return that;
466 }
467 }
468 return this;
469 }
470
392 Node* LoadElimination::AbstractState::LookupElement(Node* object, 471 Node* LoadElimination::AbstractState::LookupElement(Node* object,
393 Node* index) const { 472 Node* index) const {
394 if (this->elements_) { 473 if (this->elements_) {
395 return this->elements_->Lookup(object, index); 474 return this->elements_->Lookup(object, index);
396 } 475 }
397 return nullptr; 476 return nullptr;
398 } 477 }
399 478
400 LoadElimination::AbstractState const* 479 LoadElimination::AbstractState const*
401 LoadElimination::AbstractState::AddElement(Node* object, Node* index, 480 LoadElimination::AbstractState::AddElement(Node* object, Node* index,
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 return this_field->Lookup(object); 533 return this_field->Lookup(object);
455 } 534 }
456 return nullptr; 535 return nullptr;
457 } 536 }
458 537
459 void LoadElimination::AbstractState::Print() const { 538 void LoadElimination::AbstractState::Print() const {
460 if (checks_) { 539 if (checks_) {
461 PrintF(" checks:\n"); 540 PrintF(" checks:\n");
462 checks_->Print(); 541 checks_->Print();
463 } 542 }
543 if (maps_) {
544 PrintF(" maps:\n");
545 maps_->Print();
546 }
464 if (elements_) { 547 if (elements_) {
465 PrintF(" elements:\n"); 548 PrintF(" elements:\n");
466 elements_->Print(); 549 elements_->Print();
467 } 550 }
468 for (size_t i = 0; i < arraysize(fields_); ++i) { 551 for (size_t i = 0; i < arraysize(fields_); ++i) {
469 if (AbstractField const* const field = fields_[i]) { 552 if (AbstractField const* const field = fields_[i]) {
470 PrintF(" field %zu:\n", i); 553 PrintF(" field %zu:\n", i);
471 field->Print(); 554 field->Print();
472 } 555 }
473 } 556 }
(...skipping 19 matching lines...) Expand all
493 if (state == nullptr) return NoChange(); 576 if (state == nullptr) return NoChange();
494 if (Node* const check = state->LookupCheck(node)) { 577 if (Node* const check = state->LookupCheck(node)) {
495 ReplaceWithValue(node, check, effect); 578 ReplaceWithValue(node, check, effect);
496 return Replace(check); 579 return Replace(check);
497 } 580 }
498 state = state->AddCheck(node, zone()); 581 state = state->AddCheck(node, zone());
499 return UpdateState(node, state); 582 return UpdateState(node, state);
500 } 583 }
501 584
502 Reduction LoadElimination::ReduceCheckMaps(Node* node) { 585 Reduction LoadElimination::ReduceCheckMaps(Node* node) {
586 ZoneHandleSet<Map> const maps = CheckMapsParametersOf(node->op()).maps();
503 Node* const object = NodeProperties::GetValueInput(node, 0); 587 Node* const object = NodeProperties::GetValueInput(node, 0);
504 Node* const effect = NodeProperties::GetEffectInput(node); 588 Node* const effect = NodeProperties::GetEffectInput(node);
505 AbstractState const* state = node_states_.Get(effect); 589 AbstractState const* state = node_states_.Get(effect);
506 if (state == nullptr) return NoChange(); 590 if (state == nullptr) return NoChange();
507 int const map_input_count = node->op()->ValueInputCount() - 1; 591 ZoneHandleSet<Map> object_maps = state->LookupMaps(object);
508 if (Node* const object_map = 592 if (object_maps.contains(maps)) return Replace(effect);
Jarin 2016/11/16 14:54:41 Still confused. If I have MapCheck(m1, m2); MapCh
Benedikt Meurer 2016/12/21 08:36:49 Done.
509 state->LookupField(object, FieldIndexOf(HeapObject::kMapOffset))) { 593 // TODO(intersect)
510 for (int i = 0; i < map_input_count; ++i) { 594 state = state->KillMaps(object, zone());
511 Node* map = NodeProperties::GetValueInput(node, 1 + i); 595 state = state->AddMaps(object, maps, zone());
512 if (map == object_map) return Replace(effect);
513 }
514 }
515 if (map_input_count == 1) {
516 Node* const map0 = NodeProperties::GetValueInput(node, 1);
517 state = state->AddField(object, FieldIndexOf(HeapObject::kMapOffset), map0,
518 zone());
519 }
520 return UpdateState(node, state); 596 return UpdateState(node, state);
521 } 597 }
522 598
523 Reduction LoadElimination::ReduceEnsureWritableFastElements(Node* node) { 599 Reduction LoadElimination::ReduceEnsureWritableFastElements(Node* node) {
524 Node* const object = NodeProperties::GetValueInput(node, 0); 600 Node* const object = NodeProperties::GetValueInput(node, 0);
525 Node* const elements = NodeProperties::GetValueInput(node, 1); 601 Node* const elements = NodeProperties::GetValueInput(node, 1);
526 Node* const effect = NodeProperties::GetEffectInput(node); 602 Node* const effect = NodeProperties::GetEffectInput(node);
527 AbstractState const* state = node_states_.Get(effect); 603 AbstractState const* state = node_states_.Get(effect);
528 if (state == nullptr) return NoChange(); 604 if (state == nullptr) return NoChange();
529 Node* fixed_array_map = jsgraph()->FixedArrayMapConstant();
530 if (Node* const elements_map =
531 state->LookupField(elements, FieldIndexOf(HeapObject::kMapOffset))) {
532 // Check if the {elements} already have the fixed array map. 605 // Check if the {elements} already have the fixed array map.
533 if (elements_map == fixed_array_map) { 606 ZoneHandleSet<Map> elements_maps = state->LookupMaps(elements);
534 ReplaceWithValue(node, elements, effect); 607 ZoneHandleSet<Map> fixed_array_map(factory()->fixed_array_map());
535 return Replace(elements); 608 if (elements_maps == fixed_array_map) {
536 } 609 ReplaceWithValue(node, elements, effect);
610 return Replace(elements);
537 } 611 }
538 // We know that the resulting elements have the fixed array map. 612 // We know that the resulting elements have the fixed array map.
539 state = state->AddField(node, FieldIndexOf(HeapObject::kMapOffset), 613 state = state->AddMaps(node, fixed_array_map, zone());
540 fixed_array_map, zone());
541 // Kill the previous elements on {object}. 614 // Kill the previous elements on {object}.
542 state = 615 state =
543 state->KillField(object, FieldIndexOf(JSObject::kElementsOffset), zone()); 616 state->KillField(object, FieldIndexOf(JSObject::kElementsOffset), zone());
544 // Add the new elements on {object}. 617 // Add the new elements on {object}.
545 state = state->AddField(object, FieldIndexOf(JSObject::kElementsOffset), node, 618 state = state->AddField(object, FieldIndexOf(JSObject::kElementsOffset), node,
546 zone()); 619 zone());
547 return UpdateState(node, state); 620 return UpdateState(node, state);
548 } 621 }
549 622
550 Reduction LoadElimination::ReduceMaybeGrowFastElements(Node* node) { 623 Reduction LoadElimination::ReduceMaybeGrowFastElements(Node* node) {
551 GrowFastElementsFlags flags = GrowFastElementsFlagsOf(node->op()); 624 GrowFastElementsFlags flags = GrowFastElementsFlagsOf(node->op());
552 Node* const object = NodeProperties::GetValueInput(node, 0); 625 Node* const object = NodeProperties::GetValueInput(node, 0);
553 Node* const effect = NodeProperties::GetEffectInput(node); 626 Node* const effect = NodeProperties::GetEffectInput(node);
554 AbstractState const* state = node_states_.Get(effect); 627 AbstractState const* state = node_states_.Get(effect);
555 if (state == nullptr) return NoChange(); 628 if (state == nullptr) return NoChange();
556 if (flags & GrowFastElementsFlag::kDoubleElements) { 629 if (flags & GrowFastElementsFlag::kDoubleElements) {
557 // We know that the resulting elements have the fixed double array map. 630 // We know that the resulting elements have the fixed double array map.
558 Node* fixed_double_array_map = jsgraph()->FixedDoubleArrayMapConstant(); 631 state = state->AddMaps(
559 state = state->AddField(node, FieldIndexOf(HeapObject::kMapOffset), 632 node, ZoneHandleSet<Map>(factory()->fixed_double_array_map()), zone());
560 fixed_double_array_map, zone());
561 } else { 633 } else {
562 // We know that the resulting elements have the fixed array map. 634 // We know that the resulting elements have the fixed array map.
563 Node* fixed_array_map = jsgraph()->FixedArrayMapConstant(); 635 state = state->AddMaps(
564 state = state->AddField(node, FieldIndexOf(HeapObject::kMapOffset), 636 node, ZoneHandleSet<Map>(factory()->fixed_array_map()), zone());
565 fixed_array_map, zone());
566 } 637 }
567 if (flags & GrowFastElementsFlag::kArrayObject) { 638 if (flags & GrowFastElementsFlag::kArrayObject) {
568 // Kill the previous Array::length on {object}. 639 // Kill the previous Array::length on {object}.
569 state = 640 state =
570 state->KillField(object, FieldIndexOf(JSArray::kLengthOffset), zone()); 641 state->KillField(object, FieldIndexOf(JSArray::kLengthOffset), zone());
571 } 642 }
572 // Kill the previous elements on {object}. 643 // Kill the previous elements on {object}.
573 state = 644 state =
574 state->KillField(object, FieldIndexOf(JSObject::kElementsOffset), zone()); 645 state->KillField(object, FieldIndexOf(JSObject::kElementsOffset), zone());
575 // Add the new elements on {object}. 646 // Add the new elements on {object}.
576 state = state->AddField(object, FieldIndexOf(JSObject::kElementsOffset), node, 647 state = state->AddField(object, FieldIndexOf(JSObject::kElementsOffset), node,
577 zone()); 648 zone());
578 return UpdateState(node, state); 649 return UpdateState(node, state);
579 } 650 }
580 651
581 Reduction LoadElimination::ReduceTransitionElementsKind(Node* node) { 652 Reduction LoadElimination::ReduceTransitionElementsKind(Node* node) {
582 Node* const object = NodeProperties::GetValueInput(node, 0); 653 Node* const object = NodeProperties::GetValueInput(node, 0);
583 Node* const source_map = NodeProperties::GetValueInput(node, 1); 654 // Node* const source_map = NodeProperties::GetValueInput(node, 1);
584 Node* const target_map = NodeProperties::GetValueInput(node, 2); 655 // Node* const target_map = NodeProperties::GetValueInput(node, 2);
585 Node* const effect = NodeProperties::GetEffectInput(node); 656 Node* const effect = NodeProperties::GetEffectInput(node);
586 AbstractState const* state = node_states_.Get(effect); 657 AbstractState const* state = node_states_.Get(effect);
587 if (state == nullptr) return NoChange(); 658 if (state == nullptr) return NoChange();
659 // TODO(bmeurer): Put the map constants onto the operator.
660 // ZoneHandleSet<Map> object_maps = state->LookupMaps(object);
661 #if 0
588 if (Node* const object_map = 662 if (Node* const object_map =
589 state->LookupField(object, FieldIndexOf(HeapObject::kMapOffset))) { 663 state->LookupField(object, FieldIndexOf(HeapObject::kMapOffset))) {
590 if (target_map == object_map) { 664 if (target_map == object_map) {
591 // The {object} already has the {target_map}, so this TransitionElements 665 // The {object} already has the {target_map}, so this TransitionElements
592 // {node} is fully redundant (independent of what {source_map} is). 666 // {node} is fully redundant (independent of what {source_map} is).
593 return Replace(effect); 667 return Replace(effect);
594 } 668 }
595 state = 669 state =
596 state->KillField(object, FieldIndexOf(HeapObject::kMapOffset), zone()); 670 state->KillField(object, FieldIndexOf(HeapObject::kMapOffset), zone());
597 if (source_map == object_map) { 671 if (source_map == object_map) {
598 state = state->AddField(object, FieldIndexOf(HeapObject::kMapOffset), 672 state = state->AddField(object, FieldIndexOf(HeapObject::kMapOffset),
599 target_map, zone()); 673 target_map, zone());
600 } 674 }
601 } else { 675 } else {
602 state = 676 state =
603 state->KillField(object, FieldIndexOf(HeapObject::kMapOffset), zone()); 677 state->KillField(object, FieldIndexOf(HeapObject::kMapOffset), zone());
604 } 678 }
679 #else
680 state = state->KillMaps(object, zone());
681 #endif
605 ElementsTransition transition = ElementsTransitionOf(node->op()); 682 ElementsTransition transition = ElementsTransitionOf(node->op());
606 switch (transition) { 683 switch (transition) {
607 case ElementsTransition::kFastTransition: 684 case ElementsTransition::kFastTransition:
608 break; 685 break;
609 case ElementsTransition::kSlowTransition: 686 case ElementsTransition::kSlowTransition:
610 // Kill the elements as well. 687 // Kill the elements as well.
611 state = state->KillField(object, FieldIndexOf(JSObject::kElementsOffset), 688 state = state->KillField(object, FieldIndexOf(JSObject::kElementsOffset),
612 zone()); 689 zone());
613 break; 690 break;
614 } 691 }
615 return UpdateState(node, state); 692 return UpdateState(node, state);
616 } 693 }
617 694
618 Reduction LoadElimination::ReduceLoadField(Node* node) { 695 Reduction LoadElimination::ReduceLoadField(Node* node) {
619 FieldAccess const& access = FieldAccessOf(node->op()); 696 FieldAccess const& access = FieldAccessOf(node->op());
620 Node* const object = NodeProperties::GetValueInput(node, 0); 697 Node* const object = NodeProperties::GetValueInput(node, 0);
621 Node* const effect = NodeProperties::GetEffectInput(node); 698 Node* const effect = NodeProperties::GetEffectInput(node);
622 Node* const control = NodeProperties::GetControlInput(node); 699 Node* const control = NodeProperties::GetControlInput(node);
623 AbstractState const* state = node_states_.Get(effect); 700 AbstractState const* state = node_states_.Get(effect);
624 if (state == nullptr) return NoChange(); 701 if (state == nullptr) return NoChange();
625 int field_index = FieldIndexOf(access); 702 if (access.offset == HeapObject::kMapOffset) {
626 if (field_index >= 0) { 703 DCHECK_EQ(kTaggedBase, access.base_is_tagged);
627 if (Node* replacement = state->LookupField(object, field_index)) { 704 DCHECK(IsAnyTagged(access.machine_type.representation()));
628 // Make sure we don't resurrect dead {replacement} nodes. 705 ZoneHandleSet<Map> object_maps = state->LookupMaps(object);
629 if (!replacement->IsDead()) { 706 if (object_maps.size() == 1) {
630 // We might need to guard the {replacement} if the type of the 707 Node* value = jsgraph()->HeapConstant(object_maps[0]);
631 // {node} is more precise than the type of the {replacement}. 708 ReplaceWithValue(node, value, effect);
632 Type* const node_type = NodeProperties::GetType(node); 709 return Replace(value);
633 if (!NodeProperties::GetType(replacement)->Is(node_type)) { 710 }
634 replacement = graph()->NewNode(common()->TypeGuard(node_type), 711 } else {
635 replacement, control); 712 int field_index = FieldIndexOf(access);
713 if (field_index >= 0) {
714 if (Node* replacement = state->LookupField(object, field_index)) {
715 // Make sure we don't resurrect dead {replacement} nodes.
716 if (!replacement->IsDead()) {
717 // We might need to guard the {replacement} if the type of the
718 // {node} is more precise than the type of the {replacement}.
719 Type* const node_type = NodeProperties::GetType(node);
720 if (!NodeProperties::GetType(replacement)->Is(node_type)) {
721 replacement = graph()->NewNode(common()->TypeGuard(node_type),
722 replacement, control);
723 }
724 ReplaceWithValue(node, replacement, effect);
725 return Replace(replacement);
636 } 726 }
637 ReplaceWithValue(node, replacement, effect);
638 return Replace(replacement);
639 } 727 }
728 state = state->AddField(object, field_index, node, zone());
640 } 729 }
641 state = state->AddField(object, field_index, node, zone());
642 } 730 }
643 return UpdateState(node, state); 731 return UpdateState(node, state);
644 } 732 }
645 733
646 Reduction LoadElimination::ReduceStoreField(Node* node) { 734 Reduction LoadElimination::ReduceStoreField(Node* node) {
647 FieldAccess const& access = FieldAccessOf(node->op()); 735 FieldAccess const& access = FieldAccessOf(node->op());
648 Node* const object = NodeProperties::GetValueInput(node, 0); 736 Node* const object = NodeProperties::GetValueInput(node, 0);
649 Node* const new_value = NodeProperties::GetValueInput(node, 1); 737 Node* const new_value = NodeProperties::GetValueInput(node, 1);
650 Node* const effect = NodeProperties::GetEffectInput(node); 738 Node* const effect = NodeProperties::GetEffectInput(node);
651 AbstractState const* state = node_states_.Get(effect); 739 AbstractState const* state = node_states_.Get(effect);
652 if (state == nullptr) return NoChange(); 740 if (state == nullptr) return NoChange();
653 int field_index = FieldIndexOf(access); 741 if (access.offset == HeapObject::kMapOffset) {
654 if (field_index >= 0) { 742 DCHECK_EQ(kTaggedBase, access.base_is_tagged);
655 Node* const old_value = state->LookupField(object, field_index); 743 DCHECK(IsAnyTagged(access.machine_type.representation()));
656 if (old_value == new_value) { 744 // Kill all potential knowledge about the {object}s map.
657 // This store is fully redundant. 745 state = state->KillMaps(object, zone());
658 return Replace(effect); 746 Type* const new_value_type = NodeProperties::GetType(new_value);
747 if (new_value_type->IsConstant()) {
748 // Record the new {object} map information.
749 ZoneHandleSet<Map> object_maps(
750 Handle<Map>::cast(new_value_type->AsConstant()->Value()));
751 state = state->AddMaps(object, object_maps, zone());
659 } 752 }
660 // Kill all potentially aliasing fields and record the new value.
661 state = state->KillField(object, field_index, zone());
662 state = state->AddField(object, field_index, new_value, zone());
663 } else { 753 } else {
664 // Unsupported StoreField operator. 754 int field_index = FieldIndexOf(access);
665 state = empty_state(); 755 if (field_index >= 0) {
756 Node* const old_value = state->LookupField(object, field_index);
757 if (old_value == new_value) {
758 // This store is fully redundant.
759 return Replace(effect);
760 }
761 // Kill all potentially aliasing fields and record the new value.
762 state = state->KillField(object, field_index, zone());
763 state = state->AddField(object, field_index, new_value, zone());
764 } else {
765 // Unsupported StoreField operator.
766 state = empty_state();
767 }
666 } 768 }
667 return UpdateState(node, state); 769 return UpdateState(node, state);
668 } 770 }
669 771
670 Reduction LoadElimination::ReduceLoadElement(Node* node) { 772 Reduction LoadElimination::ReduceLoadElement(Node* node) {
671 Node* const object = NodeProperties::GetValueInput(node, 0); 773 Node* const object = NodeProperties::GetValueInput(node, 0);
672 Node* const index = NodeProperties::GetValueInput(node, 1); 774 Node* const index = NodeProperties::GetValueInput(node, 1);
673 Node* const effect = NodeProperties::GetEffectInput(node); 775 Node* const effect = NodeProperties::GetEffectInput(node);
674 Node* const control = NodeProperties::GetControlInput(node); 776 Node* const control = NodeProperties::GetControlInput(node);
675 AbstractState const* state = node_states_.Get(effect); 777 AbstractState const* state = node_states_.Get(effect);
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
839 state = state->KillField( 941 state = state->KillField(
840 object, FieldIndexOf(JSObject::kElementsOffset), zone()); 942 object, FieldIndexOf(JSObject::kElementsOffset), zone());
841 if (flags & GrowFastElementsFlag::kArrayObject) { 943 if (flags & GrowFastElementsFlag::kArrayObject) {
842 state = state->KillField( 944 state = state->KillField(
843 object, FieldIndexOf(JSArray::kLengthOffset), zone()); 945 object, FieldIndexOf(JSArray::kLengthOffset), zone());
844 } 946 }
845 break; 947 break;
846 } 948 }
847 case IrOpcode::kTransitionElementsKind: { 949 case IrOpcode::kTransitionElementsKind: {
848 Node* const object = NodeProperties::GetValueInput(current, 0); 950 Node* const object = NodeProperties::GetValueInput(current, 0);
849 state = state->KillField( 951 state = state->KillMaps(object, zone());
850 object, FieldIndexOf(HeapObject::kMapOffset), zone());
851 state = state->KillField( 952 state = state->KillField(
852 object, FieldIndexOf(JSObject::kElementsOffset), zone()); 953 object, FieldIndexOf(JSObject::kElementsOffset), zone());
853 break; 954 break;
854 } 955 }
855 case IrOpcode::kStoreField: { 956 case IrOpcode::kStoreField: {
856 FieldAccess const& access = FieldAccessOf(current->op()); 957 FieldAccess const& access = FieldAccessOf(current->op());
857 Node* const object = NodeProperties::GetValueInput(current, 0); 958 Node* const object = NodeProperties::GetValueInput(current, 0);
858 int field_index = FieldIndexOf(access); 959 int field_index = FieldIndexOf(access);
859 if (field_index < 0) return empty_state(); 960 if (field_index < 0) return empty_state();
860 state = state->KillField(object, field_index, zone()); 961 state = state->KillField(object, field_index, zone());
(...skipping 20 matching lines...) Expand all
881 } 982 }
882 } 983 }
883 return state; 984 return state;
884 } 985 }
885 986
886 // static 987 // static
887 int LoadElimination::FieldIndexOf(int offset) { 988 int LoadElimination::FieldIndexOf(int offset) {
888 DCHECK_EQ(0, offset % kPointerSize); 989 DCHECK_EQ(0, offset % kPointerSize);
889 int field_index = offset / kPointerSize; 990 int field_index = offset / kPointerSize;
890 if (field_index >= static_cast<int>(kMaxTrackedFields)) return -1; 991 if (field_index >= static_cast<int>(kMaxTrackedFields)) return -1;
891 return field_index; 992 DCHECK_LT(0, field_index);
993 return field_index - 1;
892 } 994 }
893 995
894 // static 996 // static
895 int LoadElimination::FieldIndexOf(FieldAccess const& access) { 997 int LoadElimination::FieldIndexOf(FieldAccess const& access) {
896 MachineRepresentation rep = access.machine_type.representation(); 998 MachineRepresentation rep = access.machine_type.representation();
897 switch (rep) { 999 switch (rep) {
898 case MachineRepresentation::kNone: 1000 case MachineRepresentation::kNone:
899 case MachineRepresentation::kBit: 1001 case MachineRepresentation::kBit:
900 UNREACHABLE(); 1002 UNREACHABLE();
901 break; 1003 break;
(...skipping 20 matching lines...) Expand all
922 DCHECK_EQ(kTaggedBase, access.base_is_tagged); 1024 DCHECK_EQ(kTaggedBase, access.base_is_tagged);
923 return FieldIndexOf(access.offset); 1025 return FieldIndexOf(access.offset);
924 } 1026 }
925 1027
926 CommonOperatorBuilder* LoadElimination::common() const { 1028 CommonOperatorBuilder* LoadElimination::common() const {
927 return jsgraph()->common(); 1029 return jsgraph()->common();
928 } 1030 }
929 1031
930 Graph* LoadElimination::graph() const { return jsgraph()->graph(); } 1032 Graph* LoadElimination::graph() const { return jsgraph()->graph(); }
931 1033
1034 Factory* LoadElimination::factory() const { return jsgraph()->factory(); }
1035
932 } // namespace compiler 1036 } // namespace compiler
933 } // namespace internal 1037 } // namespace internal
934 } // namespace v8 1038 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698