# HG changeset patch # User jrose # Date 1302881366 25200 # Node ID 97e8046e2562ea0bfff485b94a08a7661aa3c069 # Parent 3449f5e02cc446b879e6d98e98d5ea979ffcb66b# Parent e9b9554f7fc31109d462b47a269c0c37bbfd483c Merge diff -r 3449f5e02cc4 -r 97e8046e2562 src/cpu/x86/vm/assembler_x86.cpp --- a/src/cpu/x86/vm/assembler_x86.cpp Tue Apr 12 14:18:53 2011 -0700 +++ b/src/cpu/x86/vm/assembler_x86.cpp Fri Apr 15 08:29:26 2011 -0700 @@ -2317,7 +2317,7 @@ } void Assembler::prefetchr(Address src) { - NOT_LP64(assert(VM_Version::supports_3dnow(), "must support")); + NOT_LP64(assert(VM_Version::supports_3dnow_prefetch(), "must support")); InstructionMark im(this); prefetch_prefix(src); emit_byte(0x0D); @@ -2349,7 +2349,7 @@ } void Assembler::prefetchw(Address src) { - NOT_LP64(assert(VM_Version::supports_3dnow(), "must support")); + NOT_LP64(assert(VM_Version::supports_3dnow_prefetch(), "must support")); InstructionMark im(this); prefetch_prefix(src); emit_byte(0x0D); diff -r 3449f5e02cc4 -r 97e8046e2562 src/cpu/x86/vm/c1_LIRAssembler_x86.cpp --- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Tue Apr 12 14:18:53 2011 -0700 +++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Fri Apr 15 08:29:26 2011 -0700 @@ -1401,7 +1401,7 @@ default: ShouldNotReachHere(); break; } - } else if (VM_Version::supports_3dnow()) { + } else if (VM_Version::supports_3dnow_prefetch()) { __ prefetchr(from_addr); } } @@ -1424,7 +1424,7 @@ default: ShouldNotReachHere(); break; } - } else if (VM_Version::supports_3dnow()) { + } else if (VM_Version::supports_3dnow_prefetch()) { __ prefetchw(from_addr); } } diff -r 3449f5e02cc4 -r 97e8046e2562 src/cpu/x86/vm/vm_version_x86.cpp --- a/src/cpu/x86/vm/vm_version_x86.cpp Tue Apr 12 14:18:53 2011 -0700 +++ b/src/cpu/x86/vm/vm_version_x86.cpp Fri Apr 15 08:29:26 2011 -0700 @@ -348,7 +348,7 @@ } char buf[256]; - jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", cores_per_cpu(), threads_per_core(), cpu_family(), _model, _stepping, (supports_cmov() ? ", cmov" : ""), @@ -363,8 +363,7 @@ (supports_sse4_2() ? ", sse4.2" : ""), (supports_popcnt() ? ", popcnt" : ""), (supports_mmx_ext() ? ", mmxext" : ""), - (supports_3dnow() ? ", 3dnow" : ""), - (supports_3dnow2() ? ", 3dnowext" : ""), + (supports_3dnow_prefetch() ? ", 3dnowpref" : ""), (supports_lzcnt() ? ", lzcnt": ""), (supports_sse4a() ? ", sse4a": ""), (supports_ht() ? ", ht": "")); @@ -522,13 +521,13 @@ // set valid Prefetch instruction if( ReadPrefetchInstr < 0 ) ReadPrefetchInstr = 0; if( ReadPrefetchInstr > 3 ) ReadPrefetchInstr = 3; - if( ReadPrefetchInstr == 3 && !supports_3dnow() ) ReadPrefetchInstr = 0; - if( !supports_sse() && supports_3dnow() ) ReadPrefetchInstr = 3; + if( ReadPrefetchInstr == 3 && !supports_3dnow_prefetch() ) ReadPrefetchInstr = 0; + if( !supports_sse() && supports_3dnow_prefetch() ) ReadPrefetchInstr = 3; if( AllocatePrefetchInstr < 0 ) AllocatePrefetchInstr = 0; if( AllocatePrefetchInstr > 3 ) AllocatePrefetchInstr = 3; - if( AllocatePrefetchInstr == 3 && !supports_3dnow() ) AllocatePrefetchInstr=0; - if( !supports_sse() && supports_3dnow() ) AllocatePrefetchInstr = 3; + if( AllocatePrefetchInstr == 3 && !supports_3dnow_prefetch() ) AllocatePrefetchInstr=0; + if( !supports_sse() && supports_3dnow_prefetch() ) AllocatePrefetchInstr = 3; // Allocation prefetch settings intx cache_line_size = L1_data_cache_line_size(); @@ -576,10 +575,10 @@ logical_processors_per_package()); tty->print_cr("UseSSE=%d",UseSSE); tty->print("Allocation: "); - if (AllocatePrefetchStyle <= 0 || UseSSE == 0 && !supports_3dnow()) { + if (AllocatePrefetchStyle <= 0 || UseSSE == 0 && !supports_3dnow_prefetch()) { tty->print_cr("no prefetching"); } else { - if (UseSSE == 0 && supports_3dnow()) { + if (UseSSE == 0 && supports_3dnow_prefetch()) { tty->print("PREFETCHW"); } else if (UseSSE >= 1) { if (AllocatePrefetchInstr == 0) { diff -r 3449f5e02cc4 -r 97e8046e2562 src/cpu/x86/vm/vm_version_x86.hpp --- a/src/cpu/x86/vm/vm_version_x86.hpp Tue Apr 12 14:18:53 2011 -0700 +++ b/src/cpu/x86/vm/vm_version_x86.hpp Fri Apr 15 08:29:26 2011 -0700 @@ -188,7 +188,8 @@ CPU_FXSR = (1 << 2), CPU_HT = (1 << 3), CPU_MMX = (1 << 4), - CPU_3DNOW = (1 << 5), // 3DNow comes from cpuid 0x80000001 (EDX) + CPU_3DNOW_PREFETCH = (1 << 5), // Processor supports 3dnow prefetch and prefetchw instructions + // may not necessarily support other 3dnow instructions CPU_SSE = (1 << 6), CPU_SSE2 = (1 << 7), CPU_SSE3 = (1 << 8), // SSE3 comes from cpuid 1 (ECX) @@ -328,8 +329,9 @@ // AMD features. if (is_amd()) { - if (_cpuid_info.ext_cpuid1_edx.bits.tdnow != 0) - result |= CPU_3DNOW; + if ((_cpuid_info.ext_cpuid1_edx.bits.tdnow != 0) || + (_cpuid_info.ext_cpuid1_ecx.bits.prefetchw != 0)) + result |= CPU_3DNOW_PREFETCH; if (_cpuid_info.ext_cpuid1_ecx.bits.lzcnt != 0) result |= CPU_LZCNT; if (_cpuid_info.ext_cpuid1_ecx.bits.sse4a != 0) @@ -446,9 +448,8 @@ // // AMD features // - static bool supports_3dnow() { return (_cpuFeatures & CPU_3DNOW) != 0; } + static bool supports_3dnow_prefetch() { return (_cpuFeatures & CPU_3DNOW_PREFETCH) != 0; } static bool supports_mmx_ext() { return is_amd() && _cpuid_info.ext_cpuid1_edx.bits.mmx_amd != 0; } - static bool supports_3dnow2() { return is_amd() && _cpuid_info.ext_cpuid1_edx.bits.tdnow2 != 0; } static bool supports_lzcnt() { return (_cpuFeatures & CPU_LZCNT) != 0; } static bool supports_sse4a() { return (_cpuFeatures & CPU_SSE4A) != 0; } diff -r 3449f5e02cc4 -r 97e8046e2562 src/cpu/x86/vm/x86_32.ad --- a/src/cpu/x86/vm/x86_32.ad Tue Apr 12 14:18:53 2011 -0700 +++ b/src/cpu/x86/vm/x86_32.ad Fri Apr 15 08:29:26 2011 -0700 @@ -3423,7 +3423,7 @@ masm.movptr(boxReg, tmpReg); // consider: LEA box, [tmp-2] // Using a prefetchw helps avoid later RTS->RTO upgrades and cache probes - if ((EmitSync & 2048) && VM_Version::supports_3dnow() && os::is_MP()) { + if ((EmitSync & 2048) && VM_Version::supports_3dnow_prefetch() && os::is_MP()) { // prefetchw [eax + Offset(_owner)-2] masm.prefetchw(Address(rax, ObjectMonitor::owner_offset_in_bytes()-2)); } @@ -3467,7 +3467,7 @@ masm.movptr(boxReg, tmpReg) ; // Using a prefetchw helps avoid later RTS->RTO upgrades and cache probes - if ((EmitSync & 2048) && VM_Version::supports_3dnow() && os::is_MP()) { + if ((EmitSync & 2048) && VM_Version::supports_3dnow_prefetch() && os::is_MP()) { // prefetchw [eax + Offset(_owner)-2] masm.prefetchw(Address(rax, ObjectMonitor::owner_offset_in_bytes()-2)); } @@ -3614,7 +3614,7 @@ // See also http://gee.cs.oswego.edu/dl/jmm/cookbook.html. masm.get_thread (boxReg) ; - if ((EmitSync & 4096) && VM_Version::supports_3dnow() && os::is_MP()) { + if ((EmitSync & 4096) && VM_Version::supports_3dnow_prefetch() && os::is_MP()) { // prefetchw [ebx + Offset(_owner)-2] masm.prefetchw(Address(rbx, ObjectMonitor::owner_offset_in_bytes()-2)); } @@ -7333,7 +7333,7 @@ // Must be safe to execute with invalid address (cannot fault). instruct prefetchr0( memory mem ) %{ - predicate(UseSSE==0 && !VM_Version::supports_3dnow()); + predicate(UseSSE==0 && !VM_Version::supports_3dnow_prefetch()); match(PrefetchRead mem); ins_cost(0); size(0); @@ -7343,7 +7343,7 @@ %} instruct prefetchr( memory mem ) %{ - predicate(UseSSE==0 && VM_Version::supports_3dnow() || ReadPrefetchInstr==3); + predicate(UseSSE==0 && VM_Version::supports_3dnow_prefetch() || ReadPrefetchInstr==3); match(PrefetchRead mem); ins_cost(100); @@ -7387,7 +7387,7 @@ %} instruct prefetchw0( memory mem ) %{ - predicate(UseSSE==0 && !VM_Version::supports_3dnow()); + predicate(UseSSE==0 && !VM_Version::supports_3dnow_prefetch()); match(PrefetchWrite mem); ins_cost(0); size(0); @@ -7397,7 +7397,7 @@ %} instruct prefetchw( memory mem ) %{ - predicate(UseSSE==0 && VM_Version::supports_3dnow() || AllocatePrefetchInstr==3); + predicate(UseSSE==0 && VM_Version::supports_3dnow_prefetch() || AllocatePrefetchInstr==3); match( PrefetchWrite mem ); ins_cost(100); diff -r 3449f5e02cc4 -r 97e8046e2562 src/cpu/zero/vm/bytecodeInterpreter_zero.hpp --- a/src/cpu/zero/vm/bytecodeInterpreter_zero.hpp Tue Apr 12 14:18:53 2011 -0700 +++ b/src/cpu/zero/vm/bytecodeInterpreter_zero.hpp Fri Apr 15 08:29:26 2011 -0700 @@ -1,6 +1,6 @@ /* * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2007, 2008 Red Hat, Inc. + * Copyright 2007, 2008, 2011 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 @@ -150,4 +150,22 @@ #define SET_LOCALS_LONG_FROM_ADDR(addr, offset) (((VMJavaVal64*)&locals[-((offset)+1)])->l = \ ((VMJavaVal64*)(addr))->l) +// VMSlots implementation + +#define VMSLOTS_SLOT(offset) ((intptr_t*)&vmslots[(offset)]) +#define VMSLOTS_ADDR(offset) ((address)vmslots[(offset)]) +#define VMSLOTS_INT(offset) (*((jint*)&vmslots[(offset)])) +#define VMSLOTS_FLOAT(offset) (*((jfloat*)&vmslots[(offset)])) +#define VMSLOTS_OBJECT(offset) ((oop)vmslots[(offset)]) +#define VMSLOTS_DOUBLE(offset) (((VMJavaVal64*)&vmslots[(offset) - 1])->d) +#define VMSLOTS_LONG(offset) (((VMJavaVal64*)&vmslots[(offset) - 1])->l) + +#define SET_VMSLOTS_SLOT(value, offset) (*(intptr_t*)&vmslots[(offset)] = *(intptr_t *)(value)) +#define SET_VMSLOTS_ADDR(value, offset) (*((address *)&vmslots[(offset)]) = (value)) +#define SET_VMSLOTS_INT(value, offset) (*((jint *)&vmslots[(offset)]) = (value)) +#define SET_VMSLOTS_FLOAT(value, offset) (*((jfloat *)&vmslots[(offset)]) = (value)) +#define SET_VMSLOTS_OBJECT(value, offset) (*((oop *)&vmslots[(offset)]) = (value)) +#define SET_VMSLOTS_DOUBLE(value, offset) (((VMJavaVal64*)&vmslots[(offset) - 1])->d = (value)) +#define SET_VMSLOTS_LONG(value, offset) (((VMJavaVal64*)&vmslots[(offset) - 1])->l = (value)) + #endif // CPU_ZERO_VM_BYTECODEINTERPRETER_ZERO_HPP diff -r 3449f5e02cc4 -r 97e8046e2562 src/cpu/zero/vm/cppInterpreter_zero.cpp --- a/src/cpu/zero/vm/cppInterpreter_zero.cpp Tue Apr 12 14:18:53 2011 -0700 +++ b/src/cpu/zero/vm/cppInterpreter_zero.cpp Fri Apr 15 08:29:26 2011 -0700 @@ -1,6 +1,6 @@ /* * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. - * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. + * Copyright 2007, 2008, 2009, 2010, 2011 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 @@ -56,10 +56,13 @@ #define fixup_after_potential_safepoint() \ method = istate->method() -#define CALL_VM_NOCHECK(func) \ +#define CALL_VM_NOCHECK_NOFIX(func) \ thread->set_last_Java_frame(); \ func; \ - thread->reset_last_Java_frame(); \ + thread->reset_last_Java_frame(); + +#define CALL_VM_NOCHECK(func) \ + CALL_VM_NOCHECK_NOFIX(func) \ fixup_after_potential_safepoint() int CppInterpreter::normal_entry(methodOop method, intptr_t UNUSED, TRAPS) { @@ -177,6 +180,25 @@ method, istate->osr_entry(), istate->osr_buf(), THREAD); 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 { ShouldNotReachHere(); } @@ -607,6 +629,549 @@ return 0; } +int CppInterpreter::method_handle_entry(methodOop 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 + oop form = java_lang_invoke_MethodType::form(method_type); + int num_vmslots = java_lang_invoke_MethodTypeForm::vmslots(form); + assert(argument_slots == num_vmslots + 1, "should be"); + 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 (method->intrinsic_id() == vmIntrinsics::_invokeExact) { + CALL_VM_NOCHECK_NOFIX( + InterpreterRuntime::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 = java_lang_invoke_MethodTypeForm::genericInvoker(form); + if (adapter == NULL) { + CALL_VM_NOCHECK_NOFIX( + InterpreterRuntime::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); + + methodOop 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) { + int index = java_lang_invoke_DirectMethodHandle::vmindex(method_handle); + instanceKlass* rcvrKlass = + (instanceKlass *) receiver->klass()->klass_part(); + if (entry_kind == MethodHandles::_invokevirtual_mh) { + method = (methodOop) rcvrKlass->start_of_vtable()[index]; + } + else { + oop iclass = java_lang_invoke_MethodHandle::vmtarget(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::vmtarget(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) { + klassOop objKlassOop = arg->klass(); + klassOop klassOf = java_lang_Class::as_klassOop( + java_lang_invoke_AdapterMethodHandle::argument(method_handle)); + + if (objKlassOop != klassOf && + !objKlassOop->klass_part()->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; + 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 = + (methodOop) 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::vmtarget(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; + } + } + + 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. +// Slots < insert_before will have the same slot number after the insert. +// Slots >= insert_before will become old_slot + num_slots. +void CppInterpreter::insert_vmslots(int insert_before, int num_slots, TRAPS) { + JavaThread *thread = (JavaThread *) THREAD; + ZeroStack *stack = thread->zero_stack(); + + // Allocate the space + stack->overflow_check(num_slots, CHECK); + stack->alloc(num_slots * wordSize); + intptr_t *vmslots = stack->sp(); + + // Shuffle everything up + for (int i = 0; i < insert_before; i++) + SET_VMSLOTS_SLOT(VMSLOTS_SLOT(i + num_slots), i); +} + +void CppInterpreter::remove_vmslots(int first_slot, int num_slots, TRAPS) { + JavaThread *thread = (JavaThread *) THREAD; + ZeroStack *stack = thread->zero_stack(); + intptr_t *vmslots = stack->sp(); + + // Move everything down + for (int i = first_slot - 1; i >= 0; i--) + SET_VMSLOTS_SLOT(VMSLOTS_SLOT(i), i + num_slots); + + // Deallocate the space + stack->set_sp(stack->sp() + num_slots); +} + +BasicType CppInterpreter::result_type_of_handle(oop method_handle) { + oop method_type = java_lang_invoke_MethodHandle::type(method_handle); + oop return_type = java_lang_invoke_MethodType::rtype(method_type); + return java_lang_Class::as_BasicType(return_type, (klassOop *) NULL); +} + +intptr_t* CppInterpreter::calculate_unwind_sp(ZeroStack* stack, + oop method_handle) { + oop method_type = java_lang_invoke_MethodHandle::type(method_handle); + oop form = java_lang_invoke_MethodType::form(method_type); + int argument_slots = java_lang_invoke_MethodTypeForm::vmslots(form); + + return stack->sp() + argument_slots; +} + +IRT_ENTRY(void, CppInterpreter::throw_exception(JavaThread* thread, + Symbol* name, + char* message)) + THROW_MSG(name, message); +IRT_END + InterpreterFrame *InterpreterFrame::build(const methodOop method, TRAPS) { JavaThread *thread = (JavaThread *) THREAD; ZeroStack *stack = thread->zero_stack(); diff -r 3449f5e02cc4 -r 97e8046e2562 src/cpu/zero/vm/cppInterpreter_zero.hpp --- a/src/cpu/zero/vm/cppInterpreter_zero.hpp Tue Apr 12 14:18:53 2011 -0700 +++ b/src/cpu/zero/vm/cppInterpreter_zero.hpp Fri Apr 15 08:29:26 2011 -0700 @@ -1,6 +1,6 @@ /* * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2007, 2008, 2010 Red Hat, Inc. + * Copyright 2007, 2008, 2010, 2011 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 @@ -36,12 +36,22 @@ static int native_entry(methodOop method, intptr_t UNUSED, TRAPS); static int accessor_entry(methodOop method, intptr_t UNUSED, TRAPS); static int empty_entry(methodOop method, intptr_t UNUSED, TRAPS); + static int method_handle_entry(methodOop method, intptr_t UNUSED, TRAPS); public: // Main loop of normal_entry static void main_loop(int recurse, TRAPS); private: + // 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 remove_vmslots(int first_slot, int num_slots, TRAPS); + static BasicType result_type_of_handle(oop method_handle); + static intptr_t* calculate_unwind_sp(ZeroStack* stack, oop method_handle); + static void throw_exception(JavaThread* thread, Symbol* name,char *msg=NULL); + + private: // Fast result type determination static BasicType result_type_of(methodOop method); diff -r 3449f5e02cc4 -r 97e8046e2562 src/cpu/zero/vm/interpreter_zero.cpp --- a/src/cpu/zero/vm/interpreter_zero.cpp Tue Apr 12 14:18:53 2011 -0700 +++ b/src/cpu/zero/vm/interpreter_zero.cpp Fri Apr 15 08:29:26 2011 -0700 @@ -1,6 +1,6 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. + * Copyright 2007, 2008, 2009, 2010, 2011 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 @@ -49,6 +49,9 @@ #ifdef COMPILER1 #include "c1/c1_Runtime1.hpp" #endif +#ifdef CC_INTERP +#include "interpreter/cppInterpreter.hpp" +#endif address AbstractInterpreterGenerator::generate_slow_signature_handler() { _masm->advance(1); @@ -64,11 +67,15 @@ } address InterpreterGenerator::generate_abstract_entry() { - return ShouldNotCallThisEntry(); + return generate_entry((address) ShouldNotCallThisEntry()); } address InterpreterGenerator::generate_method_handle_entry() { - return ShouldNotCallThisEntry(); +#ifdef CC_INTERP + return generate_entry((address) CppInterpreter::method_handle_entry); +#else + return generate_entry((address) ShouldNotCallThisEntry()); +#endif // CC_INTERP } bool AbstractInterpreter::can_be_compiled(methodHandle m) { diff -r 3449f5e02cc4 -r 97e8046e2562 src/cpu/zero/vm/methodHandles_zero.cpp --- a/src/cpu/zero/vm/methodHandles_zero.cpp Tue Apr 12 14:18:53 2011 -0700 +++ b/src/cpu/zero/vm/methodHandles_zero.cpp Fri Apr 15 08:29:26 2011 -0700 @@ -1,6 +1,6 @@ /* * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2009, 2010 Red Hat, Inc. + * Copyright 2009, 2010, 2011 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 @@ -29,10 +29,21 @@ #include "prims/methodHandles.hpp" int MethodHandles::adapter_conversion_ops_supported_mask() { - ShouldNotCallThis(); + return ((1<owned_by_self()) { return _heap->largest_free_block(); } else { - // Avoid lock ordering problems with ttyLock. - ttyUnlocker ttyul; MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); return _heap->largest_free_block(); } diff -r 3449f5e02cc4 -r 97e8046e2562 src/share/vm/compiler/compileBroker.cpp --- a/src/share/vm/compiler/compileBroker.cpp Tue Apr 12 14:18:53 2011 -0700 +++ b/src/share/vm/compiler/compileBroker.cpp Fri Apr 15 08:29:26 2011 -0700 @@ -1736,8 +1736,14 @@ UseInterpreter = true; if (UseCompiler || AlwaysCompileLoopMethods ) { if (xtty != NULL) { + stringStream s; + // Dump code cache state into a buffer before locking the tty, + // because log_state() will use locks causing lock conflicts. + CodeCache::log_state(&s); + // Lock to prevent tearing + ttyLocker ttyl; xtty->begin_elem("code_cache_full"); - CodeCache::log_state(xtty); + xtty->print(s.as_string()); xtty->stamp(); xtty->end_elem(); } diff -r 3449f5e02cc4 -r 97e8046e2562 src/share/vm/interpreter/bytecodeInterpreter.cpp --- a/src/share/vm/interpreter/bytecodeInterpreter.cpp Tue Apr 12 14:18:53 2011 -0700 +++ b/src/share/vm/interpreter/bytecodeInterpreter.cpp Fri Apr 15 08:29:26 2011 -0700 @@ -554,7 +554,7 @@ /* 0xB0 */ &&opc_areturn, &&opc_return, &&opc_getstatic, &&opc_putstatic, /* 0xB4 */ &&opc_getfield, &&opc_putfield, &&opc_invokevirtual,&&opc_invokespecial, -/* 0xB8 */ &&opc_invokestatic,&&opc_invokeinterface,&&opc_default, &&opc_new, +/* 0xB8 */ &&opc_invokestatic,&&opc_invokeinterface,&&opc_invokedynamic,&&opc_new, /* 0xBC */ &&opc_newarray, &&opc_anewarray, &&opc_arraylength, &&opc_athrow, /* 0xC0 */ &&opc_checkcast, &&opc_instanceof, &&opc_monitorenter, &&opc_monitorexit, @@ -568,7 +568,7 @@ /* 0xDC */ &&opc_default, &&opc_default, &&opc_default, &&opc_default, /* 0xE0 */ &&opc_default, &&opc_default, &&opc_default, &&opc_default, -/* 0xE4 */ &&opc_default, &&opc_default, &&opc_default, &&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, /* 0xEC */ &&opc_default, &&opc_default, &&opc_default, &&opc_default, @@ -1718,8 +1718,7 @@ } // Need to throw illegal monitor state exception CALL_VM(InterpreterRuntime::throw_illegal_monitor_state_exception(THREAD), handle_exception); - // Should never reach here... - assert(false, "Should have thrown illegal monitor exception"); + ShouldNotReachHere(); } /* All of the non-quick opcodes. */ @@ -2147,6 +2146,74 @@ UPDATE_PC_AND_TOS_AND_CONTINUE(3, 2); } + CASE(_fast_aldc_w): + CASE(_fast_aldc): { + if (!EnableInvokeDynamic) { + // We should not encounter this bytecode if !EnableInvokeDynamic. + // The verifier will stop it. However, if we get past the verifier, + // this will stop the thread in a reasonable way, without crashing the JVM. + CALL_VM(InterpreterRuntime::throw_IncompatibleClassChangeError(THREAD), + handle_exception); + ShouldNotReachHere(); + } + + u2 index; + int incr; + if (opcode == Bytecodes::_fast_aldc) { + index = pc[1]; + incr = 2; + } else { + index = Bytes::get_native_u2(pc+1); + incr = 3; + } + + // We are resolved if the f1 field contains a non-null object (CallSite, etc.) + // 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. + ConstantPoolCacheEntry* cache = cp->entry_at(index); + if (cache->is_f1_null()) { + CALL_VM(InterpreterRuntime::resolve_ldc(THREAD, (Bytecodes::Code) opcode), + handle_exception); + } + + VERIFY_OOP(cache->f1()); + SET_STACK_OBJECT(cache->f1(), 0); + UPDATE_PC_AND_TOS_AND_CONTINUE(incr, 1); + } + + CASE(_invokedynamic): { + if (!EnableInvokeDynamic) { + // We should not encounter this bytecode if !EnableInvokeDynamic. + // The verifier will stop it. However, if we get past the verifier, + // this will stop the thread in a reasonable way, without crashing the JVM. + CALL_VM(InterpreterRuntime::throw_IncompatibleClassChangeError(THREAD), + handle_exception); + ShouldNotReachHere(); + } + + int index = Bytes::get_native_u4(pc+1); + + // We are resolved if the f1 field contains a non-null object (CallSite, etc.) + // 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. + assert(constantPoolCacheOopDesc::is_secondary_index(index), "incorrect format"); + ConstantPoolCacheEntry* cache = cp->secondary_entry_at(index); + if (cache->is_f1_null()) { + CALL_VM(InterpreterRuntime::resolve_invokedynamic(THREAD), + handle_exception); + } + + VERIFY_OOP(cache->f1()); + oop method_handle = java_lang_invoke_CallSite::target(cache->f1()); + CHECK_NULL(method_handle); + + istate->set_msg(call_method_handle); + istate->set_callee((methodOop) method_handle); + istate->set_bcp_advance(5); + + UPDATE_PC_AND_RETURN(0); // I'll be back... + } + CASE(_invokeinterface): { u2 index = Bytes::get_native_u2(pc+1); diff -r 3449f5e02cc4 -r 97e8046e2562 src/share/vm/interpreter/bytecodeInterpreter.hpp --- a/src/share/vm/interpreter/bytecodeInterpreter.hpp Tue Apr 12 14:18:53 2011 -0700 +++ b/src/share/vm/interpreter/bytecodeInterpreter.hpp Fri Apr 15 08:29:26 2011 -0700 @@ -107,6 +107,7 @@ rethrow_exception, // unwinding and throwing exception // requests to frame manager from C++ interpreter 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 more_monitors, // need a new monitor throwing_exception, // unwind stack and rethrow diff -r 3449f5e02cc4 -r 97e8046e2562 src/share/vm/oops/methodOop.cpp --- a/src/share/vm/oops/methodOop.cpp Tue Apr 12 14:18:53 2011 -0700 +++ b/src/share/vm/oops/methodOop.cpp Fri Apr 15 08:29:26 2011 -0700 @@ -921,6 +921,10 @@ tty->cr(); } + // invariant: cp->symbol_at_put is preceded by a refcount increment (more usually a lookup) + name->increment_refcount(); + signature->increment_refcount(); + constantPoolHandle cp; { constantPoolOop cp_oop = oopFactory::new_constantPool(_imcp_limit, IsSafeConc, CHECK_(empty)); diff -r 3449f5e02cc4 -r 97e8046e2562 src/share/vm/opto/parse2.cpp --- a/src/share/vm/opto/parse2.cpp Tue Apr 12 14:18:53 2011 -0700 +++ b/src/share/vm/opto/parse2.cpp Fri Apr 15 08:29:26 2011 -0700 @@ -795,8 +795,9 @@ taken = method()->scale_count(taken); not_taken = method()->scale_count(not_taken); - // Give up if too few counts to be meaningful - if (taken + not_taken < 40) { + // Give up if too few (or too many, in which case the sum will overflow) counts to be meaningful. + // We also check that individual counters are positive first, overwise the sum can become positive. + if (taken < 0 || not_taken < 0 || taken + not_taken < 40) { if (C->log() != NULL) { C->log()->elem("branch target_bci='%d' taken='%d' not_taken='%d'", iter().get_dest(), taken, not_taken); } @@ -804,13 +805,13 @@ } // Compute frequency that we arrive here - int sum = taken + not_taken; + float sum = taken + not_taken; // Adjust, if this block is a cloned private block but the // Jump counts are shared. Taken the private counts for // just this path instead of the shared counts. if( block()->count() > 0 ) sum = block()->count(); - cnt = (float)sum / (float)FreqCountInvocations; + cnt = sum / FreqCountInvocations; // Pin probability to sane limits float prob; diff -r 3449f5e02cc4 -r 97e8046e2562 src/share/vm/prims/methodHandleWalk.hpp --- a/src/share/vm/prims/methodHandleWalk.hpp Tue Apr 12 14:18:53 2011 -0700 +++ b/src/share/vm/prims/methodHandleWalk.hpp Fri Apr 15 08:29:26 2011 -0700 @@ -343,6 +343,7 @@ int cpool_symbol_put(int tag, Symbol* con) { if (con == NULL) return 0; ConstantValue* cv = new ConstantValue(tag, con); + con->increment_refcount(); return _constants.append(cv); } diff -r 3449f5e02cc4 -r 97e8046e2562 src/share/vm/prims/methodHandles.cpp --- a/src/share/vm/prims/methodHandles.cpp Tue Apr 12 14:18:53 2011 -0700 +++ b/src/share/vm/prims/methodHandles.cpp Fri Apr 15 08:29:26 2011 -0700 @@ -928,6 +928,7 @@ }; static bool is_always_null_type(klassOop klass) { + if (klass == NULL) return false; // safety if (!Klass::cast(klass)->oop_is_instance()) return false; instanceKlass* ik = instanceKlass::cast(klass); // Must be on the boot class path: @@ -944,6 +945,8 @@ } bool MethodHandles::class_cast_needed(klassOop src, klassOop dst) { + if (dst == NULL) return true; + if (src == NULL) return (dst != SystemDictionary::Object_klass()); if (src == dst || dst == SystemDictionary::Object_klass()) return false; // quickest checks Klass* srck = Klass::cast(src); @@ -1026,10 +1029,15 @@ int first_ptype_pos, KlassHandle insert_ptype, TRAPS) { + Handle mhi_type; + if (m->is_method_handle_invoke()) { + // use this more exact typing instead of the symbolic signature: + mhi_type = Handle(THREAD, m->method_handle_type()); + } objArrayHandle ptypes(THREAD, java_lang_invoke_MethodType::ptypes(mtype())); int pnum = first_ptype_pos; int pmax = ptypes->length(); - int mnum = 0; // method argument + int anum = 0; // method argument const char* err = NULL; ResourceMark rm(THREAD); for (SignatureStream ss(m->signature()); !ss.is_done(); ss.next()) { @@ -1048,47 +1056,70 @@ else ptype_oop = insert_ptype->java_mirror(); pnum += 1; - mnum += 1; + anum += 1; } - klassOop pklass = NULL; - BasicType ptype = T_OBJECT; - if (ptype_oop != NULL) - ptype = java_lang_Class::as_BasicType(ptype_oop, &pklass); - else - // null does not match any non-reference; use Object to report the error - pklass = SystemDictionary::Object_klass(); - klassOop mklass = NULL; - BasicType mtype = ss.type(); - if (mtype == T_ARRAY) mtype = T_OBJECT; // fold all refs to T_OBJECT - if (mtype == T_OBJECT) { - if (ptype_oop == NULL) { + KlassHandle pklass; + BasicType ptype = T_OBJECT; + bool have_ptype = false; + // missing ptype_oop does not match any non-reference; use Object to report the error + pklass = SystemDictionaryHandles::Object_klass(); + if (ptype_oop != NULL) { + have_ptype = true; + klassOop pklass_oop = NULL; + ptype = java_lang_Class::as_BasicType(ptype_oop, &pklass_oop); + pklass = KlassHandle(THREAD, pklass_oop); + } + ptype_oop = NULL; //done with this + KlassHandle aklass; + BasicType atype = ss.type(); + if (atype == T_ARRAY) atype = T_OBJECT; // fold all refs to T_OBJECT + if (atype == T_OBJECT) { + if (!have_ptype) { // null matches any reference continue; } - KlassHandle pklass_handle(THREAD, pklass); pklass = NULL; - // If we fail to resolve types at this point, we will throw an error. - Symbol* name = ss.as_symbol(CHECK); - instanceKlass* mk = instanceKlass::cast(m->method_holder()); - Handle loader(THREAD, mk->class_loader()); - Handle domain(THREAD, mk->protection_domain()); - mklass = SystemDictionary::resolve_or_null(name, loader, domain, CHECK); - pklass = pklass_handle(); - if (mklass == NULL && pklass != NULL && - Klass::cast(pklass)->name() == name && - m->is_method_handle_invoke()) { - // Assume a match. We can't really decode the signature of MH.invoke*. - continue; + if (mhi_type.is_null()) { + // If we fail to resolve types at this point, we will usually throw an error. + TempNewSymbol name = ss.as_symbol_or_null(); + if (name != NULL) { + instanceKlass* mk = instanceKlass::cast(m->method_holder()); + Handle loader(THREAD, mk->class_loader()); + Handle domain(THREAD, mk->protection_domain()); + klassOop aklass_oop = SystemDictionary::resolve_or_null(name, loader, domain, CHECK); + if (aklass_oop != NULL) + aklass = KlassHandle(THREAD, aklass_oop); + } + } else { + // for method handle invokers we don't look at the name in the signature + oop atype_oop; + if (ss.at_return_type()) + atype_oop = java_lang_invoke_MethodType::rtype(mhi_type()); + else + atype_oop = java_lang_invoke_MethodType::ptype(mhi_type(), anum-1); + klassOop aklass_oop = NULL; + atype = java_lang_Class::as_BasicType(atype_oop, &aklass_oop); + aklass = KlassHandle(THREAD, aklass_oop); } } if (!ss.at_return_type()) { - err = check_argument_type_change(ptype, pklass, mtype, mklass, mnum); + err = check_argument_type_change(ptype, pklass(), atype, aklass(), anum); } else { - err = check_return_type_change(mtype, mklass, ptype, pklass); // note reversal! + err = check_return_type_change(atype, aklass(), ptype, pklass()); // note reversal! } if (err != NULL) break; } if (err != NULL) { +#ifndef PRODUCT + if (PrintMiscellaneous && (Verbose || WizardMode)) { + tty->print("*** verify_method_signature failed: "); + java_lang_invoke_MethodType::print_signature(mtype(), tty); + tty->cr(); + tty->print_cr(" first_ptype_pos = %d, insert_ptype = "UINTX_FORMAT, first_ptype_pos, insert_ptype()); + tty->print(" Failing method: "); + m->print(); + } +#endif //PRODUCT THROW_MSG(vmSymbols::java_lang_InternalError(), err); } } @@ -1288,10 +1319,12 @@ // format, format, format const char* src_name = type2name(src_type); const char* dst_name = type2name(dst_type); - if (src_type == T_OBJECT) src_name = Klass::cast(src_klass)->external_name(); - if (dst_type == T_OBJECT) dst_name = Klass::cast(dst_klass)->external_name(); if (src_name == NULL) src_name = "unknown type"; if (dst_name == NULL) dst_name = "unknown type"; + if (src_type == T_OBJECT) + src_name = (src_klass != NULL) ? Klass::cast(src_klass)->external_name() : "an unresolved class"; + if (dst_type == T_OBJECT) + dst_name = (dst_klass != NULL) ? Klass::cast(dst_klass)->external_name() : "an unresolved class"; size_t msglen = strlen(err) + strlen(src_name) + strlen(dst_name) + (argnum < 10 ? 1 : 11); char* msg = NEW_RESOURCE_ARRAY(char, msglen + 1); diff -r 3449f5e02cc4 -r 97e8046e2562 src/share/vm/runtime/sweeper.cpp --- a/src/share/vm/runtime/sweeper.cpp Tue Apr 12 14:18:53 2011 -0700 +++ b/src/share/vm/runtime/sweeper.cpp Fri Apr 15 08:29:26 2011 -0700 @@ -418,6 +418,11 @@ // state of the code cache if it's requested. void NMethodSweeper::log_sweep(const char* msg, const char* format, ...) { if (PrintMethodFlushing) { + stringStream s; + // Dump code cache state into a buffer before locking the tty, + // because log_state() will use locks causing lock conflicts. + CodeCache::log_state(&s); + ttyLocker ttyl; tty->print("### sweeper: %s ", msg); if (format != NULL) { @@ -426,10 +431,15 @@ tty->vprint(format, ap); va_end(ap); } - CodeCache::log_state(tty); tty->cr(); + tty->print_cr(s.as_string()); } if (LogCompilation && (xtty != NULL)) { + stringStream s; + // Dump code cache state into a buffer before locking the tty, + // because log_state() will use locks causing lock conflicts. + CodeCache::log_state(&s); + ttyLocker ttyl; xtty->begin_elem("sweeper state='%s' traversals='" INTX_FORMAT "' ", msg, (intx)traversal_count()); if (format != NULL) { @@ -438,7 +448,7 @@ xtty->vprint(format, ap); va_end(ap); } - CodeCache::log_state(xtty); + xtty->print(s.as_string()); xtty->stamp(); xtty->end_elem(); } diff -r 3449f5e02cc4 -r 97e8046e2562 src/share/vm/shark/llvmHeaders.hpp --- a/src/share/vm/shark/llvmHeaders.hpp Tue Apr 12 14:18:53 2011 -0700 +++ b/src/share/vm/shark/llvmHeaders.hpp Fri Apr 15 08:29:26 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright 2008, 2009, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -46,7 +46,11 @@ #include #endif #include +#if SHARK_LLVM_VERSION >= 29 +#include +#else #include +#endif #include #include #include @@ -55,8 +59,12 @@ #include #include #include +#if SHARK_LLVM_VERSION >= 29 +#include +#else #include #endif +#endif #include