[turbofan] Introduce a dedicated ConvertTaggedHoleToUndefined operator.

Separate ConvertTaggedHoleToUndefined and CheckTaggedHole into two
separate operators, where the former is pure and just turns into
trivial control flow in the EffectControlLinearizer.

R=jarin@chromium.org

Review-Url: https://codereview.chromium.org/2236443004
Cr-Commit-Position: refs/heads/master@{#38559}
This commit is contained in:
bmeurer 2016-08-10 12:15:28 -07:00 committed by Commit bot
parent 73b0f15714
commit e61bd68ede
14 changed files with 176 additions and 191 deletions

View File

@ -714,6 +714,9 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
case IrOpcode::kCheckTaggedHole:
state = LowerCheckTaggedHole(node, frame_state, *effect, *control);
break;
case IrOpcode::kConvertTaggedHoleToUndefined:
state = LowerConvertTaggedHoleToUndefined(node, *effect, *control);
break;
case IrOpcode::kPlainPrimitiveToNumber:
state = LowerPlainPrimitiveToNumber(node, *effect, *control);
break;
@ -2418,22 +2421,35 @@ EffectControlLinearizer::LowerCheckFloat64Hole(Node* node, Node* frame_state,
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckTaggedHole(Node* node, Node* frame_state,
Node* effect, Node* control) {
CheckTaggedHoleMode mode = CheckTaggedHoleModeOf(node->op());
Node* value = node->InputAt(0);
Node* check = graph()->NewNode(machine()->WordEqual(), value,
jsgraph()->TheHoleConstant());
switch (mode) {
case CheckTaggedHoleMode::kConvertHoleToUndefined:
value = graph()->NewNode(
common()->Select(MachineRepresentation::kTagged, BranchHint::kFalse),
check, jsgraph()->UndefinedConstant(), value);
break;
case CheckTaggedHoleMode::kNeverReturnHole:
control = effect =
graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kHole),
check, frame_state, effect, control);
break;
}
control = effect =
graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kHole), check,
frame_state, effect, control);
return ValueEffectControl(value, effect, control);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerConvertTaggedHoleToUndefined(Node* node,
Node* effect,
Node* control) {
Node* value = node->InputAt(0);
Node* check = graph()->NewNode(machine()->WordEqual(), value,
jsgraph()->TheHoleConstant());
Node* branch =
graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
Node* vtrue = jsgraph()->UndefinedConstant();
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* vfalse = value;
control = graph()->NewNode(common()->Merge(2), if_true, if_false);
value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
vtrue, vfalse, control);
return ValueEffectControl(value, effect, control);
}

View File

