diff options
78 files changed, 1127 insertions, 835 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_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_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/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/nodes.h b/compiler/optimizing/nodes.h index ca846b32a3..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" 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..3f2f925a02 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" @@ -233,7 +234,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 +461,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 +1231,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 +1250,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..88340222cf 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -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/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/class_linker_test.cc b/runtime/class_linker_test.cc index 7b5a5026df..7930b4876e 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc @@ -36,6 +36,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/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_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/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_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/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_scope.h b/runtime/handle_scope.h index 629e4ecf2f..2fd42d2350 100644 --- a/runtime/handle_scope.h +++ b/runtime/handle_scope.h @@ -27,6 +27,7 @@ namespace art { namespace mirror { class Object; } + class Thread; // HandleScopes can be allocated within the bridge frame between managed and native code backed by 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..e3d32bb75e 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" 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/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..e97512b6cf 100644 --- a/runtime/jni_internal.cc +++ b/runtime/jni_internal.cc @@ -3002,7 +3002,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/mirror/art_method.cc b/runtime/mirror/art_method.cc index 1fa680d148..86bac243a0 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" 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_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/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/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/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/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/proxy_test.cc b/runtime/proxy_test.cc index 093c129add..57eb3f79b6 100644 --- a/runtime/proxy_test.cc +++ b/runtime/proxy_test.cc @@ -14,12 +14,13 @@ * 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 "mirror/art_field-inl.h" +#include "scoped_thread_state_change.h" + namespace art { class ProxyTest : public CommonCompilerTest { 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..41421bc10f 100644 --- a/runtime/reflection.cc +++ b/runtime/reflection.cc @@ -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..4cfd55e5ae 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)); 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..a6cf24e503 100644 --- a/runtime/stack.cc +++ b/runtime/stack.cc @@ -16,6 +16,7 @@ #include "stack.h" +#include "arch/context.h" #include "base/hex_dump.h" #include "mirror/art_method-inl.h" #include "mirror/class-inl.h" @@ -366,9 +367,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 +433,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..dcd4f23b3e 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -40,6 +40,7 @@ #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.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_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/trace.cc b/runtime/trace.cc index 1a450c4cb9..1eb5cf8f87 100644 --- a/runtime/trace.cc +++ b/runtime/trace.cc @@ -115,7 +115,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 +149,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 +462,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..b56bdd0c29 100644 --- a/runtime/utils.cc +++ b/runtime/utils.cc @@ -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_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_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/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" |