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

[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

Review-Url: https://codereview.chromium.org/2266823002
Cr-Commit-Position: refs/heads/master@{#38883}
parent 052ba98d
......@@ -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:
......
......@@ -350,6 +350,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:
......@@ -362,17 +366,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();
......@@ -1067,19 +1067,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))) {
......@@ -1320,42 +1307,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->IsInhabited()) {
// 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->IsInhabited()) {
// 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->IsInhabited()) {
// 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->IsInhabited()) {
// 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->IsInhabited()) {
// 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->IsInhabited()) {
// 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);
......
// 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