aboutsummaryrefslogtreecommitdiff
path: root/src/cpu/sparc
diff options
context:
space:
mode:
authorjrose <none@none>2009-04-08 10:56:49 -0700
committerjrose <none@none>2009-04-08 10:56:49 -0700
commit6094e1a45d0a3e8ebc1abeb2decefac21fda1d17 (patch)
treeb7300e43ab49aea0527e81c61bf1232f7a2c6567 /src/cpu/sparc
parent13e9fa5459a55b69b581abbf0377faf539d46849 (diff)
downloadjdk8u_hotspot-6094e1a45d0a3e8ebc1abeb2decefac21fda1d17.tar.gz
6655638: dynamic languages need method handles
Summary: initial implementation, with known omissions (x86/64, sparc, compiler optim., c-oops, C++ interp.) Reviewed-by: kvn, twisti, never
Diffstat (limited to 'src/cpu/sparc')
-rw-r--r--src/cpu/sparc/vm/assembler_sparc.cpp52
-rw-r--r--src/cpu/sparc/vm/assembler_sparc.hpp25
-rw-r--r--src/cpu/sparc/vm/assembler_sparc.inline.hpp9
-rw-r--r--src/cpu/sparc/vm/cppInterpreter_sparc.cpp11
-rw-r--r--src/cpu/sparc/vm/interpreterGenerator_sparc.hpp3
-rw-r--r--src/cpu/sparc/vm/interpreter_sparc.cpp16
-rw-r--r--src/cpu/sparc/vm/methodHandles_sparc.cpp70
-rw-r--r--src/cpu/sparc/vm/register_definitions_sparc.cpp4
-rw-r--r--src/cpu/sparc/vm/sharedRuntime_sparc.cpp12
-rw-r--r--src/cpu/sparc/vm/templateInterpreter_sparc.cpp22
10 files changed, 209 insertions, 15 deletions
diff --git a/src/cpu/sparc/vm/assembler_sparc.cpp b/src/cpu/sparc/vm/assembler_sparc.cpp
index 597a91ae3..d36caf55f 100644
--- a/src/cpu/sparc/vm/assembler_sparc.cpp
+++ b/src/cpu/sparc/vm/assembler_sparc.cpp
@@ -3029,6 +3029,58 @@ void MacroAssembler::check_klass_subtype_slow_path(Register sub_klass,
+void MacroAssembler::check_method_handle_type(Register mtype_reg, Register mh_reg,
+ Register temp_reg,
+ Label& wrong_method_type) {
+ assert_different_registers(mtype_reg, mh_reg, temp_reg);
+ // compare method type against that of the receiver
+ RegisterOrConstant mhtype_offset = delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg);
+ ld_ptr(mh_reg, mhtype_offset, temp_reg);
+ cmp(temp_reg, mtype_reg);
+ br(Assembler::notEqual, false, Assembler::pn, wrong_method_type);
+ delayed()->nop();
+}
+
+
+void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_reg) {
+ assert(mh_reg == G3_method_handle, "caller must put MH object in G3");
+ assert_different_registers(mh_reg, temp_reg);
+
+ // pick out the interpreted side of the handler
+ ld_ptr(mh_reg, delayed_value(java_dyn_MethodHandle::vmentry_offset_in_bytes, temp_reg), temp_reg);
+
+ // off we go...
+ ld_ptr(temp_reg, MethodHandleEntry::from_interpreted_entry_offset_in_bytes(), temp_reg);
+ jmp(temp_reg, 0);
+
+ // for the various stubs which take control at this point,
+ // see MethodHandles::generate_method_handle_stub
+
+ // (Can any caller use this delay slot? If so, add an option for supression.)
+ delayed()->nop();
+}
+
+RegisterOrConstant MacroAssembler::argument_offset(RegisterOrConstant arg_slot,
+ int extra_slot_offset) {
+ // cf. TemplateTable::prepare_invoke(), if (load_receiver).
+ int stackElementSize = Interpreter::stackElementWords() * wordSize;
+ int offset = Interpreter::expr_offset_in_bytes(extra_slot_offset+0);
+ int offset1 = Interpreter::expr_offset_in_bytes(extra_slot_offset+1);
+ assert(offset1 - offset == stackElementSize, "correct arithmetic");
+ if (arg_slot.is_constant()) {
+ offset += arg_slot.as_constant() * stackElementSize;
+ return offset;
+ } else {
+ Register temp = arg_slot.as_register();
+ sll_ptr(temp, exact_log2(stackElementSize), temp);
+ if (offset != 0)
+ add(temp, offset, temp);
+ return temp;
+ }
+}
+
+
+
void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg,
Register temp_reg,
Label& done, Label* slow_case,
diff --git a/src/cpu/sparc/vm/assembler_sparc.hpp b/src/cpu/sparc/vm/assembler_sparc.hpp
index 5c756c4b6..cfd935987 100644
--- a/src/cpu/sparc/vm/assembler_sparc.hpp
+++ b/src/cpu/sparc/vm/assembler_sparc.hpp
@@ -84,6 +84,10 @@ REGISTER_DECLARATION(Register, G4_scratch , G4);
REGISTER_DECLARATION(Register, Gtemp , G5);
+// JSR 292 fixed register usages:
+REGISTER_DECLARATION(Register, G5_method_type , G5);
+REGISTER_DECLARATION(Register, G3_method_handle , G3);
+
// The compiler requires that G5_megamorphic_method is G5_inline_cache_klass,
// because a single patchable "set" instruction (NativeMovConstReg,
// or NativeMovConstPatching for compiler1) instruction
@@ -91,9 +95,13 @@ REGISTER_DECLARATION(Register, Gtemp , G5);
// call site is an inline cache or is megamorphic. See the function
// CompiledIC::set_to_megamorphic.
//
-// On the other hand, G5_inline_cache_klass must differ from G5_method,
-// because both registers are needed for an inline cache that calls
-// an interpreted method.
+// If a inline cache targets an interpreted method, then the
+// G5 register will be used twice during the call. First,
+// the call site will be patched to load a compiledICHolder
+// into G5. (This is an ordered pair of ic_klass, method.)
+// The c2i adapter will first check the ic_klass, then load
+// G5_method with the method part of the pair just before
+// jumping into the interpreter.
//
// Note that G5_method is only the method-self for the interpreter,
// and is logically unrelated to G5_megamorphic_method.
@@ -1931,6 +1939,7 @@ class MacroAssembler: public Assembler {
inline void store_ptr_contents( Register s, Address& a, int offset = 0 );
inline void jumpl_to( Address& a, Register d, int offset = 0 );
inline void jump_to( Address& a, int offset = 0 );
+ inline void jump_indirect_to( Address& a, Register temp, int ld_offset = 0, int jmp_offset = 0 );
// ring buffer traceable jumps
@@ -2366,6 +2375,16 @@ class MacroAssembler: public Assembler {
Register temp2_reg,
Label& L_success);
+ // method handles (JSR 292)
+ void check_method_handle_type(Register mtype_reg, Register mh_reg,
+ Register temp_reg,
+ Label& wrong_method_type);
+ void jump_to_method_handle_entry(Register mh_reg, Register temp_reg);
+ // offset relative to Gargs of argument at tos[arg_slot].
+ // (arg_slot == 0 means the last argument, not the first).
+ RegisterOrConstant argument_offset(RegisterOrConstant arg_slot,
+ int extra_slot_offset = 0);
+
// Stack overflow checking
diff --git a/src/cpu/sparc/vm/assembler_sparc.inline.hpp b/src/cpu/sparc/vm/assembler_sparc.inline.hpp
index d9053f7f6..692c8650b 100644
--- a/src/cpu/sparc/vm/assembler_sparc.inline.hpp
+++ b/src/cpu/sparc/vm/assembler_sparc.inline.hpp
@@ -671,6 +671,15 @@ inline void MacroAssembler::jump_to( Address& a, int offset ) {
}
+inline void MacroAssembler::jump_indirect_to( Address& a, Register temp,
+ int ld_offset, int jmp_offset ) {
+ assert_not_delayed();
+ //sethi(a); // sethi is caller responsibility for this one
+ ld_ptr(a, temp, ld_offset);
+ jmp(temp, jmp_offset);
+}
+
+
inline void MacroAssembler::set_oop( jobject obj, Register d ) {
set_oop(allocate_oop_address(obj, d));
}
diff --git a/src/cpu/sparc/vm/cppInterpreter_sparc.cpp b/src/cpu/sparc/vm/cppInterpreter_sparc.cpp
index f2d6486f8..c89d6e169 100644
--- a/src/cpu/sparc/vm/cppInterpreter_sparc.cpp
+++ b/src/cpu/sparc/vm/cppInterpreter_sparc.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1017,6 +1017,7 @@ void CppInterpreterGenerator::generate_compute_interpreter_state(const Register
const int slop_factor = 2*wordSize;
const int fixed_size = ((sizeof(BytecodeInterpreter) + slop_factor) >> LogBytesPerWord) + // what is the slop factor?
+ //6815692//methodOopDesc::extra_stack_words() + // extra push slots for MH adapters
frame::memory_parameter_word_sp_offset + // register save area + param window
(native ? frame::interpreter_frame_extra_outgoing_argument_words : 0); // JNI, class
@@ -1163,6 +1164,9 @@ void CppInterpreterGenerator::generate_compute_interpreter_state(const Register
__ st_ptr(O2, XXX_STATE(_stack)); // PREPUSH
__ lduh(max_stack, O3); // Full size expression stack
+ guarantee(!EnableMethodHandles, "no support yet for java.dyn.MethodHandle"); //6815692
+ //6815692//if (EnableMethodHandles)
+ //6815692// __ inc(O3, methodOopDesc::extra_stack_entries());
__ sll(O3, LogBytesPerWord, O3);
__ sub(O2, O3, O3);
// __ sub(O3, wordSize, O3); // so prepush doesn't look out of bounds
@@ -2017,7 +2021,9 @@ static int size_activation_helper(int callee_extra_locals, int max_stack, int mo
const int fixed_size = sizeof(BytecodeInterpreter)/wordSize + // interpreter state object
frame::memory_parameter_word_sp_offset; // register save area + param window
+ const int extra_stack = 0; //6815692//methodOopDesc::extra_stack_entries();
return (round_to(max_stack +
+ extra_stack +
slop_factor +
fixed_size +
monitor_size +
@@ -2104,7 +2110,8 @@ void BytecodeInterpreter::layout_interpreterState(interpreterState to_fill,
// Need +1 here because stack_base points to the word just above the first expr stack entry
// and stack_limit is supposed to point to the word just below the last expr stack entry.
// See generate_compute_interpreter_state.
- to_fill->_stack_limit = stack_base - (method->max_stack() + 1);
+ int extra_stack = 0; //6815692//methodOopDesc::extra_stack_entries();
+ to_fill->_stack_limit = stack_base - (method->max_stack() + 1 + extra_stack);
to_fill->_monitor_base = (BasicObjectLock*) monitor_base;
// sparc specific
diff --git a/src/cpu/sparc/vm/interpreterGenerator_sparc.hpp b/src/cpu/sparc/vm/interpreterGenerator_sparc.hpp
index 3352d2abd..3ed9bc471 100644
--- a/src/cpu/sparc/vm/interpreterGenerator_sparc.hpp
+++ b/src/cpu/sparc/vm/interpreterGenerator_sparc.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@
address generate_normal_entry(bool synchronized);
address generate_native_entry(bool synchronized);
address generate_abstract_entry(void);
+ address generate_method_handle_entry(void);
address generate_math_entry(AbstractInterpreter::MethodKind kind);
address generate_empty_entry(void);
address generate_accessor_entry(void);
diff --git a/src/cpu/sparc/vm/interpreter_sparc.cpp b/src/cpu/sparc/vm/interpreter_sparc.cpp
index 898d37060..9f0dd7166 100644
--- a/src/cpu/sparc/vm/interpreter_sparc.cpp
+++ b/src/cpu/sparc/vm/interpreter_sparc.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -235,6 +235,19 @@ address InterpreterGenerator::generate_abstract_entry(void) {
}
+
+// Method handle invoker
+// Dispatch a method of the form java.dyn.MethodHandles::invoke(...)
+address InterpreterGenerator::generate_method_handle_entry(void) {
+ if (!EnableMethodHandles) {
+ return generate_abstract_entry();
+ }
+ return generate_abstract_entry(); //6815692//
+}
+
+
+
+
//----------------------------------------------------------------------------------------------------
// Entry points & stack frame layout
//
@@ -364,6 +377,7 @@ address AbstractInterpreterGenerator::generate_method_entry(AbstractInterpreter:
case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break;
case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break;
case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break;
+ case Interpreter::method_handle : entry_point = ((InterpreterGenerator*)this)->generate_method_handle_entry(); break;
case Interpreter::java_lang_math_sin : break;
case Interpreter::java_lang_math_cos : break;
case Interpreter::java_lang_math_tan : break;
diff --git a/src/cpu/sparc/vm/methodHandles_sparc.cpp b/src/cpu/sparc/vm/methodHandles_sparc.cpp
new file mode 100644
index 000000000..dd40006e1
--- /dev/null
+++ b/src/cpu/sparc/vm/methodHandles_sparc.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * 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/_methodHandles_sparc.cpp.incl"
+
+#define __ _masm->
+
+address MethodHandleEntry::start_compiled_entry(MacroAssembler* _masm,
+ address interpreted_entry) {
+ __ align(wordSize);
+ address target = __ pc() + sizeof(Data);
+ while (__ pc() < target) {
+ __ nop();
+ __ align(wordSize);
+ }
+
+ MethodHandleEntry* me = (MethodHandleEntry*) __ pc();
+ me->set_end_address(__ pc()); // set a temporary end_address
+ me->set_from_interpreted_entry(interpreted_entry);
+ me->set_type_checking_entry(NULL);
+
+ return (address) me;
+}
+
+MethodHandleEntry* MethodHandleEntry::finish_compiled_entry(MacroAssembler* _masm,
+ address start_addr) {
+ MethodHandleEntry* me = (MethodHandleEntry*) start_addr;
+ assert(me->end_address() == start_addr, "valid ME");
+
+ // Fill in the real end_address:
+ __ align(wordSize);
+ me->set_end_address(__ pc());
+
+ return me;
+}
+
+
+// Code generation
+address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm) {
+ ShouldNotReachHere(); //NYI, 6815692
+ return NULL;
+}
+
+// Generate an "entry" field for a method handle.
+// This determines how the method handle will respond to calls.
+void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) {
+ ShouldNotReachHere(); //NYI, 6815692
+}
diff --git a/src/cpu/sparc/vm/register_definitions_sparc.cpp b/src/cpu/sparc/vm/register_definitions_sparc.cpp
index d3e805570..410f62aeb 100644
--- a/src/cpu/sparc/vm/register_definitions_sparc.cpp
+++ b/src/cpu/sparc/vm/register_definitions_sparc.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -142,6 +142,8 @@ REGISTER_DEFINITION(Register, G1_scratch);
REGISTER_DEFINITION(Register, G3_scratch);
REGISTER_DEFINITION(Register, G4_scratch);
REGISTER_DEFINITION(Register, Gtemp);
+REGISTER_DEFINITION(Register, G5_method_type);
+REGISTER_DEFINITION(Register, G3_method_handle);
REGISTER_DEFINITION(Register, Lentry_args);
#ifdef CC_INTERP
diff --git a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp
index 5804fbbfe..e2bd04436 100644
--- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp
+++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -937,12 +937,12 @@ void AdapterGenerator::gen_i2c_adapter(
// Inputs:
// G2_thread - TLS
// G5_method - Method oop
- // O0 - Flag telling us to restore SP from O5
- // O4_args - Pointer to interpreter's args
- // O5 - Caller's saved SP, to be restored if needed
+ // G4 (Gargs) - Pointer to interpreter's args
+ // O0..O4 - free for scratch
+ // O5_savedSP - Caller's saved SP, to be restored if needed
// O6 - Current SP!
// O7 - Valid return address
- // L0-L7, I0-I7 - Caller's temps (no frame pushed yet)
+ // L0-L7, I0-I7 - Caller's temps (no frame pushed yet)
// Outputs:
// G2_thread - TLS
@@ -954,7 +954,7 @@ void AdapterGenerator::gen_i2c_adapter(
// F0-F7 - more outgoing args
- // O4 is about to get loaded up with compiled callee's args
+ // Gargs is the incoming argument base, and also an outgoing argument.
__ sub(Gargs, BytesPerWord, Gargs);
#ifdef ASSERT
diff --git a/src/cpu/sparc/vm/templateInterpreter_sparc.cpp b/src/cpu/sparc/vm/templateInterpreter_sparc.cpp
index 090242c17..6cbcf9272 100644
--- a/src/cpu/sparc/vm/templateInterpreter_sparc.cpp
+++ b/src/cpu/sparc/vm/templateInterpreter_sparc.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -108,6 +108,24 @@ address TemplateInterpreterGenerator::generate_ClassCastException_handler() {
}
+// Arguments are: required type in G5_method_type, and
+// failing object (or NULL) in G3_method_handle.
+address TemplateInterpreterGenerator::generate_WrongMethodType_handler() {
+ address entry = __ pc();
+ // expression stack must be empty before entering the VM if an exception
+ // happened
+ __ empty_expression_stack();
+ // load exception object
+ __ call_VM(Oexception,
+ CAST_FROM_FN_PTR(address,
+ InterpreterRuntime::throw_WrongMethodTypeException),
+ G5_method_type, // required
+ G3_method_handle); // actual
+ __ should_not_reach_here();
+ return entry;
+}
+
+
address TemplateInterpreterGenerator::generate_ArrayIndexOutOfBounds_handler(const char* name) {
address entry = __ pc();
// expression stack must be empty before entering the VM if an exception happened
@@ -448,6 +466,7 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
const int extra_space =
rounded_vm_local_words + // frame local scratch space
+ //6815692//methodOopDesc::extra_stack_words() + // extra push slots for MH adapters
frame::memory_parameter_word_sp_offset + // register save area
(native_call ? frame::interpreter_frame_extra_outgoing_argument_words : 0);
@@ -1447,6 +1466,7 @@ static int size_activation_helper(int callee_extra_locals, int max_stack, int mo
round_to(callee_extra_locals * Interpreter::stackElementWords(), WordsPerLong);
const int max_stack_words = max_stack * Interpreter::stackElementWords();
return (round_to((max_stack_words
+ //6815692//+ methodOopDesc::extra_stack_words()
+ rounded_vm_local_words
+ frame::memory_parameter_word_sp_offset), WordsPerLong)
// already rounded