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 {
V(kWrongArgumentCountForInvokeIntrinsic, \
"Wrong number of arguments for intrinsic") \
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,
enum BailoutReason {
......
......@@ -707,6 +707,9 @@ 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,6 +766,9 @@ 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,6 +637,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kArchDebugBreak:
__ int3();
break;
case kArchImpossible:
__ Abort(kConversionFromImpossibleValue);
break;
case kArchNop:
case kArchThrowTerminator:
// don't emit code for nops.
......
......@@ -57,6 +57,7 @@ enum class RecordWriteMode { kValueIsMap, kValueIsPointer, kValueIsAny };
V(ArchTableSwitch) \
V(ArchNop) \
V(ArchDebugBreak) \
V(ArchImpossible) \
V(ArchComment) \
V(ArchThrowTerminator) \
V(ArchDeoptimize) \
......
......@@ -242,6 +242,7 @@ int InstructionScheduler::GetInstructionFlags(const Instruction* instr) const {
case kArchTruncateDoubleToI:
case kArchStackSlot:
case kArchDebugBreak:
case kArchImpossible:
case kArchComment:
case kIeee754Float64Acos:
case kIeee754Float64Acosh:
......
......@@ -348,10 +348,6 @@ 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:
......@@ -364,13 +360,17 @@ InstructionOperand OperandForDeopt(OperandGenerator* g, Node* input,
UNREACHABLE();
break;
default:
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);
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);
}
}
}
UNREACHABLE();
......@@ -1065,6 +1065,19 @@ 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))) {
......@@ -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) {
OperandGenerator g(this);
Emit(kArchStackPointer, g.DefineAsRegister(node));
......
......@@ -145,6 +145,12 @@ 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,6 +302,16 @@ 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,6 +693,9 @@ 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,6 +702,9 @@ 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,6 +407,12 @@
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,6 +1077,9 @@ 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_type->IsInhabited()) {
// This is an impossible value; it should not be used at runtime.
// We just provide a dummy value here.
return jsgraph()->TheHoleConstant();
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())) {
op = simplified()->ChangeBitToTagged();
......@@ -283,10 +283,10 @@ Node* RepresentationChanger::GetFloat32RepresentationFor(
}
// Select the correct X -> Float32 operator.
const Operator* op = nullptr;
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);
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())) {
// int32 -> float64 -> float32
......@@ -352,10 +352,10 @@ Node* RepresentationChanger::GetFloat64RepresentationFor(
}
// Select the correct X -> Float64 operator.
const Operator* op = nullptr;
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);
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())) {
op = machine()->ChangeInt32ToFloat64();
......@@ -435,10 +435,10 @@ Node* RepresentationChanger::GetWord32RepresentationFor(
// Select the correct X -> Word32 operator.
const Operator* op = nullptr;
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);
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
} else if (output_rep == MachineRepresentation::kFloat64) {
......@@ -551,10 +551,10 @@ Node* RepresentationChanger::GetBitRepresentationFor(
}
// Select the correct X -> Bit operator.
const Operator* op;
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);
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();
} else {
......@@ -566,10 +566,10 @@ Node* RepresentationChanger::GetBitRepresentationFor(
Node* RepresentationChanger::GetWord64RepresentationFor(
Node* node, MachineRepresentation output_rep, Type* output_type) {
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);
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
}
......
......@@ -980,6 +980,9 @@ 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,9 +311,6 @@ 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()) {
......@@ -333,9 +330,6 @@ 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()) {
......@@ -540,6 +534,9 @@ 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");
}
}
......@@ -989,11 +986,8 @@ class RepresentationSelector {
for (int i = 0; i < node->InputCount(); i++) {
Node* input = node->InputAt(i);
NodeInfo* input_info = GetInfo(input);
Type* input_type = TypeOf(input);
MachineRepresentation rep = input_type->IsInhabited()
? input_info->representation()
: MachineRepresentation::kNone;
MachineType machine_type(rep, DeoptValueSemanticOf(input_type));
MachineType machine_type(input_info->representation(),
DeoptValueSemanticOf(TypeOf(input)));
DCHECK(machine_type.representation() !=
MachineRepresentation::kWord32 ||
machine_type.semantic() == MachineSemantic::kInt32 ||
......
......@@ -1980,6 +1980,28 @@ 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,6 +1003,14 @@ 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,6 +866,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kArchDebugBreak:
__ int3();
break;
case kArchImpossible:
__ Abort(kConversionFromImpossibleValue);
break;
case kArchNop:
case kArchThrowTerminator:
// don't emit code for nops.
......
......@@ -715,6 +715,9 @@ 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::Boolean(), MachineRepresentation::kBit);
Type::None(), MachineRepresentation::kBit);
CheckChange(IrOpcode::kChangeBitToTagged, MachineRepresentation::kBit,
Type::Boolean(), MachineRepresentation::kTagged);
Type::None(), 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::Number(),
MachineRepresentation::kFloat64, Type::None(),
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::Number(),
MachineRepresentation::kFloat32, Type::None(),
MachineRepresentation::kTagged);
CheckTwoChanges(IrOpcode::kChangeTaggedToFloat64,
IrOpcode::kTruncateFloat64ToFloat32,
MachineRepresentation::kTagged, Type::Number(),
MachineRepresentation::kTagged, Type::None(),
MachineRepresentation::kFloat32);
}
......@@ -587,7 +587,7 @@ TEST(SignednessInWord32) {
CheckChange(IrOpcode::kChangeTaggedToUint32, MachineRepresentation::kTagged,
Type::Unsigned32(), MachineRepresentation::kWord32);
CheckChange(IrOpcode::kChangeInt32ToFloat64, MachineRepresentation::kWord32,
Type::Signed32(), MachineRepresentation::kFloat64);
Type::None(), 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::Signed32(),
MachineRepresentation::kWord32, Type::None(),
MachineRepresentation::kFloat32);
CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
IrOpcode::kTruncateFloat64ToWord32,
......@@ -614,11 +614,13 @@ 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::Number(),
r.CheckNop(kMachineTypes[i].representation(), Type::None(),
kMachineTypes[i].representation());
}
// 32-bit floats.
r.CheckNop(MachineRepresentation::kFloat32, Type::None(),
MachineRepresentation::kFloat32);
r.CheckNop(MachineRepresentation::kFloat32, Type::Number(),
MachineRepresentation::kFloat32);
......@@ -637,6 +639,14 @@ 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(),
......@@ -652,39 +662,39 @@ TEST(TypeErrors) {
RepresentationChangerTester r;
// Wordish cannot be implicitly converted to/from comparison conditions.
r.CheckTypeError(MachineRepresentation::kWord8, Type::Number(),
r.CheckTypeError(MachineRepresentation::kWord8, Type::None(),
MachineRepresentation::kBit);
r.CheckTypeError(MachineRepresentation::kWord16, Type::Number(),
r.CheckTypeError(MachineRepresentation::kWord16, Type::None(),
MachineRepresentation::kBit);
r.CheckTypeError(MachineRepresentation::kWord32, Type::Number(),
r.CheckTypeError(MachineRepresentation::kWord32, Type::None(),
MachineRepresentation::kBit);
r.CheckTypeError(MachineRepresentation::kWord64, Type::Number(),
r.CheckTypeError(MachineRepresentation::kWord64, Type::None(),
MachineRepresentation::kBit);
// Floats cannot be implicitly converted to/from comparison conditions.
r.CheckTypeError(MachineRepresentation::kFloat64, Type::Number(),
r.CheckTypeError(MachineRepresentation::kFloat64, Type::None(),
MachineRepresentation::kBit);
// Floats cannot be implicitly converted to/from comparison conditions.
r.CheckTypeError(MachineRepresentation::kFloat32, Type::Number(),
r.CheckTypeError(MachineRepresentation::kFloat32, Type::None(),
MachineRepresentation::kBit);
r.CheckTypeError(MachineRepresentation::kBit, Type::Number(),
r.CheckTypeError(MachineRepresentation::kBit, Type::None(),
MachineRepresentation::kFloat32);
r.CheckTypeError(MachineRepresentation::kBit, Type::Boolean(),
MachineRepresentation::kFloat32);
// Word64 is internal and shouldn't be implicitly converted.
r.CheckTypeError(MachineRepresentation::kWord64, Type::Internal(),
r.CheckTypeError(MachineRepresentation::kWord64, Type::None(),
MachineRepresentation::kTagged);
r.CheckTypeError(MachineRepresentation::kTagged, Type::Number(),
r.CheckTypeError(MachineRepresentation::kTagged, Type::None(),
MachineRepresentation::kWord64);
r.CheckTypeError(MachineRepresentation::kTagged, Type::Boolean(),
MachineRepresentation::kWord64);
// Word64 / Word32 shouldn't be implicitly converted.
r.CheckTypeError(MachineRepresentation::kWord64, Type::Internal(),
r.CheckTypeError(MachineRepresentation::kWord64, Type::None(),
MachineRepresentation::kWord32);
r.CheckTypeError(MachineRepresentation::kWord32, Type::Number(),
r.CheckTypeError(MachineRepresentation::kWord32, Type::None(),
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