diff options
Diffstat (limited to 'deps/v8/src/hydrogen-instructions.cc')
-rw-r--r-- | deps/v8/src/hydrogen-instructions.cc | 370 |
1 files changed, 296 insertions, 74 deletions
diff --git a/deps/v8/src/hydrogen-instructions.cc b/deps/v8/src/hydrogen-instructions.cc index 5630ce391..32c3abfe7 100644 --- a/deps/v8/src/hydrogen-instructions.cc +++ b/deps/v8/src/hydrogen-instructions.cc @@ -126,7 +126,9 @@ void Range::AddConstant(int32_t value) { bool may_overflow = false; // Overflow is ignored here. lower_ = AddWithoutOverflow(lower_, value, &may_overflow); upper_ = AddWithoutOverflow(upper_, value, &may_overflow); +#ifdef DEBUG Verify(); +#endif } @@ -173,7 +175,9 @@ bool Range::AddAndCheckOverflow(Range* other) { lower_ = AddWithoutOverflow(lower_, other->lower(), &may_overflow); upper_ = AddWithoutOverflow(upper_, other->upper(), &may_overflow); KeepOrder(); +#ifdef DEBUG Verify(); +#endif return may_overflow; } @@ -183,7 +187,9 @@ bool Range::SubAndCheckOverflow(Range* other) { lower_ = SubWithoutOverflow(lower_, other->upper(), &may_overflow); upper_ = SubWithoutOverflow(upper_, other->lower(), &may_overflow); KeepOrder(); +#ifdef DEBUG Verify(); +#endif return may_overflow; } @@ -197,9 +203,11 @@ void Range::KeepOrder() { } +#ifdef DEBUG void Range::Verify() const { ASSERT(lower_ <= upper_); } +#endif bool Range::MulAndCheckOverflow(Range* other) { @@ -210,7 +218,9 @@ bool Range::MulAndCheckOverflow(Range* other) { int v4 = MulWithoutOverflow(upper_, other->upper(), &may_overflow); lower_ = Min(Min(v1, v2), Min(v3, v4)); upper_ = Max(Max(v1, v2), Max(v3, v4)); +#ifdef DEBUG Verify(); +#endif return may_overflow; } @@ -234,25 +244,6 @@ const char* HType::ToString() { } -const char* HType::ToShortString() { - switch (type_) { - case kTagged: return "t"; - case kTaggedPrimitive: return "p"; - case kTaggedNumber: return "n"; - case kSmi: return "m"; - case kHeapNumber: return "h"; - case kString: return "s"; - case kBoolean: return "b"; - case kNonPrimitive: return "r"; - case kJSArray: return "a"; - case kJSObject: return "o"; - case kUninitialized: return "z"; - } - UNREACHABLE(); - return "Unreachable code"; -} - - HType HType::TypeFromValue(Handle<Object> value) { HType result = HType::Tagged(); if (value->IsSmi()) { @@ -564,7 +555,7 @@ void HInstruction::InsertAfter(HInstruction* previous) { // followed by a simulate instruction, we need to insert after the // simulate instruction instead. HInstruction* next = previous->next_; - if (previous->HasSideEffects() && next != NULL) { + if (previous->HasObservableSideEffects() && next != NULL) { ASSERT(next->IsSimulate()); previous = next; next = previous->next_; @@ -587,11 +578,10 @@ void HInstruction::Verify() { HBasicBlock* other_block = other_operand->block(); if (cur_block == other_block) { if (!other_operand->IsPhi()) { - HInstruction* cur = cur_block->first(); + HInstruction* cur = this->previous(); while (cur != NULL) { - ASSERT(cur != this); // We should reach other_operand before! if (cur == other_operand) break; - cur = cur->next(); + cur = cur->previous(); } // Must reach other operand in the same block! ASSERT(cur == other_operand); @@ -605,7 +595,7 @@ void HInstruction::Verify() { // Verify that instructions that may have side-effects are followed // by a simulate instruction. - if (HasSideEffects() && !IsOsrEntry()) { + if (HasObservableSideEffects() && !IsOsrEntry()) { ASSERT(next()->IsSimulate()); } @@ -707,6 +697,14 @@ void HUnaryControlInstruction::PrintDataTo(StringStream* stream) { } +void HIsNilAndBranch::PrintDataTo(StringStream* stream) { + value()->PrintNameTo(stream); + stream->Add(kind() == kStrictEquality ? " === " : " == "); + stream->Add(nil() == kNullValue ? "null" : "undefined"); + HControlInstruction::PrintDataTo(stream); +} + + void HReturn::PrintDataTo(StringStream* stream) { value()->PrintNameTo(stream); } @@ -775,17 +773,33 @@ void HHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) { void HTypeofIsAndBranch::PrintDataTo(StringStream* stream) { value()->PrintNameTo(stream); - stream->Add(" == "); - stream->Add(type_literal_->GetFlatContent().ToAsciiVector()); + stream->Add(" == %o", *type_literal_); + HControlInstruction::PrintDataTo(stream); +} + + +HValue* HConstant::Canonicalize() { + return HasNoUses() && !IsBlockEntry() ? NULL : this; +} + + +HValue* HTypeof::Canonicalize() { + return HasNoUses() && !IsBlockEntry() ? NULL : this; +} + + +void HTypeof::PrintDataTo(StringStream* stream) { + value()->PrintNameTo(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?"); + if (CheckFlag(kDeoptimizeOnUndefined)) stream->Add(" deopt-on-undefined"); } @@ -857,6 +871,23 @@ void HCheckFunction::PrintDataTo(StringStream* stream) { } +const char* HCheckInstanceType::GetCheckName() { + switch (check_) { + case IS_SPEC_OBJECT: return "object"; + case IS_JS_ARRAY: return "array"; + case IS_STRING: return "string"; + case IS_SYMBOL: return "symbol"; + } + UNREACHABLE(); + return ""; +} + +void HCheckInstanceType::PrintDataTo(StringStream* stream) { + stream->Add("%s ", GetCheckName()); + HUnaryOperation::PrintDataTo(stream); +} + + void HCallStub::PrintDataTo(StringStream* stream) { stream->Add("%s ", CodeStub::MajorName(major_key_, false)); @@ -1106,15 +1137,16 @@ void HPhi::AddIndirectUsesTo(int* dest) { void HSimulate::PrintDataTo(StringStream* stream) { - stream->Add("id=%d ", ast_id()); - if (pop_count_ > 0) stream->Add("pop %d", pop_count_); + stream->Add("id=%d", ast_id()); + if (pop_count_ > 0) stream->Add(" pop %d", pop_count_); if (values_.length() > 0) { if (pop_count_ > 0) stream->Add(" /"); for (int i = 0; i < values_.length(); ++i) { - if (!HasAssignedIndexAt(i)) { - stream->Add(" push "); - } else { + if (i > 0) stream->Add(","); + if (HasAssignedIndexAt(i)) { stream->Add(" var[%d] = ", GetAssignedIndexAt(i)); + } else { + stream->Add(" push "); } values_[i]->PrintNameTo(stream); } @@ -1195,7 +1227,10 @@ void HConstant::PrintDataTo(StringStream* stream) { bool HArrayLiteral::IsCopyOnWrite() const { - return constant_elements()->map() == HEAP->fixed_cow_array_map(); + Handle<FixedArray> constant_elements = this->constant_elements(); + FixedArrayBase* constant_elements_values = + FixedArrayBase::cast(constant_elements->get(1)); + return constant_elements_values->map() == HEAP->fixed_cow_array_map(); } @@ -1208,28 +1243,17 @@ void HBinaryOperation::PrintDataTo(StringStream* stream) { } -Range* HBitAnd::InferRange() { +Range* HBitwise::InferRange() { + if (op() == Token::BIT_XOR) return HValue::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() { - 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; + int32_t result_mask = (op() == Token::BIT_AND) + ? left_mask & right_mask + : left_mask | right_mask; return (result_mask >= 0) ? new Range(0, result_mask) : HValue::InferRange(); @@ -1301,6 +1325,13 @@ void HCompareGeneric::PrintDataTo(StringStream* stream) { } +void HStringCompareAndBranch::PrintDataTo(StringStream* stream) { + stream->Add(Token::Name(token())); + stream->Add(" "); + HControlInstruction::PrintDataTo(stream); +} + + void HCompareIDAndBranch::PrintDataTo(StringStream* stream) { stream->Add(Token::Name(token())); stream->Add(" "); @@ -1311,6 +1342,14 @@ void HCompareIDAndBranch::PrintDataTo(StringStream* stream) { } +void HCompareObjectEqAndBranch::PrintDataTo(StringStream* stream) { + left()->PrintNameTo(stream); + stream->Add(" "); + right()->PrintNameTo(stream); + HControlInstruction::PrintDataTo(stream); +} + + void HGoto::PrintDataTo(StringStream* stream) { stream->Add("B%d", SuccessorAt(0)->block_id()); } @@ -1352,7 +1391,7 @@ HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* context, i < types->length() && types_.length() < kMaxLoadPolymorphism; ++i) { Handle<Map> map = types->at(i); - LookupResult lookup; + LookupResult lookup(map->GetIsolate()); map->LookupInDescriptors(NULL, *name, &lookup); if (lookup.IsProperty()) { switch (lookup.type()) { @@ -1405,14 +1444,14 @@ bool HLoadNamedFieldPolymorphic::DataEquals(HValue* value) { void HLoadNamedFieldPolymorphic::PrintDataTo(StringStream* stream) { object()->PrintNameTo(stream); - stream->Add(" ."); + stream->Add("."); stream->Add(*String::cast(*name())->ToCString()); } void HLoadNamedGeneric::PrintDataTo(StringStream* stream) { object()->PrintNameTo(stream); - stream->Add(" ."); + stream->Add("."); stream->Add(*String::cast(*name())->ToCString()); } @@ -1425,7 +1464,7 @@ void HLoadKeyedFastElement::PrintDataTo(StringStream* stream) { } -bool HLoadKeyedFastElement::RequiresHoleCheck() const { +bool HLoadKeyedFastElement::RequiresHoleCheck() { for (HUseIterator it(uses()); !it.Done(); it.Advance()) { HValue* use = it.value(); if (!use->IsChange()) return true; @@ -1442,11 +1481,6 @@ void HLoadKeyedFastDoubleElement::PrintDataTo(StringStream* stream) { } -bool HLoadKeyedFastDoubleElement::RequiresHoleCheck() const { - return true; -} - - void HLoadKeyedGeneric::PrintDataTo(StringStream* stream) { object()->PrintNameTo(stream); stream->Add("["); @@ -1488,6 +1522,7 @@ void HLoadKeyedSpecializedArrayElement::PrintDataTo( stream->Add("pixel"); break; case FAST_ELEMENTS: + case FAST_SMI_ONLY_ELEMENTS: case FAST_DOUBLE_ELEMENTS: case DICTIONARY_ELEMENTS: case NON_STRICT_ARGUMENTS_ELEMENTS: @@ -1513,10 +1548,10 @@ void HStoreNamedGeneric::PrintDataTo(StringStream* stream) { void HStoreNamedField::PrintDataTo(StringStream* stream) { object()->PrintNameTo(stream); stream->Add("."); - ASSERT(name()->IsString()); stream->Add(*String::cast(*name())->ToCString()); stream->Add(" = "); value()->PrintNameTo(stream); + stream->Add(" @%d%s", offset(), is_in_object() ? "[in-object]" : ""); if (!transition().is_null()) { stream->Add(" (transition map %p)", *transition()); } @@ -1582,6 +1617,7 @@ void HStoreKeyedSpecializedArrayElement::PrintDataTo( case EXTERNAL_PIXEL_ELEMENTS: stream->Add("pixel"); break; + case FAST_SMI_ONLY_ELEMENTS: case FAST_ELEMENTS: case FAST_DOUBLE_ELEMENTS: case DICTIONARY_ELEMENTS: @@ -1596,9 +1632,26 @@ void HStoreKeyedSpecializedArrayElement::PrintDataTo( } +void HTransitionElementsKind::PrintDataTo(StringStream* stream) { + object()->PrintNameTo(stream); + stream->Add(" %p -> %p", *original_map(), *transitioned_map()); +} + + void HLoadGlobalCell::PrintDataTo(StringStream* stream) { stream->Add("[%p]", *cell()); - if (check_hole_value()) stream->Add(" (deleteable/read-only)"); + if (!details_.IsDontDelete()) stream->Add(" (deleteable)"); + if (details_.IsReadOnly()) stream->Add(" (read-only)"); +} + + +bool HLoadGlobalCell::RequiresHoleCheck() { + if (details_.IsDontDelete() && !details_.IsReadOnly()) return false; + for (HUseIterator it(uses()); !it.Done(); it.Advance()) { + HValue* use = it.value(); + if (!use->IsChange()) return true; + } + return false; } @@ -1610,6 +1663,8 @@ void HLoadGlobalGeneric::PrintDataTo(StringStream* stream) { void HStoreGlobalCell::PrintDataTo(StringStream* stream) { stream->Add("[%p] = ", *cell()); value()->PrintNameTo(stream); + if (!details_.IsDontDelete()) stream->Add(" (deleteable)"); + if (details_.IsReadOnly()) stream->Add(" (read-only)"); } @@ -1696,6 +1751,12 @@ HType HInstanceOfKnownGlobal::CalculateInferredType() { } +HType HChange::CalculateInferredType() { + if (from().IsDouble() && to().IsTagged()) return HType::HeapNumber(); + return type(); +} + + HType HBitwiseBinaryOperation::CalculateInferredType() { return HType::TaggedNumber(); } @@ -1711,43 +1772,43 @@ HType HAdd::CalculateInferredType() { } -HType HBitAnd::CalculateInferredType() { +HType HBitNot::CalculateInferredType() { return HType::TaggedNumber(); } -HType HBitXor::CalculateInferredType() { +HType HUnaryMathOperation::CalculateInferredType() { return HType::TaggedNumber(); } -HType HBitOr::CalculateInferredType() { - return HType::TaggedNumber(); +HType HStringCharFromCode::CalculateInferredType() { + return HType::String(); } -HType HBitNot::CalculateInferredType() { - return HType::TaggedNumber(); +HType HArrayLiteral::CalculateInferredType() { + return HType::JSArray(); } -HType HUnaryMathOperation::CalculateInferredType() { - return HType::TaggedNumber(); +HType HObjectLiteralFast::CalculateInferredType() { + return HType::JSObject(); } -HType HShl::CalculateInferredType() { - return HType::TaggedNumber(); +HType HObjectLiteralGeneric::CalculateInferredType() { + return HType::JSObject(); } -HType HShr::CalculateInferredType() { - return HType::TaggedNumber(); +HType HRegExpLiteral::CalculateInferredType() { + return HType::JSObject(); } -HType HSar::CalculateInferredType() { - return HType::TaggedNumber(); +HType HFunctionLiteral::CalculateInferredType() { + return HType::JSObject(); } @@ -1838,6 +1899,167 @@ HValue* HAdd::EnsureAndPropagateNotMinusZero(BitVector* visited) { } +#define H_CONSTANT_INT32(val) \ +new(zone) HConstant(FACTORY->NewNumberFromInt(val, TENURED), \ + Representation::Integer32()) +#define H_CONSTANT_DOUBLE(val) \ +new(zone) HConstant(FACTORY->NewNumber(val, TENURED), \ + Representation::Double()) + +#define DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HInstr, op) \ +HInstruction* HInstr::New##HInstr(Zone* zone, \ + HValue* context, \ + HValue* left, \ + HValue* right) { \ + if (left->IsConstant() && right->IsConstant()) { \ + HConstant* c_left = HConstant::cast(left); \ + HConstant* c_right = HConstant::cast(right); \ + if ((c_left->HasNumberValue() && c_right->HasNumberValue())) { \ + double double_res = c_left->DoubleValue() op c_right->DoubleValue(); \ + if (TypeInfo::IsInt32Double(double_res)) { \ + return H_CONSTANT_INT32(static_cast<int32_t>(double_res)); \ + } \ + return H_CONSTANT_DOUBLE(double_res); \ + } \ + } \ + return new(zone) HInstr(context, left, right); \ +} + + +DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HAdd, +) +DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HMul, *) +DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HSub, -) + +#undef DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR + + +HInstruction* HMod::NewHMod(Zone* zone, + HValue* context, + HValue* left, + HValue* right) { + if (left->IsConstant() && right->IsConstant()) { + HConstant* c_left = HConstant::cast(left); + HConstant* c_right = HConstant::cast(right); + if (c_left->HasInteger32Value() && c_right->HasInteger32Value()) { + int32_t dividend = c_left->Integer32Value(); + int32_t divisor = c_right->Integer32Value(); + if (divisor != 0) { + int32_t res = dividend % divisor; + if ((res == 0) && (dividend < 0)) { + return H_CONSTANT_DOUBLE(-0.0); + } + return H_CONSTANT_INT32(res); + } + } + } + return new(zone) HMod(context, left, right); +} + + +HInstruction* HDiv::NewHDiv(Zone* zone, + HValue* context, + HValue* left, + HValue* right) { + // If left and right are constant values, try to return a constant value. + if (left->IsConstant() && right->IsConstant()) { + HConstant* c_left = HConstant::cast(left); + HConstant* c_right = HConstant::cast(right); + if ((c_left->HasNumberValue() && c_right->HasNumberValue())) { + if (c_right->DoubleValue() != 0) { + double double_res = c_left->DoubleValue() / c_right->DoubleValue(); + if (TypeInfo::IsInt32Double(double_res)) { + return H_CONSTANT_INT32(static_cast<int32_t>(double_res)); + } + return H_CONSTANT_DOUBLE(double_res); + } + } + } + return new(zone) HDiv(context, left, right); +} + + +HInstruction* HBitwise::NewHBitwise(Zone* zone, + Token::Value op, + HValue* context, + HValue* left, + HValue* right) { + if (left->IsConstant() && right->IsConstant()) { + HConstant* c_left = HConstant::cast(left); + HConstant* c_right = HConstant::cast(right); + if ((c_left->HasNumberValue() && c_right->HasNumberValue())) { + int32_t result; + int32_t v_left = c_left->NumberValueAsInteger32(); + int32_t v_right = c_right->NumberValueAsInteger32(); + switch (op) { + case Token::BIT_XOR: + result = v_left ^ v_right; + break; + case Token::BIT_AND: + result = v_left & v_right; + break; + case Token::BIT_OR: + result = v_left | v_right; + break; + default: + result = 0; // Please the compiler. + UNREACHABLE(); + } + return H_CONSTANT_INT32(result); + } + } + return new(zone) HBitwise(op, context, left, right); +} + + +#define DEFINE_NEW_H_BITWISE_INSTR(HInstr, result) \ +HInstruction* HInstr::New##HInstr(Zone* zone, \ + HValue* context, \ + HValue* left, \ + HValue* right) { \ + if (left->IsConstant() && right->IsConstant()) { \ + HConstant* c_left = HConstant::cast(left); \ + HConstant* c_right = HConstant::cast(right); \ + if ((c_left->HasNumberValue() && c_right->HasNumberValue())) { \ + return H_CONSTANT_INT32(result); \ + } \ + } \ + return new(zone) HInstr(context, left, right); \ +} + + +DEFINE_NEW_H_BITWISE_INSTR(HSar, +c_left->NumberValueAsInteger32() >> (c_right->NumberValueAsInteger32() & 0x1f)) +DEFINE_NEW_H_BITWISE_INSTR(HShl, +c_left->NumberValueAsInteger32() << (c_right->NumberValueAsInteger32() & 0x1f)) + +#undef DEFINE_NEW_H_BITWISE_INSTR + + +HInstruction* HShr::NewHShr(Zone* zone, + HValue* context, + HValue* left, + HValue* right) { + if (left->IsConstant() && right->IsConstant()) { + HConstant* c_left = HConstant::cast(left); + HConstant* c_right = HConstant::cast(right); + if ((c_left->HasNumberValue() && c_right->HasNumberValue())) { + int32_t left_val = c_left->NumberValueAsInteger32(); + int32_t right_val = c_right->NumberValueAsInteger32() & 0x1f; + if ((right_val == 0) && (left_val < 0)) { + return H_CONSTANT_DOUBLE( + static_cast<double>(static_cast<uint32_t>(left_val))); + } + return H_CONSTANT_INT32(static_cast<uint32_t>(left_val) >> right_val); + } + } + return new(zone) HShr(context, left, right); +} + + +#undef H_CONSTANT_INT32 +#undef H_CONSTANT_DOUBLE + + void HIn::PrintDataTo(StringStream* stream) { key()->PrintNameTo(stream); stream->Add(" "); |