Implement proxy stub for compiler_llvm.
Change-Id: Id8ba59c62795d885a18b3cc634e7ef370a2d2f97
diff --git a/src/compiler_llvm/compiler_llvm.cc b/src/compiler_llvm/compiler_llvm.cc
index 6d30912..95e9803 100644
--- a/src/compiler_llvm/compiler_llvm.cc
+++ b/src/compiler_llvm/compiler_llvm.cc
@@ -30,7 +30,7 @@
#include "oat_compilation_unit.h"
#include "oat_file.h"
#include "stl_util.h"
-#include "upcall_compiler.h"
+#include "stub_compiler.h"
#include <llvm/LinkAllPasses.h>
#include <llvm/LinkAllVMCore.h>
@@ -225,8 +225,8 @@
const Method::InvokeStub* CompilerLLVM::
GetMethodInvokeStubAddr(const CompiledInvokeStub* cm) const {
- return elf_loader_->GetMethodInvokeStubAddr(cm->GetElfIndex(),
- cm->GetElfFuncIndex());
+ return elf_loader_->GetMethodInvokeStubAddr(cm->GetStubElfIndex(),
+ cm->GetInvokeStubElfFuncIndex());
}
@@ -279,10 +279,15 @@
MutexLock GUARD_CUNIT(curr_cunit_->cunit_lock_);
- UniquePtr<UpcallCompiler> upcall_compiler(
- new UpcallCompiler(curr_cunit_, *compiler_));
+ UniquePtr<StubCompiler> stub_compiler(
+ new StubCompiler(curr_cunit_, *compiler_));
- return upcall_compiler->CreateStub(is_static, shorty);
+ CompiledInvokeStub* compiled_stub = new CompiledInvokeStub(curr_cunit_->GetElfIndex());
+
+ compiled_stub->SetInvokeStub(stub_compiler->CreateInvokeStub(is_static, shorty));
+ compiled_stub->SetProxyStub(stub_compiler->CreateProxyStub(is_static, shorty));
+
+ return compiled_stub;
}
} // namespace compiler_llvm
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 620ba39..cd79dcb 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -72,7 +72,7 @@
basic_blocks_(code_item_->insns_size_in_code_units_),
basic_block_landing_pads_(code_item_->tries_size_, NULL),
basic_block_unwind_(NULL), basic_block_unreachable_(NULL),
- shadow_frame_(NULL), jvalue_temp_(NULL), old_shadow_frame_(NULL),
+ shadow_frame_(NULL), old_shadow_frame_(NULL),
already_pushed_shadow_frame_(NULL), shadow_frame_size_(0),
elf_func_idx_(cunit_->AcquireUniqueElfFuncIndex()) {
}
@@ -168,7 +168,6 @@
#endif
irb_.SetInsertPoint(basic_block_alloca_);
- jvalue_temp_ = irb_.CreateAlloca(irb_.getJValueTy());
// Create Shadow Frame
if (method_info_.need_shadow_frame) {
@@ -2880,10 +2879,7 @@
llvm::BasicBlock* block_stub = CreateBasicBlockWithDexPC(dex_pc, "stub");
llvm::BasicBlock* block_continue = CreateBasicBlockWithDexPC(dex_pc, "cont");
- llvm::Value* code_addr_int = irb_.CreatePtrToInt(code_addr, irb_.getPtrEquivIntTy());
- llvm::Value* max_stub_int = irb_.getPtrEquivInt(special_stub::kMaxSpecialStub);
- llvm::Value* is_stub = irb_.CreateICmpULT(code_addr_int, max_stub_int);
- irb_.CreateCondBr(is_stub, block_stub, block_normal, kUnlikely);
+ irb_.CreateCondBr(irb_.CreateIsNull(code_addr), block_stub, block_normal, kUnlikely);
irb_.SetInsertPoint(block_normal);
@@ -2898,42 +2894,15 @@
irb_.SetInsertPoint(block_stub);
- {
- { // lazy link
- // TODO: Remove this after we solve the link problem.
- llvm::BasicBlock* block_proxy_stub = CreateBasicBlockWithDexPC(dex_pc, "proxy");
- llvm::BasicBlock* block_link = CreateBasicBlockWithDexPC(dex_pc, "link");
+ { // lazy link
+ // TODO: Remove this after we solve the link problem.
+ code_addr = EmitFixStub(callee_method_object_addr, callee_method_idx, is_static);
- irb_.CreateCondBr(irb_.CreateIsNull(code_addr), block_link, block_proxy_stub, kUnlikely);
+ EmitGuard_ExceptionLandingPad(dex_pc, false);
-
- irb_.SetInsertPoint(block_link);
- code_addr = EmitFixStub(callee_method_object_addr, callee_method_idx, is_static);
-
- EmitGuard_ExceptionLandingPad(dex_pc, false);
-
- llvm::Value* retval = irb_.CreateCall(code_addr, args);
- if (ret_shorty != 'V') {
- EmitStoreDalvikRetValReg(ret_shorty, kAccurate, retval);
- }
- irb_.CreateBr(block_continue);
-
-
- irb_.SetInsertPoint(block_proxy_stub);
- }
- { // proxy stub
- if (ret_shorty != 'V') {
- args.push_back(jvalue_temp_);
- }
- // TODO: Remove this after we solve the proxy trampoline calling convention problem.
- irb_.CreateCall(irb_.GetRuntime(ProxyInvokeHandler), args);
- if (ret_shorty != 'V') {
- llvm::Type* accurate_ret_type = irb_.getJType(ret_shorty, kAccurate);
- llvm::Value* result_addr =
- irb_.CreateBitCast(jvalue_temp_, accurate_ret_type->getPointerTo());
- llvm::Value* retval = irb_.CreateLoad(result_addr, kTBAAStackTemp);
- EmitStoreDalvikRetValReg(ret_shorty, kAccurate, retval);
- }
+ llvm::Value* retval = irb_.CreateCall(code_addr, args);
+ if (ret_shorty != 'V') {
+ EmitStoreDalvikRetValReg(ret_shorty, kAccurate, retval);
}
}
irb_.CreateBr(block_continue);
diff --git a/src/compiler_llvm/method_compiler.h b/src/compiler_llvm/method_compiler.h
index 44ab863..1907823 100644
--- a/src/compiler_llvm/method_compiler.h
+++ b/src/compiler_llvm/method_compiler.h
@@ -473,7 +473,6 @@
llvm::BasicBlock* basic_block_unreachable_;
llvm::AllocaInst* shadow_frame_;
- llvm::AllocaInst* jvalue_temp_;
llvm::Value* old_shadow_frame_;
llvm::Value* already_pushed_shadow_frame_;
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index 578f84e..59124ce 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -654,7 +654,7 @@
va_start(ap, proxy_method);
Object* receiver = va_arg(ap, Object*);
- Thread* thread = art_get_current_thread_from_code();
+ Thread* thread = va_arg(ap, Thread*);
MethodHelper proxy_mh(proxy_method);
const size_t num_params = proxy_mh.NumArgs();
diff --git a/src/compiler_llvm/runtime_support_llvm.h b/src/compiler_llvm/runtime_support_llvm.h
index bca9528..3e8d96d 100644
--- a/src/compiler_llvm/runtime_support_llvm.h
+++ b/src/compiler_llvm/runtime_support_llvm.h
@@ -19,16 +19,6 @@
namespace art {
-namespace compiler_llvm {
-namespace special_stub {
- enum SpecialStub {
- kProxyStub = 16,
- kMaxSpecialStub
- };
-}
-} // namespace compiler_llvm
-
-
class Method;
class Object;
diff --git a/src/compiler_llvm/upcall_compiler.cc b/src/compiler_llvm/stub_compiler.cc
similarity index 67%
rename from src/compiler_llvm/upcall_compiler.cc
rename to src/compiler_llvm/stub_compiler.cc
index 0f3a92e..2cf5141 100644
--- a/src/compiler_llvm/upcall_compiler.cc
+++ b/src/compiler_llvm/stub_compiler.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "upcall_compiler.h"
+#include "stub_compiler.h"
#include "compilation_unit.h"
#include "compiled_method.h"
@@ -40,21 +40,21 @@
using namespace runtime_support;
-UpcallCompiler::UpcallCompiler(CompilationUnit* cunit, Compiler& compiler)
+StubCompiler::StubCompiler(CompilationUnit* cunit, Compiler& compiler)
: cunit_(cunit), compiler_(&compiler), module_(cunit_->GetModule()),
- context_(cunit_->GetLLVMContext()), irb_(*cunit_->GetIRBuilder()),
- elf_func_idx_(cunit_->AcquireUniqueElfFuncIndex()) {
+ context_(cunit_->GetLLVMContext()), irb_(*cunit_->GetIRBuilder()) {
}
-CompiledInvokeStub* UpcallCompiler::CreateStub(bool is_static,
- char const* shorty) {
+uint16_t StubCompiler::CreateInvokeStub(bool is_static,
+ char const* shorty) {
+ uint16_t elf_func_idx = cunit_->AcquireUniqueElfFuncIndex();
CHECK_NE(shorty, static_cast<char const*>(NULL));
size_t shorty_size = strlen(shorty);
// Function name
- std::string func_name(ElfFuncName(elf_func_idx_));
+ std::string func_name(ElfFuncName(elf_func_idx));
// Get argument types
llvm::Type* arg_types[] = {
@@ -189,7 +189,80 @@
// store ret_addr, and ret_void. Beside, we guess that we have to use
// 50 bytes to represent one LLVM instruction.
- return new CompiledInvokeStub(cunit_->GetElfIndex(), elf_func_idx_);
+ return elf_func_idx;
+}
+
+uint16_t StubCompiler::CreateProxyStub(bool is_static,
+ char const* shorty) {
+ // Static method dosen't need proxy stub.
+ if (is_static) {
+ return NULL;
+ }
+
+ CHECK_NE(shorty, static_cast<char const*>(NULL));
+ size_t shorty_size = strlen(shorty);
+
+ uint16_t elf_func_idx = cunit_->AcquireUniqueElfFuncIndex();
+
+ // Function name
+ std::string func_name(ElfFuncName(elf_func_idx));
+
+ // Accurate function type
+ llvm::Type* accurate_ret_type = irb_.getJType(shorty[0], kAccurate);
+ std::vector<llvm::Type*> accurate_arg_types;
+ accurate_arg_types.push_back(irb_.getJObjectTy()); // method
+ accurate_arg_types.push_back(irb_.getJObjectTy()); // this
+ for (size_t i = 1; i < shorty_size; ++i) {
+ accurate_arg_types.push_back(irb_.getJType(shorty[i], kAccurate));
+ }
+ llvm::FunctionType* accurate_func_type =
+ llvm::FunctionType::get(accurate_ret_type, accurate_arg_types, false);
+
+ // Create function
+ llvm::Function* func =
+ llvm::Function::Create(accurate_func_type, llvm::Function::ExternalLinkage,
+ func_name, module_);
+
+ // Create basic block for the body of this function
+ llvm::BasicBlock* block_body =
+ llvm::BasicBlock::Create(*context_, "proxy", func);
+ irb_.SetInsertPoint(block_body);
+
+ // JValue for proxy return
+ llvm::AllocaInst* jvalue_temp = irb_.CreateAlloca(irb_.getJValueTy());
+
+ // Load actual arguments
+ llvm::Function::arg_iterator arg_iter = func->arg_begin();
+ std::vector<llvm::Value*> args;
+ args.push_back(arg_iter++); // method
+ args.push_back(arg_iter++); // this
+ args.push_back(irb_.Runtime().EmitGetCurrentThread()); // thread
+ for (size_t i = 1; i < shorty_size; ++i) {
+ args.push_back(arg_iter++);
+ }
+ if (shorty[0] != 'V') {
+ args.push_back(jvalue_temp);
+ }
+
+ // Call ProxyInvokeHandler
+ // TODO: Partial inline ProxyInvokeHandler, don't use VarArg.
+ irb_.CreateCall(irb_.GetRuntime(ProxyInvokeHandler), args);
+ if (shorty[0] != 'V') {
+ llvm::Value* result_addr =
+ irb_.CreateBitCast(jvalue_temp, accurate_ret_type->getPointerTo());
+ llvm::Value* retval = irb_.CreateLoad(result_addr, kTBAAStackTemp);
+ irb_.CreateRet(retval);
+ } else {
+ irb_.CreateRetVoid();
+ }
+
+ // Verify the generated function
+ VERIFY_LLVM_FUNCTION(*func);
+
+ // Add the memory usage approximation of the compilation unit
+ cunit_->AddMemUsageApproximation((shorty_size + 2) * 50);
+
+ return elf_func_idx;
}
diff --git a/src/compiler_llvm/upcall_compiler.h b/src/compiler_llvm/stub_compiler.h
similarity index 73%
rename from src/compiler_llvm/upcall_compiler.h
rename to src/compiler_llvm/stub_compiler.h
index 9cb49b0..4b49ec4 100644
--- a/src/compiler_llvm/upcall_compiler.h
+++ b/src/compiler_llvm/stub_compiler.h
@@ -14,13 +14,14 @@
* limitations under the License.
*/
-#ifndef ART_SRC_COMPILER_LLVM_UPCALL_COMPILER_H_
-#define ART_SRC_COMPILER_LLVM_UPCALL_COMPILER_H_
+#ifndef ART_SRC_COMPILER_LLVM_STUB_COMPILER_H_
+#define ART_SRC_COMPILER_LLVM_STUB_COMPILER_H_
#include <stdint.h>
namespace art {
class CompiledInvokeStub;
+ class CompiledProxyStub;
class Compiler;
}
@@ -36,11 +37,12 @@
class CompilerLLVM;
class IRBuilder;
-class UpcallCompiler {
+class StubCompiler {
public:
- UpcallCompiler(CompilationUnit* cunit, Compiler& compiler);
+ StubCompiler(CompilationUnit* cunit, Compiler& compiler);
- CompiledInvokeStub* CreateStub(bool is_static, char const* shorty);
+ uint16_t CreateInvokeStub(bool is_static, char const* shorty);
+ uint16_t CreateProxyStub(bool is_static, char const* shorty);
private:
CompilationUnit* cunit_;
@@ -48,7 +50,6 @@
llvm::Module* module_;
llvm::LLVMContext* context_;
IRBuilder& irb_;
- uint16_t elf_func_idx_;
};
@@ -56,4 +57,4 @@
} // namespace art
-#endif // ART_SRC_COMPILER_LLVM_UPCALL_COMPILER_H_
+#endif // ART_SRC_COMPILER_LLVM_STUB_COMPILER_H_