Flutter Engine
The Flutter Engine
Public Member Functions | List of all members
dart::CallSiteResetter Class Reference

#include <isolate_reload.h>

Inheritance diagram for dart::CallSiteResetter:
dart::ValueObject

Public Member Functions

 CallSiteResetter (Zone *zone)
 
void ZeroEdgeCounters (const Function &function)
 
void ResetCaches (const Code &code)
 
void ResetCaches (const ObjectPool &pool)
 
void Reset (const ICData &ic)
 
void ResetSwitchableCalls (const Code &code)
 
- Public Member Functions inherited from dart::ValueObject
 ValueObject ()
 
 ~ValueObject ()
 

Detailed Description

Definition at line 410 of file isolate_reload.h.

Constructor & Destructor Documentation

◆ CallSiteResetter()

dart::CallSiteResetter::CallSiteResetter ( Zone zone)
explicit

Definition at line 43 of file object_reload.cc.

44 : zone_(zone),
45 instrs_(Instructions::Handle(zone)),
46 pool_(ObjectPool::Handle(zone)),
47 object_(Object::Handle(zone)),
48 name_(String::Handle(zone)),
49 new_cls_(Class::Handle(zone)),
50 new_lib_(Library::Handle(zone)),
51 new_function_(Function::Handle(zone)),
52 new_field_(Field::Handle(zone)),
53 entries_(Array::Handle(zone)),
54 old_target_(Function::Handle(zone)),
55 new_target_(Function::Handle(zone)),
56 caller_(Function::Handle(zone)),
57 args_desc_array_(Array::Handle(zone)),
58 ic_data_array_(Array::Handle(zone)),
59 edge_counters_(Array::Handle(zone)),
60 descriptors_(PcDescriptors::Handle(zone)),
61 ic_data_(ICData::Handle(zone)) {}
static Object & Handle()
Definition: object.h:407

Member Function Documentation

◆ Reset()

void dart::CallSiteResetter::Reset ( const ICData ic)

Definition at line 766 of file object_reload.cc.

766 {
767 ICData::RebindRule rule = ic.rebind_rule();
768 if (rule == ICData::kInstance) {
769 const intptr_t num_args = ic.NumArgsTested();
770 const intptr_t len = ic.Length();
771 // We need at least one non-sentinel entry to require a check
772 // for the smi fast path case.
773 if (num_args == 2 && len >= 2) {
774 if (ic.IsImmutable()) {
775 return;
776 }
777 name_ = ic.target_name();
778 const Class& smi_class = Class::Handle(zone_, Smi::Class());
779 const Function& smi_op_target = Function::Handle(
780 zone_, Resolver::ResolveDynamicAnyArgs(zone_, smi_class, name_,
781 /*allow_add=*/true));
782 GrowableArray<intptr_t> class_ids(2);
783 Function& target = Function::Handle(zone_);
784 ic.GetCheckAt(0, &class_ids, &target);
785 if ((target.ptr() == smi_op_target.ptr()) && (class_ids[0] == kSmiCid) &&
786 (class_ids[1] == kSmiCid)) {
787 // The smi fast path case, preserve the initial entry but reset the
788 // count.
789 ic.ClearCountAt(0, *this);
790 ic.TruncateTo(/*num_checks=*/1, *this);
791 return;
792 }
793 // Fall back to the normal behavior with cached empty ICData arrays.
794 }
795 ic.Clear(*this);
796 ic.set_is_megamorphic(false);
797 return;
798 } else if (rule == ICData::kNoRebind || rule == ICData::kNSMDispatch) {
799 // TODO(30877) we should account for addition/removal of NSM.
800 // Don't rebind dispatchers.
801 return;
802 } else if (rule == ICData::kStatic || rule == ICData::kSuper) {
803 old_target_ = ic.GetTargetAt(0);
804 if (old_target_.IsNull()) {
805 FATAL("old_target is nullptr.\n");
806 }
807 name_ = old_target_.name();
808
809 if (rule == ICData::kStatic) {
810 ASSERT(old_target_.is_static() ||
811 old_target_.kind() == UntaggedFunction::kConstructor);
812 // This can be incorrect if the call site was an unqualified invocation.
813 new_cls_ = old_target_.Owner();
814 new_target_ = Resolver::ResolveFunction(zone_, new_cls_, name_);
815 if (new_target_.kind() != old_target_.kind()) {
816 new_target_ = Function::null();
817 }
818 } else {
819 // Super call.
820 caller_ = ic.Owner();
821 ASSERT(!caller_.is_static());
822 new_cls_ = caller_.Owner();
823 new_cls_ = new_cls_.SuperClass();
824 new_target_ = Resolver::ResolveDynamicAnyArgs(zone_, new_cls_, name_,
825 /*allow_add=*/true);
826 }
827 args_desc_array_ = ic.arguments_descriptor();
828 ArgumentsDescriptor args_desc(args_desc_array_);
829 if (new_target_.IsNull() ||
830 !new_target_.AreValidArguments(args_desc, nullptr)) {
831 // TODO(rmacnak): Patch to a NSME stub.
832 VTIR_Print("Cannot rebind static call to %s from %s\n",
833 old_target_.ToCString(),
834 Object::Handle(zone_, ic.Owner()).ToCString());
835 return;
836 }
837 ic.ClearAndSetStaticTarget(new_target_, *this);
838 } else {
839 FATAL("Unexpected rebind rule.");
840 }
841}
ClassPtr SuperClass(ClassTable *class_table=nullptr) const
Definition: object.cc:3665
StringPtr name() const
Definition: object.h:2992
bool AreValidArguments(intptr_t num_type_arguments, intptr_t num_arguments, const Array &argument_names, String *error_message) const
Definition: object.cc:9323
ClassPtr Owner() const
Definition: object.cc:10841
UntaggedFunction::Kind kind() const
Definition: object.h:3349
static ObjectPtr null()
Definition: object.h:433
virtual const char * ToCString() const
Definition: object.h:366
bool IsNull() const
Definition: object.h:363
static FunctionPtr ResolveDynamicAnyArgs(Zone *zone, const Class &receiver_class, const String &function_name, bool allow_add)
Definition: resolver.cc:185
static FunctionPtr ResolveFunction(Zone *zone, const Class &receiver_class, const String &function_name)
Definition: resolver.cc:167
friend class Class
Definition: object.h:10047
#define ASSERT(E)
#define FATAL(error)
uint32_t * target
#define VTIR_Print(format,...)

