am ec538490: am d3c20c1a: Update compiler blacklist to include java.net.NetworkInterface.
* commit 'ec53849091b66571b9e9fb1e79249b815c43e752':
Update compiler blacklist to include java.net.NetworkInterface.
diff --git a/build/Android.common.mk b/build/Android.common.mk
index ac1be1e..dd0ba4d 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -82,7 +82,8 @@
endif
LLVM_ROOT_PATH := external/llvm
-include $(LLVM_ROOT_PATH)/llvm.mk
+# Don't fail a dalvik minimal host build.
+-include $(LLVM_ROOT_PATH)/llvm.mk
# Clang build.
# ART_TARGET_CLANG := true
diff --git a/build/Android.oat.mk b/build/Android.oat.mk
index ea7b0b0..b680b82 100644
--- a/build/Android.oat.mk
+++ b/build/Android.oat.mk
@@ -81,6 +81,19 @@
include $(BUILD_PHONY_PACKAGE)
endif
+# If we aren't building the host toolchain, skip building the target core.art.
+ifeq ($(WITH_HOST_DALVIK),true)
+ifeq ($(ART_BUILD_TARGET),true)
+include $(CLEAR_VARS)
+LOCAL_MODULE := core.art
+LOCAL_MODULE_TAGS := optional
+LOCAL_ADDITIONAL_DEPENDENCIES := art/build/Android.common.mk
+LOCAL_ADDITIONAL_DEPENDENCIES += art/build/Android.oat.mk
+LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_CORE_IMG_OUT)
+include $(BUILD_PHONY_PACKAGE)
+endif
+endif
+
########################################################################
# The full system boot classpath
TARGET_BOOT_JARS := $(subst :, ,$(DEXPREOPT_BOOT_JARS))
diff --git a/runtime/Android.mk b/runtime/Android.mk
index 459ca0e..8df03cf 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -331,7 +331,7 @@
endif
LOCAL_C_INCLUDES += $(ART_C_INCLUDES)
LOCAL_SHARED_LIBRARIES += liblog libnativehelper
- LOCAL_SHARED_LIBRARIES += libcorkscrew # native stack trace support
+ LOCAL_SHARED_LIBRARIES += libbacktrace # native stack trace support
ifeq ($$(art_target_or_host),target)
LOCAL_SHARED_LIBRARIES += libcutils libz libdl libselinux
else # host
diff --git a/runtime/check_jni.cc b/runtime/check_jni.cc
index 3b1bda4..54cbfe6 100644
--- a/runtime/check_jni.cc
+++ b/runtime/check_jni.cc
@@ -90,12 +90,6 @@
reinterpret_cast<JNIEnvExt*>(env)->self->SirtContains(localRef);
}
-// Hack to allow forcecopy to work with jniGetNonMovableArrayElements.
-// The code deliberately uses an invalid sequence of operations, so we
-// need to pass it through unmodified. Review that code before making
-// any changes here.
-#define kNoCopyMagic 0xd5aab57f
-
// Flags passed into ScopedCheck.
#define kFlag_Default 0x0000
@@ -1098,10 +1092,6 @@
* back into the managed heap, and may or may not release the underlying storage.
*/
static void ReleaseGuardedPACopy(JNIEnv* env, jarray java_array, void* dataBuf, int mode) {
- if (reinterpret_cast<uintptr_t>(dataBuf) == kNoCopyMagic) {
- return;
- }
-
ScopedObjectAccess soa(env);
mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
@@ -1596,9 +1586,7 @@
template<typename ResultT>
ResultT Check(JNIEnv* env, jarray array, jboolean* isCopy, ResultT result) {
if (force_copy && result != NULL) {
- if (no_copy != kNoCopyMagic) {
- result = reinterpret_cast<ResultT>(CreateGuardedPACopy(env, array, isCopy));
- }
+ result = reinterpret_cast<ResultT>(CreateGuardedPACopy(env, array, isCopy));
}
return result;
}
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index f072820..db4cc00 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -4002,11 +4002,11 @@
}
mirror::ArtMethod* ClassLinker::ResolveMethod(const DexFile& dex_file,
- uint32_t method_idx,
- mirror::DexCache* dex_cache,
- mirror::ClassLoader* class_loader,
- const mirror::ArtMethod* referrer,
- InvokeType type) {
+ uint32_t method_idx,
+ mirror::DexCache* dex_cache,
+ mirror::ClassLoader* class_loader,
+ const mirror::ArtMethod* referrer,
+ InvokeType type) {
DCHECK(dex_cache != NULL);
// Check for hit in the dex cache.
mirror::ArtMethod* resolved = dex_cache->GetResolvedMethod(method_idx);
@@ -4149,10 +4149,10 @@
}
mirror::ArtField* ClassLinker::ResolveField(const DexFile& dex_file,
- uint32_t field_idx,
- mirror::DexCache* dex_cache,
- mirror::ClassLoader* class_loader,
- bool is_static) {
+ uint32_t field_idx,
+ mirror::DexCache* dex_cache,
+ mirror::ClassLoader* class_loader,
+ bool is_static) {
DCHECK(dex_cache != NULL);
mirror::ArtField* resolved = dex_cache->GetResolvedField(field_idx);
if (resolved != NULL) {
@@ -4189,9 +4189,9 @@
}
mirror::ArtField* ClassLinker::ResolveFieldJLS(const DexFile& dex_file,
- uint32_t field_idx,
- mirror::DexCache* dex_cache,
- mirror::ClassLoader* class_loader) {
+ uint32_t field_idx,
+ mirror::DexCache* dex_cache,
+ mirror::ClassLoader* class_loader) {
DCHECK(dex_cache != NULL);
mirror::ArtField* resolved = dex_cache->GetResolvedField(field_idx);
if (resolved != NULL) {
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index baeec66..11ba78b 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -346,10 +346,6 @@
return quick_resolution_trampoline_;
}
- InternTable* GetInternTable() const {
- return intern_table_;
- }
-
// Attempts to insert a class into a class table. Returns NULL if
// the class was inserted, otherwise returns an existing class with
// the same descriptor and ClassLoader.
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index 346154c..cef4ce4 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -33,6 +33,8 @@
namespace art {
+// TODO: remove dependencies on mirror classes, primarily by moving
+// EncodedStaticFieldValueIterator to its own file.
namespace mirror {
class ArtField;
class ArtMethod;
diff --git a/runtime/mem_map.cc b/runtime/mem_map.cc
index 6451d5c..7802acc 100644
--- a/runtime/mem_map.cc
+++ b/runtime/mem_map.cc
@@ -16,7 +16,7 @@
#include "mem_map.h"
-#include <corkscrew/map_info.h>
+#include <backtrace/backtrace.h>
#include "base/stringprintf.h"
#include "ScopedFd.h"
@@ -32,8 +32,8 @@
#if !defined(NDEBUG)
-static std::ostream& operator<<(std::ostream& os, map_info_t* rhs) {
- for (map_info_t* m = rhs; m != NULL; m = m->next) {
+static std::ostream& operator<<(std::ostream& os, backtrace_map_info_t* rhs) {
+ for (backtrace_map_info_t* m = rhs; m != NULL; m = m->next) {
os << StringPrintf("0x%08x-0x%08x %c%c %s\n",
static_cast<uint32_t>(m->start),
static_cast<uint32_t>(m->end),
@@ -50,8 +50,8 @@
uint32_t base = reinterpret_cast<size_t>(addr);
uint32_t limit = base + byte_count;
- map_info_t* map_info_list = load_map_info_list(getpid());
- for (map_info_t* m = map_info_list; m != NULL; m = m->next) {
+ backtrace_map_info_t* map_info_list = backtrace_create_map_info_list(getpid());
+ for (backtrace_map_info_t* m = map_info_list; m != NULL; m = m->next) {
CHECK(!(base >= m->start && base < m->end) // start of new within old
&& !(limit > m->start && limit < m->end) // end of new within old
&& !(base <= m->start && limit > m->end)) // start/end of new includes all of old
@@ -60,7 +60,7 @@
static_cast<uint32_t>(m->start), static_cast<uint32_t>(m->end), m->name)
<< map_info_list;
}
- free_map_info_list(map_info_list);
+ backtrace_destroy_map_info_list(map_info_list);
}
#else
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index 5fc8bd5..83d3acb 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -20,12 +20,15 @@
#include "common_throws.h"
#include "debugger.h"
#include "dex_file-inl.h"
+#include "gc/accounting/card_table-inl.h"
#include "gc/allocator/dlmalloc.h"
#include "gc/heap.h"
#include "gc/space/dlmalloc_space.h"
+#include "intern_table.h"
#include "jni_internal.h"
+#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
-#include "mirror/object.h"
+#include "mirror/dex_cache-inl.h"
#include "mirror/object-inl.h"
#include "object_utils.h"
#include "scoped_thread_state_change.h"
@@ -49,7 +52,10 @@
static void VMRuntime_disableJitCompilation(JNIEnv*, jobject) {
}
-static jobject VMRuntime_newNonMovableArray(JNIEnv* env, jobject, jclass javaElementClass, jint length) {
+static jobject VMRuntime_newNonMovableArray(JNIEnv* env,
+ jobject,
+ jclass javaElementClass,
+ jint length) {
ScopedObjectAccess soa(env);
#ifdef MOVING_GARBAGE_COLLECTOR
// TODO: right now, we don't have a copying collector, so there's no need
@@ -128,7 +134,7 @@
return env->NewStringUTF(kIsDebugBuild ? "libartd.so" : "libart.so");
}
-static void VMRuntime_setTargetSdkVersion(JNIEnv* env, jobject, jint targetSdkVersion) {
+static void VMRuntime_setTargetSdkVersionNative(JNIEnv* env, jobject, jint targetSdkVersion) {
// This is the target SDK version of the app we're about to run.
// Note that targetSdkVersion may be CUR_DEVELOPMENT (10000).
// Note that targetSdkVersion may be 0, meaning "current".
@@ -196,6 +202,311 @@
Runtime::Current()->GetHeap()->ConcurrentGC(self);
}
+typedef std::map<std::string, mirror::String*> StringTable;
+
+static void PreloadDexCachesStringsVisitor(const mirror::Object* root, void* arg) {
+ StringTable& table = *reinterpret_cast<StringTable*>(arg);
+ mirror::String* string = const_cast<mirror::Object*>(root)->AsString();
+ // LOG(INFO) << "VMRuntime.preloadDexCaches interned=" << string->ToModifiedUtf8();
+ table[string->ToModifiedUtf8()] = string;
+}
+
+// Based on ClassLinker::ResolveString.
+static void PreloadDexCachesResolveString(mirror::DexCache* dex_cache,
+ uint32_t string_idx,
+ StringTable& strings)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ mirror::String* string = dex_cache->GetResolvedString(string_idx);
+ if (string != NULL) {
+ return;
+ }
+ const DexFile* dex_file = dex_cache->GetDexFile();
+ uint32_t utf16Size;
+ const char* utf8 = dex_file->StringDataAndLengthByIdx(string_idx, &utf16Size);
+ string = strings[utf8];
+ if (string == NULL) {
+ return;
+ }
+ // LOG(INFO) << "VMRuntime.preloadDexCaches resolved string=" << utf8;
+ dex_cache->SetResolvedString(string_idx, string);
+}
+
+// Based on ClassLinker::ResolveType.
+static void PreloadDexCachesResolveType(mirror::DexCache* dex_cache, uint32_t type_idx)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ mirror::Class* klass = dex_cache->GetResolvedType(type_idx);
+ if (klass != NULL) {
+ return;
+ }
+ const DexFile* dex_file = dex_cache->GetDexFile();
+ const char* class_name = dex_file->StringByTypeIdx(type_idx);
+ ClassLinker* linker = Runtime::Current()->GetClassLinker();
+ if (class_name[1] == '\0') {
+ klass = linker->FindPrimitiveClass(class_name[0]);
+ } else {
+ klass = linker->LookupClass(class_name, NULL);
+ }
+ if (klass == NULL) {
+ return;
+ }
+ // LOG(INFO) << "VMRuntime.preloadDexCaches resolved klass=" << class_name;
+ dex_cache->SetResolvedType(type_idx, klass);
+ // Skip uninitialized classes because filled static storage entry implies it is initialized.
+ if (!klass->IsInitialized()) {
+ // LOG(INFO) << "VMRuntime.preloadDexCaches uninitialized klass=" << class_name;
+ return;
+ }
+ // LOG(INFO) << "VMRuntime.preloadDexCaches static storage klass=" << class_name;
+ dex_cache->GetInitializedStaticStorage()->Set(type_idx, klass);
+}
+
+// Based on ClassLinker::ResolveField.
+static void PreloadDexCachesResolveField(mirror::DexCache* dex_cache,
+ uint32_t field_idx,
+ bool is_static)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ mirror::ArtField* field = dex_cache->GetResolvedField(field_idx);
+ if (field != NULL) {
+ return;
+ }
+ const DexFile* dex_file = dex_cache->GetDexFile();
+ const DexFile::FieldId& field_id = dex_file->GetFieldId(field_idx);
+ mirror::Class* klass = dex_cache->GetResolvedType(field_id.class_idx_);
+ if (klass == NULL) {
+ return;
+ }
+ if (is_static) {
+ field = klass->FindStaticField(dex_cache, field_idx);
+ } else {
+ field = klass->FindInstanceField(dex_cache, field_idx);
+ }
+ if (field == NULL) {
+ return;
+ }
+ // LOG(INFO) << "VMRuntime.preloadDexCaches resolved field " << PrettyField(field);
+ dex_cache->SetResolvedField(field_idx, field);
+}
+
+// Based on ClassLinker::ResolveMethod.
+static void PreloadDexCachesResolveMethod(mirror::DexCache* dex_cache,
+ uint32_t method_idx,
+ InvokeType invoke_type)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ mirror::ArtMethod* method = dex_cache->GetResolvedMethod(method_idx);
+ if (method != NULL) {
+ return;
+ }
+ const DexFile* dex_file = dex_cache->GetDexFile();
+ const DexFile::MethodId& method_id = dex_file->GetMethodId(method_idx);
+ mirror::Class* klass = dex_cache->GetResolvedType(method_id.class_idx_);
+ if (klass == NULL) {
+ return;
+ }
+ switch (invoke_type) {
+ case kDirect:
+ case kStatic:
+ method = klass->FindDirectMethod(dex_cache, method_idx);
+ break;
+ case kInterface:
+ method = klass->FindInterfaceMethod(dex_cache, method_idx);
+ break;
+ case kSuper:
+ case kVirtual:
+ method = klass->FindVirtualMethod(dex_cache, method_idx);
+ break;
+ default:
+ LOG(FATAL) << "Unreachable - invocation type: " << invoke_type;
+ }
+ if (method == NULL) {
+ return;
+ }
+ // LOG(INFO) << "VMRuntime.preloadDexCaches resolved method " << PrettyMethod(method);
+ dex_cache->SetResolvedMethod(method_idx, method);
+}
+
+struct DexCacheStats {
+ uint32_t num_strings;
+ uint32_t num_types;
+ uint32_t num_fields;
+ uint32_t num_methods;
+ uint32_t num_static_storage;
+ DexCacheStats() : num_strings(0),
+ num_types(0),
+ num_fields(0),
+ num_methods(0),
+ num_static_storage(0) {}
+};
+
+static const bool kPreloadDexCachesEnabled = true;
+
+// Disabled because it takes a long time (extra half second) but
+// gives almost no benefit in terms of saving private dirty pages.
+static const bool kPreloadDexCachesStrings = false;
+
+static const bool kPreloadDexCachesTypes = true;
+static const bool kPreloadDexCachesFieldsAndMethods = true;
+
+static const bool kPreloadDexCachesCollectStats = true;
+
+static void PreloadDexCachesStatsTotal(DexCacheStats* total) {
+ if (!kPreloadDexCachesCollectStats) {
+ return;
+ }
+
+ ClassLinker* linker = Runtime::Current()->GetClassLinker();
+ const std::vector<const DexFile*>& boot_class_path = linker->GetBootClassPath();
+ for (size_t i = 0; i< boot_class_path.size(); i++) {
+ const DexFile* dex_file = boot_class_path[i];
+ CHECK(dex_file != NULL);
+ total->num_strings += dex_file->NumStringIds();
+ total->num_fields += dex_file->NumFieldIds();
+ total->num_methods += dex_file->NumMethodIds();
+ total->num_types += dex_file->NumTypeIds();
+ total->num_static_storage += dex_file->NumTypeIds();
+ }
+}
+
+static void PreloadDexCachesStatsFilled(DexCacheStats* filled)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ if (!kPreloadDexCachesCollectStats) {
+ return;
+ }
+ ClassLinker* linker = Runtime::Current()->GetClassLinker();
+ const std::vector<const DexFile*>& boot_class_path = linker->GetBootClassPath();
+ for (size_t i = 0; i< boot_class_path.size(); i++) {
+ const DexFile* dex_file = boot_class_path[i];
+ CHECK(dex_file != NULL);
+ mirror::DexCache* dex_cache = linker->FindDexCache(*dex_file);
+ for (size_t i = 0; i < dex_cache->NumStrings(); i++) {
+ mirror::String* string = dex_cache->GetResolvedString(i);
+ if (string != NULL) {
+ filled->num_strings++;
+ }
+ }
+ for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) {
+ mirror::Class* klass = dex_cache->GetResolvedType(i);
+ if (klass != NULL) {
+ filled->num_types++;
+ }
+ }
+ for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) {
+ mirror::ArtField* field = dex_cache->GetResolvedField(i);
+ if (field != NULL) {
+ filled->num_fields++;
+ }
+ }
+ for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) {
+ mirror::ArtMethod* method = dex_cache->GetResolvedMethod(i);
+ if (method != NULL) {
+ filled->num_methods++;
+ }
+ }
+ for (size_t i = 0; i < dex_cache->NumInitializedStaticStorage(); i++) {
+ mirror::StaticStorageBase* klass = dex_cache->GetInitializedStaticStorage()->Get(i);
+ if (klass != NULL) {
+ filled->num_static_storage++;
+ }
+ }
+ }
+}
+
+// TODO: http://b/11309598 This code was ported over based on the
+// Dalvik version. However, ART has similar code in other places such
+// as the CompilerDriver. This code could probably be refactored to
+// serve both uses.
+static void VMRuntime_preloadDexCaches(JNIEnv* env, jobject) {
+ if (!kPreloadDexCachesEnabled) {
+ return;
+ }
+
+ ScopedObjectAccess soa(env);
+
+ DexCacheStats total;
+ DexCacheStats before;
+ if (kPreloadDexCachesCollectStats) {
+ LOG(INFO) << "VMRuntime.preloadDexCaches starting";
+ PreloadDexCachesStatsTotal(&total);
+ PreloadDexCachesStatsFilled(&before);
+ }
+
+ Runtime* runtime = Runtime::Current();
+ ClassLinker* linker = runtime->GetClassLinker();
+
+ // We use a std::map to avoid heap allocating StringObjects to lookup in gDvm.literalStrings
+ StringTable strings;
+ if (kPreloadDexCachesStrings) {
+ runtime->GetInternTable()->VisitRoots(PreloadDexCachesStringsVisitor, &strings, false, false);
+ }
+
+ const std::vector<const DexFile*>& boot_class_path = linker->GetBootClassPath();
+ for (size_t i = 0; i< boot_class_path.size(); i++) {
+ const DexFile* dex_file = boot_class_path[i];
+ CHECK(dex_file != NULL);
+ mirror::DexCache* dex_cache = linker->FindDexCache(*dex_file);
+
+ if (kPreloadDexCachesStrings) {
+ for (size_t i = 0; i < dex_cache->NumStrings(); i++) {
+ PreloadDexCachesResolveString(dex_cache, i, strings);
+ }
+ }
+
+ if (kPreloadDexCachesTypes) {
+ for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) {
+ PreloadDexCachesResolveType(dex_cache, i);
+ }
+ }
+
+ if (kPreloadDexCachesFieldsAndMethods) {
+ for (size_t class_def_index = 0;
+ class_def_index < dex_file->NumClassDefs();
+ class_def_index++) {
+ const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
+ const byte* class_data = dex_file->GetClassData(class_def);
+ if (class_data == NULL) {
+ continue;
+ }
+ ClassDataItemIterator it(*dex_file, class_data);
+ for (; it.HasNextStaticField(); it.Next()) {
+ uint32_t field_idx = it.GetMemberIndex();
+ PreloadDexCachesResolveField(dex_cache, field_idx, true);
+ }
+ for (; it.HasNextInstanceField(); it.Next()) {
+ uint32_t field_idx = it.GetMemberIndex();
+ PreloadDexCachesResolveField(dex_cache, field_idx, false);
+ }
+ for (; it.HasNextDirectMethod(); it.Next()) {
+ uint32_t method_idx = it.GetMemberIndex();
+ InvokeType invoke_type = it.GetMethodInvokeType(class_def);
+ PreloadDexCachesResolveMethod(dex_cache, method_idx, invoke_type);
+ }
+ for (; it.HasNextVirtualMethod(); it.Next()) {
+ uint32_t method_idx = it.GetMemberIndex();
+ InvokeType invoke_type = it.GetMethodInvokeType(class_def);
+ PreloadDexCachesResolveMethod(dex_cache, method_idx, invoke_type);
+ }
+ }
+ }
+ }
+
+ if (kPreloadDexCachesCollectStats) {
+ DexCacheStats after;
+ PreloadDexCachesStatsFilled(&after);
+ LOG(INFO) << StringPrintf("VMRuntime.preloadDexCaches strings total=%d before=%d after=%d",
+ total.num_strings, before.num_strings, after.num_strings);
+ LOG(INFO) << StringPrintf("VMRuntime.preloadDexCaches types total=%d before=%d after=%d",
+ total.num_types, before.num_types, after.num_types);
+ LOG(INFO) << StringPrintf("VMRuntime.preloadDexCaches fields total=%d before=%d after=%d",
+ total.num_fields, before.num_fields, after.num_fields);
+ LOG(INFO) << StringPrintf("VMRuntime.preloadDexCaches methods total=%d before=%d after=%d",
+ total.num_methods, before.num_methods, after.num_methods);
+ LOG(INFO) << StringPrintf("VMRuntime.preloadDexCaches storage total=%d before=%d after=%d",
+ total.num_static_storage,
+ before.num_static_storage,
+ after.num_static_storage);
+ LOG(INFO) << StringPrintf("VMRuntime.preloadDexCaches finished");
+ }
+}
+
static JNINativeMethod gMethods[] = {
NATIVE_METHOD(VMRuntime, addressOf, "(Ljava/lang/Object;)J"),
NATIVE_METHOD(VMRuntime, bootClassPath, "()Ljava/lang/String;"),
@@ -208,13 +519,14 @@
NATIVE_METHOD(VMRuntime, nativeSetTargetHeapUtilization, "(F)V"),
NATIVE_METHOD(VMRuntime, newNonMovableArray, "(Ljava/lang/Class;I)Ljava/lang/Object;"),
NATIVE_METHOD(VMRuntime, properties, "()[Ljava/lang/String;"),
- NATIVE_METHOD(VMRuntime, setTargetSdkVersion, "(I)V"),
+ NATIVE_METHOD(VMRuntime, setTargetSdkVersionNative, "(I)V"),
NATIVE_METHOD(VMRuntime, registerNativeAllocation, "(I)V"),
NATIVE_METHOD(VMRuntime, registerNativeFree, "(I)V"),
NATIVE_METHOD(VMRuntime, startJitCompilation, "()V"),
NATIVE_METHOD(VMRuntime, trimHeap, "()V"),
NATIVE_METHOD(VMRuntime, vmVersion, "()Ljava/lang/String;"),
NATIVE_METHOD(VMRuntime, vmLibrary, "()Ljava/lang/String;"),
+ NATIVE_METHOD(VMRuntime, preloadDexCaches, "()V"),
};
void register_dalvik_system_VMRuntime(JNIEnv* env) {
diff --git a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
index 13cd978..0676968 100644
--- a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
+++ b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
@@ -109,8 +109,10 @@
* be removed from a future version.
*/
char native_thread_state;
- int utime, stime, task_cpu;
- GetTaskStats(t->GetTid(), native_thread_state, utime, stime, task_cpu);
+ int utime;
+ int stime;
+ int task_cpu;
+ GetTaskStats(t->GetTid(), &native_thread_state, &utime, &stime, &task_cpu);
std::vector<uint8_t>& bytes = *reinterpret_cast<std::vector<uint8_t>*>(context);
JDWP::Append4BE(bytes, t->GetThinLockId());
diff --git a/runtime/runtime.h b/runtime/runtime.h
index bc5c8b0..7c28479 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -279,6 +279,7 @@
}
InternTable* GetInternTable() const {
+ DCHECK(intern_table_ != NULL);
return intern_table_;
}
diff --git a/runtime/stack.h b/runtime/stack.h
index 8ecf8f0..7c87f45 100644
--- a/runtime/stack.h
+++ b/runtime/stack.h
@@ -138,13 +138,17 @@
int64_t GetVRegLong(size_t i) const {
DCHECK_LT(i, NumberOfVRegs());
const uint32_t* vreg = &vregs_[i];
- return *reinterpret_cast<const int64_t*>(vreg);
+ // Alignment attribute required for GCC 4.8
+ typedef const int64_t unaligned_int64 __attribute__ ((aligned (4)));
+ return *reinterpret_cast<unaligned_int64*>(vreg);
}
double GetVRegDouble(size_t i) const {
DCHECK_LT(i, NumberOfVRegs());
const uint32_t* vreg = &vregs_[i];
- return *reinterpret_cast<const double*>(vreg);
+ // Alignment attribute required for GCC 4.8
+ typedef const double unaligned_double __attribute__ ((aligned (4)));
+ return *reinterpret_cast<unaligned_double*>(vreg);
}
mirror::Object* GetVRegReference(size_t i) const {
@@ -177,13 +181,17 @@
void SetVRegLong(size_t i, int64_t val) {
DCHECK_LT(i, NumberOfVRegs());
uint32_t* vreg = &vregs_[i];
- *reinterpret_cast<int64_t*>(vreg) = val;
+ // Alignment attribute required for GCC 4.8
+ typedef int64_t unaligned_int64 __attribute__ ((aligned (4)));
+ *reinterpret_cast<unaligned_int64*>(vreg) = val;
}
void SetVRegDouble(size_t i, double val) {
DCHECK_LT(i, NumberOfVRegs());
uint32_t* vreg = &vregs_[i];
- *reinterpret_cast<double*>(vreg) = val;
+ // Alignment attribute required for GCC 4.8
+ typedef double unaligned_double __attribute__ ((aligned (4)));
+ *reinterpret_cast<unaligned_double*>(vreg) = val;
}
void SetVRegReference(size_t i, mirror::Object* val) {
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 23cafe8..e8326ea 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -417,7 +417,7 @@
void Thread::InitStackHwm() {
void* stack_base;
size_t stack_size;
- GetThreadStack(pthread_self_, stack_base, stack_size);
+ GetThreadStack(pthread_self_, &stack_base, &stack_size);
// TODO: include this in the thread dumps; potentially useful in SIGQUIT output?
VLOG(threads) << StringPrintf("Native stack is at %p (%s)", stack_base, PrettySize(stack_size).c_str());
@@ -757,7 +757,7 @@
int utime = 0;
int stime = 0;
int task_cpu = 0;
- GetTaskStats(tid, native_thread_state, utime, stime, task_cpu);
+ GetTaskStats(tid, &native_thread_state, &utime, &stime, &task_cpu);
os << " | state=" << native_thread_state
<< " schedstat=( " << scheduler_stats << " )"
diff --git a/runtime/utils.cc b/runtime/utils.cc
index bf36bf3..7fa06a3 100644
--- a/runtime/utils.cc
+++ b/runtime/utils.cc
@@ -49,8 +49,7 @@
#include <sys/syscall.h>
#endif
-#include <corkscrew/backtrace.h> // For DumpNativeStack.
-#include <corkscrew/demangle.h> // For DumpNativeStack.
+#include <backtrace/Backtrace.h> // For DumpNativeStack.
#if defined(__linux__)
#include <linux/unistd.h>
@@ -79,23 +78,23 @@
return result;
}
-void GetThreadStack(pthread_t thread, void*& stack_base, size_t& stack_size) {
+void GetThreadStack(pthread_t thread, void** stack_base, size_t* stack_size) {
#if defined(__APPLE__)
- stack_size = pthread_get_stacksize_np(thread);
+ *stack_size = pthread_get_stacksize_np(thread);
void* stack_addr = pthread_get_stackaddr_np(thread);
// Check whether stack_addr is the base or end of the stack.
// (On Mac OS 10.7, it's the end.)
int stack_variable;
if (stack_addr > &stack_variable) {
- stack_base = reinterpret_cast<byte*>(stack_addr) - stack_size;
+ *stack_base = reinterpret_cast<byte*>(stack_addr) - *stack_size;
} else {
- stack_base = stack_addr;
+ *stack_base = stack_addr;
}
#else
pthread_attr_t attributes;
CHECK_PTHREAD_CALL(pthread_getattr_np, (thread, &attributes), __FUNCTION__);
- CHECK_PTHREAD_CALL(pthread_attr_getstack, (&attributes, &stack_base, &stack_size), __FUNCTION__);
+ CHECK_PTHREAD_CALL(pthread_attr_getstack, (&attributes, stack_base, stack_size), __FUNCTION__);
CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attributes), __FUNCTION__);
#endif
}
@@ -955,8 +954,8 @@
#endif
}
-void GetTaskStats(pid_t tid, char& state, int& utime, int& stime, int& task_cpu) {
- utime = stime = task_cpu = 0;
+void GetTaskStats(pid_t tid, char* state, int* utime, int* stime, int* task_cpu) {
+ *utime = *stime = *task_cpu = 0;
std::string stats;
if (!ReadFileToString(StringPrintf("/proc/self/task/%d/stat", tid), &stats)) {
return;
@@ -966,10 +965,10 @@
// Extract the three fields we care about.
std::vector<std::string> fields;
Split(stats, ' ', fields);
- state = fields[0][0];
- utime = strtoull(fields[11].c_str(), NULL, 10);
- stime = strtoull(fields[12].c_str(), NULL, 10);
- task_cpu = strtoull(fields[36].c_str(), NULL, 10);
+ *state = fields[0][0];
+ *utime = strtoull(fields[11].c_str(), NULL, 10);
+ *stime = strtoull(fields[12].c_str(), NULL, 10);
+ *task_cpu = strtoull(fields[36].c_str(), NULL, 10);
}
std::string GetSchedulerGroupName(pid_t tid) {
@@ -997,10 +996,9 @@
return "";
}
-static const char* CleanMapName(const backtrace_symbol_t* symbol) {
- const char* map_name = symbol->map_name;
+static const char* CleanMapName(const char* map_name) {
if (map_name == NULL) {
- map_name = "???";
+ return "???";
}
// Turn "/usr/local/google/home/enh/clean-dalvik-dev/out/host/linux-x86/lib/libartd.so"
// into "libartd.so".
@@ -1011,89 +1009,36 @@
return map_name;
}
-static void FindSymbolInElf(const backtrace_frame_t* frame, const backtrace_symbol_t* symbol,
- std::string& symbol_name, uint32_t& pc_offset) {
- symbol_table_t* symbol_table = NULL;
- if (symbol->map_name != NULL) {
- symbol_table = load_symbol_table(symbol->map_name);
- }
- const symbol_t* elf_symbol = NULL;
- bool was_relative = true;
- if (symbol_table != NULL) {
- elf_symbol = find_symbol(symbol_table, symbol->relative_pc);
- if (elf_symbol == NULL) {
- elf_symbol = find_symbol(symbol_table, frame->absolute_pc);
- was_relative = false;
- }
- }
- if (elf_symbol != NULL) {
- const char* demangled_symbol_name = demangle_symbol_name(elf_symbol->name);
- if (demangled_symbol_name != NULL) {
- symbol_name = demangled_symbol_name;
- } else {
- symbol_name = elf_symbol->name;
- }
-
- // TODO: is it a libcorkscrew bug that we have to do this?
- pc_offset = (was_relative ? symbol->relative_pc : frame->absolute_pc) - elf_symbol->start;
- } else {
- symbol_name = "???";
- }
- free_symbol_table(symbol_table);
-}
-
void DumpNativeStack(std::ostream& os, pid_t tid, const char* prefix, bool include_count) {
- // Ensure libcorkscrew doesn't use a stale cache of /proc/self/maps.
- flush_my_map_info_list();
-
- const size_t MAX_DEPTH = 32;
- UniquePtr<backtrace_frame_t[]> frames(new backtrace_frame_t[MAX_DEPTH]);
- size_t ignore_count = 2; // Don't include unwind_backtrace_thread or DumpNativeStack.
- ssize_t frame_count = unwind_backtrace_thread(tid, frames.get(), ignore_count, MAX_DEPTH);
- if (frame_count == -1) {
- os << prefix << "(unwind_backtrace_thread failed for thread " << tid << ")\n";
+ UniquePtr<Backtrace> backtrace(Backtrace::Create(-1, tid));
+ if (!backtrace->Unwind(0)) {
+ os << prefix << "(backtrace::Unwind failed for thread " << tid << ")\n";
return;
- } else if (frame_count == 0) {
+ } else if (backtrace->NumFrames() == 0) {
os << prefix << "(no native stack frames for thread " << tid << ")\n";
return;
}
- UniquePtr<backtrace_symbol_t[]> backtrace_symbols(new backtrace_symbol_t[frame_count]);
- get_backtrace_symbols(frames.get(), frame_count, backtrace_symbols.get());
-
- for (size_t i = 0; i < static_cast<size_t>(frame_count); ++i) {
- const backtrace_frame_t* frame = &frames[i];
- const backtrace_symbol_t* symbol = &backtrace_symbols[i];
-
+ for (size_t i = 0; i < backtrace->NumFrames(); ++i) {
// We produce output like this:
- // ] #00 unwind_backtrace_thread+536 [0x55d75bb8] (libcorkscrew.so)
-
- std::string symbol_name;
- uint32_t pc_offset = 0;
- if (symbol->demangled_name != NULL) {
- symbol_name = symbol->demangled_name;
- pc_offset = symbol->relative_pc - symbol->relative_symbol_addr;
- } else if (symbol->symbol_name != NULL) {
- symbol_name = symbol->symbol_name;
- pc_offset = symbol->relative_pc - symbol->relative_symbol_addr;
- } else {
- // dladdr(3) didn't find a symbol; maybe it's static? Look in the ELF file...
- FindSymbolInElf(frame, symbol, symbol_name, pc_offset);
- }
+ // ] #00 unwind_backtrace_thread+536 [0x55d75bb8] (libbacktrace.so)
+ const backtrace_frame_data_t* frame = backtrace->GetFrame(i);
os << prefix;
if (include_count) {
- os << StringPrintf("#%02zd ", i);
+ os << StringPrintf("#%02zu ", i);
}
- os << symbol_name;
- if (pc_offset != 0) {
- os << "+" << pc_offset;
+ if (frame->func_name) {
+ os << frame->func_name;
+ } else {
+ os << "???";
}
- os << StringPrintf(" [%p] (%s)\n",
- reinterpret_cast<void*>(frame->absolute_pc), CleanMapName(symbol));
+ if (frame->func_offset != 0) {
+ os << "+" << frame->func_offset;
+ }
+ os << StringPrintf(" [%p]", reinterpret_cast<void*>(frame->pc));
+ os << " (" << CleanMapName(frame->map_name) << ")\n";
}
-
- free_backtrace_symbols(backtrace_symbols.get(), frame_count);
}
#if defined(__APPLE__)
diff --git a/runtime/utils.h b/runtime/utils.h
index 812a581..975f08b 100644
--- a/runtime/utils.h
+++ b/runtime/utils.h
@@ -323,10 +323,10 @@
std::string GetThreadName(pid_t tid);
// Returns details of the given thread's stack.
-void GetThreadStack(pthread_t thread, void*& stack_base, size_t& stack_size);
+void GetThreadStack(pthread_t thread, void** stack_base, size_t* stack_size);
// Reads data from "/proc/self/task/${tid}/stat".
-void GetTaskStats(pid_t tid, char& state, int& utime, int& stime, int& task_cpu);
+void GetTaskStats(pid_t tid, char* state, int* utime, int* stime, int* task_cpu);
// Returns the name of the scheduler group for the given thread the current process, or the empty string.
std::string GetSchedulerGroupName(pid_t tid);
diff --git a/runtime/verifier/register_line.cc b/runtime/verifier/register_line.cc
index 9f29bae..a615cc1 100644
--- a/runtime/verifier/register_line.cc
+++ b/runtime/verifier/register_line.cc
@@ -468,8 +468,8 @@
}
}
if (monitors_.size() != incoming_line->monitors_.size()) {
- LOG(WARNING) << "mismatched stack depths (depth=" << MonitorStackDepth()
- << ", incoming depth=" << incoming_line->MonitorStackDepth() << ")";
+ verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "mismatched stack depths (depth="
+ << MonitorStackDepth() << ", incoming depth=" << incoming_line->MonitorStackDepth() << ")";
} else if (reg_to_lock_depths_ != incoming_line->reg_to_lock_depths_) {
for (uint32_t idx = 0; idx < num_regs_; idx++) {
size_t depths = reg_to_lock_depths_.count(idx);
@@ -478,8 +478,8 @@
if (depths == 0 || incoming_depths == 0) {
reg_to_lock_depths_.erase(idx);
} else {
- LOG(WARNING) << "mismatched stack depths for register v" << idx
- << ": " << depths << " != " << incoming_depths;
+ verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "mismatched stack depths for register v" << idx
+ << ": " << depths << " != " << incoming_depths;
break;
}
}
diff --git a/test/055-enum-performance/run b/test/055-enum-performance/run
index 1436ce2..e27a622 100755
--- a/test/055-enum-performance/run
+++ b/test/055-enum-performance/run
@@ -14,5 +14,5 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# As this is a performance test we always run -O
-exec ${RUN} -O "$@"
+# As this is a performance test we always use the non-debug build.
+exec ${RUN} "${@/#libartd.so/libart.so}"
diff --git a/test/etc/host-run-test-jar b/test/etc/host-run-test-jar
index 357fb5a..da74532 100755
--- a/test/etc/host-run-test-jar
+++ b/test/etc/host-run-test-jar
@@ -9,7 +9,6 @@
fi
}
-LIB="libartd.so"
DEBUGGER="n"
GDB="n"
INTERPRETER="n"
@@ -23,11 +22,17 @@
if [ "x$1" = "x--quiet" ]; then
QUIET="y"
shift
- elif [ "x$1" = "x-lib" ]; then
+ elif [ "x$1" = "x--lib" ]; then
shift
+ if [ "x$1" = "x" ]; then
+ echo "$0 missing argument to --lib" 1>&2
+ exit 1
+ fi
LIB="$1"
- elif [ "x$1" = "x-O" ]; then
- LIB="libart.so"
+ shift
+ elif [ "x$1" = "x--boot" ]; then
+ shift
+ BOOT_OPT="$1"
shift
elif [ "x$1" = "x--debug" ]; then
DEBUGGER="y"
@@ -38,6 +43,10 @@
shift
elif [ "x$1" = "x--invoke-with" ]; then
shift
+ if [ "x$1" = "x" ]; then
+ echo "$0 missing argument to --invoke-with" 1>&2
+ exit 1
+ fi
if [ "x$INVOKE_WITH" = "x" ]; then
INVOKE_WITH="$1"
else
@@ -106,7 +115,9 @@
JNI_OPTS="-Xjnigreflimit:512 -Xcheck:jni"
+if [ "$DEV_MODE" = "y" ]; then
+ echo $cmdline "$@"
+fi
+
cd $ANDROID_BUILD_TOP
-$INVOKE_WITH $gdb $exe $gdbargs -XXlib:$LIB -Ximage:$ANDROID_ROOT/framework/core.art \
- $JNI_OPTS $INT_OPTS $DEBUGGER_OPTS \
- -cp $DEX_LOCATION/$TEST_NAME.jar Main "$@"
+$INVOKE_WITH $gdb $exe $gdbargs -XXlib:$LIB $JNI_OPTS $INT_OPTS $DEBUGGER_OPTS $BOOT_OPT -cp $DEX_LOCATION/$TEST_NAME.jar Main "$@"
diff --git a/test/etc/push-and-run-test-jar b/test/etc/push-and-run-test-jar
index cc28592..ff75d32 100755
--- a/test/etc/push-and-run-test-jar
+++ b/test/etc/push-and-run-test-jar
@@ -9,7 +9,6 @@
fi
}
-LIB="libartd.so"
GDB="n"
DEBUGGER="n"
INTERPRETER="n"
@@ -24,11 +23,17 @@
if [ "x$1" = "x--quiet" ]; then
QUIET="y"
shift
- elif [ "x$1" = "x-lib" ]; then
+ elif [ "x$1" = "x--lib" ]; then
shift
+ if [ "x$1" = "x" ]; then
+ echo "$0 missing argument to --lib" 1>&2
+ exit 1
+ fi
LIB="$1"
- elif [ "x$1" = "x-O" ]; then
- LIB="libart.so"
+ shift
+ elif [ "x$1" = "x--boot" ]; then
+ shift
+ BOOT_OPT="$1"
shift
elif [ "x$1" = "x--debug" ]; then
DEBUGGER="y"
@@ -49,6 +54,10 @@
shift
elif [ "x$1" = "x--invoke-with" ]; then
shift
+ if [ "x$1" = "x" ]; then
+ echo "$0 missing argument to --invoke-with" 1>&2
+ exit 1
+ fi
if [ "x$INVOKE_WITH" = "x" ]; then
INVOKE_WITH="$1"
else
@@ -132,7 +141,7 @@
JNI_OPTS="-Xjnigreflimit:512 -Xcheck:jni"
cmdline="cd $DEX_LOCATION && mkdir dalvik-cache && export ANDROID_DATA=$DEX_LOCATION && export DEX_LOCATION=$DEX_LOCATION && \
- $INVOKE_WITH $gdb dalvikvm $gdbargs -XXlib:$LIB $ZYGOTE $JNI_OPTS $INT_OPTS $DEBUGGER_OPTS -Ximage:/data/art-test/core.art -cp $DEX_LOCATION/$TEST_NAME.jar Main"
+ $INVOKE_WITH $gdb dalvikvm $gdbargs -XXlib:$LIB $ZYGOTE $JNI_OPTS $INT_OPTS $DEBUGGER_OPTS $BOOT_OPT -cp $DEX_LOCATION/$TEST_NAME.jar Main"
if [ "$DEV_MODE" = "y" ]; then
echo $cmdline "$@"
fi
diff --git a/test/run-test b/test/run-test
index 11dcfc5..a34cc72 100755
--- a/test/run-test
+++ b/test/run-test
@@ -58,12 +58,14 @@
expected="expected.txt"
output="output.txt"
build_output="build-output.txt"
+lib="libartd.so"
run_args="--quiet"
target_mode="yes"
dev_mode="no"
update_mode="no"
debug_mode="no"
+dalvik_mode="no"
usage="no"
build_only="no"
@@ -79,7 +81,16 @@
NEED_DEX="false"
shift
elif [ "x$1" = "x-O" ]; then
- run_args="${run_args} -O"
+ lib="libart.so"
+ shift
+ elif [ "x$1" = "x--dalvik" ]; then
+ lib="libdvm.so"
+ dalvik_mode="yes"
+ shift
+ elif [ "x$1" = "x--image" ]; then
+ shift
+ image="$1"
+ run_args="${run_args} --image $image"
shift
elif [ "x$1" = "x--debug" ]; then
run_args="${run_args} --debug"
@@ -106,6 +117,11 @@
elif [ "x$1" = "x--invoke-with" ]; then
shift
what="$1"
+ if [ "x$what" = "x" ]; then
+ echo "$0 missing argument to --invoke-with" 1>&2
+ usage="yes"
+ break
+ fi
run_args="${run_args} --invoke-with ${what}"
shift
elif [ "x$1" = "x--dev" ]; then
@@ -118,6 +134,11 @@
elif [ "x$1" = "x--output-path" ]; then
shift
tmp_dir=$1
+ if [ "x$tmp_dir" = "x" ]; then
+ echo "$0 missing argument to --output-path" 1>&2
+ usage="yes"
+ break
+ fi
shift
elif [ "x$1" = "x--update" ]; then
update_mode="yes"
@@ -134,6 +155,24 @@
fi
done
+run_args="${run_args} --lib $lib"
+
+if [ "$dalvik_mode" = "no" ]; then
+ if [ "$target_mode" = "no" ]; then
+ run_args="${run_args} --boot -Ximage:${ANDROID_HOST_OUT}/framework/core.art"
+ else
+ run_args="${run_args} --boot -Ximage:/data/art-test/core.art"
+ fi
+else
+ if [ "$target_mode" = "no" ]; then
+ framework="${OUT}/system/framework"
+ bpath="${framework}/core.jar:${framework}/conscrypt.jar:${framework}/okhttp.jar:${framework}/core-junit.jar:${framework}/bouncycastle.jar:${framework}/ext.jar"
+ run_args="${run_args} --boot -Xbootclasspath:${bpath}"
+ else
+ true # defaults to using target BOOTCLASSPATH
+ fi
+fi
+
if [ "$dev_mode" = "yes" -a "$update_mode" = "yes" ]; then
echo "--dev and --update are mutually exclusive" 1>&2
usage="yes"
@@ -185,6 +224,7 @@
echo " other runtime options are ignored."
echo " --host Use the host-mode virtual machine."
echo " --invoke-with Pass --invoke-with option to runtime."
+ echo " --dalvik Use Dalvik (off by default)."
echo " --jvm Use a host-local RI virtual machine."
echo " --output-path [path] Location where to store the build" \
"files."
@@ -237,7 +277,7 @@
if [ "$build_exit" = '0' ]; then
echo "${test_dir}: running..." 1>&2
"./${run}" $run_args "$@" 2>&1
- run_exit="$?"
+ run_exit="$?"
echo "run exit status: $run_exit" 1>&2
if [ "$run_exit" = "0" ]; then
good="yes"