Mercurial > hg > release > icedtea6-1.3
changeset 1008:e8c5220a41f5
2008-08-12 Gary Benson <gbenson@redhat.com>
* patches/icedtea-shark.patch: Updated to latest Shark.
* ports/hotspot/src/cpu/zero/vm/assembler_zero.hpp: Likewise.
* ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp: Likewise.
* ports/hotspot/src/cpu/zero/vm/frame_zero.cpp: Likewise.
* ports/hotspot/src/cpu/zero/vm/frame_zero.hpp: Likewise.
* ports/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp: Likewise.
* ports/hotspot/src/cpu/zero/vm/interpreter_zero.hpp: Likewise.
* ports/hotspot/src/cpu/zero/vm/sharkFrame_zero.hpp: Likewise.
* ports/hotspot/src/cpu/zero/vm/stackPrinter_zero.hpp: Likewise.
* ports/hotspot/src/cpu/zero/vm/stack_zero.hpp: Likewise.
* ports/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp: Likewise.
* ports/hotspot/src/share/vm/includeDB_shark: Likewise.
* ports/hotspot/src/share/vm/shark/llvmHeaders.hpp: Likewise.
* ports/hotspot/src/share/vm/shark/sharkBlock.cpp: Likewise.
* ports/hotspot/src/share/vm/shark/sharkBlock.hpp: Likewise.
* ports/hotspot/src/share/vm/shark/sharkBuilder.cpp: Likewise.
* ports/hotspot/src/share/vm/shark/sharkBuilder.hpp: Likewise.
* ports/hotspot/src/share/vm/shark/sharkCompiler.cpp: Likewise.
* ports/hotspot/src/share/vm/shark/sharkCompiler.hpp: Likewise.
* ports/hotspot/src/share/vm/shark/sharkFunction.cpp: Likewise.
* ports/hotspot/src/share/vm/shark/sharkFunction.hpp: Likewise.
* ports/hotspot/src/share/vm/shark/sharkState.cpp: Likewise.
* ports/hotspot/src/share/vm/shark/sharkState.hpp: Likewise.
* ports/hotspot/src/share/vm/shark/sharkType.cpp: Likewise.
* ports/hotspot/src/share/vm/shark/sharkType.hpp: Likewise.
* ports/hotspot/src/share/vm/shark/sharkValue.hpp: Likewise.
* ports/hotspot/src/share/vm/shark/shark_globals.hpp: Likewise.
* ports/hotspot/src/share/vm/shark/sharkConstantPool.cpp: New file.
* ports/hotspot/src/share/vm/shark/sharkConstantPool.hpp: Likewise.
* ports/hotspot/src/share/vm/shark/sharkMethod.hpp: Likewise.
* ports/hotspot/src/share/vm/shark/sharkMonitor.cpp: Likewise.
* ports/hotspot/src/share/vm/shark/sharkMonitor.hpp: Likewise.
* ports/hotspot/src/share/vm/shark/sharkRuntime.cpp: Likewise.
* ports/hotspot/src/share/vm/shark/sharkRuntime.hpp: Likewise.
line wrap: on
line diff
--- a/ChangeLog Tue Aug 12 09:37:13 2008 +0200 +++ b/ChangeLog Tue Aug 12 05:35:18 2008 -0400 @@ -1,3 +1,40 @@ +2008-08-12 Gary Benson <gbenson@redhat.com> + + * patches/icedtea-shark.patch: Updated to latest Shark. + * ports/hotspot/src/cpu/zero/vm/assembler_zero.hpp: Likewise. + * ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp: Likewise. + * ports/hotspot/src/cpu/zero/vm/frame_zero.cpp: Likewise. + * ports/hotspot/src/cpu/zero/vm/frame_zero.hpp: Likewise. + * ports/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp: Likewise. + * ports/hotspot/src/cpu/zero/vm/interpreter_zero.hpp: Likewise. + * ports/hotspot/src/cpu/zero/vm/sharkFrame_zero.hpp: Likewise. + * ports/hotspot/src/cpu/zero/vm/stackPrinter_zero.hpp: Likewise. + * ports/hotspot/src/cpu/zero/vm/stack_zero.hpp: Likewise. + * ports/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp: Likewise. + * ports/hotspot/src/share/vm/includeDB_shark: Likewise. + * ports/hotspot/src/share/vm/shark/llvmHeaders.hpp: Likewise. + * ports/hotspot/src/share/vm/shark/sharkBlock.cpp: Likewise. + * ports/hotspot/src/share/vm/shark/sharkBlock.hpp: Likewise. + * ports/hotspot/src/share/vm/shark/sharkBuilder.cpp: Likewise. + * ports/hotspot/src/share/vm/shark/sharkBuilder.hpp: Likewise. + * ports/hotspot/src/share/vm/shark/sharkCompiler.cpp: Likewise. + * ports/hotspot/src/share/vm/shark/sharkCompiler.hpp: Likewise. + * ports/hotspot/src/share/vm/shark/sharkFunction.cpp: Likewise. + * ports/hotspot/src/share/vm/shark/sharkFunction.hpp: Likewise. + * ports/hotspot/src/share/vm/shark/sharkState.cpp: Likewise. + * ports/hotspot/src/share/vm/shark/sharkState.hpp: Likewise. + * ports/hotspot/src/share/vm/shark/sharkType.cpp: Likewise. + * ports/hotspot/src/share/vm/shark/sharkType.hpp: Likewise. + * ports/hotspot/src/share/vm/shark/sharkValue.hpp: Likewise. + * ports/hotspot/src/share/vm/shark/shark_globals.hpp: Likewise. + * ports/hotspot/src/share/vm/shark/sharkConstantPool.cpp: New file. + * ports/hotspot/src/share/vm/shark/sharkConstantPool.hpp: Likewise. + * ports/hotspot/src/share/vm/shark/sharkMethod.hpp: Likewise. + * ports/hotspot/src/share/vm/shark/sharkMonitor.cpp: Likewise. + * ports/hotspot/src/share/vm/shark/sharkMonitor.hpp: Likewise. + * ports/hotspot/src/share/vm/shark/sharkRuntime.cpp: Likewise. + * ports/hotspot/src/share/vm/shark/sharkRuntime.hpp: Likewise. + 2008-08-12 Christian Thalinger <twisti@complang.tuwien.ac.at> * Makefile.am (ICEDTEA_PATCHES): Fixed typo.
--- a/patches/icedtea-shark.patch Tue Aug 12 09:37:13 2008 +0200 +++ b/patches/icedtea-shark.patch Tue Aug 12 05:35:18 2008 -0400 @@ -176,13 +176,16 @@ diff -ru openjdk/hotspot/src/share/vm/oops/methodOop.cpp openjdk/hotspot/src/share/vm/oops/methodOop.cpp --- openjdk/hotspot/src/share/vm/oops/methodOop.cpp 2008-06-20 10:22:11.000000000 +0100 +++ openjdk/hotspot/src/share/vm/oops/methodOop.cpp 2008-04-15 10:52:44.000000000 +0100 -@@ -733,7 +733,11 @@ +@@ -730,10 +730,14 @@ void methodOopDesc::set_code(methodHandl + } + + OrderAccess::storestore(); ++#ifdef SHARK ++ mh->_from_interpreted_entry = SharkMethod::mark(code->instructions_begin()); ++#else mh->_from_compiled_entry = code->verified_entry_point(); OrderAccess::storestore(); // Instantly compiled code can execute. -+#ifdef SHARK -+ mh->_from_interpreted_entry = *(address *) code->instructions_begin(); -+#else mh->_from_interpreted_entry = mh->get_i2c_entry(); +#endif // SHARK @@ -281,3 +284,22 @@ #endif // TIERED #ifndef HOTSPOT_VM_DISTRO +diff -r ef3bb05d21d5 openjdk/hotspot/src/share/vm/code/nmethod.cpp +--- openjdk/hotspot/src/share/vm/code/nmethod.cpp Fri Aug 08 11:17:59 2008 +0100 ++++ openjdk/hotspot/src/share/vm/code/nmethod.cpp Fri Aug 08 11:35:04 2008 +0100 +@@ -1453,6 +1453,7 @@ void nmethod::oops_do(OopClosure* f) { + // Method that knows how to preserve outgoing arguments at call. This method must be + // called with a frame corresponding to a Java invoke + void nmethod::preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f) { ++#ifndef SHARK + if (!method()->is_native()) { + SimpleScopeDesc ssd(this, fr.pc()); + Bytecode_invoke* call = Bytecode_invoke_at(ssd.method(), ssd.bci()); +@@ -1460,6 +1461,7 @@ void nmethod::preserve_callee_argument_o + symbolOop signature = call->signature(); + fr.oops_compiled_arguments_do(signature, is_static, reg_map, f); + } ++#endif // !SHARK + } + +
--- a/ports/hotspot/src/cpu/zero/vm/assembler_zero.hpp Tue Aug 12 09:37:13 2008 +0200 +++ b/ports/hotspot/src/cpu/zero/vm/assembler_zero.hpp Tue Aug 12 05:35:18 2008 -0400 @@ -51,6 +51,18 @@ void align(int modulus); void bang_stack_with_offset(int offset); + +#ifdef SHARK + public: + void emit_zero_byte() + { + emit_byte(0); + } + void emit_intptr(intptr_t x) + { + emit_address((address) x); + } +#endif // SHARK }; #ifdef ASSERT
--- a/ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Tue Aug 12 09:37:13 2008 +0200 +++ b/ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Tue Aug 12 05:35:18 2008 -0400 @@ -85,8 +85,7 @@ stack->set_sp(istate->stack() + 1); // Make the call - address entry_point = istate->callee_entry_point(); - ((Interpreter::method_entry_t) entry_point) (method, THREAD); + Interpreter::invoke_method(method, istate->callee_entry_point(), THREAD); fixup_after_potential_safepoint(); // Convert the result @@ -623,11 +622,13 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) { + assert (synchronized == false, "should be"); return (address) CppInterpreter::native_entry; } address InterpreterGenerator::generate_normal_entry(bool synchronized) { + assert (synchronized == false, "should be"); return (address) CppInterpreter::normal_entry; } @@ -635,14 +636,10 @@ AbstractInterpreter::MethodKind kind) { address entry_point = NULL; - bool synchronized = false; switch (kind) { case Interpreter::zerolocals: - break; - case Interpreter::zerolocals_synchronized: - synchronized = true; break; case Interpreter::native: @@ -679,10 +676,14 @@ ShouldNotReachHere(); } - if (entry_point) - return entry_point; + if (entry_point == NULL) + entry_point = ((InterpreterGenerator*)this)->generate_normal_entry(false); - return ((InterpreterGenerator*)this)->generate_normal_entry(false); +#ifdef SHARK + assert(!SharkMethod::is_shark_method(entry_point), "shouldn't be"); +#endif // SHARK + + return entry_point; } InterpreterGenerator::InterpreterGenerator(StubQueue* code)
--- a/ports/hotspot/src/cpu/zero/vm/frame_zero.cpp Tue Aug 12 09:37:13 2008 +0200 +++ b/ports/hotspot/src/cpu/zero/vm/frame_zero.cpp Tue Aug 12 05:35:18 2008 -0400 @@ -26,8 +26,6 @@ #include "incls/_precompiled.incl" #include "incls/_frame_zero.cpp.incl" -intptr_t frame::shark_dummy_bcx = 0; - #ifdef ASSERT void RegisterMap::check_location_valid() { @@ -37,8 +35,7 @@ bool frame::is_interpreted_frame() const { - return zeroframe()->is_interpreter_frame() || - zeroframe()->is_shark_frame(); + return zeroframe()->is_interpreter_frame(); } frame frame::sender_for_entry_frame(RegisterMap *map) const @@ -57,6 +54,11 @@ return frame(sender_sp()); } +frame frame::sender_for_compiled_frame(RegisterMap *map) const +{ + return frame(sender_sp()); +} + frame frame::sender(RegisterMap* map) const { // Default is not to follow arguments; the various @@ -69,6 +71,11 @@ if (is_interpreted_frame()) return sender_for_interpreter_frame(map); + assert(_cb == CodeCache::find_blob(pc()),"Must be the same"); + if (_cb != NULL) { + return sender_for_compiled_frame(map); + } + Unimplemented(); }
--- a/ports/hotspot/src/cpu/zero/vm/frame_zero.hpp Tue Aug 12 09:37:13 2008 +0200 +++ b/ports/hotspot/src/cpu/zero/vm/frame_zero.hpp Tue Aug 12 05:35:18 2008 -0400 @@ -37,7 +37,6 @@ public: // Constructors frame(intptr_t* sp); - frame(intptr_t* sp, address pc); // accessors for the instance variables intptr_t* fp() const @@ -70,6 +69,3 @@ assert(zeroframe()->is_shark_frame(), "must be"); return (SharkFrame *) zeroframe(); } - - private: - static intptr_t shark_dummy_bcx;
--- a/ports/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp Tue Aug 12 09:37:13 2008 +0200 +++ b/ports/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp Tue Aug 12 05:35:18 2008 -0400 @@ -40,11 +40,25 @@ inline frame::frame(intptr_t* sp) { _sp = sp; - if (zeroframe()->is_entry_frame()) + switch (zeroframe()->type()) { + case ZeroFrame::ENTRY_FRAME: _pc = StubRoutines::call_stub_return_pc(); - else + _cb = NULL; + break; + + case ZeroFrame::INTERPRETER_FRAME: _pc = NULL; - _cb = NULL; + _cb = NULL; + break; + + case ZeroFrame::SHARK_FRAME: + _pc = zero_sharkframe()->pc(); + _cb = CodeCache::find_blob(pc()); + break; + + default: + ShouldNotReachHere(); + } _deopt_state = not_deoptimized; } @@ -73,10 +87,7 @@ inline intptr_t* frame::interpreter_frame_bcx_addr() const { - if (zeroframe()->is_shark_frame()) - return &shark_dummy_bcx; - else - return (intptr_t*) &(get_interpreterState()->_bcp); + return (intptr_t*) &(get_interpreterState()->_bcp); } inline constantPoolCacheOop* frame::interpreter_frame_cache_addr() const @@ -86,10 +97,7 @@ inline methodOop* frame::interpreter_frame_method_addr() const { - if (zeroframe()->is_shark_frame()) - return zero_sharkframe()->method_addr(); - else - return &(get_interpreterState()->_method); + return &(get_interpreterState()->_method); } inline intptr_t* frame::interpreter_frame_mdx_addr() const @@ -154,5 +162,5 @@ inline intptr_t* frame::unextended_sp() const { - Unimplemented(); + return zero_sharkframe()->unextended_sp(); }
--- a/ports/hotspot/src/cpu/zero/vm/interpreter_zero.hpp Tue Aug 12 09:37:13 2008 +0200 +++ b/ports/hotspot/src/cpu/zero/vm/interpreter_zero.hpp Tue Aug 12 05:35:18 2008 -0400 @@ -26,6 +26,17 @@ public: typedef void (*method_entry_t)(methodOop method, TRAPS); + static void invoke_method(methodOop method, address entry_point, TRAPS) + { +#ifdef SHARK + if (SharkMethod::is_shark_method(entry_point)) { + SharkMethod::get(entry_point)->invoke(method, THREAD); + return; + } +#endif // SHARK + ((method_entry_t) entry_point) (method, THREAD); + } + public: static int expr_index_at(int i) {
--- a/ports/hotspot/src/cpu/zero/vm/sharkFrame_zero.hpp Tue Aug 12 09:37:13 2008 +0200 +++ b/ports/hotspot/src/cpu/zero/vm/sharkFrame_zero.hpp Tue Aug 12 05:35:18 2008 -0400 @@ -28,9 +28,12 @@ // | stack slot n-1 | low addresses // | ... | // | stack slot 0 | -// | monitor 0 (maybe) | +// | monitor m-1 | // | ... | +// | monitor 0 | // | method | +// | unextended_sp | +// | pc | // | frame_type | // | next_frame | high addresses // +--------------------+ ------------------ @@ -48,17 +51,25 @@ protected: enum Layout { - method_off = jf_header_words, + pc_off = jf_header_words, + unextended_sp_off, + method_off, header_words }; public: - methodOop* method_addr() const + address pc() const { - return (methodOop *) addr_of_word(method_off); + return (address) value_of_word(pc_off); } + + intptr_t* unextended_sp() const + { + return (intptr_t *) value_of_word(unextended_sp_off); + } + methodOop method() const { - return *method_addr(); + return (methodOop) value_of_word(method_off); } };
--- a/ports/hotspot/src/cpu/zero/vm/stackPrinter_zero.hpp Tue Aug 12 09:37:13 2008 +0200 +++ b/ports/hotspot/src/cpu/zero/vm/stackPrinter_zero.hpp Tue Aug 12 05:35:18 2008 -0400 @@ -101,6 +101,7 @@ if (frame->is_interpreter_frame()) { interpreterState istate = ((InterpreterFrame *) frame)->interpreter_state(); + intptr_t *monitor_base = (intptr_t *) istate->monitor_base(); if (addr >= (intptr_t *) istate) { field = istate->name_of_field_at_address((address) addr); if (field) { @@ -118,6 +119,24 @@ field = "(vtable for istate)"; } } + else if (addr >= istate->stack_base() && addr < monitor_base) { + int monitor_size = frame::interpreter_frame_monitor_size(); + int last_index = + (monitor_base - istate->stack_base()) / monitor_size - 1; + int index = + last_index - (addr - istate->stack_base()) / monitor_size; + intptr_t monitor = (intptr_t) (istate->monitor_base() - 1 - index); + intptr_t offset = (intptr_t) addr - monitor; + + if (offset == BasicObjectLock::obj_offset_in_bytes()) { + snprintf(_buf, _buflen, "monitor[%d]->_obj", index); + field = _buf; + } + else if (offset == BasicObjectLock::lock_offset_in_bytes()) { + snprintf(_buf, _buflen, "monitor[%d]->_lock", index); + field = _buf; + } + } else if (addr < istate->stack_base()) { if (istate->method()->is_native()) { address hA = istate->method()->signature_handler(); @@ -164,7 +183,13 @@ } } if (frame->is_shark_frame()) { - if (word == SharkFrame::method_off) { + if (word == SharkFrame::pc_off) { + field = "pc"; + } + else if (word == SharkFrame::unextended_sp_off) { + field = "unextended_sp"; + } + else if (word == SharkFrame::method_off) { field = "method"; methodOop method = ((SharkFrame *) frame)->method(); if (method->is_oop())
--- a/ports/hotspot/src/cpu/zero/vm/stack_zero.hpp Tue Aug 12 09:37:13 2008 +0200 +++ b/ports/hotspot/src/cpu/zero/vm/stack_zero.hpp Tue Aug 12 05:35:18 2008 -0400 @@ -98,10 +98,12 @@ { return byte_offset_of(ZeroStack, _base); } + static ByteSize top_offset() { return byte_offset_of(ZeroStack, _top); } + static ByteSize sp_offset() { return byte_offset_of(ZeroStack, _sp); @@ -118,6 +120,7 @@ // | ... | class ZeroFrame { + friend class frame; friend class ZeroStackPrinter; protected:
--- a/ports/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp Tue Aug 12 09:37:13 2008 +0200 +++ b/ports/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp Tue Aug 12 05:35:18 2008 -0400 @@ -66,7 +66,7 @@ EntryFrame::build(stack, parameters, parameter_words, call_wrapper)); // Make the call - ((Interpreter::method_entry_t) entry_point) (method, THREAD); + Interpreter::invoke_method(method, entry_point, THREAD); // Store result depending on type if (!HAS_PENDING_EXCEPTION) {
--- a/ports/hotspot/src/share/vm/includeDB_shark Tue Aug 12 09:37:13 2008 +0200 +++ b/ports/hotspot/src/share/vm/includeDB_shark Tue Aug 12 05:35:18 2008 -0400 @@ -56,6 +56,10 @@ globals.cpp shark_globals.hpp +interpreter.hpp sharkMethod.hpp + +methodOop.cpp sharkMethod.hpp + shark_globals.cpp shark_globals.hpp shark_globals.hpp shark_globals_<arch>.hpp @@ -72,6 +76,8 @@ sharkBlock.cpp shark_globals.hpp sharkBlock.cpp sharkBlock.hpp sharkBlock.cpp sharkBuilder.hpp +sharkBlock.cpp sharkConstantPool.hpp +sharkBlock.cpp sharkRuntime.hpp sharkBlock.cpp sharkState.inline.hpp sharkBlock.cpp sharkValue.hpp @@ -81,8 +87,9 @@ sharkBlock.hpp ciType.hpp sharkBlock.hpp ciTypeFlow.hpp sharkBlock.hpp llvmHeaders.hpp +sharkBlock.hpp sharkBuilder.hpp sharkBlock.hpp sharkFunction.hpp -sharkBlock.hpp sharkBuilder.hpp +sharkBlock.hpp sharkMonitor.hpp sharkBlock.hpp sharkState.hpp sharkBlock.hpp sharkValue.hpp @@ -94,8 +101,9 @@ sharkBuilder.cpp resourceArea.hpp sharkBuilder.cpp llvmHeaders.hpp sharkBuilder.cpp sharkBuilder.hpp +sharkBuilder.cpp sharkRuntime.hpp +sharkBuilder.cpp synchronizer.hpp sharkBuilder.cpp thread.hpp -sharkBuilder.cpp synchronizer.hpp sharkBuilder.hpp barrierSet.hpp sharkBuilder.hpp cardTableModRefBS.hpp @@ -119,6 +127,7 @@ sharkCompiler.cpp shark_globals.hpp sharkCompiler.cpp sharkCompiler.hpp sharkCompiler.cpp sharkFunction.hpp +sharkCompiler.cpp sharkRuntime.hpp sharkCompiler.hpp abstractCompiler.hpp sharkCompiler.hpp ciEnv.hpp @@ -126,6 +135,24 @@ sharkCompiler.hpp llvmHeaders.hpp sharkCompiler.hpp sharkBuilder.hpp +sharkConstantPool.cpp allocation.hpp +sharkConstantPool.cpp constantPoolOop.hpp +sharkConstantPool.cpp cpCacheOop.hpp +sharkConstantPool.cpp debug.hpp +sharkConstantPool.cpp llvmHeaders.hpp +sharkConstantPool.cpp methodOop.hpp +sharkConstantPool.cpp sharkBuilder.hpp +sharkConstantPool.cpp sharkConstantPool.hpp +sharkConstantPool.cpp sharkRuntime.hpp +sharkConstantPool.cpp sharkState.inline.hpp +sharkConstantPool.cpp sharkType.hpp +sharkConstantPool.cpp sharkValue.hpp + +sharkConstantPool.hpp allocation.hpp +sharkConstantPool.hpp llvmHeaders.hpp +sharkConstantPool.hpp sharkBlock.hpp +sharkConstantPool.hpp sharkBuilder.hpp + sharkFunction.cpp allocation.hpp sharkFunction.cpp ciTypeFlow.hpp sharkFunction.cpp debug.hpp @@ -133,6 +160,7 @@ sharkFunction.cpp sharkBlock.hpp sharkFunction.cpp sharkBuilder.hpp sharkFunction.cpp sharkFunction.hpp +sharkFunction.cpp sharkMonitor.hpp sharkFunction.cpp sharkState.inline.hpp sharkFunction.hpp allocation.hpp @@ -142,8 +170,32 @@ sharkFunction.hpp llvmHeaders.hpp sharkFunction.hpp sharkBuilder.hpp +sharkMethod.hpp llvmHeaders.hpp + +sharkMonitor.cpp sharkMonitor.hpp +sharkMonitor.cpp llvmHeaders.hpp + +sharkMonitor.hpp allocation.hpp +sharkMonitor.hpp llvmHeaders.hpp +sharkMonitor.hpp sharkBuilder.hpp +sharkMonitor.hpp sharkFunction.hpp + +sharkRuntime.cpp llvmHeaders.hpp +sharkRuntime.cpp klassOop.hpp +sharkRuntime.cpp sharkBuilder.hpp +sharkRuntime.cpp sharkRuntime.hpp +sharkRuntime.cpp sharkType.hpp +sharkRuntime.cpp thread.hpp + +sharkRuntime.hpp allocation.hpp +sharkRuntime.hpp llvmHeaders.hpp +sharkRuntime.hpp klassOop.hpp +sharkRuntime.hpp sharkBuilder.hpp +sharkRuntime.hpp thread.hpp + sharkState.cpp allocation.hpp sharkState.cpp ciType.hpp +sharkState.cpp ciTypeFlow.hpp sharkState.cpp sharkBlock.hpp sharkState.cpp sharkBuilder.hpp sharkState.cpp sharkState.inline.hpp @@ -152,6 +204,7 @@ sharkState.hpp allocation.hpp sharkState.hpp sharkValue.hpp +sharkState.hpp vmreg.hpp sharkState.inline.hpp sharkBlock.hpp sharkState.inline.hpp sharkState.hpp @@ -160,6 +213,7 @@ sharkType.cpp globalDefinitions.hpp sharkType.cpp llvmHeaders.hpp sharkType.cpp oop.hpp +sharkType.cpp sharkMethod.hpp sharkType.cpp sharkType.hpp sharkType.hpp allocation.hpp
--- a/ports/hotspot/src/share/vm/shark/llvmHeaders.hpp Tue Aug 12 09:37:13 2008 +0200 +++ b/ports/hotspot/src/share/vm/shark/llvmHeaders.hpp Tue Aug 12 05:35:18 2008 -0400 @@ -23,10 +23,8 @@ * */ -#ifdef ASSERT - #ifdef assert - #undef assert - #endif +#ifdef assert + #undef assert #endif #include <llvm/Argument.h> @@ -39,16 +37,18 @@ #include <llvm/Support/IRBuilder.h> #include <llvm/Type.h> +#ifdef assert + #undef assert +#endif + +// from hotspot/src/share/vm/utilities/debug.hpp #ifdef ASSERT - #ifdef assert - #undef assert - #endif - - // copied verbatim from hotspot/src/share/vm/utilities/debug.hpp - #define assert(p,msg) \ + #define assert(p, msg) \ if (!(p)) { \ report_assertion_failure(__FILE__, __LINE__, \ "assert(" XSTR(p) ",\"" msg "\")");\ BREAKPOINT; \ } +#else + #define assert(p, msg) #endif
--- a/ports/hotspot/src/share/vm/shark/sharkBlock.cpp Tue Aug 12 09:37:13 2008 +0200 +++ b/ports/hotspot/src/share/vm/shark/sharkBlock.cpp Tue Aug 12 05:35:18 2008 -0400 @@ -37,11 +37,6 @@ ciblock()->start(), ciblock()->is_private_copy() ? "_private_copy" : ""); _entry_block = function()->CreateBlock(name); - - // Cached values - _constant_pool_check = NULL; - _constant_pool_tags_check = NULL; - _constant_pool_cache_check = NULL; } void SharkBlock::parse() @@ -59,6 +54,8 @@ } if (ciblock()->has_trap()) { + current_state()->decache(); + builder()->CreateDump(LLVMValue::jint_constant(start())); builder()->CreateUnimplemented(__FILE__, __LINE__); builder()->CreateUnreachable(); return; @@ -217,6 +214,10 @@ push(a); break; + case Bytecodes::_arraylength: + do_arraylength(); + break; + case Bytecodes::_baload: do_aload(T_BYTE); break; @@ -379,11 +380,6 @@ do_return(T_OBJECT); break; - case Bytecodes::_athrow: - builder()->CreateUnimplemented(__FILE__, __LINE__); - builder()->CreateUnreachable(); - break; - case Bytecodes::_goto: case Bytecodes::_goto_w: builder()->CreateBr(successor(ciTypeFlow::GOTO_TARGET)->entry_block()); @@ -454,9 +450,26 @@ do_instance_check(); break; + case Bytecodes::_new: + do_new(); + break; + + case Bytecodes::_monitorenter: + do_monitorenter(); + break; + case Bytecodes::_monitorexit: + do_monitorexit(); + break; + default: - tty->print_cr("Unhandled bytecode %s", Bytecodes::name(bc())); - ShouldNotReachHere(); + { + const char *code = Bytecodes::name(bc()); + int buflen = 19 + strlen(code) + 1; + char *buf = (char *) function()->env()->arena()->Amalloc(buflen); + snprintf(buf, buflen, "Unhandled bytecode %s", code); + function()->record_method_not_compilable(buf); + return; + } } } @@ -479,106 +492,6 @@ ShouldNotReachHere(); } -Value *SharkBlock::constant_pool() -{ - Value *m = method(); - if (m != _constant_pool_check) { - _constant_pool_value = builder()->CreateValueOfStructEntry( - m, methodOopDesc::constants_offset(), - SharkType::oop_type(), "constants"); - _constant_pool_check = m; - } - return _constant_pool_value; -} - -Value *SharkBlock::constant_pool_tags() -{ - Value *cp = constant_pool(); - if (cp != _constant_pool_tags_check) { - _constant_pool_tags_value = builder()->CreateValueOfStructEntry( - cp, in_ByteSize(constantPoolOopDesc::tags_offset_in_bytes()), - SharkType::oop_type(), "tags"); - _constant_pool_tags_check = cp; - } - return _constant_pool_tags_value; -} - -Value *SharkBlock::constant_pool_cache() -{ - Value *cp = constant_pool(); - if (cp != _constant_pool_cache_check) { - _constant_pool_cache_value = builder()->CreateValueOfStructEntry( - cp, in_ByteSize(constantPoolOopDesc::cache_offset_in_bytes()), - SharkType::oop_type(), "cache"); - _constant_pool_cache_check = cp; - } - return _constant_pool_cache_value; -} - -Value *SharkBlock::constant_pool_tag_at(int which) -{ - return builder()->CreateArrayLoad( - constant_pool_tags(), T_BYTE, LLVMValue::jint_constant(which)); -} - -Value *SharkBlock::constant_pool_object_at(int which) -{ - return builder()->CreateArrayLoad( - constant_pool(), - T_OBJECT, in_ByteSize(sizeof(constantPoolOopDesc)), - LLVMValue::jint_constant(which)); -} - -Value *SharkBlock::constant_pool_cache_entry_at(int which) -{ - Value *entry = builder()->CreateIntToPtr( - builder()->CreateAdd( - builder()->CreatePtrToInt( - constant_pool_cache(), SharkType::intptr_type()), - LLVMValue::intptr_constant( - in_bytes(constantPoolCacheOopDesc::base_offset()) + - which * sizeof(ConstantPoolCacheEntry))), - SharkType::cpCacheEntry_type()); - -#ifdef ASSERT - // Check the entry is resolved - int shift; - switch (ConstantPoolCacheEntry::bytecode_number(bc())) { - case 1: - shift = 16; - break; - case 2: - shift = 24; - break; - default: - ShouldNotReachHere(); - } - - Value *opcode = builder()->CreateAnd( - builder()->CreateLShr( - builder()->CreateValueOfStructEntry( - entry, ConstantPoolCacheEntry::indices_offset(), - SharkType::intptr_type()), - LLVMValue::jint_constant(shift)), - LLVMValue::intptr_constant(0xff)); - - BasicBlock *not_resolved = function()->CreateBlock("not_resolved"); - BasicBlock *resolved = function()->CreateBlock("resolved"); - - builder()->CreateCondBr( - builder()->CreateICmpEQ(opcode, LLVMValue::intptr_constant(bc())), - resolved, not_resolved); - - builder()->SetInsertPoint(not_resolved); - builder()->CreateShouldNotReachHere(__FILE__, __LINE__); - builder()->CreateUnreachable(); - - builder()->SetInsertPoint(resolved); -#endif // ASSERT - - return entry; -} - void SharkBlock::check_null(SharkValue *object) { if (object->null_checked()) @@ -605,10 +518,7 @@ BasicBlock *out_of_bounds = function()->CreateBlock("out_of_bounds"); BasicBlock *in_bounds = function()->CreateBlock("in_bounds"); - Value *length = builder()->CreateValueOfStructEntry( - array->jarray_value(), in_ByteSize(arrayOopDesc::length_offset_in_bytes()), - SharkType::jint_type(), "length"); - + Value *length = builder()->CreateArrayLength(array->jarray_value()); builder()->CreateCondBr( builder()->CreateICmpSLT(index->jint_value(), length), in_bounds, out_of_bounds); @@ -672,15 +582,95 @@ builder()->SetInsertPoint(safepointed); } +CallInst* SharkBlock::call_vm_base(Constant* callee, + Value** args_start, + Value** args_end) +{ + // Decache the state + current_state()->decache(); + + // Set up the Java frame anchor + function()->set_last_Java_frame(); + + // Make the call + CallInst *result = builder()->CreateCall(callee, args_start, args_end); + + // Clear the frame anchor + function()->reset_last_Java_frame(); + + // Recache the state + current_state()->cache(); + + // Check for pending exceptions + check_pending_exception(); + + return result; +} + void SharkBlock::do_ldc() { SharkValue *value = SharkValue::from_ciConstant(iter()->get_constant()); if (value == NULL) { - Unimplemented() // XXX it's an oop :( + SharkConstantPool constants(this); + + BasicBlock *string = function()->CreateBlock("string"); + BasicBlock *klass = function()->CreateBlock("klass"); + BasicBlock *unresolved = function()->CreateBlock("unresolved"); + BasicBlock *unknown = function()->CreateBlock("unknown"); + BasicBlock *done = function()->CreateBlock("done"); + + SwitchInst *switchinst = builder()->CreateSwitch( + constants.tag_at(iter()->get_constant_index()), + unknown, 5); + + switchinst->addCase( + LLVMValue::jbyte_constant(JVM_CONSTANT_String), string); + switchinst->addCase( + LLVMValue::jbyte_constant(JVM_CONSTANT_Class), klass); + switchinst->addCase( + LLVMValue::jbyte_constant(JVM_CONSTANT_UnresolvedString), unresolved); + switchinst->addCase( + LLVMValue::jbyte_constant(JVM_CONSTANT_UnresolvedClass), unresolved); + switchinst->addCase( + LLVMValue::jbyte_constant(JVM_CONSTANT_UnresolvedClassInError), + unresolved); + + builder()->SetInsertPoint(string); + Value *string_value = constants.object_at(iter()->get_constant_index()); + builder()->CreateBr(done); + + builder()->SetInsertPoint(klass); + builder()->CreateUnimplemented(__FILE__, __LINE__); + Value *klass_value = LLVMValue::null(); + builder()->CreateBr(done); + + builder()->SetInsertPoint(unresolved); + builder()->CreateUnimplemented(__FILE__, __LINE__); + Value *unresolved_value = LLVMValue::null(); + builder()->CreateBr(done); + + builder()->SetInsertPoint(unknown); + builder()->CreateShouldNotReachHere(__FILE__, __LINE__); + builder()->CreateUnreachable(); + + builder()->SetInsertPoint(done); + PHINode *phi = builder()->CreatePHI(SharkType::jobject_type(), "constant"); + phi->addIncoming(string_value, string); + phi->addIncoming(klass_value, klass); + phi->addIncoming(unresolved_value, unresolved); + value = SharkValue::create_jobject(phi); } push(value); } +void SharkBlock::do_arraylength() +{ + SharkValue *array = pop(); + check_null(array); + Value *length = builder()->CreateArrayLength(array->jarray_value()); + push(SharkValue::create_jint(length)); +} + void SharkBlock::do_aload(BasicType basic_type) { SharkValue *index = pop(); @@ -701,6 +691,7 @@ value = builder()->CreateIntCast(value, stack_type, basic_type != T_CHAR); switch (basic_type) { + case T_BOOLEAN: case T_BYTE: case T_CHAR: case T_SHORT: @@ -708,6 +699,10 @@ push(SharkValue::create_jint(value)); break; + case T_OBJECT: + push(SharkValue::create_jobject(value)); + break; + default: tty->print_cr("Unhandled type %s", type2name(basic_type)); ShouldNotReachHere(); @@ -736,6 +731,14 @@ value = svalue->jint_value(); break; + case T_LONG: + value = svalue->jlong_value(); + break; + + case T_OBJECT: + value = svalue->jobject_value(); + break; + default: tty->print_cr("Unhandled type %s", type2name(basic_type)); ShouldNotReachHere(); @@ -777,31 +780,48 @@ } if (!is_get || value == NULL) { if (!is_field) { - Value *cache = constant_pool_cache_entry_at(iter()->get_field_index()); + SharkConstantPool constants(this); + Value *cache = constants.cache_entry_at(iter()->get_field_index()); object = builder()->CreateValueOfStructEntry( cache, ConstantPoolCacheEntry::f1_offset(), SharkType::jobject_type(), "object"); } + + BasicType basic_type = field->type()->basic_type(); + const Type *stack_type = SharkType::to_stackType(basic_type); + const Type *field_type = SharkType::to_arrayType(basic_type); + Value *addr = builder()->CreateAddressOfStructEntry( object, in_ByteSize(field->offset_in_bytes()), - PointerType::getUnqual(SharkType::to_stackType(field->type())), + PointerType::getUnqual(field_type), "field"); // Do the access if (is_get) { - value = SharkValue::create_generic( - field->type(), builder()->CreateLoad(addr, "value")); + Value *field_value = builder()->CreateLoad(addr); + + if (field_type != stack_type) + field_value = builder()->CreateIntCast( + field_value, stack_type, basic_type != T_CHAR); + + value = SharkValue::create_generic(field->type(), field_value); } else { - builder()->CreateStore(value->generic_value(), addr); + Value *field_value = value->generic_value(); + + if (field_type != stack_type) + field_value = builder()->CreateIntCast( + field_value, field_type, basic_type != T_CHAR); + + builder()->CreateStore(field_value, addr); if (!field->type()->is_primitive_type()) - Unimplemented(); // XXX builder()->CreateUpdateBarrierSet( - // oopDesc::bs(), addr, value); + builder()->CreateUpdateBarrierSet(oopDesc::bs(), addr); + if (field->is_volatile()) - Unimplemented(); // XXX __sync_synchronize + builder()->CreateMemoryBarrier(SharkBuilder::BARRIER_STORELOAD); } } @@ -814,13 +834,30 @@ { add_safepoint(); + if (target()->is_synchronized()) + monitor(0)->release(); + Value *result_addr = function()->CreatePopFrame(type2size[basic_type]); if (basic_type != T_VOID) { SharkValue *result = pop(); - assert(result->basic_type() == basic_type || - result->basic_type() == T_ARRAY && basic_type == T_OBJECT, - "type mismatch"); +#ifdef ASSERT + switch (result->basic_type()) { + case T_BOOLEAN: + case T_BYTE: + case T_CHAR: + case T_SHORT: + assert(basic_type == T_INT, "type mismatch"); + break; + + case T_ARRAY: + assert(basic_type == T_OBJECT, "type mismatch"); + break; + + default: + assert(result->basic_type() == basic_type, "type mismatch"); + } +#endif // ASSERT builder()->CreateStore( result->generic_value(), @@ -828,7 +865,6 @@ result_addr, PointerType::getUnqual(SharkType::to_stackType(basic_type)))); } - assert(stack_depth() == 0, "should be"); builder()->CreateRetVoid(); } @@ -878,46 +914,283 @@ // Find the receiver in the stack SharkValue *receiver = NULL; if (bc() != Bytecodes::_invokestatic) { - receiver = stack(method->arg_size() - 1); + int shark_slot = 0, java_slot = 0; + while (java_slot < method->arg_size() - 1) + java_slot += stack(shark_slot++)->type()->size(); + receiver = stack(shark_slot); check_null(receiver); } // Find the method we are calling Value *callee = NULL; - if (bc() == Bytecodes::_invokeinterface) { - Unimplemented(); + SharkConstantPool constants(this); + Value *cache = constants.cache_entry_at(iter()->get_method_index()); + + if (bc() == Bytecodes::_invokevirtual) { + BasicBlock *final = function()->CreateBlock("final"); + BasicBlock *not_final = function()->CreateBlock("not_final"); + BasicBlock *invoke = function()->CreateBlock("invoke"); + + Value *flags = builder()->CreateValueOfStructEntry( + cache, ConstantPoolCacheEntry::flags_offset(), + SharkType::intptr_type(), + "flags"); + + const int mask = 1 << ConstantPoolCacheEntry::vfinalMethod; + builder()->CreateCondBr( + builder()->CreateICmpNE( + builder()->CreateAnd(flags, LLVMValue::intptr_constant(mask)), + LLVMValue::intptr_constant(0)), + final, not_final); + + // For final methods f2 is the actual address of the method + builder()->SetInsertPoint(final); + Value *final_callee = builder()->CreateValueOfStructEntry( + cache, ConstantPoolCacheEntry::f2_offset(), + SharkType::methodOop_type(), + "final_callee"); + builder()->CreateBr(invoke); + + // For non-final methods f2 is the index into the vtable + builder()->SetInsertPoint(not_final); + Value *klass = builder()->CreateValueOfStructEntry( + receiver->jobject_value(), + in_ByteSize(oopDesc::klass_offset_in_bytes()), + SharkType::jobject_type(), + "klass"); + + Value *index = builder()->CreateValueOfStructEntry( + cache, ConstantPoolCacheEntry::f2_offset(), + SharkType::intptr_type(), + "index"); + + Value *nonfinal_callee = builder()->CreateArrayLoad( + klass, + SharkType::methodOop_type(), + vtableEntry::size() * wordSize, + in_ByteSize(instanceKlass::vtable_start_offset() * wordSize), + index, + "nonfinal_callee"); + builder()->CreateBr(invoke); + + builder()->SetInsertPoint(invoke); + callee = builder()->CreatePHI(SharkType::methodOop_type(), "callee"); + ((PHINode *) callee)->addIncoming(final_callee, final); + ((PHINode *) callee)->addIncoming(nonfinal_callee, not_final); + } + else if (bc() == Bytecodes::_invokeinterface) { + BasicBlock *hacky = function()->CreateBlock("hacky"); + BasicBlock *normal = function()->CreateBlock("normal"); + BasicBlock *loop = function()->CreateBlock("loop"); + BasicBlock *got_null = function()->CreateBlock("got_null"); + BasicBlock *not_null = function()->CreateBlock("not_null"); + BasicBlock *next = function()->CreateBlock("next"); + BasicBlock *got_entry = function()->CreateBlock("got_entry"); + BasicBlock *invoke = function()->CreateBlock("invoke"); + + Value *flags = builder()->CreateValueOfStructEntry( + cache, ConstantPoolCacheEntry::flags_offset(), + SharkType::intptr_type(), + "flags"); + + const int mask = 1 << ConstantPoolCacheEntry::methodInterface; + builder()->CreateCondBr( + builder()->CreateICmpNE( + builder()->CreateAnd(flags, LLVMValue::intptr_constant(mask)), + LLVMValue::intptr_constant(0)), + hacky, normal); + + // Workaround for the case where we encounter an invokeinterface, + // but should really have an invokevirtual since the resolved + // method is a virtual method in java.lang.Object. This is a + // corner case in the spec but is presumably legal, and while + // javac does not generate this code there's no reason it could + // not be produced by a compliant java compiler. See + // cpCacheOop.cpp for more details. + builder()->SetInsertPoint(hacky); + builder()->CreateUnimplemented(__FILE__, __LINE__); + Value *hacky_callee = + ConstantPointerNull::get(SharkType::methodOop_type()); + builder()->CreateBr(invoke); + + // Locate the receiver's itable + builder()->SetInsertPoint(normal); + Value *object_klass = builder()->CreateValueOfStructEntry( + receiver->jobject_value(), in_ByteSize(oopDesc::klass_offset_in_bytes()), + SharkType::jobject_type(), + "object_klass"); + + Value *vtable_start = builder()->CreateAdd( + builder()->CreatePtrToInt(object_klass, SharkType::intptr_type()), + LLVMValue::intptr_constant( + instanceKlass::vtable_start_offset() * HeapWordSize), + "vtable_start"); + + Value *vtable_length = builder()->CreateValueOfStructEntry( + object_klass, + in_ByteSize(instanceKlass::vtable_length_offset() * HeapWordSize), + SharkType::jint_type(), + "vtable_length"); + + bool needs_aligning = HeapWordsPerLong > 1; + const char *itable_start_name = "itable_start"; + Value *itable_start = builder()->CreateAdd( + vtable_start, + builder()->CreateShl( + vtable_length, + LLVMValue::jint_constant(exact_log2(vtableEntry::size() * wordSize))), + needs_aligning ? "" : itable_start_name); + if (needs_aligning) + itable_start = builder()->CreateAlign( + itable_start, BytesPerLong, itable_start_name); + + // Locate this interface's entry in the table + Value *iklass = builder()->CreateValueOfStructEntry( + cache, ConstantPoolCacheEntry::f1_offset(), + SharkType::jobject_type(), + "iklass"); + + builder()->CreateBr(loop); + builder()->SetInsertPoint(loop); + PHINode *itable_entry_addr = builder()->CreatePHI( + SharkType::intptr_type(), "itable_entry_addr"); + itable_entry_addr->addIncoming(itable_start, normal); + + Value *itable_entry = builder()->CreateIntToPtr( + itable_entry_addr, SharkType::itableOffsetEntry_type(), "itable_entry"); + + Value *itable_iklass = builder()->CreateValueOfStructEntry( + itable_entry, + in_ByteSize(itableOffsetEntry::interface_offset_in_bytes()), + SharkType::jobject_type(), + "itable_iklass"); + + builder()->CreateCondBr( + builder()->CreateICmpEQ(itable_iklass, LLVMValue::null()), + got_null, not_null); + + // A null entry means that the class doesn't implement the + // interface, and wasn't the same as the class checked when + // the interface was resolved. + builder()->SetInsertPoint(got_null); + builder()->CreateUnimplemented(__FILE__, __LINE__); + builder()->CreateUnreachable(); + + builder()->SetInsertPoint(not_null); + builder()->CreateCondBr( + builder()->CreateICmpEQ(itable_iklass, iklass), + got_entry, next); + + builder()->SetInsertPoint(next); + Value *next_entry = builder()->CreateAdd( + itable_entry_addr, + LLVMValue::intptr_constant(itableOffsetEntry::size() * wordSize)); + builder()->CreateBr(loop); + itable_entry_addr->addIncoming(next_entry, next); + + // Locate the method pointer + builder()->SetInsertPoint(got_entry); + Value *offset = builder()->CreateValueOfStructEntry( + itable_entry, + in_ByteSize(itableOffsetEntry::offset_offset_in_bytes()), + SharkType::jint_type(), + "offset"); + + Value *index = builder()->CreateValueOfStructEntry( + cache, ConstantPoolCacheEntry::f2_offset(), + SharkType::intptr_type(), + "index"); + + Value *normal_callee = builder()->CreateLoad( + builder()->CreateIntToPtr( + builder()->CreateAdd( + builder()->CreateAdd( + builder()->CreateAdd( + builder()->CreatePtrToInt( + object_klass, SharkType::intptr_type()), + offset), + builder()->CreateShl( + index, + LLVMValue::jint_constant( + exact_log2(itableMethodEntry::size() * wordSize)))), + LLVMValue::intptr_constant( + itableMethodEntry::method_offset_in_bytes())), + PointerType::getUnqual(SharkType::methodOop_type())), + "normal_callee"); + builder()->CreateBr(invoke); + + builder()->SetInsertPoint(invoke); + callee = builder()->CreatePHI(SharkType::methodOop_type(), "callee"); + ((PHINode *) callee)->addIncoming(hacky_callee, hacky); + ((PHINode *) callee)->addIncoming(normal_callee, got_entry); } else { - Value *cache = constant_pool_cache_entry_at(iter()->get_method_index()); - - if (bc() == Bytecodes::_invokevirtual) { - int mask = 1 << ConstantPoolCacheEntry::vfinalMethod; - if (method->flags().as_int() & mask == mask) { - callee = builder()->CreateValueOfStructEntry( - cache, ConstantPoolCacheEntry::f2_offset(), - SharkType::methodOop_type(), - "callee"); - } - else { - Unimplemented(); - } - } - else { - callee = builder()->CreateValueOfStructEntry( - cache, ConstantPoolCacheEntry::f1_offset(), - SharkType::methodOop_type(), - "callee"); - } + callee = builder()->CreateValueOfStructEntry( + cache, ConstantPoolCacheEntry::f1_offset(), + SharkType::methodOop_type(), + "callee"); } Value *entry_point = builder()->CreateValueOfStructEntry( callee, methodOopDesc::from_interpreted_offset(), // XXX hacky - PointerType::getUnqual(SharkType::method_entry_type()), + PointerType::getUnqual(SharkType::interpreter_entry_type()), "entry_point"); - // Make the call + // Decache for the call current_state()->decache(method); - builder()->CreateCall2(entry_point, callee, thread()); + + // Make the call + BasicBlock *interpreter_call = function()->CreateBlock("interpreter_call"); + BasicBlock *shark_call = function()->CreateBlock("shark_call"); + BasicBlock *post_call = function()->CreateBlock("post_call"); + + Value *entry_point_or_sharkmethod = builder()->CreateValueOfStructEntry( + callee, methodOopDesc::from_interpreted_offset(), + SharkType::intptr_type(), + "entry_point_or_sharkmethod"); + + builder()->CreateCondBr( + builder()->CreateICmpEQ( + builder()->CreateAnd( + entry_point_or_sharkmethod, + LLVMValue::intptr_constant(SharkMethod::marker())), + LLVMValue::intptr_constant(0)), + interpreter_call, shark_call); + + // Interpreter calls + builder()->SetInsertPoint(interpreter_call); + + Value *interpreter_entry_point = builder()->CreateIntToPtr( + entry_point_or_sharkmethod, + PointerType::getUnqual(SharkType::interpreter_entry_type()), + "interpreter_entry_point"); + + builder()->CreateCall2(interpreter_entry_point, callee, thread()); + builder()->CreateBr(post_call); + + // Shark calls + builder()->SetInsertPoint(shark_call); + + Value *base_pc = builder()->CreateAnd( + entry_point_or_sharkmethod, + LLVMValue::intptr_constant(~SharkMethod::marker()), + "base_pc"); + + Value *shark_entry_point = builder()->CreateLoad( + builder()->CreateIntToPtr( + builder()->CreateAdd( + base_pc, + LLVMValue::intptr_constant( + in_bytes(SharkMethod::entry_point_offset()))), + PointerType::getUnqual( + PointerType::getUnqual(SharkType::shark_entry_type()))), + "shark_entry_point"); + + builder()->CreateCall3(shark_entry_point, callee, base_pc, thread()); + builder()->CreateBr(post_call); + + // Recache state + builder()->SetInsertPoint(post_call); current_state()->cache(method); // Check for pending exceptions @@ -926,12 +1199,12 @@ void SharkBlock::do_instance_check() { - BasicBlock *not_null = function()->CreateBlock("not_null"); - BasicBlock *resolve = function()->CreateBlock("resolve"); - BasicBlock *resolved = function()->CreateBlock("resolved"); - BasicBlock *subclass_check = function()->CreateBlock("subclass_check"); - BasicBlock *failure = function()->CreateBlock("failure"); - BasicBlock *success = function()->CreateBlock("success"); + BasicBlock *not_null = function()->CreateBlock("not_null"); + BasicBlock *resolve = function()->CreateBlock("resolve"); + BasicBlock *resolved = function()->CreateBlock("resolved"); + BasicBlock *subtype_check = function()->CreateBlock("subtype_check"); + BasicBlock *failure = function()->CreateBlock("failure"); + BasicBlock *success = function()->CreateBlock("success"); SharkValue *sharkobject = pop(); Value *object = sharkobject->jobject_value(); @@ -943,7 +1216,8 @@ builder()->SetInsertPoint(not_null); // Get the class we're checking against - Value *tag = constant_pool_tag_at(iter()->get_klass_index()); + SharkConstantPool constants(this); + Value *tag = constants.tag_at(iter()->get_klass_index()); builder()->CreateCondBr( builder()->CreateOr( builder()->CreateICmpEQ( @@ -955,26 +1229,29 @@ // If the class is unresolved we must resolve it builder()->SetInsertPoint(resolve); builder()->CreateUnimplemented(__FILE__, __LINE__); - builder()->CreateBr(resolved); + builder()->CreateUnreachable(); // XXX builder()->CreateBr(resolved); builder()->SetInsertPoint(resolved); - Value *klass = constant_pool_object_at(iter()->get_klass_index()); + Value *check_klass = constants.object_at(iter()->get_klass_index()); // Get the class of the object being tested - Value *objKlass = builder()->CreateValueOfStructEntry( + Value *object_klass = builder()->CreateValueOfStructEntry( object, in_ByteSize(oopDesc::klass_offset_in_bytes()), SharkType::jobject_type(), - "objKlass"); + "object_klass"); - // Check if it's the same class + // Perform the check builder()->CreateCondBr( - builder()->CreateICmpEQ(klass, objKlass), - success, subclass_check); - - // Check if it's a subclass - builder()->SetInsertPoint(subclass_check); - builder()->CreateUnimplemented(__FILE__, __LINE__); - builder()->CreateUnreachable(); + builder()->CreateICmpEQ(check_klass, object_klass), + success, subtype_check); + + builder()->SetInsertPoint(subtype_check); + builder()->CreateCondBr( + builder()->CreateICmpNE( + builder()->CreateCall2( + SharkRuntime::is_subtype_of(), check_klass, object_klass), + LLVMValue::jbyte_constant(0)), + success, failure); // Handle the result if (bc() == Bytecodes::_checkcast) { @@ -1006,3 +1283,191 @@ ShouldNotReachHere(); } } + +void SharkBlock::do_new() +{ + bool will_link; + ciInstanceKlass* klass = iter()->get_klass(will_link)->as_instance_klass(); + assert(will_link, "typeflow responsibility"); + + BasicBlock *got_tlab = NULL; + BasicBlock *heap_alloc = NULL; + BasicBlock *retry = NULL; + BasicBlock *got_heap = NULL; + BasicBlock *initialize = NULL; + BasicBlock *slow_alloc_and_init = NULL; + BasicBlock *got_slow = NULL; + BasicBlock *push_object = NULL; + + SharkState *fast_state = NULL; + + Value *tlab_object = NULL; + Value *heap_object = NULL; + Value *fast_object = NULL; + Value *slow_object = NULL; + Value *object = NULL; + + // The fast path + if (!Klass::layout_helper_needs_slow_path(klass->layout_helper())) { + if (UseTLAB) { + got_tlab = function()->CreateBlock("got_tlab"); + heap_alloc = function()->CreateBlock("heap_alloc"); + } + retry = function()->CreateBlock("retry"); + got_heap = function()->CreateBlock("got_heap"); + initialize = function()->CreateBlock("initialize"); + slow_alloc_and_init = function()->CreateBlock("slow_alloc_and_init"); + push_object = function()->CreateBlock("push_object"); + + size_t size_in_bytes = klass->size_helper() << LogHeapWordSize; + + // Thread local allocation + if (UseTLAB) { + Value *top_addr = builder()->CreateAddressOfStructEntry( + thread(), Thread::tlab_top_offset(), + PointerType::getUnqual(SharkType::intptr_type()), + "top_addr"); + + Value *end = builder()->CreateValueOfStructEntry( + thread(), Thread::tlab_end_offset(), + SharkType::intptr_type(), + "end"); + + Value *old_top = builder()->CreateLoad(top_addr, "old_top"); + Value *new_top = builder()->CreateAdd( + old_top, LLVMValue::intptr_constant(size_in_bytes)); + + builder()->CreateCondBr( + builder()->CreateICmpULE(new_top, end), + got_tlab, heap_alloc); + + builder()->SetInsertPoint(got_tlab); + tlab_object = builder()->CreateIntToPtr( + old_top, SharkType::jobject_type(), "tlab_object"); + + builder()->CreateStore(new_top, top_addr); + builder()->CreateBr(initialize); + + builder()->SetInsertPoint(heap_alloc); + } + + // Heap allocation + Value *top_addr = builder()->CreateIntToPtr( + LLVMValue::intptr_constant((intptr_t) Universe::heap()->top_addr()), + PointerType::getUnqual(SharkType::intptr_type()), + "top_addr"); + + Value *end = builder()->CreateLoad( + builder()->CreateIntToPtr( + LLVMValue::intptr_constant((intptr_t) Universe::heap()->end_addr()), + PointerType::getUnqual(SharkType::intptr_type())), + "end"); + + builder()->CreateBr(retry); + builder()->SetInsertPoint(retry); + + Value *old_top = builder()->CreateLoad(top_addr, "top"); + Value *new_top = builder()->CreateAdd( + old_top, LLVMValue::intptr_constant(size_in_bytes)); + + builder()->CreateCondBr( + builder()->CreateICmpULE(new_top, end), + got_heap, slow_alloc_and_init); + + builder()->SetInsertPoint(got_heap); + heap_object = builder()->CreateIntToPtr( + old_top, SharkType::jobject_type(), "heap_object"); + + Value *check = builder()->CreateCmpxchgPtr(new_top, top_addr, old_top); + builder()->CreateCondBr( + builder()->CreateICmpEQ(old_top, check), + initialize, retry); + + // Initialize the object + builder()->SetInsertPoint(initialize); + if (tlab_object) { + PHINode *phi = builder()->CreatePHI( + SharkType::jobject_type(), "fast_object"); + phi->addIncoming(tlab_object, got_tlab); + phi->addIncoming(heap_object, got_heap); + fast_object = phi; + } + else { + fast_object = heap_object; + } + + builder()->CreateMemset( + builder()->CreateBitCast( + fast_object, PointerType::getUnqual(SharkType::jbyte_type())), + LLVMValue::jbyte_constant(0), + LLVMValue::jint_constant(size_in_bytes), + LLVMValue::jint_constant(HeapWordSize)); + + Value *mark_addr = builder()->CreateAddressOfStructEntry( + fast_object, in_ByteSize(oopDesc::mark_offset_in_bytes()), + PointerType::getUnqual(SharkType::intptr_type()), + "mark_addr"); + + Value *klass_addr = builder()->CreateAddressOfStructEntry( + fast_object, in_ByteSize(oopDesc::klass_offset_in_bytes()), + PointerType::getUnqual(SharkType::jobject_type()), + "klass_addr"); + + // Set the mark + intptr_t mark; + if (UseBiasedLocking) { + Unimplemented(); + } + else { + mark = (intptr_t) markOopDesc::prototype(); + } + builder()->CreateStore(LLVMValue::intptr_constant(mark), mark_addr); + + // Set the class + SharkConstantPool constants(this); + Value *rtklass = constants.object_at(iter()->get_klass_index()); + builder()->CreateStore(rtklass, klass_addr); + + builder()->CreateBr(push_object); + builder()->SetInsertPoint(slow_alloc_and_init); + fast_state = current_state()->copy(); + } + + // The slow path + SharkConstantPool constants(this); + call_vm( + SharkRuntime::new_instance(), + constants.object_at(iter()->get_klass_index())); + slow_object = function()->CreateLoadVMResult(); + got_slow = builder()->GetInsertBlock(); + + // Push the object + if (push_object) { + builder()->CreateBr(push_object); + builder()->SetInsertPoint(push_object); + } + if (fast_object) { + PHINode *phi = builder()->CreatePHI(SharkType::jobject_type(), "object"); + phi->addIncoming(fast_object, initialize); + phi->addIncoming(slow_object, got_slow); + object = phi; + current_state()->merge(fast_state, initialize, got_slow); + } + else { + object = slow_object; + } + + push(SharkValue::create_jobject(object)); +} + +void SharkBlock::do_monitorenter() +{ + SharkValue *lockee = pop(); + builder()->CreateUnimplemented(__FILE__, __LINE__); +} + +void SharkBlock::do_monitorexit() +{ + SharkValue *lockee = pop(); + builder()->CreateUnimplemented(__FILE__, __LINE__); +}
--- a/ports/hotspot/src/share/vm/shark/sharkBlock.hpp Tue Aug 12 09:37:13 2008 +0200 +++ b/ports/hotspot/src/share/vm/shark/sharkBlock.hpp Tue Aug 12 05:35:18 2008 -0400 @@ -61,16 +61,18 @@ { return function()->builder(); } + SharkMonitor* monitor(int index) const + { + return function()->monitor(index); + } + ciMethod* target() const + { + return function()->target(); + } llvm::Value* thread() const { return function()->thread(); } -#ifndef PRODUCT - bool debug() const - { - return function()->debug(); - } -#endif // PRODUCT // Typeflow properties public: @@ -98,6 +100,10 @@ { return ciblock()->stack_size(); } + int monitor_count() const + { + return ciblock()->monitor_count(); + } ciType* local_type_at_entry(int index) const { return ciblock()->local_type_at(index); @@ -192,7 +198,7 @@ private: SharkTrackingState* _current_state; - private: + public: SharkTrackingState* current_state() { if (_current_state == NULL) @@ -200,11 +206,12 @@ return _current_state; } - private: + public: llvm::Value* method() { return current_state()->method(); } + private: SharkValue* local(int index) { return current_state()->local(index); @@ -230,27 +237,31 @@ return current_state()->stack(slot); } + // VM calls + private: + llvm::CallInst* call_vm_base(llvm::Constant* callee, + llvm::Value** args_start, + llvm::Value** args_end); + + public: + llvm::CallInst* call_vm(llvm::Constant* callee, llvm::Value* arg1) + { + llvm::Value *args[] = {thread(), arg1}; + return call_vm_base(callee, args, args + 2); + } + llvm::CallInst* call_vm(llvm::Constant* callee, + llvm::Value* arg1, + llvm::Value* arg2, + llvm::Value* arg3) + { + llvm::Value *args[] = {thread(), arg1, arg2, arg3}; + return call_vm_base(callee, args, args + 4); + } + // Code generation public: void parse(); - // Constant pool - private: - llvm::Value* _constant_pool_check; - llvm::Value* _constant_pool_value; - llvm::Value* _constant_pool_tags_check; - llvm::Value* _constant_pool_tags_value; - llvm::Value* _constant_pool_cache_check; - llvm::Value* _constant_pool_cache_value; - - private: - llvm::Value* constant_pool(); - llvm::Value* constant_pool_tags(); - llvm::Value* constant_pool_cache(); - llvm::Value* constant_pool_tag_at(int which); - llvm::Value* constant_pool_object_at(int which); - llvm::Value* constant_pool_cache_entry_at(int which); - // Error checking private: void check_null(SharkValue* value); @@ -265,6 +276,10 @@ private: void do_ldc(); + // _arraylength bytecode + private: + void do_arraylength(); + // _*aload and *astore bytecodes private: void do_aload(BasicType basic_type); @@ -309,4 +324,13 @@ // _checkcast and _instanceof private: void do_instance_check(); + + // _new + private: + void do_new(); + + // _monitorenter and monitorexit + private: + void do_monitorenter(); + void do_monitorexit(); };
--- a/ports/hotspot/src/share/vm/shark/sharkBuilder.cpp Tue Aug 12 09:37:13 2008 +0200 +++ b/ports/hotspot/src/share/vm/shark/sharkBuilder.cpp Tue Aug 12 05:35:18 2008 -0400 @@ -28,101 +28,76 @@ using namespace llvm; -SharkBuilder::SharkBuilder(Module* module) +SharkBuilder::SharkBuilder() : IRBuilder(), - _module(module) + _module("shark"), + _module_provider(module()), + _execution_engine(ExecutionEngine::create(&_module_provider)) { init_external_functions(); } +Constant* SharkBuilder::make_function(intptr_t addr, + const FunctionType* sig, + const char* name) +{ + Constant *func = make_pointer(addr, sig); + +#ifndef PRODUCT + ResourceMark rm; + + // Use a trampoline to make dumped code more readable + Function *trampoline = (Function *) module()->getOrInsertFunction(name, sig); + SetInsertPoint(BasicBlock::Create("", trampoline)); + + Value **args = NEW_RESOURCE_ARRAY(Value*, trampoline->arg_size()); + Function::arg_iterator ai = trampoline->arg_begin(); + for (unsigned i = 0; i < trampoline->arg_size(); i++) + args[i] = ai++; + + Value *result = CreateCall(func, args, args + trampoline->arg_size()); + if (sig->getReturnType() == Type::VoidTy) + CreateRetVoid(); + else + CreateRet(result); + + func = trampoline; +#endif // !PRODUCT + + return func; +} + void SharkBuilder::init_external_functions() { std::vector<const Type*> params; - params.push_back(SharkType::intptr_type()); - params.push_back(SharkType::jint_type()); - FunctionType *type = FunctionType::get(Type::VoidTy, params, false); - Constant *func = make_pointer((intptr_t) report_should_not_reach_here, type); -#ifndef PRODUCT - // Use a trampoline to make dumped code more readable - Function *trampoline = - (Function *) module()->getOrInsertFunction("should_not_reach_here", type); - Function::arg_iterator ai = trampoline->arg_begin(); - Value *file = ai++; - Value *line = ai++; - SetInsertPoint(BasicBlock::Create("", trampoline)); - CreateCall2(func, file, line); - CreateRetVoid(); - func = trampoline; -#endif // !PRODUCT - set_report_should_not_reach_here_fn(func); - - // XXX copy and paste -- refactor this! - func = make_pointer((intptr_t) report_unimplemented, type); -#ifndef PRODUCT - // Use a trampoline to make dumped code more readable - trampoline = - (Function *) module()->getOrInsertFunction("unimplemented", type); - ai = trampoline->arg_begin(); - file = ai++; - line = ai++; - SetInsertPoint(BasicBlock::Create("", trampoline)); - CreateCall2(func, file, line); - CreateRetVoid(); - func = trampoline; -#endif // !PRODUCT - set_report_unimplemented_fn(func); - - // XXX copy and paste -- refactor this! - params.clear(); - params.push_back(SharkType::jint_type()); - params.push_back(SharkType::intptr_type()); - func = make_pointer((intptr_t) trace_bytecode, type); -#ifndef PRODUCT - // Use a trampoline to make dumped code more readable - trampoline = - (Function *) module()->getOrInsertFunction("trace_bytecode", type); - ai = trampoline->arg_begin(); - file = ai++; - line = ai++; - SetInsertPoint(BasicBlock::Create("", trampoline)); - CreateCall2(func, file, line); - CreateRetVoid(); - func = trampoline; -#endif // !PRODUCT - set_trace_bytecode_fn(func); - - params.clear(); - params.push_back(SharkType::intptr_type()); + params.push_back(PointerType::getUnqual(SharkType::jbyte_type())); params.push_back(SharkType::jbyte_type()); params.push_back(SharkType::jint_type()); params.push_back(SharkType::jint_type()); - type = FunctionType::get(Type::VoidTy, params, false); + FunctionType *type = FunctionType::get(Type::VoidTy, params, false); set_llvm_memset_fn(module()->getOrInsertFunction("llvm.memset.i32", type)); params.clear(); + params.push_back(PointerType::getUnqual(SharkType::intptr_type())); params.push_back(SharkType::intptr_type()); params.push_back(SharkType::intptr_type()); + type = FunctionType::get(SharkType::intptr_type(), params, false); + set_llvm_cmpxchg_ptr_fn( + module()->getOrInsertFunction( + "llvm.atomic.cmp.swap.i" LP64_ONLY("64") NOT_LP64("32"), type)); + + params.clear(); + for (int i = 0; i < 5; i++) + params.push_back(Type::Int1Ty); type = FunctionType::get(Type::VoidTy, params, false); - func = make_pointer((intptr_t) dump, type); -#ifndef PRODUCT - // Use a trampoline to make dumped code more readable - trampoline = - (Function *) module()->getOrInsertFunction("print_value", type); - ai = trampoline->arg_begin(); - file = ai++; - line = ai++; - SetInsertPoint(BasicBlock::Create("", trampoline)); - CreateCall2(func, file, line); - CreateRetVoid(); - func = trampoline; -#endif // !PRODUCT - set_dump_fn(func); + set_llvm_memory_barrier_fn( + module()->getOrInsertFunction("llvm.memory.barrier", type)); } Function *SharkBuilder::CreateFunction() { Function *function = Function::Create( - SharkType::method_entry_type(), + SharkType::shark_entry_type(), GlobalVariable::InternalLinkage, "func"); module()->getFunctionList().push_back(function); @@ -154,20 +129,15 @@ Unimplemented(); Value *args[] = {name, value}; - return CreateCall2(dump_fn(), name, value); + return CreateCall2(SharkRuntime::dump(), name, value); } -void SharkBuilder::dump(const char *name, intptr_t value) +CallInst* SharkBuilder::CreateCmpxchgPtr(Value* exchange_value, + Value* dst, + Value* compare_value) { - oop valueOop = (oop) value; - tty->print("%s = ", name); - if (valueOop->is_oop(true)) - valueOop->print_on(tty); - else if (value >= ' ' && value <= '~') - tty->print("'%c' (%d)", value, value); - else - tty->print("%d", value); - tty->print_cr(""); + return CreateCall3( + llvm_cmpxchg_ptr_fn(), dst, compare_value, exchange_value); } CallInst* SharkBuilder::CreateMemset(Value* dst, @@ -181,7 +151,7 @@ CallInst* SharkBuilder::CreateUnimplemented(const char* file, int line) { return CreateCall2( - report_unimplemented_fn(), + SharkRuntime::unimplemented(), LLVMValue::intptr_constant((intptr_t) file), LLVMValue::jint_constant(line)); } @@ -189,20 +159,18 @@ CallInst* SharkBuilder::CreateShouldNotReachHere(const char* file, int line) { return CreateCall2( - report_should_not_reach_here_fn(), + SharkRuntime::should_not_reach_here(), LLVMValue::intptr_constant((intptr_t) file), LLVMValue::jint_constant(line)); } -void SharkBuilder::trace_bytecode(int bci, const char* bc) +CallInst *SharkBuilder::CreateMemoryBarrier(BarrierFlags flags) { - tty->print_cr("%3d: %s", bci, bc); + Value *args[] = { + ConstantInt::get(Type::Int1Ty, (flags & BARRIER_LOADLOAD) ? 1 : 0), + ConstantInt::get(Type::Int1Ty, (flags & BARRIER_LOADSTORE) ? 1 : 0), + ConstantInt::get(Type::Int1Ty, (flags & BARRIER_STORELOAD) ? 1 : 0), + ConstantInt::get(Type::Int1Ty, (flags & BARRIER_STORESTORE) ? 1 : 0), + ConstantInt::get(Type::Int1Ty, 0)}; + return CreateCall(llvm_memory_barrier_fn(), args, args + 5); } - -CallInst* SharkBuilder::CreateTraceBytecode(int bci, Bytecodes::Code bc) -{ - return CreateCall2( - trace_bytecode_fn(), - LLVMValue::jint_constant(bci), - LLVMValue::intptr_constant((intptr_t) Bytecodes::name(bc))); -}
--- a/ports/hotspot/src/share/vm/shark/sharkBuilder.hpp Tue Aug 12 09:37:13 2008 +0200 +++ b/ports/hotspot/src/share/vm/shark/sharkBuilder.hpp Tue Aug 12 05:35:18 2008 -0400 @@ -25,16 +25,21 @@ class SharkBuilder : public llvm::IRBuilder { public: - SharkBuilder(llvm::Module* module); + SharkBuilder(); - // The module we build our functions into private: - llvm::Module* _module; + llvm::Module _module; + llvm::ExistingModuleProvider _module_provider; + llvm::ExecutionEngine* _execution_engine; - protected: - llvm::Module* module() const + public: + llvm::Module* module() { - return _module; + return &_module; + } + llvm::ExecutionEngine* execution_engine() const + { + return _execution_engine; } // Function creation @@ -62,26 +67,46 @@ name); } + llvm::LoadInst* CreateArrayLength(llvm::Value* array) + { + return CreateValueOfStructEntry( + array, in_ByteSize(arrayOopDesc::length_offset_in_bytes()), + SharkType::jint_type(), "length"); + } + + llvm::LoadInst* CreateArrayLoad(llvm::Value* arrayoop, + const llvm::Type* element_type, + int element_bytes, + ByteSize base_offset, + llvm::Value* index, + const char* name = "") + { + llvm::Value* offset = index; + + if (element_bytes != 1) + offset = CreateShl( + offset, + LLVMValue::jint_constant(exact_log2(element_bytes))); + offset = CreateAdd(LLVMValue::jint_constant(in_bytes(base_offset)),offset); + + return CreateLoad( + CreateIntToPtr( + CreateAdd(CreatePtrToInt(arrayoop, SharkType::intptr_type()), offset), + llvm::PointerType::getUnqual(element_type)), + name); + } + llvm::LoadInst* CreateArrayLoad(llvm::Value* arrayoop, BasicType basic_type, ByteSize base_offset, llvm::Value* index, const char* name = "") { - llvm::Value* offset = index; - - if (type2aelembytes[basic_type] != 1) - offset = CreateShl( - offset, - LLVMValue::jint_constant(exact_log2(type2aelembytes[basic_type]))); - offset = CreateAdd(LLVMValue::jint_constant(in_bytes(base_offset)),offset); - - const llvm::Type *array_type = SharkType::to_arrayType(basic_type); - return CreateLoad( - CreateIntToPtr( - CreateAdd(CreatePtrToInt(arrayoop, SharkType::intptr_type()), offset), - llvm::PointerType::getUnqual(array_type)), - name); + return CreateArrayLoad( + arrayoop, + SharkType::to_arrayType(basic_type), + type2aelembytes[basic_type], + base_offset, index, name); } llvm::StoreInst* CreateArrayStore(llvm::Value* arrayoop, @@ -128,8 +153,14 @@ index, value); } + // Helper for making function pointers + public: + llvm::Constant* make_function(intptr_t addr, + const llvm::FunctionType* sig, + const char* name); + // Helper for making pointers - private: + public: llvm::Constant* make_pointer(intptr_t addr, const llvm::Type* type) const { return llvm::ConstantExpr::getIntToPtr( @@ -139,59 +170,38 @@ // External functions (and intrinsics) private: - llvm::Constant* _dump_fn; + llvm::Constant* _llvm_cmpxchg_ptr_fn; + llvm::Constant* _llvm_memory_barrier_fn; llvm::Constant* _llvm_memset_fn; - llvm::Constant* _report_should_not_reach_here_fn; - llvm::Constant* _trace_bytecode_fn; - llvm::Constant* _report_unimplemented_fn; - void set_dump_fn(llvm::Constant* dump_fn) + void set_llvm_cmpxchg_ptr_fn(llvm::Constant* llvm_cmpxchg_ptr_fn) { - _dump_fn = dump_fn; + _llvm_cmpxchg_ptr_fn = llvm_cmpxchg_ptr_fn; + } + void set_llvm_memory_barrier_fn(llvm::Constant* llvm_memory_barrier_fn) + { + _llvm_memory_barrier_fn = llvm_memory_barrier_fn; } void set_llvm_memset_fn(llvm::Constant* llvm_memset_fn) { _llvm_memset_fn = llvm_memset_fn; } - void set_report_should_not_reach_here_fn(llvm::Constant* report_snrh_fn) - { - _report_should_not_reach_here_fn = report_snrh_fn; - } - void set_trace_bytecode_fn(llvm::Constant* trace_bytecode_fn) - { - _trace_bytecode_fn = trace_bytecode_fn; - } - void set_report_unimplemented_fn(llvm::Constant* report_unimplemented_fn) - { - _report_unimplemented_fn = report_unimplemented_fn; - } void init_external_functions(); - static void dump(const char *name, intptr_t value); - static void trace_bytecode(int bci, const char* bc); - protected: - llvm::Constant* dump_fn() const + llvm::Constant* llvm_cmpxchg_ptr_fn() const { - return _dump_fn; + return _llvm_cmpxchg_ptr_fn; + } + llvm::Constant* llvm_memory_barrier_fn() const + { + return _llvm_memory_barrier_fn; } llvm::Constant* llvm_memset_fn() const { return _llvm_memset_fn; } - llvm::Constant* report_should_not_reach_here_fn() const - { - return _report_should_not_reach_here_fn; - } - llvm::Constant* trace_bytecode_fn() const - { - return _trace_bytecode_fn; - } - llvm::Constant* report_unimplemented_fn() const - { - return _report_unimplemented_fn; - } public: llvm::CallInst* CreateDump(llvm::Value* value); @@ -199,15 +209,15 @@ llvm::Value* value, llvm::Value* len, llvm::Value* align); + llvm::CallInst* CreateCmpxchgPtr(llvm::Value* exchange_value, + llvm::Value* dst, + llvm::Value* compare_value); llvm::CallInst* CreateShouldNotReachHere(const char* file, int line); - llvm::CallInst* CreateTraceBytecode(int bci, Bytecodes::Code bc); llvm::CallInst* CreateUnimplemented(const char* file, int line); - // Memory barriers + // HotSpot memory barriers public: - void CreateUpdateBarrierSet(BarrierSet* bs, - llvm::Value* field, - llvm::Value* new_value) + void CreateUpdateBarrierSet(BarrierSet* bs, llvm::Value* field) { if (bs->kind() != BarrierSet::CardTableModRef) { Unimplemented(); @@ -224,4 +234,27 @@ LLVMValue::intptr_constant(CardTableModRefBS::card_shift))), llvm::PointerType::getUnqual(SharkType::jbyte_type()))); } + + // Hardware memory barriers + public: + enum BarrierFlags { + BARRIER_LOADLOAD = 1, + BARRIER_LOADSTORE = 2, + BARRIER_STORELOAD = 4, + BARRIER_STORESTORE = 8 + }; + + public: + llvm::CallInst* CreateMemoryBarrier(BarrierFlags flags); + + // Alignment + public: + llvm::Value* CreateAlign(llvm::Value* x, intptr_t s, const char* name = "") + { + assert(is_power_of_2(s), "should be"); + return CreateAnd( + CreateAdd(x, LLVMValue::intptr_constant(s - 1)), + LLVMValue::intptr_constant(~(s - 1)), + name); + } };
--- a/ports/hotspot/src/share/vm/shark/sharkCompiler.cpp Tue Aug 12 09:37:13 2008 +0200 +++ b/ports/hotspot/src/share/vm/shark/sharkCompiler.cpp Tue Aug 12 05:35:18 2008 -0400 @@ -25,22 +25,15 @@ #include "incls/_precompiled.incl" #include "incls/_sharkCompiler.cpp.incl" -#ifndef PRODUCT -#include <fstream> -#include <ostream> -#include <llvm/Bitcode/ReaderWriter.h> -#endif // !PRODUCT using namespace llvm; SharkCompiler::SharkCompiler() : AbstractCompiler(), - _module(name()), - _builder(&_module), - _module_provider(&_module), - _execution_engine(ExecutionEngine::create(&_module_provider)) + _builder() { SharkType::initialize(); + SharkRuntime::initialize(builder()); mark_initialized(); } @@ -54,50 +47,83 @@ assert(is_initialized(), "should be"); assert(entry_bci == InvocationEntryBci, "OSR is not supported"); + ResourceMark rm; + + const char *method_klass = NULL; + const char *method_name = NULL; + #ifndef PRODUCT + method_klass = klassname(target); + method_name = methodname(target); + + // Skip methods if requested static uintx methods_seen = 0; methods_seen++; - if (methods_seen < SharkStartAt || methods_seen > SharkStopAfter) { - env->record_method_not_compilable("outside SharkStartAt/SharkStopAfter"); + if (methods_seen < SharkStartAt) { + env->record_method_not_compilable("methods_seen < SharkStartAt"); return; } + else if (methods_seen > SharkStopAfter) { + while (true) + sleep(1); + } #endif // !PRODUCT - ResourceMark rm; + if (SharkOnlyCompile != NULL) { + if (!method_matches(SharkOnlyCompile, method_klass, method_name)) { + env->record_method_not_compilable("does not match SharkOnlyCompile"); + return; + } + } // Do the typeflow analysis ciTypeFlow *flow = target->get_flow_analysis(); if (env->failing()) return; -#ifndef PRODUCT - if (methods_seen == SharkPrintTypeflowAfter) { - flow->print_on(tty); + if (SharkPrintTypeflowOf != NULL) { + if (method_matches(SharkPrintTypeflowOf, method_klass, method_name)) + flow->print_on(tty); } -#endif // PRODUCT - // Generate the IR + // Create the CodeBuffer and OopMapSet + BufferBlob *bb = BufferBlob::create( + "shark_temp", sizeof(SharkMethod) + target->code_size()); + CodeBuffer cb(bb->instructions_begin(), bb->instructions_size()); + OopMapSet oopmaps; + + // Compile the method ciBytecodeStream iter(target); - SharkFunction function(builder(), flow, &iter); + SharkFunction function(builder(), flow, &iter, &cb, &oopmaps); if (env->failing()) return; -#ifndef PRODUCT - if (methods_seen == SharkDumpModuleAfter) { - tty->print_cr("%3d Dumping module to hotspot.bc", methods_seen); - std::ostream *out = new std::ofstream( - "hotspot.bc", std::ios::out | std::ios::trunc | std::ios::binary); - WriteBitcodeToFile(&_module, *out); - delete out; + if (SharkPrintBitcodeOf != NULL) { + if (method_matches(SharkPrintBitcodeOf, method_klass, method_name)) + function.function()->dump(); } -#endif // !PRODUCT + if (SharkTraceInstalls) { +#ifdef PPC + uint32_t *start = *(uint32_t **) bb->instructions_begin(); + uint32_t *limit = start; + while (*limit) + limit++; +#else + Unimplemented(); +#endif // PPC - // Compile and install the method - install_method(env, target, entry_bci, function.function()); + tty->print_cr( + "Installing method %s::%s at [%p-%p)", + method_klass, method_name, start, limit); + } + + // Install the method + install_method(env, target, entry_bci, &cb, &oopmaps); } -void SharkCompiler::install_method(ciEnv* env, - ciMethod* target, - int entry_bci, - Function* function) +void SharkCompiler::install_method(ciEnv* env, + ciMethod* target, + int entry_bci, + CodeBuffer* cb, + OopMapSet* oopmaps) { // Pretty much everything in this method is junk to stop // ciEnv::register_method() from failing assertions. @@ -106,11 +132,9 @@ env->set_oop_recorder(&oop_recorder); DebugInformationRecorder debug_info(&oop_recorder); + debug_info.set_oopmaps(oopmaps); env->set_debug_info(&debug_info); - OopMapSet oopmaps; - debug_info.set_oopmaps(&oopmaps); - Dependencies deps(env); env->set_dependencies(&deps); @@ -120,15 +144,7 @@ offsets.set_value(CodeOffsets::Verified_Entry, target->is_static() ? 0 : wordSize); - assert(CodeEntryAlignment > (int)(sizeof(intptr_t) * 2), "buffer too small"); - unsigned char buf[CodeEntryAlignment * 2]; - intptr_t *data = - (intptr_t *) align_size_up((intptr_t) buf, CodeEntryAlignment); - CodeBuffer cb((address) data, CodeEntryAlignment); - cb.initialize_oop_recorder(&oop_recorder); - *(data++) = (intptr_t) execution_engine()->getPointerToFunction(function); - *(data++) = (intptr_t) function; - cb.set_code_end((address) data); + cb->initialize_oop_recorder(&oop_recorder); ExceptionHandlerTable handler_table; ImplicitExceptionTable inc_table; @@ -137,9 +153,9 @@ entry_bci, &offsets, 0, - &cb, + cb, 0, - &oopmaps, + oopmaps, &handler_table, &inc_table, this, @@ -147,3 +163,53 @@ false, false); } + +#ifndef PRODUCT +const char* SharkCompiler::klassname(const ciMethod* target) +{ + const char *name = target->holder()->name()->as_utf8(); + char *buf = NEW_RESOURCE_ARRAY(char, strlen(name) + 1); + strcpy(buf, name); + for (char *c = buf; *c; c++) { + if (*c == '/') + *c = '.'; + } + return buf; +} + +const char* SharkCompiler::methodname(const ciMethod* target) +{ + return target->name()->as_utf8(); +} + +bool SharkCompiler::method_matches(const char* pattern, + const char* klassname, + const char* methodname) +{ + if (pattern[0] == '*') { + pattern++; + } + else { + int len = strlen(klassname); + if (strncmp(pattern, klassname, len)) + return false; + pattern += len; + } + + if (pattern[0] != ':' && pattern[1] != ':') + return false; + pattern += 2; + + if (pattern[0] == '*') { + pattern++; + } + else { + int len = strlen(methodname); + if (strncmp(pattern, methodname, len)) + return false; + pattern += len; + } + + return pattern[0] == '\0'; +} +#endif // !PRODUCT
--- a/ports/hotspot/src/share/vm/shark/sharkCompiler.hpp Tue Aug 12 09:37:13 2008 +0200 +++ b/ports/hotspot/src/share/vm/shark/sharkCompiler.hpp Tue Aug 12 05:35:18 2008 -0400 @@ -47,34 +47,30 @@ // Compilation entry point for methods void compile_method(ciEnv* env, ciMethod* target, int entry_bci); + // The builder we'll use to compile our functions private: - // The module into which we'll place our functions - llvm::Module _module; - - // The builder we'll use to create our functions SharkBuilder _builder; - // Wrapper to make our module look like a fully-fledged module provider - llvm::ExistingModuleProvider _module_provider; - - // The execution engine we'll use to compile our functions - llvm::ExecutionEngine* _execution_engine; - protected: - // Accessors SharkBuilder* builder() { return &_builder; } - llvm::ExecutionEngine* execution_engine() const - { - return _execution_engine; - } + // Method installation helper private: - // Method installation helper void install_method(ciEnv* env, ciMethod* target, int entry_bci, - llvm::Function* function); + CodeBuffer* cb, + OopMapSet* oopmaps); + + // Debug helpers + private: + static const char *klassname (const ciMethod* target) PRODUCT_RETURN0; + static const char *methodname(const ciMethod* target) PRODUCT_RETURN0; + + static bool method_matches(const char* pattern, + const char* klassname, + const char* methodname) PRODUCT_RETURN0; };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ports/hotspot/src/share/vm/shark/sharkConstantPool.cpp Tue Aug 12 05:35:18 2008 -0400 @@ -0,0 +1,156 @@ +/* + * 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/_sharkConstantPool.cpp.incl" + +using namespace llvm; + +Value *SharkConstantPool::constants() +{ + Value *m = method(); + if (m != _constants_method) { + _constants = builder()->CreateValueOfStructEntry( + m, methodOopDesc::constants_offset(), + SharkType::oop_type(), "constants"); + _constants_method = m; + } + return _constants; +} + +Value *SharkConstantPool::tags() +{ + Value *cp = constants(); + if (cp != _tags_constants) { + _tags = builder()->CreateValueOfStructEntry( + cp, in_ByteSize(constantPoolOopDesc::tags_offset_in_bytes()), + SharkType::oop_type(), "tags"); + _tags_constants = cp; + } + return _tags; +} + +Value *SharkConstantPool::cache() +{ + Value *cp = constants(); + if (cp != _cache_constants) { + _cache = builder()->CreateValueOfStructEntry( + cp, in_ByteSize(constantPoolOopDesc::cache_offset_in_bytes()), + SharkType::oop_type(), "cache"); + _cache_constants = cp; + } + return _cache; +} + +Value *SharkConstantPool::object_at(int which) +{ + return builder()->CreateArrayLoad( + constants(), + T_OBJECT, in_ByteSize(sizeof(constantPoolOopDesc)), + LLVMValue::jint_constant(which)); +} + +Value *SharkConstantPool::tag_at(int which) +{ + return builder()->CreateArrayLoad( + tags(), T_BYTE, LLVMValue::jint_constant(which)); +} + +Value *SharkConstantPool::cache_entry_at(int which) +{ + Value *entry = builder()->CreateIntToPtr( + builder()->CreateAdd( + builder()->CreatePtrToInt( + cache(), SharkType::intptr_type()), + LLVMValue::intptr_constant( + in_bytes(constantPoolCacheOopDesc::base_offset()) + + which * sizeof(ConstantPoolCacheEntry))), + SharkType::cpCacheEntry_type()); + + // Resolve the entry if necessary + int shift; + switch (ConstantPoolCacheEntry::bytecode_number(block()->bc())) { + case 1: + shift = 16; + break; + case 2: + shift = 24; + break; + default: + ShouldNotReachHere(); + } + + Value *opcode = builder()->CreateAnd( + builder()->CreateLShr( + builder()->CreateValueOfStructEntry( + entry, ConstantPoolCacheEntry::indices_offset(), + SharkType::intptr_type()), + LLVMValue::jint_constant(shift)), + LLVMValue::intptr_constant(0xff)); + + BasicBlock *orig_block = builder()->GetInsertBlock(); + SharkState *orig_state = block()->current_state()->copy(); + + BasicBlock *resolve = block()->function()->CreateBlock("resolve"); + BasicBlock *resolved = block()->function()->CreateBlock("resolved"); + + builder()->CreateCondBr( + builder()->CreateICmpNE(opcode, LLVMValue::intptr_constant(block()->bc())), + resolve, resolved); + + builder()->SetInsertPoint(resolve); + Constant *resolver; + switch (block()->bc()) { + case Bytecodes::_invokestatic: + case Bytecodes::_invokespecial: + case Bytecodes::_invokevirtual: + case Bytecodes::_invokeinterface: + resolver = SharkRuntime::resolve_invoke(); + break; + + case Bytecodes::_getfield: + case Bytecodes::_getstatic: + case Bytecodes::_putfield: + case Bytecodes::_putstatic: + resolver = SharkRuntime::resolve_get_put(); + break; + + default: + ShouldNotReachHere(); + } + + block()->call_vm( + resolver, + entry, + LLVMValue::jint_constant(block()->bci()), + LLVMValue::jint_constant(block()->bc())); + BasicBlock *resolve_block = builder()->GetInsertBlock(); + builder()->CreateBr(resolved); + + builder()->SetInsertPoint(resolved); + block()->current_state()->merge(orig_state, orig_block, resolve_block); + + return entry; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ports/hotspot/src/share/vm/shark/sharkConstantPool.hpp Tue Aug 12 05:35:18 2008 -0400 @@ -0,0 +1,70 @@ +/* + * 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 SharkConstantPool : public StackObj { + public: + SharkConstantPool(SharkBlock* block) + : _block(block), + _constants_method(NULL), + _tags_constants(NULL), + _cache_constants(NULL) {} + + private: + SharkBlock* _block; + + private: + SharkBlock* block() const + { + return _block; + } + SharkBuilder* builder() const + { + return block()->builder(); + } + llvm::Value* method() const + { + return block()->method(); + } + + private: + llvm::Value* _constants; // The constant pool, a constantPoolOop + llvm::Value* _constants_method; // The method _constants was loaded from + + llvm::Value* _tags; // The tags array, a typeArrayOop + llvm::Value* _tags_constants; // The constantPoolOop _tags is in + + llvm::Value* _cache; // The cache, a constantPoolCacheOop + llvm::Value* _cache_constants; // The constantPoolCacheOop _cache is in + + private: + llvm::Value* constants(); + llvm::Value* tags(); + llvm::Value* cache(); + + public: + llvm::Value* object_at(int which); + llvm::Value* tag_at(int which); + llvm::Value* cache_entry_at(int which); +};
--- a/ports/hotspot/src/share/vm/shark/sharkFunction.cpp Tue Aug 12 09:37:13 2008 +0200 +++ b/ports/hotspot/src/share/vm/shark/sharkFunction.cpp Tue Aug 12 05:35:18 2008 -0400 @@ -30,36 +30,54 @@ void SharkFunction::initialize() { -#ifndef PRODUCT - _debug = false; -#endif // PRODUCT - // Create the function _function = builder()->CreateFunction(); set_block_insertion_point(NULL); + // Create the assembler + _masm = new MacroAssembler(cb()); + + // Create the SharkMethod + assert( + masm()->offset() == in_bytes(SharkMethod::entry_point_offset()), "fix"); + void **code = (void **) masm()->pc(); + masm()->emit_intptr(0); + assert( + masm()->offset() == in_bytes(SharkMethod::llvm_function_offset()), "fix"); + masm()->emit_intptr((intptr_t) function()); + assert(masm()->offset() == sizeof(SharkMethod), "fix"); + // Initialize the blocks _blocks = NEW_RESOURCE_ARRAY(SharkBlock*, flow()->block_count()); - for (int i = 0; i < block_count(); i++) { + for (int i = 0; i < block_count(); i++) _blocks[i] = new SharkBlock(this, flow()->pre_order_at(i)); - if (block(i)->start() == 0) { - assert(start_block() == NULL, "multiple start blocks"); - _start_block = block(i); - } - } - start_block()->add_predecessor(NULL); + + assert(block(0)->start() == 0, "blocks out of order"); + SharkBlock *start_block = block(0); + + start_block->add_predecessor(NULL); for (int i = 0; i < block_count(); i++) { for (int j = 0; j < block(i)->num_successors(); j++) { block(i)->successor(j)->add_predecessor(block(i)); } } + // Initialize the monitors + _monitor_count = 0; + if (target()->is_synchronized() || target()->uses_monitors()) { + for (int i = 0; i < block_count(); i++) + _monitor_count = MAX2(_monitor_count, block(i)->monitor_count()); + } + if (monitor_count()) + _monitors = NEW_RESOURCE_ARRAY(SharkMonitor*, monitor_count()); + // Get our arguments Function::arg_iterator ai = function()->arg_begin(); Argument *method = ai++; + method->setName("method"); + _base_pc = ai++; + _base_pc->setName("base_pc"); _thread = ai++; - - method->setName("method"); _thread->setName("thread"); // Create the method preamble @@ -67,10 +85,27 @@ builder()->SetInsertPoint(CreateBlock()); CreateInitZeroStack(); CreatePushFrame(CreateBuildFrame()); + NOT_PRODUCT(builder()->CreateStore(method, method_slot())); + + // Lock if necessary + if (target()->is_synchronized()) { + Value *object; + if (target()->is_static()) { + Unimplemented(); + object = NULL; + } + else { + object = builder()->CreateLoad( + builder()->CreateBitCast( + builder()->CreateStructGEP(locals_slots(), max_locals() - 1), + PointerType::getUnqual(SharkType::oop_type()))); + } + monitor(0)->acquire(object); + } // Transition into the method proper - start_block()->add_incoming(new SharkEntryState(start_block())); - builder()->CreateBr(start_block()->entry_block()); + start_block->add_incoming(new SharkEntryState(method, start_block)); + builder()->CreateBr(start_block->entry_block()); // Parse the blocks for (int i = 0; i < block_count(); i++) { @@ -80,9 +115,14 @@ set_block_insertion_point(NULL); block(i)->parse(); - if (failing()) + if (failing()) { + delete function(); return; + } } + + // Compile to native code + *code = builder()->execution_engine()->getPointerToFunction(function()); } void SharkFunction::CreateInitZeroStack() @@ -157,15 +197,15 @@ Value* SharkFunction::CreateBuildFrame() { - if (flow()->method()->is_synchronized() || flow()->method()->uses_monitors()) - Unimplemented(); + 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 stack_words = max_stack(); + int frame_words = header_words + monitor_words + stack_words; - int locals_words = max_locals(); - int extra_locals = locals_words - arg_size(); - int header_words = SharkFrame::header_words; - int stack_words = max_stack(); - int frame_words = header_words + stack_words; - + _oopmap_frame_size = frame_words + extra_locals; + // Update the stack pointer Value *zero_stack_pointer = builder()->CreateSub( CreateLoadZeroStackPointer(), @@ -182,19 +222,56 @@ int offset = 0; // Java stack + _stack_slots_offset = offset; _stack_slots = builder()->CreateBitCast( - builder()->CreateStructGEP(frame, offset), + builder()->CreateStructGEP(frame, stack_slots_offset()), PointerType::getUnqual( ArrayType::get(SharkType::intptr_type(), stack_words)), "stack_slots"); offset += stack_words; + // Monitors + if (monitor_count()) { + _monitors_slots_offset = offset; + + Value *monitors = builder()->CreateBitCast( + builder()->CreateStructGEP(frame, monitors_slots_offset()), + PointerType::getUnqual( + ArrayType::get(SharkType::monitor_type(), monitor_count())), + "monitors"); + + for (int i = 0; i < monitor_count(); i++) { + char name[19]; + snprintf(name, sizeof(name), "monitor_%d", i); + + _monitors[i] = new SharkMonitor( + this, + builder()->CreateStructGEP(monitors, monitor_count() - 1 - i, name)); + + if (i != 0 || !target()->is_synchronized()) + monitor(i)->mark_free(); + } + } + offset += monitor_words; + // Method pointer + _method_slot_offset = offset++; _method_slot = builder()->CreateBitCast( - builder()->CreateStructGEP(frame, offset++), + builder()->CreateStructGEP(frame, method_slot_offset()), PointerType::getUnqual(SharkType::methodOop_type()), "method_slot"); + // Unextended SP + builder()->CreateStore( + zero_stack_pointer, + builder()->CreateStructGEP(frame, offset++)); + + // PC + _pc_slot = builder()->CreateBitCast( + builder()->CreateStructGEP(frame, offset++), + PointerType::getUnqual(SharkType::intptr_type()), + "pc_slot"); + // Frame header builder()->CreateStore( LLVMValue::intptr_constant(ZeroFrame::SHARK_FRAME), @@ -202,8 +279,9 @@ Value *fp = builder()->CreateStructGEP(frame, offset++, "fp"); // Local variables + _locals_slots_offset = offset; _locals_slots = builder()->CreateBitCast( - builder()->CreateStructGEP(frame, offset), + builder()->CreateStructGEP(frame, locals_slots_offset()), PointerType::getUnqual( ArrayType::get(SharkType::intptr_type(), locals_words)), "locals_slots");
--- a/ports/hotspot/src/share/vm/shark/sharkFunction.hpp Tue Aug 12 09:37:13 2008 +0200 +++ b/ports/hotspot/src/share/vm/shark/sharkFunction.hpp Tue Aug 12 05:35:18 2008 -0400 @@ -24,13 +24,20 @@ */ class SharkBlock; +class SharkMonitor; class SharkFunction : public StackObj { public: SharkFunction(SharkBuilder* builder, ciTypeFlow* flow, - ciBytecodeStream* iter) - : _builder(builder), _flow(flow), _iter(iter), _start_block(NULL) + ciBytecodeStream* iter, + CodeBuffer* cb, + OopMapSet* oopmaps) + : _builder(builder), + _flow(flow), + _iter(iter), + _cb(cb), + _oopmaps(oopmaps) { initialize(); } private: @@ -40,10 +47,14 @@ SharkBuilder* _builder; ciTypeFlow* _flow; ciBytecodeStream* _iter; + CodeBuffer* _cb; + OopMapSet* _oopmaps; + MacroAssembler* _masm; llvm::Function* _function; SharkBlock** _blocks; - SharkBlock* _start_block; + llvm::Value* _base_pc; llvm::Value* _thread; + int _monitor_count; public: SharkBuilder* builder() const @@ -58,6 +69,18 @@ { return _iter; } + CodeBuffer* cb() const + { + return _cb; + } + OopMapSet* oopmaps() const + { + return _oopmaps; + } + MacroAssembler* masm() const + { + return _masm; + } llvm::Function* function() const { return _function; @@ -66,19 +89,23 @@ { return _blocks[i]; } - SharkBlock* start_block() const + llvm::Value* base_pc() const { - return _start_block; + return _base_pc; } llvm::Value* thread() const { return _thread; } + int monitor_count() const + { + return _monitor_count; + } public: int arg_size() const { - return flow()->method()->arg_size(); + return target()->arg_size(); } int block_count() const { @@ -92,6 +119,10 @@ { return flow()->max_stack(); } + ciMethod* target() const + { + return flow()->method(); + } public: ciEnv* env() const @@ -158,6 +189,7 @@ { return builder()->CreateStore(value, zero_stack_pointer_addr()); } + private: llvm::LoadInst* CreateLoadZeroFramePointer(const char *name = "") { @@ -168,19 +200,26 @@ return builder()->CreateStore(value, zero_frame_pointer_addr()); } + private: void CreateStackOverflowCheck(llvm::Value* sp); public: void CreatePushFrame(llvm::Value* fp); llvm::Value* CreatePopFrame(int result_slots); - + // Frame management private: - llvm::Value* _method_slot; - llvm::Value* _locals_slots; - llvm::Value* _stack_slots; + llvm::Value* _pc_slot; + llvm::Value* _method_slot; + llvm::Value* _locals_slots; + SharkMonitor** _monitors; + llvm::Value* _stack_slots; public: + llvm::Value* pc_slot() const + { + return _pc_slot; + } llvm::Value* method_slot() const { return _method_slot; @@ -189,6 +228,10 @@ { return _locals_slots; } + SharkMonitor* monitor(int index) const + { + return _monitors[index]; + } llvm::Value* stack_slots() const { return _stack_slots; @@ -197,15 +240,76 @@ private: llvm::Value* CreateBuildFrame(); - // Debugging -#ifndef PRODUCT + // OopMap support + public: + int code_offset() const + { + int offset = masm()->offset(); + masm()->emit_zero_byte(); // keeps PCs unique + return offset; + } + void add_gc_map(int offset, OopMap* oopmap) + { + oopmaps()->add_gc_map(offset, oopmap); + } + private: - bool _debug; - + int _oopmap_frame_size; + int _stack_slots_offset; + int _monitors_slots_offset; + int _method_slot_offset; + int _locals_slots_offset; + public: - bool debug() const + int oopmap_frame_size() const + { + return _oopmap_frame_size; + } + int stack_slots_offset() const + { + return _stack_slots_offset; + } + int monitors_slots_offset() const + { + return _monitors_slots_offset; + } + int method_slot_offset() const + { + return _method_slot_offset; + } + int locals_slots_offset() const + { + return _locals_slots_offset; + } + + // VM interface + private: + llvm::StoreInst* CreateStoreLastJavaSP(llvm::Value* value) const { - return _debug; + return builder()->CreateStore( + value, + builder()->CreateAddressOfStructEntry( + thread(), JavaThread::last_Java_sp_offset(), + llvm::PointerType::getUnqual(SharkType::intptr_type()), + "last_Java_sp_addr")); + } + + public: + void set_last_Java_frame() + { + CreateStoreLastJavaSP(CreateLoadZeroFramePointer()); } -#endif // PRODUCT + void reset_last_Java_frame() + { + CreateStoreLastJavaSP(LLVMValue::intptr_constant(0)); + } + + public: + llvm::LoadInst* CreateLoadVMResult() const + { + return builder()->CreateValueOfStructEntry( + thread(), JavaThread::vm_result_offset(), + SharkType::jobject_type(), + "vm_result"); + } };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ports/hotspot/src/share/vm/shark/sharkMethod.hpp Tue Aug 12 05:35:18 2008 -0400 @@ -0,0 +1,91 @@ +/* + * 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 SharkMethod { + public: + SharkMethod() + { + ShouldNotCallThis(); + } + + public: + typedef void (*method_entry_t)(methodOop method, intptr_t base_pc, TRAPS); + + private: + method_entry_t _entry_point; + llvm::Function* _llvm_function; + + public: + method_entry_t entry_point() const + { + return _entry_point; + } + llvm::Function* llvm_function() const + { + return _llvm_function; + } + + // Identifying and manipulating Shark entry points + private: + const static intptr_t _marker = 1; + + public: + static bool is_shark_method(address entry_point) + { + return (intptr_t) entry_point & _marker; + } + static address mark(address entry_point) + { + assert(!is_shark_method(entry_point), "shouldn't be"); + return (address) ((intptr_t) entry_point | _marker); + } + static SharkMethod* get(address entry_point) + { + assert(is_shark_method(entry_point), "should be"); + return (SharkMethod *) ((intptr_t) entry_point & ~_marker); + } + + // Method invocation + public: + void invoke(methodOop method, TRAPS) + { + entry_point()(method, (intptr_t) this, THREAD); + } + + // Assembly language support + public: + static intptr_t marker() + { + return _marker; + } + static ByteSize entry_point_offset() + { + return byte_offset_of(SharkMethod, _entry_point); + } + static ByteSize llvm_function_offset() + { + return byte_offset_of(SharkMethod, _llvm_function); + } +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ports/hotspot/src/share/vm/shark/sharkMonitor.cpp Tue Aug 12 05:35:18 2008 -0400 @@ -0,0 +1,154 @@ +/* + * 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(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 *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), + lock_acquired, 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(lock_acquired); + + // It's not a recursive case so we need to drop into the runtime + builder()->SetInsertPoint(not_recursive); + builder()->CreateUnimplemented(__FILE__, __LINE__); + builder()->CreateUnreachable(); + + // All done + builder()->SetInsertPoint(lock_acquired); +} + +void SharkMonitor::release() const +{ + BasicBlock *not_recursive = function()->CreateBlock("not_recursive"); + BasicBlock *call_runtime = function()->CreateBlock("call_runtime"); + 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)), + lock_released, 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), + lock_released, call_runtime); + + // Need to drop into the runtime to release this one + builder()->SetInsertPoint(call_runtime); + set_object(lockee); + builder()->CreateUnimplemented(__FILE__, __LINE__); + builder()->CreateUnreachable(); + + // All done + builder()->SetInsertPoint(lock_released); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ports/hotspot/src/share/vm/shark/sharkMonitor.hpp Tue Aug 12 05:35:18 2008 -0400 @@ -0,0 +1,92 @@ +/* + * 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 SharkMonitor : public ResourceObj { + public: + SharkMonitor(SharkFunction* function, llvm::Value* monitor) + : _function(function), _monitor(monitor) + { initialize(); } + + private: + void initialize(); + + private: + SharkFunction* _function; + llvm::Value* _monitor; + llvm::Value* _object_addr; + llvm::Value* _displaced_header_addr; + + private: + 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 + { + builder()->CreateLoad(object_addr()); + } + void set_object(llvm::Value* object) const + { + builder()->CreateStore(object, object_addr()); + } + llvm::Value* displaced_header() const + { + 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(llvm::Value* lockee) const; + void release() const; +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ports/hotspot/src/share/vm/shark/sharkRuntime.cpp Tue Aug 12 05:35:18 2008 -0400 @@ -0,0 +1,209 @@ +/* + * 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/_sharkRuntime.cpp.incl" + +using namespace llvm; + +Constant* SharkRuntime::_new_instance; +Constant* SharkRuntime::_resolve_get_put; +Constant* SharkRuntime::_resolve_invoke; + +Constant* SharkRuntime::_dump; +Constant* SharkRuntime::_is_subtype_of; +Constant* SharkRuntime::_should_not_reach_here; +Constant* SharkRuntime::_unimplemented; + +void SharkRuntime::initialize(SharkBuilder* builder) +{ + // VM calls + std::vector<const Type*> params; + params.push_back(SharkType::thread_type()); + params.push_back(SharkType::jobject_type()); + _new_instance = builder->make_function( + (intptr_t) new_instance_C, + FunctionType::get(Type::VoidTy, params, false), + "SharkRuntime__new_instance"); + + params.clear(); + params.push_back(SharkType::thread_type()); + params.push_back(SharkType::cpCacheEntry_type()); + params.push_back(SharkType::jint_type()); + params.push_back(SharkType::jint_type()); + _resolve_get_put = builder->make_function( + (intptr_t) resolve_get_put_C, + FunctionType::get(Type::VoidTy, params, false), + "SharkRuntime__resolve_get_put"); + _resolve_invoke = builder->make_function( + (intptr_t) resolve_invoke_C, + FunctionType::get(Type::VoidTy, params, false), + "SharkRuntime__resolve_invoke"); + + // Non-VM calls + params.clear(); + params.push_back(SharkType::intptr_type()); + params.push_back(SharkType::intptr_type()); + _dump = builder->make_function( + (intptr_t) dump_C, + FunctionType::get(Type::VoidTy, params, false), + "SharkRuntime__dump"); + + params.clear(); + params.push_back(SharkType::oop_type()); + params.push_back(SharkType::oop_type()); + assert(sizeof(bool) == 1, "fix this"); + _is_subtype_of = builder->make_function( + (intptr_t) is_subtype_of_C, + FunctionType::get(Type::Int8Ty, params, false), + "SharkRuntime__is_subtype_of"); + + params.clear(); + params.push_back(SharkType::intptr_type()); + params.push_back(SharkType::jint_type()); + _should_not_reach_here = builder->make_function( + (intptr_t) report_should_not_reach_here, + FunctionType::get(Type::VoidTy, params, false), + "report_should_not_reach_here"); + _unimplemented = builder->make_function( + (intptr_t) report_unimplemented, + FunctionType::get(Type::VoidTy, params, false), + "report_unimplemented"); +} + +JRT_ENTRY(void, SharkRuntime::new_instance_C(JavaThread* thread, + klassOop klass)) +{ + // These checks are cheap to make and support reflective allocation. + int lh = Klass::cast(klass)->layout_helper(); + if (Klass::layout_helper_needs_slow_path(lh) + || !instanceKlass::cast(klass)->is_initialized()) { + KlassHandle kh(THREAD, klass); + kh->check_valid_for_instantiation(false, THREAD); + if (!HAS_PENDING_EXCEPTION) { + instanceKlass::cast(kh())->initialize(THREAD); + } + if (!HAS_PENDING_EXCEPTION) { + klass = kh(); + } else { + klass = NULL; + } + } + + if (klass != NULL) { + // Scavenge and allocate an instance. + oop result = instanceKlass::cast(klass)->allocate_instance(THREAD); + thread->set_vm_result(result); + } +} +JRT_END + +JRT_ENTRY(void, SharkRuntime::resolve_get_put_C(JavaThread* thread, + ConstantPoolCacheEntry* entry, + int bci, + Bytecodes::Code bytecode)) +{ + Unimplemented(); +} +JRT_END + +JRT_ENTRY(void, SharkRuntime::resolve_invoke_C(JavaThread* thread, + ConstantPoolCacheEntry* entry, + int bci, + Bytecodes::Code bytecode)) +{ + // Find the receiver + Handle receiver(thread, NULL); + if (bytecode == Bytecodes::_invokevirtual || bytecode == Bytecodes::_invokeinterface) { + ResourceMark rm(thread); + methodHandle mh(thread, method(thread)); + Bytecode_invoke *call = Bytecode_invoke_at(mh, bci); + symbolHandle signature(thread, call->signature()); + ArgumentSizeComputer asc(signature); + receiver = Handle(thread, (oop) tos_at(thread, asc.size())); + assert( + receiver.is_null() || + (Universe::heap()->is_in_reserved(receiver()) && + Universe::heap()->is_in_reserved(receiver->klass())), "sanity check"); + } + + // Resolve the method + CallInfo info; + { + constantPoolHandle pool(thread, method(thread)->constants()); + JvmtiHideSingleStepping jhss(thread); + LinkResolver::resolve_invoke( + info, receiver, pool, two_byte_index(thread, bci), bytecode, CHECK); + if (JvmtiExport::can_hotswap_or_post_breakpoint()) { + int retry_count = 0; + while (info.resolved_method()->is_old()) { + // It is very unlikely that method is redefined more than 100 + // times in the middle of resolve. If it is looping here more + // than 100 times means then there could be a bug here. + guarantee((retry_count++ < 100), + "Could not resolve to latest version of redefined method"); + // method is redefined in the middle of resolve so re-try. + LinkResolver::resolve_invoke( + info, receiver, pool, two_byte_index(thread, bci), bytecode, CHECK); + } + } + } + + // Update the cache entry if necessary + if (entry->is_resolved(bytecode)) + return; + + if (bytecode == Bytecodes::_invokeinterface) { + Unimplemented(); + } + else { + entry->set_method( + bytecode, + info.resolved_method(), + info.vtable_index()); + } +} +JRT_END + +// Non-VM calls +// Nothing in these must ever GC! + +void SharkRuntime::dump_C(const char *name, intptr_t value) +{ + oop valueOop = (oop) value; + tty->print("%s = ", name); + if (valueOop->is_oop(true)) + valueOop->print_on(tty); + else if (value >= ' ' && value <= '~') + tty->print("'%c' (%d)", value, value); + else + tty->print("%p", value); + tty->print_cr(""); +} + +bool SharkRuntime::is_subtype_of_C(klassOop check_klass, klassOop object_klass) +{ + return object_klass->klass_part()->is_subtype_of(check_klass); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ports/hotspot/src/share/vm/shark/sharkRuntime.hpp Tue Aug 12 05:35:18 2008 -0400 @@ -0,0 +1,112 @@ +/* + * 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 SharkRuntime : public AllStatic { + public: + static void initialize(SharkBuilder* builder); + + // VM calls + private: + static llvm::Constant* _new_instance; + static llvm::Constant* _resolve_get_put; + static llvm::Constant* _resolve_invoke; + + public: + static llvm::Constant* new_instance() + { + return _new_instance; + } + static llvm::Constant* resolve_get_put() + { + return _resolve_get_put; + } + static llvm::Constant* resolve_invoke() + { + return _resolve_invoke; + } + + private: + static void new_instance_C(JavaThread* thread, klassOop klass); + static void resolve_get_put_C(JavaThread* thread, + ConstantPoolCacheEntry* entry, + int bci, + Bytecodes::Code bytecode); + static void resolve_invoke_C(JavaThread* thread, + ConstantPoolCacheEntry* entry, + int bci, + Bytecodes::Code bytecode); + + // Helpers for VM calls + private: + static const SharkFrame* last_frame(JavaThread *thread) + { + return thread->last_frame().zero_sharkframe(); + } + static methodOop method(JavaThread *thread) + { + return last_frame(thread)->method(); + } + static address bcp(JavaThread *thread, int bci) + { + return method(thread)->code_base() + bci; + } + static int two_byte_index(JavaThread *thread, int bci) + { + return Bytes::get_Java_u2(bcp(thread, bci) + 1); + } + static intptr_t tos_at(JavaThread *thread, int offset) + { + return *(thread->zero_stack()->sp() + offset); + } + + // Non-VM calls + private: + static llvm::Constant* _dump; + static llvm::Constant* _is_subtype_of; + static llvm::Constant* _should_not_reach_here; + static llvm::Constant* _unimplemented; + + public: + static llvm::Constant* dump() + { + return _dump; + } + static llvm::Constant* is_subtype_of() + { + return _is_subtype_of; + } + static llvm::Constant* should_not_reach_here() + { + return _should_not_reach_here; + } + static llvm::Constant* unimplemented() + { + return _unimplemented; + } + + private: + static void dump_C(const char *name, intptr_t value); + static bool is_subtype_of_C(klassOop check_klass, klassOop object_klass); +};
--- a/ports/hotspot/src/share/vm/shark/sharkState.cpp Tue Aug 12 09:37:13 2008 +0200 +++ b/ports/hotspot/src/share/vm/shark/sharkState.cpp Tue Aug 12 05:35:18 2008 -0400 @@ -34,18 +34,32 @@ _stack = NEW_RESOURCE_ARRAY(SharkValue*, max_stack()); } -void SharkEntryState::initialize() +void SharkEntryState::initialize(Value* method) { char name[18]; // Method - _method = function()->function()->arg_begin(); + _method = method; // Local variables for (int i = 0; i < max_locals(); i++) { SharkValue *value = NULL; ciType *type = block()->local_type_at_entry(i); - if (type->basic_type() != T_CONFLICT) { + switch (type->basic_type()) { + case ciTypeFlow::StateVector::T_BOTTOM: + case ciTypeFlow::StateVector::T_LONG2: + case ciTypeFlow::StateVector::T_DOUBLE2: + break; + + case ciTypeFlow::StateVector::T_TOP: + Unimplemented(); + break; + + case ciTypeFlow::StateVector::T_NULL: + ShouldNotReachHere(); + break; + + default: if (i < function()->arg_size()) { snprintf(name, sizeof(name), "local_%d_", i); value = SharkValue::create_generic( @@ -83,7 +97,22 @@ for (int i = 0; i < max_locals(); i++) { SharkValue *value = NULL; ciType *type = block()->local_type_at_entry(i); - if (type->basic_type() != T_CONFLICT) { + switch (type->basic_type()) { + case ciTypeFlow::StateVector::T_BOTTOM: + case ciTypeFlow::StateVector::T_LONG2: + case ciTypeFlow::StateVector::T_DOUBLE2: + break; + + case ciTypeFlow::StateVector::T_TOP: + Unimplemented(); + break; + + case ciTypeFlow::StateVector::T_NULL: + // XXX we could do all kinds of clever stuff here + type = ciType::make(T_OBJECT); // XXX what about T_ARRAY? + // fall through + + default: snprintf(name, sizeof(name), "local_%d_", i); value = SharkValue::create_generic( type, builder()->CreatePHI(SharkType::to_stackType(type), name)); @@ -96,9 +125,20 @@ SharkValue *value = NULL; if (i < block()->stack_depth_at_entry()) { ciType *type = block()->stack_type_at_entry(i); - snprintf(name, sizeof(name), "stack_%d_", i); - value = SharkValue::create_generic( - type, builder()->CreatePHI(SharkType::to_stackType(type), name)); + switch (type->basic_type()) { + case ciTypeFlow::StateVector::T_TOP: + case ciTypeFlow::StateVector::T_BOTTOM: + case ciTypeFlow::StateVector::T_LONG2: + case ciTypeFlow::StateVector::T_DOUBLE2: + case ciTypeFlow::StateVector::T_NULL: + Unimplemented(); + break; + + default: + snprintf(name, sizeof(name), "stack_%d_", i); + value = SharkValue::create_generic( + type, builder()->CreatePHI(SharkType::to_stackType(type), name)); + } } _stack[i] = value; } @@ -150,61 +190,93 @@ void SharkTrackingState::decache(ciMethod *callee) { + // Create the OopMap + OopMap *oopmap = new OopMap( + oopmap_slot_munge(function()->oopmap_frame_size()), + oopmap_slot_munge(function()->arg_size())); + // Decache expression stack slots as necessary int stack_slots = stack_depth_in_slots(); for (int i = 0, j = 0; i < stack_slots; i++) { SharkValue *value; bool write; + bool record; + int dst; if (callee && i < callee->arg_size()) { value = pop(); write = true; + record = false; } else { value = stack(j++); - write = value->is_jobject(); + write = record = value->is_jobject(); } if (write) { + dst = i + max_stack() - stack_slots; builder()->CreateStore( value->generic_value(), builder()->CreateBitCast( - builder()->CreateStructGEP( - function()->stack_slots(), - i + max_stack() - stack_slots), + builder()->CreateStructGEP(function()->stack_slots(), dst), PointerType::getUnqual(SharkType::to_stackType(value->type())))); } + if (record) + oopmap->set_oop(slot2reg(function()->stack_slots_offset() + dst)); + if (value->is_two_word()) i++; } + // Record any monitors + for (int i = 0; i < function()->monitor_count(); i++) { + oopmap->set_oop( + slot2reg( + function()->monitors_slots_offset() + + i * frame::interpreter_frame_monitor_size() + + (BasicObjectLock::obj_offset_in_bytes() >> LogBytesPerWord))); + } + // Decache the method pointer builder()->CreateStore(method(), function()->method_slot()); + oopmap->set_oop(slot2reg(function()->method_slot_offset())); + + // Decache the PC + int offset = function()->code_offset(); + builder()->CreateStore( + builder()->CreateAdd( + function()->base_pc(), LLVMValue::intptr_constant(offset)), + function()->pc_slot()); // Decache local variables as necesary for (int i = max_locals() - 1; i >= 0; i--) { SharkValue *value = local(i); if (value && value->is_jobject()) { + int dst = max_locals() - 1 - i; + builder()->CreateStore( value->generic_value(), builder()->CreateBitCast( - builder()->CreateStructGEP( - function()->locals_slots(), - max_locals() - 1 - i), + builder()->CreateStructGEP(function()->locals_slots(), dst), PointerType::getUnqual( SharkType::to_stackType(value->type())))); + + oopmap->set_oop(slot2reg(function()->locals_slots_offset() + dst)); } } - // If we're decaching for a call then trim back the stack - if (callee && stack_slots != max_stack()) { + // Trim back the stack if necessary + if (stack_slots != max_stack()) { function()->CreateStoreZeroStackPointer( builder()->CreatePtrToInt( builder()->CreateStructGEP( function()->stack_slots(), max_stack() - stack_slots), SharkType::intptr_type())); } + + // Install the OopMap + function()->add_gc_map(offset, oopmap); } void SharkTrackingState::cache(ciMethod *callee) @@ -212,7 +284,19 @@ // If we're caching after a call then push a dummy result to set up the stack int result_size = callee ? callee->return_type()->size() : 0; if (result_size) { - push(SharkValue::create_generic(callee->return_type(), NULL)); + ciType *result_type; + switch (callee->return_type()->basic_type()) { + case T_BOOLEAN: + case T_BYTE: + case T_CHAR: + case T_SHORT: + result_type = ciType::make(T_INT); + break; + + default: + result_type = callee->return_type(); + } + push(SharkValue::create_generic(result_type, NULL)); } // Cache expression stack slots as necessary @@ -229,15 +313,14 @@ } if (read) { + int src = i + max_stack() - stack_slots; set_stack( j, SharkValue::create_generic( value->type(), builder()->CreateLoad( builder()->CreateBitCast( - builder()->CreateStructGEP( - function()->stack_slots(), - i + max_stack() - stack_slots), + builder()->CreateStructGEP(function()->stack_slots(), src), PointerType::getUnqual( SharkType::to_stackType(value->basic_type())))))); } @@ -253,25 +336,80 @@ for (int i = max_locals() - 1; i >= 0; i--) { SharkValue *value = local(i); if (value && value->is_jobject()) { + int src = max_locals() - 1 - i; set_local( i, SharkValue::create_generic( value->type(), builder()->CreateLoad( builder()->CreateBitCast( - builder()->CreateStructGEP( - function()->locals_slots(), - max_locals() - 1 - i), + builder()->CreateStructGEP(function()->locals_slots(), src), PointerType::getUnqual( SharkType::to_stackType(value->type())))))); } } - // If we're caching after a call then restore the stack pointer - if (callee && stack_slots != max_stack()) { + // Restore the stack pointer if necessary + if (stack_slots != max_stack()) { function()->CreateStoreZeroStackPointer( builder()->CreatePtrToInt( builder()->CreateStructGEP(function()->stack_slots(), 0), SharkType::intptr_type())); } } + +void SharkTrackingState::merge(SharkState* other, + BasicBlock* other_block, + BasicBlock* this_block) +{ + PHINode *phi; + char name[18]; + + // Method + Value *this_method = this->method(); + Value *other_method = other->method(); + if (this_method != other_method) { + phi = builder()->CreatePHI(SharkType::methodOop_type(), "method"); + phi->addIncoming(this_method, this_block); + phi->addIncoming(other_method, other_block); + _method = phi; + } + + // Local variables + assert(this->max_locals() == other->max_locals(), "should be"); + for (int i = 0; i < max_locals(); i++) { + SharkValue *this_value = this->local(i); + SharkValue *other_value = other->local(i); + if (this_value == other_value) + continue; + assert(this_value != NULL && other_value != NULL, "shouldn't be"); + + ciType *this_type = this_value->type(); + assert(this_type == other_value->type(), "should be"); + + snprintf(name, sizeof(name), "local_%d_", i); + phi = builder()->CreatePHI(SharkType::to_stackType(this_type), name); + phi->addIncoming(this_value->generic_value(), this_block); + phi->addIncoming(other_value->generic_value(), other_block); + _locals[i] = SharkValue::create_generic(this_type, phi); + } + + // Expression stack + assert(this->stack_depth() == other->stack_depth(), "should be"); + for (int i = 0; i < stack_depth(); i++) { + SharkValue *this_value = this->stack(i); + SharkValue *other_value = other->stack(i); + assert(this_value != NULL && other_value != NULL, "shouldn't be"); + if (this_value == other_value) + continue; + + ciType *this_type = this_value->type(); + assert(this_type == other_value->type(), "should be"); + + snprintf(name, sizeof(name), "stack_%d_", i); + phi = builder()->CreatePHI(SharkType::to_stackType(this_type), name); + phi->addIncoming(this_value->generic_value(), this_block); + phi->addIncoming(other_value->generic_value(), other_block); + set_stack(i, SharkValue::create_generic(this_type, phi)); + } +}
--- a/ports/hotspot/src/share/vm/shark/sharkState.hpp Tue Aug 12 09:37:13 2008 +0200 +++ b/ports/hotspot/src/share/vm/shark/sharkState.hpp Tue Aug 12 05:35:18 2008 -0400 @@ -83,6 +83,11 @@ assert(slot >= 0 && slot < stack_depth(), "bad stack slot"); return _sp[-(slot + 1)]; } + void set_stack(int slot, SharkValue* value) + { + assert(slot >= 0 && slot < stack_depth(), "bad stack slot"); + _sp[-(slot + 1)] = value; + } int stack_depth() const { return _sp - _stack; @@ -91,11 +96,11 @@ class SharkEntryState : public SharkState { public: - SharkEntryState(SharkBlock* start_block) - : SharkState(start_block) { initialize(); } + SharkEntryState(llvm::Value* method, SharkBlock* start_block) + : SharkState(start_block) { initialize(method); } private: - void initialize(); + void initialize(llvm::Value* method); }; class SharkPHIState : public SharkState { @@ -156,4 +161,25 @@ public: void cache(ciMethod *callee = NULL); void decache(ciMethod *callee = NULL); + + // Decache helpers + private: + static int oopmap_slot_munge(int x) + { + return x << (LogBytesPerWord - LogBytesPerInt); + } + static VMReg slot2reg(int offset) + { + return VMRegImpl::stack2reg(oopmap_slot_munge(offset)); + } + + // Copy and merge + public: + SharkTrackingState* copy() const + { + return new SharkTrackingState(this); + } + void merge(SharkState* other, + llvm::BasicBlock* other_block, + llvm::BasicBlock* this_block); };
--- a/ports/hotspot/src/share/vm/shark/sharkType.cpp Tue Aug 12 09:37:13 2008 +0200 +++ b/ports/hotspot/src/share/vm/shark/sharkType.cpp Tue Aug 12 05:35:18 2008 -0400 @@ -29,9 +29,13 @@ using namespace llvm; const PointerType* SharkType::_cpCacheEntry_type; -const FunctionType* SharkType::_method_entry_type; +const FunctionType* SharkType::_interpreter_entry_type; +const PointerType* SharkType::_itableOffsetEntry_type; +const PointerType* SharkType::_klass_type; const PointerType* SharkType::_methodOop_type; +const ArrayType* SharkType::_monitor_type; const PointerType* SharkType::_oop_type; +const FunctionType* SharkType::_shark_entry_type; const PointerType* SharkType::_thread_type; const PointerType* SharkType::_zeroStack_type; @@ -44,9 +48,19 @@ _cpCacheEntry_type = PointerType::getUnqual( ArrayType::get(Type::Int8Ty, sizeof(ConstantPoolCacheEntry))); + _itableOffsetEntry_type = PointerType::getUnqual( + ArrayType::get(Type::Int8Ty, itableOffsetEntry::size() * wordSize)); + + _klass_type = PointerType::getUnqual( + ArrayType::get(Type::Int8Ty, sizeof(Klass))); + _methodOop_type = PointerType::getUnqual( ArrayType::get(Type::Int8Ty, sizeof(methodOopDesc))); + _monitor_type = ArrayType::get( + Type::Int8Ty, + frame::interpreter_frame_monitor_size() * wordSize); + _oop_type = PointerType::getUnqual( ArrayType::get(Type::Int8Ty, sizeof(oopDesc))); @@ -59,14 +73,20 @@ std::vector<const Type*> params; params.push_back(methodOop_type()); params.push_back(thread_type()); - _method_entry_type = FunctionType::get(Type::VoidTy, params, false); + _interpreter_entry_type = FunctionType::get(Type::VoidTy, params, false); + + params.clear(); + params.push_back(methodOop_type()); + params.push_back(intptr_type()); + params.push_back(thread_type()); + _shark_entry_type = FunctionType::get(Type::VoidTy, params, false); // Java types a) on the stack and in fields, and b) in arrays for (int i = 0; i < T_CONFLICT + 1; i++) { switch (i) { case T_BOOLEAN: _to_stackType_tab[i] = jint_type(); - //_to_arrayType_tab[i] = jboolean_type(); + _to_arrayType_tab[i] = jboolean_type(); break; case T_BYTE: @@ -79,16 +99,31 @@ _to_arrayType_tab[i] = jchar_type(); break; + case T_SHORT: + _to_stackType_tab[i] = jint_type(); + _to_arrayType_tab[i] = jshort_type(); + break; + case T_INT: _to_stackType_tab[i] = jint_type(); _to_arrayType_tab[i] = jint_type(); break; + case T_LONG: + _to_stackType_tab[i] = jlong_type(); + _to_arrayType_tab[i] = jlong_type(); + break; + case T_FLOAT: _to_stackType_tab[i] = jfloat_type(); _to_arrayType_tab[i] = jfloat_type(); break; + case T_DOUBLE: + _to_stackType_tab[i] = jdouble_type(); + _to_arrayType_tab[i] = jdouble_type(); + break; + case T_OBJECT: case T_ARRAY: _to_stackType_tab[i] = jobject_type();
--- a/ports/hotspot/src/share/vm/shark/sharkType.hpp Tue Aug 12 09:37:13 2008 +0200 +++ b/ports/hotspot/src/share/vm/shark/sharkType.hpp Tue Aug 12 05:35:18 2008 -0400 @@ -38,9 +38,13 @@ // VM types private: static const llvm::PointerType* _cpCacheEntry_type; - static const llvm::FunctionType* _method_entry_type; + static const llvm::FunctionType* _interpreter_entry_type; + static const llvm::PointerType* _itableOffsetEntry_type; + static const llvm::PointerType* _klass_type; static const llvm::PointerType* _methodOop_type; + static const llvm::ArrayType* _monitor_type; static const llvm::PointerType* _oop_type; + static const llvm::FunctionType* _shark_entry_type; static const llvm::PointerType* _thread_type; static const llvm::PointerType* _zeroStack_type; @@ -49,18 +53,34 @@ { return _cpCacheEntry_type; } - static const llvm::FunctionType* method_entry_type() + static const llvm::FunctionType* interpreter_entry_type() + { + return _interpreter_entry_type; + } + static const llvm::PointerType* itableOffsetEntry_type() { - return _method_entry_type; + return _itableOffsetEntry_type; + } + static const llvm::PointerType* klass_type() + { + return _klass_type; } static const llvm::PointerType* methodOop_type() { return _methodOop_type; } + static const llvm::ArrayType* monitor_type() + { + return _monitor_type; + } static const llvm::PointerType* oop_type() { return _oop_type; } + static const llvm::FunctionType* shark_entry_type() + { + return _shark_entry_type; + } static const llvm::PointerType* thread_type() { return _thread_type; @@ -72,6 +92,10 @@ // Java types public: + static const llvm::IntegerType* jboolean_type() + { + return llvm::Type::Int8Ty; + } static const llvm::IntegerType* jbyte_type() { return llvm::Type::Int8Ty;
--- a/ports/hotspot/src/share/vm/shark/sharkValue.hpp Tue Aug 12 09:37:13 2008 +0200 +++ b/ports/hotspot/src/share/vm/shark/sharkValue.hpp Tue Aug 12 05:35:18 2008 -0400 @@ -33,6 +33,10 @@ { return llvm::ConstantInt::get(SharkType::jint_type(), value, true); } + static llvm::ConstantInt* jlong_constant(jlong value) + { + return llvm::ConstantInt::get(SharkType::jlong_type(), value, true); + } static llvm::ConstantPointerNull* null() { return llvm::ConstantPointerNull::get(SharkType::jobject_type()); @@ -85,6 +89,10 @@ { return llvm_value()->getType() == SharkType::jint_type(); } + bool is_jlong() const + { + return llvm_value()->getType() == SharkType::jlong_type(); + } bool is_jobject() const { return llvm_value()->getType() == SharkType::jobject_type(); @@ -99,13 +107,28 @@ static SharkValue* create_jint(llvm::Value* value) { assert(value->getType() == SharkType::jint_type(), "should be"); - return new SharkValue(ciType::make(T_INT), value); + return create_generic(ciType::make(T_INT), value); } llvm::Value* jint_value() const { assert(is_jint(), "should be"); return llvm_value(); } + static SharkValue* create_jlong(llvm::Value* value) + { + assert(value->getType() == SharkType::jlong_type(), "should be"); + return create_generic(ciType::make(T_LONG), value); + } + llvm::Value* jlong_value() const + { + assert(is_jlong(), "should be"); + return llvm_value(); + } + static SharkValue* create_jobject(llvm::Value* value) + { + assert(value->getType() == SharkType::jobject_type(), "should be"); + return create_generic(ciType::make(T_OBJECT), value); + } llvm::Value* jobject_value() const { assert(is_jobject(), "should be"); @@ -123,10 +146,22 @@ switch (value.basic_type()) { case T_BOOLEAN: return SharkValue::jint_constant(value.as_boolean()); - + + case T_BYTE: + return SharkValue::jint_constant(value.as_byte()); + + case T_CHAR: + return SharkValue::jint_constant(value.as_char()); + + case T_SHORT: + return SharkValue::jint_constant(value.as_short()); + case T_INT: return SharkValue::jint_constant(value.as_int()); + case T_LONG: + return SharkValue::jlong_constant(value.as_long()); + case T_OBJECT: case T_ARRAY: return NULL; @@ -159,6 +194,10 @@ { return create_jint(LLVMValue::jint_constant(value)); } + static SharkValue* jlong_constant(jlong value) + { + return create_jlong(LLVMValue::jlong_constant(value)); + } static SharkValue* null() { return create_generic(ciType::make(T_OBJECT), LLVMValue::null());
--- a/ports/hotspot/src/share/vm/shark/shark_globals.hpp Tue Aug 12 09:37:13 2008 +0200 +++ b/ports/hotspot/src/share/vm/shark/shark_globals.hpp Tue Aug 12 05:35:18 2008 -0400 @@ -33,19 +33,25 @@ "Maximum number of nodes") \ \ /* compiler debugging */ \ - notproduct(uintx, SharkStartAt, 0, \ - "First method to consider when using Shark") \ + develop(uintx, SharkStartAt, 0, \ + "First method to consider when using Shark") \ \ - notproduct(uintx, SharkStopAfter, max_uintx, \ - "Last method to consider when using Shark") \ + develop(uintx, SharkStopAfter, max_uintx, \ + "Last method to consider when using Shark") \ + \ + develop(ccstr, SharkOnlyCompile, NULL, \ + "Only compile the specified method") \ \ - notproduct(uintx, SharkDumpModuleAfter, max_uintx, \ - "Dump the LLVM bitcode after compiling this number of methods") \ + develop(ccstr, SharkPrintTypeflowOf, NULL, \ + "Print the typeflow of the specified method") \ + \ + develop(ccstr, SharkPrintBitcodeOf, NULL, \ + "Print the LLVM bitcode of the specified method") \ \ - notproduct(uintx, SharkPrintTypeflowAfter, max_uintx, \ - "Print the typeflow after compiling this number of methods") \ + develop(bool, SharkTraceBytecodes, false, \ + "Trace bytecode compilation") \ \ - notproduct(bool, SharkTraceBytecodes, false, \ - "Trace bytecode compilation") \ + develop(bool, SharkTraceInstalls, false, \ + "Trace method installation") \ SHARK_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_NOTPRODUCT_FLAG)