36 gasm_->inline_reductions_blocked_ =
true;
40 gasm_->inline_reductions_blocked_ =
false;
49 std::optional<NodeChangedCallback> node_changed_callback,
53 default_branch_semantics_(default_branch_semantics),
56 node_changed_callback_(node_changed_callback),
57 inline_reducers_(zone),
58 inline_reductions_blocked_(false),
60 mark_loop_exits_(mark_loop_exits) {
146#if V8_ENABLE_WEBASSEMBLY
147Node* GraphAssembler::LoadStackPointer() {
151Node* GraphAssembler::SetStackPointer(Node* node) {
162#define SINGLETON_CONST_DEF(Name, Type) \
163 TNode<Type> JSGraphAssembler::Name##Constant() { \
164 return TNode<Type>::UncheckedCast( \
165 AddClonedNode(jsgraph()->Name##Constant())); \
168#undef SINGLETON_CONST_DEF
170#define SINGLETON_CONST_TEST_DEF(Name, ...) \
171 TNode<Boolean> JSGraphAssembler::Is##Name(TNode<Object> value) { \
172 return TNode<Boolean>::UncheckedCast( \
173 ReferenceEqual(value, Name##Constant())); \
176#undef SINGLETON_CONST_TEST_DEF
178#define PURE_UNOP_DEF(Name) \
179 Node* GraphAssembler::Name(Node* input) { \
180 return AddNode(graph()->NewNode(machine()->Name(), input)); \
185#define PURE_BINOP_DEF(Name) \
186 Node* GraphAssembler::Name(Node* left, Node* right) { \
187 return AddNode(graph()->NewNode(machine()->Name(), left, right)); \
189#define PURE_BINOP_DEF_TNODE(Name, Result, Left, Right) \
190 TNode<Result> GraphAssembler::Name(SloppyTNode<Left> left, \
191 SloppyTNode<Right> right) { \
192 return AddNode<Result>(graph()->NewNode(machine()->Name(), left, right)); \
196#undef PURE_BINOP_DEF_TNODE
243#define CHECKED_BINOP_DEF(Name) \
244 Node* GraphAssembler::Name(Node* left, Node* right) { \
246 graph()->NewNode(machine()->Name(), left, right, control())); \
249#undef CHECKED_BINOP_DEF
252 return WordEqual(left, right);
257 return Word32Equal(left, right);
259 return WordEqual(left, right);
265 return BitcastWord32ToWord64(Int32Sub(left, right));
267 return IntSub(left, right);
273 return Int32LessThan(left, right);
275 return IntLessThan(left, right);
354Node* GraphAssembler::PackMapWord(
TNode<Map> map) {
356 Node* packed = WordXor(map_word,
IntPtrConstant(Internals::kMapWordXorMask));
365 return UnpackMapWord(map_word);
504 const char* file,
int line) {
511 const char* file,
int line) {
618 auto GsabFixedOrNormal = [&]() {
626 return GsabFixedOrNormal();
635 bitfield, a.Uint32Constant(JSArrayBufferView::kIsLengthTracking));
637 bitfield, a.Uint32Constant(JSArrayBufferView::kIsBackedByRab));
646 element_size = a.Uint32Constant(*size_opt);
651 TNode<Uint32T> elements_kind = a.LoadElementsKind(typed_array_map);
652 element_size = a.LookupByteSizeForElementsKind(elements_kind);
656 auto RabFixed = [&]() {
668 .MachineSelectIf<
UintPtrT>(a.UintPtrLessThanOrEqual(
669 a.UintPtrAdd(byte_offset, unchecked_byte_length),
670 underlying_byte_length))
671 .Then([&]() {
return unchecked_byte_length; })
672 .Else([&]() {
return a.UintPtrConstant(0); })
674 return a.UintPtrDiv(byte_length, a.ChangeUint32ToUintPtr(element_size));
678 auto RabTracking = [&]() {
687 a.UintPtrLessThanOrEqual(byte_offset, byte_length))
690 return a.UintPtrDiv(a.UintPtrSub(byte_length, byte_offset),
691 a.ChangeUint32ToUintPtr(element_size));
693 .Else([&]() {
return a.UintPtrConstant(0); })
699 auto GsabTracking = [&]() {
702 a.JSCallRuntime1(Runtime::kGrowableSharedArrayBufferByteLength,
712 a.UintPtrLessThanOrEqual(byte_offset, byte_length))
715 return a.UintPtrDiv(a.UintPtrSub(byte_length, byte_offset),
716 a.ChangeUint32ToUintPtr(element_size));
718 .Else([&]() {
return a.UintPtrConstant(0); })
723 return a.MachineSelectIf<
UintPtrT>(length_tracking_bit)
725 return a.MachineSelectIf<
UintPtrT>(backed_by_rab_bit)
731 return a.MachineSelectIf<
UintPtrT>(backed_by_rab_bit)
733 .Else(GsabFixedOrNormal)
745 auto GsabFixedOrNormal = [&]() {
754 return GsabFixedOrNormal();
763 bitfield, a.Uint32Constant(JSArrayBufferView::kIsLengthTracking));
765 bitfield, a.Uint32Constant(JSArrayBufferView::kIsBackedByRab));
772 auto RabFixed = [&]() {
783 .MachineSelectIf<
UintPtrT>(a.UintPtrLessThanOrEqual(
784 a.UintPtrAdd(byte_offset, unchecked_byte_length),
785 underlying_byte_length))
786 .Then([&]() {
return unchecked_byte_length; })
787 .Else([&]() {
return a.UintPtrConstant(0); })
793 constexpr uintptr_t all_bits =
static_cast<uintptr_t
>(-1);
794 if (*shift_opt == 0)
return byte_size;
796 a.WordAnd(byte_size, a.UintPtrConstant(all_bits << (*shift_opt))));
801 TNode<Uint32T> elements_kind = a.LoadElementsKind(typed_array_map);
803 a.LookupByteShiftForElementsKind(elements_kind);
805 a.WordShl(a.WordShr(byte_size, element_shift), element_shift));
809 auto RabTracking = [&]() {
818 a.UintPtrLessThanOrEqual(byte_offset, byte_length))
820 return RoundDownToElementSize(
821 a.UintPtrSub(byte_length, byte_offset));
823 .Else([&]() {
return a.UintPtrConstant(0); })
829 auto GsabTracking = [&]() {
832 a.JSCallRuntime1(Runtime::kGrowableSharedArrayBufferByteLength,
842 a.UintPtrLessThanOrEqual(byte_offset, byte_length))
844 return RoundDownToElementSize(
845 a.UintPtrSub(byte_length, byte_offset));
847 .Else([&]() {
return a.UintPtrConstant(0); })
852 return a.MachineSelectIf<
UintPtrT>(length_tracking_bit)
854 return a.MachineSelectIf<
UintPtrT>(backed_by_rab_bit)
860 return a.MachineSelectIf<
UintPtrT>(backed_by_rab_bit)
862 .Else(GsabFixedOrNormal)
889 bitfield, a.Uint32Constant(JSArrayBufferView::kIsLengthTracking));
891 bitfield, a.Uint32Constant(JSArrayBufferView::kIsBackedByRab));
893 auto RabLengthTracking = [&]() {
901 return a.Word32Or(detached_bit,
902 a.UintPtrLessThan(underlying_byte_length, byte_offset));
905 auto RabFixed = [&]() {
918 a.UintPtrLessThan(underlying_byte_length,
919 a.UintPtrAdd(byte_offset, unchecked_byte_length)));
923 return a.MachineSelectIf<
Word32T>(backed_by_rab_bit)
925 return a.MachineSelectIf<
Word32T>(length_tracking_bit)
926 .Then(RabLengthTracking)
930 .Else([&]() {
return detached_bit; })
935 template <
typename T>
949 std::set<ElementsKind> elements_kinds_candidates,
TNode<Context> context) {
951 std::move(elements_kinds_candidates));
963 return Word32And(bitfield,
976 std::set<ElementsKind> elements_kinds_candidates,
TNode<Context> context) {
978 std::move(elements_kinds_candidates));
986 std::set<ElementsKind> elements_kinds_candidates,
989 std::move(elements_kinds_candidates));
996 CheckIf(is_not_detached, DeoptimizeReason::kArrayBufferWasDetached, feedback);
1005 typed_array_and_rab_gsab_typed_array_elements_kind_shifts()));
1016 typed_array_and_rab_gsab_typed_array_elements_kind_sizes()));
1025 if (frame_state.has_value()) {
1089#ifdef V8_ENABLE_DIRECT_HANDLE
1095 Node* stack_slot =
StackSlot(
sizeof(uintptr_t),
alignof(uintptr_t),
true);
1138 machine()->UnalignedLoadSupported(type.representation()))
1228 int inputs_size,
Node** inputs) {
1229 return Call(
common()->
Call(call_descriptor), inputs_size, inputs);
1239 int inputs_size,
Node** inputs) {
1241 static constexpr int kTargetEffectControl = 3;
1247 inputs_size, inputs));
1278 (*node_changed_callback_)(
graph()->
end());
1297 reduction = reducer->Reduce(node,
nullptr);
1298 if (reduction.Changed())
break;
1300 if (reduction.Changed()) {
1301 Node* replacement = reduction.replacement();
1302 if (replacement != node) {
1312 if (node->opcode() == IrOpcode::kTerminate) {
#define Assert(condition)
static V8_EXPORT_PRIVATE Callable CallableFor(Isolate *isolate, Builtin builtin)
int GetStackParameterCount() const
CallInterfaceDescriptor descriptor() const
static V8_EXPORT_PRIVATE ExternalReference address_of_pending_message(LocalIsolate *local_isolate)
static ExternalReference Create(const SCTableReference &table_ref)
static constexpr int kMapOffset
static constexpr MachineType Float64()
static constexpr MachineType Uint8()
static constexpr MachineType TaggedPointer()
static constexpr MachineRepresentation PointerRepresentation()
static TNode UncheckedCast(compiler::Node *node)
static FieldAccess ForJSArrayBufferViewBuffer()
static FieldAccess ForJSArrayBufferViewByteLength()
static FieldAccess ForMap(WriteBarrierKind write_barrier=kMapWriteBarrier)
static FieldAccess ForJSArrayBufferViewByteOffset()
static FieldAccess ForJSArrayBufferByteLength()
static FieldAccess ForJSArrayBufferBitField()
static FieldAccess ForMapBitField2()
static FieldAccess ForJSTypedArrayLength()
static FieldAccess ForJSArrayBufferViewBitField()
std::set< ElementsKind > candidates_
TNode< Word32T > BuildDetachedOrOutOfBoundsCheck(TNode< JSArrayBufferView > view)
std::optional< int > TryComputeStaticElementSize()
TNode< T > MachineLoadField(FieldAccess const &access, TNode< HeapObject > object, const UseInfo &use_info)
JSGraphAssembler * assembler_
bool maybe_rab_gsab() const
TNode< UintPtrT > BuildByteLength(TNode< JSArrayBufferView > view, TNode< Context > context)
ArrayBufferViewAccessBuilder(JSGraphAssembler *assembler, InstanceType instance_type, std::set< ElementsKind > candidates)
std::optional< int > TryComputeStaticElementShift()
TNode< UintPtrT > BuildLength(TNode< JSArrayBufferView > view, TNode< Context > context)
InstanceType instance_type_
size_t ParameterCount() const
BlockInlineReduction(GraphAssembler *gasm)
Node * IsolateField(IsolateFieldId id)
virtual SimplifiedOperatorBuilder * simplified()
void ConnectUnreachableToEnd()
Node * BitcastTaggedToWord(Node *value)
void BranchImpl(BranchSemantics semantics, Node *condition, GraphAssemblerLabel< sizeof...(Vars)> *if_true, GraphAssemblerLabel< sizeof...(Vars)> *if_false, BranchHint hint, Vars...)
V8_INLINE void UpdateEffectControlWith(Node *node)
Node * BitcastWordToTaggedSigned(Node *value)
std::optional< NodeChangedCallback > node_changed_callback_
Node * BitcastMaybeObjectToWord(Node *value)
Node * Checkpoint(FrameState frame_state)
TNode< RawPtrT > StackSlot(int size, int alignment, bool is_tagged=false)
ZoneVector< Reducer * > inline_reducers_
Node * DeoptimizeIf(DeoptimizeReason reason, FeedbackSource const &feedback, Node *condition, Node *frame_state)
Node * LoadUnaligned(MachineType type, Node *object, Node *offset)
Node * Store(StoreRepresentation rep, Node *object, Node *offset, Node *value)
TNode< Uint32T > Uint32Constant(uint32_t value)
Node * IntPtrConstant(intptr_t value)
Node * TaggedEqual(Node *left, Node *right)
MachineGraph * mcgraph() const
Node * DeoptimizeIfNot(DeoptimizeReason reason, FeedbackSource const &feedback, Node *condition, Node *frame_state)
Node * ExternalConstant(ExternalReference ref)
TNode< UintPtrT > UintPtrAdd(TNode< UintPtrT > left, TNode< UintPtrT > right)
Node * TypeGuard(Type type, Node *value)
Node * LoadFramePointer()
Node * ProtectedStore(MachineRepresentation rep, Node *object, Node *offset, Node *value)
Node * SmiLessThan(Node *left, Node *right)
Node * Parameter(int index)
Node * BitcastTaggedToWordForTagAndSmiBits(Node *value)
Node * LoadHeapNumberValue(Node *heap_number)
MachineOperatorBuilder * machine() const
Node * IntPtrEqual(Node *left, Node *right)
TNode< UintPtrT > UintPtrConstant(uintptr_t value)
Node * LoadTrapOnNull(MachineType type, Node *object, Node *offset)
void RuntimeAbort(AbortReason reason)
Node * Float64RoundDown(Node *value)
TNode< UintPtrT > ChangeUint32ToUintPtr(SloppyTNode< Uint32T > value)
Node * Uint64Constant(uint64_t value)
Node * Int64Constant(int64_t value)
constexpr bool Is64() const
bool inline_reductions_blocked_
Node * ProtectedLoad(MachineType type, Node *object, Node *offset)
Node * AdaptLocalArgument(Node *argument)
void BranchWithCriticalSafetyCheck(Node *condition, GraphAssemblerLabel< 0u > *if_true, GraphAssemblerLabel< 0u > *if_false)
Node * Retain(Node *buffer)
V8_INLINE Node * AddClonedNode(Node *node)
virtual ~GraphAssembler()
Node * Projection(int index, Node *value, Node *ctrl=nullptr)
Node * UnreachableWithoutConnectToEnd()
TNode< UintPtrT > UintPtrDiv(TNode< UintPtrT > left, TNode< UintPtrT > right)
void InitializeEffectControl(Node *effect, Node *control)
TNode< BoolT > UintPtrLessThan(TNode< UintPtrT > left, TNode< UintPtrT > right)
TNode< Map > LoadMap(Node *object)
TNode< Object > Call(const CallDescriptor *call_descriptor, int inputs_size, Node **inputs)
Node * LoadRootRegister()
Node * StoreTrapOnNull(StoreRepresentation rep, Node *object, Node *offset, Node *value)
Node * UniqueIntPtrConstant(intptr_t value)
void TailCall(const CallDescriptor *call_descriptor, int inputs_size, Node **inputs)
BranchSemantics default_branch_semantics_
GraphAssembler(MachineGraph *jsgraph, Zone *zone, BranchSemantics default_branch_semantics, std::optional< NodeChangedCallback > node_changed_callback=std::nullopt, bool mark_loop_exits=false)
CommonOperatorBuilder * common() const
Node * BitcastWordToTagged(Node *value)
Node * Float64Constant(double value)
Node * IntPtrAdd(Node *a, Node *b)
TNode< UintPtrT > UintPtrSub(TNode< UintPtrT > left, TNode< UintPtrT > right)
Node * SmiSub(Node *left, Node *right)
Node * Load(MachineType type, Node *object, Node *offset)
Node * StoreUnaligned(MachineRepresentation rep, Node *object, Node *offset, Node *value)
Node * Int32Constant(int32_t value)
Node * AddNode(Node *node)
Node * IntPtrSub(Node *a, Node *b)
Node * TruncateFloat64ToInt64(Node *value, TruncateKind kind)
TNode< BoolT > UintPtrLessThanOrEqual(TNode< UintPtrT > left, TNode< UintPtrT > right)
Node * Float64RoundTruncate(Node *value)
TNode< Number > StringLength(TNode< String > string)
TNode< Map > LoadMap(TNode< HeapObject > object)
TNode< Number > ArrayBufferViewByteLength(TNode< JSArrayBufferView > array_buffer_view, InstanceType instance_type, std::set< ElementsKind > elements_kinds_candidates, TNode< Context > context)
TNode< Number > NumberConstant(double value)
TNode< Boolean > ObjectIsUndetectable(TNode< Object > value)
TNode< Number > NumberBitwiseOr(TNode< Number > lhs, TNode< Number > rhs)
Node * StoreField(FieldAccess const &, Node *object, Node *value)
Node * CheckSmi(Node *value, const FeedbackSource &feedback={})
TNode< Object > ConvertTaggedHoleToUndefined(TNode< Object > value)
Node * StringCharCodeAt(TNode< String > string, TNode< Number > position)
TNode< Number > NumberMax(TNode< Number > lhs, TNode< Number > rhs)
TNode< Object > DoubleArrayMin(TNode< JSArray > array)
Node * StoreElement(ElementAccess const &, Node *object, Node *index, Node *value)
Node * Allocate(AllocationType allocation, Node *size)
TNode< HeapObject > HeapConstant(Handle< HeapObject > object)
TNode< Object > JSCallRuntime2(Runtime::FunctionId function_id, TNode< Object > arg0, TNode< Object > arg1, TNode< Context > context, FrameState frame_state)
TNode< Object > MayThrow(const NodeGenerator0 &body)
TNode< FixedArrayBase > MaybeGrowFastElements(ElementsKind kind, const FeedbackSource &feedback, TNode< JSArray > array, TNode< FixedArrayBase > elements, TNode< Number > new_length, TNode< Number > old_length)
TNode< Word32T > ArrayBufferViewDetachedBit(TNode< JSArrayBufferView > array_buffer_view)
Operator const * PlainPrimitiveToNumberOperator()
TNode< T > ExitMachineGraph(TNode< U > input, MachineRepresentation output_representation, Type output_type)
TNode< Number > TypedArrayLength(TNode< JSTypedArray > typed_array, std::set< ElementsKind > elements_kinds_candidates, TNode< Context > context)
TNode< Boolean > NumberLessThan(TNode< Number > lhs, TNode< Number > rhs)
SetOncePointer< Operator const > to_number_operator_
TNode< Object > Constant(ObjectRef ref)
Node * CEntryStubConstant(int result_size)
Node * CheckNumberFitsInt32(Node *value, const FeedbackSource &feedback={})
TNode< Number > NumberBitwiseAnd(TNode< Number > lhs, TNode< Number > rhs)
TNode< Boolean > ToBoolean(TNode< Object > value)
TNode< Number > NumberShiftRightLogical(TNode< Number > lhs, TNode< Number > rhs)
Isolate * isolate() const
Node * CheckIf(Node *cond, DeoptimizeReason reason, const FeedbackSource &feedback={})
TNode< Number > NumberSubtract(TNode< Number > lhs, TNode< Number > rhs)
Node * CheckNumber(Node *value, const FeedbackSource &feedback={})
Node * Assert(Node *cond, const char *condition_string="", const char *file="", int line=-1)
TNode< Boolean > ReferenceEqual(TNode< Object > lhs, TNode< Object > rhs)
TNode< Uint32T > LookupByteSizeForElementsKind(TNode< Uint32T > elements_kind)
TNode< Object > JSCallRuntime1(Runtime::FunctionId function_id, TNode< Object > arg0, TNode< Context > context, std::optional< FrameState > frame_state, Operator::Properties properties=Operator::kNoProperties)
Node * ClearPendingMessage()
void TransitionAndStoreElement(MapRef double_map, MapRef fast_map, TNode< HeapObject > object, TNode< Number > index, TNode< Object > value)
TNode< Number > NumberAdd(TNode< Number > lhs, TNode< Number > rhs)
TNode< Number > NumberMin(TNode< Number > lhs, TNode< Number > rhs)
JSOperatorBuilder * javascript() const
TNode< T > EnterMachineGraph(TNode< U > input, UseInfo use_info)
JSGraph * jsgraph() const
void CheckIfTypedArrayWasDetachedOrOutOfBounds(TNode< JSTypedArray > typed_array, std::set< ElementsKind > elements_kinds_candidates, const FeedbackSource &feedback)
JSHeapBroker * broker() const
TNode< Boolean > ObjectIsSmi(TNode< Object > value)
TNode< Boolean > NumberLessThanOrEqual(TNode< Number > lhs, TNode< Number > rhs)
TNode< Number > PlainPrimitiveToNumber(TNode< Object > value)
TNode< String > StringSubstring(TNode< String > string, TNode< Number > from, TNode< Number > to)
TNode< Uint32T > LoadElementsKind(TNode< Map > map)
Node * LoadField(FieldAccess const &, Node *object)
Node * Chained(const Operator *op, Node *input)
TNode< Word32T > ArrayBufferDetachedBit(TNode< HeapObject > buffer)
TNode< Boolean > NumberEqual(TNode< Number > lhs, TNode< Number > rhs)
TNode< String > StringFromSingleCharCode(TNode< Number > code)
TNode< Uint32T > LookupByteShiftForElementsKind(TNode< Uint32T > elements_kind)
Node * BooleanNot(Node *cond)
TNode< Smi > SmiConstant(int32_t value)
TNode< Object > DoubleArrayMax(TNode< JSArray > array)
SimplifiedOperatorBuilder * simplified() override
TNode< Boolean > NumberIsFloat64Hole(TNode< Number > value)
TNode< Boolean > ObjectIsCallable(TNode< Object > value)
Node * LoadElement(ElementAccess const &, Node *object, Node *index)
static CallDescriptor * GetStubCallDescriptor(Zone *zone, const CallInterfaceDescriptor &descriptor, int stack_parameter_count, CallDescriptor::Flags flags, Operator::Properties properties=Operator::kNoProperties, StubCallMode stub_mode=StubCallMode::kCallCodeObject)
const Operator * Load(LoadRepresentation rep)
const Operator * UnalignedLoad(LoadRepresentation rep)
bool UnalignedStoreSupported(MachineRepresentation rep)
const Operator * UnalignedStore(UnalignedStoreRepresentation rep)
const Operator * Store(StoreRepresentation rep)
static void ReplaceUses(Node *node, Node *value, Node *effect=nullptr, Node *success=nullptr, Node *exception=nullptr)
static void MergeControlToEnd(TFGraph *graph, CommonOperatorBuilder *common, Node *node)
int ValueInputCount() const
constexpr Opcode opcode() const
Node * NewNode(const Operator *op, int input_count, Node *const *inputs, bool incomplete=false)
Type const kJSTypedArrayLengthType
static TypeCache const * Get()
Type const kJSArrayBufferViewByteLengthType
Type const kJSArrayBufferByteLengthType
static UseInfo TruncatingWord32()
#define COMPRESS_POINTERS_BOOL
ZoneVector< OpIndex > candidates
#define PURE_UNOP_DEF(Name)
#define PURE_BINOP_DEF(Name)
#define SINGLETON_CONST_TEST_DEF(Name,...)
#define PURE_BINOP_DEF_TNODE(Name, Result, Left, Right)
#define SINGLETON_CONST_DEF(Name, Type)
#define CHECKED_BINOP_DEF(Name)
#define PURE_ASSEMBLER_MACH_BINOP_LIST(V, T)
#define CHECKED_ASSEMBLER_MACH_BINOP_LIST(V)
#define PURE_ASSEMBLER_MACH_UNOP_LIST(V)
#define JSGRAPH_SINGLETON_CONSTANT_LIST(V)
ZoneVector< RpoNumber > & result
bool all_of(const C &container, const P &predicate)
HeapConstantNoHole(BUILTIN_CODE(isolate(), AllocateInOldGeneration))) DEFINE_GETTER(ArrayConstructorStubConstant
Map::Bits1::HasPrototypeSlotBit Map::Bits1::HasNamedInterceptorBit Map::Bits1::IsUndetectableBit Map::Bits1::IsConstructorBit bit_field2
bool IsRabGsabTypedArrayElementsKind(ElementsKind kind)
@ FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND
constexpr int kSystemPointerSize
constexpr int ElementsKindToShiftSize(ElementsKind elements_kind)
constexpr bool IsDoubleElementsKind(ElementsKind kind)
constexpr int ElementsKindToByteSize(ElementsKind elements_kind)
#define DCHECK_NOT_NULL(val)
#define DCHECK_NE(v1, v2)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)