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

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

Issue 2431563002: [turbofan] Track multiple maps for LoadElimination. (Closed)
Patch Set: REBASE. Address comment. Created 3 years, 11 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
« no previous file with comments | « src/compiler/load-elimination.h ('k') | src/compiler/simplified-operator.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 bool LoadElimination::AbstractMaps::Lookup(
326 Node* object, ZoneHandleSet<Map>* object_maps) const {
327 for (auto pair : info_for_node_) {
328 if (MustAlias(object, pair.first)) {
329 *object_maps = pair.second;
330 return true;
331 }
332 }
333 return false;
334 }
335
336 LoadElimination::AbstractMaps const* LoadElimination::AbstractMaps::Kill(
337 Node* object, Zone* zone) const {
338 for (auto pair : this->info_for_node_) {
339 if (MayAlias(object, pair.first)) {
340 AbstractMaps* that = new (zone) AbstractMaps(zone);
341 for (auto pair : this->info_for_node_) {
342 if (!MayAlias(object, pair.first)) that->info_for_node_.insert(pair);
343 }
344 return that;
345 }
346 }
347 return this;
348 }
349
350 void LoadElimination::AbstractMaps::Print() const {
351 for (auto pair : info_for_node_) {
352 PrintF(" #%d:%s\n", pair.first->id(), pair.first->op()->mnemonic());
353 OFStream os(stdout);
354 ZoneHandleSet<Map> const& maps = pair.second;
355 for (size_t i = 0; i < maps.size(); ++i) {
356 os << " - " << Brief(*maps[i]) << "\n";
357 }
358 }
359 }
360
323 bool LoadElimination::AbstractState::Equals(AbstractState const* that) const { 361 bool LoadElimination::AbstractState::Equals(AbstractState const* that) const {
324 if (this->checks_) { 362 if (this->checks_) {
325 if (!that->checks_ || !that->checks_->Equals(this->checks_)) { 363 if (!that->checks_ || !that->checks_->Equals(this->checks_)) {
326 return false; 364 return false;
327 } 365 }
328 } else if (that->checks_) { 366 } else if (that->checks_) {
329 return false; 367 return false;
330 } 368 }
331 if (this->elements_) { 369 if (this->elements_) {
332 if (!that->elements_ || !that->elements_->Equals(this->elements_)) { 370 if (!that->elements_ || !that->elements_->Equals(this->elements_)) {
333 return false; 371 return false;
334 } 372 }
335 } else if (that->elements_) { 373 } else if (that->elements_) {
336 return false; 374 return false;
337 } 375 }
338 for (size_t i = 0u; i < arraysize(fields_); ++i) { 376 for (size_t i = 0u; i < arraysize(fields_); ++i) {
339 AbstractField const* this_field = this->fields_[i]; 377 AbstractField const* this_field = this->fields_[i];
340 AbstractField const* that_field = that->fields_[i]; 378 AbstractField const* that_field = that->fields_[i];
341 if (this_field) { 379 if (this_field) {
342 if (!that_field || !that_field->Equals(this_field)) return false; 380 if (!that_field || !that_field->Equals(this_field)) return false;
343 } else if (that_field) { 381 } else if (that_field) {
344 return false; 382 return false;
345 } 383 }
346 } 384 }
385 if (this->maps_) {
386 if (!that->maps_ || !that->maps_->Equals(this->maps_)) {
387 return false;
388 }
389 } else if (that->maps_) {
390 return false;
391 }
347 return true; 392 return true;
348 } 393 }
349 394
350 void LoadElimination::AbstractState::Merge(AbstractState const* that, 395 void LoadElimination::AbstractState::Merge(AbstractState const* that,
351 Zone* zone) { 396 Zone* zone) {
352 // Merge the information we have about the checks. 397 // Merge the information we have about the checks.
353 if (this->checks_) { 398 if (this->checks_) {
354 this->checks_ = 399 this->checks_ =
355 that->checks_ ? that->checks_->Merge(this->checks_, zone) : nullptr; 400 that->checks_ ? that->checks_->Merge(this->checks_, zone) : nullptr;
356 } 401 }
357 402
358 // Merge the information we have about the elements. 403 // Merge the information we have about the elements.
359 if (this->elements_) { 404 if (this->elements_) {
360 this->elements_ = that->elements_ 405 this->elements_ = that->elements_
361 ? that->elements_->Merge(this->elements_, zone) 406 ? that->elements_->Merge(this->elements_, zone)
362 : nullptr; 407 : nullptr;
363 } 408 }
364 409
365 // Merge the information we have about the fields. 410 // Merge the information we have about the fields.
366 for (size_t i = 0; i < arraysize(fields_); ++i) { 411 for (size_t i = 0; i < arraysize(fields_); ++i) {
367 if (this->fields_[i]) { 412 if (this->fields_[i]) {
368 if (that->fields_[i]) { 413 if (that->fields_[i]) {
369 this->fields_[i] = this->fields_[i]->Merge(that->fields_[i], zone); 414 this->fields_[i] = this->fields_[i]->Merge(that->fields_[i], zone);
370 } else { 415 } else {
371 this->fields_[i] = nullptr; 416 this->fields_[i] = nullptr;
372 } 417 }
373 } 418 }
374 } 419 }
420
421 // Merge the information we have about the maps.
422 if (this->maps_) {
423 this->maps_ = that->maps_ ? that->maps_->Merge(this->maps_, zone) : nullptr;
424 }
375 } 425 }
376 426
377 Node* LoadElimination::AbstractState::LookupCheck(Node* node) const { 427 Node* LoadElimination::AbstractState::LookupCheck(Node* node) const {
378 return this->checks_ ? this->checks_->Lookup(node) : nullptr; 428 return this->checks_ ? this->checks_->Lookup(node) : nullptr;
379 } 429 }
380 430
381 LoadElimination::AbstractState const* LoadElimination::AbstractState::AddCheck( 431 LoadElimination::AbstractState const* LoadElimination::AbstractState::AddCheck(
382 Node* node, Zone* zone) const { 432 Node* node, Zone* zone) const {
383 AbstractState* that = new (zone) AbstractState(*this); 433 AbstractState* that = new (zone) AbstractState(*this);
384 if (that->checks_) { 434 if (that->checks_) {
385 that->checks_ = that->checks_->Extend(node, zone); 435 that->checks_ = that->checks_->Extend(node, zone);
386 } else { 436 } else {
387 that->checks_ = new (zone) AbstractChecks(node, zone); 437 that->checks_ = new (zone) AbstractChecks(node, zone);
388 } 438 }
389 return that; 439 return that;
390 } 440 }
391 441
442 bool LoadElimination::AbstractState::LookupMaps(
443 Node* object, ZoneHandleSet<Map>* object_map) const {
444 return this->maps_ && this->maps_->Lookup(object, object_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 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
474 return this_field->Lookup(object); 553 return this_field->Lookup(object);
475 } 554 }
476 return nullptr; 555 return nullptr;
477 } 556 }
478 557
479 void LoadElimination::AbstractState::Print() const { 558 void LoadElimination::AbstractState::Print() const {
480 if (checks_) { 559 if (checks_) {
481 PrintF(" checks:\n"); 560 PrintF(" checks:\n");
482 checks_->Print(); 561 checks_->Print();
483 } 562 }
563 if (maps_) {
564 PrintF(" maps:\n");
565 maps_->Print();
566 }
484 if (elements_) { 567 if (elements_) {
485 PrintF(" elements:\n"); 568 PrintF(" elements:\n");
486 elements_->Print(); 569 elements_->Print();
487 } 570 }
488 for (size_t i = 0; i < arraysize(fields_); ++i) { 571 for (size_t i = 0; i < arraysize(fields_); ++i) {
489 if (AbstractField const* const field = fields_[i]) { 572 if (AbstractField const* const field = fields_[i]) {
490 PrintF(" field %zu:\n", i); 573 PrintF(" field %zu:\n", i);
491 field->Print(); 574 field->Print();
492 } 575 }
493 } 576 }
(...skipping 19 matching lines...) Expand all
513 if (state == nullptr) return NoChange(); 596 if (state == nullptr) return NoChange();
514 if (Node* const check = state->LookupCheck(node)) { 597 if (Node* const check = state->LookupCheck(node)) {
515 ReplaceWithValue(node, check, effect); 598 ReplaceWithValue(node, check, effect);
516 return Replace(check); 599 return Replace(check);
517 } 600 }
518 state = state->AddCheck(node, zone()); 601 state = state->AddCheck(node, zone());
519 return UpdateState(node, state); 602 return UpdateState(node, state);
520 } 603 }
521 604
522 Reduction LoadElimination::ReduceCheckMaps(Node* node) { 605 Reduction LoadElimination::ReduceCheckMaps(Node* node) {
606 ZoneHandleSet<Map> const maps = CheckMapsParametersOf(node->op()).maps();
523 Node* const object = NodeProperties::GetValueInput(node, 0); 607 Node* const object = NodeProperties::GetValueInput(node, 0);
524 Node* const effect = NodeProperties::GetEffectInput(node); 608 Node* const effect = NodeProperties::GetEffectInput(node);
525 AbstractState const* state = node_states_.Get(effect); 609 AbstractState const* state = node_states_.Get(effect);
526 if (state == nullptr) return NoChange(); 610 if (state == nullptr) return NoChange();
527 int const map_input_count = node->op()->ValueInputCount() - 1; 611 ZoneHandleSet<Map> object_maps;
528 if (Node* const object_map = 612 if (state->LookupMaps(object, &object_maps)) {
529 state->LookupField(object, FieldIndexOf(HeapObject::kMapOffset))) { 613 if (maps.contains(object_maps)) return Replace(effect);
530 for (int i = 0; i < map_input_count; ++i) { 614 state = state->KillMaps(object, zone());
531 Node* map = NodeProperties::GetValueInput(node, 1 + i); 615 // TODO(turbofan): Compute the intersection.
532 if (map == object_map) return Replace(effect);
533 }
534 } 616 }
535 if (map_input_count == 1) { 617 state = state->AddMaps(object, maps, zone());
536 Node* const map0 = NodeProperties::GetValueInput(node, 1);
537 state = state->AddField(object, FieldIndexOf(HeapObject::kMapOffset), map0,
538 zone());
539 }
540 return UpdateState(node, state); 618 return UpdateState(node, state);
541 } 619 }
542 620
543 Reduction LoadElimination::ReduceEnsureWritableFastElements(Node* node) { 621 Reduction LoadElimination::ReduceEnsureWritableFastElements(Node* node) {
544 Node* const object = NodeProperties::GetValueInput(node, 0); 622 Node* const object = NodeProperties::GetValueInput(node, 0);
545 Node* const elements = NodeProperties::GetValueInput(node, 1); 623 Node* const elements = NodeProperties::GetValueInput(node, 1);
546 Node* const effect = NodeProperties::GetEffectInput(node); 624 Node* const effect = NodeProperties::GetEffectInput(node);
547 AbstractState const* state = node_states_.Get(effect); 625 AbstractState const* state = node_states_.Get(effect);
548 if (state == nullptr) return NoChange(); 626 if (state == nullptr) return NoChange();
549 Node* fixed_array_map = jsgraph()->FixedArrayMapConstant();
550 if (Node* const elements_map =
551 state->LookupField(elements, FieldIndexOf(HeapObject::kMapOffset))) {
552 // Check if the {elements} already have the fixed array map. 627 // Check if the {elements} already have the fixed array map.
553 if (elements_map == fixed_array_map) { 628 ZoneHandleSet<Map> elements_maps;
554 ReplaceWithValue(node, elements, effect); 629 ZoneHandleSet<Map> fixed_array_maps(factory()->fixed_array_map());
555 return Replace(elements); 630 if (state->LookupMaps(elements, &elements_maps) &&
556 } 631 fixed_array_maps.contains(elements_maps)) {
632 ReplaceWithValue(node, elements, effect);
633 return Replace(elements);
557 } 634 }
558 // We know that the resulting elements have the fixed array map. 635 // We know that the resulting elements have the fixed array map.
559 state = state->AddField(node, FieldIndexOf(HeapObject::kMapOffset), 636 state = state->AddMaps(node, fixed_array_maps, zone());
560 fixed_array_map, zone());
561 // Kill the previous elements on {object}. 637 // Kill the previous elements on {object}.
562 state = 638 state =
563 state->KillField(object, FieldIndexOf(JSObject::kElementsOffset), zone()); 639 state->KillField(object, FieldIndexOf(JSObject::kElementsOffset), zone());
564 // Add the new elements on {object}. 640 // Add the new elements on {object}.
565 state = state->AddField(object, FieldIndexOf(JSObject::kElementsOffset), node, 641 state = state->AddField(object, FieldIndexOf(JSObject::kElementsOffset), node,
566 zone()); 642 zone());
567 return UpdateState(node, state); 643 return UpdateState(node, state);
568 } 644 }
569 645
570 Reduction LoadElimination::ReduceMaybeGrowFastElements(Node* node) { 646 Reduction LoadElimination::ReduceMaybeGrowFastElements(Node* node) {
571 GrowFastElementsFlags flags = GrowFastElementsFlagsOf(node->op()); 647 GrowFastElementsFlags flags = GrowFastElementsFlagsOf(node->op());
572 Node* const object = NodeProperties::GetValueInput(node, 0); 648 Node* const object = NodeProperties::GetValueInput(node, 0);
573 Node* const effect = NodeProperties::GetEffectInput(node); 649 Node* const effect = NodeProperties::GetEffectInput(node);
574 AbstractState const* state = node_states_.Get(effect); 650 AbstractState const* state = node_states_.Get(effect);
575 if (state == nullptr) return NoChange(); 651 if (state == nullptr) return NoChange();
576 if (flags & GrowFastElementsFlag::kDoubleElements) { 652 if (flags & GrowFastElementsFlag::kDoubleElements) {
577 // We know that the resulting elements have the fixed double array map. 653 // We know that the resulting elements have the fixed double array map.
578 Node* fixed_double_array_map = jsgraph()->FixedDoubleArrayMapConstant(); 654 state = state->AddMaps(
579 state = state->AddField(node, FieldIndexOf(HeapObject::kMapOffset), 655 node, ZoneHandleSet<Map>(factory()->fixed_double_array_map()), zone());
580 fixed_double_array_map, zone());
581 } else { 656 } else {
582 // We know that the resulting elements have the fixed array map. 657 // We know that the resulting elements have the fixed array map.
583 Node* fixed_array_map = jsgraph()->FixedArrayMapConstant(); 658 state = state->AddMaps(
584 state = state->AddField(node, FieldIndexOf(HeapObject::kMapOffset), 659 node, ZoneHandleSet<Map>(factory()->fixed_array_map()), zone());
585 fixed_array_map, zone());
586 } 660 }
587 if (flags & GrowFastElementsFlag::kArrayObject) { 661 if (flags & GrowFastElementsFlag::kArrayObject) {
588 // Kill the previous Array::length on {object}. 662 // Kill the previous Array::length on {object}.
589 state = 663 state =
590 state->KillField(object, FieldIndexOf(JSArray::kLengthOffset), zone()); 664 state->KillField(object, FieldIndexOf(JSArray::kLengthOffset), zone());
591 } 665 }
592 // Kill the previous elements on {object}. 666 // Kill the previous elements on {object}.
593 state = 667 state =
594 state->KillField(object, FieldIndexOf(JSObject::kElementsOffset), zone()); 668 state->KillField(object, FieldIndexOf(JSObject::kElementsOffset), zone());
595 // Add the new elements on {object}. 669 // Add the new elements on {object}.
596 state = state->AddField(object, FieldIndexOf(JSObject::kElementsOffset), node, 670 state = state->AddField(object, FieldIndexOf(JSObject::kElementsOffset), node,
597 zone()); 671 zone());
598 return UpdateState(node, state); 672 return UpdateState(node, state);
599 } 673 }
600 674
601 Reduction LoadElimination::ReduceTransitionElementsKind(Node* node) { 675 Reduction LoadElimination::ReduceTransitionElementsKind(Node* node) {
676 ElementsTransition transition = ElementsTransitionOf(node->op());
602 Node* const object = NodeProperties::GetValueInput(node, 0); 677 Node* const object = NodeProperties::GetValueInput(node, 0);
603 Node* const source_map = NodeProperties::GetValueInput(node, 1); 678 Handle<Map> source_map(transition.source());
604 Node* const target_map = NodeProperties::GetValueInput(node, 2); 679 Handle<Map> target_map(transition.target());
605 Node* const effect = NodeProperties::GetEffectInput(node); 680 Node* const effect = NodeProperties::GetEffectInput(node);
606 AbstractState const* state = node_states_.Get(effect); 681 AbstractState const* state = node_states_.Get(effect);
607 if (state == nullptr) return NoChange(); 682 if (state == nullptr) return NoChange();
608 if (Node* const object_map = 683 ZoneHandleSet<Map> object_maps;
609 state->LookupField(object, FieldIndexOf(HeapObject::kMapOffset))) { 684 if (state->LookupMaps(object, &object_maps)) {
610 if (target_map == object_map) { 685 if (ZoneHandleSet<Map>(target_map).contains(object_maps)) {
611 // The {object} already has the {target_map}, so this TransitionElements 686 // The {object} already has the {target_map}, so this TransitionElements
612 // {node} is fully redundant (independent of what {source_map} is). 687 // {node} is fully redundant (independent of what {source_map} is).
613 return Replace(effect); 688 return Replace(effect);
614 } 689 }
615 state = 690 if (object_maps.contains(ZoneHandleSet<Map>(source_map))) {
616 state->KillField(object, FieldIndexOf(HeapObject::kMapOffset), zone()); 691 object_maps.remove(source_map, zone());
617 if (source_map == object_map) { 692 object_maps.insert(target_map, zone());
618 state = state->AddField(object, FieldIndexOf(HeapObject::kMapOffset), 693 state = state->KillMaps(object, zone());
619 target_map, zone()); 694 state = state->AddMaps(object, object_maps, zone());
620 } 695 }
621 } else { 696 } else {
622 state = 697 state = state->KillMaps(object, zone());
623 state->KillField(object, FieldIndexOf(HeapObject::kMapOffset), zone());
624 } 698 }
625 ElementsTransition transition = ElementsTransitionOf(node->op()); 699 switch (transition.mode()) {
626 switch (transition) {
627 case ElementsTransition::kFastTransition: 700 case ElementsTransition::kFastTransition:
628 break; 701 break;
629 case ElementsTransition::kSlowTransition: 702 case ElementsTransition::kSlowTransition:
630 // Kill the elements as well. 703 // Kill the elements as well.
631 state = state->KillField(object, FieldIndexOf(JSObject::kElementsOffset), 704 state = state->KillField(object, FieldIndexOf(JSObject::kElementsOffset),
632 zone()); 705 zone());
633 break; 706 break;
634 } 707 }
635 return UpdateState(node, state); 708 return UpdateState(node, state);
636 } 709 }
637 710
638 Reduction LoadElimination::ReduceLoadField(Node* node) { 711 Reduction LoadElimination::ReduceLoadField(Node* node) {
639 FieldAccess const& access = FieldAccessOf(node->op()); 712 FieldAccess const& access = FieldAccessOf(node->op());
640 Node* const object = NodeProperties::GetValueInput(node, 0); 713 Node* const object = NodeProperties::GetValueInput(node, 0);
641 Node* const effect = NodeProperties::GetEffectInput(node); 714 Node* const effect = NodeProperties::GetEffectInput(node);
642 Node* const control = NodeProperties::GetControlInput(node); 715 Node* const control = NodeProperties::GetControlInput(node);
643 AbstractState const* state = node_states_.Get(effect); 716 AbstractState const* state = node_states_.Get(effect);
644 if (state == nullptr) return NoChange(); 717 if (state == nullptr) return NoChange();
645 int field_index = FieldIndexOf(access); 718 if (access.offset == HeapObject::kMapOffset &&
646 if (field_index >= 0) { 719 access.base_is_tagged == kTaggedBase) {
647 if (Node* replacement = state->LookupField(object, field_index)) { 720 DCHECK(IsAnyTagged(access.machine_type.representation()));
648 // Make sure we don't resurrect dead {replacement} nodes. 721 ZoneHandleSet<Map> object_maps;
649 if (!replacement->IsDead()) { 722 if (state->LookupMaps(object, &object_maps) && object_maps.size() == 1) {
650 // We might need to guard the {replacement} if the type of the 723 Node* value = jsgraph()->HeapConstant(object_maps[0]);
651 // {node} is more precise than the type of the {replacement}. 724 ReplaceWithValue(node, value, effect);
652 Type* const node_type = NodeProperties::GetType(node); 725 return Replace(value);
653 if (!NodeProperties::GetType(replacement)->Is(node_type)) { 726 }
654 replacement = graph()->NewNode(common()->TypeGuard(node_type), 727 } else {
655 replacement, control); 728 int field_index = FieldIndexOf(access);
729 if (field_index >= 0) {
730 if (Node* replacement = state->LookupField(object, field_index)) {
731 // Make sure we don't resurrect dead {replacement} nodes.
732 if (!replacement->IsDead()) {
733 // We might need to guard the {replacement} if the type of the
734 // {node} is more precise than the type of the {replacement}.
735 Type* const node_type = NodeProperties::GetType(node);
736 if (!NodeProperties::GetType(replacement)->Is(node_type)) {
737 replacement = graph()->NewNode(common()->TypeGuard(node_type),
738 replacement, control);
739 }
740 ReplaceWithValue(node, replacement, effect);
741 return Replace(replacement);
656 } 742 }
657 ReplaceWithValue(node, replacement, effect);
658 return Replace(replacement);
659 } 743 }
744 state = state->AddField(object, field_index, node, zone());
660 } 745 }
661 state = state->AddField(object, field_index, node, zone());
662 } 746 }
663 return UpdateState(node, state); 747 return UpdateState(node, state);
664 } 748 }
665 749
666 Reduction LoadElimination::ReduceStoreField(Node* node) { 750 Reduction LoadElimination::ReduceStoreField(Node* node) {
667 FieldAccess const& access = FieldAccessOf(node->op()); 751 FieldAccess const& access = FieldAccessOf(node->op());
668 Node* const object = NodeProperties::GetValueInput(node, 0); 752 Node* const object = NodeProperties::GetValueInput(node, 0);
669 Node* const new_value = NodeProperties::GetValueInput(node, 1); 753 Node* const new_value = NodeProperties::GetValueInput(node, 1);
670 Node* const effect = NodeProperties::GetEffectInput(node); 754 Node* const effect = NodeProperties::GetEffectInput(node);
671 AbstractState const* state = node_states_.Get(effect); 755 AbstractState const* state = node_states_.Get(effect);
672 if (state == nullptr) return NoChange(); 756 if (state == nullptr) return NoChange();
673 int field_index = FieldIndexOf(access); 757 if (access.offset == HeapObject::kMapOffset &&
674 if (field_index >= 0) { 758 access.base_is_tagged == kTaggedBase) {
675 Node* const old_value = state->LookupField(object, field_index); 759 DCHECK(IsAnyTagged(access.machine_type.representation()));
676 if (old_value == new_value) { 760 // Kill all potential knowledge about the {object}s map.
677 // This store is fully redundant. 761 state = state->KillMaps(object, zone());
678 return Replace(effect); 762 Type* const new_value_type = NodeProperties::GetType(new_value);
763 if (new_value_type->IsHeapConstant()) {
764 // Record the new {object} map information.
765 ZoneHandleSet<Map> object_maps(
766 Handle<Map>::cast(new_value_type->AsHeapConstant()->Value()));
767 state = state->AddMaps(object, object_maps, zone());
679 } 768 }
680 // Kill all potentially aliasing fields and record the new value.
681 state = state->KillField(object, field_index, zone());
682 state = state->AddField(object, field_index, new_value, zone());
683 } else { 769 } else {
684 // Unsupported StoreField operator. 770 int field_index = FieldIndexOf(access);
685 state = state->KillFields(object, zone()); 771 if (field_index >= 0) {
772 Node* const old_value = state->LookupField(object, field_index);
773 if (old_value == new_value) {
774 // This store is fully redundant.
775 return Replace(effect);
776 }
777 // Kill all potentially aliasing fields and record the new value.
778 state = state->KillField(object, field_index, zone());
779 state = state->AddField(object, field_index, new_value, zone());
780 } else {
781 // Unsupported StoreField operator.
782 state = state->KillFields(object, zone());
783 }
686 } 784 }
687 return UpdateState(node, state); 785 return UpdateState(node, state);
688 } 786 }
689 787
690 Reduction LoadElimination::ReduceLoadElement(Node* node) { 788 Reduction LoadElimination::ReduceLoadElement(Node* node) {
691 Node* const object = NodeProperties::GetValueInput(node, 0); 789 Node* const object = NodeProperties::GetValueInput(node, 0);
692 Node* const index = NodeProperties::GetValueInput(node, 1); 790 Node* const index = NodeProperties::GetValueInput(node, 1);
693 Node* const effect = NodeProperties::GetEffectInput(node); 791 Node* const effect = NodeProperties::GetEffectInput(node);
694 Node* const control = NodeProperties::GetControlInput(node); 792 Node* const control = NodeProperties::GetControlInput(node);
695 AbstractState const* state = node_states_.Get(effect); 793 AbstractState const* state = node_states_.Get(effect);
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
858 Node* const object = NodeProperties::GetValueInput(current, 0); 956 Node* const object = NodeProperties::GetValueInput(current, 0);
859 state = state->KillField( 957 state = state->KillField(
860 object, FieldIndexOf(JSObject::kElementsOffset), zone()); 958 object, FieldIndexOf(JSObject::kElementsOffset), zone());
861 if (flags & GrowFastElementsFlag::kArrayObject) { 959 if (flags & GrowFastElementsFlag::kArrayObject) {
862 state = state->KillField( 960 state = state->KillField(
863 object, FieldIndexOf(JSArray::kLengthOffset), zone()); 961 object, FieldIndexOf(JSArray::kLengthOffset), zone());
864 } 962 }
865 break; 963 break;
866 } 964 }
867 case IrOpcode::kTransitionElementsKind: { 965 case IrOpcode::kTransitionElementsKind: {
966 ElementsTransition transition = ElementsTransitionOf(current->op());
868 Node* const object = NodeProperties::GetValueInput(current, 0); 967 Node* const object = NodeProperties::GetValueInput(current, 0);
869 Node* const target_map = NodeProperties::GetValueInput(current, 2); 968 ZoneHandleSet<Map> object_maps;
870 Node* const object_map = state->LookupField( 969 if (!state->LookupMaps(object, &object_maps) ||
871 object, FieldIndexOf(HeapObject::kMapOffset)); 970 !ZoneHandleSet<Map>(transition.target())
872 if (target_map != object_map) { 971 .contains(object_maps)) {
873 state = state->KillField( 972 state = state->KillMaps(object, zone());
874 object, FieldIndexOf(HeapObject::kMapOffset), zone());
875 state = state->KillField( 973 state = state->KillField(
876 object, FieldIndexOf(JSObject::kElementsOffset), zone()); 974 object, FieldIndexOf(JSObject::kElementsOffset), zone());
877 } 975 }
878 break; 976 break;
879 } 977 }
880 case IrOpcode::kStoreField: { 978 case IrOpcode::kStoreField: {
881 FieldAccess const& access = FieldAccessOf(current->op()); 979 FieldAccess const& access = FieldAccessOf(current->op());
882 Node* const object = NodeProperties::GetValueInput(current, 0); 980 Node* const object = NodeProperties::GetValueInput(current, 0);
883 int field_index = FieldIndexOf(access); 981 if (access.offset == HeapObject::kMapOffset) {
884 if (field_index < 0) { 982 // Invalidate what we know about the {object}s map.
885 state = state->KillFields(object, zone()); 983 state = state->KillMaps(object, zone());
886 } else { 984 } else {
887 state = state->KillField(object, field_index, zone()); 985 int field_index = FieldIndexOf(access);
986 if (field_index < 0) {
987 state = state->KillFields(object, zone());
988 } else {
989 state = state->KillField(object, field_index, zone());
990 }
888 } 991 }
889 break; 992 break;
890 } 993 }
891 case IrOpcode::kStoreElement: { 994 case IrOpcode::kStoreElement: {
892 Node* const object = NodeProperties::GetValueInput(current, 0); 995 Node* const object = NodeProperties::GetValueInput(current, 0);
893 Node* const index = NodeProperties::GetValueInput(current, 1); 996 Node* const index = NodeProperties::GetValueInput(current, 1);
894 state = state->KillElement(object, index, zone()); 997 state = state->KillElement(object, index, zone());
895 break; 998 break;
896 } 999 }
897 case IrOpcode::kStoreBuffer: 1000 case IrOpcode::kStoreBuffer:
(...skipping 11 matching lines...) Expand all
909 } 1012 }
910 } 1013 }
911 return state; 1014 return state;
912 } 1015 }
913 1016
914 // static 1017 // static
915 int LoadElimination::FieldIndexOf(int offset) { 1018 int LoadElimination::FieldIndexOf(int offset) {
916 DCHECK_EQ(0, offset % kPointerSize); 1019 DCHECK_EQ(0, offset % kPointerSize);
917 int field_index = offset / kPointerSize; 1020 int field_index = offset / kPointerSize;
918 if (field_index >= static_cast<int>(kMaxTrackedFields)) return -1; 1021 if (field_index >= static_cast<int>(kMaxTrackedFields)) return -1;
919 return field_index; 1022 DCHECK_LT(0, field_index);
1023 return field_index - 1;
920 } 1024 }
921 1025
922 // static 1026 // static
923 int LoadElimination::FieldIndexOf(FieldAccess const& access) { 1027 int LoadElimination::FieldIndexOf(FieldAccess const& access) {
924 MachineRepresentation rep = access.machine_type.representation(); 1028 MachineRepresentation rep = access.machine_type.representation();
925 switch (rep) { 1029 switch (rep) {
926 case MachineRepresentation::kNone: 1030 case MachineRepresentation::kNone:
927 case MachineRepresentation::kBit: 1031 case MachineRepresentation::kBit:
928 case MachineRepresentation::kSimd128: 1032 case MachineRepresentation::kSimd128:
929 UNREACHABLE(); 1033 UNREACHABLE();
(...skipping 25 matching lines...) Expand all
955 } 1059 }
956 return FieldIndexOf(access.offset); 1060 return FieldIndexOf(access.offset);
957 } 1061 }
958 1062
959 CommonOperatorBuilder* LoadElimination::common() const { 1063 CommonOperatorBuilder* LoadElimination::common() const {
960 return jsgraph()->common(); 1064 return jsgraph()->common();
961 } 1065 }
962 1066
963 Graph* LoadElimination::graph() const { return jsgraph()->graph(); } 1067 Graph* LoadElimination::graph() const { return jsgraph()->graph(); }
964 1068
1069 Factory* LoadElimination::factory() const { return jsgraph()->factory(); }
1070
965 } // namespace compiler 1071 } // namespace compiler
966 } // namespace internal 1072 } // namespace internal
967 } // namespace v8 1073 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/load-elimination.h ('k') | src/compiler/simplified-operator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698