diff options
author | Ryan Dahl <ry@tinyclouds.org> | 2011-06-29 17:26:51 +0200 |
---|---|---|
committer | Ryan Dahl <ry@tinyclouds.org> | 2011-06-29 17:26:51 +0200 |
commit | 33af2720f26c2b25bc7f75ce7eb454ff99db6d35 (patch) | |
tree | 9a38f0c96420edf503eebd6325dd8d2d8249f653 /deps/v8/src/hydrogen-instructions.cc | |
parent | 6afdca885adeeeed9eef8cbb01c3d97af0bc084d (diff) | |
download | node-33af2720f26c2b25bc7f75ce7eb454ff99db6d35.tar.gz |
Upgrade V8 to 3.4.8
Diffstat (limited to 'deps/v8/src/hydrogen-instructions.cc')
-rw-r--r-- | deps/v8/src/hydrogen-instructions.cc | 675 |
1 files changed, 498 insertions, 177 deletions
diff --git a/deps/v8/src/hydrogen-instructions.cc b/deps/v8/src/hydrogen-instructions.cc index c5a7146eb..771770ee8 100644 --- a/deps/v8/src/hydrogen-instructions.cc +++ b/deps/v8/src/hydrogen-instructions.cc @@ -36,6 +36,8 @@ #include "x64/lithium-x64.h" #elif V8_TARGET_ARCH_ARM #include "arm/lithium-arm.h" +#elif V8_TARGET_ARCH_MIPS +#include "mips/lithium-mips.h" #else #error Unsupported target architecture. #endif @@ -58,12 +60,20 @@ const char* Representation::Mnemonic() const { case kDouble: return "d"; case kInteger32: return "i"; case kExternal: return "x"; - case kNumRepresentations: + default: UNREACHABLE(); return NULL; } - UNREACHABLE(); - return NULL; +} + + +void HValue::AssumeRepresentation(Representation r) { + if (CheckFlag(kFlexibleRepresentation)) { + ChangeRepresentation(r); + // The representation of the value is dictated by type feedback and + // will not be changed later. + ClearFlag(kFlexibleRepresentation); + } } @@ -120,6 +130,44 @@ void Range::AddConstant(int32_t value) { } +void Range::Intersect(Range* other) { + upper_ = Min(upper_, other->upper_); + lower_ = Max(lower_, other->lower_); + bool b = CanBeMinusZero() && other->CanBeMinusZero(); + set_can_be_minus_zero(b); +} + + +void Range::Union(Range* other) { + upper_ = Max(upper_, other->upper_); + lower_ = Min(lower_, other->lower_); + bool b = CanBeMinusZero() || other->CanBeMinusZero(); + set_can_be_minus_zero(b); +} + + +void Range::Sar(int32_t value) { + int32_t bits = value & 0x1F; + lower_ = lower_ >> bits; + upper_ = upper_ >> bits; + set_can_be_minus_zero(false); +} + + +void Range::Shl(int32_t value) { + int32_t bits = value & 0x1F; + int old_lower = lower_; + int old_upper = upper_; + lower_ = lower_ << bits; + upper_ = upper_ << bits; + if (old_lower != lower_ >> bits || old_upper != upper_ >> bits) { + upper_ = kMaxInt; + lower_ = kMinInt; + } + set_can_be_minus_zero(false); +} + + bool Range::AddAndCheckOverflow(Range* other) { bool may_overflow = false; lower_ = AddWithoutOverflow(lower_, other->lower(), &may_overflow); @@ -224,31 +272,60 @@ HType HType::TypeFromValue(Handle<Object> value) { } -int HValue::LookupOperandIndex(int occurrence_index, HValue* op) { - for (int i = 0; i < OperandCount(); ++i) { - if (OperandAt(i) == op) { - if (occurrence_index == 0) return i; - --occurrence_index; - } +bool HValue::IsDefinedAfter(HBasicBlock* other) const { + return block()->block_id() > other->block_id(); +} + + +HUseIterator::HUseIterator(HUseListNode* head) : next_(head) { + Advance(); +} + + +void HUseIterator::Advance() { + current_ = next_; + if (current_ != NULL) { + next_ = current_->tail(); + value_ = current_->value(); + index_ = current_->index(); } - return -1; } -bool HValue::IsDefinedAfter(HBasicBlock* other) const { - return block()->block_id() > other->block_id(); +int HValue::UseCount() const { + int count = 0; + for (HUseIterator it(uses()); !it.Done(); it.Advance()) ++count; + return count; } -bool HValue::UsesMultipleTimes(HValue* op) { - bool seen = false; - for (int i = 0; i < OperandCount(); ++i) { - if (OperandAt(i) == op) { - if (seen) return true; - seen = true; +HUseListNode* HValue::RemoveUse(HValue* value, int index) { + HUseListNode* previous = NULL; + HUseListNode* current = use_list_; + while (current != NULL) { + if (current->value() == value && current->index() == index) { + if (previous == NULL) { + use_list_ = current->tail(); + } else { + previous->set_tail(current->tail()); + } + break; } + + previous = current; + current = current->tail(); } - return false; + +#ifdef DEBUG + // Do not reuse use list nodes in debug mode, zap them. + if (current != NULL) { + HUseListNode* temp = + new HUseListNode(current->value(), current->index(), NULL); + current->Zap(); + current = temp; + } +#endif + return current; } @@ -277,32 +354,42 @@ intptr_t HValue::Hashcode() { } +const char* HValue::Mnemonic() const { + switch (opcode()) { +#define MAKE_CASE(type) case k##type: return #type; + HYDROGEN_CONCRETE_INSTRUCTION_LIST(MAKE_CASE) +#undef MAKE_CASE + case kPhi: return "Phi"; + default: return ""; + } +} + + void HValue::SetOperandAt(int index, HValue* value) { - ASSERT(value == NULL || !value->representation().IsNone()); RegisterUse(index, value); InternalSetOperandAt(index, value); } -void HValue::ReplaceAndDelete(HValue* other) { - ReplaceValue(other); - Delete(); +void HValue::DeleteAndReplaceWith(HValue* other) { + // We replace all uses first, so Delete can assert that there are none. + if (other != NULL) ReplaceAllUsesWith(other); + ASSERT(HasNoUses()); + ClearOperands(); + DeleteFromGraph(); } -void HValue::ReplaceValue(HValue* other) { - ZoneList<HValue*> start_uses(2); - for (int i = 0; i < uses_.length(); ++i) { - HValue* use = uses_.at(i); - if (!use->block()->IsStartBlock()) { - InternalReplaceAtUse(use, other); - other->uses_.Add(use); - } else { - start_uses.Add(use); - } +void HValue::ReplaceAllUsesWith(HValue* other) { + while (use_list_ != NULL) { + HUseListNode* list_node = use_list_; + HValue* value = list_node->value(); + ASSERT(!value->block()->IsStartBlock()); + value->InternalSetOperandAt(list_node->index(), other); + use_list_ = list_node->tail(); + list_node->set_tail(other->use_list_); + other->use_list_ = list_node; } - uses_.Clear(); - uses_.AddAll(start_uses); } @@ -313,55 +400,48 @@ void HValue::ClearOperands() { } -void HValue::Delete() { - ASSERT(HasNoUses()); - ClearOperands(); - DeleteFromGraph(); -} - - -void HValue::ReplaceAtUse(HValue* use, HValue* other) { - for (int i = 0; i < use->OperandCount(); ++i) { - if (use->OperandAt(i) == this) { - use->SetOperandAt(i, other); - } +void HValue::SetBlock(HBasicBlock* block) { + ASSERT(block_ == NULL || block == NULL); + block_ = block; + if (id_ == kNoNumber && block != NULL) { + id_ = block->graph()->GetNextValueID(this); } } -void HValue::ReplaceFirstAtUse(HValue* use, HValue* other, Representation r) { - for (int i = 0; i < use->OperandCount(); ++i) { - if (use->RequiredInputRepresentation(i).Equals(r) && - use->OperandAt(i) == this) { - use->SetOperandAt(i, other); - return; - } - } +void HValue::PrintTypeTo(StringStream* stream) { + if (!representation().IsTagged() || type().Equals(HType::Tagged())) return; + stream->Add(" type[%s]", type().ToString()); } -void HValue::InternalReplaceAtUse(HValue* use, HValue* other) { - for (int i = 0; i < use->OperandCount(); ++i) { - if (use->OperandAt(i) == this) { - // Call internal method that does not update use lists. The caller is - // responsible for doing so. - use->InternalSetOperandAt(i, other); - } - } +void HValue::PrintRangeTo(StringStream* stream) { + if (range() == NULL || range()->IsMostGeneric()) return; + stream->Add(" range[%d,%d,m0=%d]", + range()->lower(), + range()->upper(), + static_cast<int>(range()->CanBeMinusZero())); } -void HValue::SetBlock(HBasicBlock* block) { - ASSERT(block_ == NULL || block == NULL); - block_ = block; - if (id_ == kNoNumber && block != NULL) { - id_ = block->graph()->GetNextValueID(this); +void HValue::PrintChangesTo(StringStream* stream) { + int changes_flags = (flags() & HValue::ChangesFlagsMask()); + if (changes_flags == 0) return; + stream->Add(" changes["); + if (changes_flags == AllSideEffects()) { + stream->Add("*"); + } else { + bool add_comma = false; +#define PRINT_DO(type) \ + if (changes_flags & (1 << kChanges##type)) { \ + if (add_comma) stream->Add(","); \ + add_comma = true; \ + stream->Add(#type); \ + } + GVN_FLAG_LIST(PRINT_DO); +#undef PRINT_DO } -} - - -void HValue::PrintTypeTo(HType type, StringStream* stream) { - stream->Add(type.ToShortString()); + stream->Add("]"); } @@ -381,12 +461,20 @@ bool HValue::UpdateInferredType() { void HValue::RegisterUse(int index, HValue* new_value) { HValue* old_value = OperandAt(index); if (old_value == new_value) return; + + HUseListNode* removed = NULL; if (old_value != NULL) { - ASSERT(old_value->uses_.Contains(this)); - old_value->uses_.RemoveElement(this); + removed = old_value->RemoveUse(this, index); } + if (new_value != NULL) { - new_value->uses_.Add(this); + if (removed == NULL) { + new_value->use_list_ = + new HUseListNode(this, index, new_value->use_list_); + } else { + removed->set_tail(new_value->use_list_); + new_value->use_list_ = removed; + } } } @@ -415,26 +503,18 @@ void HValue::ComputeInitialRange() { void HInstruction::PrintTo(StringStream* stream) { - stream->Add("%s", Mnemonic()); - if (HasSideEffects()) stream->Add("*"); - stream->Add(" "); + PrintMnemonicTo(stream); PrintDataTo(stream); + PrintRangeTo(stream); + PrintChangesTo(stream); + PrintTypeTo(stream); +} - if (range() != NULL) { - stream->Add(" range[%d,%d,m0=%d]", - range()->lower(), - range()->upper(), - static_cast<int>(range()->CanBeMinusZero())); - } - int changes_flags = (flags() & HValue::ChangesFlagsMask()); - if (changes_flags != 0) { - stream->Add(" changes[0x%x]", changes_flags); - } - - if (representation().IsTagged() && !type().Equals(HType::Tagged())) { - stream->Add(" type[%s]", type().ToString()); - } +void HInstruction::PrintMnemonicTo(StringStream* stream) { + stream->Add("%s", Mnemonic()); + if (HasSideEffects()) stream->Add("*"); + stream->Add(" "); } @@ -519,6 +599,8 @@ void HInstruction::Verify() { ASSERT(cur == other_operand); } } else { + // If the following assert fires, you may have forgotten an + // AddInstruction. ASSERT(other_block->Dominates(cur_block)); } } @@ -604,15 +686,13 @@ void HAccessArgumentsAt::PrintDataTo(StringStream* stream) { void HControlInstruction::PrintDataTo(StringStream* stream) { - if (FirstSuccessor() != NULL) { - int first_id = FirstSuccessor()->block_id(); - if (SecondSuccessor() == NULL) { - stream->Add(" B%d", first_id); - } else { - int second_id = SecondSuccessor()->block_id(); - stream->Add(" goto (B%d, B%d)", first_id, second_id); - } + stream->Add(" goto ("); + bool first_block = true; + for (HSuccessorIterator it(this); !it.Done(); it.Advance()) { + stream->Add(first_block ? "B%d" : ", B%d", it.Current()->block_id()); + first_block = false; } + stream->Add(")"); } @@ -622,6 +702,11 @@ void HUnaryControlInstruction::PrintDataTo(StringStream* stream) { } +void HReturn::PrintDataTo(StringStream* stream) { + value()->PrintNameTo(stream); +} + + void HCompareMap::PrintDataTo(StringStream* stream) { value()->PrintNameTo(stream); stream->Add(" (%p)", *map()); @@ -665,7 +750,7 @@ void HUnaryOperation::PrintDataTo(StringStream* stream) { void HHasInstanceType::PrintDataTo(StringStream* stream) { value()->PrintNameTo(stream); switch (from_) { - case FIRST_JS_OBJECT_TYPE: + case FIRST_JS_RECEIVER_TYPE: if (to_ == LAST_TYPE) stream->Add(" spec_object"); break; case JS_REGEXP_TYPE: @@ -692,17 +777,44 @@ void HTypeofIs::PrintDataTo(StringStream* stream) { void HChange::PrintDataTo(StringStream* stream) { HUnaryOperation::PrintDataTo(stream); - stream->Add(" %s to %s", from_.Mnemonic(), to_.Mnemonic()); + stream->Add(" %s to %s", from_.Mnemonic(), to().Mnemonic()); if (CanTruncateToInt32()) stream->Add(" truncating-int32"); if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?"); } -HCheckInstanceType* HCheckInstanceType::NewIsJSObjectOrJSFunction( - HValue* value) { - STATIC_ASSERT((LAST_JS_OBJECT_TYPE + 1) == JS_FUNCTION_TYPE); - return new HCheckInstanceType(value, FIRST_JS_OBJECT_TYPE, JS_FUNCTION_TYPE); +void HCheckInstanceType::GetCheckInterval(InstanceType* first, + InstanceType* last) { + ASSERT(is_interval_check()); + switch (check_) { + case IS_SPEC_OBJECT: + *first = FIRST_SPEC_OBJECT_TYPE; + *last = LAST_SPEC_OBJECT_TYPE; + return; + case IS_JS_ARRAY: + *first = *last = JS_ARRAY_TYPE; + return; + default: + UNREACHABLE(); + } +} + + +void HCheckInstanceType::GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag) { + ASSERT(!is_interval_check()); + switch (check_) { + case IS_STRING: + *mask = kIsNotStringMask; + *tag = kStringTag; + return; + case IS_SYMBOL: + *mask = kIsSymbolMask; + *tag = kSymbolTag; + return; + default: + UNREACHABLE(); + } } @@ -744,6 +856,8 @@ Range* HValue::InferRange() { } else if (representation().IsNone()) { return NULL; } else { + // Untagged integer32 cannot be -0 and we don't compute ranges for + // untagged doubles. return new Range(); } } @@ -755,7 +869,7 @@ Range* HConstant::InferRange() { result->set_can_be_minus_zero(false); return result; } - return HInstruction::InferRange(); + return HValue::InferRange(); } @@ -789,7 +903,7 @@ Range* HAdd::InferRange() { res->set_can_be_minus_zero(m0); return res; } else { - return HArithmeticBinaryOperation::InferRange(); + return HValue::InferRange(); } } @@ -805,7 +919,7 @@ Range* HSub::InferRange() { res->set_can_be_minus_zero(a->CanBeMinusZero() && b->CanBeZero()); return res; } else { - return HArithmeticBinaryOperation::InferRange(); + return HValue::InferRange(); } } @@ -823,7 +937,7 @@ Range* HMul::InferRange() { res->set_can_be_minus_zero(m0); return res; } else { - return HArithmeticBinaryOperation::InferRange(); + return HValue::InferRange(); } } @@ -848,7 +962,7 @@ Range* HDiv::InferRange() { } return result; } else { - return HArithmeticBinaryOperation::InferRange(); + return HValue::InferRange(); } } @@ -865,7 +979,7 @@ Range* HMod::InferRange() { } return result; } else { - return HArithmeticBinaryOperation::InferRange(); + return HValue::InferRange(); } } @@ -879,7 +993,7 @@ void HPhi::PrintTo(StringStream* stream) { stream->Add(" "); } stream->Add(" uses%d_%di_%dd_%dt]", - uses()->length(), + UseCount(), int32_non_phi_uses() + int32_indirect_uses(), double_non_phi_uses() + double_indirect_uses(), tagged_non_phi_uses() + tagged_indirect_uses()); @@ -896,6 +1010,14 @@ void HPhi::AddInput(HValue* value) { } +bool HPhi::HasRealUses() { + for (HUseIterator it(uses()); !it.Done(); it.Advance()) { + if (!it.value()->IsPhi()) return true; + } + return false; +} + + HValue* HPhi::GetRedundantReplacement() { HValue* candidate = NULL; int count = OperandCount(); @@ -923,12 +1045,11 @@ void HPhi::DeleteFromGraph() { void HPhi::InitRealUses(int phi_id) { // Initialize real uses. phi_id_ = phi_id; - for (int j = 0; j < uses()->length(); j++) { - HValue* use = uses()->at(j); - if (!use->IsPhi()) { - int index = use->LookupOperandIndex(0, this); - Representation req_rep = use->RequiredInputRepresentation(index); - non_phi_uses_[req_rep.kind()]++; + for (HUseIterator it(uses()); !it.Done(); it.Advance()) { + HValue* value = it.value(); + if (!value->IsPhi()) { + Representation rep = value->RequiredInputRepresentation(it.index()); + ++non_phi_uses_[rep.kind()]; } } } @@ -965,6 +1086,16 @@ void HSimulate::PrintDataTo(StringStream* stream) { } +void HDeoptimize::PrintDataTo(StringStream* stream) { + if (OperandCount() == 0) return; + OperandAt(0)->PrintNameTo(stream); + for (int i = 1; i < OperandCount(); ++i) { + stream->Add(" "); + OperandAt(i)->PrintNameTo(stream); + } +} + + void HEnterInlined::PrintDataTo(StringStream* stream) { SmartPointer<char> name = function()->debug_name()->ToCString(); stream->Add("%s, id=%d", *name, function()->id()); @@ -973,10 +1104,9 @@ void HEnterInlined::PrintDataTo(StringStream* stream) { HConstant::HConstant(Handle<Object> handle, Representation r) : handle_(handle), - constant_type_(HType::TypeFromValue(handle)), has_int32_value_(false), - int32_value_(0), has_double_value_(false), + int32_value_(0), double_value_(0) { set_representation(r); SetFlag(kUseGVN); @@ -1001,18 +1131,35 @@ HConstant* HConstant::CopyToRepresentation(Representation r) const { HConstant* HConstant::CopyToTruncatedInt32() const { if (!has_double_value_) return NULL; int32_t truncated = NumberToInt32(*handle_); - return new HConstant(Factory::NewNumberFromInt(truncated), + return new HConstant(FACTORY->NewNumberFromInt(truncated), Representation::Integer32()); } +bool HConstant::ToBoolean() const { + // Converts the constant's boolean value according to + // ECMAScript section 9.2 ToBoolean conversion. + if (HasInteger32Value()) return Integer32Value() != 0; + if (HasDoubleValue()) { + double v = DoubleValue(); + return v != 0 && !isnan(v); + } + if (handle()->IsTrue()) return true; + if (handle()->IsFalse()) return false; + if (handle()->IsUndefined()) return false; + if (handle()->IsNull()) return false; + if (handle()->IsString() && + String::cast(*handle())->length() == 0) return false; + return true; +} + void HConstant::PrintDataTo(StringStream* stream) { handle()->ShortPrint(stream); } bool HArrayLiteral::IsCopyOnWrite() const { - return constant_elements()->map() == Heap::fixed_cow_array_map(); + return constant_elements()->map() == HEAP->fixed_cow_array_map(); } @@ -1026,34 +1173,30 @@ void HBinaryOperation::PrintDataTo(StringStream* stream) { Range* HBitAnd::InferRange() { - Range* a = left()->range(); - Range* b = right()->range(); - int32_t a_mask = 0xffffffff; - int32_t b_mask = 0xffffffff; - if (a != NULL) a_mask = a->Mask(); - if (b != NULL) b_mask = b->Mask(); - int32_t result_mask = a_mask & b_mask; - if (result_mask >= 0) { - return new Range(0, result_mask); - } else { - return HBinaryOperation::InferRange(); - } + int32_t left_mask = (left()->range() != NULL) + ? left()->range()->Mask() + : 0xffffffff; + int32_t right_mask = (right()->range() != NULL) + ? right()->range()->Mask() + : 0xffffffff; + int32_t result_mask = left_mask & right_mask; + return (result_mask >= 0) + ? new Range(0, result_mask) + : HValue::InferRange(); } Range* HBitOr::InferRange() { - Range* a = left()->range(); - Range* b = right()->range(); - int32_t a_mask = 0xffffffff; - int32_t b_mask = 0xffffffff; - if (a != NULL) a_mask = a->Mask(); - if (b != NULL) b_mask = b->Mask(); - int32_t result_mask = a_mask | b_mask; - if (result_mask >= 0) { - return new Range(0, result_mask); - } else { - return HBinaryOperation::InferRange(); - } + int32_t left_mask = (left()->range() != NULL) + ? left()->range()->Mask() + : 0xffffffff; + int32_t right_mask = (right()->range() != NULL) + ? right()->range()->Mask() + : 0xffffffff; + int32_t result_mask = left_mask | right_mask; + return (result_mask >= 0) + ? new Range(0, result_mask) + : HValue::InferRange(); } @@ -1061,20 +1204,14 @@ Range* HSar::InferRange() { if (right()->IsConstant()) { HConstant* c = HConstant::cast(right()); if (c->HasInteger32Value()) { - int32_t val = c->Integer32Value(); - Range* result = NULL; - Range* left_range = left()->range(); - if (left_range == NULL) { - result = new Range(); - } else { - result = left_range->Copy(); - } - result->Sar(val); + Range* result = (left()->range() != NULL) + ? left()->range()->Copy() + : new Range(); + result->Sar(c->Integer32Value()); return result; } } - - return HBinaryOperation::InferRange(); + return HValue::InferRange(); } @@ -1082,20 +1219,14 @@ Range* HShl::InferRange() { if (right()->IsConstant()) { HConstant* c = HConstant::cast(right()); if (c->HasInteger32Value()) { - int32_t val = c->Integer32Value(); - Range* result = NULL; - Range* left_range = left()->range(); - if (left_range == NULL) { - result = new Range(); - } else { - result = left_range->Copy(); - } - result->Shl(val); + Range* result = (left()->range() != NULL) + ? left()->range()->Copy() + : new Range(); + result->Shl(c->Integer32Value()); return result; } } - - return HBinaryOperation::InferRange(); + return HValue::InferRange(); } @@ -1112,6 +1243,10 @@ void HCompare::SetInputRepresentation(Representation r) { if (r.IsTagged()) { SetAllSideEffects(); ClearFlag(kUseGVN); + } else if (r.IsDouble()) { + SetFlag(kDeoptimizeOnUndefined); + ClearAllSideEffects(); + SetFlag(kUseGVN); } else { ClearAllSideEffects(); SetFlag(kUseGVN); @@ -1130,6 +1265,70 @@ void HLoadNamedField::PrintDataTo(StringStream* stream) { } +HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* object, + ZoneMapList* types, + Handle<String> name) + : HUnaryOperation(object), + types_(Min(types->length(), kMaxLoadPolymorphism)), + name_(name), + need_generic_(false) { + set_representation(Representation::Tagged()); + SetFlag(kDependsOnMaps); + for (int i = 0; + i < types->length() && types_.length() < kMaxLoadPolymorphism; + ++i) { + Handle<Map> map = types->at(i); + LookupResult lookup; + map->LookupInDescriptors(NULL, *name, &lookup); + if (lookup.IsProperty()) { + switch (lookup.type()) { + case FIELD: { + int index = lookup.GetLocalFieldIndexFromMap(*map); + if (index < 0) { + SetFlag(kDependsOnInobjectFields); + } else { + SetFlag(kDependsOnBackingStoreFields); + } + types_.Add(types->at(i)); + break; + } + case CONSTANT_FUNCTION: + types_.Add(types->at(i)); + break; + default: + break; + } + } + } + + if (types_.length() == types->length() && FLAG_deoptimize_uncommon_cases) { + SetFlag(kUseGVN); + } else { + SetAllSideEffects(); + need_generic_ = true; + } +} + + +bool HLoadNamedFieldPolymorphic::DataEquals(HValue* value) { + HLoadNamedFieldPolymorphic* other = HLoadNamedFieldPolymorphic::cast(value); + if (types_.length() != other->types()->length()) return false; + if (!name_.is_identical_to(other->name())) return false; + if (need_generic_ != other->need_generic_) return false; + for (int i = 0; i < types_.length(); i++) { + bool found = false; + for (int j = 0; j < types_.length(); j++) { + if (types_.at(j).is_identical_to(other->types()->at(i))) { + found = true; + break; + } + } + if (!found) return false; + } + return true; +} + + void HLoadKeyedFastElement::PrintDataTo(StringStream* stream) { object()->PrintNameTo(stream); stream->Add("["); @@ -1138,6 +1337,15 @@ void HLoadKeyedFastElement::PrintDataTo(StringStream* stream) { } +bool HLoadKeyedFastElement::RequiresHoleCheck() const { + for (HUseIterator it(uses()); !it.Done(); it.Advance()) { + HValue* use = it.value(); + if (!use->IsChange()) return true; + } + return false; +} + + void HLoadKeyedGeneric::PrintDataTo(StringStream* stream) { object()->PrintNameTo(stream); stream->Add("["); @@ -1146,8 +1354,45 @@ void HLoadKeyedGeneric::PrintDataTo(StringStream* stream) { } -void HLoadPixelArrayElement::PrintDataTo(StringStream* stream) { +void HLoadKeyedSpecializedArrayElement::PrintDataTo( + StringStream* stream) { external_pointer()->PrintNameTo(stream); + stream->Add("."); + switch (elements_kind()) { + case JSObject::EXTERNAL_BYTE_ELEMENTS: + stream->Add("byte"); + break; + case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: + stream->Add("u_byte"); + break; + case JSObject::EXTERNAL_SHORT_ELEMENTS: + stream->Add("short"); + break; + case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: + stream->Add("u_short"); + break; + case JSObject::EXTERNAL_INT_ELEMENTS: + stream->Add("int"); + break; + case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: + stream->Add("u_int"); + break; + case JSObject::EXTERNAL_FLOAT_ELEMENTS: + stream->Add("float"); + break; + case JSObject::EXTERNAL_DOUBLE_ELEMENTS: + stream->Add("double"); + break; + case JSObject::EXTERNAL_PIXEL_ELEMENTS: + stream->Add("pixel"); + break; + case JSObject::FAST_ELEMENTS: + case JSObject::FAST_DOUBLE_ELEMENTS: + case JSObject::DICTIONARY_ELEMENTS: + case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS: + UNREACHABLE(); + break; + } stream->Add("["); key()->PrintNameTo(stream); stream->Add("]"); @@ -1195,8 +1440,45 @@ void HStoreKeyedGeneric::PrintDataTo(StringStream* stream) { } -void HStorePixelArrayElement::PrintDataTo(StringStream* stream) { +void HStoreKeyedSpecializedArrayElement::PrintDataTo( + StringStream* stream) { external_pointer()->PrintNameTo(stream); + stream->Add("."); + switch (elements_kind()) { + case JSObject::EXTERNAL_BYTE_ELEMENTS: + stream->Add("byte"); + break; + case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: + stream->Add("u_byte"); + break; + case JSObject::EXTERNAL_SHORT_ELEMENTS: + stream->Add("short"); + break; + case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: + stream->Add("u_short"); + break; + case JSObject::EXTERNAL_INT_ELEMENTS: + stream->Add("int"); + break; + case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: + stream->Add("u_int"); + break; + case JSObject::EXTERNAL_FLOAT_ELEMENTS: + stream->Add("float"); + break; + case JSObject::EXTERNAL_DOUBLE_ELEMENTS: + stream->Add("double"); + break; + case JSObject::EXTERNAL_PIXEL_ELEMENTS: + stream->Add("pixel"); + break; + case JSObject::FAST_ELEMENTS: + case JSObject::FAST_DOUBLE_ELEMENTS: + case JSObject::DICTIONARY_ELEMENTS: + case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS: + UNREACHABLE(); + break; + } stream->Add("["); key()->PrintNameTo(stream); stream->Add("] = "); @@ -1204,18 +1486,29 @@ void HStorePixelArrayElement::PrintDataTo(StringStream* stream) { } -void HLoadGlobal::PrintDataTo(StringStream* stream) { +void HLoadGlobalCell::PrintDataTo(StringStream* stream) { stream->Add("[%p]", *cell()); if (check_hole_value()) stream->Add(" (deleteable/read-only)"); } -void HStoreGlobal::PrintDataTo(StringStream* stream) { +void HLoadGlobalGeneric::PrintDataTo(StringStream* stream) { + stream->Add("%o ", *name()); +} + + +void HStoreGlobalCell::PrintDataTo(StringStream* stream) { stream->Add("[%p] = ", *cell()); value()->PrintNameTo(stream); } +void HStoreGlobalGeneric::PrintDataTo(StringStream* stream) { + stream->Add("%o = ", *name()); + value()->PrintNameTo(stream); +} + + void HLoadContextSlot::PrintDataTo(StringStream* stream) { value()->PrintNameTo(stream); stream->Add("[%d]", slot_index()); @@ -1269,7 +1562,7 @@ HType HPhi::CalculateInferredType() { HType HConstant::CalculateInferredType() { - return constant_type_; + return HType::TypeFromValue(handle_); } @@ -1278,7 +1571,7 @@ HType HCompare::CalculateInferredType() { } -HType HCompareJSObjectEq::CalculateInferredType() { +HType HCompareObjectEq::CalculateInferredType() { return HType::Boolean(); } @@ -1288,6 +1581,21 @@ HType HUnaryPredicate::CalculateInferredType() { } +HType HInstanceOf::CalculateInferredType() { + return HType::Boolean(); +} + + +HType HDeleteProperty::CalculateInferredType() { + return HType::Boolean(); +} + + +HType HInstanceOfKnownGlobal::CalculateInferredType() { + return HType::Boolean(); +} + + HType HBitwiseBinaryOperation::CalculateInferredType() { return HType::TaggedNumber(); } @@ -1373,6 +1681,13 @@ HValue* HChange::EnsureAndPropagateNotMinusZero(BitVector* visited) { } +HValue* HForceRepresentation::EnsureAndPropagateNotMinusZero( + BitVector* visited) { + visited->Add(id()); + return value(); +} + + HValue* HMod::EnsureAndPropagateNotMinusZero(BitVector* visited) { visited->Add(id()); if (range() == NULL || range()->CanBeMinusZero()) { @@ -1423,6 +1738,13 @@ HValue* HAdd::EnsureAndPropagateNotMinusZero(BitVector* visited) { } +void HIn::PrintDataTo(StringStream* stream) { + key()->PrintNameTo(stream); + stream->Add(" "); + object()->PrintNameTo(stream); +} + + // Node-specific verification code is only included in debug mode. #ifdef DEBUG @@ -1446,7 +1768,6 @@ void HSimulate::Verify() { void HBoundsCheck::Verify() { HInstruction::Verify(); - ASSERT(HasNoUses()); } |