Commit 0902b5f4 authored by ishell's avatar ishell Committed by Commit bot

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}
parent 44c8c1bc
......@@ -628,14 +628,23 @@ class HCheckTable : public ZoneObject {
HValue* object = instr->object()->ActualValue();
HCheckTableEntry* entry = Find(object);
// 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);
if (entry->maps_->Contains(instr->original_map())) {
// If the object has the original map, it will be transitioned.
UniqueSet<Map>* maps = entry->maps_->Copy(zone());
maps->Remove(instr->original_map());
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 {
// Object does not have the given map, thus the transition is redundant.
instr->DeleteAndReplaceWith(object);
......
......@@ -7297,8 +7297,13 @@ class HTransitionElementsKind FINAL : public HTemplateInstruction<2> {
HValue* context() const { return OperandAt(1); }
Unique<Map> original_map() const { return original_map_; }
Unique<Map> transitioned_map() const { return transitioned_map_; }
ElementsKind from_kind() const { return from_kind_; }
ElementsKind to_kind() const { return to_kind_; }
ElementsKind from_kind() const {
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
......@@ -7314,29 +7319,33 @@ class HTransitionElementsKind FINAL : public HTemplateInstruction<2> {
int RedefinedOperandIndex() OVERRIDE { return 0; }
private:
HTransitionElementsKind(HValue* context,
HValue* object,
HTransitionElementsKind(HValue* context, HValue* object,
Handle<Map> original_map,
Handle<Map> transitioned_map)
: original_map_(Unique<Map>(original_map)),
transitioned_map_(Unique<Map>(transitioned_map)),
from_kind_(original_map->elements_kind()),
to_kind_(transitioned_map->elements_kind()) {
bit_field_(
FromElementsKindField::encode(original_map->elements_kind()) |
ToElementsKindField::encode(transitioned_map->elements_kind()) |
MapIsStableField::encode(transitioned_map->is_stable())) {
SetOperandAt(0, object);
SetOperandAt(1, context);
SetFlag(kUseGVN);
SetChangesFlag(kElementsKind);
if (!IsSimpleMapChangeTransition(from_kind_, to_kind_)) {
if (!IsSimpleMapChangeTransition(from_kind(), to_kind())) {
SetChangesFlag(kElementsPointer);
SetChangesFlag(kNewSpacePromotion);
}
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> transitioned_map_;
ElementsKind from_kind_;
ElementsKind to_kind_;
uint32_t bit_field_;
};
......
// 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]);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment