Flutter Engine
The Flutter Engine
Classes | Public Member Functions | Static Public Member Functions | List of all members
dart::CodeSerializationCluster Class Reference
Inheritance diagram for dart::CodeSerializationCluster:
dart::SerializationCluster dart::ZoneAllocated

Classes

struct  CodeOrderInfo
 

Public Member Functions

 CodeSerializationCluster (Heap *heap)
 
 ~CodeSerializationCluster ()
 
void Trace (Serializer *s, ObjectPtr object)
 
void TracePool (Serializer *s, ObjectPoolPtr pool, bool only_call_targets)
 
intptr_t NonDiscardedCodeCount ()
 
void WriteAlloc (Serializer *s)
 
void WriteAlloc (Serializer *s, CodePtr code)
 
void WriteFill (Serializer *s)
 
void WriteFill (Serializer *s, Snapshot::Kind kind, CodePtr code, bool deferred)
 
GrowableArray< CodePtr > * objects ()
 
GrowableArray< CodePtr > * deferred_objects ()
 
intptr_t first_ref () const
 
intptr_t first_deferred_ref () const
 
intptr_t last_ref () const
 
- Public Member Functions inherited from dart::SerializationCluster
 SerializationCluster (const char *name, intptr_t cid, intptr_t target_instance_size=kSizeVaries, bool is_canonical=false)
 
virtual ~SerializationCluster ()
 
virtual void Trace (Serializer *serializer, ObjectPtr object)=0
 
virtual void WriteAlloc (Serializer *serializer)=0
 
virtual void WriteFill (Serializer *serializer)=0
 
void WriteAndMeasureAlloc (Serializer *serializer)
 
void WriteAndMeasureFill (Serializer *serializer)
 
const char * name () const
 
intptr_t cid () const
 
bool is_canonical () const
 
bool is_immutable () const
 
intptr_t size () const
 
intptr_t num_objects () const
 
intptr_t target_memory_size () const
 
- Public Member Functions inherited from dart::ZoneAllocated
 ZoneAllocated ()
 
void * operator new (size_t size)
 
void * operator new (size_t size, Zone *zone)
 
void operator delete (void *pointer)
 

Static Public Member Functions

static int CompareCodeOrderInfo (CodeOrderInfo const *a, CodeOrderInfo const *b)
 
static void Insert (Serializer *s, GrowableArray< CodeOrderInfo > *order_list, IntMap< intptr_t > *order_map, CodePtr code)
 
static void Sort (Serializer *s, GrowableArray< CodePtr > *codes)
 
static void Sort (Serializer *s, GrowableArray< Code * > *codes)
 
static const char * MakeDisambiguatedCodeName (Serializer *s, CodePtr c)
 

Additional Inherited Members

- Static Public Attributes inherited from dart::SerializationCluster
static constexpr intptr_t kSizeVaries = -1
 
- Protected Attributes inherited from dart::SerializationCluster
const char *const name_
 
const intptr_t cid_
 
const intptr_t target_instance_size_
 
const bool is_canonical_
 
const bool is_immutable_
 
intptr_t size_ = 0
 
intptr_t num_objects_ = 0
 
intptr_t target_memory_size_ = 0
 

Detailed Description

Definition at line 2603 of file app_snapshot.cc.

Constructor & Destructor Documentation

◆ CodeSerializationCluster()

dart::CodeSerializationCluster::CodeSerializationCluster ( Heap heap)
inlineexplicit

Definition at line 2605 of file app_snapshot.cc.

2606 : SerializationCluster("Code", kCodeCid), array_(Array::Handle()) {}
static Object & Handle()
Definition: object.h:407
SerializationCluster(const char *name, intptr_t cid, intptr_t target_instance_size=kSizeVaries, bool is_canonical=false)

◆ ~CodeSerializationCluster()

dart::CodeSerializationCluster::~CodeSerializationCluster ( )
inline

Definition at line 2607 of file app_snapshot.cc.

2607{}

Member Function Documentation

◆ CompareCodeOrderInfo()

static int dart::CodeSerializationCluster::CompareCodeOrderInfo ( CodeOrderInfo const *  a,
CodeOrderInfo const *  b 
)
inlinestatic

Definition at line 2741 of file app_snapshot.cc.

