Prepare for sharing JIT code after fork.

Only encode classes/strings/methods that are in a boot image.

Bug: 119800099
Test: boot
Change-Id: I7ed8ce2ce876ad1c6c1678939cafe4808a67bef4
diff --git a/compiler/optimizing/sharpening.cc b/compiler/optimizing/sharpening.cc
index 3e22edc..03d277f 100644
--- a/compiler/optimizing/sharpening.cc
+++ b/compiler/optimizing/sharpening.cc
@@ -100,6 +100,7 @@
     }
     code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod;
   } else if (Runtime::Current()->UseJitCompilation()) {
+    ScopedObjectAccess soa(Thread::Current());
     if (Runtime::Current()->GetJit()->CanEncodeMethod(
             callee,
             codegen->GetGraph()->IsCompilingForSharedJitCode())) {
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 201f3ce..c92630d 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -1073,30 +1073,33 @@
   thread_pool_->CreateThreads();
 }
 
-bool Jit::CanEncodeMethod(ArtMethod* method ATTRIBUTE_UNUSED,
-                          bool is_for_shared_region ATTRIBUTE_UNUSED) const {
-  // TODO: For shared region, we should only encode a method of a class
-  // allocated before any fork.
-  return true;
+bool Jit::CanEncodeMethod(ArtMethod* method, bool is_for_shared_region) const {
+  return !is_for_shared_region ||
+      Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(method->GetDeclaringClass());
 }
 
 bool Jit::CanEncodeClass(ObjPtr<mirror::Class> cls, bool is_for_shared_region) const {
-  // TODO: For shared region, we should only encode a non-moving class allocated
-  // before any fork.
-  return !is_for_shared_region || !Runtime::Current()->GetHeap()->IsMovableObject(cls);
+  return !is_for_shared_region || Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(cls);
 }
 
 bool Jit::CanEncodeString(ObjPtr<mirror::String> string, bool is_for_shared_region) const {
-  // TODO: For shared region, we should only encode a non-moving string allocated
-  // before any fork.
-  return !is_for_shared_region || !Runtime::Current()->GetHeap()->IsMovableObject(string);
+  return !is_for_shared_region || Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(string);
 }
 
-bool Jit::CanAssumeInitialized(ObjPtr<mirror::Class> cls,
-                               bool is_for_shared_region ATTRIBUTE_UNUSED) const {
-  // TODO: For shared region, we should assume initialized if the class is initialized
-  // before any fork.
-  return cls->IsInitialized();
+bool Jit::CanAssumeInitialized(ObjPtr<mirror::Class> cls, bool is_for_shared_region) const {
+  if (!is_for_shared_region) {
+    return cls->IsInitialized();
+  } else {
+    // Look up the class status in the oat file.
+    const DexFile& dex_file = *cls->GetDexCache()->GetDexFile();
+    const OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
+    // In case we run without an image there won't be a backing oat file.
+    if (oat_dex_file == nullptr || oat_dex_file->GetOatFile() == nullptr) {
+      return false;
+    }
+    uint16_t class_def_index = cls->GetDexClassDefIndex();
+    return oat_dex_file->GetOatClass(class_def_index).GetStatus() >= ClassStatus::kInitialized;
+  }
 }
 
 }  // namespace jit
diff --git a/runtime/jit/jit.h b/runtime/jit/jit.h
index e44e1c9..d272a18 100644
--- a/runtime/jit/jit.h
+++ b/runtime/jit/jit.h
@@ -326,7 +326,8 @@
 
   // Called by the compiler to know whether it can directly encode the
   // method/class/string.
-  bool CanEncodeMethod(ArtMethod* method, bool is_for_shared_region) const;
+  bool CanEncodeMethod(ArtMethod* method, bool is_for_shared_region) const
+      REQUIRES_SHARED(Locks::mutator_lock_);
   bool CanEncodeClass(ObjPtr<mirror::Class> cls, bool is_for_shared_region) const
       REQUIRES_SHARED(Locks::mutator_lock_);
   bool CanEncodeString(ObjPtr<mirror::String> string, bool is_for_shared_region) const