Incorrect handling of HTransitionElementsKind in hydrogen check elimination phase fixed.
BUG=chromium:460917 LOG=Y Review URL: https://codereview.chromium.org/1000893003 Cr-Commit-Position: refs/heads/master@{#27154}
This commit is contained in:
parent
44c8c1bcfe
commit
0902b5f4df
@ -628,14 +628,23 @@ class HCheckTable : public ZoneObject {
|
|||||||
HValue* object = instr->object()->ActualValue();
|
HValue* object = instr->object()->ActualValue();
|
||||||
HCheckTableEntry* entry = Find(object);
|
HCheckTableEntry* entry = Find(object);
|
||||||
// Can only learn more about an object that already has a known set of maps.
|
// Can only learn more about an object that already has a known set of maps.
|
||||||
if (entry == NULL) return;
|
if (entry == NULL) {
|
||||||
|
Kill(object);
|
||||||
|
return;
|
||||||
|
}
|
||||||
EnsureChecked(entry, object, instr);
|
EnsureChecked(entry, object, instr);
|
||||||
if (entry->maps_->Contains(instr->original_map())) {
|
if (entry->maps_->Contains(instr->original_map())) {
|
||||||
// If the object has the original map, it will be transitioned.
|
// If the object has the original map, it will be transitioned.
|
||||||
UniqueSet<Map>* maps = entry->maps_->Copy(zone());
|
UniqueSet<Map>* maps = entry->maps_->Copy(zone());
|
||||||
maps->Remove(instr->original_map());
|
maps->Remove(instr->original_map());
|
||||||
maps->Add(instr->transitioned_map(), zone());
|
maps->Add(instr->transitioned_map(), zone());
|
||||||
entry->maps_ = maps;
|
HCheckTableEntry::State state =
|
||||||
|
(entry->state_ == HCheckTableEntry::CHECKED_STABLE &&
|
||||||
|
instr->map_is_stable())
|
||||||
|
? HCheckTableEntry::CHECKED_STABLE
|
||||||
|
: HCheckTableEntry::CHECKED;
|
||||||
|
Kill(object);
|
||||||
|
Insert(object, NULL, maps, state);
|
||||||
} else {
|
} else {
|
||||||
// Object does not have the given map, thus the transition is redundant.
|
// Object does not have the given map, thus the transition is redundant.
|
||||||
instr->DeleteAndReplaceWith(object);
|
instr->DeleteAndReplaceWith(object);
|
||||||
|
@ -7297,8 +7297,13 @@ class HTransitionElementsKind FINAL : public HTemplateInstruction<2> {
|
|||||||
HValue* context() const { return OperandAt(1); }
|
HValue* context() const { return OperandAt(1); }
|
||||||
Unique<Map> original_map() const { return original_map_; }
|
Unique<Map> original_map() const { return original_map_; }
|
||||||
Unique<Map> transitioned_map() const { return transitioned_map_; }
|
Unique<Map> transitioned_map() const { return transitioned_map_; }
|
||||||
ElementsKind from_kind() const { return from_kind_; }
|
ElementsKind from_kind() const {
|
||||||
ElementsKind to_kind() const { return to_kind_; }
|
return FromElementsKindField::decode(bit_field_);
|
||||||
|
}
|
||||||
|
ElementsKind to_kind() const {
|
||||||
|
return ToElementsKindField::decode(bit_field_);
|
||||||
|
}
|
||||||
|
bool map_is_stable() const { return MapIsStableField::decode(bit_field_); }
|
||||||
|
|
||||||
std::ostream& PrintDataTo(std::ostream& os) const OVERRIDE; // NOLINT
|
std::ostream& PrintDataTo(std::ostream& os) const OVERRIDE; // NOLINT
|
||||||
|
|
||||||
@ -7314,29 +7319,33 @@ class HTransitionElementsKind FINAL : public HTemplateInstruction<2> {
|
|||||||
int RedefinedOperandIndex() OVERRIDE { return 0; }
|
int RedefinedOperandIndex() OVERRIDE { return 0; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HTransitionElementsKind(HValue* context,
|
HTransitionElementsKind(HValue* context, HValue* object,
|
||||||
HValue* object,
|
|
||||||
Handle<Map> original_map,
|
Handle<Map> original_map,
|
||||||
Handle<Map> transitioned_map)
|
Handle<Map> transitioned_map)
|
||||||
: original_map_(Unique<Map>(original_map)),
|
: original_map_(Unique<Map>(original_map)),
|
||||||
transitioned_map_(Unique<Map>(transitioned_map)),
|
transitioned_map_(Unique<Map>(transitioned_map)),
|
||||||
from_kind_(original_map->elements_kind()),
|
bit_field_(
|
||||||
to_kind_(transitioned_map->elements_kind()) {
|
FromElementsKindField::encode(original_map->elements_kind()) |
|
||||||
|
ToElementsKindField::encode(transitioned_map->elements_kind()) |
|
||||||
|
MapIsStableField::encode(transitioned_map->is_stable())) {
|
||||||
SetOperandAt(0, object);
|
SetOperandAt(0, object);
|
||||||
SetOperandAt(1, context);
|
SetOperandAt(1, context);
|
||||||
SetFlag(kUseGVN);
|
SetFlag(kUseGVN);
|
||||||
SetChangesFlag(kElementsKind);
|
SetChangesFlag(kElementsKind);
|
||||||
if (!IsSimpleMapChangeTransition(from_kind_, to_kind_)) {
|
if (!IsSimpleMapChangeTransition(from_kind(), to_kind())) {
|
||||||
SetChangesFlag(kElementsPointer);
|
SetChangesFlag(kElementsPointer);
|
||||||
SetChangesFlag(kNewSpacePromotion);
|
SetChangesFlag(kNewSpacePromotion);
|
||||||
}
|
}
|
||||||
set_representation(Representation::Tagged());
|
set_representation(Representation::Tagged());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class FromElementsKindField : public BitField<ElementsKind, 0, 5> {};
|
||||||
|
class ToElementsKindField : public BitField<ElementsKind, 5, 5> {};
|
||||||
|
class MapIsStableField : public BitField<bool, 10, 1> {};
|
||||||
|
|
||||||
Unique<Map> original_map_;
|
Unique<Map> original_map_;
|
||||||
Unique<Map> transitioned_map_;
|
Unique<Map> transitioned_map_;
|
||||||
ElementsKind from_kind_;
|
uint32_t bit_field_;
|
||||||
ElementsKind to_kind_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
35
test/mjsunit/regress/regress-460917.js
Normal file
35
test/mjsunit/regress/regress-460917.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// Copyright 2015 the V8 project authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
// Flags: --allow-natives-syntax
|
||||||
|
|
||||||
|
function boom(a1, a2) {
|
||||||
|
// Do something with a2 that needs a map check (for DOUBLE_ELEMENTS).
|
||||||
|
var s = a2[0];
|
||||||
|
// Emit a load that transitions a1 to FAST_ELEMENTS.
|
||||||
|
var t = a1[0];
|
||||||
|
// Emit a store to a2 that assumes DOUBLE_ELEMENTS.
|
||||||
|
// The map check is considered redundant and will be eliminated.
|
||||||
|
a2[0] = 0.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare type feedback for the "t = a1[0]" load: fast elements.
|
||||||
|
var fast_elem = new Array(1);
|
||||||
|
fast_elem[0] = "tagged";
|
||||||
|
boom(fast_elem, [1]);
|
||||||
|
|
||||||
|
// Prepare type feedback for the "a2[0] = 0.3" store: double elements.
|
||||||
|
var double_elem = new Array(1);
|
||||||
|
double_elem[0] = 0.1;
|
||||||
|
boom(double_elem, double_elem);
|
||||||
|
|
||||||
|
// Reset |double_elem| and go have a party.
|
||||||
|
double_elem = new Array(10);
|
||||||
|
double_elem[0] = 0.1;
|
||||||
|
|
||||||
|
%OptimizeFunctionOnNextCall(boom);
|
||||||
|
boom(double_elem, double_elem);
|
||||||
|
|
||||||
|
assertEquals(0.3, double_elem[0]);
|
||||||
|
assertEquals(undefined, double_elem[1]);
|
Loading…
Reference in New Issue
Block a user