diff options
Diffstat (limited to 'deps/v8/src/hydrogen-instructions.cc')
-rw-r--r-- | deps/v8/src/hydrogen-instructions.cc | 1245 |
1 files changed, 626 insertions, 619 deletions
diff --git a/deps/v8/src/hydrogen-instructions.cc b/deps/v8/src/hydrogen-instructions.cc index 56ac7196c..b75bec0f5 100644 --- a/deps/v8/src/hydrogen-instructions.cc +++ b/deps/v8/src/hydrogen-instructions.cc @@ -2,27 +2,33 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "v8.h" +#include "src/v8.h" -#include "double.h" -#include "factory.h" -#include "hydrogen-infer-representation.h" -#include "property-details-inl.h" +#include "src/double.h" +#include "src/factory.h" +#include "src/hydrogen-infer-representation.h" +#include "src/property-details-inl.h" #if V8_TARGET_ARCH_IA32 -#include "ia32/lithium-ia32.h" +#include "src/ia32/lithium-ia32.h" // NOLINT #elif V8_TARGET_ARCH_X64 -#include "x64/lithium-x64.h" +#include "src/x64/lithium-x64.h" // NOLINT #elif V8_TARGET_ARCH_ARM64 -#include "arm64/lithium-arm64.h" +#include "src/arm64/lithium-arm64.h" // NOLINT #elif V8_TARGET_ARCH_ARM -#include "arm/lithium-arm.h" +#include "src/arm/lithium-arm.h" // NOLINT #elif V8_TARGET_ARCH_MIPS -#include "mips/lithium-mips.h" +#include "src/mips/lithium-mips.h" // NOLINT +#elif V8_TARGET_ARCH_MIPS64 +#include "src/mips64/lithium-mips64.h" // NOLINT +#elif V8_TARGET_ARCH_X87 +#include "src/x87/lithium-x87.h" // NOLINT #else #error Unsupported target architecture. #endif +#include "src/base/safe_math.h" + namespace v8 { namespace internal { @@ -35,7 +41,7 @@ HYDROGEN_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE) Isolate* HValue::isolate() const { - ASSERT(block() != NULL); + DCHECK(block() != NULL); return block()->isolate(); } @@ -51,7 +57,7 @@ void HValue::AssumeRepresentation(Representation r) { void HValue::InferRepresentation(HInferRepresentationPhase* h_infer) { - ASSERT(CheckFlag(kFlexibleRepresentation)); + DCHECK(CheckFlag(kFlexibleRepresentation)); Representation new_rep = RepresentationFromInputs(); UpdateRepresentation(new_rep, h_infer, "inputs"); new_rep = RepresentationFromUses(); @@ -286,7 +292,7 @@ void Range::KeepOrder() { #ifdef DEBUG void Range::Verify() const { - ASSERT(lower_ <= upper_); + DCHECK(lower_ <= upper_); } #endif @@ -306,46 +312,6 @@ bool Range::MulAndCheckOverflow(const Representation& r, Range* other) { } -const char* HType::ToString() { - // Note: The c1visualizer syntax for locals allows only a sequence of the - // following characters: A-Za-z0-9_-|: - switch (type_) { - case kNone: return "none"; - case kTagged: return "tagged"; - case kTaggedPrimitive: return "primitive"; - case kTaggedNumber: return "number"; - case kSmi: return "smi"; - case kHeapNumber: return "heap-number"; - case kString: return "string"; - case kBoolean: return "boolean"; - case kNonPrimitive: return "non-primitive"; - case kJSArray: return "array"; - case kJSObject: return "object"; - } - UNREACHABLE(); - return "unreachable"; -} - - -HType HType::TypeFromValue(Handle<Object> value) { - HType result = HType::Tagged(); - if (value->IsSmi()) { - result = HType::Smi(); - } else if (value->IsHeapNumber()) { - result = HType::HeapNumber(); - } else if (value->IsString()) { - result = HType::String(); - } else if (value->IsBoolean()) { - result = HType::Boolean(); - } else if (value->IsJSObject()) { - result = HType::JSObject(); - } else if (value->IsJSArray()) { - result = HType::JSArray(); - } - return result; -} - - bool HValue::IsDefinedAfter(HBasicBlock* other) const { return block()->block_id() > other->block_id(); } @@ -455,7 +421,7 @@ bool HValue::Equals(HValue* other) { if (OperandAt(i)->id() != other->OperandAt(i)->id()) return false; } bool result = DataEquals(other); - ASSERT(!result || Hashcode() == other->Hashcode()); + DCHECK(!result || Hashcode() == other->Hashcode()); return result; } @@ -527,7 +493,7 @@ void HValue::ReplaceAllUsesWith(HValue* other) { while (use_list_ != NULL) { HUseListNode* list_node = use_list_; HValue* value = list_node->value(); - ASSERT(!value->block()->IsStartBlock()); + DCHECK(!value->block()->IsStartBlock()); value->InternalSetOperandAt(list_node->index(), other); use_list_ = list_node->tail(); list_node->set_tail(other->use_list_); @@ -553,7 +519,7 @@ void HValue::Kill() { void HValue::SetBlock(HBasicBlock* block) { - ASSERT(block_ == NULL || block == NULL); + DCHECK(block_ == NULL || block == NULL); block_ = block; if (id_ == kNoNumber && block != NULL) { id_ = block->graph()->GetNextValueID(this); @@ -561,36 +527,36 @@ void HValue::SetBlock(HBasicBlock* block) { } -void HValue::PrintTypeTo(StringStream* stream) { - if (!representation().IsTagged() || type().Equals(HType::Tagged())) return; - stream->Add(" type:%s", type().ToString()); +OStream& operator<<(OStream& os, const HValue& v) { return v.PrintTo(os); } + + +OStream& operator<<(OStream& os, const TypeOf& t) { + if (t.value->representation().IsTagged() && + !t.value->type().Equals(HType::Tagged())) + return os; + return os << " type:" << t.value->type(); } -void HValue::PrintChangesTo(StringStream* stream) { - GVNFlagSet changes_flags = ChangesFlags(); - if (changes_flags.IsEmpty()) return; - stream->Add(" changes["); - if (changes_flags == AllSideEffectsFlagSet()) { - stream->Add("*"); +OStream& operator<<(OStream& os, const ChangesOf& c) { + GVNFlagSet changes_flags = c.value->ChangesFlags(); + if (changes_flags.IsEmpty()) return os; + os << " changes["; + if (changes_flags == c.value->AllSideEffectsFlagSet()) { + os << "*"; } else { bool add_comma = false; -#define PRINT_DO(Type) \ - if (changes_flags.Contains(k##Type)) { \ - if (add_comma) stream->Add(","); \ - add_comma = true; \ - stream->Add(#Type); \ - } +#define PRINT_DO(Type) \ + if (changes_flags.Contains(k##Type)) { \ + if (add_comma) os << ","; \ + add_comma = true; \ + os << #Type; \ + } GVN_TRACKED_FLAG_LIST(PRINT_DO); GVN_UNTRACKED_FLAG_LIST(PRINT_DO); #undef PRINT_DO } - stream->Add("]"); -} - - -void HValue::PrintNameTo(StringStream* stream) { - stream->Add("%s%d", representation_.Mnemonic(), id()); + return os << "]"; } @@ -631,74 +597,63 @@ void HValue::RegisterUse(int index, HValue* new_value) { void HValue::AddNewRange(Range* r, Zone* zone) { if (!HasRange()) ComputeInitialRange(zone); if (!HasRange()) range_ = new(zone) Range(); - ASSERT(HasRange()); + DCHECK(HasRange()); r->StackUpon(range_); range_ = r; } void HValue::RemoveLastAddedRange() { - ASSERT(HasRange()); - ASSERT(range_->next() != NULL); + DCHECK(HasRange()); + DCHECK(range_->next() != NULL); range_ = range_->next(); } void HValue::ComputeInitialRange(Zone* zone) { - ASSERT(!HasRange()); + DCHECK(!HasRange()); range_ = InferRange(zone); - ASSERT(HasRange()); + DCHECK(HasRange()); } -void HSourcePosition::PrintTo(FILE* out) { - if (IsUnknown()) { - PrintF(out, "<?>"); +OStream& operator<<(OStream& os, const HSourcePosition& p) { + if (p.IsUnknown()) { + return os << "<?>"; + } else if (FLAG_hydrogen_track_positions) { + return os << "<" << p.inlining_id() << ":" << p.position() << ">"; } else { - if (FLAG_hydrogen_track_positions) { - PrintF(out, "<%d:%d>", inlining_id(), position()); - } else { - PrintF(out, "<0:%d>", raw()); - } + return os << "<0:" << p.raw() << ">"; } } -void HInstruction::PrintTo(StringStream* stream) { - PrintMnemonicTo(stream); - PrintDataTo(stream); - PrintChangesTo(stream); - PrintTypeTo(stream); - if (CheckFlag(HValue::kHasNoObservableSideEffects)) { - stream->Add(" [noOSE]"); - } - if (CheckFlag(HValue::kIsDead)) { - stream->Add(" [dead]"); - } +OStream& HInstruction::PrintTo(OStream& os) const { // NOLINT + os << Mnemonic() << " "; + PrintDataTo(os) << ChangesOf(this) << TypeOf(this); + if (CheckFlag(HValue::kHasNoObservableSideEffects)) os << " [noOSE]"; + if (CheckFlag(HValue::kIsDead)) os << " [dead]"; + return os; } -void HInstruction::PrintDataTo(StringStream *stream) { +OStream& HInstruction::PrintDataTo(OStream& os) const { // NOLINT for (int i = 0; i < OperandCount(); ++i) { - if (i > 0) stream->Add(" "); - OperandAt(i)->PrintNameTo(stream); + if (i > 0) os << " "; + os << NameOf(OperandAt(i)); } -} - - -void HInstruction::PrintMnemonicTo(StringStream* stream) { - stream->Add("%s ", Mnemonic()); + return os; } void HInstruction::Unlink() { - ASSERT(IsLinked()); - ASSERT(!IsControlInstruction()); // Must never move control instructions. - ASSERT(!IsBlockEntry()); // Doesn't make sense to delete these. - ASSERT(previous_ != NULL); + DCHECK(IsLinked()); + DCHECK(!IsControlInstruction()); // Must never move control instructions. + DCHECK(!IsBlockEntry()); // Doesn't make sense to delete these. + DCHECK(previous_ != NULL); previous_->next_ = next_; if (next_ == NULL) { - ASSERT(block()->last() == this); + DCHECK(block()->last() == this); block()->set_last(previous_); } else { next_->previous_ = previous_; @@ -708,11 +663,11 @@ void HInstruction::Unlink() { void HInstruction::InsertBefore(HInstruction* next) { - ASSERT(!IsLinked()); - ASSERT(!next->IsBlockEntry()); - ASSERT(!IsControlInstruction()); - ASSERT(!next->block()->IsStartBlock()); - ASSERT(next->previous_ != NULL); + DCHECK(!IsLinked()); + DCHECK(!next->IsBlockEntry()); + DCHECK(!IsControlInstruction()); + DCHECK(!next->block()->IsStartBlock()); + DCHECK(next->previous_ != NULL); HInstruction* prev = next->previous(); prev->next_ = this; next->previous_ = this; @@ -726,14 +681,14 @@ void HInstruction::InsertBefore(HInstruction* next) { void HInstruction::InsertAfter(HInstruction* previous) { - ASSERT(!IsLinked()); - ASSERT(!previous->IsControlInstruction()); - ASSERT(!IsControlInstruction() || previous->next_ == NULL); + DCHECK(!IsLinked()); + DCHECK(!previous->IsControlInstruction()); + DCHECK(!IsControlInstruction() || previous->next_ == NULL); HBasicBlock* block = previous->block(); // Never insert anything except constants into the start block after finishing // it. if (block->IsStartBlock() && block->IsFinished() && !IsConstant()) { - ASSERT(block->end()->SecondSuccessor() == NULL); + DCHECK(block->end()->SecondSuccessor() == NULL); InsertAfter(block->end()->FirstSuccessor()->first()); return; } @@ -743,7 +698,7 @@ void HInstruction::InsertAfter(HInstruction* previous) { // simulate instruction instead. HInstruction* next = previous->next_; if (previous->HasObservableSideEffects() && next != NULL) { - ASSERT(next->IsSimulate()); + DCHECK(next->IsSimulate()); previous = next; next = previous->next_; } @@ -762,6 +717,21 @@ void HInstruction::InsertAfter(HInstruction* previous) { } +bool HInstruction::Dominates(HInstruction* other) { + if (block() != other->block()) { + return block()->Dominates(other->block()); + } + // Both instructions are in the same basic block. This instruction + // should precede the other one in order to dominate it. + for (HInstruction* instr = next(); instr != NULL; instr = instr->next()) { + if (instr == other) { + return true; + } + } + return false; +} + + #ifdef DEBUG void HInstruction::Verify() { // Verify that input operands are defined before use. @@ -778,19 +748,19 @@ void HInstruction::Verify() { cur = cur->previous(); } // Must reach other operand in the same block! - ASSERT(cur == other_operand); + DCHECK(cur == other_operand); } } else { // If the following assert fires, you may have forgotten an // AddInstruction. - ASSERT(other_block->Dominates(cur_block)); + DCHECK(other_block->Dominates(cur_block)); } } // Verify that instructions that may have side-effects are followed // by a simulate instruction. if (HasObservableSideEffects() && !IsOsrEntry()) { - ASSERT(next()->IsSimulate()); + DCHECK(next()->IsSimulate()); } // Verify that instructions that can be eliminated by GVN have overridden @@ -801,7 +771,7 @@ void HInstruction::Verify() { // Verify that all uses are in the graph. for (HUseIterator use = uses(); !use.Done(); use.Advance()) { if (use.value()->IsInstruction()) { - ASSERT(HInstruction::cast(use.value())->IsLinked()); + DCHECK(HInstruction::cast(use.value())->IsLinked()); } } } @@ -820,7 +790,6 @@ bool HInstruction::CanDeoptimize() { case HValue::kBlockEntry: case HValue::kBoundsCheckBaseIndexInformation: case HValue::kCallFunction: - case HValue::kCallJSFunction: case HValue::kCallNew: case HValue::kCallNewArray: case HValue::kCallStub: @@ -865,13 +834,12 @@ bool HInstruction::CanDeoptimize() { case HValue::kMathMinMax: case HValue::kParameter: case HValue::kPhi: - case HValue::kPushArgument: + case HValue::kPushArguments: case HValue::kRegExpLiteral: case HValue::kReturn: - case HValue::kRor: - case HValue::kSar: case HValue::kSeqStringGetChar: case HValue::kStoreCodeEntry: + case HValue::kStoreFrameContext: case HValue::kStoreKeyed: case HValue::kStoreNamedField: case HValue::kStoreNamedGeneric: @@ -884,10 +852,12 @@ bool HInstruction::CanDeoptimize() { return false; case HValue::kAdd: + case HValue::kAllocateBlockContext: case HValue::kApplyArguments: case HValue::kBitwise: case HValue::kBoundsCheck: case HValue::kBranch: + case HValue::kCallJSFunction: case HValue::kCallRuntime: case HValue::kChange: case HValue::kCheckHeapObject: @@ -914,6 +884,8 @@ bool HInstruction::CanDeoptimize() { case HValue::kMul: case HValue::kOsrEntry: case HValue::kPower: + case HValue::kRor: + case HValue::kSar: case HValue::kSeqStringSetChar: case HValue::kShl: case HValue::kShr: @@ -938,27 +910,28 @@ bool HInstruction::CanDeoptimize() { } -void HDummyUse::PrintDataTo(StringStream* stream) { - value()->PrintNameTo(stream); +OStream& operator<<(OStream& os, const NameOf& v) { + return os << v.value->representation().Mnemonic() << v.value->id(); +} + +OStream& HDummyUse::PrintDataTo(OStream& os) const { // NOLINT + return os << NameOf(value()); } -void HEnvironmentMarker::PrintDataTo(StringStream* stream) { - stream->Add("%s var[%d]", kind() == BIND ? "bind" : "lookup", index()); +OStream& HEnvironmentMarker::PrintDataTo(OStream& os) const { // NOLINT + return os << (kind() == BIND ? "bind" : "lookup") << " var[" << index() + << "]"; } -void HUnaryCall::PrintDataTo(StringStream* stream) { - value()->PrintNameTo(stream); - stream->Add(" "); - stream->Add("#%d", argument_count()); +OStream& HUnaryCall::PrintDataTo(OStream& os) const { // NOLINT + return os << NameOf(value()) << " #" << argument_count(); } -void HCallJSFunction::PrintDataTo(StringStream* stream) { - function()->PrintNameTo(stream); - stream->Add(" "); - stream->Add("#%d", argument_count()); +OStream& HCallJSFunction::PrintDataTo(OStream& os) const { // NOLINT + return os << NameOf(function()) << " #" << argument_count(); } @@ -984,14 +957,9 @@ HCallJSFunction* HCallJSFunction::New( } - - -void HBinaryCall::PrintDataTo(StringStream* stream) { - first()->PrintNameTo(stream); - stream->Add(" "); - second()->PrintNameTo(stream); - stream->Add(" "); - stream->Add("#%d", argument_count()); +OStream& HBinaryCall::PrintDataTo(OStream& os) const { // NOLINT + return os << NameOf(first()) << " " << NameOf(second()) << " #" + << argument_count(); } @@ -1001,7 +969,7 @@ void HBoundsCheck::ApplyIndexChange() { DecompositionResult decomposition; bool index_is_decomposable = index()->TryDecompose(&decomposition); if (index_is_decomposable) { - ASSERT(decomposition.base() == base()); + DCHECK(decomposition.base() == base()); if (decomposition.offset() == offset() && decomposition.scale() == scale()) return; } else { @@ -1045,27 +1013,24 @@ void HBoundsCheck::ApplyIndexChange() { } -void HBoundsCheck::PrintDataTo(StringStream* stream) { - index()->PrintNameTo(stream); - stream->Add(" "); - length()->PrintNameTo(stream); +OStream& HBoundsCheck::PrintDataTo(OStream& os) const { // NOLINT + os << NameOf(index()) << " " << NameOf(length()); if (base() != NULL && (offset() != 0 || scale() != 0)) { - stream->Add(" base: (("); + os << " base: (("; if (base() != index()) { - index()->PrintNameTo(stream); + os << NameOf(index()); } else { - stream->Add("index"); + os << "index"; } - stream->Add(" + %d) >> %d)", offset(), scale()); - } - if (skip_check()) { - stream->Add(" [DISABLED]"); + os << " + " << offset() << ") >> " << scale() << ")"; } + if (skip_check()) os << " [DISABLED]"; + return os; } void HBoundsCheck::InferRepresentation(HInferRepresentationPhase* h_infer) { - ASSERT(CheckFlag(kFlexibleRepresentation)); + DCHECK(CheckFlag(kFlexibleRepresentation)); HValue* actual_index = index()->ActualValue(); HValue* actual_length = length()->ActualValue(); Representation index_rep = actual_index->representation(); @@ -1103,84 +1068,78 @@ Range* HBoundsCheck::InferRange(Zone* zone) { } -void HBoundsCheckBaseIndexInformation::PrintDataTo(StringStream* stream) { - stream->Add("base: "); - base_index()->PrintNameTo(stream); - stream->Add(", check: "); - base_index()->PrintNameTo(stream); +OStream& HBoundsCheckBaseIndexInformation::PrintDataTo( + OStream& os) const { // NOLINT + // TODO(svenpanne) This 2nd base_index() looks wrong... + return os << "base: " << NameOf(base_index()) + << ", check: " << NameOf(base_index()); } -void HCallWithDescriptor::PrintDataTo(StringStream* stream) { +OStream& HCallWithDescriptor::PrintDataTo(OStream& os) const { // NOLINT for (int i = 0; i < OperandCount(); i++) { - OperandAt(i)->PrintNameTo(stream); - stream->Add(" "); + os << NameOf(OperandAt(i)) << " "; } - stream->Add("#%d", argument_count()); + return os << "#" << argument_count(); } -void HCallNewArray::PrintDataTo(StringStream* stream) { - stream->Add(ElementsKindToString(elements_kind())); - stream->Add(" "); - HBinaryCall::PrintDataTo(stream); +OStream& HCallNewArray::PrintDataTo(OStream& os) const { // NOLINT + os << ElementsKindToString(elements_kind()) << " "; + return HBinaryCall::PrintDataTo(os); } -void HCallRuntime::PrintDataTo(StringStream* stream) { - stream->Add("%o ", *name()); - if (save_doubles() == kSaveFPRegs) { - stream->Add("[save doubles] "); - } - stream->Add("#%d", argument_count()); +OStream& HCallRuntime::PrintDataTo(OStream& os) const { // NOLINT + os << name()->ToCString().get() << " "; + if (save_doubles() == kSaveFPRegs) os << "[save doubles] "; + return os << "#" << argument_count(); +} + + +OStream& HClassOfTestAndBranch::PrintDataTo(OStream& os) const { // NOLINT + return os << "class_of_test(" << NameOf(value()) << ", \"" + << class_name()->ToCString().get() << "\")"; } -void HClassOfTestAndBranch::PrintDataTo(StringStream* stream) { - stream->Add("class_of_test("); - value()->PrintNameTo(stream); - stream->Add(", \"%o\")", *class_name()); +OStream& HWrapReceiver::PrintDataTo(OStream& os) const { // NOLINT + return os << NameOf(receiver()) << " " << NameOf(function()); } -void HWrapReceiver::PrintDataTo(StringStream* stream) { - receiver()->PrintNameTo(stream); - stream->Add(" "); - function()->PrintNameTo(stream); +OStream& HAccessArgumentsAt::PrintDataTo(OStream& os) const { // NOLINT + return os << NameOf(arguments()) << "[" << NameOf(index()) << "], length " + << NameOf(length()); } -void HAccessArgumentsAt::PrintDataTo(StringStream* stream) { - arguments()->PrintNameTo(stream); - stream->Add("["); - index()->PrintNameTo(stream); - stream->Add("], length "); - length()->PrintNameTo(stream); +OStream& HAllocateBlockContext::PrintDataTo(OStream& os) const { // NOLINT + return os << NameOf(context()) << " " << NameOf(function()); } -void HControlInstruction::PrintDataTo(StringStream* stream) { - stream->Add(" goto ("); +OStream& HControlInstruction::PrintDataTo(OStream& os) const { // NOLINT + os << " 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()); + if (!first_block) os << ", "; + os << *it.Current(); first_block = false; } - stream->Add(")"); + return os << ")"; } -void HUnaryControlInstruction::PrintDataTo(StringStream* stream) { - value()->PrintNameTo(stream); - HControlInstruction::PrintDataTo(stream); +OStream& HUnaryControlInstruction::PrintDataTo(OStream& os) const { // NOLINT + os << NameOf(value()); + return HControlInstruction::PrintDataTo(os); } -void HReturn::PrintDataTo(StringStream* stream) { - value()->PrintNameTo(stream); - stream->Add(" (pop "); - parameter_count()->PrintNameTo(stream); - stream->Add(" values)"); +OStream& HReturn::PrintDataTo(OStream& os) const { // NOLINT + return os << NameOf(value()) << " (pop " << NameOf(parameter_count()) + << " values)"; } @@ -1212,8 +1171,8 @@ Representation HBranch::observed_input_representation(int index) { bool HBranch::KnownSuccessorBlock(HBasicBlock** block) { HValue* value = this->value(); if (value->EmitAtUses()) { - ASSERT(value->IsConstant()); - ASSERT(!value->representation().IsDouble()); + DCHECK(value->IsConstant()); + DCHECK(!value->representation().IsDouble()); *block = HConstant::cast(value)->BooleanValue() ? FirstSuccessor() : SecondSuccessor(); @@ -1224,35 +1183,44 @@ bool HBranch::KnownSuccessorBlock(HBasicBlock** block) { } -void HBranch::PrintDataTo(StringStream* stream) { - HUnaryControlInstruction::PrintDataTo(stream); - stream->Add(" "); - expected_input_types().Print(stream); +OStream& HBranch::PrintDataTo(OStream& os) const { // NOLINT + return HUnaryControlInstruction::PrintDataTo(os) << " " + << expected_input_types(); } -void HCompareMap::PrintDataTo(StringStream* stream) { - value()->PrintNameTo(stream); - stream->Add(" (%p)", *map().handle()); - HControlInstruction::PrintDataTo(stream); +OStream& HCompareMap::PrintDataTo(OStream& os) const { // NOLINT + os << NameOf(value()) << " (" << *map().handle() << ")"; + HControlInstruction::PrintDataTo(os); if (known_successor_index() == 0) { - stream->Add(" [true]"); + os << " [true]"; } else if (known_successor_index() == 1) { - stream->Add(" [false]"); + os << " [false]"; } + return os; } const char* HUnaryMathOperation::OpName() const { switch (op()) { - case kMathFloor: return "floor"; - case kMathRound: return "round"; - case kMathAbs: return "abs"; - case kMathLog: return "log"; - case kMathExp: return "exp"; - case kMathSqrt: return "sqrt"; - case kMathPowHalf: return "pow-half"; - case kMathClz32: return "clz32"; + case kMathFloor: + return "floor"; + case kMathFround: + return "fround"; + case kMathRound: + return "round"; + case kMathAbs: + return "abs"; + case kMathLog: + return "log"; + case kMathExp: + return "exp"; + case kMathSqrt: + return "sqrt"; + case kMathPowHalf: + return "pow-half"; + case kMathClz32: + return "clz32"; default: UNREACHABLE(); return NULL; @@ -1285,43 +1253,41 @@ Range* HUnaryMathOperation::InferRange(Zone* zone) { } -void HUnaryMathOperation::PrintDataTo(StringStream* stream) { - const char* name = OpName(); - stream->Add("%s ", name); - value()->PrintNameTo(stream); +OStream& HUnaryMathOperation::PrintDataTo(OStream& os) const { // NOLINT + return os << OpName() << " " << NameOf(value()); } -void HUnaryOperation::PrintDataTo(StringStream* stream) { - value()->PrintNameTo(stream); +OStream& HUnaryOperation::PrintDataTo(OStream& os) const { // NOLINT + return os << NameOf(value()); } -void HHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) { - value()->PrintNameTo(stream); +OStream& HHasInstanceTypeAndBranch::PrintDataTo(OStream& os) const { // NOLINT + os << NameOf(value()); switch (from_) { case FIRST_JS_RECEIVER_TYPE: - if (to_ == LAST_TYPE) stream->Add(" spec_object"); + if (to_ == LAST_TYPE) os << " spec_object"; break; case JS_REGEXP_TYPE: - if (to_ == JS_REGEXP_TYPE) stream->Add(" reg_exp"); + if (to_ == JS_REGEXP_TYPE) os << " reg_exp"; break; case JS_ARRAY_TYPE: - if (to_ == JS_ARRAY_TYPE) stream->Add(" array"); + if (to_ == JS_ARRAY_TYPE) os << " array"; break; case JS_FUNCTION_TYPE: - if (to_ == JS_FUNCTION_TYPE) stream->Add(" function"); + if (to_ == JS_FUNCTION_TYPE) os << " function"; break; default: break; } + return os; } -void HTypeofIsAndBranch::PrintDataTo(StringStream* stream) { - value()->PrintNameTo(stream); - stream->Add(" == %o", *type_literal_.handle()); - HControlInstruction::PrintDataTo(stream); +OStream& HTypeofIsAndBranch::PrintDataTo(OStream& os) const { // NOLINT + os << NameOf(value()) << " == " << type_literal()->ToCString().get(); + return HControlInstruction::PrintDataTo(os); } @@ -1338,10 +1304,9 @@ static String* TypeOfString(HConstant* constant, Isolate* isolate) { return heap->boolean_string(); } if (unique.IsKnownGlobal(heap->null_value())) { - return FLAG_harmony_typeof ? heap->null_string() - : heap->object_string(); + return heap->object_string(); } - ASSERT(unique.IsKnownGlobal(heap->undefined_value())); + DCHECK(unique.IsKnownGlobal(heap->undefined_value())); return heap->undefined_string(); } case SYMBOL_TYPE: @@ -1373,10 +1338,8 @@ bool HTypeofIsAndBranch::KnownSuccessorBlock(HBasicBlock** block) { } -void HCheckMapValue::PrintDataTo(StringStream* stream) { - value()->PrintNameTo(stream); - stream->Add(" "); - map()->PrintNameTo(stream); +OStream& HCheckMapValue::PrintDataTo(OStream& os) const { // NOLINT + return os << NameOf(value()) << " " << NameOf(map()); } @@ -1391,23 +1354,19 @@ HValue* HCheckMapValue::Canonicalize() { } -void HForInPrepareMap::PrintDataTo(StringStream* stream) { - enumerable()->PrintNameTo(stream); +OStream& HForInPrepareMap::PrintDataTo(OStream& os) const { // NOLINT + return os << NameOf(enumerable()); } -void HForInCacheArray::PrintDataTo(StringStream* stream) { - enumerable()->PrintNameTo(stream); - stream->Add(" "); - map()->PrintNameTo(stream); - stream->Add("[%d]", idx_); +OStream& HForInCacheArray::PrintDataTo(OStream& os) const { // NOLINT + return os << NameOf(enumerable()) << " " << NameOf(map()) << "[" << idx_ + << "]"; } -void HLoadFieldByIndex::PrintDataTo(StringStream* stream) { - object()->PrintNameTo(stream); - stream->Add(" "); - index()->PrintNameTo(stream); +OStream& HLoadFieldByIndex::PrintDataTo(OStream& os) const { // NOLINT + return os << NameOf(object()) << " " << NameOf(index()); } @@ -1543,8 +1502,8 @@ HValue* HWrapReceiver::Canonicalize() { } -void HTypeof::PrintDataTo(StringStream* stream) { - value()->PrintNameTo(stream); +OStream& HTypeof::PrintDataTo(OStream& os) const { // NOLINT + return os << NameOf(value()); } @@ -1554,7 +1513,10 @@ HInstruction* HForceRepresentation::New(Zone* zone, HValue* context, HConstant* c = HConstant::cast(value); if (c->HasNumberValue()) { double double_res = c->DoubleValue(); - if (representation.CanContainDouble(double_res)) { + if (representation.IsDouble()) { + return HConstant::New(zone, context, double_res); + + } else if (representation.CanContainDouble(double_res)) { return HConstant::New(zone, context, static_cast<int32_t>(double_res), representation); @@ -1565,20 +1527,20 @@ HInstruction* HForceRepresentation::New(Zone* zone, HValue* context, } -void HForceRepresentation::PrintDataTo(StringStream* stream) { - stream->Add("%s ", representation().Mnemonic()); - value()->PrintNameTo(stream); +OStream& HForceRepresentation::PrintDataTo(OStream& os) const { // NOLINT + return os << representation().Mnemonic() << " " << NameOf(value()); } -void HChange::PrintDataTo(StringStream* stream) { - HUnaryOperation::PrintDataTo(stream); - stream->Add(" %s to %s", from().Mnemonic(), to().Mnemonic()); +OStream& HChange::PrintDataTo(OStream& os) const { // NOLINT + HUnaryOperation::PrintDataTo(os); + os << " " << from().Mnemonic() << " to " << to().Mnemonic(); - if (CanTruncateToSmi()) stream->Add(" truncating-smi"); - if (CanTruncateToInt32()) stream->Add(" truncating-int32"); - if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?"); - if (CheckFlag(kAllowUndefinedAsNaN)) stream->Add(" allow-undefined-as-nan"); + if (CanTruncateToSmi()) os << " truncating-smi"; + if (CanTruncateToInt32()) os << " truncating-int32"; + if (CheckFlag(kBailoutOnMinusZero)) os << " -0?"; + if (CheckFlag(kAllowUndefinedAsNaN)) os << " allow-undefined-as-nan"; + return os; } @@ -1592,7 +1554,7 @@ HValue* HUnaryMathOperation::Canonicalize() { val, representation(), false, false)); } } - if (op() == kMathFloor && value()->IsDiv() && value()->UseCount() == 1) { + if (op() == kMathFloor && value()->IsDiv() && value()->HasOneUse()) { HDiv* hdiv = HDiv::cast(value()); HValue* left = hdiv->left(); @@ -1633,7 +1595,9 @@ HValue* HUnaryMathOperation::Canonicalize() { HValue* HCheckInstanceType::Canonicalize() { - if (check_ == IS_STRING && value()->type().IsString()) { + if ((check_ == IS_SPEC_OBJECT && value()->type().IsJSObject()) || + (check_ == IS_JS_ARRAY && value()->type().IsJSArray()) || + (check_ == IS_STRING && value()->type().IsString())) { return value(); } @@ -1648,7 +1612,7 @@ HValue* HCheckInstanceType::Canonicalize() { void HCheckInstanceType::GetCheckInterval(InstanceType* first, InstanceType* last) { - ASSERT(is_interval_check()); + DCHECK(is_interval_check()); switch (check_) { case IS_SPEC_OBJECT: *first = FIRST_SPEC_OBJECT_TYPE; @@ -1664,7 +1628,7 @@ void HCheckInstanceType::GetCheckInterval(InstanceType* first, void HCheckInstanceType::GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag) { - ASSERT(!is_interval_check()); + DCHECK(!is_interval_check()); switch (check_) { case IS_STRING: *mask = kIsNotStringMask; @@ -1680,13 +1644,14 @@ void HCheckInstanceType::GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag) { } -void HCheckMaps::PrintDataTo(StringStream* stream) { - value()->PrintNameTo(stream); - stream->Add(" [%p", *maps()->at(0).handle()); +OStream& HCheckMaps::PrintDataTo(OStream& os) const { // NOLINT + os << NameOf(value()) << " [" << *maps()->at(0).handle(); for (int i = 1; i < maps()->size(); ++i) { - stream->Add(",%p", *maps()->at(i).handle()); + os << "," << *maps()->at(i).handle(); } - stream->Add("]%s", IsStabilityCheck() ? "(stability-check)" : ""); + os << "]"; + if (IsStabilityCheck()) os << "(stability-check)"; + return os; } @@ -1710,10 +1675,8 @@ HValue* HCheckMaps::Canonicalize() { } -void HCheckValue::PrintDataTo(StringStream* stream) { - value()->PrintNameTo(stream); - stream->Add(" "); - object().handle()->ShortPrint(stream); +OStream& HCheckValue::PrintDataTo(OStream& os) const { // NOLINT + return os << NameOf(value()) << " " << Brief(*object().handle()); } @@ -1723,7 +1686,7 @@ HValue* HCheckValue::Canonicalize() { } -const char* HCheckInstanceType::GetCheckName() { +const char* HCheckInstanceType::GetCheckName() const { switch (check_) { case IS_SPEC_OBJECT: return "object"; case IS_JS_ARRAY: return "array"; @@ -1735,34 +1698,30 @@ const char* HCheckInstanceType::GetCheckName() { } -void HCheckInstanceType::PrintDataTo(StringStream* stream) { - stream->Add("%s ", GetCheckName()); - HUnaryOperation::PrintDataTo(stream); +OStream& HCheckInstanceType::PrintDataTo(OStream& os) const { // NOLINT + os << GetCheckName() << " "; + return HUnaryOperation::PrintDataTo(os); } -void HCallStub::PrintDataTo(StringStream* stream) { - stream->Add("%s ", - CodeStub::MajorName(major_key_, false)); - HUnaryCall::PrintDataTo(stream); +OStream& HCallStub::PrintDataTo(OStream& os) const { // NOLINT + os << CodeStub::MajorName(major_key_, false) << " "; + return HUnaryCall::PrintDataTo(os); } -void HUnknownOSRValue::PrintDataTo(StringStream *stream) { +OStream& HUnknownOSRValue::PrintDataTo(OStream& os) const { // NOLINT const char* type = "expression"; if (environment_->is_local_index(index_)) type = "local"; if (environment_->is_special_index(index_)) type = "special"; if (environment_->is_parameter_index(index_)) type = "parameter"; - stream->Add("%s @ %d", type, index_); + return os << type << " @ " << index_; } -void HInstanceOf::PrintDataTo(StringStream* stream) { - left()->PrintNameTo(stream); - stream->Add(" "); - right()->PrintNameTo(stream); - stream->Add(" "); - context()->PrintNameTo(stream); +OStream& HInstanceOf::PrintDataTo(OStream& os) const { // NOLINT + return os << NameOf(left()) << " " << NameOf(right()) << " " + << NameOf(context()); } @@ -1972,15 +1931,18 @@ Range* HMathFloorOfDiv::InferRange(Zone* zone) { } +// Returns the absolute value of its argument minus one, avoiding undefined +// behavior at kMinInt. +static int32_t AbsMinus1(int32_t a) { return a < 0 ? -(a + 1) : (a - 1); } + + Range* HMod::InferRange(Zone* zone) { if (representation().IsInteger32()) { Range* a = left()->range(); Range* b = right()->range(); - // The magnitude of the modulus is bounded by the right operand. Note that - // apart for the cases involving kMinInt, the calculation below is the same - // as Max(Abs(b->lower()), Abs(b->upper())) - 1. - int32_t positive_bound = -(Min(NegAbs(b->lower()), NegAbs(b->upper())) + 1); + // The magnitude of the modulus is bounded by the right operand. + int32_t positive_bound = Max(AbsMinus1(b->lower()), AbsMinus1(b->upper())); // The result of the modulo operation has the sign of its left operand. bool left_can_be_negative = a->CanBeMinusZero() || a->CanBeNegative(); @@ -2093,7 +2055,7 @@ void InductionVariableData::DecomposeBitwise( void InductionVariableData::AddCheck(HBoundsCheck* check, int32_t upper_limit) { - ASSERT(limit_validity() != NULL); + DCHECK(limit_validity() != NULL); if (limit_validity() != check->block() && !limit_validity()->Dominates(check->block())) return; if (!phi()->block()->current_loop()->IsNestedInThisLoop( @@ -2131,9 +2093,9 @@ void InductionVariableData::ChecksRelatedToLength::UseNewIndexInCurrentBlock( int32_t mask, HValue* index_base, HValue* context) { - ASSERT(first_check_in_block() != NULL); + DCHECK(first_check_in_block() != NULL); HValue* previous_index = first_check_in_block()->index(); - ASSERT(context != NULL); + DCHECK(context != NULL); Zone* zone = index_base->block()->graph()->zone(); set_added_constant(HConstant::New(zone, context, mask)); @@ -2147,18 +2109,18 @@ void InductionVariableData::ChecksRelatedToLength::UseNewIndexInCurrentBlock( first_check_in_block()->ReplaceAllUsesWith(first_check_in_block()->index()); HInstruction* new_index = HBitwise::New(zone, context, token, index_base, added_constant()); - ASSERT(new_index->IsBitwise()); + DCHECK(new_index->IsBitwise()); new_index->ClearAllSideEffects(); new_index->AssumeRepresentation(Representation::Integer32()); set_added_index(HBitwise::cast(new_index)); added_index()->InsertBefore(first_check_in_block()); } - ASSERT(added_index()->op() == token); + DCHECK(added_index()->op() == token); added_index()->SetOperandAt(1, index_base); added_index()->SetOperandAt(2, added_constant()); first_check_in_block()->SetOperandAt(0, added_index()); - if (previous_index->UseCount() == 0) { + if (previous_index->HasNoUses()) { previous_index->DeleteAndReplaceWith(NULL); } } @@ -2263,7 +2225,7 @@ int32_t InductionVariableData::ComputeIncrement(HPhi* phi, */ void InductionVariableData::UpdateAdditionalLimit( InductionVariableLimitUpdate* update) { - ASSERT(update->updated_variable == this); + DCHECK(update->updated_variable == this); if (update->limit_is_upper) { swap(&additional_upper_limit_, &update->limit); swap(&additional_upper_limit_is_included_, &update->limit_is_included); @@ -2394,7 +2356,7 @@ void InductionVariableData::ComputeLimitFromPredecessorBlock( } else { other_target = branch->SuccessorAt(0); token = Token::NegateCompareOp(token); - ASSERT(block == branch->SuccessorAt(1)); + DCHECK(block == branch->SuccessorAt(1)); } InductionVariableData* data; @@ -2459,7 +2421,7 @@ Range* HMathMinMax::InferRange(Zone* zone) { if (operation_ == kMathMax) { res->CombinedMax(b); } else { - ASSERT(operation_ == kMathMin); + DCHECK(operation_ == kMathMin); res->CombinedMin(b); } return res; @@ -2469,22 +2431,23 @@ Range* HMathMinMax::InferRange(Zone* zone) { } -void HPhi::PrintTo(StringStream* stream) { - stream->Add("["); +void HPushArguments::AddInput(HValue* value) { + inputs_.Add(NULL, value->block()->zone()); + SetOperandAt(OperandCount() - 1, value); +} + + +OStream& HPhi::PrintTo(OStream& os) const { // NOLINT + os << "["; for (int i = 0; i < OperandCount(); ++i) { - HValue* value = OperandAt(i); - stream->Add(" "); - value->PrintNameTo(stream); - stream->Add(" "); + os << " " << NameOf(OperandAt(i)) << " "; } - stream->Add(" uses:%d_%ds_%di_%dd_%dt", - UseCount(), - smi_non_phi_uses() + smi_indirect_uses(), - int32_non_phi_uses() + int32_indirect_uses(), - double_non_phi_uses() + double_indirect_uses(), - tagged_non_phi_uses() + tagged_indirect_uses()); - PrintTypeTo(stream); - stream->Add("]"); + return os << " uses:" << UseCount() << "_" + << smi_non_phi_uses() + smi_indirect_uses() << "s_" + << int32_non_phi_uses() + int32_indirect_uses() << "i_" + << double_non_phi_uses() + double_indirect_uses() << "d_" + << tagged_non_phi_uses() + tagged_indirect_uses() << "t" + << TypeOf(this) << "]"; } @@ -2518,15 +2481,15 @@ HValue* HPhi::GetRedundantReplacement() { HValue* current = OperandAt(position++); if (current != this && current != candidate) return NULL; } - ASSERT(candidate != this); + DCHECK(candidate != this); return candidate; } void HPhi::DeleteFromGraph() { - ASSERT(block() != NULL); + DCHECK(block() != NULL); block()->RemovePhi(this); - ASSERT(block() == NULL); + DCHECK(block() == NULL); } @@ -2606,27 +2569,28 @@ void HSimulate::MergeWith(ZoneList<HSimulate*>* list) { } -void HSimulate::PrintDataTo(StringStream* stream) { - stream->Add("id=%d", ast_id().ToInt()); - if (pop_count_ > 0) stream->Add(" pop %d", pop_count_); +OStream& HSimulate::PrintDataTo(OStream& os) const { // NOLINT + os << "id=" << ast_id().ToInt(); + if (pop_count_ > 0) os << " pop " << pop_count_; if (values_.length() > 0) { - if (pop_count_ > 0) stream->Add(" /"); + if (pop_count_ > 0) os << " /"; for (int i = values_.length() - 1; i >= 0; --i) { if (HasAssignedIndexAt(i)) { - stream->Add(" var[%d] = ", GetAssignedIndexAt(i)); + os << " var[" << GetAssignedIndexAt(i) << "] = "; } else { - stream->Add(" push "); + os << " push "; } - values_[i]->PrintNameTo(stream); - if (i > 0) stream->Add(","); + os << NameOf(values_[i]); + if (i > 0) os << ","; } } + return os; } void HSimulate::ReplayEnvironment(HEnvironment* env) { if (done_with_replay_) return; - ASSERT(env != NULL); + DCHECK(env != NULL); env->set_ast_id(ast_id()); env->Drop(pop_count()); for (int i = values()->length() - 1; i >= 0; --i) { @@ -2659,7 +2623,7 @@ static void ReplayEnvironmentNested(const ZoneList<HValue*>* values, // Replay captured objects by replacing all captured objects with the // same capture id in the current and all outer environments. void HCapturedObject::ReplayEnvironment(HEnvironment* env) { - ASSERT(env != NULL); + DCHECK(env != NULL); while (env != NULL) { ReplayEnvironmentNested(env->values(), this); env = env->outer(); @@ -2667,22 +2631,22 @@ void HCapturedObject::ReplayEnvironment(HEnvironment* env) { } -void HCapturedObject::PrintDataTo(StringStream* stream) { - stream->Add("#%d ", capture_id()); - HDematerializedObject::PrintDataTo(stream); +OStream& HCapturedObject::PrintDataTo(OStream& os) const { // NOLINT + os << "#" << capture_id() << " "; + return HDematerializedObject::PrintDataTo(os); } void HEnterInlined::RegisterReturnTarget(HBasicBlock* return_target, Zone* zone) { - ASSERT(return_target->IsInlineReturnTarget()); + DCHECK(return_target->IsInlineReturnTarget()); return_targets_.Add(return_target, zone); } -void HEnterInlined::PrintDataTo(StringStream* stream) { - SmartArrayPointer<char> name = function()->debug_name()->ToCString(); - stream->Add("%s, id=%d", name.get(), function()->id().ToInt()); +OStream& HEnterInlined::PrintDataTo(OStream& os) const { // NOLINT + return os << function()->debug_name()->ToCString().get() + << ", id=" << function()->id().ToInt(); } @@ -2693,7 +2657,7 @@ static bool IsInteger32(double value) { HConstant::HConstant(Handle<Object> object, Representation r) - : HTemplateInstruction<0>(HType::TypeFromValue(object)), + : HTemplateInstruction<0>(HType::FromValue(object)), object_(Unique<Object>::CreateUninitialized(object)), object_map_(Handle<Map>::null()), has_stable_map_value_(false), @@ -2751,8 +2715,8 @@ HConstant::HConstant(Unique<Object> object, boolean_value_(boolean_value), is_undetectable_(is_undetectable), instance_type_(instance_type) { - ASSERT(!object.handle().is_null()); - ASSERT(!type.IsTaggedNumber()); + DCHECK(!object.handle().is_null()); + DCHECK(!type.IsTaggedNumber() || type.IsNone()); Initialize(r); } @@ -2810,7 +2774,7 @@ HConstant::HConstant(double double_value, HConstant::HConstant(ExternalReference reference) - : HTemplateInstruction<0>(HType::None()), + : HTemplateInstruction<0>(HType::Any()), object_(Unique<Object>(Handle<Object>::null())), object_map_(Handle<Map>::null()), has_stable_map_value_(false), @@ -2868,10 +2832,10 @@ bool HConstant::ImmortalImmovable() const { return false; } - ASSERT(!object_.handle().is_null()); + DCHECK(!object_.handle().is_null()); Heap* heap = isolate()->heap(); - ASSERT(!object_.IsKnownGlobal(heap->minus_zero_value())); - ASSERT(!object_.IsKnownGlobal(heap->nan_value())); + DCHECK(!object_.IsKnownGlobal(heap->minus_zero_value())); + DCHECK(!object_.IsKnownGlobal(heap->nan_value())); return #define IMMORTAL_IMMOVABLE_ROOT(name) \ object_.IsKnownGlobal(heap->name()) || @@ -2890,15 +2854,16 @@ bool HConstant::ImmortalImmovable() const { bool HConstant::EmitAtUses() { - ASSERT(IsLinked()); + DCHECK(IsLinked()); if (block()->graph()->has_osr() && block()->graph()->IsStandardConstant(this)) { // TODO(titzer): this seems like a hack that should be fixed by custom OSR. return true; } - if (UseCount() == 0) return true; + if (HasNoUses()) return true; if (IsCell()) return false; if (representation().IsDouble()) return false; + if (representation().IsExternal()) return false; return true; } @@ -2917,7 +2882,7 @@ HConstant* HConstant::CopyToRepresentation(Representation r, Zone* zone) const { if (has_external_reference_value_) { return new(zone) HConstant(external_reference_value_); } - ASSERT(!object_.handle().is_null()); + DCHECK(!object_.handle().is_null()); return new(zone) HConstant(object_, object_map_, has_stable_map_value_, @@ -2954,7 +2919,7 @@ Maybe<HConstant*> HConstant::CopyToTruncatedNumber(Zone* zone) { res = handle->BooleanValue() ? new(zone) HConstant(1) : new(zone) HConstant(0); } else if (handle->IsUndefined()) { - res = new(zone) HConstant(OS::nan_value()); + res = new(zone) HConstant(base::OS::nan_value()); } else if (handle->IsNull()) { res = new(zone) HConstant(0); } @@ -2962,41 +2927,35 @@ Maybe<HConstant*> HConstant::CopyToTruncatedNumber(Zone* zone) { } -void HConstant::PrintDataTo(StringStream* stream) { +OStream& HConstant::PrintDataTo(OStream& os) const { // NOLINT if (has_int32_value_) { - stream->Add("%d ", int32_value_); + os << int32_value_ << " "; } else if (has_double_value_) { - stream->Add("%f ", FmtElm(double_value_)); + os << double_value_ << " "; } else if (has_external_reference_value_) { - stream->Add("%p ", reinterpret_cast<void*>( - external_reference_value_.address())); + os << reinterpret_cast<void*>(external_reference_value_.address()) << " "; } else { - handle(Isolate::Current())->ShortPrint(stream); - stream->Add(" "); - if (HasStableMapValue()) { - stream->Add("[stable-map] "); - } - if (HasObjectMap()) { - stream->Add("[map %p] ", *ObjectMap().handle()); - } - } - if (!is_not_in_new_space_) { - stream->Add("[new space] "); + // The handle() method is silently and lazily mutating the object. + Handle<Object> h = const_cast<HConstant*>(this)->handle(Isolate::Current()); + os << Brief(*h) << " "; + if (HasStableMapValue()) os << "[stable-map] "; + if (HasObjectMap()) os << "[map " << *ObjectMap().handle() << "] "; } + if (!is_not_in_new_space_) os << "[new space] "; + return os; } -void HBinaryOperation::PrintDataTo(StringStream* stream) { - left()->PrintNameTo(stream); - stream->Add(" "); - right()->PrintNameTo(stream); - if (CheckFlag(kCanOverflow)) stream->Add(" !"); - if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?"); +OStream& HBinaryOperation::PrintDataTo(OStream& os) const { // NOLINT + os << NameOf(left()) << " " << NameOf(right()); + if (CheckFlag(kCanOverflow)) os << " !"; + if (CheckFlag(kBailoutOnMinusZero)) os << " -0?"; + return os; } void HBinaryOperation::InferRepresentation(HInferRepresentationPhase* h_infer) { - ASSERT(CheckFlag(kFlexibleRepresentation)); + DCHECK(CheckFlag(kFlexibleRepresentation)); Representation new_rep = RepresentationFromInputs(); UpdateRepresentation(new_rep, h_infer, "inputs"); @@ -3063,7 +3022,7 @@ void HBinaryOperation::AssumeRepresentation(Representation r) { void HMathMinMax::InferRepresentation(HInferRepresentationPhase* h_infer) { - ASSERT(CheckFlag(kFlexibleRepresentation)); + DCHECK(CheckFlag(kFlexibleRepresentation)); Representation new_rep = RepresentationFromInputs(); UpdateRepresentation(new_rep, h_infer, "inputs"); // Do not care about uses. @@ -3214,35 +3173,27 @@ Range* HLoadKeyed::InferRange(Zone* zone) { } -void HCompareGeneric::PrintDataTo(StringStream* stream) { - stream->Add(Token::Name(token())); - stream->Add(" "); - HBinaryOperation::PrintDataTo(stream); +OStream& HCompareGeneric::PrintDataTo(OStream& os) const { // NOLINT + os << Token::Name(token()) << " "; + return HBinaryOperation::PrintDataTo(os); } -void HStringCompareAndBranch::PrintDataTo(StringStream* stream) { - stream->Add(Token::Name(token())); - stream->Add(" "); - HControlInstruction::PrintDataTo(stream); +OStream& HStringCompareAndBranch::PrintDataTo(OStream& os) const { // NOLINT + os << Token::Name(token()) << " "; + return HControlInstruction::PrintDataTo(os); } -void HCompareNumericAndBranch::PrintDataTo(StringStream* stream) { - stream->Add(Token::Name(token())); - stream->Add(" "); - left()->PrintNameTo(stream); - stream->Add(" "); - right()->PrintNameTo(stream); - HControlInstruction::PrintDataTo(stream); +OStream& HCompareNumericAndBranch::PrintDataTo(OStream& os) const { // NOLINT + os << Token::Name(token()) << " " << NameOf(left()) << " " << NameOf(right()); + return HControlInstruction::PrintDataTo(os); } -void HCompareObjectEqAndBranch::PrintDataTo(StringStream* stream) { - left()->PrintNameTo(stream); - stream->Add(" "); - right()->PrintNameTo(stream); - HControlInstruction::PrintDataTo(stream); +OStream& HCompareObjectEqAndBranch::PrintDataTo(OStream& os) const { // NOLINT + os << NameOf(left()) << " " << NameOf(right()); + return HControlInstruction::PrintDataTo(os); } @@ -3285,11 +3236,27 @@ bool HIsObjectAndBranch::KnownSuccessorBlock(HBasicBlock** block) { bool HIsStringAndBranch::KnownSuccessorBlock(HBasicBlock** block) { + if (known_successor_index() != kNoKnownSuccessorIndex) { + *block = SuccessorAt(known_successor_index()); + return true; + } if (FLAG_fold_constants && value()->IsConstant()) { *block = HConstant::cast(value())->HasStringValue() ? FirstSuccessor() : SecondSuccessor(); return true; } + if (value()->type().IsString()) { + *block = FirstSuccessor(); + return true; + } + if (value()->type().IsSmi() || + value()->type().IsNull() || + value()->type().IsBoolean() || + value()->type().IsUndefined() || + value()->type().IsJSObject()) { + *block = SecondSuccessor(); + return true; + } *block = NULL; return false; } @@ -3364,9 +3331,8 @@ void HCompareMinusZeroAndBranch::InferRepresentation( } - -void HGoto::PrintDataTo(StringStream* stream) { - stream->Add("B%d", SuccessorAt(0)->block_id()); +OStream& HGoto::PrintDataTo(OStream& os) const { // NOLINT + return os << *SuccessorAt(0); } @@ -3409,64 +3375,65 @@ void HCompareNumericAndBranch::InferRepresentation( } -void HParameter::PrintDataTo(StringStream* stream) { - stream->Add("%u", index()); +OStream& HParameter::PrintDataTo(OStream& os) const { // NOLINT + return os << index(); } -void HLoadNamedField::PrintDataTo(StringStream* stream) { - object()->PrintNameTo(stream); - access_.PrintTo(stream); +OStream& HLoadNamedField::PrintDataTo(OStream& os) const { // NOLINT + os << NameOf(object()) << access_; if (maps() != NULL) { - stream->Add(" [%p", *maps()->at(0).handle()); + os << " [" << *maps()->at(0).handle(); for (int i = 1; i < maps()->size(); ++i) { - stream->Add(",%p", *maps()->at(i).handle()); + os << "," << *maps()->at(i).handle(); } - stream->Add("]"); + os << "]"; } - if (HasDependency()) { - stream->Add(" "); - dependency()->PrintNameTo(stream); - } + if (HasDependency()) os << " " << NameOf(dependency()); + return os; } -void HLoadNamedGeneric::PrintDataTo(StringStream* stream) { - object()->PrintNameTo(stream); - stream->Add("."); - stream->Add(String::cast(*name())->ToCString().get()); +OStream& HLoadNamedGeneric::PrintDataTo(OStream& os) const { // NOLINT + Handle<String> n = Handle<String>::cast(name()); + return os << NameOf(object()) << "." << n->ToCString().get(); } -void HLoadKeyed::PrintDataTo(StringStream* stream) { +OStream& HLoadKeyed::PrintDataTo(OStream& os) const { // NOLINT if (!is_external()) { - elements()->PrintNameTo(stream); + os << NameOf(elements()); } else { - ASSERT(elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND && + DCHECK(elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND && elements_kind() <= LAST_EXTERNAL_ARRAY_ELEMENTS_KIND); - elements()->PrintNameTo(stream); - stream->Add("."); - stream->Add(ElementsKindToString(elements_kind())); + os << NameOf(elements()) << "." << ElementsKindToString(elements_kind()); } - stream->Add("["); - key()->PrintNameTo(stream); - if (IsDehoisted()) { - stream->Add(" + %d]", index_offset()); - } else { - stream->Add("]"); - } + os << "[" << NameOf(key()); + if (IsDehoisted()) os << " + " << base_offset(); + os << "]"; - if (HasDependency()) { - stream->Add(" "); - dependency()->PrintNameTo(stream); - } + if (HasDependency()) os << " " << NameOf(dependency()); + if (RequiresHoleCheck()) os << " check_hole"; + return os; +} - if (RequiresHoleCheck()) { - stream->Add(" check_hole"); - } + +bool HLoadKeyed::TryIncreaseBaseOffset(uint32_t increase_by_value) { + // The base offset is usually simply the size of the array header, except + // with dehoisting adds an addition offset due to a array index key + // manipulation, in which case it becomes (array header size + + // constant-offset-from-key * kPointerSize) + uint32_t base_offset = BaseOffsetField::decode(bit_field_); + v8::base::internal::CheckedNumeric<uint32_t> addition_result = base_offset; + addition_result += increase_by_value; + if (!addition_result.IsValid()) return false; + base_offset = addition_result.ValueOrDie(); + if (!BaseOffsetField::is_valid(base_offset)) return false; + bit_field_ = BaseOffsetField::update(bit_field_, base_offset); + return true; } @@ -3523,11 +3490,8 @@ bool HLoadKeyed::RequiresHoleCheck() const { } -void HLoadKeyedGeneric::PrintDataTo(StringStream* stream) { - object()->PrintNameTo(stream); - stream->Add("["); - key()->PrintNameTo(stream); - stream->Add("]"); +OStream& HLoadKeyedGeneric::PrintDataTo(OStream& os) const { // NOLINT + return os << NameOf(object()) << "[" << NameOf(key()) << "]"; } @@ -3568,79 +3532,60 @@ HValue* HLoadKeyedGeneric::Canonicalize() { } -void HStoreNamedGeneric::PrintDataTo(StringStream* stream) { - object()->PrintNameTo(stream); - stream->Add("."); - ASSERT(name()->IsString()); - stream->Add(String::cast(*name())->ToCString().get()); - stream->Add(" = "); - value()->PrintNameTo(stream); +OStream& HStoreNamedGeneric::PrintDataTo(OStream& os) const { // NOLINT + Handle<String> n = Handle<String>::cast(name()); + return os << NameOf(object()) << "." << n->ToCString().get() << " = " + << NameOf(value()); } -void HStoreNamedField::PrintDataTo(StringStream* stream) { - object()->PrintNameTo(stream); - access_.PrintTo(stream); - stream->Add(" = "); - value()->PrintNameTo(stream); - if (NeedsWriteBarrier()) { - stream->Add(" (write-barrier)"); - } - if (has_transition()) { - stream->Add(" (transition map %p)", *transition_map()); - } +OStream& HStoreNamedField::PrintDataTo(OStream& os) const { // NOLINT + os << NameOf(object()) << access_ << " = " << NameOf(value()); + if (NeedsWriteBarrier()) os << " (write-barrier)"; + if (has_transition()) os << " (transition map " << *transition_map() << ")"; + return os; } -void HStoreKeyed::PrintDataTo(StringStream* stream) { +OStream& HStoreKeyed::PrintDataTo(OStream& os) const { // NOLINT if (!is_external()) { - elements()->PrintNameTo(stream); + os << NameOf(elements()); } else { - elements()->PrintNameTo(stream); - stream->Add("."); - stream->Add(ElementsKindToString(elements_kind())); - ASSERT(elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND && + DCHECK(elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND && elements_kind() <= LAST_EXTERNAL_ARRAY_ELEMENTS_KIND); + os << NameOf(elements()) << "." << ElementsKindToString(elements_kind()); } - stream->Add("["); - key()->PrintNameTo(stream); - if (IsDehoisted()) { - stream->Add(" + %d] = ", index_offset()); - } else { - stream->Add("] = "); - } - - value()->PrintNameTo(stream); + os << "[" << NameOf(key()); + if (IsDehoisted()) os << " + " << base_offset(); + return os << "] = " << NameOf(value()); } -void HStoreKeyedGeneric::PrintDataTo(StringStream* stream) { - object()->PrintNameTo(stream); - stream->Add("["); - key()->PrintNameTo(stream); - stream->Add("] = "); - value()->PrintNameTo(stream); +OStream& HStoreKeyedGeneric::PrintDataTo(OStream& os) const { // NOLINT + return os << NameOf(object()) << "[" << NameOf(key()) + << "] = " << NameOf(value()); } -void HTransitionElementsKind::PrintDataTo(StringStream* stream) { - object()->PrintNameTo(stream); +OStream& HTransitionElementsKind::PrintDataTo(OStream& os) const { // NOLINT + os << NameOf(object()); ElementsKind from_kind = original_map().handle()->elements_kind(); ElementsKind to_kind = transitioned_map().handle()->elements_kind(); - stream->Add(" %p [%s] -> %p [%s]", - *original_map().handle(), - ElementsAccessor::ForKind(from_kind)->name(), - *transitioned_map().handle(), - ElementsAccessor::ForKind(to_kind)->name()); - if (IsSimpleMapChangeTransition(from_kind, to_kind)) stream->Add(" (simple)"); + os << " " << *original_map().handle() << " [" + << ElementsAccessor::ForKind(from_kind)->name() << "] -> " + << *transitioned_map().handle() << " [" + << ElementsAccessor::ForKind(to_kind)->name() << "]"; + if (IsSimpleMapChangeTransition(from_kind, to_kind)) os << " (simple)"; + return os; } -void HLoadGlobalCell::PrintDataTo(StringStream* stream) { - stream->Add("[%p]", *cell().handle()); - if (!details_.IsDontDelete()) stream->Add(" (deleteable)"); - if (details_.IsReadOnly()) stream->Add(" (read-only)"); +OStream& HLoadGlobalCell::PrintDataTo(OStream& os) const { // NOLINT + os << "[" << *cell().handle() << "]"; + if (!details_.IsDontDelete()) os << " (deleteable)"; + if (details_.IsReadOnly()) os << " (read-only)"; + return os; } @@ -3654,36 +3599,33 @@ bool HLoadGlobalCell::RequiresHoleCheck() const { } -void HLoadGlobalGeneric::PrintDataTo(StringStream* stream) { - stream->Add("%o ", *name()); +OStream& HLoadGlobalGeneric::PrintDataTo(OStream& os) const { // NOLINT + return os << name()->ToCString().get() << " "; } -void HInnerAllocatedObject::PrintDataTo(StringStream* stream) { - base_object()->PrintNameTo(stream); - stream->Add(" offset "); - offset()->PrintTo(stream); +OStream& HInnerAllocatedObject::PrintDataTo(OStream& os) const { // NOLINT + os << NameOf(base_object()) << " offset "; + return offset()->PrintTo(os); } -void HStoreGlobalCell::PrintDataTo(StringStream* stream) { - stream->Add("[%p] = ", *cell().handle()); - value()->PrintNameTo(stream); - if (!details_.IsDontDelete()) stream->Add(" (deleteable)"); - if (details_.IsReadOnly()) stream->Add(" (read-only)"); +OStream& HStoreGlobalCell::PrintDataTo(OStream& os) const { // NOLINT + os << "[" << *cell().handle() << "] = " << NameOf(value()); + if (!details_.IsDontDelete()) os << " (deleteable)"; + if (details_.IsReadOnly()) os << " (read-only)"; + return os; } -void HLoadContextSlot::PrintDataTo(StringStream* stream) { - value()->PrintNameTo(stream); - stream->Add("[%d]", slot_index()); +OStream& HLoadContextSlot::PrintDataTo(OStream& os) const { // NOLINT + return os << NameOf(value()) << "[" << slot_index() << "]"; } -void HStoreContextSlot::PrintDataTo(StringStream* stream) { - context()->PrintNameTo(stream); - stream->Add("[%d] = ", slot_index()); - value()->PrintNameTo(stream); +OStream& HStoreContextSlot::PrintDataTo(OStream& os) const { // NOLINT + return os << NameOf(context()) << "[" << slot_index() + << "] = " << NameOf(value()); } @@ -3732,7 +3674,7 @@ Representation HUnaryMathOperation::RepresentationFromInputs() { bool HAllocate::HandleSideEffectDominator(GVNFlag side_effect, HValue* dominator) { - ASSERT(side_effect == kNewSpacePromotion); + DCHECK(side_effect == kNewSpacePromotion); Zone* zone = block()->zone(); if (!FLAG_use_allocation_folding) return false; @@ -3759,10 +3701,10 @@ bool HAllocate::HandleSideEffectDominator(GVNFlag side_effect, HValue* current_size = size(); // TODO(hpayer): Add support for non-constant allocation in dominator. - if (!current_size->IsInteger32Constant() || - !dominator_size->IsInteger32Constant()) { + if (!dominator_size->IsInteger32Constant()) { if (FLAG_trace_allocation_folding) { - PrintF("#%d (%s) cannot fold into #%d (%s), dynamic allocation size\n", + PrintF("#%d (%s) cannot fold into #%d (%s), " + "dynamic allocation size in dominator\n", id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); } return false; @@ -3773,7 +3715,33 @@ bool HAllocate::HandleSideEffectDominator(GVNFlag side_effect, return false; } - ASSERT((IsNewSpaceAllocation() && + if (!has_size_upper_bound()) { + if (FLAG_trace_allocation_folding) { + PrintF("#%d (%s) cannot fold into #%d (%s), " + "can't estimate total allocation size\n", + id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); + } + return false; + } + + if (!current_size->IsInteger32Constant()) { + // If it's not constant then it is a size_in_bytes calculation graph + // like this: (const_header_size + const_element_size * size). + DCHECK(current_size->IsInstruction()); + + HInstruction* current_instr = HInstruction::cast(current_size); + if (!current_instr->Dominates(dominator_allocate)) { + if (FLAG_trace_allocation_folding) { + PrintF("#%d (%s) cannot fold into #%d (%s), dynamic size " + "value does not dominate target allocation\n", + id(), Mnemonic(), dominator_allocate->id(), + dominator_allocate->Mnemonic()); + } + return false; + } + } + + DCHECK((IsNewSpaceAllocation() && dominator_allocate->IsNewSpaceAllocation()) || (IsOldDataSpaceAllocation() && dominator_allocate->IsOldDataSpaceAllocation()) || @@ -3785,20 +3753,16 @@ bool HAllocate::HandleSideEffectDominator(GVNFlag side_effect, int32_t original_object_size = HConstant::cast(dominator_size)->GetInteger32Constant(); int32_t dominator_size_constant = original_object_size; - int32_t current_size_constant = - HConstant::cast(current_size)->GetInteger32Constant(); - int32_t new_dominator_size = dominator_size_constant + current_size_constant; if (MustAllocateDoubleAligned()) { - if (!dominator_allocate->MustAllocateDoubleAligned()) { - dominator_allocate->MakeDoubleAligned(); - } if ((dominator_size_constant & kDoubleAlignmentMask) != 0) { dominator_size_constant += kDoubleSize / 2; - new_dominator_size += kDoubleSize / 2; } } + int32_t current_size_max_value = size_upper_bound()->GetInteger32Constant(); + int32_t new_dominator_size = dominator_size_constant + current_size_max_value; + // Since we clear the first word after folded memory, we cannot use the // whole Page::kMaxRegularHeapObjectSize memory. if (new_dominator_size > Page::kMaxRegularHeapObjectSize - kPointerSize) { @@ -3810,27 +3774,54 @@ bool HAllocate::HandleSideEffectDominator(GVNFlag side_effect, return false; } - HInstruction* new_dominator_size_constant = HConstant::CreateAndInsertBefore( - zone, - context(), - new_dominator_size, - Representation::None(), - dominator_allocate); - dominator_allocate->UpdateSize(new_dominator_size_constant); + HInstruction* new_dominator_size_value; + + if (current_size->IsInteger32Constant()) { + new_dominator_size_value = + HConstant::CreateAndInsertBefore(zone, + context(), + new_dominator_size, + Representation::None(), + dominator_allocate); + } else { + HValue* new_dominator_size_constant = + HConstant::CreateAndInsertBefore(zone, + context(), + dominator_size_constant, + Representation::Integer32(), + dominator_allocate); + + // Add old and new size together and insert. + current_size->ChangeRepresentation(Representation::Integer32()); + + new_dominator_size_value = HAdd::New(zone, context(), + new_dominator_size_constant, current_size); + new_dominator_size_value->ClearFlag(HValue::kCanOverflow); + new_dominator_size_value->ChangeRepresentation(Representation::Integer32()); + + new_dominator_size_value->InsertBefore(dominator_allocate); + } + + dominator_allocate->UpdateSize(new_dominator_size_value); + + if (MustAllocateDoubleAligned()) { + if (!dominator_allocate->MustAllocateDoubleAligned()) { + dominator_allocate->MakeDoubleAligned(); + } + } + bool keep_new_space_iterable = FLAG_log_gc || FLAG_heap_stats; #ifdef VERIFY_HEAP - if (FLAG_verify_heap && dominator_allocate->IsNewSpaceAllocation()) { + keep_new_space_iterable = keep_new_space_iterable || FLAG_verify_heap; +#endif + + if (keep_new_space_iterable && dominator_allocate->IsNewSpaceAllocation()) { dominator_allocate->MakePrefillWithFiller(); } else { // TODO(hpayer): This is a short-term hack to make allocation mementos // work again in new space. dominator_allocate->ClearNextMapWord(original_object_size); } -#else - // TODO(hpayer): This is a short-term hack to make allocation mementos - // work again in new space. - dominator_allocate->ClearNextMapWord(original_object_size); -#endif dominator_allocate->UpdateClearNextMapWord(MustClearNextMapWord()); @@ -3898,7 +3889,7 @@ HAllocate* HAllocate::GetFoldableDominator(HAllocate* dominator) { return NULL; } - ASSERT((IsOldDataSpaceAllocation() && + DCHECK((IsOldDataSpaceAllocation() && dominator_dominator->IsOldDataSpaceAllocation()) || (IsOldPointerSpaceAllocation() && dominator_dominator->IsOldPointerSpaceAllocation())); @@ -3924,7 +3915,7 @@ HAllocate* HAllocate::GetFoldableDominator(HAllocate* dominator) { void HAllocate::UpdateFreeSpaceFiller(int32_t free_space_size) { - ASSERT(filler_free_space_size_ != NULL); + DCHECK(filler_free_space_size_ != NULL); Zone* zone = block()->zone(); // We must explicitly force Smi representation here because on x64 we // would otherwise automatically choose int32, but the actual store @@ -3941,7 +3932,7 @@ void HAllocate::UpdateFreeSpaceFiller(int32_t free_space_size) { void HAllocate::CreateFreeSpaceFiller(int32_t free_space_size) { - ASSERT(filler_free_space_size_ == NULL); + DCHECK(filler_free_space_size_ == NULL); Zone* zone = block()->zone(); HInstruction* free_space_instr = HInnerAllocatedObject::New(zone, context(), dominating_allocate_, @@ -3949,7 +3940,7 @@ void HAllocate::CreateFreeSpaceFiller(int32_t free_space_size) { free_space_instr->InsertBefore(this); HConstant* filler_map = HConstant::CreateAndInsertAfter( zone, Unique<Map>::CreateImmovable( - isolate()->factory()->free_space_map()), free_space_instr); + isolate()->factory()->free_space_map()), true, free_space_instr); HInstruction* store_map = HStoreNamedField::New(zone, context(), free_space_instr, HObjectAccess::ForMap(), filler_map); store_map->SetFlag(HValue::kHasNoObservableSideEffects); @@ -3987,15 +3978,27 @@ void HAllocate::ClearNextMapWord(int offset) { } -void HAllocate::PrintDataTo(StringStream* stream) { - size()->PrintNameTo(stream); - stream->Add(" ("); - if (IsNewSpaceAllocation()) stream->Add("N"); - if (IsOldPointerSpaceAllocation()) stream->Add("P"); - if (IsOldDataSpaceAllocation()) stream->Add("D"); - if (MustAllocateDoubleAligned()) stream->Add("A"); - if (MustPrefillWithFiller()) stream->Add("F"); - stream->Add(")"); +OStream& HAllocate::PrintDataTo(OStream& os) const { // NOLINT + os << NameOf(size()) << " ("; + if (IsNewSpaceAllocation()) os << "N"; + if (IsOldPointerSpaceAllocation()) os << "P"; + if (IsOldDataSpaceAllocation()) os << "D"; + if (MustAllocateDoubleAligned()) os << "A"; + if (MustPrefillWithFiller()) os << "F"; + return os << ")"; +} + + +bool HStoreKeyed::TryIncreaseBaseOffset(uint32_t increase_by_value) { + // The base offset is usually simply the size of the array header, except + // with dehoisting adds an addition offset due to a array index key + // manipulation, in which case it becomes (array header size + + // constant-offset-from-key * kPointerSize) + v8::base::internal::CheckedNumeric<uint32_t> addition_result = base_offset_; + addition_result += increase_by_value; + if (!addition_result.IsValid()) return false; + base_offset_ = addition_result.ValueOrDie(); + return true; } @@ -4073,10 +4076,9 @@ HInstruction* HStringAdd::New(Zone* zone, Handle<String> right_string = c_right->StringValue(); // Prevent possible exception by invalid string length. if (left_string->length() + right_string->length() < String::kMaxLength) { - Handle<String> concat = zone->isolate()->factory()->NewFlatConcatString( + MaybeHandle<String> concat = zone->isolate()->factory()->NewConsString( c_left->StringValue(), c_right->StringValue()); - ASSERT(!concat.is_null()); - return HConstant::New(zone, context, concat); + return HConstant::New(zone, context, concat.ToHandleChecked()); } } } @@ -4085,19 +4087,21 @@ HInstruction* HStringAdd::New(Zone* zone, } -void HStringAdd::PrintDataTo(StringStream* stream) { +OStream& HStringAdd::PrintDataTo(OStream& os) const { // NOLINT if ((flags() & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) { - stream->Add("_CheckBoth"); + os << "_CheckBoth"; } else if ((flags() & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_LEFT) { - stream->Add("_CheckLeft"); + os << "_CheckLeft"; } else if ((flags() & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_RIGHT) { - stream->Add("_CheckRight"); + os << "_CheckRight"; } - HBinaryOperation::PrintDataTo(stream); - stream->Add(" ("); - if (pretenure_flag() == NOT_TENURED) stream->Add("N"); - else if (pretenure_flag() == TENURED) stream->Add("D"); - stream->Add(")"); + HBinaryOperation::PrintDataTo(os); + os << " ("; + if (pretenure_flag() == NOT_TENURED) + os << "N"; + else if (pretenure_flag() == TENURED) + os << "D"; + return os << ")"; } @@ -4128,7 +4132,7 @@ HInstruction* HUnaryMathOperation::New( if (!constant->HasNumberValue()) break; double d = constant->DoubleValue(); if (std::isnan(d)) { // NaN poisons everything. - return H_CONSTANT_DOUBLE(OS::nan_value()); + return H_CONSTANT_DOUBLE(base::OS::nan_value()); } if (std::isinf(d)) { // +Infinity and -Infinity. switch (op) { @@ -4136,11 +4140,12 @@ HInstruction* HUnaryMathOperation::New( return H_CONSTANT_DOUBLE((d > 0.0) ? d : 0.0); case kMathLog: case kMathSqrt: - return H_CONSTANT_DOUBLE((d > 0.0) ? d : OS::nan_value()); + return H_CONSTANT_DOUBLE((d > 0.0) ? d : base::OS::nan_value()); case kMathPowHalf: case kMathAbs: return H_CONSTANT_DOUBLE((d > 0.0) ? d : -d); case kMathRound: + case kMathFround: case kMathFloor: return H_CONSTANT_DOUBLE(d); case kMathClz32: @@ -4167,9 +4172,11 @@ HInstruction* HUnaryMathOperation::New( // Doubles are represented as Significant * 2 ^ Exponent. If the // Exponent is not negative, the double value is already an integer. if (Double(d).Exponent() >= 0) return H_CONSTANT_DOUBLE(d); - return H_CONSTANT_DOUBLE(std::floor(d + 0.5)); + return H_CONSTANT_DOUBLE(Floor(d + 0.5)); + case kMathFround: + return H_CONSTANT_DOUBLE(static_cast<double>(static_cast<float>(d))); case kMathFloor: - return H_CONSTANT_DOUBLE(std::floor(d)); + return H_CONSTANT_DOUBLE(Floor(d)); case kMathClz32: { uint32_t i = DoubleToUint32(d); return H_CONSTANT_INT( @@ -4231,7 +4238,8 @@ HInstruction* HPower::New(Zone* zone, if (c_left->HasNumberValue() && c_right->HasNumberValue()) { double result = power_helper(c_left->DoubleValue(), c_right->DoubleValue()); - return H_CONSTANT_DOUBLE(std::isnan(result) ? OS::nan_value() : result); + return H_CONSTANT_DOUBLE(std::isnan(result) ? base::OS::nan_value() + : result); } } return new(zone) HPower(left, right); @@ -4264,7 +4272,7 @@ HInstruction* HMathMinMax::New( } } // All comparisons failed, must be NaN. - return H_CONSTANT_DOUBLE(OS::nan_value()); + return H_CONSTANT_DOUBLE(base::OS::nan_value()); } } return new(zone) HMathMinMax(context, left, right, op); @@ -4402,8 +4410,8 @@ HInstruction* HSeqStringGetChar::New(Zone* zone, if (c_string->HasStringValue() && c_index->HasInteger32Value()) { Handle<String> s = c_string->StringValue(); int32_t i = c_index->Integer32Value(); - ASSERT_LE(0, i); - ASSERT_LT(i, s->length()); + DCHECK_LE(0, i); + DCHECK_LT(i, s->length()); return H_CONSTANT_INT(s->Get(i)); } } @@ -4415,10 +4423,9 @@ HInstruction* HSeqStringGetChar::New(Zone* zone, #undef H_CONSTANT_DOUBLE -void HBitwise::PrintDataTo(StringStream* stream) { - stream->Add(Token::Name(op_)); - stream->Add(" "); - HBitwiseBinaryOperation::PrintDataTo(stream); +OStream& HBitwise::PrintDataTo(OStream& os) const { // NOLINT + os << Token::Name(op_) << " "; + return HBitwiseBinaryOperation::PrintDataTo(os); } @@ -4459,7 +4466,7 @@ void HPhi::SimplifyConstantInputs() { void HPhi::InferRepresentation(HInferRepresentationPhase* h_infer) { - ASSERT(CheckFlag(kFlexibleRepresentation)); + DCHECK(CheckFlag(kFlexibleRepresentation)); Representation new_rep = RepresentationFromInputs(); UpdateRepresentation(new_rep, h_infer, "inputs"); new_rep = RepresentationFromUses(); @@ -4523,12 +4530,12 @@ bool HValue::HasNonSmiUse() { #ifdef DEBUG void HPhi::Verify() { - ASSERT(OperandCount() == block()->predecessors()->length()); + DCHECK(OperandCount() == block()->predecessors()->length()); for (int i = 0; i < OperandCount(); ++i) { HValue* value = OperandAt(i); HBasicBlock* defining_block = value->block(); HBasicBlock* predecessor_block = block()->predecessors()->at(i); - ASSERT(defining_block == predecessor_block || + DCHECK(defining_block == predecessor_block || defining_block->Dominates(predecessor_block)); } } @@ -4536,27 +4543,27 @@ void HPhi::Verify() { void HSimulate::Verify() { HInstruction::Verify(); - ASSERT(HasAstId() || next()->IsEnterInlined()); + DCHECK(HasAstId() || next()->IsEnterInlined()); } void HCheckHeapObject::Verify() { HInstruction::Verify(); - ASSERT(HasNoUses()); + DCHECK(HasNoUses()); } void HCheckValue::Verify() { HInstruction::Verify(); - ASSERT(HasNoUses()); + DCHECK(HasNoUses()); } #endif HObjectAccess HObjectAccess::ForFixedArrayHeader(int offset) { - ASSERT(offset >= 0); - ASSERT(offset < FixedArray::kHeaderSize); + DCHECK(offset >= 0); + DCHECK(offset < FixedArray::kHeaderSize); if (offset == FixedArray::kLengthOffset) return ForFixedArrayLength(); return HObjectAccess(kInobject, offset); } @@ -4564,7 +4571,7 @@ HObjectAccess HObjectAccess::ForFixedArrayHeader(int offset) { HObjectAccess HObjectAccess::ForMapAndOffset(Handle<Map> map, int offset, Representation representation) { - ASSERT(offset >= 0); + DCHECK(offset >= 0); Portion portion = kInobject; if (offset == JSObject::kElementsOffset) { @@ -4604,16 +4611,16 @@ HObjectAccess HObjectAccess::ForAllocationSiteOffset(int offset) { HObjectAccess HObjectAccess::ForContextSlot(int index) { - ASSERT(index >= 0); + DCHECK(index >= 0); Portion portion = kInobject; int offset = Context::kHeaderSize + index * kPointerSize; - ASSERT_EQ(offset, Context::SlotOffset(index) + kHeapObjectTag); + DCHECK_EQ(offset, Context::SlotOffset(index) + kHeapObjectTag); return HObjectAccess(portion, offset, Representation::Tagged()); } HObjectAccess HObjectAccess::ForJSArrayOffset(int offset) { - ASSERT(offset >= 0); + DCHECK(offset >= 0); Portion portion = kInobject; if (offset == JSObject::kElementsOffset) { @@ -4629,7 +4636,7 @@ HObjectAccess HObjectAccess::ForJSArrayOffset(int offset) { HObjectAccess HObjectAccess::ForBackingStoreOffset(int offset, Representation representation) { - ASSERT(offset >= 0); + DCHECK(offset >= 0); return HObjectAccess(kBackingStore, offset, representation, Handle<String>::null(), false, false); } @@ -4638,7 +4645,7 @@ HObjectAccess HObjectAccess::ForBackingStoreOffset(int offset, HObjectAccess HObjectAccess::ForField(Handle<Map> map, LookupResult* lookup, Handle<String> name) { - ASSERT(lookup->IsField() || lookup->IsTransitionToField()); + DCHECK(lookup->IsField() || lookup->IsTransitionToField()); int index; Representation representation; if (lookup->IsField()) { @@ -4747,39 +4754,39 @@ void HObjectAccess::SetGVNFlags(HValue *instr, PropertyAccessType access_type) { } -void HObjectAccess::PrintTo(StringStream* stream) const { - stream->Add("."); +OStream& operator<<(OStream& os, const HObjectAccess& access) { + os << "."; - switch (portion()) { - case kArrayLengths: - case kStringLengths: - stream->Add("%length"); + switch (access.portion()) { + case HObjectAccess::kArrayLengths: + case HObjectAccess::kStringLengths: + os << "%length"; break; - case kElementsPointer: - stream->Add("%elements"); + case HObjectAccess::kElementsPointer: + os << "%elements"; break; - case kMaps: - stream->Add("%map"); + case HObjectAccess::kMaps: + os << "%map"; break; - case kDouble: // fall through - case kInobject: - if (!name_.is_null()) { - stream->Add(String::cast(*name_)->ToCString().get()); + case HObjectAccess::kDouble: // fall through + case HObjectAccess::kInobject: + if (!access.name().is_null()) { + os << Handle<String>::cast(access.name())->ToCString().get(); } - stream->Add("[in-object]"); + os << "[in-object]"; break; - case kBackingStore: - if (!name_.is_null()) { - stream->Add(String::cast(*name_)->ToCString().get()); + case HObjectAccess::kBackingStore: + if (!access.name().is_null()) { + os << Handle<String>::cast(access.name())->ToCString().get(); } - stream->Add("[backing-store]"); + os << "[backing-store]"; break; - case kExternalMemory: - stream->Add("[external-memory]"); + case HObjectAccess::kExternalMemory: + os << "[external-memory]"; break; } - stream->Add("@%d", offset()); + return os << "@" << access.offset(); } } } // namespace v8::internal |