# HG changeset patch # User trims # Date 1300480109 25200 # Node ID e97ad5d5c9904f911aba163c29d56225d10a7ae3 # Parent fc1b183bfc0a2c1a65440d45a2754c9532ff2e87# Parent 048f98400b8ec5cd7176a112080f7f2a6b8d2240 Merge diff -r fc1b183bfc0a -r e97ad5d5c990 src/cpu/sparc/vm/assembler_sparc.cpp --- a/src/cpu/sparc/vm/assembler_sparc.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/cpu/sparc/vm/assembler_sparc.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -3179,7 +3179,7 @@ Label& wrong_method_type) { assert_different_registers(mtype_reg, mh_reg, temp_reg); // compare method type against that of the receiver - RegisterOrConstant mhtype_offset = delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg); + RegisterOrConstant mhtype_offset = delayed_value(java_lang_invoke_MethodHandle::type_offset_in_bytes, temp_reg); load_heap_oop(mh_reg, mhtype_offset, temp_reg); cmp(temp_reg, mtype_reg); br(Assembler::notEqual, false, Assembler::pn, wrong_method_type); @@ -3195,14 +3195,14 @@ Register temp_reg) { assert_different_registers(vmslots_reg, mh_reg, temp_reg); // load mh.type.form.vmslots - if (java_dyn_MethodHandle::vmslots_offset_in_bytes() != 0) { + if (java_lang_invoke_MethodHandle::vmslots_offset_in_bytes() != 0) { // hoist vmslots into every mh to avoid dependent load chain - ld( Address(mh_reg, delayed_value(java_dyn_MethodHandle::vmslots_offset_in_bytes, temp_reg)), vmslots_reg); + ld( Address(mh_reg, delayed_value(java_lang_invoke_MethodHandle::vmslots_offset_in_bytes, temp_reg)), vmslots_reg); } else { Register temp2_reg = vmslots_reg; - load_heap_oop(Address(mh_reg, delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg)), temp2_reg); - load_heap_oop(Address(temp2_reg, delayed_value(java_dyn_MethodType::form_offset_in_bytes, temp_reg)), temp2_reg); - ld( Address(temp2_reg, delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, temp_reg)), vmslots_reg); + load_heap_oop(Address(mh_reg, delayed_value(java_lang_invoke_MethodHandle::type_offset_in_bytes, temp_reg)), temp2_reg); + load_heap_oop(Address(temp2_reg, delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, temp_reg)), temp2_reg); + ld( Address(temp2_reg, delayed_value(java_lang_invoke_MethodTypeForm::vmslots_offset_in_bytes, temp_reg)), vmslots_reg); } } @@ -3213,7 +3213,7 @@ // pick out the interpreted side of the handler // NOTE: vmentry is not an oop! - ld_ptr(mh_reg, delayed_value(java_dyn_MethodHandle::vmentry_offset_in_bytes, temp_reg), temp_reg); + ld_ptr(mh_reg, delayed_value(java_lang_invoke_MethodHandle::vmentry_offset_in_bytes, temp_reg), temp_reg); // off we go... ld_ptr(temp_reg, MethodHandleEntry::from_interpreted_entry_offset_in_bytes(), temp_reg); diff -r fc1b183bfc0a -r e97ad5d5c990 src/cpu/sparc/vm/cppInterpreter_sparc.cpp --- a/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2011, 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 @@ -1188,7 +1188,7 @@ __ st_ptr(O2, XXX_STATE(_stack)); // PREPUSH __ lduh(max_stack, O3); // Full size expression stack - guarantee(!EnableMethodHandles, "no support yet for java.dyn.MethodHandle"); //6815692 + guarantee(!EnableMethodHandles, "no support yet for java.lang.invoke.MethodHandle"); //6815692 //6815692//if (EnableMethodHandles) //6815692// __ inc(O3, methodOopDesc::extra_stack_entries()); __ sll(O3, LogBytesPerWord, O3); diff -r fc1b183bfc0a -r e97ad5d5c990 src/cpu/sparc/vm/globals_sparc.hpp --- a/src/cpu/sparc/vm/globals_sparc.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/cpu/sparc/vm/globals_sparc.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, 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 @@ -51,6 +51,7 @@ define_pd_global(intx, OptoLoopAlignment, 16); // = 4*wordSize define_pd_global(intx, InlineFrequencyCount, 50); // we can use more inlining on the SPARC define_pd_global(intx, InlineSmallCode, 1500); + #ifdef _LP64 // Stack slots are 2X larger in LP64 than in the 32 bit VM. define_pd_global(intx, ThreadStackSize, 1024); @@ -71,4 +72,6 @@ define_pd_global(bool, UseMembar, false); +// GC Ergo Flags +define_pd_global(intx, CMSYoungGenPerWorker, 16*M); // default max size of CMS young gen, per GC worker thread #endif // CPU_SPARC_VM_GLOBALS_SPARC_HPP diff -r fc1b183bfc0a -r e97ad5d5c990 src/cpu/sparc/vm/interpreter_sparc.cpp --- a/src/cpu/sparc/vm/interpreter_sparc.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/cpu/sparc/vm/interpreter_sparc.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -260,7 +260,7 @@ // Method handle invoker -// Dispatch a method of the form java.dyn.MethodHandles::invoke(...) +// Dispatch a method of the form java.lang.invoke.MethodHandles::invoke(...) address InterpreterGenerator::generate_method_handle_entry(void) { if (!EnableMethodHandles) { return generate_abstract_entry(); diff -r fc1b183bfc0a -r e97ad5d5c990 src/cpu/sparc/vm/methodHandles_sparc.cpp --- a/src/cpu/sparc/vm/methodHandles_sparc.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/cpu/sparc/vm/methodHandles_sparc.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -112,8 +112,8 @@ } // given the MethodType, find out where the MH argument is buried - __ load_heap_oop(Address(O0_mtype, __ delayed_value(java_dyn_MethodType::form_offset_in_bytes, O1_scratch)), O4_argslot); - __ ldsw( Address(O4_argslot, __ delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, O1_scratch)), O4_argslot); + __ load_heap_oop(Address(O0_mtype, __ delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, O1_scratch)), O4_argslot); + __ ldsw( Address(O4_argslot, __ delayed_value(java_lang_invoke_MethodTypeForm::vmslots_offset_in_bytes, O1_scratch)), O4_argslot); __ add(Gargs, __ argument_offset(O4_argslot, 1), O4_argbase); // Note: argument_address uses its input as a scratch register! __ ld_ptr(Address(O4_argbase, -Interpreter::stackElementSize), G3_method_handle); @@ -141,10 +141,10 @@ // load up an adapter from the calling type (Java weaves this) Register O2_form = O2_scratch; Register O3_adapter = O3_scratch; - __ load_heap_oop(Address(O0_mtype, __ delayed_value(java_dyn_MethodType::form_offset_in_bytes, O1_scratch)), O2_form); - // load_heap_oop(Address(O2_form, __ delayed_value(java_dyn_MethodTypeForm::genericInvoker_offset_in_bytes, O1_scratch)), O3_adapter); + __ load_heap_oop(Address(O0_mtype, __ delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, O1_scratch)), O2_form); + // load_heap_oop(Address(O2_form, __ delayed_value(java_lang_invoke_MethodTypeForm::genericInvoker_offset_in_bytes, O1_scratch)), O3_adapter); // deal with old JDK versions: - __ add( Address(O2_form, __ delayed_value(java_dyn_MethodTypeForm::genericInvoker_offset_in_bytes, O1_scratch)), O3_adapter); + __ add( Address(O2_form, __ delayed_value(java_lang_invoke_MethodTypeForm::genericInvoker_offset_in_bytes, O1_scratch)), O3_adapter); __ cmp(O3_adapter, O2_form); Label sorry_no_invoke_generic; __ brx(Assembler::lessUnsigned, false, Assembler::pn, sorry_no_invoke_generic); @@ -376,16 +376,16 @@ // which conversion op types are implemented here? int MethodHandles::adapter_conversion_ops_supported_mask() { - return ((1<P, nameSymbol + OFFSET_Symbol_length, &nameSymbolLength, 2); CHECK_FAIL(err); nameString = (char*)calloc(nameSymbolLength + 1, 1); @@ -535,6 +537,7 @@ CHECK_FAIL(err); err = read_pointer(J, constantPool + signatureIndex * POINTER_SIZE + SIZE_constantPoolOopDesc, &signatureSymbol); CHECK_FAIL(err); + signatureSymbol &= (~1); // remove metadata lsb err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_length, &signatureSymbolLength, 2); CHECK_FAIL(err); signatureString = (char*)calloc(signatureSymbolLength + 1, 1); diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/c1/c1_Canonicalizer.cpp --- a/src/share/vm/c1/c1_Canonicalizer.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/c1/c1_Canonicalizer.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -209,7 +209,7 @@ // limit this optimization to current block if (value != NULL && in_current_block(conv)) { set_canonical(new StoreField(x->obj(), x->offset(), x->field(), value, x->is_static(), - x->state_before(), x->is_loaded(), x->is_initialized())); + x->state_before(), x->needs_patching())); return; } } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/c1/c1_GraphBuilder.cpp --- a/src/share/vm/c1/c1_GraphBuilder.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/c1/c1_GraphBuilder.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1456,12 +1456,12 @@ BasicType field_type = field->type()->basic_type(); ValueType* type = as_ValueType(field_type); // call will_link again to determine if the field is valid. - const bool is_loaded = holder->is_loaded() && - field->will_link(method()->holder(), code); - const bool is_initialized = is_loaded && holder->is_initialized(); + const bool needs_patching = !holder->is_loaded() || + !field->will_link(method()->holder(), code) || + PatchALot; ValueStack* state_before = NULL; - if (!is_initialized || PatchALot) { + if (!holder->is_initialized() || needs_patching) { // save state before instruction for debug info when // deoptimization happens during patching state_before = copy_state_before(); @@ -1469,10 +1469,6 @@ Value obj = NULL; if (code == Bytecodes::_getstatic || code == Bytecodes::_putstatic) { - // commoning of class constants should only occur if the class is - // fully initialized and resolved in this constant pool. The will_link test - // above essentially checks if this class is resolved in this constant pool - // so, the is_initialized flag should be suffiect. if (state_before != NULL) { // build a patching constant obj = new Constant(new ClassConstant(holder), state_before); @@ -1482,7 +1478,7 @@ } - const int offset = is_loaded ? field->offset() : -1; + const int offset = !needs_patching ? field->offset() : -1; switch (code) { case Bytecodes::_getstatic: { // check for compile-time constants, i.e., initialized static final fields @@ -1509,7 +1505,7 @@ state_before = copy_state_for_exception(); } push(type, append(new LoadField(append(obj), offset, field, true, - state_before, is_loaded, is_initialized))); + state_before, needs_patching))); } break; } @@ -1518,7 +1514,7 @@ if (state_before == NULL) { state_before = copy_state_for_exception(); } - append(new StoreField(append(obj), offset, field, val, true, state_before, is_loaded, is_initialized)); + append(new StoreField(append(obj), offset, field, val, true, state_before, needs_patching)); } break; case Bytecodes::_getfield : @@ -1526,8 +1522,8 @@ if (state_before == NULL) { state_before = copy_state_for_exception(); } - LoadField* load = new LoadField(apop(), offset, field, false, state_before, is_loaded, true); - Value replacement = is_loaded ? _memory->load(load) : load; + LoadField* load = new LoadField(apop(), offset, field, false, state_before, needs_patching); + Value replacement = !needs_patching ? _memory->load(load) : load; if (replacement != load) { assert(replacement->is_linked() || !replacement->can_be_linked(), "should already by linked"); push(type, replacement); @@ -1542,8 +1538,8 @@ if (state_before == NULL) { state_before = copy_state_for_exception(); } - StoreField* store = new StoreField(apop(), offset, field, val, false, state_before, is_loaded, true); - if (is_loaded) store = _memory->store(store); + StoreField* store = new StoreField(apop(), offset, field, val, false, state_before, needs_patching); + if (!needs_patching) store = _memory->store(store); if (store != NULL) { append(store); } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/c1/c1_Instruction.hpp --- a/src/share/vm/c1/c1_Instruction.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/c1/c1_Instruction.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -323,8 +323,6 @@ CanTrapFlag, DirectCompareFlag, IsEliminatedFlag, - IsInitializedFlag, - IsLoadedFlag, IsSafepointFlag, IsStaticFlag, IsStrictfpFlag, @@ -693,7 +691,7 @@ public: // creation AccessField(Value obj, int offset, ciField* field, bool is_static, - ValueStack* state_before, bool is_loaded, bool is_initialized) + ValueStack* state_before, bool needs_patching) : Instruction(as_ValueType(field->type()->basic_type()), state_before) , _obj(obj) , _offset(offset) @@ -701,16 +699,9 @@ , _explicit_null_check(NULL) { set_needs_null_check(!is_static); - set_flag(IsLoadedFlag, is_loaded); - set_flag(IsInitializedFlag, is_initialized); set_flag(IsStaticFlag, is_static); + set_flag(NeedsPatchingFlag, needs_patching); ASSERT_VALUES - if (!is_loaded || (PatchALot && !field->is_volatile())) { - // need to patch if the holder wasn't loaded or we're testing - // using PatchALot. Don't allow PatchALot for fields which are - // known to be volatile they aren't patchable. - set_flag(NeedsPatchingFlag, true); - } // pin of all instructions with memory access pin(); } @@ -721,11 +712,14 @@ ciField* field() const { return _field; } BasicType field_type() const { return _field->type()->basic_type(); } bool is_static() const { return check_flag(IsStaticFlag); } - bool is_loaded() const { return check_flag(IsLoadedFlag); } - bool is_initialized() const { return check_flag(IsInitializedFlag); } NullCheck* explicit_null_check() const { return _explicit_null_check; } bool needs_patching() const { return check_flag(NeedsPatchingFlag); } + // Unresolved getstatic and putstatic can cause initialization. + // Technically it occurs at the Constant that materializes the base + // of the static fields but it's simpler to model it here. + bool is_init_point() const { return is_static() && (needs_patching() || !_field->holder()->is_initialized()); } + // manipulation // Under certain circumstances, if a previous NullCheck instruction @@ -745,15 +739,15 @@ public: // creation LoadField(Value obj, int offset, ciField* field, bool is_static, - ValueStack* state_before, bool is_loaded, bool is_initialized) - : AccessField(obj, offset, field, is_static, state_before, is_loaded, is_initialized) + ValueStack* state_before, bool needs_patching) + : AccessField(obj, offset, field, is_static, state_before, needs_patching) {} ciType* declared_type() const; ciType* exact_type() const; // generic - HASHING2(LoadField, is_loaded() && !field()->is_volatile(), obj()->subst(), offset()) // cannot be eliminated if not yet loaded or if volatile + HASHING2(LoadField, !needs_patching() && !field()->is_volatile(), obj()->subst(), offset()) // cannot be eliminated if needs patching or if volatile }; @@ -764,8 +758,8 @@ public: // creation StoreField(Value obj, int offset, ciField* field, Value value, bool is_static, - ValueStack* state_before, bool is_loaded, bool is_initialized) - : AccessField(obj, offset, field, is_static, state_before, is_loaded, is_initialized) + ValueStack* state_before, bool needs_patching) + : AccessField(obj, offset, field, is_static, state_before, needs_patching) , _value(value) { set_flag(NeedsWriteBarrierFlag, as_ValueType(field_type())->is_object()); diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/c1/c1_LIR.hpp --- a/src/share/vm/c1/c1_LIR.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/c1/c1_LIR.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, 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 @@ -1156,7 +1156,7 @@ return is_invokedynamic() // An invokedynamic is always a MethodHandle call site. || - (method()->holder()->name() == ciSymbol::java_dyn_MethodHandle() && + (method()->holder()->name() == ciSymbol::java_lang_invoke_MethodHandle() && methodOopDesc::is_method_handle_invoke_name(method()->name()->sid())); } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/c1/c1_LIRGenerator.cpp --- a/src/share/vm/c1/c1_LIRGenerator.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/c1/c1_LIRGenerator.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1559,9 +1559,7 @@ (info ? new CodeEmitInfo(info) : NULL)); } - if (is_volatile) { - assert(!needs_patching && x->is_loaded(), - "how do we know it's volatile if it's not loaded"); + if (is_volatile && !needs_patching) { volatile_field_store(value.result(), address, info); } else { LIR_PatchCode patch_code = needs_patching ? lir_patch_normal : lir_patch_none; @@ -1627,9 +1625,7 @@ address = generate_address(object.result(), x->offset(), field_type); } - if (is_volatile) { - assert(!needs_patching && x->is_loaded(), - "how do we know it's volatile if it's not loaded"); + if (is_volatile && !needs_patching) { volatile_field_load(address, reg, info); } else { LIR_PatchCode patch_code = needs_patching ? lir_patch_normal : lir_patch_none; @@ -2516,7 +2512,7 @@ __ load(new LIR_Address(tmp, call_site_offset, T_OBJECT), tmp); // Load target MethodHandle from CallSite object. - __ load(new LIR_Address(tmp, java_dyn_CallSite::target_offset_in_bytes(), T_OBJECT), receiver); + __ load(new LIR_Address(tmp, java_lang_invoke_CallSite::target_offset_in_bytes(), T_OBJECT), receiver); __ call_dynamic(target, receiver, result_register, SharedRuntime::get_resolve_opt_virtual_call_stub(), diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/c1/c1_LinearScan.cpp --- a/src/share/vm/c1/c1_LinearScan.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/c1/c1_LinearScan.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -2703,7 +2703,7 @@ assert(_fpu_stack_allocator != NULL, "must be present"); opr = _fpu_stack_allocator->to_fpu_stack(opr); - assert(opr->fpu_regnrLo() == opr->fpu_regnrHi(), "assumed in calculation (only fpu_regnrHi is used)"); + assert(opr->fpu_regnrLo() == opr->fpu_regnrHi(), "assumed in calculation (only fpu_regnrLo is used)"); #endif #ifdef SPARC assert(opr->fpu_regnrLo() == opr->fpu_regnrHi() + 1, "assumed in calculation (only fpu_regnrHi is used)"); @@ -2715,7 +2715,12 @@ assert(opr->fpu_regnrLo() == opr->fpu_regnrHi(), "assumed in calculation (only fpu_regnrHi is used)"); #endif +#ifdef VM_LITTLE_ENDIAN + VMReg rname_first = frame_map()->fpu_regname(opr->fpu_regnrLo()); +#else VMReg rname_first = frame_map()->fpu_regname(opr->fpu_regnrHi()); +#endif + #ifdef _LP64 first = new LocationValue(Location::new_reg_loc(Location::dbl, rname_first)); second = &_int_0_scope_value; diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/c1/c1_ValueMap.hpp --- a/src/share/vm/c1/c1_ValueMap.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/c1/c1_ValueMap.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -141,7 +141,8 @@ // visitor functions void do_StoreField (StoreField* x) { - if (!x->is_initialized()) { + if (x->is_init_point()) { + // putstatic is an initialization point so treat it as a wide kill kill_memory(); } else { kill_field(x->field()); @@ -159,7 +160,8 @@ void do_Local (Local* x) { /* nothing to do */ } void do_Constant (Constant* x) { /* nothing to do */ } void do_LoadField (LoadField* x) { - if (!x->is_initialized()) { + if (x->is_init_point()) { + // getstatic is an initialization point so treat it as a wide kill kill_memory(); } } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/ci/ciCallSite.cpp --- a/src/share/vm/ci/ciCallSite.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/ci/ciCallSite.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2011, 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 @@ -34,7 +34,7 @@ // Return the target MethodHandle of this CallSite. ciMethodHandle* ciCallSite::get_target() const { VM_ENTRY_MARK; - oop method_handle_oop = java_dyn_CallSite::target(get_oop()); + oop method_handle_oop = java_lang_invoke_CallSite::target(get_oop()); return CURRENT_ENV->get_object(method_handle_oop)->as_method_handle(); } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/ci/ciCallSite.hpp --- a/src/share/vm/ci/ciCallSite.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/ci/ciCallSite.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2011, 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 @@ -29,7 +29,7 @@ // ciCallSite // -// The class represents a java.dyn.CallSite object. +// The class represents a java.lang.invoke.CallSite object. class ciCallSite : public ciInstance { public: ciCallSite(instanceHandle h_i) : ciInstance(h_i) {} diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/ci/ciField.cpp --- a/src/share/vm/ci/ciField.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/ci/ciField.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -177,7 +177,7 @@ // Never trust strangely unstable finals: System.out, etc. return false; // Even if general trusting is disabled, trust system-built closures in these packages. - if (holder->is_in_package("java/dyn") || holder->is_in_package("sun/dyn")) + if (holder->is_in_package("java/lang/invoke") || holder->is_in_package("sun/invoke")) return true; return TrustFinalNonStaticFields; } @@ -191,8 +191,9 @@ // Check to see if the field is constant. if (_holder->is_initialized() && this->is_final()) { if (!this->is_static()) { - // A field can be constant if it's a final static field or if it's - // a final non-static field of a trusted class ({java,sun}.dyn). + // A field can be constant if it's a final static field or if + // it's a final non-static field of a trusted class (classes in + // java.lang.invoke and sun.invoke packages and subpackages). if (trust_final_non_static_fields(_holder)) { _is_constant = true; return; diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/ci/ciMethod.cpp --- a/src/share/vm/ci/ciMethod.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/ci/ciMethod.cpp Fri Mar 18 13:28:29 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -769,7 +769,7 @@ // signature-polymorphic MethodHandle methods, invokeExact or invokeGeneric. bool ciMethod::is_method_handle_invoke() const { if (!is_loaded()) { - bool flag = (holder()->name() == ciSymbol::java_dyn_MethodHandle() && + bool flag = (holder()->name() == ciSymbol::java_lang_invoke_MethodHandle() && methodOopDesc::is_method_handle_invoke_name(name()->sid())); return flag; } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/ci/ciMethodHandle.hpp --- a/src/share/vm/ci/ciMethodHandle.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/ci/ciMethodHandle.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2011, 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 @@ -30,7 +30,7 @@ // ciMethodHandle // -// The class represents a java.dyn.MethodHandle object. +// The class represents a java.lang.invoke.MethodHandle object. class ciMethodHandle : public ciInstance { private: ciMethod* _callee; diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/ci/ciObjectFactory.cpp --- a/src/share/vm/ci/ciObjectFactory.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/ci/ciObjectFactory.cpp Fri Mar 18 13:28:29 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -342,9 +342,9 @@ return new (arena()) ciMethodData(h_md); } else if (o->is_instance()) { instanceHandle h_i(THREAD, (instanceOop)o); - if (java_dyn_CallSite::is_instance(o)) + if (java_lang_invoke_CallSite::is_instance(o)) return new (arena()) ciCallSite(h_i); - else if (java_dyn_MethodHandle::is_instance(o)) + else if (java_lang_invoke_MethodHandle::is_instance(o)) return new (arena()) ciMethodHandle(h_i); else return new (arena()) ciInstance(h_i); diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/ci/ciStreams.cpp --- a/src/share/vm/ci/ciStreams.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/ci/ciStreams.cpp Fri Mar 18 13:28:29 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -380,7 +380,7 @@ bool ignore; // report as InvokeDynamic for invokedynamic, which is syntactically classless if (cur_bc() == Bytecodes::_invokedynamic) - return CURRENT_ENV->get_klass_by_name(_holder, ciSymbol::java_dyn_InvokeDynamic(), false); + return CURRENT_ENV->get_klass_by_name(_holder, ciSymbol::java_lang_invoke_InvokeDynamic(), false); return CURRENT_ENV->get_klass_by_index(cpool, get_method_holder_index(), ignore, _holder); } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/classfile/classFileParser.cpp --- a/src/share/vm/classfile/classFileParser.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/classfile/classFileParser.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -146,12 +146,14 @@ break; case JVM_CONSTANT_MethodHandle : case JVM_CONSTANT_MethodType : - if (!EnableMethodHandles || - _major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { + if (_major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { classfile_parse_error( - (!EnableMethodHandles ? - "This JVM does not support constant tag %u in class file %s" : - "Class file version does not support constant tag %u in class file %s"), + "Class file version does not support constant tag %u in class file %s", + tag, CHECK); + } + if (!EnableMethodHandles) { + classfile_parse_error( + "This JVM does not support constant tag %u in class file %s", tag, CHECK); } if (tag == JVM_CONSTANT_MethodHandle) { @@ -170,12 +172,14 @@ case JVM_CONSTANT_InvokeDynamicTrans : // this tag appears only in old classfiles case JVM_CONSTANT_InvokeDynamic : { - if (!EnableInvokeDynamic || - _major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { + if (_major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { classfile_parse_error( - (!EnableInvokeDynamic ? - "This JVM does not support constant tag %u in class file %s" : - "Class file version does not support constant tag %u in class file %s"), + "Class file version does not support constant tag %u in class file %s", + tag, CHECK); + } + if (!EnableInvokeDynamic) { + classfile_parse_error( + "This JVM does not support constant tag %u in class file %s", tag, CHECK); } cfs->guarantee_more(5, CHECK); // bsm_index, nt, tag/access_flags @@ -1616,8 +1620,13 @@ AccessFlags access_flags; if (name == vmSymbols::class_initializer_name()) { - // We ignore the access flags for a class initializer. (JVM Spec. p. 116) - flags = JVM_ACC_STATIC; + // We ignore the other access flags for a valid class initializer. + // (JVM Spec 2nd ed., chapter 4.6) + if (_major_version < 51) { // backward compatibility + flags = JVM_ACC_STATIC; + } else if ((flags & JVM_ACC_STATIC) == JVM_ACC_STATIC) { + flags &= JVM_ACC_STATIC | JVM_ACC_STRICT; + } } else { verify_legal_method_modifiers(flags, is_interface, name, CHECK_(nullHandle)); } @@ -2797,11 +2806,11 @@ // Force MethodHandle.vmentry to be an unmanaged pointer. // There is no way for a classfile to express this, so we must help it. -void ClassFileParser::java_dyn_MethodHandle_fix_pre(constantPoolHandle cp, +void ClassFileParser::java_lang_invoke_MethodHandle_fix_pre(constantPoolHandle cp, typeArrayHandle fields, FieldAllocationCount *fac_ptr, TRAPS) { - // Add fake fields for java.dyn.MethodHandle instances + // Add fake fields for java.lang.invoke.MethodHandle instances // // This is not particularly nice, but since there is no way to express // a native wordSize field in Java, we must do it at this level. @@ -2818,9 +2827,10 @@ } } + if (AllowTransitionalJSR292 && word_sig_index == 0) return; if (word_sig_index == 0) THROW_MSG(vmSymbols::java_lang_VirtualMachineError(), - "missing I or J signature (for vmentry) in java.dyn.MethodHandle"); + "missing I or J signature (for vmentry) in java.lang.invoke.MethodHandle"); // Find vmentry field and change the signature. bool found_vmentry = false; @@ -2857,9 +2867,10 @@ } } + if (AllowTransitionalJSR292 && !found_vmentry) return; if (!found_vmentry) THROW_MSG(vmSymbols::java_lang_VirtualMachineError(), - "missing vmentry byte field in java.dyn.MethodHandle"); + "missing vmentry byte field in java.lang.invoke.MethodHandle"); } @@ -3224,9 +3235,18 @@ java_lang_Class_fix_pre(&methods, &fac, CHECK_(nullHandle)); } - // adjust the vmentry field declaration in java.dyn.MethodHandle - if (EnableMethodHandles && class_name == vmSymbols::sun_dyn_MethodHandleImpl() && class_loader.is_null()) { - java_dyn_MethodHandle_fix_pre(cp, fields, &fac, CHECK_(nullHandle)); + // adjust the vmentry field declaration in java.lang.invoke.MethodHandle + if (EnableMethodHandles && class_name == vmSymbols::java_lang_invoke_MethodHandle() && class_loader.is_null()) { + java_lang_invoke_MethodHandle_fix_pre(cp, fields, &fac, CHECK_(nullHandle)); + } + if (AllowTransitionalJSR292 && + EnableMethodHandles && class_name == vmSymbols::java_dyn_MethodHandle() && class_loader.is_null()) { + java_lang_invoke_MethodHandle_fix_pre(cp, fields, &fac, CHECK_(nullHandle)); + } + if (AllowTransitionalJSR292 && + EnableMethodHandles && class_name == vmSymbols::sun_dyn_MethodHandleImpl() && class_loader.is_null()) { + // allow vmentry field in MethodHandleImpl also + java_lang_invoke_MethodHandle_fix_pre(cp, fields, &fac, CHECK_(nullHandle)); } // Add a fake "discovered" field if it is not present diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/classfile/classFileParser.hpp --- a/src/share/vm/classfile/classFileParser.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/classfile/classFileParser.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -162,9 +162,9 @@ // Adjust the next_nonstatic_oop_offset to place the fake fields // before any Java fields. void java_lang_Class_fix_post(int* next_nonstatic_oop_offset); - // Adjust the field allocation counts for java.dyn.MethodHandle to add + // Adjust the field allocation counts for java.lang.invoke.MethodHandle to add // a fake address (void*) field. - void java_dyn_MethodHandle_fix_pre(constantPoolHandle cp, + void java_lang_invoke_MethodHandle_fix_pre(constantPoolHandle cp, typeArrayHandle fields, FieldAllocationCount *fac_ptr, TRAPS); diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/classfile/javaClasses.cpp --- a/src/share/vm/classfile/javaClasses.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/classfile/javaClasses.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -66,6 +66,28 @@ return ik->find_local_field(name_symbol, signature_symbol, fd); } +static bool find_hacked_field(instanceKlass* ik, + Symbol* name_symbol, Symbol* signature_symbol, + fieldDescriptor* fd, + bool allow_super = false) { + bool found = find_field(ik, name_symbol, signature_symbol, fd, allow_super); + if (!found && AllowTransitionalJSR292) { + Symbol* backup_sig = SystemDictionary::find_backup_signature(signature_symbol); + if (backup_sig != NULL) { + found = find_field(ik, name_symbol, backup_sig, fd, allow_super); + if (TraceMethodHandles) { + ResourceMark rm; + tty->print_cr("MethodHandles: %s.%s: backup for %s => %s%s", + ik->name()->as_C_string(), name_symbol->as_C_string(), + signature_symbol->as_C_string(), backup_sig->as_C_string(), + (found ? "" : " (NOT FOUND)")); + } + } + } + return found; +} +#define find_field find_hacked_field /* remove after AllowTransitionalJSR292 */ + // Helpful routine for computing field offsets at run time rather than hardcoding them static void compute_offset(int &dest_offset, @@ -2176,41 +2198,43 @@ } -// Support for java_dyn_MethodHandle - -int java_dyn_MethodHandle::_type_offset; -int java_dyn_MethodHandle::_vmtarget_offset; -int java_dyn_MethodHandle::_vmentry_offset; -int java_dyn_MethodHandle::_vmslots_offset; - -int sun_dyn_MemberName::_clazz_offset; -int sun_dyn_MemberName::_name_offset; -int sun_dyn_MemberName::_type_offset; -int sun_dyn_MemberName::_flags_offset; -int sun_dyn_MemberName::_vmtarget_offset; -int sun_dyn_MemberName::_vmindex_offset; - -int sun_dyn_DirectMethodHandle::_vmindex_offset; - -int sun_dyn_BoundMethodHandle::_argument_offset; -int sun_dyn_BoundMethodHandle::_vmargslot_offset; - -int sun_dyn_AdapterMethodHandle::_conversion_offset; - -void java_dyn_MethodHandle::compute_offsets() { +// Support for java_lang_invoke_MethodHandle + +int java_lang_invoke_MethodHandle::_type_offset; +int java_lang_invoke_MethodHandle::_vmtarget_offset; +int java_lang_invoke_MethodHandle::_vmentry_offset; +int java_lang_invoke_MethodHandle::_vmslots_offset; + +int java_lang_invoke_MemberName::_clazz_offset; +int java_lang_invoke_MemberName::_name_offset; +int java_lang_invoke_MemberName::_type_offset; +int java_lang_invoke_MemberName::_flags_offset; +int java_lang_invoke_MemberName::_vmtarget_offset; +int java_lang_invoke_MemberName::_vmindex_offset; + +int java_lang_invoke_DirectMethodHandle::_vmindex_offset; + +int java_lang_invoke_BoundMethodHandle::_argument_offset; +int java_lang_invoke_BoundMethodHandle::_vmargslot_offset; + +int java_lang_invoke_AdapterMethodHandle::_conversion_offset; + +void java_lang_invoke_MethodHandle::compute_offsets() { klassOop k = SystemDictionary::MethodHandle_klass(); if (k != NULL && EnableMethodHandles) { - compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::java_dyn_MethodType_signature(), true); - compute_offset(_vmtarget_offset, k, vmSymbols::vmtarget_name(), vmSymbols::object_signature(), true); - compute_offset(_vmentry_offset, k, vmSymbols::vmentry_name(), vmSymbols::machine_word_signature(), true); + bool allow_super = false; + if (AllowTransitionalJSR292) allow_super = true; // temporary, to access java.dyn.MethodHandleImpl + compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::java_lang_invoke_MethodType_signature(), allow_super); + compute_offset(_vmtarget_offset, k, vmSymbols::vmtarget_name(), vmSymbols::object_signature(), allow_super); + compute_offset(_vmentry_offset, k, vmSymbols::vmentry_name(), vmSymbols::machine_word_signature(), allow_super); // Note: MH.vmslots (if it is present) is a hoisted copy of MH.type.form.vmslots. // It is optional pending experiments to keep or toss. - compute_optional_offset(_vmslots_offset, k, vmSymbols::vmslots_name(), vmSymbols::int_signature(), true); + compute_optional_offset(_vmslots_offset, k, vmSymbols::vmslots_name(), vmSymbols::int_signature(), allow_super); } } -void sun_dyn_MemberName::compute_offsets() { +void java_lang_invoke_MemberName::compute_offsets() { klassOop k = SystemDictionary::MemberName_klass(); if (k != NULL && EnableMethodHandles) { compute_offset(_clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature()); @@ -2222,14 +2246,14 @@ } } -void sun_dyn_DirectMethodHandle::compute_offsets() { +void java_lang_invoke_DirectMethodHandle::compute_offsets() { klassOop k = SystemDictionary::DirectMethodHandle_klass(); if (k != NULL && EnableMethodHandles) { compute_offset(_vmindex_offset, k, vmSymbols::vmindex_name(), vmSymbols::int_signature(), true); } } -void sun_dyn_BoundMethodHandle::compute_offsets() { +void java_lang_invoke_BoundMethodHandle::compute_offsets() { klassOop k = SystemDictionary::BoundMethodHandle_klass(); if (k != NULL && EnableMethodHandles) { compute_offset(_vmargslot_offset, k, vmSymbols::vmargslot_name(), vmSymbols::int_signature(), true); @@ -2237,22 +2261,22 @@ } } -void sun_dyn_AdapterMethodHandle::compute_offsets() { +void java_lang_invoke_AdapterMethodHandle::compute_offsets() { klassOop k = SystemDictionary::AdapterMethodHandle_klass(); if (k != NULL && EnableMethodHandles) { compute_offset(_conversion_offset, k, vmSymbols::conversion_name(), vmSymbols::int_signature(), true); } } -oop java_dyn_MethodHandle::type(oop mh) { +oop java_lang_invoke_MethodHandle::type(oop mh) { return mh->obj_field(_type_offset); } -void java_dyn_MethodHandle::set_type(oop mh, oop mtype) { +void java_lang_invoke_MethodHandle::set_type(oop mh, oop mtype) { mh->obj_field_put(_type_offset, mtype); } -int java_dyn_MethodHandle::vmslots(oop mh) { +int java_lang_invoke_MethodHandle::vmslots(oop mh) { int vmslots_offset = _vmslots_offset; if (vmslots_offset != 0) { #ifdef ASSERT @@ -2267,7 +2291,7 @@ } // if MH.vmslots exists, hoist into it the value of type.form.vmslots -void java_dyn_MethodHandle::init_vmslots(oop mh) { +void java_lang_invoke_MethodHandle::init_vmslots(oop mh) { int vmslots_offset = _vmslots_offset; if (vmslots_offset != 0) { mh->int_field_put(vmslots_offset, compute_vmslots(mh)); @@ -2276,20 +2300,20 @@ // fetch type.form.vmslots, which is the number of JVM stack slots // required to carry the arguments of this MH -int java_dyn_MethodHandle::compute_vmslots(oop mh) { +int java_lang_invoke_MethodHandle::compute_vmslots(oop mh) { oop mtype = type(mh); if (mtype == NULL) return 0; // Java code would get NPE - oop form = java_dyn_MethodType::form(mtype); + oop form = java_lang_invoke_MethodType::form(mtype); if (form == NULL) return 0; // Java code would get NPE - return java_dyn_MethodTypeForm::vmslots(form); + return java_lang_invoke_MethodTypeForm::vmslots(form); } // fetch the low-level entry point for this mh -MethodHandleEntry* java_dyn_MethodHandle::vmentry(oop mh) { +MethodHandleEntry* java_lang_invoke_MethodHandle::vmentry(oop mh) { return (MethodHandleEntry*) mh->address_field(_vmentry_offset); } -void java_dyn_MethodHandle::set_vmentry(oop mh, MethodHandleEntry* me) { +void java_lang_invoke_MethodHandle::set_vmentry(oop mh, MethodHandleEntry* me) { assert(_vmentry_offset != 0, "must be present"); // This is always the final step that initializes a valid method handle: @@ -2303,123 +2327,123 @@ /// MemberName accessors -oop sun_dyn_MemberName::clazz(oop mname) { +oop java_lang_invoke_MemberName::clazz(oop mname) { assert(is_instance(mname), "wrong type"); return mname->obj_field(_clazz_offset); } -void sun_dyn_MemberName::set_clazz(oop mname, oop clazz) { +void java_lang_invoke_MemberName::set_clazz(oop mname, oop clazz) { assert(is_instance(mname), "wrong type"); mname->obj_field_put(_clazz_offset, clazz); } -oop sun_dyn_MemberName::name(oop mname) { +oop java_lang_invoke_MemberName::name(oop mname) { assert(is_instance(mname), "wrong type"); return mname->obj_field(_name_offset); } -void sun_dyn_MemberName::set_name(oop mname, oop name) { +void java_lang_invoke_MemberName::set_name(oop mname, oop name) { assert(is_instance(mname), "wrong type"); mname->obj_field_put(_name_offset, name); } -oop sun_dyn_MemberName::type(oop mname) { +oop java_lang_invoke_MemberName::type(oop mname) { assert(is_instance(mname), "wrong type"); return mname->obj_field(_type_offset); } -void sun_dyn_MemberName::set_type(oop mname, oop type) { +void java_lang_invoke_MemberName::set_type(oop mname, oop type) { assert(is_instance(mname), "wrong type"); mname->obj_field_put(_type_offset, type); } -int sun_dyn_MemberName::flags(oop mname) { +int java_lang_invoke_MemberName::flags(oop mname) { assert(is_instance(mname), "wrong type"); return mname->int_field(_flags_offset); } -void sun_dyn_MemberName::set_flags(oop mname, int flags) { +void java_lang_invoke_MemberName::set_flags(oop mname, int flags) { assert(is_instance(mname), "wrong type"); mname->int_field_put(_flags_offset, flags); } -oop sun_dyn_MemberName::vmtarget(oop mname) { +oop java_lang_invoke_MemberName::vmtarget(oop mname) { assert(is_instance(mname), "wrong type"); return mname->obj_field(_vmtarget_offset); } -void sun_dyn_MemberName::set_vmtarget(oop mname, oop ref) { +void java_lang_invoke_MemberName::set_vmtarget(oop mname, oop ref) { assert(is_instance(mname), "wrong type"); mname->obj_field_put(_vmtarget_offset, ref); } -int sun_dyn_MemberName::vmindex(oop mname) { +int java_lang_invoke_MemberName::vmindex(oop mname) { assert(is_instance(mname), "wrong type"); return mname->int_field(_vmindex_offset); } -void sun_dyn_MemberName::set_vmindex(oop mname, int index) { +void java_lang_invoke_MemberName::set_vmindex(oop mname, int index) { assert(is_instance(mname), "wrong type"); mname->int_field_put(_vmindex_offset, index); } -oop java_dyn_MethodHandle::vmtarget(oop mh) { +oop java_lang_invoke_MethodHandle::vmtarget(oop mh) { assert(is_instance(mh), "MH only"); return mh->obj_field(_vmtarget_offset); } -void java_dyn_MethodHandle::set_vmtarget(oop mh, oop ref) { +void java_lang_invoke_MethodHandle::set_vmtarget(oop mh, oop ref) { assert(is_instance(mh), "MH only"); mh->obj_field_put(_vmtarget_offset, ref); } -int sun_dyn_DirectMethodHandle::vmindex(oop mh) { +int java_lang_invoke_DirectMethodHandle::vmindex(oop mh) { assert(is_instance(mh), "DMH only"); return mh->int_field(_vmindex_offset); } -void sun_dyn_DirectMethodHandle::set_vmindex(oop mh, int index) { +void java_lang_invoke_DirectMethodHandle::set_vmindex(oop mh, int index) { assert(is_instance(mh), "DMH only"); mh->int_field_put(_vmindex_offset, index); } -int sun_dyn_BoundMethodHandle::vmargslot(oop mh) { +int java_lang_invoke_BoundMethodHandle::vmargslot(oop mh) { assert(is_instance(mh), "BMH only"); return mh->int_field(_vmargslot_offset); } -oop sun_dyn_BoundMethodHandle::argument(oop mh) { +oop java_lang_invoke_BoundMethodHandle::argument(oop mh) { assert(is_instance(mh), "BMH only"); return mh->obj_field(_argument_offset); } -int sun_dyn_AdapterMethodHandle::conversion(oop mh) { +int java_lang_invoke_AdapterMethodHandle::conversion(oop mh) { assert(is_instance(mh), "AMH only"); return mh->int_field(_conversion_offset); } -void sun_dyn_AdapterMethodHandle::set_conversion(oop mh, int conv) { +void java_lang_invoke_AdapterMethodHandle::set_conversion(oop mh, int conv) { assert(is_instance(mh), "AMH only"); mh->int_field_put(_conversion_offset, conv); } -// Support for java_dyn_MethodType - -int java_dyn_MethodType::_rtype_offset; -int java_dyn_MethodType::_ptypes_offset; -int java_dyn_MethodType::_form_offset; - -void java_dyn_MethodType::compute_offsets() { +// Support for java_lang_invoke_MethodType + +int java_lang_invoke_MethodType::_rtype_offset; +int java_lang_invoke_MethodType::_ptypes_offset; +int java_lang_invoke_MethodType::_form_offset; + +void java_lang_invoke_MethodType::compute_offsets() { klassOop k = SystemDictionary::MethodType_klass(); if (k != NULL) { compute_offset(_rtype_offset, k, vmSymbols::rtype_name(), vmSymbols::class_signature()); compute_offset(_ptypes_offset, k, vmSymbols::ptypes_name(), vmSymbols::class_array_signature()); - compute_offset(_form_offset, k, vmSymbols::form_name(), vmSymbols::java_dyn_MethodTypeForm_signature()); + compute_offset(_form_offset, k, vmSymbols::form_name(), vmSymbols::java_lang_invoke_MethodTypeForm_signature()); } } -void java_dyn_MethodType::print_signature(oop mt, outputStream* st) { +void java_lang_invoke_MethodType::print_signature(oop mt, outputStream* st) { st->print("("); objArrayOop pts = ptypes(mt); for (int i = 0, limit = pts->length(); i < limit; i++) { @@ -2429,7 +2453,7 @@ java_lang_Class::print_signature(rtype(mt), st); } -Symbol* java_dyn_MethodType::as_signature(oop mt, bool intern_if_not_found, TRAPS) { +Symbol* java_lang_invoke_MethodType::as_signature(oop mt, bool intern_if_not_found, TRAPS) { ResourceMark rm; stringStream buffer(128); print_signature(mt, &buffer); @@ -2444,103 +2468,83 @@ return name; } -oop java_dyn_MethodType::rtype(oop mt) { +oop java_lang_invoke_MethodType::rtype(oop mt) { assert(is_instance(mt), "must be a MethodType"); return mt->obj_field(_rtype_offset); } -objArrayOop java_dyn_MethodType::ptypes(oop mt) { +objArrayOop java_lang_invoke_MethodType::ptypes(oop mt) { assert(is_instance(mt), "must be a MethodType"); return (objArrayOop) mt->obj_field(_ptypes_offset); } -oop java_dyn_MethodType::form(oop mt) { +oop java_lang_invoke_MethodType::form(oop mt) { assert(is_instance(mt), "must be a MethodType"); return mt->obj_field(_form_offset); } -oop java_dyn_MethodType::ptype(oop mt, int idx) { +oop java_lang_invoke_MethodType::ptype(oop mt, int idx) { return ptypes(mt)->obj_at(idx); } -int java_dyn_MethodType::ptype_count(oop mt) { +int java_lang_invoke_MethodType::ptype_count(oop mt) { return ptypes(mt)->length(); } -// Support for java_dyn_MethodTypeForm - -int java_dyn_MethodTypeForm::_vmslots_offset; -int java_dyn_MethodTypeForm::_erasedType_offset; -int java_dyn_MethodTypeForm::_genericInvoker_offset; - -void java_dyn_MethodTypeForm::compute_offsets() { +// Support for java_lang_invoke_MethodTypeForm + +int java_lang_invoke_MethodTypeForm::_vmslots_offset; +int java_lang_invoke_MethodTypeForm::_erasedType_offset; +int java_lang_invoke_MethodTypeForm::_genericInvoker_offset; + +void java_lang_invoke_MethodTypeForm::compute_offsets() { klassOop k = SystemDictionary::MethodTypeForm_klass(); if (k != NULL) { compute_optional_offset(_vmslots_offset, k, vmSymbols::vmslots_name(), vmSymbols::int_signature(), true); - compute_optional_offset(_erasedType_offset, k, vmSymbols::erasedType_name(), vmSymbols::java_dyn_MethodType_signature(), true); - compute_optional_offset(_genericInvoker_offset, k, vmSymbols::genericInvoker_name(), vmSymbols::java_dyn_MethodHandle_signature(), true); + compute_optional_offset(_erasedType_offset, k, vmSymbols::erasedType_name(), vmSymbols::java_lang_invoke_MethodType_signature(), true); + compute_optional_offset(_genericInvoker_offset, k, vmSymbols::genericInvoker_name(), vmSymbols::java_lang_invoke_MethodHandle_signature(), true); if (_genericInvoker_offset == 0) _genericInvoker_offset = -1; // set to explicit "empty" value } } -int java_dyn_MethodTypeForm::vmslots(oop mtform) { +int java_lang_invoke_MethodTypeForm::vmslots(oop mtform) { assert(mtform->klass() == SystemDictionary::MethodTypeForm_klass(), "MTForm only"); return mtform->int_field(_vmslots_offset); } -oop java_dyn_MethodTypeForm::erasedType(oop mtform) { +oop java_lang_invoke_MethodTypeForm::erasedType(oop mtform) { assert(mtform->klass() == SystemDictionary::MethodTypeForm_klass(), "MTForm only"); return mtform->obj_field(_erasedType_offset); } -oop java_dyn_MethodTypeForm::genericInvoker(oop mtform) { +oop java_lang_invoke_MethodTypeForm::genericInvoker(oop mtform) { assert(mtform->klass() == SystemDictionary::MethodTypeForm_klass(), "MTForm only"); return mtform->obj_field(_genericInvoker_offset); } -// Support for java_dyn_CallSite - -int java_dyn_CallSite::_target_offset; -int java_dyn_CallSite::_caller_method_offset; -int java_dyn_CallSite::_caller_bci_offset; - -void java_dyn_CallSite::compute_offsets() { +// Support for java_lang_invoke_CallSite + +int java_lang_invoke_CallSite::_target_offset; + +void java_lang_invoke_CallSite::compute_offsets() { if (!EnableInvokeDynamic) return; klassOop k = SystemDictionary::CallSite_klass(); if (k != NULL) { - compute_offset(_target_offset, k, vmSymbols::target_name(), vmSymbols::java_dyn_MethodHandle_signature()); - compute_offset(_caller_method_offset, k, vmSymbols::vmmethod_name(), vmSymbols::sun_dyn_MemberName_signature()); - compute_offset(_caller_bci_offset, k, vmSymbols::vmindex_name(), vmSymbols::int_signature()); + compute_offset(_target_offset, k, vmSymbols::target_name(), vmSymbols::java_lang_invoke_MethodHandle_signature()); } } -oop java_dyn_CallSite::target(oop site) { +oop java_lang_invoke_CallSite::target(oop site) { return site->obj_field(_target_offset); } -void java_dyn_CallSite::set_target(oop site, oop target) { +void java_lang_invoke_CallSite::set_target(oop site, oop target) { site->obj_field_put(_target_offset, target); } -oop java_dyn_CallSite::caller_method(oop site) { - return site->obj_field(_caller_method_offset); -} - -void java_dyn_CallSite::set_caller_method(oop site, oop ref) { - site->obj_field_put(_caller_method_offset, ref); -} - -jint java_dyn_CallSite::caller_bci(oop site) { - return site->int_field(_caller_bci_offset); -} - -void java_dyn_CallSite::set_caller_bci(oop site, jint bci) { - site->int_field_put(_caller_bci_offset, bci); -} - // Support for java_security_AccessControlContext @@ -2877,16 +2881,16 @@ java_lang_Thread::compute_offsets(); java_lang_ThreadGroup::compute_offsets(); if (EnableMethodHandles) { - java_dyn_MethodHandle::compute_offsets(); - sun_dyn_MemberName::compute_offsets(); - sun_dyn_DirectMethodHandle::compute_offsets(); - sun_dyn_BoundMethodHandle::compute_offsets(); - sun_dyn_AdapterMethodHandle::compute_offsets(); - java_dyn_MethodType::compute_offsets(); - java_dyn_MethodTypeForm::compute_offsets(); + java_lang_invoke_MethodHandle::compute_offsets(); + java_lang_invoke_MemberName::compute_offsets(); + java_lang_invoke_DirectMethodHandle::compute_offsets(); + java_lang_invoke_BoundMethodHandle::compute_offsets(); + java_lang_invoke_AdapterMethodHandle::compute_offsets(); + java_lang_invoke_MethodType::compute_offsets(); + java_lang_invoke_MethodTypeForm::compute_offsets(); } if (EnableInvokeDynamic) { - java_dyn_CallSite::compute_offsets(); + java_lang_invoke_CallSite::compute_offsets(); } java_security_AccessControlContext::compute_offsets(); // Initialize reflection classes. The layouts of these classes diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/classfile/javaClasses.hpp --- a/src/share/vm/classfile/javaClasses.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/classfile/javaClasses.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -794,11 +794,11 @@ }; -// Interface to java.dyn.MethodHandle objects +// Interface to java.lang.invoke.MethodHandle objects class MethodHandleEntry; -class java_dyn_MethodHandle: AllStatic { +class java_lang_invoke_MethodHandle: AllStatic { friend class JavaClasses; private: @@ -839,7 +839,7 @@ static int vmslots_offset_in_bytes() { return _vmslots_offset; } }; -class sun_dyn_DirectMethodHandle: public java_dyn_MethodHandle { +class java_lang_invoke_DirectMethodHandle: public java_lang_invoke_MethodHandle { friend class JavaClasses; private: @@ -864,7 +864,7 @@ static int vmindex_offset_in_bytes() { return _vmindex_offset; } }; -class sun_dyn_BoundMethodHandle: public java_dyn_MethodHandle { +class java_lang_invoke_BoundMethodHandle: public java_lang_invoke_MethodHandle { friend class JavaClasses; private: @@ -891,7 +891,7 @@ static int vmargslot_offset_in_bytes() { return _vmargslot_offset; } }; -class sun_dyn_AdapterMethodHandle: public sun_dyn_BoundMethodHandle { +class java_lang_invoke_AdapterMethodHandle: public java_lang_invoke_BoundMethodHandle { friend class JavaClasses; private: @@ -942,14 +942,14 @@ }; -// Interface to sun.dyn.MemberName objects +// Interface to java.lang.invoke.MemberName objects // (These are a private interface for Java code to query the class hierarchy.) -class sun_dyn_MemberName: AllStatic { +class java_lang_invoke_MemberName: AllStatic { friend class JavaClasses; private: - // From java.dyn.MemberName: + // From java.lang.invoke.MemberName: // private Class clazz; // class in which the method is defined // private String name; // may be null if not yet materialized // private Object type; // may be null if not yet materialized @@ -1018,9 +1018,9 @@ }; -// Interface to java.dyn.MethodType objects +// Interface to java.lang.invoke.MethodType objects -class java_dyn_MethodType: AllStatic { +class java_lang_invoke_MethodType: AllStatic { friend class JavaClasses; private: @@ -1052,7 +1052,7 @@ static int form_offset_in_bytes() { return _form_offset; } }; -class java_dyn_MethodTypeForm: AllStatic { +class java_lang_invoke_MethodTypeForm: AllStatic { friend class JavaClasses; private: @@ -1075,9 +1075,9 @@ }; -// Interface to java.dyn.CallSite objects +// Interface to java.lang.invoke.CallSite objects -class java_dyn_CallSite: AllStatic { +class java_lang_invoke_CallSite: AllStatic { friend class JavaClasses; private: diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/classfile/symbolTable.cpp --- a/src/share/vm/classfile/symbolTable.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/classfile/symbolTable.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -88,7 +88,7 @@ void SymbolTable::unlink() { int removed = 0; int total = 0; - int memory_total = 0; + size_t memory_total = 0; for (int i = 0; i < the_table()->table_size(); ++i) { for (HashtableEntry** p = the_table()->bucket_addr(i); *p != NULL; ) { HashtableEntry* entry = *p; @@ -112,8 +112,10 @@ } symbols_removed += removed; symbols_counted += total; - if (PrintGCDetails) { - gclog_or_tty->print(" [Symbols=%d size=%dK] ", total, + // Exclude printing for normal PrintGCDetails because people parse + // this output. + if (PrintGCDetails && Verbose && WizardMode) { + gclog_or_tty->print(" [Symbols=%d size=" SIZE_FORMAT "K] ", total, (memory_total*HeapWordSize)/1024); } } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/classfile/systemDictionary.cpp --- a/src/share/vm/classfile/systemDictionary.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/classfile/systemDictionary.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -1887,27 +1887,99 @@ 0 }; +Symbol* SystemDictionary::find_backup_symbol(Symbol* symbol, + const char* from_prefix, + const char* to_prefix) { + assert(AllowTransitionalJSR292, ""); // delete this subroutine + Symbol* backup_symbol = NULL; + size_t from_len = strlen(from_prefix); + if (strncmp((const char*) symbol->base(), from_prefix, from_len) != 0) + return NULL; + char buf[100]; + size_t to_len = strlen(to_prefix); + size_t tail_len = symbol->utf8_length() - from_len; + size_t new_len = to_len + tail_len; + guarantee(new_len < sizeof(buf), "buf too small"); + memcpy(buf, to_prefix, to_len); + memcpy(buf + to_len, symbol->base() + from_len, tail_len); + buf[new_len] = '\0'; + vmSymbols::SID backup_sid = vmSymbols::find_sid(buf); + if (backup_sid != vmSymbols::NO_SID) { + backup_symbol = vmSymbols::symbol_at(backup_sid); + } + return backup_symbol; +} + +Symbol* SystemDictionary::find_backup_class_name(Symbol* symbol) { + assert(AllowTransitionalJSR292, ""); // delete this subroutine + if (symbol == NULL) return NULL; + Symbol* backup_symbol = find_backup_symbol(symbol, "java/lang/invoke/", "java/dyn/"); // AllowTransitionalJSR292 ONLY + if (backup_symbol == NULL) + backup_symbol = find_backup_symbol(symbol, "java/dyn/", "sun/dyn/"); // AllowTransitionalJSR292 ONLY + return backup_symbol; +} + +Symbol* SystemDictionary::find_backup_signature(Symbol* symbol) { + assert(AllowTransitionalJSR292, ""); // delete this subroutine + if (symbol == NULL) return NULL; + return find_backup_symbol(symbol, "Ljava/lang/invoke/", "Ljava/dyn/"); +} + bool SystemDictionary::initialize_wk_klass(WKID id, int init_opt, TRAPS) { assert(id >= (int)FIRST_WKID && id < (int)WKID_LIMIT, "oob"); int info = wk_init_info[id - FIRST_WKID]; int sid = (info >> CEIL_LG_OPTION_LIMIT); Symbol* symbol = vmSymbols::symbol_at((vmSymbols::SID)sid); klassOop* klassp = &_well_known_klasses[id]; - bool must_load = (init_opt < SystemDictionary::Opt); - bool try_load = true; + bool pre_load = (init_opt < SystemDictionary::Opt); + bool try_load = true; if (init_opt == SystemDictionary::Opt_Kernel) { #ifndef KERNEL try_load = false; #endif //KERNEL } - if ((*klassp) == NULL && try_load) { + Symbol* backup_symbol = NULL; // symbol to try if the current symbol fails + if (init_opt == SystemDictionary::Pre_JSR292) { + if (!EnableMethodHandles) try_load = false; // do not bother to load such classes + if (AllowTransitionalJSR292) { + backup_symbol = find_backup_class_name(symbol); + if (try_load && PreferTransitionalJSR292) { + while (backup_symbol != NULL) { + (*klassp) = resolve_or_null(backup_symbol, CHECK_0); // try backup early + if (TraceMethodHandles) { + ResourceMark rm; + tty->print_cr("MethodHandles: try backup first for %s => %s (%s)", + symbol->as_C_string(), backup_symbol->as_C_string(), + ((*klassp) == NULL) ? "no such class" : "backup load succeeded"); + } + if ((*klassp) != NULL) return true; + backup_symbol = find_backup_class_name(backup_symbol); // find next backup + } + } + } + } + if ((*klassp) != NULL) return true; + if (!try_load) return false; + while (symbol != NULL) { + bool must_load = (pre_load && (backup_symbol == NULL)); if (must_load) { (*klassp) = resolve_or_fail(symbol, true, CHECK_0); // load required class } else { (*klassp) = resolve_or_null(symbol, CHECK_0); // load optional klass } + if ((*klassp) != NULL) return true; + // Go around again. Example of long backup sequence: + // java.lang.invoke.MemberName, java.dyn.MemberName, sun.dyn.MemberName, ONLY if AllowTransitionalJSR292 + if (TraceMethodHandles && (backup_symbol != NULL)) { + ResourceMark rm; + tty->print_cr("MethodHandles: backup for %s => %s", + symbol->as_C_string(), backup_symbol->as_C_string()); + } + symbol = backup_symbol; + if (AllowTransitionalJSR292) + backup_symbol = find_backup_class_name(symbol); } - return ((*klassp) != NULL); + return false; } void SystemDictionary::initialize_wk_klasses_until(WKID limit_id, WKID &start_id, TRAPS) { @@ -2348,6 +2420,8 @@ if (THREAD->is_Compiler_thread()) return NULL; // do not attempt from within compiler bool for_invokeGeneric = (name_id == vmSymbols::VM_SYMBOL_ENUM_NAME(invokeGeneric_name)); + if (AllowInvokeForInvokeGeneric && name_id == vmSymbols::VM_SYMBOL_ENUM_NAME(invoke_name)) + for_invokeGeneric = true; bool found_on_bcp = false; Handle mt = find_method_handle_type(signature, accessing_klass, for_invokeGeneric, @@ -2376,7 +2450,7 @@ } } -// Ask Java code to find or construct a java.dyn.MethodType for the given +// Ask Java code to find or construct a java.lang.invoke.MethodType for the given // signature, as interpreted relative to the given class loader. // Because of class loader constraints, all method handle usage must be // consistent with this loader. @@ -2430,25 +2504,33 @@ } assert(arg == npts, ""); - // call sun.dyn.MethodHandleNatives::findMethodType(Class rt, Class[] pts) -> MethodType + // call java.lang.invoke.MethodHandleNatives::findMethodType(Class rt, Class[] pts) -> MethodType JavaCallArguments args(Handle(THREAD, rt())); args.push_oop(pts()); JavaValue result(T_OBJECT); + Symbol* findMethodHandleType_signature = vmSymbols::findMethodHandleType_signature(); + if (AllowTransitionalJSR292 && SystemDictionaryHandles::MethodType_klass()->name() == vmSymbols::java_dyn_MethodType()) { + findMethodHandleType_signature = vmSymbols::findMethodHandleType_TRANS_signature(); + } JavaCalls::call_static(&result, SystemDictionary::MethodHandleNatives_klass(), vmSymbols::findMethodHandleType_name(), - vmSymbols::findMethodHandleType_signature(), + findMethodHandleType_signature, &args, CHECK_(empty)); Handle method_type(THREAD, (oop) result.get_jobject()); if (for_invokeGeneric) { - // call sun.dyn.MethodHandleNatives::notifyGenericMethodType(MethodType) -> void + // call java.lang.invoke.MethodHandleNatives::notifyGenericMethodType(MethodType) -> void JavaCallArguments args(Handle(THREAD, method_type())); JavaValue no_result(T_VOID); + Symbol* notifyGenericMethodType_signature = vmSymbols::notifyGenericMethodType_signature(); + if (AllowTransitionalJSR292 && SystemDictionaryHandles::MethodType_klass()->name() == vmSymbols::java_dyn_MethodType()) { + notifyGenericMethodType_signature = vmSymbols::notifyGenericMethodType_TRANS_signature(); + } JavaCalls::call_static(&no_result, SystemDictionary::MethodHandleNatives_klass(), vmSymbols::notifyGenericMethodType_name(), - vmSymbols::notifyGenericMethodType_signature(), + notifyGenericMethodType_signature, &args, THREAD); if (HAS_PENDING_EXCEPTION) { // If the notification fails, just kill it. @@ -2489,7 +2571,7 @@ THROW_MSG_(vmSymbols::java_lang_LinkageError(), "bad signature", empty); } - // call sun.dyn.MethodHandleNatives::linkMethodHandleConstant(Class caller, int refKind, Class callee, String name, Object type) -> MethodHandle + // call java.lang.invoke.MethodHandleNatives::linkMethodHandleConstant(Class caller, int refKind, Class callee, String name, Object type) -> MethodHandle JavaCallArguments args; args.push_oop(caller->java_mirror()); // the referring class args.push_int(ref_kind); @@ -2497,15 +2579,19 @@ args.push_oop(name()); args.push_oop(type()); JavaValue result(T_OBJECT); + Symbol* linkMethodHandleConstant_signature = vmSymbols::linkMethodHandleConstant_signature(); + if (AllowTransitionalJSR292 && SystemDictionaryHandles::MethodHandle_klass()->name() == vmSymbols::java_dyn_MethodHandle()) { + linkMethodHandleConstant_signature = vmSymbols::linkMethodHandleConstant_TRANS_signature(); + } JavaCalls::call_static(&result, SystemDictionary::MethodHandleNatives_klass(), vmSymbols::linkMethodHandleConstant_name(), - vmSymbols::linkMethodHandleConstant_signature(), + linkMethodHandleConstant_signature, &args, CHECK_(empty)); return Handle(THREAD, (oop) result.get_jobject()); } -// Ask Java code to find or construct a java.dyn.CallSite for the given +// Ask Java code to find or construct a java.lang.invoke.CallSite for the given // name and signature, as interpreted relative to the given class loader. Handle SystemDictionary::make_dynamic_call_site(Handle bootstrap_method, Symbol* name, @@ -2516,13 +2602,13 @@ TRAPS) { Handle empty; guarantee(bootstrap_method.not_null() && - java_dyn_MethodHandle::is_instance(bootstrap_method()), + java_lang_invoke_MethodHandle::is_instance(bootstrap_method()), "caller must supply a valid BSM"); Handle caller_mname = MethodHandles::new_MemberName(CHECK_(empty)); MethodHandles::init_MemberName(caller_mname(), caller_method()); - // call sun.dyn.MethodHandleNatives::makeDynamicCallSite(bootm, name, mtype, info, caller_mname, caller_pos) + // call java.lang.invoke.MethodHandleNatives::makeDynamicCallSite(bootm, name, mtype, info, caller_mname, caller_pos) oop name_str_oop = StringTable::intern(name, CHECK_(empty)); // not a handle! JavaCallArguments args(Handle(THREAD, bootstrap_method())); args.push_oop(name_str_oop); @@ -2531,14 +2617,21 @@ args.push_oop(caller_mname()); args.push_int(caller_bci); JavaValue result(T_OBJECT); + Symbol* makeDynamicCallSite_signature = vmSymbols::makeDynamicCallSite_signature(); + if (AllowTransitionalJSR292 && SystemDictionaryHandles::MethodHandleNatives_klass()->name() == vmSymbols::sun_dyn_MethodHandleNatives()) { + makeDynamicCallSite_signature = vmSymbols::makeDynamicCallSite_TRANS_signature(); + } + if (AllowTransitionalJSR292 && SystemDictionaryHandles::MethodHandleNatives_klass()->name() == vmSymbols::java_dyn_MethodHandleNatives()) { + makeDynamicCallSite_signature = vmSymbols::makeDynamicCallSite_TRANS2_signature(); + } JavaCalls::call_static(&result, SystemDictionary::MethodHandleNatives_klass(), vmSymbols::makeDynamicCallSite_name(), - vmSymbols::makeDynamicCallSite_signature(), + makeDynamicCallSite_signature, &args, CHECK_(empty)); oop call_site_oop = (oop) result.get_jobject(); assert(call_site_oop->is_oop() - /*&& java_dyn_CallSite::is_instance(call_site_oop)*/, "must be sane"); + /*&& java_lang_invoke_CallSite::is_instance(call_site_oop)*/, "must be sane"); if (TraceMethodHandles) { #ifndef PRODUCT tty->print_cr("Linked invokedynamic bci=%d site="INTPTR_FORMAT":", caller_bci, call_site_oop); diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/classfile/systemDictionary.hpp --- a/src/share/vm/classfile/systemDictionary.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/classfile/systemDictionary.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -144,18 +144,18 @@ template(reflect_UnsafeStaticFieldAccessorImpl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15) \ \ /* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \ - template(MethodHandle_klass, java_dyn_MethodHandle, Opt) \ - template(MemberName_klass, sun_dyn_MemberName, Opt) \ - template(MethodHandleImpl_klass, sun_dyn_MethodHandleImpl, Opt) \ - template(MethodHandleNatives_klass, sun_dyn_MethodHandleNatives, Opt) \ - template(AdapterMethodHandle_klass, sun_dyn_AdapterMethodHandle, Opt) \ - template(BoundMethodHandle_klass, sun_dyn_BoundMethodHandle, Opt) \ - template(DirectMethodHandle_klass, sun_dyn_DirectMethodHandle, Opt) \ - template(MethodType_klass, java_dyn_MethodType, Opt) \ - template(MethodTypeForm_klass, java_dyn_MethodTypeForm, Opt) \ - template(WrongMethodTypeException_klass, java_dyn_WrongMethodTypeException, Opt) \ - template(Linkage_klass, java_dyn_Linkage, Opt) \ - template(CallSite_klass, java_dyn_CallSite, Opt) \ + template(MethodHandle_klass, java_lang_invoke_MethodHandle, Pre_JSR292) \ + template(MemberName_klass, java_lang_invoke_MemberName, Pre_JSR292) \ + template(MethodHandleImpl_klass, sun_dyn_MethodHandleImpl, Opt) /* AllowTransitionalJSR292 ONLY */ \ + template(MethodHandleNatives_klass, java_lang_invoke_MethodHandleNatives, Pre_JSR292) \ + template(AdapterMethodHandle_klass, java_lang_invoke_AdapterMethodHandle, Pre_JSR292) \ + template(BoundMethodHandle_klass, java_lang_invoke_BoundMethodHandle, Pre_JSR292) \ + template(DirectMethodHandle_klass, java_lang_invoke_DirectMethodHandle, Pre_JSR292) \ + template(MethodType_klass, java_lang_invoke_MethodType, Pre_JSR292) \ + template(MethodTypeForm_klass, java_lang_invoke_MethodTypeForm, Pre_JSR292) \ + template(WrongMethodTypeException_klass, java_lang_invoke_WrongMethodTypeException, Pre_JSR292) \ + template(Linkage_klass, java_lang_invoke_Linkage, Opt) /* AllowTransitionalJSR292 ONLY */ \ + template(CallSite_klass, java_lang_invoke_CallSite, Pre_JSR292) \ /* Note: MethodHandle must be first, and CallSite last in group */ \ \ template(StringBuffer_klass, java_lang_StringBuffer, Pre) \ @@ -207,6 +207,7 @@ enum InitOption { Pre, // preloaded; error if not present + Pre_JSR292, // preloaded if EnableMethodHandles // Order is significant. Options before this point require resolve_or_fail. // Options after this point will use resolve_or_null instead. @@ -401,6 +402,7 @@ } static klassOop check_klass_Pre(klassOop k) { return check_klass(k); } + static klassOop check_klass_Pre_JSR292(klassOop k) { return EnableInvokeDynamic ? check_klass(k) : k; } static klassOop check_klass_Opt(klassOop k) { return k; } static klassOop check_klass_Opt_Kernel(klassOop k) { return k; } //== Opt static klassOop check_klass_Opt_Only_JDK15(klassOop k) { @@ -420,6 +422,8 @@ initialize_wk_klasses_until((WKID) limit, start_id, THREAD); } + static Symbol* find_backup_symbol(Symbol* symbol, const char* from_prefix, const char* to_prefix); + public: #define WK_KLASS_DECLARE(name, ignore_symbol, option) \ static klassOop name() { return check_klass_##option(_well_known_klasses[WK_KLASS_ENUM_NAME(name)]); } @@ -441,6 +445,9 @@ static void load_abstract_ownable_synchronizer_klass(TRAPS); + static Symbol* find_backup_class_name(Symbol* class_name_symbol); + static Symbol* find_backup_signature(Symbol* signature_symbol); + private: // Tells whether ClassLoader.loadClassInternal is present static bool has_loadClassInternal() { return _has_loadClassInternal; } @@ -475,18 +482,18 @@ Handle loader2, bool is_method, TRAPS); // JSR 292 - // find the java.dyn.MethodHandles::invoke method for a given signature + // find the java.lang.invoke.MethodHandles::invoke method for a given signature static methodOop find_method_handle_invoke(Symbol* name, Symbol* signature, KlassHandle accessing_klass, TRAPS); - // ask Java to compute a java.dyn.MethodType object for a given signature + // ask Java to compute a java.lang.invoke.MethodType object for a given signature static Handle find_method_handle_type(Symbol* signature, KlassHandle accessing_klass, bool for_invokeGeneric, bool& return_bcp_flag, TRAPS); - // ask Java to compute a java.dyn.MethodHandle object for a given CP entry + // ask Java to compute a java.lang.invoke.MethodHandle object for a given CP entry static Handle link_method_handle_constant(KlassHandle caller, int ref_kind, //e.g., JVM_REF_invokeVirtual KlassHandle callee, diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/classfile/verifier.cpp --- a/src/share/vm/classfile/verifier.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/classfile/verifier.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2011, 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 @@ -1671,13 +1671,19 @@ VerificationType::long_type(), VerificationType::long2_type(), CHECK_VERIFY(this)); } else if (tag.is_method_handle()) { + Symbol* methodHandle_name = vmSymbols::java_lang_invoke_MethodHandle(); + if (AllowTransitionalJSR292 && !Universe::is_bootstrapping()) + methodHandle_name = SystemDictionaryHandles::MethodHandle_klass()->name(); current_frame->push_stack( VerificationType::reference_type( - vmSymbols::java_dyn_MethodHandle()), CHECK_VERIFY(this)); + methodHandle_name), CHECK_VERIFY(this)); } else if (tag.is_method_type()) { + Symbol* methodType_name = vmSymbols::java_lang_invoke_MethodType(); + if (AllowTransitionalJSR292 && !Universe::is_bootstrapping()) + methodType_name = SystemDictionaryHandles::MethodType_klass()->name(); current_frame->push_stack( VerificationType::reference_type( - vmSymbols::java_dyn_MethodType()), CHECK_VERIFY(this)); + methodType_name), CHECK_VERIFY(this)); } else { verify_error(bci, "Invalid index in ldc"); return; diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/classfile/vmSymbols.cpp --- a/src/share/vm/classfile/vmSymbols.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/classfile/vmSymbols.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -277,6 +277,12 @@ return sid; } +vmSymbols::SID vmSymbols::find_sid(const char* symbol_name) { + Symbol* symbol = SymbolTable::probe(symbol_name, (int) strlen(symbol_name)); + if (symbol == NULL) return NO_SID; + return find_sid(symbol); +} + static vmIntrinsics::ID wrapper_intrinsic(BasicType type, bool unboxing) { #define TYPE2(type, unboxing) ((int)(type)*2 + ((unboxing) ? 1 : 0)) switch (TYPE2(type, unboxing)) { diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/classfile/vmSymbols.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -229,33 +229,60 @@ template(base_name, "base") \ \ /* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */ \ - template(java_dyn_InvokeDynamic, "java/dyn/InvokeDynamic") \ - template(java_dyn_Linkage, "java/dyn/Linkage") \ - template(java_dyn_CallSite, "java/dyn/CallSite") \ - template(java_dyn_MethodHandle, "java/dyn/MethodHandle") \ - template(java_dyn_MethodType, "java/dyn/MethodType") \ - template(java_dyn_WrongMethodTypeException, "java/dyn/WrongMethodTypeException") \ - template(java_dyn_MethodType_signature, "Ljava/dyn/MethodType;") \ - template(java_dyn_MethodHandle_signature, "Ljava/dyn/MethodHandle;") \ + template(java_lang_invoke_InvokeDynamic, "java/lang/invoke/InvokeDynamic") \ + template(java_lang_invoke_Linkage, "java/lang/invoke/Linkage") \ + template(java_lang_invoke_CallSite, "java/lang/invoke/CallSite") \ + template(java_lang_invoke_MethodHandle, "java/lang/invoke/MethodHandle") \ + template(java_lang_invoke_MethodType, "java/lang/invoke/MethodType") \ + template(java_lang_invoke_WrongMethodTypeException, "java/lang/invoke/WrongMethodTypeException") \ + template(java_lang_invoke_MethodType_signature, "Ljava/lang/invoke/MethodType;") \ + template(java_lang_invoke_MethodHandle_signature, "Ljava/lang/invoke/MethodHandle;") \ /* internal classes known only to the JVM: */ \ - template(java_dyn_MethodTypeForm, "java/dyn/MethodTypeForm") \ - template(java_dyn_MethodTypeForm_signature, "Ljava/dyn/MethodTypeForm;") \ - template(sun_dyn_MemberName, "sun/dyn/MemberName") \ - template(sun_dyn_MemberName_signature, "Lsun/dyn/MemberName;") \ - template(sun_dyn_MethodHandleImpl, "sun/dyn/MethodHandleImpl") \ - template(sun_dyn_MethodHandleNatives, "sun/dyn/MethodHandleNatives") \ - template(sun_dyn_AdapterMethodHandle, "sun/dyn/AdapterMethodHandle") \ - template(sun_dyn_BoundMethodHandle, "sun/dyn/BoundMethodHandle") \ - template(sun_dyn_DirectMethodHandle, "sun/dyn/DirectMethodHandle") \ - /* internal up-calls made only by the JVM, via class sun.dyn.MethodHandleNatives: */ \ + template(java_lang_invoke_MethodTypeForm, "java/lang/invoke/MethodTypeForm") \ + template(java_lang_invoke_MethodTypeForm_signature, "Ljava/lang/invoke/MethodTypeForm;") \ + template(java_lang_invoke_MemberName, "java/lang/invoke/MemberName") \ + template(java_lang_invoke_MethodHandleNatives, "java/lang/invoke/MethodHandleNatives") \ + template(java_lang_invoke_AdapterMethodHandle, "java/lang/invoke/AdapterMethodHandle") \ + template(java_lang_invoke_BoundMethodHandle, "java/lang/invoke/BoundMethodHandle") \ + template(java_lang_invoke_DirectMethodHandle, "java/lang/invoke/DirectMethodHandle") \ + /* temporary transitional public names from 6839872: */ \ + template(java_dyn_InvokeDynamic, "java/dyn/InvokeDynamic") /* AllowTransitionalJSR292 ONLY */ \ + template(java_dyn_Linkage, "java/dyn/Linkage") /* AllowTransitionalJSR292 ONLY */ \ + template(java_dyn_CallSite, "java/dyn/CallSite") /* AllowTransitionalJSR292 ONLY */ \ + template(java_dyn_MethodHandle, "java/dyn/MethodHandle") /* AllowTransitionalJSR292 ONLY */ \ + template(java_dyn_MethodType, "java/dyn/MethodType") /* AllowTransitionalJSR292 ONLY */ \ + template(java_dyn_WrongMethodTypeException, "java/dyn/WrongMethodTypeException") /* AllowTransitionalJSR292 ONLY */ \ + template(java_dyn_MethodType_signature, "Ljava/dyn/MethodType;") /* AllowTransitionalJSR292 ONLY */ \ + template(java_dyn_MethodHandle_signature, "Ljava/dyn/MethodHandle;") /* AllowTransitionalJSR292 ONLY */ \ + /* temporary transitional internal names from 6839872: */ \ + template(java_dyn_MethodTypeForm, "java/dyn/MethodTypeForm") /* AllowTransitionalJSR292 ONLY */ \ + template(java_dyn_MethodTypeForm_signature, "Ljava/dyn/MethodTypeForm;") /* AllowTransitionalJSR292 ONLY */ \ + template(java_dyn_MemberName, "java/dyn/MemberName") /* AllowTransitionalJSR292 ONLY */ \ + template(java_dyn_MethodHandleNatives, "java/dyn/MethodHandleNatives") /* AllowTransitionalJSR292 ONLY */ \ + template(java_dyn_AdapterMethodHandle, "java/dyn/AdapterMethodHandle") /* AllowTransitionalJSR292 ONLY */ \ + template(java_dyn_BoundMethodHandle, "java/dyn/BoundMethodHandle") /* AllowTransitionalJSR292 ONLY */ \ + template(java_dyn_DirectMethodHandle, "java/dyn/DirectMethodHandle") /* AllowTransitionalJSR292 ONLY */ \ + /* temporary transitional internal names from EDR: */ \ + template(sun_dyn_MemberName, "sun/dyn/MemberName") /* AllowTransitionalJSR292 ONLY */ \ + template(sun_dyn_MethodHandleImpl, "sun/dyn/MethodHandleImpl") /* AllowTransitionalJSR292 ONLY */ \ + template(sun_dyn_MethodHandleNatives, "sun/dyn/MethodHandleNatives") /* AllowTransitionalJSR292 ONLY */ \ + template(sun_dyn_AdapterMethodHandle, "sun/dyn/AdapterMethodHandle") /* AllowTransitionalJSR292 ONLY */ \ + template(sun_dyn_BoundMethodHandle, "sun/dyn/BoundMethodHandle") /* AllowTransitionalJSR292 ONLY */ \ + template(sun_dyn_DirectMethodHandle, "sun/dyn/DirectMethodHandle") /* AllowTransitionalJSR292 ONLY */ \ + /* internal up-calls made only by the JVM, via class sun.invoke.MethodHandleNatives: */ \ template(findMethodHandleType_name, "findMethodHandleType") \ - template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/dyn/MethodType;") \ + template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodType;") \ + template(findMethodHandleType_TRANS_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/dyn/MethodType;") /* AllowTransitionalJSR292 ONLY */ \ template(notifyGenericMethodType_name, "notifyGenericMethodType") \ - template(notifyGenericMethodType_signature, "(Ljava/dyn/MethodType;)V") \ + template(notifyGenericMethodType_signature, "(Ljava/lang/invoke/MethodType;)V") \ + template(notifyGenericMethodType_TRANS_signature, "(Ljava/dyn/MethodType;)V") /* AllowTransitionalJSR292 ONLY */ \ template(linkMethodHandleConstant_name, "linkMethodHandleConstant") \ - template(linkMethodHandleConstant_signature, "(Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Ljava/dyn/MethodHandle;") \ + template(linkMethodHandleConstant_signature, "(Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle;") \ + template(linkMethodHandleConstant_TRANS_signature, "(Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Ljava/dyn/MethodHandle;") /* AllowTransitionalJSR292 ONLY */ \ template(makeDynamicCallSite_name, "makeDynamicCallSite") \ - template(makeDynamicCallSite_signature, "(Ljava/dyn/MethodHandle;Ljava/lang/String;Ljava/dyn/MethodType;Ljava/lang/Object;Lsun/dyn/MemberName;I)Ljava/dyn/CallSite;") \ + template(makeDynamicCallSite_signature, "(Ljava/lang/invoke/MethodHandle;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Object;Ljava/lang/invoke/MemberName;I)Ljava/lang/invoke/CallSite;") \ + template(makeDynamicCallSite_TRANS_signature, "(Ljava/dyn/MethodHandle;Ljava/lang/String;Ljava/dyn/MethodType;Ljava/lang/Object;Lsun/dyn/MemberName;I)Ljava/dyn/CallSite;") /* AllowTransitionalJSR292 ONLY */ \ + template(makeDynamicCallSite_TRANS2_signature, "(Ljava/dyn/MethodHandle;Ljava/lang/String;Ljava/dyn/MethodType;Ljava/lang/Object;Ljava/dyn/MemberName;I)Ljava/dyn/CallSite;") /* AllowTransitionalJSR292 ONLY */ \ NOT_LP64( do_alias(machine_word_signature, int_signature) ) \ LP64_ONLY( do_alias(machine_word_signature, long_signature) ) \ \ @@ -882,13 +909,15 @@ \ do_intrinsic(_invoke, java_lang_reflect_Method, invoke_name, object_object_array_object_signature, F_R) \ /* (symbols invoke_name and invoke_signature defined above) */ \ - do_intrinsic(_checkSpreadArgument, sun_dyn_MethodHandleImpl, checkSpreadArgument_name, checkSpreadArgument_signature, F_S) \ + do_intrinsic(_checkSpreadArgument, java_lang_invoke_MethodHandleNatives, checkSpreadArgument_name, checkSpreadArgument_signature, F_S) \ + do_intrinsic(_checkSpreadArgument_TRANS,sun_dyn_MethodHandleImpl, checkSpreadArgument_name, checkSpreadArgument_signature, F_S) /* AllowTransitionalJSR292 ONLY */ \ + do_intrinsic(_checkSpreadArgument_TRANS2,java_dyn_MethodHandleNatives, checkSpreadArgument_name, checkSpreadArgument_signature, F_S) /* AllowTransitionalJSR292 ONLY */ \ do_name( checkSpreadArgument_name, "checkSpreadArgument") \ do_name( checkSpreadArgument_signature, "(Ljava/lang/Object;I)V") \ - do_intrinsic(_invokeExact, java_dyn_MethodHandle, invokeExact_name, object_array_object_signature, F_RN) \ - do_intrinsic(_invokeGeneric, java_dyn_MethodHandle, invokeGeneric_name, object_array_object_signature, F_RN) \ - do_intrinsic(_invokeVarargs, java_dyn_MethodHandle, invokeVarargs_name, object_array_object_signature, F_R) \ - do_intrinsic(_invokeDynamic, java_dyn_InvokeDynamic, star_name, object_array_object_signature, F_SN) \ + do_intrinsic(_invokeExact, java_lang_invoke_MethodHandle, invokeExact_name, object_array_object_signature, F_RN) \ + do_intrinsic(_invokeGeneric, java_lang_invoke_MethodHandle, invokeGeneric_name, object_array_object_signature, F_RN) \ + do_intrinsic(_invokeVarargs, java_lang_invoke_MethodHandle, invokeVarargs_name, object_array_object_signature, F_R) \ + do_intrinsic(_invokeDynamic, java_lang_invoke_InvokeDynamic, star_name, object_array_object_signature, F_SN) \ \ /* unboxing methods: */ \ do_intrinsic(_booleanValue, java_lang_Boolean, booleanValue_name, void_boolean_signature, F_R) \ @@ -995,6 +1024,7 @@ // Returns symbol's SID if one is assigned, else NO_SID. static SID find_sid(Symbol* symbol); + static SID find_sid(const char* symbol_name); #ifndef PRODUCT // No need for this in the product: diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/code/codeCache.cpp --- a/src/share/vm/code/codeCache.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/code/codeCache.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -939,9 +939,16 @@ _heap->high(), _heap->high_boundary()); st->print_cr(" total_blobs=" UINT32_FORMAT " nmethods=" UINT32_FORMAT - " adapters=" UINT32_FORMAT " free_code_cache=" SIZE_FORMAT + " adapters=" UINT32_FORMAT " free_code_cache=" SIZE_FORMAT "Kb" " largest_free_block=" SIZE_FORMAT, - CodeCache::nof_blobs(), CodeCache::nof_nmethods(), - CodeCache::nof_adapters(), CodeCache::unallocated_capacity(), - CodeCache::largest_free_block()); + nof_blobs(), nof_nmethods(), nof_adapters(), + unallocated_capacity()/K, largest_free_block()); } + +void CodeCache::log_state(outputStream* st) { + st->print(" total_blobs='" UINT32_FORMAT "' nmethods='" UINT32_FORMAT "'" + " adapters='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'" + " largest_free_block='" SIZE_FORMAT "'", + nof_blobs(), nof_nmethods(), nof_adapters(), + unallocated_capacity(), largest_free_block()); +} diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/code/codeCache.hpp --- a/src/share/vm/code/codeCache.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/code/codeCache.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -147,6 +147,7 @@ static void verify(); // verifies the code cache static void print_trace(const char* event, CodeBlob* cb, int size = 0) PRODUCT_RETURN; static void print_bounds(outputStream* st); // Prints a summary of the bounds of the code cache + static void log_state(outputStream* st); // The full limits of the codeCache static address low_bound() { return (address) _heap->low_boundary(); } @@ -159,7 +160,7 @@ static size_t max_capacity() { return _heap->max_capacity(); } static size_t unallocated_capacity() { return _heap->unallocated_capacity(); } static size_t largest_free_block() { return _heap->largest_free_block(); } - static bool needs_flushing() { return unallocated_capacity() < CodeCacheFlushingMinimumFreeSpace; } + static bool needs_flushing() { return largest_free_block() < CodeCacheFlushingMinimumFreeSpace; } static bool needs_cache_clean() { return _needs_cache_clean; } static void set_needs_cache_clean(bool v) { _needs_cache_clean = v; } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/code/nmethod.cpp --- a/src/share/vm/code/nmethod.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/code/nmethod.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -170,7 +170,7 @@ int pc_desc_resets; // number of resets (= number of caches) int pc_desc_queries; // queries to nmethod::find_pc_desc int pc_desc_approx; // number of those which have approximate true - int pc_desc_repeats; // number of _last_pc_desc hits + int pc_desc_repeats; // number of _pc_descs[0] hits int pc_desc_hits; // number of LRU cache hits int pc_desc_tests; // total number of PcDesc examinations int pc_desc_searches; // total number of quasi-binary search steps @@ -278,40 +278,44 @@ void PcDescCache::reset_to(PcDesc* initial_pc_desc) { if (initial_pc_desc == NULL) { - _last_pc_desc = NULL; // native method + _pc_descs[0] = NULL; // native method; no PcDescs at all return; } NOT_PRODUCT(++nmethod_stats.pc_desc_resets); // reset the cache by filling it with benign (non-null) values assert(initial_pc_desc->pc_offset() < 0, "must be sentinel"); - _last_pc_desc = initial_pc_desc + 1; // first valid one is after sentinel for (int i = 0; i < cache_size; i++) _pc_descs[i] = initial_pc_desc; } PcDesc* PcDescCache::find_pc_desc(int pc_offset, bool approximate) { NOT_PRODUCT(++nmethod_stats.pc_desc_queries); - NOT_PRODUCT(if (approximate) ++nmethod_stats.pc_desc_approx); + NOT_PRODUCT(if (approximate) ++nmethod_stats.pc_desc_approx); + + // Note: one might think that caching the most recently + // read value separately would be a win, but one would be + // wrong. When many threads are updating it, the cache + // line it's in would bounce between caches, negating + // any benefit. // In order to prevent race conditions do not load cache elements // repeatedly, but use a local copy: PcDesc* res; - // Step one: Check the most recently returned value. - res = _last_pc_desc; - if (res == NULL) return NULL; // native method; no PcDescs at all + // Step one: Check the most recently added value. + res = _pc_descs[0]; + if (res == NULL) return NULL; // native method; no PcDescs at all if (match_desc(res, pc_offset, approximate)) { NOT_PRODUCT(++nmethod_stats.pc_desc_repeats); return res; } - // Step two: Check the LRU cache. - for (int i = 0; i < cache_size; i++) { + // Step two: Check the rest of the LRU cache. + for (int i = 1; i < cache_size; ++i) { res = _pc_descs[i]; - if (res->pc_offset() < 0) break; // optimization: skip empty cache + if (res->pc_offset() < 0) break; // optimization: skip empty cache if (match_desc(res, pc_offset, approximate)) { NOT_PRODUCT(++nmethod_stats.pc_desc_hits); - _last_pc_desc = res; // record this cache hit in case of repeat return res; } } @@ -322,24 +326,23 @@ void PcDescCache::add_pc_desc(PcDesc* pc_desc) { NOT_PRODUCT(++nmethod_stats.pc_desc_adds); - // Update the LRU cache by shifting pc_desc forward: + // Update the LRU cache by shifting pc_desc forward. for (int i = 0; i < cache_size; i++) { PcDesc* next = _pc_descs[i]; _pc_descs[i] = pc_desc; pc_desc = next; } - // Note: Do not update _last_pc_desc. It fronts for the LRU cache. } // adjust pcs_size so that it is a multiple of both oopSize and // sizeof(PcDesc) (assumes that if sizeof(PcDesc) is not a multiple // of oopSize, then 2*sizeof(PcDesc) is) -static int adjust_pcs_size(int pcs_size) { +static int adjust_pcs_size(int pcs_size) { int nsize = round_to(pcs_size, oopSize); if ((nsize % sizeof(PcDesc)) != 0) { nsize = pcs_size + sizeof(PcDesc); } - assert((nsize % oopSize) == 0, "correct alignment"); + assert((nsize % oopSize) == 0, "correct alignment"); return nsize; } @@ -762,7 +765,7 @@ void* nmethod::operator new(size_t size, int nmethod_size) { // Always leave some room in the CodeCache for I2C/C2I adapters - if (CodeCache::unallocated_capacity() < CodeCacheMinimumFreeSpace) return NULL; + if (CodeCache::largest_free_block() < CodeCacheMinimumFreeSpace) return NULL; return CodeCache::allocate(nmethod_size); } @@ -1180,14 +1183,17 @@ set_stack_traversal_mark(NMethodSweeper::traversal_count()); } -// Tell if a non-entrant method can be converted to a zombie (i.e., there is no activations on the stack) +// Tell if a non-entrant method can be converted to a zombie (i.e., +// there are no activations on the stack, not in use by the VM, +// and not in use by the ServiceThread) bool nmethod::can_not_entrant_be_converted() { assert(is_not_entrant(), "must be a non-entrant method"); // Since the nmethod sweeper only does partial sweep the sweeper's traversal // count can be greater than the stack traversal count before it hits the // nmethod for the second time. - return stack_traversal_mark()+1 < NMethodSweeper::traversal_count(); + return stack_traversal_mark()+1 < NMethodSweeper::traversal_count() && + !is_locked_by_vm(); } void nmethod::inc_decompile_count() { @@ -1294,6 +1300,7 @@ // Common functionality for both make_not_entrant and make_zombie bool nmethod::make_not_entrant_or_zombie(unsigned int state) { assert(state == zombie || state == not_entrant, "must be zombie or not_entrant"); + assert(!is_zombie(), "should not already be a zombie"); // Make sure neither the nmethod nor the method is flushed in case of a safepoint in code below. nmethodLocker nml(this); @@ -1301,11 +1308,6 @@ No_Safepoint_Verifier nsv; { - // If the method is already zombie there is nothing to do - if (is_zombie()) { - return false; - } - // invalidate osr nmethod before acquiring the patching lock since // they both acquire leaf locks and we don't want a deadlock. // This logic is equivalent to the logic below for patching the @@ -1375,13 +1377,12 @@ flush_dependencies(NULL); } - { - // zombie only - if a JVMTI agent has enabled the CompiledMethodUnload event - // and it hasn't already been reported for this nmethod then report it now. - // (the event may have been reported earilier if the GC marked it for unloading). - Pause_No_Safepoint_Verifier pnsv(&nsv); - post_compiled_method_unload(); - } + // zombie only - if a JVMTI agent has enabled the CompiledMethodUnload + // event and it hasn't already been reported for this nmethod then + // report it now. The event may have been reported earilier if the GC + // marked it for unloading). JvmtiDeferredEventQueue support means + // we no longer go to a safepoint here. + post_compiled_method_unload(); #ifdef ASSERT // It's no longer safe to access the oops section since zombie @@ -1566,7 +1567,7 @@ if (_jmethod_id != NULL && JvmtiExport::should_post_compiled_method_unload()) { assert(!unload_reported(), "already unloaded"); JvmtiDeferredEvent event = - JvmtiDeferredEvent::compiled_method_unload_event( + JvmtiDeferredEvent::compiled_method_unload_event(this, _jmethod_id, insts_begin()); if (SafepointSynchronize::is_at_safepoint()) { // Don't want to take the queueing lock. Add it as pending and @@ -1881,7 +1882,7 @@ oop nmethod::embeddedOop_at(u_char* p) { - RelocIterator iter(this, p, p + oopSize); + RelocIterator iter(this, p, p + 1); while (iter.next()) if (iter.type() == relocInfo::oop_type) { return iter.oop_reloc()->oop_value(); @@ -2171,10 +2172,12 @@ lock_nmethod(_nm); } -void nmethodLocker::lock_nmethod(nmethod* nm) { +// Only JvmtiDeferredEvent::compiled_method_unload_event() +// should pass zombie_ok == true. +void nmethodLocker::lock_nmethod(nmethod* nm, bool zombie_ok) { if (nm == NULL) return; Atomic::inc(&nm->_lock_count); - guarantee(!nm->is_zombie(), "cannot lock a zombie method"); + guarantee(zombie_ok || !nm->is_zombie(), "cannot lock a zombie method"); } void nmethodLocker::unlock_nmethod(nmethod* nm) { diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/code/nmethod.hpp --- a/src/share/vm/code/nmethod.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/code/nmethod.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -69,14 +69,13 @@ friend class VMStructs; private: enum { cache_size = 4 }; - PcDesc* _last_pc_desc; // most recent pc_desc found PcDesc* _pc_descs[cache_size]; // last cache_size pc_descs found public: - PcDescCache() { debug_only(_last_pc_desc = NULL); } + PcDescCache() { debug_only(_pc_descs[0] = NULL); } void reset_to(PcDesc* initial_pc_desc); PcDesc* find_pc_desc(int pc_offset, bool approximate); void add_pc_desc(PcDesc* pc_desc); - PcDesc* last_pc_desc() { return _last_pc_desc; } + PcDesc* last_pc_desc() { return _pc_descs[0]; } }; @@ -178,7 +177,7 @@ unsigned int _has_method_handle_invokes:1; // Has this method MethodHandle invokes? // Protected by Patching_lock - unsigned char _state; // {alive, not_entrant, zombie, unloaded) + unsigned char _state; // {alive, not_entrant, zombie, unloaded} #ifdef ASSERT bool _oops_are_stale; // indicates that it's no longer safe to access oops section @@ -194,7 +193,10 @@ NOT_PRODUCT(bool _has_debug_info; ) - // Nmethod Flushing lock (if non-zero, then the nmethod is not removed) + // Nmethod Flushing lock. If non-zero, then the nmethod is not removed + // and is not made into a zombie. However, once the nmethod is made into + // a zombie, it will be locked one final time if CompiledMethodUnload + // event processing needs to be done. jint _lock_count; // not_entrant method removal. Each mark_sweep pass will update @@ -522,8 +524,9 @@ void flush(); public: - // If returning true, it is unsafe to remove this nmethod even though it is a zombie - // nmethod, since the VM might have a reference to it. Should only be called from a safepoint. + // When true is returned, it is unsafe to remove this nmethod even if + // it is a zombie, since the VM or the ServiceThread might still be + // using it. bool is_locked_by_vm() const { return _lock_count >0; } // See comment at definition of _last_seen_on_stack @@ -689,13 +692,20 @@ }; -// Locks an nmethod so its code will not get removed, even if it is a zombie/not_entrant method +// Locks an nmethod so its code will not get removed and it will not +// be made into a zombie, even if it is a not_entrant method. After the +// nmethod becomes a zombie, if CompiledMethodUnload event processing +// needs to be done, then lock_nmethod() is used directly to keep the +// generated code from being reused too early. class nmethodLocker : public StackObj { nmethod* _nm; public: - static void lock_nmethod(nmethod* nm); // note: nm can be NULL + // note: nm can be NULL + // Only JvmtiDeferredEvent::compiled_method_unload_event() + // should pass zombie_ok == true. + static void lock_nmethod(nmethod* nm, bool zombie_ok = false); static void unlock_nmethod(nmethod* nm); // (ditto) nmethodLocker(address pc); // derive nm from pc diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/compiler/compileBroker.cpp --- a/src/share/vm/compiler/compileBroker.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/compiler/compileBroker.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1364,7 +1364,7 @@ // We need this HandleMark to avoid leaking VM handles. HandleMark hm(thread); - if (CodeCache::unallocated_capacity() < CodeCacheMinimumFreeSpace) { + if (CodeCache::largest_free_block() < CodeCacheMinimumFreeSpace) { // the code cache is really full handle_full_code_cache(); } else if (UseCodeCacheFlushing && CodeCache::needs_flushing()) { @@ -1645,11 +1645,13 @@ if (UseCompiler || AlwaysCompileLoopMethods ) { if (xtty != NULL) { xtty->begin_elem("code_cache_full"); + CodeCache::log_state(xtty); xtty->stamp(); xtty->end_elem(); } warning("CodeCache is full. Compiler has been disabled."); warning("Try increasing the code cache size using -XX:ReservedCodeCacheSize="); + CodeCache::print_bounds(tty); #ifndef PRODUCT if (CompileTheWorld || ExitOnFullCodeCache) { before_exit(JavaThread::current()); diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, 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 @@ -292,13 +292,15 @@ void CMSCollector::ref_processor_init() { if (_ref_processor == NULL) { // Allocate and initialize a reference processor - _ref_processor = ReferenceProcessor::create_ref_processor( - _span, // span - _cmsGen->refs_discovery_is_atomic(), // atomic_discovery - _cmsGen->refs_discovery_is_mt(), // mt_discovery - &_is_alive_closure, - ParallelGCThreads, - ParallelRefProcEnabled); + _ref_processor = + new ReferenceProcessor(_span, // span + (ParallelGCThreads > 1) && ParallelRefProcEnabled, // mt processing + (int) ParallelGCThreads, // mt processing degree + _cmsGen->refs_discovery_is_mt(), // mt discovery + (int) MAX2(ConcGCThreads, ParallelGCThreads), // mt discovery degree + _cmsGen->refs_discovery_is_atomic(), // discovery is not atomic + &_is_alive_closure, // closure for liveness info + false); // next field updates do not need write barrier // Initialize the _ref_processor field of CMSGen _cmsGen->set_ref_processor(_ref_processor); @@ -641,7 +643,7 @@ } // Support for multi-threaded concurrent phases - if (CollectedHeap::use_parallel_gc_threads() && CMSConcurrentMTEnabled) { + if (CMSConcurrentMTEnabled) { if (FLAG_IS_DEFAULT(ConcGCThreads)) { // just for now FLAG_SET_DEFAULT(ConcGCThreads, (ParallelGCThreads + 3)/4); @@ -1689,6 +1691,8 @@ MutexLockerEx y(CGC_lock, Mutex::_no_safepoint_check_flag); _full_gc_requested = true; CGC_lock->notify(); // nudge CMS thread + } else { + assert(gc_count > full_gc_count, "Error: causal loop"); } } @@ -1988,17 +1992,16 @@ // Temporarily widen the span of the weak reference processing to // the entire heap. MemRegion new_span(GenCollectedHeap::heap()->reserved_region()); - ReferenceProcessorSpanMutator x(ref_processor(), new_span); - + ReferenceProcessorSpanMutator rp_mut_span(ref_processor(), new_span); // Temporarily, clear the "is_alive_non_header" field of the // reference processor. - ReferenceProcessorIsAliveMutator y(ref_processor(), NULL); - + ReferenceProcessorIsAliveMutator rp_mut_closure(ref_processor(), NULL); // Temporarily make reference _processing_ single threaded (non-MT). - ReferenceProcessorMTProcMutator z(ref_processor(), false); - + ReferenceProcessorMTProcMutator rp_mut_mt_processing(ref_processor(), false); // Temporarily make refs discovery atomic - ReferenceProcessorAtomicMutator w(ref_processor(), true); + ReferenceProcessorAtomicMutator rp_mut_atomic(ref_processor(), true); + // Temporarily make reference _discovery_ single threaded (non-MT) + ReferenceProcessorMTDiscoveryMutator rp_mut_discovery(ref_processor(), false); ref_processor()->set_enqueuing_is_done(false); ref_processor()->enable_discovery(); @@ -4263,9 +4266,7 @@ // Refs discovery is already non-atomic. assert(!ref_processor()->discovery_is_atomic(), "Should be non-atomic"); - // Mutate the Refs discovery so it is MT during the - // multi-threaded marking phase. - ReferenceProcessorMTMutator mt(ref_processor(), num_workers > 1); + assert(ref_processor()->discovery_is_mt(), "Discovery should be MT"); DEBUG_ONLY(RememberKlassesChecker cmx(should_unload_classes());) conc_workers()->start_task(&tsk); while (tsk.yielded()) { @@ -4318,6 +4319,8 @@ ResourceMark rm; HandleMark hm; + // Temporarily make refs discovery single threaded (non-MT) + ReferenceProcessorMTDiscoveryMutator rp_mut_discovery(ref_processor(), false); MarkFromRootsClosure markFromRootsClosure(this, _span, &_markBitMap, &_markStack, &_revisitStack, CMSYield && asynch); // the last argument to iterate indicates whether the iteration @@ -4356,10 +4359,6 @@ verify_overflow_empty(); _abort_preclean = false; if (CMSPrecleaningEnabled) { - // Precleaning is currently not MT but the reference processor - // may be set for MT. Disable it temporarily here. - ReferenceProcessor* rp = ref_processor(); - ReferenceProcessorMTProcMutator z(rp, false); _eden_chunk_index = 0; size_t used = get_eden_used(); size_t capacity = get_eden_capacity(); @@ -4502,11 +4501,16 @@ _collectorState == AbortablePreclean, "incorrect state"); ResourceMark rm; HandleMark hm; + + // Precleaning is currently not MT but the reference processor + // may be set for MT. Disable it temporarily here. + ReferenceProcessor* rp = ref_processor(); + ReferenceProcessorMTDiscoveryMutator rp_mut_discovery(rp, false); + // Do one pass of scrubbing the discovered reference lists // to remove any reference objects with strongly-reachable // referents. if (clean_refs) { - ReferenceProcessor* rp = ref_processor(); CMSPrecleanRefsYieldClosure yield_cl(this); assert(rp->span().equals(_span), "Spans should be equal"); CMSKeepAliveClosure keep_alive(this, _span, &_markBitMap, @@ -5576,8 +5580,10 @@ // in the multi-threaded case, but we special-case n=1 here to get // repeatable measurements of the 1-thread overhead of the parallel code. if (n_workers > 1) { - // Make refs discovery MT-safe - ReferenceProcessorMTMutator mt(ref_processor(), true); + // Make refs discovery MT-safe, if it isn't already: it may not + // necessarily be so, since it's possible that we are doing + // ST marking. + ReferenceProcessorMTDiscoveryMutator mt(ref_processor(), true); GenCollectedHeap::StrongRootsScope srs(gch); workers->run_task(&tsk); } else { @@ -5703,14 +5709,19 @@ CMSBitMap* mark_bit_map, AbstractWorkGang* workers, OopTaskQueueSet* task_queues): + // XXX Should superclass AGTWOQ also know about AWG since it knows + // about the task_queues used by the AWG? Then it could initialize + // the terminator() object. See 6984287. The set_for_termination() + // below is a temporary band-aid for the regression in 6984287. AbstractGangTaskWOopQueues("Process referents by policy in parallel", task_queues), _task(task), _collector(collector), _span(span), _mark_bit_map(mark_bit_map) - { - assert(_collector->_span.equals(_span) && !_span.is_empty(), - "Inconsistency in _span"); - } + { + assert(_collector->_span.equals(_span) && !_span.is_empty(), + "Inconsistency in _span"); + set_for_termination(workers->active_workers()); + } OopTaskQueueSet* task_queues() { return queues(); } @@ -5872,8 +5883,7 @@ // That is OK as long as the Reference lists are balanced (see // balance_all_queues() and balance_queues()). - - rp->set_mt_degree(ParallelGCThreads); + rp->set_active_mt_degree(ParallelGCThreads); CMSRefProcTaskExecutor task_executor(*this); rp->process_discovered_references(&_is_alive_closure, &cmsKeepAliveClosure, diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, 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 @@ -1133,7 +1133,7 @@ // rare that the cost of the CAS's involved is in the // noise. That's a measurement that should be done, and // the code simplified if that turns out to be the case. - return false; + return ConcGCThreads > 1; } // Override diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, 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 @@ -51,7 +51,7 @@ volatile jint ConcurrentMarkSweepThread::_pending_yields = 0; volatile jint ConcurrentMarkSweepThread::_pending_decrements = 0; -volatile bool ConcurrentMarkSweepThread::_icms_enabled = false; +volatile jint ConcurrentMarkSweepThread::_icms_disabled = 0; volatile bool ConcurrentMarkSweepThread::_should_run = false; // When icms is enabled, the icms thread is stopped until explicitly // started. @@ -84,7 +84,7 @@ } } _sltMonitor = SLT_lock; - set_icms_enabled(CMSIncrementalMode); + assert(!CMSIncrementalMode || icms_is_enabled(), "Error"); } void ConcurrentMarkSweepThread::run() { @@ -341,11 +341,11 @@ void ConcurrentMarkSweepThread::icms_wait() { assert(UseConcMarkSweepGC && CMSIncrementalMode, "just checking"); - if (_should_stop && icms_enabled()) { + if (_should_stop && icms_is_enabled()) { MutexLockerEx x(iCMS_lock, Mutex::_no_safepoint_check_flag); trace_state("pause_icms"); _collector->stats().stop_cms_timer(); - while(!_should_run && icms_enabled()) { + while(!_should_run && icms_is_enabled()) { iCMS_lock->wait(Mutex::_no_safepoint_check_flag); } _collector->stats().start_cms_timer(); diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, 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 @@ -40,7 +40,7 @@ class ConcurrentMarkSweepGeneration; class CMSCollector; -// The Concurrent Mark Sweep GC Thread (could be several in the future). +// The Concurrent Mark Sweep GC Thread class ConcurrentMarkSweepThread: public ConcurrentGCThread { friend class VMStructs; friend class ConcurrentMarkSweepGeneration; // XXX should remove friendship @@ -55,8 +55,6 @@ static SurrogateLockerThread::SLT_msg_type _sltBuffer; static Monitor* _sltMonitor; - ConcurrentMarkSweepThread* _next; - static bool _should_terminate; enum CMS_flag_type { @@ -84,7 +82,7 @@ // Tracing messages, enabled by CMSTraceThreadState. static inline void trace_state(const char* desc); - static volatile bool _icms_enabled; // iCMS enabled? + static volatile int _icms_disabled; // a counter to track #iCMS disable & enable static volatile bool _should_run; // iCMS may run static volatile bool _should_stop; // iCMS should stop @@ -214,10 +212,25 @@ // Incremental mode is enabled globally by the flag CMSIncrementalMode. It // must also be enabled/disabled dynamically to allow foreground collections. - static inline void enable_icms() { _icms_enabled = true; } - static inline void disable_icms() { _icms_enabled = false; } - static inline void set_icms_enabled(bool val) { _icms_enabled = val; } - static inline bool icms_enabled() { return _icms_enabled; } +#define ICMS_ENABLING_ASSERT \ + assert((CMSIncrementalMode && _icms_disabled >= 0) || \ + (!CMSIncrementalMode && _icms_disabled <= 0), "Error") + + static inline void enable_icms() { + ICMS_ENABLING_ASSERT; + Atomic::dec(&_icms_disabled); + } + static inline void disable_icms() { + ICMS_ENABLING_ASSERT; + Atomic::inc(&_icms_disabled); + } + static inline bool icms_is_disabled() { + ICMS_ENABLING_ASSERT; + return _icms_disabled > 0; + } + static inline bool icms_is_enabled() { + return !icms_is_disabled(); + } }; inline void ConcurrentMarkSweepThread::trace_state(const char* desc) { diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, 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 @@ -192,14 +192,18 @@ "total_collections() should be monotonically increasing"); MutexLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag); + assert(_full_gc_count_before <= gch->total_full_collections(), "Error"); if (gch->total_full_collections() == _full_gc_count_before) { - // Disable iCMS until the full collection is done. + // Disable iCMS until the full collection is done, and + // remember that we did so. CMSCollector::disable_icms(); + _disabled_icms = true; // In case CMS thread was in icms_wait(), wake it up. CMSCollector::start_icms(); // Nudge the CMS thread to start a concurrent collection. CMSCollector::request_full_gc(_full_gc_count_before); } else { + assert(_full_gc_count_before < gch->total_full_collections(), "Error"); FullGCCount_lock->notify_all(); // Inform the Java thread its work is done } } @@ -259,6 +263,8 @@ FullGCCount_lock->wait(Mutex::_no_safepoint_check_flag); } } - // Enable iCMS back. - CMSCollector::enable_icms(); + // Enable iCMS back if we disabled it earlier. + if (_disabled_icms) { + CMSCollector::enable_icms(); + } } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.hpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -128,11 +128,14 @@ // VM operation to invoke a concurrent collection of the heap as a // GenCollectedHeap heap. class VM_GenCollectFullConcurrent: public VM_GC_Operation { + bool _disabled_icms; public: VM_GenCollectFullConcurrent(unsigned int gc_count_before, unsigned int full_gc_count_before, GCCause::Cause gc_cause) - : VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, true /* full */) { + : VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, true /* full */), + _disabled_icms(false) + { assert(FullGCCount_lock != NULL, "Error"); assert(UseAsyncConcMarkSweepGC, "Else will hang caller"); } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp --- a/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -373,7 +373,7 @@ // RSet updating while within an evacuation pause. // In this case worker_i should be the id of a GC worker thread assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause"); - assert(worker_i < (int) DirtyCardQueueSet::num_par_ids(), "incorrect worker id"); + assert(worker_i < (int) (ParallelGCThreads == 0 ? 1 : ParallelGCThreads), "incorrect worker id"); into_cset_dcq->enqueue(entry); } } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/gc_implementation/g1/concurrentMark.cpp --- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1828,7 +1828,7 @@ G1CollectedHeap* g1h = G1CollectedHeap::heap(); _cleanup_list.verify_optional(); - FreeRegionList local_free_list("Local Cleanup List"); + FreeRegionList tmp_free_list("Tmp Free List"); if (G1ConcRegionFreeingVerbose) { gclog_or_tty->print_cr("G1ConcRegionFreeing [complete cleanup] : " @@ -1842,7 +1842,7 @@ HeapRegion* hr = _cleanup_list.remove_head(); assert(hr != NULL, "the list was not empty"); hr->rem_set()->clear(); - local_free_list.add_as_tail(hr); + tmp_free_list.add_as_tail(hr); // Instead of adding one region at a time to the secondary_free_list, // we accumulate them in the local list and move them a few at a @@ -1850,20 +1850,20 @@ // we do during this process. We'll also append the local list when // _cleanup_list is empty (which means we just removed the last // region from the _cleanup_list). - if ((local_free_list.length() % G1SecondaryFreeListAppendLength == 0) || + if ((tmp_free_list.length() % G1SecondaryFreeListAppendLength == 0) || _cleanup_list.is_empty()) { if (G1ConcRegionFreeingVerbose) { gclog_or_tty->print_cr("G1ConcRegionFreeing [complete cleanup] : " "appending "SIZE_FORMAT" entries to the " "secondary_free_list, clean list still has " SIZE_FORMAT" entries", - local_free_list.length(), + tmp_free_list.length(), _cleanup_list.length()); } { MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag); - g1h->secondary_free_list_add_as_tail(&local_free_list); + g1h->secondary_free_list_add_as_tail(&tmp_free_list); SecondaryFreeList_lock->notify_all(); } @@ -1874,7 +1874,7 @@ } } } - assert(local_free_list.is_empty(), "post-condition"); + assert(tmp_free_list.is_empty(), "post-condition"); } // Support closures for reference procssing in G1 @@ -2141,21 +2141,22 @@ G1CMKeepAliveClosure g1_keep_alive(g1h, this, nextMarkBitMap()); G1CMDrainMarkingStackClosure g1_drain_mark_stack(nextMarkBitMap(), &_markStack, &g1_keep_alive); - // We use the work gang from the G1CollectedHeap and we utilize all // the worker threads. - int active_workers = MAX2(MIN2(g1h->workers()->total_workers(), (int)_max_task_num), 1); + int active_workers = g1h->workers() ? g1h->workers()->total_workers() : 1; + active_workers = MAX2(MIN2(active_workers, (int)_max_task_num), 1); G1RefProcTaskExecutor par_task_executor(g1h, this, nextMarkBitMap(), g1h->workers(), active_workers); + if (rp->processing_is_mt()) { // Set the degree of MT here. If the discovery is done MT, there // may have been a different number of threads doing the discovery // and a different number of discovered lists may have Ref objects. // That is OK as long as the Reference lists are balanced (see // balance_all_queues() and balance_queues()). - rp->set_mt_degree(active_workers); + rp->set_active_mt_degree(active_workers); rp->process_discovered_references(&g1_is_alive, &g1_keep_alive, @@ -3182,7 +3183,7 @@ template void do_oop_work(T* p) { assert( _g1h->is_in_g1_reserved((HeapWord*) p), "invariant"); - assert(!_g1h->is_on_free_list( + assert(!_g1h->is_on_master_free_list( _g1h->heap_region_containing((HeapWord*) p)), "invariant"); oop obj = oopDesc::load_decode_heap_oop(p); @@ -3403,7 +3404,7 @@ void CMTask::push(oop obj) { HeapWord* objAddr = (HeapWord*) obj; assert(_g1h->is_in_g1_reserved(objAddr), "invariant"); - assert(!_g1h->is_on_free_list( + assert(!_g1h->is_on_master_free_list( _g1h->heap_region_containing((HeapWord*) objAddr)), "invariant"); assert(!_g1h->is_obj_ill(obj), "invariant"); assert(_nextMarkBitMap->isMarked(objAddr), "invariant"); @@ -3649,7 +3650,7 @@ (void*) obj); assert(_g1h->is_in_g1_reserved((HeapWord*) obj), "invariant" ); - assert(!_g1h->is_on_free_list( + assert(!_g1h->is_on_master_free_list( _g1h->heap_region_containing((HeapWord*) obj)), "invariant"); scan_object(obj); diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp --- a/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -237,9 +237,9 @@ // The following will finish freeing up any regions that we // found to be empty during cleanup. We'll do this part // without joining the suspendible set. If an evacuation pause - // takes places, then we would carry on freeing regions in + // takes place, then we would carry on freeing regions in // case they are needed by the pause. If a Full GC takes - // places, it would wait for us to process the regions + // place, it would wait for us to process the regions // reclaimed by cleanup. double cleanup_start_sec = os::elapsedTime(); diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -479,7 +479,7 @@ // Private methods. HeapRegion* -G1CollectedHeap::new_region_try_secondary_free_list(size_t word_size) { +G1CollectedHeap::new_region_try_secondary_free_list() { MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag); while (!_secondary_free_list.is_empty() || free_regions_coming()) { if (!_secondary_free_list.is_empty()) { @@ -531,7 +531,7 @@ gclog_or_tty->print_cr("G1ConcRegionFreeing [region alloc] : " "forced to look at the secondary_free_list"); } - res = new_region_try_secondary_free_list(word_size); + res = new_region_try_secondary_free_list(); if (res != NULL) { return res; } @@ -543,7 +543,7 @@ gclog_or_tty->print_cr("G1ConcRegionFreeing [region alloc] : " "res == NULL, trying the secondary_free_list"); } - res = new_region_try_secondary_free_list(word_size); + res = new_region_try_secondary_free_list(); } if (res == NULL && do_expand) { if (expand(word_size * HeapWordSize)) { @@ -579,6 +579,9 @@ int G1CollectedHeap::humongous_obj_allocate_find_first(size_t num_regions, size_t word_size) { + assert(isHumongous(word_size), "word_size should be humongous"); + assert(num_regions * HeapRegion::GrainWords >= word_size, "pre-condition"); + int first = -1; if (num_regions == 1) { // Only one region to allocate, no need to go through the slower @@ -600,7 +603,7 @@ // request. If we are only allocating one region we use the common // region allocation code (see above). wait_while_free_regions_coming(); - append_secondary_free_list_if_not_empty(); + append_secondary_free_list_if_not_empty_with_lock(); if (free_regions() >= num_regions) { first = _hrs->find_contiguous(num_regions); @@ -608,7 +611,7 @@ for (int i = first; i < first + (int) num_regions; ++i) { HeapRegion* hr = _hrs->at(i); assert(hr->is_empty(), "sanity"); - assert(is_on_free_list(hr), "sanity"); + assert(is_on_master_free_list(hr), "sanity"); hr->set_pending_removal(true); } _free_list.remove_all_pending(num_regions); @@ -618,6 +621,126 @@ return first; } +HeapWord* +G1CollectedHeap::humongous_obj_allocate_initialize_regions(int first, + size_t num_regions, + size_t word_size) { + assert(first != -1, "pre-condition"); + assert(isHumongous(word_size), "word_size should be humongous"); + assert(num_regions * HeapRegion::GrainWords >= word_size, "pre-condition"); + + // Index of last region in the series + 1. + int last = first + (int) num_regions; + + // We need to initialize the region(s) we just discovered. This is + // a bit tricky given that it can happen concurrently with + // refinement threads refining cards on these regions and + // potentially wanting to refine the BOT as they are scanning + // those cards (this can happen shortly after a cleanup; see CR + // 6991377). So we have to set up the region(s) carefully and in + // a specific order. + + // The word size sum of all the regions we will allocate. + size_t word_size_sum = num_regions * HeapRegion::GrainWords; + assert(word_size <= word_size_sum, "sanity"); + + // This will be the "starts humongous" region. + HeapRegion* first_hr = _hrs->at(first); + // The header of the new object will be placed at the bottom of + // the first region. + HeapWord* new_obj = first_hr->bottom(); + // This will be the new end of the first region in the series that + // should also match the end of the last region in the seriers. + HeapWord* new_end = new_obj + word_size_sum; + // This will be the new top of the first region that will reflect + // this allocation. + HeapWord* new_top = new_obj + word_size; + + // First, we need to zero the header of the space that we will be + // allocating. When we update top further down, some refinement + // threads might try to scan the region. By zeroing the header we + // ensure that any thread that will try to scan the region will + // come across the zero klass word and bail out. + // + // NOTE: It would not have been correct to have used + // CollectedHeap::fill_with_object() and make the space look like + // an int array. The thread that is doing the allocation will + // later update the object header to a potentially different array + // type and, for a very short period of time, the klass and length + // fields will be inconsistent. This could cause a refinement + // thread to calculate the object size incorrectly. + Copy::fill_to_words(new_obj, oopDesc::header_size(), 0); + + // We will set up the first region as "starts humongous". This + // will also update the BOT covering all the regions to reflect + // that there is a single object that starts at the bottom of the + // first region. + first_hr->set_startsHumongous(new_top, new_end); + + // Then, if there are any, we will set up the "continues + // humongous" regions. + HeapRegion* hr = NULL; + for (int i = first + 1; i < last; ++i) { + hr = _hrs->at(i); + hr->set_continuesHumongous(first_hr); + } + // If we have "continues humongous" regions (hr != NULL), then the + // end of the last one should match new_end. + assert(hr == NULL || hr->end() == new_end, "sanity"); + + // Up to this point no concurrent thread would have been able to + // do any scanning on any region in this series. All the top + // fields still point to bottom, so the intersection between + // [bottom,top] and [card_start,card_end] will be empty. Before we + // update the top fields, we'll do a storestore to make sure that + // no thread sees the update to top before the zeroing of the + // object header and the BOT initialization. + OrderAccess::storestore(); + + // Now that the BOT and the object header have been initialized, + // we can update top of the "starts humongous" region. + assert(first_hr->bottom() < new_top && new_top <= first_hr->end(), + "new_top should be in this region"); + first_hr->set_top(new_top); + + // Now, we will update the top fields of the "continues humongous" + // regions. The reason we need to do this is that, otherwise, + // these regions would look empty and this will confuse parts of + // G1. For example, the code that looks for a consecutive number + // of empty regions will consider them empty and try to + // re-allocate them. We can extend is_empty() to also include + // !continuesHumongous(), but it is easier to just update the top + // fields here. The way we set top for all regions (i.e., top == + // end for all regions but the last one, top == new_top for the + // last one) is actually used when we will free up the humongous + // region in free_humongous_region(). + hr = NULL; + for (int i = first + 1; i < last; ++i) { + hr = _hrs->at(i); + if ((i + 1) == last) { + // last continues humongous region + assert(hr->bottom() < new_top && new_top <= hr->end(), + "new_top should fall on this region"); + hr->set_top(new_top); + } else { + // not last one + assert(new_top > hr->end(), "new_top should be above this region"); + hr->set_top(hr->end()); + } + } + // If we have continues humongous regions (hr != NULL), then the + // end of the last one should match new_end and its top should + // match new_top. + assert(hr == NULL || + (hr->end() == new_end && hr->top() == new_top), "sanity"); + + assert(first_hr->used() == word_size * HeapWordSize, "invariant"); + _summary_bytes_used += first_hr->used(); + _humongous_set.add(first_hr); + + return new_obj; +} + // If could fit into free regions w/o expansion, try. // Otherwise, if can expand, do so. // Otherwise, if using ex regions might help, try with ex given back. @@ -653,121 +776,16 @@ } } + HeapWord* result = NULL; if (first != -1) { - // Index of last region in the series + 1. - int last = first + (int) num_regions; - - // We need to initialize the region(s) we just discovered. This is - // a bit tricky given that it can happen concurrently with - // refinement threads refining cards on these regions and - // potentially wanting to refine the BOT as they are scanning - // those cards (this can happen shortly after a cleanup; see CR - // 6991377). So we have to set up the region(s) carefully and in - // a specific order. - - // The word size sum of all the regions we will allocate. - size_t word_size_sum = num_regions * HeapRegion::GrainWords; - assert(word_size <= word_size_sum, "sanity"); - - // This will be the "starts humongous" region. - HeapRegion* first_hr = _hrs->at(first); - // The header of the new object will be placed at the bottom of - // the first region. - HeapWord* new_obj = first_hr->bottom(); - // This will be the new end of the first region in the series that - // should also match the end of the last region in the seriers. - HeapWord* new_end = new_obj + word_size_sum; - // This will be the new top of the first region that will reflect - // this allocation. - HeapWord* new_top = new_obj + word_size; - - // First, we need to zero the header of the space that we will be - // allocating. When we update top further down, some refinement - // threads might try to scan the region. By zeroing the header we - // ensure that any thread that will try to scan the region will - // come across the zero klass word and bail out. - // - // NOTE: It would not have been correct to have used - // CollectedHeap::fill_with_object() and make the space look like - // an int array. The thread that is doing the allocation will - // later update the object header to a potentially different array - // type and, for a very short period of time, the klass and length - // fields will be inconsistent. This could cause a refinement - // thread to calculate the object size incorrectly. - Copy::fill_to_words(new_obj, oopDesc::header_size(), 0); - - // We will set up the first region as "starts humongous". This - // will also update the BOT covering all the regions to reflect - // that there is a single object that starts at the bottom of the - // first region. - first_hr->set_startsHumongous(new_top, new_end); - - // Then, if there are any, we will set up the "continues - // humongous" regions. - HeapRegion* hr = NULL; - for (int i = first + 1; i < last; ++i) { - hr = _hrs->at(i); - hr->set_continuesHumongous(first_hr); - } - // If we have "continues humongous" regions (hr != NULL), then the - // end of the last one should match new_end. - assert(hr == NULL || hr->end() == new_end, "sanity"); - - // Up to this point no concurrent thread would have been able to - // do any scanning on any region in this series. All the top - // fields still point to bottom, so the intersection between - // [bottom,top] and [card_start,card_end] will be empty. Before we - // update the top fields, we'll do a storestore to make sure that - // no thread sees the update to top before the zeroing of the - // object header and the BOT initialization. - OrderAccess::storestore(); - - // Now that the BOT and the object header have been initialized, - // we can update top of the "starts humongous" region. - assert(first_hr->bottom() < new_top && new_top <= first_hr->end(), - "new_top should be in this region"); - first_hr->set_top(new_top); - - // Now, we will update the top fields of the "continues humongous" - // regions. The reason we need to do this is that, otherwise, - // these regions would look empty and this will confuse parts of - // G1. For example, the code that looks for a consecutive number - // of empty regions will consider them empty and try to - // re-allocate them. We can extend is_empty() to also include - // !continuesHumongous(), but it is easier to just update the top - // fields here. The way we set top for all regions (i.e., top == - // end for all regions but the last one, top == new_top for the - // last one) is actually used when we will free up the humongous - // region in free_humongous_region(). - hr = NULL; - for (int i = first + 1; i < last; ++i) { - hr = _hrs->at(i); - if ((i + 1) == last) { - // last continues humongous region - assert(hr->bottom() < new_top && new_top <= hr->end(), - "new_top should fall on this region"); - hr->set_top(new_top); - } else { - // not last one - assert(new_top > hr->end(), "new_top should be above this region"); - hr->set_top(hr->end()); - } - } - // If we have continues humongous regions (hr != NULL), then the - // end of the last one should match new_end and its top should - // match new_top. - assert(hr == NULL || - (hr->end() == new_end && hr->top() == new_top), "sanity"); - - assert(first_hr->used() == word_size * HeapWordSize, "invariant"); - _summary_bytes_used += first_hr->used(); - _humongous_set.add(first_hr); - - return new_obj; + result = + humongous_obj_allocate_initialize_regions(first, num_regions, word_size); + assert(result != NULL, "it should always return a valid result"); } verify_region_sets_optional(); - return NULL; + + return result; } void @@ -1389,7 +1407,7 @@ g1_policy()->record_full_collection_start(); wait_while_free_regions_coming(); - append_secondary_free_list_if_not_empty(); + append_secondary_free_list_if_not_empty_with_lock(); gc_prologue(true); increment_total_collections(true /* full gc */); @@ -1444,7 +1462,7 @@ // how reference processing currently works in G1. // Temporarily make reference _discovery_ single threaded (non-MT). - ReferenceProcessorMTMutator rp_disc_ser(ref_processor(), false); + ReferenceProcessorMTDiscoveryMutator rp_disc_ser(ref_processor(), false); // Temporarily make refs discovery atomic ReferenceProcessorAtomicMutator rp_disc_atomic(ref_processor(), true); @@ -2201,16 +2219,16 @@ SharedHeap::ref_processing_init(); MemRegion mr = reserved_region(); - _ref_processor = ReferenceProcessor::create_ref_processor( - mr, // span - false, // Reference discovery is not atomic - true, // mt_discovery - &_is_alive_closure, // is alive closure - // for efficiency - ParallelGCThreads, - ParallelRefProcEnabled, - true); // Setting next fields of discovered - // lists requires a barrier. + _ref_processor = + new ReferenceProcessor(mr, // span + ParallelRefProcEnabled && (ParallelGCThreads > 1), // mt processing + (int) ParallelGCThreads, // degree of mt processing + ParallelGCThreads > 1 || ConcGCThreads > 1, // mt discovery + (int) MAX2(ParallelGCThreads, ConcGCThreads), // degree of mt discovery + false, // Reference discovery is not atomic + &_is_alive_closure, // is alive closure for efficiency + true); // Setting next fields of discovered + // lists requires a barrier. } size_t G1CollectedHeap::capacity() const { @@ -3377,15 +3395,14 @@ TraceMemoryManagerStats tms(false /* fullGC */); - // If there are any free regions available on the secondary_free_list - // make sure we append them to the free_list. However, we don't - // have to wait for the rest of the cleanup operation to - // finish. If it's still going on that's OK. If we run out of - // regions, the region allocation code will check the - // secondary_free_list and potentially wait if more free regions - // are coming (see new_region_try_secondary_free_list()). + // If the secondary_free_list is not empty, append it to the + // free_list. No need to wait for the cleanup operation to finish; + // the region allocation code will check the secondary_free_list + // and wait if necessary. If the G1StressConcRegionFreeing flag is + // set, skip this step so that the region allocation code has to + // get entries from the secondary_free_list. if (!G1StressConcRegionFreeing) { - append_secondary_free_list_if_not_empty(); + append_secondary_free_list_if_not_empty_with_lock(); } increment_gc_time_stamp(); @@ -5199,7 +5216,7 @@ size_t rs_lengths = 0; while (cur != NULL) { - assert(!is_on_free_list(cur), "sanity"); + assert(!is_on_master_free_list(cur), "sanity"); if (non_young) { if (cur->is_young()) { @@ -5543,13 +5560,10 @@ return; } - { - MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag); - // Make sure we append the secondary_free_list on the free_list so - // that all free regions we will come across can be safely - // attributed to the free_list. - append_secondary_free_list(); - } + // Make sure we append the secondary_free_list on the free_list so + // that all free regions we will come across can be safely + // attributed to the free_list. + append_secondary_free_list_if_not_empty_with_lock(); // Finally, make sure that the region accounting in the lists is // consistent with what we see in the heap. diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -56,7 +56,6 @@ class ConcurrentMark; class ConcurrentMarkThread; class ConcurrentG1Refine; -class ConcurrentZFThread; typedef OverflowTaskQueue RefToScanQueue; typedef GenericTaskQueueSet RefToScanQueueSet; @@ -64,12 +63,6 @@ typedef int RegionIdx_t; // needs to hold [ 0..max_regions() ) typedef int CardIdx_t; // needs to hold [ 0..CardsPerRegion ) -enum G1GCThreadGroups { - G1CRGroup = 0, - G1ZFGroup = 1, - G1CMGroup = 2 -}; - enum GCAllocPurpose { GCAllocForTenured, GCAllocForSurvived, @@ -294,9 +287,9 @@ // These are macros so that, if the assert fires, we get the correct // line number, file, etc. -#define heap_locking_asserts_err_msg(__extra_message) \ +#define heap_locking_asserts_err_msg(_extra_message_) \ err_msg("%s : Heap_lock locked: %s, at safepoint: %s, is VM thread: %s", \ - (__extra_message), \ + (_extra_message_), \ BOOL_TO_STR(Heap_lock->owned_by_self()), \ BOOL_TO_STR(SafepointSynchronize::is_at_safepoint()), \ BOOL_TO_STR(Thread::current()->is_VM_thread())) @@ -307,11 +300,11 @@ heap_locking_asserts_err_msg("should be holding the Heap_lock")); \ } while (0) -#define assert_heap_locked_or_at_safepoint(__should_be_vm_thread) \ +#define assert_heap_locked_or_at_safepoint(_should_be_vm_thread_) \ do { \ assert(Heap_lock->owned_by_self() || \ (SafepointSynchronize::is_at_safepoint() && \ - ((__should_be_vm_thread) == Thread::current()->is_VM_thread())), \ + ((_should_be_vm_thread_) == Thread::current()->is_VM_thread())), \ heap_locking_asserts_err_msg("should be holding the Heap_lock or " \ "should be at a safepoint")); \ } while (0) @@ -338,10 +331,10 @@ "should not be at a safepoint")); \ } while (0) -#define assert_at_safepoint(__should_be_vm_thread) \ +#define assert_at_safepoint(_should_be_vm_thread_) \ do { \ assert(SafepointSynchronize::is_at_safepoint() && \ - ((__should_be_vm_thread) == Thread::current()->is_VM_thread()), \ + ((_should_be_vm_thread_) == Thread::current()->is_VM_thread()), \ heap_locking_asserts_err_msg("should be at a safepoint")); \ } while (0) @@ -371,35 +364,40 @@ // will check whether there's anything available in the // secondary_free_list and/or wait for more regions to appear in that // list, if _free_regions_coming is set. - HeapRegion* new_region_try_secondary_free_list(size_t word_size); + HeapRegion* new_region_try_secondary_free_list(); - // It will try to allocate a single non-humongous HeapRegion - // sufficient for an allocation of the given word_size. If - // do_expand is true, it will attempt to expand the heap if - // necessary to satisfy the allocation request. Note that word_size - // is only used to make sure that we expand sufficiently but, given - // that the allocation request is assumed not to be humongous, - // having word_size is not strictly necessary (expanding by a single - // region will always be sufficient). But let's keep that parameter - // in case we need it in the future. + // Try to allocate a single non-humongous HeapRegion sufficient for + // an allocation of the given word_size. If do_expand is true, + // attempt to expand the heap if necessary to satisfy the allocation + // request. HeapRegion* new_region_work(size_t word_size, bool do_expand); - // It will try to allocate a new region to be used for allocation by - // mutator threads. It will not try to expand the heap if not region - // is available. + // Try to allocate a new region to be used for allocation by a + // mutator thread. Attempt to expand the heap if no region is + // available. HeapRegion* new_alloc_region(size_t word_size) { return new_region_work(word_size, false /* do_expand */); } - // It will try to allocate a new region to be used for allocation by - // a GC thread. It will try to expand the heap if no region is - // available. + // Try to allocate a new region to be used for allocation by a GC + // thread. Attempt to expand the heap if no region is available. HeapRegion* new_gc_alloc_region(int purpose, size_t word_size); + // Attempt to satisfy a humongous allocation request of the given + // size by finding a contiguous set of free regions of num_regions + // length and remove them from the master free list. Return the + // index of the first region or -1 if the search was unsuccessful. int humongous_obj_allocate_find_first(size_t num_regions, size_t word_size); - // Attempt to allocate an object of the given (very large) "word_size". - // Returns "NULL" on failure. + // Initialize a contiguous set of free regions of length num_regions + // and starting at index first so that they appear as a single + // humongous region. + HeapWord* humongous_obj_allocate_initialize_regions(int first, + size_t num_regions, + size_t word_size); + + // Attempt to allocate a humongous object of the given size. Return + // NULL if unsuccessful. HeapWord* humongous_obj_allocate(size_t word_size); // The following two methods, allocate_new_tlab() and @@ -776,7 +774,7 @@ // Invoke "save_marks" on all heap regions. void save_marks(); - // It frees a non-humongous region by initializing its contents and + // Frees a non-humongous region by initializing its contents and // adding it to the free list that's passed as a parameter (this is // usually a local list which will be appended to the master free // list later). The used bytes of freed regions are accumulated in @@ -787,13 +785,13 @@ FreeRegionList* free_list, bool par); - // It frees a humongous region by collapsing it into individual - // regions and calling free_region() for each of them. The freed - // regions will be added to the free list that's passed as a parameter - // (this is usually a local list which will be appended to the - // master free list later). The used bytes of freed regions are - // accumulated in pre_used. If par is true, the region's RSet will - // not be freed up. The assumption is that this will be done later. + // Frees a humongous region by collapsing it into individual regions + // and calling free_region() for each of them. The freed regions + // will be added to the free list that's passed as a parameter (this + // is usually a local list which will be appended to the master free + // list later). The used bytes of freed regions are accumulated in + // pre_used. If par is true, the region's RSet will not be freed + // up. The assumption is that this will be done later. void free_humongous_region(HeapRegion* hr, size_t* pre_used, FreeRegionList* free_list, @@ -1046,13 +1044,13 @@ #endif // HEAP_REGION_SET_FORCE_VERIFY #ifdef ASSERT - bool is_on_free_list(HeapRegion* hr) { + bool is_on_master_free_list(HeapRegion* hr) { return hr->containing_set() == &_free_list; } - bool is_on_humongous_set(HeapRegion* hr) { + bool is_in_humongous_set(HeapRegion* hr) { return hr->containing_set() == &_humongous_set; -} + } #endif // ASSERT // Wrapper for the region list operations that can be called from @@ -1066,7 +1064,9 @@ _free_list.add_as_tail(&_secondary_free_list); } - void append_secondary_free_list_if_not_empty() { + void append_secondary_free_list_if_not_empty_with_lock() { + // If the secondary free list looks empty there's no reason to + // take the lock and then try to append it. if (!_secondary_free_list.is_empty()) { MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag); append_secondary_free_list(); diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -81,6 +81,57 @@ // +// Help class for avoiding interleaved logging +class LineBuffer: public StackObj { + +private: + static const int BUFFER_LEN = 1024; + static const int INDENT_CHARS = 3; + char _buffer[BUFFER_LEN]; + int _indent_level; + int _cur; + + void vappend(const char* format, va_list ap) { + int res = vsnprintf(&_buffer[_cur], BUFFER_LEN - _cur, format, ap); + if (res != -1) { + _cur += res; + } else { + DEBUG_ONLY(warning("buffer too small in LineBuffer");) + _buffer[BUFFER_LEN -1] = 0; + _cur = BUFFER_LEN; // vsnprintf above should not add to _buffer if we are called again + } + } + +public: + explicit LineBuffer(int indent_level): _indent_level(indent_level), _cur(0) { + for (; (_cur < BUFFER_LEN && _cur < (_indent_level * INDENT_CHARS)); _cur++) { + _buffer[_cur] = ' '; + } + } + +#ifndef PRODUCT + ~LineBuffer() { + assert(_cur == _indent_level * INDENT_CHARS, "pending data in buffer - append_and_print_cr() not called?"); + } +#endif + + void append(const char* format, ...) { + va_list ap; + va_start(ap, format); + vappend(format, ap); + va_end(ap); + } + + void append_and_print_cr(const char* format, ...) { + va_list ap; + va_start(ap, format); + vappend(format, ap); + va_end(ap); + gclog_or_tty->print_cr("%s", _buffer); + _cur = _indent_level * INDENT_CHARS; + } +}; + G1CollectorPolicy::G1CollectorPolicy() : _parallel_gc_threads(G1CollectedHeap::use_parallel_gc_threads() ? ParallelGCThreads : 1), @@ -1016,10 +1067,8 @@ bool summary) { double min = data[0], max = data[0]; double total = 0.0; - int j; - for (j = 0; j < level; ++j) - gclog_or_tty->print(" "); - gclog_or_tty->print("[%s (ms):", str); + LineBuffer buf(level); + buf.append("[%s (ms):", str); for (uint i = 0; i < ParallelGCThreads; ++i) { double val = data[i]; if (val < min) @@ -1027,18 +1076,16 @@ if (val > max) max = val; total += val; - gclog_or_tty->print(" %3.1lf", val); + buf.append(" %3.1lf", val); } if (summary) { - gclog_or_tty->print_cr(""); + buf.append_and_print_cr(""); double avg = total / (double) ParallelGCThreads; - gclog_or_tty->print(" "); - for (j = 0; j < level; ++j) - gclog_or_tty->print(" "); - gclog_or_tty->print("Avg: %5.1lf, Min: %5.1lf, Max: %5.1lf", + buf.append(" "); + buf.append("Avg: %5.1lf, Min: %5.1lf, Max: %5.1lf", avg, min, max); } - gclog_or_tty->print_cr("]"); + buf.append_and_print_cr("]"); } void G1CollectorPolicy::print_par_sizes(int level, @@ -1047,10 +1094,8 @@ bool summary) { double min = data[0], max = data[0]; double total = 0.0; - int j; - for (j = 0; j < level; ++j) - gclog_or_tty->print(" "); - gclog_or_tty->print("[%s :", str); + LineBuffer buf(level); + buf.append("[%s :", str); for (uint i = 0; i < ParallelGCThreads; ++i) { double val = data[i]; if (val < min) @@ -1058,34 +1103,28 @@ if (val > max) max = val; total += val; - gclog_or_tty->print(" %d", (int) val); + buf.append(" %d", (int) val); } if (summary) { - gclog_or_tty->print_cr(""); + buf.append_and_print_cr(""); double avg = total / (double) ParallelGCThreads; - gclog_or_tty->print(" "); - for (j = 0; j < level; ++j) - gclog_or_tty->print(" "); - gclog_or_tty->print("Sum: %d, Avg: %d, Min: %d, Max: %d", + buf.append(" "); + buf.append("Sum: %d, Avg: %d, Min: %d, Max: %d", (int)total, (int)avg, (int)min, (int)max); } - gclog_or_tty->print_cr("]"); + buf.append_and_print_cr("]"); } void G1CollectorPolicy::print_stats (int level, const char* str, double value) { - for (int j = 0; j < level; ++j) - gclog_or_tty->print(" "); - gclog_or_tty->print_cr("[%s: %5.1lf ms]", str, value); + LineBuffer(level).append_and_print_cr("[%s: %5.1lf ms]", str, value); } void G1CollectorPolicy::print_stats (int level, const char* str, int value) { - for (int j = 0; j < level; ++j) - gclog_or_tty->print(" "); - gclog_or_tty->print_cr("[%s: %d]", str, value); + LineBuffer(level).append_and_print_cr("[%s: %d]", str, value); } double G1CollectorPolicy::avg_value (double* data) { @@ -2060,17 +2099,11 @@ _g1->collection_set_iterate(&cs_closure); } -static void print_indent(int level) { - for (int j = 0; j < level+1; ++j) - gclog_or_tty->print(" "); -} - void G1CollectorPolicy::print_summary (int level, const char* str, NumberSeq* seq) const { double sum = seq->sum(); - print_indent(level); - gclog_or_tty->print_cr("%-24s = %8.2lf s (avg = %8.2lf ms)", + LineBuffer(level + 1).append_and_print_cr("%-24s = %8.2lf s (avg = %8.2lf ms)", str, sum / 1000.0, seq->avg()); } @@ -2078,8 +2111,7 @@ const char* str, NumberSeq* seq) const { print_summary(level, str, seq); - print_indent(level + 5); - gclog_or_tty->print_cr("(num = %5d, std dev = %8.2lf ms, max = %8.2lf ms)", + LineBuffer(level + 6).append_and_print_cr("(num = %5d, std dev = %8.2lf ms, max = %8.2lf ms)", seq->num(), seq->sd(), seq->maximum()); } @@ -2087,6 +2119,7 @@ NumberSeq* other_times_ms, NumberSeq* calc_other_times_ms) const { bool should_print = false; + LineBuffer buf(level + 2); double max_sum = MAX2(fabs(other_times_ms->sum()), fabs(calc_other_times_ms->sum())); @@ -2095,8 +2128,7 @@ double sum_ratio = max_sum / min_sum; if (sum_ratio > 1.1) { should_print = true; - print_indent(level + 1); - gclog_or_tty->print_cr("## CALCULATED OTHER SUM DOESN'T MATCH RECORDED ###"); + buf.append_and_print_cr("## CALCULATED OTHER SUM DOESN'T MATCH RECORDED ###"); } double max_avg = MAX2(fabs(other_times_ms->avg()), @@ -2106,30 +2138,25 @@ double avg_ratio = max_avg / min_avg; if (avg_ratio > 1.1) { should_print = true; - print_indent(level + 1); - gclog_or_tty->print_cr("## CALCULATED OTHER AVG DOESN'T MATCH RECORDED ###"); + buf.append_and_print_cr("## CALCULATED OTHER AVG DOESN'T MATCH RECORDED ###"); } if (other_times_ms->sum() < -0.01) { - print_indent(level + 1); - gclog_or_tty->print_cr("## RECORDED OTHER SUM IS NEGATIVE ###"); + buf.append_and_print_cr("## RECORDED OTHER SUM IS NEGATIVE ###"); } if (other_times_ms->avg() < -0.01) { - print_indent(level + 1); - gclog_or_tty->print_cr("## RECORDED OTHER AVG IS NEGATIVE ###"); + buf.append_and_print_cr("## RECORDED OTHER AVG IS NEGATIVE ###"); } if (calc_other_times_ms->sum() < -0.01) { should_print = true; - print_indent(level + 1); - gclog_or_tty->print_cr("## CALCULATED OTHER SUM IS NEGATIVE ###"); + buf.append_and_print_cr("## CALCULATED OTHER SUM IS NEGATIVE ###"); } if (calc_other_times_ms->avg() < -0.01) { should_print = true; - print_indent(level + 1); - gclog_or_tty->print_cr("## CALCULATED OTHER AVG IS NEGATIVE ###"); + buf.append_and_print_cr("## CALCULATED OTHER AVG IS NEGATIVE ###"); } if (should_print) @@ -2210,10 +2237,9 @@ } } } else { - print_indent(0); - gclog_or_tty->print_cr("none"); + LineBuffer(1).append_and_print_cr("none"); } - gclog_or_tty->print_cr(""); + LineBuffer(0).append_and_print_cr(""); } void G1CollectorPolicy::print_tracing_info() const { @@ -2532,7 +2558,7 @@ jint regions_added = parKnownGarbageCl.marked_regions_added(); _hrSorted->incNumMarkedHeapRegions(regions_added); if (G1PrintParCleanupStats) { - gclog_or_tty->print(" Thread %d called %d times, added %d regions to list.\n", + gclog_or_tty->print_cr(" Thread %d called %d times, added %d regions to list.", i, parKnownGarbageCl.invokes(), regions_added); } } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/gc_implementation/g1/g1MarkSweep.cpp --- a/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -185,22 +185,22 @@ G1CollectedHeap* _g1h; ModRefBarrierSet* _mrbs; CompactPoint _cp; - size_t _pre_used; - FreeRegionList _free_list; HumongousRegionSet _humongous_proxy_set; void free_humongous_region(HeapRegion* hr) { HeapWord* end = hr->end(); + size_t dummy_pre_used; + FreeRegionList dummy_free_list("Dummy Free List for G1MarkSweep"); + assert(hr->startsHumongous(), "Only the start of a humongous region should be freed."); - _g1h->free_humongous_region(hr, &_pre_used, &_free_list, + _g1h->free_humongous_region(hr, &dummy_pre_used, &dummy_free_list, &_humongous_proxy_set, false /* par */); - // Do we also need to do this for the continues humongous regions - // we just collapsed? hr->prepare_for_compaction(&_cp); // Also clear the part of the card table that will be unused after // compaction. _mrbs->clear(MemRegion(hr->compaction_top(), end)); + dummy_free_list.remove_all(); } public: @@ -208,8 +208,6 @@ : _g1h(G1CollectedHeap::heap()), _mrbs(G1CollectedHeap::heap()->mr_bs()), _cp(NULL, cs, cs->initialize_threshold()), - _pre_used(0), - _free_list("Local Free List for G1MarkSweep"), _humongous_proxy_set("G1MarkSweep Humongous Proxy Set") { } void update_sets() { @@ -219,7 +217,6 @@ NULL, /* free_list */ &_humongous_proxy_set, false /* par */); - _free_list.remove_all(); } bool doHeapRegion(HeapRegion* hr) { diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/gc_implementation/g1/g1RemSet.cpp --- a/src/share/vm/gc_implementation/g1/g1RemSet.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -86,28 +86,6 @@ bool idempotent() { return true; } }; -class IntoCSRegionClosure: public HeapRegionClosure { - IntoCSOopClosure _blk; - G1CollectedHeap* _g1; -public: - IntoCSRegionClosure(G1CollectedHeap* g1, OopsInHeapRegionClosure* blk) : - _g1(g1), _blk(g1, blk) {} - bool doHeapRegion(HeapRegion* r) { - if (!r->in_collection_set()) { - _blk.set_region(r); - if (r->isHumongous()) { - if (r->startsHumongous()) { - oop obj = oop(r->bottom()); - obj->oop_iterate(&_blk); - } - } else { - r->oop_before_save_marks_iterate(&_blk); - } - } - return false; - } -}; - class VerifyRSCleanCardOopClosure: public OopClosure { G1CollectedHeap* _g1; public: @@ -329,7 +307,7 @@ // is during RSet updating within an evacuation pause. // In this case worker_i should be the id of a GC worker thread. assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause"); - assert(worker_i < (int) DirtyCardQueueSet::num_par_ids(), "should be a GC worker"); + assert(worker_i < (int) (ParallelGCThreads == 0 ? 1 : ParallelGCThreads), "should be a GC worker"); if (_g1rs->concurrentRefineOneCard(card_ptr, worker_i, true)) { // 'card_ptr' contains references that point into the collection diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/gc_implementation/g1/heapRegion.hpp --- a/src/share/vm/gc_implementation/g1/heapRegion.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/heapRegion.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -53,8 +53,8 @@ class HeapRegionSetBase; #define HR_FORMAT "%d:["PTR_FORMAT","PTR_FORMAT","PTR_FORMAT"]" -#define HR_FORMAT_PARAMS(__hr) (__hr)->hrs_index(), (__hr)->bottom(), \ - (__hr)->top(), (__hr)->end() +#define HR_FORMAT_PARAMS(_hr_) (_hr_)->hrs_index(), (_hr_)->bottom(), \ + (_hr_)->top(), (_hr_)->end() // A dirty card to oop closure for heap regions. It // knows how to get the G1 heap and how to use the bitmap @@ -518,13 +518,13 @@ containing_set, _containing_set)); _containing_set = containing_set; -} + } HeapRegionSetBase* containing_set() { return _containing_set; } #else // ASSERT void set_containing_set(HeapRegionSetBase* containing_set) { } - // containing_set() is only used in asserts so there's not reason + // containing_set() is only used in asserts so there's no reason // to provide a dummy version of it. #endif // ASSERT @@ -535,14 +535,15 @@ bool pending_removal() { return _pending_removal; } void set_pending_removal(bool pending_removal) { - // We can only set pending_removal to true, if it's false and the - // region belongs to a set. - assert(!pending_removal || - (!_pending_removal && containing_set() != NULL), "pre-condition"); - // We can only set pending_removal to false, if it's true and the - // region does not belong to a set. - assert( pending_removal || - ( _pending_removal && containing_set() == NULL), "pre-condition"); + if (pending_removal) { + assert(!_pending_removal && containing_set() != NULL, + "can only set pending removal to true if it's false and " + "the region belongs to a region set"); + } else { + assert( _pending_removal && containing_set() == NULL, + "can only set pending removal to false if it's true and " + "the region does not belong to a region set"); + } _pending_removal = pending_removal; } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/gc_implementation/g1/heapRegionSeq.cpp --- a/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -165,7 +165,7 @@ assert(num_so_far <= num, "post-condition"); if (num_so_far == num) { - // we find enough space for the humongous object + // we found enough space for the humongous object assert(from <= first && first < _regions.length(), "post-condition"); assert(first < curr && (curr - first) == (int) num, "post-condition"); for (int i = first; i < first + (int) num; ++i) { diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/gc_implementation/g1/heapRegionSeq.hpp --- a/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -76,7 +76,8 @@ // that are available for allocation. size_t free_suffix(); - // Finds a contiguous set of empty regions of length num. + // Find a contiguous set of empty regions of length num and return + // the index of the first region or -1 if the search was unsuccessful. int find_contiguous(size_t num); // Apply the "doHeapRegion" method of "blk" to all regions in "this", diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/gc_implementation/g1/heapRegionSet.cpp --- a/src/share/vm/gc_implementation/g1/heapRegionSet.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/heapRegionSet.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -42,7 +42,7 @@ return region_num; } -void HeapRegionSetBase::fill_in_ext_msg(hrl_ext_msg* msg, const char* message) { +void HeapRegionSetBase::fill_in_ext_msg(hrs_ext_msg* msg, const char* message) { msg->append("[%s] %s " "ln: "SIZE_FORMAT" rn: "SIZE_FORMAT" " "cy: "SIZE_FORMAT" ud: "SIZE_FORMAT, @@ -109,30 +109,30 @@ // for the verification calls. If we do verification without the // appropriate locks and the set changes underneath our feet // verification might fail and send us on a wild goose chase. - hrl_assert_mt_safety_ok(this); + hrs_assert_mt_safety_ok(this); guarantee(( is_empty() && length() == 0 && region_num() == 0 && total_used_bytes() == 0 && total_capacity_bytes() == 0) || (!is_empty() && length() >= 0 && region_num() >= 0 && total_used_bytes() >= 0 && total_capacity_bytes() >= 0), - hrl_ext_msg(this, "invariant")); + hrs_ext_msg(this, "invariant")); guarantee((!regions_humongous() && region_num() == length()) || ( regions_humongous() && region_num() >= length()), - hrl_ext_msg(this, "invariant")); + hrs_ext_msg(this, "invariant")); guarantee(!regions_empty() || total_used_bytes() == 0, - hrl_ext_msg(this, "invariant")); + hrs_ext_msg(this, "invariant")); guarantee(total_used_bytes() <= total_capacity_bytes(), - hrl_ext_msg(this, "invariant")); + hrs_ext_msg(this, "invariant")); } void HeapRegionSetBase::verify_start() { // See comment in verify() about MT safety and verification. - hrl_assert_mt_safety_ok(this); + hrs_assert_mt_safety_ok(this); assert(!_verify_in_progress, - hrl_ext_msg(this, "verification should not be in progress")); + hrs_ext_msg(this, "verification should not be in progress")); // Do the basic verification first before we do the checks over the regions. HeapRegionSetBase::verify(); @@ -146,11 +146,11 @@ void HeapRegionSetBase::verify_next_region(HeapRegion* hr) { // See comment in verify() about MT safety and verification. - hrl_assert_mt_safety_ok(this); + hrs_assert_mt_safety_ok(this); assert(_verify_in_progress, - hrl_ext_msg(this, "verification should be in progress")); + hrs_ext_msg(this, "verification should be in progress")); - guarantee(verify_region(hr, this), hrl_ext_msg(this, "region verification")); + guarantee(verify_region(hr, this), hrs_ext_msg(this, "region verification")); _calc_length += 1; if (!hr->isHumongous()) { @@ -164,28 +164,28 @@ void HeapRegionSetBase::verify_end() { // See comment in verify() about MT safety and verification. - hrl_assert_mt_safety_ok(this); + hrs_assert_mt_safety_ok(this); assert(_verify_in_progress, - hrl_ext_msg(this, "verification should be in progress")); + hrs_ext_msg(this, "verification should be in progress")); guarantee(length() == _calc_length, - hrl_err_msg("[%s] length: "SIZE_FORMAT" should be == " + hrs_err_msg("[%s] length: "SIZE_FORMAT" should be == " "calc length: "SIZE_FORMAT, name(), length(), _calc_length)); guarantee(region_num() == _calc_region_num, - hrl_err_msg("[%s] region num: "SIZE_FORMAT" should be == " + hrs_err_msg("[%s] region num: "SIZE_FORMAT" should be == " "calc region num: "SIZE_FORMAT, name(), region_num(), _calc_region_num)); guarantee(total_capacity_bytes() == _calc_total_capacity_bytes, - hrl_err_msg("[%s] capacity bytes: "SIZE_FORMAT" should be == " + hrs_err_msg("[%s] capacity bytes: "SIZE_FORMAT" should be == " "calc capacity bytes: "SIZE_FORMAT, name(), total_capacity_bytes(), _calc_total_capacity_bytes)); guarantee(total_used_bytes() == _calc_total_used_bytes, - hrl_err_msg("[%s] used bytes: "SIZE_FORMAT" should be == " + hrs_err_msg("[%s] used bytes: "SIZE_FORMAT" should be == " "calc used bytes: "SIZE_FORMAT, name(), total_used_bytes(), _calc_total_used_bytes)); @@ -221,9 +221,9 @@ //////////////////// HeapRegionSet //////////////////// void HeapRegionSet::update_from_proxy(HeapRegionSet* proxy_set) { - hrl_assert_mt_safety_ok(this); - hrl_assert_mt_safety_ok(proxy_set); - hrl_assert_sets_match(this, proxy_set); + hrs_assert_mt_safety_ok(this); + hrs_assert_mt_safety_ok(proxy_set); + hrs_assert_sets_match(this, proxy_set); verify_optional(); proxy_set->verify_optional(); @@ -231,19 +231,19 @@ if (proxy_set->is_empty()) return; assert(proxy_set->length() <= _length, - hrl_err_msg("[%s] proxy set length: "SIZE_FORMAT" " + hrs_err_msg("[%s] proxy set length: "SIZE_FORMAT" " "should be <= length: "SIZE_FORMAT, name(), proxy_set->length(), _length)); _length -= proxy_set->length(); assert(proxy_set->region_num() <= _region_num, - hrl_err_msg("[%s] proxy set region num: "SIZE_FORMAT" " + hrs_err_msg("[%s] proxy set region num: "SIZE_FORMAT" " "should be <= region num: "SIZE_FORMAT, name(), proxy_set->region_num(), _region_num)); _region_num -= proxy_set->region_num(); assert(proxy_set->total_used_bytes() <= _total_used_bytes, - hrl_err_msg("[%s] proxy set used bytes: "SIZE_FORMAT" " + hrs_err_msg("[%s] proxy set used bytes: "SIZE_FORMAT" " "should be <= used bytes: "SIZE_FORMAT, name(), proxy_set->total_used_bytes(), _total_used_bytes)); @@ -257,13 +257,13 @@ //////////////////// HeapRegionLinkedList //////////////////// -void HeapRegionLinkedList::fill_in_ext_msg_extra(hrl_ext_msg* msg) { +void HeapRegionLinkedList::fill_in_ext_msg_extra(hrs_ext_msg* msg) { msg->append(" hd: "PTR_FORMAT" tl: "PTR_FORMAT, head(), tail()); } void HeapRegionLinkedList::add_as_tail(HeapRegionLinkedList* from_list) { - hrl_assert_mt_safety_ok(this); - hrl_assert_mt_safety_ok(from_list); + hrs_assert_mt_safety_ok(this); + hrs_assert_mt_safety_ok(from_list); verify_optional(); from_list->verify_optional(); @@ -283,10 +283,10 @@ #endif // ASSERT if (_tail != NULL) { - assert(length() > 0 && _head != NULL, hrl_ext_msg(this, "invariant")); + assert(length() > 0 && _head != NULL, hrs_ext_msg(this, "invariant")); _tail->set_next(from_list->_head); } else { - assert(length() == 0 && _head == NULL, hrl_ext_msg(this, "invariant")); + assert(length() == 0 && _head == NULL, hrs_ext_msg(this, "invariant")); _head = from_list->_head; } _tail = from_list->_tail; @@ -301,12 +301,12 @@ } void HeapRegionLinkedList::remove_all() { - hrl_assert_mt_safety_ok(this); + hrs_assert_mt_safety_ok(this); verify_optional(); HeapRegion* curr = _head; while (curr != NULL) { - hrl_assert_region_ok(this, curr, this); + hrs_assert_region_ok(this, curr, this); HeapRegion* next = curr->next(); curr->set_next(NULL); @@ -319,9 +319,9 @@ } void HeapRegionLinkedList::remove_all_pending(size_t target_count) { - hrl_assert_mt_safety_ok(this); - assert(target_count > 1, hrl_ext_msg(this, "pre-condition")); - assert(!is_empty(), hrl_ext_msg(this, "pre-condition")); + hrs_assert_mt_safety_ok(this); + assert(target_count > 1, hrs_ext_msg(this, "pre-condition")); + assert(!is_empty(), hrs_ext_msg(this, "pre-condition")); verify_optional(); DEBUG_ONLY(size_t old_length = length();) @@ -330,27 +330,27 @@ HeapRegion* prev = NULL; size_t count = 0; while (curr != NULL) { - hrl_assert_region_ok(this, curr, this); + hrs_assert_region_ok(this, curr, this); HeapRegion* next = curr->next(); if (curr->pending_removal()) { assert(count < target_count, - hrl_err_msg("[%s] should not come across more regions " + hrs_err_msg("[%s] should not come across more regions " "pending for removal than target_count: "SIZE_FORMAT, name(), target_count)); if (prev == NULL) { - assert(_head == curr, hrl_ext_msg(this, "invariant")); + assert(_head == curr, hrs_ext_msg(this, "invariant")); _head = next; } else { - assert(_head != curr, hrl_ext_msg(this, "invariant")); + assert(_head != curr, hrs_ext_msg(this, "invariant")); prev->set_next(next); } if (next == NULL) { - assert(_tail == curr, hrl_ext_msg(this, "invariant")); + assert(_tail == curr, hrs_ext_msg(this, "invariant")); _tail = prev; } else { - assert(_tail != curr, hrl_ext_msg(this, "invariant")); + assert(_tail != curr, hrs_ext_msg(this, "invariant")); } curr->set_next(NULL); @@ -371,10 +371,10 @@ } assert(count == target_count, - hrl_err_msg("[%s] count: "SIZE_FORMAT" should be == " + hrs_err_msg("[%s] count: "SIZE_FORMAT" should be == " "target_count: "SIZE_FORMAT, name(), count, target_count)); assert(length() + target_count == old_length, - hrl_err_msg("[%s] new length should be consistent " + hrs_err_msg("[%s] new length should be consistent " "new length: "SIZE_FORMAT" old length: "SIZE_FORMAT" " "target_count: "SIZE_FORMAT, name(), length(), old_length, target_count)); @@ -385,7 +385,7 @@ void HeapRegionLinkedList::verify() { // See comment in HeapRegionSetBase::verify() about MT safety and // verification. - hrl_assert_mt_safety_ok(this); + hrs_assert_mt_safety_ok(this); // This will also do the basic verification too. verify_start(); @@ -399,7 +399,7 @@ count += 1; guarantee(count < _unrealistically_long_length, - hrl_err_msg("[%s] the calculated length: "SIZE_FORMAT" " + hrs_err_msg("[%s] the calculated length: "SIZE_FORMAT" " "seems very long, is there maybe a cycle? " "curr: "PTR_FORMAT" prev0: "PTR_FORMAT" " "prev1: "PTR_FORMAT" length: "SIZE_FORMAT, @@ -410,7 +410,7 @@ curr = curr->next(); } - guarantee(_tail == prev0, hrl_ext_msg(this, "post-condition")); + guarantee(_tail == prev0, hrs_ext_msg(this, "post-condition")); verify_end(); } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/gc_implementation/g1/heapRegionSet.hpp --- a/src/share/vm/gc_implementation/g1/heapRegionSet.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/heapRegionSet.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -28,8 +28,8 @@ #include "gc_implementation/g1/heapRegion.hpp" // Large buffer for some cases where the output might be larger than normal. -#define HRL_ERR_MSG_BUFSZ 512 -typedef FormatBuffer hrl_err_msg; +#define HRS_ERR_MSG_BUFSZ 512 +typedef FormatBuffer hrs_err_msg; // Set verification will be forced either if someone defines // HEAP_REGION_SET_FORCE_VERIFY to be 1, or in builds in which @@ -45,10 +45,10 @@ // (e.g., length, region num, used bytes sum) plus any shared // functionality (e.g., verification). -class hrl_ext_msg; +class hrs_ext_msg; class HeapRegionSetBase VALUE_OBJ_CLASS_SPEC { - friend class hrl_ext_msg; + friend class hrs_ext_msg; protected: static size_t calculate_region_num(HeapRegion* hr); @@ -104,10 +104,10 @@ virtual bool check_mt_safety() { return true; } // fill_in_ext_msg() writes the the values of the set's attributes - // in the custom err_msg (hrl_ext_msg). fill_in_ext_msg_extra() + // in the custom err_msg (hrs_ext_msg). fill_in_ext_msg_extra() // allows subclasses to append further information. - virtual void fill_in_ext_msg_extra(hrl_ext_msg* msg) { } - void fill_in_ext_msg(hrl_ext_msg* msg, const char* message); + virtual void fill_in_ext_msg_extra(hrs_ext_msg* msg) { } + void fill_in_ext_msg(hrs_ext_msg* msg, const char* message); // It updates the fields of the set to reflect hr being added to // the set. @@ -170,9 +170,9 @@ // the fields of the associated set. This can be very helpful in // diagnosing failures. -class hrl_ext_msg : public hrl_err_msg { +class hrs_ext_msg : public hrs_err_msg { public: - hrl_ext_msg(HeapRegionSetBase* set, const char* message) : hrl_err_msg("") { + hrs_ext_msg(HeapRegionSetBase* set, const char* message) : hrs_err_msg("") { set->fill_in_ext_msg(this, message); } }; @@ -180,25 +180,25 @@ // These two macros are provided for convenience, to keep the uses of // these two asserts a bit more concise. -#define hrl_assert_mt_safety_ok(_set_) \ +#define hrs_assert_mt_safety_ok(_set_) \ do { \ - assert((_set_)->check_mt_safety(), hrl_ext_msg((_set_), "MT safety")); \ + assert((_set_)->check_mt_safety(), hrs_ext_msg((_set_), "MT safety")); \ } while (0) -#define hrl_assert_region_ok(_set_, _hr_, _expected_) \ +#define hrs_assert_region_ok(_set_, _hr_, _expected_) \ do { \ assert((_set_)->verify_region((_hr_), (_expected_)), \ - hrl_ext_msg((_set_), "region verification")); \ + hrs_ext_msg((_set_), "region verification")); \ } while (0) //////////////////// HeapRegionSet //////////////////// -#define hrl_assert_sets_match(_set1_, _set2_) \ +#define hrs_assert_sets_match(_set1_, _set2_) \ do { \ assert(((_set1_)->regions_humongous() == \ (_set2_)->regions_humongous()) && \ ((_set1_)->regions_empty() == (_set2_)->regions_empty()), \ - hrl_err_msg("the contents of set %s and set %s should match", \ + hrs_err_msg("the contents of set %s and set %s should match", \ (_set1_)->name(), (_set2_)->name())); \ } while (0) @@ -267,7 +267,7 @@ HeapRegion* tail() { return _tail; } protected: - virtual void fill_in_ext_msg_extra(hrl_ext_msg* msg); + virtual void fill_in_ext_msg_extra(hrs_ext_msg* msg); // See the comment for HeapRegionSetBase::clear() virtual void clear(); @@ -309,10 +309,10 @@ virtual void print_on(outputStream* out, bool print_contents = false); }; -//////////////////// HeapRegionLinkedList //////////////////// +//////////////////// HeapRegionLinkedListIterator //////////////////// -// Iterator class that provides a convenient way to iterator over the -// regions in a HeapRegionLinkedList instance. +// Iterator class that provides a convenient way to iterate over the +// regions of a HeapRegionLinkedList instance. class HeapRegionLinkedListIterator : public StackObj { private: diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp --- a/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -42,8 +42,8 @@ } inline void HeapRegionSetBase::add_internal(HeapRegion* hr) { - hrl_assert_region_ok(this, hr, NULL); - assert(hr->next() == NULL, hrl_ext_msg(this, "should not already be linked")); + hrs_assert_region_ok(this, hr, NULL); + assert(hr->next() == NULL, hrs_ext_msg(this, "should not already be linked")); update_for_addition(hr); hr->set_containing_set(this); @@ -51,7 +51,7 @@ inline void HeapRegionSetBase::update_for_removal(HeapRegion* hr) { // Assumes the caller has already verified the region. - assert(_length > 0, hrl_ext_msg(this, "pre-condition")); + assert(_length > 0, hrs_ext_msg(this, "pre-condition")); _length -= 1; size_t region_num_diff; @@ -61,22 +61,22 @@ region_num_diff = calculate_region_num(hr); } assert(region_num_diff <= _region_num, - hrl_err_msg("[%s] region's region num: "SIZE_FORMAT" " + hrs_err_msg("[%s] region's region num: "SIZE_FORMAT" " "should be <= region num: "SIZE_FORMAT, name(), region_num_diff, _region_num)); _region_num -= region_num_diff; size_t used_bytes = hr->used(); assert(used_bytes <= _total_used_bytes, - hrl_err_msg("[%s] region's used bytes: "SIZE_FORMAT" " + hrs_err_msg("[%s] region's used bytes: "SIZE_FORMAT" " "should be <= used bytes: "SIZE_FORMAT, name(), used_bytes, _total_used_bytes)); _total_used_bytes -= used_bytes; } inline void HeapRegionSetBase::remove_internal(HeapRegion* hr) { - hrl_assert_region_ok(this, hr, this); - assert(hr->next() == NULL, hrl_ext_msg(this, "should already be unlinked")); + hrs_assert_region_ok(this, hr, this); + assert(hr->next() == NULL, hrs_ext_msg(this, "should already be unlinked")); hr->set_containing_set(NULL); update_for_removal(hr); @@ -85,13 +85,13 @@ //////////////////// HeapRegionSet //////////////////// inline void HeapRegionSet::add(HeapRegion* hr) { - hrl_assert_mt_safety_ok(this); + hrs_assert_mt_safety_ok(this); // add_internal() will verify the region. add_internal(hr); } inline void HeapRegionSet::remove(HeapRegion* hr) { - hrl_assert_mt_safety_ok(this); + hrs_assert_mt_safety_ok(this); // remove_internal() will verify the region. remove_internal(hr); } @@ -101,8 +101,8 @@ // No need to fo the MT safety check here given that this method // does not update the contents of the set but instead accumulates // the changes in proxy_set which is assumed to be thread-local. - hrl_assert_sets_match(this, proxy_set); - hrl_assert_region_ok(this, hr, this); + hrs_assert_sets_match(this, proxy_set); + hrs_assert_region_ok(this, hr, this); hr->set_containing_set(NULL); proxy_set->update_for_addition(hr); @@ -111,10 +111,10 @@ //////////////////// HeapRegionLinkedList //////////////////// inline void HeapRegionLinkedList::add_as_tail(HeapRegion* hr) { - hrl_assert_mt_safety_ok(this); + hrs_assert_mt_safety_ok(this); assert((length() == 0 && _head == NULL && _tail == NULL) || (length() > 0 && _head != NULL && _tail != NULL), - hrl_ext_msg(this, "invariant")); + hrs_ext_msg(this, "invariant")); // add_internal() will verify the region. add_internal(hr); @@ -128,10 +128,10 @@ } inline HeapRegion* HeapRegionLinkedList::remove_head() { - hrl_assert_mt_safety_ok(this); - assert(!is_empty(), hrl_ext_msg(this, "the list should not be empty")); + hrs_assert_mt_safety_ok(this); + assert(!is_empty(), hrs_ext_msg(this, "the list should not be empty")); assert(length() > 0 && _head != NULL && _tail != NULL, - hrl_ext_msg(this, "invariant")); + hrs_ext_msg(this, "invariant")); // We need to unlink it first. HeapRegion* hr = _head; @@ -147,7 +147,7 @@ } inline HeapRegion* HeapRegionLinkedList::remove_head_or_null() { - hrl_assert_mt_safety_ok(this); + hrs_assert_mt_safety_ok(this); if (!is_empty()) { return remove_head(); diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/gc_implementation/g1/heapRegionSets.cpp --- a/src/share/vm/gc_implementation/g1/heapRegionSets.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/heapRegionSets.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -52,7 +52,7 @@ FreeList_lock->owned_by_self())) || (!SafepointSynchronize::is_at_safepoint() && Heap_lock->owned_by_self()), - hrl_ext_msg(this, "master free list MT safety protocol")); + hrs_ext_msg(this, "master free list MT safety protocol")); return FreeRegionList::check_mt_safety(); } @@ -65,7 +65,7 @@ // while holding the SecondaryFreeList_lock. guarantee(SecondaryFreeList_lock->owned_by_self(), - hrl_ext_msg(this, "secondary free list MT safety protocol")); + hrs_ext_msg(this, "secondary free list MT safety protocol")); return FreeRegionList::check_mt_safety(); } @@ -81,7 +81,7 @@ return HeapRegionSet::verify_region_extra(hr); } -//////////////////// HumongousRegionSet //////////////////// +//////////////////// MasterHumongousRegionSet //////////////////// bool MasterHumongousRegionSet::check_mt_safety() { // Master Humongous Set MT safety protocol: @@ -97,6 +97,6 @@ OldSets_lock->owned_by_self())) || (!SafepointSynchronize::is_at_safepoint() && Heap_lock->owned_by_self()), - hrl_ext_msg(this, "master humongous set MT safety protocol")); + hrs_ext_msg(this, "master humongous set MT safety protocol")); return HumongousRegionSet::check_mt_safety(); } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/gc_implementation/parNew/parNewGeneration.cpp --- a/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, 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 @@ -1530,13 +1530,15 @@ { if (_ref_processor == NULL) { // Allocate and initialize a reference processor - _ref_processor = ReferenceProcessor::create_ref_processor( - _reserved, // span - refs_discovery_is_atomic(), // atomic_discovery - refs_discovery_is_mt(), // mt_discovery - NULL, // is_alive_non_header - ParallelGCThreads, - ParallelRefProcEnabled); + _ref_processor = + new ReferenceProcessor(_reserved, // span + ParallelRefProcEnabled && (ParallelGCThreads > 1), // mt processing + (int) ParallelGCThreads, // mt processing degree + refs_discovery_is_mt(), // mt discovery + (int) ParallelGCThreads, // mt discovery degree + refs_discovery_is_atomic(), // atomic_discovery + NULL, // is_alive_non_header + false); // write barrier for next field updates } } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, 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 @@ -58,9 +58,7 @@ void PSMarkSweep::initialize() { MemRegion mr = Universe::heap()->reserved_region(); - _ref_processor = new ReferenceProcessor(mr, - true, // atomic_discovery - false); // mt_discovery + _ref_processor = new ReferenceProcessor(mr); // a vanilla ref proc _counters = new CollectorCounters("PSMarkSweep", 1); } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, 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 @@ -827,13 +827,15 @@ assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity"); MemRegion mr = heap->reserved_region(); - _ref_processor = ReferenceProcessor::create_ref_processor( - mr, // span - true, // atomic_discovery - true, // mt_discovery - &_is_alive_closure, - ParallelGCThreads, - ParallelRefProcEnabled); + _ref_processor = + new ReferenceProcessor(mr, // span + ParallelRefProcEnabled && (ParallelGCThreads > 1), // mt processing + (int) ParallelGCThreads, // mt processing degree + true, // mt discovery + (int) ParallelGCThreads, // mt discovery degree + true, // atomic_discovery + &_is_alive_closure, // non-header is alive closure + false); // write barrier for next field updates _counters = new CollectorCounters("PSParallelCompact", 1); // Initialize static fields in ParCompactionManager. diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -411,7 +411,7 @@ template void PSPromotionManager::process_array_chunk_work( oop obj, int start, int end) { - assert(start < end, "invariant"); + assert(start <= end, "invariant"); T* const base = (T*)objArrayOop(obj)->base(); T* p = base + start; T* const chunk_end = base + end; diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2011, 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 @@ -796,13 +796,15 @@ // Initialize ref handling object for scavenging. MemRegion mr = young_gen->reserved(); - _ref_processor = ReferenceProcessor::create_ref_processor( - mr, // span - true, // atomic_discovery - true, // mt_discovery - NULL, // is_alive_non_header - ParallelGCThreads, - ParallelRefProcEnabled); + _ref_processor = + new ReferenceProcessor(mr, // span + ParallelRefProcEnabled && (ParallelGCThreads > 1), // mt processing + (int) ParallelGCThreads, // mt processing degree + true, // mt discovery + (int) ParallelGCThreads, // mt discovery degree + true, // atomic_discovery + NULL, // header provides liveness info + false); // next field updates do not need write barrier // Cache the cardtable BarrierSet* bs = Universe::heap()->barrier_set(); diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/interpreter/abstractInterpreter.hpp --- a/src/share/vm/interpreter/abstractInterpreter.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/interpreter/abstractInterpreter.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -96,7 +96,7 @@ empty, // empty method (code: _return) accessor, // accessor method (code: _aload_0, _getfield, _(a|i)return) abstract, // abstract method (throws an AbstractMethodException) - method_handle, // java.dyn.MethodHandles::invoke + method_handle, // java.lang.invoke.MethodHandles::invoke java_lang_math_sin, // implementation of java.lang.Math.sin (x) java_lang_math_cos, // implementation of java.lang.Math.cos (x) java_lang_math_tan, // implementation of java.lang.Math.tan (x) diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/interpreter/interpreterRuntime.cpp --- a/src/share/vm/interpreter/interpreterRuntime.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/interpreter/interpreterRuntime.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -369,7 +369,10 @@ } // create exception - THROW_MSG(vmSymbols::java_dyn_WrongMethodTypeException(), message); + Symbol* java_lang_invoke_WrongMethodTypeException = vmSymbols::java_lang_invoke_WrongMethodTypeException(); + if (AllowTransitionalJSR292) + java_lang_invoke_WrongMethodTypeException = SystemDictionaryHandles::WrongMethodTypeException_klass()->name(); + THROW_MSG(java_lang_invoke_WrongMethodTypeException, message); } IRT_END @@ -794,7 +797,7 @@ Handle info; // optional argument(s) in JVM_CONSTANT_InvokeDynamic Handle bootm = SystemDictionary::find_bootstrap_method(caller_method, caller_bci, main_index, info, CHECK); - if (!java_dyn_MethodHandle::is_instance(bootm())) { + if (!java_lang_invoke_MethodHandle::is_instance(bootm())) { THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "no bootstrap method found for invokedynamic"); } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/interpreter/linkResolver.cpp --- a/src/share/vm/interpreter/linkResolver.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/interpreter/linkResolver.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -217,11 +217,13 @@ if (EnableMethodHandles && klass() == SystemDictionary::MethodHandle_klass() && methodOopDesc::is_method_handle_invoke_name(name)) { - if (!MethodHandles::enabled()) { + if (!THREAD->is_Compiler_thread() && !MethodHandles::enabled()) { // Make sure the Java part of the runtime has been booted up. klassOop natives = SystemDictionary::MethodHandleNatives_klass(); if (natives == NULL || instanceKlass::cast(natives)->is_not_initialized()) { - SystemDictionary::resolve_or_fail(vmSymbols::sun_dyn_MethodHandleNatives(), + Symbol* natives_name = vmSymbols::java_lang_invoke_MethodHandleNatives(); + if (natives != NULL && AllowTransitionalJSR292) natives_name = Klass::cast(natives)->name(); + SystemDictionary::resolve_or_fail(natives_name, Handle(), Handle(), true, @@ -298,7 +300,7 @@ } void LinkResolver::resolve_dynamic_method(methodHandle& resolved_method, KlassHandle& resolved_klass, constantPoolHandle pool, int index, TRAPS) { - // The class is java.dyn.MethodHandle + // The class is java.lang.invoke.MethodHandle resolved_klass = SystemDictionaryHandles::MethodHandle_klass(); Symbol* method_name = vmSymbols::invokeExact_name(); diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/memory/collectorPolicy.cpp --- a/src/share/vm/memory/collectorPolicy.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/memory/collectorPolicy.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, 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 @@ -293,10 +293,11 @@ // Determine maximum size of gen0 size_t max_new_size = 0; - if (FLAG_IS_CMDLINE(MaxNewSize)) { + if (FLAG_IS_CMDLINE(MaxNewSize) || FLAG_IS_ERGO(MaxNewSize)) { if (MaxNewSize < min_alignment()) { max_new_size = min_alignment(); - } else if (MaxNewSize >= max_heap_byte_size()) { + } + if (MaxNewSize >= max_heap_byte_size()) { max_new_size = align_size_down(max_heap_byte_size() - min_alignment(), min_alignment()); warning("MaxNewSize (" SIZE_FORMAT "k) is equal to or " @@ -333,7 +334,7 @@ assert(max_new_size > 0, "All paths should set max_new_size"); // Given the maximum gen0 size, determine the initial and - // minimum sizes. + // minimum gen0 sizes. if (max_heap_byte_size() == min_heap_byte_size()) { // The maximum and minimum heap sizes are the same so @@ -396,7 +397,7 @@ } if (PrintGCDetails && Verbose) { - gclog_or_tty->print_cr("Minimum gen0 " SIZE_FORMAT " Initial gen0 " + gclog_or_tty->print_cr("1: Minimum gen0 " SIZE_FORMAT " Initial gen0 " SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT, min_gen0_size(), initial_gen0_size(), max_gen0_size()); } @@ -448,7 +449,7 @@ // At this point the minimum, initial and maximum sizes // of the overall heap and of gen0 have been determined. // The maximum gen1 size can be determined from the maximum gen0 - // and maximum heap size since not explicit flags exits + // and maximum heap size since no explicit flags exits // for setting the gen1 maximum. _max_gen1_size = max_heap_byte_size() - _max_gen0_size; _max_gen1_size = @@ -494,13 +495,13 @@ "generation sizes: using maximum heap = " SIZE_FORMAT " -XX:OldSize flag is being ignored", max_heap_byte_size()); - } + } // If there is an inconsistency between the OldSize and the minimum and/or // initial size of gen0, since OldSize was explicitly set, OldSize wins. if (adjust_gen0_sizes(&_min_gen0_size, &_min_gen1_size, min_heap_byte_size(), OldSize)) { if (PrintGCDetails && Verbose) { - gclog_or_tty->print_cr("Minimum gen0 " SIZE_FORMAT " Initial gen0 " + gclog_or_tty->print_cr("2: Minimum gen0 " SIZE_FORMAT " Initial gen0 " SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT, min_gen0_size(), initial_gen0_size(), max_gen0_size()); } @@ -509,7 +510,7 @@ if (adjust_gen0_sizes(&_initial_gen0_size, &_initial_gen1_size, initial_heap_byte_size(), OldSize)) { if (PrintGCDetails && Verbose) { - gclog_or_tty->print_cr("Minimum gen0 " SIZE_FORMAT " Initial gen0 " + gclog_or_tty->print_cr("3: Minimum gen0 " SIZE_FORMAT " Initial gen0 " SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT, min_gen0_size(), initial_gen0_size(), max_gen0_size()); } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/memory/generation.cpp --- a/src/share/vm/memory/generation.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/memory/generation.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -83,14 +83,11 @@ } // By default we get a single threaded default reference processor; -// generations needing multi-threaded refs discovery override this method. +// generations needing multi-threaded refs processing or discovery override this method. void Generation::ref_processor_init() { assert(_ref_processor == NULL, "a reference processor already exists"); assert(!_reserved.is_empty(), "empty generation?"); - _ref_processor = - new ReferenceProcessor(_reserved, // span - refs_discovery_is_atomic(), // atomic_discovery - refs_discovery_is_mt()); // mt_discovery + _ref_processor = new ReferenceProcessor(_reserved); // a vanilla reference processor if (_ref_processor == NULL) { vm_exit_during_initialization("Could not allocate ReferenceProcessor object"); } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/memory/heap.cpp --- a/src/share/vm/memory/heap.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/memory/heap.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -316,12 +316,19 @@ } size_t CodeHeap::largest_free_block() const { + // First check unused space excluding free blocks. + size_t free_sz = size(_free_segments); + size_t unused = max_capacity() - allocated_capacity() - free_sz; + if (unused >= free_sz) + return unused; + + // Now check largest free block. size_t len = 0; for (FreeBlock* b = _freelist; b != NULL; b = b->link()) { if (b->length() > len) len = b->length(); } - return size(len); + return MAX2(unused, size(len)); } // Free list management diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/memory/referenceProcessor.cpp --- a/src/share/vm/memory/referenceProcessor.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/memory/referenceProcessor.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, 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 @@ -102,40 +102,17 @@ "Unrecongnized RefDiscoveryPolicy"); } -ReferenceProcessor* -ReferenceProcessor::create_ref_processor(MemRegion span, - bool atomic_discovery, - bool mt_discovery, - BoolObjectClosure* is_alive_non_header, - int parallel_gc_threads, - bool mt_processing, - bool dl_needs_barrier) { - int mt_degree = 1; - if (parallel_gc_threads > 1) { - mt_degree = parallel_gc_threads; - } - ReferenceProcessor* rp = - new ReferenceProcessor(span, atomic_discovery, - mt_discovery, mt_degree, - mt_processing && (parallel_gc_threads > 0), - dl_needs_barrier); - if (rp == NULL) { - vm_exit_during_initialization("Could not allocate ReferenceProcessor object"); - } - rp->set_is_alive_non_header(is_alive_non_header); - rp->setup_policy(false /* default soft ref policy */); - return rp; -} - ReferenceProcessor::ReferenceProcessor(MemRegion span, - bool atomic_discovery, + bool mt_processing, + int mt_processing_degree, bool mt_discovery, - int mt_degree, - bool mt_processing, + int mt_discovery_degree, + bool atomic_discovery, + BoolObjectClosure* is_alive_non_header, bool discovered_list_needs_barrier) : _discovering_refs(false), _enqueuing_is_done(false), - _is_alive_non_header(NULL), + _is_alive_non_header(is_alive_non_header), _discovered_list_needs_barrier(discovered_list_needs_barrier), _bs(NULL), _processing_is_mt(mt_processing), @@ -144,8 +121,8 @@ _span = span; _discovery_is_atomic = atomic_discovery; _discovery_is_mt = mt_discovery; - _num_q = mt_degree; - _max_num_q = mt_degree; + _num_q = MAX2(1, mt_processing_degree); + _max_num_q = MAX2(_num_q, mt_discovery_degree); _discoveredSoftRefs = NEW_C_HEAP_ARRAY(DiscoveredList, _max_num_q * subclasses_of_ref); if (_discoveredSoftRefs == NULL) { vm_exit_during_initialization("Could not allocated RefProc Array"); @@ -163,6 +140,7 @@ if (discovered_list_needs_barrier) { _bs = Universe::heap()->barrier_set(); } + setup_policy(false /* default soft ref policy */); } #ifndef PRODUCT @@ -405,15 +383,14 @@ { } virtual void work(unsigned int work_id) { - assert(work_id < (unsigned int)_ref_processor.num_q(), "Index out-of-bounds"); + assert(work_id < (unsigned int)_ref_processor.max_num_q(), "Index out-of-bounds"); // Simplest first cut: static partitioning. int index = work_id; // The increment on "index" must correspond to the maximum number of queues // (n_queues) with which that ReferenceProcessor was created. That // is because of the "clever" way the discovered references lists were - // allocated and are indexed into. That number is ParallelGCThreads - // currently. Assert that. - assert(_n_queues == (int) ParallelGCThreads, "Different number not expected"); + // allocated and are indexed into. + assert(_n_queues == (int) _ref_processor.max_num_q(), "Different number not expected"); for (int j = 0; j < subclasses_of_ref; j++, index += _n_queues) { @@ -672,7 +649,7 @@ } } NOT_PRODUCT( - if (PrintGCDetails && TraceReferenceGC) { + if (PrintGCDetails && TraceReferenceGC && (iter.processed() > 0)) { gclog_or_tty->print_cr(" Dropped %d active Refs out of %d " "Refs in discovered list " INTPTR_FORMAT, iter.removed(), iter.processed(), (address)refs_list.head()); @@ -711,7 +688,7 @@ // Now close the newly reachable set complete_gc->do_void(); NOT_PRODUCT( - if (PrintGCDetails && TraceReferenceGC) { + if (PrintGCDetails && TraceReferenceGC && (iter.processed() > 0)) { gclog_or_tty->print_cr(" Dropped %d active Refs out of %d " "Refs in discovered list " INTPTR_FORMAT, iter.removed(), iter.processed(), (address)refs_list.head()); @@ -951,7 +928,7 @@ } if (PrintReferenceGC && PrintGCDetails) { size_t total = 0; - for (int i = 0; i < _num_q; ++i) { + for (int i = 0; i < _max_num_q; ++i) { total += refs_lists[i].length(); } gclog_or_tty->print(", %u refs", total); @@ -967,7 +944,7 @@ RefProcPhase1Task phase1(*this, refs_lists, policy, true /*marks_oops_alive*/); task_executor->execute(phase1); } else { - for (int i = 0; i < _num_q; i++) { + for (int i = 0; i < _max_num_q; i++) { process_phase1(refs_lists[i], policy, is_alive, keep_alive, complete_gc); } @@ -983,7 +960,7 @@ RefProcPhase2Task phase2(*this, refs_lists, !discovery_is_atomic() /*marks_oops_alive*/); task_executor->execute(phase2); } else { - for (int i = 0; i < _num_q; i++) { + for (int i = 0; i < _max_num_q; i++) { process_phase2(refs_lists[i], is_alive, keep_alive, complete_gc); } } @@ -994,7 +971,7 @@ RefProcPhase3Task phase3(*this, refs_lists, clear_referent, true /*marks_oops_alive*/); task_executor->execute(phase3); } else { - for (int i = 0; i < _num_q; i++) { + for (int i = 0; i < _max_num_q; i++) { process_phase3(refs_lists[i], clear_referent, is_alive, keep_alive, complete_gc); } @@ -1008,7 +985,7 @@ // for (int j = 0; j < _num_q; j++) { // int index = i * _max_num_q + j; for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) { - if (TraceReferenceGC && PrintGCDetails && ((i % _num_q) == 0)) { + if (TraceReferenceGC && PrintGCDetails && ((i % _max_num_q) == 0)) { gclog_or_tty->print_cr( "\nScrubbing %s discovered list of Null referents", list_name(i)); @@ -1350,7 +1327,7 @@ { TraceTime tt("Preclean WeakReferences", PrintGCDetails && PrintReferenceGC, false, gclog_or_tty); - for (int i = 0; i < _num_q; i++) { + for (int i = 0; i < _max_num_q; i++) { if (yield->should_return()) { return; } @@ -1363,7 +1340,7 @@ { TraceTime tt("Preclean FinalReferences", PrintGCDetails && PrintReferenceGC, false, gclog_or_tty); - for (int i = 0; i < _num_q; i++) { + for (int i = 0; i < _max_num_q; i++) { if (yield->should_return()) { return; } @@ -1376,7 +1353,7 @@ { TraceTime tt("Preclean PhantomReferences", PrintGCDetails && PrintReferenceGC, false, gclog_or_tty); - for (int i = 0; i < _num_q; i++) { + for (int i = 0; i < _max_num_q; i++) { if (yield->should_return()) { return; } @@ -1433,7 +1410,7 @@ complete_gc->do_void(); NOT_PRODUCT( - if (PrintGCDetails && PrintReferenceGC) { + if (PrintGCDetails && PrintReferenceGC && (iter.processed() > 0)) { gclog_or_tty->print_cr(" Dropped %d Refs out of %d " "Refs in discovered list " INTPTR_FORMAT, iter.removed(), iter.processed(), (address)refs_list.head()); diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/memory/referenceProcessor.hpp --- a/src/share/vm/memory/referenceProcessor.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/memory/referenceProcessor.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, 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 @@ -71,7 +71,7 @@ bool _enqueuing_is_done; // true if all weak references enqueued bool _processing_is_mt; // true during phases when // reference processing is MT. - int _next_id; // round-robin counter in + int _next_id; // round-robin mod _num_q counter in // support of work distribution // For collectors that do not keep GC marking information @@ -103,7 +103,8 @@ public: int num_q() { return _num_q; } - void set_mt_degree(int v) { _num_q = v; } + int max_num_q() { return _max_num_q; } + void set_active_mt_degree(int v) { _num_q = v; } DiscoveredList* discovered_soft_refs() { return _discoveredSoftRefs; } static oop sentinel_ref() { return _sentinelRef; } static oop* adr_sentinel_ref() { return &_sentinelRef; } @@ -216,6 +217,7 @@ VoidClosure* complete_gc, YieldClosure* yield); + // round-robin mod _num_q (not: _not_ mode _max_num_q) int next_id() { int id = _next_id; if (++_next_id == _num_q) { @@ -256,23 +258,15 @@ _max_num_q(0), _processing_is_mt(false), _next_id(0) - {} - - ReferenceProcessor(MemRegion span, bool atomic_discovery, - bool mt_discovery, - int mt_degree = 1, - bool mt_processing = false, - bool discovered_list_needs_barrier = false); + { } - // Allocates and initializes a reference processor. - static ReferenceProcessor* create_ref_processor( - MemRegion span, - bool atomic_discovery, - bool mt_discovery, - BoolObjectClosure* is_alive_non_header = NULL, - int parallel_gc_threads = 1, - bool mt_processing = false, - bool discovered_list_needs_barrier = false); + // Default parameters give you a vanilla reference processor. + ReferenceProcessor(MemRegion span, + bool mt_processing = false, int mt_processing_degree = 1, + bool mt_discovery = false, int mt_discovery_degree = 1, + bool atomic_discovery = true, + BoolObjectClosure* is_alive_non_header = NULL, + bool discovered_list_needs_barrier = false); // RefDiscoveryPolicy values enum DiscoveryPolicy { @@ -397,20 +391,20 @@ // A utility class to temporarily change the MT'ness of // reference discovery for the given ReferenceProcessor // in the scope that contains it. -class ReferenceProcessorMTMutator: StackObj { +class ReferenceProcessorMTDiscoveryMutator: StackObj { private: ReferenceProcessor* _rp; bool _saved_mt; public: - ReferenceProcessorMTMutator(ReferenceProcessor* rp, - bool mt): + ReferenceProcessorMTDiscoveryMutator(ReferenceProcessor* rp, + bool mt): _rp(rp) { _saved_mt = _rp->discovery_is_mt(); _rp->set_mt_discovery(mt); } - ~ReferenceProcessorMTMutator() { + ~ReferenceProcessorMTDiscoveryMutator() { _rp->set_mt_discovery(_saved_mt); } }; diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/oops/constantPoolOop.cpp --- a/src/share/vm/oops/constantPoolOop.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/oops/constantPoolOop.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1175,8 +1175,15 @@ case JVM_CONSTANT_UnresolvedClass: { - Symbol* k = from_cp->unresolved_klass_at(from_i); - to_cp->unresolved_klass_at_put(to_i, k); + // Can be resolved after checking tag, so check the slot first. + CPSlot entry = from_cp->slot_at(from_i); + if (entry.is_oop()) { + assert(entry.get_oop()->is_klass(), "must be"); + // Already resolved + to_cp->klass_at_put(to_i, (klassOop)entry.get_oop()); + } else { + to_cp->unresolved_klass_at_put(to_i, entry.get_symbol()); + } } break; case JVM_CONSTANT_UnresolvedClassInError: @@ -1189,8 +1196,14 @@ case JVM_CONSTANT_UnresolvedString: { - Symbol* s = from_cp->unresolved_string_at(from_i); - to_cp->unresolved_string_at_put(to_i, s); + // Can be resolved after checking tag, so check the slot first. + CPSlot entry = from_cp->slot_at(from_i); + if (entry.is_oop()) { + // Already resolved (either string or pseudo-string) + to_cp->string_at_put(to_i, entry.get_oop()); + } else { + to_cp->unresolved_string_at_put(to_i, entry.get_symbol()); + } } break; case JVM_CONSTANT_Utf8: diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/oops/cpCacheOop.hpp --- a/src/share/vm/oops/cpCacheOop.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/oops/cpCacheOop.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -190,7 +190,7 @@ ); void set_dynamic_call( - Handle call_site, // Resolved java.dyn.CallSite (f1) + Handle call_site, // Resolved java.lang.invoke.CallSite (f1) methodHandle signature_invoker // determines signature information ); diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/oops/instanceKlass.cpp --- a/src/share/vm/oops/instanceKlass.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/oops/instanceKlass.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -735,7 +735,12 @@ static int call_class_initializer_impl_counter = 0; // for debugging methodOop instanceKlass::class_initializer() { - return find_method(vmSymbols::class_initializer_name(), vmSymbols::void_method_signature()); + methodOop clinit = find_method( + vmSymbols::class_initializer_name(), vmSymbols::void_method_signature()); + if (clinit != NULL && clinit->has_valid_initializer_flags()) { + return clinit; + } + return NULL; } void instanceKlass::call_class_initializer_impl(instanceKlassHandle this_oop, TRAPS) { @@ -2415,7 +2420,7 @@ st->cr(); } else if (as_klassOop() == SystemDictionary::MethodType_klass()) { st->print(BULLET"signature: "); - java_dyn_MethodType::print_signature(obj, st); + java_lang_invoke_MethodType::print_signature(obj, st); st->cr(); } } @@ -2446,7 +2451,7 @@ } } else if (as_klassOop() == SystemDictionary::MethodType_klass()) { st->print(" = "); - java_dyn_MethodType::print_signature(obj, st); + java_lang_invoke_MethodType::print_signature(obj, st); } else if (java_lang_boxing_object::is_instance(obj)) { st->print(" = "); java_lang_boxing_object::print(obj, st); diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/oops/instanceKlass.hpp --- a/src/share/vm/oops/instanceKlass.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/oops/instanceKlass.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -193,8 +193,8 @@ typeArrayOop _inner_classes; // Implementors of this interface (not valid if it overflows) klassOop _implementors[implementors_limit]; - // invokedynamic bootstrap method (a java.dyn.MethodHandle) - oop _bootstrap_method; + // invokedynamic bootstrap method (a java.lang.invoke.MethodHandle) + oop _bootstrap_method; // AllowTransitionalJSR292 ONLY // Annotations for this class, or null if none. typeArrayOop _class_annotations; // Annotation objects (byte arrays) for fields, or null if no annotations. @@ -529,7 +529,7 @@ _enclosing_method_method_index = method_index; } // JSR 292 support - oop bootstrap_method() const { return _bootstrap_method; } + oop bootstrap_method() const { return _bootstrap_method; } // AllowTransitionalJSR292 ONLY void set_bootstrap_method(oop mh) { oop_store(&_bootstrap_method, mh); } // jmethodID support @@ -817,7 +817,7 @@ 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_bootstrap_method() const { return (oop*)&this->_bootstrap_method;} + oop* adr_bootstrap_method() const { return (oop*)&this->_bootstrap_method;} // AllowTransitionalJSR292 ONLY 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 fc1b183bfc0a -r e97ad5d5c990 src/share/vm/oops/klassVtable.cpp --- a/src/share/vm/oops/klassVtable.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/oops/klassVtable.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -883,7 +883,7 @@ int ime_num = 0; // Skip first methodOop if it is a class initializer - int i = ((methodOop)methods()->obj_at(0))->name() != vmSymbols::class_initializer_name() ? 0 : 1; + int i = ((methodOop)methods()->obj_at(0))->is_static_initializer() ? 1 : 0; // m, method_name, method_signature, klass reset each loop so they // don't need preserving across check_signature_loaders call @@ -1121,7 +1121,7 @@ assert(index < methods->length(), "should find index for resolve_invoke"); } // Adjust for , which is left out of table if first method - if (methods->length() > 0 && ((methodOop)methods->obj_at(0))->name() == vmSymbols::class_initializer_name()) { + if (methods->length() > 0 && ((methodOop)methods->obj_at(0))->is_static_initializer()) { index--; } return index; @@ -1135,7 +1135,7 @@ int index = itable_index; // Adjust for , which is left out of table if first method - if (methods->length() > 0 && ((methodOop)methods->obj_at(0))->name() == vmSymbols::class_initializer_name()) { + if (methods->length() > 0 && ((methodOop)methods->obj_at(0))->is_static_initializer()) { index++; } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/oops/methodDataOop.hpp --- a/src/share/vm/oops/methodDataOop.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/oops/methodDataOop.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -228,7 +228,7 @@ return byte_offset_of(DataLayout, _header._struct._bci); } static ByteSize cell_offset(int index) { - return byte_offset_of(DataLayout, _cells[index]); + return byte_offset_of(DataLayout, _cells) + in_ByteSize(index * cell_size); } // Return a value which, when or-ed as a byte into _flags, sets the flag. static int flag_number_to_byte_constant(int flag_number) { diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/oops/methodKlass.cpp --- a/src/share/vm/oops/methodKlass.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/oops/methodKlass.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -103,6 +103,12 @@ m->backedge_counter()->init(); m->clear_number_of_breakpoints(); +#ifdef TIERED + m->set_rate(0); + m->set_prev_event_count(0); + m->set_prev_time(0); +#endif + assert(m->is_parsable(), "must be parsable here."); assert(m->size() == size, "wrong size for object"); // We should not publish an uprasable object's reference diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/oops/methodOop.cpp --- a/src/share/vm/oops/methodOop.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/oops/methodOop.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -466,7 +466,20 @@ bool methodOopDesc::is_initializer() const { - return name() == vmSymbols::object_initializer_name() || name() == vmSymbols::class_initializer_name(); + return name() == vmSymbols::object_initializer_name() || is_static_initializer(); +} + +bool methodOopDesc::has_valid_initializer_flags() const { + return (is_static() || + instanceKlass::cast(method_holder())->major_version() < 51); +} + +bool methodOopDesc::is_static_initializer() const { + // For classfiles version 51 or greater, ensure that the clinit method is + // static. Non-static methods with the name "" are not static + // initializers. (older classfiles exempted for backward compatibility) + return name() == vmSymbols::class_initializer_name() && + has_valid_initializer_flags(); } @@ -842,7 +855,7 @@ case vmSymbols::VM_SYMBOL_ENUM_NAME(invokeGeneric_name): return true; } - if (AllowTransitionalJSR292 + if ((AllowTransitionalJSR292 || AllowInvokeForInvokeGeneric) && name_sid == vmSymbols::VM_SYMBOL_ENUM_NAME(invoke_name)) return true; return false; @@ -852,7 +865,7 @@ enum { _imcp_invoke_name = 1, // utf8: 'invokeExact' or 'invokeGeneric' _imcp_invoke_signature, // utf8: (variable Symbol*) - _imcp_method_type_value, // string: (variable java/dyn/MethodType, sic) + _imcp_method_type_value, // string: (variable java/lang/invoke/MethodType, sic) _imcp_limit }; @@ -1078,7 +1091,8 @@ vmSymbols::SID name_id = vmSymbols::find_sid(name()); if (name_id == vmSymbols::NO_SID) return; vmSymbols::SID sig_id = vmSymbols::find_sid(signature()); - if (klass_id != vmSymbols::VM_SYMBOL_ENUM_NAME(java_dyn_MethodHandle) + if (klass_id != vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_MethodHandle) + && !(klass_id == vmSymbols::VM_SYMBOL_ENUM_NAME(java_dyn_MethodHandle) && AllowTransitionalJSR292) && sig_id == vmSymbols::NO_SID) return; jshort flags = access_flags().as_short(); @@ -1104,7 +1118,8 @@ break; // Signature-polymorphic methods: MethodHandle.invoke*, InvokeDynamic.*. - case vmSymbols::VM_SYMBOL_ENUM_NAME(java_dyn_MethodHandle): + case vmSymbols::VM_SYMBOL_ENUM_NAME(java_dyn_MethodHandle): // AllowTransitionalJSR292 ONLY + case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_MethodHandle): if (is_static() || !is_native()) break; switch (name_id) { case vmSymbols::VM_SYMBOL_ENUM_NAME(invokeGeneric_name): @@ -1114,11 +1129,12 @@ id = vmIntrinsics::_invokeExact; break; case vmSymbols::VM_SYMBOL_ENUM_NAME(invoke_name): - if (AllowTransitionalJSR292) id = vmIntrinsics::_invokeExact; + if (AllowInvokeForInvokeGeneric) id = vmIntrinsics::_invokeGeneric; + else if (AllowTransitionalJSR292) id = vmIntrinsics::_invokeExact; break; } break; - case vmSymbols::VM_SYMBOL_ENUM_NAME(java_dyn_InvokeDynamic): + case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_InvokeDynamic): if (!is_static() || !is_native()) break; id = vmIntrinsics::_invokeDynamic; break; diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/oops/methodOop.hpp --- a/src/share/vm/oops/methodOop.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/oops/methodOop.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -84,6 +84,11 @@ // | invocation_counter | // | backedge_counter | // |------------------------------------------------------| +// | prev_time (tiered only, 64 bit wide) | +// | | +// |------------------------------------------------------| +// | rate (tiered) | +// |------------------------------------------------------| // | code (pointer) | // | i2i (pointer) | // | adapter (pointer) | @@ -124,6 +129,11 @@ InvocationCounter _invocation_counter; // Incremented before each activation of the method - used to trigger frequency-based optimizations InvocationCounter _backedge_counter; // Incremented before each backedge taken - used to trigger frequencey-based optimizations +#ifdef TIERED + jlong _prev_time; // Previous time the rate was acquired + float _rate; // Events (invocation and backedge counter increments) per millisecond +#endif + #ifndef PRODUCT int _compiled_invocation_count; // Number of nmethod invocations so far (for perf. debugging) #endif @@ -304,6 +314,17 @@ InvocationCounter* invocation_counter() { return &_invocation_counter; } InvocationCounter* backedge_counter() { return &_backedge_counter; } +#ifdef TIERED + // We are reusing interpreter_invocation_count as a holder for the previous event count! + // We can do that since interpreter_invocation_count is not used in tiered. + int prev_event_count() const { return _interpreter_invocation_count; } + void set_prev_event_count(int count) { _interpreter_invocation_count = count; } + jlong prev_time() const { return _prev_time; } + void set_prev_time(jlong time) { _prev_time = time; } + float rate() const { return _rate; } + void set_rate(float rate) { _rate = rate; } +#endif + int invocation_count(); int backedge_count(); @@ -497,6 +518,13 @@ // returns true if the method is an initializer ( or ). bool is_initializer() const; + // returns true if the method is static OR if the classfile version < 51 + bool has_valid_initializer_flags() const; + + // returns true if the method name is and the method has + // valid static initializer flags. + bool is_static_initializer() const; + // compiled code support // NOTE: code() is inherently racy as deopt can be clearing code // simultaneously. Use with caution. diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/opto/bytecodeInfo.cpp --- a/src/share/vm/opto/bytecodeInfo.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/opto/bytecodeInfo.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2011, 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 @@ -487,7 +487,7 @@ if (caller_jvms->method()->is_method_handle_adapter()) new_depth_adjust -= 1; // don't count actions in MH or indy adapter frames else if (callee_method->is_method_handle_invoke()) { - new_depth_adjust -= 1; // don't count method handle calls from java.dyn implem + new_depth_adjust -= 1; // don't count method handle calls from java.lang.invoke implem } if (new_depth_adjust != 0 && PrintInlining) { stringStream nm1; caller_jvms->method()->print_name(&nm1); diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/opto/callGenerator.cpp --- a/src/share/vm/opto/callGenerator.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/opto/callGenerator.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, 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 @@ -199,7 +199,7 @@ Node* call_site = kit.make_load(kit.control(), call_site_adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw); // Load the target MethodHandle from the CallSite object. - Node* target_mh_adr = kit.basic_plus_adr(call_site, call_site, java_dyn_CallSite::target_offset_in_bytes()); + Node* target_mh_adr = kit.basic_plus_adr(call_site, call_site, java_lang_invoke_CallSite::target_offset_in_bytes()); Node* target_mh = kit.make_load(kit.control(), target_mh_adr, TypeInstPtr::BOTTOM, T_OBJECT); address resolve_stub = SharedRuntime::get_resolve_opt_virtual_call_stub(); @@ -725,7 +725,7 @@ Node* call_site = kit.make_load(kit.control(), call_site_adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw); // Load the target MethodHandle from the CallSite object. - Node* target_adr = kit.basic_plus_adr(call_site, call_site, java_dyn_CallSite::target_offset_in_bytes()); + Node* target_adr = kit.basic_plus_adr(call_site, call_site, java_lang_invoke_CallSite::target_offset_in_bytes()); Node* target_mh = kit.make_load(kit.control(), target_adr, TypeInstPtr::BOTTOM, T_OBJECT); // Check if the MethodHandle is still the same. diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/opto/output.cpp --- a/src/share/vm/opto/output.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/opto/output.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1028,7 +1028,7 @@ // helper for Fill_buffer bailout logic static void turn_off_compiler(Compile* C) { - if (CodeCache::unallocated_capacity() >= CodeCacheMinimumFreeSpace*10) { + if (CodeCache::largest_free_block() >= CodeCacheMinimumFreeSpace*10) { // Do not turn off compilation if a single giant method has // blown the code cache size. C->record_failure("excessive request to CodeCache"); diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/opto/parse3.cpp --- a/src/share/vm/opto/parse3.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/opto/parse3.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2011, 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 @@ -143,8 +143,8 @@ return; } else { - // final non-static field of a trusted class ({java,sun}.dyn - // classes). + // final non-static field of a trusted class (classes in + // java.lang.invoke and sun.invoke packages and subpackages). if (obj->is_Con()) { const TypeOopPtr* oop_ptr = obj->bottom_type()->isa_oopptr(); ciObject* constant_oop = oop_ptr->const_oop(); diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/opto/type.cpp --- a/src/share/vm/opto/type.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/opto/type.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -3386,7 +3386,22 @@ instance_id = InstanceBot; tary = TypeAry::make(Type::BOTTOM, tary->_size); } + } else // Non integral arrays. + // Must fall to bottom if exact klasses in upper lattice + // are not equal or super klass is exact. + if ( above_centerline(ptr) && klass() != tap->klass() && + // meet with top[] and bottom[] are processed further down: + tap ->_klass != NULL && this->_klass != NULL && + // both are exact and not equal: + ((tap ->_klass_is_exact && this->_klass_is_exact) || + // 'tap' is exact and super or unrelated: + (tap ->_klass_is_exact && !tap->klass()->is_subtype_of(klass())) || + // 'this' is exact and super or unrelated: + (this->_klass_is_exact && !klass()->is_subtype_of(tap->klass())))) { + tary = TypeAry::make(Type::BOTTOM, tary->_size); + return make( NotNull, NULL, tary, lazy_klass, false, off, InstanceBot ); } + bool xk = false; switch (tap->ptr()) { case AnyNull: @@ -3766,7 +3781,7 @@ // Oops, need to compute _klass and cache it ciKlass* k_ary = compute_klass(); - if( this != TypeAryPtr::OOPS ) { + if( this != TypeAryPtr::OOPS && this->dual() != TypeAryPtr::OOPS ) { // The _klass field acts as a cache of the underlying // ciKlass for this array type. In order to set the field, // we need to cast away const-ness. diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/prims/jvmtiImpl.cpp --- a/src/share/vm/prims/jvmtiImpl.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/prims/jvmtiImpl.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -919,15 +919,24 @@ nmethod* nm) { JvmtiDeferredEvent event = JvmtiDeferredEvent(TYPE_COMPILED_METHOD_LOAD); event._event_data.compiled_method_load = nm; - nmethodLocker::lock_nmethod(nm); // will be unlocked when posted + // Keep the nmethod alive until the ServiceThread can process + // this deferred event. + nmethodLocker::lock_nmethod(nm); return event; } JvmtiDeferredEvent JvmtiDeferredEvent::compiled_method_unload_event( - jmethodID id, const void* code) { + nmethod* nm, jmethodID id, const void* code) { JvmtiDeferredEvent event = JvmtiDeferredEvent(TYPE_COMPILED_METHOD_UNLOAD); + event._event_data.compiled_method_unload.nm = nm; event._event_data.compiled_method_unload.method_id = id; event._event_data.compiled_method_unload.code_begin = code; + // Keep the nmethod alive until the ServiceThread can process + // this deferred event. This will keep the memory for the + // generated code from being reused too early. We pass + // zombie_ok == true here so that our nmethod that was just + // made into a zombie can be locked. + nmethodLocker::lock_nmethod(nm, true /* zombie_ok */); return event; } JvmtiDeferredEvent JvmtiDeferredEvent::dynamic_code_generated_event( @@ -946,14 +955,19 @@ case TYPE_COMPILED_METHOD_LOAD: { nmethod* nm = _event_data.compiled_method_load; JvmtiExport::post_compiled_method_load(nm); + // done with the deferred event so unlock the nmethod nmethodLocker::unlock_nmethod(nm); break; } - case TYPE_COMPILED_METHOD_UNLOAD: + case TYPE_COMPILED_METHOD_UNLOAD: { + nmethod* nm = _event_data.compiled_method_unload.nm; JvmtiExport::post_compiled_method_unload( _event_data.compiled_method_unload.method_id, _event_data.compiled_method_unload.code_begin); + // done with the deferred event so unlock the nmethod + nmethodLocker::unlock_nmethod(nm); break; + } case TYPE_DYNAMIC_CODE_GENERATED: JvmtiExport::post_dynamic_code_generated_internal( _event_data.dynamic_code_generated.name, diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/prims/jvmtiImpl.hpp --- a/src/share/vm/prims/jvmtiImpl.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/prims/jvmtiImpl.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -458,6 +458,7 @@ union { nmethod* compiled_method_load; struct { + nmethod* nm; jmethodID method_id; const void* code_begin; } compiled_method_unload; @@ -477,7 +478,7 @@ // Factory methods static JvmtiDeferredEvent compiled_method_load_event(nmethod* nm) KERNEL_RETURN_(JvmtiDeferredEvent()); - static JvmtiDeferredEvent compiled_method_unload_event( + static JvmtiDeferredEvent compiled_method_unload_event(nmethod* nm, jmethodID id, const void* code) KERNEL_RETURN_(JvmtiDeferredEvent()); static JvmtiDeferredEvent dynamic_code_generated_event( const char* name, const void* begin, const void* end) diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/prims/jvmtiRedefineClasses.cpp --- a/src/share/vm/prims/jvmtiRedefineClasses.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1084,7 +1084,10 @@ jbyte old_tag = old_cp->tag_at(old_i).value(); switch (old_tag) { case JVM_CONSTANT_Class: + case JVM_CONSTANT_UnresolvedClass: // revert the copy to JVM_CONSTANT_UnresolvedClass + // May be resolving while calling this so do the same for + // JVM_CONSTANT_UnresolvedClass (klass_name_at() deals with transition) (*merge_cp_p)->unresolved_klass_at_put(old_i, old_cp->klass_name_at(old_i)); break; diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/prims/methodHandleWalk.cpp --- a/src/share/vm/prims/methodHandleWalk.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/prims/methodHandleWalk.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -36,7 +36,7 @@ // MethodHandleChain void MethodHandleChain::set_method_handle(Handle mh, TRAPS) { - if (!java_dyn_MethodHandle::is_instance(mh())) lose("bad method handle", CHECK); + if (!java_lang_invoke_MethodHandle::is_instance(mh())) lose("bad method handle", CHECK); // set current method handle and unpack partially _method_handle = mh; @@ -47,21 +47,21 @@ _conversion = -1; _last_invoke = Bytecodes::_nop; //arbitrary non-garbage - if (sun_dyn_DirectMethodHandle::is_instance(mh())) { + if (java_lang_invoke_DirectMethodHandle::is_instance(mh())) { set_last_method(mh(), THREAD); return; } - if (sun_dyn_AdapterMethodHandle::is_instance(mh())) { + if (java_lang_invoke_AdapterMethodHandle::is_instance(mh())) { _conversion = AdapterMethodHandle_conversion(); assert(_conversion != -1, "bad conv value"); - assert(sun_dyn_BoundMethodHandle::is_instance(mh()), "also BMH"); + assert(java_lang_invoke_BoundMethodHandle::is_instance(mh()), "also BMH"); } - if (sun_dyn_BoundMethodHandle::is_instance(mh())) { + if (java_lang_invoke_BoundMethodHandle::is_instance(mh())) { if (!is_adapter()) // keep AMH and BMH separate in this model _is_bound = true; _arg_slot = BoundMethodHandle_vmargslot(); oop target = MethodHandle_vmtarget_oop(); - if (!is_bound() || java_dyn_MethodHandle::is_instance(target)) { + if (!is_bound() || java_lang_invoke_MethodHandle::is_instance(target)) { _arg_type = compute_bound_arg_type(target, NULL, _arg_slot, CHECK); } else if (target != NULL && target->is_method()) { methodOop m = (methodOop) target; @@ -100,13 +100,12 @@ BasicType MethodHandleChain::compute_bound_arg_type(oop target, methodOop m, int arg_slot, TRAPS) { // There is no direct indication of whether the argument is primitive or not. // It is implied by the _vmentry code, and by the MethodType of the target. - // FIXME: Make it explicit MethodHandleImpl refactors out from MethodHandle BasicType arg_type = T_VOID; if (target != NULL) { - oop mtype = java_dyn_MethodHandle::type(target); + oop mtype = java_lang_invoke_MethodHandle::type(target); int arg_num = MethodHandles::argument_slot_to_argnum(mtype, arg_slot); if (arg_num >= 0) { - oop ptype = java_dyn_MethodType::ptype(mtype, arg_num); + oop ptype = java_lang_invoke_MethodType::ptype(mtype, arg_num); arg_type = java_lang_Class::as_BasicType(ptype); } } else if (m != NULL) { @@ -205,28 +204,28 @@ int arg_slot = chain().adapter_arg_slot(); SlotState* arg_state = slot_state(arg_slot); if (arg_state == NULL - && conv_op > sun_dyn_AdapterMethodHandle::OP_RETYPE_RAW) { + && conv_op > java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW) { lose("bad argument index", CHECK_(empty)); } // perform the adapter action switch (chain().adapter_conversion_op()) { - case sun_dyn_AdapterMethodHandle::OP_RETYPE_ONLY: + case java_lang_invoke_AdapterMethodHandle::OP_RETYPE_ONLY: // No changes to arguments; pass the bits through. break; - case sun_dyn_AdapterMethodHandle::OP_RETYPE_RAW: { + case java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW: { // To keep the verifier happy, emit bitwise ("raw") conversions as needed. // See MethodHandles::same_basic_type_for_arguments for allowed conversions. Handle incoming_mtype(THREAD, chain().method_type_oop()); oop outgoing_mh_oop = chain().vmtarget_oop(); - if (!java_dyn_MethodHandle::is_instance(outgoing_mh_oop)) + if (!java_lang_invoke_MethodHandle::is_instance(outgoing_mh_oop)) lose("outgoing target not a MethodHandle", CHECK_(empty)); - Handle outgoing_mtype(THREAD, java_dyn_MethodHandle::type(outgoing_mh_oop)); + Handle outgoing_mtype(THREAD, java_lang_invoke_MethodHandle::type(outgoing_mh_oop)); outgoing_mh_oop = NULL; // GC safety - int nptypes = java_dyn_MethodType::ptype_count(outgoing_mtype()); - if (nptypes != java_dyn_MethodType::ptype_count(incoming_mtype())) + int nptypes = java_lang_invoke_MethodType::ptype_count(outgoing_mtype()); + if (nptypes != java_lang_invoke_MethodType::ptype_count(incoming_mtype())) lose("incoming and outgoing parameter count do not agree", CHECK_(empty)); for (int i = 0, slot = _outgoing.length() - 1; slot >= 0; slot--) { @@ -236,8 +235,8 @@ klassOop in_klass = NULL; klassOop out_klass = NULL; - BasicType inpbt = java_lang_Class::as_BasicType(java_dyn_MethodType::ptype(incoming_mtype(), i), &in_klass); - BasicType outpbt = java_lang_Class::as_BasicType(java_dyn_MethodType::ptype(outgoing_mtype(), i), &out_klass); + BasicType inpbt = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::ptype(incoming_mtype(), i), &in_klass); + BasicType outpbt = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::ptype(outgoing_mtype(), i), &out_klass); assert(inpbt == arg.basic_type(), "sanity"); if (inpbt != outpbt) { @@ -255,8 +254,8 @@ i++; // We need to skip void slots at the top of the loop. } - BasicType inrbt = java_lang_Class::as_BasicType(java_dyn_MethodType::rtype(incoming_mtype())); - BasicType outrbt = java_lang_Class::as_BasicType(java_dyn_MethodType::rtype(outgoing_mtype())); + BasicType inrbt = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::rtype(incoming_mtype())); + BasicType outrbt = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::rtype(outgoing_mtype())); if (inrbt != outrbt) { if (inrbt == T_INT && outrbt == T_VOID) { // See comments in MethodHandles::same_basic_type_for_arguments. @@ -268,7 +267,7 @@ break; } - case sun_dyn_AdapterMethodHandle::OP_CHECK_CAST: { + case java_lang_invoke_AdapterMethodHandle::OP_CHECK_CAST: { // checkcast the Nth outgoing argument in place klassOop dest_klass = NULL; BasicType dest = java_lang_Class::as_BasicType(chain().adapter_arg_oop(), &dest_klass); @@ -281,7 +280,7 @@ break; } - case sun_dyn_AdapterMethodHandle::OP_PRIM_TO_PRIM: { + case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_PRIM: { // i2l, etc., on the Nth outgoing argument in place BasicType src = chain().adapter_conversion_src_type(), dest = chain().adapter_conversion_dest_type(); @@ -306,7 +305,7 @@ break; } - case sun_dyn_AdapterMethodHandle::OP_REF_TO_PRIM: { + case java_lang_invoke_AdapterMethodHandle::OP_REF_TO_PRIM: { // checkcast to wrapper type & call intValue, etc. BasicType dest = chain().adapter_conversion_dest_type(); ArgToken arg = arg_state->_arg; @@ -324,7 +323,7 @@ break; } - case sun_dyn_AdapterMethodHandle::OP_PRIM_TO_REF: { + case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_REF: { // call wrapper type.valueOf BasicType src = chain().adapter_conversion_src_type(); ArgToken arg = arg_state->_arg; @@ -340,7 +339,7 @@ break; } - case sun_dyn_AdapterMethodHandle::OP_SWAP_ARGS: { + case java_lang_invoke_AdapterMethodHandle::OP_SWAP_ARGS: { int dest_arg_slot = chain().adapter_conversion_vminfo(); if (!slot_has_argument(dest_arg_slot)) { lose("bad swap index", CHECK_(empty)); @@ -353,7 +352,7 @@ break; } - case sun_dyn_AdapterMethodHandle::OP_ROT_ARGS: { + case java_lang_invoke_AdapterMethodHandle::OP_ROT_ARGS: { int dest_arg_slot = chain().adapter_conversion_vminfo(); if (!slot_has_argument(dest_arg_slot) || arg_slot == dest_arg_slot) { lose("bad rotate index", CHECK_(empty)); @@ -379,7 +378,7 @@ break; } - case sun_dyn_AdapterMethodHandle::OP_DUP_ARGS: { + case java_lang_invoke_AdapterMethodHandle::OP_DUP_ARGS: { int dup_slots = chain().adapter_conversion_stack_pushes(); if (dup_slots <= 0) { lose("bad dup count", CHECK_(empty)); @@ -393,7 +392,7 @@ break; } - case sun_dyn_AdapterMethodHandle::OP_DROP_ARGS: { + case java_lang_invoke_AdapterMethodHandle::OP_DROP_ARGS: { int drop_slots = -chain().adapter_conversion_stack_pushes(); if (drop_slots <= 0) { lose("bad drop count", CHECK_(empty)); @@ -407,12 +406,12 @@ break; } - case sun_dyn_AdapterMethodHandle::OP_COLLECT_ARGS: { //NYI, may GC + case java_lang_invoke_AdapterMethodHandle::OP_COLLECT_ARGS: { //NYI, may GC lose("unimplemented", CHECK_(empty)); break; } - case sun_dyn_AdapterMethodHandle::OP_SPREAD_ARGS: { + case java_lang_invoke_AdapterMethodHandle::OP_SPREAD_ARGS: { klassOop array_klass_oop = NULL; BasicType array_type = java_lang_Class::as_BasicType(chain().adapter_arg_oop(), &array_klass_oop); @@ -470,8 +469,8 @@ break; } - case sun_dyn_AdapterMethodHandle::OP_FLYBY: //NYI, runs Java code - case sun_dyn_AdapterMethodHandle::OP_RICOCHET: //NYI, runs Java code + case java_lang_invoke_AdapterMethodHandle::OP_FLYBY: //NYI, runs Java code + case java_lang_invoke_AdapterMethodHandle::OP_RICOCHET: //NYI, runs Java code lose("unimplemented", CHECK_(empty)); break; @@ -533,7 +532,7 @@ // void MethodHandleWalker::walk_incoming_state(TRAPS) { Handle mtype(THREAD, chain().method_type_oop()); - int nptypes = java_dyn_MethodType::ptype_count(mtype()); + int nptypes = java_lang_invoke_MethodType::ptype_count(mtype()); _outgoing_argc = nptypes; int argp = nptypes - 1; if (argp >= 0) { @@ -542,7 +541,7 @@ for (int i = 0; i < nptypes; i++) { klassOop arg_type_klass = NULL; BasicType arg_type = java_lang_Class::as_BasicType( - java_dyn_MethodType::ptype(mtype(), i), &arg_type_klass); + java_lang_invoke_MethodType::ptype(mtype(), i), &arg_type_klass); int index = new_local_index(arg_type); ArgToken arg = make_parameter(arg_type, arg_type_klass, index, CHECK); debug_only(arg_type_klass = (klassOop) NULL); @@ -556,7 +555,7 @@ // call make_parameter at the end of the list for the return type klassOop ret_type_klass = NULL; BasicType ret_type = java_lang_Class::as_BasicType( - java_dyn_MethodType::rtype(mtype()), &ret_type_klass); + java_lang_invoke_MethodType::rtype(mtype()), &ret_type_klass); ArgToken ret = make_parameter(ret_type, ret_type_klass, -1, CHECK); // ignore ret; client can catch it if needed } @@ -631,7 +630,7 @@ // Get return type klass. Handle first_mtype(THREAD, chain().method_type_oop()); // _rklass is NULL for primitives. - _rtype = java_lang_Class::as_BasicType(java_dyn_MethodType::rtype(first_mtype()), &_rklass); + _rtype = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::rtype(first_mtype()), &_rklass); if (_rtype == T_ARRAY) _rtype = T_OBJECT; int params = _callee->size_of_parameters(); // Incoming arguments plus receiver. @@ -960,6 +959,16 @@ if (m == NULL) { // Get the intrinsic methodOop. m = vmIntrinsics::method_for(iid); + if (m == NULL && iid == vmIntrinsics::_checkSpreadArgument && AllowTransitionalJSR292) { + m = vmIntrinsics::method_for(vmIntrinsics::_checkSpreadArgument_TRANS); + if (m == NULL) + // sun.dyn.MethodHandleImpl not found, look for java.dyn.MethodHandleNatives: + m = vmIntrinsics::method_for(vmIntrinsics::_checkSpreadArgument_TRANS2); + } + if (m == NULL) { + ArgToken zero; + lose(vmIntrinsics::name_at(iid), CHECK_(zero)); + } } klassOop klass = m->method_holder(); @@ -1396,7 +1405,7 @@ void print_method_handle(oop mh) { if (!mh->is_oop()) { tty->print_cr("*** not a method handle: "INTPTR_FORMAT, (intptr_t)mh); - } else if (java_dyn_MethodHandle::is_instance(mh)) { + } else if (java_lang_invoke_MethodHandle::is_instance(mh)) { //MethodHandlePrinter::print(mh); } else { tty->print("*** not a method handle: "); diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/prims/methodHandleWalk.hpp --- a/src/share/vm/prims/methodHandleWalk.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/prims/methodHandleWalk.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2011, 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 @@ -48,13 +48,13 @@ void set_last_method(oop target, TRAPS); static BasicType compute_bound_arg_type(oop target, methodOop m, int arg_slot, TRAPS); - oop MethodHandle_type_oop() { return java_dyn_MethodHandle::type(method_handle_oop()); } - oop MethodHandle_vmtarget_oop() { return java_dyn_MethodHandle::vmtarget(method_handle_oop()); } - int MethodHandle_vmslots() { return java_dyn_MethodHandle::vmslots(method_handle_oop()); } - int DirectMethodHandle_vmindex() { return sun_dyn_DirectMethodHandle::vmindex(method_handle_oop()); } - oop BoundMethodHandle_argument_oop() { return sun_dyn_BoundMethodHandle::argument(method_handle_oop()); } - int BoundMethodHandle_vmargslot() { return sun_dyn_BoundMethodHandle::vmargslot(method_handle_oop()); } - int AdapterMethodHandle_conversion() { return sun_dyn_AdapterMethodHandle::conversion(method_handle_oop()); } + oop MethodHandle_type_oop() { return java_lang_invoke_MethodHandle::type(method_handle_oop()); } + oop MethodHandle_vmtarget_oop() { return java_lang_invoke_MethodHandle::vmtarget(method_handle_oop()); } + int MethodHandle_vmslots() { return java_lang_invoke_MethodHandle::vmslots(method_handle_oop()); } + int DirectMethodHandle_vmindex() { return java_lang_invoke_DirectMethodHandle::vmindex(method_handle_oop()); } + oop BoundMethodHandle_argument_oop() { return java_lang_invoke_BoundMethodHandle::argument(method_handle_oop()); } + int BoundMethodHandle_vmargslot() { return java_lang_invoke_BoundMethodHandle::vmargslot(method_handle_oop()); } + int AdapterMethodHandle_conversion() { return java_lang_invoke_AdapterMethodHandle::conversion(method_handle_oop()); } public: MethodHandleChain(Handle root, TRAPS) diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/prims/methodHandles.cpp --- a/src/share/vm/prims/methodHandles.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/prims/methodHandles.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -163,9 +163,9 @@ // or it may use the klass/index form; both forms mean the same thing. methodOop m = decode_methodOop(methodOop(vmtarget), decode_flags_result); if ((decode_flags_result & _dmf_has_receiver) != 0 - && java_dyn_MethodType::is_instance(mtype)) { + && java_lang_invoke_MethodType::is_instance(mtype)) { // Extract receiver type restriction from mtype.ptypes[0]. - objArrayOop ptypes = java_dyn_MethodType::ptypes(mtype); + objArrayOop ptypes = java_lang_invoke_MethodType::ptypes(mtype); oop ptype0 = (ptypes == NULL || ptypes->length() < 1) ? oop(NULL) : ptypes->obj_at(0); if (java_lang_Class::is_instance(ptype0)) receiver_limit_result = java_lang_Class::as_klassOop(ptype0); @@ -199,18 +199,18 @@ // (MemberName is the non-operational name used for queries and setup.) methodOop MethodHandles::decode_DirectMethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result) { - oop vmtarget = sun_dyn_DirectMethodHandle::vmtarget(mh); - int vmindex = sun_dyn_DirectMethodHandle::vmindex(mh); - oop mtype = sun_dyn_DirectMethodHandle::type(mh); + oop vmtarget = java_lang_invoke_DirectMethodHandle::vmtarget(mh); + int vmindex = java_lang_invoke_DirectMethodHandle::vmindex(mh); + oop mtype = java_lang_invoke_DirectMethodHandle::type(mh); return decode_vmtarget(vmtarget, vmindex, mtype, receiver_limit_result, decode_flags_result); } methodOop MethodHandles::decode_BoundMethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result) { - assert(sun_dyn_BoundMethodHandle::is_instance(mh), ""); + assert(java_lang_invoke_BoundMethodHandle::is_instance(mh), ""); assert(mh->klass() != SystemDictionary::AdapterMethodHandle_klass(), ""); for (oop bmh = mh;;) { // Bound MHs can be stacked to bind several arguments. - oop target = java_dyn_MethodHandle::vmtarget(bmh); + oop target = java_lang_invoke_MethodHandle::vmtarget(bmh); if (target == NULL) return NULL; decode_flags_result |= MethodHandles::_dmf_binds_argument; klassOop tk = target->klass(); @@ -218,7 +218,7 @@ bmh = target; continue; } else { - if (java_dyn_MethodHandle::is_subclass(tk)) { + if (java_lang_invoke_MethodHandle::is_subclass(tk)) { //assert(tk == SystemDictionary::DirectMethodHandle_klass(), "end of BMH chain must be DMH"); return decode_MethodHandle(target, receiver_limit_result, decode_flags_result); } else { @@ -240,9 +240,9 @@ assert(mh->klass() == SystemDictionary::AdapterMethodHandle_klass(), ""); for (oop amh = mh;;) { // Adapter MHs can be stacked to convert several arguments. - int conv_op = adapter_conversion_op(sun_dyn_AdapterMethodHandle::conversion(amh)); + int conv_op = adapter_conversion_op(java_lang_invoke_AdapterMethodHandle::conversion(amh)); decode_flags_result |= (_dmf_adapter_lsb << conv_op) & _DMF_ADAPTER_MASK; - oop target = java_dyn_MethodHandle::vmtarget(amh); + oop target = java_lang_invoke_MethodHandle::vmtarget(amh); if (target == NULL) return NULL; klassOop tk = target->klass(); if (tk == SystemDictionary::AdapterMethodHandle_klass()) { @@ -258,14 +258,14 @@ methodOop MethodHandles::decode_MethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result) { if (mh == NULL) return NULL; klassOop mhk = mh->klass(); - assert(java_dyn_MethodHandle::is_subclass(mhk), "must be a MethodHandle"); + assert(java_lang_invoke_MethodHandle::is_subclass(mhk), "must be a MethodHandle"); if (mhk == SystemDictionary::DirectMethodHandle_klass()) { return decode_DirectMethodHandle(mh, receiver_limit_result, decode_flags_result); } else if (mhk == SystemDictionary::BoundMethodHandle_klass()) { return decode_BoundMethodHandle(mh, receiver_limit_result, decode_flags_result); } else if (mhk == SystemDictionary::AdapterMethodHandle_klass()) { return decode_AdapterMethodHandle(mh, receiver_limit_result, decode_flags_result); - } else if (sun_dyn_BoundMethodHandle::is_subclass(mhk)) { + } else if (java_lang_invoke_BoundMethodHandle::is_subclass(mhk)) { // could be a JavaMethodHandle (but not an adapter MH) return decode_BoundMethodHandle(mh, receiver_limit_result, decode_flags_result); } else { @@ -308,7 +308,7 @@ } else if (xk == SystemDictionary::MemberName_klass()) { // Note: This only works if the MemberName has already been resolved. return decode_MemberName(x, receiver_limit_result, decode_flags_result); - } else if (java_dyn_MethodHandle::is_subclass(xk)) { + } else if (java_lang_invoke_MethodHandle::is_subclass(xk)) { return decode_MethodHandle(x, receiver_limit_result, decode_flags_result); } else if (xk == SystemDictionary::reflect_Method_klass()) { oop clazz = java_lang_reflect_Method::clazz(x); @@ -327,7 +327,7 @@ } else { // unrecognized object assert(!x->is_method(), "already checked"); - assert(!sun_dyn_MemberName::is_instance(x), "already checked"); + assert(!java_lang_invoke_MemberName::is_instance(x), "already checked"); } return NULL; } @@ -336,15 +336,15 @@ int MethodHandles::decode_MethodHandle_stack_pushes(oop mh) { if (mh->klass() == SystemDictionary::DirectMethodHandle_klass()) return 0; // no push/pop - int this_vmslots = java_dyn_MethodHandle::vmslots(mh); + int this_vmslots = java_lang_invoke_MethodHandle::vmslots(mh); int last_vmslots = 0; oop last_mh = mh; for (;;) { - oop target = java_dyn_MethodHandle::vmtarget(last_mh); + oop target = java_lang_invoke_MethodHandle::vmtarget(last_mh); if (target->klass() == SystemDictionary::DirectMethodHandle_klass()) { - last_vmslots = java_dyn_MethodHandle::vmslots(target); + last_vmslots = java_lang_invoke_MethodHandle::vmslots(target); break; - } else if (!java_dyn_MethodHandle::is_instance(target)) { + } else if (!java_lang_invoke_MethodHandle::is_instance(target)) { // might be klass or method assert(target->is_method(), "must get here with a direct ref to method"); last_vmslots = methodOop(target)->size_of_parameters(); @@ -361,16 +361,16 @@ // MemberName support -// import sun_dyn_MemberName.* +// import java_lang_invoke_MemberName.* enum { - IS_METHOD = sun_dyn_MemberName::MN_IS_METHOD, - IS_CONSTRUCTOR = sun_dyn_MemberName::MN_IS_CONSTRUCTOR, - IS_FIELD = sun_dyn_MemberName::MN_IS_FIELD, - IS_TYPE = sun_dyn_MemberName::MN_IS_TYPE, - SEARCH_SUPERCLASSES = sun_dyn_MemberName::MN_SEARCH_SUPERCLASSES, - SEARCH_INTERFACES = sun_dyn_MemberName::MN_SEARCH_INTERFACES, + IS_METHOD = java_lang_invoke_MemberName::MN_IS_METHOD, + IS_CONSTRUCTOR = java_lang_invoke_MemberName::MN_IS_CONSTRUCTOR, + IS_FIELD = java_lang_invoke_MemberName::MN_IS_FIELD, + IS_TYPE = java_lang_invoke_MemberName::MN_IS_TYPE, + SEARCH_SUPERCLASSES = java_lang_invoke_MemberName::MN_SEARCH_SUPERCLASSES, + SEARCH_INTERFACES = java_lang_invoke_MemberName::MN_SEARCH_INTERFACES, ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE, - VM_INDEX_UNINITIALIZED = sun_dyn_MemberName::VM_INDEX_UNINITIALIZED + VM_INDEX_UNINITIALIZED = java_lang_invoke_MemberName::VM_INDEX_UNINITIALIZED }; Handle MethodHandles::new_MemberName(TRAPS) { @@ -405,10 +405,10 @@ if (!do_dispatch || (flags & IS_CONSTRUCTOR) || m->can_be_statically_bound()) vmindex = methodOopDesc::nonvirtual_vtable_index; // implies never any dispatch assert(vmindex != VM_INDEX_UNINITIALIZED, "Java sentinel value"); - sun_dyn_MemberName::set_vmtarget(mname_oop, vmtarget); - sun_dyn_MemberName::set_vmindex(mname_oop, vmindex); - sun_dyn_MemberName::set_flags(mname_oop, flags); - sun_dyn_MemberName::set_clazz(mname_oop, Klass::cast(m->method_holder())->java_mirror()); + java_lang_invoke_MemberName::set_vmtarget(mname_oop, vmtarget); + java_lang_invoke_MemberName::set_vmindex(mname_oop, vmindex); + java_lang_invoke_MemberName::set_flags(mname_oop, flags); + java_lang_invoke_MemberName::set_clazz(mname_oop, Klass::cast(m->method_holder())->java_mirror()); } void MethodHandles::init_MemberName(oop mname_oop, klassOop field_holder, AccessFlags mods, int offset) { @@ -416,21 +416,21 @@ oop vmtarget = field_holder; int vmindex = offset; // determines the field uniquely when combined with static bit assert(vmindex != VM_INDEX_UNINITIALIZED, "bad alias on vmindex"); - sun_dyn_MemberName::set_vmtarget(mname_oop, vmtarget); - sun_dyn_MemberName::set_vmindex(mname_oop, vmindex); - sun_dyn_MemberName::set_flags(mname_oop, flags); - sun_dyn_MemberName::set_clazz(mname_oop, Klass::cast(field_holder)->java_mirror()); + java_lang_invoke_MemberName::set_vmtarget(mname_oop, vmtarget); + java_lang_invoke_MemberName::set_vmindex(mname_oop, vmindex); + java_lang_invoke_MemberName::set_flags(mname_oop, flags); + java_lang_invoke_MemberName::set_clazz(mname_oop, Klass::cast(field_holder)->java_mirror()); } methodOop MethodHandles::decode_MemberName(oop mname, klassOop& receiver_limit_result, int& decode_flags_result) { - int flags = sun_dyn_MemberName::flags(mname); + int flags = java_lang_invoke_MemberName::flags(mname); if ((flags & (IS_METHOD | IS_CONSTRUCTOR)) == 0) return NULL; // not invocable - oop vmtarget = sun_dyn_MemberName::vmtarget(mname); - int vmindex = sun_dyn_MemberName::vmindex(mname); + oop vmtarget = java_lang_invoke_MemberName::vmtarget(mname); + int vmindex = java_lang_invoke_MemberName::vmindex(mname); if (vmindex == VM_INDEX_UNINITIALIZED) return NULL; // not resolved methodOop m = decode_vmtarget(vmtarget, vmindex, NULL, receiver_limit_result, decode_flags_result); - oop clazz = sun_dyn_MemberName::clazz(mname); + oop clazz = java_lang_invoke_MemberName::clazz(mname); if (clazz != NULL && java_lang_Class::is_instance(clazz)) { klassOop klass = java_lang_Class::as_klassOop(clazz); if (klass != NULL) receiver_limit_result = klass; @@ -442,8 +442,8 @@ Symbol* MethodHandles::convert_to_signature(oop type_str, bool polymorphic, TRAPS) { - if (java_dyn_MethodType::is_instance(type_str)) { - return java_dyn_MethodType::as_signature(type_str, polymorphic, CHECK_NULL); + if (java_lang_invoke_MethodType::is_instance(type_str)) { + return java_lang_invoke_MethodType::as_signature(type_str, polymorphic, CHECK_NULL); } else if (java_lang_Class::is_instance(type_str)) { return java_lang_Class::as_signature(type_str, false, CHECK_NULL); } else if (java_lang_String::is_instance(type_str)) { @@ -461,7 +461,7 @@ // Resolving it plants a vmtarget/vmindex in it, // which refers dirctly to JVM internals. void MethodHandles::resolve_MemberName(Handle mname, TRAPS) { - assert(sun_dyn_MemberName::is_instance(mname()), ""); + assert(java_lang_invoke_MemberName::is_instance(mname()), ""); #ifdef ASSERT // If this assert throws, renegotiate the sentinel value used by the Java code, // so that it is distinct from any valid vtable index value, and any special @@ -472,12 +472,12 @@ const int sentinel_limit = methodOopDesc::highest_unused_vtable_index_value - sentinel_slop; assert(VM_INDEX_UNINITIALIZED < sentinel_limit, "Java sentinel != JVM sentinels"); #endif - if (sun_dyn_MemberName::vmindex(mname()) != VM_INDEX_UNINITIALIZED) + if (java_lang_invoke_MemberName::vmindex(mname()) != VM_INDEX_UNINITIALIZED) return; // already resolved - oop defc_oop = sun_dyn_MemberName::clazz(mname()); - oop name_str = sun_dyn_MemberName::name(mname()); - oop type_str = sun_dyn_MemberName::type(mname()); - int flags = sun_dyn_MemberName::flags(mname()); + oop defc_oop = java_lang_invoke_MemberName::clazz(mname()); + oop name_str = java_lang_invoke_MemberName::name(mname()); + oop type_str = java_lang_invoke_MemberName::type(mname()); + int flags = java_lang_invoke_MemberName::flags(mname()); if (defc_oop == NULL || name_str == NULL || type_str == NULL) { THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "nothing to resolve"); @@ -510,7 +510,7 @@ // convert the external string or reflective type to an internal signature TempNewSymbol type = convert_to_signature(type_str, polymorphic_signature, CHECK); - if (java_dyn_MethodType::is_instance(type_str) && polymorphic_signature) { + if (java_lang_invoke_MethodType::is_instance(type_str) && polymorphic_signature) { polymorphic_method_type = Handle(THREAD, type_str); //preserve exactly } @@ -557,9 +557,9 @@ vmtarget = result.resolved_klass()->as_klassOop(); } int mods = (m->access_flags().as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS); - sun_dyn_MemberName::set_vmtarget(mname(), vmtarget); - sun_dyn_MemberName::set_vmindex(mname(), vmindex); - sun_dyn_MemberName::set_modifiers(mname(), mods); + java_lang_invoke_MemberName::set_vmtarget(mname(), vmtarget); + java_lang_invoke_MemberName::set_vmindex(mname(), vmindex); + java_lang_invoke_MemberName::set_modifiers(mname(), mods); DEBUG_ONLY(int junk; klassOop junk2); assert(decode_MemberName(mname(), junk2, junk) == result.resolved_method()(), "properly stored for later decoding"); @@ -586,9 +586,9 @@ oop vmtarget = m(); int vmindex = methodOopDesc::nonvirtual_vtable_index; int mods = (m->access_flags().as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS); - sun_dyn_MemberName::set_vmtarget(mname(), vmtarget); - sun_dyn_MemberName::set_vmindex(mname(), vmindex); - sun_dyn_MemberName::set_modifiers(mname(), mods); + java_lang_invoke_MemberName::set_vmtarget(mname(), vmtarget); + java_lang_invoke_MemberName::set_vmindex(mname(), vmindex); + java_lang_invoke_MemberName::set_modifiers(mname(), mods); DEBUG_ONLY(int junk; klassOop junk2); assert(decode_MemberName(mname(), junk2, junk) == result.resolved_method()(), "properly stored for later decoding"); @@ -605,9 +605,9 @@ int vmindex = fd.offset(); int mods = (fd.access_flags().as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS); if (vmindex == VM_INDEX_UNINITIALIZED) break; // should not happen - sun_dyn_MemberName::set_vmtarget(mname(), vmtarget); - sun_dyn_MemberName::set_vmindex(mname(), vmindex); - sun_dyn_MemberName::set_modifiers(mname(), mods); + java_lang_invoke_MemberName::set_vmtarget(mname(), vmtarget); + java_lang_invoke_MemberName::set_vmindex(mname(), vmindex); + java_lang_invoke_MemberName::set_modifiers(mname(), mods); return; } default: @@ -618,11 +618,11 @@ if (polymorphic_method_type.not_null()) { // Look on a non-null class loader. Handle cur_class_loader; - const int nptypes = java_dyn_MethodType::ptype_count(polymorphic_method_type()); + const int nptypes = java_lang_invoke_MethodType::ptype_count(polymorphic_method_type()); for (int i = 0; i <= nptypes; i++) { oop type_mirror; - if (i < nptypes) type_mirror = java_dyn_MethodType::ptype(polymorphic_method_type(), i); - else type_mirror = java_dyn_MethodType::rtype(polymorphic_method_type()); + if (i < nptypes) type_mirror = java_lang_invoke_MethodType::ptype(polymorphic_method_type(), i); + else type_mirror = java_lang_invoke_MethodType::rtype(polymorphic_method_type()); klassOop example_type = java_lang_Class::as_klassOop(type_mirror); if (example_type == NULL) continue; oop class_loader = Klass::cast(example_type)->class_loader(); @@ -639,9 +639,9 @@ } if (m != NULL) { int mods = (m->access_flags().as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS); - sun_dyn_MemberName::set_vmtarget(mname(), m); - sun_dyn_MemberName::set_vmindex(mname(), m->vtable_index()); - sun_dyn_MemberName::set_modifiers(mname(), mods); + java_lang_invoke_MemberName::set_vmtarget(mname(), m); + java_lang_invoke_MemberName::set_vmindex(mname(), m->vtable_index()); + java_lang_invoke_MemberName::set_modifiers(mname(), mods); return; } } @@ -653,17 +653,17 @@ // Resolving it plants a vmtarget/vmindex in it, // which refers directly to JVM internals. void MethodHandles::expand_MemberName(Handle mname, int suppress, TRAPS) { - assert(sun_dyn_MemberName::is_instance(mname()), ""); - oop vmtarget = sun_dyn_MemberName::vmtarget(mname()); - int vmindex = sun_dyn_MemberName::vmindex(mname()); + assert(java_lang_invoke_MemberName::is_instance(mname()), ""); + oop vmtarget = java_lang_invoke_MemberName::vmtarget(mname()); + int vmindex = java_lang_invoke_MemberName::vmindex(mname()); if (vmtarget == NULL || vmindex == VM_INDEX_UNINITIALIZED) { THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "nothing to expand"); } - bool have_defc = (sun_dyn_MemberName::clazz(mname()) != NULL); - bool have_name = (sun_dyn_MemberName::name(mname()) != NULL); - bool have_type = (sun_dyn_MemberName::type(mname()) != NULL); - int flags = sun_dyn_MemberName::flags(mname()); + bool have_defc = (java_lang_invoke_MemberName::clazz(mname()) != NULL); + bool have_name = (java_lang_invoke_MemberName::name(mname()) != NULL); + bool have_type = (java_lang_invoke_MemberName::type(mname()) != NULL); + int flags = java_lang_invoke_MemberName::flags(mname()); if (suppress != 0) { if (suppress & _suppress_defc) have_defc = true; @@ -687,16 +687,16 @@ if (receiver_limit != NULL && receiver_limit != defc && Klass::cast(receiver_limit)->is_subtype_of(defc)) defc = receiver_limit; - sun_dyn_MemberName::set_clazz(mname(), Klass::cast(defc)->java_mirror()); + java_lang_invoke_MemberName::set_clazz(mname(), Klass::cast(defc)->java_mirror()); } if (!have_name) { //not java_lang_String::create_from_symbol; let's intern member names Handle name = StringTable::intern(m->name(), CHECK); - sun_dyn_MemberName::set_name(mname(), name()); + java_lang_invoke_MemberName::set_name(mname(), name()); } if (!have_type) { Handle type = java_lang_String::create_from_symbol(m->signature(), CHECK); - sun_dyn_MemberName::set_type(mname(), type()); + java_lang_invoke_MemberName::set_type(mname(), type()); } return; } @@ -711,16 +711,16 @@ if (!defc->find_field_from_offset(vmindex, is_static, &fd)) break; // cannot expand if (!have_defc) { - sun_dyn_MemberName::set_clazz(mname(), defc->java_mirror()); + java_lang_invoke_MemberName::set_clazz(mname(), defc->java_mirror()); } if (!have_name) { //not java_lang_String::create_from_symbol; let's intern member names Handle name = StringTable::intern(fd.name(), CHECK); - sun_dyn_MemberName::set_name(mname(), name()); + java_lang_invoke_MemberName::set_name(mname(), name()); } if (!have_type) { Handle type = java_lang_String::create_from_symbol(fd.signature(), CHECK); - sun_dyn_MemberName::set_type(mname(), type()); + java_lang_invoke_MemberName::set_type(mname(), type()); } return; } @@ -775,7 +775,7 @@ --rskip; } else if (rfill < rlimit) { oop result = results->obj_at(rfill++); - if (!sun_dyn_MemberName::is_instance(result)) + if (!java_lang_invoke_MemberName::is_instance(result)) return -99; // caller bug! MethodHandles::init_MemberName(result, st.klass()->as_klassOop(), st.access_flags(), st.offset()); } else if (++overflow >= overflow_limit) { @@ -823,7 +823,7 @@ --rskip; } else if (rfill < rlimit) { oop result = results->obj_at(rfill++); - if (!sun_dyn_MemberName::is_instance(result)) + if (!java_lang_invoke_MemberName::is_instance(result)) return -99; // caller bug! MethodHandles::init_MemberName(result, m, true); } else if (++overflow >= overflow_limit) { @@ -857,9 +857,9 @@ // Sanitize out methodOops, klassOops, and any other non-Java data. // This is for debugging and reflection. oop MethodHandles::encode_target(Handle mh, int format, TRAPS) { - assert(java_dyn_MethodHandle::is_instance(mh()), "must be a MH"); + assert(java_lang_invoke_MethodHandle::is_instance(mh()), "must be a MH"); if (format == ETF_HANDLE_OR_METHOD_NAME) { - oop target = java_dyn_MethodHandle::vmtarget(mh()); + oop target = java_lang_invoke_MethodHandle::vmtarget(mh()); if (target == NULL) { return NULL; // unformed MH } @@ -874,10 +874,10 @@ if (target->klass() == SystemDictionary::DirectMethodHandle_klass()) { return target; } - if (!java_dyn_MethodHandle::is_instance(target)){ + if (!java_lang_invoke_MethodHandle::is_instance(target)){ return NULL; // unformed MH } - target = java_dyn_MethodHandle::vmtarget(target); + target = java_lang_invoke_MethodHandle::vmtarget(target); } } // cases of metadata in MH.vmtarget: @@ -904,7 +904,7 @@ instanceKlassHandle mname_klass(THREAD, SystemDictionary::MemberName_klass()); mname_klass->initialize(CHECK_NULL); Handle mname = mname_klass->allocate_instance_handle(CHECK_NULL); - sun_dyn_MemberName::set_vmindex(mname(), VM_INDEX_UNINITIALIZED); + java_lang_invoke_MemberName::set_vmindex(mname(), VM_INDEX_UNINITIALIZED); bool do_dispatch = ((decode_flags & MethodHandles::_dmf_does_dispatch) != 0); init_MemberName(mname(), m, do_dispatch); expand_MemberName(mname, 0, CHECK_NULL); @@ -923,6 +923,7 @@ "java/lang/Null", //"java/lang/Nothing", "sun/dyn/empty/Empty", + "sun/invoke/empty/Empty", NULL }; @@ -1025,7 +1026,7 @@ int first_ptype_pos, KlassHandle insert_ptype, TRAPS) { - objArrayHandle ptypes(THREAD, java_dyn_MethodType::ptypes(mtype())); + objArrayHandle ptypes(THREAD, java_lang_invoke_MethodType::ptypes(mtype())); int pnum = first_ptype_pos; int pmax = ptypes->length(); int mnum = 0; // method argument @@ -1036,7 +1037,7 @@ if (ss.at_return_type()) { if (pnum != pmax) { err = "too many arguments"; break; } - ptype_oop = java_dyn_MethodType::rtype(mtype()); + ptype_oop = java_lang_invoke_MethodType::rtype(mtype()); } else { if (pnum >= pmax) { err = "not enough arguments"; break; } @@ -1111,7 +1112,7 @@ } if (m_needs_receiver && err == NULL) { - objArrayOop ptypes = java_dyn_MethodType::ptypes(mtype()); + objArrayOop ptypes = java_lang_invoke_MethodType::ptypes(mtype()); if (ptypes->length() < first_ptype_pos) { err = "receiver argument is missing"; goto die; } if (has_bound_recv) @@ -1131,15 +1132,15 @@ void MethodHandles::verify_vmslots(Handle mh, TRAPS) { // Verify vmslots. - int check_slots = argument_slot_count(java_dyn_MethodHandle::type(mh())); - if (java_dyn_MethodHandle::vmslots(mh()) != check_slots) { + int check_slots = argument_slot_count(java_lang_invoke_MethodHandle::type(mh())); + if (java_lang_invoke_MethodHandle::vmslots(mh()) != check_slots) { THROW_MSG(vmSymbols::java_lang_InternalError(), "bad vmslots in BMH"); } } void MethodHandles::verify_vmargslot(Handle mh, int argnum, int argslot, TRAPS) { // Verify that argslot points at the given argnum. - int check_slot = argument_slot(java_dyn_MethodHandle::type(mh()), argnum); + int check_slot = argument_slot(java_lang_invoke_MethodHandle::type(mh()), argnum); if (argslot != check_slot || argslot < 0) { const char* fmt = "for argnum of %d, vmargslot is %d, should be %d"; size_t msglen = strlen(fmt) + 3*11 + 1; @@ -1160,8 +1161,8 @@ int delete_argnum, oop dst_mtype, int dst_beg, int dst_end, bool raw) { - objArrayOop src_ptypes = java_dyn_MethodType::ptypes(src_mtype); - objArrayOop dst_ptypes = java_dyn_MethodType::ptypes(dst_mtype); + objArrayOop src_ptypes = java_lang_invoke_MethodType::ptypes(src_mtype); + objArrayOop dst_ptypes = java_lang_invoke_MethodType::ptypes(dst_mtype); int src_max = src_ptypes->length(); int dst_max = dst_ptypes->length(); @@ -1224,8 +1225,8 @@ } // Now compare return types also. - oop src_rtype = java_dyn_MethodType::rtype(src_mtype); - oop dst_rtype = java_dyn_MethodType::rtype(dst_mtype); + oop src_rtype = java_lang_invoke_MethodType::rtype(src_mtype); + oop dst_rtype = java_lang_invoke_MethodType::rtype(dst_mtype); if (src_rtype != dst_rtype) { err = check_return_type_change(dst_rtype, src_rtype, raw); // note reversal! if (err != NULL) return err; @@ -1314,7 +1315,7 @@ // then return a negative number. Otherwise, the result // is in the range [0..vmslots] inclusive. int MethodHandles::argument_slot(oop method_type, int arg) { - objArrayOop ptypes = java_dyn_MethodType::ptypes(method_type); + objArrayOop ptypes = java_lang_invoke_MethodType::ptypes(method_type); int argslot = 0; int len = ptypes->length(); if (arg < -1 || arg >= len) return -99; @@ -1328,7 +1329,7 @@ // Given a slot number, return the argument number. int MethodHandles::argument_slot_to_argnum(oop method_type, int query_argslot) { - objArrayOop ptypes = java_dyn_MethodType::ptypes(method_type); + objArrayOop ptypes = java_lang_invoke_MethodType::ptypes(method_type); int argslot = 0; int len = ptypes->length(); for (int i = len-1; i >= 0; i--) { @@ -1394,11 +1395,11 @@ void MethodHandles::verify_DirectMethodHandle(Handle mh, methodHandle m, TRAPS) { // Verify type. - Handle mtype(THREAD, java_dyn_MethodHandle::type(mh())); + Handle mtype(THREAD, java_lang_invoke_MethodHandle::type(mh())); verify_method_type(m, mtype, false, KlassHandle(), CHECK); // Verify vmslots. - if (java_dyn_MethodHandle::vmslots(mh()) != m->size_of_parameters()) { + if (java_lang_invoke_MethodHandle::vmslots(mh()) != m->size_of_parameters()) { THROW_MSG(vmSymbols::java_lang_InternalError(), "bad vmslots in DMH"); } } @@ -1410,7 +1411,7 @@ THROW(vmSymbols::java_lang_InternalError()); } - java_dyn_MethodHandle::init_vmslots(mh()); + java_lang_invoke_MethodHandle::init_vmslots(mh()); if (VerifyMethodHandles) { // The privileged code which invokes this routine should not make @@ -1470,8 +1471,8 @@ if (me == NULL) { THROW(vmSymbols::java_lang_InternalError()); } - sun_dyn_DirectMethodHandle::set_vmtarget(mh(), vmtarget); - sun_dyn_DirectMethodHandle::set_vmindex(mh(), vmindex); + java_lang_invoke_DirectMethodHandle::set_vmtarget(mh(), vmtarget); + java_lang_invoke_DirectMethodHandle::set_vmindex(mh(), vmindex); DEBUG_ONLY(int flags; klassOop rlimit); assert(MethodHandles::decode_method(mh(), rlimit, flags) == m(), "properly stored for later decoding"); @@ -1482,15 +1483,15 @@ assert(decode_MethodHandle_stack_pushes(mh()) == 0, "DMH does not move stack"); // Done! - java_dyn_MethodHandle::set_vmentry(mh(), me); + java_lang_invoke_MethodHandle::set_vmentry(mh(), me); } void MethodHandles::verify_BoundMethodHandle_with_receiver(Handle mh, methodHandle m, TRAPS) { // Verify type. - oop receiver = sun_dyn_BoundMethodHandle::argument(mh()); - Handle mtype(THREAD, java_dyn_MethodHandle::type(mh())); + oop receiver = java_lang_invoke_BoundMethodHandle::argument(mh()); + Handle mtype(THREAD, java_lang_invoke_MethodHandle::type(mh())); KlassHandle bound_recv_type; if (receiver != NULL) bound_recv_type = KlassHandle(THREAD, receiver->klass()); verify_method_type(m, mtype, true, bound_recv_type, CHECK); @@ -1498,11 +1499,11 @@ int receiver_pos = m->size_of_parameters() - 1; // Verify MH.vmargslot, which should point at the bound receiver. - verify_vmargslot(mh, -1, sun_dyn_BoundMethodHandle::vmargslot(mh()), CHECK); + verify_vmargslot(mh, -1, java_lang_invoke_BoundMethodHandle::vmargslot(mh()), CHECK); //verify_vmslots(mh, CHECK); // Verify vmslots. - if (java_dyn_MethodHandle::vmslots(mh()) != receiver_pos) { + if (java_lang_invoke_MethodHandle::vmslots(mh()) != receiver_pos) { THROW_MSG(vmSymbols::java_lang_InternalError(), "bad vmslots in BMH (receiver)"); } } @@ -1520,7 +1521,7 @@ KlassHandle receiver_klass; { - oop receiver_oop = sun_dyn_BoundMethodHandle::argument(mh()); + oop receiver_oop = java_lang_invoke_BoundMethodHandle::argument(mh()); if (receiver_oop != NULL) receiver_klass = KlassHandle(THREAD, receiver_oop->klass()); } @@ -1531,31 +1532,31 @@ if (m.is_null()) { THROW(vmSymbols::java_lang_InternalError()); } if (m->is_abstract()) { THROW(vmSymbols::java_lang_AbstractMethodError()); } - java_dyn_MethodHandle::init_vmslots(mh()); + java_lang_invoke_MethodHandle::init_vmslots(mh()); if (VerifyMethodHandles) { verify_BoundMethodHandle_with_receiver(mh, m, CHECK); } - sun_dyn_BoundMethodHandle::set_vmtarget(mh(), m()); + java_lang_invoke_BoundMethodHandle::set_vmtarget(mh(), m()); DEBUG_ONLY(int junk; klassOop junk2); assert(MethodHandles::decode_method(mh(), junk2, junk) == m(), "properly stored for later decoding"); assert(decode_MethodHandle_stack_pushes(mh()) == 1, "BMH pushes one stack slot"); // Done! - java_dyn_MethodHandle::set_vmentry(mh(), MethodHandles::entry(MethodHandles::_bound_ref_direct_mh)); + java_lang_invoke_MethodHandle::set_vmentry(mh(), MethodHandles::entry(MethodHandles::_bound_ref_direct_mh)); } void MethodHandles::verify_BoundMethodHandle(Handle mh, Handle target, int argnum, bool direct_to_method, TRAPS) { Handle ptype_handle(THREAD, - java_dyn_MethodType::ptype(java_dyn_MethodHandle::type(target()), argnum)); + java_lang_invoke_MethodType::ptype(java_lang_invoke_MethodHandle::type(target()), argnum)); KlassHandle ptype_klass; BasicType ptype = java_lang_Class::as_BasicType(ptype_handle(), &ptype_klass); int slots_pushed = type2size[ptype]; - oop argument = sun_dyn_BoundMethodHandle::argument(mh()); + oop argument = java_lang_invoke_BoundMethodHandle::argument(mh()); const char* err = NULL; @@ -1623,9 +1624,9 @@ if (err == NULL) { // Verify the rest of the method type. - err = check_method_type_insertion(java_dyn_MethodHandle::type(mh()), + err = check_method_type_insertion(java_lang_invoke_MethodHandle::type(mh()), argnum, ptype_handle(), - java_dyn_MethodHandle::type(target())); + java_lang_invoke_MethodHandle::type(target())); } if (err != NULL) { @@ -1635,20 +1636,20 @@ void MethodHandles::init_BoundMethodHandle(Handle mh, Handle target, int argnum, TRAPS) { // Check arguments. - if (mh.is_null() || target.is_null() || !java_dyn_MethodHandle::is_instance(target())) { + if (mh.is_null() || target.is_null() || !java_lang_invoke_MethodHandle::is_instance(target())) { THROW(vmSymbols::java_lang_InternalError()); } - java_dyn_MethodHandle::init_vmslots(mh()); + java_lang_invoke_MethodHandle::init_vmslots(mh()); if (VerifyMethodHandles) { int insert_after = argnum - 1; - verify_vmargslot(mh, insert_after, sun_dyn_BoundMethodHandle::vmargslot(mh()), CHECK); + verify_vmargslot(mh, insert_after, java_lang_invoke_BoundMethodHandle::vmargslot(mh()), CHECK); verify_vmslots(mh, CHECK); } // Get bound type and required slots. - oop ptype_oop = java_dyn_MethodType::ptype(java_dyn_MethodHandle::type(target()), argnum); + oop ptype_oop = java_lang_invoke_MethodType::ptype(java_lang_invoke_MethodHandle::type(target()), argnum); BasicType ptype = java_lang_Class::as_BasicType(ptype_oop); int slots_pushed = type2size[ptype]; @@ -1659,12 +1660,12 @@ bool direct_to_method = false; if (OptimizeMethodHandles && target->klass() == SystemDictionary::DirectMethodHandle_klass() && - (argnum == 0 || sun_dyn_DirectMethodHandle::vmindex(target()) < 0)) { + (argnum == 0 || java_lang_invoke_DirectMethodHandle::vmindex(target()) < 0)) { int decode_flags = 0; klassOop receiver_limit_oop = NULL; methodHandle m(THREAD, decode_method(target(), receiver_limit_oop, decode_flags)); if (m.is_null()) { THROW_MSG(vmSymbols::java_lang_InternalError(), "DMH failed to decode"); } DEBUG_ONLY(int m_vmslots = m->size_of_parameters() - slots_pushed); // pos. of 1st arg. - assert(sun_dyn_BoundMethodHandle::vmslots(mh()) == m_vmslots, "type w/ m sig"); + assert(java_lang_invoke_BoundMethodHandle::vmslots(mh()) == m_vmslots, "type w/ m sig"); if (argnum == 0 && (decode_flags & _dmf_has_receiver) != 0) { KlassHandle receiver_limit(THREAD, receiver_limit_oop); init_BoundMethodHandle_with_receiver(mh, m, @@ -1677,11 +1678,11 @@ // to bind another argument and still invoke the methodOop directly. if (!(decode_flags & _dmf_does_dispatch)) { direct_to_method = true; - sun_dyn_BoundMethodHandle::set_vmtarget(mh(), m()); + java_lang_invoke_BoundMethodHandle::set_vmtarget(mh(), m()); } } if (!direct_to_method) - sun_dyn_BoundMethodHandle::set_vmtarget(mh(), target()); + java_lang_invoke_BoundMethodHandle::set_vmtarget(mh(), target()); if (VerifyMethodHandles) { verify_BoundMethodHandle(mh, target, argnum, direct_to_method, CHECK); @@ -1703,7 +1704,7 @@ } // Done! - java_dyn_MethodHandle::set_vmentry(mh(), me); + java_lang_invoke_MethodHandle::set_vmentry(mh(), me); } static void throw_InternalError_for_bad_conversion(int conversion, const char* err, TRAPS) { @@ -1713,8 +1714,8 @@ } void MethodHandles::verify_AdapterMethodHandle(Handle mh, int argnum, TRAPS) { - jint conversion = sun_dyn_AdapterMethodHandle::conversion(mh()); - int argslot = sun_dyn_AdapterMethodHandle::vmargslot(mh()); + jint conversion = java_lang_invoke_AdapterMethodHandle::conversion(mh()); + int argslot = java_lang_invoke_AdapterMethodHandle::vmargslot(mh()); verify_vmargslot(mh, argnum, argslot, CHECK); verify_vmslots(mh, CHECK); @@ -1731,10 +1732,10 @@ BasicType dest = adapter_conversion_dest_type(conversion); int vminfo = adapter_conversion_vminfo(conversion); // should be zero - Handle argument(THREAD, sun_dyn_AdapterMethodHandle::argument(mh())); - Handle target(THREAD, sun_dyn_AdapterMethodHandle::vmtarget(mh())); - Handle src_mtype(THREAD, java_dyn_MethodHandle::type(mh())); - Handle dst_mtype(THREAD, java_dyn_MethodHandle::type(target())); + Handle argument(THREAD, java_lang_invoke_AdapterMethodHandle::argument(mh())); + Handle target(THREAD, java_lang_invoke_AdapterMethodHandle::vmtarget(mh())); + Handle src_mtype(THREAD, java_lang_invoke_MethodHandle::type(mh())); + Handle dst_mtype(THREAD, java_lang_invoke_MethodHandle::type(target())); const char* err = NULL; @@ -1760,7 +1761,7 @@ break; case _adapter_flyby: case _adapter_ricochet: - if (!java_dyn_MethodHandle::is_instance(argument())) + if (!java_lang_invoke_MethodHandle::is_instance(argument())) { err = "MethodHandle adapter argument required"; break; } break; default: @@ -1806,9 +1807,9 @@ err = "adapter requires src/dest conversion subfields for swap"; break; } int swap_size = type2size[src]; - oop src_mtype = sun_dyn_AdapterMethodHandle::type(mh()); - oop dest_mtype = sun_dyn_AdapterMethodHandle::type(target()); - int slot_limit = sun_dyn_AdapterMethodHandle::vmslots(target()); + oop src_mtype = java_lang_invoke_AdapterMethodHandle::type(mh()); + oop dest_mtype = java_lang_invoke_AdapterMethodHandle::type(target()); + int slot_limit = java_lang_invoke_AdapterMethodHandle::vmslots(target()); int src_slot = argslot; int dest_slot = vminfo; bool rotate_up = (src_slot > dest_slot); // upward rotation @@ -1821,8 +1822,8 @@ } else if (ek == _adapter_swap_args && !(src_slot > dest_slot)) { err = "source of swap must be deeper in stack"; } else if (ek == _adapter_swap_args) { - err = check_argument_type_change(java_dyn_MethodType::ptype(src_mtype, dest_arg), - java_dyn_MethodType::ptype(dest_mtype, src_arg), + err = check_argument_type_change(java_lang_invoke_MethodType::ptype(src_mtype, dest_arg), + java_lang_invoke_MethodType::ptype(dest_mtype, src_arg), dest_arg); } else if (ek == _adapter_rot_args) { if (rotate_up) { @@ -1830,8 +1831,8 @@ // rotate up: [dest_slot..src_slot-ss] --> [dest_slot+ss..src_slot] // that is: [src_arg+1..dest_arg] --> [src_arg..dest_arg-1] for (int i = src_arg+1; i <= dest_arg && err == NULL; i++) { - err = check_argument_type_change(java_dyn_MethodType::ptype(src_mtype, i), - java_dyn_MethodType::ptype(dest_mtype, i-1), + err = check_argument_type_change(java_lang_invoke_MethodType::ptype(src_mtype, i), + java_lang_invoke_MethodType::ptype(dest_mtype, i-1), i); } } else { // rotate down @@ -1839,15 +1840,15 @@ // rotate down: [src_slot+ss..dest_slot] --> [src_slot..dest_slot-ss] // that is: [dest_arg..src_arg-1] --> [dst_arg+1..src_arg] for (int i = dest_arg; i <= src_arg-1 && err == NULL; i++) { - err = check_argument_type_change(java_dyn_MethodType::ptype(src_mtype, i), - java_dyn_MethodType::ptype(dest_mtype, i+1), + err = check_argument_type_change(java_lang_invoke_MethodType::ptype(src_mtype, i), + java_lang_invoke_MethodType::ptype(dest_mtype, i+1), i); } } } if (err == NULL) - err = check_argument_type_change(java_dyn_MethodType::ptype(src_mtype, src_arg), - java_dyn_MethodType::ptype(dest_mtype, dest_arg), + err = check_argument_type_change(java_lang_invoke_MethodType::ptype(src_mtype, src_arg), + java_lang_invoke_MethodType::ptype(dest_mtype, dest_arg), src_arg); } break; @@ -1918,8 +1919,8 @@ if (err == NULL) { // Make sure this adapter does not push too deeply. int slots_pushed = stack_move / stack_move_unit(); - int this_vmslots = java_dyn_MethodHandle::vmslots(mh()); - int target_vmslots = java_dyn_MethodHandle::vmslots(target()); + int this_vmslots = java_lang_invoke_MethodHandle::vmslots(mh()); + int target_vmslots = java_lang_invoke_MethodHandle::vmslots(target()); if (slots_pushed != (target_vmslots - this_vmslots)) { err = "stack_move inconsistent with previous and current MethodType vmslots"; } else if (slots_pushed > 0) { @@ -1961,7 +1962,7 @@ case _adapter_check_cast: { // The actual value being checked must be a reference: - err = check_argument_type_change(java_dyn_MethodType::ptype(src_mtype(), argnum), + err = check_argument_type_change(java_lang_invoke_MethodType::ptype(src_mtype(), argnum), object_java_mirror(), argnum); if (err != NULL) break; @@ -1985,9 +1986,9 @@ } void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnum, TRAPS) { - oop argument = sun_dyn_AdapterMethodHandle::argument(mh()); - int argslot = sun_dyn_AdapterMethodHandle::vmargslot(mh()); - jint conversion = sun_dyn_AdapterMethodHandle::conversion(mh()); + oop argument = java_lang_invoke_AdapterMethodHandle::argument(mh()); + int argslot = java_lang_invoke_AdapterMethodHandle::vmargslot(mh()); + jint conversion = java_lang_invoke_AdapterMethodHandle::conversion(mh()); jint conv_op = adapter_conversion_op(conversion); // adjust the adapter code to the internal EntryKind enumeration: @@ -1995,11 +1996,11 @@ EntryKind ek_opt = ek_orig; // may be optimized // Finalize the vmtarget field (Java initialized it to null). - if (!java_dyn_MethodHandle::is_instance(target())) { + if (!java_lang_invoke_MethodHandle::is_instance(target())) { throw_InternalError_for_bad_conversion(conversion, "bad target", THREAD); return; } - sun_dyn_AdapterMethodHandle::set_vmtarget(mh(), target()); + java_lang_invoke_AdapterMethodHandle::set_vmtarget(mh(), target()); if (VerifyMethodHandles) { verify_AdapterMethodHandle(mh, argnum, CHECK); @@ -2083,7 +2084,7 @@ case _adapter_rot_args: { int swap_slots = type2size[src]; - int slot_limit = sun_dyn_AdapterMethodHandle::vmslots(mh()); + int slot_limit = java_lang_invoke_AdapterMethodHandle::vmslots(mh()); int src_slot = argslot; int dest_slot = vminfo; int rotate = (ek_orig == _adapter_swap_args) ? 0 : (src_slot > dest_slot) ? 1 : -1; @@ -2147,10 +2148,10 @@ jint new_conversion = adapter_conversion(conv_op, src, dest, stack_move, vminfo); // Finalize the conversion field. (Note that it is final to Java code.) - sun_dyn_AdapterMethodHandle::set_conversion(mh(), new_conversion); + java_lang_invoke_AdapterMethodHandle::set_conversion(mh(), new_conversion); // Done! - java_dyn_MethodHandle::set_vmentry(mh(), entry(ek_opt)); + java_lang_invoke_MethodHandle::set_vmentry(mh(), entry(ek_opt)); // There should be enough memory barriers on exit from native methods // to ensure that the MH is fully initialized to all threads before @@ -2158,7 +2159,7 @@ } // -// Here are the native methods on sun.dyn.MethodHandleImpl. +// Here are the native methods on sun.invoke.MethodHandleImpl. // They are the private interface between this JVM and the HotSpot-specific // Java code that implements JSR 292 method handles. // @@ -2168,7 +2169,7 @@ // direct method handles for invokestatic or invokespecial // void init(DirectMethodHandle self, MemberName ref, boolean doDispatch, Class caller); -JVM_ENTRY(void, MHI_init_DMH(JNIEnv *env, jobject igcls, jobject mh_jh, +JVM_ENTRY(void, MHN_init_DMH(JNIEnv *env, jobject igcls, jobject mh_jh, jobject target_jh, jboolean do_dispatch, jobject caller_jh)) { ResourceMark rm; // for error messages @@ -2177,13 +2178,13 @@ Handle mh(THREAD, JNIHandles::resolve_non_null(mh_jh)); // Early returns out of this method leave the DMH in an unfinished state. - assert(java_dyn_MethodHandle::vmentry(mh()) == NULL, "must be safely null"); + assert(java_lang_invoke_MethodHandle::vmentry(mh()) == NULL, "must be safely null"); // which method are we really talking about? if (target_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } oop target_oop = JNIHandles::resolve_non_null(target_jh); - if (sun_dyn_MemberName::is_instance(target_oop) && - sun_dyn_MemberName::vmindex(target_oop) == VM_INDEX_UNINITIALIZED) { + if (java_lang_invoke_MemberName::is_instance(target_oop) && + java_lang_invoke_MemberName::vmindex(target_oop) == VM_INDEX_UNINITIALIZED) { Handle mname(THREAD, target_oop); MethodHandles::resolve_MemberName(mname, CHECK); target_oop = mname(); // in case of GC @@ -2232,7 +2233,7 @@ JVM_END // bound method handles -JVM_ENTRY(void, MHI_init_BMH(JNIEnv *env, jobject igcls, jobject mh_jh, +JVM_ENTRY(void, MHN_init_BMH(JNIEnv *env, jobject igcls, jobject mh_jh, jobject target_jh, int argnum)) { ResourceMark rm; // for error messages @@ -2241,12 +2242,12 @@ Handle mh(THREAD, JNIHandles::resolve_non_null(mh_jh)); // Early returns out of this method leave the BMH in an unfinished state. - assert(java_dyn_MethodHandle::vmentry(mh()) == NULL, "must be safely null"); + assert(java_lang_invoke_MethodHandle::vmentry(mh()) == NULL, "must be safely null"); if (target_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } Handle target(THREAD, JNIHandles::resolve_non_null(target_jh)); - if (!java_dyn_MethodHandle::is_instance(target())) { + if (!java_lang_invoke_MethodHandle::is_instance(target())) { // Target object is a reflective method. (%%% Do we need this alternate path?) Untested("init_BMH of non-MH"); if (argnum != 0) { THROW(vmSymbols::java_lang_InternalError()); } @@ -2269,7 +2270,7 @@ JVM_END // adapter method handles -JVM_ENTRY(void, MHI_init_AMH(JNIEnv *env, jobject igcls, jobject mh_jh, +JVM_ENTRY(void, MHN_init_AMH(JNIEnv *env, jobject igcls, jobject mh_jh, jobject target_jh, int argnum)) { // This is the guy we are initializing: if (mh_jh == NULL || target_jh == NULL) { @@ -2279,14 +2280,14 @@ Handle target(THREAD, JNIHandles::resolve_non_null(target_jh)); // Early returns out of this method leave the AMH in an unfinished state. - assert(java_dyn_MethodHandle::vmentry(mh()) == NULL, "must be safely null"); + assert(java_lang_invoke_MethodHandle::vmentry(mh()) == NULL, "must be safely null"); MethodHandles::init_AdapterMethodHandle(mh, target, argnum, CHECK); } JVM_END // method type forms -JVM_ENTRY(void, MHI_init_MT(JNIEnv *env, jobject igcls, jobject erased_jh)) { +JVM_ENTRY(void, MHN_init_MT(JNIEnv *env, jobject igcls, jobject erased_jh)) { if (erased_jh == NULL) return; if (TraceMethodHandles) { tty->print("creating MethodType form "); @@ -2307,9 +2308,9 @@ JVM_END // debugging and reflection -JVM_ENTRY(jobject, MHI_getTarget(JNIEnv *env, jobject igcls, jobject mh_jh, jint format)) { +JVM_ENTRY(jobject, MHN_getTarget(JNIEnv *env, jobject igcls, jobject mh_jh, jint format)) { Handle mh(THREAD, JNIHandles::resolve(mh_jh)); - if (!java_dyn_MethodHandle::is_instance(mh())) { + if (!java_lang_invoke_MethodHandle::is_instance(mh())) { THROW_NULL(vmSymbols::java_lang_IllegalArgumentException()); } oop target = MethodHandles::encode_target(mh, format, CHECK_NULL); @@ -2317,7 +2318,7 @@ } JVM_END -JVM_ENTRY(jint, MHI_getConstant(JNIEnv *env, jobject igcls, jint which)) { +JVM_ENTRY(jint, MHN_getConstant(JNIEnv *env, jobject igcls, jint which)) { switch (which) { case MethodHandles::GC_JVM_PUSH_LIMIT: guarantee(MethodHandlePushLimit >= 2 && MethodHandlePushLimit <= 0xFF, @@ -2341,36 +2342,36 @@ template(MethodHandles,ETF_DIRECT_HANDLE) \ template(MethodHandles,ETF_METHOD_NAME) \ template(MethodHandles,ETF_REFLECT_METHOD) \ - template(sun_dyn_MemberName,MN_IS_METHOD) \ - template(sun_dyn_MemberName,MN_IS_CONSTRUCTOR) \ - template(sun_dyn_MemberName,MN_IS_FIELD) \ - template(sun_dyn_MemberName,MN_IS_TYPE) \ - template(sun_dyn_MemberName,MN_SEARCH_SUPERCLASSES) \ - template(sun_dyn_MemberName,MN_SEARCH_INTERFACES) \ - template(sun_dyn_MemberName,VM_INDEX_UNINITIALIZED) \ - template(sun_dyn_AdapterMethodHandle,OP_RETYPE_ONLY) \ - template(sun_dyn_AdapterMethodHandle,OP_RETYPE_RAW) \ - template(sun_dyn_AdapterMethodHandle,OP_CHECK_CAST) \ - template(sun_dyn_AdapterMethodHandle,OP_PRIM_TO_PRIM) \ - template(sun_dyn_AdapterMethodHandle,OP_REF_TO_PRIM) \ - template(sun_dyn_AdapterMethodHandle,OP_PRIM_TO_REF) \ - template(sun_dyn_AdapterMethodHandle,OP_SWAP_ARGS) \ - template(sun_dyn_AdapterMethodHandle,OP_ROT_ARGS) \ - template(sun_dyn_AdapterMethodHandle,OP_DUP_ARGS) \ - template(sun_dyn_AdapterMethodHandle,OP_DROP_ARGS) \ - template(sun_dyn_AdapterMethodHandle,OP_COLLECT_ARGS) \ - template(sun_dyn_AdapterMethodHandle,OP_SPREAD_ARGS) \ - template(sun_dyn_AdapterMethodHandle,OP_FLYBY) \ - template(sun_dyn_AdapterMethodHandle,OP_RICOCHET) \ - template(sun_dyn_AdapterMethodHandle,CONV_OP_LIMIT) \ - template(sun_dyn_AdapterMethodHandle,CONV_OP_MASK) \ - template(sun_dyn_AdapterMethodHandle,CONV_VMINFO_MASK) \ - template(sun_dyn_AdapterMethodHandle,CONV_VMINFO_SHIFT) \ - template(sun_dyn_AdapterMethodHandle,CONV_OP_SHIFT) \ - template(sun_dyn_AdapterMethodHandle,CONV_DEST_TYPE_SHIFT) \ - template(sun_dyn_AdapterMethodHandle,CONV_SRC_TYPE_SHIFT) \ - template(sun_dyn_AdapterMethodHandle,CONV_STACK_MOVE_SHIFT) \ - template(sun_dyn_AdapterMethodHandle,CONV_STACK_MOVE_MASK) \ + template(java_lang_invoke_MemberName,MN_IS_METHOD) \ + template(java_lang_invoke_MemberName,MN_IS_CONSTRUCTOR) \ + template(java_lang_invoke_MemberName,MN_IS_FIELD) \ + template(java_lang_invoke_MemberName,MN_IS_TYPE) \ + template(java_lang_invoke_MemberName,MN_SEARCH_SUPERCLASSES) \ + template(java_lang_invoke_MemberName,MN_SEARCH_INTERFACES) \ + template(java_lang_invoke_MemberName,VM_INDEX_UNINITIALIZED) \ + template(java_lang_invoke_AdapterMethodHandle,OP_RETYPE_ONLY) \ + template(java_lang_invoke_AdapterMethodHandle,OP_RETYPE_RAW) \ + template(java_lang_invoke_AdapterMethodHandle,OP_CHECK_CAST) \ + template(java_lang_invoke_AdapterMethodHandle,OP_PRIM_TO_PRIM) \ + template(java_lang_invoke_AdapterMethodHandle,OP_REF_TO_PRIM) \ + template(java_lang_invoke_AdapterMethodHandle,OP_PRIM_TO_REF) \ + template(java_lang_invoke_AdapterMethodHandle,OP_SWAP_ARGS) \ + template(java_lang_invoke_AdapterMethodHandle,OP_ROT_ARGS) \ + template(java_lang_invoke_AdapterMethodHandle,OP_DUP_ARGS) \ + template(java_lang_invoke_AdapterMethodHandle,OP_DROP_ARGS) \ + template(java_lang_invoke_AdapterMethodHandle,OP_COLLECT_ARGS) \ + template(java_lang_invoke_AdapterMethodHandle,OP_SPREAD_ARGS) \ + template(java_lang_invoke_AdapterMethodHandle,OP_FLYBY) \ + template(java_lang_invoke_AdapterMethodHandle,OP_RICOCHET) \ + template(java_lang_invoke_AdapterMethodHandle,CONV_OP_LIMIT) \ + template(java_lang_invoke_AdapterMethodHandle,CONV_OP_MASK) \ + template(java_lang_invoke_AdapterMethodHandle,CONV_VMINFO_MASK) \ + template(java_lang_invoke_AdapterMethodHandle,CONV_VMINFO_SHIFT) \ + template(java_lang_invoke_AdapterMethodHandle,CONV_OP_SHIFT) \ + template(java_lang_invoke_AdapterMethodHandle,CONV_DEST_TYPE_SHIFT) \ + template(java_lang_invoke_AdapterMethodHandle,CONV_SRC_TYPE_SHIFT) \ + template(java_lang_invoke_AdapterMethodHandle,CONV_STACK_MOVE_SHIFT) \ + template(java_lang_invoke_AdapterMethodHandle,CONV_STACK_MOVE_MASK) \ /*end*/ #define ONE_PLUS(scope,value) 1+ @@ -2386,7 +2387,7 @@ #undef EACH_NAMED_CON #endif -JVM_ENTRY(jint, MHI_getNamedCon(JNIEnv *env, jobject igcls, jint which, jobjectArray box_jh)) { +JVM_ENTRY(jint, MHN_getNamedCon(JNIEnv *env, jobject igcls, jint which, jobjectArray box_jh)) { #ifndef PRODUCT if (which >= 0 && which < con_value_count) { int con = con_values[which]; @@ -2406,7 +2407,7 @@ JVM_END // void init(MemberName self, AccessibleObject ref) -JVM_ENTRY(void, MHI_init_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jobject target_jh)) { +JVM_ENTRY(void, MHN_init_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jobject target_jh)) { if (mname_jh == NULL || target_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh)); oop target_oop = JNIHandles::resolve_non_null(target_jh); @@ -2415,7 +2416,7 @@ JVM_END // void expand(MemberName self) -JVM_ENTRY(void, MHI_expand_Mem(JNIEnv *env, jobject igcls, jobject mname_jh)) { +JVM_ENTRY(void, MHN_expand_Mem(JNIEnv *env, jobject igcls, jobject mname_jh)) { if (mname_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh)); MethodHandles::expand_MemberName(mname, 0, CHECK); @@ -2423,14 +2424,14 @@ JVM_END // void resolve(MemberName self, Class caller) -JVM_ENTRY(void, MHI_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jclass caller_jh)) { +JVM_ENTRY(void, MHN_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jclass caller_jh)) { if (mname_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh)); // The trusted Java code that calls this method should already have performed // access checks on behalf of the given caller. But, we can verify this. if (VerifyMethodHandles && caller_jh != NULL) { - klassOop reference_klass = java_lang_Class::as_klassOop(sun_dyn_MemberName::clazz(mname())); + klassOop reference_klass = java_lang_Class::as_klassOop(java_lang_invoke_MemberName::clazz(mname())); if (reference_klass != NULL) { // Emulate LinkResolver::check_klass_accessability. klassOop caller = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(caller_jh)); @@ -2448,7 +2449,7 @@ // static native int getMembers(Class defc, String matchName, String matchSig, // int matchFlags, Class caller, int skip, MemberName[] results); -JVM_ENTRY(jint, MHI_getMembers(JNIEnv *env, jobject igcls, +JVM_ENTRY(jint, MHN_getMembers(JNIEnv *env, jobject igcls, jclass clazz_jh, jstring name_jh, jstring sig_jh, int mflags, jclass caller_jh, jint skip, jobjectArray results_jh)) { if (clazz_jh == NULL || results_jh == NULL) return -1; @@ -2487,14 +2488,14 @@ } JVM_END -JVM_ENTRY(void, MHI_registerBootstrap(JNIEnv *env, jobject igcls, jclass caller_jh, jobject bsm_jh)) { +JVM_ENTRY(void, MHN_registerBootstrap(JNIEnv *env, jobject igcls, jclass caller_jh, jobject bsm_jh)) { instanceKlassHandle ik = MethodHandles::resolve_instance_klass(caller_jh, THREAD); if (!AllowTransitionalJSR292) { THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "registerBootstrapMethod is only supported in JSR 292 EDR"); } ik->link_class(CHECK); - if (!java_dyn_MethodHandle::is_instance(JNIHandles::resolve(bsm_jh))) { + if (!java_lang_invoke_MethodHandle::is_instance(JNIHandles::resolve(bsm_jh))) { THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "method handle"); } const char* err = NULL; @@ -2522,29 +2523,28 @@ } JVM_END -JVM_ENTRY(jobject, MHI_getBootstrap(JNIEnv *env, jobject igcls, jclass caller_jh)) { +JVM_ENTRY(jobject, MHN_getBootstrap(JNIEnv *env, jobject igcls, jclass caller_jh)) { + if (!AllowTransitionalJSR292) + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "getBootstrap: transitional only"); instanceKlassHandle ik = MethodHandles::resolve_instance_klass(caller_jh, THREAD); return JNIHandles::make_local(THREAD, ik->bootstrap_method()); } JVM_END -JVM_ENTRY(void, MHI_setCallSiteTarget(JNIEnv *env, jobject igcls, jobject site_jh, jobject target_jh)) { - // No special action required, yet. - oop site_oop = JNIHandles::resolve(site_jh); - if (!java_dyn_CallSite::is_instance(site_oop)) - THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "not a CallSite"); - java_dyn_CallSite::set_target(site_oop, JNIHandles::resolve(target_jh)); +JVM_ENTRY(void, MHN_setCallSiteTarget(JNIEnv *env, jobject igcls, jobject site_jh, jobject target_jh)) { + if (!AllowTransitionalJSR292) + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "setCallSite: transitional only"); } JVM_END /// JVM_RegisterMethodHandleMethods -#define ADR "J" - #define LANG "Ljava/lang/" -#define JDYN "Ljava/dyn/" -#define IDYN "Lsun/dyn/" +#define JLINV "Ljava/lang/invoke/" /* standard package */ +#define JDYN "Ljava/dyn/" /* alternative package to JLINV if AllowTransitionalJSR292 */ +#define IDYN "Lsun/dyn/" /* alternative package to JDYN if AllowTransitionalJSR292 */ +// FIXME: After AllowTransitionalJSR292 is removed, replace JDYN and IDYN by JLINV. #define OBJ LANG"Object;" #define CLS LANG"Class;" @@ -2552,7 +2552,6 @@ #define CST JDYN"CallSite;" #define MT JDYN"MethodType;" #define MH JDYN"MethodHandle;" -#define MHI IDYN"MethodHandleImpl;" #define MEM IDYN"MemberName;" #define AMH IDYN"AdapterMethodHandle;" #define BMH IDYN"BoundMethodHandle;" @@ -2561,32 +2560,58 @@ #define CC (char*) /*cast a literal from (const char*)*/ #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) -// These are the native methods on sun.dyn.MethodHandleNatives. +// These are the native methods on sun.invoke.MethodHandleNatives. static JNINativeMethod methods[] = { // void init(MemberName self, AccessibleObject ref) - {CC"init", CC"("AMH""MH"I)V", FN_PTR(MHI_init_AMH)}, - {CC"init", CC"("BMH""OBJ"I)V", FN_PTR(MHI_init_BMH)}, - {CC"init", CC"("DMH""OBJ"Z"CLS")V", FN_PTR(MHI_init_DMH)}, - {CC"init", CC"("MT")V", FN_PTR(MHI_init_MT)}, - {CC"init", CC"("MEM""OBJ")V", FN_PTR(MHI_init_Mem)}, - {CC"expand", CC"("MEM")V", FN_PTR(MHI_expand_Mem)}, - {CC"resolve", CC"("MEM""CLS")V", FN_PTR(MHI_resolve_Mem)}, - {CC"getTarget", CC"("MH"I)"OBJ, FN_PTR(MHI_getTarget)}, - {CC"getConstant", CC"(I)I", FN_PTR(MHI_getConstant)}, + {CC"init", CC"("AMH""MH"I)V", FN_PTR(MHN_init_AMH)}, + {CC"init", CC"("BMH""OBJ"I)V", FN_PTR(MHN_init_BMH)}, + {CC"init", CC"("DMH""OBJ"Z"CLS")V", FN_PTR(MHN_init_DMH)}, + {CC"init", CC"("MT")V", FN_PTR(MHN_init_MT)}, + {CC"init", CC"("MEM""OBJ")V", FN_PTR(MHN_init_Mem)}, + {CC"expand", CC"("MEM")V", FN_PTR(MHN_expand_Mem)}, + {CC"resolve", CC"("MEM""CLS")V", FN_PTR(MHN_resolve_Mem)}, + {CC"getTarget", CC"("MH"I)"OBJ, FN_PTR(MHN_getTarget)}, + {CC"getConstant", CC"(I)I", FN_PTR(MHN_getConstant)}, // static native int getNamedCon(int which, Object[] name) - {CC"getNamedCon", CC"(I["OBJ")I", FN_PTR(MHI_getNamedCon)}, + {CC"getNamedCon", CC"(I["OBJ")I", FN_PTR(MHN_getNamedCon)}, // static native int getMembers(Class defc, String matchName, String matchSig, // int matchFlags, Class caller, int skip, MemberName[] results); - {CC"getMembers", CC"("CLS""STRG""STRG"I"CLS"I["MEM")I", FN_PTR(MHI_getMembers)} + {CC"getMembers", CC"("CLS""STRG""STRG"I"CLS"I["MEM")I", FN_PTR(MHN_getMembers)} }; // More entry points specifically for EnableInvokeDynamic. +// FIXME: Remove methods2 after AllowTransitionalJSR292 is removed. static JNINativeMethod methods2[] = { - {CC"registerBootstrap", CC"("CLS MH")V", FN_PTR(MHI_registerBootstrap)}, - {CC"getBootstrap", CC"("CLS")"MH, FN_PTR(MHI_getBootstrap)}, - {CC"setCallSiteTarget", CC"("CST MH")V", FN_PTR(MHI_setCallSiteTarget)} + {CC"registerBootstrap", CC"("CLS MH")V", FN_PTR(MHN_registerBootstrap)}, + {CC"getBootstrap", CC"("CLS")"MH, FN_PTR(MHN_getBootstrap)}, + {CC"setCallSiteTarget", CC"("CST MH")V", FN_PTR(MHN_setCallSiteTarget)} }; +static void hack_signatures(JNINativeMethod* methods, jint num_methods, const char* from_sig, const char* to_sig) { + for (int i = 0; i < num_methods; i++) { + const char* sig = methods[i].signature; + if (!strstr(sig, from_sig)) continue; + size_t buflen = strlen(sig) + 100; + char* buf = NEW_C_HEAP_ARRAY(char, buflen); + char* bufp = buf; + const char* sigp = sig; + size_t from_len = strlen(from_sig), to_len = strlen(to_sig); + while (*sigp != '\0') { + assert(bufp < buf + buflen - to_len - 1, "oob"); + if (strncmp(sigp, from_sig, from_len) != 0) { + *bufp++ = *sigp++; + } else { + strcpy(bufp, to_sig); + bufp += to_len; + sigp += from_len; + } + } + *bufp = '\0'; + methods[i].signature = buf; // replace with new signature + if (TraceMethodHandles) + tty->print_cr("MethodHandleNatives: %s: change signature %s => %s", methods[i].name, sig, buf); + } +} // This one function is exported, used by NativeLookup. @@ -2600,45 +2625,78 @@ return; // bind nothing } + if (SystemDictionary::MethodHandleNatives_klass() != NULL && + SystemDictionary::MethodHandleNatives_klass() != java_lang_Class::as_klassOop(JNIHandles::resolve(MHN_class))) { + warning("multiple versions of MethodHandleNatives in boot classpath; consider using -XX:+PreferTransitionalJSR292"); + THROW_MSG(vmSymbols::java_lang_InternalError(), "multiple versions of MethodHandleNatives in boot classpath; consider using -XX:+PreferTransitionalJSR292"); + } + bool enable_MH = true; - { + // Loop control. FIXME: Replace by dead reckoning after AllowTransitionalJSR292 is removed. + bool registered_natives = false; + bool try_plain = true, try_JDYN = true, try_IDYN = true; + for (;;) { ThreadToNativeFromVM ttnfv(thread); + if (try_plain) { try_plain = false; } + else if (try_JDYN) { try_JDYN = false; hack_signatures(methods, sizeof(methods)/sizeof(JNINativeMethod), IDYN, JDYN); } + else if (try_IDYN) { try_IDYN = false; hack_signatures(methods, sizeof(methods)/sizeof(JNINativeMethod), JDYN, JLINV); } + else { break; } int status = env->RegisterNatives(MHN_class, methods, sizeof(methods)/sizeof(JNINativeMethod)); if (env->ExceptionOccurred()) { - MethodHandles::set_enabled(false); - warning("JSR 292 method handle code is mismatched to this JVM. Disabling support."); - enable_MH = false; env->ExceptionClear(); + // and try again... + } else { + registered_natives = true; + break; } } + if (!registered_natives) { + MethodHandles::set_enabled(false); + warning("JSR 292 method handle code is mismatched to this JVM. Disabling support."); + enable_MH = false; + } if (enable_MH) { + bool found_raise_exception = false; + KlassHandle MHN_klass = SystemDictionaryHandles::MethodHandleNatives_klass(); KlassHandle MHI_klass = SystemDictionaryHandles::MethodHandleImpl_klass(); - if (MHI_klass.not_null()) { + // Loop control. FIXME: Replace by dead reckoning after AllowTransitionalJSR292 is removed. + bool try_MHN = true, try_MHI = AllowTransitionalJSR292; + for (;;) { + KlassHandle try_klass; + if (try_MHN) { try_MHN = false; try_klass = MHN_klass; } + else if (try_MHI) { try_MHI = false; try_klass = MHI_klass; } + else { break; } + if (try_klass.is_null()) continue; TempNewSymbol raiseException_name = SymbolTable::new_symbol("raiseException", CHECK); TempNewSymbol raiseException_sig = SymbolTable::new_symbol("(ILjava/lang/Object;Ljava/lang/Object;)V", CHECK); - methodOop raiseException_method = instanceKlass::cast(MHI_klass->as_klassOop()) + methodOop raiseException_method = instanceKlass::cast(try_klass->as_klassOop()) ->find_method(raiseException_name, raiseException_sig); if (raiseException_method != NULL && raiseException_method->is_static()) { MethodHandles::set_raise_exception_method(raiseException_method); - } else { - warning("JSR 292 method handle code is mismatched to this JVM. Disabling support."); - enable_MH = false; + found_raise_exception = true; + break; } - } else { + } + if (!found_raise_exception) { + warning("JSR 292 method handle code is mismatched to this JVM. Disabling support."); enable_MH = false; } } if (enable_MH) { - // We need to link the MethodHandleImpl klass before we generate - // the method handle adapters as the _raise_exception adapter uses - // one of its methods (and its c2i-adapter). - KlassHandle k = SystemDictionaryHandles::MethodHandleImpl_klass(); - instanceKlass* ik = instanceKlass::cast(k()); - ik->link_class(CHECK); + if (AllowTransitionalJSR292) { + // We need to link the MethodHandleImpl klass before we generate + // the method handle adapters as the _raise_exception adapter uses + // one of its methods (and its c2i-adapter). + klassOop k = SystemDictionary::MethodHandleImpl_klass(); + if (k != NULL) { + instanceKlass* ik = instanceKlass::cast(k); + ik->link_class(CHECK); + } + } MethodHandles::generate_adapters(); MethodHandles::set_enabled(true); @@ -2649,16 +2707,14 @@ return; // bind nothing } - { + if (AllowTransitionalJSR292) { ThreadToNativeFromVM ttnfv(thread); int status = env->RegisterNatives(MHN_class, methods2, sizeof(methods2)/sizeof(JNINativeMethod)); if (env->ExceptionOccurred()) { - MethodHandles::set_enabled(false); - warning("JSR 292 method handle code is mismatched to this JVM. Disabling support."); + // Don't do this, since it's too late: + // MethodHandles::set_enabled(false) env->ExceptionClear(); - } else { - MethodHandles::set_enabled(true); } } } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/prims/methodHandles.hpp --- a/src/share/vm/prims/methodHandles.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/prims/methodHandles.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -37,8 +37,8 @@ class MethodHandles: AllStatic { // JVM support for MethodHandle, MethodType, and related types - // in java.dyn and java.dyn.hotspot. - // See also javaClasses for layouts java_dyn_Method{Handle,Type,Type::Form}. + // in java.lang.invoke and sun.invoke. + // See also javaClasses for layouts java_lang_invoke_Method{Handle,Type,Type::Form}. public: enum EntryKind { _raise_exception, // stub for error generation from other stubs @@ -54,21 +54,21 @@ _bound_long_direct_mh, _adapter_mh_first, // adapter sequence goes here... - _adapter_retype_only = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_RETYPE_ONLY, - _adapter_retype_raw = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_RETYPE_RAW, - _adapter_check_cast = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_CHECK_CAST, - _adapter_prim_to_prim = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_PRIM_TO_PRIM, - _adapter_ref_to_prim = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_REF_TO_PRIM, - _adapter_prim_to_ref = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_PRIM_TO_REF, - _adapter_swap_args = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_SWAP_ARGS, - _adapter_rot_args = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_ROT_ARGS, - _adapter_dup_args = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_DUP_ARGS, - _adapter_drop_args = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_DROP_ARGS, - _adapter_collect_args = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_COLLECT_ARGS, - _adapter_spread_args = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_SPREAD_ARGS, - _adapter_flyby = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_FLYBY, - _adapter_ricochet = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_RICOCHET, - _adapter_mh_last = _adapter_mh_first + sun_dyn_AdapterMethodHandle::CONV_OP_LIMIT - 1, + _adapter_retype_only = _adapter_mh_first + java_lang_invoke_AdapterMethodHandle::OP_RETYPE_ONLY, + _adapter_retype_raw = _adapter_mh_first + java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW, + _adapter_check_cast = _adapter_mh_first + java_lang_invoke_AdapterMethodHandle::OP_CHECK_CAST, + _adapter_prim_to_prim = _adapter_mh_first + java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_PRIM, + _adapter_ref_to_prim = _adapter_mh_first + java_lang_invoke_AdapterMethodHandle::OP_REF_TO_PRIM, + _adapter_prim_to_ref = _adapter_mh_first + java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_REF, + _adapter_swap_args = _adapter_mh_first + java_lang_invoke_AdapterMethodHandle::OP_SWAP_ARGS, + _adapter_rot_args = _adapter_mh_first + java_lang_invoke_AdapterMethodHandle::OP_ROT_ARGS, + _adapter_dup_args = _adapter_mh_first + java_lang_invoke_AdapterMethodHandle::OP_DUP_ARGS, + _adapter_drop_args = _adapter_mh_first + java_lang_invoke_AdapterMethodHandle::OP_DROP_ARGS, + _adapter_collect_args = _adapter_mh_first + java_lang_invoke_AdapterMethodHandle::OP_COLLECT_ARGS, + _adapter_spread_args = _adapter_mh_first + java_lang_invoke_AdapterMethodHandle::OP_SPREAD_ARGS, + _adapter_flyby = _adapter_mh_first + java_lang_invoke_AdapterMethodHandle::OP_FLYBY, + _adapter_ricochet = _adapter_mh_first + java_lang_invoke_AdapterMethodHandle::OP_RICOCHET, + _adapter_mh_last = _adapter_mh_first + java_lang_invoke_AdapterMethodHandle::CONV_OP_LIMIT - 1, // Optimized adapter types @@ -107,16 +107,16 @@ static void set_enabled(bool z); private: - enum { // import sun_dyn_AdapterMethodHandle::CONV_OP_* - CONV_OP_LIMIT = sun_dyn_AdapterMethodHandle::CONV_OP_LIMIT, - CONV_OP_MASK = sun_dyn_AdapterMethodHandle::CONV_OP_MASK, - CONV_VMINFO_MASK = sun_dyn_AdapterMethodHandle::CONV_VMINFO_MASK, - CONV_VMINFO_SHIFT = sun_dyn_AdapterMethodHandle::CONV_VMINFO_SHIFT, - CONV_OP_SHIFT = sun_dyn_AdapterMethodHandle::CONV_OP_SHIFT, - CONV_DEST_TYPE_SHIFT = sun_dyn_AdapterMethodHandle::CONV_DEST_TYPE_SHIFT, - CONV_SRC_TYPE_SHIFT = sun_dyn_AdapterMethodHandle::CONV_SRC_TYPE_SHIFT, - CONV_STACK_MOVE_SHIFT = sun_dyn_AdapterMethodHandle::CONV_STACK_MOVE_SHIFT, - CONV_STACK_MOVE_MASK = sun_dyn_AdapterMethodHandle::CONV_STACK_MOVE_MASK + enum { // import java_lang_invoke_AdapterMethodHandle::CONV_OP_* + CONV_OP_LIMIT = java_lang_invoke_AdapterMethodHandle::CONV_OP_LIMIT, + CONV_OP_MASK = java_lang_invoke_AdapterMethodHandle::CONV_OP_MASK, + CONV_VMINFO_MASK = java_lang_invoke_AdapterMethodHandle::CONV_VMINFO_MASK, + CONV_VMINFO_SHIFT = java_lang_invoke_AdapterMethodHandle::CONV_VMINFO_SHIFT, + CONV_OP_SHIFT = java_lang_invoke_AdapterMethodHandle::CONV_OP_SHIFT, + CONV_DEST_TYPE_SHIFT = java_lang_invoke_AdapterMethodHandle::CONV_DEST_TYPE_SHIFT, + CONV_SRC_TYPE_SHIFT = java_lang_invoke_AdapterMethodHandle::CONV_SRC_TYPE_SHIFT, + CONV_STACK_MOVE_SHIFT = java_lang_invoke_AdapterMethodHandle::CONV_STACK_MOVE_SHIFT, + CONV_STACK_MOVE_MASK = java_lang_invoke_AdapterMethodHandle::CONV_STACK_MOVE_MASK }; static bool _enabled; @@ -471,7 +471,7 @@ }; -// Access methods for the "entry" field of a java.dyn.MethodHandle. +// Access methods for the "entry" field of a java.lang.invoke.MethodHandle. // The field is primarily a jump target for compiled calls. // However, we squirrel away some nice pointers for other uses, // just before the jump target. diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/prims/nativeLookup.cpp --- a/src/share/vm/prims/nativeLookup.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/prims/nativeLookup.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -107,29 +107,30 @@ void JNICALL JVM_RegisterPerfMethods(JNIEnv *env, jclass perfclass); } +#define CC (char*) /* cast a literal from (const char*) */ +#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) + +static JNINativeMethod lookup_special_native_methods[] = { + // Next two functions only exist for compatibility with 1.3.1 and earlier. + { CC"Java_java_io_ObjectOutputStream_getPrimitiveFieldValues", NULL, FN_PTR(JVM_GetPrimitiveFieldValues) }, // intercept ObjectOutputStream getPrimitiveFieldValues for faster serialization + { CC"Java_java_io_ObjectInputStream_setPrimitiveFieldValues", NULL, FN_PTR(JVM_SetPrimitiveFieldValues) }, // intercept ObjectInputStream setPrimitiveFieldValues for faster serialization + + { CC"Java_sun_misc_Unsafe_registerNatives", NULL, FN_PTR(JVM_RegisterUnsafeMethods) }, + { CC"Java_java_lang_invoke_MethodHandleNatives_registerNatives", NULL, FN_PTR(JVM_RegisterMethodHandleMethods) }, + { CC"Java_sun_dyn_MethodHandleNatives_registerNatives", NULL, FN_PTR(JVM_RegisterMethodHandleMethods) }, // AllowTransitionalJSR292 + { CC"Java_java_dyn_MethodHandleNatives_registerNatives", NULL, FN_PTR(JVM_RegisterMethodHandleMethods) }, // AllowTransitionalJSR292 + { CC"Java_sun_misc_Perf_registerNatives", NULL, FN_PTR(JVM_RegisterPerfMethods) } +}; + static address lookup_special_native(char* jni_name) { - // NB: To ignore the jni prefix and jni postfix strstr is used matching. - if (!JDK_Version::is_gte_jdk14x_version()) { - // These functions only exist for compatibility with 1.3.1 and earlier - // Intercept ObjectOutputStream getPrimitiveFieldValues for faster serialization - if (strstr(jni_name, "Java_java_io_ObjectOutputStream_getPrimitiveFieldValues") != NULL) { - return CAST_FROM_FN_PTR(address, JVM_GetPrimitiveFieldValues); - } - // Intercept ObjectInputStream setPrimitiveFieldValues for faster serialization - if (strstr(jni_name, "Java_java_io_ObjectInputStream_setPrimitiveFieldValues") != NULL) { - return CAST_FROM_FN_PTR(address, JVM_SetPrimitiveFieldValues); + int i = !JDK_Version::is_gte_jdk14x_version() ? 0 : 2; // see comment in lookup_special_native_methods + int count = sizeof(lookup_special_native_methods) / sizeof(JNINativeMethod); + for (; i < count; i++) { + // NB: To ignore the jni prefix and jni postfix strstr is used matching. + if (strstr(jni_name, lookup_special_native_methods[i].name) != NULL) { + return CAST_FROM_FN_PTR(address, lookup_special_native_methods[i].fnPtr); } } - if (strstr(jni_name, "Java_sun_misc_Unsafe_registerNatives") != NULL) { - return CAST_FROM_FN_PTR(address, JVM_RegisterUnsafeMethods); - } - if (strstr(jni_name, "Java_sun_dyn_MethodHandleNatives_registerNatives") != NULL) { - return CAST_FROM_FN_PTR(address, JVM_RegisterMethodHandleMethods); - } - if (strstr(jni_name, "Java_sun_misc_Perf_registerNatives") != NULL) { - return CAST_FROM_FN_PTR(address, JVM_RegisterPerfMethods); - } - return NULL; } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/runtime/advancedThresholdPolicy.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/runtime/advancedThresholdPolicy.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -0,0 +1,450 @@ +/* +* Copyright (c) 2010, 2011 Oracle and/or its affiliates. All rights reserved. +* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. +*/ + +#include "precompiled.hpp" +#include "runtime/advancedThresholdPolicy.hpp" +#include "runtime/simpleThresholdPolicy.inline.hpp" + +#ifdef TIERED +// Print an event. +void AdvancedThresholdPolicy::print_specific(EventType type, methodHandle mh, methodHandle imh, + int bci, CompLevel level) { + tty->print(" rate: "); + if (mh->prev_time() == 0) tty->print("n/a"); + else tty->print("%f", mh->rate()); + + tty->print(" k: %.2lf,%.2lf", threshold_scale(CompLevel_full_profile, Tier3LoadFeedback), + threshold_scale(CompLevel_full_optimization, Tier4LoadFeedback)); + +} + +void AdvancedThresholdPolicy::initialize() { + // Turn on ergonomic compiler count selection + if (FLAG_IS_DEFAULT(CICompilerCountPerCPU) && FLAG_IS_DEFAULT(CICompilerCount)) { + FLAG_SET_DEFAULT(CICompilerCountPerCPU, true); + } + int count = CICompilerCount; + if (CICompilerCountPerCPU) { + // Simple log n seems to grow too slowly for tiered, try something faster: log n * log log n + int log_cpu = log2_intptr(os::active_processor_count()); + int loglog_cpu = log2_intptr(MAX2(log_cpu, 1)); + count = MAX2(log_cpu * loglog_cpu, 1) * 3 / 2; + } + + set_c1_count(MAX2(count / 3, 1)); + set_c2_count(MAX2(count - count / 3, 1)); + + // Some inlining tuning +#ifdef X86 + if (FLAG_IS_DEFAULT(InlineSmallCode)) { + FLAG_SET_DEFAULT(InlineSmallCode, 2000); + } +#endif + +#ifdef SPARC + if (FLAG_IS_DEFAULT(InlineSmallCode)) { + FLAG_SET_DEFAULT(InlineSmallCode, 2500); + } +#endif + + + set_start_time(os::javaTimeMillis()); +} + +// update_rate() is called from select_task() while holding a compile queue lock. +void AdvancedThresholdPolicy::update_rate(jlong t, methodOop m) { + if (is_old(m)) { + // We don't remove old methods from the queue, + // so we can just zero the rate. + m->set_rate(0); + return; + } + + // We don't update the rate if we've just came out of a safepoint. + // delta_s is the time since last safepoint in milliseconds. + jlong delta_s = t - SafepointSynchronize::end_of_last_safepoint(); + jlong delta_t = t - (m->prev_time() != 0 ? m->prev_time() : start_time()); // milliseconds since the last measurement + // How many events were there since the last time? + int event_count = m->invocation_count() + m->backedge_count(); + int delta_e = event_count - m->prev_event_count(); + + // We should be running for at least 1ms. + if (delta_s >= TieredRateUpdateMinTime) { + // And we must've taken the previous point at least 1ms before. + if (delta_t >= TieredRateUpdateMinTime && delta_e > 0) { + m->set_prev_time(t); + m->set_prev_event_count(event_count); + m->set_rate((float)delta_e / (float)delta_t); // Rate is events per millisecond + } else + if (delta_t > TieredRateUpdateMaxTime && delta_e == 0) { + // If nothing happened for 25ms, zero the rate. Don't modify prev values. + m->set_rate(0); + } + } +} + +// Check if this method has been stale from a given number of milliseconds. +// See select_task(). +bool AdvancedThresholdPolicy::is_stale(jlong t, jlong timeout, methodOop m) { + jlong delta_s = t - SafepointSynchronize::end_of_last_safepoint(); + jlong delta_t = t - m->prev_time(); + if (delta_t > timeout && delta_s > timeout) { + int event_count = m->invocation_count() + m->backedge_count(); + int delta_e = event_count - m->prev_event_count(); + // Return true if there were no events. + return delta_e == 0; + } + return false; +} + +// We don't remove old methods from the compile queue even if they have +// very low activity. See select_task(). +bool AdvancedThresholdPolicy::is_old(methodOop method) { + return method->invocation_count() > 50000 || method->backedge_count() > 500000; +} + +double AdvancedThresholdPolicy::weight(methodOop method) { + return (method->rate() + 1) * ((method->invocation_count() + 1) * (method->backedge_count() + 1)); +} + +// Apply heuristics and return true if x should be compiled before y +bool AdvancedThresholdPolicy::compare_methods(methodOop x, methodOop y) { + if (x->highest_comp_level() > y->highest_comp_level()) { + // recompilation after deopt + return true; + } else + if (x->highest_comp_level() == y->highest_comp_level()) { + if (weight(x) > weight(y)) { + return true; + } + } + return false; +} + +// Is method profiled enough? +bool AdvancedThresholdPolicy::is_method_profiled(methodOop method) { + methodDataOop mdo = method->method_data(); + if (mdo != NULL) { + int i = mdo->invocation_count_delta(); + int b = mdo->backedge_count_delta(); + return call_predicate_helper(i, b, 1); + } + return false; +} + +// Called with the queue locked and with at least one element +CompileTask* AdvancedThresholdPolicy::select_task(CompileQueue* compile_queue) { + CompileTask *max_task = NULL; + methodOop max_method; + jlong t = os::javaTimeMillis(); + // Iterate through the queue and find a method with a maximum rate. + for (CompileTask* task = compile_queue->first(); task != NULL;) { + CompileTask* next_task = task->next(); + methodOop method = (methodOop)JNIHandles::resolve(task->method_handle()); + methodDataOop mdo = method->method_data(); + update_rate(t, method); + if (max_task == NULL) { + max_task = task; + max_method = method; + } else { + // If a method has been stale for some time, remove it from the queue. + if (is_stale(t, TieredCompileTaskTimeout, method) && !is_old(method)) { + if (PrintTieredEvents) { + print_event(KILL, method, method, task->osr_bci(), (CompLevel)task->comp_level()); + } + CompileTaskWrapper ctw(task); // Frees the task + compile_queue->remove(task); + method->clear_queued_for_compilation(); + task = next_task; + continue; + } + + // Select a method with a higher rate + if (compare_methods(method, max_method)) { + max_task = task; + max_method = method; + } + } + task = next_task; + } + + if (max_task->comp_level() == CompLevel_full_profile && is_method_profiled(max_method)) { + max_task->set_comp_level(CompLevel_limited_profile); + if (PrintTieredEvents) { + print_event(UPDATE, max_method, max_method, max_task->osr_bci(), (CompLevel)max_task->comp_level()); + } + } + + return max_task; +} + +double AdvancedThresholdPolicy::threshold_scale(CompLevel level, int feedback_k) { + double queue_size = CompileBroker::queue_size(level); + int comp_count = compiler_count(level); + double k = queue_size / (feedback_k * comp_count) + 1; + return k; +} + +// Call and loop predicates determine whether a transition to a higher +// compilation level should be performed (pointers to predicate functions +// are passed to common()). +// Tier?LoadFeedback is basically a coefficient that determines of +// how many methods per compiler thread can be in the queue before +// the threshold values double. +bool AdvancedThresholdPolicy::loop_predicate(int i, int b, CompLevel cur_level) { + switch(cur_level) { + case CompLevel_none: + case CompLevel_limited_profile: { + double k = threshold_scale(CompLevel_full_profile, Tier3LoadFeedback); + return loop_predicate_helper(i, b, k); + } + case CompLevel_full_profile: { + double k = threshold_scale(CompLevel_full_optimization, Tier4LoadFeedback); + return loop_predicate_helper(i, b, k); + } + default: + return true; + } +} + +bool AdvancedThresholdPolicy::call_predicate(int i, int b, CompLevel cur_level) { + switch(cur_level) { + case CompLevel_none: + case CompLevel_limited_profile: { + double k = threshold_scale(CompLevel_full_profile, Tier3LoadFeedback); + return call_predicate_helper(i, b, k); + } + case CompLevel_full_profile: { + double k = threshold_scale(CompLevel_full_optimization, Tier4LoadFeedback); + return call_predicate_helper(i, b, k); + } + default: + return true; + } +} + +// If a method is old enough and is still in the interpreter we would want to +// start profiling without waiting for the compiled method to arrive. +// We also take the load on compilers into the account. +bool AdvancedThresholdPolicy::should_create_mdo(methodOop method, CompLevel cur_level) { + if (cur_level == CompLevel_none && + CompileBroker::queue_size(CompLevel_full_optimization) <= + Tier3DelayOn * compiler_count(CompLevel_full_optimization)) { + int i = method->invocation_count(); + int b = method->backedge_count(); + double k = Tier0ProfilingStartPercentage / 100.0; + return call_predicate_helper(i, b, k) || loop_predicate_helper(i, b, k); + } + return false; +} + +// Create MDO if necessary. +void AdvancedThresholdPolicy::create_mdo(methodHandle mh, TRAPS) { + if (mh->is_native() || mh->is_abstract() || mh->is_accessor()) return; + if (mh->method_data() == NULL) { + methodOopDesc::build_interpreter_method_data(mh, THREAD); + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; + } + } +} + + +/* + * Method states: + * 0 - interpreter (CompLevel_none) + * 1 - pure C1 (CompLevel_simple) + * 2 - C1 with invocation and backedge counting (CompLevel_limited_profile) + * 3 - C1 with full profiling (CompLevel_full_profile) + * 4 - C2 (CompLevel_full_optimization) + * + * Common state transition patterns: + * a. 0 -> 3 -> 4. + * The most common path. But note that even in this straightforward case + * profiling can start at level 0 and finish at level 3. + * + * b. 0 -> 2 -> 3 -> 4. + * This case occures when the load on C2 is deemed too high. So, instead of transitioning + * into state 3 directly and over-profiling while a method is in the C2 queue we transition to + * level 2 and wait until the load on C2 decreases. This path is disabled for OSRs. + * + * c. 0 -> (3->2) -> 4. + * In this case we enqueue a method for compilation at level 3, but the C1 queue is long enough + * to enable the profiling to fully occur at level 0. In this case we change the compilation level + * of the method to 2, because it'll allow it to run much faster without full profiling while c2 + * is compiling. + * + * d. 0 -> 3 -> 1 or 0 -> 2 -> 1. + * After a method was once compiled with C1 it can be identified as trivial and be compiled to + * level 1. These transition can also occur if a method can't be compiled with C2 but can with C1. + * + * e. 0 -> 4. + * This can happen if a method fails C1 compilation (it will still be profiled in the interpreter) + * or because of a deopt that didn't require reprofiling (compilation won't happen in this case because + * the compiled version already exists). + * + * Note that since state 0 can be reached from any other state via deoptimization different loops + * are possible. + * + */ + +// Common transition function. Given a predicate determines if a method should transition to another level. +CompLevel AdvancedThresholdPolicy::common(Predicate p, methodOop method, CompLevel cur_level) { + if (is_trivial(method)) return CompLevel_simple; + + CompLevel next_level = cur_level; + int i = method->invocation_count(); + int b = method->backedge_count(); + + switch(cur_level) { + case CompLevel_none: + // If we were at full profile level, would we switch to full opt? + if (common(p, method, CompLevel_full_profile) == CompLevel_full_optimization) { + next_level = CompLevel_full_optimization; + } else if ((this->*p)(i, b, cur_level)) { + // C1-generated fully profiled code is about 30% slower than the limited profile + // code that has only invocation and backedge counters. The observation is that + // if C2 queue is large enough we can spend too much time in the fully profiled code + // while waiting for C2 to pick the method from the queue. To alleviate this problem + // we introduce a feedback on the C2 queue size. If the C2 queue is sufficiently long + // we choose to compile a limited profiled version and then recompile with full profiling + // when the load on C2 goes down. + if (CompileBroker::queue_size(CompLevel_full_optimization) > + Tier3DelayOn * compiler_count(CompLevel_full_optimization)) { + next_level = CompLevel_limited_profile; + } else { + next_level = CompLevel_full_profile; + } + } + break; + case CompLevel_limited_profile: + if (is_method_profiled(method)) { + // Special case: we got here because this method was fully profiled in the interpreter. + next_level = CompLevel_full_optimization; + } else { + methodDataOop mdo = method->method_data(); + if (mdo != NULL) { + if (mdo->would_profile()) { + if (CompileBroker::queue_size(CompLevel_full_optimization) <= + Tier3DelayOff * compiler_count(CompLevel_full_optimization) && + (this->*p)(i, b, cur_level)) { + next_level = CompLevel_full_profile; + } + } else { + next_level = CompLevel_full_optimization; + } + } + } + break; + case CompLevel_full_profile: + { + methodDataOop mdo = method->method_data(); + if (mdo != NULL) { + if (mdo->would_profile()) { + int mdo_i = mdo->invocation_count_delta(); + int mdo_b = mdo->backedge_count_delta(); + if ((this->*p)(mdo_i, mdo_b, cur_level)) { + next_level = CompLevel_full_optimization; + } + } else { + next_level = CompLevel_full_optimization; + } + } + } + break; + } + return next_level; +} + +// Determine if a method should be compiled with a normal entry point at a different level. +CompLevel AdvancedThresholdPolicy::call_event(methodOop method, CompLevel cur_level) { + CompLevel osr_level = (CompLevel) method->highest_osr_comp_level(); + CompLevel next_level = common(&AdvancedThresholdPolicy::call_predicate, method, cur_level); + + // If OSR method level is greater than the regular method level, the levels should be + // equalized by raising the regular method level in order to avoid OSRs during each + // invocation of the method. + if (osr_level == CompLevel_full_optimization && cur_level == CompLevel_full_profile) { + methodDataOop mdo = method->method_data(); + guarantee(mdo != NULL, "MDO should not be NULL"); + if (mdo->invocation_count() >= 1) { + next_level = CompLevel_full_optimization; + } + } else { + next_level = MAX2(osr_level, next_level); + } + + return next_level; +} + +// Determine if we should do an OSR compilation of a given method. +CompLevel AdvancedThresholdPolicy::loop_event(methodOop method, CompLevel cur_level) { + if (cur_level == CompLevel_none) { + // If there is a live OSR method that means that we deopted to the interpreter + // for the transition. + CompLevel osr_level = (CompLevel)method->highest_osr_comp_level(); + if (osr_level > CompLevel_none) { + return osr_level; + } + } + return common(&AdvancedThresholdPolicy::loop_predicate, method, cur_level); +} + +// Update the rate and submit compile +void AdvancedThresholdPolicy::submit_compile(methodHandle mh, int bci, CompLevel level, TRAPS) { + int hot_count = (bci == InvocationEntryBci) ? mh->invocation_count() : mh->backedge_count(); + update_rate(os::javaTimeMillis(), mh()); + CompileBroker::compile_method(mh, bci, level, mh, hot_count, "tiered", THREAD); +} + + +// Handle the invocation event. +void AdvancedThresholdPolicy::method_invocation_event(methodHandle mh, methodHandle imh, + CompLevel level, TRAPS) { + if (should_create_mdo(mh(), level)) { + create_mdo(mh, THREAD); + } + if (is_compilation_enabled() && !CompileBroker::compilation_is_in_queue(mh, InvocationEntryBci)) { + CompLevel next_level = call_event(mh(), level); + if (next_level != level) { + compile(mh, InvocationEntryBci, next_level, THREAD); + } + } +} + +// Handle the back branch event. Notice that we can compile the method +// with a regular entry from here. +void AdvancedThresholdPolicy::method_back_branch_event(methodHandle mh, methodHandle imh, + int bci, CompLevel level, TRAPS) { + if (should_create_mdo(mh(), level)) { + create_mdo(mh, THREAD); + } + + // If the method is already compiling, quickly bail out. + if (is_compilation_enabled() && !CompileBroker::compilation_is_in_queue(mh, bci)) { + // Use loop event as an opportinity to also check there's been + // enough calls. + CompLevel cur_level = comp_level(mh()); + CompLevel next_level = call_event(mh(), cur_level); + CompLevel next_osr_level = loop_event(mh(), level); + if (next_osr_level == CompLevel_limited_profile) { + next_osr_level = CompLevel_full_profile; // OSRs are supposed to be for very hot methods. + } + next_level = MAX2(next_level, + next_osr_level < CompLevel_full_optimization ? next_osr_level : cur_level); + bool is_compiling = false; + if (next_level != cur_level) { + compile(mh, InvocationEntryBci, next_level, THREAD); + is_compiling = true; + } + + // Do the OSR version + if (!is_compiling && next_osr_level != level) { + compile(mh, bci, next_osr_level, THREAD); + } + } +} + +#endif // TIERED diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/runtime/advancedThresholdPolicy.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/runtime/advancedThresholdPolicy.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -0,0 +1,207 @@ +/* +* Copyright (c) 2010, 2011 Oracle and/or its affiliates. All rights reserved. +* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. +*/ + +#ifndef SHARE_VM_RUNTIME_ADVANCEDTHRESHOLDPOLICY_HPP +#define SHARE_VM_RUNTIME_ADVANCEDTHRESHOLDPOLICY_HPP + +#include "runtime/simpleThresholdPolicy.hpp" + +#ifdef TIERED +class CompileTask; +class CompileQueue; + +/* + * The system supports 5 execution levels: + * * level 0 - interpreter + * * level 1 - C1 with full optimization (no profiling) + * * level 2 - C1 with invocation and backedge counters + * * level 3 - C1 with full profiling (level 2 + MDO) + * * level 4 - C2 + * + * Levels 0, 2 and 3 periodically notify the runtime about the current value of the counters + * (invocation counters and backedge counters). The frequency of these notifications is + * different at each level. These notifications are used by the policy to decide what transition + * to make. + * + * Execution starts at level 0 (interpreter), then the policy can decide either to compile the + * method at level 3 or level 2. The decision is based on the following factors: + * 1. The length of the C2 queue determines the next level. The observation is that level 2 + * is generally faster than level 3 by about 30%, therefore we would want to minimize the time + * a method spends at level 3. We should only spend the time at level 3 that is necessary to get + * adequate profiling. So, if the C2 queue is long enough it is more beneficial to go first to + * level 2, because if we transitioned to level 3 we would be stuck there until our C2 compile + * request makes its way through the long queue. When the load on C2 recedes we are going to + * recompile at level 3 and start gathering profiling information. + * 2. The length of C1 queue is used to dynamically adjust the thresholds, so as to introduce + * additional filtering if the compiler is overloaded. The rationale is that by the time a + * method gets compiled it can become unused, so it doesn't make sense to put too much onto the + * queue. + * + * After profiling is completed at level 3 the transition is made to level 4. Again, the length + * of the C2 queue is used as a feedback to adjust the thresholds. + * + * After the first C1 compile some basic information is determined about the code like the number + * of the blocks and the number of the loops. Based on that it can be decided that a method + * is trivial and compiling it with C1 will yield the same code. In this case the method is + * compiled at level 1 instead of 4. + * + * We also support profiling at level 0. If C1 is slow enough to produce the level 3 version of + * the code and the C2 queue is sufficiently small we can decide to start profiling in the + * interpreter (and continue profiling in the compiled code once the level 3 version arrives). + * If the profiling at level 0 is fully completed before level 3 version is produced, a level 2 + * version is compiled instead in order to run faster waiting for a level 4 version. + * + * Compile queues are implemented as priority queues - for each method in the queue we compute + * the event rate (the number of invocation and backedge counter increments per unit of time). + * When getting an element off the queue we pick the one with the largest rate. Maintaining the + * rate also allows us to remove stale methods (the ones that got on the queue but stopped + * being used shortly after that). +*/ + +/* Command line options: + * - Tier?InvokeNotifyFreqLog and Tier?BackedgeNotifyFreqLog control the frequency of method + * invocation and backedge notifications. Basically every n-th invocation or backedge a mutator thread + * makes a call into the runtime. + * + * - Tier?CompileThreshold, Tier?BackEdgeThreshold, Tier?MinInvocationThreshold control + * compilation thresholds. + * Level 2 thresholds are not used and are provided for option-compatibility and potential future use. + * Other thresholds work as follows: + * + * Transition from interpreter (level 0) to C1 with full profiling (level 3) happens when + * the following predicate is true (X is the level): + * + * i > TierXInvocationThreshold * s || (i > TierXMinInvocationThreshold * s && i + b > TierXCompileThreshold * s), + * + * where $i$ is the number of method invocations, $b$ number of backedges and $s$ is the scaling + * coefficient that will be discussed further. + * The intuition is to equalize the time that is spend profiling each method. + * The same predicate is used to control the transition from level 3 to level 4 (C2). It should be + * noted though that the thresholds are relative. Moreover i and b for the 0->3 transition come + * from methodOop and for 3->4 transition they come from MDO (since profiled invocations are + * counted separately). + * + * OSR transitions are controlled simply with b > TierXBackEdgeThreshold * s predicates. + * + * - Tier?LoadFeedback options are used to automatically scale the predicates described above depending + * on the compiler load. The scaling coefficients are computed as follows: + * + * s = queue_size_X / (TierXLoadFeedback * compiler_count_X) + 1, + * + * where queue_size_X is the current size of the compiler queue of level X, and compiler_count_X + * is the number of level X compiler threads. + * + * Basically these parameters describe how many methods should be in the compile queue + * per compiler thread before the scaling coefficient increases by one. + * + * This feedback provides the mechanism to automatically control the flow of compilation requests + * depending on the machine speed, mutator load and other external factors. + * + * - Tier3DelayOn and Tier3DelayOff parameters control another important feedback loop. + * Consider the following observation: a method compiled with full profiling (level 3) + * is about 30% slower than a method at level 2 (just invocation and backedge counters, no MDO). + * Normally, the following transitions will occur: 0->3->4. The problem arises when the C2 queue + * gets congested and the 3->4 transition is delayed. While the method is the C2 queue it continues + * executing at level 3 for much longer time than is required by the predicate and at suboptimal speed. + * The idea is to dynamically change the behavior of the system in such a way that if a substantial + * load on C2 is detected we would first do the 0->2 transition allowing a method to run faster. + * And then when the load decreases to allow 2->3 transitions. + * + * Tier3Delay* parameters control this switching mechanism. + * Tier3DelayOn is the number of methods in the C2 queue per compiler thread after which the policy + * no longer does 0->3 transitions but does 0->2 transitions instead. + * Tier3DelayOff switches the original behavior back when the number of methods in the C2 queue + * per compiler thread falls below the specified amount. + * The hysteresis is necessary to avoid jitter. + * + * - TieredCompileTaskTimeout is the amount of time an idle method can spend in the compile queue. + * Basically, since we use the event rate d(i + b)/dt as a value of priority when selecting a method to + * compile from the compile queue, we also can detect stale methods for which the rate has been + * 0 for some time in the same iteration. Stale methods can appear in the queue when an application + * abruptly changes its behavior. + * + * - TieredStopAtLevel, is used mostly for testing. It allows to bypass the policy logic and stick + * to a given level. For example it's useful to set TieredStopAtLevel = 1 in order to compile everything + * with pure c1. + * + * - Tier0ProfilingStartPercentage allows the interpreter to start profiling when the inequalities in the + * 0->3 predicate are already exceeded by the given percentage but the level 3 version of the + * method is still not ready. We can even go directly from level 0 to 4 if c1 doesn't produce a compiled + * version in time. This reduces the overall transition to level 4 and decreases the startup time. + * Note that this behavior is also guarded by the Tier3Delay mechanism: when the c2 queue is too long + * these is not reason to start profiling prematurely. + * + * - TieredRateUpdateMinTime and TieredRateUpdateMaxTime are parameters of the rate computation. + * Basically, the rate is not computed more frequently than TieredRateUpdateMinTime and is considered + * to be zero if no events occurred in TieredRateUpdateMaxTime. + */ + + +class AdvancedThresholdPolicy : public SimpleThresholdPolicy { + jlong _start_time; + + // Call and loop predicates determine whether a transition to a higher compilation + // level should be performed (pointers to predicate functions are passed to common(). + // Predicates also take compiler load into account. + typedef bool (AdvancedThresholdPolicy::*Predicate)(int i, int b, CompLevel cur_level); + bool call_predicate(int i, int b, CompLevel cur_level); + bool loop_predicate(int i, int b, CompLevel cur_level); + // Common transition function. Given a predicate determines if a method should transition to another level. + CompLevel common(Predicate p, methodOop method, CompLevel cur_level); + // Transition functions. + // call_event determines if a method should be compiled at a different + // level with a regular invocation entry. + CompLevel call_event(methodOop method, CompLevel cur_level); + // loop_event checks if a method should be OSR compiled at a different + // level. + CompLevel loop_event(methodOop method, CompLevel cur_level); + // Has a method been long around? + // We don't remove old methods from the compile queue even if they have + // very low activity (see select_task()). + inline bool is_old(methodOop method); + // Was a given method inactive for a given number of milliseconds. + // If it is, we would remove it from the queue (see select_task()). + inline bool is_stale(jlong t, jlong timeout, methodOop m); + // Compute the weight of the method for the compilation scheduling + inline double weight(methodOop method); + // Apply heuristics and return true if x should be compiled before y + inline bool compare_methods(methodOop x, methodOop y); + // Compute event rate for a given method. The rate is the number of event (invocations + backedges) + // per millisecond. + inline void update_rate(jlong t, methodOop m); + // Compute threshold scaling coefficient + inline double threshold_scale(CompLevel level, int feedback_k); + // If a method is old enough and is still in the interpreter we would want to + // start profiling without waiting for the compiled method to arrive. This function + // determines whether we should do that. + inline bool should_create_mdo(methodOop method, CompLevel cur_level); + // Create MDO if necessary. + void create_mdo(methodHandle mh, TRAPS); + // Is method profiled enough? + bool is_method_profiled(methodOop method); + +protected: + void print_specific(EventType type, methodHandle mh, methodHandle imh, int bci, CompLevel level); + + void set_start_time(jlong t) { _start_time = t; } + jlong start_time() const { return _start_time; } + + // Submit a given method for compilation (and update the rate). + virtual void submit_compile(methodHandle mh, int bci, CompLevel level, TRAPS); + // event() from SimpleThresholdPolicy would call these. + virtual void method_invocation_event(methodHandle method, methodHandle inlinee, + CompLevel level, TRAPS); + virtual void method_back_branch_event(methodHandle method, methodHandle inlinee, + int bci, CompLevel level, TRAPS); +public: + AdvancedThresholdPolicy() : _start_time(0) { } + // Select task is called by CompileBroker. We should return a task or NULL. + virtual CompileTask* select_task(CompileQueue* compile_queue); + virtual void initialize(); +}; + +#endif // TIERED + +#endif // SHARE_VM_RUNTIME_ADVANCEDTHRESHOLDPOLICY_HPP diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/runtime/arguments.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -242,6 +242,7 @@ JDK_Version::jdk_update(6,24), JDK_Version::jdk(8) }, { "MaxLiveObjectEvacuationRatio", JDK_Version::jdk_update(6,24), JDK_Version::jdk(8) }, + { "ForceSharedSpaces", JDK_Version::jdk_update(6,25), JDK_Version::jdk(8) }, { NULL, JDK_Version(0), JDK_Version(0) } }; @@ -1003,31 +1004,10 @@ } } -void Arguments::check_compressed_oops_compat() { -#ifdef _LP64 - assert(UseCompressedOops, "Precondition"); - // Is it on by default or set on ergonomically - bool is_on_by_default = FLAG_IS_DEFAULT(UseCompressedOops) || FLAG_IS_ERGO(UseCompressedOops); - - // If dumping an archive or forcing its use, disable compressed oops if possible - if (DumpSharedSpaces || RequireSharedSpaces) { - if (is_on_by_default) { - FLAG_SET_DEFAULT(UseCompressedOops, false); - return; - } else { - vm_exit_during_initialization( - "Class Data Sharing is not supported with compressed oops yet", NULL); - } - } else if (UseSharedSpaces) { - // UseSharedSpaces is on by default. With compressed oops, we turn it off. - FLAG_SET_DEFAULT(UseSharedSpaces, false); - } -#endif -} - void Arguments::set_tiered_flags() { + // With tiered, set default policy to AdvancedThresholdPolicy, which is 3. if (FLAG_IS_DEFAULT(CompilationPolicyChoice)) { - FLAG_SET_DEFAULT(CompilationPolicyChoice, 2); + FLAG_SET_DEFAULT(CompilationPolicyChoice, 3); } if (CompilationPolicyChoice < 2) { vm_exit_during_initialization( @@ -1122,40 +1102,28 @@ set_parnew_gc_flags(); } + // MaxHeapSize is aligned down in collectorPolicy + size_t max_heap = align_size_down(MaxHeapSize, + CardTableRS::ct_max_alignment_constraint()); + // Now make adjustments for CMS - size_t young_gen_per_worker; - intx new_ratio; - size_t min_new_default; - intx tenuring_default; - if (CMSUseOldDefaults) { // old defaults: "old" as of 6.0 - if FLAG_IS_DEFAULT(CMSYoungGenPerWorker) { - FLAG_SET_ERGO(intx, CMSYoungGenPerWorker, 4*M); - } - young_gen_per_worker = 4*M; - new_ratio = (intx)15; - min_new_default = 4*M; - tenuring_default = (intx)0; - } else { // new defaults: "new" as of 6.0 - young_gen_per_worker = CMSYoungGenPerWorker; - new_ratio = (intx)7; - min_new_default = 16*M; - tenuring_default = (intx)4; - } - - // Preferred young gen size for "short" pauses + intx tenuring_default = (intx)6; + size_t young_gen_per_worker = CMSYoungGenPerWorker; + + // Preferred young gen size for "short" pauses: + // upper bound depends on # of threads and NewRatio. const uintx parallel_gc_threads = (ParallelGCThreads == 0 ? 1 : ParallelGCThreads); const size_t preferred_max_new_size_unaligned = - ScaleForWordSize(young_gen_per_worker * parallel_gc_threads); - const size_t preferred_max_new_size = + MIN2(max_heap/(NewRatio+1), ScaleForWordSize(young_gen_per_worker * parallel_gc_threads)); + size_t preferred_max_new_size = align_size_up(preferred_max_new_size_unaligned, os::vm_page_size()); // Unless explicitly requested otherwise, size young gen - // for "short" pauses ~ 4M*ParallelGCThreads + // for "short" pauses ~ CMSYoungGenPerWorker*ParallelGCThreads // If either MaxNewSize or NewRatio is set on the command line, // assume the user is trying to set the size of the young gen. - if (FLAG_IS_DEFAULT(MaxNewSize) && FLAG_IS_DEFAULT(NewRatio)) { // Set MaxNewSize to our calculated preferred_max_new_size unless @@ -1168,49 +1136,13 @@ } if (PrintGCDetails && Verbose) { // Too early to use gclog_or_tty - tty->print_cr("Ergo set MaxNewSize: " SIZE_FORMAT, MaxNewSize); + tty->print_cr("CMS ergo set MaxNewSize: " SIZE_FORMAT, MaxNewSize); } - // Unless explicitly requested otherwise, prefer a large - // Old to Young gen size so as to shift the collection load - // to the old generation concurrent collector - - // If this is only guarded by FLAG_IS_DEFAULT(NewRatio) - // then NewSize and OldSize may be calculated. That would - // generally lead to some differences with ParNewGC for which - // there was no obvious reason. Also limit to the case where - // MaxNewSize has not been set. - - FLAG_SET_ERGO(intx, NewRatio, MAX2(NewRatio, new_ratio)); - // Code along this path potentially sets NewSize and OldSize - // Calculate the desired minimum size of the young gen but if - // NewSize has been set on the command line, use it here since - // it should be the final value. - size_t min_new; - if (FLAG_IS_DEFAULT(NewSize)) { - min_new = align_size_up(ScaleForWordSize(min_new_default), - os::vm_page_size()); - } else { - min_new = NewSize; - } - size_t prev_initial_size = InitialHeapSize; - if (prev_initial_size != 0 && prev_initial_size < min_new + OldSize) { - FLAG_SET_ERGO(uintx, InitialHeapSize, min_new + OldSize); - // Currently minimum size and the initial heap sizes are the same. - set_min_heap_size(InitialHeapSize); - if (PrintGCDetails && Verbose) { - warning("Initial heap size increased to " SIZE_FORMAT " M from " - SIZE_FORMAT " M; use -XX:NewSize=... for finer control.", - InitialHeapSize/M, prev_initial_size/M); - } - } - - // MaxHeapSize is aligned down in collectorPolicy - size_t max_heap = - align_size_down(MaxHeapSize, - CardTableRS::ct_max_alignment_constraint()); + assert(max_heap >= InitialHeapSize, "Error"); + assert(max_heap >= NewSize, "Error"); if (PrintGCDetails && Verbose) { // Too early to use gclog_or_tty @@ -1219,7 +1151,11 @@ " max_heap: " SIZE_FORMAT, min_heap_size(), InitialHeapSize, max_heap); } - if (max_heap > min_new) { + size_t min_new = preferred_max_new_size; + if (FLAG_IS_CMDLINE(NewSize)) { + min_new = NewSize; + } + if (max_heap > min_new && min_heap_size() > min_new) { // Unless explicitly requested otherwise, make young gen // at least min_new, and at most preferred_max_new_size. if (FLAG_IS_DEFAULT(NewSize)) { @@ -1227,18 +1163,17 @@ FLAG_SET_ERGO(uintx, NewSize, MIN2(preferred_max_new_size, NewSize)); if (PrintGCDetails && Verbose) { // Too early to use gclog_or_tty - tty->print_cr("Ergo set NewSize: " SIZE_FORMAT, NewSize); + tty->print_cr("CMS ergo set NewSize: " SIZE_FORMAT, NewSize); } } // Unless explicitly requested otherwise, size old gen - // so that it's at least 3X of NewSize to begin with; - // later NewRatio will decide how it grows; see above. + // so it's NewRatio x of NewSize. if (FLAG_IS_DEFAULT(OldSize)) { if (max_heap > NewSize) { - FLAG_SET_ERGO(uintx, OldSize, MIN2(3*NewSize, max_heap - NewSize)); + FLAG_SET_ERGO(uintx, OldSize, MIN2(NewRatio*NewSize, max_heap - NewSize)); if (PrintGCDetails && Verbose) { // Too early to use gclog_or_tty - tty->print_cr("Ergo set OldSize: " SIZE_FORMAT, OldSize); + tty->print_cr("CMS ergo set OldSize: " SIZE_FORMAT, OldSize); } } } @@ -1382,7 +1317,7 @@ void Arguments::set_ergonomics_flags() { // Parallel GC is not compatible with sharing. If one specifies // that they want sharing explicitly, do not set ergonomics flags. - if (DumpSharedSpaces || ForceSharedSpaces) { + if (DumpSharedSpaces || RequireSharedSpaces) { return; } @@ -1689,13 +1624,13 @@ } bool Arguments::verify_min_value(intx val, intx min, const char* name) { - // Returns true if given value is greater than specified min threshold + // Returns true if given value is at least specified min threshold // false, otherwise. if (val >= min ) { return true; } jio_fprintf(defaultStream::error_stream(), - "%s of " INTX_FORMAT " is invalid; must be greater than " INTX_FORMAT "\n", + "%s of " INTX_FORMAT " is invalid; must be at least " INTX_FORMAT "\n", name, val, min); return false; } @@ -1845,33 +1780,6 @@ status = status && verify_percentage(GCHeapFreeLimit, "GCHeapFreeLimit"); - // Check whether user-specified sharing option conflicts with GC or page size. - // Both sharing and large pages are enabled by default on some platforms; - // large pages override sharing only if explicitly set on the command line. - const bool cannot_share = UseConcMarkSweepGC || CMSIncrementalMode || - UseG1GC || UseParNewGC || UseParallelGC || UseParallelOldGC || - UseLargePages && FLAG_IS_CMDLINE(UseLargePages); - if (cannot_share) { - // Either force sharing on by forcing the other options off, or - // force sharing off. - if (DumpSharedSpaces || ForceSharedSpaces) { - jio_fprintf(defaultStream::error_stream(), - "Using Serial GC and default page size because of %s\n", - ForceSharedSpaces ? "-Xshare:on" : "-Xshare:dump"); - force_serial_gc(); - FLAG_SET_DEFAULT(UseLargePages, false); - } else { - if (UseSharedSpaces && Verbose) { - jio_fprintf(defaultStream::error_stream(), - "Turning off use of shared archive because of " - "choice of garbage collector or large pages\n"); - } - no_shared_spaces(); - } - } else if (UseLargePages && (UseSharedSpaces || DumpSharedSpaces)) { - FLAG_SET_DEFAULT(UseLargePages, false); - } - status = status && check_gc_consistency(); status = status && check_stack_pages(); @@ -1949,6 +1857,8 @@ status = false; } + status = status && verify_min_value(ParGCArrayScanChunk, 1, "ParGCArrayScanChunk"); + #ifndef SERIALGC if (UseG1GC) { status = status && verify_percentage(InitiatingHeapOccupancyPercent, @@ -2412,9 +2322,6 @@ } else if (match_option(option, "-Xshare:on", &tail)) { FLAG_SET_CMDLINE(bool, UseSharedSpaces, true); FLAG_SET_CMDLINE(bool, RequireSharedSpaces, true); -#ifdef TIERED - FLAG_SET_CMDLINE(bool, ForceSharedSpaces, true); -#endif // TIERED // -Xshare:auto } else if (match_option(option, "-Xshare:auto", &tail)) { FLAG_SET_CMDLINE(bool, UseSharedSpaces, true); @@ -2911,6 +2818,36 @@ return JNI_OK; } +void Arguments::set_shared_spaces_flags() { + // Check whether class data sharing settings conflict with GC, compressed oops + // or page size, and fix them up. Explicit sharing options override other + // settings. + const bool cannot_share = UseConcMarkSweepGC || CMSIncrementalMode || + UseG1GC || UseParNewGC || UseParallelGC || UseParallelOldGC || + UseCompressedOops || UseLargePages && FLAG_IS_CMDLINE(UseLargePages); + const bool must_share = DumpSharedSpaces || RequireSharedSpaces; + const bool might_share = must_share || UseSharedSpaces; + if (cannot_share) { + if (must_share) { + warning("selecting serial gc and disabling large pages %s" + "because of %s", "" LP64_ONLY("and compressed oops "), + DumpSharedSpaces ? "-Xshare:dump" : "-Xshare:on"); + force_serial_gc(); + FLAG_SET_CMDLINE(bool, UseLargePages, false); + LP64_ONLY(FLAG_SET_CMDLINE(bool, UseCompressedOops, false)); + } else { + if (UseSharedSpaces && Verbose) { + warning("turning off use of shared archive because of " + "choice of garbage collector or large pages"); + } + no_shared_spaces(); + } + } else if (UseLargePages && might_share) { + // Disable large pages to allow shared spaces. This is sub-optimal, since + // there may not even be a shared archive to use. + FLAG_SET_DEFAULT(UseLargePages, false); + } +} // Parse entry point called from JNI_CreateJavaVM @@ -3058,9 +2995,7 @@ // Set flags based on ergonomics. set_ergonomics_flags(); - if (UseCompressedOops) { - check_compressed_oops_compat(); - } + set_shared_spaces_flags(); // Check the GC selections again. if (!check_gc_consistency()) { @@ -3078,22 +3013,17 @@ } #ifndef KERNEL - if (UseConcMarkSweepGC) { - // Set flags for CMS and ParNew. Check UseConcMarkSweep first - // to ensure that when both UseConcMarkSweepGC and UseParNewGC - // are true, we don't call set_parnew_gc_flags() as well. + // Set heap size based on available physical memory + set_heap_size(); + // Set per-collector flags + if (UseParallelGC || UseParallelOldGC) { + set_parallel_gc_flags(); + } else if (UseConcMarkSweepGC) { // should be done before ParNew check below set_cms_and_parnew_gc_flags(); - } else { - // Set heap size based on available physical memory - set_heap_size(); - // Set per-collector flags - if (UseParallelGC || UseParallelOldGC) { - set_parallel_gc_flags(); - } else if (UseParNewGC) { - set_parnew_gc_flags(); - } else if (UseG1GC) { - set_g1_gc_flags(); - } + } else if (UseParNewGC) { // skipped if CMS is set above + set_parnew_gc_flags(); + } else if (UseG1GC) { + set_g1_gc_flags(); } #endif // KERNEL @@ -3110,7 +3040,11 @@ // Turn off biased locking for locking debug mode flags, // which are subtlely different from each other but neither works with // biased locking. - if (!UseFastLocking || UseHeavyMonitors) { + if (UseHeavyMonitors +#ifdef COMPILER1 + || !UseFastLocking +#endif // COMPILER1 + ) { if (!FLAG_IS_DEFAULT(UseBiasedLocking) && UseBiasedLocking) { // flag set to true on command line; warn the user that they // can't enable biased locking here diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/runtime/arguments.hpp --- a/src/share/vm/runtime/arguments.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/runtime/arguments.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -301,8 +301,6 @@ // Tiered static void set_tiered_flags(); - // Check compressed oops compatibility with other flags - static void check_compressed_oops_compat(); // CMS/ParNew garbage collectors static void set_parnew_gc_flags(); static void set_cms_and_parnew_gc_flags(); @@ -312,6 +310,7 @@ static void set_g1_gc_flags(); // GC ergonomics static void set_ergonomics_flags(); + static void set_shared_spaces_flags(); // Setup heap size static void set_heap_size(); // Based on automatic selection criteria, should the diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/runtime/compilationPolicy.cpp --- a/src/share/vm/runtime/compilationPolicy.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/runtime/compilationPolicy.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, 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 @@ -32,6 +32,7 @@ #include "oops/methodOop.hpp" #include "oops/oop.inline.hpp" #include "prims/nativeLookup.hpp" +#include "runtime/advancedThresholdPolicy.hpp" #include "runtime/compilationPolicy.hpp" #include "runtime/frame.hpp" #include "runtime/handles.inline.hpp" @@ -72,8 +73,15 @@ Unimplemented(); #endif break; + case 3: +#ifdef TIERED + CompilationPolicy::set_policy(new AdvancedThresholdPolicy()); +#else + Unimplemented(); +#endif + break; default: - fatal("CompilationPolicyChoice must be in the range: [0-2]"); + fatal("CompilationPolicyChoice must be in the range: [0-3]"); } CompilationPolicy::policy()->initialize(); } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/runtime/deoptimization.cpp --- a/src/share/vm/runtime/deoptimization.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/runtime/deoptimization.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -101,9 +101,9 @@ _frame_pcs = frame_pcs; _register_block = NEW_C_HEAP_ARRAY(intptr_t, RegisterMap::reg_count * 2); _return_type = return_type; + _initial_fp = 0; // PD (x86 only) _counter_temp = 0; - _initial_fp = 0; _unpack_kind = 0; _sender_sp_temp = 0; @@ -459,18 +459,9 @@ frame_sizes, frame_pcs, return_type); -#if defined(IA32) || defined(AMD64) - // We need a way to pass fp to the unpacking code so the skeletal frames - // come out correct. This is only needed for x86 because of c2 using ebp - // as an allocatable register. So this update is useless (and harmless) - // on the other platforms. It would be nice to do this in a different - // way but even the old style deoptimization had a problem with deriving - // this value. NEEDS_CLEANUP - // Note: now that c1 is using c2's deopt blob we must do this on all - // x86 based platforms - intptr_t** fp_addr = (intptr_t**) (((address)info) + info->initial_fp_offset_in_bytes()); - *fp_addr = array->sender().fp(); // was adapter_caller -#endif /* IA32 || AMD64 */ + // On some platforms, we need a way to pass fp to the unpacking code + // so the skeletal frames come out correct. + info->set_initial_fp((intptr_t) array->sender().fp()); if (array->frames() > 1) { if (VerifyStack && TraceDeoptimization) { diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/runtime/deoptimization.hpp --- a/src/share/vm/runtime/deoptimization.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/runtime/deoptimization.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -136,12 +136,12 @@ address* _frame_pcs; // Array of frame pc's, in bytes, for unrolling the stack intptr_t* _register_block; // Block for storing callee-saved registers. BasicType _return_type; // Tells if we have to restore double or long return value + intptr_t _initial_fp; // FP of the sender frame // The following fields are used as temps during the unpacking phase // (which is tight on registers, especially on x86). They really ought // to be PD variables but that involves moving this class into its own // file to use the pd include mechanism. Maybe in a later cleanup ... intptr_t _counter_temp; // SHOULD BE PD VARIABLE (x86 frame count temp) - intptr_t _initial_fp; // SHOULD BE PD VARIABLE (x86/c2 initial ebp) intptr_t _unpack_kind; // SHOULD BE PD VARIABLE (x86 unpack kind) intptr_t _sender_sp_temp; // SHOULD BE PD VARIABLE (x86 sender_sp) public: @@ -165,6 +165,8 @@ // Returns the total size of frames int size_of_frames() const; + void set_initial_fp(intptr_t fp) { _initial_fp = fp; } + // Accessors used by the code generator for the unpack stub. static int size_of_deoptimized_frame_offset_in_bytes() { return offset_of(UnrollBlock, _size_of_deoptimized_frame); } static int caller_adjustment_offset_in_bytes() { return offset_of(UnrollBlock, _caller_adjustment); } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/runtime/globals.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -1540,12 +1540,8 @@ product(bool, AlwaysPreTouch, false, \ "It forces all freshly committed pages to be pre-touched.") \ \ - product(bool, CMSUseOldDefaults, false, \ - "A flag temporarily introduced to allow reverting to some " \ - "older default settings; older as of 6.0") \ - \ - product(intx, CMSYoungGenPerWorker, 16*M, \ - "The amount of young gen chosen by default per GC worker " \ + product_pd(intx, CMSYoungGenPerWorker, \ + "The maximum size of young gen chosen by default per GC worker " \ "thread available") \ \ product(bool, GCOverheadReporting, false, \ @@ -3653,9 +3649,6 @@ product(bool, RequireSharedSpaces, false, \ "Require shared spaces in the permanent generation") \ \ - product(bool, ForceSharedSpaces, false, \ - "Require shared spaces in the permanent generation") \ - \ product(bool, DumpSharedSpaces, false, \ "Special mode: JVM reads a class list, loads classes, builds " \ "shared spaces, and dumps the shared spaces to a file to be " \ @@ -3719,6 +3712,13 @@ experimental(bool, AllowTransitionalJSR292, true, \ "recognize pre-PFD formats of invokedynamic") \ \ + experimental(bool, PreferTransitionalJSR292, false, \ + "prefer pre-PFD APIs on boot class path, if they exist") \ + \ + experimental(bool, AllowInvokeForInvokeGeneric, false, \ + "accept MethodHandle.invoke and MethodHandle.invokeGeneric " \ + "as equivalent methods") \ + \ develop(bool, TraceInvokeDynamic, false, \ "trace internal invoke dynamic operations") \ \ diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/runtime/os.cpp --- a/src/share/vm/runtime/os.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/runtime/os.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -633,10 +633,10 @@ *q = (u_char)freeBlockPad; } if (PrintMalloc && tty != NULL) - fprintf(stderr, "os::free " SIZE_FORMAT " bytes --> " PTR_FORMAT "\n", size, memblock); + fprintf(stderr, "os::free " SIZE_FORMAT " bytes --> " PTR_FORMAT "\n", size, (uintptr_t)memblock); } else if (PrintMalloc && tty != NULL) { // tty->print_cr("os::free %p", memblock); - fprintf(stderr, "os::free " PTR_FORMAT "\n", memblock); + fprintf(stderr, "os::free " PTR_FORMAT "\n", (uintptr_t)memblock); } #endif ::free((char*)memblock - space_before); diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/runtime/serviceThread.cpp --- a/src/share/vm/runtime/serviceThread.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/runtime/serviceThread.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -70,11 +70,10 @@ java_lang_Thread::set_priority(thread_oop(), NearMaxPriority); java_lang_Thread::set_daemon(thread_oop()); thread->set_threadObj(thread_oop()); + _instance = thread; Threads::add(thread); Thread::start(thread); - - _instance = thread; } } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/runtime/sweeper.cpp --- a/src/share/vm/runtime/sweeper.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/runtime/sweeper.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -426,9 +426,7 @@ tty->vprint(format, ap); va_end(ap); } - tty->print_cr(" total_blobs='" UINT32_FORMAT "' nmethods='" UINT32_FORMAT "'" - " adapters='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'", - CodeCache::nof_blobs(), CodeCache::nof_nmethods(), CodeCache::nof_adapters(), CodeCache::unallocated_capacity()); + CodeCache::log_state(tty); tty->cr(); } if (LogCompilation && (xtty != NULL)) { @@ -440,9 +438,7 @@ xtty->vprint(format, ap); va_end(ap); } - xtty->print(" total_blobs='" UINT32_FORMAT "' nmethods='" UINT32_FORMAT "'" - " adapters='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'", - CodeCache::nof_blobs(), CodeCache::nof_nmethods(), CodeCache::nof_adapters(), CodeCache::unallocated_capacity()); + CodeCache::log_state(xtty); xtty->stamp(); xtty->end_elem(); } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/utilities/debug.hpp --- a/src/share/vm/utilities/debug.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/utilities/debug.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -25,6 +25,7 @@ #ifndef SHARE_VM_UTILITIES_DEBUG_HPP #define SHARE_VM_UTILITIES_DEBUG_HPP +#include "prims/jvm.h" #include "utilities/globalDefinitions.hpp" #include @@ -48,7 +49,7 @@ FormatBuffer::FormatBuffer(const char * format, ...) { va_list argp; va_start(argp, format); - vsnprintf(_buf, bufsz, format, argp); + jio_vsnprintf(_buf, bufsz, format, argp); va_end(argp); } @@ -61,7 +62,7 @@ va_list argp; va_start(argp, format); - vsnprintf(buf_end, bufsz - len, format, argp); + jio_vsnprintf(buf_end, bufsz - len, format, argp); va_end(argp); } diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/utilities/globalDefinitions.hpp --- a/src/share/vm/utilities/globalDefinitions.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/utilities/globalDefinitions.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -1185,7 +1185,7 @@ // '%d' formats to indicate a 64-bit quantity; commonly "l" (in LP64) or "ll" // (in ILP32). -#define BOOL_TO_STR(__b) (__b) ? "true" : "false" +#define BOOL_TO_STR(_b_) ((_b_) ? "true" : "false") // Format 32-bit quantities. #define INT32_FORMAT "%d" diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/utilities/workgroup.cpp --- a/src/share/vm/utilities/workgroup.cpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/utilities/workgroup.cpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, 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 @@ -156,7 +156,7 @@ tty->print_cr("/nFinished work gang %s: %d/%d sequence %d", name(), finished_workers(), total_workers(), _sequence_number); - } + } } void AbstractWorkGang::stop() { diff -r fc1b183bfc0a -r e97ad5d5c990 src/share/vm/utilities/workgroup.hpp --- a/src/share/vm/utilities/workgroup.hpp Thu Mar 17 17:25:12 2011 -0700 +++ b/src/share/vm/utilities/workgroup.hpp Fri Mar 18 13:28:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2011, 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 @@ -36,6 +36,20 @@ # include "thread_windows.inline.hpp" #endif +// Task class hierarchy: +// AbstractGangTask +// AbstractGangTaskWOopQueues +// +// Gang/Group class hierarchy: +// AbstractWorkGang +// WorkGang +// FlexibleWorkGang +// YieldingFlexibleWorkGang (defined in another file) +// +// Worker class hierarchy: +// GangWorker (subclass of WorkerThread) +// YieldingFlexibleGangWorker (defined in another file) + // Forward declarations of classes defined here class WorkGang;