diff --git a/src/compiler/access-builder.cc b/src/compiler/access-builder.cc index 84d1d60d04..ea861aec67 100644 --- a/src/compiler/access-builder.cc +++ b/src/compiler/access-builder.cc @@ -1092,6 +1092,16 @@ ElementAccess AccessBuilder::ForTypedArrayElement(ExternalArrayType type, UNREACHABLE(); } +// static +ElementAccess AccessBuilder::ForJSForInCacheArrayElement(ForInMode mode) { + ElementAccess access = { + kTaggedBase, FixedArray::kHeaderSize, + (mode == ForInMode::kGeneric ? Type::String() + : Type::InternalizedString()), + MachineType::AnyTagged(), kFullWriteBarrier}; + return access; +} + // static FieldAccess AccessBuilder::ForHashTableBaseNumberOfElements() { FieldAccess access = { diff --git a/src/compiler/access-builder.h b/src/compiler/access-builder.h index 99ffde19c4..5fbada6f6f 100644 --- a/src/compiler/access-builder.h +++ b/src/compiler/access-builder.h @@ -6,6 +6,7 @@ #define V8_COMPILER_ACCESS_BUILDER_H_ #include "src/base/compiler-specific.h" +#include "src/compiler/js-operator.h" #include "src/compiler/simplified-operator.h" #include "src/compiler/write-barrier-kind.h" #include "src/objects/elements-kind.h" @@ -320,6 +321,9 @@ class V8_EXPORT_PRIVATE AccessBuilder final static ElementAccess ForTypedArrayElement(ExternalArrayType type, bool is_external); + // Provides access to the for-in cache array. + static ElementAccess ForJSForInCacheArrayElement(ForInMode mode); + // Provides access to HashTable fields. static FieldAccess ForHashTableBaseNumberOfElements(); static FieldAccess ForHashTableBaseNumberOfDeletedElement(); diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc index e17e6babe4..19ba4dc6e3 100644 --- a/src/compiler/js-typed-lowering.cc +++ b/src/compiler/js-typed-lowering.cc @@ -1873,16 +1873,17 @@ Reduction JSTypedLowering::ReduceJSForInNext(Node* node) { node->ReplaceInput(2, effect); node->ReplaceInput(3, control); node->TrimInputCount(4); - NodeProperties::ChangeOp( - node, - simplified()->LoadElement(AccessBuilder::ForFixedArrayElement())); - NodeProperties::SetType(node, Type::InternalizedString()); + ElementAccess access = + AccessBuilder::ForJSForInCacheArrayElement(n.Parameters().mode()); + NodeProperties::ChangeOp(node, simplified()->LoadElement(access)); + NodeProperties::SetType(node, access.type); break; } case ForInMode::kGeneric: { // Load the next {key} from the {cache_array}. Node* key = effect = graph()->NewNode( - simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()), + simplified()->LoadElement(AccessBuilder::ForJSForInCacheArrayElement( + n.Parameters().mode())), cache_array, index, effect, control); // Check if the expected map still matches that of the {receiver}. diff --git a/src/compiler/simplified-lowering-verifier.cc b/src/compiler/simplified-lowering-verifier.cc index 25f177883f..718c0e27bd 100644 --- a/src/compiler/simplified-lowering-verifier.cc +++ b/src/compiler/simplified-lowering-verifier.cc @@ -22,6 +22,23 @@ Truncation LeastGeneralTruncation(const Truncation& t1, const Truncation& t2, return LeastGeneralTruncation(LeastGeneralTruncation(t1, t2), t3); } +bool IsNonTruncatingMachineTypeFor(const MachineType& mt, const Type& type) { + if (type.IsNone()) return true; + // TODO(nicohartmann@): Add more cases here. + if (type.Is(Type::BigInt())) { + return mt.representation() == MachineRepresentation::kTaggedPointer || + mt.representation() == MachineRepresentation::kTagged; + } + switch (mt.representation()) { + case MachineRepresentation::kBit: + CHECK(mt.semantic() == MachineSemantic::kBool || + mt.semantic() == MachineSemantic::kAny); + return type.Is(Type::Boolean()); + default: + return true; + } +} + void SimplifiedLoweringVerifier::CheckType(Node* node, const Type& type) { CHECK(NodeProperties::IsTyped(node)); Type node_type = NodeProperties::GetType(node); @@ -70,6 +87,10 @@ Truncation SimplifiedLoweringVerifier::GeneralizeTruncation( case Truncation::TruncationKind::kAny: { return Truncation::Any(identify_zeros); } + case Truncation::TruncationKind::kBool: { + if (type.Is(Type::Boolean())) return Truncation::Any(); + return Truncation(Truncation::TruncationKind::kBool, identify_zeros); + } case Truncation::TruncationKind::kWord32: { if (type.Is(Type::Signed32OrMinusZero()) || type.Is(Type::Unsigned32OrMinusZero())) { @@ -99,12 +120,26 @@ Truncation SimplifiedLoweringVerifier::GeneralizeTruncation( void SimplifiedLoweringVerifier::VisitNode(Node* node, OperationTyper& op_typer) { switch (node->opcode()) { - case IrOpcode::kInt64Constant: { + case IrOpcode::kStart: + case IrOpcode::kIfTrue: + case IrOpcode::kIfFalse: + case IrOpcode::kMerge: + case IrOpcode::kEnd: + case IrOpcode::kEffectPhi: + case IrOpcode::kCheckpoint: + case IrOpcode::kFrameState: + case IrOpcode::kJSStackCheck: + break; + case IrOpcode::kInt32Constant: + case IrOpcode::kInt64Constant: + case IrOpcode::kFloat64Constant: { // Constants might be untyped, because they are cached in the graph and // used in different contexts such that no single type can be assigned. // Their type is provided by an introduced TypeGuard where necessary. break; } + case IrOpcode::kHeapConstant: + break; case IrOpcode::kCheckedFloat64ToInt32: { Type input_type = InputType(node, 0); DCHECK(input_type.Is(Type::Number())); @@ -121,6 +156,28 @@ void SimplifiedLoweringVerifier::VisitNode(Node* node, CheckAndSet(node, input_type, Truncation::Word32()); break; } + case IrOpcode::kCheckedTaggedToTaggedSigned: { + Type input_type = InputType(node, 0); + Type output_type = + Type::Intersect(input_type, Type::SignedSmall(), graph_zone()); + Truncation output_trunc = InputTruncation(node, 0); + CheckAndSet(node, output_type, output_trunc); + break; + } + case IrOpcode::kCheckedTaggedToTaggedPointer: + CheckAndSet(node, InputType(node, 0), InputTruncation(node, 0)); + break; + case IrOpcode::kTruncateTaggedToBit: { + Type input_type = InputType(node, 0); + Truncation input_trunc = InputTruncation(node, 0); + // Cannot have other truncation here, because identified values lead to + // different results when converted to bit. + CHECK(input_trunc == Truncation::Bool() || + input_trunc == Truncation::Any()); + Type output_type = op_typer.ToBoolean(input_type); + CheckAndSet(node, output_type, Truncation::Bool()); + break; + } case IrOpcode::kInt32Add: { Type output_type = op_typer.NumberAdd(InputType(node, 0), InputType(node, 1)); @@ -141,16 +198,21 @@ void SimplifiedLoweringVerifier::VisitNode(Node* node, CheckAndSet(node, output_type, output_trunc); break; } - case IrOpcode::kChangeInt31ToTaggedSigned: { - // ChangeInt31ToTaggedSigned is not truncating any values, so we can - // simply forward input. + case IrOpcode::kChangeInt31ToTaggedSigned: + case IrOpcode::kChangeInt32ToTagged: + case IrOpcode::kChangeFloat32ToFloat64: + case IrOpcode::kChangeInt32ToInt64: + case IrOpcode::kChangeUint32ToUint64: + case IrOpcode::kChangeUint64ToTagged: { + // These change operators do not truncate any values and can simply + // forward input type and truncation. CheckAndSet(node, InputType(node, 0), InputTruncation(node, 0)); break; } - case IrOpcode::kChangeInt32ToTagged: { - // ChangeInt32ToTagged is not truncating any values, so we can simply - // forward input. - CheckAndSet(node, InputType(node, 0), InputTruncation(node, 0)); + case IrOpcode::kChangeFloat64ToInt64: { + Truncation output_trunc = LeastGeneralTruncation(InputTruncation(node, 0), + Truncation::Word64()); + CheckAndSet(node, InputType(node, 0), output_trunc); break; } case IrOpcode::kInt64Add: { @@ -185,12 +247,6 @@ void SimplifiedLoweringVerifier::VisitNode(Node* node, CheckAndSet(node, output_type, output_trunc); break; } - case IrOpcode::kChangeInt32ToInt64: { - // ChangeInt32ToInt64 is not truncating any values, so we can simply - // forward input. - CheckAndSet(node, InputType(node, 0), InputTruncation(node, 0)); - break; - } case IrOpcode::kDeadValue: { CheckAndSet(node, Type::None(), Truncation::Any()); break; @@ -258,10 +314,295 @@ void SimplifiedLoweringVerifier::VisitNode(Node* node, SetTruncation(node, GeneralizeTruncation(output_trunc, output_type)); break; } - - default: - // TODO(nicohartmann): Support remaining operators. + case IrOpcode::kBranch: { + CHECK(InputType(node, 0).Is(Type::Boolean())); + CHECK_EQ(InputTruncation(node, 0), Truncation::Any()); break; + } + case IrOpcode::kTypedStateValues: { + const ZoneVector* machine_types = MachineTypesOf(node->op()); + for (int i = 0; i < static_cast(machine_types->size()); ++i) { + // Inputs must not be truncated. + CHECK_EQ(InputTruncation(node, i), Truncation::Any()); + CHECK(IsNonTruncatingMachineTypeFor(machine_types->at(i), + InputType(node, i))); + } + break; + } + case IrOpcode::kParameter: { + CHECK(NodeProperties::IsTyped(node)); + SetTruncation(node, Truncation::Any()); + break; + } + +#define CASE(code, ...) case IrOpcode::k##code: + // Control operators + CASE(Loop) + CASE(Switch) + CASE(IfSuccess) + CASE(IfException) + CASE(IfValue) + CASE(IfDefault) + CASE(Deoptimize) + CASE(DeoptimizeIf) + CASE(DeoptimizeUnless) + CASE(TrapIf) + CASE(TrapUnless) + CASE(TailCall) + CASE(Terminate) + CASE(Throw) + // Constant operators + CASE(TaggedIndexConstant) + CASE(Float32Constant) + CASE(ExternalConstant) + CASE(NumberConstant) + CASE(PointerConstant) + CASE(CompressedHeapConstant) + CASE(RelocatableInt32Constant) + CASE(RelocatableInt64Constant) + // Inner operators + CASE(Select) + CASE(Phi) + CASE(InductionVariablePhi) + CASE(BeginRegion) + CASE(FinishRegion) + CASE(StateValues) + CASE(ArgumentsElementsState) + CASE(ArgumentsLengthState) + CASE(ObjectState) + CASE(ObjectId) + CASE(TypedObjectState) + CASE(Call) + CASE(OsrValue) + CASE(LoopExit) + CASE(LoopExitValue) + CASE(LoopExitEffect) + CASE(Projection) + CASE(Retain) + CASE(MapGuard) + CASE(FoldConstant) + CASE(Unreachable) + CASE(Dead) + CASE(Plug) + CASE(StaticAssert) + // Simplified change operators + CASE(ChangeTaggedSignedToInt32) + CASE(ChangeTaggedToInt32) + CASE(ChangeTaggedToInt64) + CASE(ChangeTaggedToUint32) + CASE(ChangeTaggedToFloat64) + CASE(ChangeTaggedToTaggedSigned) + CASE(ChangeInt64ToTagged) + CASE(ChangeUint32ToTagged) + CASE(ChangeFloat64ToTagged) + CASE(ChangeFloat64ToTaggedPointer) + CASE(ChangeTaggedToBit) + CASE(ChangeBitToTagged) + CASE(ChangeInt64ToBigInt) + CASE(ChangeUint64ToBigInt) + CASE(TruncateTaggedToWord32) + CASE(TruncateTaggedToFloat64) + CASE(TruncateTaggedPointerToBit) + // Simplified checked operators + CASE(CheckedInt32Add) + CASE(CheckedInt32Sub) + CASE(CheckedInt32Div) + CASE(CheckedInt32Mod) + CASE(CheckedUint32Div) + CASE(CheckedUint32Mod) + CASE(CheckedInt32Mul) + CASE(CheckedInt32ToTaggedSigned) + CASE(CheckedInt64ToInt32) + CASE(CheckedInt64ToTaggedSigned) + CASE(CheckedUint32Bounds) + CASE(CheckedUint32ToInt32) + CASE(CheckedUint32ToTaggedSigned) + CASE(CheckedUint64Bounds) + CASE(CheckedUint64ToInt32) + CASE(CheckedUint64ToTaggedSigned) + CASE(CheckedFloat64ToInt64) + CASE(CheckedTaggedSignedToInt32) + CASE(CheckedTaggedToInt32) + CASE(CheckedTaggedToArrayIndex) + CASE(CheckedTruncateTaggedToWord32) + CASE(CheckedTaggedToFloat64) + CASE(CheckedTaggedToInt64) + SIMPLIFIED_COMPARE_BINOP_LIST(CASE) + SIMPLIFIED_NUMBER_BINOP_LIST(CASE) + SIMPLIFIED_BIGINT_BINOP_LIST(CASE) + SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(CASE) + SIMPLIFIED_NUMBER_UNOP_LIST(CASE) + // Simplified unary bigint operators + CASE(BigIntNegate) + SIMPLIFIED_SPECULATIVE_NUMBER_UNOP_LIST(CASE) + SIMPLIFIED_SPECULATIVE_BIGINT_UNOP_LIST(CASE) + SIMPLIFIED_SPECULATIVE_BIGINT_BINOP_LIST(CASE) + SIMPLIFIED_OTHER_OP_LIST(CASE) + MACHINE_COMPARE_BINOP_LIST(CASE) + MACHINE_UNOP_32_LIST(CASE) + // Binary 32bit machine operators + CASE(Word32And) + CASE(Word32Or) + CASE(Word32Xor) + CASE(Word32Shl) + CASE(Word32Shr) + CASE(Word32Sar) + CASE(Word32Rol) + CASE(Word32Ror) + CASE(Int32AddWithOverflow) + CASE(Int32SubWithOverflow) + CASE(Int32Mul) + CASE(Int32MulWithOverflow) + CASE(Int32MulHigh) + CASE(Int32Div) + CASE(Int32Mod) + CASE(Uint32Div) + CASE(Uint32Mod) + CASE(Uint32MulHigh) + // Binary 64bit machine operators + CASE(Word64And) + CASE(Word64Or) + CASE(Word64Xor) + CASE(Word64Shl) + CASE(Word64Shr) + CASE(Word64Sar) + CASE(Word64Rol) + CASE(Word64Ror) + CASE(Word64RolLowerable) + CASE(Word64RorLowerable) + CASE(Int64AddWithOverflow) + CASE(Int64Sub) + CASE(Int64SubWithOverflow) + CASE(Int64Mul) + CASE(Int64Div) + CASE(Int64Mod) + CASE(Uint64Div) + CASE(Uint64Mod) + MACHINE_FLOAT32_UNOP_LIST(CASE) + MACHINE_FLOAT32_BINOP_LIST(CASE) + MACHINE_FLOAT64_UNOP_LIST(CASE) + MACHINE_FLOAT64_BINOP_LIST(CASE) + MACHINE_ATOMIC_OP_LIST(CASE) + CASE(AbortCSADcheck) + CASE(DebugBreak) + CASE(Comment) + CASE(Load) + CASE(LoadImmutable) + CASE(Store) + CASE(StackSlot) + CASE(Word32Popcnt) + CASE(Word64Popcnt) + CASE(Word64Clz) + CASE(Word64Ctz) + CASE(Word64ClzLowerable) + CASE(Word64CtzLowerable) + CASE(Word64ReverseBits) + CASE(Word64ReverseBytes) + CASE(Simd128ReverseBytes) + CASE(Int64AbsWithOverflow) + CASE(BitcastTaggedToWord) + CASE(BitcastTaggedToWordForTagAndSmiBits) + CASE(BitcastWordToTagged) + CASE(BitcastWordToTaggedSigned) + CASE(TruncateFloat64ToWord32) + CASE(ChangeFloat64ToInt32) + CASE(ChangeFloat64ToUint32) + CASE(ChangeFloat64ToUint64) + CASE(Float64SilenceNaN) + CASE(TruncateFloat64ToInt64) + CASE(TruncateFloat64ToUint32) + CASE(TruncateFloat32ToInt32) + CASE(TruncateFloat32ToUint32) + CASE(TryTruncateFloat32ToInt64) + CASE(TryTruncateFloat64ToInt64) + CASE(TryTruncateFloat32ToUint64) + CASE(TryTruncateFloat64ToUint64) + CASE(ChangeInt32ToFloat64) + CASE(BitcastWord32ToWord64) + CASE(ChangeInt64ToFloat64) + CASE(ChangeUint32ToFloat64) + CASE(TruncateFloat64ToFloat32) + CASE(TruncateInt64ToInt32) + CASE(RoundFloat64ToInt32) + CASE(RoundInt32ToFloat32) + CASE(RoundInt64ToFloat32) + CASE(RoundInt64ToFloat64) + CASE(RoundUint32ToFloat32) + CASE(RoundUint64ToFloat32) + CASE(RoundUint64ToFloat64) + CASE(BitcastFloat32ToInt32) + CASE(BitcastFloat64ToInt64) + CASE(BitcastInt32ToFloat32) + CASE(BitcastInt64ToFloat64) + CASE(Float64ExtractLowWord32) + CASE(Float64ExtractHighWord32) + CASE(Float64InsertLowWord32) + CASE(Float64InsertHighWord32) + CASE(Word32Select) + CASE(Word64Select) + CASE(Float32Select) + CASE(Float64Select) + CASE(LoadStackCheckOffset) + CASE(LoadFramePointer) + CASE(LoadParentFramePointer) + CASE(UnalignedLoad) + CASE(UnalignedStore) + CASE(Int32PairAdd) + CASE(Int32PairSub) + CASE(Int32PairMul) + CASE(Word32PairShl) + CASE(Word32PairShr) + CASE(Word32PairSar) + CASE(ProtectedLoad) + CASE(ProtectedStore) + CASE(MemoryBarrier) + CASE(SignExtendWord8ToInt32) + CASE(SignExtendWord16ToInt32) + CASE(SignExtendWord8ToInt64) + CASE(SignExtendWord16ToInt64) + CASE(SignExtendWord32ToInt64) + CASE(StackPointerGreaterThan) + JS_SIMPLE_BINOP_LIST(CASE) + JS_SIMPLE_UNOP_LIST(CASE) + JS_OBJECT_OP_LIST(CASE) + JS_CONTEXT_OP_LIST(CASE) + JS_CALL_OP_LIST(CASE) + JS_CONSTRUCT_OP_LIST(CASE) + CASE(JSAsyncFunctionEnter) + CASE(JSAsyncFunctionReject) + CASE(JSAsyncFunctionResolve) + CASE(JSCallRuntime) + CASE(JSForInEnumerate) + CASE(JSForInNext) + CASE(JSForInPrepare) + CASE(JSGetIterator) + CASE(JSLoadMessage) + CASE(JSStoreMessage) + CASE(JSLoadModule) + CASE(JSStoreModule) + CASE(JSGetImportMeta) + CASE(JSGeneratorStore) + CASE(JSGeneratorRestoreContinuation) + CASE(JSGeneratorRestoreContext) + CASE(JSGeneratorRestoreRegister) + CASE(JSGeneratorRestoreInputOrDebugPos) + CASE(JSFulfillPromise) + CASE(JSPerformPromiseThen) + CASE(JSPromiseResolve) + CASE(JSRejectPromise) + CASE(JSResolvePromise) + CASE(JSObjectIsArray) + CASE(JSRegExpTest) + CASE(JSDebugger) { + // TODO(nicohartmann@): These operators might need to be supported. + break; + } + MACHINE_SIMD_OP_LIST(CASE) + IF_WASM(SIMPLIFIED_WASM_OP_LIST, CASE) { + // SIMD operators should not be in the graph, yet. + UNREACHABLE(); + } +#undef CASE } } diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc index 8be53e250a..817d830cbd 100644 --- a/src/compiler/simplified-lowering.cc +++ b/src/compiler/simplified-lowering.cc @@ -1317,11 +1317,12 @@ class RepresentationSelector { return MachineType(rep, MachineSemantic::kInt64); } MachineType machine_type(rep, DeoptValueSemanticOf(type)); - DCHECK(machine_type.representation() != MachineRepresentation::kWord32 || - machine_type.semantic() == MachineSemantic::kInt32 || - machine_type.semantic() == MachineSemantic::kUint32); - DCHECK(machine_type.representation() != MachineRepresentation::kBit || - type.Is(Type::Boolean())); + DCHECK_IMPLIES( + machine_type.representation() == MachineRepresentation::kWord32, + machine_type.semantic() == MachineSemantic::kInt32 || + machine_type.semantic() == MachineSemantic::kUint32); + DCHECK_IMPLIES(machine_type.representation() == MachineRepresentation::kBit, + type.Is(Type::Boolean())); return machine_type; }