@ -130,6 +130,8 @@ class EffectControlLinearizer {
Node* effect, Node* control);
ValueEffectControl LowerCheckTaggedHole(Node* node, Node* frame_state,
Node* effect, Node* control);
ValueEffectControl LowerConvertTaggedHoleToUndefined(Node* node, Node* effect,
Node* control);
ValueEffectControl LowerPlainPrimitiveToNumber(Node* node, Node* effect,
Node* control);
ValueEffectControl LowerPlainPrimitiveToWord32(Node* node, Node* effect,

View File

@ -1158,7 +1158,7 @@ JSNativeContextSpecialization::BuildElementAccess(
}
// Compute the element access.
Type* element_type = Type::Any();
Type* element_type = Type::NonInternal();
MachineType element_machine_type = MachineType::AnyTagged();
if (IsFastDoubleElementsKind(elements_kind)) {
element_type = Type::Number();
@ -1176,10 +1176,8 @@ JSNativeContextSpecialization::BuildElementAccess(
// of holey backing stores.
if (elements_kind == FAST_HOLEY_ELEMENTS ||
elements_kind == FAST_HOLEY_SMI_ELEMENTS) {
element_access.type = Type::Union(
element_type,
Type::Constant(factory()->the_hole_value(), graph()->zone()),
graph()->zone());
element_access.type =
Type::Union(element_type, Type::Hole(), graph()->zone());
}
// Perform the actual backing store access.
value = effect =
@ -1189,15 +1187,16 @@ JSNativeContextSpecialization::BuildElementAccess(
// the hole to undefined if possible, or deoptimizing otherwise.
if (elements_kind == FAST_HOLEY_ELEMENTS ||
elements_kind == FAST_HOLEY_SMI_ELEMENTS) {
// Perform the hole check on the result.
CheckTaggedHoleMode mode = CheckTaggedHoleMode::kNeverReturnHole;
// Check if we are allowed to turn the hole into undefined.
if (CanTreatHoleAsUndefined(receiver_maps, native_context)) {
// Turn the hole into undefined.
mode = CheckTaggedHoleMode::kConvertHoleToUndefined;
value = graph()->NewNode(simplified()->ConvertTaggedHoleToUndefined(),
value);
} else {
// Bailout if we see the hole.
value = effect = graph()->NewNode(simplified()->CheckTaggedHole(),
value, effect, control);
}
value = effect = graph()->NewNode(simplified()->CheckTaggedHole(mode),
value, effect, control);
} else if (elements_kind == FAST_HOLEY_DOUBLE_ELEMENTS) {
// Perform the hole check on the result.
CheckFloat64HoleMode mode = CheckFloat64HoleMode::kNeverReturnHole;

View File

@ -290,6 +290,7 @@
V(CheckTaggedSigned) \
V(CheckFloat64Hole) \
V(CheckTaggedHole) \
V(ConvertTaggedHoleToUndefined) \
V(Allocate) \
V(LoadField) \
V(LoadBuffer) \

View File

@ -2392,17 +2392,29 @@ class RepresentationSelector {
return;
}
case IrOpcode::kCheckTaggedHole: {
CheckTaggedHoleMode mode = CheckTaggedHoleModeOf(node->op());
if (truncation.IsUsedAsWord32() &&
mode == CheckTaggedHoleMode::kConvertHoleToUndefined) {
ProcessInput(node, 0, UseInfo::CheckedSigned32AsWord32());
ProcessRemainingInputs(node, 1);
SetOutput(node, MachineRepresentation::kWord32);
VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
return;
}
case IrOpcode::kConvertTaggedHoleToUndefined: {
if (InputIs(node, Type::NumberOrOddball()) &&
truncation.IsUsedAsWord32()) {
// Propagate the Word32 truncation.
VisitUnop(node, UseInfo::TruncatingWord32(),
MachineRepresentation::kWord32);
if (lower()) DeferReplacement(node, node->InputAt(0));
} else if (InputIs(node, Type::NumberOrOddball()) &&
truncation.IsUsedAsFloat64()) {
// Propagate the Float64 truncation.
VisitUnop(node, UseInfo::TruncatingFloat64(),
MachineRepresentation::kFloat64);
if (lower()) DeferReplacement(node, node->InputAt(0));
} else if (InputIs(node, Type::NonInternal())) {
VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
if (lower()) DeferReplacement(node, node->InputAt(0));
} else {
ProcessInput(node, 0, UseInfo::AnyTagged());
ProcessRemainingInputs(node, 1);
SetOutput(node, MachineRepresentation::kTagged);
// TODO(turbofan): Add a (Tagged) truncation that identifies hole
// and undefined, i.e. for a[i] === obj cases.
VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
}
return;
}

View File

@ -229,26 +229,6 @@ std::ostream& operator<<(std::ostream& os, CheckForMinusZeroMode mode) {
return os;
}
size_t hash_value(CheckTaggedHoleMode mode) {
return static_cast<size_t>(mode);
}
std::ostream& operator<<(std::ostream& os, CheckTaggedHoleMode mode) {
switch (mode) {
case CheckTaggedHoleMode::kConvertHoleToUndefined:
return os << "convert-hole-to-undefined";
case CheckTaggedHoleMode::kNeverReturnHole:
return os << "never-return-hole";
}
UNREACHABLE();
return os;
}
CheckTaggedHoleMode CheckTaggedHoleModeOf(const Operator* op) {
DCHECK_EQ(IrOpcode::kCheckTaggedHole, op->opcode());
return OpParameter<CheckTaggedHoleMode>(op);
}
size_t hash_value(CheckTaggedInputMode mode) {
return static_cast<size_t>(mode);
}
@ -351,84 +331,85 @@ NumberOperationHint NumberOperationHintOf(const Operator* op) {
return OpParameter<NumberOperationHint>(op);
}
#define PURE_OP_LIST(V) \
V(BooleanNot, Operator::kNoProperties, 1, 0) \
V(NumberEqual, Operator::kCommutative, 2, 0) \
V(NumberLessThan, Operator::kNoProperties, 2, 0) \
V(NumberLessThanOrEqual, Operator::kNoProperties, 2, 0) \
V(NumberAdd, Operator::kCommutative, 2, 0) \
V(NumberSubtract, Operator::kNoProperties, 2, 0) \
V(NumberMultiply, Operator::kCommutative, 2, 0) \
V(NumberDivide, Operator::kNoProperties, 2, 0) \
V(NumberModulus, Operator::kNoProperties, 2, 0) \
V(NumberBitwiseOr, Operator::kCommutative, 2, 0) \
V(NumberBitwiseXor, Operator::kCommutative, 2, 0) \
V(NumberBitwiseAnd, Operator::kCommutative, 2, 0) \
V(NumberShiftLeft, Operator::kNoProperties, 2, 0) \
V(NumberShiftRight, Operator::kNoProperties, 2, 0) \
V(NumberShiftRightLogical, Operator::kNoProperties, 2, 0) \
V(NumberImul, Operator::kCommutative, 2, 0) \
V(NumberAbs, Operator::kNoProperties, 1, 0) \
V(NumberClz32, Operator::kNoProperties, 1, 0) \
V(NumberCeil, Operator::kNoProperties, 1, 0) \
V(NumberFloor, Operator::kNoProperties, 1, 0) \
V(NumberFround, Operator::kNoProperties, 1, 0) \
V(NumberAcos, Operator::kNoProperties, 1, 0) \
V(NumberAcosh, Operator::kNoProperties, 1, 0) \
V(NumberAsin, Operator::kNoProperties, 1, 0) \
V(NumberAsinh, Operator::kNoProperties, 1, 0) \
V(NumberAtan, Operator::kNoProperties, 1, 0) \
V(NumberAtan2, Operator::kNoProperties, 2, 0) \
V(NumberAtanh, Operator::kNoProperties, 1, 0) \
V(NumberCbrt, Operator::kNoProperties, 1, 0) \
V(NumberCos, Operator::kNoProperties, 1, 0) \
V(NumberCosh, Operator::kNoProperties, 1, 0) \
V(NumberExp, Operator::kNoProperties, 1, 0) \
V(NumberExpm1, Operator::kNoProperties, 1, 0) \
V(NumberLog, Operator::kNoProperties, 1, 0) \
V(NumberLog1p, Operator::kNoProperties, 1, 0) \
V(NumberLog10, Operator::kNoProperties, 1, 0) \
V(NumberLog2, Operator::kNoProperties, 1, 0) \
V(NumberMax, Operator::kNoProperties, 2, 0) \
V(NumberMin, Operator::kNoProperties, 2, 0) \
V(NumberPow, Operator::kNoProperties, 2, 0) \
V(NumberRound, Operator::kNoProperties, 1, 0) \
V(NumberSign, Operator::kNoProperties, 1, 0) \
V(NumberSin, Operator::kNoProperties, 1, 0) \
V(NumberSinh, Operator::kNoProperties, 1, 0) \
V(NumberSqrt, Operator::kNoProperties, 1, 0) \
V(NumberTan, Operator::kNoProperties, 1, 0) \
V(NumberTanh, Operator::kNoProperties, 1, 0) \
V(NumberTrunc, Operator::kNoProperties, 1, 0) \
V(NumberToInt32, Operator::kNoProperties, 1, 0) \
V(NumberToUint32, Operator::kNoProperties, 1, 0) \
V(NumberSilenceNaN, Operator::kNoProperties, 1, 0) \
V(StringCharCodeAt, Operator::kNoProperties, 2, 1) \
V(StringFromCharCode, Operator::kNoProperties, 1, 0) \
V(PlainPrimitiveToNumber, Operator::kNoProperties, 1, 0) \
V(PlainPrimitiveToWord32, Operator::kNoProperties, 1, 0) \
V(PlainPrimitiveToFloat64, Operator::kNoProperties, 1, 0) \
V(ChangeTaggedSignedToInt32, Operator::kNoProperties, 1, 0) \
V(ChangeTaggedToInt32, Operator::kNoProperties, 1, 0) \
V(ChangeTaggedToUint32, Operator::kNoProperties, 1, 0) \
V(ChangeTaggedToFloat64, Operator::kNoProperties, 1, 0) \
V(ChangeInt31ToTaggedSigned, Operator::kNoProperties, 1, 0) \
V(ChangeInt32ToTagged, Operator::kNoProperties, 1, 0) \
V(ChangeUint32ToTagged, Operator::kNoProperties, 1, 0) \
V(ChangeFloat64ToTagged, Operator::kNoProperties, 1, 0) \
V(ChangeTaggedToBit, Operator::kNoProperties, 1, 0) \
V(ChangeBitToTagged, Operator::kNoProperties, 1, 0) \
V(TruncateTaggedToWord32, Operator::kNoProperties, 1, 0) \
V(TruncateTaggedToFloat64, Operator::kNoProperties, 1, 0) \
V(ObjectIsCallable, Operator::kNoProperties, 1, 0) \
V(ObjectIsNumber, Operator::kNoProperties, 1, 0) \
V(ObjectIsReceiver, Operator::kNoProperties, 1, 0) \
V(ObjectIsSmi, Operator::kNoProperties, 1, 0) \
V(ObjectIsString, Operator::kNoProperties, 1, 0) \
V(ObjectIsUndetectable, Operator::kNoProperties, 1, 0) \
V(ReferenceEqual, Operator::kCommutative, 2, 0) \
V(StringEqual, Operator::kCommutative, 2, 0) \
V(StringLessThan, Operator::kNoProperties, 2, 0) \
#define PURE_OP_LIST(V) \
V(BooleanNot, Operator::kNoProperties, 1, 0) \
V(NumberEqual, Operator::kCommutative, 2, 0) \
V(NumberLessThan, Operator::kNoProperties, 2, 0) \
V(NumberLessThanOrEqual, Operator::kNoProperties, 2, 0) \
V(NumberAdd, Operator::kCommutative, 2, 0) \
V(NumberSubtract, Operator::kNoProperties, 2, 0) \
V(NumberMultiply, Operator::kCommutative, 2, 0) \
V(NumberDivide, Operator::kNoProperties, 2, 0) \
V(NumberModulus, Operator::kNoProperties, 2, 0) \
V(NumberBitwiseOr, Operator::kCommutative, 2, 0) \
V(NumberBitwiseXor, Operator::kCommutative, 2, 0) \
V(NumberBitwiseAnd, Operator::kCommutative, 2, 0) \
V(NumberShiftLeft, Operator::kNoProperties, 2, 0) \
V(NumberShiftRight, Operator::kNoProperties, 2, 0) \
V(NumberShiftRightLogical, Operator::kNoProperties, 2, 0) \
V(NumberImul, Operator::kCommutative, 2, 0) \
V(NumberAbs, Operator::kNoProperties, 1, 0) \
V(NumberClz32, Operator::kNoProperties, 1, 0) \
V(NumberCeil, Operator::kNoProperties, 1, 0) \
V(NumberFloor, Operator::kNoProperties, 1, 0) \
V(NumberFround, Operator::kNoProperties, 1, 0) \
V(NumberAcos, Operator::kNoProperties, 1, 0) \
V(NumberAcosh, Operator::kNoProperties, 1, 0) \
V(NumberAsin, Operator::kNoProperties, 1, 0) \
V(NumberAsinh, Operator::kNoProperties, 1, 0) \
V(NumberAtan, Operator::kNoProperties, 1, 0) \
V(NumberAtan2, Operator::kNoProperties, 2, 0) \
V(NumberAtanh, Operator::kNoProperties, 1, 0) \
V(NumberCbrt, Operator::kNoProperties, 1, 0) \
V(NumberCos, Operator::kNoProperties, 1, 0) \
V(NumberCosh, Operator::kNoProperties, 1, 0) \
V(NumberExp, Operator::kNoProperties, 1, 0) \
V(NumberExpm1, Operator::kNoProperties, 1, 0) \
V(NumberLog, Operator::kNoProperties, 1, 0) \
V(NumberLog1p, Operator::kNoProperties, 1, 0) \
V(NumberLog10, Operator::kNoProperties, 1, 0) \
V(NumberLog2, Operator::kNoProperties, 1, 0) \
V(NumberMax, Operator::kNoProperties, 2, 0) \
V(NumberMin, Operator::kNoProperties, 2, 0) \
V(NumberPow, Operator::kNoProperties, 2, 0) \
V(NumberRound, Operator::kNoProperties, 1, 0) \
V(NumberSign, Operator::kNoProperties, 1, 0) \
V(NumberSin, Operator::kNoProperties, 1, 0) \
V(NumberSinh, Operator::kNoProperties, 1, 0) \
V(NumberSqrt, Operator::kNoProperties, 1, 0) \
V(NumberTan, Operator::kNoProperties, 1, 0) \
V(NumberTanh, Operator::kNoProperties, 1, 0) \
V(NumberTrunc, Operator::kNoProperties, 1, 0) \
V(NumberToInt32, Operator::kNoProperties, 1, 0) \
V(NumberToUint32, Operator::kNoProperties, 1, 0) \
V(NumberSilenceNaN, Operator::kNoProperties, 1, 0) \
V(StringCharCodeAt, Operator::kNoProperties, 2, 1) \
V(StringFromCharCode, Operator::kNoProperties, 1, 0) \
V(PlainPrimitiveToNumber, Operator::kNoProperties, 1, 0) \
V(PlainPrimitiveToWord32, Operator::kNoProperties, 1, 0) \
V(PlainPrimitiveToFloat64, Operator::kNoProperties, 1, 0) \
V(ChangeTaggedSignedToInt32, Operator::kNoProperties, 1, 0) \
V(ChangeTaggedToInt32, Operator::kNoProperties, 1, 0) \
V(ChangeTaggedToUint32, Operator::kNoProperties, 1, 0) \
V(ChangeTaggedToFloat64, Operator::kNoProperties, 1, 0) \
V(ChangeInt31ToTaggedSigned, Operator::kNoProperties, 1, 0) \
V(ChangeInt32ToTagged, Operator::kNoProperties, 1, 0) \
V(ChangeUint32ToTagged, Operator::kNoProperties, 1, 0) \
V(ChangeFloat64ToTagged, Operator::kNoProperties, 1, 0) \
V(ChangeTaggedToBit, Operator::kNoProperties, 1, 0) \
V(ChangeBitToTagged, Operator::kNoProperties, 1, 0) \
V(TruncateTaggedToWord32, Operator::kNoProperties, 1, 0) \
V(TruncateTaggedToFloat64, Operator::kNoProperties, 1, 0) \
V(ObjectIsCallable, Operator::kNoProperties, 1, 0) \
V(ObjectIsNumber, Operator::kNoProperties, 1, 0) \
V(ObjectIsReceiver, Operator::kNoProperties, 1, 0) \
V(ObjectIsSmi, Operator::kNoProperties, 1, 0) \
V(ObjectIsString, Operator::kNoProperties, 1, 0) \
V(ObjectIsUndetectable, Operator::kNoProperties, 1, 0) \
V(ConvertTaggedHoleToUndefined, Operator::kNoProperties, 1, 0) \
V(ReferenceEqual, Operator::kCommutative, 2, 0) \
V(StringEqual, Operator::kCommutative, 2, 0) \
V(StringLessThan, Operator::kNoProperties, 2, 0) \
V(StringLessThanOrEqual, Operator::kNoProperties, 2, 0)
#define SPECULATIVE_NUMBER_BINOP_LIST(V) \
@ -442,6 +423,7 @@ NumberOperationHint NumberOperationHintOf(const Operator* op) {
V(CheckIf, 1, 0) \
V(CheckNumber, 1, 1) \
V(CheckString, 1, 1) \
V(CheckTaggedHole, 1, 1) \
V(CheckTaggedPointer, 1, 1) \
V(CheckTaggedSigned, 1, 1) \
V(CheckedInt32Add, 2, 1) \
@ -546,19 +528,6 @@ struct SimplifiedOperatorGlobalCache final {
CheckFloat64HoleNaNOperator<CheckFloat64HoleMode::kNeverReturnHole>
kCheckFloat64HoleNeverReturnHoleOperator;
template <CheckTaggedHoleMode kMode>
struct CheckTaggedHoleOperator final : public Operator1<CheckTaggedHoleMode> {
CheckTaggedHoleOperator()
: Operator1<CheckTaggedHoleMode>(
IrOpcode::kCheckTaggedHole,
Operator::kFoldable | Operator::kNoThrow, "CheckTaggedHole", 1, 1,
1, 1, 1, 0, kMode) {}
};
CheckTaggedHoleOperator<CheckTaggedHoleMode::kConvertHoleToUndefined>
kCheckTaggedHoleConvertHoleToUndefinedOperator;
CheckTaggedHoleOperator<CheckTaggedHoleMode::kNeverReturnHole>
kCheckTaggedHoleNeverReturnHoleOperator;
template <PretenureFlag kPretenure>
struct AllocateOperator final : public Operator1<PretenureFlag> {
AllocateOperator()
@ -706,18 +675,6 @@ const Operator* SimplifiedOperatorBuilder::CheckFloat64Hole(
return nullptr;
}
const Operator* SimplifiedOperatorBuilder::CheckTaggedHole(
CheckTaggedHoleMode mode) {
switch (mode) {
case CheckTaggedHoleMode::kConvertHoleToUndefined:
return &cache_.kCheckTaggedHoleConvertHoleToUndefinedOperator;
case CheckTaggedHoleMode::kNeverReturnHole:
return &cache_.kCheckTaggedHoleNeverReturnHoleOperator;
}
UNREACHABLE();
return nullptr;
}
const Operator* SimplifiedOperatorBuilder::EnsureWritableFastElements() {
return &cache_.kEnsureWritableFastElements;
}

View File

@ -119,17 +119,6 @@ std::ostream& operator<<(std::ostream&, CheckFloat64HoleMode);
CheckFloat64HoleMode CheckFloat64HoleModeOf(const Operator*) WARN_UNUSED_RESULT;
enum class CheckTaggedHoleMode : uint8_t {
kNeverReturnHole, // Never return the hole (deoptimize instead).
kConvertHoleToUndefined // Convert the hole to undefined.
};
size_t hash_value(CheckTaggedHoleMode);
std::ostream& operator<<(std::ostream&, CheckTaggedHoleMode);
CheckTaggedHoleMode CheckTaggedHoleModeOf(const Operator*) WARN_UNUSED_RESULT;
enum class CheckTaggedInputMode : uint8_t {
kNumber,
kNumberOrOddball,
@ -339,7 +328,8 @@ class SimplifiedOperatorBuilder final : public ZoneObject {
const Operator* CheckedTruncateTaggedToWord32();
const Operator* CheckFloat64Hole(CheckFloat64HoleMode);
const Operator* CheckTaggedHole(CheckTaggedHoleMode);
const Operator* CheckTaggedHole();
const Operator* ConvertTaggedHoleToUndefined();
const Operator* ObjectIsCallable();
const Operator* ObjectIsNumber();

View File

@ -1234,7 +1234,7 @@ Type* Typer::Visitor::WrapContextTypeForInput(Node* node) {
if (outer->Is(Type::None())) {
return Type::None();
} else {
DCHECK(outer->Maybe(Type::Internal()));
DCHECK(outer->Maybe(Type::OtherInternal()));
return Type::Context(outer, zone());
}
}
@ -1583,19 +1583,17 @@ Type* Typer::Visitor::TypeCheckFloat64Hole(Node* node) {
}
Type* Typer::Visitor::TypeCheckTaggedHole(Node* node) {
CheckTaggedHoleMode mode = CheckTaggedHoleModeOf(node->op());
Type* type = Operand(node, 0);
type = Type::Intersect(type, Type::NonInternal(), zone());
switch (mode) {
case CheckTaggedHoleMode::kConvertHoleToUndefined: {
// The hole is turned into undefined.
type = Type::Union(type, Type::Undefined(), zone());
break;
}
case CheckTaggedHoleMode::kNeverReturnHole: {
// We deoptimize in case of the hole.
break;
}
return type;
}
Type* Typer::Visitor::TypeConvertTaggedHoleToUndefined(Node* node) {
Type* type = Operand(node, 0);
if (type->Maybe(Type::Hole())) {
// Turn "the hole" into undefined.
type = Type::Intersect(type, Type::NonInternal(), zone());
type = Type::Union(type, Type::Undefined(), zone());
}
return type;
}

View File

@ -1042,7 +1042,11 @@ void Verifier::Visitor::Check(Node* node) {
break;
case IrOpcode::kCheckTaggedHole:
CheckValueInputIs(node, 0, Type::Any());
CheckUpperIs(node, Type::Any());
CheckUpperIs(node, Type::NonInternal());
break;
case IrOpcode::kConvertTaggedHoleToUndefined:
CheckValueInputIs(node, 0, Type::Any());
CheckUpperIs(node, Type::NonInternal());
break;
case IrOpcode::kLoadField:

View File

@ -2609,6 +2609,8 @@ void Heap::CreateInitialObjects() {
set_nan_value(*factory->NewHeapNumber(
std::numeric_limits<double>::quiet_NaN(), IMMUTABLE, TENURED));
set_hole_nan_value(*factory->NewHeapNumber(bit_cast<double>(kHoleNanInt64),
IMMUTABLE, TENURED));
set_infinity_value(*factory->NewHeapNumber(V8_INFINITY, IMMUTABLE, TENURED));
set_minus_infinity_value(
*factory->NewHeapNumber(-V8_INFINITY, IMMUTABLE, TENURED));
@ -2629,7 +2631,7 @@ void Heap::CreateInitialObjects() {
// Initialize the_hole_value.
Oddball::Initialize(isolate(), factory->the_hole_value(), "hole",
handle(Smi::FromInt(-1), isolate()), "undefined",
factory->hole_nan_value(), "undefined",
Oddball::kTheHole);
// Initialize the true_value.

View File

@ -166,6 +166,7 @@ using v8::MemoryPressureLevel;
V(Cell, species_protector, SpeciesProtector) \
/* Special numbers */ \
V(HeapNumber, nan_value, NanValue) \
V(HeapNumber, hole_nan_value, HoleNanValue) \
V(HeapNumber, infinity_value, InfinityValue) \
V(HeapNumber, minus_zero_value, MinusZeroValue) \
V(HeapNumber, minus_infinity_value, MinusInfinityValue) \

View File

@ -601,7 +601,8 @@ void Oddball::OddballVerify() {
VerifyHeapPointer(to_string());
Object* number = to_number();
if (number->IsHeapObject()) {
CHECK(number == heap->nan_value());
CHECK(number == heap->nan_value() ||
number == heap->hole_nan_value());
} else {
CHECK(number->IsSmi());
int value = Smi::cast(number)->value();

View File

@ -147,10 +147,10 @@ Type::bitset BitsetType::Lub(Type* type) {
if (type->IsClass()) return type->AsClass()->Lub();
if (type->IsConstant()) return type->AsConstant()->Lub();
if (type->IsRange()) return type->AsRange()->Lub();
if (type->IsContext()) return kInternal & kTaggedPointer;
if (type->IsContext()) return kOtherInternal & kTaggedPointer;
if (type->IsArray()) return kOtherObject;
if (type->IsFunction()) return kFunction;
if (type->IsTuple()) return kInternal;
if (type->IsTuple()) return kOtherInternal;
UNREACHABLE();
return kNone;
}
@ -187,14 +187,14 @@ Type::bitset BitsetType::Lub(i::Map* map) {
if (map == heap->undefined_map()) return kUndefined;
if (map == heap->null_map()) return kNull;
if (map == heap->boolean_map()) return kBoolean;
DCHECK(map == heap->the_hole_map() ||
map == heap->uninitialized_map() ||
if (map == heap->the_hole_map()) return kHole;
DCHECK(map == heap->uninitialized_map() ||
map == heap->no_interceptor_result_sentinel_map() ||
map == heap->termination_exception_map() ||
map == heap->arguments_marker_map() ||
map == heap->optimized_out_map() ||
map == heap->stale_register_map());
return kInternal & kTaggedPointer;
return kOtherInternal & kTaggedPointer;
}
case HEAP_NUMBER_TYPE:
return kNumber & kTaggedPointer;
@ -250,10 +250,10 @@ Type::bitset BitsetType::Lub(i::Map* map) {
case SCRIPT_TYPE:
case CODE_TYPE:
case PROPERTY_CELL_TYPE:
return kInternal & kTaggedPointer;
return kOtherInternal & kTaggedPointer;
// Remaining instance types are unsupported for now. If any of them do
// require bit set types, they should get kInternal & kTaggedPointer.
// require bit set types, they should get kOtherInternal & kTaggedPointer.
case MUTABLE_HEAP_NUMBER_TYPE:
case FREE_SPACE_TYPE:
#define FIXED_TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \

View File

@ -199,7 +199,8 @@ namespace internal {
V(OtherUndetectable, 1u << 16 | REPRESENTATION(kTaggedPointer)) \
V(Proxy, 1u << 18 | REPRESENTATION(kTaggedPointer)) \
V(Function, 1u << 19 | REPRESENTATION(kTaggedPointer)) \
V(Internal, 1u << 20 | REPRESENTATION(kTagged | kUntagged)) \
V(Hole, 1u << 20 | REPRESENTATION(kTaggedPointer)) \
V(OtherInternal, 1u << 21 | REPRESENTATION(kTagged | kUntagged)) \
\
V(Signed31, kUnsigned30 | kNegative31) \
V(Signed32, kSigned31 | kOtherUnsigned31 | kOtherSigned32) \
@ -225,7 +226,7 @@ namespace internal {
V(NullOrNumber, kNull | kNumber) \
V(NullOrUndefined, kNull | kUndefined) \
V(Undetectable, kNullOrUndefined | kOtherUndetectable) \
V(NumberOrOddball, kNumber | kNullOrUndefined | kBoolean) \
V(NumberOrOddball, kNumber | kNullOrUndefined | kBoolean | kHole) \
V(NumberOrSimdOrString, kNumber | kSimd | kString) \
V(NumberOrString, kNumber | kString) \
V(NumberOrUndefined, kNumber | kUndefined) \
@ -237,6 +238,7 @@ namespace internal {
V(StringOrReceiver, kString | kReceiver) \
V(Unique, kBoolean | kUniqueName | kNull | kUndefined | \
kReceiver) \
V(Internal, kHole | kOtherInternal) \
V(NonInternal, kPrimitive | kReceiver) \
V(NonNumber, kUnique | kString | kInternal) \
V(Any, 0xfffffffeu)