2742 {
2743 if (a->not_discarded < b->not_discarded) return -1;
2744 if (a->not_discarded > b->not_discarded) return 1;
2745 if (a->instructions_id < b->instructions_id) return -1;
2746 if (a->instructions_id > b->instructions_id) return 1;
2747 return 0;
2748 }
static bool b
struct MyStruct a[10]

◆ deferred_objects()

GrowableArray< CodePtr > * dart::CodeSerializationCluster::deferred_objects ( )
inline

Definition at line 2979 of file app_snapshot.cc.

2979{ return &deferred_objects_; }

◆ first_deferred_ref()

intptr_t dart::CodeSerializationCluster::first_deferred_ref ( ) const
inline

Definition at line 2995 of file app_snapshot.cc.

2995{ return first_deferred_ref_; }

◆ first_ref()

intptr_t dart::CodeSerializationCluster::first_ref ( ) const
inline

Definition at line 2994 of file app_snapshot.cc.

2994{ return first_ref_; }

◆ Insert()

static void dart::CodeSerializationCluster::Insert ( Serializer s,
GrowableArray< CodeOrderInfo > *  order_list,
IntMap< intptr_t > *  order_map,
CodePtr  code 
)
inlinestatic

Definition at line 2750 of file app_snapshot.cc.

2753 {
2754 InstructionsPtr instr = code->untag()->instructions_;
2755 intptr_t key = static_cast<intptr_t>(instr);
2756 intptr_t instructions_id = 0;
2757
2758 if (order_map->HasKey(key)) {
2759 // We are expected to merge code objects which point to the same
2760 // instructions in the precompiled mode.
2761 RELEASE_ASSERT(!FLAG_precompiled_mode);
2762 instructions_id = order_map->Lookup(key);
2763 } else {
2764 instructions_id = order_map->Length() + 1;
2765 order_map->Insert(key, instructions_id);
2766 }
2767 CodeOrderInfo info;
2768 info.code = code;
2769 info.instructions_id = instructions_id;
2770 info.not_discarded = Code::IsDiscarded(code) ? 0 : 1;
2771 order_list->Add(info);
2772 }
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
#define RELEASE_ASSERT(cond)
Definition: assert.h:327
intptr_t Length() const
Definition: hash_map.h:27
bool HasKey(typename KeyValueTrait::Key key) const
Definition: hash_map.h:52
static bool IsDiscarded(const CodePtr code)
Definition: object.h:6834
V Lookup(const Key &key) const
Definition: hash_map.h:548
void Insert(const Key &key, const Value &value)
Definition: hash_map.h:543

◆ last_ref()

intptr_t dart::CodeSerializationCluster::last_ref ( ) const
inline

Definition at line 2996 of file app_snapshot.cc.

2996{ return last_ref_; }

◆ MakeDisambiguatedCodeName()

static const char * dart::CodeSerializationCluster::MakeDisambiguatedCodeName ( Serializer s,
CodePtr  c 
)
inlinestatic

Definition at line 2981 of file app_snapshot.cc.

2981 {
2982 if (s->profile_writer() == nullptr) {
2983 return nullptr;
2984 }
2985
2986 REUSABLE_CODE_HANDLESCOPE(s->thread());
2987 Code& code = reused_code_handle.Handle();
2988 code = c;
2989 return code.QualifiedName(
2991 Object::NameVisibility::kInternalName));
2992 }
struct MyStruct s
#define REUSABLE_CODE_HANDLESCOPE(thread)
static NameFormattingParams DisambiguatedWithoutClassName(Object::NameVisibility visibility)
Definition: object.h:2968

◆ NonDiscardedCodeCount()

intptr_t dart::CodeSerializationCluster::NonDiscardedCodeCount ( )
inline

Definition at line 2800 of file app_snapshot.cc.

2800 {
2801 intptr_t count = 0;
2802 for (auto code : objects_) {
2803 if (!Code::IsDiscarded(code)) {
2804 count++;
2805 }
2806 }
2807 return count;
2808 }
int count
Definition: FontMgrTest.cpp:50

◆ objects()

GrowableArray< CodePtr > * dart::CodeSerializationCluster::objects ( )
inline

Definition at line 2978 of file app_snapshot.cc.

