Commit a55fdb1e authored by bmeurer's avatar bmeurer Committed by Commit bot

Revert of [turbofan] Insert dummy values when changing from None type....

Revert of [turbofan] Insert dummy values when changing from None type. (patchset #5 id:80001 of https://codereview.chromium.org/2266823002/ )

Reason for revert:
Octane/Mandreel aborts with an exception now:

TypeError: __FUNCTION_TABLE__[(r2 >> 2)] is not a function

Original issue's description:
> [turbofan] Insert dummy values when changing from None type.
>
> Currently we choose the MachineRepresentation::kNone representation for
> values of Type::None, and when converting values from the kNone representation
> we use "impossible" conversions that will crash at runtime. This
> assumes that the impossible conversions should never be hit (the only
> way to produce the impossible values is to perform an always-failing
> runtime check on a value, such as Smi-checking a string). Note that
> this assumes that the runtime check is executed before the impossible
> convesrion.
>
> Introducing BitwiseOr type feedback broke this in two ways:
>
> - we always pick Word32 representation for bitwise-or, so the
>   impossible conversion does not trigger (it only triggers with
>   None representation), and we could end up with unsupported
>   conversions from Word32.
>
> - even if we inserted impossible conversions, they are pure conversions.
>   Since untagging, bitwise-or operations are also pure, we could hoist
>   all these before the smi check of the inputs and we could hit the
>   impossible conversions before we get to the smi check.
>
> This CL addresses this by just providing dummy values for conversions
> from the Type::None type. It also removes the impossible-to-* conversions.
>
> BUG=chromium:638132
>
> Committed: https://crrev.com/c83b21ab755f1420b6da85b3ff43d7e96ead9bbe
> Cr-Commit-Position: refs/heads/master@{#38883}

TBR=mstarzinger@chromium.org,jarin@chromium.org
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=chromium:638132

Review-Url: https://codereview.chromium.org/2280613002
Cr-Commit-Position: refs/heads/master@{#38893}
parent ba9367db
...@@ -267,7 +267,9 @@ namespace internal { ...@@ -267,7 +267,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 {
......
...@@ -707,6 +707,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -707,6 +707,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));
......
...@@ -637,6 +637,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -637,6 +637,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) \
......
...@@ -242,6 +242,7 @@ int InstructionScheduler::GetInstructionFlags(const Instruction* instr) const { ...@@ -242,6 +242,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:
......
...@@ -348,10 +348,6 @@ enum class FrameStateInputKind { kAny, kStackSlot }; ...@@ -348,10 +348,6 @@ enum class FrameStateInputKind { kAny, kStackSlot };
InstructionOperand OperandForDeopt(OperandGenerator* g, Node* input, InstructionOperand OperandForDeopt(OperandGenerator* g, Node* input,
FrameStateInputKind kind, FrameStateInputKind kind,
MachineRepresentation rep) { MachineRepresentation rep) {
if (rep == MachineRepresentation::kNone) {
return g->TempImmediate(FrameStateDescriptor::kImpossibleValue);
}
switch (input->opcode()) { switch (input->opcode()) {
case IrOpcode::kInt32Constant: case IrOpcode::kInt32Constant:
case IrOpcode::kInt64Constant: case IrOpcode::kInt64Constant:
...@@ -364,13 +360,17 @@ InstructionOperand OperandForDeopt(OperandGenerator* g, Node* input, ...@@ -364,13 +360,17 @@ 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) {
// Currently deopts "wrap" other operations, so the deopt's inputs case FrameStateInputKind::kStackSlot:
// are potentially needed untill the end of the deoptimising code. return g->UseUniqueSlot(input);
return g->UseAnyAtEnd(input); case FrameStateInputKind::kAny:
// Currently deopts "wrap" other operations, so the deopt's inputs
// are potentially needed untill the end of the deoptimising code.
return g->UseAnyAtEnd(input);
}
} }
} }
UNREACHABLE(); UNREACHABLE();
...@@ -1065,6 +1065,19 @@ void InstructionSelector::VisitNode(Node* node) { ...@@ -1065,6 +1065,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))) {
...@@ -1305,6 +1318,42 @@ void InstructionSelector::VisitNode(Node* node) { ...@@ -1305,6 +1318,42 @@ 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));
......
...@@ -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) \
......
...@@ -302,6 +302,16 @@ class MachineOperatorBuilder final : public ZoneObject { ...@@ -302,6 +302,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));
......
...@@ -407,6 +407,12 @@ ...@@ -407,6 +407,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.
......
...@@ -204,10 +204,10 @@ Node* RepresentationChanger::GetTaggedRepresentationFor( ...@@ -204,10 +204,10 @@ Node* RepresentationChanger::GetTaggedRepresentationFor(
} }
// Select the correct X -> Tagged operator. // Select the correct X -> Tagged operator.
const Operator* op; const Operator* op;
if (!output_type->IsInhabited()) { if (output_rep == MachineRepresentation::kNone) {
// This is an impossible value; it should not be used at runtime. // We should only asisgn this representation if the type is empty.
// We just provide a dummy value here. CHECK(!output_type->IsInhabited());
return jsgraph()->TheHoleConstant(); op = machine()->ImpossibleToTagged();
} else if (output_rep == MachineRepresentation::kBit) { } else if (output_rep == MachineRepresentation::kBit) {
if (output_type->Is(Type::Boolean())) { if (output_type->Is(Type::Boolean())) {
op = simplified()->ChangeBitToTagged(); op = simplified()->ChangeBitToTagged();
...@@ -283,10 +283,10 @@ Node* RepresentationChanger::GetFloat32RepresentationFor( ...@@ -283,10 +283,10 @@ Node* RepresentationChanger::GetFloat32RepresentationFor(
} }
// Select the correct X -> Float32 operator. // Select the correct X -> Float32 operator.
const Operator* op = nullptr; const Operator* op = nullptr;
if (!output_type->IsInhabited()) { if (output_rep == MachineRepresentation::kNone) {
// This is an impossible value; it should not be used at runtime. // We should only use kNone representation if the type is empty.
// We just provide a dummy value here. CHECK(!output_type->IsInhabited());
return jsgraph()->Float32Constant(0.0f); op = machine()->ImpossibleToFloat32();
} else if (IsWord(output_rep)) { } else if (IsWord(output_rep)) {
if (output_type->Is(Type::Signed32())) { if (output_type->Is(Type::Signed32())) {
// int32 -> float64 -> float32 // int32 -> float64 -> float32
...@@ -352,10 +352,10 @@ Node* RepresentationChanger::GetFloat64RepresentationFor( ...@@ -352,10 +352,10 @@ Node* RepresentationChanger::GetFloat64RepresentationFor(
} }
// Select the correct X -> Float64 operator. // Select the correct X -> Float64 operator.
const Operator* op = nullptr; const Operator* op = nullptr;
if (!output_type->IsInhabited()) { if (output_rep == MachineRepresentation::kNone) {
// This is an impossible value; it should not be used at runtime. // We should only use kNone representation if the type is empty.
// We just provide a dummy value here. CHECK(!output_type->IsInhabited());
return jsgraph()->Float64Constant(0.0); op = machine()->ImpossibleToFloat64();
} else if (IsWord(output_rep)) { } else if (IsWord(output_rep)) {
if (output_type->Is(Type::Signed32())) { if (output_type->Is(Type::Signed32())) {
op = machine()->ChangeInt32ToFloat64(); op = machine()->ChangeInt32ToFloat64();
...@@ -435,10 +435,10 @@ Node* RepresentationChanger::GetWord32RepresentationFor( ...@@ -435,10 +435,10 @@ 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_type->IsInhabited()) { if (output_rep == MachineRepresentation::kNone) {
// This is an impossible value; it should not be used at runtime. // We should only use kNone representation if the type is empty.
// We just provide a dummy value here. CHECK(!output_type->IsInhabited());
return jsgraph()->Int32Constant(0); op = machine()->ImpossibleToWord32();
} else if (output_rep == MachineRepresentation::kBit) { } 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) {
...@@ -551,10 +551,10 @@ Node* RepresentationChanger::GetBitRepresentationFor( ...@@ -551,10 +551,10 @@ Node* RepresentationChanger::GetBitRepresentationFor(
} }
// Select the correct X -> Bit operator. // Select the correct X -> Bit operator.
const Operator* op; const Operator* op;
if (!output_type->IsInhabited()) { if (output_rep == MachineRepresentation::kNone) {
// This is an impossible value; it should not be used at runtime. // We should only use kNone representation if the type is empty.
// We just provide a dummy value here. CHECK(!output_type->IsInhabited());
return jsgraph()->Int32Constant(0); op = machine()->ImpossibleToBit();
} else if (output_rep == MachineRepresentation::kTagged) { } else if (output_rep == MachineRepresentation::kTagged) {
op = simplified()->ChangeTaggedToBit(); op = simplified()->ChangeTaggedToBit();
} else { } else {
...@@ -566,10 +566,10 @@ Node* RepresentationChanger::GetBitRepresentationFor( ...@@ -566,10 +566,10 @@ 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_type->IsInhabited()) { if (output_rep == MachineRepresentation::kNone) {
// This is an impossible value; it should not be used at runtime. // We should only use kNone representation if the type is empty.
// We just provide a dummy value here. CHECK(!output_type->IsInhabited());
return jsgraph()->Int64Constant(0); return jsgraph()->graph()->NewNode(machine()->ImpossibleToFloat64(), node);
} else if (output_rep == MachineRepresentation::kBit) { } else if (output_rep == MachineRepresentation::kBit) {
return node; // Sloppy comparison -> word64 return node; // Sloppy comparison -> word64
} }
......
...@@ -980,6 +980,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -980,6 +980,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.
......
...@@ -311,9 +311,6 @@ class RepresentationSelector { ...@@ -311,9 +311,6 @@ class RepresentationSelector {
bool updated = UpdateFeedbackType(node); bool updated = UpdateFeedbackType(node);
TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic()); TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
VisitNode(node, info->truncation(), nullptr); VisitNode(node, info->truncation(), nullptr);
TRACE(" ==> output ");
PrintOutputInfo(info);
TRACE("\n");
if (updated) { if (updated) {
for (Node* const user : node->uses()) { for (Node* const user : node->uses()) {
if (GetInfo(user)->visited()) { if (GetInfo(user)->visited()) {
...@@ -333,9 +330,6 @@ class RepresentationSelector { ...@@ -333,9 +330,6 @@ class RepresentationSelector {
bool updated = UpdateFeedbackType(node); bool updated = UpdateFeedbackType(node);
TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic()); TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
VisitNode(node, info->truncation(), nullptr); VisitNode(node, info->truncation(), nullptr);
TRACE(" ==> output ");
PrintOutputInfo(info);
TRACE("\n");
if (updated) { if (updated) {
for (Node* const user : node->uses()) { for (Node* const user : node->uses()) {
if (GetInfo(user)->visited()) { if (GetInfo(user)->visited()) {
...@@ -540,6 +534,9 @@ class RepresentationSelector { ...@@ -540,6 +534,9 @@ class RepresentationSelector {
TRACE(" visit #%d: %s (trunc: %s)\n", node->id(), node->op()->mnemonic(), TRACE(" visit #%d: %s (trunc: %s)\n", node->id(), node->op()->mnemonic(),
info->truncation().description()); info->truncation().description());
VisitNode(node, info->truncation(), nullptr); VisitNode(node, info->truncation(), nullptr);
TRACE(" ==> output ");
PrintOutputInfo(info);
TRACE("\n");
} }
} }
...@@ -989,11 +986,8 @@ class RepresentationSelector { ...@@ -989,11 +986,8 @@ class RepresentationSelector {
for (int i = 0; i < node->InputCount(); i++) { for (int i = 0; i < node->InputCount(); i++) {
Node* input = node->InputAt(i); Node* input = node->InputAt(i);
NodeInfo* input_info = GetInfo(input); NodeInfo* input_info = GetInfo(input);
Type* input_type = TypeOf(input); MachineType machine_type(input_info->representation(),
MachineRepresentation rep = input_type->IsInhabited() DeoptValueSemanticOf(TypeOf(input)));
? input_info->representation()
: MachineRepresentation::kNone;
MachineType machine_type(rep, DeoptValueSemanticOf(input_type));
DCHECK(machine_type.representation() != DCHECK(machine_type.representation() !=
MachineRepresentation::kWord32 || MachineRepresentation::kWord32 ||
machine_type.semantic() == MachineSemantic::kInt32 || machine_type.semantic() == MachineSemantic::kInt32 ||
......
...@@ -1980,6 +1980,28 @@ Type* Typer::Visitor::TypeChangeUint32ToUint64(Node* node) { ...@@ -1980,6 +1980,28 @@ 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());
} }
......
...@@ -1003,6 +1003,14 @@ void Verifier::Visitor::Check(Node* node) { ...@@ -1003,6 +1003,14 @@ 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());
CheckValueInputIs(node, 1, Type::Unsigned31()); CheckValueInputIs(node, 1, Type::Unsigned31());
......
...@@ -866,6 +866,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -866,6 +866,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.
......
...@@ -715,6 +715,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -715,6 +715,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.
......
...@@ -493,9 +493,9 @@ static void CheckChange(IrOpcode::Value expected, MachineRepresentation from, ...@@ -493,9 +493,9 @@ static void CheckChange(IrOpcode::Value expected, MachineRepresentation from,
TEST(SingleChanges) { TEST(SingleChanges) {
CheckChange(IrOpcode::kChangeTaggedToBit, MachineRepresentation::kTagged, CheckChange(IrOpcode::kChangeTaggedToBit, MachineRepresentation::kTagged,
Type::Boolean(), MachineRepresentation::kBit); Type::None(), MachineRepresentation::kBit);
CheckChange(IrOpcode::kChangeBitToTagged, MachineRepresentation::kBit, CheckChange(IrOpcode::kChangeBitToTagged, MachineRepresentation::kBit,
Type::Boolean(), MachineRepresentation::kTagged); Type::None(), MachineRepresentation::kTagged);
CheckChange(IrOpcode::kChangeInt31ToTaggedSigned, CheckChange(IrOpcode::kChangeInt31ToTaggedSigned,
MachineRepresentation::kWord32, Type::Signed31(), MachineRepresentation::kWord32, Type::Signed31(),
...@@ -546,7 +546,7 @@ TEST(SingleChanges) { ...@@ -546,7 +546,7 @@ TEST(SingleChanges) {
Type::Unsigned32(), MachineRepresentation::kWord32); Type::Unsigned32(), MachineRepresentation::kWord32);
CheckChange(IrOpcode::kTruncateFloat64ToFloat32, CheckChange(IrOpcode::kTruncateFloat64ToFloat32,
MachineRepresentation::kFloat64, Type::Number(), MachineRepresentation::kFloat64, Type::None(),
MachineRepresentation::kFloat32); MachineRepresentation::kFloat32);
// Int32,Uint32 <-> Float32 require two changes. // Int32,Uint32 <-> Float32 require two changes.
...@@ -570,11 +570,11 @@ TEST(SingleChanges) { ...@@ -570,11 +570,11 @@ TEST(SingleChanges) {
// Float32 <-> Tagged require two changes. // Float32 <-> Tagged require two changes.
CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64, CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
IrOpcode::kChangeFloat64ToTagged, IrOpcode::kChangeFloat64ToTagged,
MachineRepresentation::kFloat32, Type::Number(), MachineRepresentation::kFloat32, Type::None(),
MachineRepresentation::kTagged); MachineRepresentation::kTagged);
CheckTwoChanges(IrOpcode::kChangeTaggedToFloat64, CheckTwoChanges(IrOpcode::kChangeTaggedToFloat64,
IrOpcode::kTruncateFloat64ToFloat32, IrOpcode::kTruncateFloat64ToFloat32,
MachineRepresentation::kTagged, Type::Number(), MachineRepresentation::kTagged, Type::None(),
MachineRepresentation::kFloat32); MachineRepresentation::kFloat32);
} }
...@@ -587,7 +587,7 @@ TEST(SignednessInWord32) { ...@@ -587,7 +587,7 @@ TEST(SignednessInWord32) {
CheckChange(IrOpcode::kChangeTaggedToUint32, MachineRepresentation::kTagged, CheckChange(IrOpcode::kChangeTaggedToUint32, MachineRepresentation::kTagged,
Type::Unsigned32(), MachineRepresentation::kWord32); Type::Unsigned32(), MachineRepresentation::kWord32);
CheckChange(IrOpcode::kChangeInt32ToFloat64, MachineRepresentation::kWord32, CheckChange(IrOpcode::kChangeInt32ToFloat64, MachineRepresentation::kWord32,
Type::Signed32(), MachineRepresentation::kFloat64); Type::None(), MachineRepresentation::kFloat64);
CheckChange(IrOpcode::kChangeFloat64ToInt32, MachineRepresentation::kFloat64, CheckChange(IrOpcode::kChangeFloat64ToInt32, MachineRepresentation::kFloat64,
Type::Signed32(), MachineRepresentation::kWord32); Type::Signed32(), MachineRepresentation::kWord32);
CheckChange(IrOpcode::kTruncateFloat64ToWord32, CheckChange(IrOpcode::kTruncateFloat64ToWord32,
...@@ -600,7 +600,7 @@ TEST(SignednessInWord32) { ...@@ -600,7 +600,7 @@ TEST(SignednessInWord32) {
CheckTwoChanges(IrOpcode::kChangeInt32ToFloat64, CheckTwoChanges(IrOpcode::kChangeInt32ToFloat64,
IrOpcode::kTruncateFloat64ToFloat32, IrOpcode::kTruncateFloat64ToFloat32,
MachineRepresentation::kWord32, Type::Signed32(), MachineRepresentation::kWord32, Type::None(),
MachineRepresentation::kFloat32); MachineRepresentation::kFloat32);
CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64, CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
IrOpcode::kTruncateFloat64ToWord32, IrOpcode::kTruncateFloat64ToWord32,
...@@ -614,11 +614,13 @@ TEST(Nops) { ...@@ -614,11 +614,13 @@ TEST(Nops) {
// X -> X is always a nop for any single representation X. // X -> X is always a nop for any single representation X.
for (size_t i = 0; i < arraysize(kMachineTypes); i++) { for (size_t i = 0; i < arraysize(kMachineTypes); i++) {
r.CheckNop(kMachineTypes[i].representation(), Type::Number(), r.CheckNop(kMachineTypes[i].representation(), Type::None(),
kMachineTypes[i].representation()); kMachineTypes[i].representation());
} }
// 32-bit floats. // 32-bit floats.
r.CheckNop(MachineRepresentation::kFloat32, Type::None(),
MachineRepresentation::kFloat32);
r.CheckNop(MachineRepresentation::kFloat32, Type::Number(), r.CheckNop(MachineRepresentation::kFloat32, Type::Number(),
MachineRepresentation::kFloat32); MachineRepresentation::kFloat32);
...@@ -637,6 +639,14 @@ TEST(Nops) { ...@@ -637,6 +639,14 @@ TEST(Nops) {
MachineRepresentation::kWord32); MachineRepresentation::kWord32);
// kRepBit (result of comparison) is implicitly a wordish thing. // kRepBit (result of comparison) is implicitly a wordish thing.
r.CheckNop(MachineRepresentation::kBit, Type::None(),
MachineRepresentation::kWord8);
r.CheckNop(MachineRepresentation::kBit, Type::None(),
MachineRepresentation::kWord16);
r.CheckNop(MachineRepresentation::kBit, Type::None(),
MachineRepresentation::kWord32);
r.CheckNop(MachineRepresentation::kBit, Type::None(),
MachineRepresentation::kWord64);
r.CheckNop(MachineRepresentation::kBit, Type::Boolean(), r.CheckNop(MachineRepresentation::kBit, Type::Boolean(),
MachineRepresentation::kWord8); MachineRepresentation::kWord8);
r.CheckNop(MachineRepresentation::kBit, Type::Boolean(), r.CheckNop(MachineRepresentation::kBit, Type::Boolean(),
...@@ -652,39 +662,39 @@ TEST(TypeErrors) { ...@@ -652,39 +662,39 @@ TEST(TypeErrors) {
RepresentationChangerTester r; RepresentationChangerTester r;
// Wordish cannot be implicitly converted to/from comparison conditions. // Wordish cannot be implicitly converted to/from comparison conditions.
r.CheckTypeError(MachineRepresentation::kWord8, Type::Number(), r.CheckTypeError(MachineRepresentation::kWord8, Type::None(),
MachineRepresentation::kBit); MachineRepresentation::kBit);
r.CheckTypeError(MachineRepresentation::kWord16, Type::Number(), r.CheckTypeError(MachineRepresentation::kWord16, Type::None(),
MachineRepresentation::kBit); MachineRepresentation::kBit);
r.CheckTypeError(MachineRepresentation::kWord32, Type::Number(), r.CheckTypeError(MachineRepresentation::kWord32, Type::None(),
MachineRepresentation::kBit); MachineRepresentation::kBit);
r.CheckTypeError(MachineRepresentation::kWord64, Type::Number(), r.CheckTypeError(MachineRepresentation::kWord64, Type::None(),
MachineRepresentation::kBit); MachineRepresentation::kBit);
// Floats cannot be implicitly converted to/from comparison conditions. // Floats cannot be implicitly converted to/from comparison conditions.
r.CheckTypeError(MachineRepresentation::kFloat64, Type::Number(), r.CheckTypeError(MachineRepresentation::kFloat64, Type::None(),
MachineRepresentation::kBit); MachineRepresentation::kBit);
// Floats cannot be implicitly converted to/from comparison conditions. // Floats cannot be implicitly converted to/from comparison conditions.
r.CheckTypeError(MachineRepresentation::kFloat32, Type::Number(), r.CheckTypeError(MachineRepresentation::kFloat32, Type::None(),
MachineRepresentation::kBit); MachineRepresentation::kBit);
r.CheckTypeError(MachineRepresentation::kBit, Type::Number(), r.CheckTypeError(MachineRepresentation::kBit, Type::None(),
MachineRepresentation::kFloat32); MachineRepresentation::kFloat32);
r.CheckTypeError(MachineRepresentation::kBit, Type::Boolean(), r.CheckTypeError(MachineRepresentation::kBit, Type::Boolean(),
MachineRepresentation::kFloat32); MachineRepresentation::kFloat32);
// Word64 is internal and shouldn't be implicitly converted. // Word64 is internal and shouldn't be implicitly converted.
r.CheckTypeError(MachineRepresentation::kWord64, Type::Internal(), r.CheckTypeError(MachineRepresentation::kWord64, Type::None(),
MachineRepresentation::kTagged); MachineRepresentation::kTagged);
r.CheckTypeError(MachineRepresentation::kTagged, Type::Number(), r.CheckTypeError(MachineRepresentation::kTagged, Type::None(),
MachineRepresentation::kWord64); MachineRepresentation::kWord64);
r.CheckTypeError(MachineRepresentation::kTagged, Type::Boolean(), r.CheckTypeError(MachineRepresentation::kTagged, Type::Boolean(),
MachineRepresentation::kWord64); MachineRepresentation::kWord64);
// Word64 / Word32 shouldn't be implicitly converted. // Word64 / Word32 shouldn't be implicitly converted.
r.CheckTypeError(MachineRepresentation::kWord64, Type::Internal(), r.CheckTypeError(MachineRepresentation::kWord64, Type::None(),
MachineRepresentation::kWord32); MachineRepresentation::kWord32);
r.CheckTypeError(MachineRepresentation::kWord32, Type::Number(), r.CheckTypeError(MachineRepresentation::kWord32, Type::None(),
MachineRepresentation::kWord64); MachineRepresentation::kWord64);
r.CheckTypeError(MachineRepresentation::kWord32, Type::Signed32(), r.CheckTypeError(MachineRepresentation::kWord32, Type::Signed32(),
MachineRepresentation::kWord64); MachineRepresentation::kWord64);
......
// 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.
// Flags: --allow-natives-syntax
function g(x, y) {
return x | y;
}
function f(b) {
if (b) {
var s = g("a", "b") && true;
return s;
}
}
// Prime function g with Smi feedback.
g(1, 2);
g(1, 2);
f(0);
f(0);
%OptimizeFunctionOnNextCall(f);
// Compile inlined function g with string inputs but Smi feedback.
f(1);
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