Merge "Change ClassStatus to fit into 4 bits."
diff --git a/compiler/dex/quick_compiler_callbacks.cc b/compiler/dex/quick_compiler_callbacks.cc
index 92b1230..540bd0c 100644
--- a/compiler/dex/quick_compiler_callbacks.cc
+++ b/compiler/dex/quick_compiler_callbacks.cc
@@ -38,7 +38,7 @@
// If we don't have class unloading enabled in the compiler, we will never see class that were
// previously verified. Return false to avoid overhead from the lookup in the compiler driver.
if (!does_class_unloading_) {
- return ClassStatus::kStatusNotReady;
+ return ClassStatus::kNotReady;
}
DCHECK(compiler_driver_ != nullptr);
// In the case of the quicken filter: avoiding verification of quickened instructions, which the
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 5d4ed46..b35a8e9 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -1809,7 +1809,7 @@
static void LoadAndUpdateStatus(const DexFile& dex_file,
const DexFile::ClassDef& class_def,
- mirror::Class::Status status,
+ ClassStatus status,
Handle<mirror::ClassLoader> class_loader,
Thread* self)
REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -1868,16 +1868,16 @@
// Just update the compiled_classes_ map. The compiler doesn't need to resolve
// the type.
ClassReference ref(dex_file, i);
- mirror::Class::Status existing = mirror::Class::kStatusNotReady;
+ ClassStatus existing = ClassStatus::kNotReady;
DCHECK(compiled_classes_.Get(ref, &existing)) << ref.dex_file->GetLocation();
ClassStateTable::InsertResult result =
- compiled_classes_.Insert(ref, existing, mirror::Class::kStatusVerified);
+ compiled_classes_.Insert(ref, existing, ClassStatus::kVerified);
CHECK_EQ(result, ClassStateTable::kInsertResultSuccess);
} else {
// Update the class status, so later compilation stages know they don't need to verify
// the class.
LoadAndUpdateStatus(
- *dex_file, class_def, mirror::Class::kStatusVerified, class_loader, soa.Self());
+ *dex_file, class_def, ClassStatus::kVerified, class_loader, soa.Self());
// Create `VerifiedMethod`s for each methods, the compiler expects one for
// quickening or compiling.
// Note that this means:
@@ -1891,7 +1891,7 @@
// this class again.
LoadAndUpdateStatus(*dex_file,
class_def,
- mirror::Class::kStatusRetryVerificationAtRuntime,
+ ClassStatus::kRetryVerificationAtRuntime,
class_loader,
soa.Self());
}
@@ -2105,10 +2105,10 @@
// Only do this if the class is resolved. If even resolution fails, quickening will go very,
// very wrong.
if (klass->IsResolved() && !klass->IsErroneousResolved()) {
- if (klass->GetStatus() < mirror::Class::kStatusVerified) {
+ if (klass->GetStatus() < ClassStatus::kVerified) {
ObjectLock<mirror::Class> lock(soa.Self(), klass);
// Set class status to verified.
- mirror::Class::SetStatus(klass, mirror::Class::kStatusVerified, soa.Self());
+ mirror::Class::SetStatus(klass, ClassStatus::kVerified, soa.Self());
// Mark methods as pre-verified. If we don't do this, the interpreter will run with
// access checks.
klass->SetSkipAccessChecksFlagOnAllMethods(
@@ -2185,7 +2185,7 @@
const bool is_boot_image = manager_->GetCompiler()->GetCompilerOptions().IsBootImage();
const bool is_app_image = manager_->GetCompiler()->GetCompilerOptions().IsAppImage();
- mirror::Class::Status old_status = klass->GetStatus();
+ ClassStatus old_status = klass->GetStatus();
// Don't initialize classes in boot space when compiling app image
if (is_app_image && klass->IsBootStrapClassLoaded()) {
// Also return early and don't store the class status in the recorded class status.
@@ -2310,7 +2310,7 @@
// would do so they can be skipped at runtime.
if (!klass->IsInitialized() &&
manager_->GetClassLinker()->ValidateSuperClassDescriptors(klass)) {
- old_status = mirror::Class::kStatusSuperclassValidated;
+ old_status = ClassStatus::kSuperclassValidated;
} else {
soa.Self()->ClearException();
}
@@ -2771,36 +2771,36 @@
DCHECK(GetCompiledMethod(method_ref) != nullptr) << method_ref.PrettyMethod();
}
-bool CompilerDriver::GetCompiledClass(const ClassReference& ref,
- mirror::Class::Status* status) const {
+bool CompilerDriver::GetCompiledClass(const ClassReference& ref, ClassStatus* status) const {
DCHECK(status != nullptr);
// The table doesn't know if something wasn't inserted. For this case it will return
- // kStatusNotReady. To handle this, just assume anything we didn't try to verify is not compiled.
+ // ClassStatus::kNotReady. To handle this, just assume anything we didn't try to verify
+ // is not compiled.
if (!compiled_classes_.Get(ref, status) ||
- *status < mirror::Class::kStatusRetryVerificationAtRuntime) {
+ *status < ClassStatus::kRetryVerificationAtRuntime) {
return false;
}
return true;
}
-mirror::Class::Status CompilerDriver::GetClassStatus(const ClassReference& ref) const {
- mirror::Class::Status status = ClassStatus::kStatusNotReady;
+ClassStatus CompilerDriver::GetClassStatus(const ClassReference& ref) const {
+ ClassStatus status = ClassStatus::kNotReady;
if (!GetCompiledClass(ref, &status)) {
classpath_classes_.Get(ref, &status);
}
return status;
}
-void CompilerDriver::RecordClassStatus(const ClassReference& ref, mirror::Class::Status status) {
+void CompilerDriver::RecordClassStatus(const ClassReference& ref, ClassStatus status) {
switch (status) {
- case mirror::Class::kStatusErrorResolved:
- case mirror::Class::kStatusErrorUnresolved:
- case mirror::Class::kStatusNotReady:
- case mirror::Class::kStatusResolved:
- case mirror::Class::kStatusRetryVerificationAtRuntime:
- case mirror::Class::kStatusVerified:
- case mirror::Class::kStatusSuperclassValidated:
- case mirror::Class::kStatusInitialized:
+ case ClassStatus::kErrorResolved:
+ case ClassStatus::kErrorUnresolved:
+ case ClassStatus::kNotReady:
+ case ClassStatus::kResolved:
+ case ClassStatus::kRetryVerificationAtRuntime:
+ case ClassStatus::kVerified:
+ case ClassStatus::kSuperclassValidated:
+ case ClassStatus::kInitialized:
break; // Expected states.
default:
LOG(FATAL) << "Unexpected class status for class "
@@ -2812,7 +2812,7 @@
ClassStateTable::InsertResult result;
ClassStateTable* table = &compiled_classes_;
do {
- mirror::Class::Status existing = mirror::Class::kStatusNotReady;
+ ClassStatus existing = ClassStatus::kNotReady;
if (!table->Get(ref, &existing)) {
// A classpath class.
if (kIsDebugBuild) {
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index e001726..bcea853 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -31,13 +31,13 @@
#include "base/mutex.h"
#include "base/timing_logger.h"
#include "class_reference.h"
+#include "class_status.h"
#include "compiler.h"
#include "dex_file.h"
#include "dex_file_types.h"
#include "driver/compiled_method_storage.h"
#include "jit/profile_compilation_info.h"
#include "method_reference.h"
-#include "mirror/class.h" // For mirror::Class::Status.
#include "os.h"
#include "safe_map.h"
#include "thread_pool.h"
@@ -47,6 +47,7 @@
namespace art {
namespace mirror {
+class Class;
class DexCache;
} // namespace mirror
@@ -55,18 +56,21 @@
class VerifierDepsTest;
} // namespace verifier
+class ArtField;
class BitVector;
class CompiledMethod;
class CompilerOptions;
class DexCompilationUnit;
+template<class T> class Handle;
struct InlineIGetIPutData;
class InstructionSetFeatures;
class InternTable;
enum InvokeType : uint32_t;
+class MemberOffset;
+template<class MirrorType> class ObjPtr;
class ParallelCompilationManager;
class ScopedObjectAccess;
template <class Allocator> class SrcMap;
-template<class T> class Handle;
class TimingLogger;
class VdexFile;
class VerificationResults;
@@ -152,8 +156,8 @@
std::unique_ptr<const std::vector<uint8_t>> CreateQuickResolutionTrampoline() const;
std::unique_ptr<const std::vector<uint8_t>> CreateQuickToInterpreterBridge() const;
- mirror::Class::Status GetClassStatus(const ClassReference& ref) const;
- bool GetCompiledClass(const ClassReference& ref, mirror::Class::Status* status) const;
+ ClassStatus GetClassStatus(const ClassReference& ref) const;
+ bool GetCompiledClass(const ClassReference& ref, ClassStatus* status) const;
CompiledMethod* GetCompiledMethod(MethodReference ref) const;
size_t GetNonRelativeLinkerPatchCount() const;
@@ -321,7 +325,7 @@
// according to the profile file.
bool ShouldVerifyClassBasedOnProfile(const DexFile& dex_file, uint16_t class_idx) const;
- void RecordClassStatus(const ClassReference& ref, mirror::Class::Status status);
+ void RecordClassStatus(const ClassReference& ref, ClassStatus status);
// Checks if the specified method has been verified without failures. Returns
// false if the method is not in the verification results (GetVerificationResults).
@@ -476,7 +480,7 @@
GUARDED_BY(requires_constructor_barrier_lock_);
// All class references that this compiler has compiled. Indexed by class defs.
- using ClassStateTable = AtomicDexRefMap<ClassReference, mirror::Class::Status>;
+ using ClassStateTable = AtomicDexRefMap<ClassReference, ClassStatus>;
ClassStateTable compiled_classes_;
// All class references that are in the classpath. Indexed by class defs.
ClassStateTable classpath_classes_;
diff --git a/compiler/driver/compiler_driver_test.cc b/compiler/driver/compiler_driver_test.cc
index 278358b..2698574 100644
--- a/compiler/driver/compiler_driver_test.cc
+++ b/compiler/driver/compiler_driver_test.cc
@@ -16,11 +16,13 @@
#include "driver/compiler_driver.h"
+#include <limits>
#include <stdint.h>
#include <stdio.h>
#include <memory>
#include "art_method-inl.h"
+#include "base/casts.h"
#include "class_linker-inl.h"
#include "common_compiler_test.h"
#include "compiler_callbacks.h"
@@ -344,11 +346,11 @@
ASSERT_NE(klass, nullptr);
EXPECT_TRUE(klass->IsVerified());
- mirror::Class::Status status;
+ ClassStatus status;
bool found = compiler_driver_->GetCompiledClass(
ClassReference(&klass->GetDexFile(), klass->GetDexTypeIndex().index_), &status);
ASSERT_TRUE(found);
- EXPECT_EQ(status, mirror::Class::kStatusVerified);
+ EXPECT_EQ(status, ClassStatus::kVerified);
}
};
@@ -367,8 +369,8 @@
CheckVerifiedClass(class_loader, "LSecond;");
}
-// Test that a class of status kStatusRetryVerificationAtRuntime is indeed recorded that way in the
-// driver.
+// Test that a class of status ClassStatus::kRetryVerificationAtRuntime is indeed
+// recorded that way in the driver.
TEST_F(CompilerDriverVerifyTest, RetryVerifcationStatusCheckVerified) {
Thread* const self = Thread::Current();
jobject class_loader;
@@ -386,17 +388,19 @@
callbacks_->SetDoesClassUnloading(true, compiler_driver_.get());
ClassReference ref(dex_file, 0u);
// Test that the status is read from the compiler driver as expected.
- for (size_t i = mirror::Class::kStatusRetryVerificationAtRuntime;
- i < mirror::Class::kStatusMax;
- ++i) {
- const mirror::Class::Status expected_status = static_cast<mirror::Class::Status>(i);
+ static_assert(enum_cast<size_t>(ClassStatus::kLast) < std::numeric_limits<size_t>::max(),
+ "Make sure incrementing the class status does not overflow.");
+ for (size_t i = enum_cast<size_t>(ClassStatus::kRetryVerificationAtRuntime);
+ i <= enum_cast<size_t>(ClassStatus::kLast);
+ ++i) {
+ const ClassStatus expected_status = enum_cast<ClassStatus>(i);
// Skip unsupported status that are not supposed to be ever recorded.
- if (expected_status == mirror::Class::kStatusVerifyingAtRuntime ||
- expected_status == mirror::Class::kStatusInitializing) {
+ if (expected_status == ClassStatus::kVerifyingAtRuntime ||
+ expected_status == ClassStatus::kInitializing) {
continue;
}
compiler_driver_->RecordClassStatus(ref, expected_status);
- mirror::Class::Status status = {};
+ ClassStatus status = {};
ASSERT_TRUE(compiler_driver_->GetCompiledClass(ref, &status));
EXPECT_EQ(status, expected_status);
}
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index f9dcb5d..13886b3 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -2103,9 +2103,8 @@
// TODO(vixl): Let the MacroAssembler handle MemOperand.
__ Add(temp, class_reg, status_offset);
__ Ldarb(temp, HeapOperand(temp));
- __ Cmp(temp, mirror::Class::kStatusInitialized);
- __ B(ne, slow_path->GetEntryLabel());
- // Use Bne instead of Blt because ARM64 doesn't have Ldarsb.
+ __ Cmp(temp, enum_cast<>(ClassStatus::kInitialized));
+ __ B(lo, slow_path->GetEntryLabel());
__ Bind(slow_path->GetExitLabel());
}
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index c6e1b04..7f83533 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -7173,12 +7173,12 @@
LoadClassSlowPathARMVIXL* slow_path, vixl32::Register class_reg) {
UseScratchRegisterScope temps(GetVIXLAssembler());
vixl32::Register temp = temps.Acquire();
- GetAssembler()->LoadFromOffset(kLoadSignedByte,
+ GetAssembler()->LoadFromOffset(kLoadUnsignedByte,
temp,
class_reg,
mirror::Class::StatusOffset().Int32Value());
- __ Cmp(temp, mirror::Class::kStatusInitialized);
- __ B(lt, slow_path->GetEntryLabel());
+ __ Cmp(temp, enum_cast<>(ClassStatus::kInitialized));
+ __ B(lo, slow_path->GetEntryLabel());
// Even if the initialized flag is set, we may be in a situation where caches are not synced
// properly. Therefore, we do a memory fence.
__ Dmb(ISH);
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index c4772ad..ebe252a 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -1915,9 +1915,9 @@
void InstructionCodeGeneratorMIPS::GenerateClassInitializationCheck(SlowPathCodeMIPS* slow_path,
Register class_reg) {
- __ LoadFromOffset(kLoadSignedByte, TMP, class_reg, mirror::Class::StatusOffset().Int32Value());
- __ LoadConst32(AT, mirror::Class::kStatusInitialized);
- __ Blt(TMP, AT, slow_path->GetEntryLabel());
+ __ LoadFromOffset(kLoadUnsignedByte, TMP, class_reg, mirror::Class::StatusOffset().Int32Value());
+ __ LoadConst32(AT, enum_cast<>(ClassStatus::kInitialized));
+ __ Bltu(TMP, AT, slow_path->GetEntryLabel());
// Even if the initialized flag is set, we need to ensure consistent memory ordering.
__ Sync(0);
__ Bind(slow_path->GetExitLabel());
diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc
index c8891ed..3ea7b82 100644
--- a/compiler/optimizing/code_generator_mips64.cc
+++ b/compiler/optimizing/code_generator_mips64.cc
@@ -1761,9 +1761,9 @@
void InstructionCodeGeneratorMIPS64::GenerateClassInitializationCheck(SlowPathCodeMIPS64* slow_path,
GpuRegister class_reg) {
- __ LoadFromOffset(kLoadSignedByte, TMP, class_reg, mirror::Class::StatusOffset().Int32Value());
- __ LoadConst32(AT, mirror::Class::kStatusInitialized);
- __ Bltc(TMP, AT, slow_path->GetEntryLabel());
+ __ LoadFromOffset(kLoadUnsignedByte, TMP, class_reg, mirror::Class::StatusOffset().Int32Value());
+ __ LoadConst32(AT, enum_cast<>(ClassStatus::kInitialized));
+ __ Bltuc(TMP, AT, slow_path->GetEntryLabel());
// Even if the initialized flag is set, we need to ensure consistent memory ordering.
__ Sync(0);
__ Bind(slow_path->GetExitLabel());
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index ba222fe..6853238 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -6220,8 +6220,8 @@
void InstructionCodeGeneratorX86::GenerateClassInitializationCheck(
SlowPathCode* slow_path, Register class_reg) {
__ cmpb(Address(class_reg, mirror::Class::StatusOffset().Int32Value()),
- Immediate(mirror::Class::kStatusInitialized));
- __ j(kLess, slow_path->GetEntryLabel());
+ Immediate(enum_cast<>(ClassStatus::kInitialized)));
+ __ j(kBelow, slow_path->GetEntryLabel());
__ Bind(slow_path->GetExitLabel());
// No need for memory fence, thanks to the X86 memory model.
}
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index caad788..1f8d822 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -5426,8 +5426,8 @@
void InstructionCodeGeneratorX86_64::GenerateClassInitializationCheck(
SlowPathCode* slow_path, CpuRegister class_reg) {
__ cmpb(Address(class_reg, mirror::Class::StatusOffset().Int32Value()),
- Immediate(mirror::Class::kStatusInitialized));
- __ j(kLess, slow_path->GetEntryLabel());
+ Immediate(enum_cast<>(ClassStatus::kInitialized)));
+ __ j(kBelow, slow_path->GetEntryLabel());
__ Bind(slow_path->GetExitLabel());
// No need for memory fence, thanks to the x86-64 memory model.
}
diff --git a/compiler/trampolines/trampoline_compiler.h b/compiler/trampolines/trampoline_compiler.h
index 1a10e4c..64c1eb5 100644
--- a/compiler/trampolines/trampoline_compiler.h
+++ b/compiler/trampolines/trampoline_compiler.h
@@ -21,6 +21,7 @@
#include <vector>
#include "driver/compiler_driver.h"
+#include "offsets.h"
namespace art {
diff --git a/compiler/verifier_deps_test.cc b/compiler/verifier_deps_test.cc
index ee1d7c6..d77842a 100644
--- a/compiler/verifier_deps_test.cc
+++ b/compiler/verifier_deps_test.cc
@@ -237,9 +237,9 @@
CHECK(soa.Self()->IsExceptionPending());
soa.Self()->ClearException();
} else if (unverified_classes.find(class_def.class_idx_) == unverified_classes.end()) {
- ASSERT_EQ(cls->GetStatus(), mirror::Class::kStatusVerified);
+ ASSERT_EQ(cls->GetStatus(), ClassStatus::kVerified);
} else {
- ASSERT_LT(cls->GetStatus(), mirror::Class::kStatusVerified);
+ ASSERT_LT(cls->GetStatus(), ClassStatus::kVerified);
}
}
}
diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc
index 738bbf8..363cb8b 100644
--- a/dex2oat/linker/image_writer.cc
+++ b/dex2oat/linker/image_writer.cc
@@ -585,7 +585,7 @@
if (dirty_image_objects_ != nullptr &&
dirty_image_objects_->find(klass->PrettyDescriptor()) != dirty_image_objects_->end()) {
bin = Bin::kKnownDirty;
- } else if (klass->GetStatus() == Class::kStatusInitialized) {
+ } else if (klass->GetStatus() == ClassStatus::kInitialized) {
bin = Bin::kClassInitialized;
// If the class's static fields are all final, put it into a separate bin
@@ -650,7 +650,7 @@
}
mirror::Class* declaring_class = m->GetDeclaringClass();
// Initialized is highly unlikely to dirty since there's no entry points to mutate.
- return declaring_class == nullptr || declaring_class->GetStatus() != Class::kStatusInitialized;
+ return declaring_class == nullptr || declaring_class->GetStatus() != ClassStatus::kInitialized;
}
bool ImageWriter::IsImageBinSlotAssigned(mirror::Object* object) const {
diff --git a/dex2oat/linker/image_writer.h b/dex2oat/linker/image_writer.h
index 3aceceb..a7c1439 100644
--- a/dex2oat/linker/image_writer.h
+++ b/dex2oat/linker/image_writer.h
@@ -62,6 +62,7 @@
} // namespace mirror
class ClassLoaderVisitor;
+class ImTable;
class ImtConflictTable;
static constexpr int kInvalidFd = -1;
diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc
index d261679..016a114 100644
--- a/dex2oat/linker/oat_writer.cc
+++ b/dex2oat/linker/oat_writer.cc
@@ -188,8 +188,8 @@
OatClassHeader(uint32_t offset,
uint32_t num_non_null_compiled_methods,
uint32_t num_methods,
- mirror::Class::Status status)
- : status_(status),
+ ClassStatus status)
+ : status_(enum_cast<uint16_t>(status)),
offset_(offset) {
// We just arbitrarily say that 0 methods means kOatClassNoneCompiled and that we won't use
// kOatClassAllCompiled unless there is at least one compiled method. This means in an
@@ -210,8 +210,8 @@
}
// Data to write.
- static_assert(mirror::Class::Status::kStatusMax < (1 << 16), "class status won't fit in 16bits");
- int16_t status_;
+ static_assert(enum_cast<>(ClassStatus::kLast) < (1 << 16), "class status won't fit in 16bits");
+ uint16_t status_;
static_assert(OatClassType::kOatClassMax < (1 << 16), "oat_class type won't fit in 16bits");
uint16_t type_;
@@ -931,17 +931,17 @@
bool EndClass() OVERRIDE {
ClassReference class_ref(dex_file_, class_def_index_);
- mirror::Class::Status status;
+ ClassStatus status;
bool found = writer_->compiler_driver_->GetCompiledClass(class_ref, &status);
if (!found) {
VerificationResults* results = writer_->compiler_driver_->GetVerificationResults();
if (results != nullptr && results->IsClassRejected(class_ref)) {
// The oat class status is used only for verification of resolved classes,
- // so use kStatusErrorResolved whether the class was resolved or unresolved
+ // so use ClassStatus::kErrorResolved whether the class was resolved or unresolved
// during compile-time verification.
- status = mirror::Class::kStatusErrorResolved;
+ status = ClassStatus::kErrorResolved;
} else {
- status = mirror::Class::kStatusNotReady;
+ status = ClassStatus::kNotReady;
}
}
diff --git a/dex2oat/linker/oat_writer_test.cc b/dex2oat/linker/oat_writer_test.cc
index e9958b1..44c2f89 100644
--- a/dex2oat/linker/oat_writer_test.cc
+++ b/dex2oat/linker/oat_writer_test.cc
@@ -455,7 +455,7 @@
ScopedNullHandle<mirror::ClassLoader>());
const OatFile::OatClass oat_class = oat_dex_file->GetOatClass(i);
- CHECK_EQ(mirror::Class::Status::kStatusNotReady, oat_class.GetStatus()) << descriptor;
+ CHECK_EQ(ClassStatus::kNotReady, oat_class.GetStatus()) << descriptor;
CHECK_EQ(kCompile ? OatClassType::kOatClassAllCompiled : OatClassType::kOatClassNoneCompiled,
oat_class.GetType()) << descriptor;
diff --git a/runtime/aot_class_linker.cc b/runtime/aot_class_linker.cc
index a62cbec..93e02ef 100644
--- a/runtime/aot_class_linker.cc
+++ b/runtime/aot_class_linker.cc
@@ -44,7 +44,7 @@
// Don't initialize klass if it's superclass is not initialized, because superclass might abort
// the transaction and rolled back after klass's change is commited.
if (strict_mode_ && !klass->IsInterface() && klass->HasSuperClass()) {
- if (klass->GetSuperClass()->GetStatus() == mirror::Class::kStatusInitializing) {
+ if (klass->GetSuperClass()->GetStatus() == ClassStatus::kInitializing) {
runtime->AbortTransactionAndThrowAbortError(self, "Can't resolve "
+ klass->PrettyTypeOf() + " because it's superclass is not initialized.");
return false;
@@ -79,11 +79,11 @@
ClassStatus old_status = callbacks->GetPreviousClassState(
ClassReference(&klass->GetDexFile(), klass->GetDexClassDefIndex()));
// Was it verified? Report no failure.
- if (old_status >= ClassStatus::kStatusVerified) {
+ if (old_status >= ClassStatus::kVerified) {
return verifier::FailureKind::kNoFailure;
}
// Does it need to be verified at runtime? Report soft failure.
- if (old_status >= ClassStatus::kStatusRetryVerificationAtRuntime) {
+ if (old_status >= ClassStatus::kRetryVerificationAtRuntime) {
// Error messages from here are only reported through -verbose:class. It is not worth it to
// create a message.
return verifier::FailureKind::kSoftFailure;
diff --git a/runtime/base/casts.h b/runtime/base/casts.h
index ac1a10c..3c6b2be 100644
--- a/runtime/base/casts.h
+++ b/runtime/base/casts.h
@@ -26,6 +26,8 @@
#include <android-base/logging.h>
+#include "stl_util_identity.h"
+
namespace art {
// Use implicit_cast as a safe version of static_cast or const_cast
@@ -97,7 +99,7 @@
// A version of static_cast that DCHECKs that the value can be precisely represented
// when converting to Dest.
template <typename Dest, typename Source>
-inline Dest dchecked_integral_cast(const Source source) {
+constexpr Dest dchecked_integral_cast(Source source) {
DCHECK(
// Check that the value is within the lower limit of Dest.
(static_cast<intmax_t>(std::numeric_limits<Dest>::min()) <=
@@ -113,6 +115,33 @@
return static_cast<Dest>(source);
}
+// A version of dchecked_integral_cast casting between an integral type and an enum type.
+// When casting to an enum type, the cast does not check if the value corresponds to an enumerator.
+// When casting from an enum type, the target type can be omitted and the enum's underlying type
+// shall be used.
+
+template <typename Dest, typename Source>
+constexpr
+typename std::enable_if<!std::is_enum<Source>::value, Dest>::type
+enum_cast(Source value) {
+ return static_cast<Dest>(
+ dchecked_integral_cast<typename std::underlying_type<Dest>::type>(value));
+}
+
+template <typename Dest = void, typename Source>
+constexpr
+typename std::enable_if<std::is_enum<Source>::value,
+ typename std::conditional<std::is_same<Dest, void>::value,
+ std::underlying_type<Source>,
+ Identity<Dest>>::type>::type::type
+enum_cast(Source value) {
+ using return_type = typename std::conditional<std::is_same<Dest, void>::value,
+ std::underlying_type<Source>,
+ Identity<Dest>>::type::type;
+ return dchecked_integral_cast<return_type>(
+ static_cast<typename std::underlying_type<Source>::type>(value));
+}
+
// A version of reinterpret_cast<>() between pointers and int64_t/uint64_t
// that goes through uintptr_t to avoid treating the pointer as "signed."
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 727dd14..7c0c68a 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -445,7 +445,7 @@
CHECK(java_lang_Object != nullptr);
// backfill Object as the super class of Class.
java_lang_Class->SetSuperClass(java_lang_Object.Get());
- mirror::Class::SetStatus(java_lang_Object, mirror::Class::kStatusLoaded, self);
+ mirror::Class::SetStatus(java_lang_Object, ClassStatus::kLoaded, self);
java_lang_Object->SetObjectSize(sizeof(mirror::Object));
// Allocate in non-movable so that it's possible to check if a JNI weak global ref has been
@@ -494,14 +494,14 @@
AllocClass(self, java_lang_Class.Get(), mirror::String::ClassSize(image_pointer_size_))));
java_lang_String->SetStringClass();
mirror::String::SetClass(java_lang_String.Get());
- mirror::Class::SetStatus(java_lang_String, mirror::Class::kStatusResolved, self);
+ mirror::Class::SetStatus(java_lang_String, ClassStatus::kResolved, self);
// Setup java.lang.ref.Reference.
Handle<mirror::Class> java_lang_ref_Reference(hs.NewHandle(
AllocClass(self, java_lang_Class.Get(), mirror::Reference::ClassSize(image_pointer_size_))));
mirror::Reference::SetClass(java_lang_ref_Reference.Get());
java_lang_ref_Reference->SetObjectSize(mirror::Reference::InstanceSize());
- mirror::Class::SetStatus(java_lang_ref_Reference, mirror::Class::kStatusResolved, self);
+ mirror::Class::SetStatus(java_lang_ref_Reference, ClassStatus::kResolved, self);
// Create storage for root classes, save away our work so far (requires descriptors).
class_roots_ = GcRoot<mirror::ObjectArray<mirror::Class>>(
@@ -554,7 +554,7 @@
SetClassRoot(kJavaLangDexCache, java_lang_DexCache.Get());
java_lang_DexCache->SetDexCacheClass();
java_lang_DexCache->SetObjectSize(mirror::DexCache::InstanceSize());
- mirror::Class::SetStatus(java_lang_DexCache, mirror::Class::kStatusResolved, self);
+ mirror::Class::SetStatus(java_lang_DexCache, ClassStatus::kResolved, self);
// Setup dalvik.system.ClassExt
@@ -562,7 +562,7 @@
AllocClass(self, java_lang_Class.Get(), mirror::ClassExt::ClassSize(image_pointer_size_))));
SetClassRoot(kDalvikSystemClassExt, dalvik_system_ClassExt.Get());
mirror::ClassExt::SetClass(dalvik_system_ClassExt.Get());
- mirror::Class::SetStatus(dalvik_system_ClassExt, mirror::Class::kStatusResolved, self);
+ mirror::Class::SetStatus(dalvik_system_ClassExt, ClassStatus::kResolved, self);
// Set up array classes for string, field, method
Handle<mirror::Class> object_array_string(hs.NewHandle(
@@ -610,15 +610,15 @@
}
// Object, String, ClassExt and DexCache need to be rerun through FindSystemClass to finish init
- mirror::Class::SetStatus(java_lang_Object, mirror::Class::kStatusNotReady, self);
+ mirror::Class::SetStatus(java_lang_Object, ClassStatus::kNotReady, self);
CheckSystemClass(self, java_lang_Object, "Ljava/lang/Object;");
CHECK_EQ(java_lang_Object->GetObjectSize(), mirror::Object::InstanceSize());
- mirror::Class::SetStatus(java_lang_String, mirror::Class::kStatusNotReady, self);
+ mirror::Class::SetStatus(java_lang_String, ClassStatus::kNotReady, self);
CheckSystemClass(self, java_lang_String, "Ljava/lang/String;");
- mirror::Class::SetStatus(java_lang_DexCache, mirror::Class::kStatusNotReady, self);
+ mirror::Class::SetStatus(java_lang_DexCache, ClassStatus::kNotReady, self);
CheckSystemClass(self, java_lang_DexCache, "Ljava/lang/DexCache;");
CHECK_EQ(java_lang_DexCache->GetObjectSize(), mirror::DexCache::InstanceSize());
- mirror::Class::SetStatus(dalvik_system_ClassExt, mirror::Class::kStatusNotReady, self);
+ mirror::Class::SetStatus(dalvik_system_ClassExt, ClassStatus::kNotReady, self);
CheckSystemClass(self, dalvik_system_ClassExt, "Ldalvik/system/ClassExt;");
CHECK_EQ(dalvik_system_ClassExt->GetObjectSize(), mirror::ClassExt::InstanceSize());
@@ -772,7 +772,7 @@
// java.lang.ref classes need to be specially flagged, but otherwise are normal classes
// finish initializing Reference class
- mirror::Class::SetStatus(java_lang_ref_Reference, mirror::Class::kStatusNotReady, self);
+ mirror::Class::SetStatus(java_lang_ref_Reference, ClassStatus::kNotReady, self);
CheckSystemClass(self, java_lang_ref_Reference, "Ljava/lang/ref/Reference;");
CHECK_EQ(java_lang_ref_Reference->GetObjectSize(), mirror::Reference::InstanceSize());
CHECK_EQ(java_lang_ref_Reference->GetClassSize(),
@@ -2309,7 +2309,7 @@
// Check for circular dependencies between classes, the lock is required for SetStatus.
if (!h_class->IsResolved() && h_class->GetClinitThreadId() == self->GetTid()) {
ThrowClassCircularityError(h_class.Get());
- mirror::Class::SetStatus(h_class, mirror::Class::kStatusErrorUnresolved, self);
+ mirror::Class::SetStatus(h_class, ClassStatus::kErrorUnresolved, self);
return nullptr;
}
}
@@ -2771,7 +2771,7 @@
// An exception occured during load, set status to erroneous while holding klass' lock in case
// notification is necessary.
if (!klass->IsErroneous()) {
- mirror::Class::SetStatus(klass, mirror::Class::kStatusErrorUnresolved, self);
+ mirror::Class::SetStatus(klass, ClassStatus::kErrorUnresolved, self);
}
return nullptr;
}
@@ -2781,7 +2781,7 @@
if (!LoadSuperAndInterfaces(klass, *new_dex_file)) {
// Loading failed.
if (!klass->IsErroneous()) {
- mirror::Class::SetStatus(klass, mirror::Class::kStatusErrorUnresolved, self);
+ mirror::Class::SetStatus(klass, ClassStatus::kErrorUnresolved, self);
}
return nullptr;
}
@@ -2800,7 +2800,7 @@
if (!LinkClass(self, descriptor, klass, interfaces, &h_new_class)) {
// Linking failed.
if (!klass->IsErroneous()) {
- mirror::Class::SetStatus(klass, mirror::Class::kStatusErrorUnresolved, self);
+ mirror::Class::SetStatus(klass, ClassStatus::kErrorUnresolved, self);
}
return nullptr;
}
@@ -3087,7 +3087,7 @@
ObjPtr<mirror::ClassLoader> class_loader) {
CHECK(klass != nullptr);
CHECK(klass->GetDexCache() != nullptr);
- CHECK_EQ(mirror::Class::kStatusNotReady, klass->GetStatus());
+ CHECK_EQ(ClassStatus::kNotReady, klass->GetStatus());
const char* descriptor = dex_file.GetClassDescriptor(dex_class_def);
CHECK(descriptor != nullptr);
@@ -3097,7 +3097,7 @@
klass->SetAccessFlags(access_flags);
klass->SetClassLoader(class_loader);
DCHECK_EQ(klass->GetPrimitiveType(), Primitive::kPrimNot);
- mirror::Class::SetStatus(klass, mirror::Class::kStatusIdx, nullptr);
+ mirror::Class::SetStatus(klass, ClassStatus::kIdx, nullptr);
klass->SetDexClassDefIndex(dex_file.GetIndexForClassDef(dex_class_def));
klass->SetDexTypeIndex(dex_class_def.class_idx_);
@@ -3623,7 +3623,7 @@
h_class->SetAccessFlags(kAccPublic | kAccFinal | kAccAbstract);
h_class->SetPrimitiveType(type);
h_class->SetIfTable(GetClassRoot(kJavaLangObject)->GetIfTable());
- mirror::Class::SetStatus(h_class, mirror::Class::kStatusInitialized, self);
+ mirror::Class::SetStatus(h_class, ClassStatus::kInitialized, self);
const char* descriptor = Primitive::Descriptor(type);
ObjPtr<mirror::Class> existing = InsertClass(descriptor,
h_class.Get(),
@@ -3738,11 +3738,11 @@
} else {
new_class->SetClassFlags(mirror::kClassFlagObjectArray);
}
- mirror::Class::SetStatus(new_class, mirror::Class::kStatusLoaded, self);
+ mirror::Class::SetStatus(new_class, ClassStatus::kLoaded, self);
new_class->PopulateEmbeddedVTable(image_pointer_size_);
ImTable* object_imt = java_lang_Object->GetImt(image_pointer_size_);
new_class->SetImt(object_imt, image_pointer_size_);
- mirror::Class::SetStatus(new_class, mirror::Class::kStatusInitialized, self);
+ mirror::Class::SetStatus(new_class, ClassStatus::kInitialized, self);
// don't need to set new_class->SetObjectSize(..)
// because Object::SizeOf delegates to Array::SizeOf
@@ -4000,7 +4000,7 @@
}
// Need to grab the lock to change status.
ObjectLock<mirror::Class> super_lock(self, klass);
- mirror::Class::SetStatus(klass, mirror::Class::kStatusErrorResolved, self);
+ mirror::Class::SetStatus(klass, ClassStatus::kErrorResolved, self);
return false;
}
@@ -4022,9 +4022,9 @@
ObjectLock<mirror::Class> lock(self, klass);
// Is somebody verifying this now?
- mirror::Class::Status old_status = klass->GetStatus();
- while (old_status == mirror::Class::kStatusVerifying ||
- old_status == mirror::Class::kStatusVerifyingAtRuntime) {
+ ClassStatus old_status = klass->GetStatus();
+ while (old_status == ClassStatus::kVerifying ||
+ old_status == ClassStatus::kVerifyingAtRuntime) {
lock.WaitIgnoringInterrupts();
// WaitIgnoringInterrupts can still receive an interrupt and return early, in this
// case we may see the same status again. b/62912904. This is why the check is
@@ -4055,18 +4055,18 @@
return verifier::FailureKind::kSoftFailure;
}
- if (klass->GetStatus() == mirror::Class::kStatusResolved) {
- mirror::Class::SetStatus(klass, mirror::Class::kStatusVerifying, self);
+ if (klass->GetStatus() == ClassStatus::kResolved) {
+ mirror::Class::SetStatus(klass, ClassStatus::kVerifying, self);
} else {
- CHECK_EQ(klass->GetStatus(), mirror::Class::kStatusRetryVerificationAtRuntime)
+ CHECK_EQ(klass->GetStatus(), ClassStatus::kRetryVerificationAtRuntime)
<< klass->PrettyClass();
CHECK(!Runtime::Current()->IsAotCompiler());
- mirror::Class::SetStatus(klass, mirror::Class::kStatusVerifyingAtRuntime, self);
+ mirror::Class::SetStatus(klass, ClassStatus::kVerifyingAtRuntime, self);
}
// Skip verification if disabled.
if (!Runtime::Current()->IsVerificationEnabled()) {
- mirror::Class::SetStatus(klass, mirror::Class::kStatusVerified, self);
+ mirror::Class::SetStatus(klass, ClassStatus::kVerified, self);
EnsureSkipAccessChecksMethods(klass, image_pointer_size_);
return verifier::FailureKind::kNoFailure;
}
@@ -4128,7 +4128,7 @@
// Try to use verification information from the oat file, otherwise do runtime verification.
const DexFile& dex_file = *klass->GetDexCache()->GetDexFile();
- mirror::Class::Status oat_file_class_status(mirror::Class::kStatusNotReady);
+ ClassStatus oat_file_class_status(ClassStatus::kNotReady);
bool preverified = VerifyClassUsingOatFile(dex_file, klass.Get(), oat_file_class_status);
VLOG(class_linker) << "Class preverified status for class "
@@ -4165,10 +4165,10 @@
// Even though there were no verifier failures we need to respect whether the super-class and
// super-default-interfaces were verified or requiring runtime reverification.
if (supertype == nullptr || supertype->IsVerified()) {
- mirror::Class::SetStatus(klass, mirror::Class::kStatusVerified, self);
+ mirror::Class::SetStatus(klass, ClassStatus::kVerified, self);
} else {
- CHECK_EQ(supertype->GetStatus(), mirror::Class::kStatusRetryVerificationAtRuntime);
- mirror::Class::SetStatus(klass, mirror::Class::kStatusRetryVerificationAtRuntime, self);
+ CHECK_EQ(supertype->GetStatus(), ClassStatus::kRetryVerificationAtRuntime);
+ mirror::Class::SetStatus(klass, ClassStatus::kRetryVerificationAtRuntime, self);
// Pretend a soft failure occurred so that we don't consider the class verified below.
verifier_failure = verifier::FailureKind::kSoftFailure;
}
@@ -4178,9 +4178,9 @@
// failures at runtime will be handled by slow paths in the generated
// code. Set status accordingly.
if (Runtime::Current()->IsAotCompiler()) {
- mirror::Class::SetStatus(klass, mirror::Class::kStatusRetryVerificationAtRuntime, self);
+ mirror::Class::SetStatus(klass, ClassStatus::kRetryVerificationAtRuntime, self);
} else {
- mirror::Class::SetStatus(klass, mirror::Class::kStatusVerified, self);
+ mirror::Class::SetStatus(klass, ClassStatus::kVerified, self);
// As this is a fake verified status, make sure the methods are _not_ marked
// kAccSkipAccessChecks later.
klass->SetVerificationAttempted();
@@ -4192,7 +4192,7 @@
<< " because: " << error_msg;
self->AssertNoPendingException();
ThrowVerifyError(klass.Get(), "%s", error_msg.c_str());
- mirror::Class::SetStatus(klass, mirror::Class::kStatusErrorResolved, self);
+ mirror::Class::SetStatus(klass, ClassStatus::kErrorResolved, self);
}
if (preverified || verifier_failure == verifier::FailureKind::kNoFailure) {
// Class is verified so we don't need to do any access check on its methods.
@@ -4234,7 +4234,7 @@
bool ClassLinker::VerifyClassUsingOatFile(const DexFile& dex_file,
ObjPtr<mirror::Class> klass,
- mirror::Class::Status& oat_file_class_status) {
+ ClassStatus& oat_file_class_status) {
// If we're compiling, we can only verify the class using the oat file if
// we are not compiling the image or if the class we're verifying is not part of
// the app. In other words, we will only check for preverification of bootclasspath
@@ -4260,15 +4260,15 @@
uint16_t class_def_index = klass->GetDexClassDefIndex();
oat_file_class_status = oat_dex_file->GetOatClass(class_def_index).GetStatus();
- if (oat_file_class_status >= mirror::Class::kStatusVerified) {
+ if (oat_file_class_status >= ClassStatus::kVerified) {
return true;
}
// If we only verified a subset of the classes at compile time, we can end up with classes that
// were resolved by the verifier.
- if (oat_file_class_status == mirror::Class::kStatusResolved) {
+ if (oat_file_class_status == ClassStatus::kResolved) {
return false;
}
- if (oat_file_class_status == mirror::Class::kStatusRetryVerificationAtRuntime) {
+ if (oat_file_class_status == ClassStatus::kRetryVerificationAtRuntime) {
// Compile time verification failed with a soft error. Compile time verification can fail
// because we have incomplete type information. Consider the following:
// class ... {
@@ -4293,7 +4293,7 @@
// in the class. These errors are unrecoverable.
return false;
}
- if (oat_file_class_status == mirror::Class::kStatusNotReady) {
+ if (oat_file_class_status == ClassStatus::kNotReady) {
// Status is uninitialized if we couldn't determine the status at compile time, for example,
// not loading the class.
// TODO: when the verifier doesn't rely on Class-es failing to resolve/load the type hierarchy
@@ -4366,7 +4366,7 @@
temp_klass->SetDexCache(GetClassRoot(kJavaLangReflectProxy)->GetDexCache());
// Object has an empty iftable, copy it for that reason.
temp_klass->SetIfTable(GetClassRoot(kJavaLangObject)->GetIfTable());
- mirror::Class::SetStatus(temp_klass, mirror::Class::kStatusIdx, self);
+ mirror::Class::SetStatus(temp_klass, ClassStatus::kIdx, self);
std::string descriptor(GetDescriptorForProxy(temp_klass.Get()));
const size_t hash = ComputeModifiedUtf8Hash(descriptor.c_str());
@@ -4434,7 +4434,7 @@
// The super class is java.lang.reflect.Proxy
temp_klass->SetSuperClass(GetClassRoot(kJavaLangReflectProxy));
// Now effectively in the loaded state.
- mirror::Class::SetStatus(temp_klass, mirror::Class::kStatusLoaded, self);
+ mirror::Class::SetStatus(temp_klass, ClassStatus::kLoaded, self);
self->AssertNoPendingException();
// At this point the class is loaded. Publish a ClassLoad event.
@@ -4450,7 +4450,7 @@
Handle<mirror::ObjectArray<mirror::Class>> h_interfaces(
hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Class>>(interfaces)));
if (!LinkClass(self, descriptor.c_str(), temp_klass, h_interfaces, &klass)) {
- mirror::Class::SetStatus(temp_klass, mirror::Class::kStatusErrorUnresolved, self);
+ mirror::Class::SetStatus(temp_klass, ClassStatus::kErrorUnresolved, self);
return nullptr;
}
}
@@ -4471,7 +4471,7 @@
{
// Lock on klass is released. Lock new class object.
ObjectLock<mirror::Class> initialization_lock(self, klass);
- mirror::Class::SetStatus(klass, mirror::Class::kStatusInitialized, self);
+ mirror::Class::SetStatus(klass, ClassStatus::kInitialized, self);
}
// sanity checks
@@ -4687,7 +4687,7 @@
VlogClassInitializationFailure(klass);
} else {
CHECK(Runtime::Current()->IsAotCompiler());
- CHECK_EQ(klass->GetStatus(), mirror::Class::kStatusRetryVerificationAtRuntime);
+ CHECK_EQ(klass->GetStatus(), ClassStatus::kRetryVerificationAtRuntime);
}
return false;
} else {
@@ -4703,12 +4703,12 @@
}
}
- // If the class is kStatusInitializing, either this thread is
+ // If the class is ClassStatus::kInitializing, either this thread is
// initializing higher up the stack or another thread has beat us
// to initializing and we need to wait. Either way, this
// invocation of InitializeClass will not be responsible for
// running <clinit> and will return.
- if (klass->GetStatus() == mirror::Class::kStatusInitializing) {
+ if (klass->GetStatus() == ClassStatus::kInitializing) {
// Could have got an exception during verification.
if (self->IsExceptionPending()) {
VlogClassInitializationFailure(klass);
@@ -4733,20 +4733,20 @@
const OatFile::OatClass oat_class = (runtime->IsStarted() && !runtime->IsAotCompiler())
? OatFile::FindOatClass(klass->GetDexFile(), klass->GetDexClassDefIndex(), &has_oat_class)
: OatFile::OatClass::Invalid();
- if (oat_class.GetStatus() < mirror::Class::kStatusSuperclassValidated &&
+ if (oat_class.GetStatus() < ClassStatus::kSuperclassValidated &&
!ValidateSuperClassDescriptors(klass)) {
- mirror::Class::SetStatus(klass, mirror::Class::kStatusErrorResolved, self);
+ mirror::Class::SetStatus(klass, ClassStatus::kErrorResolved, self);
return false;
}
self->AllowThreadSuspension();
- CHECK_EQ(klass->GetStatus(), mirror::Class::kStatusVerified) << klass->PrettyClass()
+ CHECK_EQ(klass->GetStatus(), ClassStatus::kVerified) << klass->PrettyClass()
<< " self.tid=" << self->GetTid() << " clinit.tid=" << klass->GetClinitThreadId();
// From here out other threads may observe that we're initializing and so changes of state
// require the a notification.
klass->SetClinitThreadId(self->GetTid());
- mirror::Class::SetStatus(klass, mirror::Class::kStatusInitializing, self);
+ mirror::Class::SetStatus(klass, ClassStatus::kInitializing, self);
t0 = NanoTime();
}
@@ -4773,7 +4773,7 @@
<< (self->GetException() != nullptr ? self->GetException()->Dump() : "");
ObjectLock<mirror::Class> lock(self, klass);
// Initialization failed because the super-class is erroneous.
- mirror::Class::SetStatus(klass, mirror::Class::kStatusErrorResolved, self);
+ mirror::Class::SetStatus(klass, ClassStatus::kErrorResolved, self);
return false;
}
}
@@ -4804,7 +4804,7 @@
if (!iface_initialized) {
ObjectLock<mirror::Class> lock(self, klass);
// Initialization failed because one of our interfaces with default methods is erroneous.
- mirror::Class::SetStatus(klass, mirror::Class::kStatusErrorResolved, self);
+ mirror::Class::SetStatus(klass, ClassStatus::kErrorResolved, self);
return false;
}
}
@@ -4876,7 +4876,7 @@
if (self->IsExceptionPending()) {
WrapExceptionInInitializer(klass);
- mirror::Class::SetStatus(klass, mirror::Class::kStatusErrorResolved, self);
+ mirror::Class::SetStatus(klass, ClassStatus::kErrorResolved, self);
success = false;
} else if (Runtime::Current()->IsTransactionAborted()) {
// The exception thrown when the transaction aborted has been caught and cleared
@@ -4885,7 +4885,7 @@
<< mirror::Class::PrettyDescriptor(klass.Get())
<< " without exception while transaction was aborted: re-throw it now.";
Runtime::Current()->ThrowTransactionAbortError(self);
- mirror::Class::SetStatus(klass, mirror::Class::kStatusErrorResolved, self);
+ mirror::Class::SetStatus(klass, ClassStatus::kErrorResolved, self);
success = false;
} else {
RuntimeStats* global_stats = Runtime::Current()->GetStats();
@@ -4895,7 +4895,7 @@
global_stats->class_init_time_ns += (t1 - t0);
thread_stats->class_init_time_ns += (t1 - t0);
// Set the class as initialized except if failed to initialize static fields.
- mirror::Class::SetStatus(klass, mirror::Class::kStatusInitialized, self);
+ mirror::Class::SetStatus(klass, ClassStatus::kInitialized, self);
if (VLOG_IS_ON(class_linker)) {
std::string temp;
LOG(INFO) << "Initialized class " << klass->GetDescriptor(&temp) << " from " <<
@@ -4969,14 +4969,14 @@
// we were not using WaitIgnoringInterrupts), bail out.
if (self->IsExceptionPending()) {
WrapExceptionInInitializer(klass);
- mirror::Class::SetStatus(klass, mirror::Class::kStatusErrorResolved, self);
+ mirror::Class::SetStatus(klass, ClassStatus::kErrorResolved, self);
return false;
}
// Spurious wakeup? Go back to waiting.
- if (klass->GetStatus() == mirror::Class::kStatusInitializing) {
+ if (klass->GetStatus() == ClassStatus::kInitializing) {
continue;
}
- if (klass->GetStatus() == mirror::Class::kStatusVerified &&
+ if (klass->GetStatus() == ClassStatus::kVerified &&
Runtime::Current()->IsAotCompiler()) {
// Compile time initialization failed.
return false;
@@ -5309,7 +5309,7 @@
Handle<mirror::Class> klass,
Handle<mirror::ObjectArray<mirror::Class>> interfaces,
MutableHandle<mirror::Class>* h_new_class_out) {
- CHECK_EQ(mirror::Class::kStatusLoaded, klass->GetStatus());
+ CHECK_EQ(ClassStatus::kLoaded, klass->GetStatus());
if (!LinkSuperClass(klass)) {
return false;
@@ -5329,7 +5329,7 @@
return false;
}
CreateReferenceInstanceOffsets(klass);
- CHECK_EQ(mirror::Class::kStatusLoaded, klass->GetStatus());
+ CHECK_EQ(ClassStatus::kLoaded, klass->GetStatus());
ImTable* imt = nullptr;
if (klass->ShouldHaveImt()) {
@@ -5382,7 +5382,7 @@
// This will notify waiters on klass that saw the not yet resolved
// class in the class_table_ during EnsureResolved.
- mirror::Class::SetStatus(klass, mirror::Class::kStatusResolved, self);
+ mirror::Class::SetStatus(klass, ClassStatus::kResolved, self);
h_new_class_out->Assign(klass.Get());
} else {
CHECK(!klass->IsResolved());
@@ -5398,7 +5398,7 @@
klass->SetIFieldsPtrUnchecked(nullptr);
if (UNLIKELY(h_new_class == nullptr)) {
self->AssertPendingOOMException();
- mirror::Class::SetStatus(klass, mirror::Class::kStatusErrorUnresolved, self);
+ mirror::Class::SetStatus(klass, ClassStatus::kErrorUnresolved, self);
return false;
}
@@ -5432,12 +5432,12 @@
// This will notify waiters on temp class that saw the not yet resolved class in the
// class_table_ during EnsureResolved.
- mirror::Class::SetStatus(klass, mirror::Class::kStatusRetired, self);
+ mirror::Class::SetStatus(klass, ClassStatus::kRetired, self);
- CHECK_EQ(h_new_class->GetStatus(), mirror::Class::kStatusResolving);
+ CHECK_EQ(h_new_class->GetStatus(), ClassStatus::kResolving);
// This will notify waiters on new_class that saw the not yet resolved
// class in the class_table_ during EnsureResolved.
- mirror::Class::SetStatus(h_new_class, mirror::Class::kStatusResolved, self);
+ mirror::Class::SetStatus(h_new_class, ClassStatus::kResolved, self);
// Return the new class.
h_new_class_out->Assign(h_new_class.Get());
}
@@ -5445,7 +5445,7 @@
}
bool ClassLinker::LoadSuperAndInterfaces(Handle<mirror::Class> klass, const DexFile& dex_file) {
- CHECK_EQ(mirror::Class::kStatusIdx, klass->GetStatus());
+ CHECK_EQ(ClassStatus::kIdx, klass->GetStatus());
const DexFile::ClassDef& class_def = dex_file.GetClassDef(klass->GetDexClassDefIndex());
dex::TypeIndex super_class_idx = class_def.superclass_idx_;
if (super_class_idx.IsValid()) {
@@ -5498,7 +5498,7 @@
}
}
// Mark the class as loaded.
- mirror::Class::SetStatus(klass, mirror::Class::kStatusLoaded, nullptr);
+ mirror::Class::SetStatus(klass, ClassStatus::kLoaded, nullptr);
return true;
}
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 10562f0..b4e2937 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -478,7 +478,7 @@
REQUIRES(!Locks::dex_lock_);
bool VerifyClassUsingOatFile(const DexFile& dex_file,
ObjPtr<mirror::Class> klass,
- mirror::Class::Status& oat_file_class_status)
+ ClassStatus& oat_file_class_status)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::dex_lock_);
void ResolveClassExceptionHandlerTypes(Handle<mirror::Class> klass)
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 3dca2f9..c386883 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -86,7 +86,7 @@
EXPECT_TRUE(primitive->GetSuperClass() == nullptr);
EXPECT_FALSE(primitive->HasSuperClass());
EXPECT_TRUE(primitive->GetClassLoader() == nullptr);
- EXPECT_EQ(mirror::Class::kStatusInitialized, primitive->GetStatus());
+ EXPECT_EQ(ClassStatus::kInitialized, primitive->GetStatus());
EXPECT_FALSE(primitive->IsErroneous());
EXPECT_TRUE(primitive->IsLoaded());
EXPECT_TRUE(primitive->IsResolved());
@@ -125,7 +125,7 @@
EXPECT_TRUE(JavaLangObject->GetSuperClass() == nullptr);
EXPECT_FALSE(JavaLangObject->HasSuperClass());
EXPECT_TRUE(JavaLangObject->GetClassLoader() == nullptr);
- EXPECT_EQ(mirror::Class::kStatusInitialized, JavaLangObject->GetStatus());
+ EXPECT_EQ(ClassStatus::kInitialized, JavaLangObject->GetStatus());
EXPECT_FALSE(JavaLangObject->IsErroneous());
EXPECT_TRUE(JavaLangObject->IsLoaded());
EXPECT_TRUE(JavaLangObject->IsResolved());
@@ -200,7 +200,7 @@
EXPECT_TRUE(array->HasSuperClass());
ASSERT_TRUE(array->GetComponentType() != nullptr);
ASSERT_GT(strlen(array->GetComponentType()->GetDescriptor(&temp)), 0U);
- EXPECT_EQ(mirror::Class::kStatusInitialized, array->GetStatus());
+ EXPECT_EQ(ClassStatus::kInitialized, array->GetStatus());
EXPECT_FALSE(array->IsErroneous());
EXPECT_TRUE(array->IsLoaded());
EXPECT_TRUE(array->IsResolved());
@@ -919,7 +919,7 @@
EXPECT_TRUE(MyClass->GetSuperClass() == JavaLangObject);
EXPECT_TRUE(MyClass->HasSuperClass());
EXPECT_EQ(class_loader.Get(), MyClass->GetClassLoader());
- EXPECT_EQ(mirror::Class::kStatusResolved, MyClass->GetStatus());
+ EXPECT_EQ(ClassStatus::kResolved, MyClass->GetStatus());
EXPECT_FALSE(MyClass->IsErroneous());
EXPECT_TRUE(MyClass->IsLoaded());
EXPECT_TRUE(MyClass->IsResolved());
diff --git a/runtime/class_status.h b/runtime/class_status.h
index 7f2ef6a..ada2863 100644
--- a/runtime/class_status.h
+++ b/runtime/class_status.h
@@ -24,70 +24,70 @@
// Class Status
//
-// kStatusRetired: Class that's temporarily used till class linking time
+// kRetired: Class that's temporarily used till class linking time
// has its (vtable) size figured out and has been cloned to one with the
// right size which will be the one used later. The old one is retired and
// will be gc'ed once all refs to the class point to the newly
// cloned version.
//
-// kStatusErrorUnresolved, kStatusErrorResolved: Class is erroneous. We need
+// kErrorUnresolved, kErrorResolved: Class is erroneous. We need
// to distinguish between classes that have been resolved and classes that
// have not. This is important because the const-class instruction needs to
// return a previously resolved class even if its subsequent initialization
// failed. We also need this to decide whether to wrap a previous
// initialization failure in ClassDefNotFound error or not.
//
-// kStatusNotReady: If a Class cannot be found in the class table by
+// kNotReady: If a Class cannot be found in the class table by
// FindClass, it allocates an new one with AllocClass in the
-// kStatusNotReady and calls LoadClass. Note if it does find a
-// class, it may not be kStatusResolved and it will try to push it
-// forward toward kStatusResolved.
+// kNotReady and calls LoadClass. Note if it does find a
+// class, it may not be kResolved and it will try to push it
+// forward toward kResolved.
//
-// kStatusIdx: LoadClass populates with Class with information from
-// the DexFile, moving the status to kStatusIdx, indicating that the
+// kIdx: LoadClass populates with Class with information from
+// the DexFile, moving the status to kIdx, indicating that the
// Class value in super_class_ has not been populated. The new Class
// can then be inserted into the classes table.
//
-// kStatusLoaded: After taking a lock on Class, the ClassLinker will
-// attempt to move a kStatusIdx class forward to kStatusLoaded by
+// kLoaded: After taking a lock on Class, the ClassLinker will
+// attempt to move a kIdx class forward to kLoaded by
// using ResolveClass to initialize the super_class_ and ensuring the
// interfaces are resolved.
//
-// kStatusResolving: Class is just cloned with the right size from
+// kResolving: Class is just cloned with the right size from
// temporary class that's acting as a placeholder for linking. The old
// class will be retired. New class is set to this status first before
// moving on to being resolved.
//
-// kStatusResolved: Still holding the lock on Class, the ClassLinker
+// kResolved: Still holding the lock on Class, the ClassLinker
// shows linking is complete and fields of the Class populated by making
-// it kStatusResolved. Java allows circularities of the form where a super
+// it kResolved. Java allows circularities of the form where a super
// class has a field that is of the type of the sub class. We need to be able
// to fully resolve super classes while resolving types for fields.
//
-// kStatusRetryVerificationAtRuntime: The verifier sets a class to
+// kRetryVerificationAtRuntime: The verifier sets a class to
// this state if it encounters a soft failure at compile time. This
// often happens when there are unresolved classes in other dex
// files, and this status marks a class as needing to be verified
// again at runtime.
//
// TODO: Explain the other states
-enum ClassStatus : int8_t {
- kStatusRetired = -3, // Retired, should not be used. Use the newly cloned one instead.
- kStatusErrorResolved = -2,
- kStatusErrorUnresolved = -1,
- kStatusNotReady = 0,
- kStatusIdx = 1, // Loaded, DEX idx in super_class_type_idx_ and interfaces_type_idx_.
- kStatusLoaded = 2, // DEX idx values resolved.
- kStatusResolving = 3, // Just cloned from temporary class object.
- kStatusResolved = 4, // Part of linking.
- kStatusVerifying = 5, // In the process of being verified.
- kStatusRetryVerificationAtRuntime = 6, // Compile time verification failed, retry at runtime.
- kStatusVerifyingAtRuntime = 7, // Retrying verification at runtime.
- kStatusVerified = 8, // Logically part of linking; done pre-init.
- kStatusSuperclassValidated = 9, // Superclass validation part of init done.
- kStatusInitializing = 10, // Class init in progress.
- kStatusInitialized = 11, // Ready to go.
- kStatusMax = 12,
+enum class ClassStatus : uint8_t {
+ kNotReady = 0, // Zero-initialized Class object starts in this state.
+ kRetired = 1, // Retired, should not be used. Use the newly cloned one instead.
+ kErrorResolved = 2,
+ kErrorUnresolved = 3,
+ kIdx = 4, // Loaded, DEX idx in super_class_type_idx_ and interfaces_type_idx_.
+ kLoaded = 5, // DEX idx values resolved.
+ kResolving = 6, // Just cloned from temporary class object.
+ kResolved = 7, // Part of linking.
+ kVerifying = 8, // In the process of being verified.
+ kRetryVerificationAtRuntime = 9, // Compile time verification failed, retry at runtime.
+ kVerifyingAtRuntime = 10, // Retrying verification at runtime.
+ kVerified = 11, // Logically part of linking; done pre-init.
+ kSuperclassValidated = 12, // Superclass validation part of init done.
+ kInitializing = 13, // Class init in progress.
+ kInitialized = 14, // Ready to go.
+ kLast = kInitialized
};
std::ostream& operator<<(std::ostream& os, const ClassStatus& rhs);
diff --git a/runtime/class_table.cc b/runtime/class_table.cc
index c45bbe5..e313ec5 100644
--- a/runtime/class_table.cc
+++ b/runtime/class_table.cc
@@ -79,7 +79,7 @@
mirror::Class* const existing = existing_it->Read();
CHECK_NE(existing, klass) << descriptor;
CHECK(!existing->IsResolved()) << descriptor;
- CHECK_EQ(klass->GetStatus(), mirror::Class::kStatusResolving) << descriptor;
+ CHECK_EQ(klass->GetStatus(), ClassStatus::kResolving) << descriptor;
CHECK(!klass->IsTemp()) << descriptor;
VerifyObject(klass);
// Update the element in the hash set with the new class. This is safe to do since the descriptor
diff --git a/runtime/compiler_callbacks.h b/runtime/compiler_callbacks.h
index 9041df9..4560bca 100644
--- a/runtime/compiler_callbacks.h
+++ b/runtime/compiler_callbacks.h
@@ -55,7 +55,7 @@
// Return the class status of a previous stage of the compilation. This can be used, for example,
// when class unloading is enabled during multidex compilation.
virtual ClassStatus GetPreviousClassState(ClassReference ref ATTRIBUTE_UNUSED) {
- return ClassStatus::kStatusNotReady;
+ return ClassStatus::kNotReady;
}
virtual void SetDoesClassUnloading(bool does_class_unloading ATTRIBUTE_UNUSED,
diff --git a/runtime/generated/asm_support_gen.h b/runtime/generated/asm_support_gen.h
index e158212..46630db 100644
--- a/runtime/generated/asm_support_gen.h
+++ b/runtime/generated/asm_support_gen.h
@@ -54,8 +54,6 @@
DEFINE_CHECK_EQ(static_cast<int32_t>(MIRROR_OBJECT_CLASS_OFFSET), (static_cast<int32_t>(art::mirror::Object::ClassOffset().Int32Value())))
#define MIRROR_OBJECT_LOCK_WORD_OFFSET 4
DEFINE_CHECK_EQ(static_cast<int32_t>(MIRROR_OBJECT_LOCK_WORD_OFFSET), (static_cast<int32_t>(art::mirror::Object::MonitorOffset().Int32Value())))
-#define MIRROR_CLASS_STATUS_INITIALIZED 0xb
-DEFINE_CHECK_EQ(static_cast<uint32_t>(MIRROR_CLASS_STATUS_INITIALIZED), (static_cast<uint32_t>((art::mirror::Class::kStatusInitialized))))
#define ACCESS_FLAGS_CLASS_IS_FINALIZABLE 0x80000000
DEFINE_CHECK_EQ(static_cast<uint32_t>(ACCESS_FLAGS_CLASS_IS_FINALIZABLE), (static_cast<uint32_t>((art::kAccClassIsFinalizable))))
#define ACCESS_FLAGS_CLASS_IS_INTERFACE 0x200
diff --git a/runtime/image.cc b/runtime/image.cc
index 8f35d84..b9d955c 100644
--- a/runtime/image.cc
+++ b/runtime/image.cc
@@ -26,7 +26,7 @@
namespace art {
const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' };
-const uint8_t ImageHeader::kImageVersion[] = { '0', '5', '1', '\0' }; // @FastNative access flags.
+const uint8_t ImageHeader::kImageVersion[] = { '0', '5', '2', '\0' }; // 4-bit ClassStatus.
ImageHeader::ImageHeader(uint32_t image_begin,
uint32_t image_size,
diff --git a/runtime/mirror/class-refvisitor-inl.h b/runtime/mirror/class-refvisitor-inl.h
index 3d52ead..263b774 100644
--- a/runtime/mirror/class-refvisitor-inl.h
+++ b/runtime/mirror/class-refvisitor-inl.h
@@ -32,12 +32,12 @@
inline void Class::VisitReferences(ObjPtr<Class> klass, const Visitor& visitor) {
VisitInstanceFieldsReferences<kVerifyFlags, kReadBarrierOption>(klass.Ptr(), visitor);
// Right after a class is allocated, but not yet loaded
- // (kStatusNotReady, see ClassLinker::LoadClass()), GC may find it
+ // (ClassStatus::kNotReady, see ClassLinker::LoadClass()), GC may find it
// and scan it. IsTemp() may call Class::GetAccessFlags() but may
// fail in the DCHECK in Class::GetAccessFlags() because the class
- // status is kStatusNotReady. To avoid it, rely on IsResolved()
+ // status is ClassStatus::kNotReady. To avoid it, rely on IsResolved()
// only. This is fine because a temp class never goes into the
- // kStatusResolved state.
+ // ClassStatus::kResolved state.
if (IsResolved<kVerifyFlags>()) {
// Temp classes don't ever populate imt/vtable or static fields and they are not even
// allocated with the right size for those. Also, unresolved classes don't have fields
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 10daebb..6bee3cf 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -54,23 +54,6 @@
GcRoot<Class> Class::java_lang_Class_;
-constexpr Class::Status Class::kStatusRetired;
-constexpr Class::Status Class::kStatusErrorResolved;
-constexpr Class::Status Class::kStatusErrorUnresolved;
-constexpr Class::Status Class::kStatusNotReady;
-constexpr Class::Status Class::kStatusIdx;
-constexpr Class::Status Class::kStatusLoaded;
-constexpr Class::Status Class::kStatusResolving;
-constexpr Class::Status Class::kStatusResolved;
-constexpr Class::Status Class::kStatusVerifying;
-constexpr Class::Status Class::kStatusRetryVerificationAtRuntime;
-constexpr Class::Status Class::kStatusVerifyingAtRuntime;
-constexpr Class::Status Class::kStatusVerified;
-constexpr Class::Status Class::kStatusSuperclassValidated;
-constexpr Class::Status Class::kStatusInitializing;
-constexpr Class::Status Class::kStatusInitialized;
-constexpr Class::Status Class::kStatusMax;
-
void Class::SetClassClass(ObjPtr<Class> java_lang_Class) {
CHECK(java_lang_Class_.IsNull())
<< java_lang_Class_.Read()
@@ -131,19 +114,19 @@
}
}
-void Class::SetStatus(Handle<Class> h_this, Status new_status, Thread* self) {
- Status old_status = h_this->GetStatus();
+void Class::SetStatus(Handle<Class> h_this, ClassStatus new_status, Thread* self) {
+ ClassStatus old_status = h_this->GetStatus();
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
bool class_linker_initialized = class_linker != nullptr && class_linker->IsInitialized();
if (LIKELY(class_linker_initialized)) {
if (UNLIKELY(new_status <= old_status &&
- new_status != kStatusErrorUnresolved &&
- new_status != kStatusErrorResolved &&
- new_status != kStatusRetired)) {
+ new_status != ClassStatus::kErrorUnresolved &&
+ new_status != ClassStatus::kErrorResolved &&
+ new_status != ClassStatus::kRetired)) {
LOG(FATAL) << "Unexpected change back of class status for " << h_this->PrettyClass()
<< " " << old_status << " -> " << new_status;
}
- if (new_status >= kStatusResolved || old_status >= kStatusResolved) {
+ if (new_status >= ClassStatus::kResolved || old_status >= ClassStatus::kResolved) {
// When classes are being resolved the resolution code should hold the lock.
CHECK_EQ(h_this->GetLockOwnerThreadId(), self->GetThreadId())
<< "Attempt to change status of class while not holding its lock: "
@@ -155,7 +138,7 @@
<< "Attempt to set as erroneous an already erroneous class "
<< h_this->PrettyClass()
<< " old_status: " << old_status << " new_status: " << new_status;
- CHECK_EQ(new_status == kStatusErrorResolved, old_status >= kStatusResolved);
+ CHECK_EQ(new_status == ClassStatus::kErrorResolved, old_status >= ClassStatus::kResolved);
if (VLOG_IS_ON(class_linker)) {
LOG(ERROR) << "Setting " << h_this->PrettyDescriptor() << " to erroneous.";
if (self->IsExceptionPending()) {
@@ -181,7 +164,7 @@
// Setting the object size alloc fast path needs to be after the status write so that if the
// alloc path sees a valid object size, we would know that it's initialized as long as it has a
// load-acquire/fake dependency.
- if (new_status == kStatusInitialized && !h_this->IsVariableSize()) {
+ if (new_status == ClassStatus::kInitialized && !h_this->IsVariableSize()) {
DCHECK_EQ(h_this->GetObjectSizeAllocFastPath(), std::numeric_limits<uint32_t>::max());
// Finalizable objects must always go slow path.
if (!h_this->IsFinalizable()) {
@@ -199,13 +182,13 @@
if (h_this->IsTemp()) {
// Class is a temporary one, ensure that waiters for resolution get notified of retirement
// so that they can grab the new version of the class from the class linker's table.
- CHECK_LT(new_status, kStatusResolved) << h_this->PrettyDescriptor();
- if (new_status == kStatusRetired || new_status == kStatusErrorUnresolved) {
+ CHECK_LT(new_status, ClassStatus::kResolved) << h_this->PrettyDescriptor();
+ if (new_status == ClassStatus::kRetired || new_status == ClassStatus::kErrorUnresolved) {
h_this->NotifyAll(self);
}
} else {
- CHECK_NE(new_status, kStatusRetired);
- if (old_status >= kStatusResolved || new_status >= kStatusResolved) {
+ CHECK_NE(new_status, ClassStatus::kRetired);
+ if (old_status >= ClassStatus::kResolved || new_status >= ClassStatus::kResolved) {
h_this->NotifyAll(self);
}
}
@@ -1154,7 +1137,7 @@
StackHandleScope<1> hs(self_);
Handle<mirror::Class> h_new_class_obj(hs.NewHandle(obj->AsClass()));
Object::CopyObject(h_new_class_obj.Get(), orig_->Get(), copy_bytes_);
- Class::SetStatus(h_new_class_obj, Class::kStatusResolving, self_);
+ Class::SetStatus(h_new_class_obj, ClassStatus::kResolving, self_);
h_new_class_obj->PopulateEmbeddedVTable(pointer_size_);
h_new_class_obj->SetImt(imt_, pointer_size_);
h_new_class_obj->SetClassSize(new_length_);
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index c545a9b..95fc35d 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -18,6 +18,7 @@
#define ART_RUNTIME_MIRROR_CLASS_H_
#include "base/bit_utils.h"
+#include "base/casts.h"
#include "base/enums.h"
#include "base/iteration_range.h"
#include "class_flags.h"
@@ -77,38 +78,16 @@
static constexpr uint32_t kPrimitiveTypeSizeShiftShift = 16;
static constexpr uint32_t kPrimitiveTypeMask = (1u << kPrimitiveTypeSizeShiftShift) - 1;
- // Make ClassStatus available as Class::Status.
- using Status = ClassStatus;
-
- // Required for a minimal change. Fix up and remove in a future change.
- static constexpr Status kStatusRetired = Status::kStatusRetired;
- static constexpr Status kStatusErrorResolved = Status::kStatusErrorResolved;
- static constexpr Status kStatusErrorUnresolved = Status::kStatusErrorUnresolved;
- static constexpr Status kStatusNotReady = Status::kStatusNotReady;
- static constexpr Status kStatusIdx = Status::kStatusIdx;
- static constexpr Status kStatusLoaded = Status::kStatusLoaded;
- static constexpr Status kStatusResolving = Status::kStatusResolving;
- static constexpr Status kStatusResolved = Status::kStatusResolved;
- static constexpr Status kStatusVerifying = Status::kStatusVerifying;
- static constexpr Status kStatusRetryVerificationAtRuntime =
- Status::kStatusRetryVerificationAtRuntime;
- static constexpr Status kStatusVerifyingAtRuntime = Status::kStatusVerifyingAtRuntime;
- static constexpr Status kStatusVerified = Status::kStatusVerified;
- static constexpr Status kStatusSuperclassValidated = Status::kStatusSuperclassValidated;
- static constexpr Status kStatusInitializing = Status::kStatusInitializing;
- static constexpr Status kStatusInitialized = Status::kStatusInitialized;
- static constexpr Status kStatusMax = Status::kStatusMax;
-
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
- Status GetStatus() REQUIRES_SHARED(Locks::mutator_lock_) {
+ ClassStatus GetStatus() REQUIRES_SHARED(Locks::mutator_lock_) {
// Avoid including "subtype_check_bits_and_status.h" to get the field.
// The ClassStatus is always in the least-significant bits of status_.
- return static_cast<Status>(static_cast<uint8_t>(
- static_cast<uint32_t>(GetField32Volatile<kVerifyFlags>(StatusOffset())) & 0xff));
+ return enum_cast<ClassStatus>(
+ static_cast<uint32_t>(GetField32Volatile<kVerifyFlags>(StatusOffset())) & 0xff);
}
// This is static because 'this' may be moved by GC.
- static void SetStatus(Handle<Class> h_this, Status new_status, Thread* self)
+ static void SetStatus(Handle<Class> h_this, ClassStatus new_status, Thread* self)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
static MemberOffset StatusOffset() {
@@ -118,24 +97,24 @@
// Returns true if the class has been retired.
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsRetired() REQUIRES_SHARED(Locks::mutator_lock_) {
- return GetStatus<kVerifyFlags>() == kStatusRetired;
+ return GetStatus<kVerifyFlags>() == ClassStatus::kRetired;
}
// Returns true if the class has failed to link.
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsErroneousUnresolved() REQUIRES_SHARED(Locks::mutator_lock_) {
- return GetStatus<kVerifyFlags>() == kStatusErrorUnresolved;
+ return GetStatus<kVerifyFlags>() == ClassStatus::kErrorUnresolved;
}
// Returns true if the class has failed to initialize.
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsErroneousResolved() REQUIRES_SHARED(Locks::mutator_lock_) {
- return GetStatus<kVerifyFlags>() == kStatusErrorResolved;
+ return GetStatus<kVerifyFlags>() == ClassStatus::kErrorResolved;
}
// Returns true if the class status indicets that the class has failed to link or initialize.
- static bool IsErroneous(Status status) {
- return status == kStatusErrorUnresolved || status == kStatusErrorResolved;
+ static bool IsErroneous(ClassStatus status) {
+ return status == ClassStatus::kErrorUnresolved || status == ClassStatus::kErrorResolved;
}
// Returns true if the class has failed to link or initialize.
@@ -147,44 +126,44 @@
// Returns true if the class has been loaded.
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsIdxLoaded() REQUIRES_SHARED(Locks::mutator_lock_) {
- return GetStatus<kVerifyFlags>() >= kStatusIdx;
+ return GetStatus<kVerifyFlags>() >= ClassStatus::kIdx;
}
// Returns true if the class has been loaded.
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsLoaded() REQUIRES_SHARED(Locks::mutator_lock_) {
- return GetStatus<kVerifyFlags>() >= kStatusLoaded;
+ return GetStatus<kVerifyFlags>() >= ClassStatus::kLoaded;
}
// Returns true if the class has been linked.
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsResolved() REQUIRES_SHARED(Locks::mutator_lock_) {
- Status status = GetStatus<kVerifyFlags>();
- return status >= kStatusResolved || status == kStatusErrorResolved;
+ ClassStatus status = GetStatus<kVerifyFlags>();
+ return status >= ClassStatus::kResolved || status == ClassStatus::kErrorResolved;
}
// Returns true if the class should be verified at runtime.
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool ShouldVerifyAtRuntime() REQUIRES_SHARED(Locks::mutator_lock_) {
- return GetStatus<kVerifyFlags>() == kStatusRetryVerificationAtRuntime;
+ return GetStatus<kVerifyFlags>() == ClassStatus::kRetryVerificationAtRuntime;
}
// Returns true if the class has been verified.
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsVerified() REQUIRES_SHARED(Locks::mutator_lock_) {
- return GetStatus<kVerifyFlags>() >= kStatusVerified;
+ return GetStatus<kVerifyFlags>() >= ClassStatus::kVerified;
}
// Returns true if the class is initializing.
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsInitializing() REQUIRES_SHARED(Locks::mutator_lock_) {
- return GetStatus<kVerifyFlags>() >= kStatusInitializing;
+ return GetStatus<kVerifyFlags>() >= ClassStatus::kInitializing;
}
// Returns true if the class is initialized.
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsInitialized() REQUIRES_SHARED(Locks::mutator_lock_) {
- return GetStatus<kVerifyFlags>() == kStatusInitialized;
+ return GetStatus<kVerifyFlags>() == ClassStatus::kInitialized;
}
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
@@ -333,8 +312,10 @@
// Returns true if this class is the placeholder and should retire and
// be replaced with a class with the right size for embedded imt/vtable.
bool IsTemp() REQUIRES_SHARED(Locks::mutator_lock_) {
- Status s = GetStatus();
- return s < Status::kStatusResolving && s != kStatusErrorResolved && ShouldHaveEmbeddedVTable();
+ ClassStatus s = GetStatus();
+ return s < ClassStatus::kResolving &&
+ s != ClassStatus::kErrorResolved &&
+ ShouldHaveEmbeddedVTable();
}
String* GetName() REQUIRES_SHARED(Locks::mutator_lock_); // Returns the cached name.
diff --git a/runtime/oat.h b/runtime/oat.h
index 9d21180..7d1bf85 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -32,8 +32,8 @@
class PACKED(4) OatHeader {
public:
static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' };
- // Last oat version changed reason: .bss index mapping change.
- static constexpr uint8_t kOatVersion[] = { '1', '3', '5', '\0' };
+ // Last oat version changed reason: 4-bit ClassStatus.
+ static constexpr uint8_t kOatVersion[] = { '1', '3', '6', '\0' };
static constexpr const char* kImageLocationKey = "image-location";
static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index f437db2..7a3014e 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -1654,9 +1654,8 @@
const uint8_t* status_pointer = oat_class_pointer;
CHECK_LT(status_pointer, oat_file_->End()) << oat_file_->GetLocation();
- mirror::Class::Status status =
- static_cast<mirror::Class::Status>(*reinterpret_cast<const int16_t*>(status_pointer));
- CHECK_LT(status, mirror::Class::kStatusMax);
+ ClassStatus status = enum_cast<ClassStatus>(*reinterpret_cast<const int16_t*>(status_pointer));
+ CHECK_LE(status, ClassStatus::kLast);
const uint8_t* type_pointer = status_pointer + sizeof(uint16_t);
CHECK_LT(type_pointer, oat_file_->End()) << oat_file_->GetLocation();
@@ -1737,7 +1736,7 @@
}
OatFile::OatClass::OatClass(const OatFile* oat_file,
- mirror::Class::Status status,
+ ClassStatus status,
OatClassType type,
uint32_t bitmap_size,
const uint32_t* bitmap_pointer,
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index 1fb17a4..2ed1c82 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -24,11 +24,12 @@
#include "base/array_ref.h"
#include "base/mutex.h"
#include "base/stringpiece.h"
+#include "class_status.h"
#include "compiler_filter.h"
#include "dex_file.h"
#include "dex_file_layout.h"
#include "index_bss_mapping.h"
-#include "mirror/class.h"
+#include "mirror/object.h"
#include "oat.h"
#include "os.h"
#include "type_lookup_table.h"
@@ -196,7 +197,7 @@
class OatClass FINAL {
public:
- mirror::Class::Status GetStatus() const {
+ ClassStatus GetStatus() const {
return status_;
}
@@ -224,7 +225,7 @@
// See FindOatClass().
static OatClass Invalid() {
return OatClass(/* oat_file */ nullptr,
- mirror::Class::kStatusErrorUnresolved,
+ ClassStatus::kErrorUnresolved,
kOatClassNoneCompiled,
/* bitmap_size */ 0,
/* bitmap_pointer */ nullptr,
@@ -233,7 +234,7 @@
private:
OatClass(const OatFile* oat_file,
- mirror::Class::Status status,
+ ClassStatus status,
OatClassType type,
uint32_t bitmap_size,
const uint32_t* bitmap_pointer,
@@ -241,7 +242,7 @@
const OatFile* const oat_file_;
- const mirror::Class::Status status_;
+ const ClassStatus status_;
const OatClassType type_;
diff --git a/runtime/transaction_test.cc b/runtime/transaction_test.cc
index 304017e..0bad548 100644
--- a/runtime/transaction_test.cc
+++ b/runtime/transaction_test.cc
@@ -66,7 +66,7 @@
class_linker_->VerifyClass(soa.Self(), h_klass);
ASSERT_TRUE(h_klass->IsVerified());
- mirror::Class::Status old_status = h_klass->GetStatus();
+ ClassStatus old_status = h_klass->GetStatus();
LockWord old_lock_word = h_klass->GetLockWord(false);
Runtime::Current()->EnterTransactionMode();
diff --git a/test/008-exceptions/src/Main.java b/test/008-exceptions/src/Main.java
index 89fe016..008576a 100644
--- a/test/008-exceptions/src/Main.java
+++ b/test/008-exceptions/src/Main.java
@@ -158,8 +158,8 @@
t.printStackTrace(System.out);
}
try {
- // Before splitting mirror::Class::kStatusError into
- // kStatusErrorUnresolved and kStatusErrorResolved,
+ // Before splitting ClassStatus::kError into
+ // ClassStatus::kErrorUnresolved and ClassStatus::kErrorResolved,
// this would trigger a
// CHECK(super_class->IsResolved())
// failure in
@@ -188,8 +188,8 @@
} catch (Throwable t) {
t.printStackTrace(System.out);
}
- // Before splitting mirror::Class::kStatusError into
- // kStatusErrorUnresolved and kStatusErrorResolved,
+ // Before splitting ClassStatus::kError into
+ // ClassStatus::kErrorUnresolved and ClassStatus::kErrorResolved,
// the exception from wrapper 1 would have been
// wrapped in NoClassDefFoundError but the exception
// from wrapper 2 would have been unwrapped.
diff --git a/test/626-const-class-linking/clear_dex_cache_types.cc b/test/626-const-class-linking/clear_dex_cache_types.cc
index e1af02e..96ef266 100644
--- a/test/626-const-class-linking/clear_dex_cache_types.cc
+++ b/test/626-const-class-linking/clear_dex_cache_types.cc
@@ -36,10 +36,10 @@
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<1> hs(soa.Self());
Handle<mirror::Class> klass = hs.NewHandle(soa.Decode<mirror::Class>(cls));
- mirror::Class::Status status = klass->GetStatus();
- if (status == mirror::Class::kStatusResolved) {
+ ClassStatus status = klass->GetStatus();
+ if (status == ClassStatus::kResolved) {
ObjectLock<mirror::Class> lock(soa.Self(), klass);
- klass->SetStatus(klass, mirror::Class::kStatusVerified, soa.Self());
+ klass->SetStatus(klass, ClassStatus::kVerified, soa.Self());
} else {
LOG(ERROR) << klass->PrettyClass() << " has unexpected status: " << status;
}
diff --git a/tools/cpp-define-generator/constant_class.def b/tools/cpp-define-generator/constant_class.def
index f46cd33..4f1d875 100644
--- a/tools/cpp-define-generator/constant_class.def
+++ b/tools/cpp-define-generator/constant_class.def
@@ -15,7 +15,6 @@
*/
#if defined(DEFINE_INCLUDE_DEPENDENCIES)
-#include "mirror/class.h" // kStatusInitialized
#include "modifiers.h" // kAccClassIsFinalizable
#include "base/bit_utils.h" // MostSignificantBit
#endif
@@ -23,7 +22,6 @@
#define DEFINE_FLAG_OFFSET(type_name, field_name, expr) \
DEFINE_EXPR(type_name ## _ ## field_name, uint32_t, (expr))
-DEFINE_FLAG_OFFSET(MIRROR_CLASS, STATUS_INITIALIZED, art::mirror::Class::kStatusInitialized)
DEFINE_FLAG_OFFSET(ACCESS_FLAGS, CLASS_IS_FINALIZABLE, art::kAccClassIsFinalizable)
DEFINE_FLAG_OFFSET(ACCESS_FLAGS, CLASS_IS_INTERFACE, art::kAccInterface)
// TODO: We should really have a BitPosition which also checks it's a power of 2.