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

Unified Diff: src/hydrogen-instructions.cc

Issue 22715004: Version 3.20.15 (Closed) Base URL: https://v8.googlecode.com/svn/trunk
Patch Set: Add TypedArray API and correctness patches r16033 and r16084 Created 7 years, 4 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/hydrogen-instructions.h ('k') | src/hydrogen-uint32-analysis.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/hydrogen-instructions.cc
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 997b7c2fda9b29455d03faac59c5a49a60d18d5c..3eb4aa6c0e63de6dcba0cf5444387bf02e92904e 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -149,6 +149,116 @@ void HValue::AddDependantsToWorklist(HInferRepresentationPhase* h_infer) {
}
+// This method is recursive but it is guaranteed to terminate because
+// RedefinedOperand() always dominates "this".
+bool HValue::IsRelationTrue(NumericRelation relation,
+ HValue* other,
+ int offset,
+ int scale) {
+ if (this == other) {
+ return scale == 0 && relation.IsExtendable(offset);
+ }
+
+ // Test the direct relation.
+ if (IsRelationTrueInternal(relation, other, offset, scale)) return true;
+
+ // If scale is 0 try the reversed relation.
+ if (scale == 0 &&
+ // TODO(mmassi): do we need the full, recursive IsRelationTrue?
+ other->IsRelationTrueInternal(relation.Reversed(), this, -offset)) {
+ return true;
+ }
+
+ // Try decomposition (but do not accept scaled compounds).
+ DecompositionResult decomposition;
+ if (TryDecompose(&decomposition) &&
+ decomposition.scale() == 0 &&
+ decomposition.base()->IsRelationTrue(relation, other,
+ offset + decomposition.offset(),
+ scale)) {
+ return true;
+ }
+
+ // Pass the request to the redefined value.
+ HValue* redefined = RedefinedOperand();
+ return redefined != NULL && redefined->IsRelationTrue(relation, other,
+ offset, scale);
+}
+
+
+bool HValue::TryGuaranteeRange(HValue* upper_bound) {
+ RangeEvaluationContext context = RangeEvaluationContext(this, upper_bound);
+ TryGuaranteeRangeRecursive(&context);
+ bool result = context.is_range_satisfied();
+ if (result) {
+ context.lower_bound_guarantee()->SetResponsibilityForRange(DIRECTION_LOWER);
+ context.upper_bound_guarantee()->SetResponsibilityForRange(DIRECTION_UPPER);
+ }
+ return result;
+}
+
+
+void HValue::TryGuaranteeRangeRecursive(RangeEvaluationContext* context) {
+ // Check if we already know that this value satisfies the lower bound.
+ if (context->lower_bound_guarantee() == NULL) {
+ if (IsRelationTrueInternal(NumericRelation::Ge(), context->lower_bound(),
+ context->offset(), context->scale())) {
+ context->set_lower_bound_guarantee(this);
+ }
+ }
+
+ // Check if we already know that this value satisfies the upper bound.
+ if (context->upper_bound_guarantee() == NULL) {
+ if (IsRelationTrueInternal(NumericRelation::Lt(), context->upper_bound(),
+ context->offset(), context->scale()) ||
+ (context->scale() == 0 &&
+ context->upper_bound()->IsRelationTrue(NumericRelation::Gt(),
+ this, -context->offset()))) {
+ context->set_upper_bound_guarantee(this);
+ }
+ }
+
+ if (context->is_range_satisfied()) return;
+
+ // See if our RedefinedOperand() satisfies the constraints.
+ if (RedefinedOperand() != NULL) {
+ RedefinedOperand()->TryGuaranteeRangeRecursive(context);
+ }
+ if (context->is_range_satisfied()) return;
+
+ // See if the constraints can be satisfied by decomposition.
+ DecompositionResult decomposition;
+ if (TryDecompose(&decomposition)) {
+ context->swap_candidate(&decomposition);
+ context->candidate()->TryGuaranteeRangeRecursive(context);
+ context->swap_candidate(&decomposition);
+ }
+ if (context->is_range_satisfied()) return;
+
+ // Try to modify this to satisfy the constraint.
+
+ TryGuaranteeRangeChanging(context);
+}
+
+
+RangeEvaluationContext::RangeEvaluationContext(HValue* value, HValue* upper)
+ : lower_bound_(upper->block()->graph()->GetConstant0()),
+ lower_bound_guarantee_(NULL),
+ candidate_(value),
+ upper_bound_(upper),
+ upper_bound_guarantee_(NULL),
+ offset_(0),
+ scale_(0) {
+}
+
+
+HValue* RangeEvaluationContext::ConvertGuarantee(HValue* guarantee) {
+ return guarantee->IsBoundsCheckBaseIndexInformation()
+ ? HBoundsCheckBaseIndexInformation::cast(guarantee)->bounds_check()
+ : guarantee;
+}
+
+
static int32_t ConvertAndSetOverflow(Representation r,
int64_t result,
bool* overflow) {
@@ -374,6 +484,55 @@ HType HType::TypeFromValue(Handle<Object> value) {
}
+bool HValue::Dominates(HValue* dominator, HValue* dominated) {
+ if (dominator->block() != dominated->block()) {
+ // If they are in different blocks we can use the dominance relation
+ // between the blocks.
+ return dominator->block()->Dominates(dominated->block());
+ } else {
+ // Otherwise we must see which instruction comes first, considering
+ // that phis always precede regular instructions.
+ if (dominator->IsInstruction()) {
+ if (dominated->IsInstruction()) {
+ for (HInstruction* next = HInstruction::cast(dominator)->next();
+ next != NULL;
+ next = next->next()) {
+ if (next == dominated) return true;
+ }
+ return false;
+ } else if (dominated->IsPhi()) {
+ return false;
+ } else {
+ UNREACHABLE();
+ }
+ } else if (dominator->IsPhi()) {
+ if (dominated->IsInstruction()) {
+ return true;
+ } else {
+ // We cannot compare which phi comes first.
+ UNREACHABLE();
+ }
+ } else {
+ UNREACHABLE();
+ }
+ return false;
+ }
+}
+
+
+bool HValue::TestDominanceUsingProcessedFlag(HValue* dominator,
+ HValue* dominated) {
+ if (dominator->block() != dominated->block()) {
+ return dominator->block()->Dominates(dominated->block());
+ } else {
+ // If both arguments are in the same block we check if dominator is a phi
+ // or if dominated has not already been processed: in either case we know
+ // that dominator precedes dominated.
+ return dominator->IsPhi() || !dominated->CheckFlag(kIDefsProcessingDone);
+ }
+}
+
+
bool HValue::IsDefinedAfter(HBasicBlock* other) const {
return block()->block_id() > other->block_id();
}
@@ -801,6 +960,58 @@ void HInstruction::Verify() {
#endif
+HNumericConstraint* HNumericConstraint::AddToGraph(
+ HValue* constrained_value,
+ NumericRelation relation,
+ HValue* related_value,
+ HInstruction* insertion_point) {
+ if (insertion_point == NULL) {
+ if (constrained_value->IsInstruction()) {
+ insertion_point = HInstruction::cast(constrained_value);
+ } else if (constrained_value->IsPhi()) {
+ insertion_point = constrained_value->block()->first();
+ } else {
+ UNREACHABLE();
+ }
+ }
+ HNumericConstraint* result =
+ new(insertion_point->block()->zone()) HNumericConstraint(
+ constrained_value, relation, related_value);
+ result->InsertAfter(insertion_point);
+ return result;
+}
+
+
+void HNumericConstraint::PrintDataTo(StringStream* stream) {
+ stream->Add("(");
+ constrained_value()->PrintNameTo(stream);
+ stream->Add(" %s ", relation().Mnemonic());
+ related_value()->PrintNameTo(stream);
+ stream->Add(")");
+}
+
+
+HInductionVariableAnnotation* HInductionVariableAnnotation::AddToGraph(
+ HPhi* phi,
+ NumericRelation relation,
+ int operand_index) {
+ HInductionVariableAnnotation* result =
+ new(phi->block()->zone()) HInductionVariableAnnotation(phi, relation,
+ operand_index);
+ result->InsertAfter(phi->block()->first());
+ return result;
+}
+
+
+void HInductionVariableAnnotation::PrintDataTo(StringStream* stream) {
+ stream->Add("(");
+ RedefinedOperand()->PrintNameTo(stream);
+ stream->Add(" %s ", relation().Mnemonic());
+ induction_base()->PrintNameTo(stream);
+ stream->Add(")");
+}
+
+
void HDummyUse::PrintDataTo(StringStream* stream) {
value()->PrintNameTo(stream);
}
@@ -827,6 +1038,40 @@ void HBinaryCall::PrintDataTo(StringStream* stream) {
}
+void HBoundsCheck::TryGuaranteeRangeChanging(RangeEvaluationContext* context) {
+ if (context->candidate()->ActualValue() != base()->ActualValue() ||
+ context->scale() < scale()) {
+ return;
+ }
+
+ // TODO(mmassi)
+ // Instead of checking for "same basic block" we should check for
+ // "dominates and postdominates".
+ if (context->upper_bound() == length() &&
+ context->lower_bound_guarantee() != NULL &&
+ context->lower_bound_guarantee() != this &&
+ context->lower_bound_guarantee()->block() != block() &&
+ offset() < context->offset() &&
+ index_can_increase() &&
+ context->upper_bound_guarantee() == NULL) {
+ offset_ = context->offset();
+ SetResponsibilityForRange(DIRECTION_UPPER);
+ context->set_upper_bound_guarantee(this);
+ isolate()->counters()->bounds_checks_eliminated()->Increment();
+ } else if (context->upper_bound_guarantee() != NULL &&
+ context->upper_bound_guarantee() != this &&
+ context->upper_bound_guarantee()->block() != block() &&
+ offset() > context->offset() &&
+ index_can_decrease() &&
+ context->lower_bound_guarantee() == NULL) {
+ offset_ = context->offset();
+ SetResponsibilityForRange(DIRECTION_LOWER);
+ context->set_lower_bound_guarantee(this);
+ isolate()->counters()->bounds_checks_eliminated()->Increment();
+ }
+}
+
+
void HBoundsCheck::ApplyIndexChange() {
if (skip_check()) return;
@@ -874,6 +1119,40 @@ void HBoundsCheck::ApplyIndexChange() {
base_ = NULL;
offset_ = 0;
scale_ = 0;
+ responsibility_direction_ = DIRECTION_NONE;
+}
+
+
+void HBoundsCheck::AddInformativeDefinitions() {
+ // TODO(mmassi): Executing this code during AddInformativeDefinitions
+ // is a hack. Move it to some other HPhase.
+ if (FLAG_array_bounds_checks_elimination) {
+ if (index()->TryGuaranteeRange(length())) {
+ set_skip_check();
+ }
+ if (DetectCompoundIndex()) {
+ HBoundsCheckBaseIndexInformation* base_index_info =
+ new(block()->graph()->zone())
+ HBoundsCheckBaseIndexInformation(this);
+ base_index_info->InsertAfter(this);
+ }
+ }
+}
+
+
+bool HBoundsCheck::IsRelationTrueInternal(NumericRelation relation,
+ HValue* related_value,
+ int offset,
+ int scale) {
+ if (related_value == length()) {
+ // A HBoundsCheck is smaller than the length it compared against.
+ return NumericRelation::Lt().CompoundImplies(relation, 0, 0, offset, scale);
+ } else if (related_value == block()->graph()->GetConstant0()) {
+ // A HBoundsCheck is greater than or equal to zero.
+ return NumericRelation::Ge().CompoundImplies(relation, 0, 0, offset, scale);
+ } else {
+ return false;
+ }
}
@@ -916,6 +1195,25 @@ void HBoundsCheck::InferRepresentation(HInferRepresentationPhase* h_infer) {
}
+bool HBoundsCheckBaseIndexInformation::IsRelationTrueInternal(
+ NumericRelation relation,
+ HValue* related_value,
+ int offset,
+ int scale) {
+ if (related_value == bounds_check()->length()) {
+ return NumericRelation::Lt().CompoundImplies(
+ relation,
+ bounds_check()->offset(), bounds_check()->scale(), offset, scale);
+ } else if (related_value == block()->graph()->GetConstant0()) {
+ return NumericRelation::Ge().CompoundImplies(
+ relation,
+ bounds_check()->offset(), bounds_check()->scale(), offset, scale);
+ } else {
+ return false;
+ }
+}
+
+
void HBoundsCheckBaseIndexInformation::PrintDataTo(StringStream* stream) {
stream->Add("base: ");
base_index()->PrintNameTo(stream);
@@ -1155,29 +1453,6 @@ void HLoadFieldByIndex::PrintDataTo(StringStream* stream) {
}
-static bool MatchLeftIsOnes(HValue* l, HValue* r, HValue** negated) {
- if (!l->EqualsInteger32Constant(~0)) return false;
- *negated = r;
- return true;
-}
-
-
-static bool MatchNegationViaXor(HValue* instr, HValue** negated) {
- if (!instr->IsBitwise()) return false;
- HBitwise* b = HBitwise::cast(instr);
- return (b->op() == Token::BIT_XOR) &&
- (MatchLeftIsOnes(b->left(), b->right(), negated) ||
- MatchLeftIsOnes(b->right(), b->left(), negated));
-}
-
-
-static bool MatchDoubleNegation(HValue* instr, HValue** arg) {
- HValue* negated;
- return MatchNegationViaXor(instr, &negated) &&
- MatchNegationViaXor(negated, arg);
-}
-
-
HValue* HBitwise::Canonicalize() {
if (!representation().IsSmiOrInteger32()) return this;
// If x is an int32, then x & -1 == x, x | 0 == x and x ^ 0 == x.
@@ -1190,10 +1465,18 @@ HValue* HBitwise::Canonicalize() {
!left()->CheckFlag(kUint32)) {
return left();
}
- // Optimize double negation, a common pattern used for ToInt32(x).
- HValue* arg;
- if (MatchDoubleNegation(this, &arg) && !arg->CheckFlag(kUint32)) {
- return arg;
+ return this;
+}
+
+
+HValue* HBitNot::Canonicalize() {
+ // Optimize ~~x, a common pattern used for ToInt32(x).
+ if (value()->IsBitNot()) {
+ HValue* result = HBitNot::cast(value())->value();
+ ASSERT(result->representation().IsInteger32());
+ if (!result->CheckFlag(kUint32)) {
+ return result;
+ }
}
return this;
}
@@ -1404,10 +1687,10 @@ void HCheckMaps::HandleSideEffectDominator(GVNFlag side_effect,
// for which the map is known.
if (HasNoUses() && dominator->IsStoreNamedField()) {
HStoreNamedField* store = HStoreNamedField::cast(dominator);
- if (!store->has_transition() || store->object() != value()) return;
- HConstant* transition = HConstant::cast(store->transition());
+ UniqueValueId map_unique_id = store->transition_unique_id();
+ if (!map_unique_id.IsInitialized() || store->object() != value()) return;
for (int i = 0; i < map_set()->length(); i++) {
- if (transition->UniqueValueIdsMatch(map_unique_ids_.at(i))) {
+ if (map_unique_id == map_unique_ids_.at(i)) {
DeleteAndReplaceWith(NULL);
return;
}
@@ -1458,6 +1741,13 @@ void HCheckInstanceType::PrintDataTo(StringStream* stream) {
}
+void HCheckPrototypeMaps::PrintDataTo(StringStream* stream) {
+ stream->Add("[receiver_prototype=%p,holder=%p]%s",
+ *prototypes_.first(), *prototypes_.last(),
+ CanOmitPrototypeChecks() ? " (omitted)" : "");
+}
+
+
void HCallStub::PrintDataTo(StringStream* stream) {
stream->Add("%s ",
CodeStub::MajorName(major_key_, false));
@@ -1660,6 +1950,60 @@ Range* HMod::InferRange(Zone* zone) {
}
+void HPhi::AddInformativeDefinitions() {
+ if (OperandCount() == 2) {
+ // If one of the operands is an OSR block give up (this cannot be an
+ // induction variable).
+ if (OperandAt(0)->block()->is_osr_entry() ||
+ OperandAt(1)->block()->is_osr_entry()) return;
+
+ for (int operand_index = 0; operand_index < 2; operand_index++) {
+ int other_operand_index = (operand_index + 1) % 2;
+
+ static NumericRelation relations[] = {
+ NumericRelation::Ge(),
+ NumericRelation::Le()
+ };
+
+ // Check if this phi is an induction variable. If, e.g., we know that
+ // its first input is greater than the phi itself, then that must be
+ // the back edge, and the phi is always greater than its second input.
+ for (int relation_index = 0; relation_index < 2; relation_index++) {
+ if (OperandAt(operand_index)->IsRelationTrue(relations[relation_index],
+ this)) {
+ HInductionVariableAnnotation::AddToGraph(this,
+ relations[relation_index],
+ other_operand_index);
+ }
+ }
+ }
+ }
+}
+
+
+bool HPhi::IsRelationTrueInternal(NumericRelation relation,
+ HValue* other,
+ int offset,
+ int scale) {
+ if (CheckFlag(kNumericConstraintEvaluationInProgress)) return false;
+
+ SetFlag(kNumericConstraintEvaluationInProgress);
+ bool result = true;
+ for (int i = 0; i < OperandCount(); i++) {
+ // Skip OSR entry blocks
+ if (OperandAt(i)->block()->is_osr_entry()) continue;
+
+ if (!OperandAt(i)->IsRelationTrue(relation, other, offset, scale)) {
+ result = false;
+ break;
+ }
+ }
+ ClearFlag(kNumericConstraintEvaluationInProgress);
+
+ return result;
+}
+
+
InductionVariableData* InductionVariableData::ExaminePhi(HPhi* phi) {
if (phi->block()->loop_information() == NULL) return NULL;
if (phi->OperandCount() != 2) return NULL;
@@ -2411,14 +2755,6 @@ HConstant::HConstant(ExternalReference reference)
}
-static void PrepareConstant(Handle<Object> object) {
- if (!object->IsJSObject()) return;
- Handle<JSObject> js_object = Handle<JSObject>::cast(object);
- if (!js_object->map()->is_deprecated()) return;
- JSObject::TryMigrateInstance(js_object);
-}
-
-
void HConstant::Initialize(Representation r) {
if (r.IsNone()) {
if (has_smi_value_ && kSmiValueSize == 31) {
@@ -2430,7 +2766,6 @@ void HConstant::Initialize(Representation r) {
} else if (has_external_reference_value_) {
r = Representation::External();
} else {
- PrepareConstant(handle_);
r = Representation::Tagged();
}
}
@@ -2755,6 +3090,16 @@ void HStringCompareAndBranch::PrintDataTo(StringStream* stream) {
}
+void HCompareNumericAndBranch::AddInformativeDefinitions() {
+ NumericRelation r = NumericRelation::FromToken(token());
+ if (r.IsNone()) return;
+
+ HNumericConstraint::AddToGraph(left(), r, right(), SuccessorAt(0)->first());
+ HNumericConstraint::AddToGraph(
+ left(), r.Negated(), right(), SuccessorAt(1)->first());
+}
+
+
void HCompareNumericAndBranch::PrintDataTo(StringStream* stream) {
stream->Add(Token::Name(token()));
stream->Add(" ");
@@ -2953,7 +3298,6 @@ HCheckMaps* HCheckMaps::New(Zone* zone,
HValue* typecheck) {
HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck);
check_map->map_set_.Add(map, zone);
- check_map->has_migration_target_ = map->is_migration_target();
if (map->CanOmitMapChecks() &&
value->IsConstant() &&
HConstant::cast(value)->InstanceOf(map)) {
@@ -3178,8 +3522,8 @@ void HStoreNamedField::PrintDataTo(StringStream* stream) {
if (NeedsWriteBarrier()) {
stream->Add(" (write-barrier)");
}
- if (has_transition()) {
- stream->Add(" (transition map %p)", *transition_map());
+ if (!transition().is_null()) {
+ stream->Add(" (transition map %p)", *transition());
}
}
« no previous file with comments | « src/hydrogen-instructions.h ('k') | src/hydrogen-uint32-analysis.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698