Commit a81d19d5 authored by jarin's avatar jarin Committed by Commit bot

[turbofan] Handle impossible types (Type::None()) in the backend.

BUG=chromium:630611

Review-Url: https://codereview.chromium.org/2177483002
Cr-Commit-Position: refs/heads/master@{#37994}
parent 7ede61ed
...@@ -266,7 +266,9 @@ namespace internal { ...@@ -266,7 +266,9 @@ namespace internal {
V(kWrongArgumentCountForInvokeIntrinsic, \ V(kWrongArgumentCountForInvokeIntrinsic, \
"Wrong number of arguments for intrinsic") \ "Wrong number of arguments for intrinsic") \
V(kShouldNotDirectlyEnterOsrFunction, \ V(kShouldNotDirectlyEnterOsrFunction, \
"Should not directly enter OSR-compiled function") "Should not directly enter OSR-compiled function") \
V(kConversionFromImpossibleValue, \
"Reached conversion from value with empty type (i.e., impossible type)")
#define ERROR_MESSAGES_CONSTANTS(C, T) C, #define ERROR_MESSAGES_CONSTANTS(C, T) C,
enum BailoutReason { enum BailoutReason {
......
...@@ -696,6 +696,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -696,6 +696,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kArchDebugBreak: case kArchDebugBreak:
__ stop("kArchDebugBreak"); __ stop("kArchDebugBreak");
break; break;
case kArchImpossible:
__ Abort(kConversionFromImpossibleValue);
break;
case kArchComment: { case kArchComment: {
Address comment_string = i.InputExternalReference(0).address(); Address comment_string = i.InputExternalReference(0).address();
__ RecordComment(reinterpret_cast<const char*>(comment_string)); __ RecordComment(reinterpret_cast<const char*>(comment_string));
......
...@@ -766,6 +766,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -766,6 +766,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kArchDebugBreak: case kArchDebugBreak:
__ Debug("kArchDebugBreak", 0, BREAK); __ Debug("kArchDebugBreak", 0, BREAK);
break; break;
case kArchImpossible:
__ Abort(kConversionFromImpossibleValue);
break;
case kArchComment: { case kArchComment: {
Address comment_string = i.InputExternalReference(0).address(); Address comment_string = i.InputExternalReference(0).address();
__ RecordComment(reinterpret_cast<const char*>(comment_string)); __ RecordComment(reinterpret_cast<const char*>(comment_string));
......
...@@ -865,7 +865,11 @@ void CodeGenerator::AddTranslationForOperand(Translation* translation, ...@@ -865,7 +865,11 @@ void CodeGenerator::AddTranslationForOperand(Translation* translation,
switch (constant.type()) { switch (constant.type()) {
case Constant::kInt32: case Constant::kInt32:
DCHECK(type == MachineType::Int32() || type == MachineType::Uint32() || DCHECK(type == MachineType::Int32() || type == MachineType::Uint32() ||
type.representation() == MachineRepresentation::kBit); type.representation() == MachineRepresentation::kBit ||
type.representation() == MachineRepresentation::kNone);
DCHECK(type.representation() != MachineRepresentation::kNone ||
constant.ToInt32() == FrameStateDescriptor::kImpossibleValue);
constant_object = constant_object =
isolate()->factory()->NewNumberFromInt(constant.ToInt32()); isolate()->factory()->NewNumberFromInt(constant.ToInt32());
break; break;
......
...@@ -621,6 +621,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -621,6 +621,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kArchDebugBreak: case kArchDebugBreak:
__ int3(); __ int3();
break; break;
case kArchImpossible:
__ Abort(kConversionFromImpossibleValue);
break;
case kArchNop: case kArchNop:
case kArchThrowTerminator: case kArchThrowTerminator:
// don't emit code for nops. // don't emit code for nops.
......
...@@ -57,6 +57,7 @@ enum class RecordWriteMode { kValueIsMap, kValueIsPointer, kValueIsAny }; ...@@ -57,6 +57,7 @@ enum class RecordWriteMode { kValueIsMap, kValueIsPointer, kValueIsAny };
V(ArchTableSwitch) \ V(ArchTableSwitch) \
V(ArchNop) \ V(ArchNop) \
V(ArchDebugBreak) \ V(ArchDebugBreak) \
V(ArchImpossible) \
V(ArchComment) \ V(ArchComment) \
V(ArchThrowTerminator) \ V(ArchThrowTerminator) \
V(ArchDeoptimize) \ V(ArchDeoptimize) \
......
...@@ -223,6 +223,7 @@ int InstructionScheduler::GetInstructionFlags(const Instruction* instr) const { ...@@ -223,6 +223,7 @@ int InstructionScheduler::GetInstructionFlags(const Instruction* instr) const {
case kArchTruncateDoubleToI: case kArchTruncateDoubleToI:
case kArchStackSlot: case kArchStackSlot:
case kArchDebugBreak: case kArchDebugBreak:
case kArchImpossible:
case kArchComment: case kArchComment:
case kIeee754Float64Acos: case kIeee754Float64Acos:
case kIeee754Float64Acosh: case kIeee754Float64Acosh:
......
...@@ -62,9 +62,13 @@ class OperandGenerator { ...@@ -62,9 +62,13 @@ class OperandGenerator {
} }
InstructionOperand DefineAsConstant(Node* node) { InstructionOperand DefineAsConstant(Node* node) {
return DefineAsConstant(node, ToConstant(node));
}
InstructionOperand DefineAsConstant(Node* node, Constant constant) {
selector()->MarkAsDefined(node); selector()->MarkAsDefined(node);
int virtual_register = GetVReg(node); int virtual_register = GetVReg(node);
sequence()->AddConstant(virtual_register, ToConstant(node)); sequence()->AddConstant(virtual_register, constant);
return ConstantOperand(virtual_register); return ConstantOperand(virtual_register);
} }
......
...@@ -344,9 +344,9 @@ namespace { ...@@ -344,9 +344,9 @@ namespace {
enum class FrameStateInputKind { kAny, kStackSlot }; enum class FrameStateInputKind { kAny, kStackSlot };
InstructionOperand OperandForDeopt(OperandGenerator* g, Node* input, InstructionOperand OperandForDeopt(OperandGenerator* g, Node* input,
FrameStateInputKind kind) { FrameStateInputKind kind,
MachineRepresentation rep) {
switch (input->opcode()) { switch (input->opcode()) {
case IrOpcode::kInt32Constant: case IrOpcode::kInt32Constant:
case IrOpcode::kNumberConstant: case IrOpcode::kNumberConstant:
...@@ -358,11 +358,15 @@ InstructionOperand OperandForDeopt(OperandGenerator* g, Node* input, ...@@ -358,11 +358,15 @@ InstructionOperand OperandForDeopt(OperandGenerator* g, Node* input,
UNREACHABLE(); UNREACHABLE();
break; break;
default: default:
switch (kind) { if (rep == MachineRepresentation::kNone) {
case FrameStateInputKind::kStackSlot: return g->TempImmediate(FrameStateDescriptor::kImpossibleValue);
return g->UseUniqueSlot(input); } else {
case FrameStateInputKind::kAny: switch (kind) {
return g->UseAny(input); case FrameStateInputKind::kStackSlot:
return g->UseUniqueSlot(input);
case FrameStateInputKind::kAny:
return g->UseAny(input);
}
} }
} }
UNREACHABLE(); UNREACHABLE();
...@@ -428,7 +432,7 @@ size_t AddOperandToStateValueDescriptor(StateValueDescriptor* descriptor, ...@@ -428,7 +432,7 @@ size_t AddOperandToStateValueDescriptor(StateValueDescriptor* descriptor,
break; break;
} }
default: { default: {
inputs->push_back(OperandForDeopt(g, input, kind)); inputs->push_back(OperandForDeopt(g, input, kind, type.representation()));
descriptor->fields().push_back(StateValueDescriptor::Plain(zone, type)); descriptor->fields().push_back(StateValueDescriptor::Plain(zone, type));
return 1; return 1;
} }
...@@ -886,6 +890,7 @@ void InstructionSelector::VisitNode(Node* node) { ...@@ -886,6 +890,7 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsReference(node), VisitOsrValue(node); return MarkAsReference(node), VisitOsrValue(node);
case IrOpcode::kPhi: { case IrOpcode::kPhi: {
MachineRepresentation rep = PhiRepresentationOf(node->op()); MachineRepresentation rep = PhiRepresentationOf(node->op());
if (rep == MachineRepresentation::kNone) return;
MarkAsRepresentation(rep, node); MarkAsRepresentation(rep, node);
return VisitPhi(node); return VisitPhi(node);
} }
...@@ -1049,6 +1054,19 @@ void InstructionSelector::VisitNode(Node* node) { ...@@ -1049,6 +1054,19 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsWord32(node), VisitChangeFloat64ToInt32(node); return MarkAsWord32(node), VisitChangeFloat64ToInt32(node);
case IrOpcode::kChangeFloat64ToUint32: case IrOpcode::kChangeFloat64ToUint32:
return MarkAsWord32(node), VisitChangeFloat64ToUint32(node); return MarkAsWord32(node), VisitChangeFloat64ToUint32(node);
case IrOpcode::kImpossibleToWord32:
return MarkAsWord32(node), VisitImpossibleToWord32(node);
case IrOpcode::kImpossibleToWord64:
return MarkAsWord64(node), VisitImpossibleToWord64(node);
case IrOpcode::kImpossibleToFloat32:
return MarkAsFloat32(node), VisitImpossibleToFloat32(node);
case IrOpcode::kImpossibleToFloat64:
return MarkAsFloat64(node), VisitImpossibleToFloat64(node);
case IrOpcode::kImpossibleToTagged:
MarkAsRepresentation(MachineType::PointerRepresentation(), node);
return VisitImpossibleToTagged(node);
case IrOpcode::kImpossibleToBit:
return MarkAsWord32(node), VisitImpossibleToBit(node);
case IrOpcode::kFloat64SilenceNaN: case IrOpcode::kFloat64SilenceNaN:
MarkAsFloat64(node); MarkAsFloat64(node);
if (CanProduceSignalingNaN(node->InputAt(0))) { if (CanProduceSignalingNaN(node->InputAt(0))) {
...@@ -1282,13 +1300,47 @@ void InstructionSelector::VisitNode(Node* node) { ...@@ -1282,13 +1300,47 @@ void InstructionSelector::VisitNode(Node* node) {
} }
} }
void InstructionSelector::VisitImpossibleToWord32(Node* node) {
OperandGenerator g(this);
Emit(kArchImpossible, g.DefineAsConstant(node, Constant(0)));
}
void InstructionSelector::VisitImpossibleToWord64(Node* node) {
OperandGenerator g(this);
Emit(kArchImpossible,
g.DefineAsConstant(node, Constant(static_cast<int64_t>(0))));
}
void InstructionSelector::VisitImpossibleToFloat32(Node* node) {
OperandGenerator g(this);
Emit(kArchImpossible, g.DefineAsConstant(node, Constant(0.0f)));
}
void InstructionSelector::VisitImpossibleToFloat64(Node* node) {
OperandGenerator g(this);
Emit(kArchImpossible, g.DefineAsConstant(node, Constant(0.0)));
}
void InstructionSelector::VisitImpossibleToBit(Node* node) {
OperandGenerator g(this);
Emit(kArchImpossible, g.DefineAsConstant(node, Constant(0)));
}
void InstructionSelector::VisitImpossibleToTagged(Node* node) {
OperandGenerator g(this);
#if V8_TARGET_ARCH_64_BIT
Emit(kArchImpossible,
g.DefineAsConstant(node, Constant(static_cast<int64_t>(0))));
#else // V8_TARGET_ARCH_64_BIT
Emit(kArchImpossible, g.DefineAsConstant(node, Constant(0)));
#endif // V8_TARGET_ARCH_64_BIT
}
void InstructionSelector::VisitLoadStackPointer(Node* node) { void InstructionSelector::VisitLoadStackPointer(Node* node) {
OperandGenerator g(this); OperandGenerator g(this);
Emit(kArchStackPointer, g.DefineAsRegister(node)); Emit(kArchStackPointer, g.DefineAsRegister(node));
} }
void InstructionSelector::VisitLoadFramePointer(Node* node) { void InstructionSelector::VisitLoadFramePointer(Node* node) {
OperandGenerator g(this); OperandGenerator g(this);
Emit(kArchFramePointer, g.DefineAsRegister(node)); Emit(kArchFramePointer, g.DefineAsRegister(node));
......
...@@ -1149,6 +1149,8 @@ class FrameStateDescriptor : public ZoneObject { ...@@ -1149,6 +1149,8 @@ class FrameStateDescriptor : public ZoneObject {
} }
StateValueDescriptor* GetStateValueDescriptor() { return &values_; } StateValueDescriptor* GetStateValueDescriptor() { return &values_; }
static const int kImpossibleValue = 0xdead;
private: private:
FrameStateType type_; FrameStateType type_;
BailoutId bailout_id_; BailoutId bailout_id_;
......
...@@ -145,6 +145,12 @@ MachineRepresentation AtomicStoreRepresentationOf(Operator const* op) { ...@@ -145,6 +145,12 @@ MachineRepresentation AtomicStoreRepresentationOf(Operator const* op) {
V(ChangeInt32ToInt64, Operator::kNoProperties, 1, 0, 1) \ V(ChangeInt32ToInt64, Operator::kNoProperties, 1, 0, 1) \
V(ChangeUint32ToFloat64, Operator::kNoProperties, 1, 0, 1) \ V(ChangeUint32ToFloat64, Operator::kNoProperties, 1, 0, 1) \
V(ChangeUint32ToUint64, Operator::kNoProperties, 1, 0, 1) \ V(ChangeUint32ToUint64, Operator::kNoProperties, 1, 0, 1) \
V(ImpossibleToWord32, Operator::kNoProperties, 1, 0, 1) \
V(ImpossibleToWord64, Operator::kNoProperties, 1, 0, 1) \
V(ImpossibleToFloat32, Operator::kNoProperties, 1, 0, 1) \
V(ImpossibleToFloat64, Operator::kNoProperties, 1, 0, 1) \
V(ImpossibleToTagged, Operator::kNoProperties, 1, 0, 1) \
V(ImpossibleToBit, Operator::kNoProperties, 1, 0, 1) \
V(TruncateFloat64ToFloat32, Operator::kNoProperties, 1, 0, 1) \ V(TruncateFloat64ToFloat32, Operator::kNoProperties, 1, 0, 1) \
V(TruncateInt64ToInt32, Operator::kNoProperties, 1, 0, 1) \ V(TruncateInt64ToInt32, Operator::kNoProperties, 1, 0, 1) \
V(BitcastFloat32ToInt32, Operator::kNoProperties, 1, 0, 1) \ V(BitcastFloat32ToInt32, Operator::kNoProperties, 1, 0, 1) \
......
...@@ -305,6 +305,16 @@ class MachineOperatorBuilder final : public ZoneObject { ...@@ -305,6 +305,16 @@ class MachineOperatorBuilder final : public ZoneObject {
const Operator* ChangeUint32ToFloat64(); const Operator* ChangeUint32ToFloat64();
const Operator* ChangeUint32ToUint64(); const Operator* ChangeUint32ToUint64();
// These are changes from impossible values (for example a smi-checked
// string). They can safely emit an abort instruction, which should
// never be reached.
const Operator* ImpossibleToWord32();
const Operator* ImpossibleToWord64();
const Operator* ImpossibleToFloat32();
const Operator* ImpossibleToFloat64();
const Operator* ImpossibleToTagged();
const Operator* ImpossibleToBit();
// These operators truncate or round numbers, both changing the representation // These operators truncate or round numbers, both changing the representation
// of the number and mapping multiple input values onto the same output value. // of the number and mapping multiple input values onto the same output value.
const Operator* TruncateFloat64ToFloat32(); const Operator* TruncateFloat64ToFloat32();
......
...@@ -693,6 +693,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -693,6 +693,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kArchDebugBreak: case kArchDebugBreak:
__ stop("kArchDebugBreak"); __ stop("kArchDebugBreak");
break; break;
case kArchImpossible:
__ Abort(kConversionFromImpossibleValue);
break;
case kArchComment: { case kArchComment: {
Address comment_string = i.InputExternalReference(0).address(); Address comment_string = i.InputExternalReference(0).address();
__ RecordComment(reinterpret_cast<const char*>(comment_string)); __ RecordComment(reinterpret_cast<const char*>(comment_string));
......
...@@ -702,6 +702,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -702,6 +702,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kArchDebugBreak: case kArchDebugBreak:
__ stop("kArchDebugBreak"); __ stop("kArchDebugBreak");
break; break;
case kArchImpossible:
__ Abort(kConversionFromImpossibleValue);
break;
case kArchComment: { case kArchComment: {
Address comment_string = i.InputExternalReference(0).address(); Address comment_string = i.InputExternalReference(0).address();
__ RecordComment(reinterpret_cast<const char*>(comment_string)); __ RecordComment(reinterpret_cast<const char*>(comment_string));
......
...@@ -378,6 +378,12 @@ ...@@ -378,6 +378,12 @@
V(ChangeInt32ToInt64) \ V(ChangeInt32ToInt64) \
V(ChangeUint32ToFloat64) \ V(ChangeUint32ToFloat64) \
V(ChangeUint32ToUint64) \ V(ChangeUint32ToUint64) \
V(ImpossibleToBit) \
V(ImpossibleToWord32) \
V(ImpossibleToWord64) \
V(ImpossibleToFloat32) \
V(ImpossibleToFloat64) \
V(ImpossibleToTagged) \
V(TruncateFloat64ToFloat32) \ V(TruncateFloat64ToFloat32) \
V(TruncateInt64ToInt32) \ V(TruncateInt64ToInt32) \
V(RoundFloat64ToInt32) \ V(RoundFloat64ToInt32) \
......
...@@ -1077,6 +1077,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -1077,6 +1077,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kArchDebugBreak: case kArchDebugBreak:
__ stop("kArchDebugBreak"); __ stop("kArchDebugBreak");
break; break;
case kArchImpossible:
__ Abort(kConversionFromImpossibleValue);
break;
case kArchNop: case kArchNop:
case kArchThrowTerminator: case kArchThrowTerminator:
// don't emit code for nops. // don't emit code for nops.
......
...@@ -117,8 +117,10 @@ bool IsWord(MachineRepresentation rep) { ...@@ -117,8 +117,10 @@ bool IsWord(MachineRepresentation rep) {
Node* RepresentationChanger::GetRepresentationFor( Node* RepresentationChanger::GetRepresentationFor(
Node* node, MachineRepresentation output_rep, Type* output_type, Node* node, MachineRepresentation output_rep, Type* output_type,
Node* use_node, UseInfo use_info) { Node* use_node, UseInfo use_info) {
if (output_rep == MachineRepresentation::kNone) { if (output_rep == MachineRepresentation::kNone &&
// The output representation should be set. output_type->IsInhabited()) {
// The output representation should be set if the type is inhabited (i.e.,
// if the value is possible).
return TypeError(node, output_rep, output_type, use_info.representation()); return TypeError(node, output_rep, output_type, use_info.representation());
} }
...@@ -200,7 +202,11 @@ Node* RepresentationChanger::GetTaggedRepresentationFor( ...@@ -200,7 +202,11 @@ Node* RepresentationChanger::GetTaggedRepresentationFor(
} }
// Select the correct X -> Tagged operator. // Select the correct X -> Tagged operator.
const Operator* op; const Operator* op;
if (output_rep == MachineRepresentation::kBit) { if (output_rep == MachineRepresentation::kNone) {
// We should only asisgn this representation if the type is empty.
CHECK(!output_type->IsInhabited());
op = machine()->ImpossibleToTagged();
} else if (output_rep == MachineRepresentation::kBit) {
if (output_type->Is(Type::Boolean())) { if (output_type->Is(Type::Boolean())) {
op = simplified()->ChangeBitToTagged(); op = simplified()->ChangeBitToTagged();
} else { } else {
...@@ -271,7 +277,11 @@ Node* RepresentationChanger::GetFloat32RepresentationFor( ...@@ -271,7 +277,11 @@ Node* RepresentationChanger::GetFloat32RepresentationFor(
} }
// Select the correct X -> Float32 operator. // Select the correct X -> Float32 operator.
const Operator* op = nullptr; const Operator* op = nullptr;
if (IsWord(output_rep)) { if (output_rep == MachineRepresentation::kNone) {
// We should only use kNone representation if the type is empty.
CHECK(!output_type->IsInhabited());
op = machine()->ImpossibleToFloat32();
} else if (IsWord(output_rep)) {
if (output_type->Is(Type::Signed32())) { if (output_type->Is(Type::Signed32())) {
// int32 -> float64 -> float32 // int32 -> float64 -> float32
op = machine()->ChangeInt32ToFloat64(); op = machine()->ChangeInt32ToFloat64();
...@@ -336,7 +346,11 @@ Node* RepresentationChanger::GetFloat64RepresentationFor( ...@@ -336,7 +346,11 @@ Node* RepresentationChanger::GetFloat64RepresentationFor(
} }
// Select the correct X -> Float64 operator. // Select the correct X -> Float64 operator.
const Operator* op = nullptr; const Operator* op = nullptr;
if (IsWord(output_rep)) { if (output_rep == MachineRepresentation::kNone) {
// We should only use kNone representation if the type is empty.
CHECK(!output_type->IsInhabited());
op = machine()->ImpossibleToFloat64();
} else if (IsWord(output_rep)) {
if (output_type->Is(Type::Signed32())) { if (output_type->Is(Type::Signed32())) {
op = machine()->ChangeInt32ToFloat64(); op = machine()->ChangeInt32ToFloat64();
} else if (output_type->Is(Type::Unsigned32()) || } else if (output_type->Is(Type::Unsigned32()) ||
...@@ -408,7 +422,11 @@ Node* RepresentationChanger::GetWord32RepresentationFor( ...@@ -408,7 +422,11 @@ Node* RepresentationChanger::GetWord32RepresentationFor(
// Select the correct X -> Word32 operator. // Select the correct X -> Word32 operator.
const Operator* op = nullptr; const Operator* op = nullptr;
if (output_rep == MachineRepresentation::kBit) { if (output_rep == MachineRepresentation::kNone) {
// We should only use kNone representation if the type is empty.
CHECK(!output_type->IsInhabited());
op = machine()->ImpossibleToWord32();
} else if (output_rep == MachineRepresentation::kBit) {
return node; // Sloppy comparison -> word32 return node; // Sloppy comparison -> word32
} else if (output_rep == MachineRepresentation::kFloat64) { } else if (output_rep == MachineRepresentation::kFloat64) {
if (output_type->Is(Type::Unsigned32())) { if (output_type->Is(Type::Unsigned32())) {
...@@ -497,7 +515,11 @@ Node* RepresentationChanger::GetBitRepresentationFor( ...@@ -497,7 +515,11 @@ Node* RepresentationChanger::GetBitRepresentationFor(
} }
// Select the correct X -> Bit operator. // Select the correct X -> Bit operator.
const Operator* op; const Operator* op;
if (output_rep == MachineRepresentation::kTagged) { if (output_rep == MachineRepresentation::kNone) {
// We should only use kNone representation if the type is empty.
CHECK(!output_type->IsInhabited());
op = machine()->ImpossibleToBit();
} else if (output_rep == MachineRepresentation::kTagged) {
op = simplified()->ChangeTaggedToBit(); op = simplified()->ChangeTaggedToBit();
} else { } else {
return TypeError(node, output_rep, output_type, return TypeError(node, output_rep, output_type,
...@@ -508,7 +530,11 @@ Node* RepresentationChanger::GetBitRepresentationFor( ...@@ -508,7 +530,11 @@ Node* RepresentationChanger::GetBitRepresentationFor(
Node* RepresentationChanger::GetWord64RepresentationFor( Node* RepresentationChanger::GetWord64RepresentationFor(
Node* node, MachineRepresentation output_rep, Type* output_type) { Node* node, MachineRepresentation output_rep, Type* output_type) {
if (output_rep == MachineRepresentation::kBit) { if (output_rep == MachineRepresentation::kNone) {
// We should only use kNone representation if the type is empty.
CHECK(!output_type->IsInhabited());
return jsgraph()->graph()->NewNode(machine()->ImpossibleToFloat64(), node);
} else if (output_rep == MachineRepresentation::kBit) {
return node; // Sloppy comparison -> word64 return node; // Sloppy comparison -> word64
} }
// Can't really convert Word64 to anything else. Purported to be internal. // Can't really convert Word64 to anything else. Purported to be internal.
...@@ -532,7 +558,11 @@ Node* RepresentationChanger::GetCheckedWord32RepresentationFor( ...@@ -532,7 +558,11 @@ Node* RepresentationChanger::GetCheckedWord32RepresentationFor(
// Select the correct X -> Word32 operator. // Select the correct X -> Word32 operator.
const Operator* op = nullptr; const Operator* op = nullptr;
if (output_rep == MachineRepresentation::kWord32) { if (output_rep == MachineRepresentation::kNone) {
// We should only use kNone representation if the type is empty.
CHECK(!output_type->IsInhabited());
op = machine()->ImpossibleToWord32();
} else if (output_rep == MachineRepresentation::kWord32) {
if (output_type->Is(Type::Unsigned32())) { if (output_type->Is(Type::Unsigned32())) {
op = simplified()->CheckedUint32ToInt32(); op = simplified()->CheckedUint32ToInt32();
} }
......
...@@ -913,6 +913,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -913,6 +913,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kArchDebugBreak: case kArchDebugBreak:
__ stop("kArchDebugBreak"); __ stop("kArchDebugBreak");
break; break;
case kArchImpossible:
__ Abort(kConversionFromImpossibleValue);
break;
case kArchNop: case kArchNop:
case kArchThrowTerminator: case kArchThrowTerminator:
// don't emit code for nops. // don't emit code for nops.
......
...@@ -568,7 +568,8 @@ class RepresentationSelector { ...@@ -568,7 +568,8 @@ class RepresentationSelector {
NodeInfo* info = GetInfo(node); NodeInfo* info = GetInfo(node);
queue_.pop(); queue_.pop();
info->set_visited(); info->set_visited();
TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic()); TRACE(" visit #%d: %s (trunc: %s)\n", node->id(), node->op()->mnemonic(),
info->truncation().description());
VisitNode(node, info->truncation(), nullptr); VisitNode(node, info->truncation(), nullptr);
TRACE(" ==> output "); TRACE(" ==> output ");
PrintOutputInfo(info); PrintOutputInfo(info);
...@@ -635,12 +636,12 @@ class RepresentationSelector { ...@@ -635,12 +636,12 @@ class RepresentationSelector {
info->set_queued(); info->set_queued();
nodes_.push_back(node); nodes_.push_back(node);
queue_.push(node); queue_.push(node);
TRACE(" initial: "); TRACE(" initial #%i: ", node->id());
info->AddUse(use_info); info->AddUse(use_info);
PrintTruncation(info->truncation()); PrintTruncation(info->truncation());
return; return;
} }
TRACE(" queue?: "); TRACE(" queue #%i?: ", node->id());
PrintTruncation(info->truncation()); PrintTruncation(info->truncation());
if (info->AddUse(use_info)) { if (info->AddUse(use_info)) {
// New usage information for the node is available. // New usage information for the node is available.
......
...@@ -2230,16 +2230,35 @@ Type* Typer::Visitor::TypeChangeInt32ToInt64(Node* node) { ...@@ -2230,16 +2230,35 @@ Type* Typer::Visitor::TypeChangeInt32ToInt64(Node* node) {
return Type::Internal(); return Type::Internal();
} }
Type* Typer::Visitor::TypeChangeUint32ToFloat64(Node* node) { Type* Typer::Visitor::TypeChangeUint32ToFloat64(Node* node) {
return Type::Intersect(Type::Unsigned32(), Type::UntaggedFloat64(), zone()); return Type::Intersect(Type::Unsigned32(), Type::UntaggedFloat64(), zone());
} }
Type* Typer::Visitor::TypeChangeUint32ToUint64(Node* node) { Type* Typer::Visitor::TypeChangeUint32ToUint64(Node* node) {
return Type::Internal(); return Type::Internal();
} }
Type* Typer::Visitor::TypeImpossibleToWord32(Node* node) {
return Type::None();
}
Type* Typer::Visitor::TypeImpossibleToWord64(Node* node) {
return Type::None();
}
Type* Typer::Visitor::TypeImpossibleToFloat32(Node* node) {
return Type::None();
}
Type* Typer::Visitor::TypeImpossibleToFloat64(Node* node) {
return Type::None();
}
Type* Typer::Visitor::TypeImpossibleToTagged(Node* node) {
return Type::None();
}
Type* Typer::Visitor::TypeImpossibleToBit(Node* node) { return Type::None(); }
Type* Typer::Visitor::TypeTruncateFloat64ToFloat32(Node* node) { Type* Typer::Visitor::TypeTruncateFloat64ToFloat32(Node* node) {
return Type::Intersect(Type::Number(), Type::UntaggedFloat32(), zone()); return Type::Intersect(Type::Number(), Type::UntaggedFloat32(), zone());
...@@ -2250,7 +2269,6 @@ Type* Typer::Visitor::TypeTruncateFloat64ToWord32(Node* node) { ...@@ -2250,7 +2269,6 @@ Type* Typer::Visitor::TypeTruncateFloat64ToWord32(Node* node) {
zone()); zone());
} }
Type* Typer::Visitor::TypeTruncateInt64ToInt32(Node* node) { Type* Typer::Visitor::TypeTruncateInt64ToInt32(Node* node) {
return Type::Intersect(Type::Signed32(), Type::UntaggedIntegral32(), zone()); return Type::Intersect(Type::Signed32(), Type::UntaggedIntegral32(), zone());
} }
......
...@@ -948,6 +948,13 @@ void Verifier::Visitor::Check(Node* node) { ...@@ -948,6 +948,13 @@ void Verifier::Visitor::Check(Node* node) {
// CheckUpperIs(node, to)); // CheckUpperIs(node, to));
break; break;
} }
case IrOpcode::kImpossibleToWord32:
case IrOpcode::kImpossibleToWord64:
case IrOpcode::kImpossibleToFloat32:
case IrOpcode::kImpossibleToFloat64:
case IrOpcode::kImpossibleToTagged:
case IrOpcode::kImpossibleToBit:
break;
case IrOpcode::kCheckBounds: case IrOpcode::kCheckBounds:
CheckValueInputIs(node, 0, Type::Any()); CheckValueInputIs(node, 0, Type::Any());
......
...@@ -851,6 +851,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -851,6 +851,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kArchDebugBreak: case kArchDebugBreak:
__ int3(); __ int3();
break; break;
case kArchImpossible:
__ Abort(kConversionFromImpossibleValue);
break;
case kArchNop: case kArchNop:
case kArchThrowTerminator: case kArchThrowTerminator:
// don't emit code for nops. // don't emit code for nops.
......
...@@ -704,6 +704,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -704,6 +704,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kArchDebugBreak: case kArchDebugBreak:
__ int3(); __ int3();
break; break;
case kArchImpossible:
__ Abort(kConversionFromImpossibleValue);
break;
case kArchNop: case kArchNop:
case kArchThrowTerminator: case kArchThrowTerminator:
// don't emit code for nops. // don't emit code for nops.
......
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
var global = 1;
global = 2;
function f() {
var o = { a : 1 };
global = "a";
for (var i = global; i < 2; i++) {
delete o[i];
}
}
f();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment