From d4f82b63556a5e143e0c35fc06b69dbb60405f77 Mon Sep 17 00:00:00 2001 From: TDYa127 Date: Sat, 2 Jun 2012 21:48:09 -0700 Subject: Inline String.IndexOf and String.CompareTo. Change-Id: Ie012ff37f5d0e3ae48ac4c01b9e475628b11e45d --- src/compiler_llvm/method_compiler.cc | 85 ++++++++++++++++++++++++++++++++---- 1 file changed, 77 insertions(+), 8 deletions(-) (limited to 'src/compiler_llvm/method_compiler.cc') diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc index cd79dcb7bf..eecace0923 100644 --- a/src/compiler_llvm/method_compiler.cc +++ b/src/compiler_llvm/method_compiler.cc @@ -4029,6 +4029,15 @@ bool MethodCompiler::EmitInlineJavaIntrinsic(const std::string& callee_method_na if (callee_method_name == "int java.lang.String.length()") { return EmitInlinedStringLength(args, after_invoke); } + if (callee_method_name == "int java.lang.String.indexOf(int, int)") { + return EmitInlinedStringIndexOf(args, after_invoke, false /* base 0 */); + } + if (callee_method_name == "int java.lang.String.indexOf(int)") { + return EmitInlinedStringIndexOf(args, after_invoke, true /* base 0 */); + } + if (callee_method_name == "int java.lang.String.compareTo(java.lang.String)") { + return EmitInlinedStringCompareTo(args, after_invoke); + } return true; } @@ -4041,26 +4050,23 @@ bool MethodCompiler::EmitInlinedStringCharAt(const std::vector& ar 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.(...)) llvm::Value* string_count = irb_.LoadFromObjectOffset(this_object, String::CountOffset().Int32Value(), irb_.getJIntTy(), - kTBAAHeapInstance, kInt); + kTBAAConstJObject); // 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); + kTBAAConstJObject); llvm::Value* string_value = irb_.LoadFromObjectOffset(this_object, String::ValueOffset().Int32Value(), irb_.getJObjectTy(), - kTBAAHeapInstance, kObject); + kTBAAConstJObject); // index_value = string.offset + char_index llvm::Value* index_value = irb_.CreateAdd(string_offset, char_index); @@ -4081,16 +4087,79 @@ bool MethodCompiler::EmitInlinedStringLength(const std::vector& ar 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); + kTBAAConstJObject); EmitStoreDalvikRetValReg(kInt, kAccurate, string_count); irb_.CreateBr(after_invoke); return false; } +bool MethodCompiler::EmitInlinedStringIndexOf(const std::vector& args, + llvm::BasicBlock* after_invoke, + bool zero_based) { + // TODO: Don't generate target specific bitcode, using intrinsic to delay to codegen. + if (compiler_->GetInstructionSet() == kArm || compiler_->GetInstructionSet() == kThumb2) { + DCHECK_EQ(args.size(), (zero_based ? 3U : 4U)) << + "int java.lang.String.indexOf(int, int = 0) has 3~4 args: method, this, char, start"; + llvm::Value* this_object = args[1]; + llvm::Value* char_target = args[2]; + llvm::Value* start_index = (zero_based ? irb_.getJInt(0) : args[3]); + llvm::BasicBlock* block_retry = llvm::BasicBlock::Create(*context_, "IndexOfRetry", func_); + llvm::BasicBlock* block_cont = llvm::BasicBlock::Create(*context_, "IndexOfCont", func_); + + llvm::Value* slowpath = irb_.CreateICmpSGT(char_target, irb_.getJInt(0xFFFF)); + irb_.CreateCondBr(slowpath, block_retry, block_cont, kUnlikely); + + irb_.SetInsertPoint(block_cont); + + llvm::Type* args_type[] = { irb_.getJObjectTy(), irb_.getJIntTy(), irb_.getJIntTy() }; + llvm::FunctionType* func_ty = llvm::FunctionType::get(irb_.getJIntTy(), args_type, false); + llvm::Value* func = + irb_.Runtime().EmitLoadFromThreadOffset(ENTRYPOINT_OFFSET(pIndexOf), + func_ty->getPointerTo(), + kTBAAConstJObject); + llvm::Value* result = irb_.CreateCall3(func, this_object, char_target, start_index); + EmitStoreDalvikRetValReg(kInt, kAccurate, result); + irb_.CreateBr(after_invoke); + + irb_.SetInsertPoint(block_retry); + } + return true; +} + +bool MethodCompiler::EmitInlinedStringCompareTo(const std::vector& args, + llvm::BasicBlock* after_invoke) { + // TODO: Don't generate target specific bitcode, using intrinsic to delay to codegen. + if (compiler_->GetInstructionSet() == kArm || compiler_->GetInstructionSet() == kThumb2) { + DCHECK_EQ(args.size(), 3U) << + "int java.lang.String.compareTo(java.lang.String) has 3 args: method, this, cmpto"; + llvm::Value* this_object = args[1]; + llvm::Value* cmp_object = args[2]; + llvm::BasicBlock* block_retry = llvm::BasicBlock::Create(*context_, "CompareToRetry", func_); + llvm::BasicBlock* block_cont = llvm::BasicBlock::Create(*context_, "CompareToCont", func_); + + llvm::Value* is_null = irb_.CreateICmpEQ(cmp_object, irb_.getJNull()); + irb_.CreateCondBr(is_null, block_retry, block_cont, kUnlikely); + + irb_.SetInsertPoint(block_cont); + + llvm::Type* args_type[] = { irb_.getJObjectTy(), irb_.getJObjectTy() }; + llvm::FunctionType* func_ty = llvm::FunctionType::get(irb_.getJIntTy(), args_type, false); + llvm::Value* func = + irb_.Runtime().EmitLoadFromThreadOffset(ENTRYPOINT_OFFSET(pStringCompareTo), + func_ty->getPointerTo(), + kTBAAConstJObject); + llvm::Value* result = irb_.CreateCall2(func, this_object, cmp_object); + EmitStoreDalvikRetValReg(kInt, kAccurate, result); + irb_.CreateBr(after_invoke); + + irb_.SetInsertPoint(block_retry); + } + return true; +} + bool MethodCompiler::IsInstructionDirectToReturn(uint32_t dex_pc) { for (int i = 0; i < 8; ++i) { // Trace at most 8 instructions. -- cgit v1.2.3-59-g8ed1b