◆ ResetCaches() [1/2]

void dart::CallSiteResetter::ResetCaches ( const Code code)

Definition at line 63 of file object_reload.cc.

63 {
64 // Iterate over the Code's object pool and reset all ICDatas.
65 // SubtypeTestCaches are reset during the same heap traversal as type
66 // testing stub deoptimization.
67#ifdef TARGET_ARCH_IA32
68 // IA32 does not have an object pool, but, we can iterate over all
69 // embedded objects by using the variable length data section.
70 if (!code.is_alive()) {
71 return;
72 }
73 instrs_ = code.instructions();
74 ASSERT(!instrs_.IsNull());
75 uword base_address = instrs_.PayloadStart();
76 intptr_t offsets_length = code.pointer_offsets_length();
77 const int32_t* offsets = code.untag()->data();
78 for (intptr_t i = 0; i < offsets_length; i++) {
79 int32_t offset = offsets[i];
80 ObjectPtr* object_ptr = reinterpret_cast<ObjectPtr*>(base_address + offset);
81 ObjectPtr raw_object = LoadUnaligned(object_ptr);
82 if (!raw_object->IsHeapObject()) {
83 continue;
84 }
85 object_ = raw_object;
86 if (object_.IsICData()) {
87 Reset(ICData::Cast(object_));
88 }
89 }
90#else
91 pool_ = code.object_pool();
92 ASSERT(!pool_.IsNull());
93 ResetCaches(pool_);
94#endif
95}
void ResetCaches(const Code &code)
void Reset(const ICData &ic)
uword PayloadStart() const
Definition: object.h:5745
uintptr_t uword
Definition: globals.h:501
static T LoadUnaligned(const T *ptr)
Definition: unaligned.h:14
list offsets
Definition: mskp_parser.py:37
SeparatedVector2 offset

◆ ResetCaches() [2/2]

void dart::CallSiteResetter::ResetCaches ( const ObjectPool pool)

Definition at line 181 of file object_reload.cc.

181 {
182 for (intptr_t i = 0; i < pool.Length(); i++) {
183 ObjectPool::EntryType entry_type = pool.TypeAt(i);
184 if (entry_type != ObjectPool::EntryType::kTaggedObject) {
185 continue;
186 }
187 object_ = pool.ObjectAt(i);
188 if (object_.IsICData()) {
189 Reset(ICData::Cast(object_));
190 }
191 }
192}
AutoreleasePool pool
compiler::ObjectPoolBuilderEntry::EntryType EntryType
Definition: object.h:5552

