1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "runtime_support_builder_thumb2.h" 18 19 #include "ir_builder.h" 20 #include "mirror/object.h" 21 #include "monitor.h" 22 #include "thread.h" 23 #include "utils_llvm.h" 24 25 #include <llvm/IR/DerivedTypes.h> 26 #include <llvm/IR/Function.h> 27 #include <llvm/IR/InlineAsm.h> 28 #include <llvm/IR/Module.h> 29 #include <llvm/IR/Type.h> 30 31 #include <inttypes.h> 32 #include <vector> 33 34 using ::llvm::BasicBlock; 35 using ::llvm::Function; 36 using ::llvm::FunctionType; 37 using ::llvm::InlineAsm; 38 using ::llvm::Type; 39 using ::llvm::Value; 40 41 namespace art { 42 namespace llvm { 43 44 45 void RuntimeSupportBuilderThumb2::EmitLockObject(Value* object) { 46 FunctionType* func_ty = FunctionType::get(/*Result=*/irb_.getInt32Ty(), 47 /*Params=*/irb_.getJObjectTy(), 48 /*isVarArg=*/false); 49 // $0: result 50 // $1: object 51 // $2: temp 52 // $3: temp 53 std::string asms; 54 StringAppendF(&asms, "add $3, $1, #%" PRId32 "\n", mirror::Object::MonitorOffset().Int32Value()); 55 StringAppendF(&asms, "ldr $2, [r9, #%" PRId32 "]\n", Thread::ThinLockIdOffset().Int32Value()); 56 StringAppendF(&asms, "ldrex $0, [$3]\n"); 57 StringAppendF(&asms, "lsl $2, $2, %d\n", LW_LOCK_OWNER_SHIFT); 58 StringAppendF(&asms, "bfi $2, $0, #0, #%d\n", LW_LOCK_OWNER_SHIFT - 1); 59 StringAppendF(&asms, "bfc $0, #%d, #%d\n", LW_HASH_STATE_SHIFT, LW_LOCK_OWNER_SHIFT - 1); 60 StringAppendF(&asms, "cmp $0, #0\n"); 61 StringAppendF(&asms, "it eq\n"); 62 StringAppendF(&asms, "strexeq $0, $2, [$3]\n"); 63 64 InlineAsm* func = InlineAsm::get(func_ty, asms, "=&l,l,~l,~l", true); 65 66 Value* retry_slow_path = irb_.CreateCall(func, object); 67 retry_slow_path = irb_.CreateICmpNE(retry_slow_path, irb_.getJInt(0)); 68 69 Function* parent_func = irb_.GetInsertBlock()->getParent(); 70 BasicBlock* basic_block_lock = BasicBlock::Create(context_, "lock", parent_func); 71 BasicBlock* basic_block_cont = BasicBlock::Create(context_, "lock_cont", parent_func); 72 irb_.CreateCondBr(retry_slow_path, basic_block_lock, basic_block_cont, kUnlikely); 73 74 irb_.SetInsertPoint(basic_block_lock); 75 Function* slow_func = GetRuntimeSupportFunction(runtime_support::LockObject); 76 irb_.CreateCall2(slow_func, object, EmitGetCurrentThread()); 77 irb_.CreateBr(basic_block_cont); 78 79 irb_.SetInsertPoint(basic_block_cont); 80 { // Memory barrier 81 FunctionType* asm_ty = FunctionType::get(/*Result=*/Type::getVoidTy(context_), 82 /*isVarArg=*/false); 83 InlineAsm* func = InlineAsm::get(asm_ty, "dmb sy", "", true); 84 irb_.CreateCall(func); 85 } 86 } 87 88 89 } // namespace llvm 90 } // namespace art 91