Inline specific method.
Change-Id: Ie9f035211df3ad552768be6aa3c6a38adb3ce046
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 3122712..474b89e 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -2809,12 +2809,6 @@
}
}
- llvm::Value* code_addr =
- irb_.LoadFromObjectOffset(callee_method_object_addr,
- Method::GetCodeOffset().Int32Value(),
- GetFunctionType(callee_method_idx, is_static)->getPointerTo(),
- kTBAAJRuntime);
-
// Load the actual parameter
std::vector<llvm::Value*> args;
@@ -2828,6 +2822,21 @@
EmitLoadActualParameters(args, callee_method_idx, dec_insn,
arg_fmt, is_static);
+ if (is_fast_path && (invoke_type == kDirect || invoke_type == kStatic)) {
+ bool need_retry = EmitInlineJavaIntrinsic(PrettyMethod(callee_method_idx, *dex_file_),
+ args,
+ GetNextBasicBlock(dex_pc));
+ if (!need_retry) {
+ return;
+ }
+ }
+
+ llvm::Value* code_addr =
+ irb_.LoadFromObjectOffset(callee_method_object_addr,
+ Method::GetCodeOffset().Int32Value(),
+ GetFunctionType(callee_method_idx, is_static)->getPointerTo(),
+ kTBAAJRuntime);
+
#if 0
// Invoke callee
EmitUpdateDexPC(dex_pc);
@@ -3952,6 +3961,79 @@
// TODO: Use high-level IR to do this
+bool MethodCompiler::EmitInlineJavaIntrinsic(const std::string& callee_method_name,
+ const std::vector<llvm::Value*>& args,
+ llvm::BasicBlock* after_invoke) {
+ if (callee_method_name == "char java.lang.String.charAt(int)") {
+ return EmitInlinedStringCharAt(args, after_invoke);
+ }
+ if (callee_method_name == "int java.lang.String.length()") {
+ return EmitInlinedStringLength(args, after_invoke);
+ }
+ return true;
+}
+
+bool MethodCompiler::EmitInlinedStringCharAt(const std::vector<llvm::Value*>& args,
+ llvm::BasicBlock* after_invoke) {
+ DCHECK_EQ(args.size(), 3U) <<
+ "char java.lang.String.charAt(int) has 3 args: method, this, char_index";
+ llvm::Value* this_object = args[1];
+ llvm::Value* char_index = args[2];
+ llvm::BasicBlock* block_retry = llvm::BasicBlock::Create(*context_, "CharAtRetry", func_);
+ llvm::BasicBlock* block_cont = llvm::BasicBlock::Create(*context_, "CharAtCont", func_);
+
+ // TODO: Can we safely say the String.count is ConstJObject(constant memory)? (there are so many
+ // iput to String.count in the String.<init>(...))
+ llvm::Value* string_count = irb_.LoadFromObjectOffset(this_object,
+ String::CountOffset().Int32Value(),
+ irb_.getJIntTy(),
+ kTBAAHeapInstance, kInt);
+ // Two's complement, so we can use only one "less than" to check "in bounds"
+ llvm::Value* in_bounds = irb_.CreateICmpULT(char_index, string_count);
+ irb_.CreateCondBr(in_bounds, block_cont, block_retry, kLikely);
+
+ irb_.SetInsertPoint(block_cont);
+ // TODO: Can we safely say the String.offset is ConstJObject(constant memory)?
+ llvm::Value* string_offset = irb_.LoadFromObjectOffset(this_object,
+ String::OffsetOffset().Int32Value(),
+ irb_.getJIntTy(),
+ kTBAAHeapInstance, kInt);
+ llvm::Value* string_value = irb_.LoadFromObjectOffset(this_object,
+ String::ValueOffset().Int32Value(),
+ irb_.getJObjectTy(),
+ kTBAAHeapInstance, kObject);
+
+ // index_value = string.offset + char_index
+ llvm::Value* index_value = irb_.CreateAdd(string_offset, char_index);
+
+ // array_elem_value = string.value[index_value]
+ llvm::Value* array_elem_addr = EmitArrayGEP(string_value, index_value, kChar);
+ llvm::Value* array_elem_value = irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, kChar);
+
+ EmitStoreDalvikRetValReg(kChar, kArray, array_elem_value);
+ irb_.CreateBr(after_invoke);
+
+ irb_.SetInsertPoint(block_retry);
+ return true;
+}
+
+bool MethodCompiler::EmitInlinedStringLength(const std::vector<llvm::Value*>& args,
+ llvm::BasicBlock* after_invoke) {
+ DCHECK_EQ(args.size(), 2U) <<
+ "int java.lang.String.length() has 2 args: method, this";
+ llvm::Value* this_object = args[1];
+ // TODO: Can we safely say the String.count is ConstJObject(constant memory)?
+ llvm::Value* string_count = irb_.LoadFromObjectOffset(this_object,
+ String::CountOffset().Int32Value(),
+ irb_.getJIntTy(),
+ kTBAAHeapInstance, kInt);
+ EmitStoreDalvikRetValReg(kInt, kAccurate, string_count);
+ irb_.CreateBr(after_invoke);
+ return false;
+}
+
+
+// TODO: Use high-level IR to do this
void MethodCompiler::ComputeMethodInfo() {
// If this method is static, we set the "this" register index to -1. So we don't worry about this
// method is static or not in the following comparison.