2978{ return &objects_; }

◆ Sort() [1/2]

static void dart::CodeSerializationCluster::Sort ( Serializer s,
GrowableArray< Code * > *  codes 
)
inlinestatic

Definition at line 2787 of file app_snapshot.cc.

2787 {
2788 GrowableArray<CodeOrderInfo> order_list;
2789 IntMap<intptr_t> order_map;
2790 for (intptr_t i = 0; i < codes->length(); i++) {
2791 Insert(s, &order_list, &order_map, (*codes)[i]->ptr());
2792 }
2793 order_list.Sort(CompareCodeOrderInfo);
2794 ASSERT(order_list.length() == codes->length());
2795 for (intptr_t i = 0; i < order_list.length(); i++) {
2796 *(*codes)[i] = order_list[i].code;
2797 }
2798 }
static void Insert(Serializer *s, GrowableArray< CodeOrderInfo > *order_list, IntMap< intptr_t > *order_map, CodePtr code)
static int CompareCodeOrderInfo(CodeOrderInfo const *a, CodeOrderInfo const *b)
#define ASSERT(E)

◆ Sort() [2/2]

static void dart::CodeSerializationCluster::Sort ( Serializer s,
GrowableArray< CodePtr > *  codes 
)
inlinestatic

Definition at line 2774 of file app_snapshot.cc.

2774 {
2775 GrowableArray<CodeOrderInfo> order_list;
2776 IntMap<intptr_t> order_map;
2777 for (intptr_t i = 0; i < codes->length(); i++) {
2778 Insert(s, &order_list, &order_map, (*codes)[i]);
2779 }
2780 order_list.Sort(CompareCodeOrderInfo);
2781 ASSERT(order_list.length() == codes->length());
2782 for (intptr_t i = 0; i < order_list.length(); i++) {
2783 (*codes)[i] = order_list[i].code;
2784 }
2785 }
intptr_t length() const

◆ Trace()

void dart::CodeSerializationCluster::Trace ( Serializer s,
ObjectPtr  object 
)
inlinevirtual

Implements dart::SerializationCluster.

Definition at line 2609 of file app_snapshot.cc.

