# HG changeset patch # User johnc # Date 1334947309 25200 # Node ID f3f101a5e59b0ddb269e1d6a80656183848ee43f # Parent 0105f367a14cce4837565c9ff09a90495ecb606b# Parent f7a8920427a626010c55a76f7ac57ea2c2c1b916 Merge diff -r f7a8920427a6 -r f3f101a5e59b agent/src/os/linux/ps_core.c --- a/agent/src/os/linux/ps_core.c Wed Apr 18 13:39:55 2012 -0400 +++ b/agent/src/os/linux/ps_core.c Fri Apr 20 11:41:49 2012 -0700 @@ -440,7 +440,7 @@ int j = 0; print_debug("---- sorted virtual address map ----\n"); for (j = 0; j < ph->core->num_maps; j++) { - print_debug("base = 0x%lx\tsize = %d\n", ph->core->map_array[j]->vaddr, + print_debug("base = 0x%lx\tsize = %zd\n", ph->core->map_array[j]->vaddr, ph->core->map_array[j]->memsz); } } diff -r f7a8920427a6 -r f3f101a5e59b agent/src/share/classes/sun/jvm/hotspot/jdi/VirtualMachineImpl.java --- a/agent/src/share/classes/sun/jvm/hotspot/jdi/VirtualMachineImpl.java Wed Apr 18 13:39:55 2012 -0400 +++ b/agent/src/share/classes/sun/jvm/hotspot/jdi/VirtualMachineImpl.java Fri Apr 20 11:41:49 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -889,15 +889,9 @@ Klass kls = ((ReferenceTypeImpl)type).ref(); if (kls instanceof InstanceKlass) { InstanceKlass ik = (InstanceKlass) kls; - if (ik.isInterface()) { - if (ik.nofImplementors() == 0L) { - return new ArrayList(0); - } - } else { - // if the Klass is final or if there are no subklasses loaded yet - if (ik.getAccessFlagsObj().isFinal() || ik.getSubklassKlass() == null) { - includeSubtypes = false; - } + // if the Klass is final or if there are no subklasses loaded yet + if (ik.getAccessFlagsObj().isFinal() || ik.getSubklassKlass() == null) { + includeSubtypes = false; } } else { // no subtypes for primitive array types diff -r f7a8920427a6 -r f3f101a5e59b agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java --- a/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Wed Apr 18 13:39:55 2012 -0400 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Fri Apr 20 11:41:49 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,6 @@ private static int HIGH_OFFSET; private static int GENERIC_SIGNATURE_INDEX_OFFSET; private static int FIELD_SLOTS; - public static int IMPLEMENTORS_LIMIT; // ClassState constants private static int CLASS_STATE_UNPARSABLE_BY_GC; @@ -70,13 +69,6 @@ methodOrdering = new OopField(type.getOopField("_method_ordering"), Oop.getHeaderSize()); localInterfaces = new OopField(type.getOopField("_local_interfaces"), Oop.getHeaderSize()); transitiveInterfaces = new OopField(type.getOopField("_transitive_interfaces"), Oop.getHeaderSize()); - nofImplementors = new CIntField(type.getCIntegerField("_nof_implementors"), Oop.getHeaderSize()); - IMPLEMENTORS_LIMIT = db.lookupIntConstant("instanceKlass::implementors_limit").intValue(); - implementors = new OopField[IMPLEMENTORS_LIMIT]; - for (int i = 0; i < IMPLEMENTORS_LIMIT; i++) { - long arrayOffset = Oop.getHeaderSize() + (i * db.getAddressSize()); - implementors[i] = new OopField(type.getOopField("_implementors[0]"), arrayOffset); - } fields = new OopField(type.getOopField("_fields"), Oop.getHeaderSize()); javaFieldsCount = new CIntField(type.getCIntegerField("_java_fields_count"), Oop.getHeaderSize()); constants = new OopField(type.getOopField("_constants"), Oop.getHeaderSize()); @@ -136,8 +128,6 @@ private static OopField methodOrdering; private static OopField localInterfaces; private static OopField transitiveInterfaces; - private static CIntField nofImplementors; - private static OopField[] implementors; private static OopField fields; private static CIntField javaFieldsCount; private static OopField constants; @@ -317,9 +307,6 @@ public TypeArray getMethodOrdering() { return (TypeArray) methodOrdering.getValue(this); } public ObjArray getLocalInterfaces() { return (ObjArray) localInterfaces.getValue(this); } public ObjArray getTransitiveInterfaces() { return (ObjArray) transitiveInterfaces.getValue(this); } - public long nofImplementors() { return nofImplementors.getValue(this); } - public Klass getImplementor() { return (Klass) implementors[0].getValue(this); } - public Klass getImplementor(int i) { return (Klass) implementors[i].getValue(this); } public TypeArray getFields() { return (TypeArray) fields.getValue(this); } public int getJavaFieldsCount() { return (int) javaFieldsCount.getValue(this); } public int getAllFieldsCount() { return (int)getFields().getLength() / FIELD_SLOTS; } @@ -527,9 +514,6 @@ visitor.doOop(methodOrdering, true); visitor.doOop(localInterfaces, true); visitor.doOop(transitiveInterfaces, true); - visitor.doCInt(nofImplementors, true); - for (int i = 0; i < IMPLEMENTORS_LIMIT; i++) - visitor.doOop(implementors[i], true); visitor.doOop(fields, true); visitor.doOop(constants, true); visitor.doOop(classLoader, true); diff -r f7a8920427a6 -r f3f101a5e59b src/cpu/x86/vm/templateTable_x86_32.cpp --- a/src/cpu/x86/vm/templateTable_x86_32.cpp Wed Apr 18 13:39:55 2012 -0400 +++ b/src/cpu/x86/vm/templateTable_x86_32.cpp Fri Apr 20 11:41:49 2012 -0700 @@ -2651,56 +2651,49 @@ // Check to see if a field modification watch has been set before we take // the time to call into the VM. Label L2; - __ mov32(rcx, ExternalAddress((address)JvmtiExport::get_field_modification_count_addr())); - __ testl(rcx,rcx); - __ jcc(Assembler::zero, L2); - __ pop_ptr(rbx); // copy the object pointer from tos - __ verify_oop(rbx); - __ push_ptr(rbx); // put the object pointer back on tos - __ subptr(rsp, sizeof(jvalue)); // add space for a jvalue object - __ mov(rcx, rsp); - __ push_ptr(rbx); // save object pointer so we can steal rbx, - __ xorptr(rbx, rbx); - const Address lo_value(rcx, rbx, Address::times_1, 0*wordSize); - const Address hi_value(rcx, rbx, Address::times_1, 1*wordSize); - switch (bytecode()) { // load values into the jvalue object - case Bytecodes::_fast_bputfield: __ movb(lo_value, rax); break; - case Bytecodes::_fast_sputfield: __ movw(lo_value, rax); break; - case Bytecodes::_fast_cputfield: __ movw(lo_value, rax); break; - case Bytecodes::_fast_iputfield: __ movl(lo_value, rax); break; - case Bytecodes::_fast_lputfield: - NOT_LP64(__ movptr(hi_value, rdx)); - __ movptr(lo_value, rax); - break; - - // need to call fld_s() after fstp_s() to restore the value for below - case Bytecodes::_fast_fputfield: __ fstp_s(lo_value); __ fld_s(lo_value); break; - - // need to call fld_d() after fstp_d() to restore the value for below - case Bytecodes::_fast_dputfield: __ fstp_d(lo_value); __ fld_d(lo_value); break; - - // since rcx is not an object we don't call store_check() here - case Bytecodes::_fast_aputfield: __ movptr(lo_value, rax); break; - - default: ShouldNotReachHere(); - } - __ pop_ptr(rbx); // restore copy of object pointer - - // Save rax, and sometimes rdx because call_VM() will clobber them, - // then use them for JVM/DI purposes - __ push(rax); - if (bytecode() == Bytecodes::_fast_lputfield) __ push(rdx); - // access constant pool cache entry - __ get_cache_entry_pointer_at_bcp(rax, rdx, 1); - __ verify_oop(rbx); - // rbx,: object pointer copied above - // rax,: cache entry pointer - // rcx: jvalue object on the stack - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_modification), rbx, rax, rcx); - if (bytecode() == Bytecodes::_fast_lputfield) __ pop(rdx); // restore high value - __ pop(rax); // restore lower value - __ addptr(rsp, sizeof(jvalue)); // release jvalue object space - __ bind(L2); + __ mov32(rcx, ExternalAddress((address)JvmtiExport::get_field_modification_count_addr())); + __ testl(rcx,rcx); + __ jcc(Assembler::zero, L2); + __ pop_ptr(rbx); // copy the object pointer from tos + __ verify_oop(rbx); + __ push_ptr(rbx); // put the object pointer back on tos + + // Save tos values before call_VM() clobbers them. Since we have + // to do it for every data type, we use the saved values as the + // jvalue object. + switch (bytecode()) { // load values into the jvalue object + case Bytecodes::_fast_aputfield: __ push_ptr(rax); break; + case Bytecodes::_fast_bputfield: // fall through + case Bytecodes::_fast_sputfield: // fall through + case Bytecodes::_fast_cputfield: // fall through + case Bytecodes::_fast_iputfield: __ push_i(rax); break; + case Bytecodes::_fast_dputfield: __ push_d(); break; + case Bytecodes::_fast_fputfield: __ push_f(); break; + case Bytecodes::_fast_lputfield: __ push_l(rax); break; + + default: + ShouldNotReachHere(); + } + __ mov(rcx, rsp); // points to jvalue on the stack + // access constant pool cache entry + __ get_cache_entry_pointer_at_bcp(rax, rdx, 1); + __ verify_oop(rbx); + // rbx,: object pointer copied above + // rax,: cache entry pointer + // rcx: jvalue object on the stack + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_modification), rbx, rax, rcx); + + switch (bytecode()) { // restore tos values + case Bytecodes::_fast_aputfield: __ pop_ptr(rax); break; + case Bytecodes::_fast_bputfield: // fall through + case Bytecodes::_fast_sputfield: // fall through + case Bytecodes::_fast_cputfield: // fall through + case Bytecodes::_fast_iputfield: __ pop_i(rax); break; + case Bytecodes::_fast_dputfield: __ pop_d(); break; + case Bytecodes::_fast_fputfield: __ pop_f(); break; + case Bytecodes::_fast_lputfield: __ pop_l(rax); break; + } + __ bind(L2); } } diff -r f7a8920427a6 -r f3f101a5e59b src/cpu/x86/vm/templateTable_x86_64.cpp --- a/src/cpu/x86/vm/templateTable_x86_64.cpp Wed Apr 18 13:39:55 2012 -0400 +++ b/src/cpu/x86/vm/templateTable_x86_64.cpp Fri Apr 20 11:41:49 2012 -0700 @@ -2685,26 +2685,23 @@ __ pop_ptr(rbx); // copy the object pointer from tos __ verify_oop(rbx); __ push_ptr(rbx); // put the object pointer back on tos - __ subptr(rsp, sizeof(jvalue)); // add space for a jvalue object - __ mov(c_rarg3, rsp); - const Address field(c_rarg3, 0); - + // Save tos values before call_VM() clobbers them. Since we have + // to do it for every data type, we use the saved values as the + // jvalue object. switch (bytecode()) { // load values into the jvalue object - case Bytecodes::_fast_aputfield: __ movq(field, rax); break; - case Bytecodes::_fast_lputfield: __ movq(field, rax); break; - case Bytecodes::_fast_iputfield: __ movl(field, rax); break; - case Bytecodes::_fast_bputfield: __ movb(field, rax); break; + case Bytecodes::_fast_aputfield: __ push_ptr(rax); break; + case Bytecodes::_fast_bputfield: // fall through case Bytecodes::_fast_sputfield: // fall through - case Bytecodes::_fast_cputfield: __ movw(field, rax); break; - case Bytecodes::_fast_fputfield: __ movflt(field, xmm0); break; - case Bytecodes::_fast_dputfield: __ movdbl(field, xmm0); break; + case Bytecodes::_fast_cputfield: // fall through + case Bytecodes::_fast_iputfield: __ push_i(rax); break; + case Bytecodes::_fast_dputfield: __ push_d(); break; + case Bytecodes::_fast_fputfield: __ push_f(); break; + case Bytecodes::_fast_lputfield: __ push_l(rax); break; + default: ShouldNotReachHere(); } - - // Save rax because call_VM() will clobber it, then use it for - // JVMTI purposes - __ push(rax); + __ mov(c_rarg3, rsp); // points to jvalue on the stack // access constant pool cache entry __ get_cache_entry_pointer_at_bcp(c_rarg2, rax, 1); __ verify_oop(rbx); @@ -2715,8 +2712,17 @@ CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_modification), rbx, c_rarg2, c_rarg3); - __ pop(rax); // restore lower value - __ addptr(rsp, sizeof(jvalue)); // release jvalue object space + + switch (bytecode()) { // restore tos values + case Bytecodes::_fast_aputfield: __ pop_ptr(rax); break; + case Bytecodes::_fast_bputfield: // fall through + case Bytecodes::_fast_sputfield: // fall through + case Bytecodes::_fast_cputfield: // fall through + case Bytecodes::_fast_iputfield: __ pop_i(rax); break; + case Bytecodes::_fast_dputfield: __ pop_d(); break; + case Bytecodes::_fast_fputfield: __ pop_f(); break; + case Bytecodes::_fast_lputfield: __ pop_l(rax); break; + } __ bind(L2); } } diff -r f7a8920427a6 -r f3f101a5e59b src/os/bsd/vm/osThread_bsd.hpp --- a/src/os/bsd/vm/osThread_bsd.hpp Wed Apr 18 13:39:55 2012 -0400 +++ b/src/os/bsd/vm/osThread_bsd.hpp Fri Apr 20 11:41:49 2012 -0700 @@ -72,15 +72,18 @@ #ifdef _ALLBSD_SOURCE #ifdef __APPLE__ + static size_t thread_id_size() { return sizeof(thread_t); } thread_t thread_id() const { return _thread_id; } #else + static size_t thread_id_size() { return sizeof(pthread_t); } pthread_t thread_id() const { return _thread_id; } #endif #else + static size_t thread_id_size() { return sizeof(pid_t); } pid_t thread_id() const { return _thread_id; } diff -r f7a8920427a6 -r f3f101a5e59b src/os/linux/vm/osThread_linux.hpp --- a/src/os/linux/vm/osThread_linux.hpp Wed Apr 18 13:39:55 2012 -0400 +++ b/src/os/linux/vm/osThread_linux.hpp Fri Apr 20 11:41:49 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,6 +56,8 @@ sigset_t caller_sigmask() const { return _caller_sigmask; } void set_caller_sigmask(sigset_t sigmask) { _caller_sigmask = sigmask; } + static size_t thread_id_size() { return sizeof(pid_t); } + pid_t thread_id() const { return _thread_id; } diff -r f7a8920427a6 -r f3f101a5e59b src/os/solaris/vm/osThread_solaris.hpp --- a/src/os/solaris/vm/osThread_solaris.hpp Wed Apr 18 13:39:55 2012 -0400 +++ b/src/os/solaris/vm/osThread_solaris.hpp Fri Apr 20 11:41:49 2012 -0700 @@ -36,6 +36,7 @@ bool _vm_created_thread; // true if the VM created this thread, // false if primary thread or attached thread public: + static size_t thread_id_size() { return sizeof(thread_t); } thread_t thread_id() const { return _thread_id; } uint lwp_id() const { return _lwp_id; } int native_priority() const { return _native_priority; } diff -r f7a8920427a6 -r f3f101a5e59b src/os/windows/vm/osThread_windows.hpp --- a/src/os/windows/vm/osThread_windows.hpp Wed Apr 18 13:39:55 2012 -0400 +++ b/src/os/windows/vm/osThread_windows.hpp Fri Apr 20 11:41:49 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,6 +42,8 @@ HANDLE interrupt_event() const { return _interrupt_event; } void set_interrupt_event(HANDLE interrupt_event) { _interrupt_event = interrupt_event; } + + static size_t thread_id_size() { return sizeof(unsigned long); } unsigned long thread_id() const { return _thread_id; } #ifndef PRODUCT // Used for debugging, return a unique integer for each thread. diff -r f7a8920427a6 -r f3f101a5e59b src/share/vm/c1/c1_GraphBuilder.cpp --- a/src/share/vm/c1/c1_GraphBuilder.cpp Wed Apr 18 13:39:55 2012 -0400 +++ b/src/share/vm/c1/c1_GraphBuilder.cpp Fri Apr 20 11:41:49 2012 -0700 @@ -1694,7 +1694,9 @@ // they are roughly equivalent to Object. ciInstanceKlass* singleton = NULL; if (target->holder()->nof_implementors() == 1) { - singleton = target->holder()->implementor(0); + singleton = target->holder()->implementor(); + assert(singleton != NULL && singleton != target->holder(), + "just checking"); assert(holder->is_interface(), "invokeinterface to non interface?"); ciInstanceKlass* decl_interface = (ciInstanceKlass*)holder; @@ -3130,10 +3132,23 @@ bool cantrap = true; vmIntrinsics::ID id = callee->intrinsic_id(); switch (id) { - case vmIntrinsics::_arraycopy : + case vmIntrinsics::_arraycopy: if (!InlineArrayCopy) return false; break; +#ifdef TRACE_HAVE_INTRINSICS + case vmIntrinsics::_classID: + case vmIntrinsics::_threadID: + preserves_state = true; + cantrap = true; + break; + + case vmIntrinsics::_counterTime: + preserves_state = true; + cantrap = false; + break; +#endif + case vmIntrinsics::_currentTimeMillis: case vmIntrinsics::_nanoTime: preserves_state = true; diff -r f7a8920427a6 -r f3f101a5e59b src/share/vm/c1/c1_LIRGenerator.cpp --- a/src/share/vm/c1/c1_LIRGenerator.cpp Wed Apr 18 13:39:55 2012 -0400 +++ b/src/share/vm/c1/c1_LIRGenerator.cpp Fri Apr 20 11:41:49 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2879,6 +2879,50 @@ __ cmove(lir_cond(x->cond()), t_val.result(), f_val.result(), reg, as_BasicType(x->x()->type())); } +void LIRGenerator::do_RuntimeCall(address routine, int expected_arguments, Intrinsic* x) { + assert(x->number_of_arguments() == expected_arguments, "wrong type"); + LIR_Opr reg = result_register_for(x->type()); + __ call_runtime_leaf(routine, getThreadTemp(), + reg, new LIR_OprList()); + LIR_Opr result = rlock_result(x); + __ move(reg, result); +} + +#ifdef TRACE_HAVE_INTRINSICS +void LIRGenerator::do_ThreadIDIntrinsic(Intrinsic* x) { + LIR_Opr thread = getThreadPointer(); + LIR_Opr osthread = new_pointer_register(); + __ move(new LIR_Address(thread, in_bytes(JavaThread::osthread_offset()), osthread->type()), osthread); + size_t thread_id_size = OSThread::thread_id_size(); + if (thread_id_size == (size_t) BytesPerLong) { + LIR_Opr id = new_register(T_LONG); + __ move(new LIR_Address(osthread, in_bytes(OSThread::thread_id_offset()), T_LONG), id); + __ convert(Bytecodes::_l2i, id, rlock_result(x)); + } else if (thread_id_size == (size_t) BytesPerInt) { + __ move(new LIR_Address(osthread, in_bytes(OSThread::thread_id_offset()), T_INT), rlock_result(x)); + } else { + ShouldNotReachHere(); + } +} + +void LIRGenerator::do_ClassIDIntrinsic(Intrinsic* x) { + CodeEmitInfo* info = state_for(x); + CodeEmitInfo* info2 = new CodeEmitInfo(info); // Clone for the second null check + assert(info != NULL, "must have info"); + LIRItem arg(x->argument_at(1), this); + arg.load_item(); + LIR_Opr klass = new_register(T_OBJECT); + __ move(new LIR_Address(arg.result(), java_lang_Class::klass_offset_in_bytes(), T_OBJECT), klass, info); + LIR_Opr id = new_register(T_LONG); + ByteSize offset = TRACE_ID_OFFSET; + LIR_Address* trace_id_addr = new LIR_Address(klass, in_bytes(offset), T_LONG); + __ move(trace_id_addr, id); + __ logical_or(id, LIR_OprFact::longConst(0x01l), id); + __ store(id, trace_id_addr); + __ logical_and(id, LIR_OprFact::longConst(~0x3l), id); + __ move(id, rlock_result(x)); +} +#endif void LIRGenerator::do_Intrinsic(Intrinsic* x) { switch (x->id()) { @@ -2890,25 +2934,21 @@ break; } - case vmIntrinsics::_currentTimeMillis: { - assert(x->number_of_arguments() == 0, "wrong type"); - LIR_Opr reg = result_register_for(x->type()); - __ call_runtime_leaf(CAST_FROM_FN_PTR(address, os::javaTimeMillis), getThreadTemp(), - reg, new LIR_OprList()); - LIR_Opr result = rlock_result(x); - __ move(reg, result); +#ifdef TRACE_HAVE_INTRINSICS + case vmIntrinsics::_threadID: do_ThreadIDIntrinsic(x); break; + case vmIntrinsics::_classID: do_ClassIDIntrinsic(x); break; + case vmIntrinsics::_counterTime: + do_RuntimeCall(CAST_FROM_FN_PTR(address, TRACE_TIME_METHOD), 0, x); break; - } - - case vmIntrinsics::_nanoTime: { - assert(x->number_of_arguments() == 0, "wrong type"); - LIR_Opr reg = result_register_for(x->type()); - __ call_runtime_leaf(CAST_FROM_FN_PTR(address, os::javaTimeNanos), getThreadTemp(), - reg, new LIR_OprList()); - LIR_Opr result = rlock_result(x); - __ move(reg, result); +#endif + + case vmIntrinsics::_currentTimeMillis: + do_RuntimeCall(CAST_FROM_FN_PTR(address, os::javaTimeMillis), 0, x); break; - } + + case vmIntrinsics::_nanoTime: + do_RuntimeCall(CAST_FROM_FN_PTR(address, os::javaTimeNanos), 0, x); + break; case vmIntrinsics::_Object_init: do_RegisterFinalizer(x); break; case vmIntrinsics::_getClass: do_getClass(x); break; diff -r f7a8920427a6 -r f3f101a5e59b src/share/vm/c1/c1_LIRGenerator.hpp --- a/src/share/vm/c1/c1_LIRGenerator.hpp Wed Apr 18 13:39:55 2012 -0400 +++ b/src/share/vm/c1/c1_LIRGenerator.hpp Fri Apr 20 11:41:49 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -426,6 +426,12 @@ SwitchRangeArray* create_lookup_ranges(LookupSwitch* x); void do_SwitchRanges(SwitchRangeArray* x, LIR_Opr value, BlockBegin* default_sux); + void do_RuntimeCall(address routine, int expected_arguments, Intrinsic* x); +#ifdef TRACE_HAVE_INTRINSICS + void do_ThreadIDIntrinsic(Intrinsic* x); + void do_ClassIDIntrinsic(Intrinsic* x); +#endif + public: Compilation* compilation() const { return _compilation; } FrameMap* frame_map() const { return _compilation->frame_map(); } diff -r f7a8920427a6 -r f3f101a5e59b src/share/vm/c1/c1_Runtime1.cpp --- a/src/share/vm/c1/c1_Runtime1.cpp Wed Apr 18 13:39:55 2012 -0400 +++ b/src/share/vm/c1/c1_Runtime1.cpp Fri Apr 20 11:41:49 2012 -0700 @@ -295,6 +295,9 @@ FUNCTION_CASE(entry, SharedRuntime::dtrace_method_entry); FUNCTION_CASE(entry, SharedRuntime::dtrace_method_exit); FUNCTION_CASE(entry, trace_block_entry); +#ifdef TRACE_HAVE_INTRINSICS + FUNCTION_CASE(entry, TRACE_TIME_METHOD); +#endif #undef FUNCTION_CASE diff -r f7a8920427a6 -r f3f101a5e59b src/share/vm/ci/ciInstanceKlass.cpp --- a/src/share/vm/ci/ciInstanceKlass.cpp Wed Apr 18 13:39:55 2012 -0400 +++ b/src/share/vm/ci/ciInstanceKlass.cpp Fri Apr 20 11:41:49 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,10 +59,7 @@ _has_nonstatic_fields = ik->has_nonstatic_fields(); _nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields: - _nof_implementors = ik->nof_implementors(); - for (int i = 0; i < implementors_limit; i++) { - _implementors[i] = NULL; // we will fill these lazily - } + _implementor = NULL; // we will fill these lazily Thread *thread = Thread::current(); if (ciObjectFactory::is_initialized()) { @@ -102,7 +99,6 @@ _nonstatic_field_size = -1; _has_nonstatic_fields = false; _nonstatic_fields = NULL; - _nof_implementors = -1; _loader = loader; _protection_domain = protection_domain; _is_shared = false; @@ -133,17 +129,6 @@ } // ------------------------------------------------------------------ -// ciInstanceKlass::compute_shared_nof_implementors -int ciInstanceKlass::compute_shared_nof_implementors() { - // We requery this property, since it is a very old ciObject. - GUARDED_VM_ENTRY( - instanceKlass* ik = get_instanceKlass(); - _nof_implementors = ik->nof_implementors(); - return _nof_implementors; - ) -} - -// ------------------------------------------------------------------ // ciInstanceKlass::loader oop ciInstanceKlass::loader() { ASSERT_IN_VM; @@ -540,7 +525,7 @@ if (is_shared()) { return is_final(); // approximately correct } else { - return !_has_subklass && (_nof_implementors == 0); + return !_has_subklass && (nof_implementors() == 0); } } @@ -548,35 +533,31 @@ // ciInstanceKlass::implementor // // Report an implementor of this interface. -// Returns NULL if exact information is not available. // Note that there are various races here, since my copy // of _nof_implementors might be out of date with respect // to results returned by instanceKlass::implementor. // This is OK, since any dependencies we decide to assert // will be checked later under the Compile_lock. -ciInstanceKlass* ciInstanceKlass::implementor(int n) { - if (n >= implementors_limit) { - return NULL; - } - ciInstanceKlass* impl = _implementors[n]; +ciInstanceKlass* ciInstanceKlass::implementor() { + ciInstanceKlass* impl = _implementor; if (impl == NULL) { - if (_nof_implementors > implementors_limit) { - return NULL; - } // Go into the VM to fetch the implementor. { VM_ENTRY_MARK; - klassOop k = get_instanceKlass()->implementor(n); + klassOop k = get_instanceKlass()->implementor(); if (k != NULL) { - impl = CURRENT_THREAD_ENV->get_object(k)->as_instance_klass(); + if (k == get_instanceKlass()->as_klassOop()) { + // More than one implementors. Use 'this' in this case. + impl = this; + } else { + impl = CURRENT_THREAD_ENV->get_object(k)->as_instance_klass(); + } } } // Memoize this result. if (!is_shared()) { - _implementors[n] = (impl == NULL)? this: impl; + _implementor = impl; } - } else if (impl == this) { - impl = NULL; // memoized null result from a VM query } return impl; } diff -r f7a8920427a6 -r f3f101a5e59b src/share/vm/ci/ciInstanceKlass.hpp --- a/src/share/vm/ci/ciInstanceKlass.hpp Wed Apr 18 13:39:55 2012 -0400 +++ b/src/share/vm/ci/ciInstanceKlass.hpp Fri Apr 20 11:41:49 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,9 +65,11 @@ ciConstantPoolCache* _field_cache; // cached map index->field GrowableArray* _nonstatic_fields; - enum { implementors_limit = instanceKlass::implementors_limit }; - ciInstanceKlass* _implementors[implementors_limit]; - jint _nof_implementors; + // The possible values of the _implementor fall into following three cases: + // NULL: no implementor. + // A ciInstanceKlass that's not itself: one implementor. + // Itsef: more than one implementors. + ciInstanceKlass* _implementor; GrowableArray* _non_static_fields; @@ -97,7 +99,6 @@ void compute_shared_init_state(); bool compute_shared_has_subklass(); - int compute_shared_nof_implementors(); int compute_nonstatic_fields(); GrowableArray* compute_nonstatic_fields_impl(GrowableArray* super_fields); @@ -158,10 +159,17 @@ assert(is_loaded(), "must be loaded"); return _nonstatic_oop_map_size; } ciInstanceKlass* super(); - jint nof_implementors() { + jint nof_implementors() { + ciInstanceKlass* impl; assert(is_loaded(), "must be loaded"); - if (_is_shared) return compute_shared_nof_implementors(); - return _nof_implementors; + impl = implementor(); + if (impl == NULL) { + return 0; + } else if (impl != this) { + return 1; + } else { + return 2; + } } ciInstanceKlass* get_canonical_holder(int offset); @@ -207,7 +215,7 @@ // but consider adding to vmSymbols.hpp instead. bool is_leaf_type(); - ciInstanceKlass* implementor(int n); + ciInstanceKlass* implementor(); // Is the defining class loader of this class the default loader? bool uses_default_loader(); diff -r f7a8920427a6 -r f3f101a5e59b src/share/vm/classfile/classFileParser.cpp --- a/src/share/vm/classfile/classFileParser.cpp Wed Apr 18 13:39:55 2012 -0400 +++ b/src/share/vm/classfile/classFileParser.cpp Fri Apr 20 11:41:49 2012 -0700 @@ -3354,6 +3354,7 @@ klassOop ik = oopFactory::new_instanceKlass(name, vtable_size, itable_size, static_field_size, total_oop_map_count, + access_flags, rt, CHECK_(nullHandle)); instanceKlassHandle this_klass (THREAD, ik); @@ -3362,7 +3363,6 @@ "sanity"); // Fill in information already parsed - this_klass->set_access_flags(access_flags); this_klass->set_should_verify_class(verify); jint lh = Klass::instance_layout_helper(instance_size, false); this_klass->set_layout_helper(lh); diff -r f7a8920427a6 -r f3f101a5e59b src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Wed Apr 18 13:39:55 2012 -0400 +++ b/src/share/vm/classfile/vmSymbols.hpp Fri Apr 20 11:41:49 2012 -0700 @@ -27,6 +27,7 @@ #include "oops/symbol.hpp" #include "memory/iterator.hpp" +#include "trace/traceMacros.hpp" // The class vmSymbols is a name space for fast lookup of // symbols commonly used in the VM. @@ -424,6 +425,7 @@ template(throwable_throwable_signature, "(Ljava/lang/Throwable;)Ljava/lang/Throwable;") \ template(class_void_signature, "(Ljava/lang/Class;)V") \ template(class_int_signature, "(Ljava/lang/Class;)I") \ + template(class_long_signature, "(Ljava/lang/Class;)J") \ template(class_boolean_signature, "(Ljava/lang/Class;)Z") \ template(throwable_string_void_signature, "(Ljava/lang/Throwable;Ljava/lang/String;)V") \ template(string_array_void_signature, "([Ljava/lang/String;)V") \ @@ -539,10 +541,12 @@ template(serializePropertiesToByteArray_signature, "()[B") \ template(serializeAgentPropertiesToByteArray_name, "serializeAgentPropertiesToByteArray") \ template(classRedefinedCount_name, "classRedefinedCount") \ + \ + /* trace signatures */ \ + TRACE_TEMPLATES(template) \ + \ /*end*/ - - // Here are all the intrinsics known to the runtime and the CI. // Each intrinsic consists of a public enum name (like _hashCode), // followed by a specification of its klass, name, and signature: @@ -648,6 +652,8 @@ do_intrinsic(_nanoTime, java_lang_System, nanoTime_name, void_long_signature, F_S) \ do_name( nanoTime_name, "nanoTime") \ \ + TRACE_INTRINSICS(do_intrinsic, do_class, do_name, do_signature, do_alias) \ + \ do_intrinsic(_arraycopy, java_lang_System, arraycopy_name, arraycopy_signature, F_S) \ do_name( arraycopy_name, "arraycopy") \ do_signature(arraycopy_signature, "(Ljava/lang/Object;ILjava/lang/Object;II)V") \ diff -r f7a8920427a6 -r f3f101a5e59b src/share/vm/code/dependencies.cpp --- a/src/share/vm/code/dependencies.cpp Wed Apr 18 13:39:55 2012 -0400 +++ b/src/share/vm/code/dependencies.cpp Fri Apr 20 11:41:49 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1033,21 +1033,25 @@ // (Old CHA had the same limitation.) return context_type; } - for (int i = 0; i < nof_impls; i++) { - klassOop impl = instanceKlass::cast(context_type)->implementor(i); - if (impl == NULL) { - // implementors array overflowed => no exact info. + if (nof_impls > 0) { + klassOop impl = instanceKlass::cast(context_type)->implementor(); + assert(impl != NULL, "just checking"); + // If impl is the same as the context_type, then more than one + // implementor has seen. No exact info in this case. + if (impl == context_type) { return context_type; // report an inexact witness to this sad affair } if (do_counts) { NOT_PRODUCT(deps_find_witness_steps++); } if (is_participant(impl)) { - if (participants_hide_witnesses) continue; - // else fall through to process this guy's subclasses + if (!participants_hide_witnesses) { + ADD_SUBCLASS_CHAIN(impl); + } } else if (is_witness(impl) && !ignore_witness(impl)) { return impl; + } else { + ADD_SUBCLASS_CHAIN(impl); } - ADD_SUBCLASS_CHAIN(impl); } // Recursively process each non-trivial sibling chain. @@ -1174,8 +1178,9 @@ } else if (ctx->nof_implementors() != 0) { // if it is an interface, it must be unimplemented // (if it is not an interface, nof_implementors is always zero) - klassOop impl = ctx->implementor(0); - return (impl != NULL)? impl: ctxk; + klassOop impl = ctx->implementor(); + assert(impl != NULL, "must be set"); + return impl; } else { return NULL; } diff -r f7a8920427a6 -r f3f101a5e59b src/share/vm/memory/oopFactory.cpp --- a/src/share/vm/memory/oopFactory.cpp Wed Apr 18 13:39:55 2012 -0400 +++ b/src/share/vm/memory/oopFactory.cpp Fri Apr 20 11:41:49 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -127,9 +127,12 @@ klassOop oopFactory::new_instanceKlass(Symbol* name, int vtable_len, int itable_len, int static_field_size, unsigned int nonstatic_oop_map_count, + AccessFlags access_flags, ReferenceType rt, TRAPS) { instanceKlassKlass* ikk = instanceKlassKlass::cast(Universe::instanceKlassKlassObj()); - return ikk->allocate_instance_klass(name, vtable_len, itable_len, static_field_size, nonstatic_oop_map_count, rt, CHECK_NULL); + return ikk->allocate_instance_klass(name, vtable_len, itable_len, + static_field_size, nonstatic_oop_map_count, + access_flags, rt, CHECK_NULL); } diff -r f7a8920427a6 -r f3f101a5e59b src/share/vm/memory/oopFactory.hpp --- a/src/share/vm/memory/oopFactory.hpp Wed Apr 18 13:39:55 2012 -0400 +++ b/src/share/vm/memory/oopFactory.hpp Fri Apr 20 11:41:49 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -77,6 +77,7 @@ int vtable_len, int itable_len, int static_field_size, unsigned int nonstatic_oop_map_count, + AccessFlags access_flags, ReferenceType rt, TRAPS); // Methods diff -r f7a8920427a6 -r f3f101a5e59b src/share/vm/oops/instanceKlass.cpp --- a/src/share/vm/oops/instanceKlass.cpp Wed Apr 18 13:39:55 2012 -0400 +++ b/src/share/vm/oops/instanceKlass.cpp Fri Apr 20 11:41:49 2012 -0700 @@ -567,8 +567,18 @@ ol.notify_all(CHECK); } +// The embedded _implementor field can only record one implementor. +// When there are more than one implementors, the _implementor field +// is set to the interface klassOop itself. Following are the possible +// values for the _implementor field: +// NULL - no implementor +// implementor klassOop - one implementor +// self - more than one implementor +// +// The _implementor field only exists for interfaces. void instanceKlass::add_implementor(klassOop k) { assert(Compile_lock->owned_by_self(), ""); + assert(is_interface(), "not interface"); // Filter out my subinterfaces. // (Note: Interfaces are never on the subklass list.) if (instanceKlass::cast(k)->is_interface()) return; @@ -583,17 +593,13 @@ // Any supers of the super have the same (or fewer) transitive_interfaces. return; - // Update number of implementors - int i = _nof_implementors++; - - // Record this implementor, if there are not too many already - if (i < implementors_limit) { - assert(_implementors[i] == NULL, "should be exactly one implementor"); - oop_store_without_check((oop*)&_implementors[i], k); - } else if (i == implementors_limit) { - // clear out the list on first overflow - for (int i2 = 0; i2 < implementors_limit; i2++) - oop_store_without_check((oop*)&_implementors[i2], NULL); + klassOop ik = implementor(); + if (ik == NULL) { + set_implementor(k); + } else if (ik != this->as_klassOop()) { + // There is already an implementor. Use itself as an indicator of + // more than one implementors. + set_implementor(this->as_klassOop()); } // The implementor also implements the transitive_interfaces @@ -603,9 +609,9 @@ } void instanceKlass::init_implementor() { - for (int i = 0; i < implementors_limit; i++) - oop_store_without_check((oop*)&_implementors[i], NULL); - _nof_implementors = 0; + if (is_interface()) { + set_implementor(NULL); + } } @@ -1849,24 +1855,22 @@ void instanceKlass::follow_weak_klass_links( BoolObjectClosure* is_alive, OopClosure* keep_alive) { assert(is_alive->do_object_b(as_klassOop()), "this oop should be live"); - if (ClassUnloading) { - for (int i = 0; i < implementors_limit; i++) { - klassOop impl = _implementors[i]; - if (impl == NULL) break; // no more in the list - if (!is_alive->do_object_b(impl)) { - // remove this guy from the list by overwriting him with the tail - int lasti = --_nof_implementors; - assert(lasti >= i && lasti < implementors_limit, "just checking"); - _implementors[i] = _implementors[lasti]; - _implementors[lasti] = NULL; - --i; // rerun the loop at this index + + if (is_interface()) { + if (ClassUnloading) { + klassOop impl = implementor(); + if (impl != NULL) { + if (!is_alive->do_object_b(impl)) { + // remove this guy + *start_of_implementor() = NULL; + } } - } - } else { - for (int i = 0; i < implementors_limit; i++) { - keep_alive->do_oop(&adr_implementors()[i]); + } else { + assert(adr_implementor() != NULL, "just checking"); + keep_alive->do_oop(adr_implementor()); } } + Klass::follow_weak_klass_links(is_alive, keep_alive); } diff -r f7a8920427a6 -r f3f101a5e59b src/share/vm/oops/instanceKlass.hpp --- a/src/share/vm/oops/instanceKlass.hpp Wed Apr 18 13:39:55 2012 -0400 +++ b/src/share/vm/oops/instanceKlass.hpp Fri Apr 20 11:41:49 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,8 +56,6 @@ // [methods ] // [local interfaces ] // [transitive interfaces ] -// [number of implementors ] -// [implementors ] klassOop[2] // [fields ] // [constants ] // [class loader ] @@ -77,9 +75,9 @@ // [oop map cache (stack maps) ] // [EMBEDDED Java vtable ] size in words = vtable_len // [EMBEDDED nonstatic oop-map blocks] size in words = nonstatic_oop_map_size -// -// The embedded nonstatic oop-map blocks are short pairs (offset, length) indicating -// where oops are located in instances of this klass. +// The embedded nonstatic oop-map blocks are short pairs (offset, length) +// indicating where oops are located in instances of this klass. +// [EMBEDDED implementor of the interface] only exist for interface // forward declaration for class -- see below for definition @@ -153,10 +151,6 @@ oop* oop_block_beg() const { return adr_array_klasses(); } oop* oop_block_end() const { return adr_methods_default_annotations() + 1; } - enum { - implementors_limit = 2 // how many implems can we track? - }; - protected: // // The oop block. See comment in klass.hpp before making changes. @@ -200,8 +194,6 @@ // and EnclosingMethod attributes the _inner_classes array length is // number_of_inner_classes * 4 + enclosing_method_attribute_size. typeArrayOop _inner_classes; - // Implementors of this interface (not valid if it overflows) - klassOop _implementors[implementors_limit]; // Annotations for this class, or null if none. typeArrayOop _class_annotations; // Annotation objects (byte arrays) for fields, or null if no annotations. @@ -257,7 +249,6 @@ nmethodBucket* _dependencies; // list of dependent nmethods nmethod* _osr_nmethods_head; // Head of list of on-stack replacement nmethods for this class BreakpointInfo* _breakpoints; // bpt lists, managed by methodOop - int _nof_implementors; // No of implementors of this interface (zero if not an interface) // Array of interesting part(s) of the previous version(s) of this // instanceKlass. See PreviousVersionWalker below. GrowableArray* _previous_versions; @@ -278,6 +269,13 @@ // embedded Java itables follows here // embedded static fields follows here // embedded nonstatic oop-map blocks follows here + // embedded implementor of this interface follows here + // The embedded implementor only exists if the current klass is an + // iterface. The possible values of the implementor fall into following + // three cases: + // NULL: no implementor. + // A klassOop that's not itself: one implementor. + // Itsef: more than one implementors. friend class instanceKlassKlass; friend class SystemDictionary; @@ -644,19 +642,40 @@ // support for stub routines static ByteSize init_state_offset() { return in_ByteSize(sizeof(klassOopDesc) + offset_of(instanceKlass, _init_state)); } + TRACE_DEFINE_OFFSET; static ByteSize init_thread_offset() { return in_ByteSize(sizeof(klassOopDesc) + offset_of(instanceKlass, _init_thread)); } // subclass/subinterface checks bool implements_interface(klassOop k) const; - // Access to implementors of an interface. We only store the count - // of implementors, and in case, there are only a few - // implementors, we store them in a short list. - // This accessor returns NULL if we walk off the end of the list. - klassOop implementor(int i) const { - return (i < implementors_limit)? _implementors[i]: (klassOop) NULL; + // Access to the implementor of an interface. + klassOop implementor() const + { + klassOop* k = start_of_implementor(); + if (k == NULL) { + return NULL; + } else { + return *k; + } } - int nof_implementors() const { return _nof_implementors; } + + void set_implementor(klassOop k) { + assert(is_interface(), "not interface"); + oop* addr = (oop*)start_of_implementor(); + oop_store_without_check(addr, k); + } + + int nof_implementors() const { + klassOop k = implementor(); + if (k == NULL) { + return 0; + } else if (k != this->as_klassOop()) { + return 1; + } else { + return 2; + } + } + void add_implementor(klassOop k); // k is a new class that implements this interface void init_implementor(); // initialize @@ -693,7 +712,15 @@ // Sizing (in words) static int header_size() { return align_object_offset(oopDesc::header_size() + sizeof(instanceKlass)/HeapWordSize); } - int object_size() const { return object_size(align_object_offset(vtable_length()) + align_object_offset(itable_length()) + nonstatic_oop_map_size()); } + + int object_size() const + { + return object_size(align_object_offset(vtable_length()) + + align_object_offset(itable_length()) + + (is_interface() ? + (align_object_offset(nonstatic_oop_map_size()) + (int)sizeof(klassOop)/HeapWordSize) : + nonstatic_oop_map_size())); + } static int vtable_start_offset() { return header_size(); } static int vtable_length_offset() { return oopDesc::header_size() + offset_of(instanceKlass, _vtable_len) / HeapWordSize; } static int object_size(int extra) { return align_object_size(header_size() + extra); } @@ -710,6 +737,15 @@ return (OopMapBlock*)(start_of_itable() + align_object_offset(itable_length())); } + klassOop* start_of_implementor() const { + if (is_interface()) { + return (klassOop*)(start_of_nonstatic_oop_maps() + + nonstatic_oop_map_count()); + } else { + return NULL; + } + }; + // Allocation profiling support juint alloc_size() const { return _alloc_count * size_helper(); } void set_alloc_size(juint n) {} @@ -819,7 +855,7 @@ oop* adr_host_klass() const { return (oop*)&this->_host_klass;} oop* adr_signers() const { return (oop*)&this->_signers;} oop* adr_inner_classes() const { return (oop*)&this->_inner_classes;} - oop* adr_implementors() const { return (oop*)&this->_implementors[0];} + oop* adr_implementor() const { return (oop*)start_of_implementor(); } oop* adr_methods_jmethod_ids() const { return (oop*)&this->_methods_jmethod_ids;} oop* adr_methods_cached_itable_indices() const { return (oop*)&this->_methods_cached_itable_indices;} oop* adr_class_annotations() const { return (oop*)&this->_class_annotations;} diff -r f7a8920427a6 -r f3f101a5e59b src/share/vm/oops/instanceKlassKlass.cpp --- a/src/share/vm/oops/instanceKlassKlass.cpp Wed Apr 18 13:39:55 2012 -0400 +++ b/src/share/vm/oops/instanceKlassKlass.cpp Fri Apr 20 11:41:49 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -111,7 +111,7 @@ MarkSweep::mark_and_push(ik->adr_methods_parameter_annotations()); MarkSweep::mark_and_push(ik->adr_methods_default_annotations()); - // We do not follow adr_implementors() here. It is followed later + // We do not follow adr_implementor() here. It is followed later // in instanceKlass::follow_weak_klass_links() klassKlass::oop_follow_contents(obj); @@ -180,8 +180,8 @@ blk->do_oop(ik->adr_host_klass()); blk->do_oop(ik->adr_signers()); blk->do_oop(ik->adr_inner_classes()); - for (int i = 0; i < instanceKlass::implementors_limit; i++) { - blk->do_oop(&ik->adr_implementors()[i]); + if (ik->is_interface()) { + blk->do_oop(ik->adr_implementor()); } blk->do_oop(ik->adr_class_annotations()); blk->do_oop(ik->adr_fields_annotations()); @@ -232,9 +232,9 @@ if (mr.contains(adr)) blk->do_oop(adr); adr = ik->adr_inner_classes(); if (mr.contains(adr)) blk->do_oop(adr); - adr = ik->adr_implementors(); - for (int i = 0; i < instanceKlass::implementors_limit; i++) { - if (mr.contains(&adr[i])) blk->do_oop(&adr[i]); + if (ik->is_interface()) { + adr = ik->adr_implementor(); + if (mr.contains(adr)) blk->do_oop(adr); } adr = ik->adr_class_annotations(); if (mr.contains(adr)) blk->do_oop(adr); @@ -273,8 +273,8 @@ MarkSweep::adjust_pointer(ik->adr_host_klass()); MarkSweep::adjust_pointer(ik->adr_signers()); MarkSweep::adjust_pointer(ik->adr_inner_classes()); - for (int i = 0; i < instanceKlass::implementors_limit; i++) { - MarkSweep::adjust_pointer(&ik->adr_implementors()[i]); + if (ik->is_interface()) { + MarkSweep::adjust_pointer(ik->adr_implementor()); } MarkSweep::adjust_pointer(ik->adr_class_annotations()); MarkSweep::adjust_pointer(ik->adr_fields_annotations()); @@ -328,6 +328,9 @@ for (oop* cur_oop = beg_oop; cur_oop < end_oop; ++cur_oop) { PSParallelCompact::adjust_pointer(cur_oop); } + if (ik->is_interface()) { + PSParallelCompact::adjust_pointer(ik->adr_implementor()); + } OopClosure* closure = PSParallelCompact::adjust_root_pointer_closure(); iterate_c_heap_oops(ik, closure); @@ -342,11 +345,18 @@ instanceKlassKlass::allocate_instance_klass(Symbol* name, int vtable_len, int itable_len, int static_field_size, unsigned nonstatic_oop_map_count, + AccessFlags access_flags, ReferenceType rt, TRAPS) { const int nonstatic_oop_map_size = instanceKlass::nonstatic_oop_map_size(nonstatic_oop_map_count); - int size = instanceKlass::object_size(align_object_offset(vtable_len) + align_object_offset(itable_len) + nonstatic_oop_map_size); + int size = align_object_offset(vtable_len) + align_object_offset(itable_len); + if (access_flags.is_interface()) { + size += align_object_offset(nonstatic_oop_map_size) + (int)sizeof(klassOop)/HeapWordSize; + } else { + size += nonstatic_oop_map_size; + } + size = instanceKlass::object_size(size); // Allocation KlassHandle h_this_klass(THREAD, as_klassOop()); @@ -378,6 +388,7 @@ ik->set_itable_length(itable_len); ik->set_static_field_size(static_field_size); ik->set_nonstatic_oop_map_size(nonstatic_oop_map_size); + ik->set_access_flags(access_flags); assert(k()->size() == size, "wrong size for object"); ik->set_array_klasses(NULL); @@ -470,16 +481,12 @@ if (ik->is_interface()) { st->print_cr(BULLET"nof implementors: %d", ik->nof_implementors()); - int print_impl = 0; - for (int i = 0; i < instanceKlass::implementors_limit; i++) { - if (ik->implementor(i) != NULL) { - if (++print_impl == 1) - st->print_cr(BULLET"implementor: "); - st->print(" "); - ik->implementor(i)->print_value_on(st); - } + if (ik->nof_implementors() == 1) { + st->print_cr(BULLET"implementor: "); + st->print(" "); + ik->implementor()->print_value_on(st); + st->cr(); } - if (print_impl > 0) st->cr(); } st->print(BULLET"arrays: "); ik->array_klasses()->print_value_on(st); st->cr(); @@ -640,16 +647,12 @@ } // Verify implementor fields - bool saw_null_impl = false; - for (int i = 0; i < instanceKlass::implementors_limit; i++) { - klassOop im = ik->implementor(i); - if (im == NULL) { saw_null_impl = true; continue; } - guarantee(!saw_null_impl, "non-nulls must preceded all nulls"); + klassOop im = ik->implementor(); + if (im != NULL) { guarantee(ik->is_interface(), "only interfaces should have implementor set"); - guarantee(i < ik->nof_implementors(), "should only have one implementor"); guarantee(im->is_perm(), "should be in permspace"); guarantee(im->is_klass(), "should be klass"); - guarantee(!Klass::cast(klassOop(im))->is_interface(), "implementors cannot be interfaces"); + guarantee(!Klass::cast(klassOop(im))->is_interface() || im == ik->as_klassOop(), "implementors cannot be interfaces"); } // Verify local interfaces diff -r f7a8920427a6 -r f3f101a5e59b src/share/vm/oops/instanceKlassKlass.hpp --- a/src/share/vm/oops/instanceKlassKlass.hpp Wed Apr 18 13:39:55 2012 -0400 +++ b/src/share/vm/oops/instanceKlassKlass.hpp Fri Apr 20 11:41:49 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,6 +46,7 @@ int itable_len, int static_field_size, unsigned int nonstatic_oop_map_count, + AccessFlags access_flags, ReferenceType rt, TRAPS); diff -r f7a8920427a6 -r f3f101a5e59b src/share/vm/opto/library_call.cpp --- a/src/share/vm/opto/library_call.cpp Wed Apr 18 13:39:55 2012 -0400 +++ b/src/share/vm/opto/library_call.cpp Fri Apr 20 11:41:49 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -175,7 +175,11 @@ bool inline_unsafe_allocate(); bool inline_unsafe_copyMemory(); bool inline_native_currentThread(); - bool inline_native_time_funcs(bool isNano); +#ifdef TRACE_HAVE_INTRINSICS + bool inline_native_classID(); + bool inline_native_threadID(); +#endif + bool inline_native_time_funcs(address method, const char* funcName); bool inline_native_isInterrupted(); bool inline_native_Class_query(vmIntrinsics::ID id); bool inline_native_subtype_check(); @@ -638,10 +642,18 @@ case vmIntrinsics::_isInterrupted: return inline_native_isInterrupted(); +#ifdef TRACE_HAVE_INTRINSICS + case vmIntrinsics::_classID: + return inline_native_classID(); + case vmIntrinsics::_threadID: + return inline_native_threadID(); + case vmIntrinsics::_counterTime: + return inline_native_time_funcs(CAST_FROM_FN_PTR(address, TRACE_TIME_METHOD), "counterTime"); +#endif case vmIntrinsics::_currentTimeMillis: - return inline_native_time_funcs(false); + return inline_native_time_funcs(CAST_FROM_FN_PTR(address, os::javaTimeMillis), "currentTimeMillis"); case vmIntrinsics::_nanoTime: - return inline_native_time_funcs(true); + return inline_native_time_funcs(CAST_FROM_FN_PTR(address, os::javaTimeNanos), "nanoTime"); case vmIntrinsics::_allocateInstance: return inline_unsafe_allocate(); case vmIntrinsics::_copyMemory: @@ -2840,14 +2852,63 @@ return true; } +#ifdef TRACE_HAVE_INTRINSICS +/* + * oop -> myklass + * myklass->trace_id |= USED + * return myklass->trace_id & ~0x3 + */ +bool LibraryCallKit::inline_native_classID() { + int nargs = 1 + 1; + null_check_receiver(callee()); // check then ignore argument(0) + _sp += nargs; + Node* cls = do_null_check(argument(1), T_OBJECT); + _sp -= nargs; + Node* kls = load_klass_from_mirror(cls, false, nargs, NULL, 0); + _sp += nargs; + kls = do_null_check(kls, T_OBJECT); + _sp -= nargs; + ByteSize offset = TRACE_ID_OFFSET; + Node* insp = basic_plus_adr(kls, in_bytes(offset)); + Node* tvalue = make_load(NULL, insp, TypeLong::LONG, T_LONG); + Node* bits = longcon(~0x03l); // ignore bit 0 & 1 + Node* andl = _gvn.transform(new (C, 3) AndLNode(tvalue, bits)); + Node* clsused = longcon(0x01l); // set the class bit + Node* orl = _gvn.transform(new (C, 3) OrLNode(tvalue, clsused)); + + const TypePtr *adr_type = _gvn.type(insp)->isa_ptr(); + store_to_memory(control(), insp, orl, T_LONG, adr_type); + push_pair(andl); + return true; +} + +bool LibraryCallKit::inline_native_threadID() { + Node* tls_ptr = NULL; + Node* cur_thr = generate_current_thread(tls_ptr); + Node* p = basic_plus_adr(top()/*!oop*/, tls_ptr, in_bytes(JavaThread::osthread_offset())); + Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS); + p = basic_plus_adr(top()/*!oop*/, osthread, in_bytes(OSThread::thread_id_offset())); + + Node* threadid = NULL; + size_t thread_id_size = OSThread::thread_id_size(); + if (thread_id_size == (size_t) BytesPerLong) { + threadid = ConvL2I(make_load(control(), p, TypeLong::LONG, T_LONG)); + push(threadid); + } else if (thread_id_size == (size_t) BytesPerInt) { + threadid = make_load(control(), p, TypeInt::INT, T_INT); + push(threadid); + } else { + ShouldNotReachHere(); + } + return true; +} +#endif + //------------------------inline_native_time_funcs-------------- // inline code for System.currentTimeMillis() and System.nanoTime() // these have the same type and signature -bool LibraryCallKit::inline_native_time_funcs(bool isNano) { - address funcAddr = isNano ? CAST_FROM_FN_PTR(address, os::javaTimeNanos) : - CAST_FROM_FN_PTR(address, os::javaTimeMillis); - const char * funcName = isNano ? "nanoTime" : "currentTimeMillis"; - const TypeFunc *tf = OptoRuntime::current_time_millis_Type(); +bool LibraryCallKit::inline_native_time_funcs(address funcAddr, const char* funcName) { + const TypeFunc *tf = OptoRuntime::void_long_Type(); const TypePtr* no_memory_effects = NULL; Node* time = make_runtime_call(RC_LEAF, tf, funcAddr, funcName, no_memory_effects); Node* value = _gvn.transform(new (C, 1) ProjNode(time, TypeFunc::Parms+0)); diff -r f7a8920427a6 -r f3f101a5e59b src/share/vm/opto/runtime.cpp --- a/src/share/vm/opto/runtime.cpp Wed Apr 18 13:39:55 2012 -0400 +++ b/src/share/vm/opto/runtime.cpp Fri Apr 20 11:41:49 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -709,9 +709,9 @@ return TypeFunc::make(domain, range); } -//-------------- currentTimeMillis +//-------------- currentTimeMillis, currentTimeNanos, etc -const TypeFunc* OptoRuntime::current_time_millis_Type() { +const TypeFunc* OptoRuntime::void_long_Type() { // create input type (domain) const Type **fields = TypeTuple::fields(0); const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+0, fields); diff -r f7a8920427a6 -r f3f101a5e59b src/share/vm/opto/runtime.hpp --- a/src/share/vm/opto/runtime.hpp Wed Apr 18 13:39:55 2012 -0400 +++ b/src/share/vm/opto/runtime.hpp Fri Apr 20 11:41:49 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -268,7 +268,7 @@ static const TypeFunc* Math_DD_D_Type(); // mod,pow & friends static const TypeFunc* modf_Type(); static const TypeFunc* l2f_Type(); - static const TypeFunc* current_time_millis_Type(); + static const TypeFunc* void_long_Type(); static const TypeFunc* flush_windows_Type(); diff -r f7a8920427a6 -r f3f101a5e59b src/share/vm/runtime/osThread.hpp --- a/src/share/vm/runtime/osThread.hpp Wed Apr 18 13:39:55 2012 -0400 +++ b/src/share/vm/runtime/osThread.hpp Fri Apr 20 11:41:49 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -98,6 +98,7 @@ // For java intrinsics: static ByteSize interrupted_offset() { return byte_offset_of(OSThread, _interrupted); } + static ByteSize thread_id_offset() { return byte_offset_of(OSThread, _thread_id); } // Platform dependent stuff #ifdef TARGET_OS_FAMILY_linux diff -r f7a8920427a6 -r f3f101a5e59b src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Wed Apr 18 13:39:55 2012 -0400 +++ b/src/share/vm/runtime/thread.cpp Fri Apr 20 11:41:49 2012 -0700 @@ -3468,13 +3468,13 @@ create_vm_init_libraries(); } + // Notify JVMTI agents that VM initialization is complete - nop if no agents. + JvmtiExport::post_vm_initialized(); + if (!TRACE_START()) { vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION)); } - // Notify JVMTI agents that VM initialization is complete - nop if no agents. - JvmtiExport::post_vm_initialized(); - if (CleanChunkPoolAsync) { Chunk::start_chunk_pool_cleaner_task(); } diff -r f7a8920427a6 -r f3f101a5e59b src/share/vm/runtime/vmStructs.cpp --- a/src/share/vm/runtime/vmStructs.cpp Wed Apr 18 13:39:55 2012 -0400 +++ b/src/share/vm/runtime/vmStructs.cpp Fri Apr 20 11:41:49 2012 -0700 @@ -292,8 +292,6 @@ nonstatic_field(instanceKlass, _method_ordering, typeArrayOop) \ nonstatic_field(instanceKlass, _local_interfaces, objArrayOop) \ nonstatic_field(instanceKlass, _transitive_interfaces, objArrayOop) \ - nonstatic_field(instanceKlass, _nof_implementors, int) \ - nonstatic_field(instanceKlass, _implementors[0], klassOop) \ nonstatic_field(instanceKlass, _fields, typeArrayOop) \ nonstatic_field(instanceKlass, _java_fields_count, u2) \ nonstatic_field(instanceKlass, _constants, constantPoolOop) \ @@ -2343,7 +2341,6 @@ /* instanceKlass enum */ \ /*************************************/ \ \ - declare_constant(instanceKlass::implementors_limit) \ \ /*************************************/ \ /* FieldInfo FieldOffset enum */ \ diff -r f7a8920427a6 -r f3f101a5e59b src/share/vm/trace/traceMacros.hpp --- a/src/share/vm/trace/traceMacros.hpp Wed Apr 18 13:39:55 2012 -0400 +++ b/src/share/vm/trace/traceMacros.hpp Fri Apr 20 11:41:49 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,5 +43,9 @@ #define TRACE_SET_KLASS_TRACE_ID(x1, x2) do { } while (0) #define TRACE_DEFINE_KLASS_METHODS typedef int ___IGNORED_hs_trace_type1 #define TRACE_DEFINE_KLASS_TRACE_ID typedef int ___IGNORED_hs_trace_type2 +#define TRACE_DEFINE_OFFSET typedef int ___IGNORED_hs_trace_type3 +#define TRACE_ID_OFFSET in_ByteSize(0); ShouldNotReachHere() +#define TRACE_TEMPLATES(template) +#define TRACE_INTRINSICS(do_intrinsic, do_class, do_name, do_signature, do_alias) #endif diff -r f7a8920427a6 -r f3f101a5e59b test/runtime/7158988/FieldMonitor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/7158988/FieldMonitor.java Fri Apr 20 11:41:49 2012 -0700 @@ -0,0 +1,249 @@ +/* + * Copyright 2012 SAP AG. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test FieldMonitor.java + * @bug 7158988 + * @summary verify jvm does not crash while debugging + * @run shell TestFieldMonitor.sh + * @author axel.siebenborn@sap.com + */ +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Writer; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import com.sun.jdi.Bootstrap; +import com.sun.jdi.Field; +import com.sun.jdi.ReferenceType; +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.IllegalConnectorArgumentsException; +import com.sun.jdi.connect.LaunchingConnector; +import com.sun.jdi.connect.VMStartException; +import com.sun.jdi.event.ClassPrepareEvent; +import com.sun.jdi.event.Event; +import com.sun.jdi.event.EventQueue; +import com.sun.jdi.event.EventSet; +import com.sun.jdi.event.ModificationWatchpointEvent; +import com.sun.jdi.event.VMDeathEvent; +import com.sun.jdi.event.VMDisconnectEvent; +import com.sun.jdi.request.ClassPrepareRequest; +import com.sun.jdi.request.EventRequest; +import com.sun.jdi.request.EventRequestManager; +import com.sun.jdi.request.ModificationWatchpointRequest; + +public class FieldMonitor { + + public static final String CLASS_NAME = "TestPostFieldModification"; + public static final String FIELD_NAME = "value"; + public static final String ARGUMENTS = "-Xshare:off -XX:+PrintGC"; + + public static void main(String[] args) + throws IOException, InterruptedException { + + StringBuffer sb = new StringBuffer(); + + for (int i=0; i < args.length; i++) { + sb.append(' '); + sb.append(args[i]); + } + //VirtualMachine vm = launchTarget(sb.toString()); + VirtualMachine vm = launchTarget(CLASS_NAME); + + System.out.println("Vm launched"); + // set watch field on already loaded classes + List referenceTypes = vm + .classesByName(CLASS_NAME); + for (ReferenceType refType : referenceTypes) { + addFieldWatch(vm, refType); + } + // watch for loaded classes + addClassWatch(vm); + + // process events + EventQueue eventQueue = vm.eventQueue(); + // resume the vm + + Process process = vm.process(); + + + // Copy target's output and error to our output and error. + Thread outThread = new StreamRedirectThread("out reader", process.getInputStream()); + Thread errThread = new StreamRedirectThread("error reader", process.getErrorStream()); + + errThread.start(); + outThread.start(); + + + vm.resume(); + boolean connected = true; + while (connected) { + EventSet eventSet = eventQueue.remove(); + for (Event event : eventSet) { + if (event instanceof VMDeathEvent + || event instanceof VMDisconnectEvent) { + // exit + connected = false; + } else if (event instanceof ClassPrepareEvent) { + // watch field on loaded class + System.out.println("ClassPrepareEvent"); + ClassPrepareEvent classPrepEvent = (ClassPrepareEvent) event; + ReferenceType refType = classPrepEvent + .referenceType(); + addFieldWatch(vm, refType); + } else if (event instanceof ModificationWatchpointEvent) { + System.out.println("sleep for 500 ms"); + Thread.sleep(500); + System.out.println("resume..."); + + ModificationWatchpointEvent modEvent = (ModificationWatchpointEvent) event; + System.out.println("old=" + + modEvent.valueCurrent()); + System.out.println("new=" + modEvent.valueToBe()); + System.out.println(); + } + } + eventSet.resume(); + } + // Shutdown begins when event thread terminates + try { + errThread.join(); // Make sure output is forwarded + outThread.join(); + } catch (InterruptedException exc) { + // we don't interrupt + } + } + + /** + * Find a com.sun.jdi.CommandLineLaunch connector + */ + static LaunchingConnector findLaunchingConnector() { + List connectors = Bootstrap.virtualMachineManager().allConnectors(); + Iterator iter = connectors.iterator(); + while (iter.hasNext()) { + Connector connector = iter.next(); + if (connector.name().equals("com.sun.jdi.CommandLineLaunch")) { + return (LaunchingConnector)connector; + } + } + throw new Error("No launching connector"); + } + /** + * Return the launching connector's arguments. + */ + static Map connectorArguments(LaunchingConnector connector, String mainArgs) { + Map arguments = connector.defaultArguments(); + for (String key : arguments.keySet()) { + System.out.println(key); + } + + Connector.Argument mainArg = (Connector.Argument)arguments.get("main"); + if (mainArg == null) { + throw new Error("Bad launching connector"); + } + mainArg.setValue(mainArgs); + + Connector.Argument optionsArg = (Connector.Argument)arguments.get("options"); + if (optionsArg == null) { + throw new Error("Bad launching connector"); + } + optionsArg.setValue(ARGUMENTS); + return arguments; + } + + static VirtualMachine launchTarget(String mainArgs) { + LaunchingConnector connector = findLaunchingConnector(); + Map arguments = connectorArguments(connector, mainArgs); + try { + return (VirtualMachine) connector.launch(arguments); + } catch (IOException exc) { + throw new Error("Unable to launch target VM: " + exc); + } catch (IllegalConnectorArgumentsException exc) { + throw new Error("Internal error: " + exc); + } catch (VMStartException exc) { + throw new Error("Target VM failed to initialize: " + + exc.getMessage()); + } +} + + + private static void addClassWatch(VirtualMachine vm) { + EventRequestManager erm = vm.eventRequestManager(); + ClassPrepareRequest classPrepareRequest = erm + .createClassPrepareRequest(); + classPrepareRequest.addClassFilter(CLASS_NAME); + classPrepareRequest.setEnabled(true); + } + + + private static void addFieldWatch(VirtualMachine vm, + ReferenceType refType) { + EventRequestManager erm = vm.eventRequestManager(); + Field field = refType.fieldByName(FIELD_NAME); + ModificationWatchpointRequest modificationWatchpointRequest = erm + .createModificationWatchpointRequest(field); + modificationWatchpointRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + modificationWatchpointRequest.setEnabled(true); + } +} + +class StreamRedirectThread extends Thread { + + private final BufferedReader in; + + private static final int BUFFER_SIZE = 2048; + + /** + * Set up for copy. + * @param name Name of the thread + * @param in Stream to copy from + * @param out Stream to copy to + */ + StreamRedirectThread(String name, InputStream in) { + super(name); + this.in = new BufferedReader(new InputStreamReader(in)); + } + + /** + * Copy. + */ + public void run() { + try { + String line; + while ((line = in.readLine ()) != null) { + System.out.println ("testvm: " + line); + } + System.out.flush(); + } catch(IOException exc) { + System.err.println("Child I/O Transfer - " + exc); + } + } +} diff -r f7a8920427a6 -r f3f101a5e59b test/runtime/7158988/TestFieldMonitor.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/7158988/TestFieldMonitor.sh Fri Apr 20 11:41:49 2012 -0700 @@ -0,0 +1,94 @@ +#!/bin/sh + +if [ "${TESTSRC}" = "" ] +then TESTSRC=. +fi + +if [ "${TESTJAVA}" = "" ] +then + PARENT=`dirname \`which java\`` + TESTJAVA=`dirname ${PARENT}` + echo "TESTJAVA not set, selecting " ${TESTJAVA} + echo "If this is incorrect, try setting the variable manually." +fi + +if [ "${TESTCLASSES}" = "" ] +then + echo "TESTCLASSES not set. Test cannot execute. Failed." + exit 1 +fi + +BIT_FLAG="" + +# set platform-dependent variables +OS=`uname -s` +case "$OS" in + SunOS | Linux ) + NULL=/dev/null + PS=":" + FS="/" + ## for solaris, linux it's HOME + FILE_LOCATION=$HOME + if [ -f ${FILE_LOCATION}${FS}JDK64BIT -a ${OS} = "SunOS" -a `uname -p`='sparc' ] + then + BIT_FLAG="-d64" + fi + ;; + Windows_95 | Windows_98 | Windows_ME ) + NULL=NUL + PS=";" + FS="\\" + echo "Test skipped, only for WinNT" + exit 0 + ;; + Windows_NT ) + NULL=NUL + PS=";" + FS="\\" + ;; + * ) + echo "Unrecognized system!" + exit 1; + ;; +esac + +#CLASSPATH=.${PS}${TESTCLASSES} ; export CLASSPATH + +cp ${TESTSRC}${FS}*.java . + +${TESTJAVA}${FS}bin${FS}java ${BIT_FLAG} -fullversion + +${TESTJAVA}${FS}bin${FS}javac -classpath .${PS}$TESTJAVA${FS}lib${FS}tools.jar *.java + +${TESTJAVA}${FS}bin${FS}java ${BIT_FLAG} -classpath .${PS}$TESTJAVA${FS}lib${FS}tools.jar FieldMonitor > test.out 2>&1 & + +P_PID=$! + +sleep 60 +STATUS=0 + +case "$OS" in + SunOS | Linux ) + ps -ef | grep $P_PID | grep -v grep > ${NULL} + if [ $? = 0 ]; then + kill -9 $P_PID + STATUS=1 + fi + ;; + * ) + ps | grep -i "FieldMonitor" | grep -v grep > ${NULL} + if [ $? = 0 ]; then + C_PID=`ps | grep -i "FieldMonitor" | awk '{print $1}'` + kill -s 9 $C_PID + STATUS=1 + fi + ;; +esac + +grep "A fatal error has been detected" test.out > ${NULL} +if [ $? = 0 ]; then + cat test.out + STATUS=1 +fi + +exit $STATUS diff -r f7a8920427a6 -r f3f101a5e59b test/runtime/7158988/TestPostFieldModification.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/7158988/TestPostFieldModification.java Fri Apr 20 11:41:49 2012 -0700 @@ -0,0 +1,58 @@ +/* + * Copyright 2012 SAP AG. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +public class TestPostFieldModification { + + public String value; // watch modification of value + + public static void main(String[] args){ + + System.out.println("Start threads"); + // this thread modifies the field 'value' + new Thread() { + TestPostFieldModification test = new TestPostFieldModification(); + public void run() { + test.value="test"; + for(int i = 0; i < 10; i++) { + test.value += new String("_test"); + } + } + }.start(); + + // this thread is used to trigger a gc + Thread d = new Thread() { + public void run() { + while(true) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + + } + System.gc(); + } + } + }; + d.setDaemon(true); + d.start(); + } +}