Implement thin-lock fast path for compiler-llvm.
Change-Id: I09d6a0dba4df7cbeb0c0e3f432ab3b09fce0846d
diff --git a/src/compiler_llvm/runtime_support_builder.cc b/src/compiler_llvm/runtime_support_builder.cc
index b0823d6..9095c02 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 @@
}
+/* 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]) {