26 dependencies_(dependencies),
37 switch (node->opcode()) {
38 case IrOpcode::kConvertReceiver:
40 case IrOpcode::kMaybeGrowFastElements:
42 case IrOpcode::kCheckHeapObject:
44 case IrOpcode::kCheckBounds:
46 case IrOpcode::kCheckNotTaggedHole:
48 case IrOpcode::kCheckMaps:
50 case IrOpcode::kCheckNumber:
52 case IrOpcode::kCheckNumberFitsInt32:
54 case IrOpcode::kCheckString:
56 case IrOpcode::kCheckStringOrStringWrapper:
58 case IrOpcode::kCheckEqualsInternalizedString:
60 case IrOpcode::kCheckEqualsSymbol:
62 case IrOpcode::kLoadField:
64 case IrOpcode::kNumberCeil:
65 case IrOpcode::kNumberRound:
66 case IrOpcode::kNumberTrunc:
68 case IrOpcode::kNumberFloor:
70 case IrOpcode::kNumberSilenceNaN:
72 case IrOpcode::kNumberToUint8Clamped:
76 case IrOpcode::kReferenceEqual:
78 case IrOpcode::kStringEqual:
79 case IrOpcode::kStringLessThan:
80 case IrOpcode::kStringLessThanOrEqual:
82 case IrOpcode::kStringLength:
84 case IrOpcode::kSameValue:
86 case IrOpcode::kSelect:
88 case IrOpcode::kTypedArrayLength:
90 case IrOpcode::kTypeOf:
92 case IrOpcode::kToBoolean:
94 case IrOpcode::kSpeculativeToNumber:
96 case IrOpcode::kSpeculativeNumberAdd:
98 case IrOpcode::kSpeculativeNumberSubtract:
99 case IrOpcode::kSpeculativeNumberMultiply:
100 case IrOpcode::kSpeculativeNumberPow:
101 case IrOpcode::kSpeculativeNumberDivide:
102 case IrOpcode::kSpeculativeNumberModulus:
104 case IrOpcode::kSpeculativeNumberEqual:
105 case IrOpcode::kSpeculativeNumberLessThan:
106 case IrOpcode::kSpeculativeNumberLessThanOrEqual:
108 case IrOpcode::kTransitionElementsKindOrCheckMap:
123 if (object_map.
is_stable())
return object_map;
128Node* ResolveSameValueRenames(Node* node) {
130 switch (node->opcode()) {
131 case IrOpcode::kCheckHeapObject:
132 case IrOpcode::kCheckNumber:
133 case IrOpcode::kCheckNumberFitsInt32:
134 case IrOpcode::kCheckSmi:
135 case IrOpcode::kFinishRegion:
136 case IrOpcode::kTypeGuard:
137 if (node->IsDead()) {
140 node = node->InputAt(0);
155 if (value_type.
Is(Type::Receiver())) {
156 ReplaceWithValue(node, value);
157 return Replace(value);
158 }
else if (value_type.
Is(Type::NullOrUndefined())) {
159 ReplaceWithValue(node, global_proxy);
160 return Replace(global_proxy);
169 ReplaceWithValue(node, input);
170 return Replace(input);
184 CHECK(index_type.
Is(Type::Unsigned31()));
185 CHECK(length_type.
Is(Type::Unsigned31()));
188 index_type.
Max() < length_type.
Min()) {
189 if (
v8_flags.turbo_typer_hardening) {
194 ReplaceWithValue(node, elements, check_bounds);
195 return Replace(check_bounds);
197 RelaxEffectsAndControls(node);
198 return Replace(elements);
210 !input_type.
Maybe(Type::String()) &&
211 !input_type.
Maybe(Type::MinusZero())) {
217 return Changed(node);
225 if (!input_type.
Maybe(Type::Hole())) {
226 ReplaceWithValue(node, input);
227 return Replace(input);
240 if (object_map.has_value()) {
242 if (map.equals(*object_map)) {
243 if (object_map->CanTransition()) {
258 OptionalMapRef object_map = GetStableMapFromObjectType(
broker(), object_type);
261 return Replace(effect);
271 OptionalMapRef object_map = GetStableMapFromObjectType(
broker(), object_type);
276 return Replace(effect);
284 if (input_type.
Is(Type::Number())) {
285 ReplaceWithValue(node, input);
286 return Replace(input);
294 if (input_type.
Is(Type::Signed32())) {
295 ReplaceWithValue(node, input);
296 return Replace(input);
304 if (input_type.
Is(Type::String())) {
305 ReplaceWithValue(node, input);
306 return Replace(input);
314 if (input_type.
Is(Type::StringOrStringWrapper())) {
315 ReplaceWithValue(node, input);
316 return Replace(input);
327 if (val_type.
Is(exp_type))
return Replace(effect);
339 if (val_type.
Is(exp_type))
return Replace(effect);
354 OptionalMapRef object_map =
355 GetStableMapFromObjectType(
broker(), object_type);
356 if (object_map.has_value()) {
359 ReplaceWithValue(node, value);
360 return Replace(value);
370 return Replace(input);
372 if (input_type.
Is(Type::PlainNumber()) &&
373 (input->opcode() == IrOpcode::kNumberDivide ||
374 input->opcode() == IrOpcode::kSpeculativeNumberDivide)) {
379 if (lhs_type.
IsNone() || rhs_type.
IsNone())
return NoChange();
380 if (lhs_type.
Is(Type::Unsigned32()) && rhs_type.
Is(Type::Unsigned32())) {
395 return Replace(node);
405 return Replace(input);
413 if (input_type.
Is(Type::OrderedNumber())) {
414 return Replace(input);
423 return Replace(input);
432 DCHECK_EQ(IrOpcode::kPhi, node->opcode());
439 int arity = node->op()->ValueInputCount();
441 for (
int i = 1;
i < arity; ++
i) {
446 if (!node_type.
Is(type)) {
449 return Changed(node);
455 DCHECK_EQ(IrOpcode::kReferenceEqual, node->opcode());
460 if (!lhs_type.
Maybe(rhs_type)) {
465 return Replace(
jsgraph()->FalseConstant());
469 lhs_type.
Is(Type::Boolean())) {
470 std::optional<bool> maybe_result =
472 if (maybe_result.has_value()) {
473 if (maybe_result.value()) {
474 return Replace(node->InputAt(0));
476 node->TrimInputCount(1);
478 return Changed(node);
487 case IrOpcode::kStringEqual:
489 case IrOpcode::kStringLessThan:
491 case IrOpcode::kStringLessThanOrEqual:
502 switch (comparison->
opcode()) {
503 case IrOpcode::kStringEqual:
504 if (
string.
length() != 1) {
506 return Replace(
jsgraph()->BooleanConstant(
false));
509 case IrOpcode::kStringLessThan:
511 case IrOpcode::kStringLessThanOrEqual:
512 if (
string.
length() == 0) {
515 return Replace(
jsgraph()->BooleanConstant(inverted));
529 Node* comparison,
Node* from_char_code,
Type constant_type,
bool inverted) {
530 DCHECK_EQ(IrOpcode::kStringFromSingleCharCode, from_char_code->
opcode());
535 if (!constant.IsString())
return NoChange();
540 comparison,
string, inverted);
548 from_char_code_repl =
551 simplified()->NumberBitwiseAnd(), from_char_code_repl,
552 jsgraph()->ConstantNoHole(std::numeric_limits<uint16_t>::max()));
554 if (!
string.GetFirstChar(
broker()).has_value())
return NoChange();
555 Node* constant_repl =
558 Node* number_comparison =
nullptr;
561 if (
string.
length() > 1 &&
562 comparison->
opcode() == IrOpcode::kStringLessThanOrEqual) {
566 graph()->
NewNode(comparison_op, constant_repl, from_char_code_repl);
569 if (
string.
length() > 1 &&
570 comparison->
opcode() == IrOpcode::kStringLessThan) {
574 graph()->
NewNode(comparison_op, from_char_code_repl, constant_repl);
576 ReplaceWithValue(comparison, number_comparison);
577 return Replace(number_comparison);
581 DCHECK(IrOpcode::kStringEqual == node->opcode() ||
582 IrOpcode::kStringLessThan == node->opcode() ||
583 IrOpcode::kStringLessThanOrEqual == node->opcode());
588 if (lhs->
opcode() == IrOpcode::kStringFromSingleCharCode) {
589 if (rhs->
opcode() == IrOpcode::kStringFromSingleCharCode) {
599 jsgraph()->ConstantNoHole(std::numeric_limits<uint16_t>::max()));
606 jsgraph()->ConstantNoHole(std::numeric_limits<uint16_t>::max()));
610 ReplaceWithValue(node,
equal);
611 return Replace(
equal);
614 node, lhs, rhs_type,
false);
616 }
else if (rhs->
opcode() == IrOpcode::kStringFromSingleCharCode) {
624 DCHECK_EQ(IrOpcode::kStringLength, node->opcode());
626 switch (input->opcode()) {
627 case IrOpcode::kHeapConstant: {
630 if (
m.Ref(
broker()).IsString()) {
631 uint32_t
const length =
m.Ref(
broker()).AsString().length();
633 return Replace(value);
637 case IrOpcode::kStringConcat: {
639 return Replace(input->InputAt(0));
641 case IrOpcode::kStringFromSingleCharCode: {
644 return Replace(
jsgraph()->ConstantNoHole(1));
653 DCHECK_EQ(IrOpcode::kSameValue, node->opcode());
658 if (ResolveSameValueRenames(lhs) == ResolveSameValueRenames(rhs)) {
663 return Replace(
jsgraph()->TrueConstant());
664 }
else if (lhs_type.
Is(Type::Unique()) && rhs_type.
Is(Type::Unique())) {
667 return Changed(node);
668 }
else if (lhs_type.
Is(Type::String()) && rhs_type.
Is(Type::String())) {
671 return Changed(node);
672 }
else if (lhs_type.
Is(Type::MinusZero())) {
674 node->RemoveInput(0);
676 return Changed(node);
677 }
else if (rhs_type.
Is(Type::MinusZero())) {
679 node->RemoveInput(1);
681 return Changed(node);
682 }
else if (lhs_type.
Is(Type::NaN())) {
684 node->RemoveInput(0);
686 return Changed(node);
687 }
else if (rhs_type.
Is(Type::NaN())) {
689 node->RemoveInput(1);
691 return Changed(node);
692 }
else if (lhs_type.
Is(Type::PlainNumber()) &&
693 rhs_type.
Is(Type::PlainNumber())) {
696 return Changed(node);
702 DCHECK_EQ(IrOpcode::kSelect, node->opcode());
711 return Replace(vtrue);
715 return Replace(vfalse);
723 node->TrimInputCount(1);
725 return Changed(node);
731 if (!node_type.
Is(type)) {
734 return Changed(node);
740 DCHECK_EQ(IrOpcode::kSpeculativeToNumber, node->opcode());
743 if (input_type.
Is(Type::Number())) {
745 ReplaceWithValue(node, input);
746 return Replace(input);
754 if (type.Is(Type::Boolean())) {
757 }
else if (type.Is(Type::Number())) {
760 }
else if (type.Is(Type::String())) {
763 }
else if (type.Is(Type::BigInt())) {
766 }
else if (type.Is(Type::Symbol())) {
769 }
else if (type.Is(Type::OtherUndetectableOrUndefined())) {
772 }
else if (type.Is(Type::NonCallableOrNull())) {
775 }
else if (type.Is(Type::Function())) {
783 DCHECK_EQ(IrOpcode::kTypedArrayLength, node->opcode());
787 if (
m.HasResolvedValue() &&
m.Ref(
broker()).IsJSTypedArray()) {
794 return Replace(value);
803 if (input_type.
Is(Type::Boolean())) {
805 return Replace(input);
806 }
else if (input_type.
Is(Type::OrderedNumber())) {
808 node->ReplaceInput(0,
graph()->NewNode(
simplified()->NumberEqual(), input,
810 node->TrimInputCount(1);
812 return Changed(node);
813 }
else if (input_type.
Is(Type::Number())) {
815 node->TrimInputCount(1);
817 return Changed(node);
818 }
else if (input_type.
Is(Type::DetectableReceiverOrNull())) {
822 input,
jsgraph()->NullConstant()));
823 node->TrimInputCount(1);
825 return Changed(node);
826 }
else if (input_type.
Is(Type::ReceiverOrNullOrUndefined())) {
831 node->TrimInputCount(1);
833 return Changed(node);
834 }
else if (input_type.
Is(Type::String())) {
836 node->ReplaceInput(0,
838 jsgraph()->EmptyStringConstant()));
839 node->TrimInputCount(1);
841 return Changed(node);
850 return !t1.Maybe(t3) && !t2.Maybe(t3);
853const Operator* NumberOpFromSpeculativeNumberOp(
854 SimplifiedOperatorBuilder* simplified,
const Operator* op) {
855 switch (op->opcode()) {
856 case IrOpcode::kSpeculativeNumberEqual:
857 return simplified->NumberEqual();
858 case IrOpcode::kSpeculativeNumberLessThan:
859 return simplified->NumberLessThan();
860 case IrOpcode::kSpeculativeNumberLessThanOrEqual:
861 return simplified->NumberLessThanOrEqual();
862 case IrOpcode::kSpeculativeNumberAdd:
865 case IrOpcode::kSpeculativeNumberSubtract:
866 return simplified->NumberSubtract();
867 case IrOpcode::kSpeculativeNumberMultiply:
868 return simplified->NumberMultiply();
869 case IrOpcode::kSpeculativeNumberPow:
870 return simplified->NumberPow();
871 case IrOpcode::kSpeculativeNumberDivide:
872 return simplified->NumberDivide();
873 case IrOpcode::kSpeculativeNumberModulus:
874 return simplified->NumberModulus();
891 BothAre(lhs_type, rhs_type, Type::PlainPrimitive()) &&
892 NeitherCanBe(lhs_type, rhs_type, Type::StringOrReceiver())) {
899 ReplaceWithValue(node, value);
900 return Replace(value);
909 if (input_type.
Is(Type::String())) {
911 if (
m.HasResolvedValue() &&
m.Ref(
broker()).IsString()) {
914 if (!number.has_value())
return NoChange();
915 return Replace(
jsgraph()->ConstantNoHole(number.value()));
921 if (input_value.OddballToNumber(
broker()).To(&value)) {
922 return Replace(
jsgraph()->ConstantNoHole(value));
925 if (input_type.
Is(Type::Number())) {
927 return Changed(input);
929 if (input_type.
Is(Type::Undefined())) {
931 return Replace(
jsgraph()->NaNConstant());
933 if (input_type.
Is(Type::Null())) {
935 return Replace(
jsgraph()->ZeroConstant());
944 if (reduction.Changed())
return reduction.replacement();
959 BothAre(lhs_type, rhs_type, Type::NumberOrOddball())) {
966 NumberOpFromSpeculativeNumberOp(
simplified(), node->op()), toNum_lhs,
968 ReplaceWithValue(node, value);
969 return Replace(value);
979 if (BothAre(lhs_type, rhs_type, Type::Signed32()) ||
980 BothAre(lhs_type, rhs_type, Type::Unsigned32())) {
982 NumberOpFromSpeculativeNumberOp(
simplified(), node->op()), lhs, rhs);
983 ReplaceWithValue(node, value);
984 return Replace(value);
Flags without(flag_type flag) const
static constexpr int kMapOffset
v8::internal::Factory * factory()
CheckBoundsFlags flags() const
const CheckParameters & check_parameters() const
ZoneRefSet< Map > const & maps() const
void DependOnStableMap(MapRef map)
V8_EXPORT_PRIVATE MapRef map(JSHeapBroker *broker) const
SimplifiedOperatorBuilder * simplified() const
Isolate * isolate() const
Node * ConstantNoHole(ObjectRef ref, JSHeapBroker *broker)
ElementsKind elements_kind(JSHeapBroker *broker) const
size_t byte_length() const
static void ChangeOp(Node *node, const Operator *new_op)
static Type GetType(const Node *node)
static Node * GetEffectInput(Node *node, int index=0)
static Node * GetValueInput(Node *node, int index)
static void SetType(Node *node, Type type)
static Node * GetControlInput(Node *node, int index=0)
constexpr IrOpcode::Value opcode() const
const Operator * op() const
Node * InputAt(int index) const
constexpr Opcode opcode() const
const Operator * NumberLessThan()
const Operator * NumberEqual()
const Operator * NumberLessThanOrEqual()
std::optional< double > ToNumber(JSHeapBroker *broker)
Node * NewNode(const Operator *op, int input_count, Node *const *inputs, bool incomplete=false)
Type const kIntegerOrMinusZeroOrNaN
static Type Union(Type type1, Type type2, Zone *zone)
bool Maybe(Type that) const
bool IsHeapConstant() const
const HeapConstantType * AsHeapConstant() const
static Type SignedSmall()
static Type Intersect(Type type1, Type type2, Zone *zone)
Reduction ReducePhi(Node *node)
SimplifiedOperatorBuilder * simplified() const
Reduction ReduceMaybeGrowFastElements(Node *node)
Reduction ReduceNumberFloor(Node *node)
Reduction ReduceReferenceEqual(Node *node)
TypedOptimization(Editor *editor, CompilationDependencies *dependencies, JSGraph *jsgraph, JSHeapBroker *broker)
Reduction ReduceNumberToUint8Clamped(Node *node)
Reduction ReduceStringComparison(Node *node)
Reduction ReduceCheckNumber(Node *node)
Reduction ReduceSpeculativeToNumber(Node *node)
Reduction ReduceCheckBounds(Node *node)
Reduction ReduceConvertReceiver(Node *node)
Reduction ReduceSameValue(Node *node)
Node * ConvertPlainPrimitiveToNumber(Node *node)
Reduction ReduceStringLength(Node *node)
Reduction ReduceCheckString(Node *node)
JSHeapBroker * broker() const
Reduction ReduceNumberRoundop(Node *node)
Reduction ReduceTransitionElementsKindOrCheckMap(Node *node)
Reduction ReduceCheckNotTaggedHole(Node *node)
Reduction ReduceSelect(Node *node)
Reduction ReduceCheckStringOrStringWrapper(Node *node)
TypeCache const * type_cache_
Reduction ReduceTypedArrayLength(Node *node)
~TypedOptimization() override
Reduction ReduceCheckNumberFitsInt32(Node *node)
const Operator * NumberComparisonFor(const Operator *op)
JSGraph * jsgraph() const
Reduction ReduceCheckHeapObject(Node *node)
Reduction TryReduceStringComparisonOfStringFromSingleCharCode(Node *comparison, Node *from_char_code, Type constant_type, bool inverted)
CompilationDependencies * dependencies() const
Reduction ReduceToBoolean(Node *node)
Reduction ReduceTypeOf(Node *node)
Reduction ReduceCheckEqualsSymbol(Node *node)
Reduction Reduce(Node *node) final
Reduction ReduceSpeculativeNumberAdd(Node *node)
Reduction ReduceNumberSilenceNaN(Node *node)
Reduction ReduceSpeculativeNumberComparison(Node *node)
Reduction ReduceJSToNumberInput(Node *input)
Reduction TryReduceStringComparisonOfStringFromSingleCharCodeToConstant(Node *comparison, StringRef string, bool inverted)
Reduction ReduceLoadField(Node *node)
Factory * factory() const
Reduction ReduceSpeculativeNumberBinop(Node *node)
Reduction ReduceCheckEqualsInternalizedString(Node *node)
Reduction ReduceCheckMaps(Node *node)
JSHeapBroker *const broker_
V8_INLINE const Operation & Get(const Graph &graph, OpIndex index)
@ kConvertStringAndMinusZero
CheckMapsParameters const & CheckMapsParametersOf(Operator const *op)
NumberOperationHint NumberOperationHintOf(const Operator *op)
const FieldAccess & FieldAccessOf(const Operator *op)
CheckBoundsParameters const & CheckBoundsParametersOf(Operator const *op)
ElementsTransitionWithMultipleSources const & ElementsTransitionWithMultipleSourcesOf(const Operator *op)
bool IsNone(Tagged< FieldType > obj)
bool Is(IndirectHandle< U > value)
bool IsRabGsabTypedArrayElementsKind(ElementsKind kind)
constexpr int ElementsKindToShiftSize(ElementsKind elements_kind)
int32_t NumberToInt32(Tagged< Object > number)
V8_EXPORT_PRIVATE FlagValues v8_flags
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)