Shark monitor improvements
Gary Benson
gbenson at redhat.com
Wed May 27 07:03:54 PDT 2009
Hi all,
Monitors are used in Java bytecode for synchronization. Previously,
Shark handled monitors in a similar manner to the C++ interpreter,
and a lot of the work of monitor allocation was performed at runtime.
With this commit, a lot of that work is handled at compile time.
Cheers,
Gary
--
http://gbenson.net/
-------------- next part --------------
diff -r b22d229ddbcf ChangeLog
--- a/ChangeLog Wed May 27 13:49:38 2009 +0100
+++ b/ChangeLog Wed May 27 14:59:07 2009 +0100
@@ -1,3 +1,101 @@
+2009-05-27 Gary Benson <gbenson at redhat.com>
+
+ * ports/hotspot/src/share/vm/shark/sharkFunction.hpp
+ (SharkFunction::_monitor_count): Removed.
+ (SharkFunction::_max_monitors): New field.
+ (SharkFunction::monitor_count): Removed.
+ (SharkFunction::max_monitors): New method.
+ (SharkFunction::_exception_slot_offset): Removed.
+ (SharkFunction::exception_slot): Likewise.
+ (SharkFunction::_oop_tmp_slot_offset): New field.
+ (SharkFunction::oop_tmp_slot_offset): New method.
+ (SharkFunction::monitors_slots): Removed.
+ (SharkFunction::monitors_slots_offset): Likewise.
+ (SharkFunction::monitor_offset): New method.
+ (SharkFunction::monitor_object_offset): Likewise.
+ (SharkFunction::monitor_header_offset): Likewise.
+ (SharkFunction::monitor_addr): Likewise.
+ (SharkFunction::monitor_object_addr): Likewise.
+ (SharkFunction::monitor_header_addr): Likewise.
+ * ports/hotspot/src/share/vm/shark/sharkFunction.cpp
+ (SharkFunction::initialize): Renamed _monitor_count as _max_monitors.
+ (SharkFunction::CreateBuildFrame): Renamed _monitor_count as
+ _max_monitors, remove monitor initialization, remove exception
+ pointer and add temporary oop slot.
+ (SharkFunction::monitor): Removed.
+
+ * ports/hotspot/src/share/vm/shark/sharkState.hpp
+ (SharkState::_num_monitors): New field.
+ (SharkState::max_monitors): New method.
+ (SharkState::num_monitors): Likewise.
+ (SharkState::set_num_monitors): Likewise.
+ (SharkState::_oop_tmp): New field.
+ (SharkState::oop_tmp_addr): New method.
+ (SharkState::oop_tmp): Likewise.
+ (SharkState::set_oop_tmp): Likewise.
+ * ports/hotspot/src/share/vm/shark/sharkState.inline.hpp
+ (SharkState::max_monitors): New method.
+ * ports/hotspot/src/share/vm/shark/sharkState.cpp
+ (SharkState::SharkState): Initialize oop_tmp.
+ (SharkState::initialize): Initialize num_monitors.
+ (SharkPHIState::SharkPHIState): Likewise.
+ (SharkState::equal_to): Also check oop_tmp and num_monitors.
+ (SharkPHIState::add_incoming): Likewise.
+ (SharkState::merge): Also merge oop_tmp and check num_monitors.
+
+ * ports/hotspot/src/share/vm/shark/sharkStateScanner.hpp
+ (SharkStateScanner::process_monitor): New argument.
+ (SharkStateScanner::process_oop_tmp_slot): New method.
+ (SharkStateScanner::process_exception_slot): Removed.
+ * ports/hotspot/src/share/vm/shark/sharkStateScanner.cpp
+ (SharkStateScanner::scan): Replace monitor scanning, remove
+ exception slot, and add temporary oop slot.
+
+ * ports/hotspot/src/share/vm/shark/sharkCacheDecache.hpp
+ (SharkDecacher::process_monitor): New argument.
+ (SharkDecacher::process_oop_tmp_slot): New method.
+ (SharkCacher::process_oop_tmp_slot): Likewise.
+ (SharkDecacher::process_exception_slot): Removed.
+ * ports/hotspot/src/share/vm/shark/sharkCacheDecache.cpp
+ (SharkDecacher::process_monitor): New argument.
+ (SharkDecacher::process_oop_tmp_slot): New method.
+ (SharkCacher::process_oop_tmp_slot): Likewise.
+ (SharkDecacher::process_exception_slot): Removed.
+
+ * ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp
+ (SharkTopLevelBlock::set_oop_tmp): New method.
+ (SharkTopLevelBlock::get_oop_tmp): Likewise.
+ (SharkTopLevelBlock::num_monitors): Likewise.
+ (SharkTopLevelBlock::set_num_monitors): Likewise.
+ (SharkTopLevelBlock::release_method_lock): Removed.
+ (SharkTopLevelBlock::release_locked_monitors): Likewise.
+ (SharkTopLevelBlock::acquire_lock): New method.
+ (SharkTopLevelBlock::release_lock): Likewise.
+ * ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp
+ (SharkTopLevelBlock::acquire_method_lock): Rewritten.
+ (SharkTopLevelBlock::release_method_lock): Removed.
+ (SharkTopLevelBlock::release_locked_monitors): Likewise.
+ (SharkTopLevelBlock::handle_return): New monitor release code.
+ (SharkTopLevelBlock::do_monitorenter): Rewritten.
+ (SharkTopLevelBlock::do_monitorexit): Likewise.
+ (SharkTopLevelBlock::acquire_lock): New method.
+ (SharkTopLevelBlock::release_lock): Likewise.
+
+ * ports/hotspot/src/cpu/zero/vm/sharkFrame_zero.hpp
+ (SharkFrame::Layout): Replaced exception slot with oop_tmp slot.
+ * ports/hotspot/src/cpu/zero/vm/stackPrinter_zero.hpp
+ (ZeroStackPrinter::print_word): Likewise.
+
+ * ports/hotspot/src/share/vm/shark/sharkMonitor.hpp: Removed.
+ * ports/hotspot/src/share/vm/shark/sharkMonitor.cpp: Likewise.
+
+ * ports/hotspot/src/share/vm/includeDB_shark: Updated.
+
+ * patches/hotspot/default/icedtea-shark.patch
+ (vframeArrayElement::fill_in): Remove workaround for
+ unused but recorded monitors.
+ (vframeArrayElement::unpack_on_stack): Likewise.
+
2009-05-27 Gary Benson <gbenson at redhat.com>
* ports/hotspot/src/share/vm/shark/sharkCacheDecache.hpp
diff -r b22d229ddbcf patches/hotspot/default/icedtea-shark.patch
--- a/patches/hotspot/default/icedtea-shark.patch Wed May 27 13:49:38 2009 +0100
+++ b/patches/hotspot/default/icedtea-shark.patch Wed May 27 14:59:07 2009 +0100
@@ -56,32 +56,6 @@
{0, NULL, NULL}
};
---- openjdk/hotspot/src/share/vm/runtime/vframeArray.cpp.orig 2008-11-22 00:11:18.000000000 +0000
-+++ openjdk/hotspot/src/share/vm/runtime/vframeArray.cpp 2008-12-03 14:33:49.000000000 +0000
-@@ -64,6 +64,11 @@
- assert(monitor->owner() == NULL || (!monitor->owner()->is_unlocked() && !monitor->owner()->has_bias_pattern()), "object must be null or locked, and unbiased");
- BasicObjectLock* dest = _monitors->at(index);
- dest->set_obj(monitor->owner());
-+#ifdef SHARK
-+ // XXX This can be removed when Shark knows
-+ // which monitors are in use.
-+ if (monitor->owner())
-+#endif // SHARK
- monitor->lock()->move_to(monitor->owner(), dest->lock());
- }
- }
-@@ -262,6 +267,11 @@
- top = iframe()->previous_monitor_in_interpreter_frame(top);
- BasicObjectLock* src = _monitors->at(index);
- top->set_obj(src->obj());
-+#ifdef SHARK
-+ // XXX This can be removed when Shark knows
-+ // which monitors are in use.
-+ if (src->obj())
-+#endif // SHARK
- src->lock()->move_to(src->obj(), top->lock());
- }
- if (ProfileInterpreter) {
--- openjdk/hotspot/src/share/vm/runtime/vm_version.cpp.orig 2008-12-03 14:23:37.000000000 +0000
+++ openjdk/hotspot/src/share/vm/runtime/vm_version.cpp 2008-12-03 14:33:48.000000000 +0000
@@ -94,6 +94,9 @@
diff -r b22d229ddbcf ports/hotspot/src/cpu/zero/vm/sharkFrame_zero.hpp
--- a/ports/hotspot/src/cpu/zero/vm/sharkFrame_zero.hpp Wed May 27 13:49:38 2009 +0100
+++ b/ports/hotspot/src/cpu/zero/vm/sharkFrame_zero.hpp Wed May 27 14:59:07 2009 +0100
@@ -31,7 +31,7 @@
// | monitor m-1 |
// | ... |
// | monitor 0 |
-// | exception |
+// | oop_tmp |
// | method |
// | unextended_sp |
// | pc |
@@ -55,7 +55,7 @@
pc_off = jf_header_words,
unextended_sp_off,
method_off,
- exception_off,
+ oop_tmp_off,
header_words
};
diff -r b22d229ddbcf ports/hotspot/src/cpu/zero/vm/stackPrinter_zero.hpp
--- a/ports/hotspot/src/cpu/zero/vm/stackPrinter_zero.hpp Wed May 27 13:49:38 2009 +0100
+++ b/ports/hotspot/src/cpu/zero/vm/stackPrinter_zero.hpp Wed May 27 14:59:07 2009 +0100
@@ -222,8 +222,8 @@
if (method->is_oop())
value = method->name_and_sig_as_C_string(_buf, _buflen);
}
- else if (word == SharkFrame::exception_off) {
- field = "exception";
+ else if (word == SharkFrame::oop_tmp_off) {
+ field = "oop_tmp";
}
else {
SharkFrame *sf = (SharkFrame *) frame;
diff -r b22d229ddbcf ports/hotspot/src/share/vm/includeDB_shark
--- a/ports/hotspot/src/share/vm/includeDB_shark Wed May 27 13:49:38 2009 +0100
+++ b/ports/hotspot/src/share/vm/includeDB_shark Wed May 27 14:59:07 2009 +0100
@@ -193,7 +193,6 @@
sharkFunction.cpp sharkBuilder.hpp
sharkFunction.cpp sharkEntry.hpp
sharkFunction.cpp sharkFunction.hpp
-sharkFunction.cpp sharkMonitor.hpp
sharkFunction.cpp sharkState.inline.hpp
sharkFunction.cpp sharkTopLevelBlock.hpp
@@ -241,19 +240,6 @@
sharkMemoryManager.cpp sharkEntry.hpp
sharkMemoryManager.cpp sharkMemoryManager.hpp
-sharkMonitor.cpp llvmHeaders.hpp
-sharkMonitor.cpp llvmValue.hpp
-sharkMonitor.cpp sharkMonitor.hpp
-sharkMonitor.cpp sharkRuntime.hpp
-sharkMonitor.cpp sharkState.inline.hpp
-sharkMonitor.cpp sharkTopLevelBlock.hpp
-
-sharkMonitor.hpp allocation.hpp
-sharkMonitor.hpp llvmHeaders.hpp
-sharkMonitor.hpp llvmValue.hpp
-sharkMonitor.hpp sharkBuilder.hpp
-sharkMonitor.hpp sharkFunction.hpp
-
sharkRuntime.cpp biasedLocking.hpp
sharkRuntime.cpp deoptimization.hpp
sharkRuntime.cpp llvmHeaders.hpp
@@ -326,7 +312,6 @@
sharkTopLevelBlock.hpp sharkBlock.hpp
sharkTopLevelBlock.hpp sharkBuilder.hpp
sharkTopLevelBlock.hpp sharkFunction.hpp
-sharkTopLevelBlock.hpp sharkMonitor.hpp
sharkTopLevelBlock.hpp sharkState.inline.hpp
sharkTopLevelBlock.hpp sharkValue.hpp
diff -r b22d229ddbcf ports/hotspot/src/share/vm/shark/sharkCacheDecache.cpp
--- a/ports/hotspot/src/share/vm/shark/sharkCacheDecache.cpp Wed May 27 13:49:38 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/sharkCacheDecache.cpp Wed May 27 14:59:07 2009 +0100
@@ -82,11 +82,8 @@
_monarray = new GrowableArray<MonitorValue*>(num_monitors);
}
-void SharkDecacher::process_monitor(int index, int box_offset)
+void SharkDecacher::process_monitor(int index, int box_offset, int obj_offset)
{
- int obj_offset =
- box_offset + (BasicObjectLock::obj_offset_in_bytes() >> LogBytesPerWord);
-
oopmap()->set_oop(slot2reg(obj_offset));
monarray()->append(new MonitorValue(
@@ -94,13 +91,20 @@
slot2loc(box_offset, Location::normal)));
}
-void SharkDecacher::process_exception_slot(int offset)
+void SharkDecacher::process_oop_tmp_slot(Value** value, int offset)
{
- // Record the exception slot
- oopmap()->set_oop(slot2reg(offset));
+ // Decache the temporary oop slot
+ if (*value) {
+ write_value_to_frame(
+ SharkType::oop_type(),
+ *value,
+ offset);
+
+ oopmap()->set_oop(slot2reg(offset));
+ }
}
-void SharkDecacher::process_method_slot(llvm::Value** value, int offset)
+void SharkDecacher::process_method_slot(Value** value, int offset)
{
// Decache the method pointer
write_value_to_frame(
@@ -182,14 +186,20 @@
}
}
-void SharkCacher::process_method_slot(llvm::Value** value, int offset)
+void SharkCacher::process_oop_tmp_slot(Value** value, int offset)
+{
+ // Cache the temporary oop
+ if (*value)
+ *value = read_value_from_frame(SharkType::oop_type(), offset);
+}
+
+void SharkCacher::process_method_slot(Value** value, int offset)
{
// Cache the method pointer
*value = read_value_from_frame(SharkType::methodOop_type(), offset);
}
-void SharkFunctionEntryCacher::process_method_slot(llvm::Value** value,
- int offset)
+void SharkFunctionEntryCacher::process_method_slot(Value** value, int offset)
{
// "Cache" the method pointer
*value = method();
@@ -212,9 +222,9 @@
}
}
-void SharkDecacher::write_value_to_frame(const llvm::Type* type,
- llvm::Value* value,
- int offset)
+void SharkDecacher::write_value_to_frame(const Type* type,
+ Value* value,
+ int offset)
{
if (frame_cache()->value(offset) != value) {
builder()->CreateStore(
@@ -223,7 +233,7 @@
}
}
-Value* SharkCacher::read_value_from_frame(const llvm::Type* type, int offset)
+Value* SharkCacher::read_value_from_frame(const Type* type, int offset)
{
Value *result = builder()->CreateLoad(
function()->CreateAddressOfFrameEntry(offset, type));
diff -r b22d229ddbcf ports/hotspot/src/share/vm/shark/sharkCacheDecache.hpp
--- a/ports/hotspot/src/share/vm/shark/sharkCacheDecache.hpp Wed May 27 13:49:38 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/sharkCacheDecache.hpp Wed May 27 14:59:07 2009 +0100
@@ -122,9 +122,9 @@
void process_stack_slot(int index, SharkValue** value, int offset);
void start_monitors(int num_monitors);
- void process_monitor(int index, int offset);
+ void process_monitor(int index, int box_offset, int obj_offset);
- void process_exception_slot(int offset);
+ void process_oop_tmp_slot(llvm::Value** value, int offset);
void process_method_slot(llvm::Value** value, int offset);
void process_pc_slot(int offset);
@@ -354,6 +354,7 @@
protected:
void process_stack_slot(int index, SharkValue** value, int offset);
+ void process_oop_tmp_slot(llvm::Value** value, int offset);
virtual void process_method_slot(llvm::Value** value, int offset);
void process_local_slot(int index, SharkValue** value, int offset);
diff -r b22d229ddbcf ports/hotspot/src/share/vm/shark/sharkFunction.cpp
--- a/ports/hotspot/src/share/vm/shark/sharkFunction.cpp Wed May 27 13:49:38 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/sharkFunction.cpp Wed May 27 14:59:07 2009 +0100
@@ -53,15 +53,16 @@
// Create the list of blocks
set_block_insertion_point(NULL);
_blocks = NEW_RESOURCE_ARRAY(SharkTopLevelBlock*, flow()->block_count());
- for (int i = 0; i < block_count(); i++)
- {
- ciTypeFlow::Block *b = flow()->pre_order_at(i);
- // Work around a bug in pre_order_at() that does not return the
- // correct pre-ordering. If pre_order_at() were correct this
- // line could simply be:
- // _blocks[i] = new SharkTopLevelBlock(this, b);
- _blocks[b->pre_order()] = new SharkTopLevelBlock(this, b);
- }
+ for (int i = 0; i < block_count(); i++) {
+ ciTypeFlow::Block *b = flow()->pre_order_at(i);
+
+ // Work around a bug in pre_order_at() that does not return
+ // the correct pre-ordering. If pre_order_at() were correct
+ // this line could simply be:
+ // _blocks[i] = new SharkTopLevelBlock(this, b);
+ _blocks[b->pre_order()] = new SharkTopLevelBlock(this, b);
+ }
+
// Walk the tree from the start block to determine which
// blocks are entered and which blocks require phis
SharkTopLevelBlock *start_block = block(0);
@@ -75,11 +76,11 @@
}
// Initialize the monitors
- _monitor_count = 0;
+ _max_monitors = 0;
if (target()->is_synchronized() || target()->uses_monitors()) {
for (int i = 0; i < block_count(); i++)
- _monitor_count = MAX2(
- _monitor_count, block(i)->ciblock()->monitor_count());
+ _max_monitors = MAX2(
+ _max_monitors, block(i)->ciblock()->monitor_count());
}
// Create the method preamble
@@ -216,7 +217,7 @@
int locals_words = max_locals();
int extra_locals = locals_words - arg_size();
int header_words = SharkFrame::header_words;
- int monitor_words = monitor_count()*frame::interpreter_frame_monitor_size();
+ int monitor_words = max_monitors()*frame::interpreter_frame_monitor_size();
int stack_words = max_stack();
int frame_words = header_words + monitor_words + stack_words;
@@ -242,19 +243,11 @@
offset += stack_words;
// Monitors
- if (monitor_count()) {
- _monitors_slots_offset = offset;
-
- for (int i = 0; i < monitor_count(); i++) {
- if (i != 0 || !target()->is_synchronized())
- monitor(i)->mark_free();
- }
- }
+ _monitors_slots_offset = offset;
offset += monitor_words;
- // Exception pointer
- _exception_slot_offset = offset++;
- builder()->CreateStore(LLVMValue::null(), exception_slot());
+ // Temporary oop slot
+ _oop_tmp_slot_offset = offset++;
// Method pointer
_method_slot_offset = offset++;
@@ -297,18 +290,6 @@
return result;
}
-SharkMonitor* SharkFunction::monitor(Value *index) const
-{
- Value *indexes[] = {
- LLVMValue::jint_constant(0),
- builder()->CreateSub(
- LLVMValue::jint_constant(monitor_count() - 1), index),
- };
- return new SharkMonitor(
- this,
- builder()->CreateGEP(monitors_slots(), indexes, indexes + 2));
-}
-
class DeferredZeroCheck : public ResourceObj {
public:
DeferredZeroCheck(SharkTopLevelBlock* block, SharkValue* value)
diff -r b22d229ddbcf ports/hotspot/src/share/vm/shark/sharkFunction.hpp
--- a/ports/hotspot/src/share/vm/shark/sharkFunction.hpp Wed May 27 13:49:38 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/sharkFunction.hpp Wed May 27 14:59:07 2009 +0100
@@ -23,7 +23,6 @@
*
*/
-class SharkMonitor;
class SharkTopLevelBlock;
class DeferredZeroCheck;
@@ -55,7 +54,7 @@
SharkTopLevelBlock** _blocks;
llvm::Value* _base_pc;
llvm::Value* _thread;
- int _monitor_count;
+ int _max_monitors;
GrowableArray<DeferredZeroCheck*> _deferred_zero_checks;
public:
@@ -95,9 +94,9 @@
{
return _thread;
}
- int monitor_count() const
+ int max_monitors() const
{
- return _monitor_count;
+ return _max_monitors;
}
GrowableArray<DeferredZeroCheck*>* deferred_zero_checks()
{
@@ -215,29 +214,6 @@
llvm::Value* CreateAddressOfFrameEntry(int offset,
const llvm::Type* type = NULL,
const char* name = "") const;
- public:
- llvm::Value* exception_slot() const
- {
- return CreateAddressOfFrameEntry(
- exception_slot_offset(),
- SharkType::oop_type(),
- "exception_slot");
- }
- llvm::Value* monitors_slots() const
- {
- return CreateAddressOfFrameEntry(
- monitors_slots_offset(),
- llvm::ArrayType::get(SharkType::monitor_type(), monitor_count()),
- "monitors");
- }
-
- public:
- SharkMonitor* monitor(int index) const
- {
- return monitor(LLVMValue::jint_constant(index));
- }
- SharkMonitor* monitor(llvm::Value* index) const;
-
private:
llvm::Value* CreateBuildFrame();
@@ -256,7 +232,7 @@
int _extended_frame_size;
int _stack_slots_offset;
int _monitors_slots_offset;
- int _exception_slot_offset;
+ int _oop_tmp_slot_offset;
int _method_slot_offset;
int _pc_slot_offset;
int _locals_slots_offset;
@@ -274,13 +250,9 @@
{
return _stack_slots_offset;
}
- int monitors_slots_offset() const
+ int oop_tmp_slot_offset() const
{
- return _monitors_slots_offset;
- }
- int exception_slot_offset() const
- {
- return _exception_slot_offset;
+ return _oop_tmp_slot_offset;
}
int method_slot_offset() const
{
@@ -295,6 +267,49 @@
return _locals_slots_offset;
}
+ // Monitors
+ public:
+ int monitor_offset(int index) const
+ {
+ assert(index >= 0 && index < max_monitors(), "invalid monitor index");
+ return _monitors_slots_offset +
+ (max_monitors() - 1 - index) * frame::interpreter_frame_monitor_size();
+ }
+ int monitor_object_offset(int index) const
+ {
+ return monitor_offset(index) +
+ (BasicObjectLock::obj_offset_in_bytes() >> LogBytesPerWord);
+ }
+ int monitor_header_offset(int index) const
+ {
+ return monitor_offset(index) +
+ ((BasicObjectLock::lock_offset_in_bytes() +
+ BasicLock::displaced_header_offset_in_bytes()) >> LogBytesPerWord);
+ }
+
+ public:
+ llvm::Value* monitor_addr(int index) const
+ {
+ return CreateAddressOfFrameEntry(
+ monitor_offset(index),
+ SharkType::monitor_type(),
+ "monitor");
+ }
+ llvm::Value* monitor_object_addr(int index) const
+ {
+ return CreateAddressOfFrameEntry(
+ monitor_object_offset(index),
+ SharkType::oop_type(),
+ "object_addr");
+ }
+ llvm::Value* monitor_header_addr(int index) const
+ {
+ return CreateAddressOfFrameEntry(
+ monitor_header_offset(index),
+ SharkType::intptr_type(),
+ "displaced_header_addr");
+ }
+
// VM interface
private:
llvm::StoreInst* CreateStoreLastJavaSP(llvm::Value* value) const
diff -r b22d229ddbcf ports/hotspot/src/share/vm/shark/sharkMonitor.cpp
--- a/ports/hotspot/src/share/vm/shark/sharkMonitor.cpp Wed May 27 13:49:38 2009 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,170 +0,0 @@
-/*
- * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright 2008 Red Hat, Inc.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- */
-
-#include "incls/_precompiled.incl"
-#include "incls/_sharkMonitor.cpp.incl"
-
-using namespace llvm;
-
-void SharkMonitor::initialize()
-{
- _object_addr = builder()->CreateAddressOfStructEntry(
- monitor(), in_ByteSize(BasicObjectLock::obj_offset_in_bytes()),
- PointerType::getUnqual(SharkType::oop_type()),
- "object_addr");
-
- _displaced_header_addr = builder()->CreateAddressOfStructEntry(
- monitor(), in_ByteSize(
- BasicObjectLock::lock_offset_in_bytes() +
- BasicLock::displaced_header_offset_in_bytes()),
- PointerType::getUnqual(SharkType::intptr_type()),
- "displaced_header_addr");
-}
-
-void SharkMonitor::acquire(SharkTopLevelBlock* block, Value *lockee) const
-{
- BasicBlock *try_recursive = function()->CreateBlock("try_recursive");
- BasicBlock *got_recursive = function()->CreateBlock("got_recursive");
- BasicBlock *not_recursive = function()->CreateBlock("not_recursive");
- BasicBlock *acquired_fast = function()->CreateBlock("acquired_fast");
- BasicBlock *lock_acquired = function()->CreateBlock("lock_acquired");
-
- set_object(lockee);
-
- Value *lock = builder()->CreatePtrToInt(
- displaced_header_addr(), SharkType::intptr_type());
-
- Value *mark_addr = builder()->CreateAddressOfStructEntry(
- lockee, in_ByteSize(oopDesc::mark_offset_in_bytes()),
- PointerType::getUnqual(SharkType::intptr_type()),
- "mark_addr");
-
- Value *mark = builder()->CreateLoad(mark_addr, "mark");
- Value *disp = builder()->CreateOr(
- mark, LLVMValue::intptr_constant(markOopDesc::unlocked_value), "disp");
- set_displaced_header(disp);
-
- // Try a simple lock
- Value *check = builder()->CreateCmpxchgPtr(lock, mark_addr, disp);
- builder()->CreateCondBr(
- builder()->CreateICmpEQ(disp, check),
- acquired_fast, try_recursive);
-
- // Locking failed, but maybe this thread already owns it
- builder()->SetInsertPoint(try_recursive);
- Value *addr = builder()->CreateAnd(
- disp,
- LLVMValue::intptr_constant(~markOopDesc::lock_mask_in_place));
-
- // NB we use the entire stack, but JavaThread::is_lock_owned()
- // uses a more limited range. I don't think it hurts though...
- Value *stack_limit = builder()->CreateValueOfStructEntry(
- function()->thread(), Thread::stack_base_offset(),
- SharkType::intptr_type(),
- "stack_limit");
-
- assert(sizeof(size_t) == sizeof(intptr_t), "should be");
- Value *stack_size = builder()->CreateValueOfStructEntry(
- function()->thread(), Thread::stack_size_offset(),
- SharkType::intptr_type(),
- "stack_size");
-
- Value *stack_start =
- builder()->CreateSub(stack_limit, stack_size, "stack_start");
-
- builder()->CreateCondBr(
- builder()->CreateAnd(
- builder()->CreateICmpUGE(addr, stack_start),
- builder()->CreateICmpULT(addr, stack_limit)),
- got_recursive, not_recursive);
-
- builder()->SetInsertPoint(got_recursive);
- set_displaced_header(LLVMValue::intptr_constant(0));
- builder()->CreateBr(acquired_fast);
-
- // Create an edge for the state merge
- builder()->SetInsertPoint(acquired_fast);
- SharkState *fast_state = block->current_state()->copy();
- builder()->CreateBr(lock_acquired);
-
- // It's not a recursive case so we need to drop into the runtime
- builder()->SetInsertPoint(not_recursive);
- block->call_vm_nocheck(SharkRuntime::monitorenter(), monitor());
- BasicBlock *acquired_slow = builder()->GetInsertBlock();
- builder()->CreateBr(lock_acquired);
-
- // All done
- builder()->SetInsertPoint(lock_acquired);
- block->current_state()->merge(fast_state, acquired_fast, acquired_slow);
-}
-
-void SharkMonitor::release(SharkTopLevelBlock* block) const
-{
- BasicBlock *not_recursive = function()->CreateBlock("not_recursive");
- BasicBlock *released_fast = function()->CreateBlock("released_fast");
- BasicBlock *slow_path = function()->CreateBlock("slow_path");
- BasicBlock *lock_released = function()->CreateBlock("lock_released");
-
- Value *disp = displaced_header();
- Value *lockee = object();
- set_object(LLVMValue::null());
-
- // If it is recursive then we're already done
- builder()->CreateCondBr(
- builder()->CreateICmpEQ(disp, LLVMValue::intptr_constant(0)),
- released_fast, not_recursive);
-
- // Try a simple unlock
- builder()->SetInsertPoint(not_recursive);
-
- Value *lock = builder()->CreatePtrToInt(
- displaced_header_addr(), SharkType::intptr_type());
-
- Value *mark_addr = builder()->CreateAddressOfStructEntry(
- lockee, in_ByteSize(oopDesc::mark_offset_in_bytes()),
- PointerType::getUnqual(SharkType::intptr_type()),
- "mark_addr");
-
- Value *check = builder()->CreateCmpxchgPtr(disp, mark_addr, lock);
- builder()->CreateCondBr(
- builder()->CreateICmpEQ(lock, check),
- released_fast, slow_path);
-
- // Create an edge for the state merge
- builder()->SetInsertPoint(released_fast);
- SharkState *fast_state = block->current_state()->copy();
- builder()->CreateBr(lock_released);
-
- // Need to drop into the runtime to release this one
- builder()->SetInsertPoint(slow_path);
- set_object(lockee);
- block->call_vm_nocheck(SharkRuntime::monitorexit(), monitor());
- BasicBlock *released_slow = builder()->GetInsertBlock();
- builder()->CreateBr(lock_released);
-
- // All done
- builder()->SetInsertPoint(lock_released);
- block->current_state()->merge(fast_state, released_fast, released_slow);
-}
diff -r b22d229ddbcf ports/hotspot/src/share/vm/shark/sharkMonitor.hpp
--- a/ports/hotspot/src/share/vm/shark/sharkMonitor.hpp Wed May 27 13:49:38 2009 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/*
- * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright 2008 Red Hat, Inc.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- */
-
-class SharkTopLevelBlock;
-
-class SharkMonitor : public ResourceObj {
- public:
- SharkMonitor(const SharkFunction* function, llvm::Value* monitor)
- : _function(function), _monitor(monitor)
- { initialize(); }
-
- private:
- void initialize();
-
- private:
- const SharkFunction* _function;
- llvm::Value* _monitor;
- llvm::Value* _object_addr;
- llvm::Value* _displaced_header_addr;
-
- private:
- const SharkFunction* function() const
- {
- return _function;
- }
- llvm::Value* monitor() const
- {
- return _monitor;
- }
- llvm::Value* object_addr() const
- {
- return _object_addr;
- }
- llvm::Value* displaced_header_addr() const
- {
- return _displaced_header_addr;
- }
-
- public:
- SharkBuilder* builder() const
- {
- return function()->builder();
- }
-
- public:
- llvm::Value* object() const
- {
- return builder()->CreateLoad(object_addr());
- }
- void set_object(llvm::Value* object) const
- {
- builder()->CreateStore(object, object_addr());
- }
- llvm::Value* displaced_header() const
- {
- return builder()->CreateLoad(displaced_header_addr());
- }
- void set_displaced_header(llvm::Value* displaced_header) const
- {
- builder()->CreateStore(displaced_header, displaced_header_addr());
- }
-
- public:
- void mark_free() const
- {
- set_object(LLVMValue::null());
- }
-
- public:
- void acquire(SharkTopLevelBlock* block, llvm::Value* lockee) const;
- void release(SharkTopLevelBlock* block) const;
-};
diff -r b22d229ddbcf ports/hotspot/src/share/vm/shark/sharkState.cpp
--- a/ports/hotspot/src/share/vm/shark/sharkState.cpp Wed May 27 13:49:38 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/sharkState.cpp Wed May 27 14:59:07 2009 +0100
@@ -32,6 +32,7 @@
: _block(block),
_function(function),
_method(NULL),
+ _oop_tmp(NULL),
_frame_cache(NULL)
{
initialize(NULL);
@@ -41,6 +42,7 @@
: _block(block),
_function(state->function()),
_method(state->method()),
+ _oop_tmp(state->oop_tmp()),
_frame_cache(NULL)
{
initialize(state);
@@ -76,6 +78,8 @@
else if (function()) {
_frame_cache = new SharkFrameCache(function());
}
+
+ set_num_monitors(state ? state->num_monitors() : 0);
}
bool SharkState::equal_to(SharkState *other)
@@ -89,12 +93,18 @@
if (method() != other->method())
return false;
+ if (oop_tmp() != other->oop_tmp())
+ return false;
+
if (max_locals() != other->max_locals())
return false;
if (stack_depth() != other->stack_depth())
return false;
+ if (num_monitors() != other->num_monitors())
+ return false;
+
// Local variables
for (int i = 0; i < max_locals(); i++) {
SharkValue *value = local(i);
@@ -161,6 +171,20 @@
set_method(phi);
}
+ // Temporary oop slot
+ Value *this_oop_tmp = this->oop_tmp();
+ Value *other_oop_tmp = other->oop_tmp();
+ if (this_oop_tmp != other_oop_tmp) {
+ assert(this_oop_tmp && other_oop_tmp, "can't merge NULL with non-NULL");
+ PHINode *phi = builder()->CreatePHI(SharkType::oop_type(), "oop_tmp");
+ phi->addIncoming(this_oop_tmp, this_block);
+ phi->addIncoming(other_oop_tmp, other_block);
+ set_oop_tmp(phi);
+ }
+
+ // Monitors
+ assert(this->num_monitors() == other->num_monitors(), "should be");
+
// Local variables
assert(this->max_locals() == other->max_locals(), "should be");
for (int i = 0; i < max_locals(); i++) {
@@ -365,6 +389,9 @@
push(value);
}
+ // Monitors
+ set_num_monitors(block->ciblock()->monitor_count());
+
builder()->SetInsertPoint(saved_insert_point);
}
@@ -389,4 +416,10 @@
if (stack(i))
stack(i)->addIncoming(incoming_state->stack(i), predecessor);
}
+
+ // Monitors
+ assert(num_monitors() == incoming_state->num_monitors(), "should be");
+
+ // Temporary oop slot
+ assert(oop_tmp() == incoming_state->oop_tmp(), "should be");
}
diff -r b22d229ddbcf ports/hotspot/src/share/vm/shark/sharkState.hpp
--- a/ports/hotspot/src/share/vm/shark/sharkState.hpp Wed May 27 13:49:38 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/sharkState.hpp Wed May 27 14:59:07 2009 +0100
@@ -43,6 +43,8 @@
SharkValue** _locals;
SharkValue** _stack;
SharkValue** _sp;
+ int _num_monitors;
+ llvm::Value* _oop_tmp;
public:
SharkBlock *block() const
@@ -62,6 +64,7 @@
inline SharkBuilder* builder() const;
inline int max_locals() const;
inline int max_stack() const;
+ inline int max_monitors() const;
// Method
public:
@@ -132,6 +135,32 @@
_sp -= slots;
}
+ // Monitors
+ public:
+ int num_monitors() const
+ {
+ return _num_monitors;
+ }
+ void set_num_monitors(int num_monitors)
+ {
+ _num_monitors = num_monitors;
+ }
+
+ // Temporary oop slot
+ public:
+ llvm::Value** oop_tmp_addr()
+ {
+ return &_oop_tmp;
+ }
+ llvm::Value* oop_tmp() const
+ {
+ return _oop_tmp;
+ }
+ void set_oop_tmp(llvm::Value* oop_tmp)
+ {
+ _oop_tmp = oop_tmp;
+ }
+
// Comparison
public:
bool equal_to(SharkState* other);
diff -r b22d229ddbcf ports/hotspot/src/share/vm/shark/sharkState.inline.hpp
--- a/ports/hotspot/src/share/vm/shark/sharkState.inline.hpp Wed May 27 13:49:38 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/sharkState.inline.hpp Wed May 27 14:59:07 2009 +0100
@@ -37,3 +37,8 @@
{
return block()->max_stack();
}
+
+inline int SharkState::max_monitors() const
+{
+ return function()->max_monitors();
+}
diff -r b22d229ddbcf ports/hotspot/src/share/vm/shark/sharkStateScanner.cpp
--- a/ports/hotspot/src/share/vm/shark/sharkStateScanner.cpp Wed May 27 13:49:38 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/sharkStateScanner.cpp Wed May 27 14:59:07 2009 +0100
@@ -1,6 +1,6 @@
/*
* Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright 2008 Red Hat, Inc.
+ * Copyright 2008, 2009 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -45,18 +45,19 @@
end_stack();
// Monitors
- start_monitors(function()->monitor_count());
- for (int i = 0; i < function()->monitor_count(); i++) {
+ start_monitors(state->num_monitors());
+ for (int i = 0; i < state->num_monitors(); i++) {
process_monitor(
i,
- function()->monitors_slots_offset() +
- i * frame::interpreter_frame_monitor_size());
+ function()->monitor_offset(i),
+ function()->monitor_object_offset(i));
}
end_monitors();
// Frame header
start_frame_header();
- process_exception_slot(function()->exception_slot_offset());
+ process_oop_tmp_slot(
+ state->oop_tmp_addr(), function()->oop_tmp_slot_offset());
process_method_slot(state->method_addr(), function()->method_slot_offset());
process_pc_slot(function()->pc_slot_offset());
end_frame_header();
diff -r b22d229ddbcf ports/hotspot/src/share/vm/shark/sharkStateScanner.hpp
--- a/ports/hotspot/src/share/vm/shark/sharkStateScanner.hpp Wed May 27 13:49:38 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/sharkStateScanner.hpp Wed May 27 14:59:07 2009 +0100
@@ -1,6 +1,6 @@
/*
* Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright 2008 Red Hat, Inc.
+ * Copyright 2008, 2009 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -54,11 +54,11 @@
virtual void end_stack() {}
virtual void start_monitors(int num_monitors) {}
- virtual void process_monitor(int index, int offset) {}
+ virtual void process_monitor(int index, int box_offset, int obj_offset) {}
virtual void end_monitors() {}
virtual void start_frame_header() {}
- virtual void process_exception_slot(int offset) {}
+ virtual void process_oop_tmp_slot(llvm::Value** value, int offset) {}
virtual void process_method_slot(llvm::Value** value, int offset) {}
virtual void process_pc_slot(int offset) {}
virtual void end_frame_header() {}
diff -r b22d229ddbcf ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp
--- a/ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp Wed May 27 13:49:38 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp Wed May 27 14:59:07 2009 +0100
@@ -205,34 +205,6 @@
_entry_block = function()->CreateBlock(name);
}
-void SharkTopLevelBlock::acquire_method_lock()
-{
- Value *object;
- if (target()->is_static()) {
- SharkConstantPool constants(this);
- object = constants.java_mirror();
- }
- else {
- object = local(0)->jobject_value();
- }
- iter()->force_bci(start()); // for the decache
- function()->monitor(0)->acquire(this, object);
- check_pending_exception(false);
-}
-
-void SharkTopLevelBlock::release_method_lock()
-{
- function()->monitor(0)->release(this);
-
- // We neither need nor want to check for pending exceptions here.
- // This method is only called by handle_return, which copes with
- // them implicitly:
- // - if a value is being returned then we just carry on as normal;
- // the caller will see the pending exception and handle it.
- // - if an exception is being thrown then that exception takes
- // priority and ours will be ignored.
-}
-
void SharkTopLevelBlock::emit_IR()
{
builder()->SetInsertPoint(entry_block());
@@ -544,15 +516,25 @@
{
assert (exception == NULL || type == T_VOID, "exception OR result, please");
- if (exception)
- builder()->CreateStore(exception, function()->exception_slot());
+ if (num_monitors()) {
+ // Protect our exception across possible monitor release decaches
+ if (exception)
+ set_oop_tmp(exception);
- release_locked_monitors();
- if (target()->is_synchronized())
- release_method_lock();
-
+ // We don't need to check for exceptions thrown here. If
+ // we're returning a value then we just carry on as normal:
+ // the caller will see the pending exception and handle it.
+ // If we're returning with an exception then that exception
+ // takes priority and the release_lock one will be ignored.
+ while (num_monitors())
+ release_lock();
+
+ // Reload the exception we're throwing
+ if (exception)
+ exception = get_oop_tmp();
+ }
+
if (exception) {
- exception = builder()->CreateLoad(function()->exception_slot());
builder()->CreateStore(exception, function()->pending_exception_address());
}
@@ -568,26 +550,6 @@
builder()->CreateRetVoid();
}
-void SharkTopLevelBlock::release_locked_monitors()
-{
- int base = target()->is_synchronized();
- for (int i = function()->monitor_count() - 1; i >= base; i--) {
- BasicBlock *locked = function()->CreateBlock("locked");
- BasicBlock *unlocked = function()->CreateBlock("unlocked");
-
- Value *object = function()->monitor(i)->object();
- builder()->CreateCondBr(
- builder()->CreateICmpNE(object, LLVMValue::null()),
- locked, unlocked);
-
- builder()->SetInsertPoint(locked);
- builder()->CreateUnimplemented(__FILE__, __LINE__);
- builder()->CreateUnreachable();
-
- builder()->SetInsertPoint(unlocked);
- }
-}
-
Value *SharkTopLevelBlock::lookup_for_ldc()
{
int index = iter()->get_constant_index();
@@ -1583,102 +1545,166 @@
array_klass, function()->CreateGetVMResult(), true));
}
+void SharkTopLevelBlock::acquire_method_lock()
+{
+ iter()->force_bci(start()); // for the decache in acquire_lock
+ if (target()->is_static()) {
+ SharkConstantPool constants(this);
+ acquire_lock(constants.java_mirror());
+ }
+ else {
+ acquire_lock(local(0)->jobject_value());
+ }
+ check_pending_exception(false);
+}
+
void SharkTopLevelBlock::do_monitorenter()
{
SharkValue *lockee = pop();
check_null(lockee);
- Value *object = lockee->jobject_value();
-
- // Find a free monitor, or one already allocated for this object
- BasicBlock *loop_top = function()->CreateBlock("loop_top");
- BasicBlock *loop_iter = function()->CreateBlock("loop_iter");
- BasicBlock *loop_check = function()->CreateBlock("loop_check");
- BasicBlock *no_monitor = function()->CreateBlock("no_monitor");
- BasicBlock *got_monitor = function()->CreateBlock("got_monitor");
-
- BasicBlock *entry_block = builder()->GetInsertBlock();
- builder()->CreateBr(loop_check);
-
- builder()->SetInsertPoint(loop_check);
- PHINode *index = builder()->CreatePHI(SharkType::jint_type(), "index");
- index->addIncoming(
- LLVMValue::jint_constant(function()->monitor_count() - 1), entry_block);
- builder()->CreateCondBr(
- builder()->CreateICmpUGE(index, LLVMValue::jint_constant(0)),
- loop_top, no_monitor);
-
- builder()->SetInsertPoint(loop_top);
- SharkMonitor* monitor = function()->monitor(index);
- Value *smo = monitor->object();
- builder()->CreateCondBr(
- builder()->CreateOr(
- builder()->CreateICmpEQ(smo, LLVMValue::null()),
- builder()->CreateICmpEQ(smo, object)),
- got_monitor, loop_iter);
-
- builder()->SetInsertPoint(loop_iter);
- index->addIncoming(
- builder()->CreateSub(index, LLVMValue::jint_constant(1)), loop_iter);
- builder()->CreateBr(loop_check);
-
- builder()->SetInsertPoint(no_monitor);
- builder()->CreateShouldNotReachHere(__FILE__, __LINE__);
- builder()->CreateUnreachable();
-
- // Acquire the lock
- builder()->SetInsertPoint(got_monitor);
- monitor->acquire(this, object);
- check_pending_exception();
+ acquire_lock(lockee->jobject_value());
}
void SharkTopLevelBlock::do_monitorexit()
{
- SharkValue *lockee = pop();
- // The monitorexit can't throw an NPE because the verifier checks
- // that the monitor operations are block structured before we
- // compile.
- // check_null(lockee);
- Value *object = lockee->jobject_value();
+ pop(); // don't need this (monitors are block structured)
+ release_lock();
+}
- // Find the monitor associated with this object
- BasicBlock *loop_top = function()->CreateBlock("loop_top");
- BasicBlock *loop_iter = function()->CreateBlock("loop_iter");
- BasicBlock *loop_check = function()->CreateBlock("loop_check");
- BasicBlock *no_monitor = function()->CreateBlock("no_monitor");
- BasicBlock *got_monitor = function()->CreateBlock("got_monitor");
+void SharkTopLevelBlock::acquire_lock(Value *lockee)
+{
+ BasicBlock *try_recursive = function()->CreateBlock("try_recursive");
+ BasicBlock *got_recursive = function()->CreateBlock("got_recursive");
+ BasicBlock *not_recursive = function()->CreateBlock("not_recursive");
+ BasicBlock *acquired_fast = function()->CreateBlock("acquired_fast");
+ BasicBlock *lock_acquired = function()->CreateBlock("lock_acquired");
- BasicBlock *entry_block = builder()->GetInsertBlock();
- builder()->CreateBr(loop_check);
+ int monitor = num_monitors();
+ Value *monitor_addr = function()->monitor_addr(monitor);
+ Value *monitor_object_addr = function()->monitor_object_addr(monitor);
+ Value *monitor_header_addr = function()->monitor_header_addr(monitor);
- builder()->SetInsertPoint(loop_check);
- PHINode *index = builder()->CreatePHI(SharkType::jint_type(), "index");
- index->addIncoming(
- LLVMValue::jint_constant(function()->monitor_count() - 1), entry_block);
+ // Store the object and mark the slot as live
+ builder()->CreateStore(lockee, monitor_object_addr);
+ set_num_monitors(monitor + 1);
+
+ // Try a simple lock
+ Value *mark_addr = builder()->CreateAddressOfStructEntry(
+ lockee, in_ByteSize(oopDesc::mark_offset_in_bytes()),
+ PointerType::getUnqual(SharkType::intptr_type()),
+ "mark_addr");
+
+ Value *mark = builder()->CreateLoad(mark_addr, "mark");
+ Value *disp = builder()->CreateOr(
+ mark, LLVMValue::intptr_constant(markOopDesc::unlocked_value), "disp");
+ builder()->CreateStore(disp, monitor_header_addr);
+
+ Value *lock = builder()->CreatePtrToInt(
+ monitor_header_addr, SharkType::intptr_type());
+ Value *check = builder()->CreateCmpxchgPtr(lock, mark_addr, disp);
builder()->CreateCondBr(
- builder()->CreateICmpUGE(index, LLVMValue::jint_constant(0)),
- loop_top, no_monitor);
+ builder()->CreateICmpEQ(disp, check),
+ acquired_fast, try_recursive);
- builder()->SetInsertPoint(loop_top);
- SharkMonitor* monitor = function()->monitor(index);
- Value *smo = monitor->object();
+ // Locking failed, but maybe this thread already owns it
+ builder()->SetInsertPoint(try_recursive);
+ Value *addr = builder()->CreateAnd(
+ disp,
+ LLVMValue::intptr_constant(~markOopDesc::lock_mask_in_place));
+
+ // NB we use the entire stack, but JavaThread::is_lock_owned()
+ // uses a more limited range. I don't think it hurts though...
+ Value *stack_limit = builder()->CreateValueOfStructEntry(
+ function()->thread(), Thread::stack_base_offset(),
+ SharkType::intptr_type(),
+ "stack_limit");
+
+ assert(sizeof(size_t) == sizeof(intptr_t), "should be");
+ Value *stack_size = builder()->CreateValueOfStructEntry(
+ function()->thread(), Thread::stack_size_offset(),
+ SharkType::intptr_type(),
+ "stack_size");
+
+ Value *stack_start =
+ builder()->CreateSub(stack_limit, stack_size, "stack_start");
+
builder()->CreateCondBr(
- builder()->CreateICmpEQ(smo, object),
- got_monitor, loop_iter);
+ builder()->CreateAnd(
+ builder()->CreateICmpUGE(addr, stack_start),
+ builder()->CreateICmpULT(addr, stack_limit)),
+ got_recursive, not_recursive);
- builder()->SetInsertPoint(loop_iter);
- index->addIncoming(
- builder()->CreateSub(index, LLVMValue::jint_constant(1)), loop_iter);
- builder()->CreateBr(loop_check);
+ builder()->SetInsertPoint(got_recursive);
+ builder()->CreateStore(LLVMValue::intptr_constant(0), monitor_header_addr);
+ builder()->CreateBr(acquired_fast);
- builder()->SetInsertPoint(no_monitor);
- builder()->CreateShouldNotReachHere(__FILE__, __LINE__);
- builder()->CreateUnreachable();
+ // Create an edge for the state merge
+ builder()->SetInsertPoint(acquired_fast);
+ SharkState *fast_state = current_state()->copy();
+ builder()->CreateBr(lock_acquired);
- // Release the lock
- builder()->SetInsertPoint(got_monitor);
- monitor->release(this);
- // The monitorexit can't throw an NPE because the verifier checks
- // that the monitor operations are block structured before we
- // compile.
- // check_pending_exception();
+ // It's not a recursive case so we need to drop into the runtime
+ builder()->SetInsertPoint(not_recursive);
+ call_vm_nocheck(SharkRuntime::monitorenter(), monitor_addr);
+ BasicBlock *acquired_slow = builder()->GetInsertBlock();
+ builder()->CreateBr(lock_acquired);
+
+ // All done
+ builder()->SetInsertPoint(lock_acquired);
+ current_state()->merge(fast_state, acquired_fast, acquired_slow);
}
+
+void SharkTopLevelBlock::release_lock()
+{
+ BasicBlock *not_recursive = function()->CreateBlock("not_recursive");
+ BasicBlock *released_fast = function()->CreateBlock("released_fast");
+ BasicBlock *slow_path = function()->CreateBlock("slow_path");
+ BasicBlock *lock_released = function()->CreateBlock("lock_released");
+
+ int monitor = num_monitors() - 1;
+ Value *monitor_addr = function()->monitor_addr(monitor);
+ Value *monitor_object_addr = function()->monitor_object_addr(monitor);
+ Value *monitor_header_addr = function()->monitor_header_addr(monitor);
+
+ // If it is recursive then we're already done
+ Value *disp = builder()->CreateLoad(monitor_header_addr);
+ builder()->CreateCondBr(
+ builder()->CreateICmpEQ(disp, LLVMValue::intptr_constant(0)),
+ released_fast, not_recursive);
+
+ // Try a simple unlock
+ builder()->SetInsertPoint(not_recursive);
+
+ Value *lock = builder()->CreatePtrToInt(
+ monitor_header_addr, SharkType::intptr_type());
+
+ Value *lockee = builder()->CreateLoad(monitor_object_addr);
+
+ Value *mark_addr = builder()->CreateAddressOfStructEntry(
+ lockee, in_ByteSize(oopDesc::mark_offset_in_bytes()),
+ PointerType::getUnqual(SharkType::intptr_type()),
+ "mark_addr");
+
+ Value *check = builder()->CreateCmpxchgPtr(disp, mark_addr, lock);
+ builder()->CreateCondBr(
+ builder()->CreateICmpEQ(lock, check),
+ released_fast, slow_path);
+
+ // Create an edge for the state merge
+ builder()->SetInsertPoint(released_fast);
+ SharkState *fast_state = current_state()->copy();
+ builder()->CreateBr(lock_released);
+
+ // Need to drop into the runtime to release this one
+ builder()->SetInsertPoint(slow_path);
+ call_vm_nocheck(SharkRuntime::monitorexit(), monitor_addr);
+ BasicBlock *released_slow = builder()->GetInsertBlock();
+ builder()->CreateBr(lock_released);
+
+ // All done
+ builder()->SetInsertPoint(lock_released);
+ current_state()->merge(fast_state, released_fast, released_slow);
+
+ // The object slot is now dead
+ set_num_monitors(monitor);
+}
diff -r b22d229ddbcf ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp
--- a/ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp Wed May 27 13:49:38 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp Wed May 27 14:59:07 2009 +0100
@@ -189,6 +189,33 @@
return current_state()->method();
}
+ // Temporary oop storage
+ public:
+ void set_oop_tmp(llvm::Value* value)
+ {
+ assert(value, "value must be non-NULL (will be reset by get_oop_tmp)");
+ assert(!current_state()->oop_tmp(), "oop_tmp gets and sets must match");
+ current_state()->set_oop_tmp(value);
+ }
+ llvm::Value* get_oop_tmp()
+ {
+ llvm::Value* value = current_state()->oop_tmp();
+ assert(value, "oop_tmp gets and sets must match");
+ current_state()->set_oop_tmp(NULL);
+ return value;
+ }
+
+ // Monitors
+ private:
+ int num_monitors()
+ {
+ return current_state()->num_monitors();
+ }
+ int set_num_monitors(int num_monitors)
+ {
+ current_state()->set_num_monitors(num_monitors);
+ }
+
// Code generation
public:
void emit_IR();
@@ -288,10 +315,13 @@
return call_vm_nocheck(callee, args, args + 4);
}
- // Whole-method synchronization
+ // Synchronization
+ private:
+ void acquire_lock(llvm::Value* lockee);
+ void release_lock();
+
public:
- void acquire_method_lock();
- void release_method_lock();
+ void acquire_method_lock();
// Error checking
private:
@@ -311,7 +341,6 @@
private:
void call_register_finalizer(llvm::Value* receiver);
void handle_return(BasicType type, llvm::Value* exception);
- void release_locked_monitors();
// arraylength
private:
More information about the distro-pkg-dev
mailing list