summaryrefslogtreecommitdiff
path: root/deps/v8/src/hydrogen-instructions.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/hydrogen-instructions.cc')
-rw-r--r--deps/v8/src/hydrogen-instructions.cc502
1 files changed, 324 insertions, 178 deletions
diff --git a/deps/v8/src/hydrogen-instructions.cc b/deps/v8/src/hydrogen-instructions.cc
index 0192a763f0..0e6ea00058 100644
--- a/deps/v8/src/hydrogen-instructions.cc
+++ b/deps/v8/src/hydrogen-instructions.cc
@@ -85,6 +85,81 @@ void HValue::AssumeRepresentation(Representation r) {
}
+void HValue::InferRepresentation(HInferRepresentation* h_infer) {
+ ASSERT(CheckFlag(kFlexibleRepresentation));
+ Representation new_rep = RepresentationFromInputs();
+ UpdateRepresentation(new_rep, h_infer, "inputs");
+ new_rep = RepresentationFromUses();
+ UpdateRepresentation(new_rep, h_infer, "uses");
+}
+
+
+Representation HValue::RepresentationFromUses() {
+ if (HasNoUses()) return Representation::None();
+
+ // Array of use counts for each representation.
+ int use_count[Representation::kNumRepresentations] = { 0 };
+
+ for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
+ HValue* use = it.value();
+ Representation rep = use->observed_input_representation(it.index());
+ if (rep.IsNone()) continue;
+ if (FLAG_trace_representation) {
+ PrintF("#%d %s is used by #%d %s as %s%s\n",
+ id(), Mnemonic(), use->id(), use->Mnemonic(), rep.Mnemonic(),
+ (use->CheckFlag(kTruncatingToInt32) ? "-trunc" : ""));
+ }
+ use_count[rep.kind()] += use->LoopWeight();
+ }
+ if (IsPhi()) HPhi::cast(this)->AddIndirectUsesTo(&use_count[0]);
+ int tagged_count = use_count[Representation::kTagged];
+ int double_count = use_count[Representation::kDouble];
+ int int32_count = use_count[Representation::kInteger32];
+
+ if (tagged_count > 0) return Representation::Tagged();
+ if (double_count > 0) return Representation::Double();
+ if (int32_count > 0) return Representation::Integer32();
+
+ return Representation::None();
+}
+
+
+void HValue::UpdateRepresentation(Representation new_rep,
+ HInferRepresentation* h_infer,
+ const char* reason) {
+ Representation r = representation();
+ if (new_rep.is_more_general_than(r)) {
+ // When an HConstant is marked "not convertible to integer", then
+ // never try to represent it as an integer.
+ if (new_rep.IsInteger32() && !IsConvertibleToInteger()) {
+ new_rep = Representation::Tagged();
+ if (FLAG_trace_representation) {
+ PrintF("Changing #%d %s representation %s -> %s because it's NCTI"
+ " (%s want i)\n",
+ id(), Mnemonic(), r.Mnemonic(), new_rep.Mnemonic(), reason);
+ }
+ } else {
+ if (FLAG_trace_representation) {
+ PrintF("Changing #%d %s representation %s -> %s based on %s\n",
+ id(), Mnemonic(), r.Mnemonic(), new_rep.Mnemonic(), reason);
+ }
+ }
+ ChangeRepresentation(new_rep);
+ AddDependantsToWorklist(h_infer);
+ }
+}
+
+
+void HValue::AddDependantsToWorklist(HInferRepresentation* h_infer) {
+ for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
+ h_infer->AddToWorklist(it.value());
+ }
+ for (int i = 0; i < OperandCount(); ++i) {
+ h_infer->AddToWorklist(OperandAt(i));
+ }
+}
+
+
static int32_t ConvertAndSetOverflow(int64_t result, bool* overflow) {
if (result > kMaxInt) {
*overflow = true;
@@ -301,6 +376,7 @@ HUseListNode* HUseListNode::tail() {
bool HValue::CheckUsesForFlag(Flag f) {
for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
+ if (it.value()->IsSimulate()) continue;
if (!it.value()->CheckFlag(f)) return false;
}
return true;
@@ -707,7 +783,7 @@ void HCallGlobal::PrintDataTo(StringStream* stream) {
void HCallKnownGlobal::PrintDataTo(StringStream* stream) {
- stream->Add("o ", target()->shared()->DebugName());
+ stream->Add("%o ", target()->shared()->DebugName());
stream->Add("#%d", argument_count());
}
@@ -764,6 +840,24 @@ void HReturn::PrintDataTo(StringStream* stream) {
}
+Representation HBranch::observed_input_representation(int index) {
+ static const ToBooleanStub::Types tagged_types(
+ ToBooleanStub::UNDEFINED |
+ ToBooleanStub::NULL_TYPE |
+ ToBooleanStub::SPEC_OBJECT |
+ ToBooleanStub::STRING);
+ if (expected_input_types_.ContainsAnyOf(tagged_types)) {
+ return Representation::Tagged();
+ } else if (expected_input_types_.Contains(ToBooleanStub::HEAP_NUMBER)) {
+ return Representation::Double();
+ } else if (expected_input_types_.Contains(ToBooleanStub::SMI)) {
+ return Representation::Integer32();
+ } else {
+ return Representation::None();
+ }
+}
+
+
void HCompareMap::PrintDataTo(StringStream* stream) {
value()->PrintNameTo(stream);
stream->Add(" (%p)", *map());
@@ -859,16 +953,6 @@ void HLoadFieldByIndex::PrintDataTo(StringStream* stream) {
}
-HValue* HConstant::Canonicalize() {
- return HasNoUses() ? NULL : this;
-}
-
-
-HValue* HTypeof::Canonicalize() {
- return HasNoUses() ? NULL : this;
-}
-
-
HValue* HBitwise::Canonicalize() {
if (!representation().IsInteger32()) return this;
// If x is an int32, then x & -1 == x, x | 0 == x and x ^ 0 == x.
@@ -1058,6 +1142,13 @@ void HCheckInstanceType::GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag) {
}
+void HLoadElements::PrintDataTo(StringStream* stream) {
+ value()->PrintNameTo(stream);
+ stream->Add(" ");
+ typecheck()->PrintNameTo(stream);
+}
+
+
void HCheckMaps::PrintDataTo(StringStream* stream) {
value()->PrintNameTo(stream);
stream->Add(" [%p", *map_set()->first());
@@ -1342,15 +1433,11 @@ void HPhi::InitRealUses(int phi_id) {
for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
HValue* value = it.value();
if (!value->IsPhi()) {
- Representation rep = value->ObservedInputRepresentation(it.index());
+ Representation rep = value->observed_input_representation(it.index());
non_phi_uses_[rep.kind()] += value->LoopWeight();
if (FLAG_trace_representation) {
- PrintF("%d %s is used by %d %s as %s\n",
- this->id(),
- this->Mnemonic(),
- value->id(),
- value->Mnemonic(),
- rep.Mnemonic());
+ PrintF("#%d Phi is used by real #%d %s as %s\n",
+ id(), value->id(), value->Mnemonic(), rep.Mnemonic());
}
}
}
@@ -1359,11 +1446,8 @@ void HPhi::InitRealUses(int phi_id) {
void HPhi::AddNonPhiUsesFrom(HPhi* other) {
if (FLAG_trace_representation) {
- PrintF("adding to %d %s uses of %d %s: i%d d%d t%d\n",
- this->id(),
- this->Mnemonic(),
- other->id(),
- other->Mnemonic(),
+ PrintF("adding to #%d Phi uses of #%d Phi: i%d d%d t%d\n",
+ id(), other->id(),
other->non_phi_uses_[Representation::kInteger32],
other->non_phi_uses_[Representation::kDouble],
other->non_phi_uses_[Representation::kTagged]);
@@ -1382,9 +1466,20 @@ void HPhi::AddIndirectUsesTo(int* dest) {
}
-void HPhi::ResetInteger32Uses() {
- non_phi_uses_[Representation::kInteger32] = 0;
- indirect_uses_[Representation::kInteger32] = 0;
+void HSimulate::MergeInto(HSimulate* other) {
+ for (int i = 0; i < values_.length(); ++i) {
+ HValue* value = values_[i];
+ if (HasAssignedIndexAt(i)) {
+ other->AddAssignedValue(GetAssignedIndexAt(i), value);
+ } else {
+ if (other->pop_count_ > 0) {
+ other->pop_count_--;
+ } else {
+ other->AddPushedValue(value);
+ }
+ }
+ }
+ other->pop_count_ += pop_count();
}
@@ -1393,7 +1488,7 @@ void HSimulate::PrintDataTo(StringStream* stream) {
if (pop_count_ > 0) stream->Add(" pop %d", pop_count_);
if (values_.length() > 0) {
if (pop_count_ > 0) stream->Add(" /");
- for (int i = 0; i < values_.length(); ++i) {
+ for (int i = values_.length() - 1; i >= 0; --i) {
if (i > 0) stream->Add(",");
if (HasAssignedIndexAt(i)) {
stream->Add(" var[%d] = ", GetAssignedIndexAt(i));
@@ -1432,7 +1527,6 @@ HConstant::HConstant(Handle<Object> handle, Representation r)
: handle_(handle),
has_int32_value_(false),
has_double_value_(false) {
- set_representation(r);
SetFlag(kUseGVN);
if (handle_->IsNumber()) {
double n = handle_->Number();
@@ -1441,6 +1535,16 @@ HConstant::HConstant(Handle<Object> handle, Representation r)
double_value_ = n;
has_double_value_ = true;
}
+ if (r.IsNone()) {
+ if (has_int32_value_) {
+ r = Representation::Integer32();
+ } else if (has_double_value_) {
+ r = Representation::Double();
+ } else {
+ r = Representation::Tagged();
+ }
+ }
+ set_representation(r);
}
@@ -1539,6 +1643,60 @@ void HBinaryOperation::PrintDataTo(StringStream* stream) {
}
+void HBinaryOperation::InferRepresentation(HInferRepresentation* h_infer) {
+ ASSERT(CheckFlag(kFlexibleRepresentation));
+ Representation new_rep = RepresentationFromInputs();
+ UpdateRepresentation(new_rep, h_infer, "inputs");
+ // When the operation has information about its own output type, don't look
+ // at uses.
+ if (!observed_output_representation_.IsNone()) return;
+ new_rep = RepresentationFromUses();
+ UpdateRepresentation(new_rep, h_infer, "uses");
+}
+
+
+Representation HBinaryOperation::RepresentationFromInputs() {
+ // Determine the worst case of observed input representations and
+ // the currently assumed output representation.
+ Representation rep = representation();
+ if (observed_output_representation_.is_more_general_than(rep)) {
+ rep = observed_output_representation_;
+ }
+ for (int i = 1; i <= 2; ++i) {
+ Representation input_rep = observed_input_representation(i);
+ if (input_rep.is_more_general_than(rep)) rep = input_rep;
+ }
+ // If any of the actual input representation is more general than what we
+ // have so far but not Tagged, use that representation instead.
+ Representation left_rep = left()->representation();
+ Representation right_rep = right()->representation();
+
+ if (left_rep.is_more_general_than(rep) &&
+ left()->CheckFlag(kFlexibleRepresentation)) {
+ rep = left_rep;
+ }
+ if (right_rep.is_more_general_than(rep) &&
+ right()->CheckFlag(kFlexibleRepresentation)) {
+ rep = right_rep;
+ }
+ return rep;
+}
+
+
+void HBinaryOperation::AssumeRepresentation(Representation r) {
+ set_observed_input_representation(r, r);
+ HValue::AssumeRepresentation(r);
+}
+
+
+void HMathMinMax::InferRepresentation(HInferRepresentation* h_infer) {
+ ASSERT(CheckFlag(kFlexibleRepresentation));
+ Representation new_rep = RepresentationFromInputs();
+ UpdateRepresentation(new_rep, h_infer, "inputs");
+ // Do not care about uses.
+}
+
+
Range* HBitwise::InferRange(Zone* zone) {
if (op() == Token::BIT_XOR) return HValue::InferRange(zone);
const int32_t kDefaultMask = static_cast<int32_t>(0xffffffff);
@@ -1615,7 +1773,7 @@ Range* HShl::InferRange(Zone* zone) {
}
-Range* HLoadKeyedSpecializedArrayElement::InferRange(Zone* zone) {
+Range* HLoadKeyed::InferRange(Zone* zone) {
switch (elements_kind()) {
case EXTERNAL_PIXEL_ELEMENTS:
return new(zone) Range(0, 255);
@@ -1670,9 +1828,19 @@ void HGoto::PrintDataTo(StringStream* stream) {
}
-void HCompareIDAndBranch::SetInputRepresentation(Representation r) {
- input_representation_ = r;
- if (r.IsDouble()) {
+void HCompareIDAndBranch::InferRepresentation(HInferRepresentation* h_infer) {
+ Representation rep = Representation::None();
+ Representation left_rep = left()->representation();
+ Representation right_rep = right()->representation();
+ bool observed_integers =
+ observed_input_representation(0).IsInteger32() &&
+ observed_input_representation(1).IsInteger32();
+ bool inputs_are_not_doubles =
+ !left_rep.IsDouble() && !right_rep.IsDouble();
+ if (observed_integers && inputs_are_not_doubles) {
+ rep = Representation::Integer32();
+ } else {
+ rep = Representation::Double();
// According to the ES5 spec (11.9.3, 11.8.5), Equality comparisons (==, ===
// and !=) have special handling of undefined, e.g. undefined == undefined
// is 'true'. Relational comparisons have a different semantic, first
@@ -1689,9 +1857,8 @@ void HCompareIDAndBranch::SetInputRepresentation(Representation r) {
if (!Token::IsOrderedRelationalCompareOp(token_)) {
SetFlag(kDeoptimizeOnUndefined);
}
- } else {
- ASSERT(r.IsInteger32());
}
+ ChangeRepresentation(rep);
}
@@ -1842,11 +2009,25 @@ void HLoadNamedGeneric::PrintDataTo(StringStream* stream) {
}
-void HLoadKeyedFastElement::PrintDataTo(StringStream* stream) {
- object()->PrintNameTo(stream);
+void HLoadKeyed::PrintDataTo(StringStream* stream) {
+ if (!is_external()) {
+ elements()->PrintNameTo(stream);
+ } else {
+ ASSERT(elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND &&
+ elements_kind() <= LAST_EXTERNAL_ARRAY_ELEMENTS_KIND);
+ elements()->PrintNameTo(stream);
+ stream->Add(".");
+ stream->Add(ElementsKindToString(elements_kind()));
+ }
+
stream->Add("[");
key()->PrintNameTo(stream);
- stream->Add("] ");
+ if (IsDehoisted()) {
+ stream->Add(" + %d] ", index_offset());
+ } else {
+ stream->Add("] ");
+ }
+
dependency()->PrintNameTo(stream);
if (RequiresHoleCheck()) {
stream->Add(" check_hole");
@@ -1854,29 +2035,26 @@ void HLoadKeyedFastElement::PrintDataTo(StringStream* stream) {
}
-bool HLoadKeyedFastElement::RequiresHoleCheck() {
+bool HLoadKeyed::RequiresHoleCheck() const {
if (IsFastPackedElementsKind(elements_kind())) {
return false;
}
+ if (IsFastDoubleElementsKind(elements_kind())) {
+ return true;
+ }
+
for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
HValue* use = it.value();
- if (!use->IsChange()) return true;
+ if (!use->IsChange()) {
+ return true;
+ }
}
return false;
}
-void HLoadKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
- elements()->PrintNameTo(stream);
- stream->Add("[");
- key()->PrintNameTo(stream);
- stream->Add("] ");
- dependency()->PrintNameTo(stream);
-}
-
-
void HLoadKeyedGeneric::PrintDataTo(StringStream* stream) {
object()->PrintNameTo(stream);
stream->Add("[");
@@ -1889,21 +2067,22 @@ HValue* HLoadKeyedGeneric::Canonicalize() {
// Recognize generic keyed loads that use property name generated
// by for-in statement as a key and rewrite them into fast property load
// by index.
- if (key()->IsLoadKeyedFastElement()) {
- HLoadKeyedFastElement* key_load = HLoadKeyedFastElement::cast(key());
- if (key_load->object()->IsForInCacheArray()) {
+ if (key()->IsLoadKeyed()) {
+ HLoadKeyed* key_load = HLoadKeyed::cast(key());
+ if (key_load->elements()->IsForInCacheArray()) {
HForInCacheArray* names_cache =
- HForInCacheArray::cast(key_load->object());
+ HForInCacheArray::cast(key_load->elements());
if (names_cache->enumerable() == object()) {
HForInCacheArray* index_cache =
names_cache->index_cache();
HCheckMapValue* map_check =
new(block()->zone()) HCheckMapValue(object(), names_cache->map());
- HInstruction* index = new(block()->zone()) HLoadKeyedFastElement(
+ HInstruction* index = new(block()->zone()) HLoadKeyed(
index_cache,
key_load->key(),
- key_load->key());
+ key_load->key(),
+ key_load->elements_kind());
map_check->InsertBefore(this);
index->InsertBefore(this);
HLoadFieldByIndex* load = new(block()->zone()) HLoadFieldByIndex(
@@ -1918,56 +2097,6 @@ HValue* HLoadKeyedGeneric::Canonicalize() {
}
-void HLoadKeyedSpecializedArrayElement::PrintDataTo(
- StringStream* stream) {
- external_pointer()->PrintNameTo(stream);
- stream->Add(".");
- switch (elements_kind()) {
- case EXTERNAL_BYTE_ELEMENTS:
- stream->Add("byte");
- break;
- case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
- stream->Add("u_byte");
- break;
- case EXTERNAL_SHORT_ELEMENTS:
- stream->Add("short");
- break;
- case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
- stream->Add("u_short");
- break;
- case EXTERNAL_INT_ELEMENTS:
- stream->Add("int");
- break;
- case EXTERNAL_UNSIGNED_INT_ELEMENTS:
- stream->Add("u_int");
- break;
- case EXTERNAL_FLOAT_ELEMENTS:
- stream->Add("float");
- break;
- case EXTERNAL_DOUBLE_ELEMENTS:
- stream->Add("double");
- break;
- case EXTERNAL_PIXEL_ELEMENTS:
- stream->Add("pixel");
- break;
- case FAST_ELEMENTS:
- case FAST_SMI_ELEMENTS:
- case FAST_DOUBLE_ELEMENTS:
- case FAST_HOLEY_ELEMENTS:
- case FAST_HOLEY_SMI_ELEMENTS:
- case FAST_HOLEY_DOUBLE_ELEMENTS:
- case DICTIONARY_ELEMENTS:
- case NON_STRICT_ARGUMENTS_ELEMENTS:
- UNREACHABLE();
- break;
- }
- stream->Add("[");
- key()->PrintNameTo(stream);
- stream->Add("] ");
- dependency()->PrintNameTo(stream);
-}
-
-
void HStoreNamedGeneric::PrintDataTo(StringStream* stream) {
object()->PrintNameTo(stream);
stream->Add(".");
@@ -1994,20 +2123,25 @@ void HStoreNamedField::PrintDataTo(StringStream* stream) {
}
-void HStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
- object()->PrintNameTo(stream);
- stream->Add("[");
- key()->PrintNameTo(stream);
- stream->Add("] = ");
- value()->PrintNameTo(stream);
-}
-
+void HStoreKeyed::PrintDataTo(StringStream* stream) {
+ if (!is_external()) {
+ elements()->PrintNameTo(stream);
+ } else {
+ elements()->PrintNameTo(stream);
+ stream->Add(".");
+ stream->Add(ElementsKindToString(elements_kind()));
+ ASSERT(elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND &&
+ elements_kind() <= LAST_EXTERNAL_ARRAY_ELEMENTS_KIND);
+ }
-void HStoreKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
- elements()->PrintNameTo(stream);
stream->Add("[");
key()->PrintNameTo(stream);
- stream->Add("] = ");
+ if (IsDehoisted()) {
+ stream->Add(" + %d] = ", index_offset());
+ } else {
+ stream->Add("] = ");
+ }
+
value()->PrintNameTo(stream);
}
@@ -2021,56 +2155,6 @@ void HStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
}
-void HStoreKeyedSpecializedArrayElement::PrintDataTo(
- StringStream* stream) {
- external_pointer()->PrintNameTo(stream);
- stream->Add(".");
- switch (elements_kind()) {
- case EXTERNAL_BYTE_ELEMENTS:
- stream->Add("byte");
- break;
- case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
- stream->Add("u_byte");
- break;
- case EXTERNAL_SHORT_ELEMENTS:
- stream->Add("short");
- break;
- case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
- stream->Add("u_short");
- break;
- case EXTERNAL_INT_ELEMENTS:
- stream->Add("int");
- break;
- case EXTERNAL_UNSIGNED_INT_ELEMENTS:
- stream->Add("u_int");
- break;
- case EXTERNAL_FLOAT_ELEMENTS:
- stream->Add("float");
- break;
- case EXTERNAL_DOUBLE_ELEMENTS:
- stream->Add("double");
- break;
- case EXTERNAL_PIXEL_ELEMENTS:
- stream->Add("pixel");
- break;
- case FAST_SMI_ELEMENTS:
- case FAST_ELEMENTS:
- case FAST_DOUBLE_ELEMENTS:
- case FAST_HOLEY_SMI_ELEMENTS:
- case FAST_HOLEY_ELEMENTS:
- case FAST_HOLEY_DOUBLE_ELEMENTS:
- case DICTIONARY_ELEMENTS:
- case NON_STRICT_ARGUMENTS_ELEMENTS:
- UNREACHABLE();
- break;
- }
- stream->Add("[");
- key()->PrintNameTo(stream);
- stream->Add("] = ");
- value()->PrintNameTo(stream);
-}
-
-
void HTransitionElementsKind::PrintDataTo(StringStream* stream) {
object()->PrintNameTo(stream);
ElementsKind from_kind = original_map()->elements_kind();
@@ -2090,7 +2174,7 @@ void HLoadGlobalCell::PrintDataTo(StringStream* stream) {
}
-bool HLoadGlobalCell::RequiresHoleCheck() {
+bool HLoadGlobalCell::RequiresHoleCheck() const {
if (details_.IsDontDelete() && !details_.IsReadOnly()) return false;
for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
HValue* use = it.value();
@@ -2361,10 +2445,10 @@ HValue* HAdd::EnsureAndPropagateNotMinusZero(BitVector* visited) {
}
-bool HStoreKeyedFastDoubleElement::NeedsCanonicalization() {
- // If value was loaded from unboxed double backing store or
- // converted from an integer then we don't have to canonicalize it.
- if (value()->IsLoadKeyedFastDoubleElement() ||
+bool HStoreKeyed::NeedsCanonicalization() {
+ // If value is an integer or comes from the result of a keyed load
+ // then it will be a non-hole value: no need for canonicalization.
+ if (value()->IsLoadKeyed() ||
(value()->IsChange() && HChange::cast(value())->from().IsInteger32())) {
return false;
}
@@ -2547,7 +2631,41 @@ void HBitwise::PrintDataTo(StringStream* stream) {
}
-Representation HPhi::InferredRepresentation() {
+void HPhi::InferRepresentation(HInferRepresentation* h_infer) {
+ ASSERT(CheckFlag(kFlexibleRepresentation));
+ // If there are non-Phi uses, and all of them have observed the same
+ // representation, than that's what this Phi is going to use.
+ Representation new_rep = RepresentationObservedByAllNonPhiUses();
+ if (!new_rep.IsNone()) {
+ UpdateRepresentation(new_rep, h_infer, "unanimous use observations");
+ return;
+ }
+ new_rep = RepresentationFromInputs();
+ UpdateRepresentation(new_rep, h_infer, "inputs");
+ new_rep = RepresentationFromUses();
+ UpdateRepresentation(new_rep, h_infer, "uses");
+ new_rep = RepresentationFromUseRequirements();
+ UpdateRepresentation(new_rep, h_infer, "use requirements");
+}
+
+
+Representation HPhi::RepresentationObservedByAllNonPhiUses() {
+ int non_phi_use_count = 0;
+ for (int i = Representation::kInteger32;
+ i < Representation::kNumRepresentations; ++i) {
+ non_phi_use_count += non_phi_uses_[i];
+ }
+ if (non_phi_use_count <= 1) return Representation::None();
+ for (int i = 0; i < Representation::kNumRepresentations; ++i) {
+ if (non_phi_uses_[i] == non_phi_use_count) {
+ return Representation::FromKind(static_cast<Representation::Kind>(i));
+ }
+ }
+ return Representation::None();
+}
+
+
+Representation HPhi::RepresentationFromInputs() {
bool double_occurred = false;
bool int32_occurred = false;
for (int i = 0; i < OperandCount(); ++i) {
@@ -2556,6 +2674,7 @@ Representation HPhi::InferredRepresentation() {
HPhi* hint_value = HUnknownOSRValue::cast(value)->incoming_value();
if (hint_value != NULL) {
Representation hint = hint_value->representation();
+ if (hint.IsTagged()) return hint;
if (hint.IsDouble()) double_occurred = true;
if (hint.IsInteger32()) int32_occurred = true;
}
@@ -2574,7 +2693,9 @@ Representation HPhi::InferredRepresentation() {
return Representation::Tagged();
}
} else {
- return Representation::Tagged();
+ if (value->IsPhi() && !IsConvertibleToInteger()) {
+ return Representation::Tagged();
+ }
}
}
}
@@ -2587,6 +2708,37 @@ Representation HPhi::InferredRepresentation() {
}
+Representation HPhi::RepresentationFromUseRequirements() {
+ Representation all_uses_require = Representation::None();
+ bool all_uses_require_the_same = true;
+ for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
+ // We check for observed_input_representation elsewhere.
+ Representation use_rep =
+ it.value()->RequiredInputRepresentation(it.index());
+ // No useful info from this use -> look at the next one.
+ if (use_rep.IsNone()) {
+ continue;
+ }
+ if (use_rep.Equals(all_uses_require)) {
+ continue;
+ }
+ // This use's representation contradicts what we've seen so far.
+ if (!all_uses_require.IsNone()) {
+ ASSERT(!use_rep.Equals(all_uses_require));
+ all_uses_require_the_same = false;
+ break;
+ }
+ // Otherwise, initialize observed representation.
+ all_uses_require = use_rep;
+ }
+ if (all_uses_require_the_same) {
+ return all_uses_require;
+ }
+
+ return Representation::None();
+}
+
+
// Node-specific verification code is only included in debug mode.
#ifdef DEBUG
@@ -2625,12 +2777,6 @@ void HCheckFunction::Verify() {
ASSERT(HasNoUses());
}
-
-void HCheckPrototypeMaps::Verify() {
- HInstruction::Verify();
- ASSERT(HasNoUses());
-}
-
#endif
} } // namespace v8::internal