Implement partial sharpening for LLVM.
Change-Id: I0c6953d6428edda71230c0088b9e0c9decada3b7
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 8e592fe..8d6b251 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -36,9 +36,12 @@
#include <iomanip>
#include <llvm/BasicBlock.h>
+#include <llvm/DerivedTypes.h>
#include <llvm/Function.h>
#include <llvm/GlobalVariable.h>
#include <llvm/Intrinsics.h>
+#include <llvm/Module.h>
+#include <llvm/Type.h>
namespace art {
namespace compiler_llvm {
@@ -2806,7 +2809,7 @@
// Compute invoke related information for compiler decision
int vtable_idx = -1;
uintptr_t direct_code = 0; // Currently unused
- uintptr_t direct_method = 0; // Currently unused
+ uintptr_t direct_method = 0;
bool is_fast_path = compiler_->
ComputeInvokeInfo(callee_method_idx, oat_compilation_unit_,
invoke_type, vtable_idx, direct_code, direct_method);
@@ -2834,8 +2837,15 @@
switch (invoke_type) {
case kStatic:
case kDirect:
- callee_method_object_addr =
- EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
+ if (direct_method != 0u &&
+ direct_method != static_cast<uintptr_t>(-1)) {
+ callee_method_object_addr =
+ EmitLoadSDCalleeDirectMethodObjectAddr(callee_method_idx,
+ direct_method);
+ } else {
+ callee_method_object_addr =
+ EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
+ }
break;
case kVirtual:
@@ -2982,6 +2992,27 @@
llvm::Value* MethodCompiler::
+EmitLoadSDCalleeDirectMethodObjectAddr(uint32_t callee_method_idx,
+ uintptr_t direct_method) {
+ std::string direct_method_name(
+ StringPrintf("ArtMethodObject_%08lx",
+ static_cast<unsigned long>(direct_method)));
+
+ llvm::GlobalVariable* direct_method_addr =
+ module_->getGlobalVariable(direct_method_name);
+
+ if (direct_method_addr == NULL) {
+ direct_method_addr =
+ new llvm::GlobalVariable(*module_, irb_.getJObjectTy()->getElementType(),
+ false, llvm::GlobalVariable::ExternalLinkage,
+ NULL, direct_method_name);
+ }
+
+ return direct_method_addr;
+}
+
+
+llvm::Value* MethodCompiler::
EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx) {
llvm::Value* callee_method_object_field_addr =
EmitLoadDexCacheResolvedMethodFieldAddr(callee_method_idx);
diff --git a/src/compiler_llvm/method_compiler.h b/src/compiler_llvm/method_compiler.h
index 7dded33..84c55d6 100644
--- a/src/compiler_llvm/method_compiler.h
+++ b/src/compiler_llvm/method_compiler.h
@@ -215,6 +215,9 @@
llvm::Value* EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx);
+ llvm::Value* EmitLoadSDCalleeDirectMethodObjectAddr(uint32_t callee_method_idx,
+ uintptr_t direct_method);
+
llvm::Value* EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx,
llvm::Value* this_addr);
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index fce0f41..1ebbef9 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -797,6 +797,15 @@
}
}
+ // Fixed method object address
+ const char method_object_prefix[] = "ArtMethodObject_";
+ const size_t method_object_prefix_len = sizeof(method_object_prefix) - 1;
+ if (strncmp(name, method_object_prefix, method_object_prefix_len) == 0) {
+ const char* addr_str = name + method_object_prefix_len;
+ unsigned long addr_int = strtoul(addr_str, NULL, 16);
+ return reinterpret_cast<void*>(addr_int);
+ }
+
LOG(FATAL) << "Error: Can't find symbol " << name;
return 0;
}