summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build/Android.gtest.mk49
-rw-r--r--compiler/Android.mk1
-rw-r--r--compiler/common_compiler_test.cc413
-rw-r--r--compiler/common_compiler_test.h401
-rw-r--r--compiler/dex/quick/arm/int_arm.cc20
-rw-r--r--compiler/dex/quick/arm64/assemble_arm64.cc22
-rw-r--r--compiler/dex/quick/arm64/codegen_arm64.h8
-rw-r--r--compiler/dex/quick/arm64/int_arm64.cc23
-rw-r--r--compiler/dex/quick/arm64/target_arm64.cc78
-rw-r--r--compiler/dex/quick/dex_file_method_inliner.cc10
-rw-r--r--compiler/dex/quick/dex_file_method_inliner.h3
-rwxr-xr-xcompiler/dex/quick/gen_invoke.cc85
-rw-r--r--compiler/dex/quick/mir_to_lir.cc1
-rw-r--r--compiler/dex/quick/mir_to_lir.h3
-rw-r--r--compiler/dex/quick_compiler_callbacks.cc39
-rw-r--r--compiler/dex/quick_compiler_callbacks.h (renamed from compiler/driver/compiler_callbacks_impl.h)34
-rw-r--r--compiler/driver/compiler_driver-inl.h4
-rw-r--r--compiler/driver/compiler_driver.cc2
-rw-r--r--compiler/driver/compiler_driver_test.cc3
-rw-r--r--compiler/elf_writer_test.cc2
-rw-r--r--compiler/image_test.cc10
-rw-r--r--compiler/image_writer.cc1
-rw-r--r--compiler/jni/quick/calling_convention.h1
-rw-r--r--compiler/oat_test.cc14
-rw-r--r--compiler/optimizing/code_generator.cc35
-rw-r--r--compiler/optimizing/code_generator.h6
-rw-r--r--compiler/optimizing/code_generator_arm.cc39
-rw-r--r--compiler/optimizing/code_generator_arm.h5
-rw-r--r--compiler/optimizing/code_generator_x86.cc36
-rw-r--r--compiler/optimizing/code_generator_x86.h5
-rw-r--r--compiler/optimizing/code_generator_x86_64.cc41
-rw-r--r--compiler/optimizing/code_generator_x86_64.h5
-rw-r--r--compiler/optimizing/nodes.h5
-rw-r--r--compiler/optimizing/register_allocator.h1
-rw-r--r--compiler/output_stream_test.cc1
-rw-r--r--dex2oat/dex2oat.cc12
-rw-r--r--oatdump/oatdump.cc4
-rw-r--r--patchoat/patchoat.cc5
-rw-r--r--runtime/Android.mk500
-rw-r--r--runtime/arch/arm/entrypoints_init_arm.cc8
-rw-r--r--runtime/arch/stub_test.cc7
-rw-r--r--runtime/barrier_test.cc1
-rw-r--r--runtime/base/mutex_test.cc1
-rw-r--r--runtime/base/scoped_flock_test.cc3
-rw-r--r--runtime/check_jni.cc2
-rw-r--r--runtime/class_linker-inl.h1
-rw-r--r--runtime/class_linker.cc52
-rw-r--r--runtime/class_linker.h3
-rw-r--r--runtime/class_linker_test.cc3
-rw-r--r--runtime/common_runtime_test.cc313
-rw-r--r--runtime/common_runtime_test.h333
-rw-r--r--runtime/common_throws.cc5
-rw-r--r--runtime/debugger.cc3
-rw-r--r--runtime/dex_file_test.cc5
-rw-r--r--runtime/dex_file_verifier_test.cc8
-rw-r--r--runtime/dex_method_iterator_test.cc3
-rw-r--r--runtime/entrypoints/entrypoint_utils-inl.h2
-rw-r--r--runtime/entrypoints/entrypoint_utils.cc1
-rw-r--r--runtime/entrypoints/interpreter/interpreter_entrypoints.cc1
-rw-r--r--runtime/entrypoints/jni/jni_entrypoints.cc1
-rw-r--r--runtime/entrypoints/portable/portable_throw_entrypoints.cc4
-rw-r--r--runtime/entrypoints/portable/portable_trampoline_entrypoints.cc1
-rw-r--r--runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc1
-rw-r--r--runtime/entrypoints/quick/quick_jni_entrypoints.cc1
-rw-r--r--runtime/entrypoints/quick/quick_throw_entrypoints.cc1
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc1
-rw-r--r--runtime/entrypoints_order_test.cc2
-rw-r--r--runtime/fault_handler.cc17
-rw-r--r--runtime/field_helper.cc57
-rw-r--r--runtime/field_helper.h54
-rw-r--r--runtime/gc/accounting/space_bitmap-inl.h8
-rw-r--r--runtime/gc/accounting/space_bitmap.cc10
-rw-r--r--runtime/gc/accounting/space_bitmap.h3
-rw-r--r--runtime/gc/allocator/rosalloc.h3
-rw-r--r--runtime/gc/collector/immune_region.h1
-rw-r--r--runtime/gc/collector/mark_compact.h1
-rw-r--r--runtime/gc/collector/semi_space.h1
-rw-r--r--runtime/gc/heap.cc1
-rw-r--r--runtime/gc/heap_test.cc3
-rw-r--r--runtime/gc/reference_processor-inl.h32
-rw-r--r--runtime/gc/reference_processor.cc17
-rw-r--r--runtime/gc/reference_processor.h9
-rw-r--r--runtime/gc/space/dlmalloc_space_base_test.cc2
-rw-r--r--runtime/gc/space/dlmalloc_space_random_test.cc1
-rw-r--r--runtime/gc/space/dlmalloc_space_static_test.cc1
-rw-r--r--runtime/gc/space/space_test.h4
-rw-r--r--runtime/globals.h13
-rw-r--r--runtime/handle.h58
-rw-r--r--runtime/handle_scope-inl.h2
-rw-r--r--runtime/handle_scope.h24
-rw-r--r--runtime/hprof/hprof.cc1
-rw-r--r--runtime/indirect_reference_table_test.cc1
-rw-r--r--runtime/instrumentation.cc2
-rw-r--r--runtime/intern_table_test.cc2
-rw-r--r--runtime/interpreter/interpreter_common.cc2
-rw-r--r--runtime/interpreter/interpreter_common.h2
-rw-r--r--runtime/jdwp/object_registry.cc1
-rw-r--r--runtime/jdwp/object_registry.h11
-rw-r--r--runtime/jni_internal.cc3
-rw-r--r--runtime/jni_internal_test.cc1
-rw-r--r--runtime/method_helper-inl.h50
-rw-r--r--runtime/method_helper.cc127
-rw-r--r--runtime/method_helper.h174
-rw-r--r--runtime/mirror/array.cc1
-rw-r--r--runtime/mirror/art_field-inl.h2
-rw-r--r--runtime/mirror/art_field.cc1
-rw-r--r--runtime/mirror/art_method-inl.h4
-rw-r--r--runtime/mirror/art_method.cc7
-rw-r--r--runtime/mirror/class-inl.h30
-rw-r--r--runtime/mirror/class.cc7
-rw-r--r--runtime/mirror/class.h11
-rw-r--r--runtime/mirror/dex_cache_test.cc1
-rw-r--r--runtime/mirror/object-inl.h4
-rw-r--r--runtime/mirror/object.cc4
-rw-r--r--runtime/mirror/object_test.cc1
-rw-r--r--runtime/mirror/reference-inl.h5
-rw-r--r--runtime/mirror/reference.cc43
-rw-r--r--runtime/mirror/reference.h24
-rw-r--r--runtime/mirror/string.h1
-rw-r--r--runtime/mirror/throwable.cc1
-rw-r--r--runtime/monitor.cc7
-rw-r--r--runtime/monitor_pool_test.cc2
-rw-r--r--runtime/monitor_test.cc3
-rw-r--r--runtime/native/dalvik_system_VMRuntime.cc1
-rw-r--r--runtime/native/java_lang_Class.cc1
-rw-r--r--runtime/native/java_lang_reflect_Array.cc1
-rw-r--r--runtime/native/java_lang_reflect_Constructor.cc1
-rw-r--r--runtime/native/java_lang_reflect_Field.cc2
-rw-r--r--runtime/native/java_lang_reflect_Method.cc1
-rw-r--r--runtime/noop_compiler_callbacks.h5
-rw-r--r--runtime/object_lock.cc53
-rw-r--r--runtime/object_lock.h50
-rw-r--r--runtime/object_utils.h379
-rw-r--r--runtime/parsed_options.cc14
-rw-r--r--runtime/parsed_options.h19
-rw-r--r--runtime/parsed_options_test.cc2
-rw-r--r--runtime/profiler.cc1
-rw-r--r--runtime/proxy_test.cc8
-rw-r--r--runtime/quick/inline_method_analyser.h1
-rw-r--r--runtime/quick_exception_handler.cc1
-rw-r--r--runtime/reference_table_test.cc4
-rw-r--r--runtime/reflection.cc11
-rw-r--r--runtime/reflection_test.cc2
-rw-r--r--runtime/runtime-inl.h32
-rw-r--r--runtime/runtime.cc6
-rw-r--r--runtime/runtime.h44
-rw-r--r--runtime/stack.cc11
-rw-r--r--runtime/stack.h14
-rw-r--r--runtime/thread.cc13
-rw-r--r--runtime/thread.h5
-rw-r--r--runtime/thread_list.cc9
-rw-r--r--runtime/thread_pool_test.cc1
-rw-r--r--runtime/throw_location.cc1
-rw-r--r--runtime/trace.cc25
-rw-r--r--runtime/trace.h19
-rw-r--r--runtime/transaction_test.cc1
-rw-r--r--runtime/utils.cc7
-rw-r--r--runtime/utils.h3
-rw-r--r--runtime/verifier/method_verifier.cc3
-rw-r--r--runtime/verifier/method_verifier_test.cc1
-rw-r--r--runtime/verifier/reg_type.cc1
-rw-r--r--runtime/verifier/reg_type_cache.cc1
-rw-r--r--runtime/verifier/reg_type_test.cc2
-rw-r--r--runtime/verify_object.h4
-rw-r--r--runtime/zip_archive_test.cc1
-rw-r--r--sigchainlib/sigchain.h3
-rw-r--r--test/401-optimizing-compiler/expected.txt1
-rw-r--r--test/401-optimizing-compiler/src/Main.java10
-rw-r--r--test/Android.run-test.mk98
-rw-r--r--test/ReferenceMap/stack_walk_refmap_jni.cc2
-rw-r--r--test/StackWalk/stack_walk_jni.cc2
171 files changed, 2615 insertions, 1814 deletions
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index 3a19c402db..a34058864c 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -179,6 +179,42 @@ ifeq ($(ART_USE_PORTABLE_COMPILER),true)
ART_TEST_CFLAGS += -DART_USE_PORTABLE_COMPILER=1
endif
+include $(CLEAR_VARS)
+LOCAL_MODULE := libart-gtest
+LOCAL_MODULE_TAGS := optional
+LOCAL_CPP_EXTENSION := cc
+LOCAL_CFLAGS := $(ART_TARGET_CFLAGS)
+LOCAL_SRC_FILES := runtime/common_runtime_test.cc compiler/common_compiler_test.cc
+LOCAL_C_INCLUDES := $(ART_C_INCLUDES) art/runtime art/compiler
+LOCAL_SHARED_LIBRARIES := libcutils libartd libartd-compiler libdl
+LOCAL_STATIC_LIBRARIES += libgtest_libc++
+LOCAL_CLANG := $(ART_TARGET_CLANG)
+LOCAL_ADDITIONAL_DEPENDENCIES := art/build/Android.common_build.mk
+LOCAL_ADDITIONAL_DEPENDENCIES += art/build/Android.gtest.mk
+include external/libcxx/libcxx.mk
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libart-gtest
+LOCAL_MODULE_TAGS := optional
+LOCAL_CPP_EXTENSION := cc
+LOCAL_CFLAGS := $(ART_HOST_CFLAGS)
+LOCAL_SRC_FILES := runtime/common_runtime_test.cc compiler/common_compiler_test.cc
+LOCAL_C_INCLUDES := $(ART_C_INCLUDES) art/runtime art/compiler
+LOCAL_SHARED_LIBRARIES := libartd libartd-compiler
+LOCAL_STATIC_LIBRARIES := libcutils
+ifneq ($(WITHOUT_HOST_CLANG),true)
+ # GCC host compiled tests fail with this linked, presumably due to destructors that run.
+ LOCAL_STATIC_LIBRARIES += libgtest_libc++_host
+endif
+LOCAL_LDLIBS += -ldl -lpthread
+LOCAL_MULTILIB := both
+LOCAL_CLANG := $(ART_HOST_CLANG)
+LOCAL_ADDITIONAL_DEPENDENCIES := art/build/Android.common_build.mk
+LOCAL_ADDITIONAL_DEPENDENCIES += art/build/Android.gtest.mk
+include external/libcxx/libcxx.mk
+include $(BUILD_HOST_SHARED_LIBRARY)
+
# Variables holding collections of gtest pre-requisits used to run a number of gtests.
ART_TEST_HOST_GTEST$(ART_PHONY_TEST_HOST_SUFFIX)_RULES :=
ART_TEST_HOST_GTEST$(2ND_ART_PHONY_TEST_HOST_SUFFIX)_RULES :=
@@ -285,12 +321,12 @@ define define-art-gtest
LOCAL_MODULE_TAGS := tests
endif
LOCAL_CPP_EXTENSION := $$(ART_CPP_EXTENSION)
- LOCAL_SRC_FILES := $$(art_gtest_filename) runtime/common_runtime_test.cc
+ LOCAL_SRC_FILES := $$(art_gtest_filename)
LOCAL_C_INCLUDES += $$(ART_C_INCLUDES) art/runtime $$(art_gtest_extra_c_includes)
- LOCAL_SHARED_LIBRARIES += libartd $$(art_gtest_extra_shared_libraries)
+ LOCAL_SHARED_LIBRARIES += libartd $$(art_gtest_extra_shared_libraries) libart-gtest
- # LOCAL_ADDITIONAL_DEPENDENCIES := art/build/Android.common.mk
- # LOCAL_ADDITIONAL_DEPENDENCIES += art/build/Android.gtest.mk
+ LOCAL_ADDITIONAL_DEPENDENCIES := art/build/Android.common_build.mk
+ LOCAL_ADDITIONAL_DEPENDENCIES += art/build/Android.gtest.mk
# Mac OS linker doesn't understand --export-dynamic.
ifneq ($$(HOST_OS)-$$(art_target_or_host),darwin-host)
@@ -304,7 +340,6 @@ define define-art-gtest
$$(eval $$(call set-target-local-clang-vars))
$$(eval $$(call set-target-local-cflags-vars,debug))
LOCAL_SHARED_LIBRARIES += libdl libicuuc libicui18n libnativehelper libz libcutils libvixl
- LOCAL_STATIC_LIBRARIES += libgtest_libc++
LOCAL_MODULE_PATH_32 := $$(ART_TARGET_NATIVETEST_OUT)/$$(ART_TARGET_ARCH_32)
LOCAL_MODULE_PATH_64 := $$(ART_TARGET_NATIVETEST_OUT)/$$(ART_TARGET_ARCH_64)
LOCAL_MULTILIB := both
@@ -328,10 +363,6 @@ test-art-target-gtest-$$(art_gtest_name): $$(ART_TEST_TARGET_GTEST_$$(art_gtest_
LOCAL_CFLAGS += $$(ART_HOST_CFLAGS) $$(ART_HOST_DEBUG_CFLAGS)
LOCAL_SHARED_LIBRARIES += libicuuc-host libicui18n-host libnativehelper libz-host
LOCAL_STATIC_LIBRARIES += libcutils libvixl
- ifneq ($$(WITHOUT_HOST_CLANG),true)
- # GCC host compiled tests fail with this linked, presumably due to destructors that run.
- LOCAL_STATIC_LIBRARIES += libgtest_libc++_host
- endif
LOCAL_LDLIBS += -lpthread -ldl
LOCAL_IS_HOST_MODULE := true
LOCAL_MULTILIB := both
diff --git a/compiler/Android.mk b/compiler/Android.mk
index 98a4c2fbb9..02dad2ae36 100644
--- a/compiler/Android.mk
+++ b/compiler/Android.mk
@@ -72,6 +72,7 @@ LIBART_COMPILER_SRC_FILES := \
dex/verification_results.cc \
dex/vreg_analysis.cc \
dex/ssa_transformation.cc \
+ dex/quick_compiler_callbacks.cc \
driver/compiler_driver.cc \
driver/dex_compilation_unit.cc \
jni/quick/arm/calling_convention_arm.cc \
diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc
new file mode 100644
index 0000000000..051cfb6dbc
--- /dev/null
+++ b/compiler/common_compiler_test.cc
@@ -0,0 +1,413 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common_compiler_test.h"
+
+#if defined(__arm__)
+#include <sys/ucontext.h>
+#endif
+#include <fstream>
+
+#include "class_linker.h"
+#include "compiled_method.h"
+#include "dex/quick_compiler_callbacks.h"
+#include "dex/verification_results.h"
+#include "dex/quick/dex_file_to_method_inliner_map.h"
+#include "driver/compiler_driver.h"
+#include "entrypoints/entrypoint_utils.h"
+#include "interpreter/interpreter.h"
+#include "mirror/art_method.h"
+#include "mirror/dex_cache.h"
+#include "mirror/object-inl.h"
+#include "scoped_thread_state_change.h"
+#include "thread-inl.h"
+#include "utils.h"
+
+namespace art {
+
+// Normally the ClassLinker supplies this.
+extern "C" void art_quick_generic_jni_trampoline(mirror::ArtMethod*);
+
+#if defined(__arm__)
+// A signal handler called when have an illegal instruction. We record the fact in
+// a global boolean and then increment the PC in the signal context to return to
+// the next instruction. We know the instruction is an sdiv (4 bytes long).
+static void baddivideinst(int signo, siginfo *si, void *data) {
+ UNUSED(signo);
+ UNUSED(si);
+ struct ucontext *uc = (struct ucontext *)data;
+ struct sigcontext *sc = &uc->uc_mcontext;
+ sc->arm_r0 = 0; // set R0 to #0 to signal error
+ sc->arm_pc += 4; // skip offending instruction
+}
+
+// This is in arch/arm/arm_sdiv.S. It does the following:
+// mov r1,#1
+// sdiv r0,r1,r1
+// bx lr
+//
+// the result will be the value 1 if sdiv is supported. If it is not supported
+// a SIGILL signal will be raised and the signal handler (baddivideinst) called.
+// The signal handler sets r0 to #0 and then increments pc beyond the failed instruction.
+// Thus if the instruction is not supported, the result of this function will be #0
+
+extern "C" bool CheckForARMSDIVInstruction();
+
+static InstructionSetFeatures GuessInstructionFeatures() {
+ InstructionSetFeatures f;
+
+ // Uncomment this for processing of /proc/cpuinfo.
+ if (false) {
+ // Look in /proc/cpuinfo for features we need. Only use this when we can guarantee that
+ // the kernel puts the appropriate feature flags in here. Sometimes it doesn't.
+ std::ifstream in("/proc/cpuinfo");
+ if (in) {
+ while (!in.eof()) {
+ std::string line;
+ std::getline(in, line);
+ if (!in.eof()) {
+ if (line.find("Features") != std::string::npos) {
+ if (line.find("idivt") != std::string::npos) {
+ f.SetHasDivideInstruction(true);
+ }
+ }
+ }
+ in.close();
+ }
+ } else {
+ LOG(INFO) << "Failed to open /proc/cpuinfo";
+ }
+ }
+
+ // See if have a sdiv instruction. Register a signal handler and try to execute
+ // an sdiv instruction. If we get a SIGILL then it's not supported. We can't use
+ // the /proc/cpuinfo method for this because Krait devices don't always put the idivt
+ // feature in the list.
+ struct sigaction sa, osa;
+ sa.sa_flags = SA_ONSTACK | SA_RESTART | SA_SIGINFO;
+ sa.sa_sigaction = baddivideinst;
+ sigaction(SIGILL, &sa, &osa);
+
+ if (CheckForARMSDIVInstruction()) {
+ f.SetHasDivideInstruction(true);
+ }
+
+ // Restore the signal handler.
+ sigaction(SIGILL, &osa, nullptr);
+
+ // Other feature guesses in here.
+ return f;
+}
+#endif
+
+// Given a set of instruction features from the build, parse it. The
+// input 'str' is a comma separated list of feature names. Parse it and
+// return the InstructionSetFeatures object.
+static InstructionSetFeatures ParseFeatureList(std::string str) {
+ InstructionSetFeatures result;
+ typedef std::vector<std::string> FeatureList;
+ FeatureList features;
+ Split(str, ',', features);
+ for (FeatureList::iterator i = features.begin(); i != features.end(); i++) {
+ std::string feature = Trim(*i);
+ if (feature == "default") {
+ // Nothing to do.
+ } else if (feature == "div") {
+ // Supports divide instruction.
+ result.SetHasDivideInstruction(true);
+ } else if (feature == "nodiv") {
+ // Turn off support for divide instruction.
+ result.SetHasDivideInstruction(false);
+ } else {
+ LOG(FATAL) << "Unknown instruction set feature: '" << feature << "'";
+ }
+ }
+ // Others...
+ return result;
+}
+
+CommonCompilerTest::CommonCompilerTest() {}
+CommonCompilerTest::~CommonCompilerTest() {}
+
+OatFile::OatMethod CommonCompilerTest::CreateOatMethod(const void* code, const uint8_t* gc_map) {
+ CHECK(code != nullptr);
+ const byte* base;
+ uint32_t code_offset, gc_map_offset;
+ if (gc_map == nullptr) {
+ base = reinterpret_cast<const byte*>(code); // Base of data points at code.
+ base -= kPointerSize; // Move backward so that code_offset != 0.
+ code_offset = kPointerSize;
+ gc_map_offset = 0;
+ } else {
+ // TODO: 64bit support.
+ base = nullptr; // Base of data in oat file, ie 0.
+ code_offset = PointerToLowMemUInt32(code);
+ gc_map_offset = PointerToLowMemUInt32(gc_map);
+ }
+ return OatFile::OatMethod(base, code_offset, gc_map_offset);
+}
+
+void CommonCompilerTest::MakeExecutable(mirror::ArtMethod* method) {
+ CHECK(method != nullptr);
+
+ const CompiledMethod* compiled_method = nullptr;
+ if (!method->IsAbstract()) {
+ mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
+ const DexFile& dex_file = *dex_cache->GetDexFile();
+ compiled_method =
+ compiler_driver_->GetCompiledMethod(MethodReference(&dex_file,
+ method->GetDexMethodIndex()));
+ }
+ if (compiled_method != nullptr) {
+ const std::vector<uint8_t>* code = compiled_method->GetQuickCode();
+ const void* code_ptr;
+ if (code != nullptr) {
+ uint32_t code_size = code->size();
+ CHECK_NE(0u, code_size);
+ const std::vector<uint8_t>& vmap_table = compiled_method->GetVmapTable();
+ uint32_t vmap_table_offset = vmap_table.empty() ? 0u
+ : sizeof(OatQuickMethodHeader) + vmap_table.size();
+ const std::vector<uint8_t>& mapping_table = compiled_method->GetMappingTable();
+ uint32_t mapping_table_offset = mapping_table.empty() ? 0u
+ : sizeof(OatQuickMethodHeader) + vmap_table.size() + mapping_table.size();
+ OatQuickMethodHeader method_header(mapping_table_offset, vmap_table_offset,
+ compiled_method->GetFrameSizeInBytes(),
+ compiled_method->GetCoreSpillMask(),
+ compiled_method->GetFpSpillMask(), code_size);
+
+ header_code_and_maps_chunks_.push_back(std::vector<uint8_t>());
+ std::vector<uint8_t>* chunk = &header_code_and_maps_chunks_.back();
+ size_t size = sizeof(method_header) + code_size + vmap_table.size() + mapping_table.size();
+ size_t code_offset = compiled_method->AlignCode(size - code_size);
+ size_t padding = code_offset - (size - code_size);
+ chunk->reserve(padding + size);
+ chunk->resize(sizeof(method_header));
+ memcpy(&(*chunk)[0], &method_header, sizeof(method_header));
+ chunk->insert(chunk->begin(), vmap_table.begin(), vmap_table.end());
+ chunk->insert(chunk->begin(), mapping_table.begin(), mapping_table.end());
+ chunk->insert(chunk->begin(), padding, 0);
+ chunk->insert(chunk->end(), code->begin(), code->end());
+ CHECK_EQ(padding + size, chunk->size());
+ code_ptr = &(*chunk)[code_offset];
+ } else {
+ code = compiled_method->GetPortableCode();
+ code_ptr = &(*code)[0];
+ }
+ MakeExecutable(code_ptr, code->size());
+ const void* method_code = CompiledMethod::CodePointer(code_ptr,
+ compiled_method->GetInstructionSet());
+ LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code;
+ OatFile::OatMethod oat_method = CreateOatMethod(method_code, nullptr);
+ oat_method.LinkMethod(method);
+ method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
+ } else {
+ // No code? You must mean to go into the interpreter.
+ // Or the generic JNI...
+ if (!method->IsNative()) {
+ const void* method_code = kUsePortableCompiler ? GetPortableToInterpreterBridge()
+ : GetQuickToInterpreterBridge();
+ OatFile::OatMethod oat_method = CreateOatMethod(method_code, nullptr);
+ oat_method.LinkMethod(method);
+ method->SetEntryPointFromInterpreter(interpreter::artInterpreterToInterpreterBridge);
+ } else {
+ const void* method_code = reinterpret_cast<void*>(art_quick_generic_jni_trampoline);
+
+ OatFile::OatMethod oat_method = CreateOatMethod(method_code, nullptr);
+ oat_method.LinkMethod(method);
+ method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
+ }
+ }
+ // Create bridges to transition between different kinds of compiled bridge.
+ if (method->GetEntryPointFromPortableCompiledCode() == nullptr) {
+ method->SetEntryPointFromPortableCompiledCode(GetPortableToQuickBridge());
+ } else {
+ CHECK(method->GetEntryPointFromQuickCompiledCode() == nullptr);
+ method->SetEntryPointFromQuickCompiledCode(GetQuickToPortableBridge());
+ method->SetIsPortableCompiled();
+ }
+}
+
+void CommonCompilerTest::MakeExecutable(const void* code_start, size_t code_length) {
+ CHECK(code_start != nullptr);
+ CHECK_NE(code_length, 0U);
+ uintptr_t data = reinterpret_cast<uintptr_t>(code_start);
+ uintptr_t base = RoundDown(data, kPageSize);
+ uintptr_t limit = RoundUp(data + code_length, kPageSize);
+ uintptr_t len = limit - base;
+ int result = mprotect(reinterpret_cast<void*>(base), len, PROT_READ | PROT_WRITE | PROT_EXEC);
+ CHECK_EQ(result, 0);
+
+ // Flush instruction cache
+ // Only uses __builtin___clear_cache if GCC >= 4.3.3
+#if GCC_VERSION >= 40303
+ __builtin___clear_cache(reinterpret_cast<void*>(base), reinterpret_cast<void*>(base + len));
+#else
+ // Only warn if not Intel as Intel doesn't have cache flush instructions.
+#if !defined(__i386__) && !defined(__x86_64__)
+ LOG(WARNING) << "UNIMPLEMENTED: cache flush";
+#endif
+#endif
+}
+
+void CommonCompilerTest::MakeExecutable(mirror::ClassLoader* class_loader, const char* class_name) {
+ std::string class_descriptor(DotToDescriptor(class_name));
+ Thread* self = Thread::Current();
+ StackHandleScope<1> hs(self);
+ Handle<mirror::ClassLoader> loader(hs.NewHandle(class_loader));
+ mirror::Class* klass = class_linker_->FindClass(self, class_descriptor.c_str(), loader);
+ CHECK(klass != nullptr) << "Class not found " << class_name;
+ for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
+ MakeExecutable(klass->GetDirectMethod(i));
+ }
+ for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
+ MakeExecutable(klass->GetVirtualMethod(i));
+ }
+}
+
+void CommonCompilerTest::SetUp() {
+ CommonRuntimeTest::SetUp();
+ {
+ ScopedObjectAccess soa(Thread::Current());
+
+ InstructionSet instruction_set = kRuntimeISA;
+
+ // Take the default set of instruction features from the build.
+ InstructionSetFeatures instruction_set_features =
+ ParseFeatureList(Runtime::GetDefaultInstructionSetFeatures());
+
+#if defined(__arm__)
+ InstructionSetFeatures runtime_features = GuessInstructionFeatures();
+
+ // for ARM, do a runtime check to make sure that the features we are passed from
+ // the build match the features we actually determine at runtime.
+ ASSERT_LE(instruction_set_features, runtime_features);
+#endif
+
+ runtime_->SetInstructionSet(instruction_set);
+ for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
+ Runtime::CalleeSaveType type = Runtime::CalleeSaveType(i);
+ if (!runtime_->HasCalleeSaveMethod(type)) {
+ runtime_->SetCalleeSaveMethod(
+ runtime_->CreateCalleeSaveMethod(type), type);
+ }
+ }
+
+ // TODO: make selectable
+ Compiler::Kind compiler_kind
+ = (kUsePortableCompiler) ? Compiler::kPortable : Compiler::kQuick;
+ timer_.reset(new CumulativeLogger("Compilation times"));
+ compiler_driver_.reset(new CompilerDriver(compiler_options_.get(),
+ verification_results_.get(),
+ method_inliner_map_.get(),
+ compiler_kind, instruction_set,
+ instruction_set_features,
+ true, new CompilerDriver::DescriptorSet,
+ 2, true, true, timer_.get()));
+ }
+ // We typically don't generate an image in unit tests, disable this optimization by default.
+ compiler_driver_->SetSupportBootImageFixup(false);
+}
+
+void CommonCompilerTest::SetUpRuntimeOptions(RuntimeOptions* options) {
+ CommonRuntimeTest::SetUpRuntimeOptions(options);
+
+ compiler_options_.reset(new CompilerOptions);
+ verification_results_.reset(new VerificationResults(compiler_options_.get()));
+ method_inliner_map_.reset(new DexFileToMethodInlinerMap);
+ callbacks_.reset(new QuickCompilerCallbacks(verification_results_.get(),
+ method_inliner_map_.get()));
+ options->push_back(std::make_pair("compilercallbacks", callbacks_.get()));
+}
+
+void CommonCompilerTest::TearDown() {
+ timer_.reset();
+ compiler_driver_.reset();
+ callbacks_.reset();
+ method_inliner_map_.reset();
+ verification_results_.reset();
+ compiler_options_.reset();
+
+ CommonRuntimeTest::TearDown();
+}
+
+void CommonCompilerTest::CompileClass(mirror::ClassLoader* class_loader, const char* class_name) {
+ std::string class_descriptor(DotToDescriptor(class_name));
+ Thread* self = Thread::Current();
+ StackHandleScope<1> hs(self);
+ Handle<mirror::ClassLoader> loader(hs.NewHandle(class_loader));
+ mirror::Class* klass = class_linker_->FindClass(self, class_descriptor.c_str(), loader);
+ CHECK(klass != nullptr) << "Class not found " << class_name;
+ for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
+ CompileMethod(klass->GetDirectMethod(i));
+ }
+ for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
+ CompileMethod(klass->GetVirtualMethod(i));
+ }
+}
+
+void CommonCompilerTest::CompileMethod(mirror::ArtMethod* method) {
+ CHECK(method != nullptr);
+ TimingLogger timings("CommonTest::CompileMethod", false, false);
+ TimingLogger::ScopedTiming t(__FUNCTION__, &timings);
+ compiler_driver_->CompileOne(method, &timings);
+ TimingLogger::ScopedTiming t2("MakeExecutable", &timings);
+ MakeExecutable(method);
+}
+
+void CommonCompilerTest::CompileDirectMethod(Handle<mirror::ClassLoader> class_loader,
+ const char* class_name, const char* method_name,
+ const char* signature) {
+ std::string class_descriptor(DotToDescriptor(class_name));
+ Thread* self = Thread::Current();
+ mirror::Class* klass = class_linker_->FindClass(self, class_descriptor.c_str(), class_loader);
+ CHECK(klass != nullptr) << "Class not found " << class_name;
+ mirror::ArtMethod* method = klass->FindDirectMethod(method_name, signature);
+ CHECK(method != nullptr) << "Direct method not found: "
+ << class_name << "." << method_name << signature;
+ CompileMethod(method);
+}
+
+void CommonCompilerTest::CompileVirtualMethod(Handle<mirror::ClassLoader> class_loader, const char* class_name,
+ const char* method_name, const char* signature)
+SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ std::string class_descriptor(DotToDescriptor(class_name));
+ Thread* self = Thread::Current();
+ mirror::Class* klass = class_linker_->FindClass(self, class_descriptor.c_str(), class_loader);
+ CHECK(klass != nullptr) << "Class not found " << class_name;
+ mirror::ArtMethod* method = klass->FindVirtualMethod(method_name, signature);
+ CHECK(method != NULL) << "Virtual method not found: "
+ << class_name << "." << method_name << signature;
+ CompileMethod(method);
+}
+
+void CommonCompilerTest::ReserveImageSpace() {
+ // Reserve where the image will be loaded up front so that other parts of test set up don't
+ // accidentally end up colliding with the fixed memory address when we need to load the image.
+ std::string error_msg;
+ image_reservation_.reset(MemMap::MapAnonymous("image reservation",
+ reinterpret_cast<byte*>(ART_BASE_ADDRESS),
+ (size_t)100 * 1024 * 1024, // 100MB
+ PROT_NONE,
+ false /* no need for 4gb flag with fixed mmap*/,
+ &error_msg));
+ CHECK(image_reservation_.get() != nullptr) << error_msg;
+}
+
+void CommonCompilerTest::UnreserveImageSpace() {
+ image_reservation_.reset();
+}
+
+} // namespace art
diff --git a/compiler/common_compiler_test.h b/compiler/common_compiler_test.h
index e11f61a285..df06b71c7d 100644
--- a/compiler/common_compiler_test.h
+++ b/compiler/common_compiler_test.h
@@ -17,409 +17,68 @@
#ifndef ART_COMPILER_COMMON_COMPILER_TEST_H_
#define ART_COMPILER_COMMON_COMPILER_TEST_H_
-#include "compiler.h"
-#include "compiler_callbacks.h"
+#include <list>
+#include <vector>
+
#include "common_runtime_test.h"
-#include "dex/quick/dex_file_to_method_inliner_map.h"
-#include "dex/verification_results.h"
-#include "driver/compiler_callbacks_impl.h"
-#include "driver/compiler_driver.h"
-#include "driver/compiler_options.h"
+#include "oat_file.h"
namespace art {
+namespace mirror {
+ class ClassLoader;
+} // namespace mirror
-#if defined(__arm__)
-
-#include <sys/ucontext.h>
-
-// A signal handler called when have an illegal instruction. We record the fact in
-// a global boolean and then increment the PC in the signal context to return to
-// the next instruction. We know the instruction is an sdiv (4 bytes long).
-static inline void baddivideinst(int signo, siginfo *si, void *data) {
- UNUSED(signo);
- UNUSED(si);
- struct ucontext *uc = (struct ucontext *)data;
- struct sigcontext *sc = &uc->uc_mcontext;
- sc->arm_r0 = 0; // set R0 to #0 to signal error
- sc->arm_pc += 4; // skip offending instruction
-}
-
-// This is in arch/arm/arm_sdiv.S. It does the following:
-// mov r1,#1
-// sdiv r0,r1,r1
-// bx lr
-//
-// the result will be the value 1 if sdiv is supported. If it is not supported
-// a SIGILL signal will be raised and the signal handler (baddivideinst) called.
-// The signal handler sets r0 to #0 and then increments pc beyond the failed instruction.
-// Thus if the instruction is not supported, the result of this function will be #0
-
-extern "C" bool CheckForARMSDIVInstruction();
-
-static inline InstructionSetFeatures GuessInstructionFeatures() {
- InstructionSetFeatures f;
-
- // Uncomment this for processing of /proc/cpuinfo.
- if (false) {
- // Look in /proc/cpuinfo for features we need. Only use this when we can guarantee that
- // the kernel puts the appropriate feature flags in here. Sometimes it doesn't.
- std::ifstream in("/proc/cpuinfo");
- if (in) {
- while (!in.eof()) {
- std::string line;
- std::getline(in, line);
- if (!in.eof()) {
- if (line.find("Features") != std::string::npos) {
- if (line.find("idivt") != std::string::npos) {
- f.SetHasDivideInstruction(true);
- }
- }
- }
- in.close();
- }
- } else {
- LOG(INFO) << "Failed to open /proc/cpuinfo";
- }
- }
-
- // See if have a sdiv instruction. Register a signal handler and try to execute
- // an sdiv instruction. If we get a SIGILL then it's not supported. We can't use
- // the /proc/cpuinfo method for this because Krait devices don't always put the idivt
- // feature in the list.
- struct sigaction sa, osa;
- sa.sa_flags = SA_ONSTACK | SA_RESTART | SA_SIGINFO;
- sa.sa_sigaction = baddivideinst;
- sigaction(SIGILL, &sa, &osa);
-
- if (CheckForARMSDIVInstruction()) {
- f.SetHasDivideInstruction(true);
- }
-
- // Restore the signal handler.
- sigaction(SIGILL, &osa, nullptr);
-
- // Other feature guesses in here.
- return f;
-}
-
-#endif
-
-// Given a set of instruction features from the build, parse it. The
-// input 'str' is a comma separated list of feature names. Parse it and
-// return the InstructionSetFeatures object.
-static inline InstructionSetFeatures ParseFeatureList(std::string str) {
- InstructionSetFeatures result;
- typedef std::vector<std::string> FeatureList;
- FeatureList features;
- Split(str, ',', features);
- for (FeatureList::iterator i = features.begin(); i != features.end(); i++) {
- std::string feature = Trim(*i);
- if (feature == "default") {
- // Nothing to do.
- } else if (feature == "div") {
- // Supports divide instruction.
- result.SetHasDivideInstruction(true);
- } else if (feature == "nodiv") {
- // Turn off support for divide instruction.
- result.SetHasDivideInstruction(false);
- } else {
- LOG(FATAL) << "Unknown instruction set feature: '" << feature << "'";
- }
- }
- // Others...
- return result;
-}
+class CompilerDriver;
+class CompilerOptions;
+class CumulativeLogger;
+class DexFileToMethodInlinerMap;
+class VerificationResults;
-// Normally the ClassLinker supplies this.
-extern "C" void art_quick_generic_jni_trampoline(mirror::ArtMethod*);
+template<class T> class Handle;
class CommonCompilerTest : public CommonRuntimeTest {
public:
- // Create an OatMethod based on pointers (for unit tests).
- OatFile::OatMethod CreateOatMethod(const void* code,
- const uint8_t* gc_map) {
- CHECK(code != nullptr);
- const byte* base;
- uint32_t code_offset, gc_map_offset;
- if (gc_map == nullptr) {
- base = reinterpret_cast<const byte*>(code); // Base of data points at code.
- base -= kPointerSize; // Move backward so that code_offset != 0.
- code_offset = kPointerSize;
- gc_map_offset = 0;
- } else {
- // TODO: 64bit support.
- base = nullptr; // Base of data in oat file, ie 0.
- code_offset = PointerToLowMemUInt32(code);
- gc_map_offset = PointerToLowMemUInt32(gc_map);
- }
- return OatFile::OatMethod(base,
- code_offset,
- gc_map_offset);
- }
-
- void MakeExecutable(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- CHECK(method != nullptr);
-
- const CompiledMethod* compiled_method = nullptr;
- if (!method->IsAbstract()) {
- mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
- const DexFile& dex_file = *dex_cache->GetDexFile();
- compiled_method =
- compiler_driver_->GetCompiledMethod(MethodReference(&dex_file,
- method->GetDexMethodIndex()));
- }
- if (compiled_method != nullptr) {
- const std::vector<uint8_t>* code = compiled_method->GetQuickCode();
- const void* code_ptr;
- if (code != nullptr) {
- uint32_t code_size = code->size();
- CHECK_NE(0u, code_size);
- const std::vector<uint8_t>& vmap_table = compiled_method->GetVmapTable();
- uint32_t vmap_table_offset = vmap_table.empty() ? 0u
- : sizeof(OatQuickMethodHeader) + vmap_table.size();
- const std::vector<uint8_t>& mapping_table = compiled_method->GetMappingTable();
- uint32_t mapping_table_offset = mapping_table.empty() ? 0u
- : sizeof(OatQuickMethodHeader) + vmap_table.size() + mapping_table.size();
- OatQuickMethodHeader method_header(mapping_table_offset, vmap_table_offset,
- compiled_method->GetFrameSizeInBytes(),
- compiled_method->GetCoreSpillMask(),
- compiled_method->GetFpSpillMask(), code_size);
-
- header_code_and_maps_chunks_.push_back(std::vector<uint8_t>());
- std::vector<uint8_t>* chunk = &header_code_and_maps_chunks_.back();
- size_t size = sizeof(method_header) + code_size + vmap_table.size() + mapping_table.size();
- size_t code_offset = compiled_method->AlignCode(size - code_size);
- size_t padding = code_offset - (size - code_size);
- chunk->reserve(padding + size);
- chunk->resize(sizeof(method_header));
- memcpy(&(*chunk)[0], &method_header, sizeof(method_header));
- chunk->insert(chunk->begin(), vmap_table.begin(), vmap_table.end());
- chunk->insert(chunk->begin(), mapping_table.begin(), mapping_table.end());
- chunk->insert(chunk->begin(), padding, 0);
- chunk->insert(chunk->end(), code->begin(), code->end());
- CHECK_EQ(padding + size, chunk->size());
- code_ptr = &(*chunk)[code_offset];
- } else {
- code = compiled_method->GetPortableCode();
- code_ptr = &(*code)[0];
- }
- MakeExecutable(code_ptr, code->size());
- const void* method_code = CompiledMethod::CodePointer(code_ptr,
- compiled_method->GetInstructionSet());
- LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code;
- OatFile::OatMethod oat_method = CreateOatMethod(method_code, nullptr);
- oat_method.LinkMethod(method);
- method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
- } else {
- // No code? You must mean to go into the interpreter.
- // Or the generic JNI...
- if (!method->IsNative()) {
- const void* method_code = kUsePortableCompiler ? GetPortableToInterpreterBridge()
- : GetQuickToInterpreterBridge();
- OatFile::OatMethod oat_method = CreateOatMethod(method_code, nullptr);
- oat_method.LinkMethod(method);
- method->SetEntryPointFromInterpreter(interpreter::artInterpreterToInterpreterBridge);
- } else {
- const void* method_code = reinterpret_cast<void*>(art_quick_generic_jni_trampoline);
+ CommonCompilerTest();
+ ~CommonCompilerTest();
- OatFile::OatMethod oat_method = CreateOatMethod(method_code, nullptr);
- oat_method.LinkMethod(method);
- method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
- }
- }
- // Create bridges to transition between different kinds of compiled bridge.
- if (method->GetEntryPointFromPortableCompiledCode() == nullptr) {
- method->SetEntryPointFromPortableCompiledCode(GetPortableToQuickBridge());
- } else {
- CHECK(method->GetEntryPointFromQuickCompiledCode() == nullptr);
- method->SetEntryPointFromQuickCompiledCode(GetQuickToPortableBridge());
- method->SetIsPortableCompiled();
- }
- }
+ // Create an OatMethod based on pointers (for unit tests).
+ OatFile::OatMethod CreateOatMethod(const void* code, const uint8_t* gc_map);
- static void MakeExecutable(const void* code_start, size_t code_length) {
- CHECK(code_start != nullptr);
- CHECK_NE(code_length, 0U);
- uintptr_t data = reinterpret_cast<uintptr_t>(code_start);
- uintptr_t base = RoundDown(data, kPageSize);
- uintptr_t limit = RoundUp(data + code_length, kPageSize);
- uintptr_t len = limit - base;
- int result = mprotect(reinterpret_cast<void*>(base), len, PROT_READ | PROT_WRITE | PROT_EXEC);
- CHECK_EQ(result, 0);
+ void MakeExecutable(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- // Flush instruction cache
- // Only uses __builtin___clear_cache if GCC >= 4.3.3
-#if GCC_VERSION >= 40303
- __builtin___clear_cache(reinterpret_cast<void*>(base), reinterpret_cast<void*>(base + len));
-#else
- LOG(WARNING) << "UNIMPLEMENTED: cache flush";
-#endif
- }
+ static void MakeExecutable(const void* code_start, size_t code_length);
void MakeExecutable(mirror::ClassLoader* class_loader, const char* class_name)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- std::string class_descriptor(DotToDescriptor(class_name));
- Thread* self = Thread::Current();
- StackHandleScope<1> hs(self);
- Handle<mirror::ClassLoader> loader(hs.NewHandle(class_loader));
- mirror::Class* klass = class_linker_->FindClass(self, class_descriptor.c_str(), loader);
- CHECK(klass != nullptr) << "Class not found " << class_name;
- for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
- MakeExecutable(klass->GetDirectMethod(i));
- }
- for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
- MakeExecutable(klass->GetVirtualMethod(i));
- }
- }
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
protected:
- virtual void SetUp() {
- CommonRuntimeTest::SetUp();
- {
- ScopedObjectAccess soa(Thread::Current());
-
- InstructionSet instruction_set = kNone;
-
- // Take the default set of instruction features from the build.
- InstructionSetFeatures instruction_set_features =
- ParseFeatureList(Runtime::GetDefaultInstructionSetFeatures());
-
-#if defined(__arm__)
- instruction_set = kThumb2;
- InstructionSetFeatures runtime_features = GuessInstructionFeatures();
-
- // for ARM, do a runtime check to make sure that the features we are passed from
- // the build match the features we actually determine at runtime.
- ASSERT_LE(instruction_set_features, runtime_features);
-#elif defined(__aarch64__)
- instruction_set = kArm64;
-#elif defined(__mips__)
- instruction_set = kMips;
-#elif defined(__i386__)
- instruction_set = kX86;
-#elif defined(__x86_64__)
- instruction_set = kX86_64;
-#endif
-
- runtime_->SetInstructionSet(instruction_set);
- for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
- Runtime::CalleeSaveType type = Runtime::CalleeSaveType(i);
- if (!runtime_->HasCalleeSaveMethod(type)) {
- runtime_->SetCalleeSaveMethod(
- runtime_->CreateCalleeSaveMethod(type), type);
- }
- }
-
- // TODO: make selectable
- Compiler::Kind compiler_kind
- = (kUsePortableCompiler) ? Compiler::kPortable : Compiler::kQuick;
- timer_.reset(new CumulativeLogger("Compilation times"));
- compiler_driver_.reset(new CompilerDriver(compiler_options_.get(),
- verification_results_.get(),
- method_inliner_map_.get(),
- compiler_kind, instruction_set,
- instruction_set_features,
- true, new CompilerDriver::DescriptorSet,
- 2, true, true, timer_.get()));
- }
- // We typically don't generate an image in unit tests, disable this optimization by default.
- compiler_driver_->SetSupportBootImageFixup(false);
- }
-
- virtual void SetUpRuntimeOptions(Runtime::Options *options) {
- CommonRuntimeTest::SetUpRuntimeOptions(options);
-
- compiler_options_.reset(new CompilerOptions);
- verification_results_.reset(new VerificationResults(compiler_options_.get()));
- method_inliner_map_.reset(new DexFileToMethodInlinerMap);
- callbacks_.reset(new CompilerCallbacksImpl(verification_results_.get(),
- method_inliner_map_.get()));
- options->push_back(std::make_pair("compilercallbacks", callbacks_.get()));
- }
+ virtual void SetUp();
- virtual void TearDown() {
- timer_.reset();
- compiler_driver_.reset();
- callbacks_.reset();
- method_inliner_map_.reset();
- verification_results_.reset();
- compiler_options_.reset();
+ virtual void SetUpRuntimeOptions(RuntimeOptions *options);
- CommonRuntimeTest::TearDown();
- }
+ virtual void TearDown();
void CompileClass(mirror::ClassLoader* class_loader, const char* class_name)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- std::string class_descriptor(DotToDescriptor(class_name));
- Thread* self = Thread::Current();
- StackHandleScope<1> hs(self);
- Handle<mirror::ClassLoader> loader(hs.NewHandle(class_loader));
- mirror::Class* klass = class_linker_->FindClass(self, class_descriptor.c_str(), loader);
- CHECK(klass != nullptr) << "Class not found " << class_name;
- for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
- CompileMethod(klass->GetDirectMethod(i));
- }
- for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
- CompileMethod(klass->GetVirtualMethod(i));
- }
- }
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void CompileMethod(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- CHECK(method != nullptr);
- TimingLogger timings("CommonTest::CompileMethod", false, false);
- TimingLogger::ScopedTiming t(__FUNCTION__, &timings);
- compiler_driver_->CompileOne(method, &timings);
- TimingLogger::ScopedTiming t2("MakeExecutable", &timings);
- MakeExecutable(method);
- }
+ void CompileMethod(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void CompileDirectMethod(Handle<mirror::ClassLoader> class_loader, const char* class_name,
const char* method_name, const char* signature)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- std::string class_descriptor(DotToDescriptor(class_name));
- Thread* self = Thread::Current();
- mirror::Class* klass = class_linker_->FindClass(self, class_descriptor.c_str(), class_loader);
- CHECK(klass != nullptr) << "Class not found " << class_name;
- mirror::ArtMethod* method = klass->FindDirectMethod(method_name, signature);
- CHECK(method != nullptr) << "Direct method not found: "
- << class_name << "." << method_name << signature;
- CompileMethod(method);
- }
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void CompileVirtualMethod(Handle<mirror::ClassLoader> class_loader, const char* class_name,
const char* method_name, const char* signature)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- std::string class_descriptor(DotToDescriptor(class_name));
- Thread* self = Thread::Current();
- mirror::Class* klass = class_linker_->FindClass(self, class_descriptor.c_str(), class_loader);
- CHECK(klass != nullptr) << "Class not found " << class_name;
- mirror::ArtMethod* method = klass->FindVirtualMethod(method_name, signature);
- CHECK(method != NULL) << "Virtual method not found: "
- << class_name << "." << method_name << signature;
- CompileMethod(method);
- }
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void ReserveImageSpace() {
- // Reserve where the image will be loaded up front so that other parts of test set up don't
- // accidentally end up colliding with the fixed memory address when we need to load the image.
- std::string error_msg;
- image_reservation_.reset(MemMap::MapAnonymous("image reservation",
- reinterpret_cast<byte*>(ART_BASE_ADDRESS),
- (size_t)100 * 1024 * 1024, // 100MB
- PROT_NONE,
- false /* no need for 4gb flag with fixed mmap*/,
- &error_msg));
- CHECK(image_reservation_.get() != nullptr) << error_msg;
- }
+ void ReserveImageSpace();
- void UnreserveImageSpace() {
- image_reservation_.reset();
- }
+ void UnreserveImageSpace();
std::unique_ptr<CompilerOptions> compiler_options_;
std::unique_ptr<VerificationResults> verification_results_;
std::unique_ptr<DexFileToMethodInlinerMap> method_inliner_map_;
- std::unique_ptr<CompilerCallbacksImpl> callbacks_;
+ std::unique_ptr<CompilerCallbacks> callbacks_;
std::unique_ptr<CompilerDriver> compiler_driver_;
std::unique_ptr<CumulativeLogger> timer_;
diff --git a/compiler/dex/quick/arm/int_arm.cc b/compiler/dex/quick/arm/int_arm.cc
index f4ea592781..2fcc3a5abc 100644
--- a/compiler/dex/quick/arm/int_arm.cc
+++ b/compiler/dex/quick/arm/int_arm.cc
@@ -341,7 +341,7 @@ void ArmMir2Lir::GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir) {
* is responsible for setting branch target field.
*/
LIR* ArmMir2Lir::OpCmpImmBranch(ConditionCode cond, RegStorage reg, int check_value, LIR* target) {
- LIR* branch;
+ LIR* branch = nullptr;
ArmConditionCode arm_cond = ArmConditionEncoding(cond);
/*
* A common use of OpCmpImmBranch is for null checks, and using the Thumb 16-bit
@@ -354,14 +354,22 @@ LIR* ArmMir2Lir::OpCmpImmBranch(ConditionCode cond, RegStorage reg, int check_va
*/
bool skip = ((target != NULL) && (target->opcode == kPseudoThrowTarget));
skip &= ((cu_->code_item->insns_size_in_code_units_ - current_dalvik_offset_) > 64);
- if (!skip && reg.Low8() && (check_value == 0) &&
- ((arm_cond == kArmCondEq) || (arm_cond == kArmCondNe))) {
- branch = NewLIR2((arm_cond == kArmCondEq) ? kThumb2Cbz : kThumb2Cbnz,
- reg.GetReg(), 0);
- } else {
+ if (!skip && reg.Low8() && (check_value == 0)) {
+ if (arm_cond == kArmCondEq || arm_cond == kArmCondNe) {
+ branch = NewLIR2((arm_cond == kArmCondEq) ? kThumb2Cbz : kThumb2Cbnz,
+ reg.GetReg(), 0);
+ } else if (arm_cond == kArmCondLs) {
+ // kArmCondLs is an unsigned less or equal. A comparison r <= 0 is then the same as cbz.
+ // This case happens for a bounds check of array[0].
+ branch = NewLIR2(kThumb2Cbz, reg.GetReg(), 0);
+ }
+ }
+
+ if (branch == nullptr) {
OpRegImm(kOpCmp, reg, check_value);
branch = NewLIR2(kThumbBCond, 0, arm_cond);
}
+
branch->target = target;
return branch;
}
diff --git a/compiler/dex/quick/arm64/assemble_arm64.cc b/compiler/dex/quick/arm64/assemble_arm64.cc
index 083277de43..462be54e57 100644
--- a/compiler/dex/quick/arm64/assemble_arm64.cc
+++ b/compiler/dex/quick/arm64/assemble_arm64.cc
@@ -655,10 +655,10 @@ uint8_t* Arm64Mir2Lir::EncodeLIRs(uint8_t* write_pos, LIR* lir) {
if (kIsDebugBuild && (kFailOnSizeError || kReportSizeError)) {
// Register usage checks: First establish register usage requirements based on the
// format in `kind'.
- bool want_float = false;
- bool want_64_bit = false;
- bool want_var_size = true;
- bool want_zero = false;
+ bool want_float = false; // Want a float (rather than core) register.
+ bool want_64_bit = false; // Want a 64-bit (rather than 32-bit) register.
+ bool want_var_size = true; // Want register with variable size (kFmtReg{R,F}).
+ bool want_zero = false; // Want the zero (rather than sp) register.
switch (kind) {
case kFmtRegX:
want_64_bit = true;
@@ -717,9 +717,6 @@ uint8_t* Arm64Mir2Lir::EncodeLIRs(uint8_t* write_pos, LIR* lir) {
}
}
- // TODO(Arm64): if !want_size_match, then we still should compare the size of the
- // register with the size required by the instruction width (kA64Wide).
-
// Fail, if `expected' contains an unsatisfied requirement.
if (expected != nullptr) {
LOG(WARNING) << "Method: " << PrettyMethod(cu_->method_idx, *cu_->dex_file)
@@ -734,11 +731,12 @@ uint8_t* Arm64Mir2Lir::EncodeLIRs(uint8_t* write_pos, LIR* lir) {
}
}
- // TODO(Arm64): this may or may not be necessary, depending on how wzr, xzr are
- // defined.
- if (is_zero) {
- operand = 31;
- }
+ // In the lines below, we rely on (operand & 0x1f) == 31 to be true for register sp
+ // and zr. This means that these two registers do not need any special treatment, as
+ // their bottom 5 bits are correctly set to 31 == 0b11111, which is the right
+ // value for encoding both sp and zr.
+ COMPILE_ASSERT((rxzr & 0x1f) == 0x1f, rzr_register_number_must_be_31);
+ COMPILE_ASSERT((rsp & 0x1f) == 0x1f, rsp_register_number_must_be_31);
}
value = (operand << encoder->field_loc[i].start) &
diff --git a/compiler/dex/quick/arm64/codegen_arm64.h b/compiler/dex/quick/arm64/codegen_arm64.h
index e4eeeaf580..de976531c2 100644
--- a/compiler/dex/quick/arm64/codegen_arm64.h
+++ b/compiler/dex/quick/arm64/codegen_arm64.h
@@ -105,16 +105,14 @@ class Arm64Mir2Lir FINAL : public Mir2Lir {
// Required for target - register utilities.
RegStorage TargetReg(SpecialTargetRegister reg) OVERRIDE;
RegStorage TargetReg(SpecialTargetRegister symbolic_reg, WideKind wide_kind) OVERRIDE {
- RegStorage reg = TargetReg(symbolic_reg);
if (wide_kind == kWide || wide_kind == kRef) {
- return (reg.Is64Bit()) ? reg : As64BitReg(reg);
+ return As64BitReg(TargetReg(symbolic_reg));
} else {
- return (reg.Is32Bit()) ? reg : As32BitReg(reg);
+ return Check32BitReg(TargetReg(symbolic_reg));
}
}
RegStorage TargetPtrReg(SpecialTargetRegister symbolic_reg) OVERRIDE {
- RegStorage reg = TargetReg(symbolic_reg);
- return (reg.Is64Bit() ? reg : As64BitReg(reg));
+ return As64BitReg(TargetReg(symbolic_reg));
}
RegStorage GetArgMappingToPhysicalReg(int arg_num);
RegLocation GetReturnAlt();
diff --git a/compiler/dex/quick/arm64/int_arm64.cc b/compiler/dex/quick/arm64/int_arm64.cc
index 2650892975..6dc4a7ab51 100644
--- a/compiler/dex/quick/arm64/int_arm64.cc
+++ b/compiler/dex/quick/arm64/int_arm64.cc
@@ -269,16 +269,27 @@ void Arm64Mir2Lir::GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir) {
*/
LIR* Arm64Mir2Lir::OpCmpImmBranch(ConditionCode cond, RegStorage reg, int check_value,
LIR* target) {
- LIR* branch;
+ LIR* branch = nullptr;
ArmConditionCode arm_cond = ArmConditionEncoding(cond);
- if (check_value == 0 && (arm_cond == kArmCondEq || arm_cond == kArmCondNe)) {
- ArmOpcode opcode = (arm_cond == kArmCondEq) ? kA64Cbz2rt : kA64Cbnz2rt;
- ArmOpcode wide = reg.Is64Bit() ? WIDE(0) : UNWIDE(0);
- branch = NewLIR2(opcode | wide, reg.GetReg(), 0);
- } else {
+ if (check_value == 0) {
+ if (arm_cond == kArmCondEq || arm_cond == kArmCondNe) {
+ ArmOpcode opcode = (arm_cond == kArmCondEq) ? kA64Cbz2rt : kA64Cbnz2rt;
+ ArmOpcode wide = reg.Is64Bit() ? WIDE(0) : UNWIDE(0);
+ branch = NewLIR2(opcode | wide, reg.GetReg(), 0);
+ } else if (arm_cond == kArmCondLs) {
+ // kArmCondLs is an unsigned less or equal. A comparison r <= 0 is then the same as cbz.
+ // This case happens for a bounds check of array[0].
+ ArmOpcode opcode = kA64Cbz2rt;
+ ArmOpcode wide = reg.Is64Bit() ? WIDE(0) : UNWIDE(0);
+ branch = NewLIR2(opcode | wide, reg.GetReg(), 0);
+ }
+ }
+
+ if (branch == nullptr) {
OpRegImm(kOpCmp, reg, check_value);
branch = NewLIR2(kA64B2ct, arm_cond, 0);
}
+
branch->target = target;
return branch;
}
diff --git a/compiler/dex/quick/arm64/target_arm64.cc b/compiler/dex/quick/arm64/target_arm64.cc
index 2212380eb4..6a27ad0b14 100644
--- a/compiler/dex/quick/arm64/target_arm64.cc
+++ b/compiler/dex/quick/arm64/target_arm64.cc
@@ -108,19 +108,19 @@ RegLocation Arm64Mir2Lir::LocCReturnDouble() {
RegStorage Arm64Mir2Lir::TargetReg(SpecialTargetRegister reg) {
RegStorage res_reg = RegStorage::InvalidReg();
switch (reg) {
- case kSelf: res_reg = rs_xSELF; break;
- case kSuspend: res_reg = rs_xSUSPEND; break;
- case kLr: res_reg = rs_xLR; break;
+ case kSelf: res_reg = rs_wSELF; break;
+ case kSuspend: res_reg = rs_wSUSPEND; break;
+ case kLr: res_reg = rs_wLR; break;
case kPc: res_reg = RegStorage::InvalidReg(); break;
- case kSp: res_reg = rs_sp; break;
- case kArg0: res_reg = rs_x0; break;
- case kArg1: res_reg = rs_x1; break;
- case kArg2: res_reg = rs_x2; break;
- case kArg3: res_reg = rs_x3; break;
- case kArg4: res_reg = rs_x4; break;
- case kArg5: res_reg = rs_x5; break;
- case kArg6: res_reg = rs_x6; break;
- case kArg7: res_reg = rs_x7; break;
+ case kSp: res_reg = rs_wsp; break;
+ case kArg0: res_reg = rs_w0; break;
+ case kArg1: res_reg = rs_w1; break;
+ case kArg2: res_reg = rs_w2; break;
+ case kArg3: res_reg = rs_w3; break;
+ case kArg4: res_reg = rs_w4; break;
+ case kArg5: res_reg = rs_w5; break;
+ case kArg6: res_reg = rs_w6; break;
+ case kArg7: res_reg = rs_w7; break;
case kFArg0: res_reg = rs_f0; break;
case kFArg1: res_reg = rs_f1; break;
case kFArg2: res_reg = rs_f2; break;
@@ -129,10 +129,10 @@ RegStorage Arm64Mir2Lir::TargetReg(SpecialTargetRegister reg) {
case kFArg5: res_reg = rs_f5; break;
case kFArg6: res_reg = rs_f6; break;
case kFArg7: res_reg = rs_f7; break;
- case kRet0: res_reg = rs_x0; break;
- case kRet1: res_reg = rs_x1; break;
- case kInvokeTgt: res_reg = rs_xLR; break;
- case kHiddenArg: res_reg = rs_x12; break;
+ case kRet0: res_reg = rs_w0; break;
+ case kRet1: res_reg = rs_w1; break;
+ case kInvokeTgt: res_reg = rs_wLR; break;
+ case kHiddenArg: res_reg = rs_w12; break;
case kHiddenFpArg: res_reg = RegStorage::InvalidReg(); break;
case kCount: res_reg = RegStorage::InvalidReg(); break;
default: res_reg = RegStorage::InvalidReg();
@@ -929,13 +929,13 @@ void Arm64Mir2Lir::FlushIns(RegLocation* ArgLocs, RegLocation rl_method) {
*/
RegLocation rl_src = rl_method;
rl_src.location = kLocPhysReg;
- rl_src.reg = TargetReg(kArg0);
+ rl_src.reg = TargetReg(kArg0, kRef);
rl_src.home = false;
MarkLive(rl_src);
StoreValue(rl_method, rl_src);
// If Method* has been promoted, explicitly flush
if (rl_method.location == kLocPhysReg) {
- StoreRefDisp(TargetReg(kSp), 0, TargetReg(kArg0), kNotVolatile);
+ StoreRefDisp(TargetPtrReg(kSp), 0, rl_src.reg, kNotVolatile);
}
if (cu_->num_ins == 0) {
@@ -961,9 +961,9 @@ void Arm64Mir2Lir::FlushIns(RegLocation* ArgLocs, RegLocation rl_method) {
} else {
// Needs flush.
if (t_loc->ref) {
- StoreRefDisp(TargetReg(kSp), SRegOffset(start_vreg + i), reg, kNotVolatile);
+ StoreRefDisp(TargetPtrReg(kSp), SRegOffset(start_vreg + i), reg, kNotVolatile);
} else {
- StoreBaseDisp(TargetReg(kSp), SRegOffset(start_vreg + i), reg, t_loc->wide ? k64 : k32,
+ StoreBaseDisp(TargetPtrReg(kSp), SRegOffset(start_vreg + i), reg, t_loc->wide ? k64 : k32,
kNotVolatile);
}
}
@@ -971,9 +971,9 @@ void Arm64Mir2Lir::FlushIns(RegLocation* ArgLocs, RegLocation rl_method) {
// If arriving in frame & promoted.
if (t_loc->location == kLocPhysReg) {
if (t_loc->ref) {
- LoadRefDisp(TargetReg(kSp), SRegOffset(start_vreg + i), t_loc->reg, kNotVolatile);
+ LoadRefDisp(TargetPtrReg(kSp), SRegOffset(start_vreg + i), t_loc->reg, kNotVolatile);
} else {
- LoadBaseDisp(TargetReg(kSp), SRegOffset(start_vreg + i), t_loc->reg,
+ LoadBaseDisp(TargetPtrReg(kSp), SRegOffset(start_vreg + i), t_loc->reg,
t_loc->wide ? k64 : k32, kNotVolatile);
}
}
@@ -1070,7 +1070,7 @@ int Arm64Mir2Lir::GenDalvikArgsRange(CallInfo* info, int call_state,
loc = UpdateLocWide(loc);
if (loc.location == kLocPhysReg) {
ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
- StoreBaseDisp(TargetReg(kSp), SRegOffset(loc.s_reg_low), loc.reg, k64, kNotVolatile);
+ StoreBaseDisp(TargetPtrReg(kSp), SRegOffset(loc.s_reg_low), loc.reg, k64, kNotVolatile);
}
next_arg += 2;
} else {
@@ -1078,9 +1078,10 @@ int Arm64Mir2Lir::GenDalvikArgsRange(CallInfo* info, int call_state,
if (loc.location == kLocPhysReg) {
ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
if (loc.ref) {
- StoreRefDisp(TargetReg(kSp), SRegOffset(loc.s_reg_low), loc.reg, kNotVolatile);
+ StoreRefDisp(TargetPtrReg(kSp), SRegOffset(loc.s_reg_low), loc.reg, kNotVolatile);
} else {
- StoreBaseDisp(TargetReg(kSp), SRegOffset(loc.s_reg_low), loc.reg, k32, kNotVolatile);
+ StoreBaseDisp(TargetPtrReg(kSp), SRegOffset(loc.s_reg_low), loc.reg, k32,
+ kNotVolatile);
}
}
next_arg++;
@@ -1114,8 +1115,8 @@ int Arm64Mir2Lir::GenDalvikArgsRange(CallInfo* info, int call_state,
RegStorage temp = TargetReg(kArg3, kNotWide);
// Now load the argument VR and store to the outs.
- Load32Disp(TargetReg(kSp), current_src_offset, temp);
- Store32Disp(TargetReg(kSp), current_dest_offset, temp);
+ Load32Disp(TargetPtrReg(kSp), current_src_offset, temp);
+ Store32Disp(TargetPtrReg(kSp), current_dest_offset, temp);
current_src_offset += bytes_to_move;
current_dest_offset += bytes_to_move;
@@ -1126,8 +1127,7 @@ int Arm64Mir2Lir::GenDalvikArgsRange(CallInfo* info, int call_state,
// Now handle rest not registers if they are
if (in_to_reg_storage_mapping.IsThereStackMapped()) {
- RegStorage regSingle = TargetReg(kArg2);
- RegStorage regWide = RegStorage::Solo64(TargetReg(kArg3).GetReg());
+ RegStorage regWide = TargetReg(kArg3, kWide);
for (int i = start_index; i <= last_mapped_in + regs_left_to_pass_via_stack; i++) {
RegLocation rl_arg = info->args[i];
rl_arg = UpdateRawLoc(rl_arg);
@@ -1139,25 +1139,27 @@ int Arm64Mir2Lir::GenDalvikArgsRange(CallInfo* info, int call_state,
ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
if (rl_arg.wide) {
if (rl_arg.location == kLocPhysReg) {
- StoreBaseDisp(TargetReg(kSp), out_offset, rl_arg.reg, k64, kNotVolatile);
+ StoreBaseDisp(TargetPtrReg(kSp), out_offset, rl_arg.reg, k64, kNotVolatile);
} else {
LoadValueDirectWideFixed(rl_arg, regWide);
- StoreBaseDisp(TargetReg(kSp), out_offset, regWide, k64, kNotVolatile);
+ StoreBaseDisp(TargetPtrReg(kSp), out_offset, regWide, k64, kNotVolatile);
}
} else {
if (rl_arg.location == kLocPhysReg) {
if (rl_arg.ref) {
- StoreRefDisp(TargetReg(kSp), out_offset, rl_arg.reg, kNotVolatile);
+ StoreRefDisp(TargetPtrReg(kSp), out_offset, rl_arg.reg, kNotVolatile);
} else {
- StoreBaseDisp(TargetReg(kSp), out_offset, rl_arg.reg, k32, kNotVolatile);
+ StoreBaseDisp(TargetPtrReg(kSp), out_offset, rl_arg.reg, k32, kNotVolatile);
}
} else {
if (rl_arg.ref) {
+ RegStorage regSingle = TargetReg(kArg2, kRef);
LoadValueDirectFixed(rl_arg, regSingle);
- StoreRefDisp(TargetReg(kSp), out_offset, regSingle, kNotVolatile);
+ StoreRefDisp(TargetPtrReg(kSp), out_offset, regSingle, kNotVolatile);
} else {
- LoadValueDirectFixed(rl_arg, As32BitReg(regSingle));
- StoreBaseDisp(TargetReg(kSp), out_offset, As32BitReg(regSingle), k32, kNotVolatile);
+ RegStorage regSingle = TargetReg(kArg2, kNotWide);
+ LoadValueDirectFixed(rl_arg, regSingle);
+ StoreBaseDisp(TargetPtrReg(kSp), out_offset, regSingle, k32, kNotVolatile);
}
}
}
@@ -1194,13 +1196,13 @@ int Arm64Mir2Lir::GenDalvikArgsRange(CallInfo* info, int call_state,
direct_code, direct_method, type);
if (pcrLabel) {
if (cu_->compiler_driver->GetCompilerOptions().GetExplicitNullChecks()) {
- *pcrLabel = GenExplicitNullCheck(TargetReg(kArg1), info->opt_flags);
+ *pcrLabel = GenExplicitNullCheck(TargetReg(kArg1, kRef), info->opt_flags);
} else {
*pcrLabel = nullptr;
// In lieu of generating a check for kArg1 being null, we need to
// perform a load when doing implicit checks.
RegStorage tmp = AllocTemp();
- Load32Disp(TargetReg(kArg1), 0, tmp);
+ Load32Disp(TargetReg(kArg1, kRef), 0, tmp);
MarkPossibleNullPointerException(info->opt_flags);
FreeTemp(tmp);
}
diff --git a/compiler/dex/quick/dex_file_method_inliner.cc b/compiler/dex/quick/dex_file_method_inliner.cc
index 45dd7f08a6..0e46c96501 100644
--- a/compiler/dex/quick/dex_file_method_inliner.cc
+++ b/compiler/dex/quick/dex_file_method_inliner.cc
@@ -48,6 +48,7 @@ static constexpr bool kIntrinsicIsStatic[] = {
true, // kIntrinsicMinMaxFloat
true, // kIntrinsicMinMaxDouble
true, // kIntrinsicSqrt
+ false, // kIntrinsicGet
false, // kIntrinsicCharAt
false, // kIntrinsicCompareTo
false, // kIntrinsicIsEmptyOrLength
@@ -74,6 +75,7 @@ COMPILE_ASSERT(kIntrinsicIsStatic[kIntrinsicMinMaxLong], MinMaxLong_must_be_stat
COMPILE_ASSERT(kIntrinsicIsStatic[kIntrinsicMinMaxFloat], MinMaxFloat_must_be_static);
COMPILE_ASSERT(kIntrinsicIsStatic[kIntrinsicMinMaxDouble], MinMaxDouble_must_be_static);
COMPILE_ASSERT(kIntrinsicIsStatic[kIntrinsicSqrt], Sqrt_must_be_static);
+COMPILE_ASSERT(!kIntrinsicIsStatic[kIntrinsicGet], Get_must_not_be_static);
COMPILE_ASSERT(!kIntrinsicIsStatic[kIntrinsicCharAt], CharAt_must_not_be_static);
COMPILE_ASSERT(!kIntrinsicIsStatic[kIntrinsicCompareTo], CompareTo_must_not_be_static);
COMPILE_ASSERT(!kIntrinsicIsStatic[kIntrinsicIsEmptyOrLength], IsEmptyOrLength_must_not_be_static);
@@ -126,6 +128,7 @@ const char* const DexFileMethodInliner::kClassCacheNames[] = {
"D", // kClassCacheDouble
"V", // kClassCacheVoid
"Ljava/lang/Object;", // kClassCacheJavaLangObject
+ "Ljava/lang/ref/Reference;", // kClassCacheJavaLangRefReference
"Ljava/lang/String;", // kClassCacheJavaLangString
"Ljava/lang/Double;", // kClassCacheJavaLangDouble
"Ljava/lang/Float;", // kClassCacheJavaLangFloat
@@ -152,6 +155,7 @@ const char* const DexFileMethodInliner::kNameCacheNames[] = {
"max", // kNameCacheMax
"min", // kNameCacheMin
"sqrt", // kNameCacheSqrt
+ "get", // kNameCacheGet
"charAt", // kNameCacheCharAt
"compareTo", // kNameCacheCompareTo
"isEmpty", // kNameCacheIsEmpty
@@ -220,6 +224,8 @@ const DexFileMethodInliner::ProtoDef DexFileMethodInliner::kProtoCacheDefs[] = {
{ kClassCacheBoolean, 0, { } },
// kProtoCache_I
{ kClassCacheInt, 0, { } },
+ // kProtoCache_Object
+ { kClassCacheJavaLangObject, 0, { } },
// kProtoCache_Thread
{ kClassCacheJavaLangThread, 0, { } },
// kProtoCacheJ_B
@@ -308,6 +314,8 @@ const DexFileMethodInliner::IntrinsicDef DexFileMethodInliner::kIntrinsicMethods
INTRINSIC(JavaLangMath, Sqrt, D_D, kIntrinsicSqrt, 0),
INTRINSIC(JavaLangStrictMath, Sqrt, D_D, kIntrinsicSqrt, 0),
+ INTRINSIC(JavaLangRefReference, Get, _Object, kIntrinsicGet, 0),
+
INTRINSIC(JavaLangString, CharAt, I_C, kIntrinsicCharAt, 0),
INTRINSIC(JavaLangString, CompareTo, String_I, kIntrinsicCompareTo, 0),
INTRINSIC(JavaLangString, IsEmpty, _Z, kIntrinsicIsEmptyOrLength, kIntrinsicFlagIsEmpty),
@@ -428,6 +436,8 @@ bool DexFileMethodInliner::GenIntrinsic(Mir2Lir* backend, CallInfo* info) {
return backend->GenInlinedMinMaxFP(info, intrinsic.d.data & kIntrinsicFlagMin, true /* is_double */);
case kIntrinsicSqrt:
return backend->GenInlinedSqrt(info);
+ case kIntrinsicGet:
+ return backend->GenInlinedGet(info);
case kIntrinsicCharAt:
return backend->GenInlinedCharAt(info);
case kIntrinsicCompareTo:
diff --git a/compiler/dex/quick/dex_file_method_inliner.h b/compiler/dex/quick/dex_file_method_inliner.h
index 5b3b104150..cb8c165ce5 100644
--- a/compiler/dex/quick/dex_file_method_inliner.h
+++ b/compiler/dex/quick/dex_file_method_inliner.h
@@ -107,6 +107,7 @@ class DexFileMethodInliner {
kClassCacheDouble,
kClassCacheVoid,
kClassCacheJavaLangObject,
+ kClassCacheJavaLangRefReference,
kClassCacheJavaLangString,
kClassCacheJavaLangDouble,
kClassCacheJavaLangFloat,
@@ -140,6 +141,7 @@ class DexFileMethodInliner {
kNameCacheMax,
kNameCacheMin,
kNameCacheSqrt,
+ kNameCacheGet,
kNameCacheCharAt,
kNameCacheCompareTo,
kNameCacheIsEmpty,
@@ -199,6 +201,7 @@ class DexFileMethodInliner {
kProtoCacheString_I,
kProtoCache_Z,
kProtoCache_I,
+ kProtoCache_Object,
kProtoCache_Thread,
kProtoCacheJ_B,
kProtoCacheJ_I,
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index 79065b3474..9dedeae071 100755
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -23,9 +23,12 @@
#include "invoke_type.h"
#include "mirror/array.h"
#include "mirror/class-inl.h"
+#include "mirror/dex_cache.h"
#include "mirror/object_array-inl.h"
+#include "mirror/reference-inl.h"
#include "mirror/string.h"
#include "mir_to_lir-inl.h"
+#include "scoped_thread_state_change.h"
#include "x86/codegen_x86.h"
namespace art {
@@ -1218,6 +1221,88 @@ RegLocation Mir2Lir::InlineTargetWide(CallInfo* info) {
return res;
}
+bool Mir2Lir::GenInlinedGet(CallInfo* info) {
+ if (cu_->instruction_set == kMips) {
+ // TODO - add Mips implementation
+ return false;
+ }
+
+ // the refrence class is stored in the image dex file which might not be the same as the cu's
+ // dex file. Query the reference class for the image dex file then reset to starting dex file
+ // in after loading class type.
+ uint16_t type_idx = 0;
+ const DexFile* ref_dex_file = nullptr;
+ {
+ ScopedObjectAccess soa(Thread::Current());
+ type_idx = mirror::Reference::GetJavaLangRefReference()->GetDexTypeIndex();
+ ref_dex_file = mirror::Reference::GetJavaLangRefReference()->GetDexCache()->GetDexFile();
+ }
+ CHECK(LIKELY(ref_dex_file != nullptr));
+
+ // address is either static within the image file, or needs to be patched up after compilation.
+ bool unused_type_initialized;
+ bool use_direct_type_ptr;
+ uintptr_t direct_type_ptr;
+ bool is_finalizable;
+ const DexFile* old_dex = cu_->dex_file;
+ cu_->dex_file = ref_dex_file;
+ RegStorage reg_class = TargetPtrReg(kArg1);
+ if (!cu_->compiler_driver->CanEmbedTypeInCode(*ref_dex_file, type_idx, &unused_type_initialized,
+ &use_direct_type_ptr, &direct_type_ptr,
+ &is_finalizable) || is_finalizable) {
+ cu_->dex_file = old_dex;
+ // address is not known and post-compile patch is not possible, cannot insert intrinsic.
+ return false;
+ }
+ if (use_direct_type_ptr) {
+ LoadConstant(reg_class, direct_type_ptr);
+ } else {
+ LoadClassType(type_idx, kArg1);
+ }
+ cu_->dex_file = old_dex;
+
+ // get the offset for flags in reference class.
+ uint32_t slow_path_flag_offset = 0;
+ uint32_t disable_flag_offset = 0;
+ {
+ ScopedObjectAccess soa(Thread::Current());
+ mirror::Class* reference_class = mirror::Reference::GetJavaLangRefReference();
+ slow_path_flag_offset = reference_class->GetSlowPathFlagOffset().Uint32Value();
+ disable_flag_offset = reference_class->GetDisableIntrinsicFlagOffset().Uint32Value();
+ }
+ CHECK(slow_path_flag_offset && disable_flag_offset &&
+ (slow_path_flag_offset != disable_flag_offset));
+
+ // intrinsic logic start.
+ RegLocation rl_obj = info->args[0];
+ rl_obj = LoadValue(rl_obj);
+
+ RegStorage reg_slow_path = AllocTemp();
+ RegStorage reg_disabled = AllocTemp();
+ Load32Disp(reg_class, slow_path_flag_offset, reg_slow_path);
+ Load32Disp(reg_class, disable_flag_offset, reg_disabled);
+ OpRegRegReg(kOpOr, reg_slow_path, reg_slow_path, reg_disabled);
+ FreeTemp(reg_disabled);
+
+ // if slow path, jump to JNI path target
+ LIR* slow_path_branch = OpCmpImmBranch(kCondNe, reg_slow_path, 0, nullptr);
+ FreeTemp(reg_slow_path);
+
+ // slow path not enabled, simply load the referent of the reference object
+ RegLocation rl_dest = InlineTarget(info);
+ RegLocation rl_result = EvalLoc(rl_dest, kRefReg, true);
+ GenNullCheck(rl_obj.reg, info->opt_flags);
+ LoadRefDisp(rl_obj.reg, mirror::Reference::ReferentOffset().Int32Value(), rl_result.reg,
+ kNotVolatile);
+ MarkPossibleNullPointerException(info->opt_flags);
+ StoreValue(rl_dest, rl_result);
+
+ LIR* intrinsic_finish = NewLIR0(kPseudoTargetLabel);
+ AddIntrinsicSlowPath(info, slow_path_branch, intrinsic_finish);
+
+ return true;
+}
+
bool Mir2Lir::GenInlinedCharAt(CallInfo* info) {
if (cu_->instruction_set == kMips) {
// TODO - add Mips implementation
diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc
index 07c615f342..edb3b23493 100644
--- a/compiler/dex/quick/mir_to_lir.cc
+++ b/compiler/dex/quick/mir_to_lir.cc
@@ -18,7 +18,6 @@
#include "dex/dataflow_iterator-inl.h"
#include "dex/quick/dex_file_method_inliner.h"
#include "mir_to_lir-inl.h"
-#include "object_utils.h"
#include "thread-inl.h"
namespace art {
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index 634ab943cf..c68ad6be4b 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -982,6 +982,7 @@ class Mir2Lir : public Backend {
*/
RegLocation InlineTargetWide(CallInfo* info);
+ bool GenInlinedGet(CallInfo* info);
bool GenInlinedCharAt(CallInfo* info);
bool GenInlinedStringIsEmptyOrLength(CallInfo* info, bool is_empty);
virtual bool GenInlinedReverseBits(CallInfo* info, OpSize size);
@@ -1201,7 +1202,7 @@ class Mir2Lir : public Backend {
* @param wide_kind What kind of view of the special register is required.
* @return Return the #RegStorage corresponding to the given purpose @p reg.
*
- * Note: For 32b system, wide (kWide) views only make sense for the argument registers and the
+ * @note For 32b system, wide (kWide) views only make sense for the argument registers and the
* return. In that case, this function should return a pair where the first component of
* the result will be the indicated special register.
*/
diff --git a/compiler/dex/quick_compiler_callbacks.cc b/compiler/dex/quick_compiler_callbacks.cc
new file mode 100644
index 0000000000..03bda78498
--- /dev/null
+++ b/compiler/dex/quick_compiler_callbacks.cc
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "quick_compiler_callbacks.h"
+
+#include "quick/dex_file_to_method_inliner_map.h"
+#include "verifier/method_verifier-inl.h"
+#include "verification_results.h"
+
+namespace art {
+
+bool QuickCompilerCallbacks::MethodVerified(verifier::MethodVerifier* verifier) {
+ bool result = verification_results_->ProcessVerifiedMethod(verifier);
+ if (result) {
+ MethodReference ref = verifier->GetMethodReference();
+ method_inliner_map_->GetMethodInliner(ref.dex_file)
+ ->AnalyseMethodCode(verifier);
+ }
+ return result;
+}
+
+void QuickCompilerCallbacks::ClassRejected(ClassReference ref) {
+ verification_results_->AddRejectedClass(ref);
+}
+
+} // namespace art
diff --git a/compiler/driver/compiler_callbacks_impl.h b/compiler/dex/quick_compiler_callbacks.h
index 92adb20c1f..7c9614f73a 100644
--- a/compiler/driver/compiler_callbacks_impl.h
+++ b/compiler/dex/quick_compiler_callbacks.h
@@ -14,48 +14,38 @@
* limitations under the License.
*/
-#ifndef ART_COMPILER_DRIVER_COMPILER_CALLBACKS_IMPL_H_
-#define ART_COMPILER_DRIVER_COMPILER_CALLBACKS_IMPL_H_
+#ifndef ART_COMPILER_DEX_QUICK_COMPILER_CALLBACKS_H_
+#define ART_COMPILER_DEX_QUICK_COMPILER_CALLBACKS_H_
#include "compiler_callbacks.h"
-#include "dex/quick/dex_file_to_method_inliner_map.h"
-#include "verifier/method_verifier-inl.h"
namespace art {
-class CompilerCallbacksImpl FINAL : public CompilerCallbacks {
+class VerificationResults;
+class DexFileToMethodInlinerMap;
+
+class QuickCompilerCallbacks FINAL : public CompilerCallbacks {
public:
- CompilerCallbacksImpl(VerificationResults* verification_results,
- DexFileToMethodInlinerMap* method_inliner_map)
+ QuickCompilerCallbacks(VerificationResults* verification_results,
+ DexFileToMethodInlinerMap* method_inliner_map)
: verification_results_(verification_results),
method_inliner_map_(method_inliner_map) {
CHECK(verification_results != nullptr);
CHECK(method_inliner_map != nullptr);
}
- ~CompilerCallbacksImpl() { }
+ ~QuickCompilerCallbacks() { }
bool MethodVerified(verifier::MethodVerifier* verifier)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;
- void ClassRejected(ClassReference ref) OVERRIDE {
- verification_results_->AddRejectedClass(ref);
- }
+
+ void ClassRejected(ClassReference ref) OVERRIDE;
private:
VerificationResults* const verification_results_;
DexFileToMethodInlinerMap* const method_inliner_map_;
};
-inline bool CompilerCallbacksImpl::MethodVerified(verifier::MethodVerifier* verifier) {
- bool result = verification_results_->ProcessVerifiedMethod(verifier);
- if (result) {
- MethodReference ref = verifier->GetMethodReference();
- method_inliner_map_->GetMethodInliner(ref.dex_file)
- ->AnalyseMethodCode(verifier);
- }
- return result;
-}
-
} // namespace art
-#endif // ART_COMPILER_DRIVER_COMPILER_CALLBACKS_IMPL_H_
+#endif // ART_COMPILER_DEX_QUICK_COMPILER_CALLBACKS_H_
diff --git a/compiler/driver/compiler_driver-inl.h b/compiler/driver/compiler_driver-inl.h
index e175d37914..89295f2786 100644
--- a/compiler/driver/compiler_driver-inl.h
+++ b/compiler/driver/compiler_driver-inl.h
@@ -20,12 +20,10 @@
#include "compiler_driver.h"
#include "dex/compiler_ir.h"
-#include "mirror/art_field.h"
+#include "field_helper.h"
#include "mirror/art_field-inl.h"
-#include "mirror/art_method.h"
#include "mirror/art_method-inl.h"
#include "mirror/class_loader.h"
-#include "mirror/dex_cache.h"
#include "mirror/dex_cache-inl.h"
#include "mirror/art_field-inl.h"
#include "scoped_thread_state_change.h"
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 7014c3b3f8..9e88c8d875 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -35,7 +35,7 @@
#include "dex/quick/dex_file_method_inliner.h"
#include "driver/compiler_options.h"
#include "jni_internal.h"
-#include "object_utils.h"
+#include "object_lock.h"
#include "profiler.h"
#include "runtime.h"
#include "gc/accounting/card_table-inl.h"
diff --git a/compiler/driver/compiler_driver_test.cc b/compiler/driver/compiler_driver_test.cc
index 5325a68b37..9ae9bd400a 100644
--- a/compiler/driver/compiler_driver_test.cc
+++ b/compiler/driver/compiler_driver_test.cc
@@ -25,12 +25,13 @@
#include "dex_file.h"
#include "gc/heap.h"
#include "mirror/art_method-inl.h"
-#include "mirror/class.h"
#include "mirror/class-inl.h"
+#include "mirror/class_loader.h"
#include "mirror/dex_cache-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/object-inl.h"
#include "handle_scope-inl.h"
+#include "scoped_thread_state_change.h"
namespace art {
diff --git a/compiler/elf_writer_test.cc b/compiler/elf_writer_test.cc
index e637cfbe1d..e479322238 100644
--- a/compiler/elf_writer_test.cc
+++ b/compiler/elf_writer_test.cc
@@ -16,8 +16,10 @@
#include "elf_file.h"
+#include "base/stringprintf.h"
#include "common_compiler_test.h"
#include "oat.h"
+#include "utils.h"
namespace art {
diff --git a/compiler/image_test.cc b/compiler/image_test.cc
index 6b2698085c..982e6d4f2c 100644
--- a/compiler/image_test.cc
+++ b/compiler/image_test.cc
@@ -20,14 +20,16 @@
#include <string>
#include <vector>
+#include "base/unix_file/fd_file.h"
#include "common_compiler_test.h"
-#include "compiler/elf_fixup.h"
-#include "compiler/image_writer.h"
-#include "compiler/oat_writer.h"
+#include "elf_fixup.h"
#include "gc/space/image_space.h"
+#include "image_writer.h"
#include "implicit_check_options.h"
#include "lock_word.h"
#include "mirror/object-inl.h"
+#include "oat_writer.h"
+#include "scoped_thread_state_change.h"
#include "signal_catcher.h"
#include "utils.h"
#include "vector_output_stream.h"
@@ -138,7 +140,7 @@ TEST_F(ImageTest, WriteRead) {
// Remove the reservation of the memory for use to load the image.
UnreserveImageSpace();
- Runtime::Options options;
+ RuntimeOptions options;
std::string image("-Ximage:");
image.append(image_location.GetFilename());
options.push_back(std::make_pair(image.c_str(), reinterpret_cast<void*>(NULL)));
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 38b4100ebe..8ef2964270 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -51,7 +51,6 @@
#include "mirror/string-inl.h"
#include "oat.h"
#include "oat_file.h"
-#include "object_utils.h"
#include "runtime.h"
#include "scoped_thread_state_change.h"
#include "handle_scope-inl.h"
diff --git a/compiler/jni/quick/calling_convention.h b/compiler/jni/quick/calling_convention.h
index efc0b42db4..6db0c3b8b3 100644
--- a/compiler/jni/quick/calling_convention.h
+++ b/compiler/jni/quick/calling_convention.h
@@ -19,6 +19,7 @@
#include <vector>
#include "handle_scope.h"
+#include "primitive.h"
#include "thread.h"
#include "utils/managed_register.h"
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
index d2ee0ede80..1444ca0309 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -15,15 +15,19 @@
*/
#include "common_compiler_test.h"
-#include "compiler/compiler.h"
-#include "compiler/oat_writer.h"
+#include "compiler.h"
+#include "dex/verification_results.h"
+#include "dex/quick/dex_file_to_method_inliner_map.h"
+#include "dex/quick_compiler_callbacks.h"
#include "entrypoints/quick/quick_entrypoints.h"
#include "implicit_check_options.h"
#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
-#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
+#include "mirror/object-inl.h"
#include "oat_file-inl.h"
+#include "oat_writer.h"
+#include "scoped_thread_state_change.h"
#include "vector_output_stream.h"
namespace art {
@@ -95,8 +99,8 @@ TEST_F(OatTest, WriteRead) {
compiler_options_.reset(new CompilerOptions);
verification_results_.reset(new VerificationResults(compiler_options_.get()));
method_inliner_map_.reset(new DexFileToMethodInlinerMap);
- callbacks_.reset(new CompilerCallbacksImpl(verification_results_.get(),
- method_inliner_map_.get()));
+ callbacks_.reset(new QuickCompilerCallbacks(verification_results_.get(),
+ method_inliner_map_.get()));
timer_.reset(new CumulativeLogger("Compilation times"));
compiler_driver_.reset(new CompilerDriver(compiler_options_.get(),
verification_results_.get(),
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index b0e6a75b3d..e0db0f18be 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -38,7 +38,7 @@ void CodeGenerator::CompileBaseline(CodeAllocator* allocator) {
DCHECK_EQ(frame_size_, kUninitializedFrameSize);
ComputeFrameSize(GetGraph()->GetMaximumNumberOfOutVRegs()
- + GetGraph()->GetNumberOfVRegs()
+ + GetGraph()->GetNumberOfLocalVRegs()
+ GetGraph()->GetNumberOfTemporaries()
+ 1 /* filler */);
GenerateFrameEntry();
@@ -106,6 +106,39 @@ size_t CodeGenerator::AllocateFreeRegisterInternal(
return -1;
}
+void CodeGenerator::ComputeFrameSize(size_t number_of_spill_slots) {
+ SetFrameSize(RoundUp(
+ number_of_spill_slots * kVRegSize
+ + kVRegSize // Art method
+ + FrameEntrySpillSize(),
+ kStackAlignment));
+}
+
+Location CodeGenerator::GetTemporaryLocation(HTemporary* temp) const {
+ uint16_t number_of_locals = GetGraph()->GetNumberOfLocalVRegs();
+ // Use the temporary region (right below the dex registers).
+ int32_t slot = GetFrameSize() - FrameEntrySpillSize()
+ - kVRegSize // filler
+ - (number_of_locals * kVRegSize)
+ - ((1 + temp->GetIndex()) * kVRegSize);
+ return Location::StackSlot(slot);
+}
+
+int32_t CodeGenerator::GetStackSlot(HLocal* local) const {
+ uint16_t reg_number = local->GetRegNumber();
+ uint16_t number_of_locals = GetGraph()->GetNumberOfLocalVRegs();
+ if (reg_number >= number_of_locals) {
+ // Local is a parameter of the method. It is stored in the caller's frame.
+ return GetFrameSize() + kVRegSize // ART method
+ + (reg_number - number_of_locals) * kVRegSize;
+ } else {
+ // Local is a temporary in this method. It is stored in this method's frame.
+ return GetFrameSize() - FrameEntrySpillSize()
+ - kVRegSize // filler.
+ - (number_of_locals * kVRegSize)
+ + (reg_number * kVRegSize);
+ }
+}
void CodeGenerator::AllocateRegistersLocally(HInstruction* instruction) const {
LocationSummary* locations = instruction->GetLocations();
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index abfb790d8f..18e3e5a056 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -96,7 +96,10 @@ class CodeGenerator : public ArenaObject {
virtual HGraphVisitor* GetInstructionVisitor() = 0;
virtual Assembler* GetAssembler() = 0;
virtual size_t GetWordSize() const = 0;
- virtual void ComputeFrameSize(size_t number_of_spill_slots) = 0;
+ void ComputeFrameSize(size_t number_of_spill_slots);
+ virtual size_t FrameEntrySpillSize() const = 0;
+ int32_t GetStackSlot(HLocal* local) const;
+ Location GetTemporaryLocation(HTemporary* temp) const;
uint32_t GetFrameSize() const { return frame_size_; }
void SetFrameSize(uint32_t size) { frame_size_ = size; }
@@ -150,7 +153,6 @@ class CodeGenerator : public ArenaObject {
size_t AllocateFreeRegisterInternal(bool* blocked_registers, size_t number_of_registers) const;
virtual Location GetStackLocation(HLoadLocal* load) const = 0;
- virtual Location GetTemporaryLocation(HTemporary* temp) const = 0;
// Frame size required for this method.
uint32_t frame_size_;
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index e70240783a..73c2d48320 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -99,6 +99,10 @@ CodeGeneratorARM::CodeGeneratorARM(HGraph* graph)
instruction_visitor_(graph, this),
move_resolver_(graph->GetArena(), this) {}
+size_t CodeGeneratorARM::FrameEntrySpillSize() const {
+ return kNumberOfPushedRegistersAtEntry * kArmWordSize;
+}
+
static bool* GetBlockedRegisterPairs(bool* blocked_registers) {
return blocked_registers + kNumberOfAllocIds;
}
@@ -200,14 +204,6 @@ InstructionCodeGeneratorARM::InstructionCodeGeneratorARM(HGraph* graph, CodeGene
assembler_(codegen->GetAssembler()),
codegen_(codegen) {}
-void CodeGeneratorARM::ComputeFrameSize(size_t number_of_spill_slots) {
- SetFrameSize(RoundUp(
- number_of_spill_slots * kVRegSize
- + kVRegSize // Art method
- + kNumberOfPushedRegistersAtEntry * kArmWordSize,
- kStackAlignment));
-}
-
void CodeGeneratorARM::GenerateFrameEntry() {
core_spill_mask_ |= (1 << LR | 1 << R6 | 1 << R7);
__ PushList(1 << LR | 1 << R6 | 1 << R7);
@@ -226,33 +222,6 @@ void CodeGeneratorARM::Bind(Label* label) {
__ Bind(label);
}
-Location CodeGeneratorARM::GetTemporaryLocation(HTemporary* temp) const {
- uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
- // Use the temporary region (right below the dex registers).
- int32_t slot = GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kArmWordSize)
- - kVRegSize // filler
- - (number_of_vregs * kVRegSize)
- - ((1 + temp->GetIndex()) * kVRegSize);
- return Location::StackSlot(slot);
-}
-
-int32_t CodeGeneratorARM::GetStackSlot(HLocal* local) const {
- uint16_t reg_number = local->GetRegNumber();
- uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
- uint16_t number_of_in_vregs = GetGraph()->GetNumberOfInVRegs();
- if (reg_number >= number_of_vregs - number_of_in_vregs) {
- // Local is a parameter of the method. It is stored in the caller's frame.
- return GetFrameSize() + kVRegSize // ART method
- + (reg_number - number_of_vregs + number_of_in_vregs) * kVRegSize;
- } else {
- // Local is a temporary in this method. It is stored in this method's frame.
- return GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kArmWordSize)
- - kVRegSize // filler.
- - (number_of_vregs * kVRegSize)
- + (reg_number * kVRegSize);
- }
-}
-
Location CodeGeneratorARM::GetStackLocation(HLoadLocal* load) const {
switch (load->GetType()) {
case Primitive::kPrimLong:
diff --git a/compiler/optimizing/code_generator_arm.h b/compiler/optimizing/code_generator_arm.h
index b7322b271e..1b5974f9a2 100644
--- a/compiler/optimizing/code_generator_arm.h
+++ b/compiler/optimizing/code_generator_arm.h
@@ -126,7 +126,6 @@ class CodeGeneratorARM : public CodeGenerator {
explicit CodeGeneratorARM(HGraph* graph);
virtual ~CodeGeneratorARM() { }
- virtual void ComputeFrameSize(size_t number_of_spill_slots) OVERRIDE;
virtual void GenerateFrameEntry() OVERRIDE;
virtual void GenerateFrameExit() OVERRIDE;
virtual void Bind(Label* label) OVERRIDE;
@@ -136,6 +135,8 @@ class CodeGeneratorARM : public CodeGenerator {
return kArmWordSize;
}
+ virtual size_t FrameEntrySpillSize() const OVERRIDE;
+
virtual HGraphVisitor* GetLocationBuilder() OVERRIDE {
return &location_builder_;
}
@@ -153,9 +154,7 @@ class CodeGeneratorARM : public CodeGenerator {
Primitive::Type type, bool* blocked_registers) const OVERRIDE;
virtual size_t GetNumberOfRegisters() const OVERRIDE;
- int32_t GetStackSlot(HLocal* local) const;
virtual Location GetStackLocation(HLoadLocal* load) const OVERRIDE;
- virtual Location GetTemporaryLocation(HTemporary* temp) const OVERRIDE;
virtual size_t GetNumberOfCoreRegisters() const OVERRIDE {
return kNumberOfCoreRegisters;
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 52cb39dc7f..4e69a0cad8 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -83,12 +83,8 @@ CodeGeneratorX86::CodeGeneratorX86(HGraph* graph)
instruction_visitor_(graph, this),
move_resolver_(graph->GetArena(), this) {}
-void CodeGeneratorX86::ComputeFrameSize(size_t number_of_spill_slots) {
- SetFrameSize(RoundUp(
- number_of_spill_slots * kVRegSize
- + kVRegSize // Art method
- + kNumberOfPushedRegistersAtEntry * kX86WordSize,
- kStackAlignment));
+size_t CodeGeneratorX86::FrameEntrySpillSize() const {
+ return kNumberOfPushedRegistersAtEntry * kX86WordSize;
}
static bool* GetBlockedRegisterPairs(bool* blocked_registers) {
@@ -204,34 +200,6 @@ void InstructionCodeGeneratorX86::LoadCurrentMethod(Register reg) {
__ movl(reg, Address(ESP, kCurrentMethodStackOffset));
}
-Location CodeGeneratorX86::GetTemporaryLocation(HTemporary* temp) const {
- uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
- // Use the temporary region (right below the dex registers).
- int32_t slot = GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kX86WordSize)
- - kVRegSize // filler
- - (number_of_vregs * kVRegSize)
- - ((1 + temp->GetIndex()) * kVRegSize);
- return Location::StackSlot(slot);
-}
-
-int32_t CodeGeneratorX86::GetStackSlot(HLocal* local) const {
- uint16_t reg_number = local->GetRegNumber();
- uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
- uint16_t number_of_in_vregs = GetGraph()->GetNumberOfInVRegs();
- if (reg_number >= number_of_vregs - number_of_in_vregs) {
- // Local is a parameter of the method. It is stored in the caller's frame.
- return GetFrameSize() + kVRegSize // ART method
- + (reg_number - number_of_vregs + number_of_in_vregs) * kVRegSize;
- } else {
- // Local is a temporary in this method. It is stored in this method's frame.
- return GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kX86WordSize)
- - kVRegSize // filler.
- - (number_of_vregs * kVRegSize)
- + (reg_number * kVRegSize);
- }
-}
-
-
Location CodeGeneratorX86::GetStackLocation(HLoadLocal* load) const {
switch (load->GetType()) {
case Primitive::kPrimLong:
diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h
index 2a4595447d..d622d2a685 100644
--- a/compiler/optimizing/code_generator_x86.h
+++ b/compiler/optimizing/code_generator_x86.h
@@ -128,7 +128,6 @@ class CodeGeneratorX86 : public CodeGenerator {
explicit CodeGeneratorX86(HGraph* graph);
virtual ~CodeGeneratorX86() { }
- virtual void ComputeFrameSize(size_t number_of_spill_slots) OVERRIDE;
virtual void GenerateFrameEntry() OVERRIDE;
virtual void GenerateFrameExit() OVERRIDE;
virtual void Bind(Label* label) OVERRIDE;
@@ -138,6 +137,8 @@ class CodeGeneratorX86 : public CodeGenerator {
return kX86WordSize;
}
+ virtual size_t FrameEntrySpillSize() const OVERRIDE;
+
virtual HGraphVisitor* GetLocationBuilder() OVERRIDE {
return &location_builder_;
}
@@ -155,9 +156,7 @@ class CodeGeneratorX86 : public CodeGenerator {
virtual ManagedRegister AllocateFreeRegister(
Primitive::Type type, bool* blocked_registers) const OVERRIDE;
- int32_t GetStackSlot(HLocal* local) const;
virtual Location GetStackLocation(HLoadLocal* load) const OVERRIDE;
- virtual Location GetTemporaryLocation(HTemporary* temp) const OVERRIDE;
virtual size_t GetNumberOfCoreRegisters() const OVERRIDE {
return kNumberOfCpuRegisters;
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 93d74ee1a2..e3ce5ceb4f 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -91,6 +91,10 @@ CodeGeneratorX86_64::CodeGeneratorX86_64(HGraph* graph)
instruction_visitor_(graph, this),
move_resolver_(graph->GetArena(), this) {}
+size_t CodeGeneratorX86_64::FrameEntrySpillSize() const {
+ return kNumberOfPushedRegistersAtEntry * kX86_64WordSize;
+}
+
InstructionCodeGeneratorX86_64::InstructionCodeGeneratorX86_64(HGraph* graph, CodeGeneratorX86_64* codegen)
: HGraphVisitor(graph),
assembler_(codegen->GetAssembler()),
@@ -137,16 +141,6 @@ void CodeGeneratorX86_64::SetupBlockedRegisters(bool* blocked_registers) const {
blocked_registers[R15] = true;
}
-void CodeGeneratorX86_64::ComputeFrameSize(size_t number_of_spill_slots) {
- // Add the current ART method to the frame size, the return PC, and the filler.
- SetFrameSize(RoundUp(
- number_of_spill_slots * kVRegSize
- + kVRegSize // filler
- + kVRegSize // Art method
- + kNumberOfPushedRegistersAtEntry * kX86_64WordSize,
- kStackAlignment));
-}
-
void CodeGeneratorX86_64::GenerateFrameEntry() {
// Create a fake register to mimic Quick.
static const int kFakeReturnRegister = 16;
@@ -170,33 +164,6 @@ void InstructionCodeGeneratorX86_64::LoadCurrentMethod(CpuRegister reg) {
__ movl(reg, Address(CpuRegister(RSP), kCurrentMethodStackOffset));
}
-Location CodeGeneratorX86_64::GetTemporaryLocation(HTemporary* temp) const {
- uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
- // Use the temporary region (right below the dex registers).
- int32_t slot = GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kX86_64WordSize)
- - kVRegSize // filler
- - (number_of_vregs * kVRegSize)
- - ((1 + temp->GetIndex()) * kVRegSize);
- return Location::StackSlot(slot);
-}
-
-int32_t CodeGeneratorX86_64::GetStackSlot(HLocal* local) const {
- uint16_t reg_number = local->GetRegNumber();
- uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
- uint16_t number_of_in_vregs = GetGraph()->GetNumberOfInVRegs();
- if (reg_number >= number_of_vregs - number_of_in_vregs) {
- // Local is a parameter of the method. It is stored in the caller's frame.
- return GetFrameSize() + kVRegSize // ART method
- + (reg_number - number_of_vregs + number_of_in_vregs) * kVRegSize;
- } else {
- // Local is a temporary in this method. It is stored in this method's frame.
- return GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kX86_64WordSize)
- - kVRegSize // filler
- - (number_of_vregs * kVRegSize)
- + (reg_number * kVRegSize);
- }
-}
-
Location CodeGeneratorX86_64::GetStackLocation(HLoadLocal* load) const {
switch (load->GetType()) {
case Primitive::kPrimLong:
diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h
index 97a0b2e579..8283dda4a5 100644
--- a/compiler/optimizing/code_generator_x86_64.h
+++ b/compiler/optimizing/code_generator_x86_64.h
@@ -125,7 +125,6 @@ class CodeGeneratorX86_64 : public CodeGenerator {
explicit CodeGeneratorX86_64(HGraph* graph);
virtual ~CodeGeneratorX86_64() {}
- virtual void ComputeFrameSize(size_t number_of_spill_slots) OVERRIDE;
virtual void GenerateFrameEntry() OVERRIDE;
virtual void GenerateFrameExit() OVERRIDE;
virtual void Bind(Label* label) OVERRIDE;
@@ -135,6 +134,8 @@ class CodeGeneratorX86_64 : public CodeGenerator {
return kX86_64WordSize;
}
+ virtual size_t FrameEntrySpillSize() const OVERRIDE;
+
virtual HGraphVisitor* GetLocationBuilder() OVERRIDE {
return &location_builder_;
}
@@ -151,9 +152,7 @@ class CodeGeneratorX86_64 : public CodeGenerator {
return &move_resolver_;
}
- int32_t GetStackSlot(HLocal* local) const;
virtual Location GetStackLocation(HLoadLocal* load) const OVERRIDE;
- virtual Location GetTemporaryLocation(HTemporary* temp) const OVERRIDE;
virtual size_t GetNumberOfRegisters() const OVERRIDE {
return kNumberOfRegIds;
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 689aab08b3..e87b044cc9 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -19,6 +19,7 @@
#include "locations.h"
#include "offsets.h"
+#include "primitive.h"
#include "utils/allocation.h"
#include "utils/arena_bit_vector.h"
#include "utils/growable_array.h"
@@ -138,6 +139,10 @@ class HGraph : public ArenaObject {
return number_of_in_vregs_;
}
+ uint16_t GetNumberOfLocalVRegs() const {
+ return number_of_vregs_ - number_of_in_vregs_;
+ }
+
const GrowableArray<HBasicBlock*>& GetReversePostOrder() const {
return reverse_post_order_;
}
diff --git a/compiler/optimizing/register_allocator.h b/compiler/optimizing/register_allocator.h
index 7d4cd1a862..e35ff56c75 100644
--- a/compiler/optimizing/register_allocator.h
+++ b/compiler/optimizing/register_allocator.h
@@ -18,6 +18,7 @@
#define ART_COMPILER_OPTIMIZING_REGISTER_ALLOCATOR_H_
#include "base/macros.h"
+#include "primitive.h"
#include "utils/growable_array.h"
namespace art {
diff --git a/compiler/output_stream_test.cc b/compiler/output_stream_test.cc
index 5fa0ccb143..315ca09e59 100644
--- a/compiler/output_stream_test.cc
+++ b/compiler/output_stream_test.cc
@@ -17,6 +17,7 @@
#include "file_output_stream.h"
#include "vector_output_stream.h"
+#include "base/unix_file/fd_file.h"
#include "base/logging.h"
#include "buffered_output_stream.h"
#include "common_runtime_test.h"
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 0d40c8d209..77946b03ae 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -40,7 +40,8 @@
#include "dex_file-inl.h"
#include "dex/pass_driver_me_opts.h"
#include "dex/verification_results.h"
-#include "driver/compiler_callbacks_impl.h"
+#include "dex/quick_compiler_callbacks.h"
+#include "dex/quick/dex_file_to_method_inliner_map.h"
#include "driver/compiler_driver.h"
#include "driver/compiler_options.h"
#include "elf_fixup.h"
@@ -56,7 +57,6 @@
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "oat_writer.h"
-#include "object_utils.h"
#include "os.h"
#include "runtime.h"
#include "ScopedLocalRef.h"
@@ -233,7 +233,7 @@ static void Usage(const char* fmt, ...) {
class Dex2Oat {
public:
static bool Create(Dex2Oat** p_dex2oat,
- const Runtime::Options& runtime_options,
+ const RuntimeOptions& runtime_options,
const CompilerOptions& compiler_options,
Compiler::Kind compiler_kind,
InstructionSet instruction_set,
@@ -460,7 +460,7 @@ class Dex2Oat {
CHECK(method_inliner_map != nullptr);
}
- bool CreateRuntime(const Runtime::Options& runtime_options, InstructionSet instruction_set)
+ bool CreateRuntime(const RuntimeOptions& runtime_options, InstructionSet instruction_set)
SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_) {
if (!Runtime::Create(runtime_options, false)) {
LOG(ERROR) << "Failed to create runtime";
@@ -1230,7 +1230,7 @@ static int dex2oat(int argc, char** argv) {
timings.StartTiming("dex2oat Setup");
LOG(INFO) << CommandLine();
- Runtime::Options runtime_options;
+ RuntimeOptions runtime_options;
std::vector<const DexFile*> boot_class_path;
if (boot_image_option.empty()) {
size_t failure_count = OpenDexFiles(dex_filenames, dex_locations, boot_class_path);
@@ -1249,7 +1249,7 @@ static int dex2oat(int argc, char** argv) {
std::unique_ptr<VerificationResults> verification_results(new VerificationResults(
compiler_options.get()));
DexFileToMethodInlinerMap method_inliner_map;
- CompilerCallbacksImpl callbacks(verification_results.get(), &method_inliner_map);
+ QuickCompilerCallbacks callbacks(verification_results.get(), &method_inliner_map);
runtime_options.push_back(std::make_pair("compilercallbacks", &callbacks));
runtime_options.push_back(
std::make_pair("imageinstructionset",
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 0fa1a96bd9..b8f20f3650 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -29,6 +29,7 @@
#include "dex_file-inl.h"
#include "dex_instruction.h"
#include "disassembler.h"
+#include "field_helper.h"
#include "gc_map.h"
#include "gc/space/image_space.h"
#include "gc/space/large_object_space.h"
@@ -45,7 +46,6 @@
#include "noop_compiler_callbacks.h"
#include "oat.h"
#include "oat_file-inl.h"
-#include "object_utils.h"
#include "os.h"
#include "runtime.h"
#include "safe_map.h"
@@ -1548,7 +1548,7 @@ static int oatdump(int argc, char** argv) {
return EXIT_SUCCESS;
}
- Runtime::Options options;
+ RuntimeOptions options;
std::string image_option;
std::string oat_option;
std::string boot_image_option;
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index dcf8c70501..85b4e6df32 100644
--- a/patchoat/patchoat.cc
+++ b/patchoat/patchoat.cc
@@ -26,6 +26,7 @@
#include "base/stringprintf.h"
#include "elf_utils.h"
#include "elf_file.h"
+#include "gc/space/image_space.h"
#include "image.h"
#include "instruction_set.h"
#include "mirror/art_field.h"
@@ -92,7 +93,7 @@ bool PatchOat::Patch(const std::string& image_location, off_t delta,
}
// Set up the runtime
- Runtime::Options options;
+ RuntimeOptions options;
NoopCompilerCallbacks callbacks;
options.push_back(std::make_pair("compilercallbacks", &callbacks));
std::string img = "-Ximage:" + image_location;
@@ -176,7 +177,7 @@ bool PatchOat::Patch(const File* input_oat, const std::string& image_location, o
}
// Set up the runtime
- Runtime::Options options;
+ RuntimeOptions options;
NoopCompilerCallbacks callbacks;
options.push_back(std::make_pair("compilercallbacks", &callbacks));
std::string img = "-Ximage:" + image_location;
diff --git a/runtime/Android.mk b/runtime/Android.mk
index b0c1a9ca04..f2d3c8e8c0 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -19,290 +19,294 @@ LOCAL_PATH := $(call my-dir)
include art/build/Android.common_build.mk
LIBART_COMMON_SRC_FILES := \
- atomic.cc.arm \
- barrier.cc \
- base/allocator.cc \
- base/bit_vector.cc \
- base/hex_dump.cc \
- base/logging.cc \
- base/mutex.cc \
- base/scoped_flock.cc \
- base/stringpiece.cc \
- base/stringprintf.cc \
- base/timing_logger.cc \
- base/unix_file/fd_file.cc \
- base/unix_file/mapped_file.cc \
- base/unix_file/null_file.cc \
- base/unix_file/random_access_file_utils.cc \
- base/unix_file/string_file.cc \
- check_jni.cc \
- class_linker.cc \
- common_throws.cc \
- debugger.cc \
- dex_file.cc \
- dex_file_verifier.cc \
- dex_instruction.cc \
- elf_file.cc \
- gc/allocator/dlmalloc.cc \
- gc/allocator/rosalloc.cc \
- gc/accounting/card_table.cc \
- gc/accounting/gc_allocator.cc \
- gc/accounting/heap_bitmap.cc \
- gc/accounting/mod_union_table.cc \
- gc/accounting/remembered_set.cc \
- gc/accounting/space_bitmap.cc \
- gc/collector/concurrent_copying.cc \
- gc/collector/garbage_collector.cc \
- gc/collector/immune_region.cc \
- gc/collector/mark_compact.cc \
- gc/collector/mark_sweep.cc \
- gc/collector/partial_mark_sweep.cc \
- gc/collector/semi_space.cc \
- gc/collector/sticky_mark_sweep.cc \
- gc/gc_cause.cc \
- gc/heap.cc \
- gc/reference_processor.cc \
- gc/reference_queue.cc \
- gc/space/bump_pointer_space.cc \
- gc/space/dlmalloc_space.cc \
- gc/space/image_space.cc \
- gc/space/large_object_space.cc \
- gc/space/malloc_space.cc \
- gc/space/rosalloc_space.cc \
- gc/space/space.cc \
- gc/space/zygote_space.cc \
- hprof/hprof.cc \
- image.cc \
- indirect_reference_table.cc \
- instruction_set.cc \
- instrumentation.cc \
- intern_table.cc \
- interpreter/interpreter.cc \
- interpreter/interpreter_common.cc \
- interpreter/interpreter_switch_impl.cc \
- jdwp/jdwp_event.cc \
- jdwp/jdwp_expand_buf.cc \
- jdwp/jdwp_handler.cc \
- jdwp/jdwp_main.cc \
- jdwp/jdwp_request.cc \
- jdwp/jdwp_socket.cc \
- jdwp/object_registry.cc \
- jni_internal.cc \
- jobject_comparator.cc \
- mem_map.cc \
- memory_region.cc \
- mirror/art_field.cc \
- mirror/art_method.cc \
- mirror/array.cc \
- mirror/class.cc \
- mirror/dex_cache.cc \
- mirror/object.cc \
- mirror/stack_trace_element.cc \
- mirror/string.cc \
- mirror/throwable.cc \
- monitor.cc \
- native/dalvik_system_DexFile.cc \
- native/dalvik_system_VMDebug.cc \
- native/dalvik_system_VMRuntime.cc \
- native/dalvik_system_VMStack.cc \
- native/dalvik_system_ZygoteHooks.cc \
- native/java_lang_Class.cc \
- native/java_lang_DexCache.cc \
- native/java_lang_Object.cc \
- native/java_lang_Runtime.cc \
- native/java_lang_String.cc \
- native/java_lang_System.cc \
- native/java_lang_Thread.cc \
- native/java_lang_Throwable.cc \
- native/java_lang_VMClassLoader.cc \
- native/java_lang_ref_Reference.cc \
- native/java_lang_reflect_Array.cc \
- native/java_lang_reflect_Constructor.cc \
- native/java_lang_reflect_Field.cc \
- native/java_lang_reflect_Method.cc \
- native/java_lang_reflect_Proxy.cc \
- native/java_util_concurrent_atomic_AtomicLong.cc \
- native/org_apache_harmony_dalvik_ddmc_DdmServer.cc \
- native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc \
- native/sun_misc_Unsafe.cc \
- oat.cc \
- oat_file.cc \
- offsets.cc \
- os_linux.cc \
- parsed_options.cc \
- primitive.cc \
- quick_exception_handler.cc \
- quick/inline_method_analyser.cc \
- reference_table.cc \
- reflection.cc \
- runtime.cc \
- signal_catcher.cc \
- stack.cc \
- thread.cc \
- thread_list.cc \
- thread_pool.cc \
- throw_location.cc \
- trace.cc \
- transaction.cc \
- profiler.cc \
- fault_handler.cc \
- utf.cc \
- utils.cc \
- verifier/dex_gc_map.cc \
- verifier/instruction_flags.cc \
- verifier/method_verifier.cc \
- verifier/reg_type.cc \
- verifier/reg_type_cache.cc \
- verifier/register_line.cc \
- well_known_classes.cc \
- zip_archive.cc
+ atomic.cc.arm \
+ barrier.cc \
+ base/allocator.cc \
+ base/bit_vector.cc \
+ base/hex_dump.cc \
+ base/logging.cc \
+ base/mutex.cc \
+ base/scoped_flock.cc \
+ base/stringpiece.cc \
+ base/stringprintf.cc \
+ base/timing_logger.cc \
+ base/unix_file/fd_file.cc \
+ base/unix_file/mapped_file.cc \
+ base/unix_file/null_file.cc \
+ base/unix_file/random_access_file_utils.cc \
+ base/unix_file/string_file.cc \
+ check_jni.cc \
+ class_linker.cc \
+ common_throws.cc \
+ debugger.cc \
+ dex_file.cc \
+ dex_file_verifier.cc \
+ dex_instruction.cc \
+ elf_file.cc \
+ field_helper.cc \
+ gc/allocator/dlmalloc.cc \
+ gc/allocator/rosalloc.cc \
+ gc/accounting/card_table.cc \
+ gc/accounting/gc_allocator.cc \
+ gc/accounting/heap_bitmap.cc \
+ gc/accounting/mod_union_table.cc \
+ gc/accounting/remembered_set.cc \
+ gc/accounting/space_bitmap.cc \
+ gc/collector/concurrent_copying.cc \
+ gc/collector/garbage_collector.cc \
+ gc/collector/immune_region.cc \
+ gc/collector/mark_compact.cc \
+ gc/collector/mark_sweep.cc \
+ gc/collector/partial_mark_sweep.cc \
+ gc/collector/semi_space.cc \
+ gc/collector/sticky_mark_sweep.cc \
+ gc/gc_cause.cc \
+ gc/heap.cc \
+ gc/reference_processor.cc \
+ gc/reference_queue.cc \
+ gc/space/bump_pointer_space.cc \
+ gc/space/dlmalloc_space.cc \
+ gc/space/image_space.cc \
+ gc/space/large_object_space.cc \
+ gc/space/malloc_space.cc \
+ gc/space/rosalloc_space.cc \
+ gc/space/space.cc \
+ gc/space/zygote_space.cc \
+ hprof/hprof.cc \
+ image.cc \
+ indirect_reference_table.cc \
+ instruction_set.cc \
+ instrumentation.cc \
+ intern_table.cc \
+ interpreter/interpreter.cc \
+ interpreter/interpreter_common.cc \
+ interpreter/interpreter_switch_impl.cc \
+ jdwp/jdwp_event.cc \
+ jdwp/jdwp_expand_buf.cc \
+ jdwp/jdwp_handler.cc \
+ jdwp/jdwp_main.cc \
+ jdwp/jdwp_request.cc \
+ jdwp/jdwp_socket.cc \
+ jdwp/object_registry.cc \
+ jni_internal.cc \
+ jobject_comparator.cc \
+ mem_map.cc \
+ memory_region.cc \
+ method_helper.cc \
+ mirror/art_field.cc \
+ mirror/art_method.cc \
+ mirror/array.cc \
+ mirror/class.cc \
+ mirror/dex_cache.cc \
+ mirror/object.cc \
+ mirror/reference.cc \
+ mirror/stack_trace_element.cc \
+ mirror/string.cc \
+ mirror/throwable.cc \
+ monitor.cc \
+ native/dalvik_system_DexFile.cc \
+ native/dalvik_system_VMDebug.cc \
+ native/dalvik_system_VMRuntime.cc \
+ native/dalvik_system_VMStack.cc \
+ native/dalvik_system_ZygoteHooks.cc \
+ native/java_lang_Class.cc \
+ native/java_lang_DexCache.cc \
+ native/java_lang_Object.cc \
+ native/java_lang_Runtime.cc \
+ native/java_lang_String.cc \
+ native/java_lang_System.cc \
+ native/java_lang_Thread.cc \
+ native/java_lang_Throwable.cc \
+ native/java_lang_VMClassLoader.cc \
+ native/java_lang_ref_Reference.cc \
+ native/java_lang_reflect_Array.cc \
+ native/java_lang_reflect_Constructor.cc \
+ native/java_lang_reflect_Field.cc \
+ native/java_lang_reflect_Method.cc \
+ native/java_lang_reflect_Proxy.cc \
+ native/java_util_concurrent_atomic_AtomicLong.cc \
+ native/org_apache_harmony_dalvik_ddmc_DdmServer.cc \
+ native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc \
+ native/sun_misc_Unsafe.cc \
+ oat.cc \
+ oat_file.cc \
+ object_lock.cc \
+ offsets.cc \
+ os_linux.cc \
+ parsed_options.cc \
+ primitive.cc \
+ quick_exception_handler.cc \
+ quick/inline_method_analyser.cc \
+ reference_table.cc \
+ reflection.cc \
+ runtime.cc \
+ signal_catcher.cc \
+ stack.cc \
+ thread.cc \
+ thread_list.cc \
+ thread_pool.cc \
+ throw_location.cc \
+ trace.cc \
+ transaction.cc \
+ profiler.cc \
+ fault_handler.cc \
+ utf.cc \
+ utils.cc \
+ verifier/dex_gc_map.cc \
+ verifier/instruction_flags.cc \
+ verifier/method_verifier.cc \
+ verifier/reg_type.cc \
+ verifier/reg_type_cache.cc \
+ verifier/register_line.cc \
+ well_known_classes.cc \
+ zip_archive.cc
LIBART_COMMON_SRC_FILES += \
- arch/context.cc \
- arch/memcmp16.cc \
- arch/arm/registers_arm.cc \
- arch/arm64/registers_arm64.cc \
- arch/x86/registers_x86.cc \
- arch/mips/registers_mips.cc \
- entrypoints/entrypoint_utils.cc \
- entrypoints/interpreter/interpreter_entrypoints.cc \
- entrypoints/jni/jni_entrypoints.cc \
- entrypoints/math_entrypoints.cc \
- entrypoints/portable/portable_alloc_entrypoints.cc \
- entrypoints/portable/portable_cast_entrypoints.cc \
- entrypoints/portable/portable_dexcache_entrypoints.cc \
- entrypoints/portable/portable_field_entrypoints.cc \
- entrypoints/portable/portable_fillarray_entrypoints.cc \
- entrypoints/portable/portable_invoke_entrypoints.cc \
- entrypoints/portable/portable_jni_entrypoints.cc \
- entrypoints/portable/portable_lock_entrypoints.cc \
- entrypoints/portable/portable_thread_entrypoints.cc \
- entrypoints/portable/portable_throw_entrypoints.cc \
- entrypoints/portable/portable_trampoline_entrypoints.cc \
- entrypoints/quick/quick_alloc_entrypoints.cc \
- entrypoints/quick/quick_cast_entrypoints.cc \
- entrypoints/quick/quick_deoptimization_entrypoints.cc \
- entrypoints/quick/quick_dexcache_entrypoints.cc \
- entrypoints/quick/quick_field_entrypoints.cc \
- entrypoints/quick/quick_fillarray_entrypoints.cc \
- entrypoints/quick/quick_instrumentation_entrypoints.cc \
- entrypoints/quick/quick_jni_entrypoints.cc \
- entrypoints/quick/quick_lock_entrypoints.cc \
- entrypoints/quick/quick_math_entrypoints.cc \
- entrypoints/quick/quick_thread_entrypoints.cc \
- entrypoints/quick/quick_throw_entrypoints.cc \
- entrypoints/quick/quick_trampoline_entrypoints.cc
+ arch/context.cc \
+ arch/memcmp16.cc \
+ arch/arm/registers_arm.cc \
+ arch/arm64/registers_arm64.cc \
+ arch/x86/registers_x86.cc \
+ arch/mips/registers_mips.cc \
+ entrypoints/entrypoint_utils.cc \
+ entrypoints/interpreter/interpreter_entrypoints.cc \
+ entrypoints/jni/jni_entrypoints.cc \
+ entrypoints/math_entrypoints.cc \
+ entrypoints/portable/portable_alloc_entrypoints.cc \
+ entrypoints/portable/portable_cast_entrypoints.cc \
+ entrypoints/portable/portable_dexcache_entrypoints.cc \
+ entrypoints/portable/portable_field_entrypoints.cc \
+ entrypoints/portable/portable_fillarray_entrypoints.cc \
+ entrypoints/portable/portable_invoke_entrypoints.cc \
+ entrypoints/portable/portable_jni_entrypoints.cc \
+ entrypoints/portable/portable_lock_entrypoints.cc \
+ entrypoints/portable/portable_thread_entrypoints.cc \
+ entrypoints/portable/portable_throw_entrypoints.cc \
+ entrypoints/portable/portable_trampoline_entrypoints.cc \
+ entrypoints/quick/quick_alloc_entrypoints.cc \
+ entrypoints/quick/quick_cast_entrypoints.cc \
+ entrypoints/quick/quick_deoptimization_entrypoints.cc \
+ entrypoints/quick/quick_dexcache_entrypoints.cc \
+ entrypoints/quick/quick_field_entrypoints.cc \
+ entrypoints/quick/quick_fillarray_entrypoints.cc \
+ entrypoints/quick/quick_instrumentation_entrypoints.cc \
+ entrypoints/quick/quick_jni_entrypoints.cc \
+ entrypoints/quick/quick_lock_entrypoints.cc \
+ entrypoints/quick/quick_math_entrypoints.cc \
+ entrypoints/quick/quick_thread_entrypoints.cc \
+ entrypoints/quick/quick_throw_entrypoints.cc \
+ entrypoints/quick/quick_trampoline_entrypoints.cc
# Source files that only compile with GCC.
LIBART_GCC_ONLY_SRC_FILES := \
- interpreter/interpreter_goto_table_impl.cc
+ interpreter/interpreter_goto_table_impl.cc
LIBART_TARGET_LDFLAGS :=
LIBART_HOST_LDFLAGS :=
LIBART_TARGET_SRC_FILES := \
- $(LIBART_COMMON_SRC_FILES) \
- base/logging_android.cc \
- jdwp/jdwp_adb.cc \
- monitor_android.cc \
- runtime_android.cc \
- thread_android.cc
+ $(LIBART_COMMON_SRC_FILES) \
+ base/logging_android.cc \
+ jdwp/jdwp_adb.cc \
+ monitor_android.cc \
+ runtime_android.cc \
+ thread_android.cc
LIBART_TARGET_SRC_FILES_arm := \
- arch/arm/context_arm.cc.arm \
- arch/arm/entrypoints_init_arm.cc \
- arch/arm/jni_entrypoints_arm.S \
- arch/arm/memcmp16_arm.S \
- arch/arm/portable_entrypoints_arm.S \
- arch/arm/quick_entrypoints_arm.S \
- arch/arm/arm_sdiv.S \
- arch/arm/thread_arm.cc \
- arch/arm/fault_handler_arm.cc
+ arch/arm/context_arm.cc.arm \
+ arch/arm/entrypoints_init_arm.cc \
+ arch/arm/jni_entrypoints_arm.S \
+ arch/arm/memcmp16_arm.S \
+ arch/arm/portable_entrypoints_arm.S \
+ arch/arm/quick_entrypoints_arm.S \
+ arch/arm/arm_sdiv.S \
+ arch/arm/thread_arm.cc \
+ arch/arm/fault_handler_arm.cc
LIBART_TARGET_SRC_FILES_arm64 := \
- arch/arm64/context_arm64.cc \
- arch/arm64/entrypoints_init_arm64.cc \
- arch/arm64/jni_entrypoints_arm64.S \
- arch/arm64/memcmp16_arm64.S \
- arch/arm64/portable_entrypoints_arm64.S \
- arch/arm64/quick_entrypoints_arm64.S \
- arch/arm64/thread_arm64.cc \
- monitor_pool.cc \
- arch/arm64/fault_handler_arm64.cc
+ arch/arm64/context_arm64.cc \
+ arch/arm64/entrypoints_init_arm64.cc \
+ arch/arm64/jni_entrypoints_arm64.S \
+ arch/arm64/memcmp16_arm64.S \
+ arch/arm64/portable_entrypoints_arm64.S \
+ arch/arm64/quick_entrypoints_arm64.S \
+ arch/arm64/thread_arm64.cc \
+ monitor_pool.cc \
+ arch/arm64/fault_handler_arm64.cc
LIBART_SRC_FILES_x86 := \
- arch/x86/context_x86.cc \
- arch/x86/entrypoints_init_x86.cc \
- arch/x86/jni_entrypoints_x86.S \
- arch/x86/portable_entrypoints_x86.S \
- arch/x86/quick_entrypoints_x86.S \
- arch/x86/thread_x86.cc \
- arch/x86/fault_handler_x86.cc
+ arch/x86/context_x86.cc \
+ arch/x86/entrypoints_init_x86.cc \
+ arch/x86/jni_entrypoints_x86.S \
+ arch/x86/portable_entrypoints_x86.S \
+ arch/x86/quick_entrypoints_x86.S \
+ arch/x86/thread_x86.cc \
+ arch/x86/fault_handler_x86.cc
LIBART_TARGET_SRC_FILES_x86 := \
- $(LIBART_SRC_FILES_x86)
+ $(LIBART_SRC_FILES_x86)
LIBART_SRC_FILES_x86_64 := \
- arch/x86_64/context_x86_64.cc \
- arch/x86_64/entrypoints_init_x86_64.cc \
- arch/x86_64/jni_entrypoints_x86_64.S \
- arch/x86_64/portable_entrypoints_x86_64.S \
- arch/x86_64/quick_entrypoints_x86_64.S \
- arch/x86_64/thread_x86_64.cc \
- monitor_pool.cc \
- arch/x86_64/fault_handler_x86_64.cc
+ arch/x86_64/context_x86_64.cc \
+ arch/x86_64/entrypoints_init_x86_64.cc \
+ arch/x86_64/jni_entrypoints_x86_64.S \
+ arch/x86_64/portable_entrypoints_x86_64.S \
+ arch/x86_64/quick_entrypoints_x86_64.S \
+ arch/x86_64/thread_x86_64.cc \
+ monitor_pool.cc \
+ arch/x86_64/fault_handler_x86_64.cc
LIBART_TARGET_SRC_FILES_x86_64 := \
- $(LIBART_SRC_FILES_x86_64) \
+ $(LIBART_SRC_FILES_x86_64) \
LIBART_TARGET_SRC_FILES_mips := \
- arch/mips/context_mips.cc \
- arch/mips/entrypoints_init_mips.cc \
- arch/mips/jni_entrypoints_mips.S \
- arch/mips/memcmp16_mips.S \
- arch/mips/portable_entrypoints_mips.S \
- arch/mips/quick_entrypoints_mips.S \
- arch/mips/thread_mips.cc \
- arch/mips/fault_handler_mips.cc
+ arch/mips/context_mips.cc \
+ arch/mips/entrypoints_init_mips.cc \
+ arch/mips/jni_entrypoints_mips.S \
+ arch/mips/memcmp16_mips.S \
+ arch/mips/portable_entrypoints_mips.S \
+ arch/mips/quick_entrypoints_mips.S \
+ arch/mips/thread_mips.cc \
+ arch/mips/fault_handler_mips.cc
ifeq ($(TARGET_ARCH),mips64)
$(info TODOMips64: $(LOCAL_PATH)/Android.mk Add mips64 specific runtime files)
endif # TARGET_ARCH != mips64
LIBART_HOST_SRC_FILES := \
- $(LIBART_COMMON_SRC_FILES) \
- base/logging_linux.cc \
- monitor_linux.cc \
- runtime_linux.cc \
- thread_linux.cc
+ $(LIBART_COMMON_SRC_FILES) \
+ base/logging_linux.cc \
+ monitor_linux.cc \
+ runtime_linux.cc \
+ thread_linux.cc
LIBART_HOST_SRC_FILES_32 := \
- $(LIBART_SRC_FILES_x86)
+ $(LIBART_SRC_FILES_x86)
LIBART_HOST_SRC_FILES_64 := \
- $(LIBART_SRC_FILES_x86_64)
+ $(LIBART_SRC_FILES_x86_64)
LIBART_ENUM_OPERATOR_OUT_HEADER_FILES := \
- arch/x86_64/registers_x86_64.h \
- base/mutex.h \
- dex_file.h \
- dex_instruction.h \
- gc/collector/gc_type.h \
- gc/space/space.h \
- gc/heap.h \
- indirect_reference_table.h \
- instruction_set.h \
- invoke_type.h \
- jdwp/jdwp.h \
- jdwp/jdwp_constants.h \
- lock_word.h \
- mirror/class.h \
- oat.h \
- object_callbacks.h \
- quick/inline_method_analyser.h \
- thread.h \
- thread_state.h \
- verifier/method_verifier.h
+ arch/x86_64/registers_x86_64.h \
+ base/mutex.h \
+ dex_file.h \
+ dex_instruction.h \
+ gc/collector/gc_type.h \
+ gc/space/space.h \
+ gc/heap.h \
+ indirect_reference_table.h \
+ instruction_set.h \
+ invoke_type.h \
+ jdwp/jdwp.h \
+ jdwp/jdwp_constants.h \
+ lock_word.h \
+ mirror/class.h \
+ oat.h \
+ object_callbacks.h \
+ quick/inline_method_analyser.h \
+ thread.h \
+ thread_state.h \
+ verifier/method_verifier.h
LIBART_CFLAGS :=
ifeq ($(ART_USE_PORTABLE_COMPILER),true)
diff --git a/runtime/arch/arm/entrypoints_init_arm.cc b/runtime/arch/arm/entrypoints_init_arm.cc
index cf68c65dbd..8c6afd66bd 100644
--- a/runtime/arch/arm/entrypoints_init_arm.cc
+++ b/runtime/arch/arm/entrypoints_init_arm.cc
@@ -26,11 +26,11 @@ namespace art {
// Interpreter entrypoints.
extern "C" void artInterpreterToInterpreterBridge(Thread* self, MethodHelper& mh,
- const DexFile::CodeItem* code_item,
- ShadowFrame* shadow_frame, JValue* result);
+ const DexFile::CodeItem* code_item,
+ ShadowFrame* shadow_frame, JValue* result);
extern "C" void artInterpreterToCompiledCodeBridge(Thread* self, MethodHelper& mh,
- const DexFile::CodeItem* code_item,
- ShadowFrame* shadow_frame, JValue* result);
+ const DexFile::CodeItem* code_item,
+ ShadowFrame* shadow_frame, JValue* result);
// Portable entrypoints.
extern "C" void art_portable_resolution_trampoline(mirror::ArtMethod*);
diff --git a/runtime/arch/stub_test.cc b/runtime/arch/stub_test.cc
index ce8faea709..25f9a5a251 100644
--- a/runtime/arch/stub_test.cc
+++ b/runtime/arch/stub_test.cc
@@ -14,13 +14,14 @@
* limitations under the License.
*/
+#include <cstdio>
+
#include "common_runtime_test.h"
#include "mirror/art_field-inl.h"
#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
#include "mirror/string-inl.h"
-
-#include <cstdio>
+#include "scoped_thread_state_change.h"
namespace art {
@@ -45,7 +46,7 @@ class StubTest : public CommonRuntimeTest {
}
}
- void SetUpRuntimeOptions(Runtime::Options *options) OVERRIDE {
+ void SetUpRuntimeOptions(RuntimeOptions *options) OVERRIDE {
// Use a smaller heap
for (std::pair<std::string, const void*>& pair : *options) {
if (pair.first.find("-Xmx") == 0) {
diff --git a/runtime/barrier_test.cc b/runtime/barrier_test.cc
index 086ef440a3..de348dc79d 100644
--- a/runtime/barrier_test.cc
+++ b/runtime/barrier_test.cc
@@ -22,6 +22,7 @@
#include "common_runtime_test.h"
#include "mirror/object_array-inl.h"
#include "thread_pool.h"
+#include "thread-inl.h"
namespace art {
class CheckWaitTask : public Task {
diff --git a/runtime/base/mutex_test.cc b/runtime/base/mutex_test.cc
index ee0b1beba9..289d3ef8c1 100644
--- a/runtime/base/mutex_test.cc
+++ b/runtime/base/mutex_test.cc
@@ -17,6 +17,7 @@
#include "mutex.h"
#include "common_runtime_test.h"
+#include "thread-inl.h"
namespace art {
diff --git a/runtime/base/scoped_flock_test.cc b/runtime/base/scoped_flock_test.cc
index 8fa181ab6b..1fa7a12d17 100644
--- a/runtime/base/scoped_flock_test.cc
+++ b/runtime/base/scoped_flock_test.cc
@@ -15,9 +15,8 @@
*/
#include "scoped_flock.h"
-#include "common_runtime_test.h"
-#include "gtest/gtest.h"
+#include "common_runtime_test.h"
namespace art {
diff --git a/runtime/check_jni.cc b/runtime/check_jni.cc
index fefb907422..9ad8a07d3c 100644
--- a/runtime/check_jni.cc
+++ b/runtime/check_jni.cc
@@ -23,6 +23,7 @@
#include "class_linker.h"
#include "class_linker-inl.h"
#include "dex_file-inl.h"
+#include "field_helper.h"
#include "gc/space/space.h"
#include "mirror/art_field-inl.h"
#include "mirror/art_method-inl.h"
@@ -31,7 +32,6 @@
#include "mirror/object_array-inl.h"
#include "mirror/string-inl.h"
#include "mirror/throwable.h"
-#include "object_utils.h"
#include "runtime.h"
#include "scoped_thread_state_change.h"
#include "thread.h"
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index a40a2e4cd2..25eb3a342d 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -24,7 +24,6 @@
#include "mirror/dex_cache-inl.h"
#include "mirror/iftable.h"
#include "mirror/object_array.h"
-#include "object_utils.h"
#include "handle_scope-inl.h"
namespace art {
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 1436810f36..2c11f8b89c 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -42,8 +42,10 @@
#include "intern_table.h"
#include "interpreter/interpreter.h"
#include "leb128.h"
+#include "method_helper.h"
#include "oat.h"
#include "oat_file.h"
+#include "object_lock.h"
#include "mirror/art_field-inl.h"
#include "mirror/art_method-inl.h"
#include "mirror/class.h"
@@ -54,9 +56,9 @@
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/proxy.h"
+#include "mirror/reference-inl.h"
#include "mirror/stack_trace_element.h"
#include "mirror/string-inl.h"
-#include "object_utils.h"
#include "os.h"
#include "runtime.h"
#include "entrypoints/entrypoint_utils.h"
@@ -257,6 +259,13 @@ void ClassLinker::InitFromCompiler(const std::vector<const DexFile*>& boot_class
java_lang_String->SetObjectSize(mirror::String::InstanceSize());
java_lang_String->SetStatus(mirror::Class::kStatusResolved, self);
+ // Setup Reference.
+ Handle<mirror::Class> java_lang_ref_Reference(hs.NewHandle(
+ AllocClass(self, java_lang_Class.Get(), mirror::Reference::ClassSize())));
+ mirror::Reference::SetClass(java_lang_ref_Reference.Get());
+ java_lang_ref_Reference->SetObjectSize(mirror::Reference::InstanceSize());
+ java_lang_ref_Reference->SetStatus(mirror::Class::kStatusResolved, self);
+
// Create storage for root classes, save away our work so far (requires descriptors).
class_roots_ = mirror::ObjectArray<mirror::Class>::Alloc(self, object_array_class.Get(),
kClassRootsMax);
@@ -267,6 +276,7 @@ void ClassLinker::InitFromCompiler(const std::vector<const DexFile*>& boot_class
SetClassRoot(kObjectArrayClass, object_array_class.Get());
SetClassRoot(kCharArrayClass, char_array_class.Get());
SetClassRoot(kJavaLangString, java_lang_String.Get());
+ SetClassRoot(kJavaLangRefReference, java_lang_ref_Reference.Get());
// Setup the primitive type classes.
SetClassRoot(kPrimitiveBoolean, CreatePrimitiveClass(self, Primitive::kPrimBoolean));
@@ -461,8 +471,12 @@ void ClassLinker::InitFromCompiler(const std::vector<const DexFile*>& boot_class
SetClassRoot(kJavaLangReflectProxy, java_lang_reflect_Proxy);
// java.lang.ref classes need to be specially flagged, but otherwise are normal classes
- mirror::Class* java_lang_ref_Reference = FindSystemClass(self, "Ljava/lang/ref/Reference;");
- SetClassRoot(kJavaLangRefReference, java_lang_ref_Reference);
+ // finish initializing Reference class
+ java_lang_ref_Reference->SetStatus(mirror::Class::kStatusNotReady, self);
+ mirror::Class* Reference_class = FindSystemClass(self, "Ljava/lang/ref/Reference;");
+ CHECK_EQ(java_lang_ref_Reference.Get(), Reference_class);
+ CHECK_EQ(java_lang_ref_Reference->GetObjectSize(), mirror::Reference::InstanceSize());
+ CHECK_EQ(java_lang_ref_Reference->GetClassSize(), mirror::Reference::ClassSize());
mirror::Class* java_lang_ref_FinalizerReference =
FindSystemClass(self, "Ljava/lang/ref/FinalizerReference;");
java_lang_ref_FinalizerReference->SetAccessFlags(
@@ -811,9 +825,20 @@ bool ClassLinker::OpenDexFilesFromOat(const char* dex_location, const char* oat_
}
} else {
// TODO: What to lock here?
+ bool obsolete_file_cleanup_failed;
open_oat_file.reset(FindOatFileContainingDexFileFromDexLocation(dex_location,
dex_location_checksum_pointer,
- kRuntimeISA, error_msgs));
+ kRuntimeISA, error_msgs,
+ &obsolete_file_cleanup_failed));
+ // There's no point in going forward and eventually try to regenerate the
+ // file if we couldn't remove the obsolete one. Mostly likely we will fail
+ // with the same error when trying to write the new file.
+ // In case the clean up failure is due to permission issues it's *mandatory*
+ // to stop to avoid regenerating under the wrong user.
+ // TODO: should we maybe do this only when we get permission issues? (i.e. EACCESS).
+ if (obsolete_file_cleanup_failed) {
+ return false;
+ }
}
needs_registering = true;
}
@@ -1071,7 +1096,9 @@ const OatFile* ClassLinker::FindOatFileContainingDexFileFromDexLocation(
const char* dex_location,
const uint32_t* const dex_location_checksum,
InstructionSet isa,
- std::vector<std::string>* error_msgs) {
+ std::vector<std::string>* error_msgs,
+ bool* obsolete_file_cleanup_failed) {
+ *obsolete_file_cleanup_failed = false;
// Look for an existing file next to dex. for example, for
// /foo/bar/baz.jar, look for /foo/bar/<isa>/baz.odex.
std::string odex_filename(DexFilenameToOdexFilename(dex_location, isa));
@@ -1098,9 +1125,18 @@ const OatFile* ClassLinker::FindOatFileContainingDexFileFromDexLocation(
if (oat_file != nullptr) {
return oat_file;
}
+
if (!open_failed && TEMP_FAILURE_RETRY(unlink(cache_location.c_str())) != 0) {
- PLOG(FATAL) << "Failed to remove obsolete oat file from " << cache_location;
+ std::string error_msg = StringPrintf("Failed to remove obsolete file from %s when searching"
+ "for dex file %s: %s",
+ cache_location.c_str(), dex_location, strerror(errno));
+ error_msgs->push_back(error_msg);
+ VLOG(class_linker) << error_msg;
+ // Let the caller know that we couldn't remove the obsolete file.
+ // This is a good indication that further writes may fail as well.
+ *obsolete_file_cleanup_failed = true;
}
+
std::string compound_msg = StringPrintf("Failed to open oat file from %s (error '%s') or %s "
"(error '%s').", odex_filename.c_str(), error_msg.c_str(),
cache_location.c_str(), cache_error_msg.c_str());
@@ -1231,6 +1267,7 @@ void ClassLinker::InitFromImage() {
array_iftable_ = GetClassRoot(kObjectArrayClass)->GetIfTable();
DCHECK(array_iftable_ == GetClassRoot(kBooleanArrayClass)->GetIfTable());
// String class root was set above
+ mirror::Reference::SetClass(GetClassRoot(kJavaLangRefReference));
mirror::ArtField::SetClass(GetClassRoot(kJavaLangReflectArtField));
mirror::BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass));
mirror::ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass));
@@ -1354,6 +1391,7 @@ void ClassLinker::VisitClassesWithoutClassesLock(ClassVisitor* visitor, void* ar
ClassLinker::~ClassLinker() {
mirror::Class::ResetClass();
mirror::String::ResetClass();
+ mirror::Reference::ResetClass();
mirror::ArtField::ResetClass();
mirror::ArtMethod::ResetClass();
mirror::BooleanArray::ResetArrayClass();
@@ -1600,6 +1638,8 @@ mirror::Class* ClassLinker::DefineClass(const char* descriptor,
klass.Assign(GetClassRoot(kJavaLangClass));
} else if (strcmp(descriptor, "Ljava/lang/String;") == 0) {
klass.Assign(GetClassRoot(kJavaLangString));
+ } else if (strcmp(descriptor, "Ljava/lang/ref/Reference;") == 0) {
+ klass.Assign(GetClassRoot(kJavaLangRefReference));
} else if (strcmp(descriptor, "Ljava/lang/DexCache;") == 0) {
klass.Assign(GetClassRoot(kJavaLangDexCache));
} else if (strcmp(descriptor, "Ljava/lang/reflect/ArtField;") == 0) {
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index d9b3d2541c..64bffc9bf3 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -571,7 +571,8 @@ class ClassLinker {
const OatFile* FindOatFileContainingDexFileFromDexLocation(const char* location,
const uint32_t* const location_checksum,
InstructionSet isa,
- std::vector<std::string>* error_msgs)
+ std::vector<std::string>* error_msgs,
+ bool* obsolete_file_cleanup_failed)
LOCKS_EXCLUDED(dex_lock_, Locks::mutator_lock_);
// Find a verify an oat file with the given dex file. Will return nullptr when the oat file
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 7b5a5026df..21fe0067ed 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -23,6 +23,7 @@
#include "common_runtime_test.h"
#include "dex_file.h"
#include "entrypoints/entrypoint_utils-inl.h"
+#include "field_helper.h"
#include "gc/heap.h"
#include "mirror/art_field-inl.h"
#include "mirror/art_method.h"
@@ -36,6 +37,8 @@
#include "mirror/stack_trace_element.h"
#include "mirror/string-inl.h"
#include "handle_scope-inl.h"
+#include "scoped_thread_state_change.h"
+#include "thread-inl.h"
namespace art {
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index 0ed8b63b4d..f47f13d4b5 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -14,8 +14,31 @@
* limitations under the License.
*/
+#include "common_runtime_test.h"
+
+#include <dirent.h>
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <ScopedLocalRef.h>
+
+#include "../../external/icu/icu4c/source/common/unicode/uvernum.h"
#include "base/logging.h"
+#include "base/stl_util.h"
+#include "base/stringprintf.h"
+#include "base/unix_file/fd_file.h"
+#include "class_linker.h"
+#include "compiler_callbacks.h"
+#include "dex_file.h"
+#include "gc/heap.h"
#include "gtest/gtest.h"
+#include "jni_internal.h"
+#include "mirror/class_loader.h"
+#include "noop_compiler_callbacks.h"
+#include "os.h"
+#include "runtime-inl.h"
+#include "scoped_thread_state_change.h"
+#include "thread.h"
+#include "well_known_classes.h"
int main(int argc, char **argv) {
art::InitLogging(argv);
@@ -23,3 +46,293 @@ int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
+
+namespace art {
+
+ScratchFile::ScratchFile() {
+ // ANDROID_DATA needs to be set
+ CHECK_NE(static_cast<char*>(nullptr), getenv("ANDROID_DATA")) <<
+ "Are you subclassing RuntimeTest?";
+ filename_ = getenv("ANDROID_DATA");
+ filename_ += "/TmpFile-XXXXXX";
+ int fd = mkstemp(&filename_[0]);
+ CHECK_NE(-1, fd);
+ file_.reset(new File(fd, GetFilename()));
+}
+
+ScratchFile::ScratchFile(const ScratchFile& other, const char* suffix) {
+ filename_ = other.GetFilename();
+ filename_ += suffix;
+ int fd = open(filename_.c_str(), O_RDWR | O_CREAT, 0666);
+ CHECK_NE(-1, fd);
+ file_.reset(new File(fd, GetFilename()));
+}
+
+ScratchFile::ScratchFile(File* file) {
+ CHECK(file != NULL);
+ filename_ = file->GetPath();
+ file_.reset(file);
+}
+
+ScratchFile::~ScratchFile() {
+ Unlink();
+}
+
+int ScratchFile::GetFd() const {
+ return file_->Fd();
+}
+
+void ScratchFile::Unlink() {
+ if (!OS::FileExists(filename_.c_str())) {
+ return;
+ }
+ int unlink_result = unlink(filename_.c_str());
+ CHECK_EQ(0, unlink_result);
+}
+
+CommonRuntimeTest::CommonRuntimeTest() {}
+CommonRuntimeTest::~CommonRuntimeTest() {}
+
+void CommonRuntimeTest::SetEnvironmentVariables(std::string& android_data) {
+ if (IsHost()) {
+ // $ANDROID_ROOT is set on the device, but not necessarily on the host.
+ // But it needs to be set so that icu4c can find its locale data.
+ const char* android_root_from_env = getenv("ANDROID_ROOT");
+ if (android_root_from_env == nullptr) {
+ // Use ANDROID_HOST_OUT for ANDROID_ROOT if it is set.
+ const char* android_host_out = getenv("ANDROID_HOST_OUT");
+ if (android_host_out != nullptr) {
+ setenv("ANDROID_ROOT", android_host_out, 1);
+ } else {
+ // Build it from ANDROID_BUILD_TOP or cwd
+ std::string root;
+ const char* android_build_top = getenv("ANDROID_BUILD_TOP");
+ if (android_build_top != nullptr) {
+ root += android_build_top;
+ } else {
+ // Not set by build server, so default to current directory
+ char* cwd = getcwd(nullptr, 0);
+ setenv("ANDROID_BUILD_TOP", cwd, 1);
+ root += cwd;
+ free(cwd);
+ }
+#if defined(__linux__)
+ root += "/out/host/linux-x86";
+#elif defined(__APPLE__)
+ root += "/out/host/darwin-x86";
+#else
+#error unsupported OS
+#endif
+ setenv("ANDROID_ROOT", root.c_str(), 1);
+ }
+ }
+ setenv("LD_LIBRARY_PATH", ":", 0); // Required by java.lang.System.<clinit>.
+
+ // Not set by build server, so default
+ if (getenv("ANDROID_HOST_OUT") == nullptr) {
+ setenv("ANDROID_HOST_OUT", getenv("ANDROID_ROOT"), 1);
+ }
+ }
+
+ // On target, Cannot use /mnt/sdcard because it is mounted noexec, so use subdir of dalvik-cache
+ android_data = (IsHost() ? "/tmp/art-data-XXXXXX" : "/data/dalvik-cache/art-data-XXXXXX");
+ if (mkdtemp(&android_data[0]) == nullptr) {
+ PLOG(FATAL) << "mkdtemp(\"" << &android_data[0] << "\") failed";
+ }
+ setenv("ANDROID_DATA", android_data.c_str(), 1);
+}
+
+const DexFile* CommonRuntimeTest::LoadExpectSingleDexFile(const char* location) {
+ std::vector<const DexFile*> dex_files;
+ std::string error_msg;
+ if (!DexFile::Open(location, location, &error_msg, &dex_files)) {
+ LOG(FATAL) << "Could not open .dex file '" << location << "': " << error_msg << "\n";
+ return nullptr;
+ } else {
+ CHECK_EQ(1U, dex_files.size()) << "Expected only one dex file in " << location;
+ return dex_files[0];
+ }
+}
+
+void CommonRuntimeTest::SetUp() {
+ SetEnvironmentVariables(android_data_);
+ dalvik_cache_.append(android_data_.c_str());
+ dalvik_cache_.append("/dalvik-cache");
+ int mkdir_result = mkdir(dalvik_cache_.c_str(), 0700);
+ ASSERT_EQ(mkdir_result, 0);
+
+ std::string error_msg;
+ java_lang_dex_file_ = LoadExpectSingleDexFile(GetLibCoreDexFileName().c_str());
+ boot_class_path_.push_back(java_lang_dex_file_);
+
+ std::string min_heap_string(StringPrintf("-Xms%zdm", gc::Heap::kDefaultInitialSize / MB));
+ std::string max_heap_string(StringPrintf("-Xmx%zdm", gc::Heap::kDefaultMaximumSize / MB));
+
+ callbacks_.reset(new NoopCompilerCallbacks());
+
+ RuntimeOptions options;
+ options.push_back(std::make_pair("bootclasspath", &boot_class_path_));
+ options.push_back(std::make_pair("-Xcheck:jni", nullptr));
+ options.push_back(std::make_pair(min_heap_string.c_str(), nullptr));
+ options.push_back(std::make_pair(max_heap_string.c_str(), nullptr));
+ options.push_back(std::make_pair("compilercallbacks", callbacks_.get()));
+ SetUpRuntimeOptions(&options);
+ if (!Runtime::Create(options, false)) {
+ LOG(FATAL) << "Failed to create runtime";
+ return;
+ }
+ runtime_.reset(Runtime::Current());
+ class_linker_ = runtime_->GetClassLinker();
+ class_linker_->FixupDexCaches(runtime_->GetResolutionMethod());
+ class_linker_->RunRootClinits();
+
+ // Runtime::Create acquired the mutator_lock_ that is normally given away when we
+ // Runtime::Start, give it away now and then switch to a more managable ScopedObjectAccess.
+ Thread::Current()->TransitionFromRunnableToSuspended(kNative);
+
+ // We're back in native, take the opportunity to initialize well known classes.
+ WellKnownClasses::Init(Thread::Current()->GetJniEnv());
+
+ // Create the heap thread pool so that the GC runs in parallel for tests. Normally, the thread
+ // pool is created by the runtime.
+ runtime_->GetHeap()->CreateThreadPool();
+ runtime_->GetHeap()->VerifyHeap(); // Check for heap corruption before the test
+}
+
+void CommonRuntimeTest::TearDown() {
+ const char* android_data = getenv("ANDROID_DATA");
+ ASSERT_TRUE(android_data != nullptr);
+ DIR* dir = opendir(dalvik_cache_.c_str());
+ ASSERT_TRUE(dir != nullptr);
+ dirent* e;
+ while ((e = readdir(dir)) != nullptr) {
+ if ((strcmp(e->d_name, ".") == 0) || (strcmp(e->d_name, "..") == 0)) {
+ continue;
+ }
+ std::string filename(dalvik_cache_);
+ filename.push_back('/');
+ filename.append(e->d_name);
+ int unlink_result = unlink(filename.c_str());
+ ASSERT_EQ(0, unlink_result);
+ }
+ closedir(dir);
+ int rmdir_cache_result = rmdir(dalvik_cache_.c_str());
+ ASSERT_EQ(0, rmdir_cache_result);
+ int rmdir_data_result = rmdir(android_data_.c_str());
+ ASSERT_EQ(0, rmdir_data_result);
+
+ // icu4c has a fixed 10-element array "gCommonICUDataArray".
+ // If we run > 10 tests, we fill that array and u_setCommonData fails.
+ // There's a function to clear the array, but it's not public...
+ typedef void (*IcuCleanupFn)();
+ void* sym = dlsym(RTLD_DEFAULT, "u_cleanup_" U_ICU_VERSION_SHORT);
+ CHECK(sym != nullptr) << dlerror();
+ IcuCleanupFn icu_cleanup_fn = reinterpret_cast<IcuCleanupFn>(sym);
+ (*icu_cleanup_fn)();
+
+ STLDeleteElements(&opened_dex_files_);
+
+ Runtime::Current()->GetHeap()->VerifyHeap(); // Check for heap corruption after the test
+}
+
+std::string CommonRuntimeTest::GetLibCoreDexFileName() {
+ return GetDexFileName("core-libart");
+}
+
+std::string CommonRuntimeTest::GetDexFileName(const std::string& jar_prefix) {
+ if (IsHost()) {
+ const char* host_dir = getenv("ANDROID_HOST_OUT");
+ CHECK(host_dir != nullptr);
+ return StringPrintf("%s/framework/%s-hostdex.jar", host_dir, jar_prefix.c_str());
+ }
+ return StringPrintf("%s/framework/%s.jar", GetAndroidRoot(), jar_prefix.c_str());
+}
+
+std::string CommonRuntimeTest::GetTestAndroidRoot() {
+ if (IsHost()) {
+ const char* host_dir = getenv("ANDROID_HOST_OUT");
+ CHECK(host_dir != nullptr);
+ return host_dir;
+ }
+ return GetAndroidRoot();
+}
+
+std::vector<const DexFile*> CommonRuntimeTest::OpenTestDexFiles(const char* name) {
+ CHECK(name != nullptr);
+ std::string filename;
+ if (IsHost()) {
+ filename += getenv("ANDROID_HOST_OUT");
+ filename += "/framework/";
+ } else {
+ filename += "/data/nativetest/art/";
+ }
+ filename += "art-gtest-";
+ filename += name;
+ filename += ".jar";
+ std::string error_msg;
+ std::vector<const DexFile*> dex_files;
+ bool success = DexFile::Open(filename.c_str(), filename.c_str(), &error_msg, &dex_files);
+ CHECK(success) << "Failed to open '" << filename << "': " << error_msg;
+ for (const DexFile* dex_file : dex_files) {
+ CHECK_EQ(PROT_READ, dex_file->GetPermissions());
+ CHECK(dex_file->IsReadOnly());
+ }
+ opened_dex_files_.insert(opened_dex_files_.end(), dex_files.begin(), dex_files.end());
+ return dex_files;
+}
+
+const DexFile* CommonRuntimeTest::OpenTestDexFile(const char* name) {
+ std::vector<const DexFile*> vector = OpenTestDexFiles(name);
+ EXPECT_EQ(1U, vector.size());
+ return vector[0];
+}
+
+jobject CommonRuntimeTest::LoadDex(const char* dex_name) {
+ std::vector<const DexFile*> dex_files = OpenTestDexFiles(dex_name);
+ CHECK_NE(0U, dex_files.size());
+ for (const DexFile* dex_file : dex_files) {
+ class_linker_->RegisterDexFile(*dex_file);
+ }
+ ScopedObjectAccessUnchecked soa(Thread::Current());
+ ScopedLocalRef<jobject> class_loader_local(soa.Env(),
+ soa.Env()->AllocObject(WellKnownClasses::dalvik_system_PathClassLoader));
+ jobject class_loader = soa.Env()->NewGlobalRef(class_loader_local.get());
+ soa.Self()->SetClassLoaderOverride(soa.Decode<mirror::ClassLoader*>(class_loader_local.get()));
+ Runtime::Current()->SetCompileTimeClassPath(class_loader, dex_files);
+ return class_loader;
+}
+
+CheckJniAbortCatcher::CheckJniAbortCatcher() : vm_(Runtime::Current()->GetJavaVM()) {
+ vm_->check_jni_abort_hook = Hook;
+ vm_->check_jni_abort_hook_data = &actual_;
+}
+
+CheckJniAbortCatcher::~CheckJniAbortCatcher() {
+ vm_->check_jni_abort_hook = nullptr;
+ vm_->check_jni_abort_hook_data = nullptr;
+ EXPECT_TRUE(actual_.empty()) << actual_;
+}
+
+void CheckJniAbortCatcher::Check(const char* expected_text) {
+ EXPECT_TRUE(actual_.find(expected_text) != std::string::npos) << "\n"
+ << "Expected to find: " << expected_text << "\n"
+ << "In the output : " << actual_;
+ actual_.clear();
+}
+
+void CheckJniAbortCatcher::Hook(void* data, const std::string& reason) {
+ // We use += because when we're hooking the aborts like this, multiple problems can be found.
+ *reinterpret_cast<std::string*>(data) += reason;
+}
+
+} // namespace art
+
+namespace std {
+
+template <typename T>
+std::ostream& operator<<(std::ostream& os, const std::vector<T>& rhs) {
+os << ::art::ToString(rhs);
+return os;
+}
+
+} // namespace std
diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h
index ac6d44b950..d0450317a3 100644
--- a/runtime/common_runtime_test.h
+++ b/runtime/common_runtime_test.h
@@ -17,73 +17,33 @@
#ifndef ART_RUNTIME_COMMON_RUNTIME_TEST_H_
#define ART_RUNTIME_COMMON_RUNTIME_TEST_H_
-#include <dirent.h>
-#include <dlfcn.h>
-#include <stdlib.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <fstream>
-#include <memory>
-
-#include "../../external/icu/icu4c/source/common/unicode/uvernum.h"
-#include "base/macros.h"
-#include "base/stl_util.h"
-#include "base/stringprintf.h"
-#include "base/unix_file/fd_file.h"
-#include "class_linker.h"
-#include "dex_file-inl.h"
-#include "entrypoints/entrypoint_utils.h"
-#include "gc/heap.h"
-#include "gtest/gtest.h"
-#include "instruction_set.h"
-#include "interpreter/interpreter.h"
-#include "mirror/class_loader.h"
-#include "noop_compiler_callbacks.h"
-#include "oat_file.h"
-#include "object_utils.h"
+#include <gtest/gtest.h>
+#include <jni.h>
+
+#include <string>
+
+#include "base/mutex.h"
+#include "globals.h"
#include "os.h"
-#include "runtime.h"
-#include "scoped_thread_state_change.h"
-#include "ScopedLocalRef.h"
-#include "thread.h"
-#include "utils.h"
-#include "verifier/method_verifier.h"
-#include "verifier/method_verifier-inl.h"
-#include "well_known_classes.h"
namespace art {
+class ClassLinker;
+class CompilerCallbacks;
+class DexFile;
+class JavaVMExt;
+class Runtime;
+typedef std::vector<std::pair<std::string, const void*>> RuntimeOptions;
+
class ScratchFile {
public:
- ScratchFile() {
- // ANDROID_DATA needs to be set
- CHECK_NE(static_cast<char*>(nullptr), getenv("ANDROID_DATA")) <<
- "Are you subclassing RuntimeTest?";
- filename_ = getenv("ANDROID_DATA");
- filename_ += "/TmpFile-XXXXXX";
- int fd = mkstemp(&filename_[0]);
- CHECK_NE(-1, fd);
- file_.reset(new File(fd, GetFilename()));
- }
+ ScratchFile();
- ScratchFile(const ScratchFile& other, const char* suffix) {
- filename_ = other.GetFilename();
- filename_ += suffix;
- int fd = open(filename_.c_str(), O_RDWR | O_CREAT, 0666);
- CHECK_NE(-1, fd);
- file_.reset(new File(fd, GetFilename()));
- }
+ ScratchFile(const ScratchFile& other, const char* suffix);
- explicit ScratchFile(File* file) {
- CHECK(file != NULL);
- filename_ = file->GetPath();
- file_.reset(file);
- }
+ explicit ScratchFile(File* file);
- ~ScratchFile() {
- Unlink();
- }
+ ~ScratchFile();
const std::string& GetFilename() const {
return filename_;
@@ -93,17 +53,9 @@ class ScratchFile {
return file_.get();
}
- int GetFd() const {
- return file_->Fd();
- }
+ int GetFd() const;
- void Unlink() {
- if (!OS::FileExists(filename_.c_str())) {
- return;
- }
- int unlink_result = unlink(filename_.c_str());
- CHECK_EQ(0, unlink_result);
- }
+ void Unlink();
private:
std::string filename_;
@@ -112,222 +64,37 @@ class ScratchFile {
class CommonRuntimeTest : public testing::Test {
public:
- static void SetEnvironmentVariables(std::string& android_data) {
- if (IsHost()) {
- // $ANDROID_ROOT is set on the device, but not necessarily on the host.
- // But it needs to be set so that icu4c can find its locale data.
- const char* android_root_from_env = getenv("ANDROID_ROOT");
- if (android_root_from_env == nullptr) {
- // Use ANDROID_HOST_OUT for ANDROID_ROOT if it is set.
- const char* android_host_out = getenv("ANDROID_HOST_OUT");
- if (android_host_out != nullptr) {
- setenv("ANDROID_ROOT", android_host_out, 1);
- } else {
- // Build it from ANDROID_BUILD_TOP or cwd
- std::string root;
- const char* android_build_top = getenv("ANDROID_BUILD_TOP");
- if (android_build_top != nullptr) {
- root += android_build_top;
- } else {
- // Not set by build server, so default to current directory
- char* cwd = getcwd(nullptr, 0);
- setenv("ANDROID_BUILD_TOP", cwd, 1);
- root += cwd;
- free(cwd);
- }
-#if defined(__linux__)
- root += "/out/host/linux-x86";
-#elif defined(__APPLE__)
- root += "/out/host/darwin-x86";
-#else
-#error unsupported OS
-#endif
- setenv("ANDROID_ROOT", root.c_str(), 1);
- }
- }
- setenv("LD_LIBRARY_PATH", ":", 0); // Required by java.lang.System.<clinit>.
-
- // Not set by build server, so default
- if (getenv("ANDROID_HOST_OUT") == nullptr) {
- setenv("ANDROID_HOST_OUT", getenv("ANDROID_ROOT"), 1);
- }
- }
-
- // On target, Cannot use /mnt/sdcard because it is mounted noexec, so use subdir of dalvik-cache
- android_data = (IsHost() ? "/tmp/art-data-XXXXXX" : "/data/dalvik-cache/art-data-XXXXXX");
- if (mkdtemp(&android_data[0]) == nullptr) {
- PLOG(FATAL) << "mkdtemp(\"" << &android_data[0] << "\") failed";
- }
- setenv("ANDROID_DATA", android_data.c_str(), 1);
- }
+ static void SetEnvironmentVariables(std::string& android_data);
+
+ CommonRuntimeTest();
+ ~CommonRuntimeTest();
protected:
static bool IsHost() {
return !kIsTargetBuild;
}
- const DexFile* LoadExpectSingleDexFile(const char* location) {
- std::vector<const DexFile*> dex_files;
- std::string error_msg;
- if (!DexFile::Open(location, location, &error_msg, &dex_files)) {
- LOG(FATAL) << "Could not open .dex file '" << location << "': " << error_msg << "\n";
- return nullptr;
- } else {
- CHECK_EQ(1U, dex_files.size()) << "Expected only one dex file in " << location;
- return dex_files[0];
- }
- }
+ const DexFile* LoadExpectSingleDexFile(const char* location);
- virtual void SetUp() {
- SetEnvironmentVariables(android_data_);
- dalvik_cache_.append(android_data_.c_str());
- dalvik_cache_.append("/dalvik-cache");
- int mkdir_result = mkdir(dalvik_cache_.c_str(), 0700);
- ASSERT_EQ(mkdir_result, 0);
-
- std::string error_msg;
- java_lang_dex_file_ = LoadExpectSingleDexFile(GetLibCoreDexFileName().c_str());
- boot_class_path_.push_back(java_lang_dex_file_);
-
- std::string min_heap_string(StringPrintf("-Xms%zdm", gc::Heap::kDefaultInitialSize / MB));
- std::string max_heap_string(StringPrintf("-Xmx%zdm", gc::Heap::kDefaultMaximumSize / MB));
-
- Runtime::Options options;
- options.push_back(std::make_pair("bootclasspath", &boot_class_path_));
- options.push_back(std::make_pair("-Xcheck:jni", nullptr));
- options.push_back(std::make_pair(min_heap_string.c_str(), nullptr));
- options.push_back(std::make_pair(max_heap_string.c_str(), nullptr));
- options.push_back(std::make_pair("compilercallbacks", &callbacks_));
- SetUpRuntimeOptions(&options);
- if (!Runtime::Create(options, false)) {
- LOG(FATAL) << "Failed to create runtime";
- return;
- }
- runtime_.reset(Runtime::Current());
- class_linker_ = runtime_->GetClassLinker();
- class_linker_->FixupDexCaches(runtime_->GetResolutionMethod());
- class_linker_->RunRootClinits();
-
- // Runtime::Create acquired the mutator_lock_ that is normally given away when we
- // Runtime::Start, give it away now and then switch to a more managable ScopedObjectAccess.
- Thread::Current()->TransitionFromRunnableToSuspended(kNative);
-
- // We're back in native, take the opportunity to initialize well known classes.
- WellKnownClasses::Init(Thread::Current()->GetJniEnv());
-
- // Create the heap thread pool so that the GC runs in parallel for tests. Normally, the thread
- // pool is created by the runtime.
- runtime_->GetHeap()->CreateThreadPool();
- runtime_->GetHeap()->VerifyHeap(); // Check for heap corruption before the test
- }
+ virtual void SetUp();
// Allow subclases such as CommonCompilerTest to add extra options.
- virtual void SetUpRuntimeOptions(Runtime::Options *options) {}
-
- virtual void TearDown() {
- const char* android_data = getenv("ANDROID_DATA");
- ASSERT_TRUE(android_data != nullptr);
- DIR* dir = opendir(dalvik_cache_.c_str());
- ASSERT_TRUE(dir != nullptr);
- dirent* e;
- while ((e = readdir(dir)) != nullptr) {
- if ((strcmp(e->d_name, ".") == 0) || (strcmp(e->d_name, "..") == 0)) {
- continue;
- }
- std::string filename(dalvik_cache_);
- filename.push_back('/');
- filename.append(e->d_name);
- int unlink_result = unlink(filename.c_str());
- ASSERT_EQ(0, unlink_result);
- }
- closedir(dir);
- int rmdir_cache_result = rmdir(dalvik_cache_.c_str());
- ASSERT_EQ(0, rmdir_cache_result);
- int rmdir_data_result = rmdir(android_data_.c_str());
- ASSERT_EQ(0, rmdir_data_result);
-
- // icu4c has a fixed 10-element array "gCommonICUDataArray".
- // If we run > 10 tests, we fill that array and u_setCommonData fails.
- // There's a function to clear the array, but it's not public...
- typedef void (*IcuCleanupFn)();
- void* sym = dlsym(RTLD_DEFAULT, "u_cleanup_" U_ICU_VERSION_SHORT);
- CHECK(sym != nullptr) << dlerror();
- IcuCleanupFn icu_cleanup_fn = reinterpret_cast<IcuCleanupFn>(sym);
- (*icu_cleanup_fn)();
-
- STLDeleteElements(&opened_dex_files_);
-
- Runtime::Current()->GetHeap()->VerifyHeap(); // Check for heap corruption after the test
- }
+ virtual void SetUpRuntimeOptions(RuntimeOptions* options) {}
- std::string GetLibCoreDexFileName() {
- return GetDexFileName("core-libart");
- }
+ virtual void TearDown();
- std::string GetDexFileName(const std::string& jar_prefix) {
- if (IsHost()) {
- const char* host_dir = getenv("ANDROID_HOST_OUT");
- CHECK(host_dir != nullptr);
- return StringPrintf("%s/framework/%s-hostdex.jar", host_dir, jar_prefix.c_str());
- }
- return StringPrintf("%s/framework/%s.jar", GetAndroidRoot(), jar_prefix.c_str());
- }
+ std::string GetLibCoreDexFileName();
- std::string GetTestAndroidRoot() {
- if (IsHost()) {
- const char* host_dir = getenv("ANDROID_HOST_OUT");
- CHECK(host_dir != nullptr);
- return host_dir;
- }
- return GetAndroidRoot();
- }
+ std::string GetDexFileName(const std::string& jar_prefix);
+
+ std::string GetTestAndroidRoot();
std::vector<const DexFile*> OpenTestDexFiles(const char* name)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- CHECK(name != nullptr);
- std::string filename;
- if (IsHost()) {
- filename += getenv("ANDROID_HOST_OUT");
- filename += "/framework/";
- } else {
- filename += "/data/nativetest/art/";
- }
- filename += "art-gtest-";
- filename += name;
- filename += ".jar";
- std::string error_msg;
- std::vector<const DexFile*> dex_files;
- bool success = DexFile::Open(filename.c_str(), filename.c_str(), &error_msg, &dex_files);
- CHECK(success) << "Failed to open '" << filename << "': " << error_msg;
- for (const DexFile* dex_file : dex_files) {
- CHECK_EQ(PROT_READ, dex_file->GetPermissions());
- CHECK(dex_file->IsReadOnly());
- }
- opened_dex_files_.insert(opened_dex_files_.end(), dex_files.begin(), dex_files.end());
- return dex_files;
- }
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- const DexFile* OpenTestDexFile(const char* name)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- std::vector<const DexFile*> vector = OpenTestDexFiles(name);
- EXPECT_EQ(1U, vector.size());
- return vector[0];
- }
+ const DexFile* OpenTestDexFile(const char* name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- jobject LoadDex(const char* dex_name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- std::vector<const DexFile*> dex_files = OpenTestDexFiles(dex_name);
- CHECK_NE(0U, dex_files.size());
- for (const DexFile* dex_file : dex_files) {
- class_linker_->RegisterDexFile(*dex_file);
- }
- ScopedObjectAccessUnchecked soa(Thread::Current());
- ScopedLocalRef<jobject> class_loader_local(soa.Env(),
- soa.Env()->AllocObject(WellKnownClasses::dalvik_system_PathClassLoader));
- jobject class_loader = soa.Env()->NewGlobalRef(class_loader_local.get());
- soa.Self()->SetClassLoaderOverride(soa.Decode<mirror::ClassLoader*>(class_loader_local.get()));
- Runtime::Current()->SetCompileTimeClassPath(class_loader, dex_files);
- return class_loader;
- }
+ jobject LoadDex(const char* dex_name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
std::string android_data_;
std::string dalvik_cache_;
@@ -338,7 +105,7 @@ class CommonRuntimeTest : public testing::Test {
ClassLinker* class_linker_;
private:
- NoopCompilerCallbacks callbacks_;
+ std::unique_ptr<CompilerCallbacks> callbacks_;
std::vector<const DexFile*> opened_dex_files_;
};
@@ -346,29 +113,14 @@ class CommonRuntimeTest : public testing::Test {
// rather than aborting, so be careful!
class CheckJniAbortCatcher {
public:
- CheckJniAbortCatcher() : vm_(Runtime::Current()->GetJavaVM()) {
- vm_->check_jni_abort_hook = Hook;
- vm_->check_jni_abort_hook_data = &actual_;
- }
+ CheckJniAbortCatcher();
- ~CheckJniAbortCatcher() {
- vm_->check_jni_abort_hook = nullptr;
- vm_->check_jni_abort_hook_data = nullptr;
- EXPECT_TRUE(actual_.empty()) << actual_;
- }
+ ~CheckJniAbortCatcher();
- void Check(const char* expected_text) {
- EXPECT_TRUE(actual_.find(expected_text) != std::string::npos) << "\n"
- << "Expected to find: " << expected_text << "\n"
- << "In the output : " << actual_;
- actual_.clear();
- }
+ void Check(const char* expected_text);
private:
- static void Hook(void* data, const std::string& reason) {
- // We use += because when we're hooking the aborts like this, multiple problems can be found.
- *reinterpret_cast<std::string*>(data) += reason;
- }
+ static void Hook(void* data, const std::string& reason);
JavaVMExt* vm_;
std::string actual_;
@@ -399,10 +151,7 @@ namespace std {
// TODO: isn't gtest supposed to be able to print STL types for itself?
template <typename T>
-std::ostream& operator<<(std::ostream& os, const std::vector<T>& rhs) {
- os << ::art::ToString(rhs);
- return os;
-}
+std::ostream& operator<<(std::ostream& os, const std::vector<T>& rhs);
} // namespace std
diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc
index 8de3068dca..970593d119 100644
--- a/runtime/common_throws.cc
+++ b/runtime/common_throws.cc
@@ -16,6 +16,8 @@
#include "common_throws.h"
+#include <sstream>
+
#include "base/logging.h"
#include "class_linker-inl.h"
#include "dex_file-inl.h"
@@ -25,12 +27,9 @@
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
-#include "object_utils.h"
#include "thread.h"
#include "verifier/method_verifier.h"
-#include <sstream>
-
namespace art {
static void AddReferrerLocation(std::ostream& os, mirror::Class* referrer)
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index c95be0154a..4cf4c099b2 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -25,11 +25,13 @@
#include "class_linker-inl.h"
#include "dex_file-inl.h"
#include "dex_instruction.h"
+#include "field_helper.h"
#include "gc/accounting/card_table-inl.h"
#include "gc/space/large_object_space.h"
#include "gc/space/space-inl.h"
#include "handle_scope.h"
#include "jdwp/object_registry.h"
+#include "method_helper.h"
#include "mirror/art_field-inl.h"
#include "mirror/art_method-inl.h"
#include "mirror/class.h"
@@ -39,7 +41,6 @@
#include "mirror/object_array-inl.h"
#include "mirror/string-inl.h"
#include "mirror/throwable.h"
-#include "object_utils.h"
#include "quick/inline_method_analyser.h"
#include "reflection.h"
#include "safe_map.h"
diff --git a/runtime/dex_file_test.cc b/runtime/dex_file_test.cc
index c1e00fcb0a..284aa89d99 100644
--- a/runtime/dex_file_test.cc
+++ b/runtime/dex_file_test.cc
@@ -18,7 +18,12 @@
#include <memory>
+#include "base/stl_util.h"
+#include "base/unix_file/fd_file.h"
#include "common_runtime_test.h"
+#include "os.h"
+#include "scoped_thread_state_change.h"
+#include "thread-inl.h"
namespace art {
diff --git a/runtime/dex_file_verifier_test.cc b/runtime/dex_file_verifier_test.cc
index 93faeaee7c..d475d426ff 100644
--- a/runtime/dex_file_verifier_test.cc
+++ b/runtime/dex_file_verifier_test.cc
@@ -16,11 +16,15 @@
#include "dex_file_verifier.h"
-#include <memory>
+#include "sys/mman.h"
#include "zlib.h"
+#include <memory>
-#include "common_runtime_test.h"
+#include "base/unix_file/fd_file.h"
#include "base/macros.h"
+#include "common_runtime_test.h"
+#include "scoped_thread_state_change.h"
+#include "thread-inl.h"
namespace art {
diff --git a/runtime/dex_method_iterator_test.cc b/runtime/dex_method_iterator_test.cc
index 0d00cc3134..b8f180b46f 100644
--- a/runtime/dex_method_iterator_test.cc
+++ b/runtime/dex_method_iterator_test.cc
@@ -16,7 +16,10 @@
#include "dex_method_iterator.h"
+#include "base/stl_util.h"
#include "common_runtime_test.h"
+#include "scoped_thread_state_change.h"
+#include "thread-inl.h"
namespace art {
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index 482ad47d5d..542e1a9e2e 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -25,12 +25,12 @@
#include "indirect_reference_table.h"
#include "invoke_type.h"
#include "jni_internal.h"
+#include "method_helper.h"
#include "mirror/art_method.h"
#include "mirror/array.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
#include "mirror/throwable.h"
-#include "object_utils.h"
#include "handle_scope-inl.h"
#include "thread.h"
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index d029df2c7f..d063dfb425 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -24,7 +24,6 @@
#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
-#include "object_utils.h"
#include "mirror/object_array-inl.h"
#include "reflection.h"
#include "scoped_thread_state_change.h"
diff --git a/runtime/entrypoints/interpreter/interpreter_entrypoints.cc b/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
index 329c175986..64faf76213 100644
--- a/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
+++ b/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
@@ -18,7 +18,6 @@
#include "interpreter/interpreter.h"
#include "mirror/art_method-inl.h"
#include "mirror/object-inl.h"
-#include "object_utils.h"
#include "reflection.h"
#include "runtime.h"
#include "stack.h"
diff --git a/runtime/entrypoints/jni/jni_entrypoints.cc b/runtime/entrypoints/jni/jni_entrypoints.cc
index bae4023c1d..edb3b723ef 100644
--- a/runtime/entrypoints/jni/jni_entrypoints.cc
+++ b/runtime/entrypoints/jni/jni_entrypoints.cc
@@ -18,7 +18,6 @@
#include "entrypoints/entrypoint_utils.h"
#include "mirror/art_method-inl.h"
#include "mirror/object-inl.h"
-#include "object_utils.h"
#include "scoped_thread_state_change.h"
#include "thread.h"
diff --git a/runtime/entrypoints/portable/portable_throw_entrypoints.cc b/runtime/entrypoints/portable/portable_throw_entrypoints.cc
index 9e36a05841..be6231cae5 100644
--- a/runtime/entrypoints/portable/portable_throw_entrypoints.cc
+++ b/runtime/entrypoints/portable/portable_throw_entrypoints.cc
@@ -80,7 +80,6 @@ extern "C" int32_t art_portable_find_catch_block_from_code(mirror::ArtMethod* cu
}
mirror::Class* exception_type = exception->GetClass();
StackHandleScope<1> hs(self);
- MethodHelper mh(hs.NewHandle(current_method));
const DexFile::CodeItem* code_item = current_method->GetCodeItem();
DCHECK_LT(ti_offset, code_item->tries_size_);
const DexFile::TryItem* try_item = DexFile::GetTryItems(*code_item, ti_offset);
@@ -98,7 +97,8 @@ extern "C" int32_t art_portable_find_catch_block_from_code(mirror::ArtMethod* cu
break;
}
// Does this catch exception type apply?
- mirror::Class* iter_exception_type = mh.GetDexCacheResolvedType(iter_type_idx);
+ mirror::Class* iter_exception_type =
+ current_method->GetDexCacheResolvedTypes()->Get(iter_type_idx);
if (UNLIKELY(iter_exception_type == NULL)) {
// TODO: check, the verifier (class linker?) should take care of resolving all exception
// classes early.
diff --git a/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc b/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc
index 7ee869b67f..9f75b0fcf0 100644
--- a/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc
@@ -22,7 +22,6 @@
#include "interpreter/interpreter.h"
#include "mirror/art_method-inl.h"
#include "mirror/object-inl.h"
-#include "object_utils.h"
#include "scoped_thread_state_change.h"
namespace art {
diff --git a/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc b/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
index 47fb9d66f8..f9f62c2721 100644
--- a/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
@@ -21,7 +21,6 @@
#include "mirror/class-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/object-inl.h"
-#include "object_utils.h"
#include "stack.h"
#include "thread.h"
#include "verifier/method_verifier.h"
diff --git a/runtime/entrypoints/quick/quick_jni_entrypoints.cc b/runtime/entrypoints/quick/quick_jni_entrypoints.cc
index 30e86097a6..653724989a 100644
--- a/runtime/entrypoints/quick/quick_jni_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_jni_entrypoints.cc
@@ -21,7 +21,6 @@
#include "mirror/object.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
-#include "object_utils.h"
#include "scoped_thread_state_change.h"
#include "thread.h"
#include "verify_object-inl.h"
diff --git a/runtime/entrypoints/quick/quick_throw_entrypoints.cc b/runtime/entrypoints/quick/quick_throw_entrypoints.cc
index 4dcb1c8dc6..879010e36e 100644
--- a/runtime/entrypoints/quick/quick_throw_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_throw_entrypoints.cc
@@ -18,7 +18,6 @@
#include "common_throws.h"
#include "entrypoints/entrypoint_utils-inl.h"
#include "mirror/object-inl.h"
-#include "object_utils.h"
#include "thread.h"
#include "well_known_classes.h"
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index f7cb1263f2..338bd06f7c 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -27,7 +27,6 @@
#include "mirror/dex_cache-inl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
-#include "object_utils.h"
#include "runtime.h"
#include "scoped_thread_state_change.h"
diff --git a/runtime/entrypoints_order_test.cc b/runtime/entrypoints_order_test.cc
index c572baf937..79c68a24e0 100644
--- a/runtime/entrypoints_order_test.cc
+++ b/runtime/entrypoints_order_test.cc
@@ -121,7 +121,7 @@ class EntrypointsOrderTest : public CommonRuntimeTest {
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, thread_local_end, thread_local_objects, kPointerSize);
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, thread_local_objects, rosalloc_runs, kPointerSize);
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, rosalloc_runs, thread_local_alloc_stack_top,
- kPointerSize * gc::allocator::RosAlloc::kNumThreadLocalSizeBrackets);
+ kPointerSize * kNumRosAllocThreadLocalSizeBrackets);
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, thread_local_alloc_stack_top, thread_local_alloc_stack_end,
kPointerSize);
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, thread_local_alloc_stack_end, held_mutexes, kPointerSize);
diff --git a/runtime/fault_handler.cc b/runtime/fault_handler.cc
index 3112bc0a28..b4355cad5c 100644
--- a/runtime/fault_handler.cc
+++ b/runtime/fault_handler.cc
@@ -15,23 +15,16 @@
*/
#include "fault_handler.h"
+
#include <sys/mman.h>
#include <sys/ucontext.h>
-#include "base/macros.h"
-#include "globals.h"
-#include "base/logging.h"
-#include "base/hex_dump.h"
-#include "thread.h"
-#include "mirror/art_method-inl.h"
-#include "mirror/class-inl.h"
-#include "mirror/dex_cache.h"
-#include "mirror/object_array-inl.h"
-#include "mirror/object-inl.h"
-#include "object_utils.h"
-#include "scoped_thread_state_change.h"
+
+#include "mirror/art_method.h"
+#include "mirror/class.h"
#ifdef HAVE_ANDROID_OS
#include "sigchain.h"
#endif
+#include "thread-inl.h"
#include "verify_object-inl.h"
namespace art {
diff --git a/runtime/field_helper.cc b/runtime/field_helper.cc
new file mode 100644
index 0000000000..40daa6db3f
--- /dev/null
+++ b/runtime/field_helper.cc
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "field_helper.h"
+
+#include "class_linker-inl.h"
+#include "dex_file.h"
+#include "mirror/dex_cache.h"
+#include "runtime.h"
+#include "thread-inl.h"
+
+namespace art {
+
+mirror::Class* FieldHelper::GetType(bool resolve) {
+ uint32_t field_index = field_->GetDexFieldIndex();
+ if (UNLIKELY(field_->GetDeclaringClass()->IsProxyClass())) {
+ return Runtime::Current()->GetClassLinker()->FindSystemClass(Thread::Current(),
+ field_->GetTypeDescriptor());
+ }
+ const DexFile* dex_file = field_->GetDexFile();
+ const DexFile::FieldId& field_id = dex_file->GetFieldId(field_index);
+ mirror::Class* type = field_->GetDexCache()->GetResolvedType(field_id.type_idx_);
+ if (resolve && (type == nullptr)) {
+ type = Runtime::Current()->GetClassLinker()->ResolveType(field_id.type_idx_, field_.Get());
+ CHECK(type != nullptr || Thread::Current()->IsExceptionPending());
+ }
+ return type;
+}
+
+const char* FieldHelper::GetDeclaringClassDescriptor() {
+ uint32_t field_index = field_->GetDexFieldIndex();
+ if (UNLIKELY(field_->GetDeclaringClass()->IsProxyClass())) {
+ DCHECK(field_->IsStatic());
+ DCHECK_LT(field_index, 2U);
+ // 0 == Class[] interfaces; 1 == Class[][] throws;
+ declaring_class_descriptor_ = field_->GetDeclaringClass()->GetDescriptor();
+ return declaring_class_descriptor_.c_str();
+ }
+ const DexFile* dex_file = field_->GetDexFile();
+ const DexFile::FieldId& field_id = dex_file->GetFieldId(field_index);
+ return dex_file->GetFieldDeclaringClassDescriptor(field_id);
+}
+
+} // namespace art
diff --git a/runtime/field_helper.h b/runtime/field_helper.h
new file mode 100644
index 0000000000..5eae55e09c
--- /dev/null
+++ b/runtime/field_helper.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_FIELD_HELPER_H_
+#define ART_RUNTIME_FIELD_HELPER_H_
+
+#include "base/macros.h"
+#include "handle.h"
+#include "mirror/art_field.h"
+
+namespace art {
+
+class FieldHelper {
+ public:
+ explicit FieldHelper(Handle<mirror::ArtField> f) : field_(f) {}
+
+ void ChangeField(mirror::ArtField* new_f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(new_f != nullptr);
+ field_.Assign(new_f);
+ }
+
+ mirror::ArtField* GetField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return field_.Get();
+ }
+
+ mirror::Class* GetType(bool resolve = true) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ // The returned const char* is only guaranteed to be valid for the lifetime of the FieldHelper.
+ // If you need it longer, copy it into a std::string.
+ const char* GetDeclaringClassDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ private:
+ Handle<mirror::ArtField> field_;
+ std::string declaring_class_descriptor_;
+
+ DISALLOW_COPY_AND_ASSIGN(FieldHelper);
+};
+
+} // namespace art
+
+#endif // ART_RUNTIME_FIELD_HELPER_H_
diff --git a/runtime/gc/accounting/space_bitmap-inl.h b/runtime/gc/accounting/space_bitmap-inl.h
index 1e9556a076..fc4213e8c6 100644
--- a/runtime/gc/accounting/space_bitmap-inl.h
+++ b/runtime/gc/accounting/space_bitmap-inl.h
@@ -23,14 +23,6 @@
#include "atomic.h"
#include "base/logging.h"
-#include "dex_file-inl.h"
-#include "heap_bitmap.h"
-#include "mirror/art_field-inl.h"
-#include "mirror/class-inl.h"
-#include "mirror/object-inl.h"
-#include "mirror/object_array-inl.h"
-#include "object_utils.h"
-#include "space_bitmap-inl.h"
#include "utils.h"
namespace art {
diff --git a/runtime/gc/accounting/space_bitmap.cc b/runtime/gc/accounting/space_bitmap.cc
index c0aa43ea41..39d1f9e132 100644
--- a/runtime/gc/accounting/space_bitmap.cc
+++ b/runtime/gc/accounting/space_bitmap.cc
@@ -16,6 +16,13 @@
#include "space_bitmap-inl.h"
+#include "base/stringprintf.h"
+#include "mem_map.h"
+#include "mirror/object-inl.h"
+#include "mirror/class.h"
+#include "mirror/art_field.h"
+#include "mirror/object_array.h"
+
namespace art {
namespace gc {
namespace accounting {
@@ -46,6 +53,9 @@ SpaceBitmap<kAlignment>::SpaceBitmap(const std::string& name, MemMap* mem_map, u
}
template<size_t kAlignment>
+SpaceBitmap<kAlignment>::~SpaceBitmap() {}
+
+template<size_t kAlignment>
SpaceBitmap<kAlignment>* SpaceBitmap<kAlignment>::Create(
const std::string& name, byte* heap_begin, size_t heap_capacity) {
// Round up since heap_capacity is not necessarily a multiple of kAlignment * kBitsPerWord.
diff --git a/runtime/gc/accounting/space_bitmap.h b/runtime/gc/accounting/space_bitmap.h
index 6d1ba870db..a3073bda07 100644
--- a/runtime/gc/accounting/space_bitmap.h
+++ b/runtime/gc/accounting/space_bitmap.h
@@ -54,8 +54,7 @@ class SpaceBitmap {
static SpaceBitmap* CreateFromMemMap(const std::string& name, MemMap* mem_map,
byte* heap_begin, size_t heap_capacity);
- ~SpaceBitmap() {
- }
+ ~SpaceBitmap();
// <offset> is the difference from .base to a pointer address.
// <index> is the index of .bits that contains the bit representing
diff --git a/runtime/gc/allocator/rosalloc.h b/runtime/gc/allocator/rosalloc.h
index c0ab151d6c..b2a5a3c96c 100644
--- a/runtime/gc/allocator/rosalloc.h
+++ b/runtime/gc/allocator/rosalloc.h
@@ -30,6 +30,7 @@
#include "base/logging.h"
#include "globals.h"
#include "mem_map.h"
+#include "thread.h"
#include "utils.h"
namespace art {
@@ -261,7 +262,7 @@ class RosAlloc {
// The magic number for free pages.
static const byte kMagicNumFree = 43;
// The number of size brackets. Sync this with the length of Thread::rosalloc_runs_.
- static const size_t kNumOfSizeBrackets = 34;
+ static const size_t kNumOfSizeBrackets = kNumRosAllocThreadLocalSizeBrackets;
// The number of smaller size brackets that are 16 bytes apart.
static const size_t kNumOfQuantumSizeBrackets = 32;
// The sizes (the slot sizes, in bytes) of the size brackets.
diff --git a/runtime/gc/collector/immune_region.h b/runtime/gc/collector/immune_region.h
index 0c0a89b253..277525e831 100644
--- a/runtime/gc/collector/immune_region.h
+++ b/runtime/gc/collector/immune_region.h
@@ -19,7 +19,6 @@
#include "base/macros.h"
#include "base/mutex.h"
-#include "gc/space/space-inl.h"
namespace art {
namespace mirror {
diff --git a/runtime/gc/collector/mark_compact.h b/runtime/gc/collector/mark_compact.h
index 25cfe0fbfd..bb85fa0a81 100644
--- a/runtime/gc/collector/mark_compact.h
+++ b/runtime/gc/collector/mark_compact.h
@@ -49,6 +49,7 @@ namespace accounting {
} // namespace accounting
namespace space {
+ class BumpPointerSpace;
class ContinuousMemMapAllocSpace;
class ContinuousSpace;
} // namespace space
diff --git a/runtime/gc/collector/semi_space.h b/runtime/gc/collector/semi_space.h
index bff08478e0..7f6d1dc01f 100644
--- a/runtime/gc/collector/semi_space.h
+++ b/runtime/gc/collector/semi_space.h
@@ -25,6 +25,7 @@
#include "garbage_collector.h"
#include "gc/accounting/heap_bitmap.h"
#include "immune_region.h"
+#include "mirror/object_reference.h"
#include "object_callbacks.h"
#include "offsets.h"
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 4ec9bc2f6a..292173da50 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -58,7 +58,6 @@
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/reference-inl.h"
-#include "object_utils.h"
#include "os.h"
#include "reflection.h"
#include "runtime.h"
diff --git a/runtime/gc/heap_test.cc b/runtime/gc/heap_test.cc
index 4176f4ad08..e6b5c75f4f 100644
--- a/runtime/gc/heap_test.cc
+++ b/runtime/gc/heap_test.cc
@@ -17,10 +17,11 @@
#include "common_runtime_test.h"
#include "gc/accounting/card_table-inl.h"
#include "gc/accounting/space_bitmap-inl.h"
+#include "handle_scope-inl.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
-#include "handle_scope-inl.h"
+#include "scoped_thread_state_change.h"
namespace art {
namespace gc {
diff --git a/runtime/gc/reference_processor-inl.h b/runtime/gc/reference_processor-inl.h
new file mode 100644
index 0000000000..f619a15f74
--- /dev/null
+++ b/runtime/gc/reference_processor-inl.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_GC_REFERENCE_PROCESSOR_INL_H_
+#define ART_RUNTIME_GC_REFERENCE_PROCESSOR_INL_H_
+
+#include "reference_processor.h"
+
+namespace art {
+namespace gc {
+
+inline bool ReferenceProcessor::SlowPathEnabled() {
+ return mirror::Reference::GetJavaLangRefReference()->GetSlowPathEnabled();
+}
+
+} // namespace gc
+} // namespace art
+
+#endif // ART_RUNTIME_GC_REFERENCE_PROCESSOR_INL_H_
diff --git a/runtime/gc/reference_processor.cc b/runtime/gc/reference_processor.cc
index e52bc1fd1e..d3641d196f 100644
--- a/runtime/gc/reference_processor.cc
+++ b/runtime/gc/reference_processor.cc
@@ -17,7 +17,9 @@
#include "reference_processor.h"
#include "mirror/object-inl.h"
+#include "mirror/reference.h"
#include "mirror/reference-inl.h"
+#include "reference_processor-inl.h"
#include "reflection.h"
#include "ScopedLocalRef.h"
#include "scoped_thread_state_change.h"
@@ -27,18 +29,17 @@ namespace art {
namespace gc {
ReferenceProcessor::ReferenceProcessor()
- : process_references_args_(nullptr, nullptr, nullptr), slow_path_enabled_(false),
+ : process_references_args_(nullptr, nullptr, nullptr),
preserving_references_(false), lock_("reference processor lock", kReferenceProcessorLock),
condition_("reference processor condition", lock_) {
}
void ReferenceProcessor::EnableSlowPath() {
- Locks::mutator_lock_->AssertExclusiveHeld(Thread::Current());
- slow_path_enabled_ = true;
+ mirror::Reference::GetJavaLangRefReference()->SetSlowPath(true);
}
void ReferenceProcessor::DisableSlowPath(Thread* self) {
- slow_path_enabled_ = false;
+ mirror::Reference::GetJavaLangRefReference()->SetSlowPath(false);
condition_.Broadcast(self);
}
@@ -46,11 +47,11 @@ mirror::Object* ReferenceProcessor::GetReferent(Thread* self, mirror::Reference*
mirror::Object* const referent = reference->GetReferent();
// If the referent is null then it is already cleared, we can just return null since there is no
// scenario where it becomes non-null during the reference processing phase.
- if (LIKELY(!slow_path_enabled_) || referent == nullptr) {
+ if (UNLIKELY(!SlowPathEnabled()) || referent == nullptr) {
return referent;
}
MutexLock mu(self, lock_);
- while (slow_path_enabled_) {
+ while (SlowPathEnabled()) {
mirror::HeapReference<mirror::Object>* const referent_addr =
reference->GetReferentReferenceAddr();
// If the referent became cleared, return it. Don't need barrier since thread roots can't get
@@ -117,7 +118,7 @@ void ReferenceProcessor::ProcessReferences(bool concurrent, TimingLogger* timing
process_references_args_.is_marked_callback_ = is_marked_callback;
process_references_args_.mark_callback_ = mark_object_callback;
process_references_args_.arg_ = arg;
- CHECK_EQ(slow_path_enabled_, concurrent) << "Slow path must be enabled iff concurrent";
+ CHECK_EQ(SlowPathEnabled(), concurrent) << "Slow path must be enabled iff concurrent";
}
// Unless required to clear soft references with white references, preserve some white referents.
if (!clear_soft_references) {
@@ -182,7 +183,7 @@ void ReferenceProcessor::DelayReferenceReferent(mirror::Class* klass, mirror::Re
void* arg) {
// klass can be the class of the old object if the visitor already updated the class of ref.
DCHECK(klass != nullptr);
- DCHECK(klass->IsReferenceClass());
+ DCHECK(klass->IsTypeOfReferenceClass());
mirror::HeapReference<mirror::Object>* referent = ref->GetReferentReferenceAddr();
if (referent->AsMirrorPtr() != nullptr && !is_marked_callback(referent, arg)) {
Thread* self = Thread::Current();
diff --git a/runtime/gc/reference_processor.h b/runtime/gc/reference_processor.h
index 2771ea809b..7274457a5d 100644
--- a/runtime/gc/reference_processor.h
+++ b/runtime/gc/reference_processor.h
@@ -49,6 +49,7 @@ class ReferenceProcessor {
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
LOCKS_EXCLUDED(lock_);
+ // The slow path bool is contained in the reference class object, can only be set once
// Only allow setting this with mutators suspended so that we can avoid using a lock in the
// GetReferent fast path as an optimization.
void EnableSlowPath() EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -60,7 +61,7 @@ class ReferenceProcessor {
IsHeapReferenceMarkedCallback* is_marked_callback, void* arg)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void UpdateRoots(IsMarkedCallback* callback, void* arg)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::heap_bitmap_lock_);
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::heap_bitmap_lock_);
private:
class ProcessReferencesArgs {
@@ -75,8 +76,10 @@ class ReferenceProcessor {
MarkObjectCallback* mark_callback_;
void* arg_;
};
+ bool SlowPathEnabled() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Called by ProcessReferences.
- void DisableSlowPath(Thread* self) EXCLUSIVE_LOCKS_REQUIRED(lock_);
+ void DisableSlowPath(Thread* self) EXCLUSIVE_LOCKS_REQUIRED(lock_)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// If we are preserving references it means that some dead objects may become live, we use start
// and stop preserving to block mutators using GetReferrent from getting access to these
// referents.
@@ -84,8 +87,6 @@ class ReferenceProcessor {
void StopPreservingReferences(Thread* self) LOCKS_EXCLUDED(lock_);
// Process args, used by the GetReferent to return referents which are already marked.
ProcessReferencesArgs process_references_args_ GUARDED_BY(lock_);
- // Boolean for whether or not we need to go slow path in GetReferent.
- volatile bool slow_path_enabled_;
// Boolean for whether or not we are preserving references (either soft references or finalizers).
// If this is true, then we cannot return a referent (see comment in GetReferent).
bool preserving_references_ GUARDED_BY(lock_);
diff --git a/runtime/gc/space/dlmalloc_space_base_test.cc b/runtime/gc/space/dlmalloc_space_base_test.cc
index 129eace199..02fc4a52e1 100644
--- a/runtime/gc/space/dlmalloc_space_base_test.cc
+++ b/runtime/gc/space/dlmalloc_space_base_test.cc
@@ -15,7 +15,9 @@
*/
#include "space_test.h"
+
#include "dlmalloc_space.h"
+#include "scoped_thread_state_change.h"
namespace art {
namespace gc {
diff --git a/runtime/gc/space/dlmalloc_space_random_test.cc b/runtime/gc/space/dlmalloc_space_random_test.cc
index c4f8baedfb..4b1a1b1cc0 100644
--- a/runtime/gc/space/dlmalloc_space_random_test.cc
+++ b/runtime/gc/space/dlmalloc_space_random_test.cc
@@ -15,6 +15,7 @@
*/
#include "space_test.h"
+
#include "dlmalloc_space.h"
namespace art {
diff --git a/runtime/gc/space/dlmalloc_space_static_test.cc b/runtime/gc/space/dlmalloc_space_static_test.cc
index edaa1988ab..d17d0a7d54 100644
--- a/runtime/gc/space/dlmalloc_space_static_test.cc
+++ b/runtime/gc/space/dlmalloc_space_static_test.cc
@@ -15,6 +15,7 @@
*/
#include "space_test.h"
+
#include "dlmalloc_space.h"
namespace art {
diff --git a/runtime/gc/space/space_test.h b/runtime/gc/space/space_test.h
index a2d4942c8d..02911557f3 100644
--- a/runtime/gc/space/space_test.h
+++ b/runtime/gc/space/space_test.h
@@ -17,8 +17,6 @@
#ifndef ART_RUNTIME_GC_SPACE_SPACE_TEST_H_
#define ART_RUNTIME_GC_SPACE_SPACE_TEST_H_
-#include "zygote_space.h"
-
#include <stdint.h>
#include <memory>
@@ -26,6 +24,8 @@
#include "globals.h"
#include "mirror/array-inl.h"
#include "mirror/object-inl.h"
+#include "scoped_thread_state_change.h"
+#include "zygote_space.h"
namespace art {
namespace gc {
diff --git a/runtime/globals.h b/runtime/globals.h
index 3a906f15f5..1d9f22c35e 100644
--- a/runtime/globals.h
+++ b/runtime/globals.h
@@ -105,6 +105,19 @@ static constexpr bool kUseBakerOrBrooksReadBarrier = kUseBakerReadBarrier || kUs
// If true, references within the heap are poisoned (negated).
static constexpr bool kPoisonHeapReferences = false;
+// Kinds of tracing clocks.
+enum TraceClockSource {
+ kTraceClockSourceThreadCpu,
+ kTraceClockSourceWall,
+ kTraceClockSourceDual, // Both wall and thread CPU clocks.
+};
+
+#if defined(HAVE_POSIX_CLOCKS)
+static constexpr TraceClockSource kDefaultTraceClockSource = kTraceClockSourceDual;
+#else
+static constexpr TraceClockSource kDefaultTraceClockSource = kTraceClockSourceWall;
+#endif
+
} // namespace art
#endif // ART_RUNTIME_GLOBALS_H_
diff --git a/runtime/handle.h b/runtime/handle.h
index 7e13601af9..f70faf40d0 100644
--- a/runtime/handle.h
+++ b/runtime/handle.h
@@ -28,29 +28,40 @@ class Thread;
template<class T> class Handle;
+// Handles are memory locations that contain GC roots. As the mirror::Object*s within a handle are
+// GC visible then the GC may move the references within them, something that couldn't be done with
+// a wrap pointer. Handles are generally allocated within HandleScopes. ConstHandle is a super-class
+// of Handle and doesn't support assignment operations.
template<class T>
class ConstHandle {
public:
ConstHandle() : reference_(nullptr) {
}
- ConstHandle(const ConstHandle<T>& handle) ALWAYS_INLINE : reference_(handle.reference_) {
+
+ ALWAYS_INLINE ConstHandle(const ConstHandle<T>& handle) : reference_(handle.reference_) {
}
- ConstHandle<T>& operator=(const ConstHandle<T>& handle) ALWAYS_INLINE {
+
+ ALWAYS_INLINE ConstHandle<T>& operator=(const ConstHandle<T>& handle) {
reference_ = handle.reference_;
return *this;
}
- explicit ConstHandle(StackReference<T>* reference) ALWAYS_INLINE : reference_(reference) {
+
+ ALWAYS_INLINE explicit ConstHandle(StackReference<T>* reference) : reference_(reference) {
}
- T& operator*() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE {
+
+ ALWAYS_INLINE T& operator*() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return *Get();
}
- T* operator->() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE {
+
+ ALWAYS_INLINE T* operator->() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return Get();
}
- T* Get() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE {
+
+ ALWAYS_INLINE T* Get() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return reference_->AsMirrorPtr();
}
- jobject ToJObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE {
+
+ ALWAYS_INLINE jobject ToJObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (UNLIKELY(reference_->AsMirrorPtr() == nullptr)) {
// Special case so that we work with NullHandles.
return nullptr;
@@ -73,8 +84,8 @@ class ConstHandle {
StackReference<T>* GetReference() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE {
return reference_;
}
- const StackReference<T>* GetReference() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
- ALWAYS_INLINE {
+ ALWAYS_INLINE const StackReference<T>* GetReference() const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return reference_;
}
@@ -86,47 +97,54 @@ class ConstHandle {
template<size_t kNumReferences> friend class StackHandleScope;
};
+// Handles that support assignment.
template<class T>
class Handle : public ConstHandle<T> {
public:
Handle() {
}
- Handle(const Handle<T>& handle) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE
+
+ ALWAYS_INLINE Handle(const Handle<T>& handle) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
: ConstHandle<T>(handle.reference_) {
}
- Handle<T>& operator=(const Handle<T>& handle) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
- ALWAYS_INLINE {
+
+ ALWAYS_INLINE Handle<T>& operator=(const Handle<T>& handle)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
ConstHandle<T>::operator=(handle);
return *this;
}
- explicit Handle(StackReference<T>* reference) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
- ALWAYS_INLINE : ConstHandle<T>(reference) {
+
+ ALWAYS_INLINE explicit Handle(StackReference<T>* reference)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : ConstHandle<T>(reference) {
}
- T* Assign(T* reference) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE {
+
+ ALWAYS_INLINE T* Assign(T* reference) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
StackReference<T>* ref = ConstHandle<T>::GetReference();
T* const old = ref->AsMirrorPtr();
ref->Assign(reference);
return old;
}
+ template<typename S>
+ explicit Handle(const Handle<S>& handle) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : ConstHandle<T>(handle) {
+ }
+
protected:
template<typename S>
explicit Handle(StackReference<S>* reference) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
: ConstHandle<T>(reference) {
}
- template<typename S>
- explicit Handle(const Handle<S>& handle) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
- : ConstHandle<T>(handle) {
- }
private:
friend class BuildGenericJniFrameVisitor;
- template<class S> friend class Handle;
friend class HandleScope;
template<class S> friend class HandleWrapper;
template<size_t kNumReferences> friend class StackHandleScope;
};
+// A special case of Handle that only holds references to null.
template<class T>
class NullHandle : public Handle<T> {
public:
diff --git a/runtime/handle_scope-inl.h b/runtime/handle_scope-inl.h
index 62c761475a..7bc811db87 100644
--- a/runtime/handle_scope-inl.h
+++ b/runtime/handle_scope-inl.h
@@ -17,7 +17,7 @@
#ifndef ART_RUNTIME_HANDLE_SCOPE_INL_H_
#define ART_RUNTIME_HANDLE_SCOPE_INL_H_
-#include "handle_scope-inl.h"
+#include "handle_scope.h"
#include "handle.h"
#include "thread.h"
diff --git a/runtime/handle_scope.h b/runtime/handle_scope.h
index 629e4ecf2f..42ef77927c 100644
--- a/runtime/handle_scope.h
+++ b/runtime/handle_scope.h
@@ -27,10 +27,12 @@ namespace art {
namespace mirror {
class Object;
}
+
class Thread;
-// HandleScopes can be allocated within the bridge frame between managed and native code backed by
-// stack storage or manually allocated in native.
+// HandleScopes are scoped objects containing a number of Handles. They are used to allocate
+// handles, for these handles (and the objects contained within them) to be visible/roots for the
+// GC. It is most common to stack allocate HandleScopes using StackHandleScope.
class PACKED(4) HandleScope {
public:
~HandleScope() {}
@@ -130,6 +132,7 @@ class PACKED(4) HandleScope {
private:
template<size_t kNumReferences> friend class StackHandleScope;
+
DISALLOW_COPY_AND_ASSIGN(HandleScope);
};
@@ -152,7 +155,7 @@ class HandleWrapper : public Handle<T> {
// Scoped handle storage of a fixed size that is usually stack allocated.
template<size_t kNumReferences>
-class PACKED(4) StackHandleScope : public HandleScope {
+class PACKED(4) StackHandleScope FINAL : public HandleScope {
public:
explicit StackHandleScope(Thread* self);
~StackHandleScope();
@@ -181,20 +184,29 @@ class PACKED(4) StackHandleScope : public HandleScope {
template<class T>
Handle<T> NewHandle(T* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
SetReference(pos_, object);
- return Handle<T>(GetHandle(pos_++));
+ Handle<T> h(GetHandle(pos_));
+ pos_++;
+ return h;
}
template<class T>
HandleWrapper<T> NewHandleWrapper(T** object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
SetReference(pos_, *object);
- Handle<T> h(GetHandle(pos_++));
+ Handle<T> h(GetHandle(pos_));
+ pos_++;
return HandleWrapper<T>(object, h);
}
private:
- // references_storage_ needs to be first so that it matches the address of references_.
+ // References_storage_ needs to be first so that it appears in the same location as
+ // HandleScope::references_.
StackReference<mirror::Object> references_storage_[kNumReferences];
+
+ // The thread that the stack handle scope is a linked list upon. The stack handle scope will
+ // push and pop itself from this thread.
Thread* const self_;
+
+ // Position new handles will be created.
size_t pos_;
template<size_t kNumRefs> friend class StackHandleScope;
diff --git a/runtime/hprof/hprof.cc b/runtime/hprof/hprof.cc
index 33339f8f6c..7e3b6bab26 100644
--- a/runtime/hprof/hprof.cc
+++ b/runtime/hprof/hprof.cc
@@ -52,7 +52,6 @@
#include "mirror/class.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
-#include "object_utils.h"
#include "os.h"
#include "safe_map.h"
#include "scoped_thread_state_change.h"
diff --git a/runtime/indirect_reference_table_test.cc b/runtime/indirect_reference_table_test.cc
index 449817add6..a33a981545 100644
--- a/runtime/indirect_reference_table_test.cc
+++ b/runtime/indirect_reference_table_test.cc
@@ -18,6 +18,7 @@
#include "common_runtime_test.h"
#include "mirror/object-inl.h"
+#include "scoped_thread_state_change.h"
namespace art {
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 05320ced6d..f4eaa61c1e 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -18,6 +18,7 @@
#include <sys/uio.h>
+#include "arch/context.h"
#include "atomic.h"
#include "base/unix_file/fd_file.h"
#include "class_linker.h"
@@ -34,7 +35,6 @@
#if !defined(ART_USE_PORTABLE_COMPILER)
#include "entrypoints/quick/quick_entrypoints.h"
#endif
-#include "object_utils.h"
#include "os.h"
#include "scoped_thread_state_change.h"
#include "thread.h"
diff --git a/runtime/intern_table_test.cc b/runtime/intern_table_test.cc
index 5995d9e5d3..d462e1444f 100644
--- a/runtime/intern_table_test.cc
+++ b/runtime/intern_table_test.cc
@@ -19,6 +19,8 @@
#include "common_runtime_test.h"
#include "mirror/object.h"
#include "handle_scope-inl.h"
+#include "mirror/string.h"
+#include "scoped_thread_state_change.h"
namespace art {
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index b552909498..b35da0cf1b 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -15,6 +15,8 @@
*/
#include "interpreter_common.h"
+
+#include "field_helper.h"
#include "mirror/array-inl.h"
namespace art {
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index db42eb06f1..1bcd27e2d4 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -30,6 +30,7 @@
#include "entrypoints/entrypoint_utils-inl.h"
#include "gc/accounting/card_table-inl.h"
#include "handle_scope-inl.h"
+#include "method_helper-inl.h"
#include "nth_caller_visitor.h"
#include "mirror/art_field-inl.h"
#include "mirror/art_method.h"
@@ -39,7 +40,6 @@
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/string-inl.h"
-#include "object_utils.h"
#include "ScopedLocalRef.h"
#include "scoped_thread_state_change.h"
#include "thread.h"
diff --git a/runtime/jdwp/object_registry.cc b/runtime/jdwp/object_registry.cc
index 29d3c8ab8e..ad18d8a2ce 100644
--- a/runtime/jdwp/object_registry.cc
+++ b/runtime/jdwp/object_registry.cc
@@ -16,6 +16,7 @@
#include "object_registry.h"
+#include "mirror/class.h"
#include "scoped_thread_state_change.h"
namespace art {
diff --git a/runtime/jdwp/object_registry.h b/runtime/jdwp/object_registry.h
index e1a687544a..f0314a382f 100644
--- a/runtime/jdwp/object_registry.h
+++ b/runtime/jdwp/object_registry.h
@@ -17,20 +17,21 @@
#ifndef ART_RUNTIME_JDWP_OBJECT_REGISTRY_H_
#define ART_RUNTIME_JDWP_OBJECT_REGISTRY_H_
+#include <jni.h>
#include <stdint.h>
#include <map>
#include "jdwp/jdwp.h"
-#include "mirror/art_field-inl.h"
-#include "mirror/class.h"
-#include "mirror/class-inl.h"
-#include "mirror/object-inl.h"
-#include "object_callbacks.h"
#include "safe_map.h"
namespace art {
+namespace mirror {
+ class Object;
+ class Class;
+} // namespace mirror
+
struct ObjectRegistryEntry {
// Is jni_reference a weak global or a regular global reference?
jobjectRefType jni_reference_type;
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index 845691d182..f9c7ec692c 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -41,7 +41,6 @@
#include "mirror/object_array-inl.h"
#include "mirror/string-inl.h"
#include "mirror/throwable.h"
-#include "object_utils.h"
#include "parsed_options.h"
#include "reflection.h"
#include "runtime.h"
@@ -3002,7 +3001,7 @@ extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
LOG(ERROR) << "Bad JNI version passed to CreateJavaVM: " << args->version;
return JNI_EVERSION;
}
- Runtime::Options options;
+ RuntimeOptions options;
for (int i = 0; i < args->nOptions; ++i) {
JavaVMOption* option = &args->options[i];
options.push_back(std::make_pair(std::string(option->optionString), option->extraInfo));
diff --git a/runtime/jni_internal_test.cc b/runtime/jni_internal_test.cc
index 8ef1cb6115..7c7e60c5ee 100644
--- a/runtime/jni_internal_test.cc
+++ b/runtime/jni_internal_test.cc
@@ -19,6 +19,7 @@
#include "common_compiler_test.h"
#include "mirror/art_method-inl.h"
#include "mirror/string-inl.h"
+#include "scoped_thread_state_change.h"
#include "ScopedLocalRef.h"
namespace art {
diff --git a/runtime/method_helper-inl.h b/runtime/method_helper-inl.h
new file mode 100644
index 0000000000..42a60896a0
--- /dev/null
+++ b/runtime/method_helper-inl.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_METHOD_HELPER_INL_H_
+#define ART_RUNTIME_METHOD_HELPER_INL_H_
+
+#include "method_helper.h"
+
+#include "runtime.h"
+
+namespace art {
+
+inline mirror::Class* MethodHelper::GetClassFromTypeIdx(uint16_t type_idx, bool resolve) {
+ mirror::ArtMethod* method = GetMethod();
+ mirror::Class* type = method->GetDexCacheResolvedTypes()->Get(type_idx);
+ if (type == nullptr && resolve) {
+ type = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
+ CHECK(type != nullptr || Thread::Current()->IsExceptionPending());
+ }
+ return type;
+}
+
+inline mirror::String* MethodHelper::ResolveString(uint32_t string_idx) {
+ mirror::ArtMethod* method = GetMethod();
+ mirror::String* s = method->GetDexCacheStrings()->Get(string_idx);
+ if (UNLIKELY(s == nullptr)) {
+ StackHandleScope<1> hs(Thread::Current());
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(method->GetDexCache()));
+ s = Runtime::Current()->GetClassLinker()->ResolveString(*method->GetDexFile(), string_idx,
+ dex_cache);
+ }
+ return s;
+}
+
+} // namespace art
+
+#endif // ART_RUNTIME_METHOD_HELPER_INL_H_
diff --git a/runtime/method_helper.cc b/runtime/method_helper.cc
new file mode 100644
index 0000000000..4b1b1daa9e
--- /dev/null
+++ b/runtime/method_helper.cc
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "method_helper.h"
+
+#include "class_linker.h"
+#include "dex_file-inl.h"
+#include "handle_scope-inl.h"
+#include "mirror/art_method-inl.h"
+#include "mirror/dex_cache.h"
+#include "runtime.h"
+
+namespace art {
+
+mirror::String* MethodHelper::GetNameAsString(Thread* self) {
+ const DexFile* dex_file = method_->GetDexFile();
+ mirror::ArtMethod* method = method_->GetInterfaceMethodIfProxy();
+ uint32_t dex_method_idx = method->GetDexMethodIndex();
+ const DexFile::MethodId& method_id = dex_file->GetMethodId(dex_method_idx);
+ StackHandleScope<1> hs(self);
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(method->GetDexCache()));
+ return Runtime::Current()->GetClassLinker()->ResolveString(*dex_file, method_id.name_idx_,
+ dex_cache);
+}
+
+bool MethodHelper::HasSameNameAndSignature(MethodHelper* other) {
+ const DexFile* dex_file = method_->GetDexFile();
+ const DexFile::MethodId& mid = dex_file->GetMethodId(GetMethod()->GetDexMethodIndex());
+ if (method_->GetDexCache() == other->method_->GetDexCache()) {
+ const DexFile::MethodId& other_mid =
+ dex_file->GetMethodId(other->GetMethod()->GetDexMethodIndex());
+ return mid.name_idx_ == other_mid.name_idx_ && mid.proto_idx_ == other_mid.proto_idx_;
+ }
+ const DexFile* other_dex_file = other->method_->GetDexFile();
+ const DexFile::MethodId& other_mid =
+ other_dex_file->GetMethodId(other->GetMethod()->GetDexMethodIndex());
+ if (!DexFileStringEquals(dex_file, mid.name_idx_, other_dex_file, other_mid.name_idx_)) {
+ return false; // Name mismatch.
+ }
+ return dex_file->GetMethodSignature(mid) == other_dex_file->GetMethodSignature(other_mid);
+}
+
+uint32_t MethodHelper::FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ mirror::ArtMethod* method = GetMethod();
+ const DexFile* dexfile = method->GetDexFile();
+ if (dexfile == &other_dexfile) {
+ return method->GetDexMethodIndex();
+ }
+ const DexFile::MethodId& mid = dexfile->GetMethodId(method->GetDexMethodIndex());
+ const char* mid_declaring_class_descriptor = dexfile->StringByTypeIdx(mid.class_idx_);
+ const DexFile::StringId* other_descriptor =
+ other_dexfile.FindStringId(mid_declaring_class_descriptor);
+ if (other_descriptor != nullptr) {
+ const DexFile::TypeId* other_type_id =
+ other_dexfile.FindTypeId(other_dexfile.GetIndexForStringId(*other_descriptor));
+ if (other_type_id != nullptr) {
+ const char* mid_name = dexfile->GetMethodName(mid);
+ const DexFile::StringId* other_name = other_dexfile.FindStringId(mid_name);
+ if (other_name != nullptr) {
+ uint16_t other_return_type_idx;
+ std::vector<uint16_t> other_param_type_idxs;
+ bool success = other_dexfile.CreateTypeList(
+ dexfile->GetMethodSignature(mid).ToString(), &other_return_type_idx,
+ &other_param_type_idxs);
+ if (success) {
+ const DexFile::ProtoId* other_sig =
+ other_dexfile.FindProtoId(other_return_type_idx, other_param_type_idxs);
+ if (other_sig != nullptr) {
+ const DexFile::MethodId* other_mid = other_dexfile.FindMethodId(
+ *other_type_id, *other_name, *other_sig);
+ if (other_mid != nullptr) {
+ return other_dexfile.GetIndexForMethodId(*other_mid);
+ }
+ }
+ }
+ }
+ }
+ }
+ return DexFile::kDexNoIndex;
+}
+
+uint32_t MethodHelper::FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile,
+ uint32_t name_and_signature_idx)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ mirror::ArtMethod* method = GetMethod();
+ const DexFile* dexfile = method->GetDexFile();
+ const uint32_t dex_method_idx = method->GetDexMethodIndex();
+ const DexFile::MethodId& mid = dexfile->GetMethodId(dex_method_idx);
+ const DexFile::MethodId& name_and_sig_mid = other_dexfile.GetMethodId(name_and_signature_idx);
+ DCHECK_STREQ(dexfile->GetMethodName(mid), other_dexfile.GetMethodName(name_and_sig_mid));
+ DCHECK_EQ(dexfile->GetMethodSignature(mid), other_dexfile.GetMethodSignature(name_and_sig_mid));
+ if (dexfile == &other_dexfile) {
+ return dex_method_idx;
+ }
+ const char* mid_declaring_class_descriptor = dexfile->StringByTypeIdx(mid.class_idx_);
+ const DexFile::StringId* other_descriptor =
+ other_dexfile.FindStringId(mid_declaring_class_descriptor);
+ if (other_descriptor != nullptr) {
+ const DexFile::TypeId* other_type_id =
+ other_dexfile.FindTypeId(other_dexfile.GetIndexForStringId(*other_descriptor));
+ if (other_type_id != nullptr) {
+ const DexFile::MethodId* other_mid = other_dexfile.FindMethodId(
+ *other_type_id, other_dexfile.GetStringId(name_and_sig_mid.name_idx_),
+ other_dexfile.GetProtoId(name_and_sig_mid.proto_idx_));
+ if (other_mid != nullptr) {
+ return other_dexfile.GetIndexForMethodId(*other_mid);
+ }
+ }
+ }
+ return DexFile::kDexNoIndex;
+}
+
+} // namespace art
diff --git a/runtime/method_helper.h b/runtime/method_helper.h
new file mode 100644
index 0000000000..012695e4d1
--- /dev/null
+++ b/runtime/method_helper.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_METHOD_HELPER_H_
+#define ART_RUNTIME_METHOD_HELPER_H_
+
+#include "base/macros.h"
+#include "handle.h"
+#include "mirror/art_method.h"
+#include "primitive.h"
+
+namespace art {
+
+class MethodHelper {
+ public:
+ explicit MethodHelper(Handle<mirror::ArtMethod> m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : method_(m), shorty_(nullptr), shorty_len_(0) {
+ SetMethod(m.Get());
+ }
+
+ void ChangeMethod(mirror::ArtMethod* new_m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(new_m != nullptr);
+ SetMethod(new_m);
+ shorty_ = nullptr;
+ }
+
+ mirror::ArtMethod* GetMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return method_->GetInterfaceMethodIfProxy();
+ }
+
+ mirror::String* GetNameAsString(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ const char* GetShorty() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ const char* result = shorty_;
+ if (result == nullptr) {
+ result = method_->GetShorty(&shorty_len_);
+ shorty_ = result;
+ }
+ return result;
+ }
+
+ uint32_t GetShortyLength() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ if (shorty_ == nullptr) {
+ GetShorty();
+ }
+ return shorty_len_;
+ }
+
+ // Counts the number of references in the parameter list of the corresponding method.
+ // Note: Thus does _not_ include "this" for non-static methods.
+ uint32_t GetNumberOfReferenceArgsWithoutReceiver() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ const char* shorty = GetShorty();
+ uint32_t refs = 0;
+ for (uint32_t i = 1; i < shorty_len_ ; ++i) {
+ if (shorty[i] == 'L') {
+ refs++;
+ }
+ }
+
+ return refs;
+ }
+
+ // May cause thread suspension due to GetClassFromTypeIdx calling ResolveType this caused a large
+ // number of bugs at call sites.
+ mirror::Class* GetReturnType(bool resolve = true) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ mirror::ArtMethod* method = GetMethod();
+ const DexFile* dex_file = method->GetDexFile();
+ const DexFile::MethodId& method_id = dex_file->GetMethodId(method->GetDexMethodIndex());
+ const DexFile::ProtoId& proto_id = dex_file->GetMethodPrototype(method_id);
+ uint16_t return_type_idx = proto_id.return_type_idx_;
+ return GetClassFromTypeIdx(return_type_idx, resolve);
+ }
+
+ size_t NumArgs() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ // "1 +" because the first in Args is the receiver.
+ // "- 1" because we don't count the return type.
+ return (method_->IsStatic() ? 0 : 1) + GetShortyLength() - 1;
+ }
+
+ // Get the primitive type associated with the given parameter.
+ Primitive::Type GetParamPrimitiveType(size_t param) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ CHECK_LT(param, NumArgs());
+ if (GetMethod()->IsStatic()) {
+ param++; // 0th argument must skip return value at start of the shorty
+ } else if (param == 0) {
+ return Primitive::kPrimNot;
+ }
+ return Primitive::GetType(GetShorty()[param]);
+ }
+
+ // Is the specified parameter a long or double, where parameter 0 is 'this' for instance methods.
+ bool IsParamALongOrDouble(size_t param) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ Primitive::Type type = GetParamPrimitiveType(param);
+ return type == Primitive::kPrimLong || type == Primitive::kPrimDouble;
+ }
+
+ // Is the specified parameter a reference, where parameter 0 is 'this' for instance methods.
+ bool IsParamAReference(size_t param) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetParamPrimitiveType(param) == Primitive::kPrimNot;
+ }
+
+ bool HasSameNameAndSignature(MethodHelper* other) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ bool HasSameSignatureWithDifferentClassLoaders(MethodHelper* other)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ if (UNLIKELY(GetReturnType() != other->GetReturnType())) {
+ return false;
+ }
+ const DexFile::TypeList* types = method_->GetParameterTypeList();
+ const DexFile::TypeList* other_types = other->method_->GetParameterTypeList();
+ if (types == nullptr) {
+ return (other_types == nullptr) || (other_types->Size() == 0);
+ } else if (UNLIKELY(other_types == nullptr)) {
+ return types->Size() == 0;
+ }
+ uint32_t num_types = types->Size();
+ if (UNLIKELY(num_types != other_types->Size())) {
+ return false;
+ }
+ for (uint32_t i = 0; i < num_types; ++i) {
+ mirror::Class* param_type = GetClassFromTypeIdx(types->GetTypeItem(i).type_idx_);
+ mirror::Class* other_param_type =
+ other->GetClassFromTypeIdx(other_types->GetTypeItem(i).type_idx_);
+ if (UNLIKELY(param_type != other_param_type)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ mirror::Class* GetClassFromTypeIdx(uint16_t type_idx, bool resolve = true)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ mirror::String* ResolveString(uint32_t string_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ uint32_t FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ // The name_and_signature_idx MUST point to a MethodId with the same name and signature in the
+ // other_dexfile, such as the method index used to resolve this method in the other_dexfile.
+ uint32_t FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile,
+ uint32_t name_and_signature_idx)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ private:
+ // Set the method_ field, for proxy methods looking up the interface method via the resolved
+ // methods table.
+ void SetMethod(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ method_.Assign(method);
+ }
+
+ Handle<mirror::ArtMethod> method_;
+ const char* shorty_;
+ uint32_t shorty_len_;
+
+ DISALLOW_COPY_AND_ASSIGN(MethodHelper);
+};
+
+} // namespace art
+
+#endif // ART_RUNTIME_METHOD_HELPER_H_
diff --git a/runtime/mirror/array.cc b/runtime/mirror/array.cc
index f7b573729b..63f9860278 100644
--- a/runtime/mirror/array.cc
+++ b/runtime/mirror/array.cc
@@ -25,7 +25,6 @@
#include "object-inl.h"
#include "object_array.h"
#include "object_array-inl.h"
-#include "object_utils.h"
#include "handle_scope-inl.h"
#include "thread.h"
#include "utils.h"
diff --git a/runtime/mirror/art_field-inl.h b/runtime/mirror/art_field-inl.h
index 90247edc76..00bed92cb3 100644
--- a/runtime/mirror/art_field-inl.h
+++ b/runtime/mirror/art_field-inl.h
@@ -20,10 +20,10 @@
#include "art_field.h"
#include "base/logging.h"
+#include "dex_cache.h"
#include "gc/accounting/card_table-inl.h"
#include "jvalue.h"
#include "object-inl.h"
-#include "object_utils.h"
#include "primitive.h"
namespace art {
diff --git a/runtime/mirror/art_field.cc b/runtime/mirror/art_field.cc
index f2729f660e..da21dfef06 100644
--- a/runtime/mirror/art_field.cc
+++ b/runtime/mirror/art_field.cc
@@ -20,7 +20,6 @@
#include "gc/accounting/card_table-inl.h"
#include "object-inl.h"
#include "object_array-inl.h"
-#include "object_utils.h"
#include "runtime.h"
#include "scoped_thread_state_change.h"
#include "utils.h"
diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h
index a5b5df6137..01b05a6e6f 100644
--- a/runtime/mirror/art_method-inl.h
+++ b/runtime/mirror/art_method-inl.h
@@ -19,11 +19,13 @@
#include "art_method.h"
+#include "class_linker.h"
+#include "dex_cache.h"
#include "dex_file.h"
#include "entrypoints/entrypoint_utils.h"
+#include "method_helper.h"
#include "object-inl.h"
#include "object_array.h"
-#include "object_utils.h"
#include "oat.h"
#include "quick/quick_method_frame_info.h"
#include "read_barrier-inl.h"
diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc
index 1fa680d148..167f848824 100644
--- a/runtime/mirror/art_method.cc
+++ b/runtime/mirror/art_method.cc
@@ -16,6 +16,7 @@
#include "art_method.h"
+#include "arch/context.h"
#include "art_field-inl.h"
#include "art_method-inl.h"
#include "base/stringpiece.h"
@@ -26,12 +27,12 @@
#include "interpreter/interpreter.h"
#include "jni_internal.h"
#include "mapping_table.h"
-#include "object-inl.h"
-#include "object_array.h"
+#include "method_helper.h"
#include "object_array-inl.h"
+#include "object_array.h"
+#include "object-inl.h"
#include "scoped_thread_state_change.h"
#include "string.h"
-#include "object_utils.h"
#include "well_known_classes.h"
namespace art {
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 349d4a34df..329a984842 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -30,6 +30,7 @@
#include "iftable.h"
#include "object_array-inl.h"
#include "read_barrier-inl.h"
+#include "reference-inl.h"
#include "runtime.h"
#include "string.h"
@@ -591,6 +592,11 @@ inline bool Class::IsArtMethodClass() const {
return this == ArtMethod::GetJavaLangReflectArtMethod<kReadBarrierOption>();
}
+template<ReadBarrierOption kReadBarrierOption>
+inline bool Class::IsReferenceClass() const {
+ return this == Reference::GetJavaLangRefReference<kReadBarrierOption>();
+}
+
template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline bool Class::IsClassClass() {
Class* java_lang_Class = GetClass<kVerifyFlags, kReadBarrierOption>()->
@@ -642,6 +648,30 @@ inline ObjectArray<ObjectArray<Class>>* Class::GetThrows() {
return GetFieldObject<ObjectArray<ObjectArray<Class>>>(field_offset);
}
+inline MemberOffset Class::GetDisableIntrinsicFlagOffset() {
+ CHECK(IsReferenceClass());
+ // First static field
+ DCHECK(GetSFields()->Get(0)->IsArtField());
+ DCHECK_STREQ(GetSFields()->Get(0)->GetName(), "disableIntrinsic");
+ return GetSFields()->Get(0)->GetOffset();
+}
+
+inline MemberOffset Class::GetSlowPathFlagOffset() {
+ CHECK(IsReferenceClass());
+ // Second static field
+ DCHECK(GetSFields()->Get(1)->IsArtField());
+ DCHECK_STREQ(GetSFields()->Get(1)->GetName(), "slowPathEnabled");
+ return GetSFields()->Get(1)->GetOffset();
+}
+
+inline bool Class::GetSlowPathEnabled() {
+ return GetField32(GetSlowPathFlagOffset());
+}
+
+inline void Class::SetSlowPath(bool enabled) {
+ SetField32<false>(GetSlowPathFlagOffset(), enabled);
+}
+
inline void Class::InitializeClassVisitor::operator()(
mirror::Object* obj, size_t usable_size) const {
DCHECK_LE(class_size_, usable_size);
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index be05fb8a9b..fadf80ebcf 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -18,17 +18,16 @@
#include "art_field-inl.h"
#include "art_method-inl.h"
-#include "class-inl.h"
#include "class_linker.h"
#include "class_loader.h"
+#include "class-inl.h"
#include "dex_cache.h"
#include "dex_file-inl.h"
#include "gc/accounting/card_table-inl.h"
-#include "object-inl.h"
+#include "handle_scope-inl.h"
#include "object_array-inl.h"
-#include "object_utils.h"
+#include "object-inl.h"
#include "runtime.h"
-#include "handle_scope-inl.h"
#include "thread.h"
#include "throwable.h"
#include "utils.h"
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 0f42044b37..648bddeca5 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -261,7 +261,7 @@ class MANAGED Class FINAL : public Object {
}
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
- bool IsReferenceClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ bool IsTypeOfReferenceClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return (GetAccessFlags<kVerifyFlags>() & kAccClassIsReference) != 0;
}
@@ -419,6 +419,9 @@ class MANAGED Class FINAL : public Object {
template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
bool IsArtMethodClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
+ bool IsReferenceClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
static MemberOffset ComponentTypeOffset() {
return OFFSET_OF_OBJECT_MEMBER(Class, component_type_);
}
@@ -976,6 +979,12 @@ class MANAGED Class FINAL : public Object {
// For proxy class only.
ObjectArray<ObjectArray<Class>>* GetThrows() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ // For reference class only.
+ MemberOffset GetDisableIntrinsicFlagOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ MemberOffset GetSlowPathFlagOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool GetSlowPathEnabled() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetSlowPath(bool enabled) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
// Used to initialize a class in the allocation code path to ensure it is guarded by a StoreStore
// fence.
class InitializeClassVisitor {
diff --git a/runtime/mirror/dex_cache_test.cc b/runtime/mirror/dex_cache_test.cc
index 3d28dc603f..ef6fc67c75 100644
--- a/runtime/mirror/dex_cache_test.cc
+++ b/runtime/mirror/dex_cache_test.cc
@@ -24,6 +24,7 @@
#include "mirror/object_array-inl.h"
#include "mirror/object-inl.h"
#include "handle_scope-inl.h"
+#include "scoped_thread_state_change.h"
namespace art {
namespace mirror {
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index 3d4568379d..9dbfb56c79 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -249,7 +249,7 @@ inline ArtMethod* Object::AsArtMethod() {
template<VerifyObjectFlags kVerifyFlags>
inline bool Object::IsReferenceInstance() {
- return GetClass<kVerifyFlags>()->IsReferenceClass();
+ return GetClass<kVerifyFlags>()->IsTypeOfReferenceClass();
}
template<VerifyObjectFlags kVerifyFlags>
@@ -806,7 +806,7 @@ inline void Object::VisitReferences(const Visitor& visitor,
} else {
DCHECK(!klass->IsVariableSize());
VisitInstanceFieldsReferences<kVisitClass>(klass, visitor);
- if (UNLIKELY(klass->IsReferenceClass<kVerifyNone>())) {
+ if (UNLIKELY(klass->IsTypeOfReferenceClass<kVerifyNone>())) {
ref_visitor(klass, AsReference());
}
}
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index 5f88d54fe0..961bc64819 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -24,13 +24,13 @@
#include "class.h"
#include "class-inl.h"
#include "class_linker-inl.h"
+#include "field_helper.h"
#include "gc/accounting/card_table-inl.h"
#include "gc/heap.h"
#include "iftable-inl.h"
#include "monitor.h"
#include "object-inl.h"
#include "object_array-inl.h"
-#include "object_utils.h"
#include "runtime.h"
#include "handle_scope-inl.h"
#include "throwable.h"
@@ -57,7 +57,7 @@ class CopyReferenceFieldsWithReadBarrierVisitor {
ALWAYS_INLINE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// Copy java.lang.ref.Reference.referent which isn't visited in
// Object::VisitReferences().
- DCHECK(klass->IsReferenceClass());
+ DCHECK(klass->IsTypeOfReferenceClass());
this->operator()(ref, mirror::Reference::ReferentOffset(), false);
}
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index 7e1de5d060..a7ea6c9c08 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -36,6 +36,7 @@
#include "object-inl.h"
#include "object_array-inl.h"
#include "handle_scope-inl.h"
+#include "scoped_thread_state_change.h"
#include "string-inl.h"
namespace art {
diff --git a/runtime/mirror/reference-inl.h b/runtime/mirror/reference-inl.h
index 43767c8792..b353402602 100644
--- a/runtime/mirror/reference-inl.h
+++ b/runtime/mirror/reference-inl.h
@@ -22,6 +22,11 @@
namespace art {
namespace mirror {
+inline uint32_t Reference::ClassSize() {
+ uint32_t vtable_entries = Object::kVTableLength + 5;
+ return Class::ComputeClassSize(false, vtable_entries, 2, 0, 0);
+}
+
inline bool Reference::IsEnqueuable() {
// Not using volatile reads as an optimization since this is only called with all the mutators
// suspended.
diff --git a/runtime/mirror/reference.cc b/runtime/mirror/reference.cc
new file mode 100644
index 0000000000..077cd4b913
--- /dev/null
+++ b/runtime/mirror/reference.cc
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "reference.h"
+
+namespace art {
+namespace mirror {
+
+Class* Reference::java_lang_ref_Reference_ = nullptr;
+
+void Reference::SetClass(Class* java_lang_ref_Reference) {
+ CHECK(java_lang_ref_Reference_ == nullptr);
+ CHECK(java_lang_ref_Reference != nullptr);
+ java_lang_ref_Reference_ = java_lang_ref_Reference;
+}
+
+void Reference::ResetClass() {
+ CHECK(java_lang_ref_Reference_ != nullptr);
+ java_lang_ref_Reference_ = nullptr;
+}
+
+void Reference::VisitRoots(RootCallback* callback, void* arg) {
+ if (java_lang_ref_Reference_ != nullptr) {
+ callback(reinterpret_cast<mirror::Object**>(&java_lang_ref_Reference_),
+ arg, 0, kRootStickyClass);
+ }
+}
+
+} // namespace mirror
+} // namespace art
diff --git a/runtime/mirror/reference.h b/runtime/mirror/reference.h
index 9c9d87be01..07d47d31e7 100644
--- a/runtime/mirror/reference.h
+++ b/runtime/mirror/reference.h
@@ -17,7 +17,11 @@
#ifndef ART_RUNTIME_MIRROR_REFERENCE_H_
#define ART_RUNTIME_MIRROR_REFERENCE_H_
+#include "class.h"
#include "object.h"
+#include "object_callbacks.h"
+#include "read_barrier.h"
+#include "thread.h"
namespace art {
@@ -36,6 +40,14 @@ namespace mirror {
// C++ mirror of java.lang.ref.Reference
class MANAGED Reference : public Object {
public:
+ // Size of java.lang.ref.Reference.class.
+ static uint32_t ClassSize();
+
+ // Size of an instance of java.lang.ref.Reference.
+ static constexpr uint32_t InstanceSize() {
+ return sizeof(Reference);
+ }
+
static MemberOffset PendingNextOffset() {
return OFFSET_OF_OBJECT_MEMBER(Reference, pending_next_);
}
@@ -80,6 +92,16 @@ class MANAGED Reference : public Object {
bool IsEnqueuable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
+ static Class* GetJavaLangRefReference() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(java_lang_ref_Reference_ != nullptr);
+ return ReadBarrier::BarrierForRoot<mirror::Class, kReadBarrierOption>(
+ &java_lang_ref_Reference_);
+ }
+ static void SetClass(Class* klass);
+ static void ResetClass(void);
+ static void VisitRoots(RootCallback* callback, void* arg);
+
private:
// Note: This avoids a read barrier, it should only be used by the GC.
HeapReference<Object>* GetReferentReferenceAddr() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -92,6 +114,8 @@ class MANAGED Reference : public Object {
HeapReference<Reference> queue_next_; // Note this is Java volatile:
HeapReference<Object> referent_; // Note this is Java volatile:
+ static Class* java_lang_ref_Reference_;
+
friend struct art::ReferenceOffsets; // for verifying offset information
friend class gc::ReferenceProcessor;
friend class gc::ReferenceQueue;
diff --git a/runtime/mirror/string.h b/runtime/mirror/string.h
index 8ab4db90e9..46bdd59b5c 100644
--- a/runtime/mirror/string.h
+++ b/runtime/mirror/string.h
@@ -19,6 +19,7 @@
#include <gtest/gtest.h>
+#include "object.h"
#include "object_callbacks.h"
#include "read_barrier.h"
diff --git a/runtime/mirror/throwable.cc b/runtime/mirror/throwable.cc
index 6efc9e2f54..1c3f1ed5bf 100644
--- a/runtime/mirror/throwable.cc
+++ b/runtime/mirror/throwable.cc
@@ -23,7 +23,6 @@
#include "object-inl.h"
#include "object_array.h"
#include "object_array-inl.h"
-#include "object_utils.h"
#include "stack_trace_element.h"
#include "utils.h"
#include "well_known_classes.h"
diff --git a/runtime/monitor.cc b/runtime/monitor.cc
index 5633a77b6f..4b26edac61 100644
--- a/runtime/monitor.cc
+++ b/runtime/monitor.cc
@@ -28,7 +28,6 @@
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
-#include "object_utils.h"
#include "scoped_thread_state_change.h"
#include "thread.h"
#include "thread_list.h"
@@ -746,7 +745,11 @@ mirror::Object* Monitor::MonitorEnter(Thread* self, mirror::Object* obj) {
contention_count++;
Runtime* runtime = Runtime::Current();
if (contention_count <= runtime->GetMaxSpinsBeforeThinkLockInflation()) {
- NanoSleep(1000); // Sleep for 1us and re-attempt.
+ // TODO: Consider switch thread state to kBlocked when we are yielding.
+ // Use sched_yield instead of NanoSleep since NanoSleep can wait much longer than the
+ // parameter you pass in. This can cause thread suspension to take excessively long
+ // make long pauses. See b/16307460.
+ sched_yield();
} else {
contention_count = 0;
InflateThinLocked(self, h_obj, lock_word, 0);
diff --git a/runtime/monitor_pool_test.cc b/runtime/monitor_pool_test.cc
index cddc245a42..e1837f52ab 100644
--- a/runtime/monitor_pool_test.cc
+++ b/runtime/monitor_pool_test.cc
@@ -17,6 +17,8 @@
#include "monitor_pool.h"
#include "common_runtime_test.h"
+#include "scoped_thread_state_change.h"
+#include "thread-inl.h"
namespace art {
diff --git a/runtime/monitor_test.cc b/runtime/monitor_test.cc
index bdba494e14..af24368e2f 100644
--- a/runtime/monitor_test.cc
+++ b/runtime/monitor_test.cc
@@ -24,6 +24,7 @@
#include "handle_scope-inl.h"
#include "mirror/class-inl.h"
#include "mirror/string-inl.h" // Strings are easiest to allocate
+#include "scoped_thread_state_change.h"
#include "thread_pool.h"
#include "utils.h"
@@ -31,7 +32,7 @@ namespace art {
class MonitorTest : public CommonRuntimeTest {
protected:
- void SetUpRuntimeOptions(Runtime::Options *options) OVERRIDE {
+ void SetUpRuntimeOptions(RuntimeOptions *options) OVERRIDE {
// Use a smaller heap
for (std::pair<std::string, const void*>& pair : *options) {
if (pair.first.find("-Xmx") == 0) {
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index f1a987f80a..b0b64aac16 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -30,7 +30,6 @@
#include "mirror/class-inl.h"
#include "mirror/dex_cache-inl.h"
#include "mirror/object-inl.h"
-#include "object_utils.h"
#include "runtime.h"
#include "scoped_fast_native_object_access.h"
#include "scoped_thread_state_change.h"
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index cede1a0899..e577c2c960 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -21,7 +21,6 @@
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
#include "mirror/object-inl.h"
-#include "object_utils.h"
#include "scoped_thread_state_change.h"
#include "scoped_fast_native_object_access.h"
#include "ScopedLocalRef.h"
diff --git a/runtime/native/java_lang_reflect_Array.cc b/runtime/native/java_lang_reflect_Array.cc
index eae4584019..f94e42b260 100644
--- a/runtime/native/java_lang_reflect_Array.cc
+++ b/runtime/native/java_lang_reflect_Array.cc
@@ -20,7 +20,6 @@
#include "jni_internal.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
-#include "object_utils.h"
#include "scoped_fast_native_object_access.h"
#include "handle_scope-inl.h"
diff --git a/runtime/native/java_lang_reflect_Constructor.cc b/runtime/native/java_lang_reflect_Constructor.cc
index 1981bfd5ab..34cb93ae94 100644
--- a/runtime/native/java_lang_reflect_Constructor.cc
+++ b/runtime/native/java_lang_reflect_Constructor.cc
@@ -20,7 +20,6 @@
#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
-#include "object_utils.h"
#include "reflection.h"
#include "scoped_fast_native_object_access.h"
#include "well_known_classes.h"
diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc
index 3564dfdf47..3903ffcd6a 100644
--- a/runtime/native/java_lang_reflect_Field.cc
+++ b/runtime/native/java_lang_reflect_Field.cc
@@ -18,11 +18,11 @@
#include "class_linker-inl.h"
#include "common_throws.h"
#include "dex_file-inl.h"
+#include "field_helper.h"
#include "jni_internal.h"
#include "mirror/art_field-inl.h"
#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
-#include "object_utils.h"
#include "reflection.h"
#include "scoped_fast_native_object_access.h"
diff --git a/runtime/native/java_lang_reflect_Method.cc b/runtime/native/java_lang_reflect_Method.cc
index ac602acb21..f029b16746 100644
--- a/runtime/native/java_lang_reflect_Method.cc
+++ b/runtime/native/java_lang_reflect_Method.cc
@@ -21,7 +21,6 @@
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
-#include "object_utils.h"
#include "reflection.h"
#include "scoped_fast_native_object_access.h"
#include "well_known_classes.h"
diff --git a/runtime/noop_compiler_callbacks.h b/runtime/noop_compiler_callbacks.h
index 702b2e1f5c..65498deaab 100644
--- a/runtime/noop_compiler_callbacks.h
+++ b/runtime/noop_compiler_callbacks.h
@@ -25,10 +25,15 @@ class NoopCompilerCallbacks FINAL : public CompilerCallbacks {
public:
NoopCompilerCallbacks() {}
~NoopCompilerCallbacks() {}
+
bool MethodVerified(verifier::MethodVerifier* verifier) OVERRIDE {
return true;
}
+
void ClassRejected(ClassReference ref) OVERRIDE {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NoopCompilerCallbacks);
};
} // namespace art
diff --git a/runtime/object_lock.cc b/runtime/object_lock.cc
new file mode 100644
index 0000000000..f7accc0f31
--- /dev/null
+++ b/runtime/object_lock.cc
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "object_lock.h"
+
+#include "mirror/object-inl.h"
+#include "monitor.h"
+
+namespace art {
+
+template <typename T>
+ObjectLock<T>::ObjectLock(Thread* self, Handle<T> object) : self_(self), obj_(object) {
+ CHECK(object.Get() != nullptr);
+ obj_->MonitorEnter(self_);
+}
+
+template <typename T>
+ObjectLock<T>::~ObjectLock() {
+ obj_->MonitorExit(self_);
+}
+
+template <typename T>
+void ObjectLock<T>::WaitIgnoringInterrupts() {
+ Monitor::Wait(self_, obj_.Get(), 0, 0, false, kWaiting);
+}
+
+template <typename T>
+void ObjectLock<T>::Notify() {
+ obj_->Notify(self_);
+}
+
+template <typename T>
+void ObjectLock<T>::NotifyAll() {
+ obj_->NotifyAll(self_);
+}
+
+template class ObjectLock<mirror::Class>;
+template class ObjectLock<mirror::Object>;
+
+} // namespace art
diff --git a/runtime/object_lock.h b/runtime/object_lock.h
new file mode 100644
index 0000000000..acddc03e29
--- /dev/null
+++ b/runtime/object_lock.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_OBJECT_LOCK_H_
+#define ART_RUNTIME_OBJECT_LOCK_H_
+
+#include "base/macros.h"
+#include "base/mutex.h"
+#include "handle.h"
+
+namespace art {
+
+class Thread;
+
+template <typename T>
+class ObjectLock {
+ public:
+ ObjectLock(Thread* self, Handle<T> object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ ~ObjectLock() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ void WaitIgnoringInterrupts() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ void Notify() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ void NotifyAll() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ private:
+ Thread* const self_;
+ Handle<T> const obj_;
+
+ DISALLOW_COPY_AND_ASSIGN(ObjectLock);
+};
+
+} // namespace art
+
+#endif // ART_RUNTIME_OBJECT_LOCK_H_
diff --git a/runtime/object_utils.h b/runtime/object_utils.h
deleted file mode 100644
index 4379b4ad2a..0000000000
--- a/runtime/object_utils.h
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_RUNTIME_OBJECT_UTILS_H_
-#define ART_RUNTIME_OBJECT_UTILS_H_
-
-#include "class_linker.h"
-#include "dex_file.h"
-#include "monitor.h"
-#include "mirror/art_field.h"
-#include "mirror/art_method.h"
-#include "mirror/class.h"
-#include "mirror/dex_cache.h"
-#include "mirror/iftable.h"
-#include "mirror/string.h"
-
-#include "runtime.h"
-#include "handle_scope-inl.h"
-
-#include <string>
-
-namespace art {
-
-template <typename T>
-class ObjectLock {
- public:
- ObjectLock(Thread* self, Handle<T> object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
- : self_(self), obj_(object) {
- CHECK(object.Get() != nullptr);
- obj_->MonitorEnter(self_);
- }
-
- ~ObjectLock() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- obj_->MonitorExit(self_);
- }
-
- void WaitIgnoringInterrupts() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- Monitor::Wait(self_, obj_.Get(), 0, 0, false, kWaiting);
- }
-
- void Notify() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- obj_->Notify(self_);
- }
-
- void NotifyAll() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- obj_->NotifyAll(self_);
- }
-
- private:
- Thread* const self_;
- Handle<T> const obj_;
- DISALLOW_COPY_AND_ASSIGN(ObjectLock);
-};
-
-class FieldHelper {
- public:
- explicit FieldHelper(Handle<mirror::ArtField> f) : field_(f) {}
-
- void ChangeField(mirror::ArtField* new_f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(new_f != nullptr);
- field_.Assign(new_f);
- }
-
- mirror::ArtField* GetField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return field_.Get();
- }
-
- mirror::Class* GetType(bool resolve = true) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- uint32_t field_index = field_->GetDexFieldIndex();
- if (UNLIKELY(field_->GetDeclaringClass()->IsProxyClass())) {
- return Runtime::Current()->GetClassLinker()->FindSystemClass(Thread::Current(),
- field_->GetTypeDescriptor());
- }
- const DexFile* dex_file = field_->GetDexFile();
- const DexFile::FieldId& field_id = dex_file->GetFieldId(field_index);
- mirror::Class* type = field_->GetDexCache()->GetResolvedType(field_id.type_idx_);
- if (resolve && (type == nullptr)) {
- type = Runtime::Current()->GetClassLinker()->ResolveType(field_id.type_idx_, field_.Get());
- CHECK(type != nullptr || Thread::Current()->IsExceptionPending());
- }
- return type;
- }
-
- // The returned const char* is only guaranteed to be valid for the lifetime of the FieldHelper.
- // If you need it longer, copy it into a std::string.
- const char* GetDeclaringClassDescriptor()
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- uint32_t field_index = field_->GetDexFieldIndex();
- if (UNLIKELY(field_->GetDeclaringClass()->IsProxyClass())) {
- DCHECK(field_->IsStatic());
- DCHECK_LT(field_index, 2U);
- // 0 == Class[] interfaces; 1 == Class[][] throws;
- declaring_class_descriptor_ = field_->GetDeclaringClass()->GetDescriptor();
- return declaring_class_descriptor_.c_str();
- }
- const DexFile* dex_file = field_->GetDexFile();
- const DexFile::FieldId& field_id = dex_file->GetFieldId(field_index);
- return dex_file->GetFieldDeclaringClassDescriptor(field_id);
- }
-
- private:
- Handle<mirror::ArtField> field_;
- std::string declaring_class_descriptor_;
-
- DISALLOW_COPY_AND_ASSIGN(FieldHelper);
-};
-
-class MethodHelper {
- public:
- explicit MethodHelper(Handle<mirror::ArtMethod> m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
- : method_(m), shorty_(nullptr), shorty_len_(0) {
- SetMethod(m.Get());
- }
-
- void ChangeMethod(mirror::ArtMethod* new_m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(new_m != nullptr);
- SetMethod(new_m);
- shorty_ = nullptr;
- }
-
- mirror::ArtMethod* GetMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return method_->GetInterfaceMethodIfProxy();
- }
-
- mirror::String* GetNameAsString(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- const DexFile* dex_file = method_->GetDexFile();
- mirror::ArtMethod* method = method_->GetInterfaceMethodIfProxy();
- uint32_t dex_method_idx = method->GetDexMethodIndex();
- const DexFile::MethodId& method_id = dex_file->GetMethodId(dex_method_idx);
- StackHandleScope<1> hs(self);
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(method->GetDexCache()));
- return Runtime::Current()->GetClassLinker()->ResolveString(*dex_file, method_id.name_idx_,
- dex_cache);
- }
-
- const char* GetShorty() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- const char* result = shorty_;
- if (result == nullptr) {
- result = method_->GetShorty(&shorty_len_);
- shorty_ = result;
- }
- return result;
- }
-
- uint32_t GetShortyLength() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (shorty_ == nullptr) {
- GetShorty();
- }
- return shorty_len_;
- }
-
- // Counts the number of references in the parameter list of the corresponding method.
- // Note: Thus does _not_ include "this" for non-static methods.
- uint32_t GetNumberOfReferenceArgsWithoutReceiver() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- const char* shorty = GetShorty();
- uint32_t refs = 0;
- for (uint32_t i = 1; i < shorty_len_ ; ++i) {
- if (shorty[i] == 'L') {
- refs++;
- }
- }
-
- return refs;
- }
-
- // May cause thread suspension due to GetClassFromTypeIdx calling ResolveType this caused a large
- // number of bugs at call sites.
- mirror::Class* GetReturnType(bool resolve = true) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- mirror::ArtMethod* method = GetMethod();
- const DexFile* dex_file = method->GetDexFile();
- const DexFile::MethodId& method_id = dex_file->GetMethodId(method->GetDexMethodIndex());
- const DexFile::ProtoId& proto_id = dex_file->GetMethodPrototype(method_id);
- uint16_t return_type_idx = proto_id.return_type_idx_;
- return GetClassFromTypeIdx(return_type_idx, resolve);
- }
-
- size_t NumArgs() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- // "1 +" because the first in Args is the receiver.
- // "- 1" because we don't count the return type.
- return (method_->IsStatic() ? 0 : 1) + GetShortyLength() - 1;
- }
-
- // Get the primitive type associated with the given parameter.
- Primitive::Type GetParamPrimitiveType(size_t param) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- CHECK_LT(param, NumArgs());
- if (GetMethod()->IsStatic()) {
- param++; // 0th argument must skip return value at start of the shorty
- } else if (param == 0) {
- return Primitive::kPrimNot;
- }
- return Primitive::GetType(GetShorty()[param]);
- }
-
- // Is the specified parameter a long or double, where parameter 0 is 'this' for instance methods.
- bool IsParamALongOrDouble(size_t param) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- Primitive::Type type = GetParamPrimitiveType(param);
- return type == Primitive::kPrimLong || type == Primitive::kPrimDouble;
- }
-
- // Is the specified parameter a reference, where parameter 0 is 'this' for instance methods.
- bool IsParamAReference(size_t param) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetParamPrimitiveType(param) == Primitive::kPrimNot;
- }
-
- bool HasSameNameAndSignature(MethodHelper* other) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- const DexFile* dex_file = method_->GetDexFile();
- const DexFile::MethodId& mid = dex_file->GetMethodId(GetMethod()->GetDexMethodIndex());
- if (method_->GetDexCache() == other->method_->GetDexCache()) {
- const DexFile::MethodId& other_mid =
- dex_file->GetMethodId(other->GetMethod()->GetDexMethodIndex());
- return mid.name_idx_ == other_mid.name_idx_ && mid.proto_idx_ == other_mid.proto_idx_;
- }
- const DexFile* other_dex_file = other->method_->GetDexFile();
- const DexFile::MethodId& other_mid =
- other_dex_file->GetMethodId(other->GetMethod()->GetDexMethodIndex());
- if (!DexFileStringEquals(dex_file, mid.name_idx_, other_dex_file, other_mid.name_idx_)) {
- return false; // Name mismatch.
- }
- return dex_file->GetMethodSignature(mid) == other_dex_file->GetMethodSignature(other_mid);
- }
-
- bool HasSameSignatureWithDifferentClassLoaders(MethodHelper* other)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (UNLIKELY(GetReturnType() != other->GetReturnType())) {
- return false;
- }
- const DexFile::TypeList* types = method_->GetParameterTypeList();
- const DexFile::TypeList* other_types = other->method_->GetParameterTypeList();
- if (types == nullptr) {
- return (other_types == nullptr) || (other_types->Size() == 0);
- } else if (UNLIKELY(other_types == nullptr)) {
- return types->Size() == 0;
- }
- uint32_t num_types = types->Size();
- if (UNLIKELY(num_types != other_types->Size())) {
- return false;
- }
- for (uint32_t i = 0; i < num_types; ++i) {
- mirror::Class* param_type = GetClassFromTypeIdx(types->GetTypeItem(i).type_idx_);
- mirror::Class* other_param_type =
- other->GetClassFromTypeIdx(other_types->GetTypeItem(i).type_idx_);
- if (UNLIKELY(param_type != other_param_type)) {
- return false;
- }
- }
- return true;
- }
-
- mirror::Class* GetClassFromTypeIdx(uint16_t type_idx, bool resolve = true)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- mirror::ArtMethod* method = GetMethod();
- mirror::Class* type = method->GetDexCacheResolvedTypes()->Get(type_idx);
- if (type == nullptr && resolve) {
- type = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
- CHECK(type != nullptr || Thread::Current()->IsExceptionPending());
- }
- return type;
- }
-
- mirror::Class* GetDexCacheResolvedType(uint16_t type_idx)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetMethod()->GetDexCacheResolvedTypes()->Get(type_idx);
- }
-
- mirror::String* ResolveString(uint32_t string_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- mirror::ArtMethod* method = GetMethod();
- mirror::String* s = method->GetDexCacheStrings()->Get(string_idx);
- if (UNLIKELY(s == nullptr)) {
- StackHandleScope<1> hs(Thread::Current());
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(method->GetDexCache()));
- s = Runtime::Current()->GetClassLinker()->ResolveString(*method->GetDexFile(), string_idx,
- dex_cache);
- }
- return s;
- }
-
- uint32_t FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- mirror::ArtMethod* method = GetMethod();
- const DexFile* dexfile = method->GetDexFile();
- if (dexfile == &other_dexfile) {
- return method->GetDexMethodIndex();
- }
- const DexFile::MethodId& mid = dexfile->GetMethodId(method->GetDexMethodIndex());
- const char* mid_declaring_class_descriptor = dexfile->StringByTypeIdx(mid.class_idx_);
- const DexFile::StringId* other_descriptor =
- other_dexfile.FindStringId(mid_declaring_class_descriptor);
- if (other_descriptor != nullptr) {
- const DexFile::TypeId* other_type_id =
- other_dexfile.FindTypeId(other_dexfile.GetIndexForStringId(*other_descriptor));
- if (other_type_id != nullptr) {
- const char* mid_name = dexfile->GetMethodName(mid);
- const DexFile::StringId* other_name = other_dexfile.FindStringId(mid_name);
- if (other_name != nullptr) {
- uint16_t other_return_type_idx;
- std::vector<uint16_t> other_param_type_idxs;
- bool success = other_dexfile.CreateTypeList(
- dexfile->GetMethodSignature(mid).ToString(), &other_return_type_idx,
- &other_param_type_idxs);
- if (success) {
- const DexFile::ProtoId* other_sig =
- other_dexfile.FindProtoId(other_return_type_idx, other_param_type_idxs);
- if (other_sig != nullptr) {
- const DexFile::MethodId* other_mid = other_dexfile.FindMethodId(
- *other_type_id, *other_name, *other_sig);
- if (other_mid != nullptr) {
- return other_dexfile.GetIndexForMethodId(*other_mid);
- }
- }
- }
- }
- }
- }
- return DexFile::kDexNoIndex;
- }
-
- // The name_and_signature_idx MUST point to a MethodId with the same name and signature in the
- // other_dexfile, such as the method index used to resolve this method in the other_dexfile.
- uint32_t FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile,
- uint32_t name_and_signature_idx)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- mirror::ArtMethod* method = GetMethod();
- const DexFile* dexfile = method->GetDexFile();
- const uint32_t dex_method_idx = method->GetDexMethodIndex();
- const DexFile::MethodId& mid = dexfile->GetMethodId(dex_method_idx);
- const DexFile::MethodId& name_and_sig_mid = other_dexfile.GetMethodId(name_and_signature_idx);
- DCHECK_STREQ(dexfile->GetMethodName(mid), other_dexfile.GetMethodName(name_and_sig_mid));
- DCHECK_EQ(dexfile->GetMethodSignature(mid), other_dexfile.GetMethodSignature(name_and_sig_mid));
- if (dexfile == &other_dexfile) {
- return dex_method_idx;
- }
- const char* mid_declaring_class_descriptor = dexfile->StringByTypeIdx(mid.class_idx_);
- const DexFile::StringId* other_descriptor =
- other_dexfile.FindStringId(mid_declaring_class_descriptor);
- if (other_descriptor != nullptr) {
- const DexFile::TypeId* other_type_id =
- other_dexfile.FindTypeId(other_dexfile.GetIndexForStringId(*other_descriptor));
- if (other_type_id != nullptr) {
- const DexFile::MethodId* other_mid = other_dexfile.FindMethodId(
- *other_type_id, other_dexfile.GetStringId(name_and_sig_mid.name_idx_),
- other_dexfile.GetProtoId(name_and_sig_mid.proto_idx_));
- if (other_mid != nullptr) {
- return other_dexfile.GetIndexForMethodId(*other_mid);
- }
- }
- }
- return DexFile::kDexNoIndex;
- }
-
- private:
- // Set the method_ field, for proxy methods looking up the interface method via the resolved
- // methods table.
- void SetMethod(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- method_.Assign(method);
- }
-
- Handle<mirror::ArtMethod> method_;
- const char* shorty_;
- uint32_t shorty_len_;
-
- DISALLOW_COPY_AND_ASSIGN(MethodHelper);
-};
-
-} // namespace art
-
-#endif // ART_RUNTIME_OBJECT_UTILS_H_
diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc
index a016cc50ac..577691c90b 100644
--- a/runtime/parsed_options.cc
+++ b/runtime/parsed_options.cc
@@ -24,11 +24,13 @@
#include "debugger.h"
#include "gc/heap.h"
#include "monitor.h"
+#include "runtime.h"
+#include "trace.h"
#include "utils.h"
namespace art {
-ParsedOptions* ParsedOptions::Create(const Runtime::Options& options, bool ignore_unrecognized) {
+ParsedOptions* ParsedOptions::Create(const RuntimeOptions& options, bool ignore_unrecognized) {
std::unique_ptr<ParsedOptions> parsed(new ParsedOptions());
if (parsed->Parse(options, ignore_unrecognized)) {
return parsed.release();
@@ -164,7 +166,7 @@ bool ParsedOptions::ParseXGcOption(const std::string& option) {
return true;
}
-bool ParsedOptions::Parse(const Runtime::Options& options, bool ignore_unrecognized) {
+bool ParsedOptions::Parse(const RuntimeOptions& options, bool ignore_unrecognized) {
const char* boot_class_path_string = getenv("BOOTCLASSPATH");
if (boot_class_path_string != NULL) {
boot_class_path_string_ = boot_class_path_string;
@@ -258,7 +260,7 @@ bool ParsedOptions::Parse(const Runtime::Options& options, bool ignore_unrecogni
method_trace_file_ = "/data/method-trace-file.bin";
method_trace_file_size_ = 10 * MB;
- profile_clock_source_ = kDefaultProfilerClockSource;
+ profile_clock_source_ = kDefaultTraceClockSource;
verify_ = true;
image_isa_ = kRuntimeISA;
@@ -542,11 +544,11 @@ bool ParsedOptions::Parse(const Runtime::Options& options, bool ignore_unrecogni
return false;
}
} else if (option == "-Xprofile:threadcpuclock") {
- Trace::SetDefaultClockSource(kProfilerClockSourceThreadCpu);
+ Trace::SetDefaultClockSource(kTraceClockSourceThreadCpu);
} else if (option == "-Xprofile:wallclock") {
- Trace::SetDefaultClockSource(kProfilerClockSourceWall);
+ Trace::SetDefaultClockSource(kTraceClockSourceWall);
} else if (option == "-Xprofile:dualclock") {
- Trace::SetDefaultClockSource(kProfilerClockSourceDual);
+ Trace::SetDefaultClockSource(kTraceClockSourceDual);
} else if (option == "-Xenable-profiler") {
profiler_options_.enabled_ = true;
} else if (StartsWith(option, "-Xprofile-filename:")) {
diff --git a/runtime/parsed_options.h b/runtime/parsed_options.h
index 4c74be680c..b1de62a54f 100644
--- a/runtime/parsed_options.h
+++ b/runtime/parsed_options.h
@@ -18,17 +18,26 @@
#define ART_RUNTIME_PARSED_OPTIONS_H_
#include <string>
+#include <vector>
+#include <jni.h>
+
+#include "globals.h"
#include "gc/collector_type.h"
-#include "runtime.h"
-#include "trace.h"
+#include "instruction_set.h"
+#include "profiler_options.h"
namespace art {
+class CompilerCallbacks;
+class DexFile;
+
+typedef std::vector<std::pair<std::string, const void*>> RuntimeOptions;
+
class ParsedOptions {
public:
// returns null if problem parsing and ignore_unrecognized is false
- static ParsedOptions* Create(const Runtime::Options& options, bool ignore_unrecognized);
+ static ParsedOptions* Create(const RuntimeOptions& options, bool ignore_unrecognized);
const std::vector<const DexFile*>* boot_class_path_;
std::string boot_class_path_string_;
@@ -80,7 +89,7 @@ class ParsedOptions {
std::vector<std::string> image_compiler_options_;
ProfilerOptions profiler_options_;
std::string profile_output_filename_;
- ProfilerClockSource profile_clock_source_;
+ TraceClockSource profile_clock_source_;
bool verify_;
InstructionSet image_isa_;
@@ -105,7 +114,7 @@ class ParsedOptions {
void Exit(int status);
void Abort();
- bool Parse(const Runtime::Options& options, bool ignore_unrecognized);
+ bool Parse(const RuntimeOptions& options, bool ignore_unrecognized);
bool ParseXGcOption(const std::string& option);
bool ParseStringAfterChar(const std::string& option, char after_char, std::string* parsed_value);
bool ParseInteger(const std::string& option, char after_char, int* parsed_value);
diff --git a/runtime/parsed_options_test.cc b/runtime/parsed_options_test.cc
index b58a29c471..5154d69292 100644
--- a/runtime/parsed_options_test.cc
+++ b/runtime/parsed_options_test.cc
@@ -36,7 +36,7 @@ TEST_F(ParsedOptionsTest, ParsedOptions) {
boot_class_path += "-Xbootclasspath:";
boot_class_path += lib_core;
- Runtime::Options options;
+ RuntimeOptions options;
options.push_back(std::make_pair(boot_class_path.c_str(), null));
options.push_back(std::make_pair("-classpath", null));
options.push_back(std::make_pair(lib_core.c_str(), null));
diff --git a/runtime/profiler.cc b/runtime/profiler.cc
index 7a7a92a7c0..951444812b 100644
--- a/runtime/profiler.cc
+++ b/runtime/profiler.cc
@@ -32,7 +32,6 @@
#include "mirror/dex_cache.h"
#include "mirror/object_array-inl.h"
#include "mirror/object-inl.h"
-#include "object_utils.h"
#include "os.h"
#include "scoped_thread_state_change.h"
#include "ScopedLocalRef.h"
diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc
index 093c129add..bd6656dda1 100644
--- a/runtime/proxy_test.cc
+++ b/runtime/proxy_test.cc
@@ -14,12 +14,14 @@
* limitations under the License.
*/
-#include "common_compiler_test.h"
-#include "mirror/art_field-inl.h"
-
#include <jni.h>
#include <vector>
+#include "common_compiler_test.h"
+#include "field_helper.h"
+#include "mirror/art_field-inl.h"
+#include "scoped_thread_state_change.h"
+
namespace art {
class ProxyTest : public CommonCompilerTest {
diff --git a/runtime/quick/inline_method_analyser.h b/runtime/quick/inline_method_analyser.h
index 5128b19d12..982553d3af 100644
--- a/runtime/quick/inline_method_analyser.h
+++ b/runtime/quick/inline_method_analyser.h
@@ -48,6 +48,7 @@ enum InlineMethodOpcode : uint16_t {
kIntrinsicMinMaxFloat,
kIntrinsicMinMaxDouble,
kIntrinsicSqrt,
+ kIntrinsicGet,
kIntrinsicCharAt,
kIntrinsicCompareTo,
kIntrinsicIsEmptyOrLength,
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index 49f6fe015e..6581f9b627 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -16,6 +16,7 @@
#include "quick_exception_handler.h"
+#include "arch/context.h"
#include "dex_instruction.h"
#include "entrypoints/entrypoint_utils.h"
#include "handle_scope-inl.h"
diff --git a/runtime/reference_table_test.cc b/runtime/reference_table_test.cc
index 32290393ce..d2877f98d1 100644
--- a/runtime/reference_table_test.cc
+++ b/runtime/reference_table_test.cc
@@ -17,6 +17,10 @@
#include "reference_table.h"
#include "common_runtime_test.h"
+#include "mirror/array.h"
+#include "mirror/string.h"
+#include "scoped_thread_state_change.h"
+#include "thread-inl.h"
namespace art {
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index fe5e1043a9..0af4117783 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -20,14 +20,14 @@
#include "common_throws.h"
#include "dex_file-inl.h"
#include "jni_internal.h"
+#include "method_helper.h"
#include "mirror/art_field-inl.h"
#include "mirror/art_method-inl.h"
-#include "mirror/class.h"
#include "mirror/class-inl.h"
-#include "mirror/object_array.h"
+#include "mirror/class.h"
#include "mirror/object_array-inl.h"
+#include "mirror/object_array.h"
#include "nth_caller_visitor.h"
-#include "object_utils.h"
#include "scoped_thread_state_change.h"
#include "stack.h"
#include "well_known_classes.h"
@@ -567,6 +567,11 @@ bool VerifyObjectIsClass(mirror::Object* o, mirror::Class* c) {
return true;
}
+static std::string PrettyDescriptor(Primitive::Type type) {
+ std::string descriptor_string(Primitive::Descriptor(type));
+ return PrettyDescriptor(descriptor_string);
+}
+
bool ConvertPrimitiveValue(const ThrowLocation* throw_location, bool unbox_for_result,
Primitive::Type srcType, Primitive::Type dstType,
const JValue& src, JValue* dst) {
diff --git a/runtime/reflection_test.cc b/runtime/reflection_test.cc
index abe68ef8d7..9d10daaffc 100644
--- a/runtime/reflection_test.cc
+++ b/runtime/reflection_test.cc
@@ -18,9 +18,11 @@
#include <float.h>
#include <limits.h>
+#include "ScopedLocalRef.h"
#include "common_compiler_test.h"
#include "mirror/art_method-inl.h"
+#include "scoped_thread_state_change.h"
namespace art {
diff --git a/runtime/runtime-inl.h b/runtime/runtime-inl.h
index d08e658824..f776bcd336 100644
--- a/runtime/runtime-inl.h
+++ b/runtime/runtime-inl.h
@@ -19,6 +19,8 @@
#include "runtime.h"
+#include "read_barrier-inl.h"
+
namespace art {
inline QuickMethodFrameInfo Runtime::GetRuntimeMethodFrameInfo(mirror::ArtMethod* method) {
@@ -37,6 +39,36 @@ inline QuickMethodFrameInfo Runtime::GetRuntimeMethodFrameInfo(mirror::ArtMethod
}
}
+inline mirror::ArtMethod* Runtime::GetResolutionMethod() {
+ CHECK(HasResolutionMethod());
+ return ReadBarrier::BarrierForRoot<mirror::ArtMethod, kWithReadBarrier>(&resolution_method_);
+}
+
+inline mirror::ArtMethod* Runtime::GetImtConflictMethod() {
+ CHECK(HasImtConflictMethod());
+ return ReadBarrier::BarrierForRoot<mirror::ArtMethod, kWithReadBarrier>(&imt_conflict_method_);
+}
+
+inline mirror::ObjectArray<mirror::ArtMethod>* Runtime::GetDefaultImt()
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ CHECK(HasDefaultImt());
+ return ReadBarrier::BarrierForRoot<mirror::ObjectArray<mirror::ArtMethod>, kWithReadBarrier>(
+ &default_imt_);
+}
+
+inline mirror::ArtMethod* Runtime::GetCalleeSaveMethod(CalleeSaveType type)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(HasCalleeSaveMethod(type));
+ return ReadBarrier::BarrierForRoot<mirror::ArtMethod, kWithReadBarrier>(
+ &callee_save_methods_[type]);
+}
+
+inline mirror::ArtMethod* Runtime::GetCalleeSaveMethodUnchecked(CalleeSaveType type)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return ReadBarrier::BarrierForRoot<mirror::ArtMethod, kWithReadBarrier>(
+ &callee_save_methods_[type]);
+}
+
} // namespace art
#endif // ART_RUNTIME_RUNTIME_INL_H_
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index c354ad51ca..0ddd2aed4a 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -49,6 +49,7 @@
#include "fault_handler.h"
#include "gc/accounting/card_table-inl.h"
#include "gc/heap.h"
+#include "gc/space/image_space.h"
#include "gc/space/space.h"
#include "image.h"
#include "instrumentation.h"
@@ -324,7 +325,7 @@ void Runtime::SweepSystemWeaks(IsMarkedCallback* visitor, void* arg) {
GetJavaVM()->SweepJniWeakGlobals(visitor, arg);
}
-bool Runtime::Create(const Options& options, bool ignore_unrecognized) {
+bool Runtime::Create(const RuntimeOptions& options, bool ignore_unrecognized) {
// TODO: acquire a static mutex on Runtime to avoid racing.
if (Runtime::instance_ != NULL) {
return false;
@@ -534,7 +535,7 @@ void Runtime::StartDaemonThreads() {
VLOG(startup) << "Runtime::StartDaemonThreads exiting";
}
-bool Runtime::Init(const Options& raw_options, bool ignore_unrecognized) {
+bool Runtime::Init(const RuntimeOptions& raw_options, bool ignore_unrecognized) {
CHECK_EQ(sysconf(_SC_PAGE_SIZE), kPageSize);
std::unique_ptr<ParsedOptions> options(ParsedOptions::Create(raw_options, ignore_unrecognized));
@@ -925,6 +926,7 @@ void Runtime::VisitConstantRoots(RootCallback* callback, void* arg) {
mirror::ArtField::VisitRoots(callback, arg);
mirror::ArtMethod::VisitRoots(callback, arg);
mirror::Class::VisitRoots(callback, arg);
+ mirror::Reference::VisitRoots(callback, arg);
mirror::StackTraceElement::VisitRoots(callback, arg);
mirror::String::VisitRoots(callback, arg);
mirror::Throwable::VisitRoots(callback, arg);
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 45af437edb..fccccbdfd7 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -32,7 +32,6 @@
#include "offsets.h"
#include "profiler_options.h"
#include "quick/quick_method_frame_info.h"
-#include "read_barrier-inl.h"
#include "runtime_stats.h"
#include "safe_map.h"
@@ -69,6 +68,8 @@ class ThreadList;
class Trace;
class Transaction;
+typedef std::vector<std::pair<std::string, const void*>> RuntimeOptions;
+
// Not all combinations of flags are valid. You may not visit all roots as well as the new roots
// (no logical reason to do this). You also may not start logging new roots and stop logging new
// roots (also no logical reason to do this).
@@ -82,10 +83,8 @@ enum VisitRootFlags : uint8_t {
class Runtime {
public:
- typedef std::vector<std::pair<std::string, const void*>> Options;
-
// Creates and initializes a new runtime.
- static bool Create(const Options& options, bool ignore_unrecognized)
+ static bool Create(const RuntimeOptions& options, bool ignore_unrecognized)
SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_);
bool IsCompiler() const {
@@ -266,13 +265,10 @@ class Runtime {
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Returns a special method that calls into a trampoline for runtime method resolution
- mirror::ArtMethod* GetResolutionMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- CHECK(HasResolutionMethod());
- return ReadBarrier::BarrierForRoot<mirror::ArtMethod, kWithReadBarrier>(&resolution_method_);
- }
+ mirror::ArtMethod* GetResolutionMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool HasResolutionMethod() const {
- return resolution_method_ != NULL;
+ return resolution_method_ != nullptr;
}
void SetResolutionMethod(mirror::ArtMethod* method) {
@@ -281,14 +277,11 @@ class Runtime {
mirror::ArtMethod* CreateResolutionMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- // Returns a special method that calls into a trampoline for runtime imt conflicts
- mirror::ArtMethod* GetImtConflictMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- CHECK(HasImtConflictMethod());
- return ReadBarrier::BarrierForRoot<mirror::ArtMethod, kWithReadBarrier>(&imt_conflict_method_);
- }
+ // Returns a special method that calls into a trampoline for runtime imt conflicts.
+ mirror::ArtMethod* GetImtConflictMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool HasImtConflictMethod() const {
- return imt_conflict_method_ != NULL;
+ return imt_conflict_method_ != nullptr;
}
void SetImtConflictMethod(mirror::ArtMethod* method) {
@@ -299,14 +292,10 @@ class Runtime {
// Returns an imt with every entry set to conflict, used as default imt for all classes.
mirror::ObjectArray<mirror::ArtMethod>* GetDefaultImt()
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- CHECK(HasDefaultImt());
- return ReadBarrier::BarrierForRoot<mirror::ObjectArray<mirror::ArtMethod>, kWithReadBarrier>(
- &default_imt_);
- }
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool HasDefaultImt() const {
- return default_imt_ != NULL;
+ return default_imt_ != nullptr;
}
void SetDefaultImt(mirror::ObjectArray<mirror::ArtMethod>* imt) {
@@ -329,17 +318,10 @@ class Runtime {
}
mirror::ArtMethod* GetCalleeSaveMethod(CalleeSaveType type)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(HasCalleeSaveMethod(type));
- return ReadBarrier::BarrierForRoot<mirror::ArtMethod, kWithReadBarrier>(
- &callee_save_methods_[type]);
- }
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
mirror::ArtMethod* GetCalleeSaveMethodUnchecked(CalleeSaveType type)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return ReadBarrier::BarrierForRoot<mirror::ArtMethod, kWithReadBarrier>(
- &callee_save_methods_[type]);
- }
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
QuickMethodFrameInfo GetCalleeSaveMethodFrameInfo(CalleeSaveType type) const {
return callee_save_method_frame_infos_[type];
@@ -474,7 +456,7 @@ class Runtime {
void BlockSignals();
- bool Init(const Options& options, bool ignore_unrecognized)
+ bool Init(const RuntimeOptions& options, bool ignore_unrecognized)
SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_);
void InitNativeMethods() LOCKS_EXCLUDED(Locks::mutator_lock_);
void InitThreadGroups(Thread* self);
diff --git a/runtime/stack.cc b/runtime/stack.cc
index d5405fbdf0..71e566efc3 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -16,13 +16,13 @@
#include "stack.h"
+#include "arch/context.h"
#include "base/hex_dump.h"
#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
#include "mirror/object.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
-#include "object_utils.h"
#include "quick/quick_method_frame_info.h"
#include "runtime.h"
#include "thread.h"
@@ -366,9 +366,10 @@ std::string StackVisitor::DescribeLocation() const {
return result;
}
-instrumentation::InstrumentationStackFrame& StackVisitor::GetInstrumentationStackFrame(uint32_t depth) const {
- CHECK_LT(depth, thread_->GetInstrumentationStack()->size());
- return thread_->GetInstrumentationStack()->at(depth);
+static instrumentation::InstrumentationStackFrame& GetInstrumentationStackFrame(Thread* thread,
+ uint32_t depth) {
+ CHECK_LT(depth, thread->GetInstrumentationStack()->size());
+ return thread->GetInstrumentationStack()->at(depth);
}
void StackVisitor::SanityCheckFrame() const {
@@ -431,7 +432,7 @@ void StackVisitor::WalkStack(bool include_transitions) {
// the stack for an exception where the side stack will be unwound in VisitFrame.
if (GetQuickInstrumentationExitPc() == return_pc) {
const instrumentation::InstrumentationStackFrame& instrumentation_frame =
- GetInstrumentationStackFrame(instrumentation_stack_depth);
+ GetInstrumentationStackFrame(thread_, instrumentation_stack_depth);
instrumentation_stack_depth++;
if (GetMethod() == Runtime::Current()->GetCalleeSaveMethod(Runtime::kSaveAll)) {
// Skip runtime save all callee frames which are used to deliver exceptions.
diff --git a/runtime/stack.h b/runtime/stack.h
index 9402cddf56..ef498ef06f 100644
--- a/runtime/stack.h
+++ b/runtime/stack.h
@@ -17,20 +17,16 @@
#ifndef ART_RUNTIME_STACK_H_
#define ART_RUNTIME_STACK_H_
+#include <stdint.h>
+#include <string>
+
#include "dex_file.h"
-#include "instrumentation.h"
-#include "arch/context.h"
-#include "base/casts.h"
-#include "base/macros.h"
#include "instruction_set.h"
-#include "mirror/object.h"
#include "mirror/object_reference.h"
+#include "throw_location.h"
#include "utils.h"
#include "verify_object.h"
-#include <stdint.h>
-#include <string>
-
namespace art {
namespace mirror {
@@ -711,8 +707,6 @@ class StackVisitor {
bool GetFPR(uint32_t reg, uintptr_t* val) const;
bool SetFPR(uint32_t reg, uintptr_t value);
- instrumentation::InstrumentationStackFrame& GetInstrumentationStackFrame(uint32_t depth) const;
-
void SanityCheckFrame() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
Thread* const thread_;
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 7827dfb650..9fa158d5e0 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -32,27 +32,29 @@
#include "arch/context.h"
#include "base/mutex.h"
-#include "class_linker.h"
#include "class_linker-inl.h"
+#include "class_linker.h"
#include "debugger.h"
#include "dex_file-inl.h"
#include "entrypoints/entrypoint_utils.h"
#include "entrypoints/quick/quick_alloc_entrypoints.h"
#include "gc_map.h"
#include "gc/accounting/card_table-inl.h"
+#include "gc/allocator/rosalloc.h"
#include "gc/heap.h"
#include "gc/space/space.h"
+#include "handle_scope-inl.h"
#include "handle_scope.h"
#include "indirect_reference_table-inl.h"
#include "jni_internal.h"
#include "mirror/art_field-inl.h"
#include "mirror/art_method-inl.h"
-#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
+#include "mirror/class-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/stack_trace_element.h"
#include "monitor.h"
-#include "object_utils.h"
+#include "object_lock.h"
#include "quick_exception_handler.h"
#include "quick/quick_method_frame_info.h"
#include "reflection.h"
@@ -60,10 +62,9 @@
#include "scoped_thread_state_change.h"
#include "ScopedLocalRef.h"
#include "ScopedUtfChars.h"
-#include "handle_scope-inl.h"
#include "stack.h"
-#include "thread-inl.h"
#include "thread_list.h"
+#include "thread-inl.h"
#include "utils.h"
#include "verifier/dex_gc_map.h"
#include "verify_object-inl.h"
@@ -1055,7 +1056,7 @@ Thread::Thread(bool daemon) : tls32_(daemon), wait_monitor_(nullptr), interrupte
tls32_.state_and_flags.as_struct.state = kNative;
memset(&tlsPtr_.held_mutexes[0], 0, sizeof(tlsPtr_.held_mutexes));
std::fill(tlsPtr_.rosalloc_runs,
- tlsPtr_.rosalloc_runs + gc::allocator::RosAlloc::kNumThreadLocalSizeBrackets,
+ tlsPtr_.rosalloc_runs + kNumRosAllocThreadLocalSizeBrackets,
gc::allocator::RosAlloc::GetDedicatedFullRun());
for (uint32_t i = 0; i < kMaxCheckpoints; ++i) {
tlsPtr_.checkpoint_functions[i] = nullptr;
diff --git a/runtime/thread.h b/runtime/thread.h
index bf125f9b7a..d08c2fce82 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -31,7 +31,6 @@
#include "entrypoints/jni/jni_entrypoints.h"
#include "entrypoints/portable/portable_entrypoints.h"
#include "entrypoints/quick/quick_entrypoints.h"
-#include "gc/allocator/rosalloc.h"
#include "globals.h"
#include "handle_scope.h"
#include "instruction_set.h"
@@ -93,6 +92,8 @@ enum ThreadFlag {
kCheckpointRequest = 2 // Request that the thread do some checkpoint work and then continue.
};
+static constexpr size_t kNumRosAllocThreadLocalSizeBrackets = 34;
+
class Thread {
public:
// How much of the reserved bytes is reserved for incoming signals.
@@ -1076,7 +1077,7 @@ class Thread {
size_t thread_local_objects;
// There are RosAlloc::kNumThreadLocalSizeBrackets thread-local size brackets per thread.
- void* rosalloc_runs[gc::allocator::RosAlloc::kNumThreadLocalSizeBrackets];
+ void* rosalloc_runs[kNumRosAllocThreadLocalSizeBrackets];
// Thread-local allocation stack data/routines.
mirror::Object** thread_local_alloc_stack_top;
diff --git a/runtime/thread_list.cc b/runtime/thread_list.cc
index 54732fae04..b649b626ca 100644
--- a/runtime/thread_list.cc
+++ b/runtime/thread_list.cc
@@ -39,6 +39,8 @@
namespace art {
+static constexpr uint64_t kLongThreadSuspendThreshold = MsToNs(5);
+
ThreadList::ThreadList()
: suspend_all_count_(0), debug_suspend_all_count_(0),
thread_exit_cond_("thread exit condition variable", *Locks::thread_list_lock_) {
@@ -304,8 +306,8 @@ void ThreadList::SuspendAll() {
DCHECK(self != nullptr);
VLOG(threads) << *self << " SuspendAll starting...";
-
ATRACE_BEGIN("Suspending mutator threads");
+ uint64_t start_time = NanoTime();
Locks::mutator_lock_->AssertNotHeld(self);
Locks::thread_list_lock_->AssertNotHeld(self);
@@ -338,6 +340,11 @@ void ThreadList::SuspendAll() {
Locks::mutator_lock_->ExclusiveLock(self);
#endif
+ uint64_t end_time = NanoTime();
+ if (end_time - start_time > kLongThreadSuspendThreshold) {
+ LOG(WARNING) << "Suspending all threads took: " << PrettyDuration(end_time - start_time);
+ }
+
if (kDebugLocking) {
// Debug check that all threads are suspended.
AssertThreadsAreSuspended(self, self);
diff --git a/runtime/thread_pool_test.cc b/runtime/thread_pool_test.cc
index 292c94f64b..4bd44dcb0f 100644
--- a/runtime/thread_pool_test.cc
+++ b/runtime/thread_pool_test.cc
@@ -20,6 +20,7 @@
#include "atomic.h"
#include "common_runtime_test.h"
+#include "thread-inl.h"
namespace art {
diff --git a/runtime/throw_location.cc b/runtime/throw_location.cc
index a1347a49bb..04abe64453 100644
--- a/runtime/throw_location.cc
+++ b/runtime/throw_location.cc
@@ -19,7 +19,6 @@
#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
-#include "object_utils.h"
#include "utils.h"
namespace art {
diff --git a/runtime/trace.cc b/runtime/trace.cc
index 1a450c4cb9..f51b8c435a 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -30,7 +30,6 @@
#include "mirror/dex_cache.h"
#include "mirror/object_array-inl.h"
#include "mirror/object-inl.h"
-#include "object_utils.h"
#include "os.h"
#include "scoped_thread_state_change.h"
#include "ScopedLocalRef.h"
@@ -115,7 +114,7 @@ static const uint16_t kTraceVersionDualClock = 3;
static const uint16_t kTraceRecordSizeSingleClock = 10; // using v2
static const uint16_t kTraceRecordSizeDualClock = 14; // using v3 with two timestamps
-ProfilerClockSource Trace::default_clock_source_ = kDefaultProfilerClockSource;
+TraceClockSource Trace::default_clock_source_ = kDefaultTraceClockSource;
Trace* volatile Trace::the_trace_ = NULL;
pthread_t Trace::sampling_pthread_ = 0U;
@@ -149,34 +148,34 @@ void Trace::FreeStackTrace(std::vector<mirror::ArtMethod*>* stack_trace) {
temp_stack_trace_.reset(stack_trace);
}
-void Trace::SetDefaultClockSource(ProfilerClockSource clock_source) {
+void Trace::SetDefaultClockSource(TraceClockSource clock_source) {
#if defined(HAVE_POSIX_CLOCKS)
default_clock_source_ = clock_source;
#else
- if (clock_source != kProfilerClockSourceWall) {
+ if (clock_source != kTraceClockSourceWall) {
LOG(WARNING) << "Ignoring tracing request to use CPU time.";
}
#endif
}
-static uint16_t GetTraceVersion(ProfilerClockSource clock_source) {
- return (clock_source == kProfilerClockSourceDual) ? kTraceVersionDualClock
+static uint16_t GetTraceVersion(TraceClockSource clock_source) {
+ return (clock_source == kTraceClockSourceDual) ? kTraceVersionDualClock
: kTraceVersionSingleClock;
}
-static uint16_t GetRecordSize(ProfilerClockSource clock_source) {
- return (clock_source == kProfilerClockSourceDual) ? kTraceRecordSizeDualClock
+static uint16_t GetRecordSize(TraceClockSource clock_source) {
+ return (clock_source == kTraceClockSourceDual) ? kTraceRecordSizeDualClock
: kTraceRecordSizeSingleClock;
}
bool Trace::UseThreadCpuClock() {
- return (clock_source_ == kProfilerClockSourceThreadCpu) ||
- (clock_source_ == kProfilerClockSourceDual);
+ return (clock_source_ == kTraceClockSourceThreadCpu) ||
+ (clock_source_ == kTraceClockSourceDual);
}
bool Trace::UseWallClock() {
- return (clock_source_ == kProfilerClockSourceWall) ||
- (clock_source_ == kProfilerClockSourceDual);
+ return (clock_source_ == kTraceClockSourceWall) ||
+ (clock_source_ == kTraceClockSourceDual);
}
static void MeasureClockOverhead(Trace* trace) {
@@ -462,7 +461,7 @@ Trace::Trace(File* trace_file, int buffer_size, int flags, bool sampling_enabled
cur_offset_.StoreRelaxed(kTraceHeaderLength);
}
-static void DumpBuf(uint8_t* buf, size_t buf_size, ProfilerClockSource clock_source)
+static void DumpBuf(uint8_t* buf, size_t buf_size, TraceClockSource clock_source)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
uint8_t* ptr = buf + kTraceHeaderLength;
uint8_t* end = buf + buf_size;
diff --git a/runtime/trace.h b/runtime/trace.h
index 9c8d35bb93..d7836b8965 100644
--- a/runtime/trace.h
+++ b/runtime/trace.h
@@ -36,19 +36,8 @@ namespace mirror {
class ArtField;
class ArtMethod;
} // namespace mirror
-class Thread;
-
-enum ProfilerClockSource {
- kProfilerClockSourceThreadCpu,
- kProfilerClockSourceWall,
- kProfilerClockSourceDual, // Both wall and thread CPU clocks.
-};
-#if defined(HAVE_POSIX_CLOCKS)
-const ProfilerClockSource kDefaultProfilerClockSource = kProfilerClockSourceDual;
-#else
-const ProfilerClockSource kDefaultProfilerClockSource = kProfilerClockSourceWall;
-#endif
+class Thread;
enum TracingMode {
kTracingInactive,
@@ -62,7 +51,7 @@ class Trace FINAL : public instrumentation::InstrumentationListener {
kTraceCountAllocs = 1,
};
- static void SetDefaultClockSource(ProfilerClockSource clock_source);
+ static void SetDefaultClockSource(TraceClockSource clock_source);
static void Start(const char* trace_filename, int trace_fd, int buffer_size, int flags,
bool direct_to_ddms, bool sampling_enabled, int interval_us)
@@ -138,7 +127,7 @@ class Trace FINAL : public instrumentation::InstrumentationListener {
static Trace* volatile the_trace_ GUARDED_BY(Locks::trace_lock_);
// The default profiler clock source.
- static ProfilerClockSource default_clock_source_;
+ static TraceClockSource default_clock_source_;
// Sampling thread, non-zero when sampling.
static pthread_t sampling_pthread_;
@@ -158,7 +147,7 @@ class Trace FINAL : public instrumentation::InstrumentationListener {
// True if traceview should sample instead of instrumenting method entry/exit.
const bool sampling_enabled_;
- const ProfilerClockSource clock_source_;
+ const TraceClockSource clock_source_;
// Size of buf_.
const int buffer_size_;
diff --git a/runtime/transaction_test.cc b/runtime/transaction_test.cc
index a03b389e0b..691aec4f2c 100644
--- a/runtime/transaction_test.cc
+++ b/runtime/transaction_test.cc
@@ -20,6 +20,7 @@
#include "mirror/array-inl.h"
#include "mirror/art_field-inl.h"
#include "mirror/art_method-inl.h"
+#include "scoped_thread_state_change.h"
namespace art {
diff --git a/runtime/utils.cc b/runtime/utils.cc
index d038571e96..8b1ad39edc 100644
--- a/runtime/utils.cc
+++ b/runtime/utils.cc
@@ -28,6 +28,7 @@
#include "base/stl_util.h"
#include "base/unix_file/fd_file.h"
#include "dex_file-inl.h"
+#include "field_helper.h"
#include "mirror/art_field-inl.h"
#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
@@ -35,7 +36,6 @@
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/string.h"
-#include "object_utils.h"
#include "os.h"
#include "scoped_thread_state_change.h"
#include "utf-inl.h"
@@ -281,11 +281,6 @@ std::string PrettyDescriptor(const std::string& descriptor) {
return result;
}
-std::string PrettyDescriptor(Primitive::Type type) {
- std::string descriptor_string(Primitive::Descriptor(type));
- return PrettyDescriptor(descriptor_string);
-}
-
std::string PrettyField(mirror::ArtField* f, bool with_type) {
if (f == NULL) {
return "null";
diff --git a/runtime/utils.h b/runtime/utils.h
index b47de81d62..2cb3af7aec 100644
--- a/runtime/utils.h
+++ b/runtime/utils.h
@@ -26,7 +26,7 @@
#include "base/logging.h"
#include "globals.h"
#include "instruction_set.h"
-#include "primitive.h"
+#include "base/mutex.h"
#ifdef HAVE_ANDROID_OS
#include "cutils/properties.h"
@@ -279,7 +279,6 @@ bool EndsWith(const std::string& s, const char* suffix);
std::string PrettyDescriptor(mirror::String* descriptor)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
std::string PrettyDescriptor(const std::string& descriptor);
-std::string PrettyDescriptor(Primitive::Type type);
std::string PrettyDescriptor(mirror::Class* klass)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index eabb993879..a1b86e05f5 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -25,10 +25,12 @@
#include "dex_file-inl.h"
#include "dex_instruction-inl.h"
#include "dex_instruction_visitor.h"
+#include "field_helper.h"
#include "gc/accounting/card_table-inl.h"
#include "indenter.h"
#include "intern_table.h"
#include "leb128.h"
+#include "method_helper.h"
#include "mirror/art_field-inl.h"
#include "mirror/art_method-inl.h"
#include "mirror/class.h"
@@ -36,7 +38,6 @@
#include "mirror/dex_cache-inl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
-#include "object_utils.h"
#include "register_line-inl.h"
#include "runtime.h"
#include "scoped_thread_state_change.h"
diff --git a/runtime/verifier/method_verifier_test.cc b/runtime/verifier/method_verifier_test.cc
index f70faf59a4..a5895e6dbf 100644
--- a/runtime/verifier/method_verifier_test.cc
+++ b/runtime/verifier/method_verifier_test.cc
@@ -22,6 +22,7 @@
#include "class_linker-inl.h"
#include "common_runtime_test.h"
#include "dex_file.h"
+#include "scoped_thread_state_change.h"
namespace art {
namespace verifier {
diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc
index e24c92091c..f0729e4271 100644
--- a/runtime/verifier/reg_type.cc
+++ b/runtime/verifier/reg_type.cc
@@ -24,7 +24,6 @@
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
-#include "object_utils.h"
#include "reg_type_cache-inl.h"
#include "scoped_thread_state_change.h"
diff --git a/runtime/verifier/reg_type_cache.cc b/runtime/verifier/reg_type_cache.cc
index ff9edbbeaf..91fba4d2bb 100644
--- a/runtime/verifier/reg_type_cache.cc
+++ b/runtime/verifier/reg_type_cache.cc
@@ -21,7 +21,6 @@
#include "dex_file-inl.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
-#include "object_utils.h"
namespace art {
namespace verifier {
diff --git a/runtime/verifier/reg_type_test.cc b/runtime/verifier/reg_type_test.cc
index 1935a5b1bc..9dc0df13fb 100644
--- a/runtime/verifier/reg_type_test.cc
+++ b/runtime/verifier/reg_type_test.cc
@@ -21,6 +21,8 @@
#include "base/casts.h"
#include "common_runtime_test.h"
#include "reg_type_cache-inl.h"
+#include "scoped_thread_state_change.h"
+#include "thread-inl.h"
namespace art {
namespace verifier {
diff --git a/runtime/verify_object.h b/runtime/verify_object.h
index 6640e0dd4a..8e1653ddb9 100644
--- a/runtime/verify_object.h
+++ b/runtime/verify_object.h
@@ -52,10 +52,10 @@ static constexpr VerifyObjectFlags kDefaultVerifyFlags = kVerifyNone;
static constexpr VerifyObjectMode kVerifyObjectSupport =
kDefaultVerifyFlags != 0 ? kVerifyObjectModeFast : kVerifyObjectModeDisabled;
-void VerifyObject(mirror::Object* obj) ALWAYS_INLINE NO_THREAD_SAFETY_ANALYSIS;
+ALWAYS_INLINE void VerifyObject(mirror::Object* obj) NO_THREAD_SAFETY_ANALYSIS;
// Check that c.getClass() == c.getClass().getClass().
-bool VerifyClassClass(mirror::Class* c) ALWAYS_INLINE NO_THREAD_SAFETY_ANALYSIS;
+ALWAYS_INLINE bool VerifyClassClass(mirror::Class* c) NO_THREAD_SAFETY_ANALYSIS;
} // namespace art
diff --git a/runtime/zip_archive_test.cc b/runtime/zip_archive_test.cc
index d303d1e502..96abee2dc3 100644
--- a/runtime/zip_archive_test.cc
+++ b/runtime/zip_archive_test.cc
@@ -22,6 +22,7 @@
#include <zlib.h>
#include <memory>
+#include "base/unix_file/fd_file.h"
#include "common_runtime_test.h"
#include "os.h"
diff --git a/sigchainlib/sigchain.h b/sigchainlib/sigchain.h
index f6f2253d72..a4ce81ce4c 100644
--- a/sigchainlib/sigchain.h
+++ b/sigchainlib/sigchain.h
@@ -18,10 +18,13 @@
#define ART_SIGCHAINLIB_SIGCHAIN_H_
#include <signal.h>
+
namespace art {
void ClaimSignalChain(int signal, struct sigaction* oldaction);
+
void UnclaimSignalChain(int signal);
+
void InvokeUserSignalHandler(int sig, siginfo_t* info, void* context);
} // namespace art
diff --git a/test/401-optimizing-compiler/expected.txt b/test/401-optimizing-compiler/expected.txt
index 97492a411f..d6ef64b96b 100644
--- a/test/401-optimizing-compiler/expected.txt
+++ b/test/401-optimizing-compiler/expected.txt
@@ -11,3 +11,4 @@ Forced GC
Forced GC
Forced GC
Forced GC
+Forced GC
diff --git a/test/401-optimizing-compiler/src/Main.java b/test/401-optimizing-compiler/src/Main.java
index e5706a52fe..a5192e1e64 100644
--- a/test/401-optimizing-compiler/src/Main.java
+++ b/test/401-optimizing-compiler/src/Main.java
@@ -71,6 +71,10 @@ public class Main {
if (m.$opt$TestOtherParameter(new Main()) == m) {
throw new Error("Unexpected value returned");
}
+
+ if (m.$opt$TestReturnNewObject(m) == m) {
+ throw new Error("Unexpected value returned");
+ }
}
static int $opt$TestInvokeIntParameter(int param) {
@@ -108,6 +112,12 @@ public class Main {
return other;
}
+ Object $opt$TestReturnNewObject(Object other) {
+ Object o = new Object();
+ forceGCStaticMethod();
+ return o;
+ }
+
public static void $opt$TestInvokeStatic() {
printStaticMethod();
printStaticMethodWith2Args(1, 2);
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index 25bcf0a790..1683074eba 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -21,26 +21,62 @@ include art/build/Android.common_test.mk
TEST_ART_RUN_TESTS := $(wildcard $(LOCAL_PATH)/[0-9]*)
TEST_ART_RUN_TESTS := $(subst $(LOCAL_PATH)/,, $(TEST_ART_RUN_TESTS))
+# List all the test names for host and target excluding the -trace suffix
+# $(1): test name, e.g. 003-omnibus-opcodes
+# $(2): undefined or -trace
+define all-run-test-names
+ test-art-host-run-test$(2)-default-$(1)32 \
+ test-art-host-run-test$(2)-optimizing-$(1)32 \
+ test-art-host-run-test$(2)-interpreter-$(1)32 \
+ test-art-host-run-test$(2)-default-$(1)64 \
+ test-art-host-run-test$(2)-optimizing-$(1)64 \
+ test-art-host-run-test$(2)-interpreter-$(1)64 \
+ test-art-target-run-test$(2)-default-$(1)32 \
+ test-art-target-run-test$(2)-optimizing-$(1)32 \
+ test-art-target-run-test$(2)-interpreter-$(1)32 \
+ test-art-target-run-test$(2)-default-$(1)64 \
+ test-art-target-run-test$(2)-optimizing-$(1)64 \
+ test-art-target-run-test$(2)-interpreter-$(1)64
+endef # all-run-test-names
+
# Tests that are timing sensitive and flaky on heavily loaded systems.
TEST_ART_TIMING_SENSITIVE_RUN_TESTS := \
- test-art-host-run-test-default-053-wait-some32 \
- test-art-host-run-test-default-053-wait-some64 \
- test-art-host-run-test-interpreter-053-wait-some32 \
- test-art-host-run-test-interpreter-053-wait-some64 \
- test-art-host-run-test-optimizing-053-wait-some32 \
- test-art-host-run-test-optimizing-053-wait-some64 \
- test-art-host-run-test-default-055-enum-performance32 \
- test-art-host-run-test-default-055-enum-performance64 \
- test-art-host-run-test-interpreter-055-enum-performance32 \
- test-art-host-run-test-interpreter-055-enum-performance64 \
- test-art-host-run-test-optimizing-055-enum-performance32 \
- test-art-host-run-test-optimizing-055-enum-performance64
+ 053-wait-some \
+ 055-enum-performance
# disable timing sensitive tests on "dist" builds.
ifdef dist_goal
- ART_TEST_KNOWN_BROKEN += $(TEST_ART_TIMING_SENSITIVE_RUN_TESTS)
+ ART_TEST_KNOWN_BROKEN += $(foreach test, $(TEST_ART_TIMING_SENSITIVE_RUN_TESTS), $(call all-run-test-names,$(test),))
+ ART_TEST_KNOWN_BROKEN += $(foreach test, $(TEST_ART_TIMING_SENSITIVE_RUN_TESTS), $(call all-run-test-names,$(test),-trace))
endif
+# Tests that are broken in --trace mode.
+TEST_ART_BROKEN_TRACE_RUN_TESTS := \
+ 003-omnibus-opcodes \
+ 004-annotations \
+ 018-stack-overflow \
+ 023-many-interfaces \
+ 031-class-attributes \
+ 037-inherit \
+ 044-proxy \
+ 046-reflect \
+ 051-thread \
+ 055-enum-performance \
+ 064-field-access \
+ 078-polymorphic-virtual \
+ 080-oom-throw \
+ 082-inline-execute \
+ 083-compiler-regressions \
+ 097-duplicate-method \
+ 100-reflect2 \
+ 102-concurrent-gc \
+ 103-string-append \
+ 107-int-math2 \
+ 112-double-math \
+ 701-easy-div-rem
+
+ART_TEST_KNOWN_BROKEN += $(foreach test, $(TEST_ART_BROKEN_TRACE_RUN_TESTS), $(call all-run-test-names,$(test),-trace))
+
# The path where build only targets will be output, e.g.
# out/target/product/generic_x86_64/obj/PACKAGING/art-run-tests_intermediates/DATA
art_run_tests_dir := $(call intermediates-dir-for,PACKAGING,art-run-tests)/DATA
@@ -96,9 +132,11 @@ ART_TEST_HOST_RUN_TEST_ALL_RULES :=
ART_TEST_HOST_RUN_TEST_DEFAULT_RULES :=
ART_TEST_HOST_RUN_TEST_INTERPRETER_RULES :=
ART_TEST_HOST_RUN_TEST_OPTIMIZING_RULES :=
+ART_TEST_HOST_RUN_TEST_ALL$(ART_PHONY_TEST_HOST_SUFFIX)_RULES :=
ART_TEST_HOST_RUN_TEST_DEFAULT$(ART_PHONY_TEST_HOST_SUFFIX)_RULES :=
ART_TEST_HOST_RUN_TEST_INTERPRETER$(ART_PHONY_TEST_HOST_SUFFIX)_RULES :=
ART_TEST_HOST_RUN_TEST_OPTIMIZING$(ART_PHONY_TEST_HOST_SUFFIX)_RULES :=
+ART_TEST_HOST_RUN_TEST_ALL$(2ND_ART_PHONY_TEST_HOST_SUFFIX)_RULES :=
ART_TEST_HOST_RUN_TEST_DEFAULT$(2ND_ART_PHONY_TEST_HOST_SUFFIX)_RULES :=
ART_TEST_HOST_RUN_TEST_INTERPRETER$(2ND_ART_PHONY_TEST_HOST_SUFFIX)_RULES :=
ART_TEST_HOST_RUN_TEST_OPTIMIZING$(2ND_ART_PHONY_TEST_HOST_SUFFIX)_RULES :=
@@ -124,8 +162,10 @@ endif
# $(2): host or target
# $(3): default, optimizing or interpreter
# $(4): 32 or 64
+# $(5): run tests with tracing enabled or not: trace or undefined
define define-test-art-run-test
run_test_options := $(addprefix --runtime-option ,$(DALVIKVM_FLAGS))
+ run_test_rule_name := test-art-$(2)-run-test-$(3)-$(1)$(4)
uc_host_or_target :=
prereq_rule :=
ifeq ($(2),host)
@@ -163,7 +203,14 @@ define define-test-art-run-test
$$(error found $(4) expected 32 or 64)
endif
endif
- run_test_rule_name := test-art-$(2)-run-test-$(3)-$(1)$(4)
+ ifeq ($(5),trace)
+ run_test_options += --trace
+ run_test_rule_name := test-art-$(2)-run-test-trace-$(3)-$(1)$(4)
+ else
+ ifneq (,$(5))
+ $$(error found $(5) expected undefined or -trace)
+ endif
+ endif
run_test_options := --output-path $(ART_HOST_TEST_DIR)/run-test-output/$$(run_test_rule_name) \
$$(run_test_options)
$$(run_test_rule_name): PRIVATE_RUN_TEST_OPTIONS := $$(run_test_options)
@@ -222,9 +269,13 @@ define define-test-art-run-test-group
ART_TEST_$$(group_uc_host_or_target)_RUN_TEST_INTERPRETER_$(1)_RULES :=
ART_TEST_$$(group_uc_host_or_target)_RUN_TEST_OPTIMIZING_$(1)_RULES :=
ART_TEST_$$(group_uc_host_or_target)_RUN_TEST_$(1)_RULES :=
- $$(eval $$(call define-test-art-run-test,$(1),$(2),default,$$(ART_PHONY_TEST_$$(group_uc_host_or_target)_SUFFIX)))
- $$(eval $$(call define-test-art-run-test,$(1),$(2),interpreter,$$(ART_PHONY_TEST_$$(group_uc_host_or_target)_SUFFIX)))
- $$(eval $$(call define-test-art-run-test,$(1),$(2),optimizing,$$(ART_PHONY_TEST_$$(group_uc_host_or_target)_SUFFIX)))
+ $$(eval $$(call define-test-art-run-test,$(1),$(2),default,$$(ART_PHONY_TEST_$$(group_uc_host_or_target)_SUFFIX),))
+ $$(eval $$(call define-test-art-run-test,$(1),$(2),interpreter,$$(ART_PHONY_TEST_$$(group_uc_host_or_target)_SUFFIX),))
+ $$(eval $$(call define-test-art-run-test,$(1),$(2),optimizing,$$(ART_PHONY_TEST_$$(group_uc_host_or_target)_SUFFIX),))
+ ifeq ($(2),host)
+ # For now just test tracing on the host with default.
+ $$(eval $$(call define-test-art-run-test,$(1),$(2),default,$$(ART_PHONY_TEST_$$(group_uc_host_or_target)_SUFFIX),trace))
+ endif
do_second := false
ifeq ($(2),host)
ifneq ($$(HOST_PREFER_32_BIT),true)
@@ -236,9 +287,13 @@ define define-test-art-run-test-group
endif
endif
ifeq (true,$$(do_second))
- $$(eval $$(call define-test-art-run-test,$(1),$(2),default,$$(2ND_ART_PHONY_TEST_$$(group_uc_host_or_target)_SUFFIX)))
- $$(eval $$(call define-test-art-run-test,$(1),$(2),interpreter,$$(2ND_ART_PHONY_TEST_$$(group_uc_host_or_target)_SUFFIX)))
- $$(eval $$(call define-test-art-run-test,$(1),$(2),optimizing,$$(2ND_ART_PHONY_TEST_$$(group_uc_host_or_target)_SUFFIX)))
+ $$(eval $$(call define-test-art-run-test,$(1),$(2),default,$$(2ND_ART_PHONY_TEST_$$(group_uc_host_or_target)_SUFFIX),))
+ $$(eval $$(call define-test-art-run-test,$(1),$(2),interpreter,$$(2ND_ART_PHONY_TEST_$$(group_uc_host_or_target)_SUFFIX),))
+ $$(eval $$(call define-test-art-run-test,$(1),$(2),optimizing,$$(2ND_ART_PHONY_TEST_$$(group_uc_host_or_target)_SUFFIX),))
+ ifeq ($(2),host)
+ # For now just test tracing on the host with default.
+ $$(eval $$(call define-test-art-run-test,$(1),$(2),default,$$(2ND_ART_PHONY_TEST_$$(group_uc_host_or_target)_SUFFIX),trace))
+ endif
endif
$$(eval $$(call define-test-art-run-test-group-rule,test-art-$(2)-run-test-default-$(1), \
@@ -319,6 +374,7 @@ endif
define-test-art-run-test :=
define-test-art-run-test-group-rule :=
define-test-art-run-test-group :=
+all-run-test-names :=
ART_TEST_TARGET_RUN_TEST_ALL_RULES :=
ART_TEST_TARGET_RUN_TEST_DEFAULT_RULES :=
ART_TEST_TARGET_RUN_TEST_INTERPRETER_RULES :=
@@ -335,9 +391,11 @@ ART_TEST_HOST_RUN_TEST_ALL_RULES :=
ART_TEST_HOST_RUN_TEST_DEFAULT_RULES :=
ART_TEST_HOST_RUN_TEST_INTERPRETER_RULES :=
ART_TEST_HOST_RUN_TEST_OPTIMIZING_RULES :=
+ART_TEST_HOST_RUN_TEST_ALL$(ART_PHONY_TEST_HOST_SUFFIX)_RULES :=
ART_TEST_HOST_RUN_TEST_DEFAULT$(ART_PHONY_TEST_HOST_SUFFIX)_RULES :=
ART_TEST_HOST_RUN_TEST_INTERPRETER$(ART_PHONY_TEST_HOST_SUFFIX)_RULES :=
ART_TEST_HOST_RUN_TEST_OPTIMIZING$(ART_PHONY_TEST_HOST_SUFFIX)_RULES :=
+ART_TEST_HOST_RUN_TEST_ALL$(2ND_ART_PHONY_TEST_HOST_SUFFIX)_RULES :=
ART_TEST_HOST_RUN_TEST_DEFAULT$(2ND_ART_PHONY_TEST_HOST_SUFFIX)_RULES :=
ART_TEST_HOST_RUN_TEST_INTERPRETER$(2ND_ART_PHONY_TEST_HOST_SUFFIX)_RULES :=
ART_TEST_HOST_RUN_TEST_OPTIMIZING$(2ND_ART_PHONY_TEST_HOST_SUFFIX)_RULES :=
diff --git a/test/ReferenceMap/stack_walk_refmap_jni.cc b/test/ReferenceMap/stack_walk_refmap_jni.cc
index 87187ed19d..e5a1786102 100644
--- a/test/ReferenceMap/stack_walk_refmap_jni.cc
+++ b/test/ReferenceMap/stack_walk_refmap_jni.cc
@@ -20,12 +20,10 @@
#include "class_linker.h"
#include "dex_file-inl.h"
#include "gc_map.h"
-#include "mirror/art_method.h"
#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/object-inl.h"
-#include "object_utils.h"
#include "scoped_thread_state_change.h"
#include "thread.h"
#include "jni.h"
diff --git a/test/StackWalk/stack_walk_jni.cc b/test/StackWalk/stack_walk_jni.cc
index c849c54bbe..e404f6ab7d 100644
--- a/test/StackWalk/stack_walk_jni.cc
+++ b/test/StackWalk/stack_walk_jni.cc
@@ -19,12 +19,10 @@
#include "class_linker.h"
#include "gc_map.h"
-#include "mirror/art_method.h"
#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/object-inl.h"
-#include "object_utils.h"
#include "jni.h"
#include "scoped_thread_state_change.h"