Mercurial > hg > release > icedtea6-1.3
changeset 1026:4f4d268762d7
2008-08-20 Gary Benson <gbenson@redhat.com>
* patches/icedtea-shark.patch: Updated to latest Shark.
* ports/hotspot/src/cpu/zero/vm/assembler_zero.cpp: Likewise.
* ports/hotspot/src/cpu/zero/vm/assembler_zero.hpp: Likewise.
* ports/hotspot/src/cpu/zero/vm/cppInterpreterGenerator_zero.hpp:
Likewise.
* ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp: Likewise.
* ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp: Likewise.
* ports/hotspot/src/cpu/zero/vm/interpreter_zero.cpp: Likewise.
* ports/hotspot/src/cpu/zero/vm/interpreter_zero.hpp: Likewise.
* ports/hotspot/src/share/vm/includeDB_shark: 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/sharkConstantPool.cpp: 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/sharkMonitor.hpp: Likewise.
* ports/hotspot/src/share/vm/shark/sharkRuntime.cpp: Likewise.
* ports/hotspot/src/share/vm/shark/sharkRuntime.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/cpu/zero/vm/entry_zero.hpp: New file.
* ports/hotspot/src/share/vm/shark/sharkEntry.cpp: Likewise.
* ports/hotspot/src/share/vm/shark/sharkEntry.hpp: Likewise.
* ports/hotspot/src/share/vm/shark/sharkMethod.hpp: Removed.
line wrap: on
line diff
--- a/ChangeLog Wed Aug 20 04:12:41 2008 -0400 +++ b/ChangeLog Wed Aug 20 04:24:45 2008 -0400 @@ -1,3 +1,37 @@ +2008-08-20 Gary Benson <gbenson@redhat.com> + + * patches/icedtea-shark.patch: Updated to latest Shark. + * ports/hotspot/src/cpu/zero/vm/assembler_zero.cpp: Likewise. + * ports/hotspot/src/cpu/zero/vm/assembler_zero.hpp: Likewise. + * ports/hotspot/src/cpu/zero/vm/cppInterpreterGenerator_zero.hpp: + Likewise. + * ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp: Likewise. + * ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp: Likewise. + * ports/hotspot/src/cpu/zero/vm/interpreter_zero.cpp: Likewise. + * ports/hotspot/src/cpu/zero/vm/interpreter_zero.hpp: Likewise. + * ports/hotspot/src/share/vm/includeDB_shark: 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/sharkConstantPool.cpp: 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/sharkMonitor.hpp: Likewise. + * ports/hotspot/src/share/vm/shark/sharkRuntime.cpp: Likewise. + * ports/hotspot/src/share/vm/shark/sharkRuntime.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/cpu/zero/vm/entry_zero.hpp: New file. + * ports/hotspot/src/share/vm/shark/sharkEntry.cpp: Likewise. + * ports/hotspot/src/share/vm/shark/sharkEntry.hpp: Likewise. + * ports/hotspot/src/share/vm/shark/sharkMethod.hpp: Removed. + 2008-08-20 Gary Benson <gbenson@redhat.com> * ports/hotspot/src/cpu/zero/vm/bytecodeInterpreter_zero.inline.hpp
--- a/patches/icedtea-shark.patch Wed Aug 20 04:12:41 2008 -0400 +++ b/patches/icedtea-shark.patch Wed Aug 20 04:24:45 2008 -0400 @@ -181,7 +181,7 @@ OrderAccess::storestore(); +#ifdef SHARK -+ mh->_from_interpreted_entry = SharkMethod::mark(code->instructions_begin()); ++ mh->_from_interpreted_entry = code->instructions_begin(); +#else mh->_from_compiled_entry = code->verified_entry_point(); OrderAccess::storestore();
--- a/ports/hotspot/src/cpu/zero/vm/assembler_zero.cpp Wed Aug 20 04:12:41 2008 -0400 +++ b/ports/hotspot/src/cpu/zero/vm/assembler_zero.cpp Wed Aug 20 04:24:45 2008 -0400 @@ -28,11 +28,7 @@ int AbstractAssembler::code_fill_byte() { -#ifdef SHARK return 0; -#else - Unimplemented(); -#endif // SHARK } void Assembler::pd_patch_instruction(address branch, address target) @@ -47,27 +43,26 @@ } #endif // PRODUCT +void MacroAssembler::align(int modulus) +{ + while (offset() % modulus != 0) + emit_byte(AbstractAssembler::code_fill_byte()); +} + void MacroAssembler::bang_stack_with_offset(int offset) { Unimplemented(); } -void MacroAssembler::align(int modulus) +void MacroAssembler::advance(int bytes) { - // Loads of places assert that code is generated, - // and I'm guessing plenty of places assume that - // *something* was generated. This is a sneaky - // place to emit such a something. - emit_byte(0x23); - - // Probably ought to align it too, while we're here. - while (offset() % modulus != 0) - emit_byte(0x23); + _code_pos += bytes; + sync(); } static void _UnimplementedStub() { - report_unimplemented("fake-generated-code", 23); + report_unimplemented(__FILE__, __LINE__); } address UnimplementedStub()
--- a/ports/hotspot/src/cpu/zero/vm/assembler_zero.hpp Wed Aug 20 04:12:41 2008 -0400 +++ b/ports/hotspot/src/cpu/zero/vm/assembler_zero.hpp Wed Aug 20 04:24:45 2008 -0400 @@ -23,28 +23,21 @@ * */ -// The definitions needed for zero assembly code generation. - -// The zero Assembler: Pure assembler doing NO optimizations on -// the instruction level; i.e., what you write is what you get. -// The Assembler is generating code into a CodeBuffer. +// In normal, CPU-specific ports of HotSpot these two classes are used +// for generating assembly language. We don't do any of this in zero, +// of course, but we do sneak entry points around in CodeBuffers so we +// generate those here. class Assembler : public AbstractAssembler { public: Assembler(CodeBuffer* code) : AbstractAssembler(code) {} - // Function to fix up forward branches void pd_patch_instruction(address branch, address target); #ifndef PRODUCT static void pd_print_patched_instruction(address branch); #endif // PRODUCT }; -// MacroAssembler extends Assembler by frequently used macros. -// -// Instructions for which a 'better' code sequence exists depending -// on arguments should also go in here. - class MacroAssembler : public Assembler { public: MacroAssembler(CodeBuffer* code) : Assembler(code) {} @@ -52,17 +45,8 @@ 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 + void advance(int bytes); }; #ifdef ASSERT @@ -79,4 +63,5 @@ // Nothing to do with the assembler (or lack of), // just a real convenient place to include these. #include <ffi.h> +#include <entry_zero.hpp> #include <stack_zero.hpp>
--- a/ports/hotspot/src/cpu/zero/vm/cppInterpreterGenerator_zero.hpp Wed Aug 20 04:12:41 2008 -0400 +++ b/ports/hotspot/src/cpu/zero/vm/cppInterpreterGenerator_zero.hpp Wed Aug 20 04:24:45 2008 -0400 @@ -0,0 +1,39 @@ +/* + * Copyright 2003-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. + * + */ + + protected: + MacroAssembler* assembler() const + { + return _masm; + } + + protected: + address generate_entry(ZeroEntry::method_entry_t entry_point) + { + ZeroEntry *entry = (ZeroEntry *) assembler()->pc(); + assembler()->advance(sizeof(ZeroEntry)); + entry->set_entry_point(entry_point); + return (address) entry; + }
--- a/ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Wed Aug 20 04:12:41 2008 -0400 +++ b/ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Wed Aug 20 04:24:45 2008 -0400 @@ -37,7 +37,7 @@ thread->reset_last_Java_frame(); \ fixup_after_potential_safepoint() -void CppInterpreter::normal_entry(methodOop method, TRAPS) +void CppInterpreter::normal_entry(methodOop method, intptr_t UNUSED, TRAPS) { JavaThread *thread = (JavaThread *) THREAD; ZeroStack *stack = thread->zero_stack(); @@ -146,7 +146,7 @@ stack->push(result[-i]); } -void CppInterpreter::native_entry(methodOop method, TRAPS) +void CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) { JavaThread *thread = (JavaThread *) THREAD; ZeroStack *stack = thread->zero_stack(); @@ -374,7 +374,7 @@ } } -void CppInterpreter::accessor_entry(methodOop method, TRAPS) +void CppInterpreter::accessor_entry(methodOop method, intptr_t UNUSED, TRAPS) { JavaThread *thread = (JavaThread *) THREAD; ZeroStack *stack = thread->zero_stack(); @@ -382,7 +382,7 @@ // Drop into the slow path if we need a safepoint check if (SafepointSynchronize::do_call_back()) { - normal_entry(method, THREAD); + normal_entry(method, 0, THREAD); return; } @@ -390,7 +390,7 @@ // if we have a NullPointerException oop object = LOCALS_OBJECT(0); if (object == NULL) { - normal_entry(method, THREAD); + normal_entry(method, 0, THREAD); return; } @@ -413,7 +413,7 @@ constantPoolCacheOop cache = method->constants()->cache(); ConstantPoolCacheEntry* entry = cache->entry_at(index); if (!entry->is_resolved(Bytecodes::_getfield)) { - normal_entry(method, THREAD); + normal_entry(method, 0, THREAD); return; } @@ -505,14 +505,14 @@ } } -void CppInterpreter::empty_entry(methodOop method, TRAPS) +void CppInterpreter::empty_entry(methodOop method, intptr_t UNUSED, TRAPS) { JavaThread *thread = (JavaThread *) THREAD; ZeroStack *stack = thread->zero_stack(); // Drop into the slow path if we need a safepoint check if (SafepointSynchronize::do_call_back()) { - normal_entry(method, THREAD); + normal_entry(method, 0, THREAD); return; } @@ -609,7 +609,7 @@ if (!UseFastEmptyMethods) return NULL; - return (address) CppInterpreter::empty_entry; + return generate_entry(CppInterpreter::empty_entry); } address InterpreterGenerator::generate_accessor_entry() @@ -617,19 +617,21 @@ if (!UseFastAccessorMethods) return NULL; - return (address) CppInterpreter::accessor_entry; + return generate_entry(CppInterpreter::accessor_entry); } address InterpreterGenerator::generate_native_entry(bool synchronized) { assert (synchronized == false, "should be"); - return (address) CppInterpreter::native_entry; + + return generate_entry(CppInterpreter::native_entry); } address InterpreterGenerator::generate_normal_entry(bool synchronized) { assert (synchronized == false, "should be"); - return (address) CppInterpreter::normal_entry; + + return generate_entry(CppInterpreter::normal_entry); } address AbstractInterpreterGenerator::generate_method_entry( @@ -679,10 +681,6 @@ if (entry_point == NULL) entry_point = ((InterpreterGenerator*)this)->generate_normal_entry(false); -#ifdef SHARK - assert(!SharkMethod::is_shark_method(entry_point), "shouldn't be"); -#endif // SHARK - return entry_point; } @@ -732,21 +730,25 @@ address CppInterpreterGenerator::generate_result_handler_for( BasicType type) { + assembler()->advance(1); return ShouldNotReachHereStub(); } address CppInterpreterGenerator::generate_tosca_to_stack_converter( BasicType type) { + assembler()->advance(1); return ShouldNotReachHereStub(); } address CppInterpreterGenerator::generate_stack_to_stack_converter( BasicType type) { + assembler()->advance(1); return ShouldNotReachHereStub(); } address CppInterpreterGenerator::generate_stack_to_native_abi_converter( BasicType type) { + assembler()->advance(1); return ShouldNotReachHereStub(); }
--- a/ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp Wed Aug 20 04:12:41 2008 -0400 +++ b/ports/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp Wed Aug 20 04:24:45 2008 -0400 @@ -25,13 +25,12 @@ protected: - // Size of interpreter code. We don't have generated code so - // this should be zero, but that hits all kinds of assertions + // Size of interpreter code const static int InterpreterCodeSize = 6 * K; private: // Method entries - static void normal_entry(methodOop method, TRAPS); - static void native_entry(methodOop method, TRAPS); - static void accessor_entry(methodOop method, TRAPS); - static void empty_entry(methodOop method, TRAPS); + static void normal_entry(methodOop method, intptr_t UNUSED, TRAPS); + static void native_entry(methodOop method, intptr_t UNUSED, TRAPS); + static void accessor_entry(methodOop method, intptr_t UNUSED, TRAPS); + static void empty_entry(methodOop method, intptr_t UNUSED, TRAPS);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ports/hotspot/src/cpu/zero/vm/entry_zero.hpp Wed Aug 20 04:24:45 2008 -0400 @@ -0,0 +1,60 @@ +/* + * Copyright 2003-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 ZeroEntry { + public: + ZeroEntry() + { + ShouldNotCallThis(); + } + + public: + typedef void (*method_entry_t)(methodOop method, intptr_t base_pc, TRAPS); + + private: + method_entry_t _entry_point; + + public: + method_entry_t entry_point() const + { + return _entry_point; + } + void set_entry_point(method_entry_t entry_point) + { + _entry_point = entry_point; + } + + public: + void invoke(methodOop method, TRAPS) const + { + entry_point()(method, (intptr_t) this, THREAD); + } + + public: + static ByteSize entry_point_offset() + { + return byte_offset_of(ZeroEntry, _entry_point); + } +};
--- a/ports/hotspot/src/cpu/zero/vm/interpreter_zero.cpp Wed Aug 20 04:12:41 2008 -0400 +++ b/ports/hotspot/src/cpu/zero/vm/interpreter_zero.cpp Wed Aug 20 04:24:45 2008 -0400 @@ -28,6 +28,7 @@ address AbstractInterpreterGenerator::generate_slow_signature_handler() { + _masm->advance(1); return (address) InterpreterRuntime::slow_signature_handler; }
--- a/ports/hotspot/src/cpu/zero/vm/interpreter_zero.hpp Wed Aug 20 04:12:41 2008 -0400 +++ b/ports/hotspot/src/cpu/zero/vm/interpreter_zero.hpp Wed Aug 20 04:24:45 2008 -0400 @@ -24,17 +24,9 @@ */ 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); + ((ZeroEntry *) entry_point)->invoke(method, THREAD); } public:
--- a/ports/hotspot/src/share/vm/includeDB_shark Wed Aug 20 04:12:41 2008 -0400 +++ b/ports/hotspot/src/share/vm/includeDB_shark Wed Aug 20 04:24:45 2008 -0400 @@ -56,9 +56,7 @@ globals.cpp shark_globals.hpp -interpreter.hpp sharkMethod.hpp - -methodOop.cpp sharkMethod.hpp +methodOop.cpp sharkEntry.hpp shark_globals.cpp shark_globals.hpp @@ -126,6 +124,7 @@ sharkCompiler.cpp oopRecorder.hpp sharkCompiler.cpp shark_globals.hpp sharkCompiler.cpp sharkCompiler.hpp +sharkCompiler.cpp sharkEntry.hpp sharkCompiler.cpp sharkFunction.hpp sharkCompiler.cpp sharkRuntime.hpp @@ -153,12 +152,18 @@ sharkConstantPool.hpp sharkBlock.hpp sharkConstantPool.hpp sharkBuilder.hpp +sharkEntry.cpp sharkEntry.hpp + +sharkEntry.hpp llvmHeaders.hpp + sharkFunction.cpp allocation.hpp sharkFunction.cpp ciTypeFlow.hpp sharkFunction.cpp debug.hpp sharkFunction.cpp llvmHeaders.hpp +sharkFunction.cpp shark_globals.hpp sharkFunction.cpp sharkBlock.hpp sharkFunction.cpp sharkBuilder.hpp +sharkFunction.cpp sharkEntry.hpp sharkFunction.cpp sharkFunction.hpp sharkFunction.cpp sharkMonitor.hpp sharkFunction.cpp sharkState.inline.hpp @@ -170,8 +175,6 @@ sharkFunction.hpp llvmHeaders.hpp sharkFunction.hpp sharkBuilder.hpp -sharkMethod.hpp llvmHeaders.hpp - sharkMonitor.cpp sharkMonitor.hpp sharkMonitor.cpp llvmHeaders.hpp @@ -213,7 +216,7 @@ sharkType.cpp globalDefinitions.hpp sharkType.cpp llvmHeaders.hpp sharkType.cpp oop.hpp -sharkType.cpp sharkMethod.hpp +sharkType.cpp sharkEntry.hpp sharkType.cpp sharkType.hpp sharkType.hpp allocation.hpp
--- a/ports/hotspot/src/share/vm/shark/sharkBlock.cpp Wed Aug 20 04:12:41 2008 -0400 +++ b/ports/hotspot/src/share/vm/shark/sharkBlock.cpp Wed Aug 20 04:24:45 2008 -0400 @@ -71,6 +71,10 @@ if(UseLoopSafepoints) { int len; + // XXX if a lcmp is followed by an if_?? then C2 maybe-inserts + // the safepoint before the lcmp rather than before the if. + // Maybe we should do this too. See parse2.cpp for details. + switch (bc()) { case Bytecodes::_goto: case Bytecodes::_goto_w: @@ -112,6 +116,10 @@ case Bytecodes::_nop: break; + case Bytecodes::_aconst_null: + push(SharkValue::null()); + break; + case Bytecodes::_iconst_m1: push(SharkValue::jint_constant(-1)); break; @@ -134,6 +142,30 @@ push(SharkValue::jint_constant(5)); break; + case Bytecodes::_lconst_0: + push(SharkValue::jlong_constant(0)); + break; + case Bytecodes::_lconst_1: + push(SharkValue::jlong_constant(1)); + break; + + case Bytecodes::_fconst_0: + push(SharkValue::jfloat_constant(0)); + break; + case Bytecodes::_fconst_1: + push(SharkValue::jfloat_constant(1)); + break; + case Bytecodes::_fconst_2: + push(SharkValue::jfloat_constant(2)); + break; + + case Bytecodes::_dconst_0: + push(SharkValue::jdouble_constant(0)); + break; + case Bytecodes::_dconst_1: + push(SharkValue::jdouble_constant(1)); + break; + case Bytecodes::_bipush: push(SharkValue::jint_constant(iter()->get_byte())); break; @@ -141,10 +173,6 @@ push(SharkValue::jint_constant(iter()->get_short())); break; - case Bytecodes::_aconst_null: - push(SharkValue::null()); - break; - case Bytecodes::_ldc: case Bytecodes::_ldc_w: case Bytecodes::_ldc2_w: @@ -152,72 +180,41 @@ break; case Bytecodes::_iload_0: + case Bytecodes::_lload_0: case Bytecodes::_fload_0: + case Bytecodes::_dload_0: case Bytecodes::_aload_0: push(local(0)); break; case Bytecodes::_iload_1: + case Bytecodes::_lload_1: case Bytecodes::_fload_1: + case Bytecodes::_dload_1: case Bytecodes::_aload_1: push(local(1)); break; case Bytecodes::_iload_2: + case Bytecodes::_lload_2: case Bytecodes::_fload_2: + case Bytecodes::_dload_2: case Bytecodes::_aload_2: push(local(2)); break; case Bytecodes::_iload_3: + case Bytecodes::_lload_3: case Bytecodes::_fload_3: + case Bytecodes::_dload_3: case Bytecodes::_aload_3: push(local(3)); break; case Bytecodes::_iload: + case Bytecodes::_lload: case Bytecodes::_fload: + case Bytecodes::_dload: case Bytecodes::_aload: push(local(iter()->get_index())); break; - case Bytecodes::_istore_0: - case Bytecodes::_fstore_0: - case Bytecodes::_astore_0: - set_local(0, pop()); - break; - case Bytecodes::_istore_1: - case Bytecodes::_fstore_1: - case Bytecodes::_astore_1: - set_local(1, pop()); - break; - case Bytecodes::_istore_2: - case Bytecodes::_fstore_2: - case Bytecodes::_astore_2: - set_local(2, pop()); - break; - case Bytecodes::_istore_3: - case Bytecodes::_fstore_3: - case Bytecodes::_astore_3: - set_local(3, pop()); - break; - case Bytecodes::_istore: - case Bytecodes::_fstore: - case Bytecodes::_astore: - set_local(iter()->get_index(), pop()); - break; - - case Bytecodes::_pop: - assert(stack(0)->is_one_word(), "should be"); - pop(); - break; - case Bytecodes::_dup: - assert(stack(0)->is_one_word(), "should be"); - a = pop(); - push(a); - push(a); - break; - - case Bytecodes::_arraylength: - do_arraylength(); - break; - case Bytecodes::_baload: do_aload(T_BYTE); break; @@ -243,6 +240,42 @@ do_aload(T_OBJECT); break; + case Bytecodes::_istore_0: + case Bytecodes::_lstore_0: + case Bytecodes::_fstore_0: + case Bytecodes::_dstore_0: + case Bytecodes::_astore_0: + set_local(0, pop()); + break; + case Bytecodes::_istore_1: + case Bytecodes::_lstore_1: + case Bytecodes::_fstore_1: + case Bytecodes::_dstore_1: + case Bytecodes::_astore_1: + set_local(1, pop()); + break; + case Bytecodes::_istore_2: + case Bytecodes::_lstore_2: + case Bytecodes::_fstore_2: + case Bytecodes::_dstore_2: + case Bytecodes::_astore_2: + set_local(2, pop()); + break; + case Bytecodes::_istore_3: + case Bytecodes::_lstore_3: + case Bytecodes::_fstore_3: + case Bytecodes::_dstore_3: + case Bytecodes::_astore_3: + set_local(3, pop()); + break; + case Bytecodes::_istore: + case Bytecodes::_lstore: + case Bytecodes::_fstore: + case Bytecodes::_dstore: + case Bytecodes::_astore: + set_local(iter()->get_index(), pop()); + break; + case Bytecodes::_bastore: do_astore(T_BYTE); break; @@ -268,6 +301,137 @@ do_astore(T_OBJECT); break; + case Bytecodes::_pop: + pop_and_assert_one_word(); + break; + case Bytecodes::_pop2: + if (stack(0)->is_two_word()) { + pop_and_assert_two_word(); + } + else { + pop_and_assert_one_word(); + pop_and_assert_one_word(); + } + break; + case Bytecodes::_swap: + a = pop_and_assert_one_word(); + b = pop_and_assert_one_word(); + push(a); + push(b); + break; + case Bytecodes::_dup: + a = pop_and_assert_one_word(); + push(a); + push(a); + break; + case Bytecodes::_dup_x1: + a = pop_and_assert_one_word(); + b = pop_and_assert_one_word(); + push(a); + push(b); + push(a); + break; + case Bytecodes::_dup_x2: + if (stack(1)->is_two_word()) { + a = pop_and_assert_one_word(); + b = pop_and_assert_two_word(); + push(a); + push(b); + push(a); + } + else { + a = pop_and_assert_one_word(); + b = pop_and_assert_one_word(); + c = pop_and_assert_one_word(); + push(a); + push(c); + push(b); + push(a); + } + break; + case Bytecodes::_dup2: + if (stack(0)->is_two_word()) { + a = pop_and_assert_two_word(); + push(a); + push(a); + } + else { + a = pop_and_assert_one_word(); + b = pop_and_assert_one_word(); + push(b); + push(a); + push(b); + push(a); + } + break; + case Bytecodes::_dup2_x1: + if (stack(0)->is_two_word()) { + a = pop_and_assert_two_word(); + b = pop_and_assert_one_word(); + push(a); + push(b); + push(a); + } + else { + a = pop_and_assert_one_word(); + b = pop_and_assert_one_word(); + c = pop_and_assert_one_word(); + push(b); + push(a); + push(c); + push(b); + push(a); + } + break; + case Bytecodes::_dup2_x2: + if (stack(0)->is_one_word()) { + if (stack(2)->is_one_word()) { + a = pop_and_assert_one_word(); + b = pop_and_assert_one_word(); + c = pop_and_assert_one_word(); + d = pop_and_assert_one_word(); + push(b); + push(a); + push(d); + push(c); + push(b); + push(a); + } + else { + a = pop_and_assert_one_word(); + b = pop_and_assert_one_word(); + c = pop_and_assert_two_word(); + push(b); + push(a); + push(c); + push(b); + push(a); + } + } + else { + if (stack(1)->is_one_word()) { + a = pop_and_assert_two_word(); + b = pop_and_assert_one_word(); + c = pop_and_assert_one_word(); + push(a); + push(c); + push(b); + push(a); + } + else { + a = pop_and_assert_two_word(); + b = pop_and_assert_two_word(); + push(a); + push(b); + push(a); + } + } + break; + + case Bytecodes::_arraylength: + do_arraylength(); + break; + case Bytecodes::_getfield: do_getfield(); break; @@ -281,28 +445,52 @@ do_putstatic(); break; + case Bytecodes::_iadd: + b = pop(); + a = pop(); + push(SharkValue::create_jint( + builder()->CreateAdd(a->jint_value(), b->jint_value()))); + break; + case Bytecodes::_isub: + b = pop(); + a = pop(); + push(SharkValue::create_jint( + builder()->CreateSub(a->jint_value(), b->jint_value()))); + break; case Bytecodes::_imul: b = pop(); a = pop(); push(SharkValue::create_jint( builder()->CreateMul(a->jint_value(), b->jint_value()))); break; - case Bytecodes::_iadd: - b = pop(); - a = pop(); - push(SharkValue::create_jint( - builder()->CreateAdd(a->jint_value(), b->jint_value()))); + case Bytecodes::_idiv: + do_idiv(); + break; + case Bytecodes::_irem: + do_irem(); break; case Bytecodes::_ineg: a = pop(); push(SharkValue::create_jint( builder()->CreateNeg(a->jint_value()))); break; - case Bytecodes::_isub: + case Bytecodes::_ishl: b = pop(); a = pop(); push(SharkValue::create_jint( - builder()->CreateSub(a->jint_value(), b->jint_value()))); + builder()->CreateShl(a->jint_value(), b->jint_value()))); + break; + case Bytecodes::_ishr: + b = pop(); + a = pop(); + push(SharkValue::create_jint( + builder()->CreateAShr(a->jint_value(), b->jint_value()))); + break; + case Bytecodes::_iushr: + b = pop(); + a = pop(); + push(SharkValue::create_jint( + builder()->CreateLShr(a->jint_value(), b->jint_value()))); break; case Bytecodes::_iand: b = pop(); @@ -322,39 +510,152 @@ push(SharkValue::create_jint( builder()->CreateXor(a->jint_value(), b->jint_value()))); break; - case Bytecodes::_ishl: + + case Bytecodes::_ladd: + b = pop(); + a = pop(); + push(SharkValue::create_jlong( + builder()->CreateAdd(a->jlong_value(), b->jlong_value()))); + break; + case Bytecodes::_lsub: + b = pop(); + a = pop(); + push(SharkValue::create_jlong( + builder()->CreateSub(a->jlong_value(), b->jlong_value()))); + break; + case Bytecodes::_lmul: + b = pop(); + a = pop(); + push(SharkValue::create_jlong( + builder()->CreateMul(a->jlong_value(), b->jlong_value()))); + break; + case Bytecodes::_ldiv: + do_ldiv(); + break; + case Bytecodes::_lrem: + do_lrem(); + break; + case Bytecodes::_lneg: + a = pop(); + push(SharkValue::create_jlong( + builder()->CreateNeg(a->jlong_value()))); + break; + case Bytecodes::_lshl: b = pop(); a = pop(); - push(SharkValue::create_jint( - builder()->CreateShl(a->jint_value(), b->jint_value()))); + push(SharkValue::create_jlong( + builder()->CreateShl( + a->jlong_value(), + builder()->CreateIntCast( + b->jint_value(), SharkType::jlong_type(), true)))); break; - case Bytecodes::_ishr: + case Bytecodes::_lshr: + b = pop(); + a = pop(); + push(SharkValue::create_jlong( + builder()->CreateAShr( + a->jlong_value(), + builder()->CreateIntCast( + b->jint_value(), SharkType::jlong_type(), true)))); + break; + case Bytecodes::_lushr: b = pop(); a = pop(); - push(SharkValue::create_jint( - builder()->CreateAShr(a->jint_value(), b->jint_value()))); + push(SharkValue::create_jlong( + builder()->CreateLShr( + a->jlong_value(), + builder()->CreateIntCast( + b->jint_value(), SharkType::jlong_type(), true)))); break; - case Bytecodes::_iushr: + case Bytecodes::_land: + b = pop(); + a = pop(); + push(SharkValue::create_jlong( + builder()->CreateAnd(a->jlong_value(), b->jlong_value()))); + break; + case Bytecodes::_lor: + b = pop(); + a = pop(); + push(SharkValue::create_jlong( + builder()->CreateOr(a->jlong_value(), b->jlong_value()))); + break; + case Bytecodes::_lxor: b = pop(); a = pop(); - push(SharkValue::create_jint( - builder()->CreateLShr(a->jint_value(), b->jint_value()))); + push(SharkValue::create_jlong( + builder()->CreateXor(a->jlong_value(), b->jlong_value()))); break; - case Bytecodes::_i2b: - push(SharkValue::create_jint( - builder()->CreateAShr( - builder()->CreateShl( - pop()->jint_value(), - LLVMValue::jint_constant(24)), - LLVMValue::jint_constant(24)))); + case Bytecodes::_fadd: + b = pop(); + a = pop(); + push(SharkValue::create_jfloat( + builder()->CreateAdd(a->jfloat_value(), b->jfloat_value()))); + break; + case Bytecodes::_fsub: + b = pop(); + a = pop(); + push(SharkValue::create_jfloat( + builder()->CreateSub(a->jfloat_value(), b->jfloat_value()))); + break; + case Bytecodes::_fmul: + b = pop(); + a = pop(); + push(SharkValue::create_jfloat( + builder()->CreateMul(a->jfloat_value(), b->jfloat_value()))); + break; + case Bytecodes::_fdiv: + b = pop(); + a = pop(); + push(SharkValue::create_jfloat( + builder()->CreateFDiv(a->jfloat_value(), b->jfloat_value()))); + break; + case Bytecodes::_frem: + b = pop(); + a = pop(); + push(SharkValue::create_jfloat( + builder()->CreateFRem(a->jfloat_value(), b->jfloat_value()))); + break; + case Bytecodes::_fneg: + a = pop(); + push(SharkValue::create_jfloat( + builder()->CreateNeg(a->jfloat_value()))); break; - case Bytecodes::_i2c: - push(SharkValue::create_jint( - builder()->CreateAnd( - pop()->jint_value(), - LLVMValue::jint_constant(0xffff)))); + case Bytecodes::_dadd: + b = pop(); + a = pop(); + push(SharkValue::create_jdouble( + builder()->CreateAdd(a->jdouble_value(), b->jdouble_value()))); + break; + case Bytecodes::_dsub: + b = pop(); + a = pop(); + push(SharkValue::create_jdouble( + builder()->CreateSub(a->jdouble_value(), b->jdouble_value()))); + break; + case Bytecodes::_dmul: + b = pop(); + a = pop(); + push(SharkValue::create_jdouble( + builder()->CreateMul(a->jdouble_value(), b->jdouble_value()))); + break; + case Bytecodes::_ddiv: + b = pop(); + a = pop(); + push(SharkValue::create_jdouble( + builder()->CreateFDiv(a->jdouble_value(), b->jdouble_value()))); + break; + case Bytecodes::_drem: + b = pop(); + a = pop(); + push(SharkValue::create_jdouble( + builder()->CreateFRem(a->jdouble_value(), b->jdouble_value()))); + break; + case Bytecodes::_dneg: + a = pop(); + push(SharkValue::create_jdouble( + builder()->CreateNeg(a->jdouble_value()))); break; case Bytecodes::_iinc: @@ -366,20 +667,122 @@ LLVMValue::jint_constant(iter()->get_iinc_con()), local(i)->jint_value()))); break; - + + case Bytecodes::_lcmp: + do_lcmp(); + break; + + case Bytecodes::_i2l: + push(SharkValue::create_jlong( + builder()->CreateIntCast( + pop()->jint_value(), SharkType::jlong_type(), true))); + break; + case Bytecodes::_i2f: + push(SharkValue::create_jfloat( + builder()->CreateSIToFP( + pop()->jint_value(), SharkType::jfloat_type()))); + break; + case Bytecodes::_i2d: + push(SharkValue::create_jdouble( + builder()->CreateSIToFP( + pop()->jint_value(), SharkType::jdouble_type()))); + break; + + case Bytecodes::_l2i: + push(SharkValue::create_jint( + builder()->CreateIntCast( + pop()->jlong_value(), SharkType::jint_type(), true))); + break; + case Bytecodes::_l2f: + push(SharkValue::create_jfloat( + builder()->CreateSIToFP( + pop()->jlong_value(), SharkType::jfloat_type()))); + break; + case Bytecodes::_l2d: + push(SharkValue::create_jdouble( + builder()->CreateSIToFP( + pop()->jlong_value(), SharkType::jdouble_type()))); + break; + + case Bytecodes::_f2i: + push(SharkValue::create_jint( + builder()->CreateFPToSI( + pop()->jfloat_value(), SharkType::jint_type()))); + break; + case Bytecodes::_f2l: + push(SharkValue::create_jint( + builder()->CreateFPToSI( + pop()->jfloat_value(), SharkType::jlong_type()))); + break; + case Bytecodes::_f2d: + push(SharkValue::create_jdouble( + builder()->CreateFPExt( + pop()->jfloat_value(), SharkType::jdouble_type()))); + break; + + case Bytecodes::_d2i: + push(SharkValue::create_jint( + builder()->CreateFPToSI( + pop()->jdouble_value(), SharkType::jint_type()))); + break; + case Bytecodes::_d2l: + push(SharkValue::create_jlong( + builder()->CreateFPToSI( + pop()->jdouble_value(), SharkType::jlong_type()))); + break; + case Bytecodes::_d2f: + push(SharkValue::create_jfloat( + builder()->CreateFPTrunc( + pop()->jdouble_value(), SharkType::jfloat_type()))); + break; + + case Bytecodes::_i2b: + push(SharkValue::create_jint( + builder()->CreateAShr( + builder()->CreateShl( + pop()->jint_value(), + LLVMValue::jint_constant(24)), + LLVMValue::jint_constant(24)))); + break; + case Bytecodes::_i2c: + push(SharkValue::create_jint( + builder()->CreateAnd( + pop()->jint_value(), + LLVMValue::jint_constant(0xffff)))); + break; + case Bytecodes::_i2s: + push(SharkValue::create_jint( + builder()->CreateAShr( + builder()->CreateShl( + pop()->jint_value(), + LLVMValue::jint_constant(16)), + LLVMValue::jint_constant(16)))); + break; + case Bytecodes::_return: do_return(T_VOID); break; case Bytecodes::_ireturn: do_return(T_INT); break; + case Bytecodes::_lreturn: + do_return(T_LONG); + break; case Bytecodes::_freturn: do_return(T_FLOAT); break; + case Bytecodes::_dreturn: + do_return(T_DOUBLE); + break; case Bytecodes::_areturn: 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()); @@ -453,6 +856,9 @@ case Bytecodes::_new: do_new(); break; + case Bytecodes::_newarray: + do_newarray(); + break; case Bytecodes::_monitorenter: do_monitorenter(); @@ -467,10 +873,12 @@ 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; + record_method_not_compilable(buf); } } + + if (failing()) + return; } if (falls_through()) { @@ -492,25 +900,42 @@ ShouldNotReachHere(); } -void SharkBlock::check_null(SharkValue *object) +void SharkBlock::check_zero(SharkValue *value) { - if (object->null_checked()) + if (value->zero_checked()) return; - BasicBlock *null = function()->CreateBlock("null"); - BasicBlock *not_null = function()->CreateBlock("not_null"); + BasicBlock *zero = function()->CreateBlock("zero"); + BasicBlock *not_zero = function()->CreateBlock("not_zero"); - builder()->CreateCondBr( - builder()->CreateICmpEQ(object->jobject_value(), LLVMValue::null()), - null, not_null); + Value *a, *b; + switch (value->basic_type()) { + case T_INT: + a = value->jint_value(); + b = LLVMValue::jint_constant(0); + break; + case T_LONG: + a = value->jlong_value(); + b = LLVMValue::jlong_constant(0); + break; + case T_OBJECT: + case T_ARRAY: + a = value->jobject_value(); + b = LLVMValue::LLVMValue::null(); + break; + default: + ShouldNotReachHere(); + } - builder()->SetInsertPoint(null); + builder()->CreateCondBr(builder()->CreateICmpNE(a, b), not_zero, zero); + + builder()->SetInsertPoint(zero); builder()->CreateUnimplemented(__FILE__, __LINE__); builder()->CreateUnreachable(); - builder()->SetInsertPoint(not_null); + builder()->SetInsertPoint(not_zero); - object->set_null_checked(true); + value->set_zero_checked(true); } void SharkBlock::check_bounds(SharkValue* array, SharkValue* index) @@ -683,8 +1108,9 @@ check_null(array); check_bounds(array, index); - Value *value = builder()->CreateArrayLoad( - array->jarray_value(), basic_type, index->jint_value()); + Value *value = builder()->CreateLoad( + builder()->CreateArrayAddress( + array->jarray_value(), basic_type, index->jint_value())); const Type *stack_type = SharkType::to_stackType(basic_type); if (value->getType() != stack_type) @@ -699,6 +1125,18 @@ push(SharkValue::create_jint(value)); break; + case T_LONG: + push(SharkValue::create_jlong(value)); + break; + + case T_FLOAT: + push(SharkValue::create_jfloat(value)); + break; + + case T_DOUBLE: + push(SharkValue::create_jdouble(value)); + break; + case T_OBJECT: push(SharkValue::create_jobject(value)); break; @@ -735,8 +1173,17 @@ value = svalue->jlong_value(); break; + case T_FLOAT: + value = svalue->jfloat_value(); + break; + + case T_DOUBLE: + value = svalue->jdouble_value(); + break; + case T_OBJECT: value = svalue->jobject_value(); + // XXX assignability check break; default: @@ -748,9 +1195,80 @@ if (value->getType() != array_type) value = builder()->CreateIntCast(value, array_type, basic_type != T_CHAR); - builder()->CreateArrayStore( - array->jarray_value(), basic_type, - index->jint_value(), value); + Value *addr = builder()->CreateArrayAddress( + array->jarray_value(), basic_type, index->jint_value(), "addr"); + + builder()->CreateStore(value, addr); + + if (!element_type->is_primitive_type()) + builder()->CreateUpdateBarrierSet(oopDesc::bs(), addr); +} + +void SharkBlock::do_div_or_rem(bool is_long, bool is_rem) +{ + SharkValue *sb = pop(); + SharkValue *sa = pop(); + + check_divide_by_zero(sb); + + Value *a, *b, *p, *q; + if (is_long) { + a = sa->jlong_value(); + b = sb->jlong_value(); + p = LLVMValue::jlong_constant(0x8000000000000000LL); + q = LLVMValue::jlong_constant(-1); + } + else { + a = sa->jint_value(); + b = sb->jint_value(); + p = LLVMValue::jint_constant(0x80000000); + q = LLVMValue::jint_constant(-1); + } + + BasicBlock *special_case = function()->CreateBlock("special_case"); + BasicBlock *general_case = function()->CreateBlock("general_case"); + BasicBlock *done = function()->CreateBlock("done"); + + builder()->CreateCondBr( + builder()->CreateAnd( + builder()->CreateICmpEQ(a, p), + builder()->CreateICmpEQ(b, q)), + special_case, general_case); + + builder()->SetInsertPoint(special_case); + Value *special_result; + if (is_rem) { + if (is_long) + special_result = LLVMValue::jlong_constant(0); + else + special_result = LLVMValue::jint_constant(0); + } + else { + special_result = a; + } + builder()->CreateBr(done); + + builder()->SetInsertPoint(general_case); + Value *general_result; + if (is_rem) + general_result = builder()->CreateSRem(a, b); + else + general_result = builder()->CreateSDiv(a, b); + builder()->CreateBr(done); + + builder()->SetInsertPoint(done); + PHINode *result; + if (is_long) + result = builder()->CreatePHI(SharkType::jlong_type(), "result"); + else + result = builder()->CreatePHI(SharkType::jint_type(), "result"); + result->addIncoming(special_result, special_case); + result->addIncoming(general_result, general_case); + + if (is_long) + push(SharkValue::create_jlong(result)); + else + push(SharkValue::create_jint(result)); } void SharkBlock::do_field_access(bool is_get, bool is_field) @@ -796,7 +1314,7 @@ Value *addr = builder()->CreateAddressOfStructEntry( object, in_ByteSize(field->offset_in_bytes()), PointerType::getUnqual(field_type), - "field"); + "addr"); // Do the access if (is_get) { @@ -820,8 +1338,12 @@ if (!field->type()->is_primitive_type()) builder()->CreateUpdateBarrierSet(oopDesc::bs(), addr); - if (field->is_volatile()) + if (field->is_volatile()) { builder()->CreateMemoryBarrier(SharkBuilder::BARRIER_STORELOAD); +#ifdef PPC + record_method_not_compilable("Missing memory barrier"); +#endif // PPC + } } } @@ -830,12 +1352,43 @@ push(value); } +void SharkBlock::do_lcmp() +{ + Value *b = pop()->jlong_value(); + Value *a = pop()->jlong_value(); + + BasicBlock *ne = function()->CreateBlock("lcmp_ne"); + BasicBlock *lt = function()->CreateBlock("lcmp_lt"); + BasicBlock *gt = function()->CreateBlock("lcmp_gt"); + BasicBlock *done = function()->CreateBlock("done"); + + BasicBlock *eq = builder()->GetInsertBlock(); + builder()->CreateCondBr(builder()->CreateICmpEQ(a, b), done, ne); + + builder()->SetInsertPoint(ne); + builder()->CreateCondBr(builder()->CreateICmpSLT(a, b), lt, gt); + + builder()->SetInsertPoint(lt); + builder()->CreateBr(done); + + builder()->SetInsertPoint(gt); + builder()->CreateBr(done); + + builder()->SetInsertPoint(done); + PHINode *result = builder()->CreatePHI(SharkType::jint_type(), "result"); + result->addIncoming(LLVMValue::jint_constant(-1), lt); + result->addIncoming(LLVMValue::jint_constant(0), eq); + result->addIncoming(LLVMValue::jint_constant(1), gt); + + push(SharkValue::create_jint(result)); +} + void SharkBlock::do_return(BasicType basic_type) { add_safepoint(); if (target()->is_synchronized()) - monitor(0)->release(); + function()->monitor(0)->release(); Value *result_addr = function()->CreatePopFrame(type2size[basic_type]); if (basic_type != T_VOID) { @@ -964,12 +1517,13 @@ SharkType::intptr_type(), "index"); - Value *nonfinal_callee = builder()->CreateArrayLoad( - klass, - SharkType::methodOop_type(), - vtableEntry::size() * wordSize, - in_ByteSize(instanceKlass::vtable_start_offset() * wordSize), - index, + Value *nonfinal_callee = builder()->CreateLoad( + builder()->CreateArrayAddress( + klass, + SharkType::methodOop_type(), + vtableEntry::size() * wordSize, + in_ByteSize(instanceKlass::vtable_start_offset() * wordSize), + index), "nonfinal_callee"); builder()->CreateBr(invoke); @@ -1131,66 +1685,23 @@ "callee"); } - Value *entry_point = builder()->CreateValueOfStructEntry( - callee, methodOopDesc::from_interpreted_offset(), // XXX hacky - PointerType::getUnqual(SharkType::interpreter_entry_type()), - "entry_point"); - - // Decache for the call - current_state()->decache(method); - - // 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( + Value *base_pc = 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( + Value *entry_point = builder()->CreateLoad( builder()->CreateIntToPtr( builder()->CreateAdd( base_pc, - LLVMValue::intptr_constant( - in_bytes(SharkMethod::entry_point_offset()))), + LLVMValue::intptr_constant(in_bytes(ZeroEntry::entry_point_offset()))), PointerType::getUnqual( - PointerType::getUnqual(SharkType::shark_entry_type()))), - "shark_entry_point"); + PointerType::getUnqual(SharkType::entry_point_type()))), + "entry_point"); - builder()->CreateCall3(shark_entry_point, callee, base_pc, thread()); - builder()->CreateBr(post_call); - - // Recache state - builder()->SetInsertPoint(post_call); + // Make the call + current_state()->decache(method); + builder()->CreateCall3(entry_point, callee, base_pc, thread()); current_state()->cache(method); // Check for pending exceptions @@ -1438,7 +1949,7 @@ call_vm( SharkRuntime::new_instance(), constants.object_at(iter()->get_klass_index())); - slow_object = function()->CreateLoadVMResult(); + slow_object = function()->CreateGetVMResult(); got_slow = builder()->GetInsertBlock(); // Push the object @@ -1457,17 +1968,115 @@ object = slow_object; } - push(SharkValue::create_jobject(object)); + SharkValue *result = SharkValue::create_jobject(object); + result->set_zero_checked(true); + push(result); +} + +void SharkBlock::do_newarray() +{ + BasicType type = (BasicType) iter()->get_index(); + + call_vm( + SharkRuntime::newarray(), + LLVMValue::jint_constant(type), + pop()->jint_value()); + + SharkValue *result = SharkValue::create_generic( + ciArrayKlass::make(ciType::make(type)), + function()->CreateGetVMResult()); + result->set_zero_checked(true); + push(result); } void SharkBlock::do_monitorenter() { SharkValue *lockee = pop(); - builder()->CreateUnimplemented(__FILE__, __LINE__); + check_null(lockee); + Value *object = lockee->jobject_value(); + + // Find a free monitor, or one already allocated for this object + BasicBlock *loop_top = function()->CreateBlock("loop_top"); + BasicBlock *loop_iter = function()->CreateBlock("loop_iter"); + BasicBlock *loop_check = function()->CreateBlock("loop_check"); + BasicBlock *no_monitor = function()->CreateBlock("no_monitor"); + BasicBlock *got_monitor = function()->CreateBlock("got_monitor"); + + BasicBlock *entry_block = builder()->GetInsertBlock(); + builder()->CreateBr(loop_check); + + builder()->SetInsertPoint(loop_check); + PHINode *index = builder()->CreatePHI(SharkType::jint_type(), "index"); + index->addIncoming( + LLVMValue::jint_constant(function()->monitor_count() - 1), entry_block); + builder()->CreateCondBr( + builder()->CreateICmpUGE(index, LLVMValue::jint_constant(0)), + loop_top, no_monitor); + + builder()->SetInsertPoint(loop_top); + SharkMonitor* monitor = function()->monitor(index); + Value *smo = monitor->object(); + builder()->CreateCondBr( + builder()->CreateOr( + builder()->CreateICmpEQ(smo, LLVMValue::null()), + builder()->CreateICmpEQ(smo, object)), + got_monitor, loop_iter); + + builder()->SetInsertPoint(loop_iter); + index->addIncoming( + builder()->CreateSub(index, LLVMValue::jint_constant(1)), loop_iter); + builder()->CreateBr(loop_check); + + builder()->SetInsertPoint(no_monitor); + builder()->CreateShouldNotReachHere(__FILE__, __LINE__); + builder()->CreateUnreachable(); + + // Acquire the lock + builder()->SetInsertPoint(got_monitor); + monitor->acquire(object); } void SharkBlock::do_monitorexit() { SharkValue *lockee = pop(); - builder()->CreateUnimplemented(__FILE__, __LINE__); + check_null(lockee); + Value *object = lockee->jobject_value(); + + // Find the monitor associated with this object + BasicBlock *loop_top = function()->CreateBlock("loop_top"); + BasicBlock *loop_iter = function()->CreateBlock("loop_iter"); + BasicBlock *loop_check = function()->CreateBlock("loop_check"); + BasicBlock *no_monitor = function()->CreateBlock("no_monitor"); + BasicBlock *got_monitor = function()->CreateBlock("got_monitor"); + + BasicBlock *entry_block = builder()->GetInsertBlock(); + builder()->CreateBr(loop_check); + + builder()->SetInsertPoint(loop_check); + PHINode *index = builder()->CreatePHI(SharkType::jint_type(), "index"); + index->addIncoming( + LLVMValue::jint_constant(function()->monitor_count() - 1), entry_block); + builder()->CreateCondBr( + builder()->CreateICmpUGE(index, LLVMValue::jint_constant(0)), + loop_top, no_monitor); + + builder()->SetInsertPoint(loop_top); + SharkMonitor* monitor = function()->monitor(index); + Value *smo = monitor->object(); + builder()->CreateCondBr( + builder()->CreateICmpEQ(smo, object), + got_monitor, loop_iter); + + builder()->SetInsertPoint(loop_iter); + index->addIncoming( + builder()->CreateSub(index, LLVMValue::jint_constant(1)), loop_iter); + builder()->CreateBr(loop_check); + + builder()->SetInsertPoint(no_monitor); + builder()->CreateShouldNotReachHere(__FILE__, __LINE__); + builder()->CreateUnreachable(); + + // Release the lock + builder()->SetInsertPoint(got_monitor); + monitor->release(); }
--- a/ports/hotspot/src/share/vm/shark/sharkBlock.hpp Wed Aug 20 04:12:41 2008 -0400 +++ b/ports/hotspot/src/share/vm/shark/sharkBlock.hpp Wed Aug 20 04:24:45 2008 -0400 @@ -61,9 +61,13 @@ { return function()->builder(); } - SharkMonitor* monitor(int index) const + bool failing() const { - return function()->monitor(index); + return function()->failing(); + } + void record_method_not_compilable(const char* reason) const + { + function()->record_method_not_compilable(reason); } ciMethod* target() const { @@ -100,10 +104,6 @@ { 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); @@ -237,6 +237,21 @@ return current_state()->stack(slot); } + // Handy macros for the various pop, swap and dup bytecodes + private: + SharkValue* pop_and_assert_one_word() + { + SharkValue* result = pop(); + assert(result->is_one_word(), "should be"); + return result; + } + SharkValue* pop_and_assert_two_word() + { + SharkValue* result = pop(); + assert(result->is_two_word(), "should be"); + return result; + } + // VM calls private: llvm::CallInst* call_vm_base(llvm::Constant* callee, @@ -244,13 +259,21 @@ llvm::Value** args_end); public: - llvm::CallInst* call_vm(llvm::Constant* callee, llvm::Value* arg1) + 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 *args[] = {thread(), arg1, arg2}; + return call_vm_base(callee, args, args + 3); + } + llvm::CallInst* call_vm(llvm::Constant* callee, + llvm::Value* arg1, llvm::Value* arg2, llvm::Value* arg3) { @@ -264,7 +287,15 @@ // Error checking private: - void check_null(SharkValue* value); + void check_null(SharkValue* object) + { + check_zero(object); + } + void check_divide_by_zero(SharkValue* value) + { + check_zero(value); + } + void check_zero(SharkValue* value); void check_bounds(SharkValue* array, SharkValue* index); void check_pending_exception(); @@ -272,20 +303,40 @@ private: void add_safepoint(); - // _ldc* bytecodes + // ldc* private: void do_ldc(); - // _arraylength bytecode + // arraylength private: void do_arraylength(); - // _*aload and *astore bytecodes + // *aload and *astore private: void do_aload(BasicType basic_type); void do_astore(BasicType basic_type); - // _get* and _put* bytecodes + // *div and *rem + private: + void do_idiv() + { + do_div_or_rem(false, false); + } + void do_irem() + { + do_div_or_rem(false, true); + } + void do_ldiv() + { + do_div_or_rem(true, false); + } + void do_lrem() + { + do_div_or_rem(true, true); + } + void do_div_or_rem(bool is_long, bool is_rem); + + // get* and put* private: void do_getstatic() { @@ -305,31 +356,36 @@ } void do_field_access(bool is_get, bool is_field); - // _*return bytecodes + // lcmp + private: + void do_lcmp(); + + // *return private: void do_return(BasicType basic_type); - // _if* bytecodes + // if* private: void do_if(llvm::ICmpInst::Predicate p, SharkValue* b, SharkValue* a); - // _*switch bytecodes + // *switch private: void do_tableswitch(); - // _invoke* bytecodes + // invoke* private: void do_call(); - // _checkcast and _instanceof + // checkcast and instanceof private: void do_instance_check(); - // _new + // new and newarray private: void do_new(); + void do_newarray(); - // _monitorenter and monitorexit + // monitorenter and monitorexit private: void do_monitorenter(); void do_monitorexit();
--- a/ports/hotspot/src/share/vm/shark/sharkBuilder.cpp Wed Aug 20 04:12:41 2008 -0400 +++ b/ports/hotspot/src/share/vm/shark/sharkBuilder.cpp Wed Aug 20 04:24:45 2008 -0400 @@ -97,7 +97,7 @@ Function *SharkBuilder::CreateFunction() { Function *function = Function::Create( - SharkType::shark_entry_type(), + SharkType::entry_point_type(), GlobalVariable::InternalLinkage, "func"); module()->getFunctionList().push_back(function);
--- a/ports/hotspot/src/share/vm/shark/sharkBuilder.hpp Wed Aug 20 04:12:41 2008 -0400 +++ b/ports/hotspot/src/share/vm/shark/sharkBuilder.hpp Wed Aug 20 04:24:45 2008 -0400 @@ -74,7 +74,7 @@ SharkType::jint_type(), "length"); } - llvm::LoadInst* CreateArrayLoad(llvm::Value* arrayoop, + llvm::Value* CreateArrayAddress(llvm::Value* arrayoop, const llvm::Type* element_type, int element_bytes, ByteSize base_offset, @@ -82,77 +82,43 @@ 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); + 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)), + return CreateIntToPtr( + CreateAdd(CreatePtrToInt(arrayoop, SharkType::intptr_type()), offset), + llvm::PointerType::getUnqual(element_type), name); } - llvm::LoadInst* CreateArrayLoad(llvm::Value* arrayoop, + llvm::Value* CreateArrayAddress(llvm::Value* arrayoop, BasicType basic_type, ByteSize base_offset, llvm::Value* index, const char* name = "") { - return CreateArrayLoad( + return CreateArrayAddress( arrayoop, SharkType::to_arrayType(basic_type), type2aelembytes[basic_type], base_offset, index, name); } - llvm::StoreInst* CreateArrayStore(llvm::Value* arrayoop, - BasicType basic_type, - ByteSize base_offset, - llvm::Value* index, - llvm::Value* value) - { - 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 CreateStore( - value, - CreateIntToPtr( - CreateAdd(CreatePtrToInt(arrayoop, SharkType::intptr_type()), offset), - llvm::PointerType::getUnqual(array_type))); - } - - llvm::LoadInst* CreateArrayLoad(llvm::Value* arrayoop, + llvm::Value* CreateArrayAddress(llvm::Value* arrayoop, BasicType basic_type, llvm::Value* index, const char* name = "") { - return CreateArrayLoad( + return CreateArrayAddress( arrayoop, basic_type, in_ByteSize(arrayOopDesc::base_offset_in_bytes(basic_type)), index, name); } - llvm::StoreInst* CreateArrayStore(llvm::Value* arrayoop, - BasicType basic_type, - llvm::Value* index, - llvm::Value* value) - { - return CreateArrayStore( - arrayoop, basic_type, - in_ByteSize(arrayOopDesc::base_offset_in_bytes(basic_type)), - index, value); - } - // Helper for making function pointers public: llvm::Constant* make_function(intptr_t addr,
--- a/ports/hotspot/src/share/vm/shark/sharkCompiler.cpp Wed Aug 20 04:12:41 2008 -0400 +++ b/ports/hotspot/src/share/vm/shark/sharkCompiler.cpp Wed Aug 20 04:24:45 2008 -0400 @@ -48,14 +48,9 @@ assert(entry_bci == InvocationEntryBci, "OSR is not supported"); ResourceMark rm; + const char *name = methodname(target); - 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++; @@ -70,7 +65,7 @@ #endif // !PRODUCT if (SharkOnlyCompile != NULL) { - if (!method_matches(SharkOnlyCompile, method_klass, method_name)) { + if (strcmp(SharkOnlyCompile, name)) { env->record_method_not_compilable("does not match SharkOnlyCompile"); return; } @@ -81,43 +76,23 @@ if (env->failing()) return; if (SharkPrintTypeflowOf != NULL) { - if (method_matches(SharkPrintTypeflowOf, method_klass, method_name)) + if (!strcmp(SharkPrintTypeflowOf, name)) flow->print_on(tty); } // Create the CodeBuffer and OopMapSet BufferBlob *bb = BufferBlob::create( - "shark_temp", sizeof(SharkMethod) + target->code_size()); + "shark_temp", sizeof(SharkEntry) + target->code_size()); CodeBuffer cb(bb->instructions_begin(), bb->instructions_size()); OopMapSet oopmaps; - // Compile the method + // Compile the method into the CodeBuffer ciBytecodeStream iter(target); - SharkFunction function(builder(), flow, &iter, &cb, &oopmaps); + SharkFunction function(builder(), name, flow, &iter, &cb, &oopmaps); if (env->failing()) return; - if (SharkPrintBitcodeOf != NULL) { - if (method_matches(SharkPrintBitcodeOf, method_klass, method_name)) - function.function()->dump(); - } - if (SharkTraceInstalls) { - uint32_t *start = NULL; - uint32_t *limit = NULL; -#ifdef PPC - start = *(uint32_t **) bb->instructions_begin(); - limit = start; - while (*limit) - limit++; -#else - Unimplemented(); -#endif // PPC - tty->print_cr( - "Installing method %s::%s at [%p-%p)", - method_klass, method_name, start, limit); - } - - // Install the method + // Install the method into the VM install_method(env, target, entry_bci, &cb, &oopmaps); } @@ -166,52 +141,26 @@ 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(); -} + const char *klassname = target->holder()->name()->as_utf8(); + const char *methodname = 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; - } + char *buf = NEW_RESOURCE_ARRAY( + char, strlen(klassname) + 2 + strlen(methodname) + 1); - if (pattern[0] != ':' && pattern[1] != ':') - return false; - pattern += 2; - - if (pattern[0] == '*') { - pattern++; + char *dst = buf; + for (const char *c = klassname; *c; c++) { + if (*c == '/') + *(dst++) = '.'; + else + *(dst++) = *c; } - else { - int len = strlen(methodname); - if (strncmp(pattern, methodname, len)) - return false; - pattern += len; + *(dst++) = ':'; + *(dst++) = ':'; + for (const char *c = methodname; *c; c++) { + *(dst++) = *c; } - - return pattern[0] == '\0'; + *(dst++) = '\0'; + return buf; } -#endif // !PRODUCT
--- a/ports/hotspot/src/share/vm/shark/sharkCompiler.hpp Wed Aug 20 04:12:41 2008 -0400 +++ b/ports/hotspot/src/share/vm/shark/sharkCompiler.hpp Wed Aug 20 04:24:45 2008 -0400 @@ -57,7 +57,7 @@ return &_builder; } - // Method installation helper + // Helpers private: void install_method(ciEnv* env, ciMethod* target, @@ -65,12 +65,5 @@ 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; + static const char *methodname(const ciMethod* target); };
--- a/ports/hotspot/src/share/vm/shark/sharkConstantPool.cpp Wed Aug 20 04:12:41 2008 -0400 +++ b/ports/hotspot/src/share/vm/shark/sharkConstantPool.cpp Wed Aug 20 04:24:45 2008 -0400 @@ -66,16 +66,18 @@ Value *SharkConstantPool::object_at(int which) { - return builder()->CreateArrayLoad( - constants(), - T_OBJECT, in_ByteSize(sizeof(constantPoolOopDesc)), - LLVMValue::jint_constant(which)); + return builder()->CreateLoad( + builder()->CreateArrayAddress( + 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)); + return builder()->CreateLoad( + builder()->CreateArrayAddress( + tags(), T_BYTE, LLVMValue::jint_constant(which))); } Value *SharkConstantPool::cache_entry_at(int which)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ports/hotspot/src/share/vm/shark/sharkEntry.cpp Wed Aug 20 04:24:45 2008 -0400 @@ -0,0 +1,136 @@ +/* + * 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/_sharkEntry.cpp.incl" + +#ifndef PRODUCT +void SharkEntry::print_statistics(const char* name) const +{ + address start = code_start(); + address limit = code_limit(); + + ttyLocker ttyl; + tty->print(" [%p-%p): %s (%d bytes code", start, limit, name, limit - start); + print_pd_statistics(start, limit); + tty->print_cr(")"); +} + +// Lots of the stuff down here is machine- and LLVM-specific. +// It's only debug stuff though, and none of it's critical. + +address SharkEntry::code_start() const +{ + return (address) entry_point(); +} + +address SharkEntry::code_limit() const +{ +#ifdef PPC + // LLVM seems to insert three junk instructions and a null after + // every function. Only the first junk instruction seems to be + // kept after the next function is generated, however, so this + // method will only work before you generate another function. + // I wish there was a nicer way to do this, but that's life... + uint32_t *limit = (uint32_t *) code_start(); + while (*limit) + limit++; + assert(limit[-1] == 0xd143cfec && limit[-2] == 0xd143cfec, "should be"); + limit -= 3; + return (address) limit; +#else + Unimplemented(); +#endif // PPC +} + +void SharkEntry::print_pd_statistics(address start, address limit) const +{ +#ifdef PPC + uint32_t *pc = (uint32_t *) start; + uint32_t instr; + + // Walk over the bit that allocates the frame + instr = *(pc++); + assert (instr == 0x7c0802a6, "expecting 'mflr r0'"); + + instr = *(pc++); + assert (instr == NOT_LP64(0x90010004) LP64_ONLY(0xf8010004), + "expecting st" NOT_LP64("w") LP64_ONLY("d") " r0,4(r1)"); + + instr = *(pc++); + assert ((instr & 0xffff8001) == NOT_LP64(0x94218000) LP64_ONLY(0xf8218001), + "expecting st" NOT_LP64("w") LP64_ONLY("d") "u r1,-X(r1)"); + int frame_size = -((instr | 0xffff0000) LP64_ONLY(& 0xfffffffc)); + tty->print(", %d bytes stack", frame_size); + + // Walk over the bit that stores the non-volatile registers + int first_reg = -1; + int next_slot = frame_size - wordSize; + int last_reg = -1; + while (pc < (uint32_t *) limit) { + instr = *(pc++); + + // The opcode should be stw/std + int opcode = instr >> 26; + if (opcode != NOT_LP64(36) LP64_ONLY(62)) + break; + + // The destination should be next_slot(r1) + int ra = (instr & 0x001f0000) >> 16; + if (ra != 1) + break; + + int ds = instr & 0x0000ffff; + if (ds != next_slot) + break; + next_slot -= wordSize; + + // The source should be the next register after last_reg + int rs = (instr & 0x03e00000) >> 21; + if (first_reg == -1) { + assert(rs >= 13, "storing a non-volatile register?"); + first_reg = last_reg = rs; + } + else { + assert(rs == last_reg + 1, "register stores out of order?"); + last_reg = rs; + } + } + + if (first_reg == -1) { + tty->print(", 0 registers"); + } + else { + int num_registers = last_reg - first_reg + 1; + if (num_registers == 1) + tty->print(", 1 register"); + else + tty->print(", %d registers", num_registers); + if (num_registers >= 19) + tty->print("!"); + } +#endif // PPC +} +#endif // !PRODUCT
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ports/hotspot/src/share/vm/shark/sharkEntry.hpp Wed Aug 20 04:24:45 2008 -0400 @@ -0,0 +1,55 @@ +/* + * 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 SharkEntry : public ZeroEntry { + private: + llvm::Function* _llvm_function; + + public: + llvm::Function* llvm_function() const + { + return _llvm_function; + } + void set_llvm_function(llvm::Function* llvm_function) + { + _llvm_function = llvm_function; + } + + public: + static ByteSize llvm_function_offset() + { + return byte_offset_of(SharkEntry, _llvm_function); + } + + public: + void print_statistics(const char* name) const PRODUCT_RETURN; + +#ifndef PRODUCT + private: + address code_start() const; + address code_limit() const; + void print_pd_statistics(address start, address limit) const; +#endif // !PRODUCT +};
--- a/ports/hotspot/src/share/vm/shark/sharkFunction.cpp Wed Aug 20 04:12:41 2008 -0400 +++ b/ports/hotspot/src/share/vm/shark/sharkFunction.cpp Wed Aug 20 04:24:45 2008 -0400 @@ -30,24 +30,17 @@ void SharkFunction::initialize() { + // Create the assembler and emit the entry point + _assembler = new MacroAssembler(cb()); + SharkEntry *entry = (SharkEntry *) assembler()->pc(); + assembler()->advance(sizeof(SharkEntry)); + // 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"); + entry->set_llvm_function(function()); // Initialize the blocks + set_block_insertion_point(NULL); _blocks = NEW_RESOURCE_ARRAY(SharkBlock*, flow()->block_count()); for (int i = 0; i < block_count(); i++) _blocks[i] = new SharkBlock(this, flow()->pre_order_at(i)); @@ -66,10 +59,9 @@ _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()); + _monitor_count = MAX2( + _monitor_count, block(i)->ciblock()->monitor_count()); } - if (monitor_count()) - _monitors = NEW_RESOURCE_ARRAY(SharkMonitor*, monitor_count()); // Get our arguments Function::arg_iterator ai = function()->arg_begin(); @@ -91,8 +83,29 @@ if (target()->is_synchronized()) { Value *object; if (target()->is_static()) { - Unimplemented(); - object = NULL; + Value *constants = builder()->CreateValueOfStructEntry( + method, + methodOopDesc::constants_offset(), + SharkType::oop_type(), + "constants"); + + Value *pool_holder = builder()->CreateValueOfStructEntry( + constants, + in_ByteSize(constantPoolOopDesc::pool_holder_offset_in_bytes()), + SharkType::oop_type(), + "pool_holder"); + + Value *klass_part = builder()->CreateAddressOfStructEntry( + pool_holder, + in_ByteSize(klassOopDesc::klass_part_offset_in_bytes()), + SharkType::klass_type(), + "klass_part"); + + object = builder()->CreateValueOfStructEntry( + klass_part, + in_ByteSize(Klass::java_mirror_offset_in_bytes()), + SharkType::oop_type(), + "java_mirror"); } else { object = builder()->CreateLoad( @@ -116,13 +129,25 @@ block(i)->parse(); if (failing()) { - delete function(); + // XXX should delete function() here, but that breaks + // -XX:SharkPrintBitcodeOf. I guess some of the things + // we're sharing via SharkBuilder or SharkRuntime or + // SharkType are being freed return; } } + // Dump the bitcode, if requested + if (SharkPrintBitcodeOf != NULL) { + if (!strcmp(SharkPrintBitcodeOf, name())) + function()->dump(); + } + // Compile to native code - *code = builder()->execution_engine()->getPointerToFunction(function()); + void *code = builder()->execution_engine()->getPointerToFunction(function()); + entry->set_entry_point((ZeroEntry::method_entry_t) code); + if (SharkTraceInstalls) + entry->print_statistics(name()); } void SharkFunction::CreateInitZeroStack() @@ -234,20 +259,13 @@ if (monitor_count()) { _monitors_slots_offset = offset; - Value *monitors = builder()->CreateBitCast( + _monitors_slots = 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(); } @@ -290,3 +308,15 @@ assert(offset == frame_words + locals_words, "should do"); return fp; } + +SharkMonitor* SharkFunction::monitor(Value *index) const +{ + Value *indexes[] = { + LLVMValue::jint_constant(0), + builder()->CreateSub( + LLVMValue::jint_constant(monitor_count() - 1), index), + }; + return new SharkMonitor( + this, + builder()->CreateGEP(monitors_slots(), indexes, indexes + 2)); +}
--- a/ports/hotspot/src/share/vm/shark/sharkFunction.hpp Wed Aug 20 04:12:41 2008 -0400 +++ b/ports/hotspot/src/share/vm/shark/sharkFunction.hpp Wed Aug 20 04:24:45 2008 -0400 @@ -29,11 +29,13 @@ class SharkFunction : public StackObj { public: SharkFunction(SharkBuilder* builder, + const char* name, ciTypeFlow* flow, ciBytecodeStream* iter, CodeBuffer* cb, OopMapSet* oopmaps) : _builder(builder), + _name(name), _flow(flow), _iter(iter), _cb(cb), @@ -45,11 +47,12 @@ private: SharkBuilder* _builder; + const char* _name; ciTypeFlow* _flow; ciBytecodeStream* _iter; CodeBuffer* _cb; OopMapSet* _oopmaps; - MacroAssembler* _masm; + MacroAssembler* _assembler; llvm::Function* _function; SharkBlock** _blocks; llvm::Value* _base_pc; @@ -61,6 +64,10 @@ { return _builder; } + const char* name() const + { + return _name; + } ciTypeFlow* flow() const { return _flow; @@ -77,9 +84,9 @@ { return _oopmaps; } - MacroAssembler* masm() const + MacroAssembler* assembler() const { - return _masm; + return _assembler; } llvm::Function* function() const { @@ -135,7 +142,7 @@ } void record_method_not_compilable(const char* reason) const { - return env()->record_method_not_compilable(reason); + env()->record_method_not_compilable(reason); } // Block management @@ -152,7 +159,7 @@ } public: - llvm::BasicBlock* CreateBlock(const char* name = "") + llvm::BasicBlock* CreateBlock(const char* name = "") const { return llvm::BasicBlock::Create(name, function(), block_insertion_point()); } @@ -212,7 +219,7 @@ llvm::Value* _pc_slot; llvm::Value* _method_slot; llvm::Value* _locals_slots; - SharkMonitor** _monitors; + llvm::Value* _monitors_slots; llvm::Value* _stack_slots; public: @@ -228,15 +235,22 @@ { return _locals_slots; } - SharkMonitor* monitor(int index) const + llvm::Value* monitors_slots() const { - return _monitors[index]; + return _monitors_slots; } llvm::Value* stack_slots() const { return _stack_slots; } + public: + SharkMonitor* monitor(int index) const + { + return monitor(LLVMValue::jint_constant(index)); + } + SharkMonitor* monitor(llvm::Value* index) const; + private: llvm::Value* CreateBuildFrame(); @@ -244,8 +258,8 @@ public: int code_offset() const { - int offset = masm()->offset(); - masm()->emit_zero_byte(); // keeps PCs unique + int offset = assembler()->offset(); + assembler()->advance(1); // keeps PCs unique return offset; } void add_gc_map(int offset, OopMap* oopmap) @@ -305,11 +319,14 @@ } public: - llvm::LoadInst* CreateLoadVMResult() const + llvm::LoadInst* CreateGetVMResult() const { - return builder()->CreateValueOfStructEntry( + llvm::Value *addr = builder()->CreateAddressOfStructEntry( thread(), JavaThread::vm_result_offset(), - SharkType::jobject_type(), - "vm_result"); + llvm::PointerType::getUnqual(SharkType::jobject_type()), + "vm_result_addr"); + llvm::LoadInst *result = builder()->CreateLoad(addr, "vm_result"); + builder()->CreateStore(LLVMValue::null(), addr); + return result; } };
--- a/ports/hotspot/src/share/vm/shark/sharkMethod.hpp Wed Aug 20 04:12:41 2008 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -/* - * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. - * Copyright 2008 Red Hat, Inc. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - */ - -class 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); - } -};
--- a/ports/hotspot/src/share/vm/shark/sharkMonitor.hpp Wed Aug 20 04:12:41 2008 -0400 +++ b/ports/hotspot/src/share/vm/shark/sharkMonitor.hpp Wed Aug 20 04:24:45 2008 -0400 @@ -25,7 +25,7 @@ class SharkMonitor : public ResourceObj { public: - SharkMonitor(SharkFunction* function, llvm::Value* monitor) + SharkMonitor(const SharkFunction* function, llvm::Value* monitor) : _function(function), _monitor(monitor) { initialize(); } @@ -33,13 +33,13 @@ void initialize(); private: - SharkFunction* _function; - llvm::Value* _monitor; - llvm::Value* _object_addr; - llvm::Value* _displaced_header_addr; + const SharkFunction* _function; + llvm::Value* _monitor; + llvm::Value* _object_addr; + llvm::Value* _displaced_header_addr; private: - SharkFunction* function() const + const SharkFunction* function() const { return _function; }
--- a/ports/hotspot/src/share/vm/shark/sharkRuntime.cpp Wed Aug 20 04:12:41 2008 -0400 +++ b/ports/hotspot/src/share/vm/shark/sharkRuntime.cpp Wed Aug 20 04:24:45 2008 -0400 @@ -28,6 +28,7 @@ using namespace llvm; +Constant* SharkRuntime::_newarray; Constant* SharkRuntime::_new_instance; Constant* SharkRuntime::_resolve_get_put; Constant* SharkRuntime::_resolve_invoke; @@ -42,6 +43,15 @@ // VM calls std::vector<const Type*> params; params.push_back(SharkType::thread_type()); + params.push_back(SharkType::jint_type()); + params.push_back(SharkType::jint_type()); + _newarray = builder->make_function( + (intptr_t) newarray_C, + FunctionType::get(Type::VoidTy, params, false), + "SharkRuntime__newarray"); + + params.clear(); + params.push_back(SharkType::thread_type()); params.push_back(SharkType::jobject_type()); _new_instance = builder->make_function( (intptr_t) new_instance_C, @@ -93,6 +103,15 @@ "report_unimplemented"); } +JRT_ENTRY(void, SharkRuntime::newarray_C(JavaThread* thread, + BasicType type, + int size)) +{ + oop obj = oopFactory::new_typeArray(type, size, CHECK); + thread->set_vm_result(obj); +} +JRT_END + JRT_ENTRY(void, SharkRuntime::new_instance_C(JavaThread* thread, klassOop klass)) {
--- a/ports/hotspot/src/share/vm/shark/sharkRuntime.hpp Wed Aug 20 04:12:41 2008 -0400 +++ b/ports/hotspot/src/share/vm/shark/sharkRuntime.hpp Wed Aug 20 04:24:45 2008 -0400 @@ -29,11 +29,16 @@ // VM calls private: + static llvm::Constant* _newarray; static llvm::Constant* _new_instance; static llvm::Constant* _resolve_get_put; static llvm::Constant* _resolve_invoke; public: + static llvm::Constant* newarray() + { + return _newarray; + } static llvm::Constant* new_instance() { return _new_instance; @@ -48,6 +53,7 @@ } private: + static void newarray_C(JavaThread* thread, BasicType type, int size); static void new_instance_C(JavaThread* thread, klassOop klass); static void resolve_get_put_C(JavaThread* thread, ConstantPoolCacheEntry* entry,
--- a/ports/hotspot/src/share/vm/shark/sharkState.cpp Wed Aug 20 04:12:41 2008 -0400 +++ b/ports/hotspot/src/share/vm/shark/sharkState.cpp Wed Aug 20 04:24:45 2008 -0400 @@ -67,7 +67,8 @@ builder()->CreateLoad( builder()->CreateBitCast( builder()->CreateStructGEP( - function()->locals_slots(), max_locals() - 1 - i), + function()->locals_slots(), + max_locals() - type->size() - i), PointerType::getUnqual(SharkType::to_stackType(type))), name)); } @@ -121,28 +122,31 @@ } // Expression stack + _sp = _stack; for (int i = 0; i < max_stack(); i++) { - SharkValue *value = NULL; if (i < block()->stack_depth_at_entry()) { ciType *type = block()->stack_type_at_entry(i); switch (type->basic_type()) { case ciTypeFlow::StateVector::T_TOP: case ciTypeFlow::StateVector::T_BOTTOM: + case ciTypeFlow::StateVector::T_NULL: + Unimplemented(); + break; + 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( + *(_sp++) = SharkValue::create_generic( type, builder()->CreatePHI(SharkType::to_stackType(type), name)); } } - _stack[i] = value; } - _sp = _stack + block()->stack_depth_at_entry(); +#ifdef ASSERT + _stack_depth_at_entry = stack_depth(); +#endif // ASSERT builder()->SetInsertPoint(saved_insert_point); } @@ -163,9 +167,8 @@ } // Expression stack - assert(block()->stack_depth_at_entry() == incoming_state->stack_depth(), - "should be"); - for (int i = 0; i < block()->stack_depth_at_entry(); i++) { + assert(_stack_depth_at_entry == incoming_state->stack_depth(), "should be"); + for (int i = 0; i < incoming_state->stack_depth(); i++) { ((PHINode *) stack(i)->generic_value())->addIncoming( incoming_state->stack(i)->generic_value(), predecessor);
--- a/ports/hotspot/src/share/vm/shark/sharkState.hpp Wed Aug 20 04:12:41 2008 -0400 +++ b/ports/hotspot/src/share/vm/shark/sharkState.hpp Wed Aug 20 04:24:45 2008 -0400 @@ -111,6 +111,11 @@ private: void initialize(); +#ifdef ASSERT + private: + int _stack_depth_at_entry; +#endif // ASSERT + public: void add_incoming(SharkState* incoming_state); };
--- a/ports/hotspot/src/share/vm/shark/sharkType.cpp Wed Aug 20 04:12:41 2008 -0400 +++ b/ports/hotspot/src/share/vm/shark/sharkType.cpp Wed Aug 20 04:24:45 2008 -0400 @@ -29,13 +29,12 @@ using namespace llvm; const PointerType* SharkType::_cpCacheEntry_type; -const FunctionType* SharkType::_interpreter_entry_type; +const FunctionType* SharkType::_entry_point_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; @@ -72,14 +71,9 @@ std::vector<const Type*> params; params.push_back(methodOop_type()); - params.push_back(thread_type()); - _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); + _entry_point_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++) {
--- a/ports/hotspot/src/share/vm/shark/sharkType.hpp Wed Aug 20 04:12:41 2008 -0400 +++ b/ports/hotspot/src/share/vm/shark/sharkType.hpp Wed Aug 20 04:24:45 2008 -0400 @@ -38,13 +38,12 @@ // VM types private: static const llvm::PointerType* _cpCacheEntry_type; - static const llvm::FunctionType* _interpreter_entry_type; + static const llvm::FunctionType* _entry_point_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; @@ -53,9 +52,9 @@ { return _cpCacheEntry_type; } - static const llvm::FunctionType* interpreter_entry_type() + static const llvm::FunctionType* entry_point_type() { - return _interpreter_entry_type; + return _entry_point_type; } static const llvm::PointerType* itableOffsetEntry_type() { @@ -77,10 +76,6 @@ { return _oop_type; } - static const llvm::FunctionType* shark_entry_type() - { - return _shark_entry_type; - } static const llvm::PointerType* thread_type() { return _thread_type;
--- a/ports/hotspot/src/share/vm/shark/sharkValue.hpp Wed Aug 20 04:12:41 2008 -0400 +++ b/ports/hotspot/src/share/vm/shark/sharkValue.hpp Wed Aug 20 04:24:45 2008 -0400 @@ -37,6 +37,14 @@ { return llvm::ConstantInt::get(SharkType::jlong_type(), value, true); } + static llvm::ConstantFP* jfloat_constant(jfloat value) + { + return llvm::ConstantFP::get(SharkType::jfloat_type(), value); + } + static llvm::ConstantFP* jdouble_constant(jdouble value) + { + return llvm::ConstantFP::get(SharkType::jdouble_type(), value); + } static llvm::ConstantPointerNull* null() { return llvm::ConstantPointerNull::get(SharkType::jobject_type()); @@ -52,12 +60,12 @@ class SharkValue : public ResourceObj { protected: SharkValue(ciType* type, llvm::Value* value) - : _type(type), _llvm_value(value), _null_checked(false) {} + : _type(type), _llvm_value(value), _zero_checked(false) {} private: ciType* _type; llvm::Value* _llvm_value; - bool _null_checked; + bool _zero_checked; public: ciType* type() const @@ -93,6 +101,14 @@ { return llvm_value()->getType() == SharkType::jlong_type(); } + bool is_jfloat() const + { + return llvm_value()->getType() == SharkType::jfloat_type(); + } + bool is_jdouble() const + { + return llvm_value()->getType() == SharkType::jdouble_type(); + } bool is_jobject() const { return llvm_value()->getType() == SharkType::jobject_type(); @@ -102,32 +118,27 @@ return basic_type() == T_ARRAY; } - // Typed conversion between Shark and LLVM values + // Typed conversions to LLVM values public: - static SharkValue* create_jint(llvm::Value* value) - { - assert(value->getType() == SharkType::jint_type(), "should be"); - 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) + llvm::Value* jfloat_value() const { - assert(value->getType() == SharkType::jobject_type(), "should be"); - return create_generic(ciType::make(T_OBJECT), value); + assert(is_jfloat(), "should be"); + return llvm_value(); + } + llvm::Value* jdouble_value() const + { + assert(is_jdouble(), "should be"); + return llvm_value(); } llvm::Value* jobject_value() const { @@ -140,6 +151,35 @@ return llvm_value(); } + // Typed conversion from LLVM values + public: + static SharkValue* create_jint(llvm::Value* value) + { + assert(value->getType() == SharkType::jint_type(), "should be"); + return create_generic(ciType::make(T_INT), value); + } + static SharkValue* create_jlong(llvm::Value* value) + { + assert(value->getType() == SharkType::jlong_type(), "should be"); + return create_generic(ciType::make(T_LONG), value); + } + static SharkValue* create_jfloat(llvm::Value* value) + { + assert(value->getType() == SharkType::jfloat_type(), "should be"); + return create_generic(ciType::make(T_FLOAT), value); + } + static SharkValue* create_jdouble(llvm::Value* value) + { + assert(value->getType() == SharkType::jdouble_type(), "should be"); + return create_generic(ciType::make(T_DOUBLE), value); + } + static SharkValue* create_jobject(llvm::Value* value) + { + assert(value->getType() == SharkType::jobject_type(), "should be"); + return create_generic(ciType::make(T_OBJECT), value); + } + + // Typed conversion from HotSpot ciConstants public: static SharkValue* from_ciConstant(ciConstant value) { @@ -162,6 +202,12 @@ case T_LONG: return SharkValue::jlong_constant(value.as_long()); + case T_FLOAT: + return SharkValue::jfloat_constant(value.as_float()); + + case T_DOUBLE: + return SharkValue::jdouble_constant(value.as_double()); + case T_OBJECT: case T_ARRAY: return NULL; @@ -198,19 +244,27 @@ { return create_jlong(LLVMValue::jlong_constant(value)); } + static SharkValue* jfloat_constant(jfloat value) + { + return create_jfloat(LLVMValue::jfloat_constant(value)); + } + static SharkValue* jdouble_constant(jdouble value) + { + return create_jdouble(LLVMValue::jdouble_constant(value)); + } static SharkValue* null() { return create_generic(ciType::make(T_OBJECT), LLVMValue::null()); } - // Repeated null-check removal + // Repeated null and divide-by-zero check removal public: - bool null_checked() const + bool zero_checked() const { - return _null_checked; + return _zero_checked; } - void set_null_checked(bool null_checked) + void set_zero_checked(bool zero_checked) { - _null_checked = null_checked; + _zero_checked = zero_checked; } };