Home | History | Annotate | Download | only in llvm
      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