15#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(FFI_UNIT_TESTS)
19#if !defined(FFI_UNIT_TESTS)
67 switch (representation_) {
91 return representation_ ==
kFloat || representation_ ==
kDouble ||
96 return representation_ ==
kVoid;
101 switch (representation_) {
155 const auto alignment =
198 intptr_t member_packing) {
201 const intptr_t kAtLeast1ByteAligned = 1;
204 intptr_t alignment_field = kAtLeast1ByteAligned;
207 intptr_t alignment_stack = kAtLeast1ByteAligned;
208 intptr_t alignment_stack_vararg = kAtLeast1ByteAligned;
209#if (defined(DART_TARGET_OS_MACOS_IOS) || defined(DART_TARGET_OS_MACOS)) && \
210 defined(TARGET_ARCH_ARM64)
232 const intptr_t member_align_field =
235 if (member_align_stack > member_packing &&
242 alignment_field =
Utils::Maximum(alignment_field, member_align_field);
243 alignment_stack =
Utils::Maximum(alignment_stack, member_align_stack);
244 alignment_stack_vararg =
251 alignment_stack, alignment_stack_vararg);
260 const intptr_t kAtLeast1ByteAligned = 1;
263 intptr_t alignment_field = kAtLeast1ByteAligned;
266 intptr_t alignment_stack = kAtLeast1ByteAligned;
274 alignment_field =
Utils::Maximum(alignment_field, member_align_field);
275 alignment_stack =
Utils::Maximum(alignment_stack, member_align_stack);
283#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(FFI_UNIT_TESTS)
285 switch (representation_) {
315 switch (representation_) {
319 return kUnboxedUint8;
321 return kUnboxedInt16;
323 return kUnboxedUint16;
325 return kUnboxedInt32;
327 return kUnboxedUint32;
330 return kUnboxedInt64;
332 return kUnboxedFloat;
334 return kUnboxedDouble;
347 return other.
AsPrimitive().representation_ == representation_;
354 return other.
AsArray().length_ == length_ &&
362 const auto& other_compound = other.
AsCompound();
363 const auto& other_members = other_compound.
members_;
397 intptr_t index)
const {
398 ASSERT(index == 0 || index == 1);
442#if !defined(FFI_UNIT_TESTS)
446 const char**
error) {
447 const auto& struct_layout = pragma;
448 const auto& clazz =
Class::Handle(zone, struct_layout.clazz());
450 .Equals(Symbols::FfiStructLayout()));
451 const auto& struct_layout_fields =
Array::Handle(zone, clazz.fields());
452 ASSERT(struct_layout_fields.Length() == 2);
453 const auto& types_field =
456 .Equals(Symbols::FfiFieldTypes()));
457 const auto& field_types =
459 const auto& packed_field =
462 .Equals(Symbols::FfiFieldPacking()));
465 const intptr_t member_packing =
466 packed_value.IsNull() ?
kMaxInt32 : packed_value.AsInt64Value();
471 zone, field_types.Length());
472 for (intptr_t
i = 0;
i < field_types.Length();
i++) {
473 field_instance ^= field_types.
At(
i);
474 if (field_instance.IsAbstractType()) {
476 field_type ^= field_types.At(
i);
477 const auto& field_native_type =
479 if (*
error !=
nullptr) {
482 field_native_types.Add(field_native_type);
485 const auto& struct_layout_array_class =
488 .Equals(Symbols::FfiStructLayoutArray()));
489 const auto& struct_layout_array_fields =
491 ASSERT(struct_layout_array_fields.Length() == 2);
492 const auto& element_type_field =
495 .Equals(Symbols::FfiElementType()));
496 field_type ^= field_instance.GetField(element_type_field);
497 const auto& length_field =
500 .Equals(Symbols::Length()));
502 zone,
Smi::RawCast(field_instance.GetField(length_field)));
503 const auto element_type =
505 if (*
error !=
nullptr) {
508 const auto field_native_type =
510 field_native_types.Add(field_native_type);
524 const Class& abi_specific_int,
525 const char**
error) {
528 ASSERT(fields.Length() == 1);
529 const auto& native_types_field =
532 .Equals(Symbols::FfiNativeTypes()));
533 const auto& native_types =
537 const int64_t abi_index =
static_cast<int64_t
>(
TargetAbi());
540 if (abi_abstract_type.IsNull()) {
542 "AbiSpecificInteger '%s' is missing mapping for '%s'.",
551 const char**
error) {
559 const auto& superClass =
Class::Handle(zone, cls.SuperClass());
560 const bool is_struct =
String::Handle(zone, superClass.UserVisibleName())
561 .Equals(Symbols::Struct());
562 const bool is_union =
String::Handle(zone, superClass.UserVisibleName())
564 const bool is_abi_specific_int =
566 .Equals(Symbols::AbiSpecificInteger());
571 if (is_struct || is_union) {
572 pragma_name = Symbols::vm_ffi_struct_fields().
ptr();
574 ASSERT(is_abi_specific_int);
575 pragma_name = Symbols::vm_ffi_abi_specific_mapping().
ptr();
578 pragma_name,
true, &pragmas);
579 ASSERT(!pragmas.IsNull());
580 ASSERT(pragmas.IsGrowableObjectArray());
581 const auto& pragmas_array = GrowableObjectArray::Cast(pragmas);
586 if (is_struct || is_union) {
587 class_symbol = Symbols::FfiStructLayout().
ptr();
589 ASSERT(is_abi_specific_int);
590 class_symbol = Symbols::FfiAbiSpecificMapping().
ptr();
592 for (intptr_t
i = 0;
i < pragmas_array.Length();
i++) {
593 pragma ^= pragmas_array.At(
i);
594 clazz ^= pragma.clazz();
595 library ^= clazz.library();
596 if (
String::Handle(zone, clazz.UserVisibleName()).Equals(class_symbol) &&
602 if (is_struct || is_union) {
605 ASSERT(is_abi_specific_int);
610#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(FFI_UNIT_TESTS)
629 FATAL(
"Unhandled representation %u", rep);
645 zone, argument_representations.
length());
646 for (intptr_t
i = 0;
i < argument_representations.
length();
i++) {
648 zone, argument_representations.
At(
i)));
659 return textBuffer.
buffer();
662#if !defined(FFI_UNIT_TESTS)
691 return "half-double";
730 return textBuffer.
buffer();
736 f->AddString(
"Array(");
737 f->Printf(
"element type: ");
739 f->Printf(
", length: %" Pd "", length_);
752 f->AddString(
"members: {");
759 f->AddString(
",\n ");
779 f->AddString(
"Struct");
783 f->AddString(
"Union");
787 intptr_t member_index)
const {
788 f->Printf(
"%" Pd ": ", member_offsets_[member_index]);
791#if !defined(FFI_UNIT_TESTS)
799 for (intptr_t
i = 0;
i < argument_types_.
length();
i++) {
803 if (
i == variadic_arguments_index_) {
804 f->AddString(
"varargs: ");
806 argument_types_[
i]->PrintTo(
f);
808 f->AddString(
") => ");
848 return members_[
i]->FirstPrimitiveMember();
857 intptr_t offset_in_members)
const {
858 if (offset_in_members == 0) *first =
this;
859 if (offset_in_members == 1) *second =
this;
860 return offset_in_members + 1;
866 intptr_t offset_in_members)
const {
867 for (intptr_t
i = 0;
i < length_;
i++) {
871 return offset_in_members;
877 intptr_t offset_in_members)
const {
880 members_[
i]->PrimitivePairMembers(first, second, offset_in_members);
882 return offset_in_members;
885#if !defined(DART_PRECOMPILED_RUNTIME)
888 ASSERT(this_range.Contains(range));
895 ASSERT(this_range.Contains(range));
897 const intptr_t element_size_in_bytes = element_type_.
SizeInBytes();
900 const intptr_t first_element_start = range.
start() / element_size_in_bytes;
901 const intptr_t last_element_index =
903 const intptr_t num_elements = last_element_index - first_element_start + 1;
904 ASSERT(num_elements >= 1);
906 if (num_elements > 2) {
913 const intptr_t first_start = first_element_start * element_size_in_bytes;
914 const auto first_range =
916 const auto first_range_clipped = range.
Intersect(first_range);
917 const auto range_in_first = first_range_clipped.
Translate(-first_start);
923 if (num_elements == 2) {
925 const intptr_t second_element_index = first_element_start + 1;
926 const intptr_t second_start = second_element_index * element_size_in_bytes;
927 const auto second_range =
929 const auto second_range_clipped = range.
Intersect(second_range);
930 const auto range_in_second = second_range_clipped.
Translate(-second_start);
939 ASSERT(this_range.Contains(range));
943 const intptr_t member_offset = member_offsets_[
i];
944 const intptr_t member_size = member.SizeInBytes();
947 const auto member_range_clipped = member_range.Intersect(range);
948 const auto range_in_member =
949 member_range_clipped.Translate(-member_offset);
950 if (!member.ContainsOnlyFloats(range_in_member)) {
955 if (member_range.After(range)) {
966 const intptr_t member_size = member.SizeInBytes();
968 if (member_range.Overlaps(range)) {
969 const auto member_range_clipped = member_range.Intersect(range);
970 if (!member.ContainsOnlyFloats(member_range_clipped)) {
983 intptr_t float_only_chunks = 0;
986 const auto chunk_range =
992 return float_only_chunks;
996 const intptr_t total_chunks =
1014 const intptr_t max_check = 2;
1027 const intptr_t member_offset = member_offsets_.
At(
i);
1028 if (member.ContainsUnalignedMembers(
offset + member_offset)) {
1038 if (member.ContainsUnalignedMembers(
offset)) {
1047 bool* only_double) {
1048 for (intptr_t
i = 0;
i < types.
length();
i++) {
1049 const auto&
type = *types.
At(
i);
1050 const auto& member_type =
1052 if (member_type.IsPrimitive()) {
1054 *only_float = *only_float && (
type ==
kFloat);
1057 if (member_type.IsCompound()) {
1059 only_float, only_double);
1065 bool only_float =
true;
1066 bool only_double =
true;
1068 return (only_double || only_float) && types.
length() > 0;
1075#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(FFI_UNIT_TESTS)
1080 return kUnboxedInt32;
1082 return kUnboxedUint32;
1089 return kUnboxedInt64;
1095 return widened.AsRepresentation();
static void Union(SkRegion *rgn, const SkIRect &rect)
#define RELEASE_ASSERT(cond)
const T & At(intptr_t index) const
static constexpr AlignmentStrategy kFieldAlignment
static constexpr AlignmentStrategy kArgumentStackAlignmentVarArgs
static constexpr AlignmentStrategy kArgumentStackAlignment
const char * UserVisibleNameCString() const
ObjectPtr GetField(const Field &field) const
static bool FindPragma(Thread *T, bool only_core, const Object &object, const String &pragma_name, bool multiple=false, Object *options=nullptr)
static ObjectPtr RawCast(ObjectPtr obj)
static Thread * Current()
static constexpr T Maximum(T x, T y)
static T Minimum(T x, T y)
static constexpr T RoundUp(T x, uintptr_t alignment, uintptr_t offset=0)
char * PrintToString(const char *format,...) PRINTF_ATTRIBUTE(2
virtual void PrintTo(BaseTextBuffer *f, bool multi_line=false, bool verbose=true) const
virtual intptr_t SizeInBytes() const
virtual bool Equals(const NativeType &other) const
virtual bool ContainsOnlyFloats(Range range) const
virtual bool ContainsUnalignedMembers(intptr_t offset=0) const
virtual intptr_t PrimitivePairMembers(const NativePrimitiveType **first, const NativePrimitiveType **second, intptr_t offset_in_members=0) const
virtual const NativePrimitiveType & FirstPrimitiveMember() const
virtual intptr_t NumPrimitiveMembersRecursive() const
virtual intptr_t NumPrimitiveMembersRecursive() const =0
const NativeTypes & members() const
virtual bool Equals(const NativeType &other) const
bool ContainsHomogeneousFloats() const
virtual intptr_t SizeInBytes() const
intptr_t NumberOfWordSizeChunksOnlyFloat() const
virtual intptr_t AlignmentInBytesStack(bool is_vararg=false) const
virtual intptr_t PrimitivePairMembers(const NativePrimitiveType **first, const NativePrimitiveType **second, intptr_t offset_in_members=0) const
virtual const NativePrimitiveType & FirstPrimitiveMember() const
const NativeTypes & members_
virtual bool ContainsOnlyFloats(Range range) const =0
intptr_t NumberOfWordSizeChunksNotOnlyFloat() const
virtual void PrintMemberOffset(BaseTextBuffer *f, intptr_t member_index) const
virtual intptr_t AlignmentInBytesField() const
virtual void PrintTo(BaseTextBuffer *f, bool multi_line=false, bool verbose=true) const
virtual void PrintCompoundType(BaseTextBuffer *f) const =0
static const NativeFunctionType * FromRepresentations(Zone *zone, Representation return_representation, const ZoneGrowableArray< Representation > &argument_representations)
const NativeTypes & argument_types() const
void PrintTo(BaseTextBuffer *f) const
const NativeType & return_type() const
const char * ToCString() const
NativeFunctionType(const NativeTypes &argument_types, const NativeType &return_type, intptr_t variadic_arguments_index=kNoVariadicArguments)
virtual bool IsFloat() const
virtual Representation AsRepresentation() const
virtual bool IsVoid() const
virtual const NativePrimitiveType & FirstPrimitiveMember() const
virtual NativePrimitiveType & Split(Zone *zone, intptr_t part) const
virtual bool ContainsOnlyFloats(Range range) const
virtual bool Equals(const NativeType &other) const
virtual bool ContainsUnalignedMembers(intptr_t offset=0) const
virtual intptr_t PrimitivePairMembers(const NativePrimitiveType **first, const NativePrimitiveType **second, intptr_t offset_in_members=0) const
virtual bool IsExpressibleAsRepresentation() const
PrimitiveType representation() const
virtual bool IsSigned() const
virtual intptr_t NumPrimitiveMembersRecursive() const
virtual intptr_t AlignmentInBytesStack(bool is_vararg=false) const
virtual intptr_t AlignmentInBytesField() const
NativePrimitiveType(PrimitiveType rep)
virtual void PrintTo(BaseTextBuffer *f, bool multi_line=false, bool verbose=true) const
virtual bool IsInt() const
virtual intptr_t SizeInBytes() const
virtual bool ContainsOnlyFloats(Range range) const
static NativeStructType & FromNativeTypes(Zone *zone, const NativeTypes &members, intptr_t member_packing=kMaxInt32)
virtual bool ContainsUnalignedMembers(intptr_t offset=0) const
virtual void PrintMemberOffset(BaseTextBuffer *f, intptr_t member_index) const
virtual intptr_t NumPrimitiveMembersRecursive() const
virtual void PrintCompoundType(BaseTextBuffer *f) const
const ZoneGrowableArray< intptr_t > & member_offsets() const
const NativeCompoundType & AsCompound() const
Representation AsRepresentationOverApprox(Zone *zone_) const
virtual bool IsInt() const
static const NativeType * FromAbstractType(Zone *zone, const AbstractType &type, const char **error)
virtual bool IsCompound() const
virtual void PrintTo(BaseTextBuffer *f, bool multi_line=false, bool verbose=true) const
virtual intptr_t PrimitivePairMembers(const NativePrimitiveType **first, const NativePrimitiveType **second, intptr_t offset_in_members=0) const =0
virtual bool IsSigned() const
const NativeArrayType & AsArray() const
const NativePrimitiveType & AsPrimitive() const
const char * ToCString() const
virtual intptr_t AlignmentInBytesStack(bool is_vararg=false) const =0
virtual intptr_t SizeInBytes() const =0
virtual const NativePrimitiveType & FirstPrimitiveMember() const =0
virtual bool IsArray() const
const NativeType & WidenTo4Bytes(Zone *zone) const
virtual bool ContainsOnlyFloats(Range range) const =0
virtual bool IsPrimitive() const
const NativeType & WidenTo8Bytes(Zone *zone) const
static const NativeType & FromTypedDataClassId(Zone *zone, classid_t class_id)
static NativePrimitiveType & FromRepresentation(Zone *zone, Representation rep)
virtual intptr_t AlignmentInBytesField() const =0
virtual bool IsStruct() const
virtual bool ContainsUnalignedMembers(intptr_t offset=0) const =0
virtual bool Equals(const NativeType &other) const
const NativeStructType & AsStruct() const
virtual intptr_t NumPrimitiveMembersRecursive() const =0
static NativeUnionType & FromNativeTypes(Zone *zone, const NativeTypes &members)
virtual bool ContainsUnalignedMembers(intptr_t offset=0) const
virtual intptr_t NumPrimitiveMembersRecursive() const
virtual void PrintCompoundType(BaseTextBuffer *f) const
virtual bool ContainsOnlyFloats(Range range) const
static Range StartAndLength(intptr_t start_inclusive, intptr_t length)
const Range Intersect(const Range &other) const
bool Overlaps(const Range &other) const
static Range StartAndEnd(intptr_t start_inclusive, intptr_t end_exclusive)
intptr_t end_inclusive() const
const Range Translate(intptr_t delta) const
const uint8_t uint32_t uint32_t GError ** error
PrimitiveType PrimitiveTypeFromSizeInBytes(intptr_t size)
static const char * PrimitiveTypeToCString(PrimitiveType rep)
static const intptr_t fundamental_size_in_bytes[kVoid+1]
static PrimitiveType split_fundamental(PrimitiveType in)
static const NativeType * CompoundFromPragma(Zone *zone, const Instance &pragma, bool is_struct, const char **error)
static bool ContainsHomogeneousFloatsInternal(const NativeTypes &types)
const char * target_abi_name
static PrimitiveType TypeRepresentation(classid_t class_id)
static PrimitiveType fundamental_rep(Representation rep)
constexpr PrimitiveType kAddress
static const NativeType * AbiSpecificFromPragma(Zone *zone, const Instance &pragma, const Class &abi_specific_int, const char **error)
static void ContainsHomogeneousFloatsRecursive(const NativeTypes &types, bool *only_float, bool *only_double)
static constexpr intptr_t kWordSize
bool IsFfiPredefinedClassId(classid_t class_id)
constexpr int32_t kMaxInt32
static constexpr Representation kUnboxedIntPtr
@ kAlignedToWordSizeAndValueSize
@ kAlignedToValueSizeBut8AlignedTo4
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
#define UNREACHABLE_THIS()