diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/compiler_llvm/compilation_unit.cc | 15 | ||||
| -rw-r--r-- | src/compiler_llvm/jni_compiler.cc | 15 | ||||
| -rw-r--r-- | src/compiler_llvm/method_compiler.cc | 8 | ||||
| -rw-r--r-- | src/compiler_llvm/runtime_support_builder.cc | 51 | ||||
| -rw-r--r-- | src/compiler_llvm/runtime_support_builder.h | 4 | ||||
| -rw-r--r-- | src/compiler_llvm/runtime_support_builder_arm.cc | 19 | ||||
| -rw-r--r-- | src/compiler_llvm/runtime_support_builder_arm.h | 4 | ||||
| -rw-r--r-- | src/compiler_llvm/runtime_support_builder_thumb2.cc | 85 | ||||
| -rw-r--r-- | src/compiler_llvm/runtime_support_builder_thumb2.h | 37 | ||||
| -rw-r--r-- | src/compiler_llvm/runtime_support_llvm.cc | 2 | ||||
| -rw-r--r-- | src/compiler_llvm/runtime_support_llvm.h | 3 |
11 files changed, 217 insertions, 26 deletions
diff --git a/src/compiler_llvm/compilation_unit.cc b/src/compiler_llvm/compilation_unit.cc index 5f239ab245..5dc03c361e 100644 --- a/src/compiler_llvm/compilation_unit.cc +++ b/src/compiler_llvm/compilation_unit.cc @@ -24,6 +24,7 @@ #include "os.h" #include "runtime_support_builder_arm.h" +#include "runtime_support_builder_thumb2.h" #include "runtime_support_builder_x86.h" #include <llvm/ADT/OwningPtr.h> @@ -180,13 +181,15 @@ CompilationUnit::CompilationUnit(InstructionSet insn_set, size_t elf_idx) // We always need a switch case, so just use a normal function. switch(insn_set_) { - default: - runtime_support_.reset(new RuntimeSupportBuilder(*context_, *module_, *irb_)); - break; + default: + runtime_support_.reset(new RuntimeSupportBuilder(*context_, *module_, *irb_)); + break; case kArm: - case kThumb2: runtime_support_.reset(new RuntimeSupportBuilderARM(*context_, *module_, *irb_)); break; + case kThumb2: + runtime_support_.reset(new RuntimeSupportBuilderThumb2(*context_, *module_, *irb_)); + break; case kX86: runtime_support_.reset(new RuntimeSupportBuilderX86(*context_, *module_, *irb_)); break; @@ -254,13 +257,13 @@ bool CompilationUnit::MaterializeToFile(llvm::raw_ostream& out_stream) { switch (insn_set_) { case kThumb2: target_triple = "thumb-none-linux-gnueabi"; - target_attr = "+thumb2,+neon,+neonfp,+vfp3"; + target_attr = "+thumb2,+neon,+neonfp,+vfp3,+db"; break; case kArm: target_triple = "armv7-none-linux-gnueabi"; // TODO: Fix for Xoom. - target_attr = "+v7,+neon,+neonfp,+vfp3"; + target_attr = "+v7,+neon,+neonfp,+vfp3,+db"; break; case kX86: diff --git a/src/compiler_llvm/jni_compiler.cc b/src/compiler_llvm/jni_compiler.cc index 838c89da81..bb45facba6 100644 --- a/src/compiler_llvm/jni_compiler.cc +++ b/src/compiler_llvm/jni_compiler.cc @@ -108,9 +108,6 @@ CompiledMethod* JniCompiler::Compile() { } } - // Get thread object - llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread(); - // Shadow stack llvm::StructType* shadow_frame_type = irb_.getShadowFrameTy(sirt_size); llvm::AllocaInst* shadow_frame_ = irb_.CreateAlloca(shadow_frame_type); @@ -187,10 +184,7 @@ CompiledMethod* JniCompiler::Compile() { // Acquire lock for synchronized methods. if (is_synchronized) { - // Acquire lock - irb_.CreateCall2(irb_.GetRuntime(LockObject), - this_object_or_class_object, - thread_object_addr); + irb_.Runtime().EmitLockObject(this_object_or_class_object); } // saved_local_ref_cookie = env->local_ref_cookie @@ -218,9 +212,7 @@ CompiledMethod* JniCompiler::Compile() { // Release lock for synchronized methods. if (is_synchronized) { - irb_.CreateCall2(irb_.GetRuntime(UnlockObject), - this_object_or_class_object, - thread_object_addr); + irb_.Runtime().EmitUnlockObject(this_object_or_class_object); } // Set thread state to kRunnable @@ -232,6 +224,9 @@ CompiledMethod* JniCompiler::Compile() { irb_.Runtime().EmitTestSuspend(); if (return_shorty == 'L') { + // Get thread object + llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread(); + // If the return value is reference, it may point to SIRT, we should decode it. retval = irb_.CreateCall2(irb_.GetRuntime(DecodeJObjectInThread), thread_object_addr, diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc index eecace0923..4021f7bc8f 100644 --- a/src/compiler_llvm/method_compiler.cc +++ b/src/compiler_llvm/method_compiler.cc @@ -1551,9 +1551,7 @@ void MethodCompiler::EmitInsn_MonitorEnter(uint32_t dex_pc, EmitGuard_NullPointerException(dex_pc, object_addr); } - llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread(); - - irb_.CreateCall2(irb_.GetRuntime(LockObject), object_addr, thread_object_addr); + irb_.Runtime().EmitLockObject(object_addr); irb_.CreateBr(GetNextBasicBlock(dex_pc)); } @@ -1573,9 +1571,7 @@ void MethodCompiler::EmitInsn_MonitorExit(uint32_t dex_pc, EmitUpdateDexPC(dex_pc); - llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread(); - - irb_.CreateCall2(irb_.GetRuntime(UnlockObject), object_addr, thread_object_addr); + irb_.Runtime().EmitUnlockObject(object_addr); EmitGuard_ExceptionLandingPad(dex_pc, true); diff --git a/src/compiler_llvm/runtime_support_builder.cc b/src/compiler_llvm/runtime_support_builder.cc index b0823d60e2..9095c02a6b 100644 --- a/src/compiler_llvm/runtime_support_builder.cc +++ b/src/compiler_llvm/runtime_support_builder.cc @@ -18,6 +18,8 @@ #include "card_table.h" #include "ir_builder.h" +#include "monitor.h" +#include "object.h" #include "shadow_frame.h" #include "thread.h" #include "utils_llvm.h" @@ -179,6 +181,55 @@ void RuntimeSupportBuilder::EmitTestSuspend() { } +/* Monitor */ + +void RuntimeSupportBuilder::EmitLockObject(llvm::Value* object) { + // TODO: Implement a fast path. + Function* slow_func = GetRuntimeSupportFunction(runtime_support::LockObject); + irb_.CreateCall2(slow_func, object, EmitGetCurrentThread()); +} + +void RuntimeSupportBuilder::EmitUnlockObject(llvm::Value* object) { + llvm::Value* lock_id = + EmitLoadFromThreadOffset(Thread::ThinLockIdOffset().Int32Value(), + irb_.getJIntTy(), + kTBAARuntimeInfo); + llvm::Value* monitor = + irb_.LoadFromObjectOffset(object, + Object::MonitorOffset().Int32Value(), + irb_.getJIntTy(), + kTBAARuntimeInfo); + + llvm::Value* my_monitor = irb_.CreateShl(lock_id, LW_LOCK_OWNER_SHIFT); + llvm::Value* hash_state = irb_.CreateAnd(monitor, (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT)); + llvm::Value* real_monitor = irb_.CreateAnd(monitor, ~(LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT)); + + // Is thin lock, held by us and not recursively acquired + llvm::Value* is_fast_path = irb_.CreateICmpEQ(real_monitor, my_monitor); + + llvm::Function* parent_func = irb_.GetInsertBlock()->getParent(); + BasicBlock* bb_fast = BasicBlock::Create(context_, "unlock_fast", parent_func); + BasicBlock* bb_slow = BasicBlock::Create(context_, "unlock_slow", parent_func); + BasicBlock* bb_cont = BasicBlock::Create(context_, "unlock_cont", parent_func); + irb_.CreateCondBr(is_fast_path, bb_fast, bb_slow, kLikely); + + irb_.SetInsertPoint(bb_fast); + // Set all bits to zero (except hash state) + irb_.StoreToObjectOffset(object, + Object::MonitorOffset().Int32Value(), + hash_state, + kTBAARuntimeInfo); + irb_.CreateBr(bb_cont); + + irb_.SetInsertPoint(bb_slow); + Function* slow_func = GetRuntimeSupportFunction(runtime_support::UnlockObject); + irb_.CreateCall2(slow_func, object, EmitGetCurrentThread()); + irb_.CreateBr(bb_cont); + + irb_.SetInsertPoint(bb_cont); +} + + void RuntimeSupportBuilder::OptimizeRuntimeSupport() { // TODO: Remove this after we remove suspend loop pass. if (!target_runtime_support_func_[runtime_support::TestSuspend]) { diff --git a/src/compiler_llvm/runtime_support_builder.h b/src/compiler_llvm/runtime_support_builder.h index 89cf30a002..7b54c69d69 100644 --- a/src/compiler_llvm/runtime_support_builder.h +++ b/src/compiler_llvm/runtime_support_builder.h @@ -60,6 +60,10 @@ class RuntimeSupportBuilder { virtual llvm::Value* EmitIsExceptionPending(); virtual void EmitTestSuspend(); + /* Monitor */ + virtual void EmitLockObject(llvm::Value* object); + virtual void EmitUnlockObject(llvm::Value* object); + llvm::Function* GetRuntimeSupportFunction(runtime_support::RuntimeId id) { if (id >= 0 && id < runtime_support::MAX_ID) { return runtime_support_func_decls_[id]; diff --git a/src/compiler_llvm/runtime_support_builder_arm.cc b/src/compiler_llvm/runtime_support_builder_arm.cc index a180520994..6ce9ea4fd1 100644 --- a/src/compiler_llvm/runtime_support_builder_arm.cc +++ b/src/compiler_llvm/runtime_support_builder_arm.cc @@ -33,6 +33,7 @@ using namespace llvm; namespace art { namespace compiler_llvm { +/* Thread */ llvm::Value* RuntimeSupportBuilderARM::EmitGetCurrentThread() { Function* ori_func = GetRuntimeSupportFunction(runtime_support::GetCurrentThread); @@ -73,5 +74,23 @@ void RuntimeSupportBuilderARM::EmitSetCurrentThread(llvm::Value* thread) { } +/* Monitor */ + +void RuntimeSupportBuilderARM::EmitLockObject(llvm::Value* object) { + RuntimeSupportBuilder::EmitLockObject(object); + FunctionType* func_ty = FunctionType::get(/*Result=*/Type::getVoidTy(context_), + /*isVarArg=*/false); + InlineAsm* func = InlineAsm::get(func_ty, "dmb sy", "", true); + irb_.CreateCall(func); +} + +void RuntimeSupportBuilderARM::EmitUnlockObject(llvm::Value* object) { + RuntimeSupportBuilder::EmitUnlockObject(object); + FunctionType* func_ty = FunctionType::get(/*Result=*/Type::getVoidTy(context_), + /*isVarArg=*/false); + InlineAsm* func = InlineAsm::get(func_ty, "dmb sy", "", true); + irb_.CreateCall(func); +} + } // namespace compiler_llvm } // namespace art diff --git a/src/compiler_llvm/runtime_support_builder_arm.h b/src/compiler_llvm/runtime_support_builder_arm.h index bf8a589315..882892573f 100644 --- a/src/compiler_llvm/runtime_support_builder_arm.h +++ b/src/compiler_llvm/runtime_support_builder_arm.h @@ -34,6 +34,10 @@ class RuntimeSupportBuilderARM : public RuntimeSupportBuilder { virtual void EmitStoreToThreadOffset(int64_t offset, llvm::Value* value, TBAASpecialType s_ty); virtual void EmitSetCurrentThread(llvm::Value* thread); + + /* Monitor */ + virtual void EmitLockObject(llvm::Value* object); + virtual void EmitUnlockObject(llvm::Value* object); }; } // namespace compiler_llvm diff --git a/src/compiler_llvm/runtime_support_builder_thumb2.cc b/src/compiler_llvm/runtime_support_builder_thumb2.cc new file mode 100644 index 0000000000..3299afe1bd --- /dev/null +++ b/src/compiler_llvm/runtime_support_builder_thumb2.cc @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "runtime_support_builder_thumb2.h" + +#include "ir_builder.h" +#include "monitor.h" +#include "object.h" +#include "thread.h" +#include "utils_llvm.h" + +#include <llvm/DerivedTypes.h> +#include <llvm/Function.h> +#include <llvm/InlineAsm.h> +#include <llvm/Module.h> +#include <llvm/Type.h> + +#include <inttypes.h> +#include <vector> + +using namespace llvm; + +namespace art { +namespace compiler_llvm { + + +void RuntimeSupportBuilderThumb2::EmitLockObject(llvm::Value* object) { + FunctionType* func_ty = FunctionType::get(/*Result=*/irb_.getInt32Ty(), + /*Params=*/irb_.getJObjectTy(), + /*isVarArg=*/false); + // $0: result + // $1: object + // $2: temp + // $3: temp + std::string asms; + StringAppendF(&asms, "add $3, $1, #%"PRId32"\n", Object::MonitorOffset().Int32Value()); + StringAppendF(&asms, "ldr $2, [r9, #%"PRId32"]\n", Thread::ThinLockIdOffset().Int32Value()); + StringAppendF(&asms, "ldrex $0, [$3]\n"); + StringAppendF(&asms, "lsl $2, $2, %d\n", LW_LOCK_OWNER_SHIFT); + StringAppendF(&asms, "bfi $2, $0, #0, #%d\n", LW_LOCK_OWNER_SHIFT - 1); + StringAppendF(&asms, "bfc $0, #%d, #%d\n", LW_HASH_STATE_SHIFT, LW_LOCK_OWNER_SHIFT - 1); + StringAppendF(&asms, "cmp $0, #0\n"); + StringAppendF(&asms, "it eq\n"); + StringAppendF(&asms, "strexeq $0, $2, [$3]\n"); + + InlineAsm* func = InlineAsm::get(func_ty, asms, "=&l,l,~l,~l", true); + + llvm::Value* retry_slow_path = irb_.CreateCall(func, object); + retry_slow_path = irb_.CreateICmpNE(retry_slow_path, irb_.getJInt(0)); + + llvm::Function* parent_func = irb_.GetInsertBlock()->getParent(); + BasicBlock* basic_block_lock = BasicBlock::Create(context_, "lock", parent_func); + BasicBlock* basic_block_cont = BasicBlock::Create(context_, "lock_cont", parent_func); + irb_.CreateCondBr(retry_slow_path, basic_block_lock, basic_block_cont, kUnlikely); + + irb_.SetInsertPoint(basic_block_lock); + Function* slow_func = GetRuntimeSupportFunction(runtime_support::LockObject); + irb_.CreateCall2(slow_func, object, EmitGetCurrentThread()); + irb_.CreateBr(basic_block_cont); + + irb_.SetInsertPoint(basic_block_cont); + { // Memory barrier + FunctionType* asm_ty = FunctionType::get(/*Result=*/Type::getVoidTy(context_), + /*isVarArg=*/false); + InlineAsm* func = InlineAsm::get(asm_ty, "dmb sy", "", true); + irb_.CreateCall(func); + } +} + + +} // namespace compiler_llvm +} // namespace art diff --git a/src/compiler_llvm/runtime_support_builder_thumb2.h b/src/compiler_llvm/runtime_support_builder_thumb2.h new file mode 100644 index 0000000000..3ac0b9f307 --- /dev/null +++ b/src/compiler_llvm/runtime_support_builder_thumb2.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_COMPILER_LLVM_RUNTIME_SUPPORT_BUILDER_THUMB2_H_ +#define ART_SRC_COMPILER_LLVM_RUNTIME_SUPPORT_BUILDER_THUMB2_H_ + +#include "runtime_support_builder_arm.h" + +namespace art { +namespace compiler_llvm { + +class RuntimeSupportBuilderThumb2 : public RuntimeSupportBuilderARM { + public: + RuntimeSupportBuilderThumb2(llvm::LLVMContext& context, llvm::Module& module, IRBuilder& irb) + : RuntimeSupportBuilderARM(context, module, irb) {} + + /* Monitor */ + virtual void EmitLockObject(llvm::Value* object); +}; + +} // namespace compiler_llvm +} // namespace art + +#endif // ART_SRC_COMPILER_LLVM_RUNTIME_SUPPORT_BUILDER_THUMB2_H_ diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc index bf74e062be..99f9fee16e 100644 --- a/src/compiler_llvm/runtime_support_llvm.cc +++ b/src/compiler_llvm/runtime_support_llvm.cc @@ -62,7 +62,7 @@ Thread* art_get_current_thread_from_code() { } void art_set_current_thread_from_code(void* thread_object_addr) { - LOG(FATAL) << "Implemented by IRBuilder."; + // Nothing to be done. } void art_lock_object_from_code(Object* obj, Thread* thread) { diff --git a/src/compiler_llvm/runtime_support_llvm.h b/src/compiler_llvm/runtime_support_llvm.h index 8f7307912d..6757ff51a9 100644 --- a/src/compiler_llvm/runtime_support_llvm.h +++ b/src/compiler_llvm/runtime_support_llvm.h @@ -21,9 +21,6 @@ namespace art { -class Method; -class Object; - //---------------------------------------------------------------------------- // Thread //---------------------------------------------------------------------------- |