Clear PreCompiled when we transition to debuggable after zygote fork
We were leaving the PreCompiled bits set on method objects. This meant
that in some circumstances non-debuggable compiled code could be
reattached to methods after the switch to debuggable with the zygote
fork.
Bug: 144947842
Test: atest CtsJvmtiRunTest1982HostTestCases
Change-Id: I1f642f6da441c4f023ec1cbd873c05914c73dd7e
diff --git a/runtime/jit/jit_code_cache.h b/runtime/jit/jit_code_cache.h
index 61fee34..22b43cc 100644
--- a/runtime/jit/jit_code_cache.h
+++ b/runtime/jit/jit_code_cache.h
@@ -104,6 +104,14 @@
// This map is writable only by the zygote, and readable by all children.
class ZygoteMap {
public:
+ struct Entry {
+ ArtMethod* method;
+ // Note we currently only allocate code in the low 4g, so we could just reserve 4 bytes
+ // for the code pointer. For simplicity and in the case we move to 64bit
+ // addresses for code, just keep it void* for now.
+ const void* code_ptr;
+ };
+
explicit ZygoteMap(JitMemoryRegion* region)
: map_(), region_(region), compilation_state_(nullptr) {}
@@ -140,15 +148,20 @@
*compilation_state_ == ZygoteCompilationState::kNotifiedOk;
}
- private:
- struct Entry {
- ArtMethod* method;
- // Note we currently only allocate code in the low 4g, so we could just reserve 4 bytes
- // for the code pointer. For simplicity and in the case we move to 64bit
- // addresses for code, just keep it void* for now.
- const void* code_ptr;
- };
+ ArrayRef<const Entry>::const_iterator cbegin() const {
+ return map_.cbegin();
+ }
+ ArrayRef<const Entry>::iterator begin() {
+ return map_.begin();
+ }
+ ArrayRef<const Entry>::const_iterator cend() const {
+ return map_.cend();
+ }
+ ArrayRef<const Entry>::iterator end() {
+ return map_.end();
+ }
+ private:
// The map allocated with `region_`.
ArrayRef<const Entry> map_;
@@ -370,8 +383,9 @@
// Clear the entrypoints of JIT compiled methods that belong in the zygote space.
// This is used for removing non-debuggable JIT code at the point we realize the runtime
- // is debuggable.
- void ClearEntryPointsInZygoteExecSpace() REQUIRES(!Locks::jit_lock_) REQUIRES(Locks::mutator_lock_);
+ // is debuggable. Also clear the Precompiled flag from all methods so the non-debuggable code
+ // doesn't come back.
+ void TransitionToDebuggable() REQUIRES(!Locks::jit_lock_) REQUIRES(Locks::mutator_lock_);
JitMemoryRegion* GetCurrentRegion();
bool IsSharedRegion(const JitMemoryRegion& region) const { return ®ion == &shared_region_; }