diff options
author | 2012-05-01 15:47:55 +0800 | |
---|---|---|
committer | 2012-06-27 03:47:58 -0700 | |
commit | 971bf3f9184010d68b9a3ad30b396fa401af91a3 (patch) | |
tree | 493e80309ce41fd21359da8093fbebfd21b7936c | |
parent | 468a7b1fcb2114ec973e31b5276daea0be62c198 (diff) |
Compile method one-by-one.
Change-Id: Ic56fb397f3bd6dee32372eb875261a3383eaf30c
28 files changed, 592 insertions, 1530 deletions
diff --git a/build/Android.common.mk b/build/Android.common.mk index c4f04be9c6..74bc4a919d 100644 --- a/build/Android.common.mk +++ b/build/Android.common.mk @@ -233,7 +233,6 @@ LIBART_COMMON_SRC_FILES := \ ifeq ($(ART_USE_LLVM_COMPILER),true) LIBART_COMMON_SRC_FILES += \ - src/compiler_llvm/elf_loader.cc \ src/compiler_llvm/inferred_reg_category_map.cc \ src/compiler_llvm/procedure_linkage_table.cc \ src/compiler_llvm/runtime_support_llvm.cc diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk index 9f75115753..d090395d5e 100644 --- a/build/Android.gtest.mk +++ b/build/Android.gtest.mk @@ -63,11 +63,6 @@ define build-art-test LOCAL_SHARED_LIBRARIES += libdynamic_annotations-host endif - ifeq ($(ART_USE_LLVM_COMPILER),true) - LOCAL_C_INCLUDES += frameworks/compile/linkloader - LOCAL_STATIC_LIBRARIES += librsloader - endif - # Mac OS linker doesn't understand --export-dynamic. ifneq ($(HOST_OS)-$$(art_target_or_host),darwin-host) # Allow jni_compiler_test to find Java_MyClassNatives_bar within itself using dlopen(NULL, ...). diff --git a/build/Android.libart-compiler-llvm.mk b/build/Android.libart-compiler-llvm.mk index e2c66e446a..9ec356aaf9 100644 --- a/build/Android.libart-compiler-llvm.mk +++ b/build/Android.libart-compiler-llvm.mk @@ -74,7 +74,7 @@ define build-libart-compiler-llvm endif LOCAL_C_INCLUDES += $(ART_C_INCLUDES) - LOCAL_C_INCLUDES += frameworks/compile/linkloader + libart_compiler_llvm_arm_STATIC_LIBRARIES := \ libLLVMARMInfo \ libLLVMARMDisassembler \ @@ -111,6 +111,7 @@ define build-libart-compiler-llvm endif LOCAL_STATIC_LIBRARIES += \ + libLLVMObject \ libLLVMLinker \ libLLVMipo \ libLLVMBitWriter \ @@ -129,8 +130,8 @@ define build-libart-compiler-llvm libLLVMMC \ libLLVMMCParser \ libLLVMCore \ - libLLVMSupport \ - librsloader + libLLVMSupport + LOCAL_SHARED_LIBRARIES := liblog libnativehelper LOCAL_SHARED_LIBRARIES += libcorkscrew # native stack trace support ifeq ($$(art_target_or_host),target) diff --git a/build/Android.libart.mk b/build/Android.libart.mk index 01fa42ba80..9ccbe3fc37 100644 --- a/build/Android.libart.mk +++ b/build/Android.libart.mk @@ -98,13 +98,6 @@ $$(ENUM_OPERATOR_OUT_GEN): $$(GENERATED_SRC_DIR)/%_operator_out.cc : art/%.h endif endif LOCAL_C_INCLUDES += $(ART_C_INCLUDES) - ifeq ($(ART_USE_LLVM_COMPILER),true) - LOCAL_C_INCLUDES += frameworks/compile/linkloader - LOCAL_STATIC_LIBRARIES += librsloader - endif - ifeq ($(ART_REQUIRE_LLVM),true) - LOCAL_STATIC_LIBRARIES += libLLVMSupport - endif LOCAL_SHARED_LIBRARIES := liblog libnativehelper LOCAL_SHARED_LIBRARIES += libcorkscrew # native stack trace support ifeq ($$(art_target_or_host),target) diff --git a/src/common_test.h b/src/common_test.h index cdcac240ad..58d0219643 100644 --- a/src/common_test.h +++ b/src/common_test.h @@ -177,14 +177,10 @@ class CommonTest : public testing::Test { MakeExecutable(code_array->GetData(), code_array->GetLength()); } -#if !defined(ART_USE_LLVM_COMPILER) // LLVM compilation uses ELF instead static void MakeExecutable(const std::vector<uint8_t>& code) { CHECK_NE(code.size(), 0U); MakeExecutable(&code[0], code.size()); } -#else - static void MakeExecutable(const std::vector<uint8_t>&) {} -#endif // Create an OatMethod based on pointers (for unit tests) OatFile::OatMethod CreateOatMethod(const void* code, @@ -205,13 +201,7 @@ class CommonTest : public testing::Test { reinterpret_cast<uint32_t>(gc_map), reinterpret_cast<uint32_t>(invoke_stub) #if defined(ART_USE_LLVM_COMPILER) - , NULL, - static_cast<uint16_t>(-1u), - static_cast<uint16_t>(-1u), - static_cast<uint16_t>(-1u), - static_cast<uint16_t>(-1u), - static_cast<uint16_t>(-1u), - static_cast<uint16_t>(-1u) + , 0 #endif ); } @@ -224,17 +214,12 @@ class CommonTest : public testing::Test { compiler_->FindInvokeStub(mh.IsStatic(), mh.GetShorty()); CHECK(compiled_invoke_stub != NULL) << PrettyMethod(method); - const Method::InvokeStub* method_invoke_stub = NULL; - if (compiled_invoke_stub->IsExecutableInElf()) { - method_invoke_stub = - compiler_->GetMethodInvokeStubAddr(compiled_invoke_stub, method); - } else { - const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode(); - MakeExecutable(invoke_stub); - method_invoke_stub = reinterpret_cast<const Method::InvokeStub*>( + const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode(); + MakeExecutable(invoke_stub); + const Method::InvokeStub* method_invoke_stub = + reinterpret_cast<const Method::InvokeStub*>( CompiledCode::CodePointer(&invoke_stub[0], compiled_invoke_stub->GetInstructionSet())); - } LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " invoke_stub=" << reinterpret_cast<void*>(method_invoke_stub); @@ -247,14 +232,10 @@ class CommonTest : public testing::Test { method->GetDexMethodIndex())); CHECK(compiled_method != NULL) << PrettyMethod(method); - const void* method_code = NULL; - if (compiled_method->IsExecutableInElf()) { - method_code = compiler_->GetMethodCodeAddr(compiled_method, method); - } else { - const std::vector<uint8_t>& code = compiled_method->GetCode(); - MakeExecutable(code); - method_code = CompiledMethod::CodePointer(&code[0], compiled_method->GetInstructionSet()); - } + const std::vector<uint8_t>& code = compiled_method->GetCode(); + MakeExecutable(code); + const void* method_code = CompiledMethod::CodePointer(&code[0], + compiled_method->GetInstructionSet()); LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code; @@ -380,9 +361,6 @@ class CommonTest : public testing::Test { image_classes_.reset(new std::set<std::string>); compiler_.reset(new Compiler(instruction_set, true, 2, false, image_classes_.get(), true, true)); -#if defined(ART_USE_LLVM_COMPILER) - compiler_->EnableAutoElfLoading(); -#endif Runtime::Current()->GetHeap()->VerifyHeap(); // Check for heap corruption before the test } diff --git a/src/compiled_method.h b/src/compiled_method.h index 7ddde0c730..ca3a597149 100644 --- a/src/compiled_method.h +++ b/src/compiled_method.h @@ -32,22 +32,14 @@ namespace art { class CompiledCode { public: CompiledCode(InstructionSet instruction_set) - : instruction_set_(instruction_set), elf_idx_(-1), elf_func_idx_(-1) { + : instruction_set_(instruction_set) { } CompiledCode(InstructionSet instruction_set, const std::vector<uint8_t>& code) - : instruction_set_(instruction_set), code_(code), elf_idx_(-1), - elf_func_idx_(-1) { + : instruction_set_(instruction_set), code_(code) { CHECK_NE(code.size(), 0U); } - CompiledCode(InstructionSet instruction_set, - uint16_t elf_idx, - uint16_t elf_func_idx) - : instruction_set_(instruction_set), elf_idx_(elf_idx), - elf_func_idx_(elf_func_idx) { - } - InstructionSet GetInstructionSet() const { return instruction_set_; } @@ -57,6 +49,7 @@ class CompiledCode { } void SetCode(const std::vector<uint8_t>& code) { + CHECK_NE(code.size(), 0U); code_ = code; } @@ -64,18 +57,6 @@ class CompiledCode { return (code_ == rhs.code_); } - bool IsExecutableInElf() const { - return (elf_idx_ != static_cast<uint16_t>(-1u)); - } - - uint16_t GetElfIndex() const { - return elf_idx_; - } - - uint16_t GetElfFuncIndex() const { - return elf_func_idx_; - } - // To align an offset from a page-aligned value to make it suitable // for code storage. For example on ARM, to ensure that PC relative // valu computations work out as expected. @@ -95,10 +76,6 @@ class CompiledCode { private: const InstructionSet instruction_set_; std::vector<uint8_t> code_; - - // LLVM-specific fields - uint16_t elf_idx_; - uint16_t elf_func_idx_; }; class CompiledMethod : public CompiledCode { @@ -124,9 +101,8 @@ class CompiledMethod : public CompiledCode { // Constructs a CompiledMethod for the LLVM compiler. CompiledMethod(InstructionSet instruction_set, - uint16_t elf_idx, - uint16_t elf_func_idx) - : CompiledCode(instruction_set, elf_idx, elf_func_idx), + const std::vector<uint8_t>& code) + : CompiledCode(instruction_set, code), frame_size_in_bytes_(kStackAlignment), core_spill_mask_(0), fp_spill_mask_(0) { } @@ -162,12 +138,6 @@ class CompiledInvokeStub : public CompiledCode { explicit CompiledInvokeStub(InstructionSet instruction_set, const std::vector<uint8_t>& code); - explicit CompiledInvokeStub(InstructionSet instruction_set, - uint16_t elf_idx, - uint16_t elf_func_idx) - : CompiledCode(instruction_set, elf_idx, elf_func_idx) { - } - ~CompiledInvokeStub(); }; diff --git a/src/compiler.cc b/src/compiler.cc index a726606013..272ba9efcb 100644 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -319,14 +319,8 @@ Compiler::Compiler(InstructionSet instruction_set, bool image, size_t thread_cou compiler_(NULL), compiler_context_(NULL), jni_compiler_(NULL), -#if !defined(ART_USE_LLVM_COMPILER) - create_invoke_stub_(NULL) { -#else - create_invoke_stub_(NULL), - compiler_enable_auto_elf_loading_(NULL), - compiler_get_method_code_addr_(NULL), - compiler_get_method_invoke_stub_addr_(NULL) { -#endif + create_invoke_stub_(NULL) +{ std::string compiler_so_name(MakeCompilerSoName(instruction_set_)); compiler_library_ = dlopen(compiler_so_name.c_str(), RTLD_LAZY); if (compiler_library_ == NULL) { @@ -353,12 +347,6 @@ Compiler::Compiler(InstructionSet instruction_set, bool image, size_t thread_cou #if defined(ART_USE_LLVM_COMPILER) create_proxy_stub_ = FindFunction<CreateProxyStubFn>( compiler_so_name, compiler_library_, "ArtCreateProxyStub"); - compiler_enable_auto_elf_loading_ = FindFunction<CompilerEnableAutoElfLoadingFn>( - compiler_so_name, compiler_library_, "compilerLLVMEnableAutoElfLoading"); - compiler_get_method_code_addr_ = FindFunction<CompilerGetMethodCodeAddrFn>( - compiler_so_name, compiler_library_, "compilerLLVMGetMethodCodeAddr"); - compiler_get_method_invoke_stub_addr_ = FindFunction<CompilerGetMethodInvokeStubAddrFn>( - compiler_so_name, compiler_library_, "compilerLLVMGetMethodInvokeStubAddr"); #endif CHECK(!Runtime::Current()->IsStarted()); @@ -395,10 +383,17 @@ Compiler::~Compiler() { STLDeleteElements(&methods_to_patch_); } #if defined(ART_USE_LLVM_COMPILER) - CompilerCallbackFn f = FindFunction<CompilerCallbackFn>(MakeCompilerSoName(instruction_set_), - compiler_library_, - "compilerLLVMDispose"); - (*f)(*this); + // Uninitialize compiler_context_ + typedef void (*UninitCompilerContextFn)(Compiler&); + + std::string compiler_so_name(MakeCompilerSoName(instruction_set_)); + + UninitCompilerContextFn uninit_compiler_context = + FindFunction<void (*)(Compiler&)>(compiler_so_name, + compiler_library_, + "ArtUnInitCompilerContext"); + + uninit_compiler_context(*this); #endif if (compiler_library_ != NULL) { VLOG(compiler) << "dlclose(" << compiler_library_ << ")"; @@ -511,12 +506,6 @@ void Compiler::PreCompile(ClassLoader* class_loader, void Compiler::PostCompile(ClassLoader* class_loader, const std::vector<const DexFile*>& dex_files) { SetGcMaps(class_loader, dex_files); -#if defined(ART_USE_LLVM_COMPILER) - CompilerCallbackFn f = FindFunction<CompilerCallbackFn>(MakeCompilerSoName(instruction_set_), - compiler_library_, - "compilerLLVMMaterializeRemainder"); - (*f)(*this); -#endif } bool Compiler::IsImageClass(const std::string& descriptor) const { @@ -1683,31 +1672,4 @@ void Compiler::SetBitcodeFileName(std::string const& filename) { } #endif -#if defined(ART_USE_LLVM_COMPILER) -void Compiler::EnableAutoElfLoading() { - compiler_enable_auto_elf_loading_(*this); -} - -const void* Compiler::GetMethodCodeAddr(const CompiledMethod* cm, - const Method* method) const { - return compiler_get_method_code_addr_(*this, cm, method); -} - -const Method::InvokeStub* Compiler::GetMethodInvokeStubAddr(const CompiledInvokeStub* cm, - const Method* method) const { - return compiler_get_method_invoke_stub_addr_(*this, cm, method); -} - -std::vector<ElfImage> Compiler::GetElfImages() const { - typedef std::vector<ElfImage> (*GetElfImagesFn)(const Compiler&); - - GetElfImagesFn get_elf_images = - FindFunction<GetElfImagesFn>(MakeCompilerSoName(instruction_set_), - compiler_library_, - "compilerLLVMGetElfImages"); - - return get_elf_images(*this); -} -#endif - } // namespace art diff --git a/src/compiler.h b/src/compiler.h index 5202967323..46d3647ac2 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -25,7 +25,6 @@ #include "compiled_method.h" #include "dex_cache.h" #include "dex_file.h" -#include "elf_image.h" #include "instruction_set.h" #include "invoke_type.h" #include "oat_file.h" @@ -146,34 +145,6 @@ class Compiler { void SetBitcodeFileName(std::string const& filename); #endif -#if defined(ART_USE_LLVM_COMPILER) - void EnableAutoElfLoading(); - - const void* GetMethodCodeAddr(const CompiledMethod* cm, - const Method* method) const; - - const Method::InvokeStub* GetMethodInvokeStubAddr(const CompiledInvokeStub* cm, - const Method* method) const; - - std::vector<ElfImage> GetElfImages() const; -#else - void EnableAutoElfLoader() { } - - const void* GetMethodCodeAddr(const CompiledMethod*, - const Method*) const { - return NULL; - } - - const Method::InvokeStub* GetMethodInvokeStubAddr(const CompiledInvokeStub*, - const Method*) const { - return NULL; - } - - std::vector<ElfImage> GetElfImages() const { - return std::vector<ElfImage>(); - } -#endif - void SetCompilerContext(void* compiler_context) { compiler_context_ = compiler_context; } diff --git a/src/compiler_llvm/compilation_unit.cc b/src/compiler_llvm/compilation_unit.cc index 38faf618cf..fdbf575c0f 100644 --- a/src/compiler_llvm/compilation_unit.cc +++ b/src/compiler_llvm/compilation_unit.cc @@ -17,6 +17,7 @@ #include "compilation_unit.h" #include "compiled_method.h" +#include "compiler_llvm.h" #include "file.h" #include "instruction_set.h" #include "ir_builder.h" @@ -47,8 +48,10 @@ #include <llvm/DerivedTypes.h> #include <llvm/LLVMContext.h> #include <llvm/Module.h> +#include <llvm/Object/ObjectFile.h> #include <llvm/PassManager.h> #include <llvm/Support/Debug.h> +#include <llvm/Support/ELF.h> #include <llvm/Support/FormattedStream.h> #include <llvm/Support/ManagedStatic.h> #include <llvm/Support/MemoryBuffer.h> @@ -77,37 +80,6 @@ namespace { -class UpdateFrameSizePass : public llvm::MachineFunctionPass { - public: - static char ID; - - UpdateFrameSizePass() : llvm::MachineFunctionPass(ID), cunit_(NULL) { - LOG(FATAL) << "Unexpected instantiation of UpdateFrameSizePass"; - // NOTE: We have to declare this constructor for llvm::RegisterPass, but - // this constructor won't work because we have no information on - // CompilationUnit. Thus, we should place a LOG(FATAL) here. - } - - UpdateFrameSizePass(art::compiler_llvm::CompilationUnit* cunit) - : llvm::MachineFunctionPass(ID), cunit_(cunit) { - } - - virtual bool runOnMachineFunction(llvm::MachineFunction &MF) { - cunit_->UpdateFrameSizeInBytes(MF.getFunction(), - MF.getFrameInfo()->getStackSize()); - return false; - } - - private: - art::compiler_llvm::CompilationUnit* cunit_; -}; - -char UpdateFrameSizePass::ID = 0; - -llvm::RegisterPass<UpdateFrameSizePass> reg_update_frame_size_pass_( - "update-frame-size", "Update frame size pass", false, false); - - // TODO: We may need something to manage these passes. // TODO: We need high-level IR to analysis and do this at the IRBuilder level. class AddSuspendCheckToLoopLatchPass : public llvm::LoopPass { @@ -167,10 +139,10 @@ namespace compiler_llvm { llvm::Module* makeLLVMModuleContents(llvm::Module* module); -CompilationUnit::CompilationUnit(InstructionSet insn_set, size_t elf_idx) -: cunit_lock_("compilation_unit_lock"), insn_set_(insn_set), elf_idx_(elf_idx), - context_(new llvm::LLVMContext()), compiled_methods_map_(new CompiledMethodMap()), - mem_usage_(0), num_elf_funcs_(0) { +CompilationUnit::CompilationUnit(const CompilerLLVM* compiler_llvm, + size_t cunit_idx) +: compiler_llvm_(compiler_llvm), cunit_idx_(cunit_idx), + context_(new llvm::LLVMContext()) { // Create the module and include the runtime function declaration module_ = new llvm::Module("art", *context_); @@ -180,7 +152,7 @@ CompilationUnit::CompilationUnit(InstructionSet insn_set, size_t elf_idx) irb_.reset(new IRBuilder(*context_, *module_)); // We always need a switch case, so just use a normal function. - switch(insn_set_) { + switch(GetInstructionSet()) { default: runtime_support_.reset(new RuntimeSupportBuilder(*context_, *module_, *irb_)); break; @@ -205,57 +177,56 @@ CompilationUnit::~CompilationUnit() { } -bool CompilationUnit::Materialize(size_t thread_count) { - MutexLock GUARD(cunit_lock_); +InstructionSet CompilationUnit::GetInstructionSet() const { + return compiler_llvm_->GetInstructionSet(); +} - // Materialize the bitcode to elf_image_ - llvm::raw_string_ostream str_os(elf_image_); - bool success = MaterializeToFile(str_os); - LOG(INFO) << "Compilation Unit: " << elf_idx_ << (success ? " (done)" : " (failed)"); - // Free the resources - context_.reset(NULL); - irb_.reset(NULL); - module_ = NULL; - runtime_support_.reset(NULL); - compiled_methods_map_.reset(NULL); +bool CompilationUnit::Materialize() { + std::string elf_image; - return success; -} + // Compile and prelink llvm::Module + if (!MaterializeToString(elf_image)) { + LOG(ERROR) << "Failed to materialize compilation unit " << cunit_idx_; + DeleteResources(); + return false; + } +#if 0 + // Dump the ELF image for debugging + std::string filename(StringPrintf("%s/Art%zu.elf", + GetArtCacheOrDie(GetAndroidData()).c_str(), + cunit_idx_)); + UniquePtr<File> output(OS::OpenFile(filename.c_str(), true)); + output->WriteFully(elf_image.data(), elf_image.size()); +#endif + + // Extract the .text section and prelink the code + if (!ExtractCodeAndPrelink(elf_image)) { + LOG(ERROR) << "Failed to extract code from compilation unit " << cunit_idx_; + DeleteResources(); + return false; + } -void CompilationUnit::RegisterCompiledMethod(const llvm::Function* func, - CompiledMethod* compiled_method) { - MutexLock GUARD(cunit_lock_); - compiled_methods_map_->Put(func, compiled_method); + DeleteResources(); + return true; } -void CompilationUnit::UpdateFrameSizeInBytes(const llvm::Function* func, - size_t frame_size_in_bytes) { - MutexLock GUARD(cunit_lock_); - SafeMap<const llvm::Function*, CompiledMethod*>::iterator iter = - compiled_methods_map_->find(func); - - if (iter != compiled_methods_map_->end()) { - CompiledMethod* compiled_method = iter->second; - compiled_method->SetFrameSizeInBytes(frame_size_in_bytes); - - if (frame_size_in_bytes > 1728u) { - LOG(WARNING) << "Huge frame size: " << frame_size_in_bytes - << " elf_idx=" << compiled_method->GetElfIndex() - << " elf_func_idx=" << compiled_method->GetElfFuncIndex(); - } - } +bool CompilationUnit::MaterializeToString(std::string& str_buffer) { + llvm::raw_string_ostream str_os(str_buffer); + return MaterializeToRawOStream(str_os); } -bool CompilationUnit::MaterializeToFile(llvm::raw_ostream& out_stream) { + +bool CompilationUnit::MaterializeToRawOStream(llvm::raw_ostream& out_stream) { // Lookup the LLVM target char const* target_triple = NULL; char const* target_cpu = ""; char const* target_attr = NULL; - switch (insn_set_) { + InstructionSet insn_set = GetInstructionSet(); + switch (insn_set) { case kThumb2: target_triple = "thumb-none-linux-gnueabi"; target_cpu = "cortex-a9"; @@ -281,7 +252,7 @@ bool CompilationUnit::MaterializeToFile(llvm::raw_ostream& out_stream) { break; default: - LOG(FATAL) << "Unknown instruction set: " << insn_set_; + LOG(FATAL) << "Unknown instruction set: " << insn_set; } std::string errmsg; @@ -375,11 +346,6 @@ bool CompilationUnit::MaterializeToFile(llvm::raw_ostream& out_stream) { return false; } - // FIXME: Unable to run the UpdateFrameSizePass pass since it tries to - // update the value reside in the different address space. - // Add pass to update the frame_size_in_bytes_ - //pm.add(new ::UpdateFrameSizePass(this)); - // Run the per-function optimization fpm.doInitialization(); for (llvm::Module::iterator F = module_->begin(), E = module_->end(); @@ -395,5 +361,130 @@ bool CompilationUnit::MaterializeToFile(llvm::raw_ostream& out_stream) { return true; } + +bool CompilationUnit::ExtractCodeAndPrelink(const std::string& elf_image) { + llvm::OwningPtr<llvm::MemoryBuffer> elf_image_buff( + llvm::MemoryBuffer::getMemBuffer(llvm::StringRef(elf_image.data(), + elf_image.size()))); + + llvm::OwningPtr<llvm::object::ObjectFile> elf_file( + llvm::object::ObjectFile::createELFObjectFile(elf_image_buff.take())); + + llvm::error_code ec; + + const ProcedureLinkageTable& plt = compiler_llvm_->GetProcedureLinkageTable(); + + for (llvm::object::section_iterator + sec_iter = elf_file->begin_sections(), + sec_end = elf_file->end_sections(); + sec_iter != sec_end; sec_iter.increment(ec)) { + + CHECK(ec == 0) << "Failed to read section because " << ec.message(); + + // Read the section information + llvm::StringRef name; + uint64_t alignment = 0u; + uint64_t size = 0u; + + CHECK(sec_iter->getName(name) == 0); + CHECK(sec_iter->getSize(size) == 0); + CHECK(sec_iter->getAlignment(alignment) == 0); + + if (name == ".data" || name == ".bss" || name == ".rodata") { + if (size > 0) { + LOG(FATAL) << "Compilation unit " << cunit_idx_ << " has non-empty " + << name.str() << " section"; + } + + } else if (name == "" || name == ".rel.text" || + name == ".ARM.attributes" || name == ".symtab" || + name == ".strtab" || name == ".shstrtab") { + // We can ignore these sections. We don't have to copy them into + // the result Oat file. + + } else if (name == ".text") { + // Ensure the alignment requirement is less than or equal to + // kArchAlignment + CheckCodeAlign(alignment); + + // Copy the compiled code + llvm::StringRef contents; + CHECK(sec_iter->getContents(contents) == 0); + + copy(contents.data(), + contents.data() + contents.size(), + back_inserter(compiled_code_)); + + // Prelink the compiled code + for (llvm::object::relocation_iterator + rel_iter = sec_iter->begin_relocations(), + rel_end = sec_iter->end_relocations(); rel_iter != rel_end; + rel_iter.increment(ec)) { + + CHECK(ec == 0) << "Failed to read relocation because " << ec.message(); + + // Read the relocation information + llvm::object::SymbolRef sym_ref; + uint64_t rel_offset = 0; + uint64_t rel_type = 0; + int64_t rel_addend = 0; + + CHECK(rel_iter->getSymbol(sym_ref) == 0); + CHECK(rel_iter->getOffset(rel_offset) == 0); + CHECK(rel_iter->getType(rel_type) == 0); + CHECK(rel_iter->getAdditionalInfo(rel_addend) == 0); + + // Read the symbol related to this relocation fixup + llvm::StringRef sym_name; + CHECK(sym_ref.getName(sym_name) == 0); + + // Relocate the fixup. + // TODO: Support more relocation type. + CHECK(rel_type == llvm::ELF::R_ARM_ABS32); + CHECK_LE(rel_offset + 4, compiled_code_.size()); + + uintptr_t dest_addr = plt.GetEntryAddress(sym_name.str().c_str()); + uintptr_t final_addr = dest_addr + rel_addend; + compiled_code_[rel_offset] = final_addr & 0xff; + compiled_code_[rel_offset + 1] = (final_addr >> 8) & 0xff; + compiled_code_[rel_offset + 2] = (final_addr >> 16) & 0xff; + compiled_code_[rel_offset + 3] = (final_addr >> 24) & 0xff; + } + + } else { + LOG(WARNING) << "Unexpected section: " << name.str(); + } + } + + return true; +} + + +// Check whether the align is less than or equal to the code alignment of +// that architecture. Since the Oat writer only guarantee that the compiled +// method being aligned to kArchAlignment, we have no way to align the ELf +// section if the section alignment is greater than kArchAlignment. +void CompilationUnit::CheckCodeAlign(uint32_t align) const { + InstructionSet insn_set = GetInstructionSet(); + switch (insn_set) { + case kThumb2: + case kArm: + CHECK_LE(align, static_cast<uint32_t>(kArmAlignment)); + break; + + case kX86: + CHECK_LE(align, static_cast<uint32_t>(kX86Alignment)); + break; + + case kMips: + CHECK_LE(align, static_cast<uint32_t>(kMipsAlignment)); + break; + + default: + LOG(FATAL) << "Unknown instruction set: " << insn_set; + } +} + + } // namespace compiler_llvm } // namespace art diff --git a/src/compiler_llvm/compilation_unit.h b/src/compiler_llvm/compilation_unit.h index d391620798..576b65f8b3 100644 --- a/src/compiler_llvm/compilation_unit.h +++ b/src/compiler_llvm/compilation_unit.h @@ -18,7 +18,6 @@ #define ART_SRC_COMPILER_LLVM_COMPILATION_UNIT_H_ #include "../mutex.h" -#include "elf_image.h" #include "globals.h" #include "instruction_set.h" #include "logging.h" @@ -44,81 +43,52 @@ namespace llvm { namespace art { namespace compiler_llvm { +class CompilerLLVM; class IRBuilder; class CompilationUnit { public: - CompilationUnit(InstructionSet insn_set, size_t elf_idx); + CompilationUnit(const CompilerLLVM* compiler_llvm, + size_t cunit_idx); ~CompilationUnit(); - size_t GetElfIndex() const { - return elf_idx_; + size_t GetIndex() const { + return cunit_idx_; } - InstructionSet GetInstructionSet() const { - cunit_lock_.AssertHeld(); - return insn_set_; - } + InstructionSet GetInstructionSet() const; llvm::LLVMContext* GetLLVMContext() const { - cunit_lock_.AssertHeld(); return context_.get(); } llvm::Module* GetModule() const { - cunit_lock_.AssertHeld(); return module_; } IRBuilder* GetIRBuilder() const { - cunit_lock_.AssertHeld(); return irb_.get(); } - ElfImage GetElfImage() const { - MutexLock GUARD(cunit_lock_); - CHECK_GT(elf_image_.size(), 0u); - return ElfImage(elf_image_); - } - - uint16_t AcquireUniqueElfFuncIndex() { - cunit_lock_.AssertHeld(); - CHECK(num_elf_funcs_ < UINT16_MAX); - return num_elf_funcs_++; - } - void SetBitcodeFileName(const std::string& bitcode_filename) { - MutexLock GUARD(cunit_lock_); bitcode_filename_ = bitcode_filename; } - bool Materialize(size_t thread_count); + bool Materialize(); bool IsMaterialized() const { - MutexLock GUARD(cunit_lock_); return (context_.get() == NULL); } - bool IsMaterializeThresholdReached() const { - MutexLock GUARD(cunit_lock_); - return (mem_usage_ > 1000000u); // (threshold: 1 MB) - } - - void AddMemUsageApproximation(size_t usage) { - MutexLock GUARD(cunit_lock_); - mem_usage_ += usage; + const std::vector<uint8_t>& GetCompiledCode() const { + DCHECK(IsMaterialized()); + return compiled_code_; } - void RegisterCompiledMethod(const llvm::Function* func, CompiledMethod* cm); - - void UpdateFrameSizeInBytes(const llvm::Function* func, size_t frame_size_in_bytes); - - mutable Mutex cunit_lock_; - private: - InstructionSet insn_set_; - const size_t elf_idx_; + const CompilerLLVM* compiler_llvm_; + const size_t cunit_idx_; UniquePtr<llvm::LLVMContext> context_; UniquePtr<IRBuilder> irb_; @@ -126,15 +96,24 @@ class CompilationUnit { llvm::Module* module_; std::string bitcode_filename_; - std::string elf_image_; - typedef SafeMap<const llvm::Function*, CompiledMethod*> CompiledMethodMap; - UniquePtr<CompiledMethodMap> compiled_methods_map_; + std::vector<uint8_t> compiled_code_; + + SafeMap<const llvm::Function*, CompiledMethod*> compiled_methods_map_; + + void CheckCodeAlign(uint32_t offset) const; + + void DeleteResources() { + module_ = NULL; // Managed by context_ + context_.reset(NULL); + irb_.reset(NULL); + runtime_support_.reset(NULL); + } - size_t mem_usage_; - uint16_t num_elf_funcs_; + bool MaterializeToString(std::string& str_buffer); + bool MaterializeToRawOStream(llvm::raw_ostream& out_stream); - bool MaterializeToFile(llvm::raw_ostream& out_stream); + bool ExtractCodeAndPrelink(const std::string& elf_image); }; } // namespace compiler_llvm diff --git a/src/compiler_llvm/compiler_llvm.cc b/src/compiler_llvm/compiler_llvm.cc index 6c8188ef6f..b793fbda64 100644 --- a/src/compiler_llvm/compiler_llvm.cc +++ b/src/compiler_llvm/compiler_llvm.cc @@ -22,8 +22,6 @@ #include "compiled_method.h" #include "compiler.h" #include "dex_cache.h" -#include "elf_image.h" -#include "elf_loader.h" #include "ir_builder.h" #include "jni_compiler.h" #include "method_compiler.h" @@ -95,9 +93,9 @@ llvm::Module* makeLLVMModuleContents(llvm::Module* module); CompilerLLVM::CompilerLLVM(Compiler* compiler, InstructionSet insn_set) - : compiler_(compiler), compiler_lock_("llvm_compiler_lock"), - insn_set_(insn_set), curr_cunit_(NULL) { - + : compiler_(compiler), insn_set_(insn_set), + num_cunits_lock_("compilation unit counter lock"), num_cunits_(0), + plt_(insn_set) { // Initialize LLVM libraries pthread_once(&llvm_initialized, InitializeLLVM); @@ -105,152 +103,21 @@ CompilerLLVM::CompilerLLVM(Compiler* compiler, InstructionSet insn_set) CompilerLLVM::~CompilerLLVM() { - STLDeleteElements(&cunits_); -} - - -void CompilerLLVM::EnsureCompilationUnit() { - compiler_lock_.AssertHeld(); - - if (curr_cunit_ != NULL) { - return; - } - - // Allocate compilation unit - size_t cunit_idx = cunits_.size(); - curr_cunit_ = new CompilationUnit(insn_set_, cunit_idx); - - // Register compilation unit - cunits_.push_back(curr_cunit_); -} - - -void CompilerLLVM::MaterializeRemainder() { - compiler_lock_.Lock(); - // Localize - CompilationUnit* cunit = curr_cunit_; - // Reset the curr_cuit_ - curr_cunit_ = NULL; - compiler_lock_.Unlock(); - - if (cunit != NULL) { - Materialize(cunit); - } -} - - -void CompilerLLVM::MaterializeIfThresholdReached() { - compiler_lock_.Lock(); - // Localize - CompilationUnit* cunit = curr_cunit_; - - if (curr_cunit_ != NULL && curr_cunit_->IsMaterializeThresholdReached()) { - // Delete the compilation unit - curr_cunit_ = NULL; - } else { - // Reset cunit such that Materialize() won't be invoked - cunit = NULL; - } - - compiler_lock_.Unlock(); - - if (cunit != NULL) { - Materialize(cunit); - } } -void CompilerLLVM::Materialize(CompilationUnit* cunit) { - DCHECK(cunit != NULL); - DCHECK(!cunit->IsMaterialized()); - - // Write bitcode to file when filename is set - if (IsBitcodeFileNameAvailable()) { - const size_t cunit_idx = cunits_.size(); - cunit->SetBitcodeFileName( - StringPrintf("%s-%zu", bitcode_filename_.c_str(), cunit_idx)); - } - - // Materialize the llvm::Module into ELF object file - cunit->Materialize(compiler_->GetThreadCount()); - - // Load ELF image when automatic ELF loading is enabled - if (IsAutoElfLoadingEnabled()) { - LoadElfFromCompilationUnit(cunit); - } -} - - -void CompilerLLVM::EnableAutoElfLoading() { - MutexLock GUARD(compiler_lock_); - - if (IsAutoElfLoadingEnabled()) { - // If there is an existing ELF loader, then do nothing. - // Because the existing ELF loader may have returned some code address - // already. If we replace the existing ELF loader with - // elf_loader_.reset(...), then it is possible to have some dangling - // pointer. - return; - } - - // Create ELF loader and load the materialized CompilationUnit - elf_loader_.reset(new ElfLoader()); - - for (size_t i = 0; i < cunits_.size(); ++i) { - if (cunits_[i]->IsMaterialized()) { - LoadElfFromCompilationUnit(cunits_[i]); - } - } -} - - -void CompilerLLVM::LoadElfFromCompilationUnit(const CompilationUnit* cunit) { - MutexLock GUARD(compiler_lock_); - DCHECK(cunit->IsMaterialized()) << cunit->GetElfIndex(); - - if (!elf_loader_->LoadElfAt(cunit->GetElfIndex(), - cunit->GetElfImage(), - OatFile::kRelocAll)) { - LOG(ERROR) << "Failed to load ELF from compilation unit " - << cunit->GetElfIndex(); - } -} - - -const void* CompilerLLVM::GetMethodCodeAddr(const CompiledMethod* cm) const { - return elf_loader_->GetMethodCodeAddr(cm->GetElfIndex(), - cm->GetElfFuncIndex()); -} - - -const Method::InvokeStub* CompilerLLVM:: -GetMethodInvokeStubAddr(const CompiledInvokeStub* cm) const { - return elf_loader_->GetMethodInvokeStubAddr(cm->GetElfIndex(), - cm->GetElfFuncIndex()); -} - - -std::vector<ElfImage> CompilerLLVM::GetElfImages() const { - std::vector<ElfImage> result; - - for (size_t i = 0; i < cunits_.size(); ++i) { - result.push_back(cunits_[i]->GetElfImage()); - } - - return result; +CompilationUnit* CompilerLLVM::AllocateCompilationUnit() { + MutexLock GUARD(num_cunits_lock_); + return new CompilationUnit(this, num_cunits_++); } CompiledMethod* CompilerLLVM:: CompileDexMethod(OatCompilationUnit* oat_compilation_unit) { - MutexLock GUARD(compiler_lock_); - - EnsureCompilationUnit(); - - MutexLock GUARD_CUNIT(curr_cunit_->cunit_lock_); + UniquePtr<CompilationUnit> cunit(AllocateCompilationUnit()); UniquePtr<MethodCompiler> method_compiler( - new MethodCompiler(curr_cunit_, compiler_, oat_compilation_unit)); + new MethodCompiler(cunit.get(), compiler_, oat_compilation_unit)); return method_compiler->Compile(); } @@ -258,14 +125,10 @@ CompileDexMethod(OatCompilationUnit* oat_compilation_unit) { CompiledMethod* CompilerLLVM:: CompileNativeMethod(OatCompilationUnit* oat_compilation_unit) { - MutexLock GUARD(compiler_lock_); - - EnsureCompilationUnit(); - - MutexLock GUARD_CUNIT(curr_cunit_->cunit_lock_); + UniquePtr<CompilationUnit> cunit(AllocateCompilationUnit()); UniquePtr<JniCompiler> jni_compiler( - new JniCompiler(curr_cunit_, *compiler_, oat_compilation_unit)); + new JniCompiler(cunit.get(), *compiler_, oat_compilation_unit)); return jni_compiler->Compile(); } @@ -273,28 +136,20 @@ CompileNativeMethod(OatCompilationUnit* oat_compilation_unit) { CompiledInvokeStub* CompilerLLVM::CreateInvokeStub(bool is_static, char const *shorty) { - MutexLock GUARD(compiler_lock_); - - EnsureCompilationUnit(); - - MutexLock GUARD_CUNIT(curr_cunit_->cunit_lock_); + UniquePtr<CompilationUnit> cunit(AllocateCompilationUnit()); UniquePtr<StubCompiler> stub_compiler( - new StubCompiler(curr_cunit_, *compiler_)); + new StubCompiler(cunit.get(), *compiler_)); return stub_compiler->CreateInvokeStub(is_static, shorty); } CompiledInvokeStub* CompilerLLVM::CreateProxyStub(char const *shorty) { - MutexLock GUARD(compiler_lock_); - - EnsureCompilationUnit(); - - MutexLock GUARD_CUNIT(curr_cunit_->cunit_lock_); + UniquePtr<CompilationUnit> cunit(AllocateCompilationUnit()); UniquePtr<StubCompiler> stub_compiler( - new StubCompiler(curr_cunit_, *compiler_)); + new StubCompiler(cunit.get(), *compiler_)); return stub_compiler->CreateProxyStub(shorty); } @@ -324,6 +179,11 @@ extern "C" void ArtInitCompilerContext(art::Compiler& compiler) { compiler.SetCompilerContext(compiler_llvm); } +extern "C" void ArtUnInitCompilerContext(art::Compiler& compiler) { + delete ContextOf(compiler); + compiler.SetCompilerContext(NULL); +} + extern "C" art::CompiledMethod* ArtCompileMethod(art::Compiler& compiler, const art::DexFile::CodeItem* code_item, uint32_t access_flags, uint32_t method_idx, @@ -338,7 +198,6 @@ extern "C" art::CompiledMethod* ArtCompileMethod(art::Compiler& compiler, method_idx, access_flags); art::compiler_llvm::CompilerLLVM* compiler_llvm = ContextOf(compiler); art::CompiledMethod* result = compiler_llvm->CompileDexMethod(&oat_compilation_unit); - compiler_llvm->MaterializeIfThresholdReached(); return result; } @@ -354,7 +213,6 @@ extern "C" art::CompiledMethod* ArtJniCompileMethod(art::Compiler& compiler, art::compiler_llvm::CompilerLLVM* compiler_llvm = ContextOf(compiler); art::CompiledMethod* result = compiler_llvm->CompileNativeMethod(&oat_compilation_unit); - compiler_llvm->MaterializeIfThresholdReached(); return result; } @@ -364,7 +222,6 @@ extern "C" art::CompiledInvokeStub* ArtCreateInvokeStub(art::Compiler& compiler, uint32_t shorty_len) { art::compiler_llvm::CompilerLLVM* compiler_llvm = ContextOf(compiler); art::CompiledInvokeStub* result = compiler_llvm->CreateInvokeStub(is_static, shorty); - compiler_llvm->MaterializeIfThresholdReached(); return result; } @@ -373,7 +230,6 @@ extern "C" art::CompiledInvokeStub* ArtCreateProxyStub(art::Compiler& compiler, uint32_t shorty_len) { art::compiler_llvm::CompilerLLVM* compiler_llvm = ContextOf(compiler); art::CompiledInvokeStub* result = compiler_llvm->CreateProxyStub(shorty); - compiler_llvm->MaterializeIfThresholdReached(); return result; } @@ -381,37 +237,3 @@ extern "C" void compilerLLVMSetBitcodeFileName(art::Compiler& compiler, std::string const& filename) { ContextOf(compiler)->SetBitcodeFileName(filename); } - -extern "C" void compilerLLVMMaterializeRemainder(art::Compiler& compiler) { - ContextOf(compiler)->MaterializeRemainder(); -} - -extern "C" void compilerLLVMEnableAutoElfLoading(art::Compiler& compiler) { - art::compiler_llvm::CompilerLLVM* compiler_llvm = - reinterpret_cast<art::compiler_llvm::CompilerLLVM*>(compiler.GetCompilerContext()); - return compiler_llvm->EnableAutoElfLoading(); -} - -extern "C" const void* compilerLLVMGetMethodCodeAddr(const art::Compiler& compiler, - const art::CompiledMethod* cm, - const art::Method*) { - const art::compiler_llvm::CompilerLLVM* compiler_llvm = - reinterpret_cast<const art::compiler_llvm::CompilerLLVM*>(compiler.GetCompilerContext()); - return compiler_llvm->GetMethodCodeAddr(cm); -} - -extern "C" const art::Method::InvokeStub* compilerLLVMGetMethodInvokeStubAddr(const art::Compiler& compiler, - const art::CompiledInvokeStub* cm, - const art::Method*) { - const art::compiler_llvm::CompilerLLVM* compiler_llvm = - reinterpret_cast<const art::compiler_llvm::CompilerLLVM*>(compiler.GetCompilerContext()); - return compiler_llvm->GetMethodInvokeStubAddr(cm); -} - -extern "C" std::vector<art::ElfImage> compilerLLVMGetElfImages(const art::Compiler& compiler) { - return ContextOf(compiler)->GetElfImages(); -} - -extern "C" void compilerLLVMDispose(art::Compiler& compiler) { - delete ContextOf(compiler); -} diff --git a/src/compiler_llvm/compiler_llvm.h b/src/compiler_llvm/compiler_llvm.h index 7cc4a0e42d..24a766e2f4 100644 --- a/src/compiler_llvm/compiler_llvm.h +++ b/src/compiler_llvm/compiler_llvm.h @@ -19,10 +19,10 @@ #include "compiler.h" #include "dex_file.h" -#include "elf_image.h" #include "instruction_set.h" #include "macros.h" #include "object.h" +#include "procedure_linkage_table.h" #include <UniquePtr.h> @@ -54,7 +54,6 @@ namespace art { namespace compiler_llvm { class CompilationUnit; -class ElfLoader; class IRBuilder; class CompilerLLVM { @@ -63,10 +62,6 @@ class CompilerLLVM { ~CompilerLLVM(); - void MaterializeIfThresholdReached(); - - void MaterializeRemainder(); - Compiler* GetCompiler() const { return compiler_; } @@ -75,31 +70,10 @@ class CompilerLLVM { return insn_set_; } - size_t GetNumCompilationUnits() const { - return cunits_.size(); - } - - const CompilationUnit* GetCompilationUnit(size_t i) const { - return cunits_[i]; - } - void SetBitcodeFileName(std::string const& filename) { bitcode_filename_ = filename; } - void EnableAutoElfLoading(); - - bool IsAutoElfLoadingEnabled() const { - return (elf_loader_.get() != NULL); - } - - const void* GetMethodCodeAddr(const CompiledMethod* cm) const; - - const Method::InvokeStub* GetMethodInvokeStubAddr( - const CompiledInvokeStub* cm) const; - - std::vector<ElfImage> GetElfImages() const; - CompiledMethod* CompileDexMethod(OatCompilationUnit* oat_compilation_unit); CompiledMethod* CompileNativeMethod(OatCompilationUnit* oat_compilation_unit); @@ -108,32 +82,29 @@ class CompilerLLVM { CompiledInvokeStub* CreateProxyStub(const char *shorty); + const ProcedureLinkageTable& GetProcedureLinkageTable() const { + return plt_; + } + private: - void EnsureCompilationUnit(); + CompilationUnit* AllocateCompilationUnit(); void Materialize(CompilationUnit* cunit); - void LoadElfFromCompilationUnit(const CompilationUnit* cunit); - bool IsBitcodeFileNameAvailable() const { return !bitcode_filename_.empty(); } Compiler* compiler_; - public: - Mutex compiler_lock_; - - private: InstructionSet insn_set_; - CompilationUnit* curr_cunit_; - - std::vector<CompilationUnit*> cunits_; + Mutex num_cunits_lock_; + size_t num_cunits_; std::string bitcode_filename_; - UniquePtr<ElfLoader> elf_loader_; + ProcedureLinkageTable plt_; DISALLOW_COPY_AND_ASSIGN(CompilerLLVM); }; diff --git a/src/compiler_llvm/elf_loader.cc b/src/compiler_llvm/elf_loader.cc deleted file mode 100644 index 8432a07013..0000000000 --- a/src/compiler_llvm/elf_loader.cc +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2012 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 "elf_loader.h" - -#include "compiled_method.h" -#include "elf_image.h" -#include "logging.h" -#include "oat_file.h" -#include "object.h" -#include "runtime_support_llvm.h" -#include "utils_llvm.h" - -#include <android/librsloader.h> - -namespace art { -namespace compiler_llvm { - - -ElfLoader::~ElfLoader() { - // Release every ELF object - for (size_t i = 0; i < executables_.size(); ++i) { - rsloaderDisposeExec(executables_[i]); - } -} - - -bool ElfLoader::LoadElfAt(size_t elf_idx, - const ElfImage& elf_image, - OatFile::RelocationBehavior reloc) { - if (elf_idx < executables_.size() && executables_[elf_idx] != NULL) { - return false; - } - - if (elf_idx >= executables_.size()) { - executables_.resize(elf_idx + 1); - elf_images_.resize(elf_idx + 1); - } - - RSExecRef executable = rsloaderLoadExecutable(elf_image.begin(), - elf_image.size(), - reloc == OatFile::kRelocNone ? 1 : 0); - - if (executable == NULL) { - LOG(WARNING) << "Failed to load ELF" - << " image: " << static_cast<const void*>(elf_image.begin()) - << " size: " << elf_image.size(); - return false; - } - - if (reloc == OatFile::kRelocAll) { - if (!rsloaderRelocateExecutable(executable, - art_find_runtime_support_func, NULL)) { - LOG(ERROR) << "Failed to relocate the ELF image"; - rsloaderDisposeExec(executable); - return false; - } - relocated = true; - } - - executables_[elf_idx] = executable; - elf_images_[elf_idx] = elf_image; - return true; -} - - -void ElfLoader::RelocateExecutable() { - if (relocated) { - return; - } - LOG(INFO) << "Reload ELF for relocate."; - for (size_t i = 0; i < executables_.size(); ++i) { - if (executables_[i] != NULL) { - // TODO: After implement in-place linking, we will no longer need to dispose and reload. - rsloaderDisposeExec(executables_[i]); - executables_[i] = rsloaderLoadExecutable(elf_images_[i].begin(), elf_images_[i].size(), 0); - if (executables_[i] == NULL) { - LOG(FATAL) << "Failed to reload ELF image " << i; - } - if (!rsloaderRelocateExecutable(executables_[i], - art_find_runtime_support_func, NULL)) { - LOG(FATAL) << "Failed to relocate ELF image " << i; - } - } - } - relocated = true; -} - - -const void* ElfLoader::GetMethodCodeAddr(uint16_t elf_idx, - uint16_t elf_func_idx) const { - CHECK_LT(elf_idx, executables_.size()); - return GetAddr(elf_idx, ElfFuncName(elf_func_idx).c_str()); -} - - -const Method::InvokeStub* ElfLoader:: -GetMethodInvokeStubAddr(uint16_t elf_idx, uint16_t elf_func_idx) const { - CHECK_LT(elf_idx, executables_.size()); - return reinterpret_cast<const Method::InvokeStub*>( - GetAddr(elf_idx, ElfFuncName(elf_func_idx).c_str())); -} - - -size_t ElfLoader::GetCodeSize(uint16_t elf_idx, uint16_t elf_func_idx) const { - CHECK_LT(elf_idx, executables_.size()); - CHECK(executables_[elf_idx] != NULL); - return rsloaderGetSymbolSize(executables_[elf_idx], - ElfFuncName(elf_func_idx).c_str()); -} - - -const void* ElfLoader::GetAddr(size_t elf_idx, const char* sym_name) const { - CHECK_LT(elf_idx, executables_.size()); - CHECK(executables_[elf_idx] != NULL); - return rsloaderGetSymbolAddress(executables_[elf_idx], sym_name); -} - - -} // namespace compiler_llvm -} // namespace art diff --git a/src/compiler_llvm/elf_loader.h b/src/compiler_llvm/elf_loader.h deleted file mode 100644 index 9e8611ca59..0000000000 --- a/src/compiler_llvm/elf_loader.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ART_SRC_COMPILER_LLVM_ELF_LOADER_H_ -#define ART_SRC_COMPILER_LLVM_ELF_LOADER_H_ - -#include "elf_image.h" -#include "globals.h" -#include "oat_file.h" -#include "object.h" - -#include <android/librsloader.h> -#include <vector> - -namespace art { -namespace compiler_llvm { - -class ElfLoader { - public: - ElfLoader() : relocated(false) {} - ~ElfLoader(); - - bool LoadElfAt(size_t elf_idx, const ElfImage& elf_image, - OatFile::RelocationBehavior reloc); - - void RelocateExecutable(); - - const void* GetMethodCodeAddr(uint16_t elf_idx, - uint16_t elf_func_idx) const; - - const Method::InvokeStub* GetMethodInvokeStubAddr(uint16_t elf_idx, - uint16_t elf_func_idx) const; - - size_t GetCodeSize(uint16_t elf_idx, uint16_t elf_func_idx) const; - - private: - const void* GetAddr(size_t elf_idx, const char* sym_name) const; - - bool relocated; - std::vector<ElfImage> elf_images_; - std::vector<RSExecRef> executables_; -}; - - -} // namespace compiler_llvm -} // namespace art - -#endif // ART_SRC_COMPILER_LLVM_ELF_LOADER_H_ diff --git a/src/compiler_llvm/jni_compiler.cc b/src/compiler_llvm/jni_compiler.cc index 37ca82f2ff..f4f5be56c3 100644 --- a/src/compiler_llvm/jni_compiler.cc +++ b/src/compiler_llvm/jni_compiler.cc @@ -51,8 +51,7 @@ JniCompiler::JniCompiler(CompilationUnit* cunit, class_loader_(oat_compilation_unit->class_loader_), dex_cache_(oat_compilation_unit->dex_cache_), dex_file_(oat_compilation_unit->dex_file_), - method_(dex_cache_->GetResolvedMethod(method_idx_)), - elf_func_idx_(cunit_->AcquireUniqueElfFuncIndex()) { + method_(dex_cache_->GetResolvedMethod(method_idx_)) { // Check: Ensure that the method is resolved CHECK_NE(method_, static_cast<art::Method*>(NULL)); @@ -262,26 +261,16 @@ CompiledMethod* JniCompiler::Compile() { // Verify the generated bitcode VERIFY_LLVM_FUNCTION(*func_); - // Add the memory usage approximation of the compilation unit - cunit_->AddMemUsageApproximation((sirt_size * 4 + 50) * 50); - // NOTE: We will emit 4 LLVM instructions per object argument, - // And about 50 instructions for other operations. (Some runtime support will be inlined.) - // Beside, we guess that we have to use 50 bytes to represent one LLVM instruction. + cunit_->Materialize(); - CompiledMethod* compiled_method = - new CompiledMethod(cunit_->GetInstructionSet(), - cunit_->GetElfIndex(), - elf_func_idx_); - - cunit_->RegisterCompiledMethod(func_, compiled_method); - - return compiled_method; + return new CompiledMethod(cunit_->GetInstructionSet(), + cunit_->GetCompiledCode()); } void JniCompiler::CreateFunction() { // LLVM function name - std::string func_name(ElfFuncName(elf_func_idx_)); + std::string func_name(ElfFuncName(cunit_->GetIndex())); // Get function type llvm::FunctionType* func_type = diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc index eef71db957..da8f91adf2 100644 --- a/src/compiler_llvm/method_compiler.cc +++ b/src/compiler_llvm/method_compiler.cc @@ -72,8 +72,7 @@ MethodCompiler::MethodCompiler(CompilationUnit* cunit, basic_block_landing_pads_(code_item_->tries_size_, NULL), basic_block_unwind_(NULL), basic_block_unreachable_(NULL), shadow_frame_(NULL), old_shadow_frame_(NULL), - already_pushed_shadow_frame_(NULL), shadow_frame_size_(0), - elf_func_idx_(cunit_->AcquireUniqueElfFuncIndex()) { + already_pushed_shadow_frame_(NULL), shadow_frame_size_(0) { } @@ -84,7 +83,7 @@ MethodCompiler::~MethodCompiler() { void MethodCompiler::CreateFunction() { // LLVM function name - std::string func_name(ElfFuncName(elf_func_idx_)); + std::string func_name(ElfFuncName(cunit_->GetIndex())); // Get function type llvm::FunctionType* func_type = @@ -3616,20 +3615,10 @@ CompiledMethod *MethodCompiler::Compile() { // Verify the generated bitcode VERIFY_LLVM_FUNCTION(*func_); - // Add the memory usage approximation of the compilation unit - cunit_->AddMemUsageApproximation(code_item_->insns_size_in_code_units_ * 900); - // NOTE: From statistics, the bitcode size is 4.5 times bigger than the - // Dex file. Besides, we have to convert the code unit into bytes. - // Thus, we got our magic number 9. + cunit_->Materialize(); - CompiledMethod* compiled_method = - new CompiledMethod(cunit_->GetInstructionSet(), - cunit_->GetElfIndex(), - elf_func_idx_); - - cunit_->RegisterCompiledMethod(func_, compiled_method); - - return compiled_method; + return new CompiledMethod(cunit_->GetInstructionSet(), + cunit_->GetCompiledCode()); } diff --git a/src/compiler_llvm/stub_compiler.cc b/src/compiler_llvm/stub_compiler.cc index 0d64f0defa..af05e5246f 100644 --- a/src/compiler_llvm/stub_compiler.cc +++ b/src/compiler_llvm/stub_compiler.cc @@ -48,13 +48,11 @@ StubCompiler::StubCompiler(CompilationUnit* cunit, Compiler& compiler) CompiledInvokeStub* StubCompiler::CreateInvokeStub(bool is_static, char const* shorty) { - uint16_t elf_func_idx = cunit_->AcquireUniqueElfFuncIndex(); - CHECK(shorty != NULL); size_t shorty_size = strlen(shorty); // Function name - std::string func_name(ElfFuncName(elf_func_idx)); + std::string func_name(ElfFuncName(cunit_->GetIndex())); // Get argument types llvm::Type* arg_types[] = { @@ -186,15 +184,10 @@ CompiledInvokeStub* StubCompiler::CreateInvokeStub(bool is_static, // Verify the generated function VERIFY_LLVM_FUNCTION(*func); - // Add the memory usage approximation of the compilation unit - cunit_->AddMemUsageApproximation((shorty_size * 3 + 8) * 50); - // NOTE: We will emit 3 LLVM instructions per shorty for the argument, - // plus 3 for pointer arithmetic, and 5 for code_addr, retval, ret_addr, - // store ret_addr, and ret_void. Beside, we guess that we have to use - // 50 bytes to represent one LLVM instruction. + cunit_->Materialize(); return new CompiledInvokeStub(cunit_->GetInstructionSet(), - cunit_->GetElfIndex(), elf_func_idx); + cunit_->GetCompiledCode()); } @@ -202,10 +195,8 @@ CompiledInvokeStub* StubCompiler::CreateProxyStub(char const* shorty) { CHECK(shorty != NULL); size_t shorty_size = strlen(shorty); - uint16_t elf_func_idx = cunit_->AcquireUniqueElfFuncIndex(); - // Function name - std::string func_name(ElfFuncName(elf_func_idx)); + std::string func_name(ElfFuncName(cunit_->GetIndex())); // Accurate function type llvm::Type* accurate_ret_type = irb_.getJType(shorty[0], kAccurate); @@ -266,11 +257,10 @@ CompiledInvokeStub* StubCompiler::CreateProxyStub(char const* shorty) { // Verify the generated function VERIFY_LLVM_FUNCTION(*func); - // Add the memory usage approximation of the compilation unit - cunit_->AddMemUsageApproximation((shorty_size + 2) * 50); + cunit_->Materialize(); return new CompiledInvokeStub(cunit_->GetInstructionSet(), - cunit_->GetElfIndex(), elf_func_idx); + cunit_->GetCompiledCode()); } diff --git a/src/compiler_llvm/utils_llvm.h b/src/compiler_llvm/utils_llvm.h index dd35f0a089..eb5fd53e0a 100644 --- a/src/compiler_llvm/utils_llvm.h +++ b/src/compiler_llvm/utils_llvm.h @@ -32,8 +32,8 @@ namespace art { #define VERIFY_LLVM_FUNCTION(func) #endif -inline static std::string ElfFuncName(uint16_t elf_func_idx) { - return StringPrintf("Art%u", static_cast<unsigned int>(elf_func_idx)); +inline static std::string ElfFuncName(uint16_t idx) { + return StringPrintf("Art%u", static_cast<unsigned int>(idx)); } class CStringLessThanComparator { diff --git a/src/elf_image.h b/src/elf_image.h deleted file mode 100644 index 094467ab07..0000000000 --- a/src/elf_image.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ART_SRC_ELF_IMAGE_H_ -#define ART_SRC_ELF_IMAGE_H_ - -#include "globals.h" -#include <string> -#include <vector> - -namespace art { - -class ElfImage { - public: - explicit ElfImage(const std::vector<uint8_t>& v) - : begin_(&*v.begin()), size_(v.size()) { - } - - explicit ElfImage(const std::string& s) - : begin_(reinterpret_cast<const uint8_t*>(s.data())), size_(s.size()) { - } - - explicit ElfImage(const byte* begin, size_t size) - : begin_(begin), size_(size) { - } - - // TODO: Remove this after implement in-place linking. - ElfImage() : begin_(NULL), size_(0) { - } - - const byte* begin() const { - return begin_; - } - - const byte* end() const { - return (begin_ + size_); - } - - size_t size() const { - return size_; - } - - private: - const byte* begin_; - size_t size_; -}; - -} // namespace art - -#endif // ART_SRC_ELF_IMAGE_H_ diff --git a/src/oat.cc b/src/oat.cc index ce7c1333a4..cd9e0a36b0 100644 --- a/src/oat.cc +++ b/src/oat.cc @@ -29,7 +29,6 @@ OatHeader::OatHeader() { OatHeader::OatHeader(InstructionSet instruction_set, const std::vector<const DexFile*>* dex_files, - uint32_t elf_image_count, uint32_t image_file_location_checksum, const std::string& image_file_location) { memcpy(magic_, kOatMagic, sizeof(kOatMagic)); @@ -43,9 +42,6 @@ OatHeader::OatHeader(InstructionSet instruction_set, dex_file_count_ = dex_files->size(); UpdateChecksum(&dex_file_count_, sizeof(dex_file_count_)); - elf_image_count_ = elf_image_count; - UpdateChecksum(&elf_image_count_, sizeof(elf_image_count_)); - image_file_location_checksum_ = image_file_location_checksum; UpdateChecksum(&image_file_location_checksum_, sizeof(image_file_location_checksum_)); @@ -53,7 +49,6 @@ OatHeader::OatHeader(InstructionSet instruction_set, UpdateChecksum(&image_file_location_size_, sizeof(image_file_location_size_)); UpdateChecksum(image_file_location.data(), image_file_location_size_); - elf_image_table_offset_ = 0; executable_offset_ = 0; } @@ -77,16 +72,6 @@ uint32_t OatHeader::GetDexFileCount() const { return dex_file_count_; } -uint32_t OatHeader::GetElfImageCount() const { - DCHECK(IsValid()); - return elf_image_count_; -} - -uint32_t OatHeader::GetElfImageTableOffset() const { - DCHECK(IsValid()); - return elf_image_table_offset_; -} - uint32_t OatHeader::GetChecksum() const { CHECK(IsValid()); return adler32_checksum_; @@ -131,12 +116,6 @@ std::string OatHeader::GetImageFileLocation() const { GetImageFileLocationSize()); } -void OatHeader::SetElfImageTableOffset(uint32_t elf_image_table_offset) { - DCHECK(IsValid()); - elf_image_table_offset_ = elf_image_table_offset; - UpdateChecksum(&elf_image_table_offset_, sizeof(elf_image_table_offset_)); -} - void OatHeader::SetExecutableOffset(uint32_t executable_offset) { DCHECK_ALIGNED(executable_offset, kPageSize); CHECK_GT(executable_offset, sizeof(OatHeader)); @@ -156,12 +135,6 @@ OatMethodOffsets::OatMethodOffsets() vmap_table_offset_(0), gc_map_offset_(0), invoke_stub_offset_(0) -#if defined(ART_USE_LLVM_COMPILER) - , code_elf_idx_(static_cast<uint16_t>(-1u)), - code_elf_func_idx_(static_cast<uint16_t>(-1u)), - invoke_stub_elf_idx_(static_cast<uint16_t>(-1u)), - invoke_stub_elf_func_idx_(static_cast<uint16_t>(-1u)) -#endif {} OatMethodOffsets::OatMethodOffsets(uint32_t code_offset, @@ -173,12 +146,7 @@ OatMethodOffsets::OatMethodOffsets(uint32_t code_offset, uint32_t gc_map_offset, uint32_t invoke_stub_offset #if defined(ART_USE_LLVM_COMPILER) - , uint16_t code_elf_idx, - uint16_t code_elf_func_idx, - uint16_t invoke_stub_elf_idx, - uint16_t invoke_stub_elf_func_idx, - uint16_t proxy_stub_elf_idx, - uint16_t proxy_stub_elf_func_idx + , uint32_t proxy_stub_offset #endif ) : code_offset_(code_offset), @@ -190,12 +158,7 @@ OatMethodOffsets::OatMethodOffsets(uint32_t code_offset, gc_map_offset_(gc_map_offset), invoke_stub_offset_(invoke_stub_offset) #if defined(ART_USE_LLVM_COMPILER) - , code_elf_idx_(code_elf_idx), - code_elf_func_idx_(code_elf_func_idx), - invoke_stub_elf_idx_(invoke_stub_elf_idx), - invoke_stub_elf_func_idx_(invoke_stub_elf_func_idx), - proxy_stub_elf_idx_(proxy_stub_elf_idx), - proxy_stub_elf_func_idx_(proxy_stub_elf_func_idx) + , proxy_stub_offset_(proxy_stub_offset) #endif {} @@ -30,7 +30,6 @@ class PACKED OatHeader { OatHeader(); OatHeader(InstructionSet instruction_set, const std::vector<const DexFile*>* dex_files, - uint32_t elf_image_count, uint32_t image_file_location_checksum, const std::string& image_file_location); @@ -39,11 +38,8 @@ class PACKED OatHeader { uint32_t GetChecksum() const; void UpdateChecksum(const void* data, size_t length); uint32_t GetDexFileCount() const; - uint32_t GetElfImageCount() const; - uint32_t GetElfImageTableOffset() const; uint32_t GetExecutableOffset() const; InstructionSet GetInstructionSet() const; - void SetElfImageTableOffset(uint32_t elf_image_offset); void SetExecutableOffset(uint32_t executable_offset); uint32_t GetImageFileLocationChecksum() const; uint32_t GetImageFileLocationSize() const; @@ -60,8 +56,6 @@ class PACKED OatHeader { InstructionSet instruction_set_; uint32_t dex_file_count_; - uint32_t elf_image_count_; - uint32_t elf_image_table_offset_; uint32_t executable_offset_; uint32_t image_file_location_checksum_; @@ -74,6 +68,7 @@ class PACKED OatHeader { class PACKED OatMethodOffsets { public: OatMethodOffsets(); + OatMethodOffsets(uint32_t code_offset, uint32_t frame_size_in_bytes, uint32_t core_spill_mask, @@ -83,14 +78,10 @@ class PACKED OatMethodOffsets { uint32_t gc_map_offset, uint32_t invoke_stub_offset #if defined(ART_USE_LLVM_COMPILER) - , uint16_t code_elf_idx, - uint16_t code_elf_func_idx, - uint16_t invoke_stub_elf_idx, - uint16_t invoke_stub_elf_func_idx, - uint16_t proxy_stub_elf_idx, - uint16_t proxy_stub_elf_func_idx + , uint32_t proxy_stub_offset #endif ); + ~OatMethodOffsets(); uint32_t code_offset_; @@ -103,12 +94,7 @@ class PACKED OatMethodOffsets { uint32_t invoke_stub_offset_; #if defined(ART_USE_LLVM_COMPILER) - uint16_t code_elf_idx_; - uint16_t code_elf_func_idx_; - uint16_t invoke_stub_elf_idx_; - uint16_t invoke_stub_elf_func_idx_; - uint16_t proxy_stub_elf_idx_; - uint16_t proxy_stub_elf_func_idx_; + uint32_t proxy_stub_offset_; #endif }; diff --git a/src/oat_file.cc b/src/oat_file.cc index 239239bdd4..f64f5120f7 100644 --- a/src/oat_file.cc +++ b/src/oat_file.cc @@ -20,10 +20,6 @@ #include "os.h" #include "stl_util.h" -#if defined(ART_USE_LLVM_COMPILER) -#include "compiler_llvm/elf_loader.h" -#endif - namespace art { std::string OatFile::DexFilenameToOatFilename(const std::string& location) { @@ -64,19 +60,12 @@ OatFile* OatFile::Open(File& file, } OatFile::OatFile(const std::string& location) - : location_(location) -#if defined(ART_USE_LLVM_COMPILER) - , elf_loader_(new compiler_llvm::ElfLoader()) -#endif -{ + : location_(location) { CHECK(!location_.empty()); } OatFile::~OatFile() { STLDeleteValues(&oat_dex_files_); -#if defined(ART_USE_LLVM_COMPILER) - STLDeleteElements(&oat_elf_images_); -#endif } bool OatFile::Map(File& file, @@ -182,31 +171,6 @@ bool OatFile::Map(File& file, methods_offsets_pointer)); } -#if !defined(ART_USE_LLVM_COMPILER) - CHECK_EQ(oat_header.GetElfImageTableOffset(), 0u); - CHECK_EQ(oat_header.GetElfImageCount(), 0u); - -#else - oat = map->Begin() + oat_header.GetElfImageTableOffset(); - CHECK_EQ((reinterpret_cast<uintptr_t>(oat) & 0x3), 0u); - - for (uint32_t i = 0, end = oat_header.GetElfImageCount(); i < end; ++i) { - uint32_t elf_offset = *reinterpret_cast<const uint32_t*>(oat); - oat += sizeof(uint32_t); - - uint32_t elf_size = *reinterpret_cast<const uint32_t*>(oat); - oat += sizeof(uint32_t); - - const byte* elf_begin = map->Begin() + elf_offset; - - oat_elf_images_.push_back(new OatElfImage(this, elf_begin, elf_size)); - - if (!elf_loader_->LoadElfAt(i, ElfImage(elf_begin, elf_size), reloc)) { - LOG(ERROR) << "Failed to load ELF image. index: " << i; - } - } -#endif - mem_map_.reset(map.release()); return true; } @@ -246,9 +210,7 @@ std::vector<const OatFile::OatDexFile*> OatFile::GetOatDexFiles() const { } void OatFile::RelocateExecutable() { -#if defined(ART_USE_LLVM_COMPILER) - elf_loader_->RelocateExecutable(); -#endif + UNIMPLEMENTED(WARNING) << "Relocate the executable"; } OatFile::OatDexFile::OatDexFile(const OatFile* oat_file, @@ -308,13 +270,7 @@ const OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index) oat_method_offsets.gc_map_offset_, oat_method_offsets.invoke_stub_offset_ #if defined(ART_USE_LLVM_COMPILER) - , oat_file_->elf_loader_.get(), - oat_method_offsets.code_elf_idx_, - oat_method_offsets.code_elf_func_idx_, - oat_method_offsets.invoke_stub_elf_idx_, - oat_method_offsets.invoke_stub_elf_func_idx_, - oat_method_offsets.proxy_stub_elf_idx_, - oat_method_offsets.proxy_stub_elf_func_idx_ + , oat_method_offsets.proxy_stub_offset_ #endif ); } @@ -329,13 +285,7 @@ OatFile::OatMethod::OatMethod(const byte* base, const uint32_t gc_map_offset, const uint32_t invoke_stub_offset #if defined(ART_USE_LLVM_COMPILER) - , const compiler_llvm::ElfLoader* elf_loader, - const uint16_t code_elf_idx, - const uint16_t code_elf_func_idx, - const uint16_t invoke_stub_elf_idx, - const uint16_t invoke_stub_elf_func_idx, - const uint16_t proxy_stub_elf_idx, - const uint16_t proxy_stub_elf_func_idx + , const uint32_t proxy_stub_offset #endif ) : begin_(base), @@ -348,13 +298,7 @@ OatFile::OatMethod::OatMethod(const byte* base, gc_map_offset_(gc_map_offset), invoke_stub_offset_(invoke_stub_offset) #if defined(ART_USE_LLVM_COMPILER) - , elf_loader_(elf_loader), - code_elf_idx_(code_elf_idx), - code_elf_func_idx_(code_elf_func_idx), - invoke_stub_elf_idx_(invoke_stub_elf_idx), - invoke_stub_elf_func_idx_(invoke_stub_elf_func_idx), - proxy_stub_elf_idx_(proxy_stub_elf_idx), - proxy_stub_elf_func_idx_(proxy_stub_elf_func_idx) + , proxy_stub_offset_(proxy_stub_offset) #endif { #ifndef NDEBUG @@ -374,92 +318,37 @@ OatFile::OatMethod::OatMethod(const byte* base, OatFile::OatMethod::~OatMethod() {} const void* OatFile::OatMethod::GetCode() const { - if (!IsCodeInElf()) { - return GetOatPointer<const void*>(code_offset_); - } else { -#if !defined(ART_USE_LLVM_COMPILER) - UNIMPLEMENTED(FATAL); - return NULL; -#else - CHECK(elf_loader_ != NULL); - const void* code = - elf_loader_->GetMethodCodeAddr(code_elf_idx_, code_elf_func_idx_); - CHECK(code != NULL); - return code; -#endif - } + return GetOatPointer<const void*>(code_offset_); } uint32_t OatFile::OatMethod::GetCodeSize() const { - if (!IsCodeInElf()) { - uintptr_t code = reinterpret_cast<uint32_t>(GetCode()); + uintptr_t code = reinterpret_cast<uint32_t>(GetCode()); - if (code == 0) { - return 0; - } - // TODO: make this Thumb2 specific - code &= ~0x1; - return reinterpret_cast<uint32_t*>(code)[-1]; - } else { -#if !defined(ART_USE_LLVM_COMPILER) - UNIMPLEMENTED(ERROR); + if (code == 0) { return 0; -#else - CHECK(elf_loader_ != NULL); - return elf_loader_->GetCodeSize(code_elf_idx_, code_elf_func_idx_); -#endif } + // TODO: make this Thumb2 specific + code &= ~0x1; + return reinterpret_cast<uint32_t*>(code)[-1]; } const Method::InvokeStub* OatFile::OatMethod::GetInvokeStub() const { - if (!IsInvokeStubInElf()) { - return GetOatPointer<const Method::InvokeStub*>(invoke_stub_offset_); - } else { -#if !defined(ART_USE_LLVM_COMPILER) - UNIMPLEMENTED(FATAL); - return NULL; -#else - CHECK(elf_loader_ != NULL); - const Method::InvokeStub* stub = - elf_loader_->GetMethodInvokeStubAddr(invoke_stub_elf_idx_, - invoke_stub_elf_func_idx_); - CHECK(stub != NULL); - return stub; -#endif - } + return GetOatPointer<const Method::InvokeStub*>(invoke_stub_offset_); } uint32_t OatFile::OatMethod::GetInvokeStubSize() const { - if (!IsInvokeStubInElf()) { - uintptr_t code = reinterpret_cast<uint32_t>(GetInvokeStub()); - if (code == 0) { - return 0; - } - // TODO: make this Thumb2 specific - code &= ~0x1; - return reinterpret_cast<uint32_t*>(code)[-1]; - } else { -#if !defined(ART_USE_LLVM_COMPILER) - UNIMPLEMENTED(WARNING); + uintptr_t code = reinterpret_cast<uint32_t>(GetInvokeStub()); + if (code == 0) { return 0; -#else - CHECK(elf_loader_ != NULL); - return elf_loader_->GetCodeSize(invoke_stub_elf_idx_, - invoke_stub_elf_func_idx_); -#endif } + // TODO: make this Thumb2 specific + code &= ~0x1; + return reinterpret_cast<uint32_t*>(code)[-1]; } #if defined(ART_USE_LLVM_COMPILER) const void* OatFile::OatMethod::GetProxyStub() const { - CHECK(elf_loader_ != NULL); - const void* stub = NULL; - if (proxy_stub_elf_func_idx_ != static_cast<uint16_t>(-1)) { - stub = elf_loader_->GetMethodCodeAddr(proxy_stub_elf_idx_, - proxy_stub_elf_func_idx_); - CHECK(stub != NULL); - } - return stub; + return GetOatPointer<const void*>(proxy_stub_offset_); } #endif @@ -487,12 +376,4 @@ void OatFile::OatMethod::LinkMethodOffsets(Method* method) const { method->SetOatInvokeStubOffset(GetInvokeStubOffset()); } -#if defined(ART_USE_LLVM_COMPILER) -OatFile::OatElfImage::OatElfImage(const OatFile* oat_file, - const byte* addr, - uint32_t size) - : oat_file_(oat_file), elf_addr_(addr), elf_size_(size) { -} -#endif - } // namespace art diff --git a/src/oat_file.h b/src/oat_file.h index a4ca2de156..856a033e18 100644 --- a/src/oat_file.h +++ b/src/oat_file.h @@ -25,14 +25,6 @@ #include "oat.h" #include "object.h" -#if defined(ART_USE_LLVM_COMPILER) -namespace art { - namespace compiler_llvm { - class ElfLoader; - } -} -#endif - namespace art { class OatFile { @@ -103,37 +95,6 @@ class OatFile { return invoke_stub_offset_; } -#if defined(ART_USE_LLVM_COMPILER) - uint16_t GetCodeElfIndex() const { - return code_elf_idx_; - } - uint16_t GetCodeElfFuncIndex() const { - return code_elf_func_idx_; - } - uint16_t GetInvokeStubElfIndex() const { - return invoke_stub_elf_idx_; - } - uint16_t GetInvokeStubElfFuncIndex() const { - return invoke_stub_elf_func_idx_; - } -#endif - - bool IsCodeInElf() const { -#if defined(ART_USE_LLVM_COMPILER) - return (code_elf_idx_ != static_cast<uint16_t>(-1)); -#else - return false; -#endif - } - - bool IsInvokeStubInElf() const { -#if defined(ART_USE_LLVM_COMPILER) - return (invoke_stub_elf_idx_ != static_cast<uint16_t>(-1)); -#else - return false; -#endif - } - const void* GetCode() const; uint32_t GetCodeSize() const; @@ -167,13 +128,7 @@ class OatFile { const uint32_t gc_map_offset, const uint32_t invoke_stub_offset #if defined(ART_USE_LLVM_COMPILER) - , const compiler_llvm::ElfLoader* elf_loader, - const uint16_t code_elf_idx, - const uint16_t code_elf_func_idx, - const uint16_t invoke_stub_elf_idx, - const uint16_t invoke_stub_elf_func_idx, - const uint16_t proxy_stub_elf_idx, - const uint16_t proxy_stub_elf_func_idx + , const uint32_t proxy_stub_offset #endif ); @@ -198,14 +153,7 @@ class OatFile { uint32_t invoke_stub_offset_; #if defined(ART_USE_LLVM_COMPILER) - const compiler_llvm::ElfLoader* elf_loader_; - - uint16_t code_elf_idx_; - uint16_t code_elf_func_idx_; - uint16_t invoke_stub_elf_idx_; - uint16_t invoke_stub_elf_func_idx_; - uint16_t proxy_stub_elf_idx_; - uint16_t proxy_stub_elf_func_idx_; + uint32_t proxy_stub_offset_; #endif friend class OatClass; @@ -266,43 +214,10 @@ class OatFile { DISALLOW_COPY_AND_ASSIGN(OatDexFile); }; -#if defined(ART_USE_LLVM_COMPILER) - class OatElfImage { - public: - const byte* begin() const { - return elf_addr_; - } - - const byte* end() const { - return (elf_addr_ + elf_size_); - } - - size_t size() const { - return elf_size_; - } - - private: - OatElfImage(const OatFile* oat_file, const byte* addr, uint32_t size); - - const OatFile* oat_file_; - const byte* elf_addr_; - uint32_t elf_size_; - - friend class OatFile; - DISALLOW_COPY_AND_ASSIGN(OatElfImage); - }; -#endif - const OatDexFile* GetOatDexFile(const std::string& dex_file_location, bool warn_if_not_found = true) const; std::vector<const OatDexFile*> GetOatDexFiles() const; -#if defined(ART_USE_LLVM_COMPILER) - const OatElfImage* GetOatElfImage(size_t i) const { - return oat_elf_images_[i]; - } -#endif - size_t Size() const { return End() - Begin(); } @@ -327,11 +242,6 @@ class OatFile { typedef SafeMap<std::string, const OatDexFile*> Table; Table oat_dex_files_; -#if defined(ART_USE_LLVM_COMPILER) - std::vector<OatElfImage*> oat_elf_images_; - UniquePtr<compiler_llvm::ElfLoader> elf_loader_; -#endif - friend class OatClass; friend class OatDexFile; friend class OatDumper; // For GetBase and GetLimit diff --git a/src/oat_writer.cc b/src/oat_writer.cc index 2558ebac89..013a561957 100644 --- a/src/oat_writer.cc +++ b/src/oat_writer.cc @@ -20,7 +20,6 @@ #include "class_linker.h" #include "class_loader.h" -#include "elf_image.h" #include "file.h" #include "os.h" #include "safe_map.h" @@ -53,15 +52,12 @@ OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files, image_file_location_checksum_ = image_file_location_checksum; image_file_location_ = image_file_location; dex_files_ = &dex_files; - elf_images_ = compiler_->GetElfImages(); oat_header_ = NULL; executable_offset_padding_length_ = 0; size_t offset = InitOatHeader(); offset = InitOatDexFiles(offset); offset = InitDexFiles(offset); - offset = InitOatElfImages(offset); - offset = InitElfImages(offset); offset = InitOatClasses(offset); offset = InitOatCode(offset); offset = InitOatCodeDexFiles(offset); @@ -72,7 +68,6 @@ OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files, OatWriter::~OatWriter() { delete oat_header_; STLDeleteElements(&oat_dex_files_); - STLDeleteElements(&oat_elf_images_); STLDeleteElements(&oat_classes_); } @@ -80,7 +75,6 @@ size_t OatWriter::InitOatHeader() { // create the OatHeader oat_header_ = new OatHeader(compiler_->GetInstructionSet(), dex_files_, - elf_images_.size(), image_file_location_checksum_, image_file_location_); size_t offset = sizeof(*oat_header_); @@ -115,34 +109,6 @@ size_t OatWriter::InitDexFiles(size_t offset) { return offset; } -size_t OatWriter::InitOatElfImages(size_t offset) { - size_t n = elf_images_.size(); - if (n != 0) { - // Offset to ELF image table should be rounded up to 4-byte aligned, so that - // we can read the uint32_t directly. - offset = RoundUp(offset, 4); - oat_header_->SetElfImageTableOffset(offset); - } else { - oat_header_->SetElfImageTableOffset(0); - } - - for (size_t i = 0; i < n; ++i) { - OatElfImage* oat_elf_image = new OatElfImage(elf_images_[i]); - oat_elf_images_.push_back(oat_elf_image); - offset += oat_elf_image->SizeOf(); - } - return offset; -} - -size_t OatWriter::InitElfImages(size_t offset) { - for (size_t i = 0; i < oat_elf_images_.size(); ++i) { - offset = RoundUp(offset, 4); - oat_elf_images_[i]->SetElfOffset(offset); - offset += oat_elf_images_[i]->GetElfSize(); - } - return offset; -} - size_t OatWriter::InitOatClasses(size_t offset) { // create the OatClasses // calculate the offsets within OatDexFiles to OatClasses @@ -258,10 +224,6 @@ size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index, uint32_t method_idx, const DexFile* dex_file) { // derived from CompiledMethod if available uint32_t code_offset = 0; -#if defined(ART_USE_LLVM_COMPILER) - uint16_t code_elf_idx = static_cast<uint16_t>(-1u); - uint16_t code_elf_func_idx = static_cast<uint16_t>(-1u); -#endif uint32_t frame_size_in_bytes = kStackAlignment; uint32_t core_spill_mask = 0; uint32_t fp_spill_mask = 0; @@ -271,125 +233,107 @@ size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index, // derived from CompiledInvokeStub if available uint32_t invoke_stub_offset = 0; #if defined(ART_USE_LLVM_COMPILER) - uint16_t invoke_stub_elf_idx = static_cast<uint16_t>(-1u); - uint16_t invoke_stub_elf_func_idx = static_cast<uint16_t>(-1u); - uint16_t proxy_stub_elf_idx = static_cast<uint16_t>(-1u); - uint16_t proxy_stub_elf_func_idx = static_cast<uint16_t>(-1u); + uint32_t proxy_stub_offset = 0; #endif CompiledMethod* compiled_method = compiler_->GetCompiledMethod(Compiler::MethodReference(dex_file, method_idx)); if (compiled_method != NULL) { - if (compiled_method->IsExecutableInElf()) { -#if defined(ART_USE_LLVM_COMPILER) - code_elf_idx = compiled_method->GetElfIndex(); - code_elf_func_idx = compiled_method->GetElfFuncIndex(); -#endif - frame_size_in_bytes = compiled_method->GetFrameSizeInBytes(); + offset = compiled_method->AlignCode(offset); + DCHECK_ALIGNED(offset, kArmAlignment); + const std::vector<uint8_t>& code = compiled_method->GetCode(); + uint32_t code_size = code.size() * sizeof(code[0]); + CHECK_NE(code_size, 0U); + uint32_t thumb_offset = compiled_method->CodeDelta(); + code_offset = offset + sizeof(code_size) + thumb_offset; + + // Deduplicate code arrays + SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code); + if (code_iter != code_offsets_.end()) { + code_offset = code_iter->second; } else { - offset = compiled_method->AlignCode(offset); - DCHECK_ALIGNED(offset, kArmAlignment); - const std::vector<uint8_t>& code = compiled_method->GetCode(); - uint32_t code_size = code.size() * sizeof(code[0]); - CHECK_NE(code_size, 0U); - uint32_t thumb_offset = compiled_method->CodeDelta(); - code_offset = offset + sizeof(code_size) + thumb_offset; - - // Deduplicate code arrays - SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code); - if (code_iter != code_offsets_.end()) { - code_offset = code_iter->second; - } else { - code_offsets_.Put(&code, code_offset); - offset += sizeof(code_size); // code size is prepended before code - offset += code_size; - oat_header_->UpdateChecksum(&code[0], code_size); - } - frame_size_in_bytes = compiled_method->GetFrameSizeInBytes(); - core_spill_mask = compiled_method->GetCoreSpillMask(); - fp_spill_mask = compiled_method->GetFpSpillMask(); - - const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable(); - size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]); - mapping_table_offset = (mapping_table_size == 0) ? 0 : offset; - - // Deduplicate mapping tables - SafeMap<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter = mapping_table_offsets_.find(&mapping_table); - if (mapping_iter != mapping_table_offsets_.end()) { - mapping_table_offset = mapping_iter->second; - } else { - mapping_table_offsets_.Put(&mapping_table, mapping_table_offset); - offset += mapping_table_size; - oat_header_->UpdateChecksum(&mapping_table[0], mapping_table_size); - } - - const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable(); - size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]); - vmap_table_offset = (vmap_table_size == 0) ? 0 : offset; + code_offsets_.Put(&code, code_offset); + offset += sizeof(code_size); // code size is prepended before code + offset += code_size; + oat_header_->UpdateChecksum(&code[0], code_size); + } + frame_size_in_bytes = compiled_method->GetFrameSizeInBytes(); + core_spill_mask = compiled_method->GetCoreSpillMask(); + fp_spill_mask = compiled_method->GetFpSpillMask(); + + const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable(); + size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]); + mapping_table_offset = (mapping_table_size == 0) ? 0 : offset; + + // Deduplicate mapping tables + SafeMap<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter = mapping_table_offsets_.find(&mapping_table); + if (mapping_iter != mapping_table_offsets_.end()) { + mapping_table_offset = mapping_iter->second; + } else { + mapping_table_offsets_.Put(&mapping_table, mapping_table_offset); + offset += mapping_table_size; + oat_header_->UpdateChecksum(&mapping_table[0], mapping_table_size); + } - // Deduplicate vmap tables - SafeMap<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter = vmap_table_offsets_.find(&vmap_table); - if (vmap_iter != vmap_table_offsets_.end()) { - vmap_table_offset = vmap_iter->second; - } else { - vmap_table_offsets_.Put(&vmap_table, vmap_table_offset); - offset += vmap_table_size; - oat_header_->UpdateChecksum(&vmap_table[0], vmap_table_size); - } + const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable(); + size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]); + vmap_table_offset = (vmap_table_size == 0) ? 0 : offset; - const std::vector<uint8_t>& gc_map = compiled_method->GetGcMap(); - size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]); - gc_map_offset = (gc_map_size == 0) ? 0 : offset; + // Deduplicate vmap tables + SafeMap<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter = vmap_table_offsets_.find(&vmap_table); + if (vmap_iter != vmap_table_offsets_.end()) { + vmap_table_offset = vmap_iter->second; + } else { + vmap_table_offsets_.Put(&vmap_table, vmap_table_offset); + offset += vmap_table_size; + oat_header_->UpdateChecksum(&vmap_table[0], vmap_table_size); + } -#ifndef NDEBUG - // We expect GC maps except when the class hasn't been verified or the method is native - CompiledClass* compiled_class = - compiler_->GetCompiledClass(Compiler::MethodReference(dex_file, class_def_index)); - Class::Status status = - (compiled_class != NULL) ? compiled_class->GetStatus() : Class::kStatusNotReady; - CHECK(gc_map_size != 0 || is_native || status < Class::kStatusVerified) - << &gc_map << " " << gc_map_size << " " << (is_native ? "true" : "false") << " " << (status < Class::kStatusVerified) << " " << status << " " << PrettyMethod(method_idx, *dex_file); + const std::vector<uint8_t>& gc_map = compiled_method->GetGcMap(); + size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]); + gc_map_offset = (gc_map_size == 0) ? 0 : offset; + +#if !defined(NDEBUG) && !defined(ART_USE_LLVM_COMPILER) + // We expect GC maps except when the class hasn't been verified or the method is native + CompiledClass* compiled_class = + compiler_->GetCompiledClass(Compiler::MethodReference(dex_file, class_def_index)); + Class::Status status = + (compiled_class != NULL) ? compiled_class->GetStatus() : Class::kStatusNotReady; + CHECK(gc_map_size != 0 || is_native || status < Class::kStatusVerified) + << &gc_map << " " << gc_map_size << " " << (is_native ? "true" : "false") << " " << (status < Class::kStatusVerified) << " " << status << " " << PrettyMethod(method_idx, *dex_file); #endif - // Deduplicate GC maps - SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator gc_map_iter = gc_map_offsets_.find(&gc_map); - if (gc_map_iter != gc_map_offsets_.end()) { - gc_map_offset = gc_map_iter->second; - } else { - gc_map_offsets_.Put(&gc_map, gc_map_offset); - offset += gc_map_size; - oat_header_->UpdateChecksum(&gc_map[0], gc_map_size); - } + // Deduplicate GC maps + SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator gc_map_iter = gc_map_offsets_.find(&gc_map); + if (gc_map_iter != gc_map_offsets_.end()) { + gc_map_offset = gc_map_iter->second; + } else { + gc_map_offsets_.Put(&gc_map, gc_map_offset); + offset += gc_map_size; + oat_header_->UpdateChecksum(&gc_map[0], gc_map_size); } } const char* shorty = dex_file->GetMethodShorty(dex_file->GetMethodId(method_idx)); const CompiledInvokeStub* compiled_invoke_stub = compiler_->FindInvokeStub(is_static, shorty); if (compiled_invoke_stub != NULL) { - if (compiled_invoke_stub->IsExecutableInElf()) { -#if defined(ART_USE_LLVM_COMPILER) - invoke_stub_elf_idx = compiled_invoke_stub->GetElfIndex(); - invoke_stub_elf_func_idx = compiled_invoke_stub->GetElfFuncIndex(); -#endif + offset = CompiledMethod::AlignCode(offset, compiler_->GetInstructionSet()); + DCHECK_ALIGNED(offset, kArmAlignment); + const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode(); + uint32_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]); + CHECK_NE(invoke_stub_size, 0U); + uint32_t thumb_offset = compiled_invoke_stub->CodeDelta(); + invoke_stub_offset = offset + sizeof(invoke_stub_size) + thumb_offset; + + // Deduplicate invoke stubs + SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter = code_offsets_.find(&invoke_stub); + if (stub_iter != code_offsets_.end()) { + invoke_stub_offset = stub_iter->second; } else { - offset = CompiledMethod::AlignCode(offset, compiler_->GetInstructionSet()); - DCHECK_ALIGNED(offset, kArmAlignment); - const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode(); - uint32_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]); - CHECK_NE(invoke_stub_size, 0U); - uint32_t thumb_offset = compiled_invoke_stub->CodeDelta(); - invoke_stub_offset = offset + sizeof(invoke_stub_size) + thumb_offset; - - // Deduplicate invoke stubs - SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter = code_offsets_.find(&invoke_stub); - if (stub_iter != code_offsets_.end()) { - invoke_stub_offset = stub_iter->second; - } else { - code_offsets_.Put(&invoke_stub, invoke_stub_offset); - offset += sizeof(invoke_stub_size); // invoke stub size is prepended before code - offset += invoke_stub_size; - oat_header_->UpdateChecksum(&invoke_stub[0], invoke_stub_size); - } + code_offsets_.Put(&invoke_stub, invoke_stub_offset); + offset += sizeof(invoke_stub_size); // invoke stub size is prepended before code + offset += invoke_stub_size; + oat_header_->UpdateChecksum(&invoke_stub[0], invoke_stub_size); } } @@ -397,9 +341,24 @@ size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index, if (!is_static) { const CompiledInvokeStub* compiled_proxy_stub = compiler_->FindProxyStub(shorty); if (compiled_proxy_stub != NULL) { - DCHECK(compiled_proxy_stub->IsExecutableInElf()); - proxy_stub_elf_idx = compiled_proxy_stub->GetElfIndex(); - proxy_stub_elf_func_idx = compiled_proxy_stub->GetElfFuncIndex(); + offset = CompiledMethod::AlignCode(offset, compiler_->GetInstructionSet()); + DCHECK_ALIGNED(offset, kArmAlignment); + const std::vector<uint8_t>& proxy_stub = compiled_proxy_stub->GetCode(); + uint32_t proxy_stub_size = proxy_stub.size() * sizeof(proxy_stub[0]); + CHECK_NE(proxy_stub_size, 0U); + uint32_t thumb_offset = compiled_proxy_stub->CodeDelta(); + proxy_stub_offset = offset + sizeof(proxy_stub_size) + thumb_offset; + + // Deduplicate proxy stubs + SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter = code_offsets_.find(&proxy_stub); + if (stub_iter != code_offsets_.end()) { + proxy_stub_offset = stub_iter->second; + } else { + code_offsets_.Put(&proxy_stub, proxy_stub_offset); + offset += sizeof(proxy_stub_size); // proxy stub size is prepended before code + offset += proxy_stub_size; + oat_header_->UpdateChecksum(&proxy_stub[0], proxy_stub_size); + } } } #endif @@ -414,12 +373,7 @@ size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index, gc_map_offset, invoke_stub_offset #if defined(ART_USE_LLVM_COMPILER) - , code_elf_idx, - code_elf_func_idx, - invoke_stub_elf_idx, - invoke_stub_elf_func_idx, - proxy_stub_elf_idx, - proxy_stub_elf_func_idx + , proxy_stub_offset #endif ); @@ -505,25 +459,6 @@ bool OatWriter::WriteTables(File* file) { return false; } } - for (size_t i = 0; i != oat_elf_images_.size(); ++i) { - if (!oat_elf_images_[i]->Write(file)) { - PLOG(ERROR) << "Failed to write oat elf information to " << file->name(); - return false; - } - } - for (size_t i = 0; i != oat_elf_images_.size(); ++i) { - uint32_t expected_offset = oat_elf_images_[i]->GetElfOffset(); - off_t actual_offset = lseek(file->Fd(), expected_offset, SEEK_SET); - if (static_cast<uint32_t>(actual_offset) != expected_offset) { - PLOG(ERROR) << "Failed to seek to dex file section." - << " Actual: " << actual_offset - << " Expected: " << expected_offset; - return false; - } - if (!oat_elf_images_[i]->WriteElfImage(file)) { - return false; - } - } for (size_t i = 0; i != oat_classes_.size(); ++i) { if (!oat_classes_[i]->Write(file)) { PLOG(ERROR) << "Failed to write oat methods information to " << file->name(); @@ -629,126 +564,169 @@ size_t OatWriter::WriteCodeMethod(File* file, size_t code_offset, size_t oat_cla if (compiled_method != NULL) { // ie. not an abstract method - if (!compiled_method->IsExecutableInElf()) { - uint32_t aligned_code_offset = compiled_method->AlignCode(code_offset); - uint32_t aligned_code_delta = aligned_code_offset - code_offset; - if (aligned_code_delta != 0) { - off_t new_offset = lseek(file->Fd(), aligned_code_delta, SEEK_CUR); - if (static_cast<uint32_t>(new_offset) != aligned_code_offset) { - PLOG(ERROR) << "Failed to seek to align oat code. Actual: " << new_offset - << " Expected: " << aligned_code_offset << " File: " << file->name(); - return 0; - } - code_offset += aligned_code_delta; - DCHECK_CODE_OFFSET(); - } - DCHECK_ALIGNED(code_offset, kArmAlignment); - const std::vector<uint8_t>& code = compiled_method->GetCode(); - uint32_t code_size = code.size() * sizeof(code[0]); - CHECK_NE(code_size, 0U); - - // Deduplicate code arrays - size_t offset = code_offset + sizeof(code_size) + compiled_method->CodeDelta(); - SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code); - if (code_iter != code_offsets_.end() && offset != method_offsets.code_offset_) { - DCHECK(code_iter->second == method_offsets.code_offset_) << PrettyMethod(method_idx, dex_file); - } else { - DCHECK(offset == method_offsets.code_offset_) << PrettyMethod(method_idx, dex_file); - if (!file->WriteFully(&code_size, sizeof(code_size))) { - ReportWriteFailure("method code size", method_idx, dex_file, file); - return 0; - } - code_offset += sizeof(code_size); - DCHECK_CODE_OFFSET(); - if (!file->WriteFully(&code[0], code_size)) { - ReportWriteFailure("method code", method_idx, dex_file, file); - return 0; - } - code_offset += code_size; + uint32_t aligned_code_offset = compiled_method->AlignCode(code_offset); + uint32_t aligned_code_delta = aligned_code_offset - code_offset; + if (aligned_code_delta != 0) { + off_t new_offset = lseek(file->Fd(), aligned_code_delta, SEEK_CUR); + if (static_cast<uint32_t>(new_offset) != aligned_code_offset) { + PLOG(ERROR) << "Failed to seek to align oat code. Actual: " << new_offset + << " Expected: " << aligned_code_offset << " File: " << file->name(); + return 0; } + code_offset += aligned_code_delta; DCHECK_CODE_OFFSET(); - - const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable(); - size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]); - - // Deduplicate mapping tables - SafeMap<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter = - mapping_table_offsets_.find(&mapping_table); - if (mapping_iter != mapping_table_offsets_.end() && - code_offset != method_offsets.mapping_table_offset_) { - DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0) - || mapping_iter->second == method_offsets.mapping_table_offset_) - << PrettyMethod(method_idx, dex_file); - } else { - DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0) - || code_offset == method_offsets.mapping_table_offset_) - << PrettyMethod(method_idx, dex_file); - if (!file->WriteFully(&mapping_table[0], mapping_table_size)) { - ReportWriteFailure("mapping table", method_idx, dex_file, file); - return 0; - } - code_offset += mapping_table_size; + } + DCHECK_ALIGNED(code_offset, kArmAlignment); + const std::vector<uint8_t>& code = compiled_method->GetCode(); + uint32_t code_size = code.size() * sizeof(code[0]); + CHECK_NE(code_size, 0U); + + // Deduplicate code arrays + size_t offset = code_offset + sizeof(code_size) + compiled_method->CodeDelta(); + SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code); + if (code_iter != code_offsets_.end() && offset != method_offsets.code_offset_) { + DCHECK(code_iter->second == method_offsets.code_offset_) << PrettyMethod(method_idx, dex_file); + } else { + DCHECK(offset == method_offsets.code_offset_) << PrettyMethod(method_idx, dex_file); + if (!file->WriteFully(&code_size, sizeof(code_size))) { + ReportWriteFailure("method code size", method_idx, dex_file, file); + return 0; } + code_offset += sizeof(code_size); DCHECK_CODE_OFFSET(); - - const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable(); - size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]); - - // Deduplicate vmap tables - SafeMap<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter = - vmap_table_offsets_.find(&vmap_table); - if (vmap_iter != vmap_table_offsets_.end() && - code_offset != method_offsets.vmap_table_offset_) { - DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0) - || vmap_iter->second == method_offsets.vmap_table_offset_) - << PrettyMethod(method_idx, dex_file); - } else { - DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0) - || code_offset == method_offsets.vmap_table_offset_) - << PrettyMethod(method_idx, dex_file); - if (!file->WriteFully(&vmap_table[0], vmap_table_size)) { - ReportWriteFailure("vmap table", method_idx, dex_file, file); - return 0; - } - code_offset += vmap_table_size; + if (!file->WriteFully(&code[0], code_size)) { + ReportWriteFailure("method code", method_idx, dex_file, file); + return 0; } - DCHECK_CODE_OFFSET(); - - const std::vector<uint8_t>& gc_map = compiled_method->GetGcMap(); - size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]); - - // Deduplicate GC maps - SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator gc_map_iter = - gc_map_offsets_.find(&gc_map); - if (gc_map_iter != gc_map_offsets_.end() && - code_offset != method_offsets.gc_map_offset_) { - DCHECK((gc_map_size == 0 && method_offsets.gc_map_offset_ == 0) - || gc_map_iter->second == method_offsets.gc_map_offset_) - << PrettyMethod(method_idx, dex_file); - } else { - DCHECK((gc_map_size == 0 && method_offsets.gc_map_offset_ == 0) - || code_offset == method_offsets.gc_map_offset_) - << PrettyMethod(method_idx, dex_file); - if (!file->WriteFully(&gc_map[0], gc_map_size)) { - ReportWriteFailure("GC map", method_idx, dex_file, file); - return 0; - } - code_offset += gc_map_size; + code_offset += code_size; + } + DCHECK_CODE_OFFSET(); + + const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable(); + size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]); + + // Deduplicate mapping tables + SafeMap<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter = + mapping_table_offsets_.find(&mapping_table); + if (mapping_iter != mapping_table_offsets_.end() && + code_offset != method_offsets.mapping_table_offset_) { + DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0) + || mapping_iter->second == method_offsets.mapping_table_offset_) + << PrettyMethod(method_idx, dex_file); + } else { + DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0) + || code_offset == method_offsets.mapping_table_offset_) + << PrettyMethod(method_idx, dex_file); + if (!file->WriteFully(&mapping_table[0], mapping_table_size)) { + ReportWriteFailure("mapping table", method_idx, dex_file, file); + return 0; } - DCHECK_CODE_OFFSET(); + code_offset += mapping_table_size; + } + DCHECK_CODE_OFFSET(); + + const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable(); + size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]); + + // Deduplicate vmap tables + SafeMap<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter = + vmap_table_offsets_.find(&vmap_table); + if (vmap_iter != vmap_table_offsets_.end() && + code_offset != method_offsets.vmap_table_offset_) { + DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0) + || vmap_iter->second == method_offsets.vmap_table_offset_) + << PrettyMethod(method_idx, dex_file); + } else { + DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0) + || code_offset == method_offsets.vmap_table_offset_) + << PrettyMethod(method_idx, dex_file); + if (!file->WriteFully(&vmap_table[0], vmap_table_size)) { + ReportWriteFailure("vmap table", method_idx, dex_file, file); + return 0; + } + code_offset += vmap_table_size; } + DCHECK_CODE_OFFSET(); + + const std::vector<uint8_t>& gc_map = compiled_method->GetGcMap(); + size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]); + + // Deduplicate GC maps + SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator gc_map_iter = + gc_map_offsets_.find(&gc_map); + if (gc_map_iter != gc_map_offsets_.end() && + code_offset != method_offsets.gc_map_offset_) { + DCHECK((gc_map_size == 0 && method_offsets.gc_map_offset_ == 0) + || gc_map_iter->second == method_offsets.gc_map_offset_) + << PrettyMethod(method_idx, dex_file); + } else { + DCHECK((gc_map_size == 0 && method_offsets.gc_map_offset_ == 0) + || code_offset == method_offsets.gc_map_offset_) + << PrettyMethod(method_idx, dex_file); + if (!file->WriteFully(&gc_map[0], gc_map_size)) { + ReportWriteFailure("GC map", method_idx, dex_file, file); + return 0; + } + code_offset += gc_map_size; + } + DCHECK_CODE_OFFSET(); } const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx)); const CompiledInvokeStub* compiled_invoke_stub = compiler_->FindInvokeStub(is_static, shorty); if (compiled_invoke_stub != NULL) { - if (!compiled_invoke_stub->IsExecutableInElf()) { + uint32_t aligned_code_offset = CompiledMethod::AlignCode(code_offset, + compiler_->GetInstructionSet()); + uint32_t aligned_code_delta = aligned_code_offset - code_offset; + if (aligned_code_delta != 0) { + off_t new_offset = lseek(file->Fd(), aligned_code_delta, SEEK_CUR); + if (static_cast<uint32_t>(new_offset) != aligned_code_offset) { + PLOG(ERROR) << "Failed to seek to align invoke stub code. Actual: " << new_offset + << " Expected: " << aligned_code_offset; + return 0; + } + code_offset += aligned_code_delta; + DCHECK_CODE_OFFSET(); + } + DCHECK_ALIGNED(code_offset, kArmAlignment); + const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode(); + uint32_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]); + CHECK_NE(invoke_stub_size, 0U); + + // Deduplicate invoke stubs + size_t offset = code_offset + sizeof(invoke_stub_size) + compiled_invoke_stub->CodeDelta(); + SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter = + code_offsets_.find(&invoke_stub); + if (stub_iter != code_offsets_.end() && offset != method_offsets.invoke_stub_offset_) { + DCHECK(stub_iter->second == method_offsets.invoke_stub_offset_) << PrettyMethod(method_idx, dex_file); + } else { + DCHECK(offset == method_offsets.invoke_stub_offset_) << PrettyMethod(method_idx, dex_file); + if (!file->WriteFully(&invoke_stub_size, sizeof(invoke_stub_size))) { + ReportWriteFailure("invoke stub code size", method_idx, dex_file, file); + return 0; + } + code_offset += sizeof(invoke_stub_size); + DCHECK_CODE_OFFSET(); + if (!file->WriteFully(&invoke_stub[0], invoke_stub_size)) { + ReportWriteFailure("invoke stub code", method_idx, dex_file, file); + return 0; + } + code_offset += invoke_stub_size; + DCHECK_CODE_OFFSET(); + } + } + +#if defined(ART_USE_LLVM_COMPILER) + if (!is_static) { + const CompiledInvokeStub* compiled_proxy_stub = compiler_->FindProxyStub(shorty); + if (compiled_proxy_stub != NULL) { uint32_t aligned_code_offset = CompiledMethod::AlignCode(code_offset, compiler_->GetInstructionSet()); uint32_t aligned_code_delta = aligned_code_offset - code_offset; + CHECK(aligned_code_delta < 48u); if (aligned_code_delta != 0) { off_t new_offset = lseek(file->Fd(), aligned_code_delta, SEEK_CUR); if (static_cast<uint32_t>(new_offset) != aligned_code_offset) { - PLOG(ERROR) << "Failed to seek to align invoke stub code. Actual: " << new_offset + PLOG(ERROR) << "Failed to seek to align proxy stub code. Actual: " << new_offset << " Expected: " << aligned_code_offset; return 0; } @@ -756,33 +734,35 @@ size_t OatWriter::WriteCodeMethod(File* file, size_t code_offset, size_t oat_cla DCHECK_CODE_OFFSET(); } DCHECK_ALIGNED(code_offset, kArmAlignment); - const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode(); - uint32_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]); - CHECK_NE(invoke_stub_size, 0U); + const std::vector<uint8_t>& proxy_stub = compiled_proxy_stub->GetCode(); + uint32_t proxy_stub_size = proxy_stub.size() * sizeof(proxy_stub[0]); + CHECK_NE(proxy_stub_size, 0U); - // Deduplicate invoke stubs - size_t offset = code_offset + sizeof(invoke_stub_size) + compiled_invoke_stub->CodeDelta(); + // Deduplicate proxy stubs + size_t offset = code_offset + sizeof(proxy_stub_size) + compiled_proxy_stub->CodeDelta(); SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter = - code_offsets_.find(&invoke_stub); - if (stub_iter != code_offsets_.end() && offset != method_offsets.invoke_stub_offset_) { - DCHECK(stub_iter->second == method_offsets.invoke_stub_offset_) << PrettyMethod(method_idx, dex_file); + code_offsets_.find(&proxy_stub); + if (stub_iter != code_offsets_.end() && offset != method_offsets.proxy_stub_offset_) { + DCHECK(stub_iter->second == method_offsets.proxy_stub_offset_) << PrettyMethod(method_idx, dex_file); } else { - DCHECK(offset == method_offsets.invoke_stub_offset_) << PrettyMethod(method_idx, dex_file); - if (!file->WriteFully(&invoke_stub_size, sizeof(invoke_stub_size))) { - ReportWriteFailure("invoke stub code size", method_idx, dex_file, file); + DCHECK(offset == method_offsets.proxy_stub_offset_) << PrettyMethod(method_idx, dex_file); + if (!file->WriteFully(&proxy_stub_size, sizeof(proxy_stub_size))) { + ReportWriteFailure("proxy stub code size", method_idx, dex_file, file); return 0; } - code_offset += sizeof(invoke_stub_size); + code_offset += sizeof(proxy_stub_size); DCHECK_CODE_OFFSET(); - if (!file->WriteFully(&invoke_stub[0], invoke_stub_size)) { - ReportWriteFailure("invoke stub code", method_idx, dex_file, file); + if (!file->WriteFully(&proxy_stub[0], proxy_stub_size)) { + ReportWriteFailure("proxy stub code", method_idx, dex_file, file); return 0; } - code_offset += invoke_stub_size; + code_offset += proxy_stub_size; + DCHECK_CODE_OFFSET(); } DCHECK_CODE_OFFSET(); } } +#endif return code_offset; } @@ -867,48 +847,4 @@ bool OatWriter::OatClass::Write(File* file) const { return true; } -OatWriter::OatElfImage::OatElfImage(const ElfImage& image) - : elf_offset_(0), elf_size_(image.size()), elf_addr_(image.begin()) { -} - -size_t OatWriter::OatElfImage::SizeOf() const { - return (sizeof(elf_offset_) + sizeof(elf_size_)); -} - -uint32_t OatWriter::OatElfImage::GetElfSize() const { - return elf_size_; -} - -uint32_t OatWriter::OatElfImage::GetElfOffset() const { - DCHECK_NE(elf_offset_, 0U); - return elf_offset_; -} - -void OatWriter::OatElfImage::SetElfOffset(uint32_t offset) { - DCHECK_NE(offset, 0U); - DCHECK_EQ((offset & 0x3LU), 0U); - elf_offset_ = offset; -} - -bool OatWriter::OatElfImage::Write(File* file) const { - DCHECK_NE(elf_offset_, 0U); - if (!file->WriteFully(&elf_offset_, sizeof(elf_offset_))) { - PLOG(ERROR) << "Failed to write ELF offset to " << file->name(); - return false; - } - if (!file->WriteFully(&elf_size_, sizeof(elf_size_))) { - PLOG(ERROR) << "Failed to write ELF size to " << file->name(); - return false; - } - return true; -} - -bool OatWriter::OatElfImage::WriteElfImage(File* file) const { - if (!file->WriteFully(elf_addr_, elf_size_)) { - PLOG(ERROR) << "Failed to write ELF image to " << file->name(); - return false; - } - return true; -} - } // namespace art diff --git a/src/oat_writer.h b/src/oat_writer.h index 29072abd8a..b748dbc35f 100644 --- a/src/oat_writer.h +++ b/src/oat_writer.h @@ -49,16 +49,6 @@ namespace art { // ... // OatClass[C] // -// OatElfImage[0] one OatElfImage for each ELF image -// OatElfImage[1] contains the size, checksum, and offset to the ELF image. -// ... -// OatElfImage[E] -// -// ELF[0] -// ELF[1] -// ... -// ELF[E] -// // padding if necessary so that the following code will be page aligned // // CompiledMethod one variable sized blob with the contents of each CompiledMethod @@ -92,8 +82,6 @@ class OatWriter { size_t InitOatDexFiles(size_t offset); size_t InitDexFiles(size_t offset); size_t InitOatClasses(size_t offset); - size_t InitOatElfImages(size_t offset); - size_t InitElfImages(size_t offset); size_t InitOatCode(size_t offset); size_t InitOatCodeDexFiles(size_t offset); size_t InitOatCodeDexFile(size_t offset, @@ -155,25 +143,6 @@ class OatWriter { DISALLOW_COPY_AND_ASSIGN(OatClass); }; - class OatElfImage { - public: - explicit OatElfImage(const ElfImage& elf_image); - size_t SizeOf() const; - uint32_t GetElfSize() const; - uint32_t GetElfOffset() const; - void SetElfOffset(uint32_t offset); - bool Write(File* file) const; - bool WriteElfImage(File* file) const; - - private: - // data to write - uint32_t elf_offset_; - const uint32_t elf_size_; - - const byte* const elf_addr_; - DISALLOW_COPY_AND_ASSIGN(OatElfImage); - }; - const Compiler* compiler_; // TODO: remove the ClassLoader when the code storage moves out of Method @@ -182,8 +151,6 @@ class OatWriter { // note OatFile does not take ownership of the DexFiles const std::vector<const DexFile*>* dex_files_; - std::vector<ElfImage> elf_images_; - // dependency on the image uint32_t image_file_location_checksum_; std::string image_file_location_; @@ -192,7 +159,6 @@ class OatWriter { OatHeader* oat_header_; std::vector<OatDexFile*> oat_dex_files_; std::vector<OatClass*> oat_classes_; - std::vector<OatElfImage*> oat_elf_images_; uint32_t executable_offset_padding_length_; template <class T> struct MapCompare { diff --git a/src/oatdump.cc b/src/oatdump.cc index b599eaa054..a33cd0967e 100644 --- a/src/oatdump.cc +++ b/src/oatdump.cc @@ -57,11 +57,6 @@ static void usage() { " Example: --boot-image=/system/framework/boot.art\n" "\n"); fprintf(stderr, - " --extract-elf-to=<file.elf>: provide the prefix of the filename for\n" - " the output ELF files.\n" - " Example: --extract-elf-to=output.elf\n" - "\n"); - fprintf(stderr, " --host-prefix may be used to translate host paths to target paths during\n" " cross compilation.\n" " Example: --host-prefix=out/target/product/crespo\n" @@ -113,9 +108,6 @@ class OatDumper { os << "DEX FILE COUNT:\n"; os << oat_header.GetDexFileCount() << "\n\n"; - os << "ELF IMAGE COUNT:\n"; - os << oat_header.GetElfImageCount() << "\n\n"; - os << "EXECUTABLE OFFSET:\n"; os << StringPrintf("0x%08x\n\n", oat_header.GetExecutableOffset()); @@ -318,35 +310,17 @@ class OatDumper { os << StringPrintf("\t\tgc_map: %p (offset=0x%08x)\n", oat_method.GetGcMap(), oat_method.GetGcMapOffset()); DumpGcMap(os, oat_method.GetGcMap()); - os << StringPrintf( -#if defined(ART_USE_LLVM_COMPILER) - "\t\tCODE: %p (offset=0x%08x size=%d elf_idx=%d elf_func_idx=%d)%s\n", -#else - "\t\tCODE: %p (offset=0x%08x size=%d)%s\n", -#endif + os << StringPrintf("\t\tCODE: %p (offset=0x%08x size=%d)%s\n", oat_method.GetCode(), oat_method.GetCodeOffset(), oat_method.GetCodeSize(), -#if defined(ART_USE_LLVM_COMPILER) - static_cast<int>(oat_method.GetCodeElfIndex()), - static_cast<int>(oat_method.GetCodeElfFuncIndex()), -#endif oat_method.GetCode() != NULL ? "..." : ""); DumpCode(os, oat_method.GetCode(), oat_method.GetCodeSize(), oat_method.GetMappingTable(), dex_file, code_item); - os << StringPrintf( -#if defined(ART_USE_LLVM_COMPILER) - "\t\tINVOKE STUB: %p (offset=0x%08x size=%d elf_idx=%d elf_func_idx=%d)%s\n", -#else - "\t\tINVOKE STUB: %p (offset=0x%08x size=%d)%s\n", -#endif + os << StringPrintf("\t\tINVOKE STUB: %p (offset=0x%08x size=%d)%s\n", oat_method.GetInvokeStub(), oat_method.GetInvokeStubOffset(), oat_method.GetInvokeStubSize(), -#if defined(ART_USE_LLVM_COMPILER) - static_cast<int>(oat_method.GetInvokeStubElfIndex()), - static_cast<int>(oat_method.GetInvokeStubElfFuncIndex()), -#endif oat_method.GetInvokeStub() != NULL ? "..." : ""); DumpCode(os, reinterpret_cast<const void*>(oat_method.GetInvokeStub()), oat_method.GetInvokeStubSize(), NULL, dex_file, NULL); @@ -1158,8 +1132,6 @@ static int oatdump(int argc, char** argv) { image_filename = option.substr(strlen("--image=")).data(); } else if (option.starts_with("--boot-image=")) { boot_image_filename = option.substr(strlen("--boot-image=")).data(); - } else if (option.starts_with("--extract-elf-to=")) { - elf_filename_prefix = option.substr(strlen("--extract-elf-to=")).data(); } else if (option.starts_with("--host-prefix=")) { host_prefix.reset(new std::string(option.substr(strlen("--host-prefix=")).data())); } else if (option.starts_with("--output=")) { @@ -1204,25 +1176,6 @@ static int oatdump(int argc, char** argv) { } OatDumper oat_dumper(*host_prefix.get(), *oat_file); oat_dumper.Dump(*os); - -#if defined(ART_USE_LLVM_COMPILER) - if (!elf_filename_prefix.empty()) { - uint32_t elf_image_count = oat_file->GetOatHeader().GetElfImageCount(); - for (uint32_t i = 0; i < elf_image_count; ++i) { - const OatFile::OatElfImage* elf_image = oat_file->GetOatElfImage(i); - - std::string elf_filename( - StringPrintf("%s-%u", elf_filename_prefix.c_str(), i)); - - UniquePtr<File> elf_file(OS::OpenFile(elf_filename.c_str(), true)); - - if (!elf_file->WriteFully(elf_image->begin(), elf_image->size())) { - fprintf(stderr, "Failed to write ELF image to: %s\n", - elf_filename.c_str()); - } - } - } -#endif return EXIT_SUCCESS; } diff --git a/src/runtime.cc b/src/runtime.cc index 5f20a4ba3b..b5928b2d0d 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -48,6 +48,10 @@ #include "verifier/method_verifier.h" #include "well_known_classes.h" +#if defined(ART_USE_LLVM_COMPILER) +#include "compiler_llvm/procedure_linkage_table.h" +#endif + #include "JniConstants.h" // Last to avoid LOG redefinition in ics-mr1-plus-art. namespace art { @@ -83,13 +87,27 @@ Runtime::Runtime() tracer_(NULL), use_compile_time_class_path_(false), main_thread_group_(NULL), - system_thread_group_(NULL) { + system_thread_group_(NULL) +#if defined(ART_USE_LLVM_COMPILER) +#if defined(__arm__) + , plt_(kArm) +#elif defined(__mips__) + , plt_(kMips) +#elif defined(__i386__) + , plt_(kX86) +#endif +#endif + { for (int i = 0; i < Runtime::kLastTrampolineMethodType; i++) { resolution_stub_array_[i] = NULL; } for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) { callee_save_methods_[i] = NULL; } + +#if defined(ART_USE_LLVM_COMPILER) + CHECK(plt_.AllocateTable()) << "Failed to allocate PLT"; +#endif } Runtime::~Runtime() { diff --git a/src/runtime.h b/src/runtime.h index a6cebe74bb..ba579ea5bd 100644 --- a/src/runtime.h +++ b/src/runtime.h @@ -33,6 +33,10 @@ #include "safe_map.h" #include "stringpiece.h" +#if defined(ART_USE_LLVM_COMPILER) +#include "compiler_llvm/procedure_linkage_table.h" +#endif + namespace art { template<class T> class PrimitiveArray; @@ -422,6 +426,9 @@ class Runtime { jobject main_thread_group_; jobject system_thread_group_; +#if defined(ART_USE_LLVM_COMPILER) + compiler_llvm::ProcedureLinkageTable plt_; +#endif DISALLOW_COPY_AND_ASSIGN(Runtime); }; |