Update frame size after the bitcode is translated into machine code.
Change-Id: I59923a6cb1a1079d9cfe6d995fe0067ee1c49e80
diff --git a/src/compiled_method.h b/src/compiled_method.h
index 2920256..96dfa00 100644
--- a/src/compiled_method.h
+++ b/src/compiled_method.h
@@ -65,6 +65,12 @@
const std::vector<uint16_t>& GetVmapTable() const;
const std::vector<uint8_t>& GetGcMap() const;
+#if defined(ART_USE_LLVM_COMPILER)
+ void SetFrameSizeInBytes(size_t new_frame_size_in_bytes) {
+ frame_size_in_bytes_ = new_frame_size_in_bytes;
+ }
+#endif
+
// Aligns an offset from a page aligned value to make it suitable
// for code storage. important to ensure that PC relative value
// computations work out as expected on ARM.
@@ -99,7 +105,7 @@
// For non-LLVM
const InstructionSet instruction_set_;
std::vector<uint8_t> code_;
- const size_t frame_size_in_bytes_;
+ size_t frame_size_in_bytes_;
const uint32_t core_spill_mask_;
const uint32_t fp_spill_mask_;
std::vector<uint32_t> mapping_table_;
diff --git a/src/compiler_llvm/compilation_unit.cc b/src/compiler_llvm/compilation_unit.cc
index fde023c..09e193d 100644
--- a/src/compiler_llvm/compilation_unit.cc
+++ b/src/compiler_llvm/compilation_unit.cc
@@ -16,6 +16,7 @@
#include "compilation_unit.h"
+#include "compiled_method.h"
#include "instruction_set.h"
#include "ir_builder.h"
#include "logging.h"
@@ -34,6 +35,9 @@
#include <llvm/Assembly/PrintModulePass.h>
#include <llvm/Bitcode/ReaderWriter.h>
#include <llvm/CallGraphSCCPass.h>
+#include <llvm/CodeGen/MachineFrameInfo.h>
+#include <llvm/CodeGen/MachineFunction.h>
+#include <llvm/CodeGen/MachineFunctionPass.h>
#include <llvm/DerivedTypes.h>
#include <llvm/LLVMContext.h>
#include <llvm/Module.h>
@@ -57,6 +61,40 @@
#include <string>
+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);
+
+} // end anonymous namespace
+
namespace art {
namespace compiler_llvm {
@@ -204,6 +242,9 @@
return false;
}
+ // 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();
@@ -227,5 +268,29 @@
}
+void CompilationUnit::RegisterCompiledMethod(const llvm::Function* func,
+ CompiledMethod* compiled_method) {
+ compiled_methods_map_.Put(func, compiled_method);
+}
+
+
+void CompilationUnit::UpdateFrameSizeInBytes(const llvm::Function* func,
+ size_t frame_size_in_bytes) {
+ 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();
+ }
+ }
+}
+
+
} // namespace compiler_llvm
} // namespace art
diff --git a/src/compiler_llvm/compilation_unit.h b/src/compiler_llvm/compilation_unit.h
index 4b33ece..18ecfa0 100644
--- a/src/compiler_llvm/compilation_unit.h
+++ b/src/compiler_llvm/compilation_unit.h
@@ -23,11 +23,17 @@
#include "logging.h"
#include "runtime_support_builder.h"
#include "runtime_support_func.h"
+#include "safe_map.h"
#include <UniquePtr.h>
#include <string>
+namespace art {
+ class CompiledMethod;
+}
+
namespace llvm {
+ class Function;
class LLVMContext;
class Module;
}
@@ -96,6 +102,10 @@
mem_usage_ += usage;
}
+ void RegisterCompiledMethod(const llvm::Function* func, CompiledMethod* cm);
+
+ void UpdateFrameSizeInBytes(const llvm::Function* func, size_t frame_size_in_bytes);
+
private:
InstructionSet insn_set_;
const size_t elf_idx_;
@@ -108,6 +118,8 @@
std::string elf_image_;
std::string bitcode_filename_;
+ SafeMap<const llvm::Function*, CompiledMethod*> compiled_methods_map_;
+
size_t mem_usage_;
uint16_t num_elf_funcs_;
};
diff --git a/src/compiler_llvm/jni_compiler.cc b/src/compiler_llvm/jni_compiler.cc
index 68ce2d8..b35d792 100644
--- a/src/compiler_llvm/jni_compiler.cc
+++ b/src/compiler_llvm/jni_compiler.cc
@@ -293,9 +293,14 @@
// Verify the generated bitcode
llvm::verifyFunction(*func_, llvm::PrintMessageAction);
- return new CompiledMethod(cunit_->GetInstructionSet(),
- cunit_->GetElfIndex(),
- elf_func_idx_);
+ CompiledMethod* compiled_method =
+ new CompiledMethod(cunit_->GetInstructionSet(),
+ cunit_->GetElfIndex(),
+ elf_func_idx_);
+
+ cunit_->RegisterCompiledMethod(func_, compiled_method);
+
+ return compiled_method;
}
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index fc9c4d8..153d99a 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -3681,9 +3681,14 @@
// Dex file. Besides, we have to convert the code unit into bytes.
// Thus, we got our magic number 9.
- return new CompiledMethod(cunit_->GetInstructionSet(),
- cunit_->GetElfIndex(),
- elf_func_idx_);
+ CompiledMethod* compiled_method =
+ new CompiledMethod(cunit_->GetInstructionSet(),
+ cunit_->GetElfIndex(),
+ elf_func_idx_);
+
+ cunit_->RegisterCompiledMethod(func_, compiled_method);
+
+ return compiled_method;
}
diff --git a/src/oat_writer.cc b/src/oat_writer.cc
index 2ccf207..4d11237 100644
--- a/src/oat_writer.cc
+++ b/src/oat_writer.cc
@@ -277,6 +277,7 @@
if (compiled_method->IsExecutableInElf()) {
code_elf_idx = compiled_method->GetElfIndex();
code_elf_func_idx = compiled_method->GetElfFuncIndex();
+ frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
} else {
offset = compiled_method->AlignCode(offset);
DCHECK_ALIGNED(offset, kArmAlignment);
diff --git a/src/object.h b/src/object.h
index 00492f0..5e67f62 100644
--- a/src/object.h
+++ b/src/object.h
@@ -798,9 +798,7 @@
size_t GetFrameSizeInBytes() const {
DCHECK_EQ(sizeof(size_t), sizeof(uint32_t));
size_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(Method, frame_size_in_bytes_), false);
-#if !defined(ART_USE_LLVM_COMPILER) // LLVM uses shadow stack instead.
DCHECK_LE(static_cast<size_t>(kStackAlignment), result);
-#endif
return result;
}