Merge "dalvikvm.cc: use proper nativehelper headers"
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index b3160dd..f3718c4 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -291,7 +291,6 @@
instruction_set_(instruction_set == kArm ? kThumb2 : instruction_set),
instruction_set_features_(instruction_set_features),
requires_constructor_barrier_lock_("constructor barrier lock"),
- compiled_classes_lock_("compiled classes lock"),
non_relative_linker_patch_count_(0u),
image_classes_(image_classes),
classes_to_compile_(compiled_classes),
@@ -1947,7 +1946,12 @@
if (compiler_only_verifies) {
// Just update the compiled_classes_ map. The compiler doesn't need to resolve
// the type.
- compiled_classes_.Overwrite(ClassReference(dex_file, i), mirror::Class::kStatusVerified);
+ DexFileReference ref(dex_file, i);
+ mirror::Class::Status existing = mirror::Class::kStatusNotReady;
+ DCHECK(compiled_classes_.Get(ref, &existing)) << ref.dex_file->GetLocation();
+ ClassStateTable::InsertResult result =
+ compiled_classes_.Insert(ref, existing, mirror::Class::kStatusVerified);
+ CHECK_EQ(result, ClassStateTable::kInsertResultSuccess);
} else {
// Update the class status, so later compilation stages know they don't need to verify
// the class.
@@ -1978,6 +1982,13 @@
void CompilerDriver::Verify(jobject jclass_loader,
const std::vector<const DexFile*>& dex_files,
TimingLogger* timings) {
+ // Always add the dex files to compiled_classes_. This happens for all compiler filters.
+ for (const DexFile* dex_file : dex_files) {
+ if (!compiled_classes_.HaveDexFile(dex_file)) {
+ compiled_classes_.AddDexFile(dex_file, dex_file->NumClassDefs());
+ }
+ }
+
if (FastVerify(jclass_loader, dex_files, timings)) {
return;
}
@@ -2202,6 +2213,9 @@
size_t thread_count,
TimingLogger* timings) {
TimingLogger::ScopedTiming t("Verify Dex File", timings);
+ if (!compiled_classes_.HaveDexFile(&dex_file)) {
+ compiled_classes_.AddDexFile(&dex_file, dex_file.NumClassDefs());
+ }
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
ParallelCompilationManager context(class_linker, class_loader, this, &dex_file, dex_files,
thread_pool);
@@ -2248,12 +2262,13 @@
const bool is_app_image = manager_->GetCompiler()->GetCompilerOptions().IsAppImage();
mirror::Class::Status 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.
+ return;
+ }
// Only try to initialize classes that were successfully verified.
if (klass->IsVerified()) {
- // Don't initialize classes in boot space when compiling app image
- if (is_app_image && klass->IsBootStrapClassLoaded()) {
- return;
- }
// Attempt to initialize the class but bail if we either need to initialize the super-class
// or static fields.
manager_->GetClassLinker()->EnsureInitialized(soa.Self(), klass, false, false);
@@ -2860,12 +2875,12 @@
bool CompilerDriver::GetCompiledClass(ClassReference ref, mirror::Class::Status* status) const {
DCHECK(status != nullptr);
- MutexLock mu(Thread::Current(), compiled_classes_lock_);
- ClassStateTable::const_iterator it = compiled_classes_.find(ref);
- if (it == compiled_classes_.end()) {
+ // The table doesn't know if something wasn't inserted. For this case it will return
+ // kStatusNotReady. To handle this, just assume anything not verified is not compiled.
+ if (!compiled_classes_.Get(DexFileReference(ref.first, ref.second), status) ||
+ *status < mirror::Class::kStatusVerified) {
return false;
}
- *status = it->second;
return true;
}
@@ -2886,15 +2901,20 @@
<< " of " << status;
}
- MutexLock mu(Thread::Current(), compiled_classes_lock_);
- auto it = compiled_classes_.find(ref);
- if (it == compiled_classes_.end()) {
- compiled_classes_.Overwrite(ref, status);
- } else if (status > it->second) {
+ ClassStateTable::InsertResult result;
+ do {
+ DexFileReference dex_ref(ref.first, ref.second);
+ mirror::Class::Status existing = mirror::Class::kStatusNotReady;
+ CHECK(compiled_classes_.Get(dex_ref, &existing)) << dex_ref.dex_file->GetLocation();
+ if (existing >= status) {
+ // Existing status is already better than we expect, break.
+ break;
+ }
// Update the status if we now have a greater one. This happens with vdex,
// which records a class is verified, but does not resolve it.
- it->second = status;
- }
+ result = compiled_classes_.Insert(dex_ref, existing, status);
+ CHECK(result != ClassStateTable::kInsertResultInvalidDexFile);
+ } while (result != ClassStateTable::kInsertResultSuccess);
}
CompiledMethod* CompilerDriver::GetCompiledMethod(MethodReference ref) const {
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index a3272d3..93234cb 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -117,12 +117,12 @@
void CompileAll(jobject class_loader,
const std::vector<const DexFile*>& dex_files,
TimingLogger* timings)
- REQUIRES(!Locks::mutator_lock_, !compiled_classes_lock_, !dex_to_dex_references_lock_);
+ REQUIRES(!Locks::mutator_lock_, !dex_to_dex_references_lock_);
// Compile a single Method.
void CompileOne(Thread* self, ArtMethod* method, TimingLogger* timings)
REQUIRES_SHARED(Locks::mutator_lock_)
- REQUIRES(!compiled_classes_lock_, !dex_to_dex_references_lock_);
+ REQUIRES(!dex_to_dex_references_lock_);
VerificationResults* GetVerificationResults() const;
@@ -153,8 +153,7 @@
std::unique_ptr<const std::vector<uint8_t>> CreateQuickResolutionTrampoline() const;
std::unique_ptr<const std::vector<uint8_t>> CreateQuickToInterpreterBridge() const;
- bool GetCompiledClass(ClassReference ref, mirror::Class::Status* status) const
- REQUIRES(!compiled_classes_lock_);
+ bool GetCompiledClass(ClassReference ref, mirror::Class::Status* status) const;
CompiledMethod* GetCompiledMethod(MethodReference ref) const;
size_t GetNonRelativeLinkerPatchCount() const;
@@ -337,8 +336,7 @@
// according to the profile file.
bool ShouldVerifyClassBasedOnProfile(const DexFile& dex_file, uint16_t class_idx) const;
- void RecordClassStatus(ClassReference ref, mirror::Class::Status status)
- REQUIRES(!compiled_classes_lock_);
+ void RecordClassStatus(ClassReference ref, mirror::Class::Status status);
// Checks if the specified method has been verified without failures. Returns
// false if the method is not in the verification results (GetVerificationResults).
@@ -387,7 +385,7 @@
void PreCompile(jobject class_loader,
const std::vector<const DexFile*>& dex_files,
TimingLogger* timings)
- REQUIRES(!Locks::mutator_lock_, !compiled_classes_lock_);
+ REQUIRES(!Locks::mutator_lock_);
void LoadImageClasses(TimingLogger* timings) REQUIRES(!Locks::mutator_lock_);
@@ -408,12 +406,9 @@
// Do fast verification through VerifierDeps if possible. Return whether
// verification was successful.
- // NO_THREAD_SAFETY_ANALYSIS as the method accesses a guarded value in a
- // single-threaded way.
bool FastVerify(jobject class_loader,
const std::vector<const DexFile*>& dex_files,
- TimingLogger* timings)
- NO_THREAD_SAFETY_ANALYSIS;
+ TimingLogger* timings);
void Verify(jobject class_loader,
const std::vector<const DexFile*>& dex_files,
@@ -441,12 +436,12 @@
void InitializeClasses(jobject class_loader,
const std::vector<const DexFile*>& dex_files,
TimingLogger* timings)
- REQUIRES(!Locks::mutator_lock_, !compiled_classes_lock_);
+ REQUIRES(!Locks::mutator_lock_);
void InitializeClasses(jobject class_loader,
const DexFile& dex_file,
const std::vector<const DexFile*>& dex_files,
TimingLogger* timings)
- REQUIRES(!Locks::mutator_lock_, !compiled_classes_lock_);
+ REQUIRES(!Locks::mutator_lock_);
void UpdateImageClasses(TimingLogger* timings) REQUIRES(!Locks::mutator_lock_);
@@ -484,10 +479,9 @@
std::map<ClassReference, bool> requires_constructor_barrier_
GUARDED_BY(requires_constructor_barrier_lock_);
- using ClassStateTable = SafeMap<const ClassReference, mirror::Class::Status>;
- // All class references that this compiler has compiled.
- mutable Mutex compiled_classes_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
- ClassStateTable compiled_classes_ GUARDED_BY(compiled_classes_lock_);
+ // All class references that this compiler has compiled. Indexed by class defs.
+ using ClassStateTable = AtomicDexRefMap<mirror::Class::Status>;
+ ClassStateTable compiled_classes_;
typedef AtomicDexRefMap<CompiledMethod*> MethodTable;
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index b5d3736..0ef496f 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -1787,7 +1787,7 @@
for (const DexFile* dex_file : *dex_file_vector) {
for (const std::string& filter : no_inline_filters) {
// Use dex_file->GetLocation() rather than dex_file->GetBaseLocation(). This
- // allows tests to specify <test-dexfile>:classes2.dex if needed but if the
+ // allows tests to specify <test-dexfile>!classes2.dex if needed but if the
// base location passes the StartsWith() test, so do all extra locations.
std::string dex_location = dex_file->GetLocation();
if (filter.find('/') == std::string::npos) {
diff --git a/runtime/atomic.h b/runtime/atomic.h
index 25dd1a3..09eae40 100644
--- a/runtime/atomic.h
+++ b/runtime/atomic.h
@@ -187,7 +187,7 @@
template<typename T>
class PACKED(sizeof(T)) Atomic : public std::atomic<T> {
public:
- Atomic<T>() : std::atomic<T>(0) { }
+ Atomic<T>() : std::atomic<T>(T()) { }
explicit Atomic<T>(T value) : std::atomic<T>(value) { }
diff --git a/runtime/class_loader_context_test.cc b/runtime/class_loader_context_test.cc
index 1b46f67..a87552d 100644
--- a/runtime/class_loader_context_test.cc
+++ b/runtime/class_loader_context_test.cc
@@ -488,4 +488,12 @@
ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context->EncodeContextForOatFile("")));
}
+TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchAfterEncodingMultidex) {
+ jobject class_loader = LoadDexInPathClassLoader("MultiDex", nullptr);
+
+ std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader);
+
+ ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context->EncodeContextForOatFile("")));
+}
+
} // namespace art
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index eb3b210..990ab11 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -62,11 +62,11 @@
static const uint16_t kDexNoIndex16 = 0xFFFF;
// The separator character in MultiDex locations.
- static constexpr char kMultiDexSeparator = ':';
+ static constexpr char kMultiDexSeparator = '!';
// A string version of the previous. This is a define so that we can merge string literals in the
// preprocessor.
- #define kMultiDexSeparatorString ":"
+ #define kMultiDexSeparatorString "!"
// Raw header_item.
struct Header {
@@ -499,7 +499,7 @@
return GetBaseLocation(location.c_str());
}
- // Returns the ':classes*.dex' part of the dex location. Returns an empty
+ // Returns the '!classes*.dex' part of the dex location. Returns an empty
// string if there is no multidex suffix for the given location.
// The kMultiDexSeparator is included in the returned suffix.
static std::string GetMultiDexSuffix(const std::string& location) {
diff --git a/runtime/dex_file_test.cc b/runtime/dex_file_test.cc
index 78d5c5f..1a73062 100644
--- a/runtime/dex_file_test.cc
+++ b/runtime/dex_file_test.cc
@@ -535,9 +535,9 @@
std::string dex_location_str = "/system/app/framework.jar";
const char* dex_location = dex_location_str.c_str();
ASSERT_EQ("/system/app/framework.jar", DexFile::GetMultiDexLocation(0, dex_location));
- ASSERT_EQ("/system/app/framework.jar:classes2.dex",
+ ASSERT_EQ("/system/app/framework.jar!classes2.dex",
DexFile::GetMultiDexLocation(1, dex_location));
- ASSERT_EQ("/system/app/framework.jar:classes101.dex",
+ ASSERT_EQ("/system/app/framework.jar!classes101.dex",
DexFile::GetMultiDexLocation(100, dex_location));
}
@@ -563,11 +563,11 @@
TEST(DexFileUtilsTest, GetBaseLocationAndMultiDexSuffix) {
EXPECT_EQ("/foo/bar/baz.jar", DexFile::GetBaseLocation("/foo/bar/baz.jar"));
- EXPECT_EQ("/foo/bar/baz.jar", DexFile::GetBaseLocation("/foo/bar/baz.jar:classes2.dex"));
- EXPECT_EQ("/foo/bar/baz.jar", DexFile::GetBaseLocation("/foo/bar/baz.jar:classes8.dex"));
+ EXPECT_EQ("/foo/bar/baz.jar", DexFile::GetBaseLocation("/foo/bar/baz.jar!classes2.dex"));
+ EXPECT_EQ("/foo/bar/baz.jar", DexFile::GetBaseLocation("/foo/bar/baz.jar!classes8.dex"));
EXPECT_EQ("", DexFile::GetMultiDexSuffix("/foo/bar/baz.jar"));
- EXPECT_EQ(":classes2.dex", DexFile::GetMultiDexSuffix("/foo/bar/baz.jar:classes2.dex"));
- EXPECT_EQ(":classes8.dex", DexFile::GetMultiDexSuffix("/foo/bar/baz.jar:classes8.dex"));
+ EXPECT_EQ("!classes2.dex", DexFile::GetMultiDexSuffix("/foo/bar/baz.jar!classes2.dex"));
+ EXPECT_EQ("!classes8.dex", DexFile::GetMultiDexSuffix("/foo/bar/baz.jar!classes8.dex"));
}
TEST_F(DexFileTest, ZipOpenClassesPresent) {
diff --git a/runtime/jit/profile_compilation_info.cc b/runtime/jit/profile_compilation_info.cc
index a247b56..45c3792 100644
--- a/runtime/jit/profile_compilation_info.cc
+++ b/runtime/jit/profile_compilation_info.cc
@@ -47,9 +47,8 @@
namespace art {
const uint8_t ProfileCompilationInfo::kProfileMagic[] = { 'p', 'r', 'o', '\0' };
-// Last profile version: Move startup methods to use a bitmap. Also add support for post-startup
-// methods.
-const uint8_t ProfileCompilationInfo::kProfileVersion[] = { '0', '0', '8', '\0' };
+// Last profile version: update the multidex separator.
+const uint8_t ProfileCompilationInfo::kProfileVersion[] = { '0', '0', '9', '\0' };
static constexpr uint16_t kMaxDexFileKeyLength = PATH_MAX;
@@ -1341,7 +1340,7 @@
os << "ProfileInfo:";
- const std::string kFirstDexFileKeySubstitute = ":classes.dex";
+ const std::string kFirstDexFileKeySubstitute = "!classes.dex";
for (const DexFileData* dex_data : info_) {
os << "\n";
diff --git a/runtime/native/java_lang_VMClassLoader.cc b/runtime/native/java_lang_VMClassLoader.cc
index 745d09d..4034e8c 100644
--- a/runtime/native/java_lang_VMClassLoader.cc
+++ b/runtime/native/java_lang_VMClassLoader.cc
@@ -134,7 +134,7 @@
for (size_t i = 0; i < path.size(); ++i) {
const DexFile* dex_file = path[i];
- // For multidex locations, e.g., x.jar:classes2.dex, we want to look into x.jar.
+ // For multidex locations, e.g., x.jar!classes2.dex, we want to look into x.jar.
const std::string& location(dex_file->GetBaseLocation());
ScopedLocalRef<jstring> javaPath(env, env->NewStringUTF(location.c_str()));
diff --git a/runtime/oat.h b/runtime/oat.h
index f4edb16..de4b942 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: add new class status to skip superclass validation.
- static constexpr uint8_t kOatVersion[] = { '1', '2', '9', '\0' };
+ // Last oat version changed reason: update kMultiDexSeparator from ':' to '!'.
+ static constexpr uint8_t kOatVersion[] = { '1', '3', '0', '\0' };
static constexpr const char* kImageLocationKey = "image-location";
static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index b112b84..be7d495 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -289,8 +289,8 @@
// If not null, abs_dex_location is used to resolve the absolute dex
// location of relative dex locations encoded in the oat file.
// For example, given absolute location "/data/app/foo/base.apk", encoded
- // dex locations "base.apk", "base.apk:classes2.dex", etc. would be resolved
- // to "/data/app/foo/base.apk", "/data/app/foo/base.apk:classes2.dex", etc.
+ // dex locations "base.apk", "base.apk!classes2.dex", etc. would be resolved
+ // to "/data/app/foo/base.apk", "/data/app/foo/base.apk!classes2.dex", etc.
// Relative encoded dex locations that don't match the given abs_dex_location
// are left unchanged.
static std::string ResolveRelativeEncodedDexLocation(
diff --git a/runtime/oat_file_test.cc b/runtime/oat_file_test.cc
index d5fe1f3..7bf0f84 100644
--- a/runtime/oat_file_test.cc
+++ b/runtime/oat_file_test.cc
@@ -45,13 +45,13 @@
OatFile::ResolveRelativeEncodedDexLocation(
"/data/app/foo/base.apk", "foo/base.apk"));
- EXPECT_EQ(std::string("/data/app/foo/base.apk:classes2.dex"),
+ EXPECT_EQ(std::string("/data/app/foo/base.apk!classes2.dex"),
OatFile::ResolveRelativeEncodedDexLocation(
- "/data/app/foo/base.apk", "base.apk:classes2.dex"));
+ "/data/app/foo/base.apk", "base.apk!classes2.dex"));
- EXPECT_EQ(std::string("/data/app/foo/base.apk:classes11.dex"),
+ EXPECT_EQ(std::string("/data/app/foo/base.apk!classes11.dex"),
OatFile::ResolveRelativeEncodedDexLocation(
- "/data/app/foo/base.apk", "base.apk:classes11.dex"));
+ "/data/app/foo/base.apk", "base.apk!classes11.dex"));
EXPECT_EQ(std::string("base.apk"),
OatFile::ResolveRelativeEncodedDexLocation(
diff --git a/test/569-checker-pattern-replacement/run b/test/569-checker-pattern-replacement/run
index f7e9df2..8ab6527 100755
--- a/test/569-checker-pattern-replacement/run
+++ b/test/569-checker-pattern-replacement/run
@@ -15,4 +15,4 @@
# limitations under the License.
exec ${RUN} "$@" \
- -Xcompiler-option --no-inline-from=core-oj,569-checker-pattern-replacement.jar:classes2.dex
+ -Xcompiler-option --no-inline-from="core-oj,569-checker-pattern-replacement.jar!classes2.dex"
diff --git a/test/testrunner/env.py b/test/testrunner/env.py
index a0c4ea8..6596ff4 100644
--- a/test/testrunner/env.py
+++ b/test/testrunner/env.py
@@ -233,8 +233,8 @@
HOST_OUT_EXECUTABLES = os.path.join(ANDROID_BUILD_TOP,
_get_build_var("HOST_OUT_EXECUTABLES"))
-os.environ['JACK'] = HOST_OUT_EXECUTABLES + '/jack'
-os.environ['DX'] = HOST_OUT_EXECUTABLES + '/dx'
-os.environ['SMALI'] = HOST_OUT_EXECUTABLES + '/smali'
-os.environ['JASMIN'] = HOST_OUT_EXECUTABLES + '/jasmin'
-os.environ['DXMERGER'] = HOST_OUT_EXECUTABLES + '/dexmerger'
+
+# Set up default values for $JACK, $DX, $SMALI, etc to the $HOST_OUT_EXECUTABLES/$name path.
+for tool in ['jack', 'dx', 'smali', 'jasmin', 'dxmerger']:
+ binary = tool if tool != 'dxmerger' else 'dexmerger'
+ os.environ.setdefault(tool.upper(), HOST_OUT_EXECUTABLES + '/' + binary)