◆ ResetSwitchableCalls()

void dart::CallSiteResetter::ResetSwitchableCalls ( const Code code)

Definition at line 120 of file object_reload.cc.

120 {
121 if (code.is_optimized()) {
122 return; // No switchable calls in optimized code.
123 }
124
125 object_ = code.owner();
126 if (!object_.IsFunction()) {
127 return; // No switchable calls in stub code.
128 }
129 const Function& function = Function::Cast(object_);
130
131 if (function.kind() == UntaggedFunction::kIrregexpFunction) {
132 // Regex matchers do not support breakpoints or stepping, and they only call
133 // core library functions that cannot change due to reload. As a performance
134 // optimization, avoid this matching of ICData to PCs for these functions'
135 // large number of instance calls.
136 ASSERT(!function.is_debuggable());
137 return;
138 }
139
140 ic_data_array_ = function.ic_data_array();
141 if (ic_data_array_.IsNull()) {
142 // The megamorphic miss stub and some recognized function doesn't populate
143 // their ic_data_array. Check this only happens for functions without IC
144 // calls.
145#if defined(DEBUG)
146 descriptors_ = code.pc_descriptors();
147 PcDescriptors::Iterator iter(descriptors_, UntaggedPcDescriptors::kIcCall);
148 while (iter.MoveNext()) {
149 FATAL("%s has IC calls but no ic_data_array\n",
150 function.ToFullyQualifiedCString());
151 }
152#endif
153 return;
154 }
155
156 descriptors_ = code.pc_descriptors();
157 PcDescriptors::Iterator iter(descriptors_, UntaggedPcDescriptors::kIcCall);
158 while (iter.MoveNext()) {
159 uword pc = code.PayloadStart() + iter.PcOffset();
161 // This check both avoids unnecessary patching to reduce log spam and
162 // prevents patching over breakpoint stubs.
163 if (!object_.IsICData()) {
164 FindICData(ic_data_array_, iter.DeoptId(), &ic_data_);
165 ASSERT(ic_data_.rebind_rule() == ICData::kInstance);
166 ASSERT(ic_data_.NumArgsTested() == 1);
167 const Code& stub =
168 ic_data_.is_tracking_exactness()
169 ? StubCode::OneArgCheckInlineCacheWithExactnessCheck()
170 : StubCode::OneArgCheckInlineCache();
171 CodePatcher::PatchInstanceCallAt(pc, code, ic_data_, stub);
172 if (FLAG_trace_ic) {
173 OS::PrintErr("Instance call at %" Px
174 " resetting to polymorphic dispatch, %s\n",
175 pc, ic_data_.ToCString());
176 }
177 }
178 }
179}
static void PatchInstanceCallAt(uword return_address, const Code &caller_code, const Object &data, const Code &target)
static CodePtr GetInstanceCallAt(uword return_address, const Code &caller_code, Object *data)
intptr_t NumArgsTested() const
Definition: object.cc:16471
RebindRule rebind_rule() const
Definition: object.cc:16547
bool is_tracking_exactness() const
Definition: object.h:2483
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
Dart_NativeFunction function
Definition: fuchsia.cc:51
static void FindICData(const Array &ic_data_array, intptr_t deopt_id, ICData *ic_data)
#define Px
Definition: globals.h:410

◆ ZeroEdgeCounters()

void dart::CallSiteResetter::ZeroEdgeCounters ( const Function function)

Definition at line 26 of file object_reload.cc.

26 {
27 ic_data_array_ = function.ic_data_array();
28 if (ic_data_array_.IsNull()) {
29 return;
30 }
31 ASSERT(ic_data_array_.Length() > 0);
32 edge_counters_ ^=
34 if (edge_counters_.IsNull()) {
35 return;
36 }
37 // Fill edge counters array with zeros.
38 for (intptr_t i = 0; i < edge_counters_.Length(); i++) {
39 edge_counters_.SetAt(i, Object::smi_zero());
40 }
41}
ObjectPtr At(intptr_t index) const
Definition: object.h:10875
intptr_t Length() const
Definition: object.h:10829
void SetAt(intptr_t index, const Object &value) const
Definition: object.h:10880
static constexpr intptr_t kEdgeCounters
Definition: object.h:4058

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