8000780: make Zero build and run with JDK8
Reviewed-by: coleenp, dholmes, twisti
This commit is contained in:
parent
f0534ca470
commit
e184d5cc4e
@ -453,14 +453,30 @@ ifneq ($(OSNAME),windows)
|
|||||||
ifeq ($(JVM_VARIANT_ZEROSHARK), true)
|
ifeq ($(JVM_VARIANT_ZEROSHARK), true)
|
||||||
$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(SHARK_DIR)/%.$(LIBRARY_SUFFIX)
|
$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(SHARK_DIR)/%.$(LIBRARY_SUFFIX)
|
||||||
$(install-file)
|
$(install-file)
|
||||||
|
$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo): $(SHARK_DIR)/%.debuginfo
|
||||||
|
$(install-file)
|
||||||
|
$(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(SHARK_DIR)/%.diz
|
||||||
|
$(install-file)
|
||||||
$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(SHARK_DIR)/%.$(LIBRARY_SUFFIX)
|
$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(SHARK_DIR)/%.$(LIBRARY_SUFFIX)
|
||||||
$(install-file)
|
$(install-file)
|
||||||
|
$(EXPORT_SERVER_DIR)/%.debuginfo: $(SHARK_DIR)/%.debuginfo
|
||||||
|
$(install-file)
|
||||||
|
$(EXPORT_SERVER_DIR)/%.diz: $(SHARK_DIR)/%.diz
|
||||||
|
$(install-file)
|
||||||
endif
|
endif
|
||||||
ifeq ($(JVM_VARIANT_ZERO), true)
|
ifeq ($(JVM_VARIANT_ZERO), true)
|
||||||
$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(ZERO_DIR)/%.$(LIBRARY_SUFFIX)
|
$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(ZERO_DIR)/%.$(LIBRARY_SUFFIX)
|
||||||
$(install-file)
|
$(install-file)
|
||||||
|
$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(ZERO_DIR)/%.debuginfo
|
||||||
|
$(install-file)
|
||||||
|
$(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(ZERO_DIR)/%.diz
|
||||||
|
$(install-file)
|
||||||
$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(ZERO_DIR)/%.$(LIBRARY_SUFFIX)
|
$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(ZERO_DIR)/%.$(LIBRARY_SUFFIX)
|
||||||
$(install-file)
|
$(install-file)
|
||||||
|
$(EXPORT_SERVER_DIR)/%.debuginfo: $(ZERO_DIR)/%.debuginfo
|
||||||
|
$(install-file)
|
||||||
|
$(EXPORT_SERVER_DIR)/%.diz: $(ZERO_DIR)/%.diz
|
||||||
|
$(install-file)
|
||||||
endif
|
endif
|
||||||
ifeq ($(JVM_VARIANT_MINIMAL1), true)
|
ifeq ($(JVM_VARIANT_MINIMAL1), true)
|
||||||
$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(MINIMAL1_DIR)/%.$(LIBRARY_SUFFIX)
|
$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(MINIMAL1_DIR)/%.$(LIBRARY_SUFFIX)
|
||||||
|
@ -31,12 +31,17 @@
|
|||||||
return _masm;
|
return _masm;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
public:
|
||||||
address generate_entry(address entry_point) {
|
static address generate_entry_impl(MacroAssembler* masm, address entry_point) {
|
||||||
ZeroEntry *entry = (ZeroEntry *) assembler()->pc();
|
ZeroEntry *entry = (ZeroEntry *) masm->pc();
|
||||||
assembler()->advance(sizeof(ZeroEntry));
|
masm->advance(sizeof(ZeroEntry));
|
||||||
entry->set_entry_point(entry_point);
|
entry->set_entry_point(entry_point);
|
||||||
return (address) entry;
|
return (address) entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
address generate_entry(address entry_point) {
|
||||||
|
return generate_entry_impl(assembler(), entry_point);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // CPU_ZERO_VM_CPPINTERPRETERGENERATOR_ZERO_HPP
|
#endif // CPU_ZERO_VM_CPPINTERPRETERGENERATOR_ZERO_HPP
|
||||||
|
@ -180,25 +180,6 @@ void CppInterpreter::main_loop(int recurse, TRAPS) {
|
|||||||
method, istate->osr_entry(), istate->osr_buf(), THREAD);
|
method, istate->osr_entry(), istate->osr_buf(), THREAD);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (istate->msg() == BytecodeInterpreter::call_method_handle) {
|
|
||||||
oop method_handle = istate->callee();
|
|
||||||
|
|
||||||
// Trim back the stack to put the parameters at the top
|
|
||||||
stack->set_sp(istate->stack() + 1);
|
|
||||||
|
|
||||||
// Make the call
|
|
||||||
process_method_handle(method_handle, THREAD);
|
|
||||||
fixup_after_potential_safepoint();
|
|
||||||
|
|
||||||
// Convert the result
|
|
||||||
istate->set_stack(stack->sp() - 1);
|
|
||||||
|
|
||||||
// Restore the stack
|
|
||||||
stack->set_sp(istate->stack_limit() + 1);
|
|
||||||
|
|
||||||
// Resume the interpreter
|
|
||||||
istate->set_msg(BytecodeInterpreter::method_resume);
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
}
|
}
|
||||||
@ -535,35 +516,35 @@ int CppInterpreter::accessor_entry(Method* method, intptr_t UNUSED, TRAPS) {
|
|||||||
if (entry->is_volatile()) {
|
if (entry->is_volatile()) {
|
||||||
switch (entry->flag_state()) {
|
switch (entry->flag_state()) {
|
||||||
case ctos:
|
case ctos:
|
||||||
SET_LOCALS_INT(object->char_field_acquire(entry->f2()), 0);
|
SET_LOCALS_INT(object->char_field_acquire(entry->f2_as_index()), 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case btos:
|
case btos:
|
||||||
SET_LOCALS_INT(object->byte_field_acquire(entry->f2()), 0);
|
SET_LOCALS_INT(object->byte_field_acquire(entry->f2_as_index()), 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case stos:
|
case stos:
|
||||||
SET_LOCALS_INT(object->short_field_acquire(entry->f2()), 0);
|
SET_LOCALS_INT(object->short_field_acquire(entry->f2_as_index()), 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case itos:
|
case itos:
|
||||||
SET_LOCALS_INT(object->int_field_acquire(entry->f2()), 0);
|
SET_LOCALS_INT(object->int_field_acquire(entry->f2_as_index()), 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ltos:
|
case ltos:
|
||||||
SET_LOCALS_LONG(object->long_field_acquire(entry->f2()), 0);
|
SET_LOCALS_LONG(object->long_field_acquire(entry->f2_as_index()), 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ftos:
|
case ftos:
|
||||||
SET_LOCALS_FLOAT(object->float_field_acquire(entry->f2()), 0);
|
SET_LOCALS_FLOAT(object->float_field_acquire(entry->f2_as_index()), 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case dtos:
|
case dtos:
|
||||||
SET_LOCALS_DOUBLE(object->double_field_acquire(entry->f2()), 0);
|
SET_LOCALS_DOUBLE(object->double_field_acquire(entry->f2_as_index()), 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case atos:
|
case atos:
|
||||||
SET_LOCALS_OBJECT(object->obj_field_acquire(entry->f2()), 0);
|
SET_LOCALS_OBJECT(object->obj_field_acquire(entry->f2_as_index()), 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -573,35 +554,35 @@ int CppInterpreter::accessor_entry(Method* method, intptr_t UNUSED, TRAPS) {
|
|||||||
else {
|
else {
|
||||||
switch (entry->flag_state()) {
|
switch (entry->flag_state()) {
|
||||||
case ctos:
|
case ctos:
|
||||||
SET_LOCALS_INT(object->char_field(entry->f2()), 0);
|
SET_LOCALS_INT(object->char_field(entry->f2_as_index()), 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case btos:
|
case btos:
|
||||||
SET_LOCALS_INT(object->byte_field(entry->f2()), 0);
|
SET_LOCALS_INT(object->byte_field(entry->f2_as_index()), 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case stos:
|
case stos:
|
||||||
SET_LOCALS_INT(object->short_field(entry->f2()), 0);
|
SET_LOCALS_INT(object->short_field(entry->f2_as_index()), 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case itos:
|
case itos:
|
||||||
SET_LOCALS_INT(object->int_field(entry->f2()), 0);
|
SET_LOCALS_INT(object->int_field(entry->f2_as_index()), 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ltos:
|
case ltos:
|
||||||
SET_LOCALS_LONG(object->long_field(entry->f2()), 0);
|
SET_LOCALS_LONG(object->long_field(entry->f2_as_index()), 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ftos:
|
case ftos:
|
||||||
SET_LOCALS_FLOAT(object->float_field(entry->f2()), 0);
|
SET_LOCALS_FLOAT(object->float_field(entry->f2_as_index()), 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case dtos:
|
case dtos:
|
||||||
SET_LOCALS_DOUBLE(object->double_field(entry->f2()), 0);
|
SET_LOCALS_DOUBLE(object->double_field(entry->f2_as_index()), 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case atos:
|
case atos:
|
||||||
SET_LOCALS_OBJECT(object->obj_field(entry->f2()), 0);
|
SET_LOCALS_OBJECT(object->obj_field(entry->f2_as_index()), 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -629,516 +610,6 @@ int CppInterpreter::empty_entry(Method* method, intptr_t UNUSED, TRAPS) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CppInterpreter::method_handle_entry(Method* method,
|
|
||||||
intptr_t UNUSED, TRAPS) {
|
|
||||||
JavaThread *thread = (JavaThread *) THREAD;
|
|
||||||
ZeroStack *stack = thread->zero_stack();
|
|
||||||
int argument_slots = method->size_of_parameters();
|
|
||||||
int result_slots = type2size[result_type_of(method)];
|
|
||||||
intptr_t *vmslots = stack->sp();
|
|
||||||
intptr_t *unwind_sp = vmslots + argument_slots;
|
|
||||||
|
|
||||||
// Find the MethodType
|
|
||||||
address p = (address) method;
|
|
||||||
for (jint* pc = method->method_type_offsets_chain(); (*pc) != -1; pc++) {
|
|
||||||
p = *(address*)(p + (*pc));
|
|
||||||
}
|
|
||||||
oop method_type = (oop) p;
|
|
||||||
|
|
||||||
// The MethodHandle is in the slot after the arguments
|
|
||||||
int num_vmslots = argument_slots - 1;
|
|
||||||
oop method_handle = VMSLOTS_OBJECT(num_vmslots);
|
|
||||||
|
|
||||||
// InvokeGeneric requires some extra shuffling
|
|
||||||
oop mhtype = java_lang_invoke_MethodHandle::type(method_handle);
|
|
||||||
bool is_exact = mhtype == method_type;
|
|
||||||
if (!is_exact) {
|
|
||||||
if (true || // FIXME
|
|
||||||
method->intrinsic_id() == vmIntrinsics::_invokeExact) {
|
|
||||||
CALL_VM_NOCHECK_NOFIX(
|
|
||||||
SharedRuntime::throw_WrongMethodTypeException(
|
|
||||||
thread, method_type, mhtype));
|
|
||||||
// NB all oops trashed!
|
|
||||||
assert(HAS_PENDING_EXCEPTION, "should do");
|
|
||||||
stack->set_sp(unwind_sp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
assert(method->intrinsic_id() == vmIntrinsics::_invokeGeneric, "should be");
|
|
||||||
|
|
||||||
// Load up an adapter from the calling type
|
|
||||||
// NB the x86 code for this (in methodHandles_x86.cpp, search for
|
|
||||||
// "genericInvoker") is really really odd. I'm hoping it's trying
|
|
||||||
// to accomodate odd VM/class library combinations I can ignore.
|
|
||||||
oop adapter = NULL; //FIXME: load the adapter from the CP cache
|
|
||||||
IF (adapter == NULL) {
|
|
||||||
CALL_VM_NOCHECK_NOFIX(
|
|
||||||
SharedRuntime::throw_WrongMethodTypeException(
|
|
||||||
thread, method_type, mhtype));
|
|
||||||
// NB all oops trashed!
|
|
||||||
assert(HAS_PENDING_EXCEPTION, "should do");
|
|
||||||
stack->set_sp(unwind_sp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adapters are shared among form-families of method-type. The
|
|
||||||
// type being called is passed as a trusted first argument so that
|
|
||||||
// the adapter knows the actual types of its arguments and return
|
|
||||||
// values.
|
|
||||||
insert_vmslots(num_vmslots + 1, 1, THREAD);
|
|
||||||
if (HAS_PENDING_EXCEPTION) {
|
|
||||||
// NB all oops trashed!
|
|
||||||
stack->set_sp(unwind_sp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
vmslots = stack->sp();
|
|
||||||
num_vmslots++;
|
|
||||||
SET_VMSLOTS_OBJECT(method_type, num_vmslots);
|
|
||||||
|
|
||||||
method_handle = adapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start processing
|
|
||||||
process_method_handle(method_handle, THREAD);
|
|
||||||
if (HAS_PENDING_EXCEPTION)
|
|
||||||
result_slots = 0;
|
|
||||||
|
|
||||||
// If this is an invokeExact then the eventual callee will not
|
|
||||||
// have unwound the method handle argument so we have to do it.
|
|
||||||
// If a result is being returned the it will be above the method
|
|
||||||
// handle argument we're unwinding.
|
|
||||||
if (is_exact) {
|
|
||||||
intptr_t result[2];
|
|
||||||
for (int i = 0; i < result_slots; i++)
|
|
||||||
result[i] = stack->pop();
|
|
||||||
stack->pop();
|
|
||||||
for (int i = result_slots - 1; i >= 0; i--)
|
|
||||||
stack->push(result[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check
|
|
||||||
assert(stack->sp() == unwind_sp - result_slots, "should be");
|
|
||||||
|
|
||||||
// No deoptimized frames on the stack
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CppInterpreter::process_method_handle(oop method_handle, TRAPS) {
|
|
||||||
JavaThread *thread = (JavaThread *) THREAD;
|
|
||||||
ZeroStack *stack = thread->zero_stack();
|
|
||||||
intptr_t *vmslots = stack->sp();
|
|
||||||
|
|
||||||
bool direct_to_method = false;
|
|
||||||
BasicType src_rtype = T_ILLEGAL;
|
|
||||||
BasicType dst_rtype = T_ILLEGAL;
|
|
||||||
|
|
||||||
MethodHandleEntry *entry =
|
|
||||||
java_lang_invoke_MethodHandle::vmentry(method_handle);
|
|
||||||
MethodHandles::EntryKind entry_kind =
|
|
||||||
(MethodHandles::EntryKind) (((intptr_t) entry) & 0xffffffff);
|
|
||||||
|
|
||||||
Method* method = NULL;
|
|
||||||
switch (entry_kind) {
|
|
||||||
case MethodHandles::_invokestatic_mh:
|
|
||||||
direct_to_method = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MethodHandles::_invokespecial_mh:
|
|
||||||
case MethodHandles::_invokevirtual_mh:
|
|
||||||
case MethodHandles::_invokeinterface_mh:
|
|
||||||
{
|
|
||||||
oop receiver =
|
|
||||||
VMSLOTS_OBJECT(
|
|
||||||
java_lang_invoke_MethodHandle::vmslots(method_handle) - 1);
|
|
||||||
if (receiver == NULL) {
|
|
||||||
stack->set_sp(calculate_unwind_sp(stack, method_handle));
|
|
||||||
CALL_VM_NOCHECK_NOFIX(
|
|
||||||
throw_exception(
|
|
||||||
thread, vmSymbols::java_lang_NullPointerException()));
|
|
||||||
// NB all oops trashed!
|
|
||||||
assert(HAS_PENDING_EXCEPTION, "should do");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (entry_kind != MethodHandles::_invokespecial_mh) {
|
|
||||||
intptr_t index = java_lang_invoke_DirectMethodHandle::vmindex(method_handle);
|
|
||||||
InstanceKlass* rcvrKlass =
|
|
||||||
(InstanceKlass *) receiver->klass();
|
|
||||||
if (entry_kind == MethodHandles::_invokevirtual_mh) {
|
|
||||||
method = (Method*) rcvrKlass->start_of_vtable()[index];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
oop iclass = java_lang_invoke_MethodHandle::next_target(method_handle);
|
|
||||||
itableOffsetEntry* ki =
|
|
||||||
(itableOffsetEntry *) rcvrKlass->start_of_itable();
|
|
||||||
int i, length = rcvrKlass->itable_length();
|
|
||||||
for (i = 0; i < length; i++, ki++ ) {
|
|
||||||
if (ki->interface_klass() == iclass)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i == length) {
|
|
||||||
stack->set_sp(calculate_unwind_sp(stack, method_handle));
|
|
||||||
CALL_VM_NOCHECK_NOFIX(
|
|
||||||
throw_exception(
|
|
||||||
thread, vmSymbols::java_lang_IncompatibleClassChangeError()));
|
|
||||||
// NB all oops trashed!
|
|
||||||
assert(HAS_PENDING_EXCEPTION, "should do");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
itableMethodEntry* im = ki->first_method_entry(receiver->klass());
|
|
||||||
method = im[index].method();
|
|
||||||
if (method == NULL) {
|
|
||||||
stack->set_sp(calculate_unwind_sp(stack, method_handle));
|
|
||||||
CALL_VM_NOCHECK_NOFIX(
|
|
||||||
throw_exception(
|
|
||||||
thread, vmSymbols::java_lang_AbstractMethodError()));
|
|
||||||
// NB all oops trashed!
|
|
||||||
assert(HAS_PENDING_EXCEPTION, "should do");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
direct_to_method = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MethodHandles::_bound_ref_direct_mh:
|
|
||||||
case MethodHandles::_bound_int_direct_mh:
|
|
||||||
case MethodHandles::_bound_long_direct_mh:
|
|
||||||
direct_to_method = true;
|
|
||||||
// fall through
|
|
||||||
case MethodHandles::_bound_ref_mh:
|
|
||||||
case MethodHandles::_bound_int_mh:
|
|
||||||
case MethodHandles::_bound_long_mh:
|
|
||||||
{
|
|
||||||
BasicType arg_type = T_ILLEGAL;
|
|
||||||
int arg_mask = -1;
|
|
||||||
int arg_slots = -1;
|
|
||||||
MethodHandles::get_ek_bound_mh_info(
|
|
||||||
entry_kind, arg_type, arg_mask, arg_slots);
|
|
||||||
int arg_slot =
|
|
||||||
java_lang_invoke_BoundMethodHandle::vmargslot(method_handle);
|
|
||||||
|
|
||||||
// Create the new slot(s)
|
|
||||||
intptr_t *unwind_sp = calculate_unwind_sp(stack, method_handle);
|
|
||||||
insert_vmslots(arg_slot, arg_slots, THREAD);
|
|
||||||
if (HAS_PENDING_EXCEPTION) {
|
|
||||||
// all oops trashed
|
|
||||||
stack->set_sp(unwind_sp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
vmslots = stack->sp();
|
|
||||||
|
|
||||||
// Store bound argument into new stack slot
|
|
||||||
oop arg = java_lang_invoke_BoundMethodHandle::argument(method_handle);
|
|
||||||
if (arg_type == T_OBJECT) {
|
|
||||||
assert(arg_slots == 1, "should be");
|
|
||||||
SET_VMSLOTS_OBJECT(arg, arg_slot);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
jvalue arg_value;
|
|
||||||
arg_type = java_lang_boxing_object::get_value(arg, &arg_value);
|
|
||||||
switch (arg_type) {
|
|
||||||
case T_BOOLEAN:
|
|
||||||
SET_VMSLOTS_INT(arg_value.z, arg_slot);
|
|
||||||
break;
|
|
||||||
case T_CHAR:
|
|
||||||
SET_VMSLOTS_INT(arg_value.c, arg_slot);
|
|
||||||
break;
|
|
||||||
case T_BYTE:
|
|
||||||
SET_VMSLOTS_INT(arg_value.b, arg_slot);
|
|
||||||
break;
|
|
||||||
case T_SHORT:
|
|
||||||
SET_VMSLOTS_INT(arg_value.s, arg_slot);
|
|
||||||
break;
|
|
||||||
case T_INT:
|
|
||||||
SET_VMSLOTS_INT(arg_value.i, arg_slot);
|
|
||||||
break;
|
|
||||||
case T_FLOAT:
|
|
||||||
SET_VMSLOTS_FLOAT(arg_value.f, arg_slot);
|
|
||||||
break;
|
|
||||||
case T_LONG:
|
|
||||||
SET_VMSLOTS_LONG(arg_value.j, arg_slot + 1);
|
|
||||||
break;
|
|
||||||
case T_DOUBLE:
|
|
||||||
SET_VMSLOTS_DOUBLE(arg_value.d, arg_slot + 1);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
tty->print_cr("unhandled type %s", type2name(arg_type));
|
|
||||||
ShouldNotReachHere();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MethodHandles::_adapter_retype_only:
|
|
||||||
case MethodHandles::_adapter_retype_raw:
|
|
||||||
src_rtype = result_type_of_handle(
|
|
||||||
java_lang_invoke_MethodHandle::next_target(method_handle));
|
|
||||||
dst_rtype = result_type_of_handle(method_handle);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MethodHandles::_adapter_check_cast:
|
|
||||||
{
|
|
||||||
int arg_slot =
|
|
||||||
java_lang_invoke_AdapterMethodHandle::vmargslot(method_handle);
|
|
||||||
oop arg = VMSLOTS_OBJECT(arg_slot);
|
|
||||||
if (arg != NULL) {
|
|
||||||
Klass* objKlassOop = arg->klass();
|
|
||||||
Klass* klassOf = java_lang_Class::as_Klass(
|
|
||||||
java_lang_invoke_AdapterMethodHandle::argument(method_handle));
|
|
||||||
|
|
||||||
if (objKlassOop != klassOf &&
|
|
||||||
!objKlassOop->is_subtype_of(klassOf)) {
|
|
||||||
ResourceMark rm(THREAD);
|
|
||||||
const char* objName = Klass::cast(objKlassOop)->external_name();
|
|
||||||
const char* klassName = Klass::cast(klassOf)->external_name();
|
|
||||||
char* message = SharedRuntime::generate_class_cast_message(
|
|
||||||
objName, klassName);
|
|
||||||
|
|
||||||
stack->set_sp(calculate_unwind_sp(stack, method_handle));
|
|
||||||
CALL_VM_NOCHECK_NOFIX(
|
|
||||||
throw_exception(
|
|
||||||
thread, vmSymbols::java_lang_ClassCastException(), message));
|
|
||||||
// NB all oops trashed!
|
|
||||||
assert(HAS_PENDING_EXCEPTION, "should do");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MethodHandles::_adapter_dup_args:
|
|
||||||
{
|
|
||||||
int arg_slot =
|
|
||||||
java_lang_invoke_AdapterMethodHandle::vmargslot(method_handle);
|
|
||||||
int conv =
|
|
||||||
java_lang_invoke_AdapterMethodHandle::conversion(method_handle);
|
|
||||||
int num_slots = -MethodHandles::adapter_conversion_stack_move(conv);
|
|
||||||
assert(num_slots > 0, "should be");
|
|
||||||
|
|
||||||
// Create the new slot(s)
|
|
||||||
intptr_t *unwind_sp = calculate_unwind_sp(stack, method_handle);
|
|
||||||
stack->overflow_check(num_slots, THREAD);
|
|
||||||
if (HAS_PENDING_EXCEPTION) {
|
|
||||||
// all oops trashed
|
|
||||||
stack->set_sp(unwind_sp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Duplicate the arguments
|
|
||||||
for (int i = num_slots - 1; i >= 0; i--)
|
|
||||||
stack->push(*VMSLOTS_SLOT(arg_slot + i));
|
|
||||||
|
|
||||||
vmslots = stack->sp(); // unused, but let the compiler figure that out
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MethodHandles::_adapter_drop_args:
|
|
||||||
{
|
|
||||||
int arg_slot =
|
|
||||||
java_lang_invoke_AdapterMethodHandle::vmargslot(method_handle);
|
|
||||||
int conv =
|
|
||||||
java_lang_invoke_AdapterMethodHandle::conversion(method_handle);
|
|
||||||
int num_slots = MethodHandles::adapter_conversion_stack_move(conv);
|
|
||||||
assert(num_slots > 0, "should be");
|
|
||||||
|
|
||||||
remove_vmslots(arg_slot, num_slots, THREAD); // doesn't trap
|
|
||||||
vmslots = stack->sp(); // unused, but let the compiler figure that out
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MethodHandles::_adapter_opt_swap_1:
|
|
||||||
case MethodHandles::_adapter_opt_swap_2:
|
|
||||||
case MethodHandles::_adapter_opt_rot_1_up:
|
|
||||||
case MethodHandles::_adapter_opt_rot_1_down:
|
|
||||||
case MethodHandles::_adapter_opt_rot_2_up:
|
|
||||||
case MethodHandles::_adapter_opt_rot_2_down:
|
|
||||||
{
|
|
||||||
int arg1 =
|
|
||||||
java_lang_invoke_AdapterMethodHandle::vmargslot(method_handle);
|
|
||||||
int conv =
|
|
||||||
java_lang_invoke_AdapterMethodHandle::conversion(method_handle);
|
|
||||||
int arg2 = MethodHandles::adapter_conversion_vminfo(conv);
|
|
||||||
|
|
||||||
int swap_bytes = 0, rotate = 0;
|
|
||||||
MethodHandles::get_ek_adapter_opt_swap_rot_info(
|
|
||||||
entry_kind, swap_bytes, rotate);
|
|
||||||
int swap_slots = swap_bytes >> LogBytesPerWord;
|
|
||||||
|
|
||||||
intptr_t tmp;
|
|
||||||
switch (rotate) {
|
|
||||||
case 0: // swap
|
|
||||||
for (int i = 0; i < swap_slots; i++) {
|
|
||||||
tmp = *VMSLOTS_SLOT(arg1 + i);
|
|
||||||
SET_VMSLOTS_SLOT(VMSLOTS_SLOT(arg2 + i), arg1 + i);
|
|
||||||
SET_VMSLOTS_SLOT(&tmp, arg2 + i);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1: // up
|
|
||||||
assert(arg1 - swap_slots > arg2, "should be");
|
|
||||||
|
|
||||||
tmp = *VMSLOTS_SLOT(arg1);
|
|
||||||
for (int i = arg1 - swap_slots; i >= arg2; i--)
|
|
||||||
SET_VMSLOTS_SLOT(VMSLOTS_SLOT(i), i + swap_slots);
|
|
||||||
SET_VMSLOTS_SLOT(&tmp, arg2);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case -1: // down
|
|
||||||
assert(arg2 - swap_slots > arg1, "should be");
|
|
||||||
|
|
||||||
tmp = *VMSLOTS_SLOT(arg1);
|
|
||||||
for (int i = arg1 + swap_slots; i <= arg2; i++)
|
|
||||||
SET_VMSLOTS_SLOT(VMSLOTS_SLOT(i), i - swap_slots);
|
|
||||||
SET_VMSLOTS_SLOT(&tmp, arg2);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
ShouldNotReachHere();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MethodHandles::_adapter_opt_i2l:
|
|
||||||
{
|
|
||||||
int arg_slot =
|
|
||||||
java_lang_invoke_AdapterMethodHandle::vmargslot(method_handle);
|
|
||||||
int arg = VMSLOTS_INT(arg_slot);
|
|
||||||
intptr_t *unwind_sp = calculate_unwind_sp(stack, method_handle);
|
|
||||||
insert_vmslots(arg_slot, 1, THREAD);
|
|
||||||
if (HAS_PENDING_EXCEPTION) {
|
|
||||||
// all oops trashed
|
|
||||||
stack->set_sp(unwind_sp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
vmslots = stack->sp();
|
|
||||||
arg_slot++;
|
|
||||||
SET_VMSLOTS_LONG(arg, arg_slot);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MethodHandles::_adapter_opt_unboxi:
|
|
||||||
case MethodHandles::_adapter_opt_unboxl:
|
|
||||||
{
|
|
||||||
int arg_slot =
|
|
||||||
java_lang_invoke_AdapterMethodHandle::vmargslot(method_handle);
|
|
||||||
oop arg = VMSLOTS_OBJECT(arg_slot);
|
|
||||||
jvalue arg_value;
|
|
||||||
if (arg == NULL) {
|
|
||||||
// queue a nullpointer exception for the caller
|
|
||||||
stack->set_sp(calculate_unwind_sp(stack, method_handle));
|
|
||||||
CALL_VM_NOCHECK_NOFIX(
|
|
||||||
throw_exception(
|
|
||||||
thread, vmSymbols::java_lang_NullPointerException()));
|
|
||||||
// NB all oops trashed!
|
|
||||||
assert(HAS_PENDING_EXCEPTION, "should do");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
BasicType arg_type = java_lang_boxing_object::get_value(arg, &arg_value);
|
|
||||||
if (arg_type == T_LONG || arg_type == T_DOUBLE) {
|
|
||||||
intptr_t *unwind_sp = calculate_unwind_sp(stack, method_handle);
|
|
||||||
insert_vmslots(arg_slot, 1, THREAD);
|
|
||||||
if (HAS_PENDING_EXCEPTION) {
|
|
||||||
// all oops trashed
|
|
||||||
stack->set_sp(unwind_sp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
vmslots = stack->sp();
|
|
||||||
arg_slot++;
|
|
||||||
}
|
|
||||||
switch (arg_type) {
|
|
||||||
case T_BOOLEAN:
|
|
||||||
SET_VMSLOTS_INT(arg_value.z, arg_slot);
|
|
||||||
break;
|
|
||||||
case T_CHAR:
|
|
||||||
SET_VMSLOTS_INT(arg_value.c, arg_slot);
|
|
||||||
break;
|
|
||||||
case T_BYTE:
|
|
||||||
SET_VMSLOTS_INT(arg_value.b, arg_slot);
|
|
||||||
break;
|
|
||||||
case T_SHORT:
|
|
||||||
SET_VMSLOTS_INT(arg_value.s, arg_slot);
|
|
||||||
break;
|
|
||||||
case T_INT:
|
|
||||||
SET_VMSLOTS_INT(arg_value.i, arg_slot);
|
|
||||||
break;
|
|
||||||
case T_FLOAT:
|
|
||||||
SET_VMSLOTS_FLOAT(arg_value.f, arg_slot);
|
|
||||||
break;
|
|
||||||
case T_LONG:
|
|
||||||
SET_VMSLOTS_LONG(arg_value.j, arg_slot);
|
|
||||||
break;
|
|
||||||
case T_DOUBLE:
|
|
||||||
SET_VMSLOTS_DOUBLE(arg_value.d, arg_slot);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
tty->print_cr("unhandled type %s", type2name(arg_type));
|
|
||||||
ShouldNotReachHere();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
tty->print_cr("unhandled entry_kind %s",
|
|
||||||
MethodHandles::entry_name(entry_kind));
|
|
||||||
ShouldNotReachHere();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Continue along the chain
|
|
||||||
if (direct_to_method) {
|
|
||||||
if (method == NULL) {
|
|
||||||
method =
|
|
||||||
(Method*) java_lang_invoke_MethodHandle::vmtarget(method_handle);
|
|
||||||
}
|
|
||||||
address entry_point = method->from_interpreted_entry();
|
|
||||||
Interpreter::invoke_method(method, entry_point, THREAD);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
process_method_handle(
|
|
||||||
java_lang_invoke_MethodHandle::next_target(method_handle), THREAD);
|
|
||||||
}
|
|
||||||
// NB all oops now trashed
|
|
||||||
|
|
||||||
// Adapt the result type, if necessary
|
|
||||||
if (src_rtype != dst_rtype && !HAS_PENDING_EXCEPTION) {
|
|
||||||
switch (dst_rtype) {
|
|
||||||
case T_VOID:
|
|
||||||
for (int i = 0; i < type2size[src_rtype]; i++)
|
|
||||||
stack->pop();
|
|
||||||
return;
|
|
||||||
|
|
||||||
case T_INT:
|
|
||||||
switch (src_rtype) {
|
|
||||||
case T_VOID:
|
|
||||||
stack->overflow_check(1, CHECK);
|
|
||||||
stack->push(0);
|
|
||||||
return;
|
|
||||||
|
|
||||||
case T_BOOLEAN:
|
|
||||||
case T_CHAR:
|
|
||||||
case T_BYTE:
|
|
||||||
case T_SHORT:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// INT results sometimes need narrowing
|
|
||||||
case T_BOOLEAN:
|
|
||||||
case T_CHAR:
|
|
||||||
case T_BYTE:
|
|
||||||
case T_SHORT:
|
|
||||||
switch (src_rtype) {
|
|
||||||
case T_INT:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tty->print_cr("unhandled conversion:");
|
|
||||||
tty->print_cr("src_rtype = %s", type2name(src_rtype));
|
|
||||||
tty->print_cr("dst_rtype = %s", type2name(dst_rtype));
|
|
||||||
ShouldNotReachHere();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The new slots will be inserted before slot insert_before.
|
// The new slots will be inserted before slot insert_before.
|
||||||
// Slots < insert_before will have the same slot number after the insert.
|
// Slots < insert_before will have the same slot number after the insert.
|
||||||
// Slots >= insert_before will become old_slot + num_slots.
|
// Slots >= insert_before will become old_slot + num_slots.
|
||||||
@ -1380,10 +851,6 @@ address AbstractInterpreterGenerator::generate_method_entry(
|
|||||||
entry_point = ((InterpreterGenerator*) this)->generate_abstract_entry();
|
entry_point = ((InterpreterGenerator*) this)->generate_abstract_entry();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Interpreter::method_handle:
|
|
||||||
entry_point = ((InterpreterGenerator*) this)->generate_method_handle_entry();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Interpreter::java_lang_math_sin:
|
case Interpreter::java_lang_math_sin:
|
||||||
case Interpreter::java_lang_math_cos:
|
case Interpreter::java_lang_math_cos:
|
||||||
case Interpreter::java_lang_math_tan:
|
case Interpreter::java_lang_math_tan:
|
||||||
@ -1391,6 +858,8 @@ address AbstractInterpreterGenerator::generate_method_entry(
|
|||||||
case Interpreter::java_lang_math_log:
|
case Interpreter::java_lang_math_log:
|
||||||
case Interpreter::java_lang_math_log10:
|
case Interpreter::java_lang_math_log10:
|
||||||
case Interpreter::java_lang_math_sqrt:
|
case Interpreter::java_lang_math_sqrt:
|
||||||
|
case Interpreter::java_lang_math_pow:
|
||||||
|
case Interpreter::java_lang_math_exp:
|
||||||
entry_point = ((InterpreterGenerator*) this)->generate_math_entry(kind);
|
entry_point = ((InterpreterGenerator*) this)->generate_math_entry(kind);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -36,7 +36,6 @@
|
|||||||
static int native_entry(Method* method, intptr_t UNUSED, TRAPS);
|
static int native_entry(Method* method, intptr_t UNUSED, TRAPS);
|
||||||
static int accessor_entry(Method* method, intptr_t UNUSED, TRAPS);
|
static int accessor_entry(Method* method, intptr_t UNUSED, TRAPS);
|
||||||
static int empty_entry(Method* method, intptr_t UNUSED, TRAPS);
|
static int empty_entry(Method* method, intptr_t UNUSED, TRAPS);
|
||||||
static int method_handle_entry(Method* method, intptr_t UNUSED, TRAPS);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Main loop of normal_entry
|
// Main loop of normal_entry
|
||||||
@ -44,7 +43,6 @@
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// Helpers for method_handle_entry
|
// Helpers for method_handle_entry
|
||||||
static void process_method_handle(oop method_handle, TRAPS);
|
|
||||||
static void insert_vmslots(int insert_before, int num_slots, TRAPS);
|
static void insert_vmslots(int insert_before, int num_slots, TRAPS);
|
||||||
static void remove_vmslots(int first_slot, int num_slots, TRAPS);
|
static void remove_vmslots(int first_slot, int num_slots, TRAPS);
|
||||||
static BasicType result_type_of_handle(oop method_handle);
|
static BasicType result_type_of_handle(oop method_handle);
|
||||||
|
@ -351,7 +351,7 @@ void SharkFrame::identify_word(int frame_index,
|
|||||||
switch (offset) {
|
switch (offset) {
|
||||||
case pc_off:
|
case pc_off:
|
||||||
strncpy(fieldbuf, "pc", buflen);
|
strncpy(fieldbuf, "pc", buflen);
|
||||||
if (method()->is_oop()) {
|
if (method()->is_method()) {
|
||||||
nmethod *code = method()->code();
|
nmethod *code = method()->code();
|
||||||
if (code && code->pc_desc_at(pc())) {
|
if (code && code->pc_desc_at(pc())) {
|
||||||
SimpleScopeDesc ssd(code, pc());
|
SimpleScopeDesc ssd(code, pc());
|
||||||
@ -367,7 +367,7 @@ void SharkFrame::identify_word(int frame_index,
|
|||||||
|
|
||||||
case method_off:
|
case method_off:
|
||||||
strncpy(fieldbuf, "method", buflen);
|
strncpy(fieldbuf, "method", buflen);
|
||||||
if (method()->is_oop()) {
|
if (method()->is_method()) {
|
||||||
method()->name_and_sig_as_C_string(valuebuf, buflen);
|
method()->name_and_sig_as_C_string(valuebuf, buflen);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -378,7 +378,7 @@ void SharkFrame::identify_word(int frame_index,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Variable part
|
// Variable part
|
||||||
if (method()->is_oop()) {
|
if (method()->is_method()) {
|
||||||
identify_vp_word(frame_index, addr_of_word(offset),
|
identify_vp_word(frame_index, addr_of_word(offset),
|
||||||
addr_of_word(header_words + 1),
|
addr_of_word(header_words + 1),
|
||||||
unextended_sp() + method()->max_stack(),
|
unextended_sp() + method()->max_stack(),
|
||||||
@ -430,4 +430,3 @@ intptr_t *frame::initial_deoptimization_info() {
|
|||||||
// unused... but returns fp() to minimize changes introduced by 7087445
|
// unused... but returns fp() to minimize changes introduced by 7087445
|
||||||
return fp();
|
return fp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +36,8 @@ inline frame::frame() {
|
|||||||
_deopt_state = unknown;
|
_deopt_state = unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline address frame::sender_pc() const { ShouldNotCallThis(); }
|
||||||
|
|
||||||
inline frame::frame(ZeroFrame* zf, intptr_t* sp) {
|
inline frame::frame(ZeroFrame* zf, intptr_t* sp) {
|
||||||
_zeroframe = zf;
|
_zeroframe = zf;
|
||||||
_sp = sp;
|
_sp = sp;
|
||||||
|
@ -40,7 +40,7 @@ int InlineCacheBuffer::ic_stub_code_size() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin,
|
void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin,
|
||||||
Metadata* cached_oop,
|
void* cached_oop,
|
||||||
address entry_point) {
|
address entry_point) {
|
||||||
// NB ic_stub_code_size() must return the size of the code we generate
|
// NB ic_stub_code_size() must return the size of the code we generate
|
||||||
ShouldNotCallThis();
|
ShouldNotCallThis();
|
||||||
@ -51,7 +51,6 @@ address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) {
|
|||||||
ShouldNotCallThis();
|
ShouldNotCallThis();
|
||||||
}
|
}
|
||||||
|
|
||||||
Metadata* InlineCacheBuffer::ic_buffer_cached_oop(address code_begin) {
|
void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) {
|
||||||
// NB ic_stub_code_size() must return the size of the code we generate
|
|
||||||
ShouldNotCallThis();
|
ShouldNotCallThis();
|
||||||
}
|
}
|
||||||
|
@ -24,26 +24,159 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
|
#include "interpreter/interpreterGenerator.hpp"
|
||||||
#include "interpreter/interpreter.hpp"
|
#include "interpreter/interpreter.hpp"
|
||||||
#include "memory/allocation.inline.hpp"
|
#include "memory/allocation.inline.hpp"
|
||||||
#include "prims/methodHandles.hpp"
|
#include "prims/methodHandles.hpp"
|
||||||
|
|
||||||
int MethodHandles::adapter_conversion_ops_supported_mask() {
|
void MethodHandles::invoke_target(Method* method, TRAPS) {
|
||||||
return ((1<<java_lang_invoke_AdapterMethodHandle::OP_RETYPE_ONLY)
|
|
||||||
|(1<<java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW)
|
JavaThread *thread = (JavaThread *) THREAD;
|
||||||
|(1<<java_lang_invoke_AdapterMethodHandle::OP_CHECK_CAST)
|
ZeroStack *stack = thread->zero_stack();
|
||||||
|(1<<java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_PRIM)
|
InterpreterFrame *frame = thread->top_zero_frame()->as_interpreter_frame();
|
||||||
|(1<<java_lang_invoke_AdapterMethodHandle::OP_REF_TO_PRIM)
|
interpreterState istate = frame->interpreter_state();
|
||||||
|(1<<java_lang_invoke_AdapterMethodHandle::OP_SWAP_ARGS)
|
|
||||||
|(1<<java_lang_invoke_AdapterMethodHandle::OP_ROT_ARGS)
|
// Trim back the stack to put the parameters at the top
|
||||||
|(1<<java_lang_invoke_AdapterMethodHandle::OP_DUP_ARGS)
|
stack->set_sp(istate->stack() + 1);
|
||||||
|(1<<java_lang_invoke_AdapterMethodHandle::OP_DROP_ARGS)
|
|
||||||
//|(1<<java_lang_invoke_AdapterMethodHandle::OP_SPREAD_ARGS) //BUG!
|
Interpreter::invoke_method(method, method->from_interpreted_entry(), THREAD);
|
||||||
);
|
|
||||||
// FIXME: MethodHandlesTest gets a crash if we enable OP_SPREAD_ARGS.
|
// Convert the result
|
||||||
|
istate->set_stack(stack->sp() - 1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MethodHandles::generate_method_handle_stub(MacroAssembler* masm,
|
oop MethodHandles::popFromStack(TRAPS) {
|
||||||
MethodHandles::EntryKind ek) {
|
|
||||||
init_entry(ek, (MethodHandleEntry *) ek);
|
JavaThread *thread = (JavaThread *) THREAD;
|
||||||
|
InterpreterFrame *frame = thread->top_zero_frame()->as_interpreter_frame();
|
||||||
|
interpreterState istate = frame->interpreter_state();
|
||||||
|
intptr_t* topOfStack = istate->stack();
|
||||||
|
|
||||||
|
oop top = STACK_OBJECT(-1);
|
||||||
|
MORE_STACK(-1);
|
||||||
|
istate->set_stack(topOfStack);
|
||||||
|
|
||||||
|
return top;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int MethodHandles::method_handle_entry_invokeBasic(Method* method, intptr_t UNUSED, TRAPS) {
|
||||||
|
|
||||||
|
JavaThread *thread = (JavaThread *) THREAD;
|
||||||
|
InterpreterFrame *frame = thread->top_zero_frame()->as_interpreter_frame();
|
||||||
|
interpreterState istate = frame->interpreter_state();
|
||||||
|
intptr_t* topOfStack = istate->stack();
|
||||||
|
|
||||||
|
// 'this' is a MethodHandle. We resolve the target method by accessing this.form.vmentry.vmtarget.
|
||||||
|
int numArgs = method->size_of_parameters();
|
||||||
|
oop lform1 = java_lang_invoke_MethodHandle::form(STACK_OBJECT(-numArgs)); // this.form
|
||||||
|
oop vmEntry1 = java_lang_invoke_LambdaForm::vmentry(lform1);
|
||||||
|
Method* vmtarget = (Method*) java_lang_invoke_MemberName::vmtarget(vmEntry1);
|
||||||
|
|
||||||
|
invoke_target(vmtarget, THREAD);
|
||||||
|
|
||||||
|
// No deoptimized frames on the stack
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MethodHandles::method_handle_entry_linkToStaticOrSpecial(Method* method, intptr_t UNUSED, TRAPS) {
|
||||||
|
|
||||||
|
// Pop appendix argument from stack. This is a MemberName which we resolve to the
|
||||||
|
// target method.
|
||||||
|
oop vmentry = popFromStack(THREAD);
|
||||||
|
|
||||||
|
Method* vmtarget = (Method*) java_lang_invoke_MemberName::vmtarget(vmentry);
|
||||||
|
|
||||||
|
invoke_target(vmtarget, THREAD);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MethodHandles::method_handle_entry_linkToInterface(Method* method, intptr_t UNUSED, TRAPS) {
|
||||||
|
JavaThread *thread = (JavaThread *) THREAD;
|
||||||
|
InterpreterFrame *frame = thread->top_zero_frame()->as_interpreter_frame();
|
||||||
|
interpreterState istate = frame->interpreter_state();
|
||||||
|
|
||||||
|
// Pop appendix argument from stack. This is a MemberName which we resolve to the
|
||||||
|
// target method.
|
||||||
|
oop vmentry = popFromStack(THREAD);
|
||||||
|
intptr_t* topOfStack = istate->stack();
|
||||||
|
|
||||||
|
// Resolve target method by looking up in the receiver object's itable.
|
||||||
|
Klass* clazz = java_lang_Class::as_Klass(java_lang_invoke_MemberName::clazz(vmentry));
|
||||||
|
intptr_t vmindex = java_lang_invoke_MemberName::vmindex(vmentry);
|
||||||
|
Method* target = (Method*) java_lang_invoke_MemberName::vmtarget(vmentry);
|
||||||
|
|
||||||
|
int numArgs = target->size_of_parameters();
|
||||||
|
oop recv = STACK_OBJECT(-numArgs);
|
||||||
|
|
||||||
|
InstanceKlass* klass_part = InstanceKlass::cast(recv->klass());
|
||||||
|
itableOffsetEntry* ki = (itableOffsetEntry*) klass_part->start_of_itable();
|
||||||
|
int i;
|
||||||
|
for ( i = 0 ; i < klass_part->itable_length() ; i++, ki++ ) {
|
||||||
|
if (ki->interface_klass() == clazz) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
itableMethodEntry* im = ki->first_method_entry(recv->klass());
|
||||||
|
Method* vmtarget = im[vmindex].method();
|
||||||
|
|
||||||
|
invoke_target(vmtarget, THREAD);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MethodHandles::method_handle_entry_linkToVirtual(Method* method, intptr_t UNUSED, TRAPS) {
|
||||||
|
JavaThread *thread = (JavaThread *) THREAD;
|
||||||
|
|
||||||
|
InterpreterFrame *frame = thread->top_zero_frame()->as_interpreter_frame();
|
||||||
|
interpreterState istate = frame->interpreter_state();
|
||||||
|
|
||||||
|
// Pop appendix argument from stack. This is a MemberName which we resolve to the
|
||||||
|
// target method.
|
||||||
|
oop vmentry = popFromStack(THREAD);
|
||||||
|
intptr_t* topOfStack = istate->stack();
|
||||||
|
|
||||||
|
// Resolve target method by looking up in the receiver object's vtable.
|
||||||
|
intptr_t vmindex = java_lang_invoke_MemberName::vmindex(vmentry);
|
||||||
|
Method* target = (Method*) java_lang_invoke_MemberName::vmtarget(vmentry);
|
||||||
|
int numArgs = target->size_of_parameters();
|
||||||
|
oop recv = STACK_OBJECT(-numArgs);
|
||||||
|
Klass* clazz = recv->klass();
|
||||||
|
Klass* klass_part = InstanceKlass::cast(clazz);
|
||||||
|
klassVtable* vtable = klass_part->vtable();
|
||||||
|
Method* vmtarget = vtable->method_at(vmindex);
|
||||||
|
|
||||||
|
invoke_target(vmtarget, THREAD);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MethodHandles::method_handle_entry_invalid(Method* method, intptr_t UNUSED, TRAPS) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* masm,
|
||||||
|
vmIntrinsics::ID iid) {
|
||||||
|
switch (iid) {
|
||||||
|
case vmIntrinsics::_invokeGeneric:
|
||||||
|
case vmIntrinsics::_compiledLambdaForm:
|
||||||
|
// Perhaps surprisingly, the symbolic references visible to Java are not directly used.
|
||||||
|
// They are linked to Java-generated adapters via MethodHandleNatives.linkMethod.
|
||||||
|
// They all allow an appendix argument.
|
||||||
|
return InterpreterGenerator::generate_entry_impl(masm, (address) MethodHandles::method_handle_entry_invalid);
|
||||||
|
case vmIntrinsics::_invokeBasic:
|
||||||
|
return InterpreterGenerator::generate_entry_impl(masm, (address) MethodHandles::method_handle_entry_invokeBasic);
|
||||||
|
case vmIntrinsics::_linkToStatic:
|
||||||
|
case vmIntrinsics::_linkToSpecial:
|
||||||
|
return InterpreterGenerator::generate_entry_impl(masm, (address) MethodHandles::method_handle_entry_linkToStaticOrSpecial);
|
||||||
|
case vmIntrinsics::_linkToInterface:
|
||||||
|
return InterpreterGenerator::generate_entry_impl(masm, (address) MethodHandles::method_handle_entry_linkToInterface);
|
||||||
|
case vmIntrinsics::_linkToVirtual:
|
||||||
|
return InterpreterGenerator::generate_entry_impl(masm, (address) MethodHandles::method_handle_entry_linkToVirtual);
|
||||||
|
default:
|
||||||
|
ShouldNotReachHere();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,14 @@
|
|||||||
|
|
||||||
// Adapters
|
// Adapters
|
||||||
enum /* platform_dependent_constants */ {
|
enum /* platform_dependent_constants */ {
|
||||||
adapter_code_size = 0
|
adapter_code_size = sizeof(ZeroEntry) * (Interpreter::method_handle_invoke_LAST - Interpreter::method_handle_invoke_FIRST + 1)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
static oop popFromStack(TRAPS);
|
||||||
|
static void invoke_target(Method* method, TRAPS);
|
||||||
|
static int method_handle_entry_invokeBasic(Method* method, intptr_t UNUSED, TRAPS);
|
||||||
|
static int method_handle_entry_linkToStaticOrSpecial(Method* method, intptr_t UNUSED, TRAPS);
|
||||||
|
static int method_handle_entry_linkToVirtual(Method* method, intptr_t UNUSED, TRAPS);
|
||||||
|
static int method_handle_entry_linkToInterface(Method* method, intptr_t UNUSED, TRAPS);
|
||||||
|
static int method_handle_entry_invalid(Method* method, intptr_t UNUSED, TRAPS);
|
||||||
|
@ -114,5 +114,8 @@ class ConcreteRegisterImpl : public AbstractRegisterImpl {
|
|||||||
};
|
};
|
||||||
|
|
||||||
CONSTANT_REGISTER_DECLARATION(Register, noreg, (-1));
|
CONSTANT_REGISTER_DECLARATION(Register, noreg, (-1));
|
||||||
|
#ifndef DONT_USE_REGISTER_DEFINES
|
||||||
|
#define noreg ((Register)(noreg_RegisterEnumValue))
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // CPU_ZERO_VM_REGISTER_ZERO_HPP
|
#endif // CPU_ZERO_VM_REGISTER_ZERO_HPP
|
||||||
|
@ -77,3 +77,7 @@ void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src,
|
|||||||
CodeBuffer* dst) {
|
CodeBuffer* dst) {
|
||||||
ShouldNotCallThis();
|
ShouldNotCallThis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void metadata_Relocation::pd_fix_value(address x) {
|
||||||
|
ShouldNotCallThis();
|
||||||
|
}
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include "runtime/sharedRuntime.hpp"
|
#include "runtime/sharedRuntime.hpp"
|
||||||
#include "runtime/vframeArray.hpp"
|
#include "runtime/vframeArray.hpp"
|
||||||
#include "vmreg_zero.inline.hpp"
|
#include "vmreg_zero.inline.hpp"
|
||||||
|
|
||||||
#ifdef COMPILER1
|
#ifdef COMPILER1
|
||||||
#include "c1/c1_Runtime1.hpp"
|
#include "c1/c1_Runtime1.hpp"
|
||||||
#endif
|
#endif
|
||||||
@ -47,6 +48,12 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static address zero_null_code_stub() {
|
||||||
|
address start = ShouldNotCallThisStub();
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
|
int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
|
||||||
VMRegPair *regs,
|
VMRegPair *regs,
|
||||||
int total_args_passed,
|
int total_args_passed,
|
||||||
@ -63,16 +70,14 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(
|
|||||||
AdapterFingerPrint *fingerprint) {
|
AdapterFingerPrint *fingerprint) {
|
||||||
return AdapterHandlerLibrary::new_entry(
|
return AdapterHandlerLibrary::new_entry(
|
||||||
fingerprint,
|
fingerprint,
|
||||||
ShouldNotCallThisStub(),
|
CAST_FROM_FN_PTR(address,zero_null_code_stub),
|
||||||
ShouldNotCallThisStub(),
|
CAST_FROM_FN_PTR(address,zero_null_code_stub),
|
||||||
ShouldNotCallThisStub());
|
CAST_FROM_FN_PTR(address,zero_null_code_stub));
|
||||||
}
|
}
|
||||||
|
|
||||||
nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
|
nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
|
||||||
methodHandle method,
|
methodHandle method,
|
||||||
int compile_id,
|
int compile_id,
|
||||||
int total_args_passed,
|
|
||||||
int max_arg,
|
|
||||||
BasicType *sig_bt,
|
BasicType *sig_bt,
|
||||||
VMRegPair *regs,
|
VMRegPair *regs,
|
||||||
BasicType ret_type) {
|
BasicType ret_type) {
|
||||||
@ -96,19 +101,20 @@ uint SharedRuntime::out_preserve_stack_slots() {
|
|||||||
ShouldNotCallThis();
|
ShouldNotCallThis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JRT_LEAF(void, zero_stub())
|
||||||
|
ShouldNotCallThis();
|
||||||
|
JRT_END
|
||||||
|
|
||||||
static RuntimeStub* generate_empty_runtime_stub(const char* name) {
|
static RuntimeStub* generate_empty_runtime_stub(const char* name) {
|
||||||
CodeBuffer buffer(name, 0, 0);
|
return CAST_FROM_FN_PTR(RuntimeStub*,zero_stub);
|
||||||
return RuntimeStub::new_runtime_stub(name, &buffer, 0, 0, NULL, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static SafepointBlob* generate_empty_safepoint_blob() {
|
static SafepointBlob* generate_empty_safepoint_blob() {
|
||||||
CodeBuffer buffer("handler_blob", 0, 0);
|
return CAST_FROM_FN_PTR(SafepointBlob*,zero_stub);
|
||||||
return SafepointBlob::create(&buffer, NULL, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static DeoptimizationBlob* generate_empty_deopt_blob() {
|
static DeoptimizationBlob* generate_empty_deopt_blob() {
|
||||||
CodeBuffer buffer("handler_blob", 0, 0);
|
return CAST_FROM_FN_PTR(DeoptimizationBlob*,zero_stub);
|
||||||
return DeoptimizationBlob::create(&buffer, NULL, 0, 0, 0, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -116,7 +122,7 @@ void SharedRuntime::generate_deopt_blob() {
|
|||||||
_deopt_blob = generate_empty_deopt_blob();
|
_deopt_blob = generate_empty_deopt_blob();
|
||||||
}
|
}
|
||||||
|
|
||||||
SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, bool cause_return) {
|
SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_type) {
|
||||||
return generate_empty_safepoint_blob();
|
return generate_empty_safepoint_blob();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,6 +130,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha
|
|||||||
return generate_empty_runtime_stub("resolve_blob");
|
return generate_empty_runtime_stub("resolve_blob");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
|
int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
|
||||||
VMRegPair *regs,
|
VMRegPair *regs,
|
||||||
int total_args_passed) {
|
int total_args_passed) {
|
||||||
|
@ -758,7 +758,7 @@ void CodeBuffer::relocate_code_to(CodeBuffer* dest) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dest->blob() == NULL) {
|
if (dest->blob() == NULL && dest_filled != NULL) {
|
||||||
// Destination is a final resting place, not just another buffer.
|
// Destination is a final resting place, not just another buffer.
|
||||||
// Normalize uninitialized bytes in the final padding.
|
// Normalize uninitialized bytes in the final padding.
|
||||||
Copy::fill_to_bytes(dest_filled, dest_end - dest_filled,
|
Copy::fill_to_bytes(dest_filled, dest_end - dest_filled,
|
||||||
|
@ -320,6 +320,7 @@ class AbstractInterpreterGenerator: public StackObj {
|
|||||||
void bang_stack_shadow_pages(bool native_call);
|
void bang_stack_shadow_pages(bool native_call);
|
||||||
|
|
||||||
void generate_all();
|
void generate_all();
|
||||||
|
void initialize_method_handle_entries();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AbstractInterpreterGenerator(StubQueue* _code);
|
AbstractInterpreterGenerator(StubQueue* _code);
|
||||||
|
@ -235,10 +235,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// JavaStack Implementation
|
|
||||||
#define MORE_STACK(count) \
|
|
||||||
(topOfStack -= ((count) * Interpreter::stackElementWords))
|
|
||||||
|
|
||||||
|
|
||||||
#define UPDATE_PC(opsize) {pc += opsize; }
|
#define UPDATE_PC(opsize) {pc += opsize; }
|
||||||
/*
|
/*
|
||||||
@ -575,7 +571,7 @@ BytecodeInterpreter::run(interpreterState istate) {
|
|||||||
|
|
||||||
/* 0xE0 */ &&opc_default, &&opc_default, &&opc_default, &&opc_default,
|
/* 0xE0 */ &&opc_default, &&opc_default, &&opc_default, &&opc_default,
|
||||||
/* 0xE4 */ &&opc_default, &&opc_fast_aldc, &&opc_fast_aldc_w, &&opc_return_register_finalizer,
|
/* 0xE4 */ &&opc_default, &&opc_fast_aldc, &&opc_fast_aldc_w, &&opc_return_register_finalizer,
|
||||||
/* 0xE8 */ &&opc_default, &&opc_default, &&opc_default, &&opc_default,
|
/* 0xE8 */ &&opc_invokehandle,&&opc_default, &&opc_default, &&opc_default,
|
||||||
/* 0xEC */ &&opc_default, &&opc_default, &&opc_default, &&opc_default,
|
/* 0xEC */ &&opc_default, &&opc_default, &&opc_default, &&opc_default,
|
||||||
|
|
||||||
/* 0xF0 */ &&opc_default, &&opc_default, &&opc_default, &&opc_default,
|
/* 0xF0 */ &&opc_default, &&opc_default, &&opc_default, &&opc_default,
|
||||||
@ -1773,7 +1769,7 @@ run:
|
|||||||
|
|
||||||
oop obj;
|
oop obj;
|
||||||
if ((Bytecodes::Code)opcode == Bytecodes::_getstatic) {
|
if ((Bytecodes::Code)opcode == Bytecodes::_getstatic) {
|
||||||
Klass* k = (Klass*) cache->f1();
|
Klass* k = cache->f1_as_klass();
|
||||||
obj = k->java_mirror();
|
obj = k->java_mirror();
|
||||||
MORE_STACK(1); // Assume single slot push
|
MORE_STACK(1); // Assume single slot push
|
||||||
} else {
|
} else {
|
||||||
@ -1885,7 +1881,7 @@ run:
|
|||||||
--count;
|
--count;
|
||||||
}
|
}
|
||||||
if ((Bytecodes::Code)opcode == Bytecodes::_putstatic) {
|
if ((Bytecodes::Code)opcode == Bytecodes::_putstatic) {
|
||||||
Klass* k = (Klass*) cache->f1();
|
Klass* k = cache->f1_as_klass();
|
||||||
obj = k->java_mirror();
|
obj = k->java_mirror();
|
||||||
} else {
|
} else {
|
||||||
--count;
|
--count;
|
||||||
@ -2190,6 +2186,7 @@ run:
|
|||||||
}
|
}
|
||||||
|
|
||||||
CASE(_invokedynamic): {
|
CASE(_invokedynamic): {
|
||||||
|
|
||||||
if (!EnableInvokeDynamic) {
|
if (!EnableInvokeDynamic) {
|
||||||
// We should not encounter this bytecode if !EnableInvokeDynamic.
|
// We should not encounter this bytecode if !EnableInvokeDynamic.
|
||||||
// The verifier will stop it. However, if we get past the verifier,
|
// The verifier will stop it. However, if we get past the verifier,
|
||||||
@ -2199,30 +2196,68 @@ run:
|
|||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
}
|
}
|
||||||
|
|
||||||
int index = Bytes::get_native_u4(pc+1);
|
u4 index = Bytes::get_native_u4(pc+1);
|
||||||
|
ConstantPoolCacheEntry* cache = cp->constant_pool()->invokedynamic_cp_cache_entry_at(index);
|
||||||
|
|
||||||
// We are resolved if the resolved_references field contains a non-null object (CallSite, etc.)
|
// We are resolved if the resolved_references field contains a non-null object (CallSite, etc.)
|
||||||
// This kind of CP cache entry does not need to match the flags byte, because
|
// This kind of CP cache entry does not need to match the flags byte, because
|
||||||
// there is a 1-1 relation between bytecode type and CP entry type.
|
// there is a 1-1 relation between bytecode type and CP entry type.
|
||||||
ConstantPool* constants = METHOD->constants();
|
if (! cache->is_resolved((Bytecodes::Code) opcode)) {
|
||||||
oop result = constants->resolved_references()->obj_at(index);
|
|
||||||
if (result == NULL) {
|
|
||||||
CALL_VM(InterpreterRuntime::resolve_invokedynamic(THREAD),
|
CALL_VM(InterpreterRuntime::resolve_invokedynamic(THREAD),
|
||||||
handle_exception);
|
handle_exception);
|
||||||
result = THREAD->vm_result();
|
cache = cp->constant_pool()->invokedynamic_cp_cache_entry_at(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
VERIFY_OOP(result);
|
Method* method = cache->f1_as_method();
|
||||||
oop method_handle = java_lang_invoke_CallSite::target(result);
|
VERIFY_OOP(method);
|
||||||
CHECK_NULL(method_handle);
|
|
||||||
|
|
||||||
istate->set_msg(call_method_handle);
|
if (cache->has_appendix()) {
|
||||||
istate->set_callee((Method*) method_handle);
|
ConstantPool* constants = METHOD->constants();
|
||||||
|
SET_STACK_OBJECT(cache->appendix_if_resolved(constants), 0);
|
||||||
|
MORE_STACK(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
istate->set_msg(call_method);
|
||||||
|
istate->set_callee(method);
|
||||||
|
istate->set_callee_entry_point(method->from_interpreted_entry());
|
||||||
istate->set_bcp_advance(5);
|
istate->set_bcp_advance(5);
|
||||||
|
|
||||||
UPDATE_PC_AND_RETURN(0); // I'll be back...
|
UPDATE_PC_AND_RETURN(0); // I'll be back...
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CASE(_invokehandle): {
|
||||||
|
|
||||||
|
if (!EnableInvokeDynamic) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
|
||||||
|
u2 index = Bytes::get_native_u2(pc+1);
|
||||||
|
ConstantPoolCacheEntry* cache = cp->entry_at(index);
|
||||||
|
|
||||||
|
if (! cache->is_resolved((Bytecodes::Code) opcode)) {
|
||||||
|
CALL_VM(InterpreterRuntime::resolve_invokehandle(THREAD),
|
||||||
|
handle_exception);
|
||||||
|
cache = cp->entry_at(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
Method* method = cache->f1_as_method();
|
||||||
|
|
||||||
|
VERIFY_OOP(method);
|
||||||
|
|
||||||
|
if (cache->has_appendix()) {
|
||||||
|
ConstantPool* constants = METHOD->constants();
|
||||||
|
SET_STACK_OBJECT(cache->appendix_if_resolved(constants), 0);
|
||||||
|
MORE_STACK(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
istate->set_msg(call_method);
|
||||||
|
istate->set_callee(method);
|
||||||
|
istate->set_callee_entry_point(method->from_interpreted_entry());
|
||||||
|
istate->set_bcp_advance(3);
|
||||||
|
|
||||||
|
UPDATE_PC_AND_RETURN(0); // I'll be back...
|
||||||
|
}
|
||||||
|
|
||||||
CASE(_invokeinterface): {
|
CASE(_invokeinterface): {
|
||||||
u2 index = Bytes::get_native_u2(pc+1);
|
u2 index = Bytes::get_native_u2(pc+1);
|
||||||
|
|
||||||
|
@ -50,6 +50,10 @@
|
|||||||
|
|
||||||
#ifdef CC_INTERP
|
#ifdef CC_INTERP
|
||||||
|
|
||||||
|
// JavaStack Implementation
|
||||||
|
#define MORE_STACK(count) \
|
||||||
|
(topOfStack -= ((count) * Interpreter::stackElementWords))
|
||||||
|
|
||||||
// CVM definitions find hotspot equivalents...
|
// CVM definitions find hotspot equivalents...
|
||||||
|
|
||||||
union VMJavaVal64 {
|
union VMJavaVal64 {
|
||||||
@ -107,7 +111,6 @@ public:
|
|||||||
rethrow_exception, // unwinding and throwing exception
|
rethrow_exception, // unwinding and throwing exception
|
||||||
// requests to frame manager from C++ interpreter
|
// requests to frame manager from C++ interpreter
|
||||||
call_method, // request for new frame from interpreter, manager responds with method_entry
|
call_method, // request for new frame from interpreter, manager responds with method_entry
|
||||||
call_method_handle, // like the above, except the callee is a method handle
|
|
||||||
return_from_method, // request from interpreter to unwind, manager responds with method_continue
|
return_from_method, // request from interpreter to unwind, manager responds with method_continue
|
||||||
more_monitors, // need a new monitor
|
more_monitors, // need a new monitor
|
||||||
throwing_exception, // unwind stack and rethrow
|
throwing_exception, // unwind stack and rethrow
|
||||||
|
@ -117,7 +117,6 @@ void CppInterpreterGenerator::generate_all() {
|
|||||||
method_entry(empty);
|
method_entry(empty);
|
||||||
method_entry(accessor);
|
method_entry(accessor);
|
||||||
method_entry(abstract);
|
method_entry(abstract);
|
||||||
method_entry(method_handle);
|
|
||||||
method_entry(java_lang_math_sin );
|
method_entry(java_lang_math_sin );
|
||||||
method_entry(java_lang_math_cos );
|
method_entry(java_lang_math_cos );
|
||||||
method_entry(java_lang_math_tan );
|
method_entry(java_lang_math_tan );
|
||||||
@ -125,7 +124,12 @@ void CppInterpreterGenerator::generate_all() {
|
|||||||
method_entry(java_lang_math_sqrt );
|
method_entry(java_lang_math_sqrt );
|
||||||
method_entry(java_lang_math_log );
|
method_entry(java_lang_math_log );
|
||||||
method_entry(java_lang_math_log10 );
|
method_entry(java_lang_math_log10 );
|
||||||
|
method_entry(java_lang_math_pow );
|
||||||
|
method_entry(java_lang_math_exp );
|
||||||
method_entry(java_lang_ref_reference_get);
|
method_entry(java_lang_ref_reference_get);
|
||||||
|
|
||||||
|
initialize_method_handle_entries();
|
||||||
|
|
||||||
Interpreter::_native_entry_begin = Interpreter::code()->code_end();
|
Interpreter::_native_entry_begin = Interpreter::code()->code_end();
|
||||||
method_entry(native);
|
method_entry(native);
|
||||||
method_entry(native_synchronized);
|
method_entry(native_synchronized);
|
||||||
|
@ -464,3 +464,11 @@ void AbstractInterpreterGenerator::bang_stack_shadow_pages(bool native_call) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AbstractInterpreterGenerator::initialize_method_handle_entries() {
|
||||||
|
// method handle entry kinds are generated later in MethodHandlesAdapterGenerator::generate:
|
||||||
|
for (int i = Interpreter::method_handle_invoke_FIRST; i <= Interpreter::method_handle_invoke_LAST; i++) {
|
||||||
|
Interpreter::MethodKind kind = (Interpreter::MethodKind) i;
|
||||||
|
Interpreter::_entry_table[kind] = Interpreter::_entry_table[Interpreter::abstract];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -373,11 +373,7 @@ void TemplateInterpreterGenerator::generate_all() {
|
|||||||
method_entry(java_lang_math_pow )
|
method_entry(java_lang_math_pow )
|
||||||
method_entry(java_lang_ref_reference_get)
|
method_entry(java_lang_ref_reference_get)
|
||||||
|
|
||||||
// method handle entry kinds are generated later in MethodHandlesAdapterGenerator::generate:
|
initialize_method_handle_entries();
|
||||||
for (int i = Interpreter::method_handle_invoke_FIRST; i <= Interpreter::method_handle_invoke_LAST; i++) {
|
|
||||||
Interpreter::MethodKind kind = (Interpreter::MethodKind) i;
|
|
||||||
Interpreter::_entry_table[kind] = Interpreter::_entry_table[Interpreter::abstract];
|
|
||||||
}
|
|
||||||
|
|
||||||
// all native method kinds (must be one contiguous block)
|
// all native method kinds (must be one contiguous block)
|
||||||
Interpreter::_native_entry_begin = Interpreter::code()->code_end();
|
Interpreter::_native_entry_begin = Interpreter::code()->code_end();
|
||||||
|
@ -2474,7 +2474,7 @@ typedef BinaryTreeDictionary<Metablock, FreeList> MetablockTreeDictionary;
|
|||||||
/* frame */ \
|
/* frame */ \
|
||||||
/**********************/ \
|
/**********************/ \
|
||||||
\
|
\
|
||||||
X86_ONLY(declare_constant(frame::entry_frame_call_wrapper_offset)) \
|
NOT_ZERO(X86_ONLY(declare_constant(frame::entry_frame_call_wrapper_offset))) \
|
||||||
declare_constant(frame::pc_return_offset) \
|
declare_constant(frame::pc_return_offset) \
|
||||||
\
|
\
|
||||||
/*************/ \
|
/*************/ \
|
||||||
|
@ -282,6 +282,22 @@
|
|||||||
#define NOT_WIN64(code) code
|
#define NOT_WIN64(code) code
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(ZERO)
|
||||||
|
#define ZERO_ONLY(code) code
|
||||||
|
#define NOT_ZERO(code)
|
||||||
|
#else
|
||||||
|
#define ZERO_ONLY(code)
|
||||||
|
#define NOT_ZERO(code) code
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(SHARK)
|
||||||
|
#define SHARK_ONLY(code) code
|
||||||
|
#define NOT_SHARK(code)
|
||||||
|
#else
|
||||||
|
#define SHARK_ONLY(code)
|
||||||
|
#define NOT_SHARK(code) code
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(IA32) || defined(AMD64)
|
#if defined(IA32) || defined(AMD64)
|
||||||
#define X86
|
#define X86
|
||||||
#define X86_ONLY(code) code
|
#define X86_ONLY(code) code
|
||||||
|
Loading…
x
Reference in New Issue
Block a user