Reland of [turbofan] Insert dummy values when changing from None type.
This reverts commit a55fdb1e7c
, relands
https://codereview.chromium.org/2266823002/.
BUG=chromium:638132
Review-Url: https://codereview.chromium.org/2277283002
Cr-Commit-Position: refs/heads/master@{#38917}
This commit is contained in:
parent
2101e691ca
commit
2a97b1bcb1
@ -267,9 +267,7 @@ namespace internal {
|
||||
V(kWrongArgumentCountForInvokeIntrinsic, \
|
||||
"Wrong number of arguments for intrinsic") \
|
||||
V(kShouldNotDirectlyEnterOsrFunction, \
|
||||
"Should not directly enter OSR-compiled function") \
|
||||
V(kConversionFromImpossibleValue, \
|
||||
"Reached conversion from value with empty type (i.e., impossible type)")
|
||||
"Should not directly enter OSR-compiled function")
|
||||
|
||||
#define ERROR_MESSAGES_CONSTANTS(C, T) C,
|
||||
enum BailoutReason {
|
||||
|
@ -707,9 +707,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
case kArchDebugBreak:
|
||||
__ stop("kArchDebugBreak");
|
||||
break;
|
||||
case kArchImpossible:
|
||||
__ Abort(kConversionFromImpossibleValue);
|
||||
break;
|
||||
case kArchComment: {
|
||||
Address comment_string = i.InputExternalReference(0).address();
|
||||
__ RecordComment(reinterpret_cast<const char*>(comment_string));
|
||||
|
@ -766,9 +766,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
case kArchDebugBreak:
|
||||
__ Debug("kArchDebugBreak", 0, BREAK);
|
||||
break;
|
||||
case kArchImpossible:
|
||||
__ Abort(kConversionFromImpossibleValue);
|
||||
break;
|
||||
case kArchComment: {
|
||||
Address comment_string = i.InputExternalReference(0).address();
|
||||
__ RecordComment(reinterpret_cast<const char*>(comment_string));
|
||||
|
@ -637,9 +637,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
case kArchDebugBreak:
|
||||
__ int3();
|
||||
break;
|
||||
case kArchImpossible:
|
||||
__ Abort(kConversionFromImpossibleValue);
|
||||
break;
|
||||
case kArchNop:
|
||||
case kArchThrowTerminator:
|
||||
// don't emit code for nops.
|
||||
|
@ -57,7 +57,6 @@ enum class RecordWriteMode { kValueIsMap, kValueIsPointer, kValueIsAny };
|
||||
V(ArchTableSwitch) \
|
||||
V(ArchNop) \
|
||||
V(ArchDebugBreak) \
|
||||
V(ArchImpossible) \
|
||||
V(ArchComment) \
|
||||
V(ArchThrowTerminator) \
|
||||
V(ArchDeoptimize) \
|
||||
|
@ -242,7 +242,6 @@ int InstructionScheduler::GetInstructionFlags(const Instruction* instr) const {
|
||||
case kArchTruncateDoubleToI:
|
||||
case kArchStackSlot:
|
||||
case kArchDebugBreak:
|
||||
case kArchImpossible:
|
||||
case kArchComment:
|
||||
case kIeee754Float64Acos:
|
||||
case kIeee754Float64Acosh:
|
||||
|
@ -348,6 +348,10 @@ enum class FrameStateInputKind { kAny, kStackSlot };
|
||||
InstructionOperand OperandForDeopt(OperandGenerator* g, Node* input,
|
||||
FrameStateInputKind kind,
|
||||
MachineRepresentation rep) {
|
||||
if (rep == MachineRepresentation::kNone) {
|
||||
return g->TempImmediate(FrameStateDescriptor::kImpossibleValue);
|
||||
}
|
||||
|
||||
switch (input->opcode()) {
|
||||
case IrOpcode::kInt32Constant:
|
||||
case IrOpcode::kInt64Constant:
|
||||
@ -360,17 +364,13 @@ InstructionOperand OperandForDeopt(OperandGenerator* g, Node* input,
|
||||
UNREACHABLE();
|
||||
break;
|
||||
default:
|
||||
if (rep == MachineRepresentation::kNone) {
|
||||
return g->TempImmediate(FrameStateDescriptor::kImpossibleValue);
|
||||
} else {
|
||||
switch (kind) {
|
||||
case FrameStateInputKind::kStackSlot:
|
||||
return g->UseUniqueSlot(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);
|
||||
}
|
||||
switch (kind) {
|
||||
case FrameStateInputKind::kStackSlot:
|
||||
return g->UseUniqueSlot(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();
|
||||
@ -1065,19 +1065,6 @@ void InstructionSelector::VisitNode(Node* node) {
|
||||
return MarkAsWord32(node), VisitChangeFloat64ToInt32(node);
|
||||
case IrOpcode::kChangeFloat64ToUint32:
|
||||
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:
|
||||
MarkAsFloat64(node);
|
||||
if (CanProduceSignalingNaN(node->InputAt(0))) {
|
||||
@ -1318,42 +1305,6 @@ 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) {
|
||||
OperandGenerator g(this);
|
||||
Emit(kArchStackPointer, g.DefineAsRegister(node));
|
||||
|
@ -145,12 +145,6 @@ MachineRepresentation AtomicStoreRepresentationOf(Operator const* op) {
|
||||
V(ChangeInt32ToInt64, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(ChangeUint32ToFloat64, 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(TruncateInt64ToInt32, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(BitcastFloat32ToInt32, Operator::kNoProperties, 1, 0, 1) \
|
||||
|
@ -302,16 +302,6 @@ class MachineOperatorBuilder final : public ZoneObject {
|
||||
const Operator* ChangeUint32ToFloat64();
|
||||
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
|
||||
// of the number and mapping multiple input values onto the same output value.
|
||||
const Operator* TruncateFloat64ToFloat32();
|
||||
|
@ -693,9 +693,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
case kArchDebugBreak:
|
||||
__ stop("kArchDebugBreak");
|
||||
break;
|
||||
case kArchImpossible:
|
||||
__ Abort(kConversionFromImpossibleValue);
|
||||
break;
|
||||
case kArchComment: {
|
||||
Address comment_string = i.InputExternalReference(0).address();
|
||||
__ RecordComment(reinterpret_cast<const char*>(comment_string));
|
||||
|
@ -702,9 +702,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
case kArchDebugBreak:
|
||||
__ stop("kArchDebugBreak");
|
||||
break;
|
||||
case kArchImpossible:
|
||||
__ Abort(kConversionFromImpossibleValue);
|
||||
break;
|
||||
case kArchComment: {
|
||||
Address comment_string = i.InputExternalReference(0).address();
|
||||
__ RecordComment(reinterpret_cast<const char*>(comment_string));
|
||||
|
@ -407,12 +407,6 @@
|
||||
V(ChangeInt32ToInt64) \
|
||||
V(ChangeUint32ToFloat64) \
|
||||
V(ChangeUint32ToUint64) \
|
||||
V(ImpossibleToBit) \
|
||||
V(ImpossibleToWord32) \
|
||||
V(ImpossibleToWord64) \
|
||||
V(ImpossibleToFloat32) \
|
||||
V(ImpossibleToFloat64) \
|
||||
V(ImpossibleToTagged) \
|
||||
V(TruncateFloat64ToFloat32) \
|
||||
V(TruncateInt64ToInt32) \
|
||||
V(RoundFloat64ToInt32) \
|
||||
|
@ -1077,9 +1077,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
case kArchDebugBreak:
|
||||
__ stop("kArchDebugBreak");
|
||||
break;
|
||||
case kArchImpossible:
|
||||
__ Abort(kConversionFromImpossibleValue);
|
||||
break;
|
||||
case kArchNop:
|
||||
case kArchThrowTerminator:
|
||||
// don't emit code for nops.
|
||||
|
@ -204,10 +204,10 @@ Node* RepresentationChanger::GetTaggedRepresentationFor(
|
||||
}
|
||||
// Select the correct X -> Tagged operator.
|
||||
const Operator* op;
|
||||
if (output_rep == MachineRepresentation::kNone) {
|
||||
// We should only asisgn this representation if the type is empty.
|
||||
CHECK(!output_type->IsInhabited());
|
||||
op = machine()->ImpossibleToTagged();
|
||||
if (output_type->Is(Type::None())) {
|
||||
// This is an impossible value; it should not be used at runtime.
|
||||
// We just provide a dummy value here.
|
||||
return jsgraph()->TheHoleConstant();
|
||||
} else if (output_rep == MachineRepresentation::kBit) {
|
||||
if (output_type->Is(Type::Boolean())) {
|
||||
op = simplified()->ChangeBitToTagged();
|
||||
@ -283,10 +283,10 @@ Node* RepresentationChanger::GetFloat32RepresentationFor(
|
||||
}
|
||||
// Select the correct X -> Float32 operator.
|
||||
const Operator* op = nullptr;
|
||||
if (output_rep == MachineRepresentation::kNone) {
|
||||
// We should only use kNone representation if the type is empty.
|
||||
CHECK(!output_type->IsInhabited());
|
||||
op = machine()->ImpossibleToFloat32();
|
||||
if (output_type->Is(Type::None())) {
|
||||
// This is an impossible value; it should not be used at runtime.
|
||||
// We just provide a dummy value here.
|
||||
return jsgraph()->Float32Constant(0.0f);
|
||||
} else if (IsWord(output_rep)) {
|
||||
if (output_type->Is(Type::Signed32())) {
|
||||
// int32 -> float64 -> float32
|
||||
@ -352,10 +352,10 @@ Node* RepresentationChanger::GetFloat64RepresentationFor(
|
||||
}
|
||||
// Select the correct X -> Float64 operator.
|
||||
const Operator* op = nullptr;
|
||||
if (output_rep == MachineRepresentation::kNone) {
|
||||
// We should only use kNone representation if the type is empty.
|
||||
CHECK(!output_type->IsInhabited());
|
||||
op = machine()->ImpossibleToFloat64();
|
||||
if (output_type->Is(Type::None())) {
|
||||
// This is an impossible value; it should not be used at runtime.
|
||||
// We just provide a dummy value here.
|
||||
return jsgraph()->Float64Constant(0.0);
|
||||
} else if (IsWord(output_rep)) {
|
||||
if (output_type->Is(Type::Signed32())) {
|
||||
op = machine()->ChangeInt32ToFloat64();
|
||||
@ -435,10 +435,10 @@ Node* RepresentationChanger::GetWord32RepresentationFor(
|
||||
|
||||
// Select the correct X -> Word32 operator.
|
||||
const Operator* op = nullptr;
|
||||
if (output_rep == MachineRepresentation::kNone) {
|
||||
// We should only use kNone representation if the type is empty.
|
||||
CHECK(!output_type->IsInhabited());
|
||||
op = machine()->ImpossibleToWord32();
|
||||
if (output_type->Is(Type::None())) {
|
||||
// This is an impossible value; it should not be used at runtime.
|
||||
// We just provide a dummy value here.
|
||||
return jsgraph()->Int32Constant(0);
|
||||
} else if (output_rep == MachineRepresentation::kBit) {
|
||||
return node; // Sloppy comparison -> word32
|
||||
} else if (output_rep == MachineRepresentation::kFloat64) {
|
||||
@ -551,10 +551,10 @@ Node* RepresentationChanger::GetBitRepresentationFor(
|
||||
}
|
||||
// Select the correct X -> Bit operator.
|
||||
const Operator* op;
|
||||
if (output_rep == MachineRepresentation::kNone) {
|
||||
// We should only use kNone representation if the type is empty.
|
||||
CHECK(!output_type->IsInhabited());
|
||||
op = machine()->ImpossibleToBit();
|
||||
if (output_type->Is(Type::None())) {
|
||||
// This is an impossible value; it should not be used at runtime.
|
||||
// We just provide a dummy value here.
|
||||
return jsgraph()->Int32Constant(0);
|
||||
} else if (output_rep == MachineRepresentation::kTagged) {
|
||||
op = simplified()->ChangeTaggedToBit();
|
||||
} else {
|
||||
@ -566,10 +566,10 @@ Node* RepresentationChanger::GetBitRepresentationFor(
|
||||
|
||||
Node* RepresentationChanger::GetWord64RepresentationFor(
|
||||
Node* node, MachineRepresentation output_rep, Type* output_type) {
|
||||
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);
|
||||
if (output_type->Is(Type::None())) {
|
||||
// This is an impossible value; it should not be used at runtime.
|
||||
// We just provide a dummy value here.
|
||||
return jsgraph()->Int64Constant(0);
|
||||
} else if (output_rep == MachineRepresentation::kBit) {
|
||||
return node; // Sloppy comparison -> word64
|
||||
}
|
||||
|
@ -980,9 +980,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
case kArchDebugBreak:
|
||||
__ stop("kArchDebugBreak");
|
||||
break;
|
||||
case kArchImpossible:
|
||||
__ Abort(kConversionFromImpossibleValue);
|
||||
break;
|
||||
case kArchNop:
|
||||
case kArchThrowTerminator:
|
||||
// don't emit code for nops.
|
||||
|
@ -311,6 +311,9 @@ class RepresentationSelector {
|
||||
bool updated = UpdateFeedbackType(node);
|
||||
TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
|
||||
VisitNode(node, info->truncation(), nullptr);
|
||||
TRACE(" ==> output ");
|
||||
PrintOutputInfo(info);
|
||||
TRACE("\n");
|
||||
if (updated) {
|
||||
for (Node* const user : node->uses()) {
|
||||
if (GetInfo(user)->visited()) {
|
||||
@ -330,6 +333,9 @@ class RepresentationSelector {
|
||||
bool updated = UpdateFeedbackType(node);
|
||||
TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
|
||||
VisitNode(node, info->truncation(), nullptr);
|
||||
TRACE(" ==> output ");
|
||||
PrintOutputInfo(info);
|
||||
TRACE("\n");
|
||||
if (updated) {
|
||||
for (Node* const user : node->uses()) {
|
||||
if (GetInfo(user)->visited()) {
|
||||
@ -534,9 +540,6 @@ class RepresentationSelector {
|
||||
TRACE(" visit #%d: %s (trunc: %s)\n", node->id(), node->op()->mnemonic(),
|
||||
info->truncation().description());
|
||||
VisitNode(node, info->truncation(), nullptr);
|
||||
TRACE(" ==> output ");
|
||||
PrintOutputInfo(info);
|
||||
TRACE("\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -986,8 +989,11 @@ class RepresentationSelector {
|
||||
for (int i = 0; i < node->InputCount(); i++) {
|
||||
Node* input = node->InputAt(i);
|
||||
NodeInfo* input_info = GetInfo(input);
|
||||
MachineType machine_type(input_info->representation(),
|
||||
DeoptValueSemanticOf(TypeOf(input)));
|
||||
Type* input_type = TypeOf(input);
|
||||
MachineRepresentation rep = input_type->IsInhabited()
|
||||
? input_info->representation()
|
||||
: MachineRepresentation::kNone;
|
||||
MachineType machine_type(rep, DeoptValueSemanticOf(input_type));
|
||||
DCHECK(machine_type.representation() !=
|
||||
MachineRepresentation::kWord32 ||
|
||||
machine_type.semantic() == MachineSemantic::kInt32 ||
|
||||
|
@ -1980,28 +1980,6 @@ Type* Typer::Visitor::TypeChangeUint32ToUint64(Node* node) {
|
||||
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) {
|
||||
return Type::Intersect(Type::Number(), Type::UntaggedFloat32(), zone());
|
||||
}
|
||||
|
@ -1003,14 +1003,6 @@ void Verifier::Visitor::Check(Node* node) {
|
||||
// CheckUpperIs(node, to));
|
||||
break;
|
||||
}
|
||||
case IrOpcode::kImpossibleToWord32:
|
||||
case IrOpcode::kImpossibleToWord64:
|
||||
case IrOpcode::kImpossibleToFloat32:
|
||||
case IrOpcode::kImpossibleToFloat64:
|
||||
case IrOpcode::kImpossibleToTagged:
|
||||
case IrOpcode::kImpossibleToBit:
|
||||
break;
|
||||
|
||||
case IrOpcode::kCheckBounds:
|
||||
CheckValueInputIs(node, 0, Type::Any());
|
||||
CheckValueInputIs(node, 1, Type::Unsigned31());
|
||||
|
@ -866,9 +866,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
case kArchDebugBreak:
|
||||
__ int3();
|
||||
break;
|
||||
case kArchImpossible:
|
||||
__ Abort(kConversionFromImpossibleValue);
|
||||
break;
|
||||
case kArchNop:
|
||||
case kArchThrowTerminator:
|
||||
// don't emit code for nops.
|
||||
|
@ -715,9 +715,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
case kArchDebugBreak:
|
||||
__ int3();
|
||||
break;
|
||||
case kArchImpossible:
|
||||
__ Abort(kConversionFromImpossibleValue);
|
||||
break;
|
||||
case kArchNop:
|
||||
case kArchThrowTerminator:
|
||||
// don't emit code for nops.
|
||||
|
@ -493,9 +493,9 @@ static void CheckChange(IrOpcode::Value expected, MachineRepresentation from,
|
||||
|
||||
TEST(SingleChanges) {
|
||||
CheckChange(IrOpcode::kChangeTaggedToBit, MachineRepresentation::kTagged,
|
||||
Type::None(), MachineRepresentation::kBit);
|
||||
Type::Boolean(), MachineRepresentation::kBit);
|
||||
CheckChange(IrOpcode::kChangeBitToTagged, MachineRepresentation::kBit,
|
||||
Type::None(), MachineRepresentation::kTagged);
|
||||
Type::Boolean(), MachineRepresentation::kTagged);
|
||||
|
||||
CheckChange(IrOpcode::kChangeInt31ToTaggedSigned,
|
||||
MachineRepresentation::kWord32, Type::Signed31(),
|
||||
@ -546,7 +546,7 @@ TEST(SingleChanges) {
|
||||
Type::Unsigned32(), MachineRepresentation::kWord32);
|
||||
|
||||
CheckChange(IrOpcode::kTruncateFloat64ToFloat32,
|
||||
MachineRepresentation::kFloat64, Type::None(),
|
||||
MachineRepresentation::kFloat64, Type::Number(),
|
||||
MachineRepresentation::kFloat32);
|
||||
|
||||
// Int32,Uint32 <-> Float32 require two changes.
|
||||
@ -570,11 +570,11 @@ TEST(SingleChanges) {
|
||||
// Float32 <-> Tagged require two changes.
|
||||
CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
|
||||
IrOpcode::kChangeFloat64ToTagged,
|
||||
MachineRepresentation::kFloat32, Type::None(),
|
||||
MachineRepresentation::kFloat32, Type::Number(),
|
||||
MachineRepresentation::kTagged);
|
||||
CheckTwoChanges(IrOpcode::kChangeTaggedToFloat64,
|
||||
IrOpcode::kTruncateFloat64ToFloat32,
|
||||
MachineRepresentation::kTagged, Type::None(),
|
||||
MachineRepresentation::kTagged, Type::Number(),
|
||||
MachineRepresentation::kFloat32);
|
||||
}
|
||||
|
||||
@ -587,7 +587,7 @@ TEST(SignednessInWord32) {
|
||||
CheckChange(IrOpcode::kChangeTaggedToUint32, MachineRepresentation::kTagged,
|
||||
Type::Unsigned32(), MachineRepresentation::kWord32);
|
||||
CheckChange(IrOpcode::kChangeInt32ToFloat64, MachineRepresentation::kWord32,
|
||||
Type::None(), MachineRepresentation::kFloat64);
|
||||
Type::Signed32(), MachineRepresentation::kFloat64);
|
||||
CheckChange(IrOpcode::kChangeFloat64ToInt32, MachineRepresentation::kFloat64,
|
||||
Type::Signed32(), MachineRepresentation::kWord32);
|
||||
CheckChange(IrOpcode::kTruncateFloat64ToWord32,
|
||||
@ -600,7 +600,7 @@ TEST(SignednessInWord32) {
|
||||
|
||||
CheckTwoChanges(IrOpcode::kChangeInt32ToFloat64,
|
||||
IrOpcode::kTruncateFloat64ToFloat32,
|
||||
MachineRepresentation::kWord32, Type::None(),
|
||||
MachineRepresentation::kWord32, Type::Signed32(),
|
||||
MachineRepresentation::kFloat32);
|
||||
CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
|
||||
IrOpcode::kTruncateFloat64ToWord32,
|
||||
@ -614,13 +614,11 @@ TEST(Nops) {
|
||||
|
||||
// X -> X is always a nop for any single representation X.
|
||||
for (size_t i = 0; i < arraysize(kMachineTypes); i++) {
|
||||
r.CheckNop(kMachineTypes[i].representation(), Type::None(),
|
||||
r.CheckNop(kMachineTypes[i].representation(), Type::Number(),
|
||||
kMachineTypes[i].representation());
|
||||
}
|
||||
|
||||
// 32-bit floats.
|
||||
r.CheckNop(MachineRepresentation::kFloat32, Type::None(),
|
||||
MachineRepresentation::kFloat32);
|
||||
r.CheckNop(MachineRepresentation::kFloat32, Type::Number(),
|
||||
MachineRepresentation::kFloat32);
|
||||
|
||||
@ -639,14 +637,6 @@ TEST(Nops) {
|
||||
MachineRepresentation::kWord32);
|
||||
|
||||
// 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(),
|
||||
MachineRepresentation::kWord8);
|
||||
r.CheckNop(MachineRepresentation::kBit, Type::Boolean(),
|
||||
@ -662,39 +652,39 @@ TEST(TypeErrors) {
|
||||
RepresentationChangerTester r;
|
||||
|
||||
// Wordish cannot be implicitly converted to/from comparison conditions.
|
||||
r.CheckTypeError(MachineRepresentation::kWord8, Type::None(),
|
||||
r.CheckTypeError(MachineRepresentation::kWord8, Type::Number(),
|
||||
MachineRepresentation::kBit);
|
||||
r.CheckTypeError(MachineRepresentation::kWord16, Type::None(),
|
||||
r.CheckTypeError(MachineRepresentation::kWord16, Type::Number(),
|
||||
MachineRepresentation::kBit);
|
||||
r.CheckTypeError(MachineRepresentation::kWord32, Type::None(),
|
||||
r.CheckTypeError(MachineRepresentation::kWord32, Type::Number(),
|
||||
MachineRepresentation::kBit);
|
||||
r.CheckTypeError(MachineRepresentation::kWord64, Type::None(),
|
||||
r.CheckTypeError(MachineRepresentation::kWord64, Type::Number(),
|
||||
MachineRepresentation::kBit);
|
||||
|
||||
// Floats cannot be implicitly converted to/from comparison conditions.
|
||||
r.CheckTypeError(MachineRepresentation::kFloat64, Type::None(),
|
||||
r.CheckTypeError(MachineRepresentation::kFloat64, Type::Number(),
|
||||
MachineRepresentation::kBit);
|
||||
|
||||
// Floats cannot be implicitly converted to/from comparison conditions.
|
||||
r.CheckTypeError(MachineRepresentation::kFloat32, Type::None(),
|
||||
r.CheckTypeError(MachineRepresentation::kFloat32, Type::Number(),
|
||||
MachineRepresentation::kBit);
|
||||
r.CheckTypeError(MachineRepresentation::kBit, Type::None(),
|
||||
r.CheckTypeError(MachineRepresentation::kBit, Type::Number(),
|
||||
MachineRepresentation::kFloat32);
|
||||
r.CheckTypeError(MachineRepresentation::kBit, Type::Boolean(),
|
||||
MachineRepresentation::kFloat32);
|
||||
|
||||
// Word64 is internal and shouldn't be implicitly converted.
|
||||
r.CheckTypeError(MachineRepresentation::kWord64, Type::None(),
|
||||
r.CheckTypeError(MachineRepresentation::kWord64, Type::Internal(),
|
||||
MachineRepresentation::kTagged);
|
||||
r.CheckTypeError(MachineRepresentation::kTagged, Type::None(),
|
||||
r.CheckTypeError(MachineRepresentation::kTagged, Type::Number(),
|
||||
MachineRepresentation::kWord64);
|
||||
r.CheckTypeError(MachineRepresentation::kTagged, Type::Boolean(),
|
||||
MachineRepresentation::kWord64);
|
||||
|
||||
// Word64 / Word32 shouldn't be implicitly converted.
|
||||
r.CheckTypeError(MachineRepresentation::kWord64, Type::None(),
|
||||
r.CheckTypeError(MachineRepresentation::kWord64, Type::Internal(),
|
||||
MachineRepresentation::kWord32);
|
||||
r.CheckTypeError(MachineRepresentation::kWord32, Type::None(),
|
||||
r.CheckTypeError(MachineRepresentation::kWord32, Type::Number(),
|
||||
MachineRepresentation::kWord64);
|
||||
r.CheckTypeError(MachineRepresentation::kWord32, Type::Signed32(),
|
||||
MachineRepresentation::kWord64);
|
||||
|
26
test/mjsunit/compiler/regress-638132.js
Normal file
26
test/mjsunit/compiler/regress-638132.js
Normal file
@ -0,0 +1,26 @@
|
||||
// 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);
|
Loading…
Reference in New Issue
Block a user