2609 {
2610 CodePtr code = Code::RawCast(object);
2611
2612 const bool is_deferred = !s->InCurrentLoadingUnitOrRoot(code);
2613 if (is_deferred) {
2614 s->RecordDeferredCode(code);
2615 } else {
2616 objects_.Add(code);
2617 }
2618
2619 // Even if this code object is itself deferred we still need to scan
2620 // the pool for references to other code objects (which might reside
2621 // in the current loading unit).
2622 ObjectPoolPtr pool = code->untag()->object_pool_;
2623 if (s->kind() == Snapshot::kFullAOT) {
2624 TracePool(s, pool, /*only_call_targets=*/is_deferred);
2625 } else {
2626 if (s->InCurrentLoadingUnitOrRoot(pool)) {
2627 s->Push(pool);
2628 } else {
2629 TracePool(s, pool, /*only_call_targets=*/true);
2630 }
2631 }
2632
2633 if (s->kind() == Snapshot::kFullJIT) {
2634 s->Push(code->untag()->deopt_info_array_);
2635 s->Push(code->untag()->static_calls_target_table_);
2636 s->Push(code->untag()->compressed_stackmaps_);
2637 } else if (s->kind() == Snapshot::kFullAOT) {
2638 // Note: we don't trace compressed_stackmaps_ because we are going to emit
2639 // a separate mapping table into RO data which is not going to be a real
2640 // heap object.
2641#if defined(DART_PRECOMPILER)
2642 auto const calls_array = code->untag()->static_calls_target_table_;
2643 if (calls_array != Array::null()) {
2644 // Some Code entries in the static calls target table may only be
2645 // accessible via here, so push the Code objects.
2646 array_ = calls_array;
2647 for (auto entry : StaticCallsTable(array_)) {
2648 auto kind = Code::KindField::decode(
2650 switch (kind) {
2651 case Code::kCallViaCode:
2652 // Code object in the pool.
2653 continue;
2655 // TTS will be reachable through type object which itself is
2656 // in the pool.
2657 continue;
2660 auto destination = entry.Get<Code::kSCallTableCodeOrTypeTarget>();
2661 ASSERT(destination->IsHeapObject() && destination->IsCode());
2662 s->Push(destination);
2663 }
2664 }
2665 }
2666#else
2667 UNREACHABLE();
2668#endif
2669 }
2670
2671 if (Code::IsDiscarded(code)) {
2672 ASSERT(s->kind() == Snapshot::kFullAOT && FLAG_dwarf_stack_traces_mode &&
2673 !FLAG_retain_code_objects);
2674 // Only object pool and static call table entries and the compressed
2675 // stack maps should be pushed.
2676 return;
2677 }
2678
2679 s->Push(code->untag()->owner_);
2680 s->Push(code->untag()->exception_handlers_);
2681 s->Push(code->untag()->pc_descriptors_);
2682 s->Push(code->untag()->catch_entry_);
2683 if (!FLAG_precompiled_mode || !FLAG_dwarf_stack_traces_mode) {
2684 s->Push(code->untag()->inlined_id_to_function_);
2685 if (s->InCurrentLoadingUnitOrRoot(code->untag()->code_source_map_)) {
2686 s->Push(code->untag()->code_source_map_);
2687 }
2688 }
2689#if !defined(PRODUCT)
2690 s->Push(code->untag()->return_address_metadata_);
2691 if (FLAG_code_comments) {
2692 s->Push(code->untag()->comments_);
2693 }
2694#endif
2695 }
AutoreleasePool pool
#define UNREACHABLE()
Definition: assert.h:248
void Add(const T &value)
static constexpr CallKind decode(intptr_t value)
Definition: bitfield.h:171
void TracePool(Serializer *s, ObjectPoolPtr pool, bool only_call_targets)
@ kPcRelativeCall
Definition: object.h:6969
@ kPcRelativeTTSCall
Definition: object.h:6970
@ kCallViaCode
Definition: object.h:6972
@ kPcRelativeTailCall
Definition: object.h:6971
@ kSCallTableCodeOrTypeTarget
Definition: object.h:6982
@ kSCallTableKindAndOffset
Definition: object.h:6981
static ObjectPtr null()
Definition: object.h:433
static ObjectPtr RawCast(ObjectPtr obj)
Definition: object.h:325
intptr_t Value() const
Definition: object.h:9990
ArrayOfTuplesView< Code::SCallTableEntry, std::tuple< Smi, Object, Function > > StaticCallsTable
Definition: object.h:13546

◆ TracePool()

void dart::CodeSerializationCluster::TracePool ( Serializer s,
ObjectPoolPtr  pool,
bool  only_call_targets 
)
inline

Definition at line 2697 of file app_snapshot.cc.

2697 {
2698 if (pool == ObjectPool::null()) {
2699 return;
2700 }
2701
2702 const intptr_t length = pool->untag()->length_;
2703 uint8_t* entry_bits = pool->untag()->entry_bits();
2704 for (intptr_t i = 0; i < length; i++) {
2705 auto entry_type = ObjectPool::TypeBits::decode(entry_bits[i]);
2706 if (entry_type == ObjectPool::EntryType::kTaggedObject) {
2707 const ObjectPtr target = pool->untag()->data()[i].raw_obj_;
2708 // A field is a call target because its initializer may be called
2709 // indirectly by passing the field to the runtime. A const closure
2710 // is a call target because its function may be called indirectly
2711 // via a closure call.
2712 intptr_t cid = target->GetClassIdMayBeSmi();
2713 if (!only_call_targets || (cid == kCodeCid) || (cid == kFunctionCid) ||
2714 (cid == kFieldCid) || (cid == kClosureCid)) {
2715 s->Push(target);
2716 } else if (cid >= kNumPredefinedCids) {
2717 s->Push(s->isolate_group()->class_table()->At(cid));
2718 }
2719 }
2720 }
2721 }
uint32_t * target
size_t length
@ kNumPredefinedCids
Definition: class_id.h:257

◆ WriteAlloc() [1/2]

void dart::CodeSerializationCluster::WriteAlloc ( Serializer s)
inlinevirtual

Implements dart::SerializationCluster.

Definition at line 2810 of file app_snapshot.cc.

2810 {
2811 const intptr_t non_discarded_count = NonDiscardedCodeCount();
2812 const intptr_t count = objects_.length();
2813 ASSERT(count == non_discarded_count || (s->kind() == Snapshot::kFullAOT));
2814
2815 first_ref_ = s->next_ref_index();
2816 s->WriteUnsigned(non_discarded_count);
2817 for (auto code : objects_) {
2818 if (!Code::IsDiscarded(code)) {
2819 WriteAlloc(s, code);
2820 } else {
2821 // Mark discarded code unreachable, so that we could later
2822 // assign artificial references to it.
2823 s->heap()->SetObjectId(code, kUnreachableReference);
2824 }
2825 }
2826
2827 s->WriteUnsigned(deferred_objects_.length());
2828 first_deferred_ref_ = s->next_ref_index();
2829 for (auto code : deferred_objects_) {
2831 WriteAlloc(s, code);
2832 }
2833 last_ref_ = s->next_ref_index() - 1;
2834 }
void WriteAlloc(Serializer *s)
static constexpr intptr_t kUnreachableReference

◆ WriteAlloc() [2/2]

void dart::CodeSerializationCluster::WriteAlloc ( Serializer s,
CodePtr  code 
)
inline

Definition at line 2836 of file app_snapshot.cc.

2836 {
2838 s->AssignRef(code);
2840 const int32_t state_bits = code->untag()->state_bits_;
2841 s->Write<int32_t>(state_bits);
2843 }
#define AutoTraceObjectName(obj, str)
static const char * MakeDisambiguatedCodeName(Serializer *s, CodePtr c)

◆ WriteFill() [1/2]

void dart::CodeSerializationCluster::WriteFill ( Serializer s)
inlinevirtual

Implements dart::SerializationCluster.

Definition at line 2845 of file app_snapshot.cc.

2845 {
2846 Snapshot::Kind kind = s->kind();
2847 const intptr_t count = objects_.length();
2848 for (intptr_t i = 0; i < count; i++) {
2849 CodePtr code = objects_[i];
2850#if defined(DART_PRECOMPILER)
2851 if (FLAG_write_v8_snapshot_profile_to != nullptr &&
2853 s->CreateArtificialNodeIfNeeded(code);
2854 }
2855#endif
2856 // Note: for discarded code this function will not write anything out
2857 // it is only called to produce information into snapshot profile.
2858 WriteFill(s, kind, code, /*deferred=*/false);
2859 }
2860 const intptr_t deferred_count = deferred_objects_.length();
2861 for (intptr_t i = 0; i < deferred_count; i++) {
2862 CodePtr code = deferred_objects_[i];
2863 WriteFill(s, kind, code, /*deferred=*/true);
2864 }
2865 }
void WriteFill(Serializer *s)

◆ WriteFill() [2/2]

void dart::CodeSerializationCluster::WriteFill ( Serializer s,
Snapshot::Kind  kind,
CodePtr  code,
bool  deferred 
)
inline

Definition at line 2867 of file app_snapshot.cc.

2870 {
2871 const intptr_t bytes_written = s->bytes_written();
2873
2874 intptr_t pointer_offsets_length =
2875 Code::PtrOffBits::decode(code->untag()->state_bits_);
2876 if (pointer_offsets_length != 0) {
2877 FATAL("Cannot serialize code with embedded pointers");
2878 }
2879 if (kind == Snapshot::kFullAOT && Code::IsDisabled(code)) {
2880 // Disabled code is fatal in AOT since we cannot recompile.
2881 s->UnexpectedObject(code, "Disabled code");
2882 }
2883
2884 s->WriteInstructions(code->untag()->instructions_,
2885 code->untag()->unchecked_offset_, code, deferred);
2886 if (kind == Snapshot::kFullJIT) {
2887 // TODO(rmacnak): Fix references to disabled code before serializing.
2888 // For now, we may write the FixCallersTarget or equivalent stub. This
2889 // will cause a fixup if this code is called.
2890 const uint32_t active_unchecked_offset =
2891 code->untag()->unchecked_entry_point_ - code->untag()->entry_point_;
2892 s->WriteInstructions(code->untag()->active_instructions_,
2893 active_unchecked_offset, code, deferred);
2894 }
2895
2896#if defined(DART_PRECOMPILER)
2897 if (FLAG_write_v8_snapshot_profile_to != nullptr) {
2898 // If we are writing V8 snapshot profile then attribute references going
2899 // through the object pool and static calls to the code object itself.
2900 if (kind == Snapshot::kFullAOT &&
2901 code->untag()->object_pool_ != ObjectPool::null()) {
2902 ObjectPoolPtr pool = code->untag()->object_pool_;
2903 // Non-empty per-code object pools should not be reachable in this mode.
2904 ASSERT(!s->HasRef(pool) || pool == Object::empty_object_pool().ptr());
2905 s->CreateArtificialNodeIfNeeded(pool);
2906 s->AttributePropertyRef(pool, "object_pool_");
2907 }
2908 if (kind != Snapshot::kFullJIT &&
2909 code->untag()->static_calls_target_table_ != Array::null()) {
2910 auto const table = code->untag()->static_calls_target_table_;
2911 // Non-empty static call target tables shouldn't be reachable in this
2912 // mode.
2913 ASSERT(!s->HasRef(table) || table == Object::empty_array().ptr());
2914 s->CreateArtificialNodeIfNeeded(table);
2915 s->AttributePropertyRef(table, "static_calls_target_table_");
2916 }
2917 }
2918#endif // defined(DART_PRECOMPILER)
2919
2920 if (Code::IsDiscarded(code)) {
2921 // No bytes should be written to represent this code.
2922 ASSERT(s->bytes_written() == bytes_written);
2923 // Only write instructions, compressed stackmaps and state bits
2924 // for the discarded Code objects.
2925 ASSERT(kind == Snapshot::kFullAOT && FLAG_dwarf_stack_traces_mode &&
2926 !FLAG_retain_code_objects);
2927#if defined(DART_PRECOMPILER)
2928 if (FLAG_write_v8_snapshot_profile_to != nullptr) {
2929 // Keep the owner as a (possibly artificial) node for snapshot analysis.
2930 const auto& owner = code->untag()->owner_;
2931 s->CreateArtificialNodeIfNeeded(owner);
2932 s->AttributePropertyRef(owner, "owner_");
2933 }
2934#endif
2935 return;
2936 }
2937
2938 // No need to write object pool out if we are producing full AOT
2939 // snapshot with bare instructions.
2940 if (kind != Snapshot::kFullAOT) {
2941 if (s->InCurrentLoadingUnitOrRoot(code->untag()->object_pool_)) {
2942 WriteField(code, object_pool_);
2943 } else {
2944 WriteFieldValue(object_pool_, ObjectPool::null());
2945 }
2946 }
2947 WriteField(code, owner_);
2948 WriteField(code, exception_handlers_);
2949 WriteField(code, pc_descriptors_);
2950 WriteField(code, catch_entry_);
2951 if (s->kind() == Snapshot::kFullJIT) {
2952 WriteField(code, compressed_stackmaps_);
2953 }
2954 if (FLAG_precompiled_mode && FLAG_dwarf_stack_traces_mode) {
2955 WriteFieldValue(inlined_id_to_function_, Array::null());
2956 WriteFieldValue(code_source_map_, CodeSourceMap::null());
2957 } else {
2958 WriteField(code, inlined_id_to_function_);
2959 if (s->InCurrentLoadingUnitOrRoot(code->untag()->code_source_map_)) {
2960 WriteField(code, code_source_map_);
2961 } else {
2962 WriteFieldValue(code_source_map_, CodeSourceMap::null());
2963 }
2964 }
2965 if (kind == Snapshot::kFullJIT) {
2966 WriteField(code, deopt_info_array_);
2967 WriteField(code, static_calls_target_table_);
2968 }
2969
2970#if !defined(PRODUCT)
2971 WriteField(code, return_address_metadata_);
2972 if (FLAG_code_comments) {
2973 WriteField(code, comments_);
2974 }
2975#endif
2976 }
SI F table(const skcms_Curve *curve, F v)
#define WriteFieldValue(field, value)
#define WriteField(obj, field)
bool IsDisabled() const
Definition: object.h:7257
#define FATAL(error)
static DecodeResult decode(std::string path)
Definition: png_codec.cpp:124

The documentation for this class was generated from the following file: