[vm] Account for direct code calls from unoptimized code for --reused_instructions.
For example, constructors directly reference an allocation stub.
Change-Id: I5779c476c7721d2cc4b6ceb9348a1ffeaa5e082d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/97272
Reviewed-by: Siva Annamalai <asiva@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc
index 4ca767d..37b9f7d 100644
--- a/runtime/vm/image_snapshot.cc
+++ b/runtime/vm/image_snapshot.cc
@@ -823,7 +823,11 @@
class DropCodeVisitor : public FunctionVisitor, public ClassVisitor {
public:
explicit DropCodeVisitor(const void* reused_instructions)
- : code_(Code::Handle()), instructions_(Instructions::Handle()) {
+ : code_(Code::Handle()),
+ instructions_(Instructions::Handle()),
+ pool_(ObjectPool::Handle()),
+ table_(Array::Handle()),
+ entry_(Object::Handle()) {
ImageWriter::SetupShared(&reused_instructions_, reused_instructions);
if (FLAG_trace_reused_instructions) {
OS::PrintErr("%" Pd " reusable instructions\n",
@@ -833,18 +837,20 @@
void Visit(const Class& cls) {
code_ = cls.allocation_stub();
- if (!code_.IsNull() && !IsAvailable(code_)) {
- if (FLAG_trace_reused_instructions) {
- OS::PrintErr("No reusable instructions for %s\n", cls.ToCString());
+ if (!code_.IsNull()) {
+ if (!CanKeep(code_)) {
+ if (FLAG_trace_reused_instructions) {
+ OS::PrintErr("No reusable instructions for %s\n", cls.ToCString());
+ }
+ cls.DisableAllocationStub();
}
- cls.DisableAllocationStub();
}
}
void Visit(const Function& func) {
if (func.HasCode()) {
code_ = func.CurrentCode();
- if (!IsAvailable(code_)) {
+ if (!CanKeep(code_)) {
if (FLAG_trace_reused_instructions) {
OS::PrintErr("No reusable instructions for %s\n", func.ToCString());
}
@@ -854,16 +860,44 @@
}
}
code_ = func.unoptimized_code();
- if (!code_.IsNull() && !IsAvailable(code_)) {
+ if (!code_.IsNull() && !CanKeep(code_)) {
if (FLAG_trace_reused_instructions) {
OS::PrintErr("No reusable instructions for %s\n", func.ToCString());
}
func.ClearCode();
func.ClearICDataArray();
- return;
}
}
+ bool CanKeep(const Code& code) {
+ if (!IsAvailable(code)) {
+ return false;
+ }
+
+ pool_ = code.object_pool();
+ for (intptr_t i = 0; i < pool_.Length(); i++) {
+ if (pool_.TypeAt(i) == ObjectPool::EntryType::kTaggedObject) {
+ entry_ = pool_.ObjectAt(i);
+ if (entry_.IsCode() && !IsAvailable(Code::Cast(entry_))) {
+ return false;
+ }
+ }
+ }
+
+ table_ = code.static_calls_target_table();
+ if (!table_.IsNull()) {
+ StaticCallsTable static_calls(table_);
+ for (auto& view : static_calls) {
+ entry_ = view.Get<Code::kSCallTableCodeTarget>();
+ if (entry_.IsCode() && !IsAvailable(Code::Cast(entry_))) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
private:
bool IsAvailable(const Code& code) {
ObjectOffsetPair* pair = reused_instructions_.Lookup(code.instructions());
@@ -873,6 +907,9 @@
ObjectOffsetMap reused_instructions_;
Code& code_;
Instructions& instructions_;
+ ObjectPool& pool_;
+ Array& table_;
+ Object& entry_;
DISALLOW_COPY_AND_ASSIGN(DropCodeVisitor);
};
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index df88871..5d6d587 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -9435,7 +9435,6 @@
public:
TupleView(const Array& array, intptr_t index)
: array_(array), index_(index) {
- ASSERT(!array.IsNull());
}
template <EnumType kElement>
@@ -9483,6 +9482,7 @@
};
explicit ArrayOfTuplesView(const Array& array) : array_(array), index_(-1) {
+ ASSERT(!array.IsNull());
ASSERT(array.Length() >= kStartOffset);
ASSERT((array.Length() - kStartOffset) % EntrySize == kStartOffset);
}