From c6d82df5714df45d3a4b12aa992ec8fa2e28efeb Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Thu, 18 Aug 2016 14:31:02 -0700 Subject: [PATCH 001/110] 8162496: missing precedence edge for anti_dependence Fix Implicit Null Check optimization code. Reviewed-by: roland, aph --- hotspot/src/share/vm/opto/block.cpp | 3 +++ hotspot/src/share/vm/opto/block.hpp | 7 +++---- hotspot/src/share/vm/opto/lcm.cpp | 29 ++++++++++++++++++++++++++--- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/hotspot/src/share/vm/opto/block.cpp b/hotspot/src/share/vm/opto/block.cpp index ffa06e03358..ba43bf5de6f 100644 --- a/hotspot/src/share/vm/opto/block.cpp +++ b/hotspot/src/share/vm/opto/block.cpp @@ -1212,6 +1212,9 @@ void PhaseCFG::verify() const { if (j >= 1 && n->is_Mach() && n->as_Mach()->ideal_Opcode() == Op_CreateEx) { assert(j == 1 || block->get_node(j-1)->is_Phi(), "CreateEx must be first instruction in block"); } + if (n->needs_anti_dependence_check()) { + verify_anti_dependences(block, n); + } for (uint k = 0; k < n->req(); k++) { Node *def = n->in(k); if (def && def != n) { diff --git a/hotspot/src/share/vm/opto/block.hpp b/hotspot/src/share/vm/opto/block.hpp index e1d4874d3ee..8a7cad375d4 100644 --- a/hotspot/src/share/vm/opto/block.hpp +++ b/hotspot/src/share/vm/opto/block.hpp @@ -186,14 +186,13 @@ public: Block* lone_fall_through(); // Return lone fall-through Block or null Block* dom_lca(Block* that); // Compute LCA in dominator tree. -#ifdef ASSERT + bool dominates(Block* that) { int dom_diff = this->_dom_depth - that->_dom_depth; if (dom_diff > 0) return false; for (; dom_diff < 0; dom_diff++) that = that->_idom; return this == that; } -#endif // Report the alignment required by this block. Must be a power of 2. // The previous block will insert nops to get this alignment. @@ -481,9 +480,9 @@ class PhaseCFG : public Phase { MachNode* _goto; Block* insert_anti_dependences(Block* LCA, Node* load, bool verify = false); - void verify_anti_dependences(Block* LCA, Node* load) { + void verify_anti_dependences(Block* LCA, Node* load) const { assert(LCA == get_block_for_node(load), "should already be scheduled"); - insert_anti_dependences(LCA, load, true); + const_cast(this)->insert_anti_dependences(LCA, load, true); } bool move_to_next(Block* bx, uint b_index); diff --git a/hotspot/src/share/vm/opto/lcm.cpp b/hotspot/src/share/vm/opto/lcm.cpp index aabb17ac8d1..7d94f25abf3 100644 --- a/hotspot/src/share/vm/opto/lcm.cpp +++ b/hotspot/src/share/vm/opto/lcm.cpp @@ -240,6 +240,14 @@ void PhaseCFG::implicit_null_check(Block* block, Node *proj, Node *val, int allo continue; } + // Check that node's control edge is not-null block's head or dominates it, + // otherwise we can't hoist it because there are other control dependencies. + Node* ctrl = mach->in(0); + if (ctrl != NULL && !(ctrl == not_null_block->head() || + get_block_for_node(ctrl)->dominates(not_null_block))) { + continue; + } + // check if the offset is not too high for implicit exception { intptr_t offset = 0; @@ -379,9 +387,12 @@ void PhaseCFG::implicit_null_check(Block* block, Node *proj, Node *val, int allo block->add_inst(best); map_node_to_block(best, block); - // Move the control dependence - if (best->in(0) && best->in(0) == old_block->head()) - best->set_req(0, block->head()); + // Move the control dependence if it is pinned to not-null block. + // Don't change it in other cases: NULL or dominating control. + if (best->in(0) == not_null_block->head()) { + // Set it to control edge of null check. + best->set_req(0, proj->in(0)->in(0)); + } // Check for flag-killing projections that also need to be hoisted // Should be DU safe because no edge updates. @@ -437,6 +448,18 @@ void PhaseCFG::implicit_null_check(Block* block, Node *proj, Node *val, int allo latency_from_uses(nul_chk); latency_from_uses(best); + + // insert anti-dependences to defs in this block + if (! best->needs_anti_dependence_check()) { + for (uint k = 1; k < block->number_of_nodes(); k++) { + Node *n = block->get_node(k); + if (n->needs_anti_dependence_check() && + n->in(LoadNode::Memory) == best->in(StoreNode::Memory)) { + // Found anti-dependent load + insert_anti_dependences(block, n); + } + } + } } From ebb0356d35529535cbb698dae7f7a82d8853aaa0 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Fri, 19 Aug 2016 08:34:30 +0200 Subject: [PATCH 002/110] 8064892: Non-methods code cache overflow is not handled correctly Should keep track of requested code blob type for error reporting. Added additional debug output. Reviewed-by: kvn, dpochepk --- hotspot/src/share/vm/code/codeCache.cpp | 31 ++++++++++++++++--------- hotspot/src/share/vm/code/codeCache.hpp | 2 +- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/hotspot/src/share/vm/code/codeCache.cpp b/hotspot/src/share/vm/code/codeCache.cpp index 36e33c4c5aa..e1a5d2fd0c9 100644 --- a/hotspot/src/share/vm/code/codeCache.cpp +++ b/hotspot/src/share/vm/code/codeCache.cpp @@ -437,7 +437,7 @@ CodeBlob* CodeCache::next_blob(CodeBlob* cb) { * run the constructor for the CodeBlob subclass he is busy * instantiating. */ -CodeBlob* CodeCache::allocate(int size, int code_blob_type, bool strict) { +CodeBlob* CodeCache::allocate(int size, int code_blob_type, int orig_code_blob_type) { // Possibly wakes up the sweeper thread. NMethodSweeper::notify(code_blob_type); assert_locked_or_safepoint(CodeCache_lock); @@ -455,32 +455,41 @@ CodeBlob* CodeCache::allocate(int size, int code_blob_type, bool strict) { cb = (CodeBlob*)heap->allocate(size); if (cb != NULL) break; if (!heap->expand_by(CodeCacheExpansionSize)) { + // Save original type for error reporting + if (orig_code_blob_type == CodeBlobType::All) { + orig_code_blob_type = code_blob_type; + } // Expansion failed - if (SegmentedCodeCache && !strict) { + if (SegmentedCodeCache) { // Fallback solution: Try to store code in another code heap. + // NonNMethod -> MethodNonProfiled -> MethodProfiled (-> MethodNonProfiled) // Note that in the sweeper, we check the reverse_free_ratio of the code heap // and force stack scanning if less than 10% of the code heap are free. int type = code_blob_type; switch (type) { case CodeBlobType::NonNMethod: type = CodeBlobType::MethodNonProfiled; - strict = false; // Allow recursive search for other heaps - break; - case CodeBlobType::MethodProfiled: - type = CodeBlobType::MethodNonProfiled; - strict = true; break; case CodeBlobType::MethodNonProfiled: type = CodeBlobType::MethodProfiled; - strict = true; + break; + case CodeBlobType::MethodProfiled: + // Avoid loop if we already tried that code heap + if (type == orig_code_blob_type) { + type = CodeBlobType::MethodNonProfiled; + } break; } - if (heap_available(type)) { - return allocate(size, type, strict); + if (type != code_blob_type && type != orig_code_blob_type && heap_available(type)) { + if (PrintCodeCacheExtension) { + tty->print_cr("Extension of %s failed. Trying to allocate in %s.", + heap->name(), get_code_heap(type)->name()); + } + return allocate(size, type, orig_code_blob_type); } } MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); - CompileBroker::handle_full_code_cache(code_blob_type); + CompileBroker::handle_full_code_cache(orig_code_blob_type); return NULL; } if (PrintCodeCacheExtension) { diff --git a/hotspot/src/share/vm/code/codeCache.hpp b/hotspot/src/share/vm/code/codeCache.hpp index ba81a8ab1a9..43aafbf8587 100644 --- a/hotspot/src/share/vm/code/codeCache.hpp +++ b/hotspot/src/share/vm/code/codeCache.hpp @@ -126,7 +126,7 @@ class CodeCache : AllStatic { static void initialize(); // Allocation/administration - static CodeBlob* allocate(int size, int code_blob_type, bool strict = false); // allocates a new CodeBlob + static CodeBlob* allocate(int size, int code_blob_type, int orig_code_blob_type = CodeBlobType::All); // allocates a new CodeBlob static void commit(CodeBlob* cb); // called when the allocated CodeBlob has been filled static int alignment_unit(); // guaranteed alignment of all CodeBlobs static int alignment_offset(); // guaranteed offset of first CodeBlob byte within alignment unit (i.e., allocation header) From 1c5cc2ccdf006e22966cc51e35c8b6385bf59012 Mon Sep 17 00:00:00 2001 From: Dmitrij Pochepko Date: Sat, 20 Aug 2016 00:15:45 +0300 Subject: [PATCH 003/110] 8139700: compiler/jvmci/compilerToVM/DisassembleCodeBlobTest and InvalidateInstalledCodeTest timeout Reviewed-by: kvn --- .../compiler/jvmci/compilerToVM/CompileCodeTestCase.java | 6 ++++++ .../jvmci/compilerToVM/DisassembleCodeBlobTest.java | 1 - .../jvmci/compilerToVM/InvalidateInstalledCodeTest.java | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/hotspot/test/compiler/jvmci/compilerToVM/CompileCodeTestCase.java b/hotspot/test/compiler/jvmci/compilerToVM/CompileCodeTestCase.java index 697aee29904..b7deb126b7a 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/CompileCodeTestCase.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/CompileCodeTestCase.java @@ -107,6 +107,12 @@ public class CompileCodeTestCase { } public NMethod compile(int level) { + String directive = "[{ match: \"" + executable.getDeclaringClass().getName().replace('.', '/') + + "." + (executable instanceof Constructor ? "" : executable.getName()) + + "\", " + "BackgroundCompilation: false }]"; + if (WB.addCompilerDirective(directive) != 1) { + throw new Error("Failed to add compiler directive: " + directive); + } boolean enqueued = WB.enqueueMethodForCompilation(executable, level, bci); if (!enqueued) { diff --git a/hotspot/test/compiler/jvmci/compilerToVM/DisassembleCodeBlobTest.java b/hotspot/test/compiler/jvmci/compilerToVM/DisassembleCodeBlobTest.java index 8bb3820593d..853ae361455 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/DisassembleCodeBlobTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/DisassembleCodeBlobTest.java @@ -34,7 +34,6 @@ * jdk.vm.ci/jdk.vm.ci.hotspot * jdk.vm.ci/jdk.vm.ci.code * - * @ignore 8139700 * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper * @build sun.hotspot.WhiteBox * compiler.jvmci.compilerToVM.DisassembleCodeBlobTest diff --git a/hotspot/test/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java b/hotspot/test/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java index 23ff0b9685a..280015001e3 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java @@ -35,7 +35,7 @@ * jdk.vm.ci/jdk.vm.ci.code * jdk.vm.ci/jdk.vm.ci.runtime * - * @ignore 8139700 + * @ignore 8163894 * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper * @build compiler.jvmci.compilerToVM.InvalidateInstalledCodeTest * @build sun.hotspot.WhiteBox From 14830c4604cfa587d29e492f56668ebba82b8f30 Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Mon, 22 Aug 2016 11:47:15 -0700 Subject: [PATCH 004/110] 8164122: C1: assert(false) failed: stack or locks not matching (invalid bytecodes) Ignore return value if MH intrinsic returns void Reviewed-by: roland, kvn --- hotspot/src/share/vm/c1/c1_GraphBuilder.cpp | 55 ++++++++++++--------- hotspot/src/share/vm/c1/c1_GraphBuilder.hpp | 18 ++++--- 2 files changed, 45 insertions(+), 28 deletions(-) diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp index 7120e76c874..bd2cd0fb0f8 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp @@ -683,6 +683,7 @@ GraphBuilder::ScopeData::ScopeData(ScopeData* parent) , _cleanup_block(NULL) , _cleanup_return_prev(NULL) , _cleanup_state(NULL) + , _ignore_return(false) { if (parent != NULL) { _max_inline_size = (intx) ((float) NestedInliningSizeRatio * (float) parent->max_inline_size() / 100.0f); @@ -1445,7 +1446,7 @@ void GraphBuilder::call_register_finalizer() { } -void GraphBuilder::method_return(Value x) { +void GraphBuilder::method_return(Value x, bool ignore_return) { if (RegisterFinalizersAtInit && method()->intrinsic_id() == vmIntrinsics::_Object_init) { call_register_finalizer(); @@ -1518,7 +1519,9 @@ void GraphBuilder::method_return(Value x) { int invoke_bci = state()->caller_state()->bci(); set_state(state()->caller_state()->copy_for_parsing()); if (x != NULL) { - state()->push(x->type(), x); + if (!ignore_return) { + state()->push(x->type(), x); + } if (profile_return() && x->type()->is_object_kind()) { ciMethod* caller = state()->scope()->method(); ciMethodData* md = caller->method_data_or_null(); @@ -1563,6 +1566,7 @@ void GraphBuilder::method_return(Value x) { append(new MemBar(lir_membar_storestore)); } + assert(!ignore_return, "Ignoring return value works only for inlining"); append(new Return(x)); } @@ -1981,7 +1985,7 @@ void GraphBuilder::invoke(Bytecodes::Code code) { code == Bytecodes::_invokedynamic) { ciMethod* inline_target = (cha_monomorphic_target != NULL) ? cha_monomorphic_target : target; // static binding => check if callee is ok - bool success = try_inline(inline_target, (cha_monomorphic_target != NULL) || (exact_target != NULL), code, better_receiver); + bool success = try_inline(inline_target, (cha_monomorphic_target != NULL) || (exact_target != NULL), false, code, better_receiver); CHECK_BAILOUT(); clear_inline_bailout(); @@ -2611,6 +2615,8 @@ BlockEnd* GraphBuilder::iterate_bytecodes_for_block(int bci) { push_exception = true; } + bool ignore_return = scope_data()->ignore_return(); + while (!bailed_out() && last()->as_BlockEnd() == NULL && (code = stream()->next()) != ciBytecodeStream::EOBC() && (block_at(s.cur_bci()) == NULL || block_at(s.cur_bci()) == block())) { @@ -2806,12 +2812,12 @@ BlockEnd* GraphBuilder::iterate_bytecodes_for_block(int bci) { case Bytecodes::_ret : ret(s.get_index()); break; case Bytecodes::_tableswitch : table_switch(); break; case Bytecodes::_lookupswitch : lookup_switch(); break; - case Bytecodes::_ireturn : method_return(ipop()); break; - case Bytecodes::_lreturn : method_return(lpop()); break; - case Bytecodes::_freturn : method_return(fpop()); break; - case Bytecodes::_dreturn : method_return(dpop()); break; - case Bytecodes::_areturn : method_return(apop()); break; - case Bytecodes::_return : method_return(NULL ); break; + case Bytecodes::_ireturn : method_return(ipop(), ignore_return); break; + case Bytecodes::_lreturn : method_return(lpop(), ignore_return); break; + case Bytecodes::_freturn : method_return(fpop(), ignore_return); break; + case Bytecodes::_dreturn : method_return(dpop(), ignore_return); break; + case Bytecodes::_areturn : method_return(apop(), ignore_return); break; + case Bytecodes::_return : method_return(NULL , ignore_return); break; case Bytecodes::_getstatic : // fall through case Bytecodes::_putstatic : // fall through case Bytecodes::_getfield : // fall through @@ -3336,7 +3342,7 @@ int GraphBuilder::recursive_inline_level(ciMethod* cur_callee) const { } -bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known, Bytecodes::Code bc, Value receiver) { +bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known, bool ignore_return, Bytecodes::Code bc, Value receiver) { const char* msg = NULL; // clear out any existing inline bailout condition @@ -3351,7 +3357,7 @@ bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known, Bytecodes::Co // method handle invokes if (callee->is_method_handle_intrinsic()) { - if (try_method_handle_inline(callee)) { + if (try_method_handle_inline(callee, ignore_return)) { if (callee->has_reserved_stack_access()) { compilation()->set_has_reserved_stack_access(true); } @@ -3363,7 +3369,7 @@ bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known, Bytecodes::Co // handle intrinsics if (callee->intrinsic_id() != vmIntrinsics::_none && (CheckIntrinsics ? callee->intrinsic_candidate() : true)) { - if (try_inline_intrinsics(callee)) { + if (try_inline_intrinsics(callee, ignore_return)) { print_inlining(callee, "intrinsic"); if (callee->has_reserved_stack_access()) { compilation()->set_has_reserved_stack_access(true); @@ -3384,7 +3390,7 @@ bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known, Bytecodes::Co if (bc == Bytecodes::_illegal) { bc = code(); } - if (try_inline_full(callee, holder_known, bc, receiver)) { + if (try_inline_full(callee, holder_known, ignore_return, bc, receiver)) { if (callee->has_reserved_stack_access()) { compilation()->set_has_reserved_stack_access(true); } @@ -3415,7 +3421,7 @@ const char* GraphBuilder::should_not_inline(ciMethod* callee) const { return NULL; } -void GraphBuilder::build_graph_for_intrinsic(ciMethod* callee) { +void GraphBuilder::build_graph_for_intrinsic(ciMethod* callee, bool ignore_return) { vmIntrinsics::ID id = callee->intrinsic_id(); assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); @@ -3509,14 +3515,16 @@ void GraphBuilder::build_graph_for_intrinsic(ciMethod* callee) { vmIntrinsics::can_trap(id)); // append instruction & push result Value value = append_split(result); - if (result_type != voidType) push(result_type, value); + if (result_type != voidType && !ignore_return) { + push(result_type, value); + } if (callee != method() && profile_return() && result_type->is_object_kind()) { profile_return_type(result, callee); } } -bool GraphBuilder::try_inline_intrinsics(ciMethod* callee) { +bool GraphBuilder::try_inline_intrinsics(ciMethod* callee, bool ignore_return) { // For calling is_intrinsic_available we need to transition to // the '_thread_in_vm' state because is_intrinsic_available() // accesses critical VM-internal data. @@ -3536,7 +3544,7 @@ bool GraphBuilder::try_inline_intrinsics(ciMethod* callee) { return false; } } - build_graph_for_intrinsic(callee); + build_graph_for_intrinsic(callee, ignore_return); return true; } @@ -3691,7 +3699,7 @@ void GraphBuilder::fill_sync_handler(Value lock, BlockBegin* sync_handler, bool } -bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, Bytecodes::Code bc, Value receiver) { +bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, bool ignore_return, Bytecodes::Code bc, Value receiver) { assert(!callee->is_native(), "callee must not be native"); if (CompilationPolicy::policy()->should_not_inline(compilation()->env(), callee)) { INLINE_BAILOUT("inlining prohibited by policy"); @@ -3889,6 +3897,7 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, Bytecode // Clear out bytecode stream scope_data()->set_stream(NULL); + scope_data()->set_ignore_return(ignore_return); CompileLog* log = compilation()->log(); if (log != NULL) log->head("parse method='%d'", log->identify(callee)); @@ -3958,7 +3967,7 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, Bytecode } -bool GraphBuilder::try_method_handle_inline(ciMethod* callee) { +bool GraphBuilder::try_method_handle_inline(ciMethod* callee, bool ignore_return) { ValueStack* state_before = copy_state_before(); vmIntrinsics::ID iid = callee->intrinsic_id(); switch (iid) { @@ -3972,7 +3981,8 @@ bool GraphBuilder::try_method_handle_inline(ciMethod* callee) { // We don't do CHA here so only inline static and statically bindable methods. if (target->is_static() || target->can_be_statically_bound()) { Bytecodes::Code bc = target->is_static() ? Bytecodes::_invokestatic : Bytecodes::_invokevirtual; - if (try_inline(target, /*holder_known*/ true, bc)) { + ignore_return = ignore_return || (callee->return_type()->is_void() && !target->return_type()->is_void()); + if (try_inline(target, /*holder_known*/ true, ignore_return, bc)) { return true; } } else { @@ -3994,10 +4004,11 @@ bool GraphBuilder::try_method_handle_inline(ciMethod* callee) { ValueType* type = apop()->type(); if (type->is_constant()) { ciMethod* target = type->as_ObjectType()->constant_value()->as_member_name()->get_vmtarget(); + ignore_return = ignore_return || (callee->return_type()->is_void() && !target->return_type()->is_void()); // If the target is another method handle invoke, try to recursively get // a better target. if (target->is_method_handle_intrinsic()) { - if (try_method_handle_inline(target)) { + if (try_method_handle_inline(target, ignore_return)) { return true; } } else { @@ -4032,7 +4043,7 @@ bool GraphBuilder::try_method_handle_inline(ciMethod* callee) { // We don't do CHA here so only inline static and statically bindable methods. if (target->is_static() || target->can_be_statically_bound()) { Bytecodes::Code bc = target->is_static() ? Bytecodes::_invokestatic : Bytecodes::_invokevirtual; - if (try_inline(target, /*holder_known*/ true, bc)) { + if (try_inline(target, /*holder_known*/ true, ignore_return, bc)) { return true; } } else { diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp index 20bed2b164d..413aa2bddfb 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp @@ -100,6 +100,9 @@ class GraphBuilder VALUE_OBJ_CLASS_SPEC { Instruction* _cleanup_return_prev; // Instruction before return instruction ValueStack* _cleanup_state; // State of that block (not yet pinned) + // When inlining do not push the result on the stack + bool _ignore_return; + public: ScopeData(ScopeData* parent); @@ -163,6 +166,9 @@ class GraphBuilder VALUE_OBJ_CLASS_SPEC { BlockBegin* inline_cleanup_block() const { return _cleanup_block; } Instruction* inline_cleanup_return_prev() const{ return _cleanup_return_prev; } ValueStack* inline_cleanup_state() const { return _cleanup_state; } + + bool ignore_return() const { return _ignore_return; } + void set_ignore_return(bool ignore_return) { _ignore_return = ignore_return; } }; // for all GraphBuilders @@ -246,7 +252,7 @@ class GraphBuilder VALUE_OBJ_CLASS_SPEC { void ret(int local_index); void table_switch(); void lookup_switch(); - void method_return(Value x); + void method_return(Value x, bool ignore_return = false); void call_register_finalizer(); void access_field(Bytecodes::Code code); void invoke(Bytecodes::Code code); @@ -340,19 +346,19 @@ class GraphBuilder VALUE_OBJ_CLASS_SPEC { void inline_sync_entry(Value lock, BlockBegin* sync_handler); void fill_sync_handler(Value lock, BlockBegin* sync_handler, bool default_handler = false); - void build_graph_for_intrinsic(ciMethod* callee); + void build_graph_for_intrinsic(ciMethod* callee, bool ignore_return); // inliners - bool try_inline( ciMethod* callee, bool holder_known, Bytecodes::Code bc = Bytecodes::_illegal, Value receiver = NULL); - bool try_inline_intrinsics(ciMethod* callee); - bool try_inline_full( ciMethod* callee, bool holder_known, Bytecodes::Code bc = Bytecodes::_illegal, Value receiver = NULL); + bool try_inline( ciMethod* callee, bool holder_known, bool ignore_return, Bytecodes::Code bc = Bytecodes::_illegal, Value receiver = NULL); + bool try_inline_intrinsics(ciMethod* callee, bool ignore_return = false); + bool try_inline_full( ciMethod* callee, bool holder_known, bool ignore_return, Bytecodes::Code bc = Bytecodes::_illegal, Value receiver = NULL); bool try_inline_jsr(int jsr_dest_bci); const char* check_can_parse(ciMethod* callee) const; const char* should_not_inline(ciMethod* callee) const; // JSR 292 support - bool try_method_handle_inline(ciMethod* callee); + bool try_method_handle_inline(ciMethod* callee, bool ignore_return); // helpers void inline_bailout(const char* msg); From da1655a0095e1081fc307d1e9827fc989f5d075b Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Mon, 22 Aug 2016 19:29:15 +0000 Subject: [PATCH 005/110] 8163864: [JVMCI] move MethodProfileWidth to jvmci_globals.hpp Reviewed-by: zmajo --- hotspot/src/share/vm/jvmci/jvmci_globals.cpp | 1 + hotspot/src/share/vm/jvmci/jvmci_globals.hpp | 3 +++ hotspot/src/share/vm/oops/methodData.hpp | 3 +++ hotspot/src/share/vm/runtime/globals.hpp | 3 --- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/jvmci/jvmci_globals.cpp b/hotspot/src/share/vm/jvmci/jvmci_globals.cpp index 7308935d79b..bb300a32d1c 100644 --- a/hotspot/src/share/vm/jvmci/jvmci_globals.cpp +++ b/hotspot/src/share/vm/jvmci/jvmci_globals.cpp @@ -84,6 +84,7 @@ bool JVMCIGlobals::check_jvmci_flags_are_consistent() { CHECK_NOT_SET(JVMCICountersExcludeCompiler, EnableJVMCI) CHECK_NOT_SET(JVMCIUseFastLocking, EnableJVMCI) CHECK_NOT_SET(JVMCINMethodSizeLimit, EnableJVMCI) + CHECK_NOT_SET(MethodProfileWidth, EnableJVMCI) CHECK_NOT_SET(TraceUncollectedSpeculations, EnableJVMCI) #ifndef PRODUCT diff --git a/hotspot/src/share/vm/jvmci/jvmci_globals.hpp b/hotspot/src/share/vm/jvmci/jvmci_globals.hpp index c2905f5f110..ea6fd77c18f 100644 --- a/hotspot/src/share/vm/jvmci/jvmci_globals.hpp +++ b/hotspot/src/share/vm/jvmci/jvmci_globals.hpp @@ -88,6 +88,9 @@ experimental(intx, JVMCINMethodSizeLimit, (80*K)*wordSize, \ "Maximum size of a compiled method.") \ \ + experimental(intx, MethodProfileWidth, 0, \ + "Number of methods to record in call profile") \ + \ develop(bool, TraceUncollectedSpeculations, false, \ "Print message when a failed speculation was not collected") diff --git a/hotspot/src/share/vm/oops/methodData.hpp b/hotspot/src/share/vm/oops/methodData.hpp index 59669602a38..ee39f066288 100644 --- a/hotspot/src/share/vm/oops/methodData.hpp +++ b/hotspot/src/share/vm/oops/methodData.hpp @@ -30,6 +30,9 @@ #include "oops/method.hpp" #include "oops/oop.hpp" #include "runtime/orderAccess.hpp" +#if INCLUDE_JVMCI +#include "jvmci/jvmci_globals.hpp" +#endif class BytecodeStream; class KlassSizeStats; diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 89314669efd..20b22a7cc9b 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -3027,9 +3027,6 @@ public: "Number of receiver types to record in call/cast profile") \ range(0, 8) \ \ - experimental(intx, MethodProfileWidth, 0, \ - "Number of methods to record in call profile") \ - \ develop(intx, BciProfileWidth, 2, \ "Number of return bci's to record in ret profile") \ \ From 913622a64157c4c2ce496ecddf7a8c4315e1ff84 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Tue, 23 Aug 2016 13:44:26 +0200 Subject: [PATCH 006/110] 8038348: Instance field load is replaced by wrong data Phi Store additional information in PhiNodes corresponding to known instance field values to avoid incorrect reusage. Reviewed-by: kvn, vlivanov --- hotspot/src/share/vm/opto/cfgnode.hpp | 10 +++++++++- hotspot/src/share/vm/opto/macro.cpp | 4 ++-- hotspot/src/share/vm/opto/memnode.cpp | 4 ++-- hotspot/src/share/vm/opto/phaseX.cpp | 14 ++++++++++++++ hotspot/src/share/vm/opto/type.hpp | 2 +- 5 files changed, 28 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/opto/cfgnode.hpp b/hotspot/src/share/vm/opto/cfgnode.hpp index 8651b672121..4866e43eb47 100644 --- a/hotspot/src/share/vm/opto/cfgnode.hpp +++ b/hotspot/src/share/vm/opto/cfgnode.hpp @@ -119,6 +119,9 @@ class JProjNode : public ProjNode { // input in slot 0. class PhiNode : public TypeNode { const TypePtr* const _adr_type; // non-null only for Type::MEMORY nodes. + // The following fields are only used for data PhiNodes to indicate + // that the PhiNode represents the value of a known instance field. + int _inst_mem_id; // Instance memory id (node index of the memory Phi) const int _inst_id; // Instance id of the memory slice. const int _inst_index; // Alias index of the instance memory slice. // Array elements references have the same alias_idx but different offset. @@ -138,11 +141,13 @@ public: }; PhiNode( Node *r, const Type *t, const TypePtr* at = NULL, + const int imid = -1, const int iid = TypeOopPtr::InstanceTop, const int iidx = Compile::AliasIdxTop, const int ioffs = Type::OffsetTop ) : TypeNode(t,r->req()), _adr_type(at), + _inst_mem_id(imid), _inst_id(iid), _inst_index(iidx), _inst_offset(ioffs) @@ -194,11 +199,14 @@ public: virtual bool pinned() const { return in(0) != 0; } virtual const TypePtr *adr_type() const { verify_adr_type(true); return _adr_type; } + void set_inst_mem_id(int inst_mem_id) { _inst_mem_id = inst_mem_id; } + const int inst_mem_id() const { return _inst_mem_id; } const int inst_id() const { return _inst_id; } const int inst_index() const { return _inst_index; } const int inst_offset() const { return _inst_offset; } - bool is_same_inst_field(const Type* tp, int id, int index, int offset) { + bool is_same_inst_field(const Type* tp, int mem_id, int id, int index, int offset) { return type()->basic_type() == tp->basic_type() && + inst_mem_id() == mem_id && inst_id() == id && inst_index() == index && inst_offset() == offset && diff --git a/hotspot/src/share/vm/opto/macro.cpp b/hotspot/src/share/vm/opto/macro.cpp index 653d20f2d96..8aaeb0e4637 100644 --- a/hotspot/src/share/vm/opto/macro.cpp +++ b/hotspot/src/share/vm/opto/macro.cpp @@ -491,7 +491,7 @@ Node *PhaseMacroExpand::value_from_mem_phi(Node *mem, BasicType ft, const Type * for (DUIterator_Fast kmax, k = region->fast_outs(kmax); k < kmax; k++) { Node* phi = region->fast_out(k); if (phi->is_Phi() && phi != mem && - phi->as_Phi()->is_same_inst_field(phi_type, instance_id, alias_idx, offset)) { + phi->as_Phi()->is_same_inst_field(phi_type, (int)mem->_idx, instance_id, alias_idx, offset)) { return phi; } } @@ -510,7 +510,7 @@ Node *PhaseMacroExpand::value_from_mem_phi(Node *mem, BasicType ft, const Type * GrowableArray values(length, length, NULL, false); // create a new Phi for the value - PhiNode *phi = new PhiNode(mem->in(0), phi_type, NULL, instance_id, alias_idx, offset); + PhiNode *phi = new PhiNode(mem->in(0), phi_type, NULL, mem->_idx, instance_id, alias_idx, offset); transform_later(phi); value_phis->push(phi, mem->_idx); diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp index 1ea3bd2c902..d82a4a64f97 100644 --- a/hotspot/src/share/vm/opto/memnode.cpp +++ b/hotspot/src/share/vm/opto/memnode.cpp @@ -1112,7 +1112,7 @@ Node* LoadNode::Identity(PhaseGVN* phase) { for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) { Node* phi = region->fast_out(i); if (phi->is_Phi() && phi != mem && - phi->as_Phi()->is_same_inst_field(this_type, this_iid, this_index, this_offset)) { + phi->as_Phi()->is_same_inst_field(this_type, (int)mem->_idx, this_iid, this_index, this_offset)) { return phi; } } @@ -1395,7 +1395,7 @@ Node *LoadNode::split_through_phi(PhaseGVN *phase) { this_iid = base->_idx; } PhaseIterGVN* igvn = phase->is_IterGVN(); - Node* phi = new PhiNode(region, this_type, NULL, this_iid, this_index, this_offset); + Node* phi = new PhiNode(region, this_type, NULL, mem->_idx, this_iid, this_index, this_offset); for (uint i = 1; i < region->req(); i++) { Node* x; Node* the_clone = NULL; diff --git a/hotspot/src/share/vm/opto/phaseX.cpp b/hotspot/src/share/vm/opto/phaseX.cpp index 0934a0fd7df..c7cde9e873a 100644 --- a/hotspot/src/share/vm/opto/phaseX.cpp +++ b/hotspot/src/share/vm/opto/phaseX.cpp @@ -491,6 +491,8 @@ PhaseRenumberLive::PhaseRenumberLive(PhaseGVN* gvn, uint current_idx = 0; // The current new node ID. Incremented after every assignment. for (uint i = 0; i < _useful.size(); i++) { Node* n = _useful.at(i); + // Sanity check that fails if we ever decide to execute this phase after EA + assert(!n->is_Phi() || n->as_Phi()->inst_mem_id() == -1, "should not be linked to data Phi"); const Type* type = gvn->type_or_null(n); new_type_array.map(current_idx, type); @@ -1448,6 +1450,18 @@ void PhaseIterGVN::subsume_node( Node *old, Node *nn ) { i -= num_edges; // we deleted 1 or more copies of this edge } + // Search for instance field data PhiNodes in the same region pointing to the old + // memory PhiNode and update their instance memory ids to point to the new node. + if (old->is_Phi() && old->as_Phi()->type()->has_memory() && old->in(0) != NULL) { + Node* region = old->in(0); + for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) { + PhiNode* phi = region->fast_out(i)->isa_Phi(); + if (phi != NULL && phi->inst_mem_id() == (int)old->_idx) { + phi->set_inst_mem_id((int)nn->_idx); + } + } + } + // Smash all inputs to 'old', isolating him completely Node *temp = new Node(1); temp->init_req(0,nn); // Add a use to nn to prevent him from dying diff --git a/hotspot/src/share/vm/opto/type.hpp b/hotspot/src/share/vm/opto/type.hpp index 07b91cb0245..1252dc14db6 100644 --- a/hotspot/src/share/vm/opto/type.hpp +++ b/hotspot/src/share/vm/opto/type.hpp @@ -963,7 +963,7 @@ protected: // If not InstanceTop or InstanceBot, indicates that this is // a particular instance of this type which is distinct. - // This is the the node index of the allocation node creating this instance. + // This is the node index of the allocation node creating this instance. int _instance_id; static const TypeOopPtr* make_from_klass_common(ciKlass* klass, bool klass_change, bool try_for_exact); From 00979c250a4bb182832b907cfe8a0fa71da876d5 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Tue, 23 Aug 2016 15:16:45 +0000 Subject: [PATCH 007/110] 8164214: [JVMCI] include VarHandle in signature polymorphic method test Reviewed-by: kvn, twisti, iveresov, psandoz --- .../src/jdk/vm/ci/hotspot/CompilerToVM.java | 17 +++-- .../vm/ci/hotspot/HotSpotConstantPool.java | 62 ++++++++++++------- .../jdk/vm/ci/meta/ResolvedJavaMethod.java | 19 ------ .../src/share/vm/jvmci/jvmciCompilerToVM.cpp | 22 +++++-- .../runtime/test/TestResolvedJavaMethod.java | 36 ++++------- 5 files changed, 81 insertions(+), 75 deletions(-) diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java index c96da48e6fc..4ceed9283ad 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java @@ -244,16 +244,20 @@ final class CompilerToVM { native void resolveInvokeDynamicInPool(HotSpotConstantPool constantPool, int cpi); /** - * Ensures that the type referenced by the entry for a + * If {@code cpi} denotes an entry representing a * signature - * polymorphic method at index {@code cpi} in {@code constantPool} is loaded and - * initialized. - * - * The behavior of this method is undefined if {@code cpi} does not denote an entry representing - * a signature polymorphic method. + * polymorphic method, this method ensures that the type referenced by the entry is loaded + * and initialized. It {@code cpi} does not denote a signature polymorphic method, this method + * does nothing. */ native void resolveInvokeHandleInPool(HotSpotConstantPool constantPool, int cpi); + /** + * Gets the list of type names (in the format of {@link JavaType#getName()}) denoting the + * classes that define signature polymorphic methods. + */ + native String[] getSignaturePolymorphicHolders(); + /** * Gets the resolved type denoted by the entry at index {@code cpi} in {@code constantPool}. * @@ -610,4 +614,5 @@ final class CompilerToVM { * @return the number of bytes required for deoptimization of this frame state */ native int interpreterFrameSize(BytecodeFrame frame); + } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java index 1f29ff8cce4..bd2c1699973 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java @@ -282,7 +282,7 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject * @return constant pool tag */ private JVM_CONSTANT getTagAt(int index) { - assertBounds(index); + assert checkBounds(index); HotSpotVMConfig config = config(); final long metaspaceConstantPoolTags = UNSAFE.getAddress(getMetaspaceConstantPool() + config.constantPoolTagsOffset); final int tag = UNSAFE.getByteVolatile(null, metaspaceConstantPoolTags + config.arrayU1DataOffset + index); @@ -299,7 +299,7 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject * @return constant pool entry */ private long getEntryAt(int index) { - assertBounds(index); + assert checkBounds(index); int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize; return UNSAFE.getAddress(getMetaspaceConstantPool() + config().constantPoolSize + offset); } @@ -311,7 +311,7 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject * @return integer constant pool entry at index */ private int getIntAt(int index) { - assertTag(index, JVM_CONSTANT.Integer); + assert checkTag(index, JVM_CONSTANT.Integer); int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize; return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + offset); } @@ -323,7 +323,7 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject * @return long constant pool entry */ private long getLongAt(int index) { - assertTag(index, JVM_CONSTANT.Long); + assert checkTag(index, JVM_CONSTANT.Long); int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize; return UNSAFE.getLong(getMetaspaceConstantPool() + config().constantPoolSize + offset); } @@ -335,7 +335,7 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject * @return float constant pool entry */ private float getFloatAt(int index) { - assertTag(index, JVM_CONSTANT.Float); + assert checkTag(index, JVM_CONSTANT.Float); int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize; return UNSAFE.getFloat(getMetaspaceConstantPool() + config().constantPoolSize + offset); } @@ -347,7 +347,7 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject * @return float constant pool entry */ private double getDoubleAt(int index) { - assertTag(index, JVM_CONSTANT.Double); + assert checkTag(index, JVM_CONSTANT.Double); int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize; return UNSAFE.getDouble(getMetaspaceConstantPool() + config().constantPoolSize + offset); } @@ -359,7 +359,7 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject * @return {@code JVM_CONSTANT_NameAndType} constant pool entry */ private int getNameAndTypeAt(int index) { - assertTag(index, JVM_CONSTANT.NameAndType); + assert checkTag(index, JVM_CONSTANT.NameAndType); int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize; return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + offset); } @@ -441,7 +441,7 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject * @return klass reference index */ private int getUncachedKlassRefIndexAt(int index) { - assertTagIsFieldOrMethod(index); + assert checkTagIsFieldOrMethod(index); int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize; final int refIndex = UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + offset); // klass ref index is in the low 16-bits. @@ -449,23 +449,27 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject } /** - * Asserts that the constant pool index {@code index} is in the bounds of the constant pool. + * Checks that the constant pool index {@code index} is in the bounds of the constant pool. * * @param index constant pool index + * @throws AssertionError if the check fails */ - private void assertBounds(int index) { + private boolean checkBounds(int index) { assert 0 <= index && index < length() : "index " + index + " not between 0 and " + length(); + return true; } /** - * Asserts that the constant pool tag at index {@code index} is equal to {@code tag}. + * Checks that the constant pool tag at index {@code index} is equal to {@code tag}. * * @param index constant pool index * @param tag expected tag + * @throws AssertionError if the check fails */ - private void assertTag(int index, JVM_CONSTANT tag) { + private boolean checkTag(int index, JVM_CONSTANT tag) { final JVM_CONSTANT tagAt = getTagAt(index); assert tagAt == tag : "constant pool tag at index " + index + " is " + tagAt + " but expected " + tag; + return true; } /** @@ -473,10 +477,12 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject * or a {@link JVM_CONSTANT#MethodRef}, or a {@link JVM_CONSTANT#InterfaceMethodref}. * * @param index constant pool index + * @throws AssertionError if the check fails */ - private void assertTagIsFieldOrMethod(int index) { + private boolean checkTagIsFieldOrMethod(int index) { final JVM_CONSTANT tagAt = getTagAt(index); assert tagAt == JVM_CONSTANT.Fieldref || tagAt == JVM_CONSTANT.MethodRef || tagAt == JVM_CONSTANT.InterfaceMethodref : tagAt; + return true; } @Override @@ -523,7 +529,7 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject @Override public String lookupUtf8(int cpi) { - assertTag(cpi, JVM_CONSTANT.Utf8); + assert checkTag(cpi, JVM_CONSTANT.Utf8); return compilerToVM().getSymbol(getEntryAt(cpi)); } @@ -690,11 +696,10 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject UNSAFE.ensureClassInitialized(klass); } if (tag == JVM_CONSTANT.MethodRef) { - if (Bytecodes.isInvokeHandleAlias(opcode)) { + if (Bytecodes.isInvokeHandleAlias(opcode) && isSignaturePolymorphicHolder(type)) { final int methodRefCacheIndex = rawIndexToConstantPoolIndex(cpi, opcode); - if (isInvokeHandle(methodRefCacheIndex, type)) { - compilerToVM().resolveInvokeHandleInPool(this, methodRefCacheIndex); - } + assert checkTag(compilerToVM().constantPoolRemapInstructionOperandFromCache(this, methodRefCacheIndex), JVM_CONSTANT.MethodRef); + compilerToVM().resolveInvokeHandleInPool(this, methodRefCacheIndex); } } @@ -708,11 +713,26 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject // nothing break; } + } - private boolean isInvokeHandle(int methodRefCacheIndex, HotSpotResolvedObjectTypeImpl klass) { - assertTag(compilerToVM().constantPoolRemapInstructionOperandFromCache(this, methodRefCacheIndex), JVM_CONSTANT.MethodRef); - return ResolvedJavaMethod.isSignaturePolymorphic(klass, getNameOf(methodRefCacheIndex), runtime().getHostJVMCIBackend().getMetaAccess()); + // Lazily initialized. + private static String[] signaturePolymorphicHolders; + + /** + * Determines if {@code type} contains signature polymorphic methods. + */ + private static boolean isSignaturePolymorphicHolder(final HotSpotResolvedObjectTypeImpl type) { + String name = type.getName(); + if (signaturePolymorphicHolders == null) { + signaturePolymorphicHolders = compilerToVM().getSignaturePolymorphicHolders(); + } + for (String holder : signaturePolymorphicHolders) { + if (name.equals(holder)) { + return true; + } + } + return false; } @Override diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java index 2c6736bacfa..3b2facc26d9 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java @@ -23,7 +23,6 @@ package jdk.vm.ci.meta; import java.lang.annotation.Annotation; -import java.lang.invoke.MethodHandle; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Array; import java.lang.reflect.Method; @@ -330,22 +329,4 @@ public interface ResolvedJavaMethod extends JavaMethod, InvokeTarget, ModifiersP } SpeculationLog getSpeculationLog(); - - /** - * Determines if the method identified by its holder and name is a - * signature - * polymorphic method. - */ - static boolean isSignaturePolymorphic(JavaType holder, String name, MetaAccessProvider metaAccess) { - if (!holder.getName().equals("Ljava/lang/invoke/MethodHandle;")) { - return false; - } - ResolvedJavaType methodHandleType = metaAccess.lookupJavaType(MethodHandle.class); - Signature signature = metaAccess.parseMethodDescriptor("([Ljava/lang/Object;)Ljava/lang/Object;"); - ResolvedJavaMethod method = methodHandleType.findMethod(name, signature); - if (method == null) { - return false; - } - return method.isNative() && method.isVarArgs(); - } } diff --git a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp index edc47626853..b0f7022ce61 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp @@ -1266,10 +1266,23 @@ C2V_END C2V_VMENTRY(void, resolveInvokeHandleInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index)) constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool); - CallInfo callInfo; - LinkResolver::resolve_invoke(callInfo, Handle(), cp, index, Bytecodes::_invokehandle, CHECK); - ConstantPoolCacheEntry* cp_cache_entry = cp_cache_entry = cp->cache()->entry_at(cp->decode_cpcache_index(index)); - cp_cache_entry->set_method_handle(cp, callInfo); + KlassHandle holder = cp->klass_ref_at(index, CHECK); + Symbol* name = cp->name_ref_at(index); + if (MethodHandles::is_signature_polymorphic_name(holder(), name)) { + CallInfo callInfo; + LinkResolver::resolve_invoke(callInfo, Handle(), cp, index, Bytecodes::_invokehandle, CHECK); + ConstantPoolCacheEntry* cp_cache_entry = cp_cache_entry = cp->cache()->entry_at(cp->decode_cpcache_index(index)); + cp_cache_entry->set_method_handle(cp, callInfo); + } +C2V_END + +C2V_VMENTRY(jobject, getSignaturePolymorphicHolders, (JNIEnv*, jobject)) + objArrayHandle holders = oopFactory::new_objArray(SystemDictionary::String_klass(), 2, CHECK_NULL); + Handle mh = java_lang_String::create_from_str("Ljava/lang/invoke/MethodHandle;", CHECK_NULL); + Handle vh = java_lang_String::create_from_str("Ljava/lang/invoke/VarHandle;", CHECK_NULL); + holders->obj_at_put(0, mh()); + holders->obj_at_put(1, vh()); + return JNIHandles::make_local(THREAD, holders()); C2V_END C2V_VMENTRY(jboolean, shouldDebugNonSafepoints, (JNIEnv*, jobject)) @@ -1511,6 +1524,7 @@ JNINativeMethod CompilerToVM::methods[] = { {CC "resolveInvokeDynamicInPool", CC "(" HS_CONSTANT_POOL "I)V", FN_PTR(resolveInvokeDynamicInPool)}, {CC "resolveInvokeHandleInPool", CC "(" HS_CONSTANT_POOL "I)V", FN_PTR(resolveInvokeHandleInPool)}, {CC "resolveMethod", CC "(" HS_RESOLVED_KLASS HS_RESOLVED_METHOD HS_RESOLVED_KLASS ")" HS_RESOLVED_METHOD, FN_PTR(resolveMethod)}, + {CC "getSignaturePolymorphicHolders", CC "()[" STRING, FN_PTR(getSignaturePolymorphicHolders)}, {CC "getVtableIndexForInterfaceMethod", CC "(" HS_RESOLVED_KLASS HS_RESOLVED_METHOD ")I", FN_PTR(getVtableIndexForInterfaceMethod)}, {CC "getClassInitializer", CC "(" HS_RESOLVED_KLASS ")" HS_RESOLVED_METHOD, FN_PTR(getClassInitializer)}, {CC "hasFinalizableSubclass", CC "(" HS_RESOLVED_KLASS ")Z", FN_PTR(hasFinalizableSubclass)}, diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java index 7805d193ec1..2faefc8bc49 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java @@ -33,19 +33,16 @@ package jdk.vm.ci.runtime.test; -import jdk.vm.ci.meta.ConstantPool; -import jdk.vm.ci.meta.ExceptionHandler; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaType; -import org.junit.Assert; -import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import java.lang.invoke.MethodHandle; import java.lang.reflect.Constructor; import java.lang.reflect.Member; import java.lang.reflect.Method; @@ -57,10 +54,13 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import org.junit.Assert; +import org.junit.Test; + +import jdk.vm.ci.meta.ConstantPool; +import jdk.vm.ci.meta.ExceptionHandler; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; /** * Tests for {@link ResolvedJavaMethod}. @@ -407,20 +407,6 @@ public class TestResolvedJavaMethod extends MethodUniverse { } } - @Test - public void isSignaturePolymorphicTest() { - ResolvedJavaType methodHandleType = metaAccess.lookupJavaType(MethodHandle.class); - assertTrue(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "invokeExact", metaAccess)); - assertTrue(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "invoke", metaAccess)); - assertTrue(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "invokeBasic", metaAccess)); - assertTrue(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "linkToVirtual", metaAccess)); - assertTrue(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "linkToStatic", metaAccess)); - assertTrue(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "linkToSpecial", metaAccess)); - assertTrue(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "linkToInterface", metaAccess)); - assertFalse(ResolvedJavaMethod.isSignaturePolymorphic(methodHandleType, "type", metaAccess)); - assertFalse(ResolvedJavaMethod.isSignaturePolymorphic(metaAccess.lookupJavaType(Object.class), "toString", metaAccess)); - } - /** * All public non-final methods should be available in the vtable. */ From f724bcdd9d6de98cd2e77ad55ff898518cd074fc Mon Sep 17 00:00:00 2001 From: Dmitrij Pochepko Date: Tue, 23 Aug 2016 19:30:56 +0300 Subject: [PATCH 008/110] 8164608: [TESTBUG] compiler/profiling tests fail to compile Reviewed-by: ctornqvi --- .../test/compiler/profiling/spectrapredefineclass/Launcher.java | 2 +- .../profiling/spectrapredefineclass_classloaders/Launcher.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/test/compiler/profiling/spectrapredefineclass/Launcher.java b/hotspot/test/compiler/profiling/spectrapredefineclass/Launcher.java index 76740831dec..9ca9ba0283b 100644 --- a/hotspot/test/compiler/profiling/spectrapredefineclass/Launcher.java +++ b/hotspot/test/compiler/profiling/spectrapredefineclass/Launcher.java @@ -40,7 +40,7 @@ package compiler.profiling.spectrapredefineclass; import jdk.test.lib.JDKToolLauncher; -import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.process.OutputAnalyzer; import java.io.File; import java.io.IOException; diff --git a/hotspot/test/compiler/profiling/spectrapredefineclass_classloaders/Launcher.java b/hotspot/test/compiler/profiling/spectrapredefineclass_classloaders/Launcher.java index 1f785b6d55e..857fbbbbd84 100644 --- a/hotspot/test/compiler/profiling/spectrapredefineclass_classloaders/Launcher.java +++ b/hotspot/test/compiler/profiling/spectrapredefineclass_classloaders/Launcher.java @@ -43,7 +43,7 @@ package compiler.profiling.spectrapredefineclass_classloaders; import jdk.test.lib.JDKToolLauncher; -import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.process.OutputAnalyzer; import java.io.File; import java.io.IOException; From a06d2b8547c6f4f3dfabb7348f9c17e5de4c069c Mon Sep 17 00:00:00 2001 From: Tatiana Pivovarova Date: Tue, 23 Aug 2016 19:53:40 +0300 Subject: [PATCH 009/110] 8164648: [TESTBUG] jittester failed compilation after 8157957 Reviewed-by: vlivanov --- hotspot/test/testlibrary/jittester/Makefile | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/hotspot/test/testlibrary/jittester/Makefile b/hotspot/test/testlibrary/jittester/Makefile index 4068d9d0af5..808765729dc 100644 --- a/hotspot/test/testlibrary/jittester/Makefile +++ b/hotspot/test/testlibrary/jittester/Makefile @@ -70,17 +70,17 @@ DIST_DIR = dist DIST_JAR = $(DIST_DIR)/JITtester.jar SRC_FILES = $(shell find $(SRC_DIR) -name '*.java') -TESTLIBRARY_SRC_DIR = ../jdk/test/lib +TESTLIBRARY_SRC_DIR = ../../../../test/lib/jdk/test/lib TESTLIBRARY_SRC_FILES = $(TESTLIBRARY_SRC_DIR)/Asserts.java \ $(TESTLIBRARY_SRC_DIR)/JDKToolFinder.java \ $(TESTLIBRARY_SRC_DIR)/JDKToolLauncher.java \ - $(TESTLIBRARY_SRC_DIR)/OutputAnalyzer.java \ - $(TESTLIBRARY_SRC_DIR)/OutputBuffer.java \ - $(TESTLIBRARY_SRC_DIR)/Pair.java \ $(TESTLIBRARY_SRC_DIR)/Platform.java \ - $(TESTLIBRARY_SRC_DIR)/ProcessTools.java \ - $(TESTLIBRARY_SRC_DIR)/StreamPumper.java \ - $(TESTLIBRARY_SRC_DIR)/Utils.java + $(TESTLIBRARY_SRC_DIR)/Utils.java \ + $(TESTLIBRARY_SRC_DIR)/process/OutputAnalyzer.java \ + $(TESTLIBRARY_SRC_DIR)/process/OutputBuffer.java \ + $(TESTLIBRARY_SRC_DIR)/process/ProcessTools.java \ + $(TESTLIBRARY_SRC_DIR)/process/StreamPumper.java \ + $(TESTLIBRARY_SRC_DIR)/util/Pair.java .PHONY: cleantmp @@ -120,7 +120,6 @@ cleantmp: copytestlibrary: $(DRIVER_DIR) @cp -r src/jdk/test/lib/jittester/jtreg/*.java $(DRIVER_DIR) - @cp -r ../jdk $(TESTBASE_DIR)/ testgroup: $(TESTBASE_DIR) @echo 'jittester_all = \\' > $(TESTGROUP_FILE) From 82de2bf10ec114d5cf17cff705de3e37a81731c4 Mon Sep 17 00:00:00 2001 From: Vivek Deshpande Date: Tue, 23 Aug 2016 12:26:05 -0700 Subject: [PATCH 010/110] 8151988: Hotspot deoptimizes div/mod pair usage Don't remove control edge of Mod node until DivMod node matching Reviewed-by: kvn --- hotspot/src/share/vm/opto/compile.cpp | 44 +++++++++++++++++++-------- hotspot/src/share/vm/opto/divnode.cpp | 14 --------- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index 7824b118b22..518caf6896c 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -3159,45 +3159,65 @@ void Compile::final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc) { break; #endif - case Op_ModI: + case Op_ModI: { + Node* di = NULL; if (UseDivMod) { // Check if a%b and a/b both exist - Node* d = n->find_similar(Op_DivI); - if (d) { + di = n->find_similar(Op_DivI); + if (di) { // Replace them with a fused divmod if supported if (Matcher::has_match_rule(Op_DivModI)) { DivModINode* divmod = DivModINode::make(n); - d->subsume_by(divmod->div_proj(), this); + di->subsume_by(divmod->div_proj(), this); n->subsume_by(divmod->mod_proj(), this); } else { // replace a%b with a-((a/b)*b) - Node* mult = new MulINode(d, d->in(2)); - Node* sub = new SubINode(d->in(1), mult); + Node* mult = new MulINode(di, di->in(2)); + Node* sub = new SubINode(di->in(1), mult); n->subsume_by(sub, this); } } } + if (di == NULL) { + // Remove useless control edge in case of not mod-zero. + const Type *t = n->in(2)->bottom_type(); + const TypeInt *ti = t->is_int(); + if (n->in(0) && (ti->_hi < 0 || ti->_lo > 0)) { + n->set_req(0, NULL); + } + } break; + } - case Op_ModL: + case Op_ModL: { + Node* dl = NULL; if (UseDivMod) { // Check if a%b and a/b both exist - Node* d = n->find_similar(Op_DivL); - if (d) { + dl = n->find_similar(Op_DivL); + if (dl) { // Replace them with a fused divmod if supported if (Matcher::has_match_rule(Op_DivModL)) { DivModLNode* divmod = DivModLNode::make(n); - d->subsume_by(divmod->div_proj(), this); + dl->subsume_by(divmod->div_proj(), this); n->subsume_by(divmod->mod_proj(), this); } else { // replace a%b with a-((a/b)*b) - Node* mult = new MulLNode(d, d->in(2)); - Node* sub = new SubLNode(d->in(1), mult); + Node* mult = new MulLNode(dl, dl->in(2)); + Node* sub = new SubLNode(dl->in(1), mult); n->subsume_by(sub, this); } } } + if (dl == NULL) { + // Remove useless control edge in case of not mod-zero. + const Type *t = n->in(2)->bottom_type(); + const TypeLong *tl = t->is_long(); + if (n->in(0) && (tl->_hi < 0 || tl->_lo > 0)) { + n->set_req(0, NULL); + } + } break; + } case Op_LoadVector: case Op_StoreVector: diff --git a/hotspot/src/share/vm/opto/divnode.cpp b/hotspot/src/share/vm/opto/divnode.cpp index de839cc2c6b..cf45d3b966c 100644 --- a/hotspot/src/share/vm/opto/divnode.cpp +++ b/hotspot/src/share/vm/opto/divnode.cpp @@ -853,13 +853,6 @@ Node *ModINode::Ideal(PhaseGVN *phase, bool can_reshape) { if( t == Type::TOP ) return NULL; const TypeInt *ti = t->is_int(); - // Check for useless control input - // Check for excluding mod-zero case - if( in(0) && (ti->_hi < 0 || ti->_lo > 0) ) { - set_req(0, NULL); // Yank control input - return this; - } - // See if we are MOD'ing by 2^k or 2^k-1. if( !ti->is_con() ) return NULL; jint con = ti->get_con(); @@ -1024,13 +1017,6 @@ Node *ModLNode::Ideal(PhaseGVN *phase, bool can_reshape) { if( t == Type::TOP ) return NULL; const TypeLong *tl = t->is_long(); - // Check for useless control input - // Check for excluding mod-zero case - if( in(0) && (tl->_hi < 0 || tl->_lo > 0) ) { - set_req(0, NULL); // Yank control input - return this; - } - // See if we are MOD'ing by 2^k or 2^k-1. if( !tl->is_con() ) return NULL; jlong con = tl->get_con(); From 1fd875eaf944a91df875b0f193713efd802d475f Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Tue, 23 Aug 2016 22:24:31 +0000 Subject: [PATCH 011/110] 8164358: [JVMCI] expose Hotspot intrinsics and HotSpotIntrinsicCandidate info to JVMCI Reviewed-by: twisti, kvn, never --- .../src/jdk/vm/ci/hotspot/CompilerToVM.java | 1 + .../vm/ci/hotspot/HotSpotJVMCIRuntime.java | 3 + .../ci/hotspot/HotSpotResolvedJavaMethod.java | 9 ++ .../HotSpotResolvedJavaMethodImpl.java | 4 + .../jdk/vm/ci/hotspot/HotSpotVMConfig.java | 1 + .../vm/ci/hotspot/HotSpotVMConfigAccess.java | 7 ++ .../vm/ci/hotspot/HotSpotVMConfigStore.java | 24 +++-- .../jdk/vm/ci/hotspot/VMIntrinsicMethod.java | 87 +++++++++++++++++++ .../src/share/vm/jvmci/jvmciCompilerToVM.cpp | 46 +++++++++- .../src/share/vm/jvmci/jvmciCompilerToVM.hpp | 4 +- .../src/share/vm/jvmci/jvmciJavaClasses.hpp | 6 ++ .../share/vm/jvmci/systemDictionary_jvmci.hpp | 1 + .../src/share/vm/jvmci/vmStructs_jvmci.cpp | 1 + .../src/share/vm/jvmci/vmSymbols_jvmci.hpp | 1 + ...onTest.java => ReadConfigurationTest.java} | 18 +++- 15 files changed, 199 insertions(+), 14 deletions(-) create mode 100644 hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/VMIntrinsicMethod.java rename hotspot/test/compiler/jvmci/compilerToVM/{InitializeConfigurationTest.java => ReadConfigurationTest.java} (77%) diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java index 4ceed9283ad..34b80e013b3 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java @@ -352,6 +352,7 @@ final class CompilerToVM { * [String name, Long value, ...] vmConstants, * [String name, Long value, ...] vmAddresses, * VMFlag[] vmFlags + * VMIntrinsicMethod[] vmIntrinsics * ] * * diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java index 4d6be98fc6f..3c70ea7bbf0 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java @@ -497,6 +497,9 @@ public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider { for (Map.Entry e : typeSizes.entrySet()) { printConfigLine(vm, "[vmconfig:type size] %s = %d%n", e.getKey(), e.getValue()); } + for (VMIntrinsicMethod e : store.getIntrinsics()) { + printConfigLine(vm, "[vmconfig:intrinsic] %d = %s.%s %s%n", e.id, e.declaringClass, e.name, e.descriptor); + } } public OutputStream getLogStream() { diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java index 8634881fe4d..dc56435038a 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java @@ -111,6 +111,15 @@ public interface HotSpotResolvedJavaMethod extends ResolvedJavaMethod { int intrinsicId(); + /** + * Determines if this method denotes itself as a candidate for intrinsification. As of JDK 9, + * this is denoted by the {@code HotSpotIntrinsicCandidate} annotation. In earlier JDK versions, + * this method returns true. + * + * @see JDK-8076112 + */ + boolean isIntrinsicCandidate(); + /** * Allocates a compile id for this method by asking the VM for one. * diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index 196616c4d61..dd4658d1d3d 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -693,6 +693,10 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp return UNSAFE.getChar(metaspaceMethod + config.methodIntrinsicIdOffset); } + public boolean isIntrinsicCandidate() { + return (getFlags() & config().methodFlagsIntrinsicCandidate) != 0; + } + @Override public JavaConstant invoke(JavaConstant receiver, JavaConstant[] arguments) { assert !isConstructor(); diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java index 46f5d71096c..64ec7c0b886 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java @@ -144,6 +144,7 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess { final int methodFlagsCallerSensitive = getConstant("Method::_caller_sensitive", Integer.class); final int methodFlagsForceInline = getConstant("Method::_force_inline", Integer.class); + final int methodFlagsIntrinsicCandidate = getConstant("Method::_intrinsic_candidate", Integer.class); final int methodFlagsDontInline = getConstant("Method::_dont_inline", Integer.class); final int methodFlagsReservedStackAccess = getConstant("Method::_reserved_stack_access", Integer.class); final int nonvirtualVtableIndex = getConstant("Method::nonvirtual_vtable_index", Integer.class); diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java index 73ce3c545f0..9bb538d587b 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java @@ -29,6 +29,13 @@ import jdk.vm.ci.common.JVMCIError; */ public class HotSpotVMConfigAccess { + /** + * Gets the available configuration data. + */ + public HotSpotVMConfigStore getStore() { + return store; + } + /** * Gets the address of a C++ symbol. * diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigStore.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigStore.java index c0554391a79..e6f074d948f 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigStore.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigStore.java @@ -24,8 +24,10 @@ package jdk.vm.ci.hotspot; import static jdk.vm.ci.common.InitTimer.timer; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import jdk.vm.ci.common.InitTimer; @@ -80,11 +82,19 @@ public final class HotSpotVMConfigStore { return Collections.unmodifiableMap(vmFields); } + /** + * Gets the VM intrinsic descriptions exposed by this object. + */ + public List getIntrinsics() { + return Collections.unmodifiableList(vmIntrinsics); + } + final HashMap vmFields; final HashMap vmTypeSizes; final HashMap vmConstants; final HashMap vmAddresses; final HashMap vmFlags; + final List vmIntrinsics; /** * Reads the database of VM info. The return value encodes the info in a nested object array @@ -97,6 +107,7 @@ public final class HotSpotVMConfigStore { * [String name, Long value, ...] vmConstants, * [String name, Long value, ...] vmAddresses, * VMFlag[] vmFlags + * VMIntrinsicMethod[] vmIntrinsics * ] * */ @@ -106,7 +117,7 @@ public final class HotSpotVMConfigStore { try (InitTimer t = timer("CompilerToVm readConfiguration")) { data = compilerToVm.readConfiguration(); } - assert data.length == 5 : data.length; + assert data.length == 6 : data.length; // @formatter:off VMField[] vmFieldsInfo = (VMField[]) data[0]; @@ -115,11 +126,12 @@ public final class HotSpotVMConfigStore { Object[] vmAddressesInfo = (Object[]) data[3]; VMFlag[] vmFlagsInfo = (VMFlag[]) data[4]; - vmFields = new HashMap<>(vmFieldsInfo.length); - vmTypeSizes = new HashMap<>(vmTypesSizesInfo.length); - vmConstants = new HashMap<>(vmConstantsInfo.length); - vmAddresses = new HashMap<>(vmAddressesInfo.length); - vmFlags = new HashMap<>(vmFlagsInfo.length); + vmFields = new HashMap<>(vmFieldsInfo.length); + vmTypeSizes = new HashMap<>(vmTypesSizesInfo.length); + vmConstants = new HashMap<>(vmConstantsInfo.length); + vmAddresses = new HashMap<>(vmAddressesInfo.length); + vmFlags = new HashMap<>(vmFlagsInfo.length); + vmIntrinsics = Arrays.asList((VMIntrinsicMethod[]) data[5]); // @formatter:on try (InitTimer t = timer("HotSpotVMConfigStore fill maps")) { diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/VMIntrinsicMethod.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/VMIntrinsicMethod.java new file mode 100644 index 00000000000..2621543d657 --- /dev/null +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/VMIntrinsicMethod.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.vm.ci.hotspot; + +import jdk.vm.ci.meta.Signature; + +/** + * Describes a method for which the VM has an intrinsic implementation. + */ +public final class VMIntrinsicMethod { + + /** + * The name of the class declaring the intrinsified method. The name is in + * class + * file format (e.g., {@code "java/lang/Thread"} instead of {@code "java.lang.Thread"}). + */ + public final String declaringClass; + + /** + * The name of the intrinsified method. This is not guaranteed to be a legal method name (e.g., + * there is a HotSpot intrinsic with the name {@code ""}). + */ + public final String name; + + /** + * The {@link Signature#toMethodDescriptor() descriptor} of the intrinsified method. This is not + * guaranteed to be a legal method descriptor (e.g., intrinsics for signature polymorphic + * methods have a descriptor of {@code "*"}). + */ + public final String descriptor; + + /** + * The unique VM identifier for the intrinsic. + */ + public final int id; + + VMIntrinsicMethod(String declaringClass, String name, String descriptor, int id) { + this.declaringClass = declaringClass; + this.name = name; + this.descriptor = descriptor; + this.id = id; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof VMIntrinsicMethod) { + VMIntrinsicMethod that = (VMIntrinsicMethod) obj; + if (that.id == this.id) { + assert that.name.equals(this.name) && + that.declaringClass.equals(this.declaringClass) && + that.descriptor.equals(this.descriptor); + return true; + } + } + return false; + } + + @Override + public int hashCode() { + return id; + } + + @Override + public String toString() { + return String.format("IntrinsicMethod[declaringClass=%s, name=%s, descriptor=%s, id=%d]", declaringClass, name, descriptor, id); + } +} diff --git a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp index b0f7022ce61..69429aaf885 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp @@ -203,6 +203,40 @@ void CompilerToVM::Data::initialize() { #undef SET_TRIGFUNC } +objArrayHandle CompilerToVM::initialize_intrinsics(TRAPS) { + objArrayHandle vmIntrinsics = oopFactory::new_objArray(VMIntrinsicMethod::klass(), (vmIntrinsics::ID_LIMIT - 1), CHECK_(objArrayHandle())); + int index = 0; + // The intrinsics for a class are usually adjacent to each other. + // When they are, the string for the class name can be reused. + vmSymbols::SID kls_sid = vmSymbols::NO_SID; + Handle kls_str; +#define SID_ENUM(n) vmSymbols::VM_SYMBOL_ENUM_NAME(n) +#define VM_SYMBOL_TO_STRING(s) \ + java_lang_String::create_from_symbol(vmSymbols::symbol_at(SID_ENUM(s)), CHECK_(objArrayHandle())) +#define VM_INTRINSIC_INFO(id, kls, name, sig, ignore_fcode) { \ + instanceHandle vmIntrinsicMethod = InstanceKlass::cast(VMIntrinsicMethod::klass())->allocate_instance_handle(CHECK_(objArrayHandle())); \ + if (kls_sid != SID_ENUM(kls)) { \ + kls_str = VM_SYMBOL_TO_STRING(kls); \ + kls_sid = SID_ENUM(kls); \ + } \ + Handle name_str = VM_SYMBOL_TO_STRING(name); \ + Handle sig_str = VM_SYMBOL_TO_STRING(sig); \ + VMIntrinsicMethod::set_declaringClass(vmIntrinsicMethod, kls_str()); \ + VMIntrinsicMethod::set_name(vmIntrinsicMethod, name_str()); \ + VMIntrinsicMethod::set_descriptor(vmIntrinsicMethod, sig_str()); \ + VMIntrinsicMethod::set_id(vmIntrinsicMethod, vmIntrinsics::id); \ + vmIntrinsics->obj_at_put(index++, vmIntrinsicMethod()); \ + } + + VM_INTRINSICS_DO(VM_INTRINSIC_INFO, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE) +#undef SID_ENUM +#undef VM_SYMBOL_TO_STRING +#undef VM_INTRINSIC_INFO + assert(index == vmIntrinsics::ID_LIMIT - 1, "must be"); + + return vmIntrinsics; +} + C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv *env)) #define BOXED_LONG(name, value) oop name; do { jvalue p; p.j = (jlong) (value); name = java_lang_boxing_object::create(T_LONG, &p, CHECK_NULL);} while(0) #define BOXED_DOUBLE(name, value) oop name; do { jvalue p; p.d = (jdouble) (value); name = java_lang_boxing_object::create(T_DOUBLE, &p, CHECK_NULL);} while(0) @@ -211,8 +245,9 @@ C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv *env)) CompilerToVM::Data::initialize(); - VMField::klass()->initialize(thread); - VMFlag::klass()->initialize(thread); + VMField::klass()->initialize(CHECK_NULL); + VMFlag::klass()->initialize(CHECK_NULL); + VMIntrinsicMethod::klass()->initialize(CHECK_NULL); int len = JVMCIVMStructs::localHotSpotVMStructs_count(); objArrayHandle vmFields = oopFactory::new_objArray(VMField::klass(), len, CHECK_NULL); @@ -220,7 +255,7 @@ C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv *env)) VMStructEntry vmField = JVMCIVMStructs::localHotSpotVMStructs[i]; instanceHandle vmFieldObj = InstanceKlass::cast(VMField::klass())->allocate_instance_handle(CHECK_NULL); size_t name_buf_len = strlen(vmField.typeName) + strlen(vmField.fieldName) + 2 /* "::" */; - char* name_buf = NEW_RESOURCE_ARRAY(char, name_buf_len + 1); + char* name_buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, name_buf_len + 1); sprintf(name_buf, "%s::%s", vmField.typeName, vmField.fieldName); Handle name = java_lang_String::create_from_str(name_buf, CHECK_NULL); Handle type = java_lang_String::create_from_str(vmField.typeString, CHECK_NULL); @@ -338,12 +373,15 @@ C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv *env)) vmFlags->obj_at_put(i, vmFlagObj()); } - objArrayOop data = oopFactory::new_objArray(SystemDictionary::Object_klass(), 5, CHECK_NULL); + objArrayHandle vmIntrinsics = CompilerToVM::initialize_intrinsics(CHECK_NULL); + + objArrayOop data = oopFactory::new_objArray(SystemDictionary::Object_klass(), 6, CHECK_NULL); data->obj_at_put(0, vmFields()); data->obj_at_put(1, vmTypes()); data->obj_at_put(2, vmConstants()); data->obj_at_put(3, vmAddresses()); data->obj_at_put(4, vmFlags()); + data->obj_at_put(5, vmIntrinsics()); return (jobjectArray) JNIHandles::make_local(THREAD, data); #undef BOXED_LONG diff --git a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp index 2bbd2034795..364be048220 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp +++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp @@ -83,8 +83,10 @@ class CompilerToVM { } }; - public: static JNINativeMethod methods[]; + + static objArrayHandle initialize_intrinsics(TRAPS); + public: static int methods_count(); static inline Method* asMethod(jobject jvmci_method) { diff --git a/hotspot/src/share/vm/jvmci/jvmciJavaClasses.hpp b/hotspot/src/share/vm/jvmci/jvmciJavaClasses.hpp index 8f8f0715ef7..d6039fca4a3 100644 --- a/hotspot/src/share/vm/jvmci/jvmciJavaClasses.hpp +++ b/hotspot/src/share/vm/jvmci/jvmciJavaClasses.hpp @@ -124,6 +124,12 @@ class JVMCIJavaClasses : AllStatic { oop_field(VMFlag, type, "Ljava/lang/String;") \ oop_field(VMFlag, value, "Ljava/lang/Object;") \ end_class \ + start_class(VMIntrinsicMethod) \ + oop_field(VMIntrinsicMethod, declaringClass, "Ljava/lang/String;") \ + oop_field(VMIntrinsicMethod, name, "Ljava/lang/String;") \ + oop_field(VMIntrinsicMethod, descriptor, "Ljava/lang/String;") \ + int_field(VMIntrinsicMethod, id) \ + end_class \ start_class(Assumptions_NoFinalizableSubclass) \ oop_field(Assumptions_NoFinalizableSubclass, receiverType, "Ljdk/vm/ci/meta/ResolvedJavaType;") \ end_class \ diff --git a/hotspot/src/share/vm/jvmci/systemDictionary_jvmci.hpp b/hotspot/src/share/vm/jvmci/systemDictionary_jvmci.hpp index 05f12fb84ed..cd0bb6c20bd 100644 --- a/hotspot/src/share/vm/jvmci/systemDictionary_jvmci.hpp +++ b/hotspot/src/share/vm/jvmci/systemDictionary_jvmci.hpp @@ -51,6 +51,7 @@ do_klass(HotSpotCompilationRequestResult_klass, jdk_vm_ci_hotspot_HotSpotCompilationRequestResult, Jvmci) \ do_klass(VMField_klass, jdk_vm_ci_hotspot_VMField, Jvmci) \ do_klass(VMFlag_klass, jdk_vm_ci_hotspot_VMFlag, Jvmci) \ + do_klass(VMIntrinsicMethod_klass, jdk_vm_ci_hotspot_VMIntrinsicMethod, Jvmci) \ do_klass(Assumptions_ConcreteMethod_klass, jdk_vm_ci_meta_Assumptions_ConcreteMethod, Jvmci) \ do_klass(Assumptions_NoFinalizableSubclass_klass, jdk_vm_ci_meta_Assumptions_NoFinalizableSubclass, Jvmci) \ do_klass(Assumptions_ConcreteSubtype_klass, jdk_vm_ci_meta_Assumptions_ConcreteSubtype, Jvmci) \ diff --git a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp index 90f5cf15fc7..3d48df55477 100644 --- a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp +++ b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp @@ -493,6 +493,7 @@ declare_constant(Method::_force_inline) \ declare_constant(Method::_dont_inline) \ declare_constant(Method::_hidden) \ + declare_constant(Method::_intrinsic_candidate) \ declare_constant(Method::_reserved_stack_access) \ \ declare_constant(Method::nonvirtual_vtable_index) \ diff --git a/hotspot/src/share/vm/jvmci/vmSymbols_jvmci.hpp b/hotspot/src/share/vm/jvmci/vmSymbols_jvmci.hpp index 70d4b99fb23..84cdc649d14 100644 --- a/hotspot/src/share/vm/jvmci/vmSymbols_jvmci.hpp +++ b/hotspot/src/share/vm/jvmci/vmSymbols_jvmci.hpp @@ -52,6 +52,7 @@ template(jdk_vm_ci_hotspot_HotSpotCompilationRequestResult, "jdk/vm/ci/hotspot/HotSpotCompilationRequestResult") \ template(jdk_vm_ci_hotspot_VMField, "jdk/vm/ci/hotspot/VMField") \ template(jdk_vm_ci_hotspot_VMFlag, "jdk/vm/ci/hotspot/VMFlag") \ + template(jdk_vm_ci_hotspot_VMIntrinsicMethod, "jdk/vm/ci/hotspot/VMIntrinsicMethod") \ template(jdk_vm_ci_meta_JavaConstant, "jdk/vm/ci/meta/JavaConstant") \ template(jdk_vm_ci_meta_PrimitiveConstant, "jdk/vm/ci/meta/PrimitiveConstant") \ template(jdk_vm_ci_meta_RawConstant, "jdk/vm/ci/meta/RawConstant") \ diff --git a/hotspot/test/compiler/jvmci/compilerToVM/InitializeConfigurationTest.java b/hotspot/test/compiler/jvmci/compilerToVM/ReadConfigurationTest.java similarity index 77% rename from hotspot/test/compiler/jvmci/compilerToVM/InitializeConfigurationTest.java rename to hotspot/test/compiler/jvmci/compilerToVM/ReadConfigurationTest.java index 5e8c75aee1a..b10ef88a7eb 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/InitializeConfigurationTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/ReadConfigurationTest.java @@ -30,8 +30,9 @@ * @modules java.base/jdk.internal.misc * @modules jdk.vm.ci/jdk.vm.ci.hotspot * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper + * @build compiler.jvmci.compilerToVM.ReadConfigurationTest * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI - * compiler.jvmci.compilerToVM.InitializeConfigurationTest + * compiler.jvmci.compilerToVM.ReadConfigurationTest */ package compiler.jvmci.compilerToVM; @@ -40,16 +41,27 @@ import jdk.test.lib.Asserts; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; import jdk.vm.ci.hotspot.HotSpotVMConfigStore; +import jdk.vm.ci.hotspot.VMIntrinsicMethod; -public class InitializeConfigurationTest { +public class ReadConfigurationTest { public static void main(String args[]) { - new InitializeConfigurationTest().runTest(); + new ReadConfigurationTest().runTest(); } private void runTest() { TestHotSpotVMConfig config = new TestHotSpotVMConfig(HotSpotJVMCIRuntime.runtime().getConfigStore()); Asserts.assertNE(config.codeCacheHighBound, 0L, "Got null address"); Asserts.assertNE(config.stubRoutineJintArrayCopy, 0L, "Got null address"); + + for (VMIntrinsicMethod m : config.getStore().getIntrinsics()) { + Asserts.assertNotNull(m); + Asserts.assertNotNull(m.declaringClass); + Asserts.assertFalse(m.declaringClass.contains("."), + "declaringClass should be in class file format: " + m.declaringClass); + Asserts.assertNotNull(m.name); + Asserts.assertNotNull(m.descriptor); + Asserts.assertTrue(m.id > 0); + } } private static class TestHotSpotVMConfig extends HotSpotVMConfigAccess { From bf0209ffa90a7f0bf317947844bc92797d2f3fbd Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Thu, 25 Aug 2016 12:51:10 +0300 Subject: [PATCH 012/110] 8162101: C2: Handle "wide" aliases for unsafe accesses Reviewed-by: kvn --- hotspot/src/share/vm/opto/library_call.cpp | 24 ++++---- hotspot/src/share/vm/opto/type.hpp | 4 +- .../test/compiler/unsafe/OpaqueAccesses.java | 57 +++++++++++++++++++ 3 files changed, 73 insertions(+), 12 deletions(-) diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 5de8f721463..9780c4f0764 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -2309,25 +2309,27 @@ bool LibraryCallKit::inline_unsafe_access(bool is_store, const BasicType type, c if (_gvn.type(base)->isa_ptr() != TypePtr::NULL_PTR) { heap_base_oop = base; } + + // Can base be NULL? Otherwise, always on-heap access. + bool can_access_non_heap = TypePtr::NULL_PTR->higher_equal(_gvn.type(heap_base_oop)); + val = is_store ? argument(4) : NULL; const TypePtr *adr_type = _gvn.type(adr)->isa_ptr(); - // Try to categorize the address. If it comes up as TypeJavaPtr::BOTTOM, - // there was not enough information to nail it down. + // Try to categorize the address. Compile::AliasType* alias_type = C->alias_type(adr_type); assert(alias_type->index() != Compile::AliasIdxBot, "no bare pointers here"); - // Only field, array element or unknown locations are supported. - if (alias_type->adr_type() != TypeRawPtr::BOTTOM && - alias_type->adr_type() != TypeOopPtr::BOTTOM && - alias_type->basic_type() == T_ILLEGAL) { - return false; + if (alias_type->adr_type() == TypeInstPtr::KLASS || + alias_type->adr_type() == TypeAryPtr::RANGE) { + return false; // not supported } bool mismatched = false; BasicType bt = alias_type->basic_type(); if (bt != T_ILLEGAL) { + assert(alias_type->adr_type()->is_oopptr(), "should be on-heap access"); if (bt == T_BYTE && adr_type->isa_aryptr()) { // Alias type doesn't differentiate between byte[] and boolean[]). // Use address type to get the element type. @@ -2342,10 +2344,12 @@ bool LibraryCallKit::inline_unsafe_access(bool is_store, const BasicType type, c return false; } mismatched = (bt != type); - } else if (alias_type->adr_type() == TypeOopPtr::BOTTOM) { + } else if (alias_type->adr_type()->isa_oopptr()) { mismatched = true; // conservatively mark all "wide" on-heap accesses as mismatched } + assert(!mismatched || alias_type->adr_type()->is_oopptr(), "off-heap access can't be mismatched"); + // First guess at the value type. const Type *value_type = Type::get_const_basic_type(type); @@ -2357,7 +2361,7 @@ bool LibraryCallKit::inline_unsafe_access(bool is_store, const BasicType type, c bool need_mem_bar; switch (kind) { case Relaxed: - need_mem_bar = (alias_type->adr_type() == TypeOopPtr::BOTTOM); + need_mem_bar = mismatched || can_access_non_heap; break; case Opaque: // Opaque uses CPUOrder membars for protection against code movement. @@ -2512,7 +2516,7 @@ bool LibraryCallKit::inline_unsafe_access(bool is_store, const BasicType type, c (void) store_to_memory(control(), adr, val, type, adr_type, mo, requires_atomic_access, unaligned, mismatched); } else { // Possibly an oop being stored to Java heap or native memory - if (!TypePtr::NULL_PTR->higher_equal(_gvn.type(heap_base_oop))) { + if (!can_access_non_heap) { // oop to Java heap. (void) store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, type, mo, mismatched); } else { diff --git a/hotspot/src/share/vm/opto/type.hpp b/hotspot/src/share/vm/opto/type.hpp index 1252dc14db6..8179bc6794b 100644 --- a/hotspot/src/share/vm/opto/type.hpp +++ b/hotspot/src/share/vm/opto/type.hpp @@ -210,11 +210,11 @@ public: static int cmp( const Type *const t1, const Type *const t2 ); // Test for higher or equal in lattice // Variant that drops the speculative part of the types - int higher_equal(const Type *t) const { + bool higher_equal(const Type *t) const { return !cmp(meet(t),t->remove_speculative()); } // Variant that keeps the speculative part of the types - int higher_equal_speculative(const Type *t) const { + bool higher_equal_speculative(const Type *t) const { return !cmp(meet_speculative(t),t); } diff --git a/hotspot/test/compiler/unsafe/OpaqueAccesses.java b/hotspot/test/compiler/unsafe/OpaqueAccesses.java index bc274e5399b..70c54087796 100644 --- a/hotspot/test/compiler/unsafe/OpaqueAccesses.java +++ b/hotspot/test/compiler/unsafe/OpaqueAccesses.java @@ -30,6 +30,22 @@ * * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions * -XX:-TieredCompilation -Xbatch + * -XX:+UseCompressedOops -XX:+UseCompressedClassPointers + * -XX:CompileCommand=dontinline,compiler.unsafe.OpaqueAccesses::test* + * compiler.unsafe.OpaqueAccesses + * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions + * -XX:-TieredCompilation -Xbatch + * -XX:+UseCompressedOops -XX:-UseCompressedClassPointers + * -XX:CompileCommand=dontinline,compiler.unsafe.OpaqueAccesses::test* + * compiler.unsafe.OpaqueAccesses + * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions + * -XX:-TieredCompilation -Xbatch + * -XX:-UseCompressedOops -XX:+UseCompressedClassPointers + * -XX:CompileCommand=dontinline,compiler.unsafe.OpaqueAccesses::test* + * compiler.unsafe.OpaqueAccesses + * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions + * -XX:-TieredCompilation -Xbatch + * -XX:-UseCompressedOops -XX:-UseCompressedClassPointers * -XX:CompileCommand=dontinline,compiler.unsafe.OpaqueAccesses::test* * compiler.unsafe.OpaqueAccesses */ @@ -61,6 +77,7 @@ public class OpaqueAccesses { } private Object f = new Object(); + private long l1, l2; static Object testFixedOffsetField(Object o) { return UNSAFE.getObject(o, F_OFFSET); @@ -74,6 +91,22 @@ public class OpaqueAccesses { return UNSAFE.getInt(o, 4); } + static int testFixedOffsetHeader8(Object o) { + return UNSAFE.getInt(o, 8); + } + + static int testFixedOffsetHeader12(Object o) { + return UNSAFE.getInt(o, 12); + } + + static int testFixedOffsetHeader16(Object o) { + return UNSAFE.getInt(o, 16); + } + + static int testFixedOffsetHeader17(Object o) { + return UNSAFE.getIntUnaligned(o, 17); + } + static Object testFixedBase(long off) { return UNSAFE.getObject(INSTANCE, off); } @@ -90,6 +123,22 @@ public class OpaqueAccesses { return UNSAFE.getInt(arr, 4); } + static int testFixedOffsetHeaderArray8(Object[] arr) { + return UNSAFE.getInt(arr, 8); + } + + static int testFixedOffsetHeaderArray12(Object[] arr) { + return UNSAFE.getInt(arr, 12); + } + + static int testFixedOffsetHeaderArray16(Object[] arr) { + return UNSAFE.getInt(arr, 16); + } + + static int testFixedOffsetHeaderArray17(Object[] arr) { + return UNSAFE.getIntUnaligned(arr, 17); + } + static Object testFixedOffsetArray(Object[] arr) { return UNSAFE.getObject(arr, E_OFFSET); } @@ -118,6 +167,10 @@ public class OpaqueAccesses { testFixedOffsetField(INSTANCE); testFixedOffsetHeader0(INSTANCE); testFixedOffsetHeader4(INSTANCE); + testFixedOffsetHeader8(INSTANCE); + testFixedOffsetHeader12(INSTANCE); + testFixedOffsetHeader16(INSTANCE); + testFixedOffsetHeader17(INSTANCE); testFixedBase(F_OFFSET); testOpaque(INSTANCE, F_OFFSET); testMixedAccess(); @@ -125,6 +178,10 @@ public class OpaqueAccesses { // Array testFixedOffsetHeaderArray0(ARRAY); testFixedOffsetHeaderArray4(ARRAY); + testFixedOffsetHeaderArray8(ARRAY); + testFixedOffsetHeaderArray12(ARRAY); + testFixedOffsetHeaderArray16(ARRAY); + testFixedOffsetHeaderArray17(ARRAY); testFixedOffsetArray(ARRAY); testFixedBaseArray(E_OFFSET); testOpaqueArray(ARRAY, E_OFFSET); From d536ff4377834d56a3dac041e2b3666d9a74d7bd Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Thu, 25 Aug 2016 12:52:18 +0300 Subject: [PATCH 013/110] 8155635: C2: Mixed unsafe accesses break alias analysis Reviewed-by: jrose, kvn --- hotspot/src/share/vm/opto/compile.cpp | 23 +++--- hotspot/src/share/vm/opto/library_call.cpp | 36 ++------- hotspot/src/share/vm/opto/type.cpp | 7 ++ hotspot/src/share/vm/opto/type.hpp | 2 + .../unsafe/MixedUnsafeStoreObject.java | 73 +++++++++++++++++++ 5 files changed, 103 insertions(+), 38 deletions(-) create mode 100644 hotspot/test/compiler/unsafe/MixedUnsafeStoreObject.java diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index 518caf6896c..f0b0e398ec1 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -1708,16 +1708,21 @@ Compile::AliasType* Compile::find_alias_type(const TypePtr* adr_type, bool no_cr const TypePtr* flat = flatten_alias_type(adr_type); #ifdef ASSERT - assert(flat == flatten_alias_type(flat), "idempotent"); - assert(flat != TypePtr::BOTTOM, "cannot alias-analyze an untyped ptr"); - if (flat->isa_oopptr() && !flat->isa_klassptr()) { - const TypeOopPtr* foop = flat->is_oopptr(); - // Scalarizable allocations have exact klass always. - bool exact = !foop->klass_is_exact() || foop->is_known_instance(); - const TypePtr* xoop = foop->cast_to_exactness(exact)->is_ptr(); - assert(foop == flatten_alias_type(xoop), "exactness must not affect alias type"); + { + ResourceMark rm; + assert(flat == flatten_alias_type(flat), "not idempotent: adr_type = %s; flat = %s => %s", + Type::str(adr_type), Type::str(flat), Type::str(flatten_alias_type(flat))); + assert(flat != TypePtr::BOTTOM, "cannot alias-analyze an untyped ptr: adr_type = %s", + Type::str(adr_type)); + if (flat->isa_oopptr() && !flat->isa_klassptr()) { + const TypeOopPtr* foop = flat->is_oopptr(); + // Scalarizable allocations have exact klass always. + bool exact = !foop->klass_is_exact() || foop->is_known_instance(); + const TypePtr* xoop = foop->cast_to_exactness(exact)->is_ptr(); + assert(foop == flatten_alias_type(xoop), "exactness must not affect alias type: foop = %s; xoop = %s", + Type::str(foop), Type::str(xoop)); + } } - assert(flat == flatten_alias_type(flat), "exact bit doesn't matter"); #endif int idx = AliasIdxTop; diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 9780c4f0764..2fae1704c8f 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -2242,8 +2242,8 @@ const TypeOopPtr* LibraryCallKit::sharpen_unsafe_type(Compile::AliasType* alias_ #ifndef PRODUCT if (C->print_intrinsics() || C->print_inlining()) { - tty->print(" from base type: "); adr_type->dump(); - tty->print(" sharpened value: "); tjp->dump(); + tty->print(" from base type: "); adr_type->dump(); tty->cr(); + tty->print(" sharpened value: "); tjp->dump(); tty->cr(); } #endif // Sharpen the value type. @@ -2308,6 +2308,8 @@ bool LibraryCallKit::inline_unsafe_access(bool is_store, const BasicType type, c adr = make_unsafe_address(base, offset); if (_gvn.type(base)->isa_ptr() != TypePtr::NULL_PTR) { heap_base_oop = base; + } else if (type == T_OBJECT) { + return false; // off-heap oop accesses are not supported } // Can base be NULL? Otherwise, always on-heap access. @@ -2512,34 +2514,10 @@ bool LibraryCallKit::inline_unsafe_access(bool is_store, const BasicType type, c break; } - if (type != T_OBJECT) { - (void) store_to_memory(control(), adr, val, type, adr_type, mo, requires_atomic_access, unaligned, mismatched); + if (type == T_OBJECT) { + store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, type, mo, mismatched); } else { - // Possibly an oop being stored to Java heap or native memory - if (!can_access_non_heap) { - // oop to Java heap. - (void) store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, type, mo, mismatched); - } else { - // We can't tell at compile time if we are storing in the Java heap or outside - // of it. So we need to emit code to conditionally do the proper type of - // store. - - IdealKit ideal(this); -#define __ ideal. - // QQQ who knows what probability is here?? - __ if_then(heap_base_oop, BoolTest::ne, null(), PROB_UNLIKELY(0.999)); { - // Sync IdealKit and graphKit. - sync_kit(ideal); - Node* st = store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, type, mo, mismatched); - // Update IdealKit memory. - __ sync_kit(this); - } __ else_(); { - __ store(__ ctrl(), adr, val, type, alias_type->index(), mo, requires_atomic_access, mismatched); - } __ end_if(); - // Final sync IdealKit and GraphKit. - final_sync(ideal); -#undef __ - } + store_to_memory(control(), adr, val, type, adr_type, mo, requires_atomic_access, unaligned, mismatched); } } diff --git a/hotspot/src/share/vm/opto/type.cpp b/hotspot/src/share/vm/opto/type.cpp index 84cf9d27ca6..43e47473168 100644 --- a/hotspot/src/share/vm/opto/type.cpp +++ b/hotspot/src/share/vm/opto/type.cpp @@ -1015,6 +1015,13 @@ void Type::dump_on(outputStream *st) const { st->print(" [narrowklass]"); } } + +//----------------------------------------------------------------------------- +const char* Type::str(const Type* t) { + stringStream ss; + t->dump_on(&ss); + return ss.as_string(); +} #endif //------------------------------singleton-------------------------------------- diff --git a/hotspot/src/share/vm/opto/type.hpp b/hotspot/src/share/vm/opto/type.hpp index 8179bc6794b..2cd3a2e835f 100644 --- a/hotspot/src/share/vm/opto/type.hpp +++ b/hotspot/src/share/vm/opto/type.hpp @@ -359,6 +359,8 @@ public: } virtual void dump2( Dict &d, uint depth, outputStream *st ) const; static void dump_stats(); + + static const char* str(const Type* t); #endif void typerr(const Type *t) const; // Mixing types error diff --git a/hotspot/test/compiler/unsafe/MixedUnsafeStoreObject.java b/hotspot/test/compiler/unsafe/MixedUnsafeStoreObject.java new file mode 100644 index 00000000000..e7ff724f528 --- /dev/null +++ b/hotspot/test/compiler/unsafe/MixedUnsafeStoreObject.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8155635 + * @modules java.base/jdk.internal.misc + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xbatch -XX:-TieredCompilation compiler.unsafe.MixedUnsafeStoreObject + * @run main/othervm -Xbatch compiler.unsafe.MixedUnsafeStoreObject + */ + +package compiler.unsafe; + +import jdk.internal.misc.Unsafe; + +public class MixedUnsafeStoreObject { + static final Unsafe UNSAFE = Unsafe.getUnsafe(); + + static final long F_OFFSET; + + static { + try { + F_OFFSET = UNSAFE.objectFieldOffset(T.class.getDeclaredField("f")); + } catch (Exception e) { + throw new Error(e); + } + } + + static class T { + Object f; + } + + public static void testFieldInstanceObject(Object t) { + for (int c = 0; c < 20000; c++) { // trigger OSR compilation + // java/lang/Object+12 * + // _base = InstPtr, _ptr = BotPTR, _field = NULL, mismatched = true + UNSAFE.putObject(t, F_OFFSET, "foo"); + } + } + + public static void testFieldInstanceT(T t) { + for (int c = 0; c < 20000; c++) { // trigger OSR compilation + // ...$T+12 * + // _base = InstPtr, _ptr = BotPTR, _field = T.f, mismatched = false + UNSAFE.putObject(t, F_OFFSET, "foo"); + } + } + public static void main(String[] args) { + testFieldInstanceObject(new T()); + testFieldInstanceT(new T()); + } +} + From 1f57e1599791bad63f07604f2d9f3db7ae534084 Mon Sep 17 00:00:00 2001 From: Jamsheed Mohammed C M Date: Thu, 25 Aug 2016 02:10:03 -0700 Subject: [PATCH 014/110] 8158639: C2 compilation fails with SIGSEGV Fixed the jvms for callsite traps based on declared signature. Reviewed-by: kvn, vlivanov, dlong --- hotspot/src/share/vm/opto/callGenerator.cpp | 5 ++++- hotspot/src/share/vm/opto/graphKit.hpp | 5 ++++- hotspot/test/compiler/jsr292/NullConstantReceiver.java | 3 ++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/opto/callGenerator.cpp b/hotspot/src/share/vm/opto/callGenerator.cpp index 1497a11b198..de9f44c359d 100644 --- a/hotspot/src/share/vm/opto/callGenerator.cpp +++ b/hotspot/src/share/vm/opto/callGenerator.cpp @@ -1164,7 +1164,10 @@ JVMState* UncommonTrapCallGenerator::generate(JVMState* jvms) { GraphKit kit(jvms); kit.C->print_inlining_update(this); // Take the trap with arguments pushed on the stack. (Cf. null_check_receiver). - int nargs = method()->arg_size(); + // Callsite signature can be different from actual method being called (i.e _linkTo* sites). + // Use callsite signature always. + ciMethod* declared_method = kit.method()->get_method_at_bci(kit.bci()); + int nargs = declared_method->arg_size(); kit.inc_sp(nargs); assert(nargs <= kit.sp() && kit.sp() <= jvms->stk_size(), "sane sp w/ args pushed"); if (_reason == Deoptimization::Reason_class_check && diff --git a/hotspot/src/share/vm/opto/graphKit.hpp b/hotspot/src/share/vm/opto/graphKit.hpp index 797705d3a42..6d60539b527 100644 --- a/hotspot/src/share/vm/opto/graphKit.hpp +++ b/hotspot/src/share/vm/opto/graphKit.hpp @@ -664,7 +664,10 @@ class GraphKit : public Phase { // callee (with all arguments still on the stack). Node* null_check_receiver_before_call(ciMethod* callee) { assert(!callee->is_static(), "must be a virtual method"); - const int nargs = callee->arg_size(); + // Callsite signature can be different from actual method being called (i.e _linkTo* sites). + // Use callsite signature always. + ciMethod* declared_method = method()->get_method_at_bci(bci()); + const int nargs = declared_method->arg_size(); inc_sp(nargs); Node* n = null_check_receiver(); dec_sp(nargs); diff --git a/hotspot/test/compiler/jsr292/NullConstantReceiver.java b/hotspot/test/compiler/jsr292/NullConstantReceiver.java index 42c2b879dd2..47da7d54414 100644 --- a/hotspot/test/compiler/jsr292/NullConstantReceiver.java +++ b/hotspot/test/compiler/jsr292/NullConstantReceiver.java @@ -23,9 +23,10 @@ /** * @test - * @bug 8059556 + * @bug 8059556 8158639 * * @run main/othervm -Xbatch compiler.jsr292.NullConstantReceiver + * @run main/othervm -Xbatch -XX:CompileCommand=exclude,*::run compiler.jsr292.NullConstantReceiver */ package compiler.jsr292; From 4aea7b33334ee78e56441ae55af0b790fdf659ea Mon Sep 17 00:00:00 2001 From: Sharath Ballal Date: Fri, 26 Aug 2016 13:11:20 +0300 Subject: [PATCH 015/110] 8163346: Update jmap-hashcode/Test8028623.java for better diagnostic of timeout Update jmap-hashcode/Test8028623.java to use LingeredApp and rename it to jhsdb/HeapDumpTest.java Reviewed-by: dsamersoff, dholmes --- .../sa/jmap-hashcode/Test8028623.java | 83 ------------------- 1 file changed, 83 deletions(-) delete mode 100644 hotspot/test/serviceability/sa/jmap-hashcode/Test8028623.java diff --git a/hotspot/test/serviceability/sa/jmap-hashcode/Test8028623.java b/hotspot/test/serviceability/sa/jmap-hashcode/Test8028623.java deleted file mode 100644 index 6af55b5fdf9..00000000000 --- a/hotspot/test/serviceability/sa/jmap-hashcode/Test8028623.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2014, 2016, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import jdk.test.lib.JDKToolLauncher; -import jdk.test.lib.process.OutputBuffer; -import jdk.test.lib.Platform; -import jdk.test.lib.process.ProcessTools; - -import java.io.File; - -/* - * @test - * @bug 8028623 - * @summary Test hashing of extended characters in Serviceability Agent. - * @library /test/lib - * @modules java.base/jdk.internal.misc - * java.compiler - * java.management - * jdk.jvmstat/sun.jvmstat.monitor - * @compile -encoding utf8 Test8028623.java - * @run main/othervm -XX:+UsePerfData Test8028623 - */ -public class Test8028623 { - - public static int \u00CB = 1; - public static String dumpFile = "heap.bin"; - - public static void main (String[] args) { - - System.out.println(\u00CB); - - try { - if (!Platform.shouldSAAttach()) { - System.out.println("SA attach not expected to work - test skipped."); - return; - } - long pid = ProcessTools.getProcessId(); - JDKToolLauncher jmap = JDKToolLauncher.create("jhsdb") - .addToolArg("jmap") - .addToolArg("--binaryheap") - .addToolArg("--pid") - .addToolArg(Long.toString(pid)); - ProcessBuilder pb = new ProcessBuilder(jmap.getCommand()); - OutputBuffer output = ProcessTools.getOutput(pb); - Process p = pb.start(); - int e = p.waitFor(); - System.out.println("stdout:"); - System.out.println(output.getStdout()); - System.out.println("stderr:"); - System.out.println(output.getStderr()); - - if (e != 0) { - throw new RuntimeException("jmap returns: " + e); - } - if (! new File(dumpFile).exists()) { - throw new RuntimeException("dump file NOT created: '" + dumpFile + "'"); - } - } catch (Throwable t) { - t.printStackTrace(); - throw new RuntimeException("Test failed with: " + t); - } - } -} From e710f3bd8b54ab4fe43cc620d04ef31c31aacc50 Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Fri, 26 Aug 2016 06:37:34 -0700 Subject: [PATCH 016/110] 8161280: assert failed: reference count underflow for symbol Reviewed-by: dholmes, coleenp, kbarrett --- hotspot/src/share/vm/oops/symbol.cpp | 11 +++++----- hotspot/src/share/vm/runtime/atomic.hpp | 27 +++++++++++++------------ 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/hotspot/src/share/vm/oops/symbol.cpp b/hotspot/src/share/vm/oops/symbol.cpp index f515621efff..5f4ad042e75 100644 --- a/hotspot/src/share/vm/oops/symbol.cpp +++ b/hotspot/src/share/vm/oops/symbol.cpp @@ -229,24 +229,25 @@ unsigned int Symbol::new_hash(juint seed) { } void Symbol::increment_refcount() { - // Only increment the refcount if positive. If negative either + // Only increment the refcount if non-negative. If negative either // overflow has occurred or it is a permanent symbol in a read only // shared archive. - if (_refcount >= 0) { + if (_refcount >= 0) { // not a permanent symbol Atomic::inc(&_refcount); NOT_PRODUCT(Atomic::inc(&_total_count);) } } void Symbol::decrement_refcount() { - if (_refcount >= 0) { - Atomic::dec(&_refcount); + if (_refcount >= 0) { // not a permanent symbol + jshort new_value = Atomic::add(-1, &_refcount); #ifdef ASSERT - if (_refcount < 0) { + if (new_value == -1) { // we have transitioned from 0 -> -1 print(); assert(false, "reference count underflow for symbol"); } #endif + (void)new_value; } } diff --git a/hotspot/src/share/vm/runtime/atomic.hpp b/hotspot/src/share/vm/runtime/atomic.hpp index a685b6070e8..ccf24669fa1 100644 --- a/hotspot/src/share/vm/runtime/atomic.hpp +++ b/hotspot/src/share/vm/runtime/atomic.hpp @@ -76,6 +76,7 @@ class Atomic : AllStatic { // Atomically add to a location. Returns updated value. add*() provide: // add-value-to-dest + inline static jshort add (jshort add_value, volatile jshort* dest); inline static jint add (jint add_value, volatile jint* dest); inline static size_t add (size_t add_value, volatile size_t* dest); inline static intptr_t add_ptr(intptr_t add_value, volatile intptr_t* dest); @@ -208,10 +209,11 @@ inline jlong Atomic::add(jlong add_value, volatile jlong* dest) { return old; } -inline void Atomic::inc(volatile short* dest) { - // Most platforms do not support atomic increment on a 2-byte value. However, +inline jshort Atomic::add(jshort add_value, volatile jshort* dest) { + // Most platforms do not support atomic add on a 2-byte value. However, // if the value occupies the most significant 16 bits of an aligned 32-bit - // word, then we can do this with an atomic add of 0x10000 to the 32-bit word. + // word, then we can do this with an atomic add of (add_value << 16) + // to the 32-bit word. // // The least significant parts of this 32-bit word will never be affected, even // in case of overflow/underflow. @@ -219,21 +221,20 @@ inline void Atomic::inc(volatile short* dest) { // Use the ATOMIC_SHORT_PAIR macro (see macros.hpp) to get the desired alignment. #ifdef VM_LITTLE_ENDIAN assert((intx(dest) & 0x03) == 0x02, "wrong alignment"); - (void)Atomic::add(0x10000, (volatile int*)(dest-1)); + jint new_value = Atomic::add(add_value << 16, (volatile jint*)(dest-1)); #else assert((intx(dest) & 0x03) == 0x00, "wrong alignment"); - (void)Atomic::add(0x10000, (volatile int*)(dest)); + jint new_value = Atomic::add(add_value << 16, (volatile jint*)(dest)); #endif + return (jshort)(new_value >> 16); // preserves sign } -inline void Atomic::dec(volatile short* dest) { -#ifdef VM_LITTLE_ENDIAN - assert((intx(dest) & 0x03) == 0x02, "wrong alignment"); - (void)Atomic::add(-0x10000, (volatile int*)(dest-1)); -#else - assert((intx(dest) & 0x03) == 0x00, "wrong alignment"); - (void)Atomic::add(-0x10000, (volatile int*)(dest)); -#endif +inline void Atomic::inc(volatile jshort* dest) { + (void)add(1, dest); +} + +inline void Atomic::dec(volatile jshort* dest) { + (void)add(-1, dest); } #endif // SHARE_VM_RUNTIME_ATOMIC_HPP From ae70b68f7e7051de45ba241223692b32b2b55298 Mon Sep 17 00:00:00 2001 From: Marcus Larsson Date: Tue, 5 Apr 2016 16:51:58 +0200 Subject: [PATCH 017/110] 8150894: Unused -Xlog tag sequences are silently ignored Reviewed-by: rehn, sla --- .../src/share/vm/logging/logConfiguration.cpp | 16 +++- .../vm/logging/logTagLevelExpression.cpp | 73 ++++++++++++++++--- .../vm/logging/logTagLevelExpression.hpp | 5 ++ hotspot/src/share/vm/logging/logTagSet.hpp | 2 +- .../native/logging/test_logConfiguration.cpp | 14 +++- 5 files changed, 93 insertions(+), 17 deletions(-) diff --git a/hotspot/src/share/vm/logging/logConfiguration.cpp b/hotspot/src/share/vm/logging/logConfiguration.cpp index 3081fe93432..bdec5d689d4 100644 --- a/hotspot/src/share/vm/logging/logConfiguration.cpp +++ b/hotspot/src/share/vm/logging/logConfiguration.cpp @@ -289,6 +289,8 @@ void LogConfiguration::configure_stdout(LogLevelType level, bool exact_match, .. } expr.set_level(level); expr.new_combination(); + assert(expr.verify_tagsets(), + "configure_stdout() called with invalid/non-existing tag set"); // Apply configuration to stdout (output #0), with the same decorators as before. ConfigurationLock cl; @@ -334,9 +336,16 @@ bool LogConfiguration::parse_command_line_arguments(const char* opts) { char errbuf[512]; stringStream ss(errbuf, sizeof(errbuf)); bool success = parse_log_arguments(output, what, decorators, output_options, &ss); - if (!success) { - errbuf[strlen(errbuf) - 1] = '\0'; // Strip trailing newline. - log_error(logging)("%s", errbuf); + + if (ss.size() > 0) { + errbuf[strlen(errbuf) - 1] = '\0'; // Strip trailing newline + // If it failed, log the error. If it didn't fail, but something was written + // to the stream, log it as a warning. + if (!success) { + log_error(logging)("%s", ss.base()); + } else { + log_warning(logging)("%s", ss.base()); + } } os::free(copy); @@ -386,6 +395,7 @@ bool LogConfiguration::parse_log_arguments(const char* outputstr, } configure_output(idx, expr, decorators); notify_update_listeners(); + expr.verify_tagsets(errstream); return true; } diff --git a/hotspot/src/share/vm/logging/logTagLevelExpression.cpp b/hotspot/src/share/vm/logging/logTagLevelExpression.cpp index 0770c38ba8d..6520c62d962 100644 --- a/hotspot/src/share/vm/logging/logTagLevelExpression.cpp +++ b/hotspot/src/share/vm/logging/logTagLevelExpression.cpp @@ -29,6 +29,65 @@ const char* LogTagLevelExpression::DefaultExpressionString = "all"; +static bool matches_tagset(const LogTagType tags[], + bool allow_other_tags, + const LogTagSet& ts) { + bool contains_all = true; + size_t tag_idx; + for (tag_idx = 0; tag_idx < LogTag::MaxTags && tags[tag_idx] != LogTag::__NO_TAG; tag_idx++) { + if (!ts.contains(tags[tag_idx])) { + contains_all = false; + break; + } + } + // All tags in the expression must be part of the tagset, + // and either the expression allows other tags (has a wildcard), + // or the number of tags in the expression and tagset must match. + return contains_all && (allow_other_tags || tag_idx == ts.ntags()); +} + +bool LogTagLevelExpression::verify_tagsets(outputStream* out) const { + bool valid = true; + + for (size_t i = 0; i < _ncombinations; i++) { + bool matched = false; + for (LogTagSet* ts = LogTagSet::first(); ts != NULL; ts = ts->next()) { + if (matches_tagset(_tags[i], _allow_other_tags[i], *ts)) { + matched = true; + break; + } + } + + if (!matched) { + // If this was the first invalid combination, write the message header + if (valid && out != NULL) { + out->print("No tag set matches selection(s): "); + } + valid = false; + + // Break as soon as possible unless listing all invalid combinations + if (out == NULL) { + break; + } + + // List the combination on the outputStream + for (size_t t = 0; t < LogTag::MaxTags && _tags[i][t] != LogTag::__NO_TAG; t++) { + out->print("%s%s", (t == 0 ? "" : "+"), LogTag::name(_tags[i][t])); + } + if (_allow_other_tags[i]) { + out->print("*"); + } + out->print(" "); + } + } + + if (!valid && out != NULL) { + out->cr(); + } + + return valid; +} + bool LogTagLevelExpression::parse(const char* str, outputStream* errstream) { bool success = true; if (str == NULL || strcmp(str, "") == 0) { @@ -120,20 +179,10 @@ LogLevelType LogTagLevelExpression::level_for(const LogTagSet& ts) const { // Return NotMentioned if the given tagset isn't covered by this expression. LogLevelType level = LogLevel::NotMentioned; for (size_t combination = 0; combination < _ncombinations; combination++) { - bool contains_all = true; - size_t tag_idx; - for (tag_idx = 0; tag_idx < LogTag::MaxTags && _tags[combination][tag_idx] != LogTag::__NO_TAG; tag_idx++) { - if (!ts.contains(_tags[combination][tag_idx])) { - contains_all = false; - break; - } - } - // All tags in the expression must be part of the tagset, - // and either the expression allows other tags (has a wildcard), - // or the number of tags in the expression and tagset must match. - if (contains_all && (_allow_other_tags[combination] || tag_idx == ts.ntags())) { + if (matches_tagset(_tags[combination], _allow_other_tags[combination], ts)) { level = _level[combination]; } } return level; } + diff --git a/hotspot/src/share/vm/logging/logTagLevelExpression.hpp b/hotspot/src/share/vm/logging/logTagLevelExpression.hpp index 9a0d7c9cd79..e1f4cb2e94a 100644 --- a/hotspot/src/share/vm/logging/logTagLevelExpression.hpp +++ b/hotspot/src/share/vm/logging/logTagLevelExpression.hpp @@ -83,6 +83,11 @@ class LogTagLevelExpression : public StackObj { bool parse(const char* str, outputStream* errstream = NULL); LogLevelType level_for(const LogTagSet& ts) const; + + // Verify the tagsets/selections mentioned in this expression. + // Returns false if some invalid tagset was found. If given an outputstream, + // this function will list all the invalid selections on the stream. + bool verify_tagsets(outputStream* out = NULL) const; }; #endif // SHARE_VM_LOGGING_LOGTAGLEVELEXPRESSION_HPP diff --git a/hotspot/src/share/vm/logging/logTagSet.hpp b/hotspot/src/share/vm/logging/logTagSet.hpp index a40ed5175bc..e6281565ee5 100644 --- a/hotspot/src/share/vm/logging/logTagSet.hpp +++ b/hotspot/src/share/vm/logging/logTagSet.hpp @@ -86,7 +86,7 @@ class LogTagSet VALUE_OBJ_CLASS_SPEC { } bool contains(LogTagType tag) const { - for (size_t i = 0; _tag[i] != LogTag::__NO_TAG; i++) { + for (size_t i = 0; i < LogTag::MaxTags && _tag[i] != LogTag::__NO_TAG; i++) { if (tag == _tag[i]) { return true; } diff --git a/hotspot/test/native/logging/test_logConfiguration.cpp b/hotspot/test/native/logging/test_logConfiguration.cpp index 528111ef31b..035909b5070 100644 --- a/hotspot/test/native/logging/test_logConfiguration.cpp +++ b/hotspot/test/native/logging/test_logConfiguration.cpp @@ -287,5 +287,17 @@ TEST_F(LogConfigurationTest, parse_log_arguments) { const LogDecorators::Decorator decorator = static_cast(d); EXPECT_TRUE(LogConfiguration::parse_log_arguments("#0", "", LogDecorators::name(decorator), "", &ss)); } - EXPECT_STREQ("", ss.as_string()) << "Error reported while parsing: " << ss.as_string(); +} + +TEST_F(LogConfigurationTest, parse_invalid_tagset) { + static const char* invalid_tagset = "logging+start+exit+safepoint+gc"; // Must not exist for test to function. + + // Make sure warning is produced if one or more configured tagsets are invalid + ResourceMark rm; + stringStream ss; + bool success = LogConfiguration::parse_log_arguments("stdout", invalid_tagset, NULL, NULL, &ss); + const char* msg = ss.as_string(); + EXPECT_TRUE(success) << "Should only cause a warning, not an error"; + EXPECT_TRUE(string_contains_substring(msg, "No tag set matches selection(s):")); + EXPECT_TRUE(string_contains_substring(msg, invalid_tagset)); } From fe2f9368759e85e8230906ecbd971893c33104b2 Mon Sep 17 00:00:00 2001 From: Kirill Zhaldybin Date: Mon, 15 Aug 2016 13:18:35 +0300 Subject: [PATCH 018/110] 8163860: Convert TestOldFreeSpaceCalculation_test to GTest Reviewed-by: iignatyev, dfazunen --- .../vm/gc/parallel/psAdaptiveSizePolicy.cpp | 17 +----- .../share/vm/utilities/internalVMTests.cpp | 1 - .../gc/parallel/test_psAdaptiveSizePolicy.cpp | 61 +++++++++++++++++++ 3 files changed, 62 insertions(+), 17 deletions(-) create mode 100644 hotspot/test/native/gc/parallel/test_psAdaptiveSizePolicy.cpp diff --git a/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp b/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp index c8554287512..8f27dd13729 100644 --- a/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp +++ b/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2016, 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,18 +1133,3 @@ bool PSAdaptiveSizePolicy::print() const { return false; } - -#ifndef PRODUCT - -void TestOldFreeSpaceCalculation_test() { - assert(PSAdaptiveSizePolicy::calculate_free_based_on_live(100, 20) == 25, "Calculation of free memory failed"); - assert(PSAdaptiveSizePolicy::calculate_free_based_on_live(100, 50) == 100, "Calculation of free memory failed"); - assert(PSAdaptiveSizePolicy::calculate_free_based_on_live(100, 60) == 150, "Calculation of free memory failed"); - assert(PSAdaptiveSizePolicy::calculate_free_based_on_live(100, 75) == 300, "Calculation of free memory failed"); - assert(PSAdaptiveSizePolicy::calculate_free_based_on_live(400, 20) == 100, "Calculation of free memory failed"); - assert(PSAdaptiveSizePolicy::calculate_free_based_on_live(400, 50) == 400, "Calculation of free memory failed"); - assert(PSAdaptiveSizePolicy::calculate_free_based_on_live(400, 60) == 600, "Calculation of free memory failed"); - assert(PSAdaptiveSizePolicy::calculate_free_based_on_live(400, 75) == 1200, "Calculation of free memory failed"); -} - -#endif /* !PRODUCT */ diff --git a/hotspot/src/share/vm/utilities/internalVMTests.cpp b/hotspot/src/share/vm/utilities/internalVMTests.cpp index bdeb84abedf..a9aaaf22aeb 100644 --- a/hotspot/src/share/vm/utilities/internalVMTests.cpp +++ b/hotspot/src/share/vm/utilities/internalVMTests.cpp @@ -87,7 +87,6 @@ void InternalVMTests::run() { run_unit_test(VMStructs_test); #endif #if INCLUDE_ALL_GCS - run_unit_test(TestOldFreeSpaceCalculation_test); run_unit_test(TestG1BiasedArray_test); run_unit_test(TestBufferingOopClosure_test); run_unit_test(TestCodeCacheRemSet_test); diff --git a/hotspot/test/native/gc/parallel/test_psAdaptiveSizePolicy.cpp b/hotspot/test/native/gc/parallel/test_psAdaptiveSizePolicy.cpp new file mode 100644 index 00000000000..a3971c69257 --- /dev/null +++ b/hotspot/test/native/gc/parallel/test_psAdaptiveSizePolicy.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "utilities/macros.hpp" +#include "gc/parallel/psAdaptiveSizePolicy.hpp" +#include "unittest.hpp" + +#if INCLUDE_ALL_GCS + + TEST_VM(gc, oldFreeSpaceCalculation) { + + struct TestCase { + size_t live; + uintx ratio; + size_t expectedResult; + }; + + TestCase test_cases[] = { + {100, 20, 25}, + {100, 50, 100}, + {100, 60, 150}, + {100, 75, 300}, + {400, 20, 100}, + {400, 50, 400}, + {400, 60, 600}, + {400, 75, 1200}, + }; + + size_t array_len = sizeof(test_cases) / sizeof(TestCase); + for (size_t i = 0; i < array_len; ++i) { + ASSERT_EQ(PSAdaptiveSizePolicy::calculate_free_based_on_live( + test_cases[i].live, test_cases[i].ratio), + test_cases[i].expectedResult) + << " Calculation of free memory failed" + << " - Test case " << i << ": live = " << test_cases[i].live + << "; ratio = " << test_cases[i].ratio; + } + } +#endif From d65aa31fd5c107729eb461ed7095b352695c39db Mon Sep 17 00:00:00 2001 From: Kirill Zhaldybin Date: Mon, 22 Aug 2016 16:43:56 +0300 Subject: [PATCH 019/110] 8164028: Convert TestPredictions_test to GTest Reviewed-by: jwilhelm, dfazunen, ehelin --- hotspot/src/share/vm/gc/g1/g1Predictions.cpp | 98 ------------------- hotspot/src/share/vm/gc/g1/g1Predictions.hpp | 6 +- .../share/vm/utilities/internalVMTests.cpp | 1 - .../test/native/gc/g1/test_g1Predictions.cpp | 98 +++++++++++++++++++ 4 files changed, 99 insertions(+), 104 deletions(-) delete mode 100644 hotspot/src/share/vm/gc/g1/g1Predictions.cpp create mode 100644 hotspot/test/native/gc/g1/test_g1Predictions.cpp diff --git a/hotspot/src/share/vm/gc/g1/g1Predictions.cpp b/hotspot/src/share/vm/gc/g1/g1Predictions.cpp deleted file mode 100644 index 12092beeca4..00000000000 --- a/hotspot/src/share/vm/gc/g1/g1Predictions.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2015, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "gc/g1/g1Predictions.hpp" - -#ifndef PRODUCT - -void G1Predictions::test() { - double const epsilon = 1e-6; - { - // Some basic formula tests with confidence = 0.0 - G1Predictions predictor(0.0); - TruncatedSeq s; - - double p0 = predictor.get_new_prediction(&s); - assert(p0 < epsilon, "Initial prediction of empty sequence must be 0.0 but is %f", p0); - - s.add(5.0); - double p1 = predictor.get_new_prediction(&s); - assert(fabs(p1 - 5.0) < epsilon, "Prediction should be 5.0 but is %f", p1); - for (int i = 0; i < 40; i++) { - s.add(5.0); - } - double p2 = predictor.get_new_prediction(&s); - assert(fabs(p2 - 5.0) < epsilon, "Prediction should be 5.0 but is %f", p1); - } - - { - // The following tests checks that the initial predictions are based on the - // average of the sequence and not on the stddev (which is 0). - G1Predictions predictor(0.5); - TruncatedSeq s; - - s.add(1.0); - double p1 = predictor.get_new_prediction(&s); - assert(p1 > 1.0, "First prediction must be larger than average, but avg is %f and prediction %f", s.davg(), p1); - s.add(1.0); - double p2 = predictor.get_new_prediction(&s); - assert(p2 < p1, "First prediction must be larger than second, but they are %f %f", p1, p2); - s.add(1.0); - double p3 = predictor.get_new_prediction(&s); - assert(p3 < p2, "Second prediction must be larger than third, but they are %f %f", p2, p3); - s.add(1.0); - s.add(1.0); // Five elements are now in the sequence. - double p5 = predictor.get_new_prediction(&s); - assert(p5 < p3, "Fifth prediction must be smaller than third, but they are %f %f", p3, p5); - assert(fabs(p5 - 1.0) < epsilon, "Prediction must be 1.0+epsilon, but is %f", p5); - } - - { - // The following tests checks that initially prediction based on the average is - // used, that gets overridden by the stddev prediction at the end. - G1Predictions predictor(0.5); - TruncatedSeq s; - - s.add(0.5); - double p1 = predictor.get_new_prediction(&s); - assert(p1 > 0.5, "First prediction must be larger than average, but avg is %f and prediction %f", s.davg(), p1); - s.add(0.2); - double p2 = predictor.get_new_prediction(&s); - assert(p2 < p1, "First prediction must be larger than second, but they are %f %f", p1, p2); - s.add(0.5); - double p3 = predictor.get_new_prediction(&s); - assert(p3 < p2, "Second prediction must be larger than third, but they are %f %f", p2, p3); - s.add(0.2); - s.add(2.0); - double p5 = predictor.get_new_prediction(&s); - assert(p5 > p3, "Fifth prediction must be bigger than third, but they are %f %f", p3, p5); - } -} - -void TestPredictions_test() { - G1Predictions::test(); -} - -#endif diff --git a/hotspot/src/share/vm/gc/g1/g1Predictions.hpp b/hotspot/src/share/vm/gc/g1/g1Predictions.hpp index 6dad458e546..bcd430e7385 100644 --- a/hotspot/src/share/vm/gc/g1/g1Predictions.hpp +++ b/hotspot/src/share/vm/gc/g1/g1Predictions.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -57,10 +57,6 @@ class G1Predictions VALUE_OBJ_CLASS_SPEC { double get_new_prediction(TruncatedSeq const* seq) const { return seq->davg() + _sigma * stddev_estimate(seq); } - -#ifndef PRODUCT - static void test(); -#endif }; #endif // SHARE_VM_GC_G1_G1PREDICTIONS_HPP diff --git a/hotspot/src/share/vm/utilities/internalVMTests.cpp b/hotspot/src/share/vm/utilities/internalVMTests.cpp index a9aaaf22aeb..03737b6a213 100644 --- a/hotspot/src/share/vm/utilities/internalVMTests.cpp +++ b/hotspot/src/share/vm/utilities/internalVMTests.cpp @@ -95,7 +95,6 @@ void InternalVMTests::run() { run_unit_test(IHOP_test); } run_unit_test(test_memset_with_concurrent_readers); - run_unit_test(TestPredictions_test); run_unit_test(WorkerDataArray_test); run_unit_test(ParallelCompact_test); #endif diff --git a/hotspot/test/native/gc/g1/test_g1Predictions.cpp b/hotspot/test/native/gc/g1/test_g1Predictions.cpp new file mode 100644 index 00000000000..6b08390d1f6 --- /dev/null +++ b/hotspot/test/native/gc/g1/test_g1Predictions.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "gc/g1/g1Predictions.hpp" +#include "unittest.hpp" + +static const double epsilon = 1e-6; + +// Some basic formula tests with confidence = 0.0 +TEST_VM(G1Predictions, basic_predictions) { + G1Predictions predictor(0.0); + TruncatedSeq s; + + double p0 = predictor.get_new_prediction(&s); + ASSERT_LT(p0, epsilon) << "Initial prediction of empty sequence must be 0.0"; + + s.add(5.0); + double p1 = predictor.get_new_prediction(&s); + ASSERT_NEAR(p1, 5.0, epsilon); + + for (int i = 0; i < 40; i++) { + s.add(5.0); + } + double p2 = predictor.get_new_prediction(&s); + ASSERT_NEAR(p2, 5.0, epsilon); +} + +// The following tests checks that the initial predictions are based on +// the average of the sequence and not on the stddev (which is 0). +TEST_VM(G1Predictions, average_not_stdev_predictions) { + G1Predictions predictor(0.5); + TruncatedSeq s; + + s.add(1.0); + double p1 = predictor.get_new_prediction(&s); + ASSERT_GT(p1, s.davg()) << "First prediction must be greater than average"; + + s.add(1.0); + double p2 = predictor.get_new_prediction(&s); + ASSERT_GT(p1, p2) << "First prediction must be greater than second"; + + s.add(1.0); + double p3 = predictor.get_new_prediction(&s); + ASSERT_GT(p2, p3) << "Second prediction must be greater than third"; + + s.add(1.0); + s.add(1.0); // Five elements are now in the sequence. + double p4 = predictor.get_new_prediction(&s); + ASSERT_LT(p4, p3) << "Fourth prediction must be smaller than third"; + ASSERT_NEAR(p4, 1.0, epsilon); +} + +// The following tests checks that initially prediction based on +// the average is used, that gets overridden by the stddev prediction at +// the end. +TEST_VM(G1Predictions, average_stdev_predictions) { + G1Predictions predictor(0.5); + TruncatedSeq s; + + s.add(0.5); + double p1 = predictor.get_new_prediction(&s); + ASSERT_GT(p1, s.davg()) << "First prediction must be greater than average"; + + s.add(0.2); + double p2 = predictor.get_new_prediction(&s); + ASSERT_GT(p1, p2) << "First prediction must be greater than second"; + + s.add(0.5); + double p3 = predictor.get_new_prediction(&s); + ASSERT_GT(p2, p3) << "Second prediction must be greater than third"; + + s.add(0.2); + s.add(2.0); + double p4 = predictor.get_new_prediction(&s); + ASSERT_GT(p4, p3) << "Fourth prediction must be greater than third"; +} From 0391d651efc713183972f1bb5e128929005b8332 Mon Sep 17 00:00:00 2001 From: Dmitrij Pochepko Date: Tue, 23 Aug 2016 19:30:35 +0300 Subject: [PATCH 020/110] 8164608: [TESTBUG] compiler/profiling tests fail to compile Reviewed-by: ctornqvi --- test/lib/jdk/test/lib/Utils.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/lib/jdk/test/lib/Utils.java b/test/lib/jdk/test/lib/Utils.java index aececb0301f..752624272f6 100644 --- a/test/lib/jdk/test/lib/Utils.java +++ b/test/lib/jdk/test/lib/Utils.java @@ -87,6 +87,16 @@ public final class Utils { */ public static final String TEST_SRC = System.getProperty("test.src", "").trim(); + /* + * Returns the value of 'test.jdk' system property + */ + public static final String TEST_JDK = System.getProperty("test.jdk"); + + /** + * Returns the value of 'test.classes' system property + */ + public static final String TEST_CLASSES = System.getProperty("test.classes", "."); + private static Unsafe unsafe = null; /** From 10245a95e3e931bc8467246bb360c02a73cf04b9 Mon Sep 17 00:00:00 2001 From: Marcus Larsson Date: Fri, 26 Aug 2016 14:27:41 +0200 Subject: [PATCH 021/110] 8150823: UL disables log outputs incorrectly Reviewed-by: rehn, sla --- hotspot/src/share/vm/logging/logConfiguration.cpp | 7 ++++--- hotspot/test/native/logging/test_logConfiguration.cpp | 9 ++++++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/hotspot/src/share/vm/logging/logConfiguration.cpp b/hotspot/src/share/vm/logging/logConfiguration.cpp index bdec5d689d4..0817a650e70 100644 --- a/hotspot/src/share/vm/logging/logConfiguration.cpp +++ b/hotspot/src/share/vm/logging/logConfiguration.cpp @@ -243,6 +243,7 @@ void LogConfiguration::configure_output(size_t idx, const LogTagLevelExpression& } void LogConfiguration::disable_output(size_t idx) { + assert(idx < _n_outputs, "invalid index: " SIZE_FORMAT " (_n_outputs: " SIZE_FORMAT ")", idx, _n_outputs); LogOutput* out = _outputs[idx]; // Remove the output from all tagsets. @@ -253,7 +254,7 @@ void LogConfiguration::disable_output(size_t idx) { // Delete the output unless stdout/stderr if (out != LogOutput::Stderr && out != LogOutput::Stdout) { - delete_output(find_output(out->name())); + delete_output(idx); } else { out->set_config_string("all=off"); } @@ -261,8 +262,8 @@ void LogConfiguration::disable_output(size_t idx) { void LogConfiguration::disable_logging() { ConfigurationLock cl; - for (size_t i = 0; i < _n_outputs; i++) { - disable_output(i); + for (size_t i = _n_outputs; i > 0; i--) { + disable_output(i - 1); } notify_update_listeners(); } diff --git a/hotspot/test/native/logging/test_logConfiguration.cpp b/hotspot/test/native/logging/test_logConfiguration.cpp index 035909b5070..b07839ad04a 100644 --- a/hotspot/test/native/logging/test_logConfiguration.cpp +++ b/hotspot/test/native/logging/test_logConfiguration.cpp @@ -164,10 +164,17 @@ TEST_F(LogConfigurationTest, disable_logging) { // Add TestLogFileName as an output set_log_config(TestLogFileName, "logging=info"); + // Add a second file output + char other_file_name[2 * K]; + jio_snprintf(other_file_name, sizeof(other_file_name), "%s-other", TestLogFileName); + set_log_config(other_file_name, "logging=info"); + LogConfiguration::disable_logging(); - // Verify TestLogFileName was disabled + // Verify that both file outputs were disabled EXPECT_FALSE(is_described(TestLogFileName)); + EXPECT_FALSE(is_described(other_file_name)); + delete_file(other_file_name); // Verify that no tagset has logging enabled for (LogTagSet* ts = LogTagSet::first(); ts != NULL; ts = ts->next()) { From 56ff858c45bbc4c584271f33a2e0c51d2405252e Mon Sep 17 00:00:00 2001 From: Dmitry Fazunenko Date: Mon, 29 Aug 2016 23:04:48 +0400 Subject: [PATCH 022/110] 8164660: MinimalVM is not tested with GC tests Reviewed-by: jmasa, tschatzl --- hotspot/test/gc/TestCardTablePageCommits.java | 1 - hotspot/test/gc/TestObjectAlignment.java | 1 - hotspot/test/gc/TestSmallHeap.java | 1 - hotspot/test/gc/TestSoftReferencesBehaviorOnOOME.java | 1 - hotspot/test/gc/TestVerifyDuringStartup.java | 1 - hotspot/test/gc/TestVerifySilently.java | 1 - hotspot/test/gc/TestVerifySubSet.java | 1 - hotspot/test/gc/g1/TestEagerReclaimHumongousRegions.java | 1 + .../gc/g1/TestEagerReclaimHumongousRegionsClearMarkBits.java | 1 + .../test/gc/g1/TestEagerReclaimHumongousRegionsWithRefs.java | 1 + hotspot/test/gc/g1/TestG1TraceEagerReclaimHumongousObjects.java | 1 + hotspot/test/gc/g1/TestGCLogMessages.java | 1 + hotspot/test/gc/g1/TestHumongousAllocInitialMark.java | 1 + hotspot/test/gc/g1/TestHumongousAllocNearlyFullRegion.java | 1 + hotspot/test/gc/g1/TestHumongousCodeCacheRoots.java | 1 + hotspot/test/gc/g1/TestPrintRegionRememberedSetInfo.java | 1 + hotspot/test/gc/g1/TestStringDeduplicationAgeThreshold.java | 1 + hotspot/test/gc/g1/TestStringDeduplicationFullGC.java | 1 + hotspot/test/gc/g1/TestStringDeduplicationInterned.java | 1 + hotspot/test/gc/g1/TestStringDeduplicationPrintOptions.java | 1 + hotspot/test/gc/g1/TestStringDeduplicationTableRehash.java | 1 + hotspot/test/gc/g1/TestStringDeduplicationTableResize.java | 1 + hotspot/test/gc/g1/TestStringDeduplicationYoungGC.java | 1 + hotspot/test/gc/g1/TestStringSymbolTableStats.java | 1 + hotspot/test/gc/serial/HeapChangeLogging.java | 2 +- 25 files changed, 18 insertions(+), 8 deletions(-) diff --git a/hotspot/test/gc/TestCardTablePageCommits.java b/hotspot/test/gc/TestCardTablePageCommits.java index fe50587d95a..e3d70b38533 100644 --- a/hotspot/test/gc/TestCardTablePageCommits.java +++ b/hotspot/test/gc/TestCardTablePageCommits.java @@ -34,7 +34,6 @@ import jdk.test.lib.Platform; * @requires vm.gc.Parallel * @library /test/lib * @modules java.base/jdk.internal.misc - * java.management * @run driver TestCardTablePageCommits */ public class TestCardTablePageCommits { diff --git a/hotspot/test/gc/TestObjectAlignment.java b/hotspot/test/gc/TestObjectAlignment.java index 9c6be10bd3f..ac4c1e267e7 100644 --- a/hotspot/test/gc/TestObjectAlignment.java +++ b/hotspot/test/gc/TestObjectAlignment.java @@ -28,7 +28,6 @@ * @summary G1: Concurrent marking crashes with -XX:ObjectAlignmentInBytes>=32 in 64bit VMs * @library /test/lib * @modules java.base/jdk.internal.misc - * java.management * @run main/othervm TestObjectAlignment -Xmx20M -XX:+ExplicitGCInvokesConcurrent -XX:+IgnoreUnrecognizedVMOptions -XX:ObjectAlignmentInBytes=8 * @run main/othervm TestObjectAlignment -Xmx20M -XX:+ExplicitGCInvokesConcurrent -XX:+IgnoreUnrecognizedVMOptions -XX:ObjectAlignmentInBytes=16 * @run main/othervm TestObjectAlignment -Xmx20M -XX:+ExplicitGCInvokesConcurrent -XX:+IgnoreUnrecognizedVMOptions -XX:ObjectAlignmentInBytes=32 diff --git a/hotspot/test/gc/TestSmallHeap.java b/hotspot/test/gc/TestSmallHeap.java index f604a4c5a06..9fb8f36a851 100644 --- a/hotspot/test/gc/TestSmallHeap.java +++ b/hotspot/test/gc/TestSmallHeap.java @@ -28,7 +28,6 @@ * @summary Verify that starting the VM with a small heap works * @library /test/lib * @modules java.base/jdk.internal.misc - * @modules java.management/sun.management * @build sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestSmallHeap diff --git a/hotspot/test/gc/TestSoftReferencesBehaviorOnOOME.java b/hotspot/test/gc/TestSoftReferencesBehaviorOnOOME.java index 6ea205757e7..79afdfb6bff 100644 --- a/hotspot/test/gc/TestSoftReferencesBehaviorOnOOME.java +++ b/hotspot/test/gc/TestSoftReferencesBehaviorOnOOME.java @@ -27,7 +27,6 @@ * @summary Tests that all SoftReferences has been cleared at time of OOM. * @library /test/lib * @modules java.base/jdk.internal.misc - * java.management * @run main/othervm -Xmx128m TestSoftReferencesBehaviorOnOOME 512 2k * @run main/othervm -Xmx128m TestSoftReferencesBehaviorOnOOME 128k 256k * @run main/othervm -Xmx128m TestSoftReferencesBehaviorOnOOME 2k 32k diff --git a/hotspot/test/gc/TestVerifyDuringStartup.java b/hotspot/test/gc/TestVerifyDuringStartup.java index 7439e40c04e..744b52be360 100644 --- a/hotspot/test/gc/TestVerifyDuringStartup.java +++ b/hotspot/test/gc/TestVerifyDuringStartup.java @@ -27,7 +27,6 @@ * @summary Simple test run with -XX:+VerifyDuringStartup -XX:-UseTLAB to verify 8010463 * @library /test/lib * @modules java.base/jdk.internal.misc - * java.management */ import jdk.test.lib.JDKToolFinder; diff --git a/hotspot/test/gc/TestVerifySilently.java b/hotspot/test/gc/TestVerifySilently.java index 7d11c44c7c3..5b811cfdc6d 100644 --- a/hotspot/test/gc/TestVerifySilently.java +++ b/hotspot/test/gc/TestVerifySilently.java @@ -27,7 +27,6 @@ * @summary Test silent verification. * @library /test/lib * @modules java.base/jdk.internal.misc - * java.management */ import jdk.test.lib.process.ProcessTools; diff --git a/hotspot/test/gc/TestVerifySubSet.java b/hotspot/test/gc/TestVerifySubSet.java index c43079475bc..b8ac248541d 100644 --- a/hotspot/test/gc/TestVerifySubSet.java +++ b/hotspot/test/gc/TestVerifySubSet.java @@ -27,7 +27,6 @@ * @summary Test VerifySubSet option * @library /test/lib * @modules java.base/jdk.internal.misc - * java.management */ import jdk.test.lib.process.ProcessTools; diff --git a/hotspot/test/gc/g1/TestEagerReclaimHumongousRegions.java b/hotspot/test/gc/g1/TestEagerReclaimHumongousRegions.java index 71ec43de6ff..1a7945b4791 100644 --- a/hotspot/test/gc/g1/TestEagerReclaimHumongousRegions.java +++ b/hotspot/test/gc/g1/TestEagerReclaimHumongousRegions.java @@ -27,6 +27,7 @@ * @summary Test to make sure that eager reclaim of humongous objects work. We simply try to fill * up the heap with humongous objects that should be eagerly reclaimable to avoid Full GC. * @key gc + * @requires vm.gc.G1 * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/hotspot/test/gc/g1/TestEagerReclaimHumongousRegionsClearMarkBits.java b/hotspot/test/gc/g1/TestEagerReclaimHumongousRegionsClearMarkBits.java index a516e02185a..d36782936d5 100644 --- a/hotspot/test/gc/g1/TestEagerReclaimHumongousRegionsClearMarkBits.java +++ b/hotspot/test/gc/g1/TestEagerReclaimHumongousRegionsClearMarkBits.java @@ -27,6 +27,7 @@ * @summary Test to make sure that eager reclaim of humongous objects correctly clears * mark bitmaps at reclaim. * @key gc + * @requires vm.gc.G1 * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/hotspot/test/gc/g1/TestEagerReclaimHumongousRegionsWithRefs.java b/hotspot/test/gc/g1/TestEagerReclaimHumongousRegionsWithRefs.java index 6bfa89b00bf..8643564236a 100644 --- a/hotspot/test/gc/g1/TestEagerReclaimHumongousRegionsWithRefs.java +++ b/hotspot/test/gc/g1/TestEagerReclaimHumongousRegionsWithRefs.java @@ -30,6 +30,7 @@ * referencing that we know is in the old gen. After changing this reference, the object * should still be eagerly reclaimable to avoid Full GC. * @key gc + * @requires vm.gc.G1 * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/hotspot/test/gc/g1/TestG1TraceEagerReclaimHumongousObjects.java b/hotspot/test/gc/g1/TestG1TraceEagerReclaimHumongousObjects.java index 2c27eb276ab..aafc5aa3dfb 100644 --- a/hotspot/test/gc/g1/TestG1TraceEagerReclaimHumongousObjects.java +++ b/hotspot/test/gc/g1/TestG1TraceEagerReclaimHumongousObjects.java @@ -27,6 +27,7 @@ * @summary Ensure that the output for a G1TraceEagerReclaimHumongousObjects * includes the expected necessary messages. * @key gc + * @requires vm.gc.G1 * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/hotspot/test/gc/g1/TestGCLogMessages.java b/hotspot/test/gc/g1/TestGCLogMessages.java index 776ef7d826a..6b2ac94d699 100644 --- a/hotspot/test/gc/g1/TestGCLogMessages.java +++ b/hotspot/test/gc/g1/TestGCLogMessages.java @@ -27,6 +27,7 @@ * @summary Ensure the output for a minor GC with G1 * includes the expected necessary messages. * @key gc + * @requires vm.gc.G1 * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/hotspot/test/gc/g1/TestHumongousAllocInitialMark.java b/hotspot/test/gc/g1/TestHumongousAllocInitialMark.java index c760c36db48..01fe107c725 100644 --- a/hotspot/test/gc/g1/TestHumongousAllocInitialMark.java +++ b/hotspot/test/gc/g1/TestHumongousAllocInitialMark.java @@ -25,6 +25,7 @@ * @test TestHumongousAllocInitialMark * @bug 7168848 * @summary G1: humongous object allocations should initiate marking cycles when necessary + * @requires vm.gc.G1 * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/hotspot/test/gc/g1/TestHumongousAllocNearlyFullRegion.java b/hotspot/test/gc/g1/TestHumongousAllocNearlyFullRegion.java index 7c0d7a170c3..ce01acd68a3 100644 --- a/hotspot/test/gc/g1/TestHumongousAllocNearlyFullRegion.java +++ b/hotspot/test/gc/g1/TestHumongousAllocNearlyFullRegion.java @@ -26,6 +26,7 @@ * @bug 8143587 * @summary G1: humongous object allocations should work even when there is * not enough space in the heapRegion to fit a filler object. + * @requires vm.gc.G1 * @modules java.base/jdk.internal.misc * @library /test/lib * @run driver TestHumongousAllocNearlyFullRegion diff --git a/hotspot/test/gc/g1/TestHumongousCodeCacheRoots.java b/hotspot/test/gc/g1/TestHumongousCodeCacheRoots.java index 955474c99e6..8acd37ca497 100644 --- a/hotspot/test/gc/g1/TestHumongousCodeCacheRoots.java +++ b/hotspot/test/gc/g1/TestHumongousCodeCacheRoots.java @@ -26,6 +26,7 @@ * @key regression * @key gc * @bug 8027756 + * @requires vm.gc.G1 * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/hotspot/test/gc/g1/TestPrintRegionRememberedSetInfo.java b/hotspot/test/gc/g1/TestPrintRegionRememberedSetInfo.java index 79b797b4286..873851c3805 100644 --- a/hotspot/test/gc/g1/TestPrintRegionRememberedSetInfo.java +++ b/hotspot/test/gc/g1/TestPrintRegionRememberedSetInfo.java @@ -26,6 +26,7 @@ * @key gc * @bug 8014240 * @summary Test output of G1PrintRegionRememberedSetInfo + * @requires vm.gc.G1 * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/hotspot/test/gc/g1/TestStringDeduplicationAgeThreshold.java b/hotspot/test/gc/g1/TestStringDeduplicationAgeThreshold.java index 25e6a12ff5e..aa5192d843e 100644 --- a/hotspot/test/gc/g1/TestStringDeduplicationAgeThreshold.java +++ b/hotspot/test/gc/g1/TestStringDeduplicationAgeThreshold.java @@ -26,6 +26,7 @@ * @summary Test string deduplication age threshold * @bug 8029075 * @key gc + * @requires vm.gc.G1 * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/hotspot/test/gc/g1/TestStringDeduplicationFullGC.java b/hotspot/test/gc/g1/TestStringDeduplicationFullGC.java index 1c2ab7389c4..be88c99cdd1 100644 --- a/hotspot/test/gc/g1/TestStringDeduplicationFullGC.java +++ b/hotspot/test/gc/g1/TestStringDeduplicationFullGC.java @@ -26,6 +26,7 @@ * @summary Test string deduplication during full GC * @bug 8029075 * @key gc + * @requires vm.gc.G1 * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/hotspot/test/gc/g1/TestStringDeduplicationInterned.java b/hotspot/test/gc/g1/TestStringDeduplicationInterned.java index 766c9f821b0..48f4b598d31 100644 --- a/hotspot/test/gc/g1/TestStringDeduplicationInterned.java +++ b/hotspot/test/gc/g1/TestStringDeduplicationInterned.java @@ -26,6 +26,7 @@ * @summary Test string deduplication of interned strings * @bug 8029075 * @key gc + * @requires vm.gc.G1 * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/hotspot/test/gc/g1/TestStringDeduplicationPrintOptions.java b/hotspot/test/gc/g1/TestStringDeduplicationPrintOptions.java index 43940962f9b..bb47eb52c7f 100644 --- a/hotspot/test/gc/g1/TestStringDeduplicationPrintOptions.java +++ b/hotspot/test/gc/g1/TestStringDeduplicationPrintOptions.java @@ -26,6 +26,7 @@ * @summary Test string deduplication print options * @bug 8029075 * @key gc + * @requires vm.gc.G1 * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/hotspot/test/gc/g1/TestStringDeduplicationTableRehash.java b/hotspot/test/gc/g1/TestStringDeduplicationTableRehash.java index 5f466f3681d..7c52c36612c 100644 --- a/hotspot/test/gc/g1/TestStringDeduplicationTableRehash.java +++ b/hotspot/test/gc/g1/TestStringDeduplicationTableRehash.java @@ -26,6 +26,7 @@ * @summary Test string deduplication table rehash * @bug 8029075 * @key gc + * @requires vm.gc.G1 * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/hotspot/test/gc/g1/TestStringDeduplicationTableResize.java b/hotspot/test/gc/g1/TestStringDeduplicationTableResize.java index 1259869e4e5..2a72f4042e2 100644 --- a/hotspot/test/gc/g1/TestStringDeduplicationTableResize.java +++ b/hotspot/test/gc/g1/TestStringDeduplicationTableResize.java @@ -26,6 +26,7 @@ * @summary Test string deduplication table resize * @bug 8029075 * @key gc + * @requires vm.gc.G1 * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/hotspot/test/gc/g1/TestStringDeduplicationYoungGC.java b/hotspot/test/gc/g1/TestStringDeduplicationYoungGC.java index a65e4ab3ce2..4cbc744a6f6 100644 --- a/hotspot/test/gc/g1/TestStringDeduplicationYoungGC.java +++ b/hotspot/test/gc/g1/TestStringDeduplicationYoungGC.java @@ -26,6 +26,7 @@ * @summary Test string deduplication during young GC * @bug 8029075 * @key gc + * @requires vm.gc.G1 * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/hotspot/test/gc/g1/TestStringSymbolTableStats.java b/hotspot/test/gc/g1/TestStringSymbolTableStats.java index 62994fa2d55..d0c3d312e91 100644 --- a/hotspot/test/gc/g1/TestStringSymbolTableStats.java +++ b/hotspot/test/gc/g1/TestStringSymbolTableStats.java @@ -26,6 +26,7 @@ * @bug 8027476 8027455 * @summary Ensure that the G1TraceStringSymbolTableScrubbing prints the expected message. * @key gc + * @requires vm.gc.G1 * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/hotspot/test/gc/serial/HeapChangeLogging.java b/hotspot/test/gc/serial/HeapChangeLogging.java index a8ef6f64464..ffc646d5d46 100644 --- a/hotspot/test/gc/serial/HeapChangeLogging.java +++ b/hotspot/test/gc/serial/HeapChangeLogging.java @@ -24,9 +24,9 @@ /* * @test HeapChangeLogging.java * @bug 8027440 + * @requires vm.gc.Serial * @library /test/lib * @modules java.base/jdk.internal.misc - * java.management * @summary Allocate to get a promotion failure and verify that that heap change logging is present. * @run main HeapChangeLogging */ From 6db26ca5bfbe97e9ae948da1e8fa201e07dec14e Mon Sep 17 00:00:00 2001 From: David Holmes Date: Mon, 29 Aug 2016 20:13:45 -0400 Subject: [PATCH 023/110] 8158854: Ensure release_store is paired with load_acquire in lock-free code Reviewed-by: shade, dcubed, zgu --- .../src/share/vm/classfile/classLoader.hpp | 8 ++-- hotspot/src/share/vm/classfile/verifier.cpp | 4 +- hotspot/src/share/vm/oops/arrayKlass.hpp | 2 + .../src/share/vm/oops/arrayKlass.inline.hpp | 39 +++++++++++++++++++ hotspot/src/share/vm/oops/instanceKlass.cpp | 6 ++- hotspot/src/share/vm/oops/instanceKlass.hpp | 12 +++--- .../share/vm/oops/instanceKlass.inline.hpp | 17 ++++++++ hotspot/src/share/vm/oops/objArrayKlass.cpp | 9 +++-- hotspot/src/share/vm/oops/typeArrayKlass.cpp | 9 +++-- hotspot/src/share/vm/runtime/vmStructs.cpp | 4 +- 10 files changed, 87 insertions(+), 23 deletions(-) create mode 100644 hotspot/src/share/vm/oops/arrayKlass.inline.hpp diff --git a/hotspot/src/share/vm/classfile/classLoader.hpp b/hotspot/src/share/vm/classfile/classLoader.hpp index e0d56862b95..35c000a6be1 100644 --- a/hotspot/src/share/vm/classfile/classLoader.hpp +++ b/hotspot/src/share/vm/classfile/classLoader.hpp @@ -50,12 +50,14 @@ class ClassFileStream; class ClassPathEntry : public CHeapObj { private: - ClassPathEntry* _next; + ClassPathEntry* volatile _next; public: // Next entry in class path - ClassPathEntry* next() const { return _next; } + ClassPathEntry* next() const { + return (ClassPathEntry*) OrderAccess::load_ptr_acquire(&_next); + } void set_next(ClassPathEntry* next) { - // may have unlocked readers, so write atomically. + // may have unlocked readers, so ensure visibility. OrderAccess::release_store_ptr(&_next, next); } virtual bool is_jrt() = 0; diff --git a/hotspot/src/share/vm/classfile/verifier.cpp b/hotspot/src/share/vm/classfile/verifier.cpp index 2194859c30c..440257b9e79 100644 --- a/hotspot/src/share/vm/classfile/verifier.cpp +++ b/hotspot/src/share/vm/classfile/verifier.cpp @@ -67,12 +67,12 @@ static void* volatile _verify_byte_codes_fn = NULL; static volatile jint _is_new_verify_byte_codes_fn = (jint) true; static void* verify_byte_codes_fn() { - if (_verify_byte_codes_fn == NULL) { + if (OrderAccess::load_ptr_acquire(&_verify_byte_codes_fn) == NULL) { void *lib_handle = os::native_java_library(); void *func = os::dll_lookup(lib_handle, "VerifyClassCodesForMajorVersion"); OrderAccess::release_store_ptr(&_verify_byte_codes_fn, func); if (func == NULL) { - OrderAccess::release_store(&_is_new_verify_byte_codes_fn, false); + _is_new_verify_byte_codes_fn = false; func = os::dll_lookup(lib_handle, "VerifyClassCodes"); OrderAccess::release_store_ptr(&_verify_byte_codes_fn, func); } diff --git a/hotspot/src/share/vm/oops/arrayKlass.hpp b/hotspot/src/share/vm/oops/arrayKlass.hpp index 3761229a1ce..c7dcd1f8657 100644 --- a/hotspot/src/share/vm/oops/arrayKlass.hpp +++ b/hotspot/src/share/vm/oops/arrayKlass.hpp @@ -56,7 +56,9 @@ class ArrayKlass: public Klass { void set_dimension(int dimension) { _dimension = dimension; } Klass* higher_dimension() const { return _higher_dimension; } + inline Klass* higher_dimension_acquire() const; // load with acquire semantics void set_higher_dimension(Klass* k) { _higher_dimension = k; } + inline void release_set_higher_dimension(Klass* k); // store with release semantics Klass** adr_higher_dimension() { return (Klass**)&this->_higher_dimension;} Klass* lower_dimension() const { return _lower_dimension; } diff --git a/hotspot/src/share/vm/oops/arrayKlass.inline.hpp b/hotspot/src/share/vm/oops/arrayKlass.inline.hpp new file mode 100644 index 00000000000..43f62915f34 --- /dev/null +++ b/hotspot/src/share/vm/oops/arrayKlass.inline.hpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_OOPS_ARRAYKLASS_INLINE_HPP +#define SHARE_VM_OOPS_ARRAYKLASS_INLINE_HPP + +#include "runtime/orderAccess.inline.hpp" +#include "oops/arrayKlass.hpp" + +inline Klass* ArrayKlass::higher_dimension_acquire() const { + return (Klass*) OrderAccess::load_ptr_acquire(&_higher_dimension); +} + +inline void ArrayKlass::release_set_higher_dimension(Klass* k) { + OrderAccess::release_store_ptr(&_higher_dimension, k); +} + +#endif // SHARE_VM_OOPS_ARRAYKLASS_INLINE_HPP diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index d6b2323af28..1385affc5df 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -1041,7 +1041,8 @@ Klass* InstanceKlass::array_klass_impl(bool or_null, int n, TRAPS) { } Klass* InstanceKlass::array_klass_impl(instanceKlassHandle this_k, bool or_null, int n, TRAPS) { - if (this_k->array_klasses() == NULL) { + // Need load-acquire for lock-free read + if (this_k->array_klasses_acquire() == NULL) { if (or_null) return NULL; ResourceMark rm; @@ -1054,7 +1055,8 @@ Klass* InstanceKlass::array_klass_impl(instanceKlassHandle this_k, bool or_null, // Check if update has already taken place if (this_k->array_klasses() == NULL) { Klass* k = ObjArrayKlass::allocate_objArray_klass(this_k->class_loader_data(), 1, this_k, CHECK_NULL); - this_k->set_array_klasses(k); + // use 'release' to pair with lock-free load + this_k->release_set_array_klasses(k); } } } diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index 24da1868237..da36a1422b4 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -148,7 +148,7 @@ class InstanceKlass: public Klass { // Package this class is defined in PackageEntry* _package_entry; // Array classes holding elements of this class. - Klass* _array_klasses; + Klass* volatile _array_klasses; // Constant pool for this class. ConstantPool* _constants; // The InnerClasses attribute and EnclosingMethod attribute. The @@ -230,7 +230,7 @@ class InstanceKlass: public Klass { OopMapCache* volatile _oop_map_cache; // OopMapCache for all methods in the klass (allocated lazily) MemberNameTable* _member_names; // Member names JNIid* _jni_ids; // First JNI identifier for static fields in this class - jmethodID* _methods_jmethod_ids; // jmethodIDs corresponding to method_idnum, or NULL if none + jmethodID* volatile _methods_jmethod_ids; // jmethodIDs corresponding to method_idnum, or NULL if none intptr_t _dep_context; // packed DependencyContext structure nmethod* _osr_nmethods_head; // Head of list of on-stack replacement nmethods for this class #if INCLUDE_JVMTI @@ -368,7 +368,9 @@ class InstanceKlass: public Klass { // array klasses Klass* array_klasses() const { return _array_klasses; } + inline Klass* array_klasses_acquire() const; // load with acquire semantics void set_array_klasses(Klass* k) { _array_klasses = k; } + inline void release_set_array_klasses(Klass* k); // store with release semantics // methods Array* methods() const { return _methods; } @@ -1238,10 +1240,8 @@ private: // cache management logic if the caches can grow instead of just // going from NULL to non-NULL. bool idnum_can_increment() const { return has_been_redefined(); } - jmethodID* methods_jmethod_ids_acquire() const - { return (jmethodID*)OrderAccess::load_ptr_acquire(&_methods_jmethod_ids); } - void release_set_methods_jmethod_ids(jmethodID* jmeths) - { OrderAccess::release_store_ptr(&_methods_jmethod_ids, jmeths); } + inline jmethodID* methods_jmethod_ids_acquire() const; + inline void release_set_methods_jmethod_ids(jmethodID* jmeths); // Lock during initialization public: diff --git a/hotspot/src/share/vm/oops/instanceKlass.inline.hpp b/hotspot/src/share/vm/oops/instanceKlass.inline.hpp index 3fe04808df4..a213272a9e5 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.inline.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.inline.hpp @@ -29,10 +29,27 @@ #include "oops/instanceKlass.hpp" #include "oops/klass.hpp" #include "oops/oop.inline.hpp" +#include "runtime/orderAccess.inline.hpp" #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" +inline Klass* InstanceKlass::array_klasses_acquire() const { + return (Klass*) OrderAccess::load_ptr_acquire(&_array_klasses); +} + +inline void InstanceKlass::release_set_array_klasses(Klass* k) { + OrderAccess::release_store_ptr(&_array_klasses, k); +} + +inline jmethodID* InstanceKlass::methods_jmethod_ids_acquire() const { + return (jmethodID*)OrderAccess::load_ptr_acquire(&_methods_jmethod_ids); +} + +inline void InstanceKlass::release_set_methods_jmethod_ids(jmethodID* jmeths) { + OrderAccess::release_store_ptr(&_methods_jmethod_ids, jmeths); +} + // The iteration over the oops in objects is a hot path in the GC code. // By force inlining the following functions, we get similar GC performance // as the previous macro based implementation. diff --git a/hotspot/src/share/vm/oops/objArrayKlass.cpp b/hotspot/src/share/vm/oops/objArrayKlass.cpp index 1abcc152fc6..bf2672daa78 100644 --- a/hotspot/src/share/vm/oops/objArrayKlass.cpp +++ b/hotspot/src/share/vm/oops/objArrayKlass.cpp @@ -34,6 +34,7 @@ #include "memory/metadataFactory.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.inline.hpp" +#include "oops/arrayKlass.inline.hpp" #include "oops/instanceKlass.hpp" #include "oops/klass.inline.hpp" #include "oops/objArrayKlass.inline.hpp" @@ -42,7 +43,6 @@ #include "oops/symbol.hpp" #include "runtime/handles.inline.hpp" #include "runtime/mutexLocker.hpp" -#include "runtime/orderAccess.inline.hpp" #include "utilities/copy.hpp" #include "utilities/macros.hpp" @@ -321,7 +321,8 @@ Klass* ObjArrayKlass::array_klass_impl(bool or_null, int n, TRAPS) { int dim = dimension(); if (dim == n) return this; - if (higher_dimension() == NULL) { + // lock-free read needs acquire semantics + if (higher_dimension_acquire() == NULL) { if (or_null) return NULL; ResourceMark rm; @@ -339,8 +340,8 @@ Klass* ObjArrayKlass::array_klass_impl(bool or_null, int n, TRAPS) { ObjArrayKlass::allocate_objArray_klass(class_loader_data(), dim + 1, this, CHECK_NULL); ObjArrayKlass* ak = ObjArrayKlass::cast(k); ak->set_lower_dimension(this); - OrderAccess::storestore(); - set_higher_dimension(ak); + // use 'release' to pair with lock-free load + release_set_higher_dimension(ak); assert(ak->is_objArray_klass(), "incorrect initialization of ObjArrayKlass"); } } diff --git a/hotspot/src/share/vm/oops/typeArrayKlass.cpp b/hotspot/src/share/vm/oops/typeArrayKlass.cpp index 76b2bb8e6b9..580c4694512 100644 --- a/hotspot/src/share/vm/oops/typeArrayKlass.cpp +++ b/hotspot/src/share/vm/oops/typeArrayKlass.cpp @@ -34,6 +34,7 @@ #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "memory/universe.inline.hpp" +#include "oops/arrayKlass.inline.hpp" #include "oops/instanceKlass.hpp" #include "oops/klass.inline.hpp" #include "oops/objArrayKlass.hpp" @@ -41,7 +42,6 @@ #include "oops/typeArrayKlass.inline.hpp" #include "oops/typeArrayOop.inline.hpp" #include "runtime/handles.inline.hpp" -#include "runtime/orderAccess.inline.hpp" #include "utilities/macros.hpp" bool TypeArrayKlass::compute_is_subtype_of(Klass* k) { @@ -166,7 +166,8 @@ Klass* TypeArrayKlass::array_klass_impl(bool or_null, int n, TRAPS) { if (dim == n) return this; - if (higher_dimension() == NULL) { + // lock-free read needs acquire semantics + if (higher_dimension_acquire() == NULL) { if (or_null) return NULL; ResourceMark rm; @@ -181,8 +182,8 @@ Klass* TypeArrayKlass::array_klass_impl(bool or_null, int n, TRAPS) { class_loader_data(), dim + 1, this, CHECK_NULL); ObjArrayKlass* h_ak = ObjArrayKlass::cast(oak); h_ak->set_lower_dimension(this); - OrderAccess::storestore(); - set_higher_dimension(h_ak); + // use 'release' to pair with lock-free load + release_set_higher_dimension(h_ak); assert(h_ak->is_objArray_klass(), "incorrect initialization of ObjArrayKlass"); } } diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 34b48c3cf80..81994ce96f1 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -242,7 +242,7 @@ typedef CompactHashtable SymbolCompactHashTable; nonstatic_field(ConstantPool, _reference_map, Array*) \ nonstatic_field(ConstantPoolCache, _length, int) \ nonstatic_field(ConstantPoolCache, _constant_pool, ConstantPool*) \ - nonstatic_field(InstanceKlass, _array_klasses, Klass*) \ + volatile_nonstatic_field(InstanceKlass, _array_klasses, Klass*) \ nonstatic_field(InstanceKlass, _methods, Array*) \ nonstatic_field(InstanceKlass, _default_methods, Array*) \ nonstatic_field(InstanceKlass, _local_interfaces, Array*) \ @@ -271,7 +271,7 @@ typedef CompactHashtable SymbolCompactHashTable; nonstatic_field(InstanceKlass, _osr_nmethods_head, nmethod*) \ JVMTI_ONLY(nonstatic_field(InstanceKlass, _breakpoints, BreakpointInfo*)) \ nonstatic_field(InstanceKlass, _generic_signature_index, u2) \ - nonstatic_field(InstanceKlass, _methods_jmethod_ids, jmethodID*) \ + volatile_nonstatic_field(InstanceKlass, _methods_jmethod_ids, jmethodID*) \ volatile_nonstatic_field(InstanceKlass, _idnum_allocated_count, u2) \ nonstatic_field(InstanceKlass, _annotations, Annotations*) \ nonstatic_field(InstanceKlass, _method_ordering, Array*) \ From 5258f6573c1e6a02e9d14ba98b53fdc08edde799 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Tue, 30 Aug 2016 09:17:49 +0200 Subject: [PATCH 024/110] 8155917: Memory access in free regions during G1 full gc causes regressions in SPECjvm2008 scimark.fft,lu,sor,sparse with 9+116 on Linux-x64 Do not unnecessarily touch the memory of free regions during the compaction phase in G1 full gc causing some OSes to allocate physical memory for them, decreasing performance in some situations. Reviewed-by: mgerdin, jmasa --- hotspot/src/share/vm/gc/shared/space.inline.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/gc/shared/space.inline.hpp b/hotspot/src/share/vm/gc/shared/space.inline.hpp index 3943a6da5dc..77b6f4ceb5a 100644 --- a/hotspot/src/share/vm/gc/shared/space.inline.hpp +++ b/hotspot/src/share/vm/gc/shared/space.inline.hpp @@ -293,10 +293,11 @@ inline void CompactibleSpace::scan_and_compact(SpaceType* space) { verify_up_to_first_dead(space); + HeapWord* const bottom = space->bottom(); HeapWord* const end_of_live = space->_end_of_live; assert(space->_first_dead <= end_of_live, "Invariant. _first_dead: " PTR_FORMAT " <= end_of_live: " PTR_FORMAT, p2i(space->_first_dead), p2i(end_of_live)); - if (space->_first_dead == end_of_live && !oop(space->bottom())->is_gc_marked()) { + if (space->_first_dead == end_of_live && (bottom == end_of_live || !oop(bottom)->is_gc_marked())) { // Nothing to compact. The space is either empty or all live object should be left in place. clear_empty_region(space); return; @@ -305,8 +306,8 @@ inline void CompactibleSpace::scan_and_compact(SpaceType* space) { const intx scan_interval = PrefetchScanIntervalInBytes; const intx copy_interval = PrefetchCopyIntervalInBytes; - assert(space->bottom() < end_of_live, "bottom: " PTR_FORMAT " should be < end_of_live: " PTR_FORMAT, p2i(space->bottom()), p2i(end_of_live)); - HeapWord* cur_obj = space->bottom(); + assert(bottom < end_of_live, "bottom: " PTR_FORMAT " should be < end_of_live: " PTR_FORMAT, p2i(bottom), p2i(end_of_live)); + HeapWord* cur_obj = bottom; if (space->_first_dead > cur_obj && !oop(cur_obj)->is_gc_marked()) { // All object before _first_dead can be skipped. They should not be moved. // A pointer to the first live object is stored at the memory location for _first_dead. From 8445923b1ce3b6bcbf5a7ea2221f6013398c2902 Mon Sep 17 00:00:00 2001 From: Jini George Date: Tue, 30 Aug 2016 11:06:25 +0300 Subject: [PATCH 025/110] 8164562: serviceability/sa/TestInstanceKlassSizeForInterface.java: fails with NPE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addition of –XX:+UnlockDiagnosticVMOptions for the test invocation for jcmd and modularization related cleanup Reviewed-by: dholmes, mchung --- .../sa/TestInstanceKlassSize.java | 33 ++++++++++++------- .../sa/TestInstanceKlassSizeForInterface.java | 29 ++++++++++------ 2 files changed, 40 insertions(+), 22 deletions(-) diff --git a/hotspot/test/serviceability/sa/TestInstanceKlassSize.java b/hotspot/test/serviceability/sa/TestInstanceKlassSize.java index db1ed0f180f..dd8deda1612 100644 --- a/hotspot/test/serviceability/sa/TestInstanceKlassSize.java +++ b/hotspot/test/serviceability/sa/TestInstanceKlassSize.java @@ -23,6 +23,7 @@ import sun.jvm.hotspot.HotSpotAgent; import sun.jvm.hotspot.utilities.SystemDictionaryHelper; +import sun.jvm.hotspot.oops.InstanceKlass; import sun.jvm.hotspot.debugger.*; import java.util.ArrayList; @@ -44,15 +45,19 @@ import java.util.*; * @test * @library /test/lib * @modules java.base/jdk.internal.misc - * @modules jdk.hotspot.agent - * @modules jdk.hotspot.agent/sun.jvm.hotspot - * @modules jdk.hotspot.agent/sun.jvm.hotspot.utilities - * @modules jdk.hotspot.agent/sun.jvm.hotspot.oops - * @compile -XDignore.symbol.file=true -Xmodule:jdk.hotspot.agent - * -XaddExports:java.base/jdk.internal.misc=jdk.hotspot.agent - * -XaddExports:java.management/java.lang.management=jdk.hotspot.agent + * @compile -XDignore.symbol.file=true + * --add-exports=jdk.hotspot.agent/sun.jvm.hotspot=ALL-UNNAMED + * --add-exports=jdk.hotspot.agent/sun.jvm.hotspot.utilities=ALL-UNNAMED + * --add-exports=jdk.hotspot.agent/sun.jvm.hotspot.oops=ALL-UNNAMED + * --add-exports=jdk.hotspot.agent/sun.jvm.hotspot.debugger=ALL-UNNAMED * TestInstanceKlassSize.java - * @run main/othervm TestInstanceKlassSize + * @run main/othervm + * --add-modules=jdk.hotspot.agent + * --add-exports=jdk.hotspot.agent/sun.jvm.hotspot=ALL-UNNAMED + * --add-exports=jdk.hotspot.agent/sun.jvm.hotspot.utilities=ALL-UNNAMED + * --add-exports=jdk.hotspot.agent/sun.jvm.hotspot.oops=ALL-UNNAMED + * --add-exports=jdk.hotspot.agent/sun.jvm.hotspot.debugger=ALL-UNNAMED + * TestInstanceKlassSize */ public class TestInstanceKlassSize { @@ -112,11 +117,11 @@ public class TestInstanceKlassSize { " java.lang.Byte", }; String[] toolArgs = { - "-XX:+UnlockDiagnosticVMOptions", "--add-modules=jdk.hotspot.agent", "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot=ALL-UNNAMED", "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.utilities=ALL-UNNAMED", "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.oops=ALL-UNNAMED", + "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.debugger=ALL-UNNAMED", "TestInstanceKlassSize", Long.toString(app.getPid()) }; @@ -136,6 +141,8 @@ public class TestInstanceKlassSize { String jcmdInstanceKlassSize = getJcmdInstanceKlassSize( jcmdOutput, instanceKlassName); + Asserts.assertNotNull(jcmdInstanceKlassSize, + "Could not get the instance klass size from the jcmd output"); for (String s : output.asLines()) { if (s.contains(instanceKlassName)) { Asserts.assertTrue( @@ -165,10 +172,12 @@ public class TestInstanceKlassSize { } for (String SAInstanceKlassName : SAInstanceKlassNames) { - Long size = SystemDictionaryHelper.findInstanceKlass( - SAInstanceKlassName).getSize(); + InstanceKlass ik = SystemDictionaryHelper.findInstanceKlass( + SAInstanceKlassName); + Asserts.assertNotNull(ik, + String.format("Unable to find instance klass for %s", ik)); System.out.println("SA: The size of " + SAInstanceKlassName + - " is " + size); + " is " + ik.getSize()); } agent.detach(); } diff --git a/hotspot/test/serviceability/sa/TestInstanceKlassSizeForInterface.java b/hotspot/test/serviceability/sa/TestInstanceKlassSizeForInterface.java index 0c23373e6e3..0bd8bc38b23 100644 --- a/hotspot/test/serviceability/sa/TestInstanceKlassSizeForInterface.java +++ b/hotspot/test/serviceability/sa/TestInstanceKlassSizeForInterface.java @@ -38,15 +38,20 @@ import jdk.test.lib.Asserts; * @test * @library /test/lib * @modules java.base/jdk.internal.misc - * @modules jdk.hotspot.agent - * @modules jdk.hotspot.agent/sun.jvm.hotspot - * @modules jdk.hotspot.agent/sun.jvm.hotspot.utilities - * @modules jdk.hotspot.agent/sun.jvm.hotspot.oops - * @compile -XDignore.symbol.file=true -Xmodule:jdk.hotspot.agent - * -XaddExports:java.base/jdk.internal.misc=jdk.hotspot.agent - * -XaddExports:java.management/java.lang.management=jdk.hotspot.agent + * @compile -XDignore.symbol.file=true + * --add-exports=jdk.hotspot.agent/sun.jvm.hotspot=ALL-UNNAMED + * --add-exports=jdk.hotspot.agent/sun.jvm.hotspot.utilities=ALL-UNNAMED + * --add-exports=jdk.hotspot.agent/sun.jvm.hotspot.oops=ALL-UNNAMED + * --add-exports=jdk.hotspot.agent/sun.jvm.hotspot.debugger=ALL-UNNAMED * TestInstanceKlassSizeForInterface.java - * @run main/othervm TestInstanceKlassSizeForInterface + * @run main/othervm + * -XX:+UnlockDiagnosticVMOptions + * --add-modules=jdk.hotspot.agent + * --add-exports=jdk.hotspot.agent/sun.jvm.hotspot=ALL-UNNAMED + * --add-exports=jdk.hotspot.agent/sun.jvm.hotspot.utilities=ALL-UNNAMED + * --add-exports=jdk.hotspot.agent/sun.jvm.hotspot.oops=ALL-UNNAMED + * --add-exports=jdk.hotspot.agent/sun.jvm.hotspot.debugger=ALL-UNNAMED + * TestInstanceKlassSizeForInterface */ interface Language { @@ -80,6 +85,8 @@ public class TestInstanceKlassSizeForInterface { for (String instanceKlassName : instanceKlassNames) { InstanceKlass iKlass = SystemDictionaryHelper.findInstanceKlass( instanceKlassName); + Asserts.assertNotNull(iKlass, + String.format("Unable to find instance klass for %s", instanceKlassName)); System.out.println("SA: The size of " + instanceKlassName + " is " + iKlass.getSize()); } @@ -106,11 +113,11 @@ public class TestInstanceKlassSizeForInterface { // Grab the pid from the current java process and pass it String[] toolArgs = { - "-XX:+UnlockDiagnosticVMOptions", "--add-modules=jdk.hotspot.agent", "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot=ALL-UNNAMED", "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.utilities=ALL-UNNAMED", "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.oops=ALL-UNNAMED", + "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.debugger=ALL-UNNAMED", "TestInstanceKlassSizeForInterface", Long.toString(ProcessTools.getProcessId()) }; @@ -138,6 +145,8 @@ public class TestInstanceKlassSizeForInterface { String jcmdInstanceKlassSize = getJcmdInstanceKlassSize( jcmdOutput, instanceKlassName); + Asserts.assertNotNull(jcmdInstanceKlassSize, + "Could not get the instance klass size from the jcmd output"); for (String s : SAOutput.asLines()) { if (s.contains(instanceKlassName)) { Asserts.assertTrue( @@ -162,7 +171,7 @@ public class TestInstanceKlassSizeForInterface { return; } - if ( args == null || args.length == 0 ) { + if (args == null || args.length == 0) { ParselTongue lang = new ParselTongue(); Language ventro = new Language() { From 4f55b6c7e03687e9b799456d6e4d0b82027566ec Mon Sep 17 00:00:00 2001 From: Alexander Kulyakhtin Date: Tue, 30 Aug 2016 12:48:03 +0300 Subject: [PATCH 026/110] 8148103: add more tests for task "Update JDI and JDWP for modules" A new JDWP test Reviewed-by: sspitsyn --- .../jdwp/AllModulesCommandTest.java | 149 ++++++++++++++++ .../jdwp/AllModulesCommandTestDebuggee.java | 55 ++++++ .../serviceability/jdwp/DebuggeeLauncher.java | 166 ++++++++++++++++++ .../jdwp/JdwpAllModulesCmd.java | 32 ++++ .../jdwp/JdwpAllModulesReply.java | 61 +++++++ .../serviceability/jdwp/JdwpCanReadCmd.java | 35 ++++ .../serviceability/jdwp/JdwpCanReadReply.java | 41 +++++ .../test/serviceability/jdwp/JdwpChannel.java | 71 ++++++++ .../jdwp/JdwpClassLoaderCmd.java | 34 ++++ .../jdwp/JdwpClassLoaderReply.java | 42 +++++ hotspot/test/serviceability/jdwp/JdwpCmd.java | 93 ++++++++++ .../test/serviceability/jdwp/JdwpExitCmd.java | 34 ++++ .../serviceability/jdwp/JdwpModNameCmd.java | 34 ++++ .../serviceability/jdwp/JdwpModNameReply.java | 42 +++++ .../test/serviceability/jdwp/JdwpReply.java | 75 ++++++++ .../serviceability/jdwp/StreamHandler.java | 81 +++++++++ 16 files changed, 1045 insertions(+) create mode 100644 hotspot/test/serviceability/jdwp/AllModulesCommandTest.java create mode 100644 hotspot/test/serviceability/jdwp/AllModulesCommandTestDebuggee.java create mode 100644 hotspot/test/serviceability/jdwp/DebuggeeLauncher.java create mode 100644 hotspot/test/serviceability/jdwp/JdwpAllModulesCmd.java create mode 100644 hotspot/test/serviceability/jdwp/JdwpAllModulesReply.java create mode 100644 hotspot/test/serviceability/jdwp/JdwpCanReadCmd.java create mode 100644 hotspot/test/serviceability/jdwp/JdwpCanReadReply.java create mode 100644 hotspot/test/serviceability/jdwp/JdwpChannel.java create mode 100644 hotspot/test/serviceability/jdwp/JdwpClassLoaderCmd.java create mode 100644 hotspot/test/serviceability/jdwp/JdwpClassLoaderReply.java create mode 100644 hotspot/test/serviceability/jdwp/JdwpCmd.java create mode 100644 hotspot/test/serviceability/jdwp/JdwpExitCmd.java create mode 100644 hotspot/test/serviceability/jdwp/JdwpModNameCmd.java create mode 100644 hotspot/test/serviceability/jdwp/JdwpModNameReply.java create mode 100644 hotspot/test/serviceability/jdwp/JdwpReply.java create mode 100644 hotspot/test/serviceability/jdwp/StreamHandler.java diff --git a/hotspot/test/serviceability/jdwp/AllModulesCommandTest.java b/hotspot/test/serviceability/jdwp/AllModulesCommandTest.java new file mode 100644 index 00000000000..33bb583c59d --- /dev/null +++ b/hotspot/test/serviceability/jdwp/AllModulesCommandTest.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.IOException; +import java.util.Arrays; +import java.util.concurrent.CountDownLatch; +import java.util.Set; +import java.util.HashSet; +import static jdk.test.lib.Asserts.assertTrue; + +/** + * @test + * @summary Tests AllModules JDWP command + * @library /test/lib + * @modules java.base/jdk.internal.misc + * @compile AllModulesCommandTestDebuggee.java + * @run main/othervm AllModulesCommandTest + */ +public class AllModulesCommandTest implements DebuggeeLauncher.Listener { + + private DebuggeeLauncher launcher; + private JdwpChannel channel; + private CountDownLatch jdwpLatch = new CountDownLatch(1); + private Set jdwpModuleNames = new HashSet<>(); + private Set javaModuleNames = new HashSet<>(); + + public static void main(String[] args) throws Throwable { + new AllModulesCommandTest().doTest(); + } + + private void doTest() throws Throwable { + launcher = new DebuggeeLauncher(this); + launcher.launchDebuggee(); + // Await till the debuggee sends all the necessary modules info to check against + // then start the JDWP session + jdwpLatch.await(); + doJdwp(); + } + + @Override + public void onDebuggeeModuleInfo(String modName) { + // The debuggee has sent out info about a loaded module + javaModuleNames.add(modName); + } + + @Override + public void onDebuggeeSendingCompleted() { + // The debuggee has completed sending all the info + // We can start the JDWP session + jdwpLatch.countDown(); + } + + @Override + public void onDebuggeeError(String message) { + System.err.println("Debuggee error: '" + message + "'"); + System.exit(1); + } + + private void doJdwp() throws Exception { + try { + // Establish JDWP socket connection + channel = new JdwpChannel(); + channel.connect(); + // Send out ALLMODULES JDWP command + // and verify the reply + JdwpAllModulesReply reply = new JdwpAllModulesCmd().send(channel); + assertReply(reply); + for (int i = 0; i < reply.getModulesCount(); ++i) { + long modId = reply.getModuleId(i); + // For each module reported by JDWP get its name using the JDWP NAME command + getModuleName(modId); + // Assert the JDWP CANREAD and CLASSLOADER commands + assertCanRead(modId); + assertClassLoader(modId); + } + + System.out.println("Module names reported by JDWP: " + Arrays.toString(jdwpModuleNames.toArray())); + System.out.println("Module names reported by Java: " + Arrays.toString(javaModuleNames.toArray())); + + // Modules reported by the JDWP should be the same as reported by the Java API + if (!jdwpModuleNames.equals(javaModuleNames)) { + throw new RuntimeException("Modules info reported by Java API differs from that reported by JDWP."); + } else { + System.out.println("Test passed!"); + } + + } finally { + launcher.terminateDebuggee(); + try { + new JdwpExitCmd(0).send(channel); + channel.disconnect(); + } catch (Exception x) { + } + } + } + + private void getModuleName(long modId) throws IOException { + // Send out the JDWP NAME command and store the reply + JdwpModNameReply reply = new JdwpModNameCmd(modId).send(channel); + assertReply(reply); + String modName = reply.getModuleName(); + if (modName != null) { // JDWP reports unnamed modules, ignore them + jdwpModuleNames.add(modName); + } + } + + private void assertReply(JdwpReply reply) { + // Simple assert for any JDWP reply + if (reply.getErrorCode() != 0) { + throw new RuntimeException("Unexpected reply error code " + reply.getErrorCode() + " for reply " + reply); + } + } + + private void assertCanRead(long modId) throws IOException { + // Simple assert for the CANREAD command + JdwpCanReadReply reply = new JdwpCanReadCmd(modId, modId).send(channel); + assertReply(reply); + assertTrue(reply.canRead(), "canRead() reports false for reading from the same module"); + } + + private void assertClassLoader(long modId) throws IOException { + // Simple assert for the CLASSLOADER command + JdwpClassLoaderReply reply = new JdwpClassLoaderCmd(modId).send(channel); + assertReply(reply); + long clId = reply.getClassLoaderId(); + assertTrue(clId >= 0, "bad classloader refId " + clId + " for module id " + modId); + } + +} diff --git a/hotspot/test/serviceability/jdwp/AllModulesCommandTestDebuggee.java b/hotspot/test/serviceability/jdwp/AllModulesCommandTestDebuggee.java new file mode 100644 index 00000000000..1b686ec9ae4 --- /dev/null +++ b/hotspot/test/serviceability/jdwp/AllModulesCommandTestDebuggee.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.reflect.Module; +import java.lang.reflect.Layer; +import java.util.Set; +import java.util.HashSet; + +/** + * The debuggee to be launched by the test + * Sends out the info about the loaded modules + * then stays to respond to the JDWP commands + */ +public class AllModulesCommandTestDebuggee { + + public static void main(String[] args) throws InterruptedException { + + int modCount = Layer.boot().modules().size(); + + // Send all modules names via the process output + for (Module mod : Layer.boot().modules()) { + String info = String.format("module %s", mod.getName()); + write(info); + } + // Signal that the sending is done + write("ready"); + Thread.sleep(Long.MAX_VALUE); + } + + private static void write(String s) { + System.out.println(s); + System.out.flush(); + } + +} diff --git a/hotspot/test/serviceability/jdwp/DebuggeeLauncher.java b/hotspot/test/serviceability/jdwp/DebuggeeLauncher.java new file mode 100644 index 00000000000..259c9ac0f6c --- /dev/null +++ b/hotspot/test/serviceability/jdwp/DebuggeeLauncher.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.IOException; +import java.net.ServerSocket; +import java.util.StringTokenizer; +import jdk.test.lib.JDKToolFinder; +import jdk.test.lib.Utils; +import static jdk.test.lib.Asserts.assertFalse; + +/** + * Launches the debuggee with the necessary JDWP options and handles the output + */ +public class DebuggeeLauncher implements StreamHandler.Listener { + + public interface Listener { + + /** + * Callback to use when a module name is received from the debuggee + * + * @param modName module name reported by the debuggee + */ + void onDebuggeeModuleInfo(String modName); + + /** + * Callback to use when the debuggee completes sending out the info + */ + void onDebuggeeSendingCompleted(); + + /** + * Callback to handle any debuggee error + * + * @param line line from the debuggee's stderr + */ + void onDebuggeeError(String line); + } + + private static int jdwpPort = -1; + private static final String CLS_DIR = System.getProperty("test.classes", "").trim(); + private static final String DEBUGGEE = "AllModulesCommandTestDebuggee"; + private Process p; + private final Listener listener; + private StreamHandler inputHandler; + private StreamHandler errorHandler; + + /** + * @param listener the listener we report the debuggee events to + */ + public DebuggeeLauncher(Listener listener) { + this.listener = listener; + } + + /** + * Starts the debuggee with the necessary JDWP options and handles the + * debuggee's stdout and stderr outputs + * + * @throws Throwable + */ + public void launchDebuggee() throws Throwable { + + ProcessBuilder pb = new ProcessBuilder(getCommand()); + p = pb.start(); + inputHandler = new StreamHandler(p.getInputStream(), this); + errorHandler = new StreamHandler(p.getErrorStream(), this); + inputHandler.start(); + errorHandler.start(); + } + + /** + * Command to start the debuggee with the JDWP options and using the JDK + * under test + * + * @return the command + */ + private String[] getCommand() { + return new String[]{ + JDKToolFinder.getTestJDKTool("java"), + getJdwpOptions(), + "-cp", + CLS_DIR, + DEBUGGEE + }; + } + + /** + * Terminates the debuggee + */ + public void terminateDebuggee() { + if (p.isAlive()) { + p.destroyForcibly(); + } + } + + /** + * Debuggee JDWP options + * + * @return the JDWP options to start the debuggee with + */ + private static String getJdwpOptions() { + return "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=" + getJdwpPort(); + } + + /** + * Find an available port for the JDWP session + * + * @return JDWP port + */ + public static int getJdwpPort() { + if (jdwpPort == -1) { + jdwpPort = findFreePort(); + assertFalse(jdwpPort == -1, "Can not find vailbale port for JDWP"); + } + return jdwpPort; + } + + private static int findFreePort() { + try (ServerSocket socket = new ServerSocket(0)) { + return socket.getLocalPort(); + } catch (IOException e) { + } + return -1; + } + + @Override + public void onStringRead(StreamHandler handler, String line) { + if (handler.equals(errorHandler)) { + terminateDebuggee(); + listener.onDebuggeeError(line); + } else { + processDebuggeeOutput(line); + } + } + + private void processDebuggeeOutput(String line) { + StringTokenizer st = new StringTokenizer(line); + String token = st.nextToken(); + switch (token) { + case "module": + listener.onDebuggeeModuleInfo(st.nextToken()); + break; + case "ready": + listener.onDebuggeeSendingCompleted(); + break; + } + } +} diff --git a/hotspot/test/serviceability/jdwp/JdwpAllModulesCmd.java b/hotspot/test/serviceability/jdwp/JdwpAllModulesCmd.java new file mode 100644 index 00000000000..020b95f9962 --- /dev/null +++ b/hotspot/test/serviceability/jdwp/JdwpAllModulesCmd.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * The JDWP ALLMODULES command + */ +public class JdwpAllModulesCmd extends JdwpCmd { + + public JdwpAllModulesCmd() { + super(22, 1, JdwpAllModulesReply.class, 0); + } +} diff --git a/hotspot/test/serviceability/jdwp/JdwpAllModulesReply.java b/hotspot/test/serviceability/jdwp/JdwpAllModulesReply.java new file mode 100644 index 00000000000..53d3de1f11f --- /dev/null +++ b/hotspot/test/serviceability/jdwp/JdwpAllModulesReply.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * The JDWP reply to the ALLMODULES command + */ +public class JdwpAllModulesReply extends JdwpReply { + + private int modulesCount; + private long[] modulesId; + + protected void parseData(DataInputStream ds) throws IOException { + modulesCount = ds.readInt(); + modulesId = new long[modulesCount]; + for (int nmod = 0; nmod < modulesCount; ++nmod) { + modulesId[nmod] = readRefId(ds); + } + } + + /** + * Number of modules reported + * + * @return modules count + */ + public int getModulesCount() { + return modulesCount; + } + + /** + * The id of a module reported + * + * @param ndx module index in the array of the reported ids + * @return module id + */ + public long getModuleId(int ndx) { + return modulesId[ndx]; + } +} diff --git a/hotspot/test/serviceability/jdwp/JdwpCanReadCmd.java b/hotspot/test/serviceability/jdwp/JdwpCanReadCmd.java new file mode 100644 index 00000000000..81cb5a9983c --- /dev/null +++ b/hotspot/test/serviceability/jdwp/JdwpCanReadCmd.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * The JDWP CANREAD command + */ +public class JdwpCanReadCmd extends JdwpCmd { + + public JdwpCanReadCmd(long modId, long srcModId) { + super(3, 18, JdwpCanReadReply.class, 2 * refLen()); + putRefId(modId); + putRefId(srcModId); + } + +} diff --git a/hotspot/test/serviceability/jdwp/JdwpCanReadReply.java b/hotspot/test/serviceability/jdwp/JdwpCanReadReply.java new file mode 100644 index 00000000000..f838baf89b6 --- /dev/null +++ b/hotspot/test/serviceability/jdwp/JdwpCanReadReply.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.io.DataInputStream; +import java.io.IOException; + +/** + * The reply to the JDWP CANREAD command + */ +public class JdwpCanReadReply extends JdwpReply { + + private boolean canRead; + + protected void parseData(DataInputStream ds) throws IOException { + canRead = ds.read() == 1; + } + + public boolean canRead() { + return canRead; + } + +} diff --git a/hotspot/test/serviceability/jdwp/JdwpChannel.java b/hotspot/test/serviceability/jdwp/JdwpChannel.java new file mode 100644 index 00000000000..d2e780c802f --- /dev/null +++ b/hotspot/test/serviceability/jdwp/JdwpChannel.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.IOException; +import java.io.InputStream; +import java.net.Socket; +import java.util.Arrays; + +/** + * JDWP socket transport + */ +public class JdwpChannel { + + private Socket sock; + + public void connect() throws IOException { + sock = new Socket("localhost", DebuggeeLauncher.getJdwpPort()); + handshake(); + } + + /** + * Sends JDWP handshake and verifies the reply + * @throws IOException + */ + private void handshake() throws IOException { + final byte[] HANDSHAKE = "JDWP-Handshake".getBytes(); + sock.getOutputStream().write(HANDSHAKE, 0, HANDSHAKE.length); + + byte[] reply = new byte[14]; + sock.getInputStream().read(reply, 0, 14); + if (!Arrays.equals(HANDSHAKE, reply)) { + throw new RuntimeException("Error during handshake. Reply was: " + new String(reply) + " expected " + new String(HANDSHAKE)); + } + } + + public void disconnect() { + try { + sock.close(); + } catch (IOException x) { + } + } + + public void write(byte[] data, int length) throws IOException { + sock.getOutputStream().write(data, 0, length); + } + + public InputStream getInputStream() throws IOException { + return sock.getInputStream(); + } + +} diff --git a/hotspot/test/serviceability/jdwp/JdwpClassLoaderCmd.java b/hotspot/test/serviceability/jdwp/JdwpClassLoaderCmd.java new file mode 100644 index 00000000000..14ffb615f73 --- /dev/null +++ b/hotspot/test/serviceability/jdwp/JdwpClassLoaderCmd.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * The JDWP CLASSLOADER command + */ +public class JdwpClassLoaderCmd extends JdwpCmd { + + public JdwpClassLoaderCmd(long modId) { + super(2, 18, JdwpClassLoaderReply.class, refLen()); + putRefId(modId); + } + +} diff --git a/hotspot/test/serviceability/jdwp/JdwpClassLoaderReply.java b/hotspot/test/serviceability/jdwp/JdwpClassLoaderReply.java new file mode 100644 index 00000000000..bb1cbcd6ace --- /dev/null +++ b/hotspot/test/serviceability/jdwp/JdwpClassLoaderReply.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * The JDWP CLASSLOADER reply + */ +public class JdwpClassLoaderReply extends JdwpReply { + + private long refId; + + protected void parseData(DataInputStream ds) throws IOException { + refId = readRefId(ds); + } + + public long getClassLoaderId() { + return refId; + } + +} diff --git a/hotspot/test/serviceability/jdwp/JdwpCmd.java b/hotspot/test/serviceability/jdwp/JdwpCmd.java new file mode 100644 index 00000000000..fe7f28707a8 --- /dev/null +++ b/hotspot/test/serviceability/jdwp/JdwpCmd.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.IOException; +import java.nio.ByteBuffer; + +/** + * Generic JDWP command + * @param the corresponding JDWP reply class, to construct a reply object + */ +public abstract class JdwpCmd { + + private ByteBuffer data; + private static int id = 1; + private final byte FLAGS = 0; + private T reply; + private final int dataLen; + private final int HEADER_LEN = 11; + + /** + * JDWWp command + * @param cmd command code + * @param cmdSet command set + * @param replyClz command reply class + * @param dataLen length of additional data for the command + */ + JdwpCmd(int cmd, int cmdSet, Class replyClz, int dataLen) { + this.dataLen = dataLen; + data = ByteBuffer.allocate(HEADER_LEN + dataLen); + data.putInt(HEADER_LEN + dataLen); + data.putInt(id++); + data.put(FLAGS); + data.put((byte) cmdSet); + data.put((byte) cmd); + if (replyClz != null) { + try { + reply = replyClz.newInstance(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } + + JdwpCmd(int cmd, int cmdSet, Class replyClz) { + this(cmd, cmdSet, replyClz, 0); + } + + int getDataLength() { + return dataLen; + } + + public final T send(JdwpChannel channel) throws IOException { + System.err.println("Sending command: " + this); + channel.write(data.array(), HEADER_LEN + getDataLength()); + if (reply != null) { + reply.initFromStream(channel.getInputStream()); + } + return (T) reply; + } + + protected void putRefId(long refId) { + data.putLong(refId); + } + + protected void putInt(int val) { + data.putInt(val); + } + + protected static int refLen() { + return 8; + } + +} diff --git a/hotspot/test/serviceability/jdwp/JdwpExitCmd.java b/hotspot/test/serviceability/jdwp/JdwpExitCmd.java new file mode 100644 index 00000000000..e63031a57ca --- /dev/null +++ b/hotspot/test/serviceability/jdwp/JdwpExitCmd.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * The JDWP EXIT command to terminate the debuggee + */ +public class JdwpExitCmd extends JdwpCmd { + + public JdwpExitCmd(int exitCode) { + super(10, 1, null, 4); + putInt(exitCode); + } + +} diff --git a/hotspot/test/serviceability/jdwp/JdwpModNameCmd.java b/hotspot/test/serviceability/jdwp/JdwpModNameCmd.java new file mode 100644 index 00000000000..2fe4b12aec2 --- /dev/null +++ b/hotspot/test/serviceability/jdwp/JdwpModNameCmd.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * The JDWP NAME command + */ +public class JdwpModNameCmd extends JdwpCmd { + + public JdwpModNameCmd(long modId) { + super(1, 18, JdwpModNameReply.class, refLen()); + putRefId(modId); + } + +} diff --git a/hotspot/test/serviceability/jdwp/JdwpModNameReply.java b/hotspot/test/serviceability/jdwp/JdwpModNameReply.java new file mode 100644 index 00000000000..c6db98e6614 --- /dev/null +++ b/hotspot/test/serviceability/jdwp/JdwpModNameReply.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * JDWP reply to the NAME command + */ +public class JdwpModNameReply extends JdwpReply { + + private byte[] name; + + protected void parseData(DataInputStream ds) throws IOException { + name = readJdwpString(ds); + } + + public String getModuleName() { + return name == null ? null : new String(name); + } + +} diff --git a/hotspot/test/serviceability/jdwp/JdwpReply.java b/hotspot/test/serviceability/jdwp/JdwpReply.java new file mode 100644 index 00000000000..a3f95a5d509 --- /dev/null +++ b/hotspot/test/serviceability/jdwp/JdwpReply.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * Generic JDWP reply + */ +public abstract class JdwpReply { + + protected final static int HEADER_LEN = 11; + private byte[] errCode = new byte[2]; + private byte[] data; + + public final void initFromStream(InputStream is) throws IOException { + DataInputStream ds = new DataInputStream(is); + + int length = ds.readInt(); + int id = ds.readInt(); + byte flags = (byte) ds.read(); + + ds.read(errCode, 0, 2); + + int dataLength = length - HEADER_LEN; + if (dataLength > 0) { + data = new byte[dataLength]; + ds.read(data, 0, dataLength); + parseData(new DataInputStream(new ByteArrayInputStream(data))); + } + } + + protected void parseData(DataInputStream ds) throws IOException { + } + + protected byte[] readJdwpString(DataInputStream ds) throws IOException { + byte[] str = null; + int len = ds.readInt(); + if (len > 0) { + str = new byte[len]; + ds.read(str, 0, len); + } + return str; + } + + protected long readRefId(DataInputStream ds) throws IOException { + return ds.readLong(); + } + + public int getErrorCode() { + return (((errCode[0] & 0xFF) << 8) | (errCode[1] & 0xFF)); + } +} diff --git a/hotspot/test/serviceability/jdwp/StreamHandler.java b/hotspot/test/serviceability/jdwp/StreamHandler.java new file mode 100644 index 00000000000..257f66a66a9 --- /dev/null +++ b/hotspot/test/serviceability/jdwp/StreamHandler.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * Handles the process output (either stdin or stdout) + * passing the lines to a listener + */ +public class StreamHandler implements Runnable { + + public interface Listener { + /** + * Called when a line has been read from the process output stream + * @param handler this StreamHandler + * @param s the line + */ + void onStringRead(StreamHandler handler, String s); + } + + private final ExecutorService executor; + private final InputStream is; + private final Listener listener; + + /** + * @param is input stream to read from + * @param listener listener to pass the read lines to + * @throws IOException + */ + public StreamHandler(InputStream is, Listener listener) throws IOException { + this.is = is; + this.listener = listener; + executor = Executors.newSingleThreadExecutor(); + } + + /** + * Starts asynchronous reading + */ + public void start() { + executor.submit(this); + } + + @Override + public void run() { + try { + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + String line; + while ((line = br.readLine()) != null) { + listener.onStringRead(this, line); + } + } catch (Exception x) { + throw new RuntimeException(x); + } + } + +} From 66706edf1561310326bb5f61837d179e25e351cb Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Tue, 30 Aug 2016 23:48:16 -0400 Subject: [PATCH 027/110] 8156500: Move Reference pending list into VM to prevent deadlocks Move reference pending list and locking into VM Co-authored-by: Per Liden Reviewed-by: coleenp, dholmes, dcubed, mchung, plevart --- hotspot/make/symbols/symbols-unix | 3 + .../sun/jvm/hotspot/runtime/Threads.java | 4 +- .../sun/jvm/hotspot/utilities/soql/sa.js | 1 - hotspot/src/share/vm/ci/ciReplay.cpp | 5 +- .../src/share/vm/classfile/javaClasses.cpp | 41 ---- .../src/share/vm/classfile/javaClasses.hpp | 13 - .../src/share/vm/compiler/compileBroker.cpp | 10 - .../vm/gc/cms/concurrentMarkSweepThread.cpp | 18 -- .../src/share/vm/gc/cms/vmCMSOperations.cpp | 28 +-- .../src/share/vm/gc/cms/vmCMSOperations.hpp | 8 - .../share/vm/gc/g1/concurrentMarkThread.cpp | 4 +- .../src/share/vm/gc/g1/g1CollectedHeap.hpp | 6 - .../src/share/vm/gc/g1/vm_operations_g1.cpp | 21 +- .../src/share/vm/gc/g1/vm_operations_g1.hpp | 18 +- .../src/share/vm/gc/shared/collectedHeap.hpp | 6 - .../share/vm/gc/shared/genCollectedHeap.hpp | 4 - .../gc/shared/referencePendingListLocker.cpp | 222 ------------------ .../gc/shared/referencePendingListLocker.hpp | 95 -------- .../share/vm/gc/shared/referenceProcessor.cpp | 53 +---- .../share/vm/gc/shared/referenceProcessor.hpp | 9 +- .../src/share/vm/gc/shared/vmGCOperations.cpp | 16 +- .../src/share/vm/gc/shared/vmGCOperations.hpp | 8 - hotspot/src/share/vm/memory/universe.cpp | 43 +++- hotspot/src/share/vm/memory/universe.hpp | 14 ++ hotspot/src/share/vm/oops/method.cpp | 7 - hotspot/src/share/vm/prims/jvm.cpp | 29 +++ hotspot/src/share/vm/prims/jvm.h | 12 + hotspot/src/share/vm/runtime/thread.cpp | 9 - hotspot/src/share/vm/runtime/vmStructs.cpp | 2 - 29 files changed, 133 insertions(+), 576 deletions(-) delete mode 100644 hotspot/src/share/vm/gc/shared/referencePendingListLocker.cpp delete mode 100644 hotspot/src/share/vm/gc/shared/referencePendingListLocker.hpp diff --git a/hotspot/make/symbols/symbols-unix b/hotspot/make/symbols/symbols-unix index 406d6f99db3..04dd4aeff53 100644 --- a/hotspot/make/symbols/symbols-unix +++ b/hotspot/make/symbols/symbols-unix @@ -67,6 +67,7 @@ JVM_FindSignal JVM_FreeMemory JVM_GC JVM_GetAllThreads +JVM_GetAndClearReferencePendingList JVM_GetArrayElement JVM_GetArrayLength JVM_GetCallerClass @@ -130,6 +131,7 @@ JVM_GetSystemPackages JVM_GetTemporaryDirectory JVM_GetVmArguments JVM_Halt +JVM_HasReferencePendingList JVM_HoldsLock JVM_IHashCode JVM_InitProperties @@ -179,6 +181,7 @@ JVM_SuspendThread JVM_ToStackTraceElement JVM_TotalMemory JVM_UnloadLibrary +JVM_WaitForReferencePendingList JVM_Yield # Module related API's diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java index cfcab6b8413..1e471412d58 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java @@ -129,8 +129,6 @@ public class Threads { virtualConstructor.addMapping("CompilerThread", CompilerThread.class); virtualConstructor.addMapping("CodeCacheSweeperThread", CodeCacheSweeperThread.class); } - // for now, use JavaThread itself. fix it later with appropriate class if needed - virtualConstructor.addMapping("ReferencePendingListLockerThread", JavaThread.class); virtualConstructor.addMapping("JvmtiAgentThread", JvmtiAgentThread.class); virtualConstructor.addMapping("ServiceThread", ServiceThread.class); } @@ -172,7 +170,7 @@ public class Threads { return thread; } catch (Exception e) { throw new RuntimeException("Unable to deduce type of thread from address " + threadAddr + - " (expected type JavaThread, CompilerThread, ServiceThread, JvmtiAgentThread, ReferencePendingListLockerThread, or CodeCacheSweeperThread)", e); + " (expected type JavaThread, CompilerThread, ServiceThread, JvmtiAgentThread or CodeCacheSweeperThread)", e); } } diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/sa.js b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/sa.js index 7a7f4501493..2bd5c556d0d 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/sa.js +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/sa.js @@ -837,7 +837,6 @@ vmType2Class["InterpreterCodelet"] = sapkg.interpreter.InterpreterCodelet; vmType2Class["JavaThread"] = sapkg.runtime.JavaThread; vmType2Class["CompilerThread"] = sapkg.runtime.CompilerThread; vmType2Class["CodeCacheSweeperThread"] = sapkg.runtime.CodeCacheSweeperThread; -vmType2Class["ReferencePendingListLockerThread"] = sapkg.runtime.JavaThread; vmType2Class["DebuggerThread"] = sapkg.runtime.DebuggerThread; // gc diff --git a/hotspot/src/share/vm/ci/ciReplay.cpp b/hotspot/src/share/vm/ci/ciReplay.cpp index ec788919c32..50a1dd37c3b 100644 --- a/hotspot/src/share/vm/ci/ciReplay.cpp +++ b/hotspot/src/share/vm/ci/ciReplay.cpp @@ -29,7 +29,6 @@ #include "ci/ciKlass.hpp" #include "ci/ciUtilities.hpp" #include "compiler/compileBroker.hpp" -#include "gc/shared/referencePendingListLocker.hpp" #include "memory/allocation.inline.hpp" #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" @@ -577,9 +576,7 @@ class CompileReplay : public StackObj { Method* method = parse_method(CHECK); if (had_error()) return; /* just copied from Method, to build interpret data*/ - if (ReferencePendingListLocker::is_locked_by_self()) { - return; - } + // To be properly initialized, some profiling in the MDO needs the // method to be rewritten (number of arguments at a call for // instance) diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp index 6df74ae4244..b3a6564d92e 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.cpp +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp @@ -3015,41 +3015,6 @@ void java_lang_boxing_object::print(BasicType type, jvalue* value, outputStream* } } - -// Support for java_lang_ref_Reference -HeapWord *java_lang_ref_Reference::pending_list_lock_addr() { - InstanceKlass* ik = SystemDictionary::Reference_klass(); - address addr = ik->static_field_addr(static_lock_offset); - return (HeapWord*) addr; -} - -oop java_lang_ref_Reference::pending_list_lock() { - InstanceKlass* ik = SystemDictionary::Reference_klass(); - address addr = ik->static_field_addr(static_lock_offset); - if (UseCompressedOops) { - return oopDesc::load_decode_heap_oop((narrowOop *)addr); - } else { - return oopDesc::load_decode_heap_oop((oop*)addr); - } -} - -HeapWord *java_lang_ref_Reference::pending_list_addr() { - InstanceKlass* ik = SystemDictionary::Reference_klass(); - address addr = ik->static_field_addr(static_pending_offset); - // XXX This might not be HeapWord aligned, almost rather be char *. - return (HeapWord*)addr; -} - -oop java_lang_ref_Reference::pending_list() { - char *addr = (char *)pending_list_addr(); - if (UseCompressedOops) { - return oopDesc::load_decode_heap_oop((narrowOop *)addr); - } else { - return oopDesc::load_decode_heap_oop((oop*)addr); - } -} - - // Support for java_lang_ref_SoftReference jlong java_lang_ref_SoftReference::timestamp(oop ref) { @@ -3616,8 +3581,6 @@ int java_lang_ref_Reference::referent_offset; int java_lang_ref_Reference::queue_offset; int java_lang_ref_Reference::next_offset; int java_lang_ref_Reference::discovered_offset; -int java_lang_ref_Reference::static_lock_offset; -int java_lang_ref_Reference::static_pending_offset; int java_lang_ref_Reference::number_of_fake_oop_fields; int java_lang_ref_SoftReference::timestamp_offset; int java_lang_ref_SoftReference::static_clock_offset; @@ -3772,8 +3735,6 @@ void JavaClasses::compute_hard_coded_offsets() { java_lang_ref_Reference::queue_offset = java_lang_ref_Reference::hc_queue_offset * x + header; java_lang_ref_Reference::next_offset = java_lang_ref_Reference::hc_next_offset * x + header; java_lang_ref_Reference::discovered_offset = java_lang_ref_Reference::hc_discovered_offset * x + header; - java_lang_ref_Reference::static_lock_offset = java_lang_ref_Reference::hc_static_lock_offset * x; - java_lang_ref_Reference::static_pending_offset = java_lang_ref_Reference::hc_static_pending_offset * x; // Artificial fields for java_lang_ref_Reference // The first field is for the discovered field added in 1.4 java_lang_ref_Reference::number_of_fake_oop_fields = 1; @@ -4006,8 +3967,6 @@ void JavaClasses::check_offsets() { CHECK_OFFSET("java/lang/ref/Reference", java_lang_ref_Reference, next, "Ljava/lang/ref/Reference;"); // Fake field //CHECK_OFFSET("java/lang/ref/Reference", java_lang_ref_Reference, discovered, "Ljava/lang/ref/Reference;"); - CHECK_STATIC_OFFSET("java/lang/ref/Reference", java_lang_ref_Reference, lock, "Ljava/lang/ref/Reference$Lock;"); - CHECK_STATIC_OFFSET("java/lang/ref/Reference", java_lang_ref_Reference, pending, "Ljava/lang/ref/Reference;"); // java.lang.ref.SoftReference diff --git a/hotspot/src/share/vm/classfile/javaClasses.hpp b/hotspot/src/share/vm/classfile/javaClasses.hpp index 7d101b88ea6..307cd65d5f8 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.hpp +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp @@ -886,17 +886,11 @@ class java_lang_ref_Reference: AllStatic { hc_next_offset = 2, hc_discovered_offset = 3 // Is not last, see SoftRefs. }; - enum { - hc_static_lock_offset = 0, - hc_static_pending_offset = 1 - }; static int referent_offset; static int queue_offset; static int next_offset; static int discovered_offset; - static int static_lock_offset; - static int static_pending_offset; static int number_of_fake_oop_fields; // Accessors @@ -912,13 +906,6 @@ class java_lang_ref_Reference: AllStatic { static inline void set_discovered(oop ref, oop value); static inline void set_discovered_raw(oop ref, oop value); static inline HeapWord* discovered_addr(oop ref); - - // Accessors for statics - static oop pending_list_lock(); - static oop pending_list(); - - static HeapWord* pending_list_lock_addr(); - static HeapWord* pending_list_addr(); }; diff --git a/hotspot/src/share/vm/compiler/compileBroker.cpp b/hotspot/src/share/vm/compiler/compileBroker.cpp index b3bc80c6a51..62433c1c088 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.cpp +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp @@ -32,7 +32,6 @@ #include "compiler/compileLog.hpp" #include "compiler/compilerOracle.hpp" #include "compiler/directivesParser.hpp" -#include "gc/shared/referencePendingListLocker.hpp" #include "interpreter/linkResolver.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" @@ -893,15 +892,6 @@ void CompileBroker::compile_method_base(const methodHandle& method, return; } - // If the requesting thread is holding the pending list lock - // then we just return. We can't risk blocking while holding - // the pending list lock or a 3-way deadlock may occur - // between the reference handler thread, a GC (instigated - // by a compiler thread), and compiled method registration. - if (ReferencePendingListLocker::is_locked_by_self()) { - return; - } - if (TieredCompilation) { // Tiered policy requires MethodCounters to exist before adding a method to // the queue. Create if we don't have them yet. diff --git a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp index 3ea77838462..43a32e913e8 100644 --- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp +++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp @@ -28,7 +28,6 @@ #include "gc/cms/concurrentMarkSweepThread.hpp" #include "gc/shared/gcId.hpp" #include "gc/shared/genCollectedHeap.hpp" -#include "gc/shared/referencePendingListLocker.hpp" #include "oops/oop.inline.hpp" #include "runtime/init.hpp" #include "runtime/interfaceSupport.hpp" @@ -77,23 +76,6 @@ void ConcurrentMarkSweepThread::run_service() { log_warning(gc)("Couldn't bind CMS thread to processor " UINTX_FORMAT, CPUForCMSThread); } - { - MutexLockerEx x(CGC_lock, true); - set_CMS_flag(CMS_cms_wants_token); - assert(is_init_completed() && Universe::is_fully_initialized(), "ConcurrentGCThread::run() should have waited for this."); - - // Wait until the surrogate locker thread that will do - // pending list locking on our behalf has been created. - // We cannot start the SLT thread ourselves since we need - // to be a JavaThread to do so. - CMSLoopCountWarn loopY("CMS::run", "waiting for SLT installation", 2); - while (!ReferencePendingListLocker::is_initialized() && !should_terminate()) { - CGC_lock->wait(true, 200); - loopY.tick(); - } - clear_CMS_flag(CMS_cms_wants_token); - } - while (!should_terminate()) { sleepBeforeNextCycle(); if (should_terminate()) break; diff --git a/hotspot/src/share/vm/gc/cms/vmCMSOperations.cpp b/hotspot/src/share/vm/gc/cms/vmCMSOperations.cpp index 73f205485db..3aa8a0ccd6b 100644 --- a/hotspot/src/share/vm/gc/cms/vmCMSOperations.cpp +++ b/hotspot/src/share/vm/gc/cms/vmCMSOperations.cpp @@ -37,14 +37,6 @@ ////////////////////////////////////////////////////////// // Methods in abstract class VM_CMS_Operation ////////////////////////////////////////////////////////// -void VM_CMS_Operation::acquire_pending_list_lock() { - _pending_list_locker.lock(); -} - -void VM_CMS_Operation::release_and_notify_pending_list_lock() { - _pending_list_locker.unlock(); -} - void VM_CMS_Operation::verify_before_gc() { if (VerifyBeforeGC && GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) { @@ -85,17 +77,10 @@ bool VM_CMS_Operation::doit_prologue() { assert(!ConcurrentMarkSweepThread::cms_thread_has_cms_token(), "Possible deadlock"); - if (needs_pending_list_lock()) { - acquire_pending_list_lock(); - } - // Get the Heap_lock after the pending_list_lock. Heap_lock->lock(); if (lost_race()) { assert(_prologue_succeeded == false, "Initialized in c'tor"); Heap_lock->unlock(); - if (needs_pending_list_lock()) { - release_and_notify_pending_list_lock(); - } } else { _prologue_succeeded = true; } @@ -108,11 +93,10 @@ void VM_CMS_Operation::doit_epilogue() { assert(!ConcurrentMarkSweepThread::cms_thread_has_cms_token(), "Possible deadlock"); - // Release the Heap_lock first. - Heap_lock->unlock(); - if (needs_pending_list_lock()) { - release_and_notify_pending_list_lock(); + if (Universe::has_reference_pending_list()) { + Heap_lock->notify_all(); } + Heap_lock->unlock(); } ////////////////////////////////////////////////////////// @@ -230,9 +214,11 @@ void VM_GenCollectFullConcurrent::doit_epilogue() { Thread* thr = Thread::current(); assert(thr->is_Java_thread(), "just checking"); JavaThread* jt = (JavaThread*)thr; - // Release the Heap_lock first. + + if (Universe::has_reference_pending_list()) { + Heap_lock->notify_all(); + } Heap_lock->unlock(); - release_and_notify_pending_list_lock(); // It is fine to test whether completed collections has // exceeded our request count without locking because diff --git a/hotspot/src/share/vm/gc/cms/vmCMSOperations.hpp b/hotspot/src/share/vm/gc/cms/vmCMSOperations.hpp index e6fe2c2ac25..fd39fe479d9 100644 --- a/hotspot/src/share/vm/gc/cms/vmCMSOperations.hpp +++ b/hotspot/src/share/vm/gc/cms/vmCMSOperations.hpp @@ -28,7 +28,6 @@ #include "gc/cms/concurrentMarkSweepGeneration.hpp" #include "gc/shared/gcCause.hpp" #include "gc/shared/gcId.hpp" -#include "gc/shared/referencePendingListLocker.hpp" #include "gc/shared/vmGCOperations.hpp" #include "runtime/vm_operations.hpp" @@ -52,9 +51,6 @@ class CMSCollector; class VM_CMS_Operation: public VM_Operation { - private: - ReferencePendingListLocker _pending_list_locker; - protected: CMSCollector* _collector; // associated collector bool _prologue_succeeded; // whether doit_prologue succeeded @@ -62,10 +58,6 @@ class VM_CMS_Operation: public VM_Operation { bool lost_race() const; - // java.lang.ref.Reference support - void acquire_pending_list_lock(); - void release_and_notify_pending_list_lock(); - public: VM_CMS_Operation(CMSCollector* collector): _collector(collector), diff --git a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp index 469412245bf..9c94863a43b 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp +++ b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp @@ -175,7 +175,7 @@ void ConcurrentMarkThread::run_service() { TimeHelper::counter_to_millis(mark_end - mark_start)); CMCheckpointRootsFinalClosure final_cl(_cm); - VM_CGC_Operation op(&final_cl, "Pause Remark", true /* needs_pll */); + VM_CGC_Operation op(&final_cl, "Pause Remark"); VMThread::execute(&op); } if (cm()->restart_for_overflow()) { @@ -199,7 +199,7 @@ void ConcurrentMarkThread::run_service() { delay_to_keep_mmu(g1_policy, false /* cleanup */); CMCleanUp cl_cl(_cm); - VM_CGC_Operation op(&cl_cl, "Pause Cleanup", false /* needs_pll */); + VM_CGC_Operation op(&cl_cl, "Pause Cleanup"); VMThread::execute(&op); } else { // We don't want to update the marking status if a GC pause diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp index b47778324b4..4aadccbe916 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp @@ -1273,12 +1273,6 @@ public: return true; } - // The reference pending list lock is acquired from from the - // ConcurrentMarkThread. - virtual bool needs_reference_pending_list_locker_thread() const { - return true; - } - inline bool is_in_young(const oop obj); virtual bool is_scavengable(const void* addr); diff --git a/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp b/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp index 333499a0a97..148fe80e3ef 100644 --- a/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp +++ b/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp @@ -204,14 +204,6 @@ void VM_G1IncCollectionPause::doit_epilogue() { } } -void VM_CGC_Operation::acquire_pending_list_lock() { - _pending_list_locker.lock(); -} - -void VM_CGC_Operation::release_and_notify_pending_list_lock() { - _pending_list_locker.unlock(); -} - void VM_CGC_Operation::doit() { GCIdMark gc_id_mark(_gc_id); GCTraceCPUTime tcpu; @@ -222,20 +214,13 @@ void VM_CGC_Operation::doit() { } bool VM_CGC_Operation::doit_prologue() { - // Note the relative order of the locks must match that in - // VM_GC_Operation::doit_prologue() or deadlocks can occur - if (_needs_pending_list_lock) { - acquire_pending_list_lock(); - } Heap_lock->lock(); return true; } void VM_CGC_Operation::doit_epilogue() { - // Note the relative order of the unlocks must match that in - // VM_GC_Operation::doit_epilogue() - Heap_lock->unlock(); - if (_needs_pending_list_lock) { - release_and_notify_pending_list_lock(); + if (Universe::has_reference_pending_list()) { + Heap_lock->notify_all(); } + Heap_lock->unlock(); } diff --git a/hotspot/src/share/vm/gc/g1/vm_operations_g1.hpp b/hotspot/src/share/vm/gc/g1/vm_operations_g1.hpp index 5aab7096586..94844f72881 100644 --- a/hotspot/src/share/vm/gc/g1/vm_operations_g1.hpp +++ b/hotspot/src/share/vm/gc/g1/vm_operations_g1.hpp @@ -27,7 +27,6 @@ #include "gc/g1/g1AllocationContext.hpp" #include "gc/shared/gcId.hpp" -#include "gc/shared/referencePendingListLocker.hpp" #include "gc/shared/vmGCOperations.hpp" // VM_operations for the G1 collector. @@ -103,20 +102,13 @@ public: // Concurrent GC stop-the-world operations such as remark and cleanup; // consider sharing these with CMS's counterparts. class VM_CGC_Operation: public VM_Operation { - VoidClosure* _cl; - const char* _printGCMessage; - bool _needs_pending_list_lock; - ReferencePendingListLocker _pending_list_locker; - uint _gc_id; - -protected: - // java.lang.ref.Reference support - void acquire_pending_list_lock(); - void release_and_notify_pending_list_lock(); + VoidClosure* _cl; + const char* _printGCMessage; + uint _gc_id; public: - VM_CGC_Operation(VoidClosure* cl, const char *printGCMsg, bool needs_pending_list_lock) - : _cl(cl), _printGCMessage(printGCMsg), _needs_pending_list_lock(needs_pending_list_lock), _gc_id(GCId::current()) {} + VM_CGC_Operation(VoidClosure* cl, const char *printGCMsg) + : _cl(cl), _printGCMessage(printGCMsg), _gc_id(GCId::current()) {} virtual VMOp_Type type() const { return VMOp_CGC_Operation; } virtual void doit(); virtual bool doit_prologue(); diff --git a/hotspot/src/share/vm/gc/shared/collectedHeap.hpp b/hotspot/src/share/vm/gc/shared/collectedHeap.hpp index 303252369e4..af26fc892e9 100644 --- a/hotspot/src/share/vm/gc/shared/collectedHeap.hpp +++ b/hotspot/src/share/vm/gc/shared/collectedHeap.hpp @@ -441,12 +441,6 @@ class CollectedHeap : public CHeapObj { // remembered set. virtual void flush_deferred_store_barrier(JavaThread* thread); - // Should return true if the reference pending list lock is - // acquired from non-Java threads, such as a concurrent GC thread. - virtual bool needs_reference_pending_list_locker_thread() const { - return false; - } - // Perform a collection of the heap; intended for use in implementing // "System.gc". This probably implies as full a collection as the // "CollectedHeap" supports. diff --git a/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp b/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp index f4a7e252942..9a469d14f7d 100644 --- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp +++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp @@ -281,10 +281,6 @@ public: return UseConcMarkSweepGC; } - virtual bool needs_reference_pending_list_locker_thread() const { - return UseConcMarkSweepGC; - } - // We don't need barriers for stores to objects in the // young gen and, a fortiori, for initializing stores to // objects therein. This applies to DefNew+Tenured and ParNew+CMS diff --git a/hotspot/src/share/vm/gc/shared/referencePendingListLocker.cpp b/hotspot/src/share/vm/gc/shared/referencePendingListLocker.cpp deleted file mode 100644 index 0c35d65aeee..00000000000 --- a/hotspot/src/share/vm/gc/shared/referencePendingListLocker.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (c) 2016, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "classfile/javaClasses.hpp" -#include "classfile/systemDictionary.hpp" -#include "gc/shared/collectedHeap.hpp" -#include "gc/shared/referencePendingListLocker.hpp" -#include "memory/universe.hpp" -#include "runtime/javaCalls.hpp" -#include "utilities/preserveException.hpp" - -ReferencePendingListLockerThread::ReferencePendingListLockerThread() : - JavaThread(&start), - _monitor(Monitor::nonleaf, "ReferencePendingListLocker", false, Monitor::_safepoint_check_sometimes), - _message(NONE) {} - -ReferencePendingListLockerThread* ReferencePendingListLockerThread::create(TRAPS) { - // Create Java thread objects - instanceKlassHandle thread_klass = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), true, CHECK_NULL); - instanceHandle thread_object = thread_klass->allocate_instance_handle(CHECK_NULL); - Handle thread_name = java_lang_String::create_from_str("Reference Pending List Locker", CHECK_NULL); - Handle thread_group = Universe::system_thread_group(); - JavaValue result(T_VOID); - JavaCalls::call_special(&result, - thread_object, - thread_klass, - vmSymbols::object_initializer_name(), - vmSymbols::threadgroup_string_void_signature(), - thread_group, - thread_name, - CHECK_NULL); - - { - MutexLocker ml(Threads_lock); - - // Allocate thread - ReferencePendingListLockerThread* thread = new ReferencePendingListLockerThread(); - if (thread == NULL || thread->osthread() == NULL) { - vm_exit_during_initialization("java.lang.OutOfMemoryError", - os::native_thread_creation_failed_msg()); - } - - // Initialize thread - java_lang_Thread::set_thread(thread_object(), thread); - java_lang_Thread::set_priority(thread_object(), NearMaxPriority); - java_lang_Thread::set_daemon(thread_object()); - thread->set_threadObj(thread_object()); - - // Start thread - Threads::add(thread); - Thread::start(thread); - - return thread; - } -} - -void ReferencePendingListLockerThread::start(JavaThread* thread, TRAPS) { - ReferencePendingListLockerThread* locker_thread = static_cast(thread); - locker_thread->receive_and_handle_messages(); -} - -bool ReferencePendingListLockerThread::is_hidden_from_external_view() const { - return true; -} - -void ReferencePendingListLockerThread::send_message(Message message) { - assert(message != NONE, "Should not be none"); - MonitorLockerEx ml(&_monitor, Monitor::_no_safepoint_check_flag); - - // Wait for completion of current message - while (_message != NONE) { - ml.wait(Monitor::_no_safepoint_check_flag); - } - - // Send new message - _message = message; - ml.notify_all(); - - // Wait for completion of new message - while (_message != NONE) { - ml.wait(Monitor::_no_safepoint_check_flag); - } -} - -void ReferencePendingListLockerThread::receive_and_handle_messages() { - ReferencePendingListLocker pending_list_locker; - MonitorLockerEx ml(&_monitor); - - // Main loop, never terminates - for (;;) { - // Wait for message - while (_message == NONE) { - ml.wait(); - } - - // Handle message - if (_message == LOCK) { - pending_list_locker.lock(); - } else if (_message == UNLOCK) { - pending_list_locker.unlock(); - } else { - ShouldNotReachHere(); - } - - // Clear message - _message = NONE; - ml.notify_all(); - } -} - -void ReferencePendingListLockerThread::lock() { - send_message(LOCK); -} - -void ReferencePendingListLockerThread::unlock() { - send_message(UNLOCK); -} - -bool ReferencePendingListLocker::_is_initialized = false; -ReferencePendingListLockerThread* ReferencePendingListLocker::_locker_thread = NULL; - -void ReferencePendingListLocker::initialize(bool needs_locker_thread, TRAPS) { - if (needs_locker_thread) { - _locker_thread = ReferencePendingListLockerThread::create(CHECK); - } - - _is_initialized = true; -} - -bool ReferencePendingListLocker::is_initialized() { - return _is_initialized; -} - -bool ReferencePendingListLocker::is_locked_by_self() { - oop pending_list_lock = java_lang_ref_Reference::pending_list_lock(); - if (pending_list_lock == NULL) { - return false; - } - - JavaThread* thread = JavaThread::current(); - Handle handle(thread, pending_list_lock); - return ObjectSynchronizer::current_thread_holds_lock(thread, handle); -} - -void ReferencePendingListLocker::lock() { - assert(!Heap_lock->owned_by_self(), "Heap_lock must not be owned by requesting thread"); - - if (Thread::current()->is_Java_thread()) { - assert(java_lang_ref_Reference::pending_list_lock() != NULL, "Not initialized"); - - // We may enter this with a pending exception - PRESERVE_EXCEPTION_MARK; - - HandleMark hm; - Handle handle(THREAD, java_lang_ref_Reference::pending_list_lock()); - - // Lock - ObjectSynchronizer::fast_enter(handle, &_basic_lock, false, THREAD); - - assert(is_locked_by_self(), "Locking failed"); - - if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; - } - } else { - // Delegate operation to locker thread - assert(_locker_thread != NULL, "Locker thread not created"); - _locker_thread->lock(); - } -} - -void ReferencePendingListLocker::unlock() { - if (Thread::current()->is_Java_thread()) { - assert(java_lang_ref_Reference::pending_list_lock() != NULL, "Not initialized"); - - // We may enter this with a pending exception - PRESERVE_EXCEPTION_MARK; - - HandleMark hm; - Handle handle(THREAD, java_lang_ref_Reference::pending_list_lock()); - - assert(is_locked_by_self(), "Should be locked by self"); - - // Notify waiters if the pending list is non-empty - if (java_lang_ref_Reference::pending_list() != NULL) { - ObjectSynchronizer::notifyall(handle, THREAD); - } - - // Unlock - ObjectSynchronizer::fast_exit(handle(), &_basic_lock, THREAD); - - if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; - } - } else { - // Delegate operation to locker thread - assert(_locker_thread != NULL, "Locker thread not created"); - _locker_thread->unlock(); - } -} diff --git a/hotspot/src/share/vm/gc/shared/referencePendingListLocker.hpp b/hotspot/src/share/vm/gc/shared/referencePendingListLocker.hpp deleted file mode 100644 index 62cf7eed995..00000000000 --- a/hotspot/src/share/vm/gc/shared/referencePendingListLocker.hpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2016, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef SHARE_VM_GC_SHARED_REFERENCEPENDINGLISTLOCKER_HPP -#define SHARE_VM_GC_SHARED_REFERENCEPENDINGLISTLOCKER_HPP - -#include "memory/allocation.hpp" -#include "runtime/basicLock.hpp" -#include "runtime/mutex.hpp" -#include "runtime/thread.hpp" -#include "utilities/exceptions.hpp" - -// -// The ReferencePendingListLockerThread locks and unlocks the reference -// pending list lock on behalf a non-Java thread, typically a concurrent -// GC thread. This interface should not be directly accessed. All uses -// should instead go through the ReferencePendingListLocker, which calls -// this thread if needed. -// -class ReferencePendingListLockerThread : public JavaThread { -private: - enum Message { - NONE, - LOCK, - UNLOCK - }; - - Monitor _monitor; - Message _message; - - ReferencePendingListLockerThread(); - - static void start(JavaThread* thread, TRAPS); - - void send_message(Message message); - void receive_and_handle_messages(); - -public: - static ReferencePendingListLockerThread* create(TRAPS); - - virtual bool is_hidden_from_external_view() const; - - void lock(); - void unlock(); -}; - -// -// The ReferencePendingListLocker is the main interface for locking and -// unlocking the reference pending list lock, which needs to be held by -// the GC when adding references to the pending list. Since this is a -// Java-level monitor it can only be locked/unlocked by a Java thread. -// For this reason there is an option to spawn a helper thread, the -// ReferencePendingListLockerThread, during initialization. If a helper -// thread is spawned all lock operations from non-Java threads will be -// delegated to the helper thread. The helper thread is typically needed -// by concurrent GCs. -// -class ReferencePendingListLocker VALUE_OBJ_CLASS_SPEC { -private: - static bool _is_initialized; - static ReferencePendingListLockerThread* _locker_thread; - BasicLock _basic_lock; - -public: - static void initialize(bool needs_locker_thread, TRAPS); - static bool is_initialized(); - - static bool is_locked_by_self(); - - void lock(); - void unlock(); -}; - -#endif // SHARE_VM_GC_SHARED_REFERENCEPENDINGLISTLOCKER_HPP diff --git a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp index 2200e7620a4..38df96ddd4c 100644 --- a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp +++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp @@ -289,39 +289,16 @@ void ReferenceProcessor::process_phaseJNI(BoolObjectClosure* is_alive, complete_gc->do_void(); } - -template -bool enqueue_discovered_ref_helper(ReferenceProcessor* ref, - AbstractRefProcTaskExecutor* task_executor) { - - // Remember old value of pending references list - T* pending_list_addr = (T*)java_lang_ref_Reference::pending_list_addr(); - T old_pending_list_value = *pending_list_addr; - +void ReferenceProcessor::enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor) { // Enqueue references that are not made active again, and // clear the decks for the next collection (cycle). - ref->enqueue_discovered_reflists((HeapWord*)pending_list_addr, task_executor); - // Do the post-barrier on pending_list_addr missed in - // enqueue_discovered_reflist. - oopDesc::bs()->write_ref_field(pending_list_addr, oopDesc::load_decode_heap_oop(pending_list_addr)); + enqueue_discovered_reflists(task_executor); // Stop treating discovered references specially. - ref->disable_discovery(); - - // Return true if new pending references were added - return old_pending_list_value != *pending_list_addr; + disable_discovery(); } -bool ReferenceProcessor::enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor) { - if (UseCompressedOops) { - return enqueue_discovered_ref_helper(this, task_executor); - } else { - return enqueue_discovered_ref_helper(this, task_executor); - } -} - -void ReferenceProcessor::enqueue_discovered_reflist(DiscoveredList& refs_list, - HeapWord* pending_list_addr) { +void ReferenceProcessor::enqueue_discovered_reflist(DiscoveredList& refs_list) { // Given a list of refs linked through the "discovered" field // (java.lang.ref.Reference.discovered), self-loop their "next" field // thus distinguishing them from active References, then @@ -354,10 +331,9 @@ void ReferenceProcessor::enqueue_discovered_reflist(DiscoveredList& refs_list, oopDesc::bs()->write_ref_field(java_lang_ref_Reference::discovered_addr(obj), next_d); } else { // This is the last object. - // Swap refs_list into pending_list_addr and - // set obj's discovered to what we read from pending_list_addr. - oop old = oopDesc::atomic_exchange_oop(refs_list.head(), pending_list_addr); - // Need post-barrier on pending_list_addr. See enqueue_discovered_ref_helper() above. + // Swap refs_list into pending list and set obj's + // discovered to what we read from the pending list. + oop old = Universe::swap_reference_pending_list(refs_list.head()); java_lang_ref_Reference::set_discovered_raw(obj, old); // old may be NULL oopDesc::bs()->write_ref_field(java_lang_ref_Reference::discovered_addr(obj), old); } @@ -369,10 +345,8 @@ class RefProcEnqueueTask: public AbstractRefProcTaskExecutor::EnqueueTask { public: RefProcEnqueueTask(ReferenceProcessor& ref_processor, DiscoveredList discovered_refs[], - HeapWord* pending_list_addr, int n_queues) - : EnqueueTask(ref_processor, discovered_refs, - pending_list_addr, n_queues) + : EnqueueTask(ref_processor, discovered_refs, n_queues) { } virtual void work(unsigned int work_id) { @@ -387,8 +361,7 @@ public: for (int j = 0; j < ReferenceProcessor::number_of_subclasses_of_ref(); j++, index += _n_queues) { - _ref_processor.enqueue_discovered_reflist( - _refs_lists[index], _pending_list_addr); + _ref_processor.enqueue_discovered_reflist(_refs_lists[index]); _refs_lists[index].set_head(NULL); _refs_lists[index].set_length(0); } @@ -396,17 +369,15 @@ public: }; // Enqueue references that are not made active again -void ReferenceProcessor::enqueue_discovered_reflists(HeapWord* pending_list_addr, - AbstractRefProcTaskExecutor* task_executor) { +void ReferenceProcessor::enqueue_discovered_reflists(AbstractRefProcTaskExecutor* task_executor) { if (_processing_is_mt && task_executor != NULL) { // Parallel code - RefProcEnqueueTask tsk(*this, _discovered_refs, - pending_list_addr, _max_num_q); + RefProcEnqueueTask tsk(*this, _discovered_refs, _max_num_q); task_executor->execute(tsk); } else { // Serial code: call the parent class's implementation for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { - enqueue_discovered_reflist(_discovered_refs[i], pending_list_addr); + enqueue_discovered_reflist(_discovered_refs[i]); _discovered_refs[i].set_head(NULL); _discovered_refs[i].set_length(0); } diff --git a/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp b/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp index c5d0f5f8321..393029642b4 100644 --- a/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp +++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp @@ -290,7 +290,7 @@ class ReferenceProcessor : public CHeapObj { VoidClosure* complete_gc); // Enqueue references with a certain reachability level - void enqueue_discovered_reflist(DiscoveredList& refs_list, HeapWord* pending_list_addr); + void enqueue_discovered_reflist(DiscoveredList& refs_list); // "Preclean" all the discovered reference lists // by removing references with strongly reachable referents. @@ -311,7 +311,7 @@ class ReferenceProcessor : public CHeapObj { // occupying the i / _num_q slot. const char* list_name(uint i); - void enqueue_discovered_reflists(HeapWord* pending_list_addr, AbstractRefProcTaskExecutor* task_executor); + void enqueue_discovered_reflists(AbstractRefProcTaskExecutor* task_executor); protected: // "Preclean" the given discovered reference list @@ -424,7 +424,7 @@ class ReferenceProcessor : public CHeapObj { GCTimer *gc_timer); // Enqueue references at end of GC (called by the garbage collector) - bool enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor = NULL); + void enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor = NULL); // If a discovery is in process that is being superceded, abandon it: all // the discovered lists will be empty, and all the objects on them will @@ -613,11 +613,9 @@ class AbstractRefProcTaskExecutor::EnqueueTask { protected: EnqueueTask(ReferenceProcessor& ref_processor, DiscoveredList refs_lists[], - HeapWord* pending_list_addr, int n_queues) : _ref_processor(ref_processor), _refs_lists(refs_lists), - _pending_list_addr(pending_list_addr), _n_queues(n_queues) { } @@ -627,7 +625,6 @@ public: protected: ReferenceProcessor& _ref_processor; DiscoveredList* _refs_lists; - HeapWord* _pending_list_addr; int _n_queues; }; diff --git a/hotspot/src/share/vm/gc/shared/vmGCOperations.cpp b/hotspot/src/share/vm/gc/shared/vmGCOperations.cpp index 9ac7d42e0a0..ce73880ba2a 100644 --- a/hotspot/src/share/vm/gc/shared/vmGCOperations.cpp +++ b/hotspot/src/share/vm/gc/shared/vmGCOperations.cpp @@ -62,14 +62,6 @@ void VM_GC_Operation::notify_gc_end() { HS_DTRACE_WORKAROUND_TAIL_CALL_BUG(); } -void VM_GC_Operation::acquire_pending_list_lock() { - _pending_list_locker.lock(); -} - -void VM_GC_Operation::release_and_notify_pending_list_lock() { - _pending_list_locker.unlock(); -} - // Allocations may fail in several threads at about the same time, // resulting in multiple gc requests. We only want to do one of them. // In case a GC locker is active and the need for a GC is already signaled, @@ -102,16 +94,13 @@ bool VM_GC_Operation::doit_prologue() { proper_unit_for_byte_size(NewSize))); } - acquire_pending_list_lock(); // If the GC count has changed someone beat us to the collection - // Get the Heap_lock after the pending_list_lock. Heap_lock->lock(); // Check invocations if (skip_operation()) { // skip collection Heap_lock->unlock(); - release_and_notify_pending_list_lock(); _prologue_succeeded = false; } else { _prologue_succeeded = true; @@ -122,9 +111,10 @@ bool VM_GC_Operation::doit_prologue() { void VM_GC_Operation::doit_epilogue() { assert(Thread::current()->is_Java_thread(), "just checking"); - // Release the Heap_lock first. + if (Universe::has_reference_pending_list()) { + Heap_lock->notify_all(); + } Heap_lock->unlock(); - release_and_notify_pending_list_lock(); } bool VM_GC_HeapInspection::skip_operation() const { diff --git a/hotspot/src/share/vm/gc/shared/vmGCOperations.hpp b/hotspot/src/share/vm/gc/shared/vmGCOperations.hpp index fe742964b56..80e652e1029 100644 --- a/hotspot/src/share/vm/gc/shared/vmGCOperations.hpp +++ b/hotspot/src/share/vm/gc/shared/vmGCOperations.hpp @@ -27,7 +27,6 @@ #include "gc/shared/collectedHeap.hpp" #include "gc/shared/genCollectedHeap.hpp" -#include "gc/shared/referencePendingListLocker.hpp" #include "memory/heapInspection.hpp" #include "prims/jvmtiExport.hpp" #include "runtime/handles.hpp" @@ -70,9 +69,6 @@ // class VM_GC_Operation: public VM_Operation { - private: - ReferencePendingListLocker _pending_list_locker; - protected: uint _gc_count_before; // gc count before acquiring PLL uint _full_gc_count_before; // full gc count before acquiring PLL @@ -83,10 +79,6 @@ class VM_GC_Operation: public VM_Operation { virtual bool skip_operation() const; - // java.lang.ref.Reference support - void acquire_pending_list_lock(); - void release_and_notify_pending_list_lock(); - public: VM_GC_Operation(uint gc_count_before, GCCause::Cause _cause, diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp index 1e434d1b79a..97cd396b340 100644 --- a/hotspot/src/share/vm/memory/universe.cpp +++ b/hotspot/src/share/vm/memory/universe.cpp @@ -135,6 +135,7 @@ oop Universe::_arithmetic_exception_instance = NULL; oop Universe::_virtual_machine_error_instance = NULL; oop Universe::_vm_exception = NULL; oop Universe::_allocation_context_notification_obj = NULL; +oop Universe::_reference_pending_list = NULL; Array* Universe::_the_empty_int_array = NULL; Array* Universe::_the_empty_short_array = NULL; @@ -212,6 +213,7 @@ void Universe::oops_do(OopClosure* f, bool do_all) { f->do_oop((oop*)&_system_thread_group); f->do_oop((oop*)&_vm_exception); f->do_oop((oop*)&_allocation_context_notification_obj); + f->do_oop((oop*)&_reference_pending_list); debug_only(f->do_oop((oop*)&_fullgc_alot_dummy_array);) } @@ -488,6 +490,35 @@ void Universe::fixup_mirrors(TRAPS) { java_lang_Class::set_fixup_mirror_list(NULL); } +#define assert_pll_locked(test) \ + assert(Heap_lock->test(), "Reference pending list access requires lock") + +#define assert_pll_ownership() assert_pll_locked(owned_by_self) + +oop Universe::reference_pending_list() { + assert_pll_ownership(); + return _reference_pending_list; +} + +void Universe::set_reference_pending_list(oop list) { + assert_pll_ownership(); + _reference_pending_list = list; +} + +bool Universe::has_reference_pending_list() { + assert_pll_ownership(); + return _reference_pending_list != NULL; +} + +oop Universe::swap_reference_pending_list(oop list) { + assert_pll_locked(is_locked); + return (oop)Atomic::xchg_ptr(list, &_reference_pending_list); +} + +#undef assert_pll_locked +#undef assert_pll_ownership + + static bool has_run_finalizers_on_exit = false; void Universe::run_finalizers_on_exit() { @@ -565,12 +596,14 @@ bool Universe::should_fill_in_stack_trace(Handle throwable) { oop Universe::gen_out_of_memory_error(oop default_err) { // generate an out of memory error: - // - if there is a preallocated error with backtrace available then return it wth - // a filled in stack trace. - // - if there are no preallocated errors with backtrace available then return - // an error without backtrace. + // - if there is a preallocated error and stack traces are available + // (j.l.Throwable is initialized), then return the preallocated + // error with a filled in stack trace, and with the message + // provided by the default error. + // - otherwise, return the default error, without a stack trace. int next; - if (_preallocated_out_of_memory_error_avail_count > 0) { + if ((_preallocated_out_of_memory_error_avail_count > 0) && + SystemDictionary::Throwable_klass()->is_initialized()) { next = (int)Atomic::add(-1, &_preallocated_out_of_memory_error_avail_count); assert(next < (int)PreallocatedOutOfMemoryErrorCount, "avail count is corrupt"); } else { diff --git a/hotspot/src/share/vm/memory/universe.hpp b/hotspot/src/share/vm/memory/universe.hpp index 054b11aa873..2ded08fc801 100644 --- a/hotspot/src/share/vm/memory/universe.hpp +++ b/hotspot/src/share/vm/memory/universe.hpp @@ -185,6 +185,9 @@ class Universe: AllStatic { static oop _allocation_context_notification_obj; + // References waiting to be transferred to the ReferenceHandler + static oop _reference_pending_list; + // The particular choice of collected heap. static CollectedHeap* _collectedHeap; @@ -334,6 +337,17 @@ class Universe: AllStatic { static inline oop allocation_context_notification_obj(); static inline void set_allocation_context_notification_obj(oop obj); + // Reference pending list manipulation. Access is protected by + // Heap_lock. The getter, setter and predicate require the caller + // owns the lock. Swap is used by parallel non-concurrent reference + // processing threads, where some higher level controller owns + // Heap_lock, so requires the lock is locked, but not necessarily by + // the current thread. + static oop reference_pending_list(); + static void set_reference_pending_list(oop list); + static bool has_reference_pending_list(); + static oop swap_reference_pending_list(oop list); + static Array* the_empty_int_array() { return _the_empty_int_array; } static Array* the_empty_short_array() { return _the_empty_short_array; } static Array* the_empty_method_array() { return _the_empty_method_array; } diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp index f890d1d1e9b..95e38717dc5 100644 --- a/hotspot/src/share/vm/oops/method.cpp +++ b/hotspot/src/share/vm/oops/method.cpp @@ -30,7 +30,6 @@ #include "gc/shared/collectedHeap.inline.hpp" #include "gc/shared/gcLocker.hpp" #include "gc/shared/generation.hpp" -#include "gc/shared/referencePendingListLocker.hpp" #include "interpreter/bytecodeStream.hpp" #include "interpreter/bytecodeTracer.hpp" #include "interpreter/bytecodes.hpp" @@ -400,12 +399,6 @@ void Method::build_interpreter_method_data(const methodHandle& method, TRAPS) { return; } - // Do not profile method if current thread holds the pending list lock, - // which avoids deadlock for acquiring the MethodData_lock. - if (ReferencePendingListLocker::is_locked_by_self()) { - return; - } - // Grab a lock here to prevent multiple // MethodData*s from being created. MutexLocker ml(MethodData_lock, THREAD); diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index b66c22bf74e..549e9f47109 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -3352,6 +3352,35 @@ JVM_ENTRY(jobjectArray, JVM_GetSystemPackages(JNIEnv *env)) JVM_END +// java.lang.ref.Reference /////////////////////////////////////////////////////////////// + + +JVM_ENTRY(jobject, JVM_GetAndClearReferencePendingList(JNIEnv* env)) + JVMWrapper("JVM_GetAndClearReferencePendingList"); + + MonitorLockerEx ml(Heap_lock); + oop ref = Universe::reference_pending_list(); + if (ref != NULL) { + Universe::set_reference_pending_list(NULL); + } + return JNIHandles::make_local(env, ref); +JVM_END + +JVM_ENTRY(jboolean, JVM_HasReferencePendingList(JNIEnv* env)) + JVMWrapper("JVM_HasReferencePendingList"); + MonitorLockerEx ml(Heap_lock); + return Universe::has_reference_pending_list(); +JVM_END + +JVM_ENTRY(void, JVM_WaitForReferencePendingList(JNIEnv* env)) + JVMWrapper("JVM_WaitForReferencePendingList"); + MonitorLockerEx ml(Heap_lock); + while (!Universe::has_reference_pending_list()) { + ml.wait(); + } +JVM_END + + // ObjectInputStream /////////////////////////////////////////////////////////////// bool force_verify_field_access(Klass* current_class, Klass* field_class, AccessFlags access, bool classloader_only) { diff --git a/hotspot/src/share/vm/prims/jvm.h b/hotspot/src/share/vm/prims/jvm.h index 58a8fbfeb75..7a0da904bd1 100644 --- a/hotspot/src/share/vm/prims/jvm.h +++ b/hotspot/src/share/vm/prims/jvm.h @@ -296,6 +296,18 @@ JVM_GetSystemPackage(JNIEnv *env, jstring name); JNIEXPORT jobjectArray JNICALL JVM_GetSystemPackages(JNIEnv *env); +/* + * java.lang.ref.Reference + */ +JNIEXPORT jobject JNICALL +JVM_GetAndClearReferencePendingList(JNIEnv *env); + +JNIEXPORT jboolean JNICALL +JVM_HasReferencePendingList(JNIEnv *env); + +JNIEXPORT void JNICALL +JVM_WaitForReferencePendingList(JNIEnv *env); + /* * java.io.ObjectInputStream */ diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index f3481dad820..aa17ff69641 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -35,7 +35,6 @@ #include "compiler/compileTask.hpp" #include "gc/shared/gcId.hpp" #include "gc/shared/gcLocker.inline.hpp" -#include "gc/shared/referencePendingListLocker.hpp" #include "gc/shared/workgroup.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/linkResolver.hpp" @@ -3718,14 +3717,6 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { Management::record_vm_init_completed(); #endif // INCLUDE_MANAGEMENT - // Note that we do not use CHECK_0 here since we are inside an EXCEPTION_MARK and - // set_init_completed has just been called, causing exceptions not to be shortcut - // anymore. We call vm_exit_during_initialization directly instead. - - // Initialize reference pending list locker - bool needs_locker_thread = Universe::heap()->needs_reference_pending_list_locker_thread(); - ReferencePendingListLocker::initialize(needs_locker_thread, CHECK_JNI_ERR); - // Signal Dispatcher needs to be started before VMInit event is posted os::signal_init(); diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 81994ce96f1..26147144526 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -54,7 +54,6 @@ #include "gc/shared/genCollectedHeap.hpp" #include "gc/shared/generation.hpp" #include "gc/shared/generationSpec.hpp" -#include "gc/shared/referencePendingListLocker.hpp" #include "gc/shared/space.hpp" #include "interpreter/bytecodeInterpreter.hpp" #include "interpreter/bytecodes.hpp" @@ -1637,7 +1636,6 @@ typedef CompactHashtable SymbolCompactHashTable; declare_type(JavaThread, Thread) \ declare_type(JvmtiAgentThread, JavaThread) \ declare_type(ServiceThread, JavaThread) \ - declare_type(ReferencePendingListLockerThread, JavaThread) \ declare_type(CompilerThread, JavaThread) \ declare_type(CodeCacheSweeperThread, JavaThread) \ declare_toplevel_type(OSThread) \ From ab538ab5ed85aeff06fdcba603ff1d50e5131c12 Mon Sep 17 00:00:00 2001 From: Jini George Date: Wed, 31 Aug 2016 11:47:14 +0300 Subject: [PATCH 028/110] 8163150: SA: CLHSDB printmdo throws an exception with "java.lang.InternalError: missing reason for 22" Accounted for the new JVMCI related Deoptimization Reasons. Reviewed-by: dsamersoff, sla --- .../sun/jvm/hotspot/oops/MethodData.java | 7 +++-- .../jvm/hotspot/oops/ReceiverTypeData.java | 26 +++++++++++++++---- .../sun/jvm/hotspot/oops/VirtualCallData.java | 8 ++++-- hotspot/src/share/vm/runtime/vmStructs.cpp | 13 +++++++++- 4 files changed, 44 insertions(+), 10 deletions(-) diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/MethodData.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/MethodData.java index 1549538a10e..f01bb5e6ce5 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/MethodData.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/MethodData.java @@ -36,6 +36,7 @@ import sun.jvm.hotspot.utilities.*; public class MethodData extends Metadata implements MethodDataInterface { static int TypeProfileWidth = 2; static int BciProfileWidth = 2; + static int MethodProfileWidth = 0; static int CompileThreshold; static int Reason_many; // indicates presence of several reasons @@ -142,6 +143,8 @@ public class MethodData extends Metadata implements MethodDataInterface parametersTypeData() { int di = (int)parametersTypeDataDi.getValue(getAddress()); - if (di == -1) { + if (di == -1 || di == -2) { return null; } DataLayout dataLayout = new DataLayout(this, di + (int)data.getOffset()); diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ReceiverTypeData.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ReceiverTypeData.java index 7ac053fe0c5..ed2a120ca61 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ReceiverTypeData.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ReceiverTypeData.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, 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 @@ -38,9 +38,21 @@ import sun.jvm.hotspot.utilities.*; // that the check is reached, and a series of (Klass, count) pairs // which are used to store a type profile for the receiver of the check. public class ReceiverTypeData extends CounterData { - static final int receiver0Offset = counterCellCount; - static final int count0Offset = receiver0Offset + 1; - static final int receiverTypeRowCellCount = (count0Offset + 1) - receiver0Offset; + static final int INCLUDE_JVMCI; + static final int nonProfiledCountOffset = counterCellCount; + static final int receiver0Offset; + static final int count0Offset; + static final int receiverTypeRowCellCount; + static { + INCLUDE_JVMCI = VM.getVM().getTypeDataBase().lookupIntConstant("INCLUDE_JVMCI"); + if (INCLUDE_JVMCI == 1) { + receiver0Offset = nonProfiledCountOffset + 1; + } else { + receiver0Offset = counterCellCount; + } + count0Offset = receiver0Offset + 1; + receiverTypeRowCellCount = (count0Offset + 1) - receiver0Offset; + } final MethodDataInterface methodData; public ReceiverTypeData(MethodDataInterface methodData, DataLayout layout) { @@ -53,7 +65,11 @@ public class ReceiverTypeData extends CounterData { boolean isReceivertypedata() { return true; } static int staticCellCount() { - return counterCellCount + MethodData.TypeProfileWidth * receiverTypeRowCellCount; + int cellCount = counterCellCount + MethodData.TypeProfileWidth * receiverTypeRowCellCount; + if (INCLUDE_JVMCI == 1) { + cellCount += 1; + } + return cellCount; } public int cellCount() { diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/VirtualCallData.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/VirtualCallData.java index eec5000a6a4..fe7183822a1 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/VirtualCallData.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/VirtualCallData.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, 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 @@ -44,7 +44,11 @@ public class VirtualCallData extends ReceiverTypeData { static int staticCellCount() { // At this point we could add more profile state, e.g., for arguments. // But for now it's the same size as the base record type. - return ReceiverTypeData.staticCellCount(); + int cellCount = ReceiverTypeData.staticCellCount(); + if (INCLUDE_JVMCI == 1) { + cellCount += MethodData.MethodProfileWidth * receiverTypeRowCellCount; + } + return cellCount; } public int cellCount() { diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 26147144526..84eb6fa7d86 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -2626,6 +2626,11 @@ typedef CompactHashtable SymbolCompactHashTable; declare_constant(Deoptimization::Reason_rtm_state_change) \ declare_constant(Deoptimization::Reason_unstable_if) \ declare_constant(Deoptimization::Reason_unstable_fused_if) \ + NOT_ZERO(JVMCI_ONLY(declare_constant(Deoptimization::Reason_aliasing))) \ + NOT_ZERO(JVMCI_ONLY(declare_constant(Deoptimization::Reason_transfer_to_interpreter))) \ + NOT_ZERO(JVMCI_ONLY(declare_constant(Deoptimization::Reason_not_compiled_exception_handler))) \ + NOT_ZERO(JVMCI_ONLY(declare_constant(Deoptimization::Reason_unresolved))) \ + NOT_ZERO(JVMCI_ONLY(declare_constant(Deoptimization::Reason_jsr_mismatch))) \ declare_constant(Deoptimization::Reason_tenured) \ declare_constant(Deoptimization::Reason_LIMIT) \ declare_constant(Deoptimization::Reason_RECORDED_LIMIT) \ @@ -2750,7 +2755,13 @@ typedef CompactHashtable SymbolCompactHashTable; declare_constant(ConcreteRegisterImpl::number_of_registers) \ declare_preprocessor_constant("REG_COUNT", REG_COUNT) \ declare_c2_preprocessor_constant("SAVED_ON_ENTRY_REG_COUNT", SAVED_ON_ENTRY_REG_COUNT) \ - declare_c2_preprocessor_constant("C_SAVED_ON_ENTRY_REG_COUNT", C_SAVED_ON_ENTRY_REG_COUNT) + declare_c2_preprocessor_constant("C_SAVED_ON_ENTRY_REG_COUNT", C_SAVED_ON_ENTRY_REG_COUNT) \ + \ + /****************/ \ + /* JVMCI */ \ + /****************/ \ + \ + declare_preprocessor_constant("INCLUDE_JVMCI", INCLUDE_JVMCI) //-------------------------------------------------------------------------------- From 31d8fcc4f9a43440d6e7d8d3585cc24b28846fbb Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Wed, 31 Aug 2016 06:35:19 -0400 Subject: [PATCH 029/110] 8164692: InstanceKlass::_previous_version_count goes negative Decrement previous_version_count when it's removed from the list. Reviewed-by: dcubed, dlong, sspitsyn --- .../share/vm/classfile/classLoaderData.cpp | 2 +- hotspot/src/share/vm/oops/instanceKlass.cpp | 19 +++++-- hotspot/src/share/vm/oops/instanceKlass.hpp | 5 +- .../runtime/RedefineTests/RedefineCount.java | 56 +++++++++++++++++++ 4 files changed, 74 insertions(+), 8 deletions(-) create mode 100644 hotspot/test/runtime/RedefineTests/RedefineCount.java diff --git a/hotspot/src/share/vm/classfile/classLoaderData.cpp b/hotspot/src/share/vm/classfile/classLoaderData.cpp index ba1191614b1..f7711449312 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.cpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp @@ -962,7 +962,7 @@ bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive_closure, // Mark metadata seen on the stack only so we can delete unneeded entries. // Only walk all metadata, including the expensive code cache walk, for Full GC - // and only if class redefinition and if there's previous versions of + // and only if class redefinition occurred and if there are previous versions of // Klasses to delete. bool walk_all_metadata = clean_previous_versions && JvmtiExport::has_redefined_a_class() && diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index 1385affc5df..2b34d9ae8c2 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -3370,6 +3370,7 @@ int InstanceKlass::_previous_version_count = 0; // Purge previous versions before adding new previous versions of the class. void InstanceKlass::purge_previous_versions(InstanceKlass* ik) { + assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint"); if (ik->previous_versions() != NULL) { // This klass has previous versions so see what we can cleanup // while it is safe to do so. @@ -3398,7 +3399,12 @@ void InstanceKlass::purge_previous_versions(InstanceKlass* ik) { // are executing. Unlink this previous_version. // The previous version InstanceKlass is on the ClassLoaderData deallocate list // so will be deallocated during the next phase of class unloading. - log_trace(redefine, class, iklass, purge)("previous version " INTPTR_FORMAT " is dead", p2i(pv_node)); + // + // Update count for class unloading. + _previous_version_count--; + log_trace(redefine, class, iklass, purge) + ("previous version " INTPTR_FORMAT " is dead. previous_version_count = %d", + p2i(pv_node), _previous_version_count); // For debugging purposes. pv_node->set_is_scratch_class(); pv_node->class_loader_data()->add_to_deallocate_list(pv_node); @@ -3513,6 +3519,7 @@ void InstanceKlass::add_previous_version(instanceKlassHandle scratch_class, int emcp_method_count) { assert(Thread::current()->is_VM_thread(), "only VMThread can add previous versions"); + assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint"); ResourceMark rm; log_trace(redefine, class, iklass, add) @@ -3536,8 +3543,6 @@ void InstanceKlass::add_previous_version(instanceKlassHandle scratch_class, // For debugging purposes. scratch_class->set_is_scratch_class(); scratch_class->class_loader_data()->add_to_deallocate_list(scratch_class()); - // Update count for class unloading. - _previous_version_count--; return; } @@ -3565,12 +3570,14 @@ void InstanceKlass::add_previous_version(instanceKlassHandle scratch_class, } // Add previous version if any methods are still running. - log_trace(redefine, class, iklass, add)("scratch class added; one of its methods is on_stack"); + // Update count for class unloading. + _previous_version_count++; + log_trace(redefine, class, iklass, add) + ("scratch class added; one of its methods is on_stack. previous_version_count = %d", + _previous_version_count); assert(scratch_class->previous_versions() == NULL, "shouldn't have a previous version"); scratch_class->link_previous_versions(previous_versions()); link_previous_versions(scratch_class()); - // Update count for class unloading. - _previous_version_count++; } // end add_previous_version() #endif // INCLUDE_JVMTI diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index da36a1422b4..c9cc2cfb64f 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -771,7 +771,10 @@ public: static int _previous_version_count; public: static void purge_previous_versions(InstanceKlass* ik); - static bool has_previous_versions() { return _previous_version_count > 0; } + static bool has_previous_versions() { + assert(_previous_version_count >= 0, "count should never be negative"); + return _previous_version_count > 0; + } // JVMTI: Support for caching a class file before it is modified by an agent that can do retransformation void set_cached_class_file(JvmtiCachedClassFileData *data) { diff --git a/hotspot/test/runtime/RedefineTests/RedefineCount.java b/hotspot/test/runtime/RedefineTests/RedefineCount.java new file mode 100644 index 00000000000..ce8d40d0902 --- /dev/null +++ b/hotspot/test/runtime/RedefineTests/RedefineCount.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8164692 + * @summary Redefine previous_versions count goes negative + * @library /test/lib + * @modules java.base/jdk.internal.misc + * @modules java.compiler + * java.instrument + * jdk.jartool/sun.tools.jar + * @run main RedefineClassHelper + * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace RedefineCount + */ +public class RedefineCount { + + public static String newB = + "class RedefineCount$B {" + + "}"; + + static class B { } + + public static void main(String[] args) throws Exception { + + // Redefine a class and create some garbage + // Since there are no methods running, the previous version is never added to the + // previous_version_list and the count should stay zero and not go negative + RedefineClassHelper.redefineClass(B.class, newB); + + for (int i = 0; i < 20 ; i++) { + String s = new String("some garbage"); + System.gc(); + } + } +} From 0fd1f32873d512edf5ca82029359ad618784492d Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Wed, 31 Aug 2016 10:27:32 -0400 Subject: [PATCH 030/110] 8162412: Ignore any System property specified as -Djdk.module that matches reserved module system properties Change the checks for module related properties to look for specific properties, not just jdk.module Reviewed-by: coleenp, gziemski, ddmitriev --- hotspot/src/share/vm/runtime/arguments.cpp | 55 +++++++++++----- .../runtime/modules/ModuleOptionsWarn.java | 62 ++++++++++++++++++- 2 files changed, 98 insertions(+), 19 deletions(-) diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index a4decf9c983..18cd2374e3f 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -163,26 +163,47 @@ static void logOption(const char* opt) { bool needs_module_property_warning = false; -#define MODULE_PROPERTY_PREFIX "jdk.module" -#define MODULE_PROPERTY_PREFIX_LEN 10 -#define MODULE_MAIN_PROPERTY "jdk.module.main" -#define MODULE_MAIN_PROPERTY_LEN 15 +#define MODULE_PROPERTY_PREFIX "jdk.module." +#define MODULE_PROPERTY_PREFIX_LEN 11 +#define ADDEXPORTS "addexports" +#define ADDEXPORTS_LEN 10 +#define ADDREADS "addreads" +#define ADDREADS_LEN 8 +#define PATCH "patch" +#define PATCH_LEN 5 +#define ADDMODS "addmods" +#define ADDMODS_LEN 7 +#define LIMITMODS "limitmods" +#define LIMITMODS_LEN 9 +#define PATH "path" +#define PATH_LEN 4 +#define UPGRADE_PATH "upgrade.path" +#define UPGRADE_PATH_LEN 12 -// Return TRUE if option matches property, or property=, or property.. -static bool matches_property_prefix(const char* option, const char* property, size_t len) { - return (strncmp(option, property, len) == 0) && - (option[len] == '=' || option[len] == '.' || option[len] == '\0'); +// Return TRUE if option matches 'property', or 'property=', or 'property.'. +static bool matches_property_suffix(const char* option, const char* property, size_t len) { + return ((strncmp(option, property, len) == 0) && + (option[len] == '=' || option[len] == '.' || option[len] == '\0')); } -// Return true if the property is either "jdk.module" or starts with "jdk.module.", -// but does not start with "jdk.module.main". -// Return false if jdk.module.main because jdk.module.main and jdk.module.main.class -// are valid non-internal system properties. -// "property" should be passed without the leading "-D". +// Return true if property starts with "jdk.module." and its ensuing chars match +// any of the reserved module properties. +// property should be passed without the leading "-D". bool Arguments::is_internal_module_property(const char* property) { assert((strncmp(property, "-D", 2) != 0), "Unexpected leading -D"); - return (matches_property_prefix(property, MODULE_PROPERTY_PREFIX, MODULE_PROPERTY_PREFIX_LEN) && - !matches_property_prefix(property, MODULE_MAIN_PROPERTY, MODULE_MAIN_PROPERTY_LEN)); + if (strncmp(property, MODULE_PROPERTY_PREFIX, MODULE_PROPERTY_PREFIX_LEN) == 0) { + const char* property_suffix = property + MODULE_PROPERTY_PREFIX_LEN; + if (matches_property_suffix(property_suffix, ADDEXPORTS, ADDEXPORTS_LEN) || + matches_property_suffix(property_suffix, ADDREADS, ADDREADS_LEN) || + matches_property_suffix(property_suffix, PATCH, PATCH_LEN) || + matches_property_suffix(property_suffix, ADDMODS, ADDMODS_LEN) || + matches_property_suffix(property_suffix, LIMITMODS, LIMITMODS_LEN) || + matches_property_suffix(property_suffix, PATH, PATH_LEN) || + matches_property_suffix(property_suffix, UPGRADE_PATH, UPGRADE_PATH_LEN)) { + return true; + } + } + return false; } // Process java launcher properties. @@ -4287,8 +4308,8 @@ jint Arguments::parse(const JavaVMInitArgs* initial_cmd_args) { } if (needs_module_property_warning) { - warning("Ignoring system property options whose names start with '-Djdk.module'." - " They are reserved for internal use."); + warning("Ignoring system property options whose names match the '-Djdk.module.*'." + " names that are reserved for internal use."); } #if defined(_ALLBSD_SOURCE) || defined(AIX) // UseLargePages is not yet supported on BSD and AIX. diff --git a/hotspot/test/runtime/modules/ModuleOptionsWarn.java b/hotspot/test/runtime/modules/ModuleOptionsWarn.java index 7ad1f9b2ca9..6446e0ae5fd 100644 --- a/hotspot/test/runtime/modules/ModuleOptionsWarn.java +++ b/hotspot/test/runtime/modules/ModuleOptionsWarn.java @@ -29,6 +29,7 @@ * @library /test/lib */ +import java.util.Map; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; @@ -37,16 +38,65 @@ public class ModuleOptionsWarn { public static void main(String[] args) throws Exception { - // Test that a warning is issued for module related properties that get ignored. + // Test that a warning is not issued for extraneous jdk.module properties. ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( "-XX:+PrintWarnings", "-Djdk.module.ignored", "-version"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("Ignoring system property option"); + output.shouldHaveExitValue(0); + + // Test that a warning is issued for a reserved jdk.module property. + pb = ProcessTools.createJavaProcessBuilder( + "-XX:+PrintWarnings", "-Djdk.module.addmods", "-version"); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Ignoring system property option"); + output.shouldHaveExitValue(0); + + // Test that a warning is issued for a reserved jdk.module property ending in '.'. + pb = ProcessTools.createJavaProcessBuilder( + "-XX:+PrintWarnings", "-Djdk.module.limitmods.", "-version"); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Ignoring system property option"); + output.shouldHaveExitValue(0); + + // Test that a warning is issued for a reserved jdk.module property ending in '='. + pb = ProcessTools.createJavaProcessBuilder( + "-XX:+PrintWarnings", "-Djdk.module.addexports=", "-version"); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Ignoring system property option"); + output.shouldHaveExitValue(0); + + // Test that a warning is issued for a reserved jdk.module property ending in ".stuff" + pb = ProcessTools.createJavaProcessBuilder( + "-XX:+PrintWarnings", "-Djdk.module.addreads.stuff", "-version"); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Ignoring system property option"); + output.shouldHaveExitValue(0); + + // Test that a warning is issued for a reserved jdk.module property ending in "=stuff" + pb = ProcessTools.createJavaProcessBuilder( + "-XX:+PrintWarnings", "-Djdk.module.path=stuff", "-version"); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Ignoring system property option"); + output.shouldHaveExitValue(0); + + // Test that a warning is issued for a reserved jdk.module property ending in ".=" + pb = ProcessTools.createJavaProcessBuilder( + "-XX:+PrintWarnings", "-Djdk.module.upgrade.path.=xx", "-version"); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Ignoring system property option"); + output.shouldHaveExitValue(0); + + // Test that a warning is issued for a reserved jdk.module property ending in "." + pb = ProcessTools.createJavaProcessBuilder( + "-XX:+PrintWarnings", "-Djdk.module.patch.3=xx", "-version"); + output = new OutputAnalyzer(pb.start()); output.shouldContain("Ignoring system property option"); output.shouldHaveExitValue(0); // Test that a warning can be suppressed for module related properties that get ignored. pb = ProcessTools.createJavaProcessBuilder( - "-Djdk.module.ignored", "-XX:-PrintWarnings", "-version"); + "-Djdk.module.addmods", "-XX:-PrintWarnings", "-version"); output = new OutputAnalyzer(pb.start()); output.shouldNotContain("Ignoring system property option"); output.shouldHaveExitValue(0); @@ -57,5 +107,13 @@ public class ModuleOptionsWarn { output = new OutputAnalyzer(pb.start()); output.shouldNotContain("Ignoring system property option"); output.shouldHaveExitValue(0); + + // Test that a warning is issued for module related properties specified using _JAVA_OPTIONS. + pb = ProcessTools.createJavaProcessBuilder("-XX:+PrintWarnings", "-version"); + Map env = pb.environment(); + env.put("_JAVA_OPTIONS", "-Djdk.module.addreads"); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Ignoring system property option"); + output.shouldHaveExitValue(0); } } From 992e74a1831ec01940173aa594cb82964d9832ed Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Wed, 31 Aug 2016 16:48:26 +0200 Subject: [PATCH 031/110] 8164862: 2 JVMCI tests should not be executed on linux-x86 Reviewed-by: kvn, gtriantafill --- .../src/jdk/vm/ci/code/test/MaxOopMapStackOffsetTest.java | 2 +- .../src/jdk/vm/ci/code/test/NativeCallTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/MaxOopMapStackOffsetTest.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/MaxOopMapStackOffsetTest.java index 9caed4279dd..4a9532809c7 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/MaxOopMapStackOffsetTest.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/MaxOopMapStackOffsetTest.java @@ -23,7 +23,7 @@ /** * @test - * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" + * @requires (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9") & os.arch != "aarch64" * @library / * @modules jdk.vm.ci/jdk.vm.ci.hotspot * jdk.vm.ci/jdk.vm.ci.meta diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/NativeCallTest.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/NativeCallTest.java index ccbc9d981a3..0800e7bea10 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/NativeCallTest.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/NativeCallTest.java @@ -23,7 +23,7 @@ /** * @test - * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" + * @requires (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9") & os.arch != "aarch64" * @library /test/lib / * @modules jdk.vm.ci/jdk.vm.ci.hotspot * jdk.vm.ci/jdk.vm.ci.code From ddfcdd9299d73b70f3d5b28002a063016bd3a6bd Mon Sep 17 00:00:00 2001 From: Martin Doerr Date: Wed, 31 Aug 2016 19:41:57 -0400 Subject: [PATCH 032/110] 8165014: Unaligned unsafe access should throw InternalError on Solaris Reviewed-by: dholmes, coleenp --- hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp index a4a4e3da963..cf782a2f75f 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp @@ -444,7 +444,7 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, if (thread->thread_state() == _thread_in_vm) { - if (sig == SIGBUS && info->si_code == BUS_OBJERR && thread->doing_unsafe_access()) { + if (sig == SIGBUS && thread->doing_unsafe_access()) { stub = SharedRuntime::handle_unsafe_access(thread, npc); } } From d67d71f44c3a2626877760bb85e37da59fb1584f Mon Sep 17 00:00:00 2001 From: Robbin Ehn Date: Thu, 1 Sep 2016 08:30:17 +0200 Subject: [PATCH 033/110] 8163589: Add back class id intrinsic method for event based tracing Reviewed-by: kvn, mgronlun --- hotspot/src/share/vm/c1/c1_Compiler.cpp | 3 ++ hotspot/src/share/vm/c1/c1_LIRGenerator.cpp | 34 ++++++++++++++++ hotspot/src/share/vm/c1/c1_LIRGenerator.hpp | 4 ++ hotspot/src/share/vm/classfile/vmSymbols.cpp | 1 + hotspot/src/share/vm/opto/c2compiler.cpp | 1 + hotspot/src/share/vm/opto/library_call.cpp | 41 ++++++++++++++++++++ 6 files changed, 84 insertions(+) diff --git a/hotspot/src/share/vm/c1/c1_Compiler.cpp b/hotspot/src/share/vm/c1/c1_Compiler.cpp index e292574e80c..08f2fdddb85 100644 --- a/hotspot/src/share/vm/c1/c1_Compiler.cpp +++ b/hotspot/src/share/vm/c1/c1_Compiler.cpp @@ -221,6 +221,9 @@ bool Compiler::is_intrinsic_supported(const methodHandle& method) { case vmIntrinsics::_putCharStringU: #ifdef TRACE_HAVE_INTRINSICS case vmIntrinsics::_counterTime: +#if defined(_LP64) || !defined(TRACE_ID_CLASS_SHIFT) + case vmIntrinsics::_getClassId: +#endif #endif break; default: diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp index a0f94545a7e..81f353ba184 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp @@ -3083,6 +3083,37 @@ void LIRGenerator::do_IfOp(IfOp* x) { __ cmove(lir_cond(x->cond()), t_val.result(), f_val.result(), reg, as_BasicType(x->x()->type())); } +#ifdef TRACE_HAVE_INTRINSICS +void LIRGenerator::do_ClassIDIntrinsic(Intrinsic* x) { + CodeEmitInfo* info = state_for(x); + CodeEmitInfo* info2 = new CodeEmitInfo(info); // Clone for the second null check + + assert(info != NULL, "must have info"); + LIRItem arg(x->argument_at(0), this); + + arg.load_item(); + LIR_Opr klass = new_register(T_METADATA); + __ move(new LIR_Address(arg.result(), java_lang_Class::klass_offset_in_bytes(), T_ADDRESS), klass, info); + LIR_Opr id = new_register(T_LONG); + ByteSize offset = TRACE_KLASS_TRACE_ID_OFFSET; + LIR_Address* trace_id_addr = new LIR_Address(klass, in_bytes(offset), T_LONG); + + __ move(trace_id_addr, id); + __ logical_or(id, LIR_OprFact::longConst(0x01l), id); + __ store(id, trace_id_addr); + +#ifdef TRACE_ID_META_BITS + __ logical_and(id, LIR_OprFact::longConst(~TRACE_ID_META_BITS), id); +#endif +#ifdef TRACE_ID_CLASS_SHIFT + __ unsigned_shift_right(id, TRACE_ID_CLASS_SHIFT, id); +#endif + + __ move(id, rlock_result(x)); +} +#endif + + void LIRGenerator::do_RuntimeCall(address routine, Intrinsic* x) { assert(x->number_of_arguments() == 0, "wrong type"); // Enforce computation of _reserved_argument_area_size which is required on some platforms. @@ -3108,6 +3139,9 @@ void LIRGenerator::do_Intrinsic(Intrinsic* x) { } #ifdef TRACE_HAVE_INTRINSICS + case vmIntrinsics::_getClassId: + do_ClassIDIntrinsic(x); + break; case vmIntrinsics::_counterTime: do_RuntimeCall(CAST_FROM_FN_PTR(address, TRACE_TIME_METHOD), x); break; diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp index 91536455821..cda06580660 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp @@ -438,6 +438,10 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure { SwitchRangeArray* create_lookup_ranges(LookupSwitch* x); void do_SwitchRanges(SwitchRangeArray* x, LIR_Opr value, BlockBegin* default_sux); +#ifdef TRACE_HAVE_INTRINSICS + void do_ClassIDIntrinsic(Intrinsic* x); +#endif + void do_RuntimeCall(address routine, Intrinsic* x); ciKlass* profile_type(ciMethodData* md, int md_first_offset, int md_offset, intptr_t profiled_k, diff --git a/hotspot/src/share/vm/classfile/vmSymbols.cpp b/hotspot/src/share/vm/classfile/vmSymbols.cpp index a52570c17c5..10a77f3f4f7 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.cpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp @@ -366,6 +366,7 @@ bool vmIntrinsics::can_trap(vmIntrinsics::ID id) { switch(id) { #ifdef TRACE_HAVE_INTRINSICS case vmIntrinsics::_counterTime: + case vmIntrinsics::_getClassId: #endif case vmIntrinsics::_currentTimeMillis: case vmIntrinsics::_nanoTime: diff --git a/hotspot/src/share/vm/opto/c2compiler.cpp b/hotspot/src/share/vm/opto/c2compiler.cpp index c80ca6eaa8c..ddbaa6b8de6 100644 --- a/hotspot/src/share/vm/opto/c2compiler.cpp +++ b/hotspot/src/share/vm/opto/c2compiler.cpp @@ -530,6 +530,7 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method, bool is_virt case vmIntrinsics::_isInterrupted: #ifdef TRACE_HAVE_INTRINSICS case vmIntrinsics::_counterTime: + case vmIntrinsics::_getClassId: #endif case vmIntrinsics::_currentTimeMillis: case vmIntrinsics::_nanoTime: diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 2fae1704c8f..205d72bf664 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -254,6 +254,9 @@ class LibraryCallKit : public GraphKit { bool inline_native_currentThread(); bool inline_native_time_funcs(address method, const char* funcName); +#ifdef TRACE_HAVE_INTRINSICS + bool inline_native_classID(); +#endif bool inline_native_isInterrupted(); bool inline_native_Class_query(vmIntrinsics::ID id); bool inline_native_subtype_check(); @@ -708,6 +711,7 @@ bool LibraryCallKit::try_to_inline(int predicate) { #ifdef TRACE_HAVE_INTRINSICS case vmIntrinsics::_counterTime: return inline_native_time_funcs(CAST_FROM_FN_PTR(address, TRACE_TIME_METHOD), "counterTime"); + case vmIntrinsics::_getClassId: return inline_native_classID(); #endif case vmIntrinsics::_currentTimeMillis: return inline_native_time_funcs(CAST_FROM_FN_PTR(address, os::javaTimeMillis), "currentTimeMillis"); case vmIntrinsics::_nanoTime: return inline_native_time_funcs(CAST_FROM_FN_PTR(address, os::javaTimeNanos), "nanoTime"); @@ -3132,6 +3136,43 @@ bool LibraryCallKit::inline_native_time_funcs(address funcAddr, const char* func return true; } +#ifdef TRACE_HAVE_INTRINSICS + +/* +* oop -> myklass +* myklass->trace_id |= USED +* return myklass->trace_id & ~0x3 +*/ +bool LibraryCallKit::inline_native_classID() { + Node* cls = null_check(argument(0), T_OBJECT); + Node* kls = load_klass_from_mirror(cls, false, NULL, 0); + kls = null_check(kls, T_OBJECT); + + ByteSize offset = TRACE_KLASS_TRACE_ID_OFFSET; + Node* insp = basic_plus_adr(kls, in_bytes(offset)); + Node* tvalue = make_load(NULL, insp, TypeLong::LONG, T_LONG, MemNode::unordered); + + Node* clsused = longcon(0x01l); // set the class bit + Node* orl = _gvn.transform(new OrLNode(tvalue, clsused)); + const TypePtr *adr_type = _gvn.type(insp)->isa_ptr(); + store_to_memory(control(), insp, orl, T_LONG, adr_type, MemNode::unordered); + +#ifdef TRACE_ID_META_BITS + Node* mbits = longcon(~TRACE_ID_META_BITS); + tvalue = _gvn.transform(new AndLNode(tvalue, mbits)); +#endif +#ifdef TRACE_ID_CLASS_SHIFT + Node* cbits = intcon(TRACE_ID_CLASS_SHIFT); + tvalue = _gvn.transform(new URShiftLNode(tvalue, cbits)); +#endif + + set_result(tvalue); + return true; + +} + +#endif + //------------------------inline_native_currentThread------------------ bool LibraryCallKit::inline_native_currentThread() { Node* junk = NULL; From 635fad4510390d064aa4dbabcca9271b0749f717 Mon Sep 17 00:00:00 2001 From: Kirill Zhaldybin Date: Wed, 24 Aug 2016 18:10:09 +0300 Subject: [PATCH 034/110] 8164738: Convert AltHashing_test to GTest Reviewed-by: dholmes, coleenp --- hotspot/src/share/vm/classfile/altHashing.cpp | 102 +---------------- hotspot/src/share/vm/classfile/altHashing.hpp | 14 +-- .../share/vm/utilities/internalVMTests.cpp | 1 - .../test/native/classfile/test_AltHashing.cpp | 107 ++++++++++++++++++ 4 files changed, 111 insertions(+), 113 deletions(-) create mode 100644 hotspot/test/native/classfile/test_AltHashing.cpp diff --git a/hotspot/src/share/vm/classfile/altHashing.cpp b/hotspot/src/share/vm/classfile/altHashing.cpp index ee6b810d1e6..df3f9446aef 100644 --- a/hotspot/src/share/vm/classfile/altHashing.cpp +++ b/hotspot/src/share/vm/classfile/altHashing.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -205,103 +205,3 @@ juint AltHashing::murmur3_32(juint seed, const int* data, int len) { juint AltHashing::murmur3_32(const int* data, int len) { return murmur3_32(0, data, len); } - -#ifndef PRODUCT -// Overloaded versions for internal test. -juint AltHashing::murmur3_32(const jbyte* data, int len) { - return murmur3_32(0, data, len); -} - -juint AltHashing::murmur3_32(const jchar* data, int len) { - return murmur3_32(0, data, len); -} - -// Internal test for alternate hashing. Translated from JDK version -// test/sun/misc/Hashing.java -static const jbyte ONE_BYTE[] = { (jbyte) 0x80}; -static const jbyte TWO_BYTE[] = { (jbyte) 0x80, (jbyte) 0x81}; -static const jchar ONE_CHAR[] = { (jchar) 0x8180}; -static const jbyte THREE_BYTE[] = { (jbyte) 0x80, (jbyte) 0x81, (jbyte) 0x82}; -static const jbyte FOUR_BYTE[] = { (jbyte) 0x80, (jbyte) 0x81, (jbyte) 0x82, (jbyte) 0x83}; -static const jchar TWO_CHAR[] = { (jchar) 0x8180, (jchar) 0x8382}; -static const jint ONE_INT[] = { (jint)0x83828180}; -static const jbyte SIX_BYTE[] = { (jbyte) 0x80, (jbyte) 0x81, (jbyte) 0x82, (jbyte) 0x83, (jbyte) 0x84, (jbyte) 0x85}; -static const jchar THREE_CHAR[] = { (jchar) 0x8180, (jchar) 0x8382, (jchar) 0x8584}; -static const jbyte EIGHT_BYTE[] = { - (jbyte) 0x80, (jbyte) 0x81, (jbyte) 0x82, - (jbyte) 0x83, (jbyte) 0x84, (jbyte) 0x85, - (jbyte) 0x86, (jbyte) 0x87}; -static const jchar FOUR_CHAR[] = { - (jchar) 0x8180, (jchar) 0x8382, - (jchar) 0x8584, (jchar) 0x8786}; - -static const jint TWO_INT[] = { (jint)0x83828180, (jint)0x87868584}; - -static const juint MURMUR3_32_X86_CHECK_VALUE = 0xB0F57EE3; - -void AltHashing::testMurmur3_32_ByteArray() { - // printf("testMurmur3_32_ByteArray\n"); - - jbyte vector[256]; - jbyte hashes[4 * 256]; - - for (int i = 0; i < 256; i++) { - vector[i] = (jbyte) i; - } - - // Hash subranges {}, {0}, {0,1}, {0,1,2}, ..., {0,...,255} - for (int i = 0; i < 256; i++) { - juint hash = murmur3_32(256 - i, vector, i); - hashes[i * 4] = (jbyte) hash; - hashes[i * 4 + 1] = (jbyte)(hash >> 8); - hashes[i * 4 + 2] = (jbyte)(hash >> 16); - hashes[i * 4 + 3] = (jbyte)(hash >> 24); - } - - // hash to get const result. - juint final_hash = murmur3_32(hashes, 4*256); - - assert (MURMUR3_32_X86_CHECK_VALUE == final_hash, - "Calculated hash result not as expected. Expected %08X got %08X\n", - MURMUR3_32_X86_CHECK_VALUE, - final_hash); -} - -void AltHashing::testEquivalentHashes() { - juint jbytes, jchars, ints; - - // printf("testEquivalentHashes\n"); - - jbytes = murmur3_32(TWO_BYTE, 2); - jchars = murmur3_32(ONE_CHAR, 1); - assert (jbytes == jchars, - "Hashes did not match. b:%08x != c:%08x\n", jbytes, jchars); - - jbytes = murmur3_32(FOUR_BYTE, 4); - jchars = murmur3_32(TWO_CHAR, 2); - ints = murmur3_32(ONE_INT, 1); - assert ((jbytes == jchars) && (jbytes == ints), - "Hashes did not match. b:%08x != c:%08x != i:%08x\n", jbytes, jchars, ints); - - jbytes = murmur3_32(SIX_BYTE, 6); - jchars = murmur3_32(THREE_CHAR, 3); - assert (jbytes == jchars, - "Hashes did not match. b:%08x != c:%08x\n", jbytes, jchars); - - jbytes = murmur3_32(EIGHT_BYTE, 8); - jchars = murmur3_32(FOUR_CHAR, 4); - ints = murmur3_32(TWO_INT, 2); - assert ((jbytes == jchars) && (jbytes == ints), - "Hashes did not match. b:%08x != c:%08x != i:%08x\n", jbytes, jchars, ints); -} - -// Returns true if the alternate hashcode is correct -void AltHashing::test_alt_hash() { - testMurmur3_32_ByteArray(); - testEquivalentHashes(); -} - -void AltHashing_test() { - AltHashing::test_alt_hash(); -} -#endif // PRODUCT diff --git a/hotspot/src/share/vm/classfile/altHashing.hpp b/hotspot/src/share/vm/classfile/altHashing.hpp index 2e04fd33a2d..43af02f39ce 100644 --- a/hotspot/src/share/vm/classfile/altHashing.hpp +++ b/hotspot/src/share/vm/classfile/altHashing.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -37,26 +37,18 @@ */ class AltHashing : AllStatic { + friend class AltHashingTest; // utility function copied from java/lang/Integer static juint Integer_rotateLeft(juint i, int distance) { - return (i << distance) | (i >> (32-distance)); + return (i << distance) | (i >> (32 - distance)); } static juint murmur3_32(const int* data, int len); static juint murmur3_32(juint seed, const int* data, int len); -#ifndef PRODUCT - // Hashing functions used for internal testing - static juint murmur3_32(const jbyte* data, int len); - static juint murmur3_32(const jchar* data, int len); - static void testMurmur3_32_ByteArray(); - static void testEquivalentHashes(); -#endif // PRODUCT - public: static juint compute_seed(); static juint murmur3_32(juint seed, const jbyte* data, int len); static juint murmur3_32(juint seed, const jchar* data, int len); - NOT_PRODUCT(static void test_alt_hash();) }; #endif // SHARE_VM_CLASSFILE_ALTHASHING_HPP diff --git a/hotspot/src/share/vm/utilities/internalVMTests.cpp b/hotspot/src/share/vm/utilities/internalVMTests.cpp index c6543b71cab..70eece1f2d8 100644 --- a/hotspot/src/share/vm/utilities/internalVMTests.cpp +++ b/hotspot/src/share/vm/utilities/internalVMTests.cpp @@ -56,7 +56,6 @@ void InternalVMTests::run() { run_unit_test(CollectedHeap_test); run_unit_test(QuickSort_test); run_unit_test(GuardedMemory_test); - run_unit_test(AltHashing_test); run_unit_test(TestNewSize_test); run_unit_test(TestOldSize_test); run_unit_test(TestKlass_test); diff --git a/hotspot/test/native/classfile/test_AltHashing.cpp b/hotspot/test/native/classfile/test_AltHashing.cpp new file mode 100644 index 00000000000..4718bdd97b2 --- /dev/null +++ b/hotspot/test/native/classfile/test_AltHashing.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +#include "precompiled.hpp" +#include "classfile/altHashing.hpp" +#include "unittest.hpp" + +// Internal test for alternate hashing. Translated from JDK version +// test/sun/misc/Hashing.java +static const jbyte ONE_BYTE[] = {(jbyte) 0x80}; +static const jbyte TWO_BYTE[] = {(jbyte) 0x80, (jbyte) 0x81}; +static const jchar ONE_CHAR[] = {(jchar) 0x8180}; +static const jbyte THREE_BYTE[] = {(jbyte) 0x80, (jbyte) 0x81, (jbyte) 0x82}; +static const jbyte FOUR_BYTE[] = {(jbyte) 0x80, (jbyte) 0x81, (jbyte) 0x82, (jbyte) 0x83}; +static const jchar TWO_CHAR[] = {(jchar) 0x8180, (jchar) 0x8382}; +static const jint ONE_INT[] = {(jint) 0x83828180}; +static const jbyte SIX_BYTE[] = {(jbyte) 0x80, (jbyte) 0x81, (jbyte) 0x82, (jbyte) 0x83, (jbyte) 0x84, (jbyte) 0x85}; +static const jchar THREE_CHAR[] = {(jchar) 0x8180, (jchar) 0x8382, (jchar) 0x8584}; +static const jbyte EIGHT_BYTE[] = { + (jbyte) 0x80, (jbyte) 0x81, (jbyte) 0x82, + (jbyte) 0x83, (jbyte) 0x84, (jbyte) 0x85, + (jbyte) 0x86, (jbyte) 0x87 +}; +static const jchar FOUR_CHAR[] = { + (jchar) 0x8180, (jchar) 0x8382, + (jchar) 0x8584, (jchar) 0x8786 +}; + +static const jint TWO_INT[] = {(jint) 0x83828180, (jint) 0x87868584}; +static const juint MURMUR3_32_X86_CHECK_VALUE = 0xB0F57EE3; + +class AltHashingTest : public ::testing::Test { + public: + + static juint murmur3_32(const int* data, int len) { + return AltHashing::murmur3_32(data, len); + } +}; + +TEST_F(AltHashingTest, murmur3_32_byte_array_test) { + jbyte vector[256]; + jbyte hashes[4 * 256]; + + for (int i = 0; i < 256; i++) { + vector[i] = (jbyte) i; + } + + // Hash subranges {}, {0}, {0,1}, {0,1,2}, ..., {0,...,255} + for (int i = 0; i < 256; i++) { + juint hash = AltHashing::murmur3_32(256 - i, vector, i); + hashes[i * 4] = (jbyte) hash; + hashes[i * 4 + 1] = (jbyte) (hash >> 8); + hashes[i * 4 + 2] = (jbyte) (hash >> 16); + hashes[i * 4 + 3] = (jbyte) (hash >> 24); + } + + // hash to get const result. + juint final_hash = AltHashing::murmur3_32(0, hashes, 4 * 256); + + ASSERT_EQ(MURMUR3_32_X86_CHECK_VALUE, final_hash) + << "Calculated hash result not as expected."; +} + +TEST_F(AltHashingTest, equivalent_hashes_test) { + juint jbytes, jchars, ints; + + jbytes = AltHashing::murmur3_32(0, TWO_BYTE, 2); + jchars = AltHashing::murmur3_32(0, ONE_CHAR, 1); + ASSERT_EQ(jbytes, jchars) << "Hashes did not match."; + + jbytes = AltHashing::murmur3_32(0, FOUR_BYTE, 4); + jchars = AltHashing::murmur3_32(0, TWO_CHAR, 2); + ints = AltHashingTest::murmur3_32(ONE_INT, 1); + + ASSERT_EQ(jbytes, jchars) << "Hashes did not match."; + ASSERT_EQ(jbytes, ints) << "Hashes did not match."; + + jbytes = AltHashing::murmur3_32(0, SIX_BYTE, 6); + jchars = AltHashing::murmur3_32(0, THREE_CHAR, 3); + ASSERT_EQ(jbytes, jchars) << "Hashes did not match."; + + jbytes = AltHashing::murmur3_32(0, EIGHT_BYTE, 8); + jchars = AltHashing::murmur3_32(0, FOUR_CHAR, 4); + ints = AltHashingTest::murmur3_32(TWO_INT, 2); + + ASSERT_EQ(jbytes, jchars) << "Hashes did not match."; + ASSERT_EQ(jbytes, ints) << "Hashes did not match."; +} From ad62406df7b039617f6aa6693e5dc8be14f3b082 Mon Sep 17 00:00:00 2001 From: Kirill Zhaldybin Date: Wed, 24 Aug 2016 19:21:20 +0300 Subject: [PATCH 035/110] 8164743: Convert TestAsUtf8 to GTest Reviewed-by: dholmes, rprotacio --- .../share/vm/utilities/internalVMTests.cpp | 1 - hotspot/src/share/vm/utilities/utf8.cpp | 29 +---------- hotspot/test/native/utilities/test_utf8.cpp | 50 +++++++++++++++++++ 3 files changed, 51 insertions(+), 29 deletions(-) create mode 100644 hotspot/test/native/utilities/test_utf8.cpp diff --git a/hotspot/src/share/vm/utilities/internalVMTests.cpp b/hotspot/src/share/vm/utilities/internalVMTests.cpp index 70eece1f2d8..bdeb84abedf 100644 --- a/hotspot/src/share/vm/utilities/internalVMTests.cpp +++ b/hotspot/src/share/vm/utilities/internalVMTests.cpp @@ -60,7 +60,6 @@ void InternalVMTests::run() { run_unit_test(TestOldSize_test); run_unit_test(TestKlass_test); run_unit_test(TestBitMap_test); - run_unit_test(TestAsUtf8); run_unit_test(TestResourcehash_test); run_unit_test(ObjectMonitor_test); run_unit_test(Test_linked_list); diff --git a/hotspot/src/share/vm/utilities/utf8.cpp b/hotspot/src/share/vm/utilities/utf8.cpp index 93ad3e23d89..0f479bad8dd 100644 --- a/hotspot/src/share/vm/utilities/utf8.cpp +++ b/hotspot/src/share/vm/utilities/utf8.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -547,30 +547,3 @@ template int UNICODE::quoted_ascii_length(jbyte* base, int length); template int UNICODE::quoted_ascii_length(jchar* base, int length); template void UNICODE::as_quoted_ascii(const jbyte* base, int length, char* buf, int buflen); template void UNICODE::as_quoted_ascii(const jchar* base, int length, char* buf, int buflen); - - -#ifndef PRODUCT -void TestAsUtf8() { - char res[60]; - jchar str[20]; - - for (int i = 0; i < 20; i++) { - str[i] = 0x0800; // char that is 2B in UTF-16 but 3B in UTF-8 - } - str[19] = (jchar)'\0'; - - // The resulting string in UTF-8 is 3*19 bytes long, but should be truncated - UNICODE::as_utf8(str, 19, res, 10); - assert(strlen(res) == 9, "string should be truncated here"); - - UNICODE::as_utf8(str, 19, res, 18); - assert(strlen(res) == 15, "string should be truncated here"); - - UNICODE::as_utf8(str, 19, res, 20); - assert(strlen(res) == 18, "string should be truncated here"); - - // Test with an "unbounded" buffer - UNICODE::as_utf8(str, 19, res, INT_MAX); - assert(strlen(res) == 3*19, "string should end here"); -} -#endif diff --git a/hotspot/test/native/utilities/test_utf8.cpp b/hotspot/test/native/utilities/test_utf8.cpp new file mode 100644 index 00000000000..a36f016ecd0 --- /dev/null +++ b/hotspot/test/native/utilities/test_utf8.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "utilities/utf8.hpp" +#include "unittest.hpp" + +TEST(utf8, length) { + char res[60]; + jchar str[20]; + + for (int i = 0; i < 20; i++) { + str[i] = 0x0800; // char that is 2B in UTF-16 but 3B in UTF-8 + } + str[19] = (jchar) '\0'; + + // The resulting string in UTF-8 is 3*19 bytes long, but should be truncated + UNICODE::as_utf8(str, 19, res, 10); + ASSERT_EQ(strlen(res), (size_t) 9) << "string should be truncated here"; + + UNICODE::as_utf8(str, 19, res, 18); + ASSERT_EQ(strlen(res), (size_t) 15) << "string should be truncated here"; + + UNICODE::as_utf8(str, 19, res, 20); + ASSERT_EQ(strlen(res), (size_t) 18) << "string should be truncated here"; + + // Test with an "unbounded" buffer + UNICODE::as_utf8(str, 19, res, INT_MAX); + ASSERT_EQ(strlen(res), (size_t) 3 * 19) << "string should end here"; +} From 3ba0af5c09b3168b2be2b2b5ffe313cd1e6ac5d9 Mon Sep 17 00:00:00 2001 From: Dmitry Fazunenko Date: Thu, 25 Aug 2016 14:12:09 +0400 Subject: [PATCH 036/110] 8164133: Tests gc/arguments/TestAlignmentToUseLargePages.java and gc/cms/TestBubbleUpRef.java use too small heap Reviewed-by: jmasa, sangheki, kzhaldyb --- .../TestAlignmentToUseLargePages.java | 22 +++++++++---------- hotspot/test/gc/cms/TestBubbleUpRef.java | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/hotspot/test/gc/arguments/TestAlignmentToUseLargePages.java b/hotspot/test/gc/arguments/TestAlignmentToUseLargePages.java index 45d447840a1..0238ae8b37a 100644 --- a/hotspot/test/gc/arguments/TestAlignmentToUseLargePages.java +++ b/hotspot/test/gc/arguments/TestAlignmentToUseLargePages.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, 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,16 +29,16 @@ * @key gc * @key regression * @requires vm.gc=="null" - * @run main/othervm -Xms7M -Xmx9M -XX:+UseParallelGC -XX:-UseParallelOldGC -XX:+UseLargePages TestAlignmentToUseLargePages - * @run main/othervm -Xms7M -Xmx9M -XX:+UseParallelGC -XX:-UseParallelOldGC -XX:-UseLargePages TestAlignmentToUseLargePages - * @run main/othervm -Xms7M -Xmx9M -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:+UseLargePages TestAlignmentToUseLargePages - * @run main/othervm -Xms7M -Xmx9M -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:-UseLargePages TestAlignmentToUseLargePages - * @run main/othervm -Xms7M -Xmx9M -XX:+UseSerialGC -XX:+UseLargePages TestAlignmentToUseLargePages - * @run main/othervm -Xms7M -Xmx9M -XX:+UseSerialGC -XX:-UseLargePages TestAlignmentToUseLargePages - * @run main/othervm -Xms7M -Xmx9M -XX:+UseConcMarkSweepGC -XX:+UseLargePages TestAlignmentToUseLargePages - * @run main/othervm -Xms7M -Xmx9M -XX:+UseConcMarkSweepGC -XX:-UseLargePages TestAlignmentToUseLargePages - * @run main/othervm -Xms7M -Xmx9M -XX:+UseG1GC -XX:+UseLargePages TestAlignmentToUseLargePages - * @run main/othervm -Xms7M -Xmx9M -XX:+UseG1GC -XX:-UseLargePages TestAlignmentToUseLargePages + * @run main/othervm -Xms71M -Xmx91M -XX:+UseParallelGC -XX:-UseParallelOldGC -XX:+UseLargePages TestAlignmentToUseLargePages + * @run main/othervm -Xms71M -Xmx91M -XX:+UseParallelGC -XX:-UseParallelOldGC -XX:-UseLargePages TestAlignmentToUseLargePages + * @run main/othervm -Xms71M -Xmx91M -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:+UseLargePages TestAlignmentToUseLargePages + * @run main/othervm -Xms71M -Xmx91M -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:-UseLargePages TestAlignmentToUseLargePages + * @run main/othervm -Xms71M -Xmx91M -XX:+UseSerialGC -XX:+UseLargePages TestAlignmentToUseLargePages + * @run main/othervm -Xms71M -Xmx91M -XX:+UseSerialGC -XX:-UseLargePages TestAlignmentToUseLargePages + * @run main/othervm -Xms71M -Xmx91M -XX:+UseConcMarkSweepGC -XX:+UseLargePages TestAlignmentToUseLargePages + * @run main/othervm -Xms71M -Xmx91M -XX:+UseConcMarkSweepGC -XX:-UseLargePages TestAlignmentToUseLargePages + * @run main/othervm -Xms71M -Xmx91M -XX:+UseG1GC -XX:+UseLargePages TestAlignmentToUseLargePages + * @run main/othervm -Xms71M -Xmx91M -XX:+UseG1GC -XX:-UseLargePages TestAlignmentToUseLargePages */ public class TestAlignmentToUseLargePages { diff --git a/hotspot/test/gc/cms/TestBubbleUpRef.java b/hotspot/test/gc/cms/TestBubbleUpRef.java index 9cc5ffd2fd3..90a9aa5510b 100644 --- a/hotspot/test/gc/cms/TestBubbleUpRef.java +++ b/hotspot/test/gc/cms/TestBubbleUpRef.java @@ -35,7 +35,7 @@ import java.util.ListIterator; * stays nearly full. * @run main/othervm * -XX:+UseConcMarkSweepGC -XX:-CMSYield -XX:-CMSPrecleanRefLists1 - * -XX:CMSInitiatingOccupancyFraction=0 -Xmx8m TestBubbleUpRef 16000 50 10000 + * -XX:CMSInitiatingOccupancyFraction=0 -Xmx80m TestBubbleUpRef 16000 50 10000 */ /** @@ -53,7 +53,7 @@ import java.util.ListIterator; * Do it again. * * Use the following VM options - * -Xmx8m -XX:-CMSYield [-XX:+UseConcMarkSweepGC] -XX:-CMSPrecleanRefLists1 + * -Xmx80m -XX:-CMSYield [-XX:+UseConcMarkSweepGC] -XX:-CMSPrecleanRefLists1 * -XX:CMSInitiatingOccupancyFraction=0 * * Use parameter: From 820b9e7a162912f36818d6cca1ef7fefc8ec8e49 Mon Sep 17 00:00:00 2001 From: Christian Tornqvist Date: Thu, 25 Aug 2016 08:40:53 -0400 Subject: [PATCH 037/110] 8164737: Remove Unsafe dependency from ProcessTools Reviewed-by: gtriantafill, dholmes --- .../unsafe/TestUnsafeMismatchedArrayFieldAccess.java | 4 ++-- .../jvmci/compilerToVM/GetResolvedJavaMethodTest.java | 4 ++-- .../compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java | 4 ++-- .../compiler/jvmci/compilerToVM/ResolveFieldInPoolTest.java | 4 ++-- .../test/compiler/jvmci/compilerToVM/ResolveMethodTest.java | 3 ++- .../loopopts/superword/TestVectorizationWithInvariant.java | 4 ++-- hotspot/test/compiler/rtm/locking/TestRTMAbortRatio.java | 4 ++-- .../test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java | 4 ++-- .../compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java | 4 ++-- .../test/compiler/rtm/locking/TestRTMLockingThreshold.java | 4 ++-- .../test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java | 4 ++-- hotspot/test/compiler/testlibrary/rtm/XAbortProvoker.java | 4 ++-- hotspot/test/compiler/unsafe/UnsafeRaw.java | 3 ++- hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java | 3 ++- hotspot/test/gc/arguments/TestTargetSurvivorRatioFlag.java | 3 ++- hotspot/test/runtime/ErrorHandling/CreateCoredumpOnCrash.java | 4 ++-- hotspot/test/runtime/ErrorHandling/ProblematicFrameTest.java | 4 ++-- hotspot/test/runtime/Unsafe/AllocateInstance.java | 4 ++-- hotspot/test/runtime/Unsafe/AllocateMemory.java | 4 ++-- hotspot/test/runtime/Unsafe/CopyMemory.java | 4 ++-- hotspot/test/runtime/Unsafe/DefineClass.java | 4 ++-- hotspot/test/runtime/Unsafe/FieldOffset.java | 4 ++-- hotspot/test/runtime/Unsafe/GetField.java | 4 ++-- hotspot/test/runtime/Unsafe/GetPutAddress.java | 4 ++-- hotspot/test/runtime/Unsafe/GetPutBoolean.java | 4 ++-- hotspot/test/runtime/Unsafe/GetPutByte.java | 4 ++-- hotspot/test/runtime/Unsafe/GetPutChar.java | 4 ++-- hotspot/test/runtime/Unsafe/GetPutDouble.java | 4 ++-- hotspot/test/runtime/Unsafe/GetPutFloat.java | 4 ++-- hotspot/test/runtime/Unsafe/GetPutInt.java | 4 ++-- hotspot/test/runtime/Unsafe/GetPutLong.java | 4 ++-- hotspot/test/runtime/Unsafe/GetPutObject.java | 4 ++-- hotspot/test/runtime/Unsafe/GetPutShort.java | 4 ++-- hotspot/test/runtime/Unsafe/GetUncompressedObject.java | 4 ++-- hotspot/test/runtime/Unsafe/NestedUnsafe.java | 4 ++-- hotspot/test/runtime/Unsafe/PageSize.java | 4 ++-- hotspot/test/runtime/Unsafe/RangeCheck.java | 4 ++-- hotspot/test/runtime/Unsafe/Reallocate.java | 4 ++-- hotspot/test/runtime/Unsafe/SetMemory.java | 4 ++-- hotspot/test/runtime/Unsafe/ThrowException.java | 4 ++-- .../ctw/src/sun/hotspot/tools/ctw/PathHandler.java | 2 +- 41 files changed, 81 insertions(+), 77 deletions(-) diff --git a/hotspot/test/compiler/intrinsics/unsafe/TestUnsafeMismatchedArrayFieldAccess.java b/hotspot/test/compiler/intrinsics/unsafe/TestUnsafeMismatchedArrayFieldAccess.java index 973b213e221..b56d1b4e5bf 100644 --- a/hotspot/test/compiler/intrinsics/unsafe/TestUnsafeMismatchedArrayFieldAccess.java +++ b/hotspot/test/compiler/intrinsics/unsafe/TestUnsafeMismatchedArrayFieldAccess.java @@ -36,11 +36,11 @@ package compiler.intrinsics.unsafe; import jdk.internal.misc.Unsafe; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; public class TestUnsafeMismatchedArrayFieldAccess { - private static final Unsafe UNSAFE = Utils.getUnsafe(); + private static final Unsafe UNSAFE = UnsafeHelper.getUnsafe(); static { try { diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java index c04196acf5b..c1c382d768d 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java @@ -45,7 +45,7 @@ package compiler.jvmci.compilerToVM; import jdk.internal.misc.Unsafe; import jdk.test.lib.Asserts; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.vm.ci.hotspot.CompilerToVMHelper; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.hotspot.PublicMetaspaceWrapperObject; @@ -114,7 +114,7 @@ public class GetResolvedJavaMethodTest { abstract HotSpotResolvedJavaMethod getResolvedJavaMethod(); } - private static final Unsafe UNSAFE = Utils.getUnsafe(); + private static final Unsafe UNSAFE = UnsafeHelper.getUnsafe(); private static final WhiteBox WB = WhiteBox.getWhiteBox(); private static final Field METASPACE_METHOD_FIELD; private static final Class TEST_CLASS = GetResolvedJavaMethodTest.class; diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java index 4d0d5b84445..80021f8e79b 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java @@ -53,7 +53,7 @@ package compiler.jvmci.compilerToVM; import jdk.internal.misc.Unsafe; import jdk.test.lib.Asserts; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.vm.ci.hotspot.CompilerToVMHelper; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; @@ -154,7 +154,7 @@ public class GetResolvedJavaTypeTest { abstract HotSpotResolvedObjectType getResolvedJavaType(); } - private static final Unsafe UNSAFE = Utils.getUnsafe(); + private static final Unsafe UNSAFE = UnsafeHelper.getUnsafe(); private static final WhiteBox WB = WhiteBox.getWhiteBox(); private static final Class TEST_CLASS = GetResolvedJavaTypeTest.class; /* a compressed parameter for tested method is set to false because diff --git a/hotspot/test/compiler/jvmci/compilerToVM/ResolveFieldInPoolTest.java b/hotspot/test/compiler/jvmci/compilerToVM/ResolveFieldInPoolTest.java index a7307936124..4985773a831 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/ResolveFieldInPoolTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveFieldInPoolTest.java @@ -53,7 +53,7 @@ import compiler.jvmci.compilerToVM.ConstantPoolTestsHelper.DummyClasses; import jdk.internal.misc.Unsafe; import jdk.internal.org.objectweb.asm.Opcodes; import jdk.test.lib.Asserts; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.vm.ci.hotspot.CompilerToVMHelper; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; import jdk.vm.ci.meta.ConstantPool; @@ -69,7 +69,7 @@ import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.CON */ public class ResolveFieldInPoolTest { - private static final Unsafe UNSAFE = Utils.getUnsafe(); + private static final Unsafe UNSAFE = UnsafeHelper.getUnsafe(); public static void main(String[] args) throws Exception { Map typeTests = new HashMap<>(); diff --git a/hotspot/test/compiler/jvmci/compilerToVM/ResolveMethodTest.java b/hotspot/test/compiler/jvmci/compilerToVM/ResolveMethodTest.java index b6164e0c4d2..e6416fdbab6 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/ResolveMethodTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveMethodTest.java @@ -52,6 +52,7 @@ import compiler.jvmci.common.testcases.SingleSubclassedClass; import jdk.internal.misc.Unsafe; import jdk.test.lib.Asserts; import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.vm.ci.hotspot.CompilerToVMHelper; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; @@ -60,7 +61,7 @@ import java.util.HashSet; import java.util.Set; public class ResolveMethodTest { - private static final Unsafe UNSAFE = Utils.getUnsafe(); + private static final Unsafe UNSAFE = UnsafeHelper.getUnsafe(); public static void main(String args[]) { ResolveMethodTest test = new ResolveMethodTest(); diff --git a/hotspot/test/compiler/loopopts/superword/TestVectorizationWithInvariant.java b/hotspot/test/compiler/loopopts/superword/TestVectorizationWithInvariant.java index 02361b9719c..686e2f465e2 100644 --- a/hotspot/test/compiler/loopopts/superword/TestVectorizationWithInvariant.java +++ b/hotspot/test/compiler/loopopts/superword/TestVectorizationWithInvariant.java @@ -34,7 +34,7 @@ package compiler.loopopts.superword; import jdk.internal.misc.Unsafe; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; public class TestVectorizationWithInvariant { @@ -43,7 +43,7 @@ public class TestVectorizationWithInvariant { private static final long CHAR_ARRAY_OFFSET; static { - unsafe = Utils.getUnsafe(); + unsafe = UnsafeHelper.getUnsafe(); BYTE_ARRAY_OFFSET = unsafe.arrayBaseOffset(byte[].class); CHAR_ARRAY_OFFSET = unsafe.arrayBaseOffset(char[].class); } diff --git a/hotspot/test/compiler/rtm/locking/TestRTMAbortRatio.java b/hotspot/test/compiler/rtm/locking/TestRTMAbortRatio.java index 6605ef1adcf..e45212e268d 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMAbortRatio.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMAbortRatio.java @@ -49,7 +49,7 @@ import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.internal.misc.Unsafe; import jdk.test.lib.Asserts; import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.test.lib.cli.CommandLineOptionTest; import jdk.test.lib.cli.predicate.AndPredicate; @@ -125,7 +125,7 @@ public class TestRTMAbortRatio extends CommandLineOptionTest { public static class Test implements CompilableTest { private static final int TOTAL_ITERATIONS = 10000; private static final int WARMUP_ITERATIONS = 1000; - private static final Unsafe UNSAFE = Utils.getUnsafe(); + private static final Unsafe UNSAFE = UnsafeHelper.getUnsafe(); private final Object monitor = new Object(); // Following field have to be static in order to avoid escape analysis. @SuppressWarnings("UnsuedDeclaration") diff --git a/hotspot/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java b/hotspot/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java index 4f43be68d4f..21c1a612b6f 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java @@ -51,7 +51,7 @@ import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.internal.misc.Unsafe; import jdk.test.lib.Asserts; import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.test.lib.cli.CommandLineOptionTest; import jdk.test.lib.cli.predicate.AndPredicate; @@ -158,7 +158,7 @@ public class TestRTMAfterNonRTMDeopt extends CommandLineOptionTest { private static int field = 0; private static final int ITERATIONS = 10000; private static final int RANGE_CHECK_AT = ITERATIONS / 2; - private static final Unsafe UNSAFE = Utils.getUnsafe(); + private static final Unsafe UNSAFE = UnsafeHelper.getUnsafe(); private final Object monitor = new Object(); @Override diff --git a/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java b/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java index 9386321d7d0..6807d82463a 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java @@ -48,7 +48,7 @@ import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.internal.misc.Unsafe; import jdk.test.lib.Asserts; import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.test.lib.cli.CommandLineOptionTest; import jdk.test.lib.cli.predicate.AndPredicate; @@ -133,7 +133,7 @@ public class TestRTMDeoptOnLowAbortRatio extends CommandLineOptionTest { } public static class Test implements CompilableTest { - private static final Unsafe UNSAFE = Utils.getUnsafe(); + private static final Unsafe UNSAFE = UnsafeHelper.getUnsafe(); private final Object monitor = new Object(); @Override diff --git a/hotspot/test/compiler/rtm/locking/TestRTMLockingThreshold.java b/hotspot/test/compiler/rtm/locking/TestRTMLockingThreshold.java index 0f6ccbf591e..0dfea49a526 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMLockingThreshold.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMLockingThreshold.java @@ -49,7 +49,7 @@ import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.internal.misc.Unsafe; import jdk.test.lib.Asserts; import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.test.lib.cli.CommandLineOptionTest; import jdk.test.lib.cli.predicate.AndPredicate; @@ -142,7 +142,7 @@ public class TestRTMLockingThreshold extends CommandLineOptionTest { @SuppressWarnings("UnsuedDeclaration") private static int field = 0; private static final int TOTAL_ITERATIONS = 10000; - private static final Unsafe UNSAFE = Utils.getUnsafe(); + private static final Unsafe UNSAFE = UnsafeHelper.getUnsafe(); private final Object monitor = new Object(); diff --git a/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java b/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java index 29f560d39f0..e7158d4f670 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java @@ -49,7 +49,7 @@ import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.internal.misc.Unsafe; import jdk.test.lib.Asserts; import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.test.lib.cli.CommandLineOptionTest; import jdk.test.lib.cli.predicate.AndPredicate; @@ -113,7 +113,7 @@ public class TestRTMTotalCountIncrRate extends CommandLineOptionTest { public static class Test implements CompilableTest { private static final long TOTAL_ITERATIONS = 10000L; - private static final Unsafe UNSAFE = Utils.getUnsafe(); + private static final Unsafe UNSAFE = UnsafeHelper.getUnsafe(); private final Object monitor = new Object(); // Following field have to be static in order to avoid escape analysis. @SuppressWarnings("UnsuedDeclaration") diff --git a/hotspot/test/compiler/testlibrary/rtm/XAbortProvoker.java b/hotspot/test/compiler/testlibrary/rtm/XAbortProvoker.java index b7891eecad5..ab476b311c2 100644 --- a/hotspot/test/compiler/testlibrary/rtm/XAbortProvoker.java +++ b/hotspot/test/compiler/testlibrary/rtm/XAbortProvoker.java @@ -25,7 +25,7 @@ package compiler.testlibrary.rtm; import jdk.internal.misc.Unsafe; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; /** * Current RTM locking implementation force transaction abort @@ -35,7 +35,7 @@ class XAbortProvoker extends AbortProvoker { // Following field have to be static in order to avoid escape analysis. @SuppressWarnings("UnsuedDeclaration") private static int field = 0; - private static final Unsafe UNSAFE = Utils.getUnsafe(); + private static final Unsafe UNSAFE = UnsafeHelper.getUnsafe(); public XAbortProvoker() { this(new Object()); diff --git a/hotspot/test/compiler/unsafe/UnsafeRaw.java b/hotspot/test/compiler/unsafe/UnsafeRaw.java index 269ca5483e9..3bf38ca941d 100644 --- a/hotspot/test/compiler/unsafe/UnsafeRaw.java +++ b/hotspot/test/compiler/unsafe/UnsafeRaw.java @@ -35,6 +35,7 @@ package compiler.unsafe; import jdk.internal.misc.Unsafe; import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import java.util.Random; @@ -81,7 +82,7 @@ public class UnsafeRaw { } public static void main(String[] args) throws Exception { - Unsafe unsafe = Utils.getUnsafe(); + Unsafe unsafe = UnsafeHelper.getUnsafe(); final int array_size = 128; final int element_size = 4; final int magic = 0x12345678; diff --git a/hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java b/hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java index 08a5b16fc3b..51cc5550559 100644 --- a/hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java +++ b/hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java @@ -37,6 +37,7 @@ import java.util.Collections; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.internal.misc.Unsafe; public class TestMaxMinHeapFreeRatioFlags { @@ -133,7 +134,7 @@ public class TestMaxMinHeapFreeRatioFlags { */ public static class RatioVerifier { - private static final Unsafe unsafe = Utils.getUnsafe(); + private static final Unsafe unsafe = UnsafeHelper.getUnsafe(); // Size of byte array that will be allocated public static final int CHUNK_SIZE = 1024; diff --git a/hotspot/test/gc/arguments/TestTargetSurvivorRatioFlag.java b/hotspot/test/gc/arguments/TestTargetSurvivorRatioFlag.java index af91d12ddd3..2f980e5f325 100644 --- a/hotspot/test/gc/arguments/TestTargetSurvivorRatioFlag.java +++ b/hotspot/test/gc/arguments/TestTargetSurvivorRatioFlag.java @@ -46,6 +46,7 @@ import jdk.internal.misc.Unsafe; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import sun.hotspot.WhiteBox; /* In order to test that TargetSurvivorRatio affects survivor space occupancy @@ -248,7 +249,7 @@ public class TestTargetSurvivorRatioFlag { public static class TargetSurvivorRatioVerifier { static final WhiteBox wb = WhiteBox.getWhiteBox(); - static final Unsafe unsafe = Utils.getUnsafe(); + static final Unsafe unsafe = UnsafeHelper.getUnsafe(); // Desired size of memory allocated at once public static final int CHUNK_SIZE = 1024; diff --git a/hotspot/test/runtime/ErrorHandling/CreateCoredumpOnCrash.java b/hotspot/test/runtime/ErrorHandling/CreateCoredumpOnCrash.java index b6a7d1311a2..a5a19fed1df 100644 --- a/hotspot/test/runtime/ErrorHandling/CreateCoredumpOnCrash.java +++ b/hotspot/test/runtime/ErrorHandling/CreateCoredumpOnCrash.java @@ -34,13 +34,13 @@ import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.Platform; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.internal.misc.Unsafe; public class CreateCoredumpOnCrash { private static class Crasher { public static void main(String[] args) { - Utils.getUnsafe().putInt(0L, 0); + UnsafeHelper.getUnsafe().putInt(0L, 0); } } diff --git a/hotspot/test/runtime/ErrorHandling/ProblematicFrameTest.java b/hotspot/test/runtime/ErrorHandling/ProblematicFrameTest.java index 768ffae1994..e3b88c29673 100644 --- a/hotspot/test/runtime/ErrorHandling/ProblematicFrameTest.java +++ b/hotspot/test/runtime/ErrorHandling/ProblematicFrameTest.java @@ -35,14 +35,14 @@ import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.internal.misc.Unsafe; public class ProblematicFrameTest { private static class Crasher { public static void main(String[] args) { - Utils.getUnsafe().getInt(0); + UnsafeHelper.getUnsafe().getInt(0); } } diff --git a/hotspot/test/runtime/Unsafe/AllocateInstance.java b/hotspot/test/runtime/Unsafe/AllocateInstance.java index 56c7f8f95d0..ca2d56dd749 100644 --- a/hotspot/test/runtime/Unsafe/AllocateInstance.java +++ b/hotspot/test/runtime/Unsafe/AllocateInstance.java @@ -30,12 +30,12 @@ * @run main AllocateInstance */ -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.internal.misc.Unsafe; import static jdk.test.lib.Asserts.*; public class AllocateInstance { - static final Unsafe UNSAFE = Utils.getUnsafe(); + static final Unsafe UNSAFE = UnsafeHelper.getUnsafe(); class TestClass { public boolean calledConstructor = false; diff --git a/hotspot/test/runtime/Unsafe/AllocateMemory.java b/hotspot/test/runtime/Unsafe/AllocateMemory.java index c32ef73664f..afb48c24488 100644 --- a/hotspot/test/runtime/Unsafe/AllocateMemory.java +++ b/hotspot/test/runtime/Unsafe/AllocateMemory.java @@ -31,13 +31,13 @@ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:MallocMaxTestWords=100m AllocateMemory */ -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.internal.misc.Unsafe; import static jdk.test.lib.Asserts.*; public class AllocateMemory { public static void main(String args[]) throws Exception { - Unsafe unsafe = Utils.getUnsafe(); + Unsafe unsafe = UnsafeHelper.getUnsafe(); // Allocate a byte, write to the location and read back the value long address = unsafe.allocateMemory(1); diff --git a/hotspot/test/runtime/Unsafe/CopyMemory.java b/hotspot/test/runtime/Unsafe/CopyMemory.java index 3afe405db3a..0b832c3ee67 100644 --- a/hotspot/test/runtime/Unsafe/CopyMemory.java +++ b/hotspot/test/runtime/Unsafe/CopyMemory.java @@ -30,14 +30,14 @@ * @run main CopyMemory */ -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.internal.misc.Unsafe; import static jdk.test.lib.Asserts.*; public class CopyMemory { final static int LENGTH = 8; public static void main(String args[]) throws Exception { - Unsafe unsafe = Utils.getUnsafe(); + Unsafe unsafe = UnsafeHelper.getUnsafe(); long src = unsafe.allocateMemory(LENGTH); long dst = unsafe.allocateMemory(LENGTH); assertNotEquals(src, 0L); diff --git a/hotspot/test/runtime/Unsafe/DefineClass.java b/hotspot/test/runtime/Unsafe/DefineClass.java index 44f8aeaef27..613e9afef6f 100644 --- a/hotspot/test/runtime/Unsafe/DefineClass.java +++ b/hotspot/test/runtime/Unsafe/DefineClass.java @@ -34,13 +34,13 @@ import java.security.ProtectionDomain; import java.io.InputStream; import jdk.test.lib.InMemoryJavaCompiler; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.internal.misc.Unsafe; import static jdk.test.lib.Asserts.*; public class DefineClass { public static void main(String args[]) throws Exception { - Unsafe unsafe = Utils.getUnsafe(); + Unsafe unsafe = UnsafeHelper.getUnsafe(); TestClassLoader classloader = new TestClassLoader(); ProtectionDomain pd = new ProtectionDomain(null, null); diff --git a/hotspot/test/runtime/Unsafe/FieldOffset.java b/hotspot/test/runtime/Unsafe/FieldOffset.java index 43bdf871e5f..b4d425b8421 100644 --- a/hotspot/test/runtime/Unsafe/FieldOffset.java +++ b/hotspot/test/runtime/Unsafe/FieldOffset.java @@ -31,14 +31,14 @@ */ import java.lang.reflect.Field; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.internal.misc.Unsafe; import java.lang.reflect.*; import static jdk.test.lib.Asserts.*; public class FieldOffset { public static void main(String args[]) throws Exception { - Unsafe unsafe = Utils.getUnsafe(); + Unsafe unsafe = UnsafeHelper.getUnsafe(); Field[] fields = Test.class.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { diff --git a/hotspot/test/runtime/Unsafe/GetField.java b/hotspot/test/runtime/Unsafe/GetField.java index 3aa5ede2c0f..48533068f31 100644 --- a/hotspot/test/runtime/Unsafe/GetField.java +++ b/hotspot/test/runtime/Unsafe/GetField.java @@ -30,14 +30,14 @@ * @run main GetField */ -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.internal.misc.Unsafe; import java.lang.reflect.*; import static jdk.test.lib.Asserts.*; public class GetField { public static void main(String args[]) throws Exception { - Unsafe unsafe = Utils.getUnsafe(); + Unsafe unsafe = UnsafeHelper.getUnsafe(); // Unsafe.INVALID_FIELD_OFFSET is a static final int field, // make sure getField returns the correct field Field field = Unsafe.class.getField("INVALID_FIELD_OFFSET"); diff --git a/hotspot/test/runtime/Unsafe/GetPutAddress.java b/hotspot/test/runtime/Unsafe/GetPutAddress.java index 0b18d4d26c8..07fa4afa429 100644 --- a/hotspot/test/runtime/Unsafe/GetPutAddress.java +++ b/hotspot/test/runtime/Unsafe/GetPutAddress.java @@ -31,13 +31,13 @@ */ import jdk.test.lib.Platform; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.internal.misc.Unsafe; import static jdk.test.lib.Asserts.*; public class GetPutAddress { public static void main(String args[]) throws Exception { - Unsafe unsafe = Utils.getUnsafe(); + Unsafe unsafe = UnsafeHelper.getUnsafe(); int addressSize = unsafe.addressSize(); // Ensure the size returned from Unsafe.addressSize is correct assertEquals(unsafe.addressSize(), Platform.is32bit() ? 4 : 8); diff --git a/hotspot/test/runtime/Unsafe/GetPutBoolean.java b/hotspot/test/runtime/Unsafe/GetPutBoolean.java index 03bddbfd5dd..fe53ad4f911 100644 --- a/hotspot/test/runtime/Unsafe/GetPutBoolean.java +++ b/hotspot/test/runtime/Unsafe/GetPutBoolean.java @@ -31,13 +31,13 @@ */ import java.lang.reflect.Field; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.internal.misc.Unsafe; import static jdk.test.lib.Asserts.*; public class GetPutBoolean { public static void main(String args[]) throws Exception { - Unsafe unsafe = Utils.getUnsafe(); + Unsafe unsafe = UnsafeHelper.getUnsafe(); Test t = new Test(); Field field = Test.class.getField("b1"); diff --git a/hotspot/test/runtime/Unsafe/GetPutByte.java b/hotspot/test/runtime/Unsafe/GetPutByte.java index 10ccbfdcf59..9e2909e4e7d 100644 --- a/hotspot/test/runtime/Unsafe/GetPutByte.java +++ b/hotspot/test/runtime/Unsafe/GetPutByte.java @@ -31,13 +31,13 @@ */ import java.lang.reflect.Field; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.internal.misc.Unsafe; import static jdk.test.lib.Asserts.*; public class GetPutByte { public static void main(String args[]) throws Exception { - Unsafe unsafe = Utils.getUnsafe(); + Unsafe unsafe = UnsafeHelper.getUnsafe(); Test t = new Test(); Field field = Test.class.getField("b"); diff --git a/hotspot/test/runtime/Unsafe/GetPutChar.java b/hotspot/test/runtime/Unsafe/GetPutChar.java index 8a05acd7018..7fcfeea8c26 100644 --- a/hotspot/test/runtime/Unsafe/GetPutChar.java +++ b/hotspot/test/runtime/Unsafe/GetPutChar.java @@ -31,13 +31,13 @@ */ import java.lang.reflect.Field; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.internal.misc.Unsafe; import static jdk.test.lib.Asserts.*; public class GetPutChar { public static void main(String args[]) throws Exception { - Unsafe unsafe = Utils.getUnsafe(); + Unsafe unsafe = UnsafeHelper.getUnsafe(); Test t = new Test(); Field field = Test.class.getField("c"); diff --git a/hotspot/test/runtime/Unsafe/GetPutDouble.java b/hotspot/test/runtime/Unsafe/GetPutDouble.java index f9ccd548873..fb7210ae2ff 100644 --- a/hotspot/test/runtime/Unsafe/GetPutDouble.java +++ b/hotspot/test/runtime/Unsafe/GetPutDouble.java @@ -31,13 +31,13 @@ */ import java.lang.reflect.Field; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.internal.misc.Unsafe; import static jdk.test.lib.Asserts.*; public class GetPutDouble { public static void main(String args[]) throws Exception { - Unsafe unsafe = Utils.getUnsafe(); + Unsafe unsafe = UnsafeHelper.getUnsafe(); Test t = new Test(); Field field = Test.class.getField("d"); diff --git a/hotspot/test/runtime/Unsafe/GetPutFloat.java b/hotspot/test/runtime/Unsafe/GetPutFloat.java index 005b2301591..26821864435 100644 --- a/hotspot/test/runtime/Unsafe/GetPutFloat.java +++ b/hotspot/test/runtime/Unsafe/GetPutFloat.java @@ -31,13 +31,13 @@ */ import java.lang.reflect.Field; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.internal.misc.Unsafe; import static jdk.test.lib.Asserts.*; public class GetPutFloat { public static void main(String args[]) throws Exception { - Unsafe unsafe = Utils.getUnsafe(); + Unsafe unsafe = UnsafeHelper.getUnsafe(); Test t = new Test(); Field field = Test.class.getField("f"); diff --git a/hotspot/test/runtime/Unsafe/GetPutInt.java b/hotspot/test/runtime/Unsafe/GetPutInt.java index a43b7e17ef0..56b4d762974 100644 --- a/hotspot/test/runtime/Unsafe/GetPutInt.java +++ b/hotspot/test/runtime/Unsafe/GetPutInt.java @@ -30,13 +30,13 @@ */ import java.lang.reflect.Field; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.internal.misc.Unsafe; import static jdk.test.lib.Asserts.*; public class GetPutInt { public static void main(String args[]) throws Exception { - Unsafe unsafe = Utils.getUnsafe(); + Unsafe unsafe = UnsafeHelper.getUnsafe(); Test t = new Test(); Field field = Test.class.getField("i"); diff --git a/hotspot/test/runtime/Unsafe/GetPutLong.java b/hotspot/test/runtime/Unsafe/GetPutLong.java index 8feef0bce3c..d039e2275aa 100644 --- a/hotspot/test/runtime/Unsafe/GetPutLong.java +++ b/hotspot/test/runtime/Unsafe/GetPutLong.java @@ -31,13 +31,13 @@ */ import java.lang.reflect.Field; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.internal.misc.Unsafe; import static jdk.test.lib.Asserts.*; public class GetPutLong { public static void main(String args[]) throws Exception { - Unsafe unsafe = Utils.getUnsafe(); + Unsafe unsafe = UnsafeHelper.getUnsafe(); Test t = new Test(); Field field = Test.class.getField("l"); diff --git a/hotspot/test/runtime/Unsafe/GetPutObject.java b/hotspot/test/runtime/Unsafe/GetPutObject.java index aa6c75dbbe0..1ffc7b4d756 100644 --- a/hotspot/test/runtime/Unsafe/GetPutObject.java +++ b/hotspot/test/runtime/Unsafe/GetPutObject.java @@ -31,13 +31,13 @@ */ import java.lang.reflect.Field; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.internal.misc.Unsafe; import static jdk.test.lib.Asserts.*; public class GetPutObject { public static void main(String args[]) throws Exception { - Unsafe unsafe = Utils.getUnsafe(); + Unsafe unsafe = UnsafeHelper.getUnsafe(); Test t = new Test(); Object o = new Object(); Field field = Test.class.getField("o"); diff --git a/hotspot/test/runtime/Unsafe/GetPutShort.java b/hotspot/test/runtime/Unsafe/GetPutShort.java index 7a95ec23d61..ae1cb97d9ad 100644 --- a/hotspot/test/runtime/Unsafe/GetPutShort.java +++ b/hotspot/test/runtime/Unsafe/GetPutShort.java @@ -31,13 +31,13 @@ */ import java.lang.reflect.Field; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.internal.misc.Unsafe; import static jdk.test.lib.Asserts.*; public class GetPutShort { public static void main(String args[]) throws Exception { - Unsafe unsafe = Utils.getUnsafe(); + Unsafe unsafe = UnsafeHelper.getUnsafe(); Test t = new Test(); Field field = Test.class.getField("s"); diff --git a/hotspot/test/runtime/Unsafe/GetUncompressedObject.java b/hotspot/test/runtime/Unsafe/GetUncompressedObject.java index f9a70e65450..380ab8438aa 100644 --- a/hotspot/test/runtime/Unsafe/GetUncompressedObject.java +++ b/hotspot/test/runtime/Unsafe/GetUncompressedObject.java @@ -30,13 +30,13 @@ import static jdk.test.lib.Asserts.*; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.internal.misc.Unsafe; public class GetUncompressedObject { public static void main(String args[]) throws Exception { - Unsafe unsafe = Utils.getUnsafe(); + Unsafe unsafe = UnsafeHelper.getUnsafe(); // Allocate some memory and fill it with non-zero values. final int size = 32; diff --git a/hotspot/test/runtime/Unsafe/NestedUnsafe.java b/hotspot/test/runtime/Unsafe/NestedUnsafe.java index 1acd3e505f4..32d9bb74fbd 100644 --- a/hotspot/test/runtime/Unsafe/NestedUnsafe.java +++ b/hotspot/test/runtime/Unsafe/NestedUnsafe.java @@ -35,7 +35,7 @@ import java.security.ProtectionDomain; import java.io.InputStream; import java.lang.*; import jdk.test.lib.InMemoryJavaCompiler; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.internal.misc.Unsafe; import static jdk.test.lib.Asserts.*; @@ -50,7 +50,7 @@ public class NestedUnsafe { " } } "); public static void main(String args[]) throws Exception { - Unsafe unsafe = Utils.getUnsafe(); + Unsafe unsafe = UnsafeHelper.getUnsafe(); Class klass = unsafe.defineAnonymousClass(NestedUnsafe.class, klassbuf, new Object[0]); unsafe.ensureClassInitialized(klass); diff --git a/hotspot/test/runtime/Unsafe/PageSize.java b/hotspot/test/runtime/Unsafe/PageSize.java index 39b6c7cf7fa..a0b487a4dff 100644 --- a/hotspot/test/runtime/Unsafe/PageSize.java +++ b/hotspot/test/runtime/Unsafe/PageSize.java @@ -31,13 +31,13 @@ */ import java.lang.reflect.Field; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.internal.misc.Unsafe; import static jdk.test.lib.Asserts.*; public class PageSize { public static void main(String args[]) throws Exception { - Unsafe unsafe = Utils.getUnsafe(); + Unsafe unsafe = UnsafeHelper.getUnsafe(); int pageSize = unsafe.pageSize(); for (int n = 1; n != 0; n <<= 1) { diff --git a/hotspot/test/runtime/Unsafe/RangeCheck.java b/hotspot/test/runtime/Unsafe/RangeCheck.java index 76ccea330e5..e9e9f224a29 100644 --- a/hotspot/test/runtime/Unsafe/RangeCheck.java +++ b/hotspot/test/runtime/Unsafe/RangeCheck.java @@ -33,7 +33,7 @@ import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.Platform; -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.internal.misc.Unsafe; @@ -60,7 +60,7 @@ public class RangeCheck { public static class DummyClassWithMainRangeCheck { public static void main(String args[]) throws Exception { - Unsafe unsafe = Utils.getUnsafe(); + Unsafe unsafe = UnsafeHelper.getUnsafe(); unsafe.getObject(new DummyClassWithMainRangeCheck(), Short.MAX_VALUE); } } diff --git a/hotspot/test/runtime/Unsafe/Reallocate.java b/hotspot/test/runtime/Unsafe/Reallocate.java index 5dec176fa04..837e587fc28 100644 --- a/hotspot/test/runtime/Unsafe/Reallocate.java +++ b/hotspot/test/runtime/Unsafe/Reallocate.java @@ -31,13 +31,13 @@ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:MallocMaxTestWords=100m Reallocate */ -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.internal.misc.Unsafe; import static jdk.test.lib.Asserts.*; public class Reallocate { public static void main(String args[]) throws Exception { - Unsafe unsafe = Utils.getUnsafe(); + Unsafe unsafe = UnsafeHelper.getUnsafe(); long address = unsafe.allocateMemory(1); assertNotEquals(address, 0L); diff --git a/hotspot/test/runtime/Unsafe/SetMemory.java b/hotspot/test/runtime/Unsafe/SetMemory.java index a426c741a3d..77eed63f60a 100644 --- a/hotspot/test/runtime/Unsafe/SetMemory.java +++ b/hotspot/test/runtime/Unsafe/SetMemory.java @@ -30,13 +30,13 @@ * @run main SetMemory */ -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.internal.misc.Unsafe; import static jdk.test.lib.Asserts.*; public class SetMemory { public static void main(String args[]) throws Exception { - Unsafe unsafe = Utils.getUnsafe(); + Unsafe unsafe = UnsafeHelper.getUnsafe(); long address = unsafe.allocateMemory(1); assertNotEquals(address, 0L); unsafe.setMemory(address, 1, (byte)17); diff --git a/hotspot/test/runtime/Unsafe/ThrowException.java b/hotspot/test/runtime/Unsafe/ThrowException.java index 5056000acb3..465618c3cff 100644 --- a/hotspot/test/runtime/Unsafe/ThrowException.java +++ b/hotspot/test/runtime/Unsafe/ThrowException.java @@ -30,13 +30,13 @@ * @run main ThrowException */ -import jdk.test.lib.Utils; +import jdk.test.lib.unsafe.UnsafeHelper; import jdk.internal.misc.Unsafe; import static jdk.test.lib.Asserts.*; public class ThrowException { public static void main(String args[]) throws Exception { - Unsafe unsafe = Utils.getUnsafe(); + Unsafe unsafe = UnsafeHelper.getUnsafe(); try { unsafe.throwException(new TestException()); } catch (Throwable t) { diff --git a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java index a8e149161f4..a86010c84ae 100644 --- a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java +++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java @@ -39,7 +39,7 @@ import java.util.regex.Pattern; * Concrete subclasses should implement method {@link #process()}. */ public abstract class PathHandler { - private static final Unsafe UNSAFE = jdk.test.lib.Utils.getUnsafe(); + private static final Unsafe UNSAFE = jdk.test.lib.unsafe.UnsafeHelper.getUnsafe(); private static final AtomicLong CLASS_COUNT = new AtomicLong(0L); private static volatile boolean CLASSES_LIMIT_REACHED = false; private static final Pattern JAR_IN_DIR_PATTERN From c6c1bee762ec8b9f1ab316ee4637bf2b3cb19473 Mon Sep 17 00:00:00 2001 From: Rachel Protacio Date: Thu, 25 Aug 2016 09:23:45 -0400 Subject: [PATCH 038/110] 8148854: Class names "SomeClass" and "LSomeClass;" treated by JVM as an equivalent Added default format checking of class names loaded by the app class loader Reviewed-by: coleenp, lfoltan --- .../share/vm/classfile/classFileParser.cpp | 13 +- hotspot/src/share/vm/classfile/verifier.cpp | 2 +- hotspot/src/share/vm/classfile/verifier.hpp | 6 +- hotspot/src/share/vm/runtime/reflection.cpp | 2 +- .../test/runtime/ClassFile/BadHelloWorld.jcod | 138 ++++++++++++++++++ .../runtime/ClassFile/FormatCheckingTest.java | 45 ++++++ 6 files changed, 200 insertions(+), 6 deletions(-) create mode 100644 hotspot/test/runtime/ClassFile/BadHelloWorld.jcod create mode 100644 hotspot/test/runtime/ClassFile/FormatCheckingTest.java diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index 30262696a8c..13c8ce71e9e 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -5402,6 +5402,17 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, bool changed_by_loa debug_only(ik->verify();) } +static bool relax_format_check_for(ClassLoaderData* loader_data) { + bool trusted = (loader_data->is_the_null_class_loader_data() || + SystemDictionary::is_platform_class_loader(loader_data->class_loader())); + bool need_verify = + // verifyAll + (BytecodeVerificationLocal && BytecodeVerificationRemote) || + // verifyRemote + (!BytecodeVerificationLocal && BytecodeVerificationRemote && !trusted); + return !need_verify; +} + ClassFileParser::ClassFileParser(ClassFileStream* stream, Symbol* name, ClassLoaderData* loader_data, @@ -5490,7 +5501,7 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream, // Check if verification needs to be relaxed for this class file // Do not restrict it to jdk1.0 or jdk1.1 to maintain backward compatibility (4982376) - _relax_verify = Verifier::relax_verify_for(_loader_data->class_loader()); + _relax_verify = relax_format_check_for(_loader_data); parse_stream(stream, CHECK); diff --git a/hotspot/src/share/vm/classfile/verifier.cpp b/hotspot/src/share/vm/classfile/verifier.cpp index c0976d55d4b..2194859c30c 100644 --- a/hotspot/src/share/vm/classfile/verifier.cpp +++ b/hotspot/src/share/vm/classfile/verifier.cpp @@ -88,7 +88,7 @@ bool Verifier::should_verify_for(oop class_loader, bool should_verify_class) { BytecodeVerificationLocal : BytecodeVerificationRemote; } -bool Verifier::relax_verify_for(oop loader) { +bool Verifier::relax_access_for(oop loader) { bool trusted = java_lang_ClassLoader::is_trusted_loader(loader); bool need_verify = // verifyAll diff --git a/hotspot/src/share/vm/classfile/verifier.hpp b/hotspot/src/share/vm/classfile/verifier.hpp index a613c62a3d5..f4c00eb9b1d 100644 --- a/hotspot/src/share/vm/classfile/verifier.hpp +++ b/hotspot/src/share/vm/classfile/verifier.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, 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,8 +58,8 @@ class Verifier : AllStatic { // -Xverify:all/none override this value static bool should_verify_for(oop class_loader, bool should_verify_class); - // Relax certain verifier checks to enable some broken 1.1 apps to run on 1.2. - static bool relax_verify_for(oop class_loader); + // Relax certain access checks to enable some broken 1.1 apps to run on 1.2. + static bool relax_access_for(oop class_loader); // Print output for class+resolve static void trace_class_resolution(Klass* resolve_class, InstanceKlass* verify_class); diff --git a/hotspot/src/share/vm/runtime/reflection.cpp b/hotspot/src/share/vm/runtime/reflection.cpp index 7b2753e516f..ae574a4edbf 100644 --- a/hotspot/src/share/vm/runtime/reflection.cpp +++ b/hotspot/src/share/vm/runtime/reflection.cpp @@ -446,7 +446,7 @@ static bool can_relax_access_check_for(const Klass* accessor, (accessor_ik->major_version() < Verifier::STRICTER_ACCESS_CTRL_CHECK_VERSION && accessee_ik->major_version() < Verifier::STRICTER_ACCESS_CTRL_CHECK_VERSION)) { return classloader_only && - Verifier::relax_verify_for(accessor_ik->class_loader()) && + Verifier::relax_access_for(accessor_ik->class_loader()) && accessor_ik->protection_domain() == accessee_ik->protection_domain() && accessor_ik->class_loader() == accessee_ik->class_loader(); } diff --git a/hotspot/test/runtime/ClassFile/BadHelloWorld.jcod b/hotspot/test/runtime/ClassFile/BadHelloWorld.jcod new file mode 100644 index 00000000000..9b984e602d6 --- /dev/null +++ b/hotspot/test/runtime/ClassFile/BadHelloWorld.jcod @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file fuzzes the class name #15 to have a leading 'L' and ending ';'. + */ + +class BadHelloWorld { + 0xCAFEBABE; + 0; // minor version + 52; // version + [31] { // Constant Pool + ; // first element is empty + Utf8 "BadHelloWorld"; // #1 at 0x0A + class #1; // #2 at 0x1A + Utf8 "java/lang/Object"; // #3 at 0x1D + class #3; // #4 at 0x30 + Utf8 ""; // #5 at 0x33 + Utf8 "()V"; // #6 at 0x3C + NameAndType #5 #6; // #7 at 0x42 + Method #4 #7; // #8 at 0x47 + Utf8 "toString"; // #9 at 0x4C + Utf8 "()Ljava/lang/String;"; // #10 at 0x57 + Utf8 "Hello, world!"; // #11 at 0x6E + String #11; // #12 at 0x7E + Utf8 "main"; // #13 at 0x81 + Utf8 "([Ljava/lang/String;)V"; // #14 at 0x88 + Utf8 "LBadHelloWorld;"; // #15 at 0xA1 + class #15; // #16 at 0xB3 + Method #16 #7; // #17 at 0xB6 + Utf8 "java/lang/System"; // #18 at 0xBB + class #18; // #19 at 0xCE + Utf8 "out"; // #20 at 0xD1 + Utf8 "Ljava/io/PrintStream;"; // #21 at 0xD7 + NameAndType #20 #21; // #22 at 0xEF + Field #19 #22; // #23 at 0xF4 + Utf8 "java/io/PrintStream"; // #24 at 0xF9 + class #24; // #25 at 0x010F + Utf8 "println"; // #26 at 0x0112 + Utf8 "(Ljava/lang/Object;)V"; // #27 at 0x011C + NameAndType #26 #27; // #28 at 0x0134 + Method #25 #28; // #29 at 0x0139 + Utf8 "Code"; // #30 at 0x013E + } // Constant Pool + + 0x0021; // access + #2;// this_cpx + #4;// super_cpx + + [0] { // Interfaces + } // Interfaces + + [0] { // fields + } // fields + + [3] { // methods + { // Member at 0x0151 + 0x0001; // access + #5; // name_cpx + #6; // sig_cpx + [1] { // Attributes + Attr(#30, 17) { // Code at 0x0159 + 1; // max_stack + 1; // max_locals + Bytes[5]{ + 0x2AB70008B1; + }; + [0] { // Traps + } // end Traps + [0] { // Attributes + } // Attributes + } // end Code + } // Attributes + } // Member + ; + { // Member at 0x0170 + 0x0001; // access + #9; // name_cpx + #10; // sig_cpx + [1] { // Attributes + Attr(#30, 15) { // Code at 0x0178 + 1; // max_stack + 1; // max_locals + Bytes[3]{ + 0x120CB0; + }; + [0] { // Traps + } // end Traps + [0] { // Attributes + } // Attributes + } // end Code + } // Attributes + } // Member + ; + { // Member at 0x018D + 0x0089; // access + #13; // name_cpx + #14; // sig_cpx + [1] { // Attributes + Attr(#30, 28) { // Code at 0x0195 + 2; // max_stack + 2; // max_locals + Bytes[16]{ + 0xBB001059B700114C; + 0xB200172BB6001DB1; + }; + [0] { // Traps + } // end Traps + [0] { // Attributes + } // Attributes + } // end Code + } // Attributes + } // Member + } // methods + + [0] { // Attributes + } // Attributes +} // end class BadHelloWorld diff --git a/hotspot/test/runtime/ClassFile/FormatCheckingTest.java b/hotspot/test/runtime/ClassFile/FormatCheckingTest.java new file mode 100644 index 00000000000..243f00f2cf1 --- /dev/null +++ b/hotspot/test/runtime/ClassFile/FormatCheckingTest.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8148854 + * @summary Ensure class name loaded by app class loader is format checked by default + * @library /test/lib + * @compile BadHelloWorld.jcod + * @modules java.base/jdk.internal.misc + * java.management + * @run main FormatCheckingTest + */ + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class FormatCheckingTest { + public static void main(String args[]) throws Throwable { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("BadHelloWorld"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("java.lang.ClassFormatError: Illegal class name"); + output.shouldHaveExitValue(1); + } +} From d1eb1ae8eace18fb68d0862f1159fd3105074df6 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Thu, 25 Aug 2016 12:24:05 +0900 Subject: [PATCH 039/110] 8163581: Heap Parameters in HSDB cannot handle G1CollectedHeap Reviewed-by: dholmes, sjohanss --- .../classes/sun/jvm/hotspot/gc/g1/G1CollectedHeap.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/g1/G1CollectedHeap.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/g1/G1CollectedHeap.java index f9f0a07838d..a9e91802bba 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/g1/G1CollectedHeap.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/g1/G1CollectedHeap.java @@ -24,6 +24,7 @@ package sun.jvm.hotspot.gc.g1; +import java.io.PrintStream; import java.util.Iterator; import java.util.Observable; import java.util.Observer; @@ -125,6 +126,15 @@ public class G1CollectedHeap extends CollectedHeap { return CollectedHeapName.G1_COLLECTED_HEAP; } + @Override + public void printOn(PrintStream tty) { + MemRegion mr = reservedRegion(); + + tty.print("garbage-first heap"); + tty.print(" [" + mr.start() + ", " + mr.end() + "]"); + tty.println(" region size " + (HeapRegion.grainBytes() / 1024) + "K"); + } + public G1CollectedHeap(Address addr) { super(addr); } From 8214dd5bfcc7b5b2b48f59213d6cf99716f9565e Mon Sep 17 00:00:00 2001 From: Christian Tornqvist Date: Thu, 25 Aug 2016 08:39:06 -0400 Subject: [PATCH 040/110] 8164737: Remove Unsafe dependency from ProcessTools Reviewed-by: gtriantafill, dholmes --- test/lib/jdk/test/lib/Utils.java | 19 ------- .../lib/jdk/test/lib/unsafe/UnsafeHelper.java | 52 +++++++++++++++++++ 2 files changed, 52 insertions(+), 19 deletions(-) create mode 100644 test/lib/jdk/test/lib/unsafe/UnsafeHelper.java diff --git a/test/lib/jdk/test/lib/Utils.java b/test/lib/jdk/test/lib/Utils.java index aececb0301f..66ad61e8981 100644 --- a/test/lib/jdk/test/lib/Utils.java +++ b/test/lib/jdk/test/lib/Utils.java @@ -25,7 +25,6 @@ package jdk.test.lib; import java.io.File; import java.io.IOException; -import java.lang.reflect.Field; import java.net.InetAddress; import java.net.MalformedURLException; import java.net.ServerSocket; @@ -51,7 +50,6 @@ import java.util.function.Consumer; import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; -import jdk.internal.misc.Unsafe; import static jdk.test.lib.Asserts.assertTrue; import jdk.test.lib.process.ProcessTools; @@ -87,8 +85,6 @@ public final class Utils { */ public static final String TEST_SRC = System.getProperty("test.src", "").trim(); - private static Unsafe unsafe = null; - /** * Defines property name for seed value. */ @@ -373,21 +369,6 @@ public final class Utils { return new String(Files.readAllBytes(filePath)); } - /** - * @return Unsafe instance. - */ - public static synchronized Unsafe getUnsafe() { - if (unsafe == null) { - try { - Field f = Unsafe.class.getDeclaredField("theUnsafe"); - f.setAccessible(true); - unsafe = (Unsafe) f.get(null); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new RuntimeException("Unable to get Unsafe instance.", e); - } - } - return unsafe; - } private static final char[] hexArray = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; /** diff --git a/test/lib/jdk/test/lib/unsafe/UnsafeHelper.java b/test/lib/jdk/test/lib/unsafe/UnsafeHelper.java new file mode 100644 index 00000000000..4a6c92644a6 --- /dev/null +++ b/test/lib/jdk/test/lib/unsafe/UnsafeHelper.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.unsafe; + +import jdk.internal.misc.Unsafe; +import java.lang.reflect.Field; + + +/** + * Helper class for accessing the jdk.internal.misc.Unsafe functionality + */ +public final class UnsafeHelper { + private static Unsafe unsafe = null; + + /** + * @return Unsafe instance. + */ + public static synchronized Unsafe getUnsafe() { + if (unsafe == null) { + try { + Field f = Unsafe.class.getDeclaredField("theUnsafe"); + f.setAccessible(true); + unsafe = (Unsafe) f.get(null); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new RuntimeException("Unable to get Unsafe instance.", e); + } + } + return unsafe; + } +} + From 99f0753054d6324a3203473e0e75a759522c1dca Mon Sep 17 00:00:00 2001 From: Marcus Larsson Date: Mon, 29 Aug 2016 14:11:22 +0200 Subject: [PATCH 041/110] 8157948: UL allows same log file with multiple file= Reviewed-by: dholmes, rehn --- hotspot/src/share/vm/logging/log.cpp | 2 +- .../src/share/vm/logging/logConfiguration.cpp | 117 ++++++++++++------ .../src/share/vm/logging/logConfiguration.hpp | 2 +- .../src/share/vm/logging/logFileOutput.cpp | 4 +- .../src/share/vm/logging/logFileOutput.hpp | 1 + .../native/logging/test_logConfiguration.cpp | 27 ++++ .../native/logging/test_logFileOutput.cpp | 2 +- 7 files changed, 111 insertions(+), 44 deletions(-) diff --git a/hotspot/src/share/vm/logging/log.cpp b/hotspot/src/share/vm/logging/log.cpp index 8796c1794e4..3f63d143f27 100644 --- a/hotspot/src/share/vm/logging/log.cpp +++ b/hotspot/src/share/vm/logging/log.cpp @@ -1161,7 +1161,7 @@ void Test_invalid_log_file() { // Attempt to log to a directory (existing log not a regular file) create_directory(target_name); - LogFileOutput bad_file("tmplogdir"); + LogFileOutput bad_file("file=tmplogdir"); assert(bad_file.initialize("", &ss) == false, "file was initialized " "when there was an existing directory with the same name"); assert(strstr(ss.as_string(), "tmplogdir is not a regular file") != NULL, diff --git a/hotspot/src/share/vm/logging/logConfiguration.cpp b/hotspot/src/share/vm/logging/logConfiguration.cpp index 0817a650e70..29a65cd3a1f 100644 --- a/hotspot/src/share/vm/logging/logConfiguration.cpp +++ b/hotspot/src/share/vm/logging/logConfiguration.cpp @@ -44,6 +44,9 @@ size_t LogConfiguration::_n_outputs = 0; LogConfiguration::UpdateListenerFunction* LogConfiguration::_listener_callbacks = NULL; size_t LogConfiguration::_n_listener_callbacks = 0; +// LogFileOutput is the default type of output, its type prefix should be used if no type was specified +static const char* implicit_output_prefix = LogFileOutput::Prefix; + // Stack object to take the lock for configuring the logging. // Should only be held during the critical parts of the configuration // (when calling configure_output or reading/modifying the outputs array). @@ -107,6 +110,55 @@ void LogConfiguration::finalize() { FREE_C_HEAP_ARRAY(LogOutput*, _outputs); } +// Normalizes the given LogOutput name to type=name form. +// For example, foo, "foo", file="foo", will all be normalized to file=foo (no quotes, prefixed). +static bool normalize_output_name(const char* full_name, char* buffer, size_t len, outputStream* errstream) { + const char* start_quote = strchr(full_name, '"'); + const char* equals = strchr(full_name, '='); + const bool quoted = start_quote != NULL; + const bool is_stdout_or_stderr = (strcmp(full_name, "stdout") == 0 || strcmp(full_name, "stderr") == 0); + + // ignore equals sign within quotes + if (quoted && equals > start_quote) { + equals = NULL; + } + + const char* prefix = ""; + size_t prefix_len = 0; + const char* name = full_name; + if (equals != NULL) { + // split on equals sign + name = equals + 1; + prefix = full_name; + prefix_len = equals - full_name + 1; + } else if (!is_stdout_or_stderr) { + prefix = implicit_output_prefix; + prefix_len = strlen(prefix); + } + size_t name_len = strlen(name); + + if (quoted) { + const char* end_quote = strchr(start_quote + 1, '"'); + if (end_quote == NULL) { + errstream->print_cr("Output name has opening quote but is missing a terminating quote."); + return false; + } + if (start_quote != name || end_quote[1] != '\0') { + errstream->print_cr("Output name can not be partially quoted." + " Either surround the whole name with quotation marks," + " or do not use quotation marks at all."); + return false; + } + // strip start and end quote + name++; + name_len -= 2; + } + + int ret = jio_snprintf(buffer, len, "%.*s%.*s", prefix_len, prefix, name_len, name); + assert(ret > 0, "buffer issue"); + return true; +} + size_t LogConfiguration::find_output(const char* name) { for (size_t i = 0; i < _n_outputs; i++) { if (strcmp(_outputs[i]->name(), name) == 0) { @@ -116,39 +168,14 @@ size_t LogConfiguration::find_output(const char* name) { return SIZE_MAX; } -LogOutput* LogConfiguration::new_output(char* name, const char* options, outputStream* errstream) { - const char* type; - char* equals_pos = strchr(name, '='); - if (equals_pos == NULL) { - type = "file"; - } else { - *equals_pos = '\0'; - type = name; - name = equals_pos + 1; - } - - // Check if name is quoted, and if so, strip the quotes - char* quote = strchr(name, '"'); - if (quote != NULL) { - char* end_quote = strchr(name + 1, '"'); - if (end_quote == NULL) { - errstream->print_cr("Output name has opening quote but is missing a terminating quote."); - return NULL; - } else if (quote != name || end_quote[1] != '\0') { - errstream->print_cr("Output name can not be partially quoted." - " Either surround the whole name with quotation marks," - " or do not use quotation marks at all."); - return NULL; - } - name++; - *end_quote = '\0'; - } - +LogOutput* LogConfiguration::new_output(const char* name, + const char* options, + outputStream* errstream) { LogOutput* output; - if (strcmp(type, "file") == 0) { + if (strncmp(name, LogFileOutput::Prefix, strlen(LogFileOutput::Prefix)) == 0) { output = new LogFileOutput(name); } else { - errstream->print_cr("Unsupported log output type."); + errstream->print_cr("Unsupported log output type: %s", name); return NULL; } @@ -374,25 +401,35 @@ bool LogConfiguration::parse_log_arguments(const char* outputstr, ConfigurationLock cl; size_t idx; - if (outputstr[0] == '#') { - int ret = sscanf(outputstr+1, SIZE_FORMAT, &idx); + if (outputstr[0] == '#') { // Output specified using index + int ret = sscanf(outputstr + 1, SIZE_FORMAT, &idx); if (ret != 1 || idx >= _n_outputs) { errstream->print_cr("Invalid output index '%s'", outputstr); return false; } - } else { - idx = find_output(outputstr); + } else { // Output specified using name + // Normalize the name, stripping quotes and ensures it includes type prefix + size_t len = strlen(outputstr) + strlen(implicit_output_prefix) + 1; + char* normalized = NEW_C_HEAP_ARRAY(char, len, mtLogging); + if (!normalize_output_name(outputstr, normalized, len, errstream)) { + return false; + } + + idx = find_output(normalized); if (idx == SIZE_MAX) { - char* tmp = os::strdup_check_oom(outputstr, mtLogging); - LogOutput* output = new_output(tmp, output_options, errstream); - os::free(tmp); - if (output == NULL) { - return false; + // Attempt to create and add the output + LogOutput* output = new_output(normalized, output_options, errstream); + if (output != NULL) { + idx = add_output(output); } - idx = add_output(output); } else if (output_options != NULL && strlen(output_options) > 0) { errstream->print_cr("Output options for existing outputs are ignored."); } + + FREE_C_HEAP_ARRAY(char, normalized); + if (idx == SIZE_MAX) { + return false; + } } configure_output(idx, expr, decorators); notify_update_listeners(); diff --git a/hotspot/src/share/vm/logging/logConfiguration.hpp b/hotspot/src/share/vm/logging/logConfiguration.hpp index 9efbadddd02..344e66af5e2 100644 --- a/hotspot/src/share/vm/logging/logConfiguration.hpp +++ b/hotspot/src/share/vm/logging/logConfiguration.hpp @@ -59,7 +59,7 @@ class LogConfiguration : public AllStatic { static size_t _n_listener_callbacks; // Create a new output. Returns NULL if failed. - static LogOutput* new_output(char* name, const char* options, outputStream* errstream); + static LogOutput* new_output(const char* name, const char* options, outputStream* errstream); // Add an output to the list of configured outputs. Returns the assigned index. static size_t add_output(LogOutput* out); diff --git a/hotspot/src/share/vm/logging/logFileOutput.cpp b/hotspot/src/share/vm/logging/logFileOutput.cpp index 77cad087a0c..3f431ef3e54 100644 --- a/hotspot/src/share/vm/logging/logFileOutput.cpp +++ b/hotspot/src/share/vm/logging/logFileOutput.cpp @@ -31,6 +31,7 @@ #include "utilities/globalDefinitions.hpp" #include "utilities/defaultStream.hpp" +const char* LogFileOutput::Prefix = "file="; const char* LogFileOutput::FileOpenMode = "a"; const char* LogFileOutput::PidFilenamePlaceholder = "%p"; const char* LogFileOutput::TimestampFilenamePlaceholder = "%t"; @@ -45,7 +46,8 @@ LogFileOutput::LogFileOutput(const char* name) _file_name(NULL), _archive_name(NULL), _archive_name_len(0), _rotate_size(DefaultFileSize), _file_count(DefaultFileCount), _current_size(0), _current_file(0), _rotation_semaphore(1) { - _file_name = make_file_name(name, _pid_str, _vm_start_time_str); + assert(strstr(name, Prefix) == name, "invalid output name '%s': missing prefix: %s", name, Prefix); + _file_name = make_file_name(name + strlen(Prefix), _pid_str, _vm_start_time_str); } void LogFileOutput::set_file_name_parameters(jlong vm_start_time) { diff --git a/hotspot/src/share/vm/logging/logFileOutput.hpp b/hotspot/src/share/vm/logging/logFileOutput.hpp index 3ec3a771985..7808ab33f81 100644 --- a/hotspot/src/share/vm/logging/logFileOutput.hpp +++ b/hotspot/src/share/vm/logging/logFileOutput.hpp @@ -91,6 +91,7 @@ class LogFileOutput : public LogFileStreamOutput { return _name; } + static const char* Prefix; static void set_file_name_parameters(jlong start_time); }; diff --git a/hotspot/test/native/logging/test_logConfiguration.cpp b/hotspot/test/native/logging/test_logConfiguration.cpp index b07839ad04a..a5e52ca80ca 100644 --- a/hotspot/test/native/logging/test_logConfiguration.cpp +++ b/hotspot/test/native/logging/test_logConfiguration.cpp @@ -308,3 +308,30 @@ TEST_F(LogConfigurationTest, parse_invalid_tagset) { EXPECT_TRUE(string_contains_substring(msg, "No tag set matches selection(s):")); EXPECT_TRUE(string_contains_substring(msg, invalid_tagset)); } + +TEST_F(LogConfigurationTest, output_name_normalization) { + const char* patterns[] = { "%s", "file=%s", "\"%s\"", "file=\"%s\"" }; + char buf[1 * K]; + for (size_t i = 0; i < ARRAY_SIZE(patterns); i++) { + int ret = jio_snprintf(buf, sizeof(buf), patterns[i], TestLogFileName); + ASSERT_NE(-1, ret); + set_log_config(buf, "logging=trace"); + EXPECT_TRUE(is_described("#2: ")); + EXPECT_TRUE(is_described(TestLogFileName)); + EXPECT_FALSE(is_described("#3: ")) + << "duplicate file output due to incorrect normalization for pattern: " << patterns[i]; + } + + // Make sure prefixes are ignored when used within quotes + // (this should create a log with "file=" in its filename) + int ret = jio_snprintf(buf, sizeof(buf), "\"file=%s\"", TestLogFileName); + ASSERT_NE(-1, ret); + set_log_config(buf, "logging=trace"); + EXPECT_TRUE(is_described("#3: ")) << "prefix within quotes not ignored as it should be"; + set_log_config(buf, "all=off"); + + // Remove the extra log file created + ret = jio_snprintf(buf, sizeof(buf), "file=%s", TestLogFileName); + ASSERT_NE(-1, ret); + delete_file(buf); +} diff --git a/hotspot/test/native/logging/test_logFileOutput.cpp b/hotspot/test/native/logging/test_logFileOutput.cpp index da13e539412..b561048e7a5 100644 --- a/hotspot/test/native/logging/test_logFileOutput.cpp +++ b/hotspot/test/native/logging/test_logFileOutput.cpp @@ -29,7 +29,7 @@ #include "utilities/globalDefinitions.hpp" #include "utilities/ostream.hpp" -static const char* name = "testlog.pid%p.%t.log"; +static const char* name = "file=testlog.pid%p.%t.log"; // Test parsing a bunch of valid file output options TEST(LogFileOutput, parse_valid) { From d871b35f4074415a12cc8ca88284617a0254ba42 Mon Sep 17 00:00:00 2001 From: Kirill Zhaldybin Date: Mon, 29 Aug 2016 20:15:12 +0300 Subject: [PATCH 042/110] 8164230: Convert TestCodeCacheRemSet_test to GTest Reviewed-by: mgerdin, dfazunen --- .../src/share/vm/gc/g1/g1CodeCacheRemSet.cpp | 160 +++--------------- .../src/share/vm/gc/g1/g1CodeCacheRemSet.hpp | 8 +- .../src/share/vm/gc/g1/g1CodeRootSetTable.hpp | 76 +++++++++ .../share/vm/utilities/internalVMTests.cpp | 1 - .../native/gc/g1/test_g1CodeCacheRemSet.cpp | 94 ++++++++++ 5 files changed, 200 insertions(+), 139 deletions(-) create mode 100644 hotspot/src/share/vm/gc/g1/g1CodeRootSetTable.hpp create mode 100644 hotspot/test/native/gc/g1/test_g1CodeCacheRemSet.cpp diff --git a/hotspot/src/share/vm/gc/g1/g1CodeCacheRemSet.cpp b/hotspot/src/share/vm/gc/g1/g1CodeCacheRemSet.cpp index afbe72c8c6a..88611f472ca 100644 --- a/hotspot/src/share/vm/gc/g1/g1CodeCacheRemSet.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CodeCacheRemSet.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "code/codeCache.hpp" #include "code/nmethod.hpp" +#include "gc/g1/g1CodeRootSetTable.hpp" #include "gc/g1/g1CodeCacheRemSet.hpp" #include "gc/g1/heapRegion.hpp" #include "memory/heap.hpp" @@ -33,58 +34,13 @@ #include "utilities/hashtable.inline.hpp" #include "utilities/stack.inline.hpp" -class CodeRootSetTable : public Hashtable { - friend class G1CodeRootSetTest; - typedef HashtableEntry Entry; +G1CodeRootSetTable* volatile G1CodeRootSetTable::_purge_list = NULL; - static CodeRootSetTable* volatile _purge_list; - - CodeRootSetTable* _purge_next; - - unsigned int compute_hash(nmethod* nm) { - uintptr_t hash = (uintptr_t)nm; - return hash ^ (hash >> 7); // code heap blocks are 128byte aligned - } - - void remove_entry(Entry* e, Entry* previous); - Entry* new_entry(nmethod* nm); - - public: - CodeRootSetTable(int size) : Hashtable(size, sizeof(Entry)), _purge_next(NULL) {} - ~CodeRootSetTable(); - - // Needs to be protected locks - bool add(nmethod* nm); - bool remove(nmethod* nm); - - // Can be called without locking - bool contains(nmethod* nm); - - int entry_size() const { return BasicHashtable::entry_size(); } - - void copy_to(CodeRootSetTable* new_table); - void nmethods_do(CodeBlobClosure* blk); - - template - int remove_if(CB& should_remove); - - static void purge_list_append(CodeRootSetTable* tbl); - static void purge(); - - static size_t static_mem_size() { - return sizeof(_purge_list); - } - - size_t mem_size(); -}; - -CodeRootSetTable* volatile CodeRootSetTable::_purge_list = NULL; - -size_t CodeRootSetTable::mem_size() { - return sizeof(CodeRootSetTable) + (entry_size() * number_of_entries()) + (sizeof(HashtableBucket) * table_size()); +size_t G1CodeRootSetTable::mem_size() { + return sizeof(G1CodeRootSetTable) + (entry_size() * number_of_entries()) + (sizeof(HashtableBucket) * table_size()); } -CodeRootSetTable::Entry* CodeRootSetTable::new_entry(nmethod* nm) { +G1CodeRootSetTable::Entry* G1CodeRootSetTable::new_entry(nmethod* nm) { unsigned int hash = compute_hash(nm); Entry* entry = (Entry*) new_entry_free_list(); if (entry == NULL) { @@ -96,7 +52,7 @@ CodeRootSetTable::Entry* CodeRootSetTable::new_entry(nmethod* nm) { return entry; } -void CodeRootSetTable::remove_entry(Entry* e, Entry* previous) { +void G1CodeRootSetTable::remove_entry(Entry* e, Entry* previous) { int index = hash_to_index(e->hash()); assert((e == bucket(index)) == (previous == NULL), "if e is the first entry then previous should be null"); @@ -108,7 +64,7 @@ void CodeRootSetTable::remove_entry(Entry* e, Entry* previous) { free_entry(e); } -CodeRootSetTable::~CodeRootSetTable() { +G1CodeRootSetTable::~G1CodeRootSetTable() { for (int index = 0; index < table_size(); ++index) { for (Entry* e = bucket(index); e != NULL; ) { Entry* to_remove = e; @@ -125,7 +81,7 @@ CodeRootSetTable::~CodeRootSetTable() { } } -bool CodeRootSetTable::add(nmethod* nm) { +bool G1CodeRootSetTable::add(nmethod* nm) { if (!contains(nm)) { Entry* e = new_entry(nm); int index = hash_to_index(e->hash()); @@ -135,7 +91,7 @@ bool CodeRootSetTable::add(nmethod* nm) { return false; } -bool CodeRootSetTable::contains(nmethod* nm) { +bool G1CodeRootSetTable::contains(nmethod* nm) { int index = hash_to_index(compute_hash(nm)); for (Entry* e = bucket(index); e != NULL; e = e->next()) { if (e->literal() == nm) { @@ -145,7 +101,7 @@ bool CodeRootSetTable::contains(nmethod* nm) { return false; } -bool CodeRootSetTable::remove(nmethod* nm) { +bool G1CodeRootSetTable::remove(nmethod* nm) { int index = hash_to_index(compute_hash(nm)); Entry* previous = NULL; for (Entry* e = bucket(index); e != NULL; previous = e, e = e->next()) { @@ -157,7 +113,7 @@ bool CodeRootSetTable::remove(nmethod* nm) { return false; } -void CodeRootSetTable::copy_to(CodeRootSetTable* new_table) { +void G1CodeRootSetTable::copy_to(G1CodeRootSetTable* new_table) { for (int index = 0; index < table_size(); ++index) { for (Entry* e = bucket(index); e != NULL; e = e->next()) { new_table->add(e->literal()); @@ -166,7 +122,7 @@ void CodeRootSetTable::copy_to(CodeRootSetTable* new_table) { new_table->copy_freelist(this); } -void CodeRootSetTable::nmethods_do(CodeBlobClosure* blk) { +void G1CodeRootSetTable::nmethods_do(CodeBlobClosure* blk) { for (int index = 0; index < table_size(); ++index) { for (Entry* e = bucket(index); e != NULL; e = e->next()) { blk->do_code_blob(e->literal()); @@ -175,7 +131,7 @@ void CodeRootSetTable::nmethods_do(CodeBlobClosure* blk) { } template -int CodeRootSetTable::remove_if(CB& should_remove) { +int G1CodeRootSetTable::remove_if(CB& should_remove) { int num_removed = 0; for (int index = 0; index < table_size(); ++index) { Entry* previous = NULL; @@ -198,52 +154,52 @@ G1CodeRootSet::~G1CodeRootSet() { delete _table; } -CodeRootSetTable* G1CodeRootSet::load_acquire_table() { - return (CodeRootSetTable*) OrderAccess::load_ptr_acquire(&_table); +G1CodeRootSetTable* G1CodeRootSet::load_acquire_table() { + return (G1CodeRootSetTable*) OrderAccess::load_ptr_acquire(&_table); } void G1CodeRootSet::allocate_small_table() { - CodeRootSetTable* temp = new CodeRootSetTable(SmallSize); + G1CodeRootSetTable* temp = new G1CodeRootSetTable(SmallSize); OrderAccess::release_store_ptr(&_table, temp); } -void CodeRootSetTable::purge_list_append(CodeRootSetTable* table) { +void G1CodeRootSetTable::purge_list_append(G1CodeRootSetTable* table) { for (;;) { table->_purge_next = _purge_list; - CodeRootSetTable* old = (CodeRootSetTable*) Atomic::cmpxchg_ptr(table, &_purge_list, table->_purge_next); + G1CodeRootSetTable* old = (G1CodeRootSetTable*) Atomic::cmpxchg_ptr(table, &_purge_list, table->_purge_next); if (old == table->_purge_next) { break; } } } -void CodeRootSetTable::purge() { - CodeRootSetTable* table = _purge_list; +void G1CodeRootSetTable::purge() { + G1CodeRootSetTable* table = _purge_list; _purge_list = NULL; while (table != NULL) { - CodeRootSetTable* to_purge = table; + G1CodeRootSetTable* to_purge = table; table = table->_purge_next; delete to_purge; } } void G1CodeRootSet::move_to_large() { - CodeRootSetTable* temp = new CodeRootSetTable(LargeSize); + G1CodeRootSetTable* temp = new G1CodeRootSetTable(LargeSize); _table->copy_to(temp); - CodeRootSetTable::purge_list_append(_table); + G1CodeRootSetTable::purge_list_append(_table); OrderAccess::release_store_ptr(&_table, temp); } void G1CodeRootSet::purge() { - CodeRootSetTable::purge(); + G1CodeRootSetTable::purge(); } size_t G1CodeRootSet::static_mem_size() { - return CodeRootSetTable::static_mem_size(); + return G1CodeRootSetTable::static_mem_size(); } void G1CodeRootSet::add(nmethod* method) { @@ -278,7 +234,7 @@ bool G1CodeRootSet::remove(nmethod* method) { } bool G1CodeRootSet::contains(nmethod* method) { - CodeRootSetTable* table = load_acquire_table(); // contains() may be called outside of lock, so ensure mem sync. + G1CodeRootSetTable* table = load_acquire_table(); // contains() may be called outside of lock, so ensure mem sync. if (table != NULL) { return table->contains(method); } @@ -348,67 +304,3 @@ void G1CodeRootSet::clean(HeapRegion* owner) { clear(); } } - -#ifndef PRODUCT - -class G1CodeRootSetTest { - public: - static void test() { - { - G1CodeRootSet set1; - assert(set1.is_empty(), "Code root set must be initially empty but is not."); - - assert(G1CodeRootSet::static_mem_size() == sizeof(void*), - "The code root set's static memory usage is incorrect, " SIZE_FORMAT " bytes", G1CodeRootSet::static_mem_size()); - - set1.add((nmethod*)1); - assert(set1.length() == 1, "Added exactly one element, but set contains " - SIZE_FORMAT " elements", set1.length()); - - const size_t num_to_add = (size_t)G1CodeRootSet::Threshold + 1; - - for (size_t i = 1; i <= num_to_add; i++) { - set1.add((nmethod*)1); - } - assert(set1.length() == 1, - "Duplicate detection should not have increased the set size but " - "is " SIZE_FORMAT, set1.length()); - - for (size_t i = 2; i <= num_to_add; i++) { - set1.add((nmethod*)(uintptr_t)(i)); - } - assert(set1.length() == num_to_add, - "After adding in total " SIZE_FORMAT " distinct code roots, they " - "need to be in the set, but there are only " SIZE_FORMAT, - num_to_add, set1.length()); - - assert(CodeRootSetTable::_purge_list != NULL, "should have grown to large hashtable"); - - size_t num_popped = 0; - for (size_t i = 1; i <= num_to_add; i++) { - bool removed = set1.remove((nmethod*)i); - if (removed) { - num_popped += 1; - } else { - break; - } - } - assert(num_popped == num_to_add, - "Managed to pop " SIZE_FORMAT " code roots, but only " SIZE_FORMAT " " - "were added", num_popped, num_to_add); - assert(CodeRootSetTable::_purge_list != NULL, "should have grown to large hashtable"); - - G1CodeRootSet::purge(); - - assert(CodeRootSetTable::_purge_list == NULL, "should have purged old small tables"); - - } - - } -}; - -void TestCodeCacheRemSet_test() { - G1CodeRootSetTest::test(); -} - -#endif diff --git a/hotspot/src/share/vm/gc/g1/g1CodeCacheRemSet.hpp b/hotspot/src/share/vm/gc/g1/g1CodeCacheRemSet.hpp index fcd82187909..3c7ed50d81c 100644 --- a/hotspot/src/share/vm/gc/g1/g1CodeCacheRemSet.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CodeCacheRemSet.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 @@ -28,7 +28,7 @@ #include "memory/allocation.hpp" class CodeBlobClosure; -class CodeRootSetTable; +class G1CodeRootSetTable; class HeapRegion; class nmethod; @@ -42,8 +42,8 @@ class G1CodeRootSet VALUE_OBJ_CLASS_SPEC { const static size_t Threshold = 24; const static size_t LargeSize = 512; - CodeRootSetTable* _table; - CodeRootSetTable* load_acquire_table(); + G1CodeRootSetTable* _table; + G1CodeRootSetTable* load_acquire_table(); size_t _length; diff --git a/hotspot/src/share/vm/gc/g1/g1CodeRootSetTable.hpp b/hotspot/src/share/vm/gc/g1/g1CodeRootSetTable.hpp new file mode 100644 index 00000000000..4a3b6bbc25b --- /dev/null +++ b/hotspot/src/share/vm/gc/g1/g1CodeRootSetTable.hpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef SHARE_VM_GC_G1_G1CODEROOTSETTABLE_HPP +#define SHARE_VM_GC_G1_G1CODEROOTSETTABLE_HPP + +#include "utilities/hashtable.hpp" + +class nmethod; + +class G1CodeRootSetTable : public Hashtable { + friend class G1CodeRootSetTest; + typedef HashtableEntry Entry; + + static G1CodeRootSetTable* volatile _purge_list; + + G1CodeRootSetTable* _purge_next; + + unsigned int compute_hash(nmethod* nm) { + uintptr_t hash = (uintptr_t)nm; + return hash ^ (hash >> 7); // code heap blocks are 128byte aligned + } + + void remove_entry(Entry* e, Entry* previous); + Entry* new_entry(nmethod* nm); + + public: + G1CodeRootSetTable(int size) : Hashtable(size, sizeof(Entry)), _purge_next(NULL) {} + ~G1CodeRootSetTable(); + + // Needs to be protected by locks + bool add(nmethod* nm); + bool remove(nmethod* nm); + + // Can be called without locking + bool contains(nmethod* nm); + + int entry_size() const { return BasicHashtable::entry_size(); } + + void copy_to(G1CodeRootSetTable* new_table); + void nmethods_do(CodeBlobClosure* blk); + + template + int remove_if(CB& should_remove); + + static void purge_list_append(G1CodeRootSetTable* tbl); + static void purge(); + + static size_t static_mem_size() { + return sizeof(_purge_list); + } + + size_t mem_size(); +}; + +#endif /* SHARE_VM_GC_G1_G1CODEROOTSETTABLE_HPP */ diff --git a/hotspot/src/share/vm/utilities/internalVMTests.cpp b/hotspot/src/share/vm/utilities/internalVMTests.cpp index 03737b6a213..6e7ad0bdf6a 100644 --- a/hotspot/src/share/vm/utilities/internalVMTests.cpp +++ b/hotspot/src/share/vm/utilities/internalVMTests.cpp @@ -89,7 +89,6 @@ void InternalVMTests::run() { #if INCLUDE_ALL_GCS run_unit_test(TestG1BiasedArray_test); run_unit_test(TestBufferingOopClosure_test); - run_unit_test(TestCodeCacheRemSet_test); if (UseG1GC) { run_unit_test(FreeRegionList_test); run_unit_test(IHOP_test); diff --git a/hotspot/test/native/gc/g1/test_g1CodeCacheRemSet.cpp b/hotspot/test/native/gc/g1/test_g1CodeCacheRemSet.cpp new file mode 100644 index 00000000000..4365e9929a8 --- /dev/null +++ b/hotspot/test/native/gc/g1/test_g1CodeCacheRemSet.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2014, 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "gc/g1/g1CodeRootSetTable.hpp" +#include "gc/g1/g1CodeCacheRemSet.hpp" +#include "unittest.hpp" + +class G1CodeRootSetTest : public ::testing::Test { + public: + + size_t threshold() { + return G1CodeRootSet::Threshold; + } + + G1CodeRootSetTable* purge_list() { + return G1CodeRootSetTable::_purge_list; + } +}; + +TEST_VM_F(G1CodeRootSetTest, g1_code_cache_rem_set) { + G1CodeRootSet root_set; + + ASSERT_TRUE(root_set.is_empty()) << "Code root set must be initially empty " + "but is not."; + + ASSERT_EQ(G1CodeRootSet::static_mem_size(), sizeof (void*)) << + "The code root set's static memory usage is incorrect, " + << G1CodeRootSet::static_mem_size() << " bytes"; + + root_set.add((nmethod*) 1); + ASSERT_EQ(root_set.length(), (size_t) 1) << "Added exactly one element, but" + " set contains " << root_set.length() << " elements"; + + const size_t num_to_add = (size_t) threshold() + 1; + + for (size_t i = 1; i <= num_to_add; i++) { + root_set.add((nmethod*) 1); + } + ASSERT_EQ(root_set.length(), (size_t) 1) + << "Duplicate detection should not have increased the set size but " + << "is " << root_set.length(); + + for (size_t i = 2; i <= num_to_add; i++) { + root_set.add((nmethod*) (uintptr_t) (i)); + } + + ASSERT_EQ(root_set.length(), num_to_add) + << "After adding in total " << num_to_add << " distinct code roots, " + "they need to be in the set, but there are only " << root_set.length(); + + ASSERT_NE(purge_list(), (G1CodeRootSetTable*) NULL) + << "should have grown to large hashtable"; + + size_t num_popped = 0; + for (size_t i = 1; i <= num_to_add; i++) { + bool removed = root_set.remove((nmethod*) i); + if (removed) { + num_popped += 1; + } else { + break; + } + } + ASSERT_EQ(num_popped, num_to_add) + << "Managed to pop " << num_popped << " code roots, but only " + << num_to_add << " were added"; + ASSERT_NE(purge_list(), (G1CodeRootSetTable*) NULL) + << "should have grown to large hashtable"; + + G1CodeRootSet::purge(); + + ASSERT_EQ(purge_list(), (G1CodeRootSetTable*) NULL) + << "should have purged old small tables"; +} From 87d30c0c7d328e5bd92f19488786e22f1c571ef3 Mon Sep 17 00:00:00 2001 From: Kirill Zhaldybin Date: Thu, 1 Sep 2016 20:46:40 +0300 Subject: [PATCH 043/110] 8164039: Convert test_memset_with_concurrent_readers to GTest Reviewed-by: iignatyev, kbarrett --- .../share/vm/utilities/internalVMTests.cpp | 1 - .../test_memset_with_concurrent_readers.cpp} | 53 +++++++++---------- 2 files changed, 24 insertions(+), 30 deletions(-) rename hotspot/{src/share/vm/gc/shared/memset_with_concurrent_readers.cpp => test/native/gc/shared/test_memset_with_concurrent_readers.cpp} (69%) diff --git a/hotspot/src/share/vm/utilities/internalVMTests.cpp b/hotspot/src/share/vm/utilities/internalVMTests.cpp index 6e7ad0bdf6a..76087d52bfe 100644 --- a/hotspot/src/share/vm/utilities/internalVMTests.cpp +++ b/hotspot/src/share/vm/utilities/internalVMTests.cpp @@ -93,7 +93,6 @@ void InternalVMTests::run() { run_unit_test(FreeRegionList_test); run_unit_test(IHOP_test); } - run_unit_test(test_memset_with_concurrent_readers); run_unit_test(WorkerDataArray_test); run_unit_test(ParallelCompact_test); #endif diff --git a/hotspot/src/share/vm/gc/shared/memset_with_concurrent_readers.cpp b/hotspot/test/native/gc/shared/test_memset_with_concurrent_readers.cpp similarity index 69% rename from hotspot/src/share/vm/gc/shared/memset_with_concurrent_readers.cpp rename to hotspot/test/native/gc/shared/test_memset_with_concurrent_readers.cpp index 27625a30dfd..7af5b232ad6 100644 --- a/hotspot/src/share/vm/gc/shared/memset_with_concurrent_readers.cpp +++ b/hotspot/test/native/gc/shared/test_memset_with_concurrent_readers.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -19,30 +19,22 @@ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. - * */ #include "precompiled.hpp" - #include -#include "gc/shared/memset_with_concurrent_readers.hpp" -#include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" -#include "utilities/macros.hpp" -#include "utilities/ostream.hpp" +#include +#include "gc/shared/memset_with_concurrent_readers.hpp" +#include "unittest.hpp" #if INCLUDE_ALL_GCS -// Unit test -#ifndef PRODUCT - static unsigned line_byte(const char* line, size_t i) { return unsigned(line[i]) & 0xFF; } -// Verify memset_with_concurrent_readers mimics memset. -// We don't attempt to verify the concurrent reader case. -void test_memset_with_concurrent_readers() { +TEST(gc, memset_with_concurrent_readers) { const size_t chunk_size = 8 * BytesPerWord; const unsigned chunk_count = 4; const size_t block_size = (chunk_count + 4) * chunk_size; @@ -76,29 +68,32 @@ void test_memset_with_concurrent_readers() { bool middle_set = !memcmp(set_block, block + set_start, set_size); bool tail_clear = !memcmp(clear_block, block + set_end, block_size - set_end); if (!(head_clear && middle_set && tail_clear)) { - tty->print_cr("*** memset_with_concurrent_readers failed: " - "set start " SIZE_FORMAT ", set end " SIZE_FORMAT, - set_start, set_end); + std::ostringstream err_stream; + err_stream << "*** memset_with_concurrent_readers failed: set start " + << set_start << ", set end " << set_end << std::endl; for (unsigned chunk = 0; chunk < (block_size / chunk_size); ++chunk) { for (unsigned line = 0; line < (chunk_size / BytesPerWord); ++line) { + const char* lp = &block[chunk * chunk_size + line * BytesPerWord]; - tty->print_cr("%d,%d: %2x %2x %2x %2x %2x %2x %2x %2x", - chunk, line, - line_byte(lp, 0), line_byte(lp, 1), - line_byte(lp, 2), line_byte(lp, 3), - line_byte(lp, 4), line_byte(lp, 5), - line_byte(lp, 6), line_byte(lp, 7)); + + err_stream << std::dec << chunk << "," << line << ": " << std::hex + << std::setw(2) << line_byte(lp, 0) << " " + << std::setw(2) << line_byte(lp, 1) << " " + << std::setw(2) << line_byte(lp, 2) << " " + << std::setw(2) << line_byte(lp, 3) << " " + << std::setw(2) << line_byte(lp, 4) << " " + << std::setw(2) << line_byte(lp, 5) << " " + << std::setw(2) << line_byte(lp, 6) << " " + << std::setw(2) << line_byte(lp, 7) << std::endl; } } - assert(head_clear, "leading byte not clear"); - assert(middle_set, "memset byte not set"); - assert(tail_clear, "trailing bye not clear"); + EXPECT_TRUE(head_clear) << "leading byte not clear"; + EXPECT_TRUE(middle_set) << "memset byte not set"; + EXPECT_TRUE(tail_clear) << "trailing bye not clear"; + ASSERT_TRUE(head_clear && middle_set && tail_clear) << err_stream.str(); } } } } } - -#endif // end unit test - -#endif // INCLUDE_ALL_GCS +#endif From f03ab592ccc80856e340bc9524e40f827b09d913 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Thu, 1 Sep 2016 18:02:13 -0400 Subject: [PATCH 044/110] 8165268: [BACKOUT] InstanceKlass::_previous_version_count goes negative Reviewed-by: dcubed --- .../share/vm/classfile/classLoaderData.cpp | 2 +- hotspot/src/share/vm/oops/instanceKlass.cpp | 19 ++----- hotspot/src/share/vm/oops/instanceKlass.hpp | 5 +- .../runtime/RedefineTests/RedefineCount.java | 56 ------------------- 4 files changed, 8 insertions(+), 74 deletions(-) delete mode 100644 hotspot/test/runtime/RedefineTests/RedefineCount.java diff --git a/hotspot/src/share/vm/classfile/classLoaderData.cpp b/hotspot/src/share/vm/classfile/classLoaderData.cpp index f7711449312..ba1191614b1 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.cpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp @@ -962,7 +962,7 @@ bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive_closure, // Mark metadata seen on the stack only so we can delete unneeded entries. // Only walk all metadata, including the expensive code cache walk, for Full GC - // and only if class redefinition occurred and if there are previous versions of + // and only if class redefinition and if there's previous versions of // Klasses to delete. bool walk_all_metadata = clean_previous_versions && JvmtiExport::has_redefined_a_class() && diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index 2b34d9ae8c2..1385affc5df 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -3370,7 +3370,6 @@ int InstanceKlass::_previous_version_count = 0; // Purge previous versions before adding new previous versions of the class. void InstanceKlass::purge_previous_versions(InstanceKlass* ik) { - assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint"); if (ik->previous_versions() != NULL) { // This klass has previous versions so see what we can cleanup // while it is safe to do so. @@ -3399,12 +3398,7 @@ void InstanceKlass::purge_previous_versions(InstanceKlass* ik) { // are executing. Unlink this previous_version. // The previous version InstanceKlass is on the ClassLoaderData deallocate list // so will be deallocated during the next phase of class unloading. - // - // Update count for class unloading. - _previous_version_count--; - log_trace(redefine, class, iklass, purge) - ("previous version " INTPTR_FORMAT " is dead. previous_version_count = %d", - p2i(pv_node), _previous_version_count); + log_trace(redefine, class, iklass, purge)("previous version " INTPTR_FORMAT " is dead", p2i(pv_node)); // For debugging purposes. pv_node->set_is_scratch_class(); pv_node->class_loader_data()->add_to_deallocate_list(pv_node); @@ -3519,7 +3513,6 @@ void InstanceKlass::add_previous_version(instanceKlassHandle scratch_class, int emcp_method_count) { assert(Thread::current()->is_VM_thread(), "only VMThread can add previous versions"); - assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint"); ResourceMark rm; log_trace(redefine, class, iklass, add) @@ -3543,6 +3536,8 @@ void InstanceKlass::add_previous_version(instanceKlassHandle scratch_class, // For debugging purposes. scratch_class->set_is_scratch_class(); scratch_class->class_loader_data()->add_to_deallocate_list(scratch_class()); + // Update count for class unloading. + _previous_version_count--; return; } @@ -3570,14 +3565,12 @@ void InstanceKlass::add_previous_version(instanceKlassHandle scratch_class, } // Add previous version if any methods are still running. - // Update count for class unloading. - _previous_version_count++; - log_trace(redefine, class, iklass, add) - ("scratch class added; one of its methods is on_stack. previous_version_count = %d", - _previous_version_count); + log_trace(redefine, class, iklass, add)("scratch class added; one of its methods is on_stack"); assert(scratch_class->previous_versions() == NULL, "shouldn't have a previous version"); scratch_class->link_previous_versions(previous_versions()); link_previous_versions(scratch_class()); + // Update count for class unloading. + _previous_version_count++; } // end add_previous_version() #endif // INCLUDE_JVMTI diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index c9cc2cfb64f..da36a1422b4 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -771,10 +771,7 @@ public: static int _previous_version_count; public: static void purge_previous_versions(InstanceKlass* ik); - static bool has_previous_versions() { - assert(_previous_version_count >= 0, "count should never be negative"); - return _previous_version_count > 0; - } + static bool has_previous_versions() { return _previous_version_count > 0; } // JVMTI: Support for caching a class file before it is modified by an agent that can do retransformation void set_cached_class_file(JvmtiCachedClassFileData *data) { diff --git a/hotspot/test/runtime/RedefineTests/RedefineCount.java b/hotspot/test/runtime/RedefineTests/RedefineCount.java deleted file mode 100644 index ce8d40d0902..00000000000 --- a/hotspot/test/runtime/RedefineTests/RedefineCount.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2016, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 8164692 - * @summary Redefine previous_versions count goes negative - * @library /test/lib - * @modules java.base/jdk.internal.misc - * @modules java.compiler - * java.instrument - * jdk.jartool/sun.tools.jar - * @run main RedefineClassHelper - * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace RedefineCount - */ -public class RedefineCount { - - public static String newB = - "class RedefineCount$B {" + - "}"; - - static class B { } - - public static void main(String[] args) throws Exception { - - // Redefine a class and create some garbage - // Since there are no methods running, the previous version is never added to the - // previous_version_list and the count should stay zero and not go negative - RedefineClassHelper.redefineClass(B.class, newB); - - for (int i = 0; i < 20 ; i++) { - String s = new String("some garbage"); - System.gc(); - } - } -} From 3e07dc6611689d1307ad6f1ecefcc7fcdb48bf75 Mon Sep 17 00:00:00 2001 From: Robbin Ehn Date: Fri, 2 Sep 2016 08:51:26 +0200 Subject: [PATCH 045/110] 8165215: Setting same UL tag multiple times matches wrong tagset Reviewed-by: mlarsson, rprotacio --- hotspot/src/share/vm/logging/logTagLevelExpression.cpp | 9 ++++++++- hotspot/src/share/vm/logging/logTagLevelExpression.hpp | 8 +++++++- .../test/native/logging/test_logTagLevelExpression.cpp | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/logging/logTagLevelExpression.cpp b/hotspot/src/share/vm/logging/logTagLevelExpression.cpp index 6520c62d962..6b53ab563a9 100644 --- a/hotspot/src/share/vm/logging/logTagLevelExpression.cpp +++ b/hotspot/src/share/vm/logging/logTagLevelExpression.cpp @@ -164,7 +164,14 @@ bool LogTagLevelExpression::parse(const char* str, outputStream* errstream) { success = false; break; } - add_tag(tag); + if (!add_tag(tag)) { + if (errstream != NULL) { + errstream->print_cr("Tag combination have duplicate tag '%s' in what-expression.", + cur_tag); + } + success = false; + break; + } cur_tag = plus_pos + 1; } while (plus_pos != NULL); diff --git a/hotspot/src/share/vm/logging/logTagLevelExpression.hpp b/hotspot/src/share/vm/logging/logTagLevelExpression.hpp index e1f4cb2e94a..278f265a0d0 100644 --- a/hotspot/src/share/vm/logging/logTagLevelExpression.hpp +++ b/hotspot/src/share/vm/logging/logTagLevelExpression.hpp @@ -59,9 +59,15 @@ class LogTagLevelExpression : public StackObj { _ntags = 0; } - void add_tag(LogTagType tag) { + bool add_tag(LogTagType tag) { assert(_ntags < LogTag::MaxTags, "Can't have more tags than MaxTags!"); + for (size_t i = 0; i < _ntags; i++) { + if (_tags[_ncombinations][i] == tag) { + return false; + } + } _tags[_ncombinations][_ntags++] = tag; + return true; } void set_level(LogLevelType level) { diff --git a/hotspot/test/native/logging/test_logTagLevelExpression.cpp b/hotspot/test/native/logging/test_logTagLevelExpression.cpp index 72bd244a5ca..870c6af42db 100644 --- a/hotspot/test/native/logging/test_logTagLevelExpression.cpp +++ b/hotspot/test/native/logging/test_logTagLevelExpression.cpp @@ -33,7 +33,7 @@ TEST(LogTagLevelExpression, parse) { const char* invalid_substr[] = { "=", "+", " ", "+=", "+=*", "*+", " +", "**", "++", ".", ",", ",," ",+", " *", "all+", "all*", "+all", "+all=Warning", "==Info", "=InfoWarning", - "BadTag+", "logging++", "logging*+", ",=", "gc+gc+gc+gc+gc+gc" + "BadTag+", "logging++", "logging*+", ",=", "gc+gc+" }; const char* valid_expression[] = { "all", "gc", "gc,logging", "gc+logging", "logging+gc", "logging+gc,gc", "logging+gc*", "gc=trace", From e4f4b40488a329dba5e19c8c57317673b6632d85 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Fri, 2 Sep 2016 09:49:10 +0200 Subject: [PATCH 046/110] 8164936: G1 age table printout contains contents from previous GC Split tenuring threshold update and printing into two separate parts so that they can be used independently. Reviewed-by: jmasa, sangheki --- .../src/share/vm/gc/g1/g1CollectedHeap.cpp | 1 + .../src/share/vm/gc/g1/g1DefaultPolicy.cpp | 16 ++- .../src/share/vm/gc/g1/g1DefaultPolicy.hpp | 4 + hotspot/src/share/vm/gc/g1/g1Policy.hpp | 3 + .../share/vm/gc/serial/defNewGeneration.cpp | 15 ++- hotspot/src/share/vm/gc/shared/ageTable.cpp | 27 +++-- hotspot/src/share/vm/gc/shared/ageTable.hpp | 8 +- hotspot/test/gc/TestAgeOutput.java | 103 ++++++++++++++++++ 8 files changed, 154 insertions(+), 23 deletions(-) create mode 100644 hotspot/test/gc/TestAgeOutput.java diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index e1462e9343c..7b6974c4f58 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -4513,6 +4513,7 @@ void G1CollectedHeap::post_evacuate_collection_set(EvacuationInfo& evacuation_in #if defined(COMPILER2) || INCLUDE_JVMCI DerivedPointerTable::update_pointers(); #endif + g1_policy()->print_age_table(); } void G1CollectedHeap::record_obj_copy_mem_stats() { diff --git a/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.cpp b/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.cpp index 454f73bc0c6..803c1b62d79 100644 --- a/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.cpp +++ b/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.cpp @@ -885,6 +885,15 @@ bool G1DefaultPolicy::adaptive_young_list_length() const { return _young_gen_sizer.adaptive_young_list_length(); } +size_t G1DefaultPolicy::desired_survivor_size() const { + size_t const survivor_capacity = HeapRegion::GrainWords * _max_survivor_regions; + return (size_t)((((double)survivor_capacity) * TargetSurvivorRatio) / 100); +} + +void G1DefaultPolicy::print_age_table() { + _survivors_age_table.print_age_table(_tenuring_threshold); +} + void G1DefaultPolicy::update_max_gc_locker_expansion() { uint expansion_region_num = 0; if (GCLockerEdenExpansionPercent > 0) { @@ -908,8 +917,11 @@ void G1DefaultPolicy::update_survivors_policy() { // smaller than 1.0) we'll get 1. _max_survivor_regions = (uint) ceil(max_survivor_regions_d); - _tenuring_threshold = _survivors_age_table.compute_tenuring_threshold( - HeapRegion::GrainWords * _max_survivor_regions, _policy_counters); + _tenuring_threshold = _survivors_age_table.compute_tenuring_threshold(desired_survivor_size()); + if (UsePerfData) { + _policy_counters->tenuring_threshold()->set_value(_tenuring_threshold); + _policy_counters->desired_survivor_size()->set_value(desired_survivor_size() * oopSize); + } } bool G1DefaultPolicy::force_initial_mark_if_outside_cycle(GCCause::Cause gc_cause) { diff --git a/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.hpp b/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.hpp index 21ab55a4ab4..6eba7e76e20 100644 --- a/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.hpp +++ b/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.hpp @@ -360,6 +360,8 @@ private: AgeTable _survivors_age_table; +protected: + size_t desired_survivor_size() const; public: uint tenuring_threshold() const { return _tenuring_threshold; } @@ -379,6 +381,8 @@ public: _survivors_age_table.merge(age_table); } + void print_age_table(); + void update_max_gc_locker_expansion(); void update_survivors_policy(); diff --git a/hotspot/src/share/vm/gc/g1/g1Policy.hpp b/hotspot/src/share/vm/gc/g1/g1Policy.hpp index 78240032d2d..92aa6050e70 100644 --- a/hotspot/src/share/vm/gc/g1/g1Policy.hpp +++ b/hotspot/src/share/vm/gc/g1/g1Policy.hpp @@ -181,6 +181,9 @@ public: virtual void note_stop_adding_survivor_regions() = 0; virtual void record_age_table(AgeTable* age_table) = 0; + virtual void print_age_table() = 0; +protected: + virtual size_t desired_survivor_size() const = 0; }; #endif // SHARE_VM_GC_G1_G1POLICY_HPP diff --git a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp index 147bc06d305..e7f96a22228 100644 --- a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp +++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp @@ -564,9 +564,18 @@ HeapWord* DefNewGeneration::expand_and_allocate(size_t size, void DefNewGeneration::adjust_desired_tenuring_threshold() { // Set the desired survivor size to half the real survivor space - GCPolicyCounters* gc_counters = GenCollectedHeap::heap()->gen_policy()->counters(); - _tenuring_threshold = - age_table()->compute_tenuring_threshold(to()->capacity()/HeapWordSize, gc_counters); + size_t const survivor_capacity = to()->capacity() / HeapWordSize; + size_t const desired_survivor_size = (size_t)((((double)survivor_capacity) * TargetSurvivorRatio) / 100); + + _tenuring_threshold = age_table()->compute_tenuring_threshold(desired_survivor_size); + + if (UsePerfData) { + GCPolicyCounters* gc_counters = GenCollectedHeap::heap()->gen_policy()->counters(); + gc_counters->tenuring_threshold()->set_value(_tenuring_threshold); + gc_counters->desired_survivor_size()->set_value(desired_survivor_size * oopSize); + } + + age_table()->print_age_table(_tenuring_threshold); } void DefNewGeneration::collect(bool full, diff --git a/hotspot/src/share/vm/gc/shared/ageTable.cpp b/hotspot/src/share/vm/gc/shared/ageTable.cpp index 48ddfa1e492..d2a76cff1d0 100644 --- a/hotspot/src/share/vm/gc/shared/ageTable.cpp +++ b/hotspot/src/share/vm/gc/shared/ageTable.cpp @@ -27,7 +27,6 @@ #include "gc/shared/ageTableTracer.hpp" #include "gc/shared/collectedHeap.hpp" #include "gc/shared/collectorPolicy.hpp" -#include "gc/shared/gcPolicyCounters.hpp" #include "memory/resourceArea.hpp" #include "logging/log.hpp" #include "oops/oop.inline.hpp" @@ -75,8 +74,7 @@ void AgeTable::merge(AgeTable* subTable) { } } -uint AgeTable::compute_tenuring_threshold(size_t survivor_capacity, GCPolicyCounters* gc_counters) { - size_t desired_survivor_size = (size_t)((((double) survivor_capacity)*TargetSurvivorRatio)/100); +uint AgeTable::compute_tenuring_threshold(size_t desired_survivor_size) { uint result; if (AlwaysTenure || NeverTenure) { @@ -99,9 +97,16 @@ uint AgeTable::compute_tenuring_threshold(size_t survivor_capacity, GCPolicyCoun log_debug(gc, age)("Desired survivor size " SIZE_FORMAT " bytes, new threshold " UINTX_FORMAT " (max threshold " UINTX_FORMAT ")", - desired_survivor_size*oopSize, (uintx) result, MaxTenuringThreshold); + desired_survivor_size * oopSize, (uintx) result, MaxTenuringThreshold); + return result; +} + +void AgeTable::print_age_table(uint tenuring_threshold) { if (log_is_enabled(Trace, gc, age) || UsePerfData || AgeTableTracer::is_tenuring_distribution_event_enabled()) { + log_trace(gc, age)("Age table with threshold %u (max threshold " UINTX_FORMAT ")", + tenuring_threshold, MaxTenuringThreshold); + size_t total = 0; uint age = 1; while (age < table_size) { @@ -109,20 +114,14 @@ uint AgeTable::compute_tenuring_threshold(size_t survivor_capacity, GCPolicyCoun total += wordSize; if (wordSize > 0) { log_trace(gc, age)("- age %3u: " SIZE_FORMAT_W(10) " bytes, " SIZE_FORMAT_W(10) " total", - age, wordSize*oopSize, total*oopSize); + age, wordSize * oopSize, total * oopSize); } - AgeTableTracer::send_tenuring_distribution_event(age, wordSize*oopSize); + AgeTableTracer::send_tenuring_distribution_event(age, wordSize * oopSize); if (UsePerfData) { - _perf_sizes[age]->set_value(wordSize*oopSize); + _perf_sizes[age]->set_value(wordSize * oopSize); } age++; } - if (UsePerfData) { - gc_counters->tenuring_threshold()->set_value(result); - gc_counters->desired_survivor_size()->set_value( - desired_survivor_size*oopSize); - } } - - return result; } + diff --git a/hotspot/src/share/vm/gc/shared/ageTable.hpp b/hotspot/src/share/vm/gc/shared/ageTable.hpp index 4af836f8acd..858ae0ae5dd 100644 --- a/hotspot/src/share/vm/gc/shared/ageTable.hpp +++ b/hotspot/src/share/vm/gc/shared/ageTable.hpp @@ -29,8 +29,6 @@ #include "oops/oop.hpp" #include "runtime/perfData.hpp" -class GCPolicyCounters; - /* Copyright (c) 1992, 2016, Oracle and/or its affiliates, and Stanford University. See the LICENSE file for license information. */ @@ -67,10 +65,12 @@ class AgeTable VALUE_OBJ_CLASS_SPEC { // for parallel young generation gc. void merge(AgeTable* subTable); - // calculate new tenuring threshold based on age information - uint compute_tenuring_threshold(size_t survivor_capacity, GCPolicyCounters* gc_counters); + // Calculate new tenuring threshold based on age information. + uint compute_tenuring_threshold(size_t desired_survivor_size); + void print_age_table(uint tenuring_threshold); private: + PerfVariable* _perf_sizes[table_size]; }; diff --git a/hotspot/test/gc/TestAgeOutput.java b/hotspot/test/gc/TestAgeOutput.java new file mode 100644 index 00000000000..6be8c14e0e0 --- /dev/null +++ b/hotspot/test/gc/TestAgeOutput.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test TestAgeOutput + * @bug 8164936 + * @summary Check that collectors using age table based aging print an age table even for the first garbage collection + * @key gc + * @requires vm.gc=="null" + * @modules java.base/jdk.internal.misc + * @library /test/lib + * @build sun.hotspot.WhiteBox + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -XX:+UseSerialGC TestAgeOutput UseSerialGC + * @run main/othervm -XX:+UseConcMarkSweepGC TestAgeOutput UseConcMarkSweepGC + * @run main/othervm -XX:+UseG1GC TestAgeOutput UseG1GC + */ + +import sun.hotspot.WhiteBox; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import jdk.test.lib.Platform; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +import static jdk.test.lib.Asserts.*; + +public class TestAgeOutput { + + public static void checkPattern(String pattern, String what) throws Exception { + Pattern r = Pattern.compile(pattern); + Matcher m = r.matcher(what); + + if (!m.find()) { + throw new RuntimeException("Could not find pattern " + pattern + " in output"); + } + } + + public static void runTest(String gcArg) throws Exception { + final String[] arguments = { + "-Xbootclasspath/a:.", + "-XX:+UnlockExperimentalVMOptions", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "-XX:+" + gcArg, + "-Xmx10M", + "-Xlog:gc+age=trace", + GCTest.class.getName() + }; + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(arguments); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + output.shouldHaveExitValue(0); + + System.out.println(output.getStdout()); + + String stdout = output.getStdout(); + + checkPattern(".*GC\\(0\\) .*Desired survivor size.*", stdout); + checkPattern(".*GC\\(0\\) .*Age table with threshold.*", stdout); + checkPattern(".*GC\\(0\\) .*- age 1:.*", stdout); + } + + public static void main(String[] args) throws Exception { + runTest(args[0]); + } + + static class GCTest { + private static final WhiteBox WB = WhiteBox.getWhiteBox(); + + public static Object holder; + + public static void main(String [] args) { + holder = new byte[100]; + WB.youngGC(); + System.out.println(holder); + } + } +} + From 8a4ddec87486c8b743cd04e4e995e8b5b353f4ed Mon Sep 17 00:00:00 2001 From: Kirill Zhaldybin Date: Tue, 30 Aug 2016 21:35:56 +0300 Subject: [PATCH 047/110] 8157468: gc/testlibrary contains a lot of duplicated code Reviewed-by: dfazunen, iignatyev --- hotspot/test/gc/testlibrary/Helpers.java | 67 ++++-------------------- 1 file changed, 9 insertions(+), 58 deletions(-) diff --git a/hotspot/test/gc/testlibrary/Helpers.java b/hotspot/test/gc/testlibrary/Helpers.java index e97d4a03ea9..e326308e5d1 100644 --- a/hotspot/test/gc/testlibrary/Helpers.java +++ b/hotspot/test/gc/testlibrary/Helpers.java @@ -32,7 +32,6 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; public class Helpers { @@ -124,20 +123,13 @@ public class Helpers { */ public static String generate(String className, String superClass, String constructor, long fieldCount) { - StringBuilder builder = new StringBuilder(); - builder.append(String.format("public class %s%s {\n", className, superClass == null ? "" - : " extends " + superClass)); - - if (constructor != null) { - builder.append(constructor); - } - - for (int i = 0; i < fieldCount; ++i) { - builder.append(String.format("long f%d;\n", i)); - } - - builder.append("}\n"); - return builder.toString(); + return new StringBuilder() + .append(String.format("public class %s%s {\n", className, superClass == null ? "" + : " extends " + superClass)) + .append(constructor == null ? "" : constructor) + .append(fieldsGenerator(fieldCount)) + .append("}\n") + .toString(); } /** @@ -212,50 +204,9 @@ public class Helpers { Path workDir, String prefix) throws IOException, ClassNotFoundException { - if (instanceSize % SIZE_OF_LONG != 0L) { - throw new Error(String.format("Test bug: only sizes aligned by 8 bytes are supported and %d was specified", - instanceSize)); - } + generateByTemplateAndCompile(className, null, "public class ${ClassName} extends ${BaseClass} {\n${Fields}}\n", + "", instanceSize, workDir, prefix); - long instanceSizeWithoutObjectHeader = instanceSize - WhiteBox.getWhiteBox().getObjectSize(new Object()); - - int generatedClassesCount; - int fieldsInLastClassCount; - - int sizeOfLastFile = (int) (instanceSizeWithoutObjectHeader - % (MAXIMUM_AMOUNT_OF_FIELDS_IN_CLASS * SIZE_OF_LONG)); - - if (sizeOfLastFile != 0) { - generatedClassesCount = (int) instanceSizeWithoutObjectHeader - / (MAXIMUM_AMOUNT_OF_FIELDS_IN_CLASS * SIZE_OF_LONG) + 1; - fieldsInLastClassCount = sizeOfLastFile / SIZE_OF_LONG; - } else { - generatedClassesCount = (int) instanceSizeWithoutObjectHeader - / (MAXIMUM_AMOUNT_OF_FIELDS_IN_CLASS * SIZE_OF_LONG); - fieldsInLastClassCount = MAXIMUM_AMOUNT_OF_FIELDS_IN_CLASS; - } - - for (int i = 0; i < generatedClassesCount; i++) { - // for the last generated class we use specified class name - String clsName = (i == generatedClassesCount - 1) ? className : prefix + i; - - // If we already have a file with the same name we do not create it again - if (Files.notExists(Paths.get(clsName + ".java"))) { - Helpers.compileClass(clsName, workDir, - Helpers.generate( - clsName, - // for first generated class we don't have 'extends' - (i == 0 ? null : prefix + (i - 1)), - null, - // for the last generated class we use different field count - (i == generatedClassesCount - 1) ? fieldsInLastClassCount - : MAXIMUM_AMOUNT_OF_FIELDS_IN_CLASS)); - } else { - System.out.println("Class " + clsName + - ".java already exists, skipping class' generation and compilation"); - } - - } return classLoader.loadClass(className); } From 23ceda31a0994e3ae21dfda2bd78d33854d14631 Mon Sep 17 00:00:00 2001 From: Marcus Larsson Date: Wed, 31 Aug 2016 09:38:46 +0200 Subject: [PATCH 048/110] 8164939: GTest LogDecorations.iso8601_time_test fails on macOS Reviewed-by: sla, dsamersoff --- hotspot/test/native/logging/test_logDecorations.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/test/native/logging/test_logDecorations.cpp b/hotspot/test/native/logging/test_logDecorations.cpp index 324792b24b8..c23fb1b8227 100644 --- a/hotspot/test/native/logging/test_logDecorations.cpp +++ b/hotspot/test/native/logging/test_logDecorations.cpp @@ -144,7 +144,7 @@ TEST(LogDecorations, iso8601_time) { reported_time.tm_hour = h; reported_time.tm_min = m; reported_time.tm_sec = s; - reported_time.tm_isdst = daylight; + reported_time.tm_isdst = -1; // let mktime deduce DST settings time_t reported_ts = mktime(&reported_time); expected_ts = mktime(localtime(&expected_ts)); time_t diff = reported_ts - expected_ts; From 6449bab3d190709a932ed8c8b0c983335c8dce9c Mon Sep 17 00:00:00 2001 From: Alexander Scherbatiy Date: Wed, 31 Aug 2016 11:13:53 +0300 Subject: [PATCH 049/110] 8163193: Metal L&F gradient is lighter on HiDPI display after the fix JDK-8143064 Reviewed-by: serb, ssadetsky --- .../classes/sun/swing/CachedPainter.java | 18 ++- .../8163193/ButtonGradientTest.java | 134 ++++++++++++++++++ 2 files changed, 146 insertions(+), 6 deletions(-) create mode 100644 jdk/test/javax/swing/plaf/metal/MetalGradient/8163193/ButtonGradientTest.java diff --git a/jdk/src/java.desktop/share/classes/sun/swing/CachedPainter.java b/jdk/src/java.desktop/share/classes/sun/swing/CachedPainter.java index 818e20dbdd3..92c0e3bad8e 100644 --- a/jdk/src/java.desktop/share/classes/sun/swing/CachedPainter.java +++ b/jdk/src/java.desktop/share/classes/sun/swing/CachedPainter.java @@ -107,13 +107,16 @@ public abstract class CachedPainter { ImageCache cache = getCache(key); Image image = cache.getImage(key, config, w, h, args); int attempts = 0; + VolatileImage volatileImage = (image instanceof VolatileImage) + ? (VolatileImage) image + : null; do { boolean draw = false; - if (image instanceof VolatileImage) { + if (volatileImage != null) { // See if we need to recreate the image - switch (((VolatileImage)image).validate(config)) { + switch (volatileImage.validate(config)) { case VolatileImage.IMAGE_INCOMPATIBLE: - ((VolatileImage)image).flush(); + volatileImage.flush(); image = null; break; case VolatileImage.IMAGE_RESTORED: @@ -126,11 +129,14 @@ public abstract class CachedPainter { image = createImage(c, w, h, config, args); cache.setImage(key, config, w, h, args, image); draw = true; + volatileImage = (image instanceof VolatileImage) + ? (VolatileImage) image + : null; } if (draw) { // Render to the Image Graphics2D g2 = (Graphics2D) image.getGraphics(); - if (w != baseWidth || h != baseHeight) { + if (volatileImage == null && (w != baseWidth || h != baseHeight)) { g2.scale((double) w / baseWidth, (double) h / baseHeight); } paintToImage(c, image, g2, baseWidth, baseHeight, args); @@ -140,8 +146,8 @@ public abstract class CachedPainter { // If we did this 3 times and the contents are still lost // assume we're painting to a VolatileImage that is bogus and // give up. Presumably we'll be called again to paint. - } while ((image instanceof VolatileImage) && - ((VolatileImage)image).contentsLost() && ++attempts < 3); + } while ((volatileImage != null) && + volatileImage.contentsLost() && ++attempts < 3); return image; } diff --git a/jdk/test/javax/swing/plaf/metal/MetalGradient/8163193/ButtonGradientTest.java b/jdk/test/javax/swing/plaf/metal/MetalGradient/8163193/ButtonGradientTest.java new file mode 100644 index 00000000000..8860d768a0d --- /dev/null +++ b/jdk/test/javax/swing/plaf/metal/MetalGradient/8163193/ButtonGradientTest.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.GradientPaint; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.image.BufferedImage; +import java.util.List; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.plaf.metal.MetalLookAndFeel; + +/* + * @test + * @bug 8163193 + * @key headful + * @summary Metal L&F gradient is lighter on HiDPI display + * @run main/othervm -Dsun.java2d.uiScale=2 ButtonGradientTest + */ +public class ButtonGradientTest { + + private static JFrame frame; + private static JButton button; + + public static void main(String[] args) throws Exception { + try { + testGradient(); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void testGradient() throws Exception { + Robot robot = new Robot(); + robot.setAutoDelay(50); + + SwingUtilities.invokeAndWait(ButtonGradientTest::createAndShowGUI); + robot.waitForIdle(); + + Rectangle rect = getButtonBounds(); + List gradient = (List) UIManager.get("Button.gradient"); + float ratio = ((Number) gradient.get(0)).floatValue(); + Color c1 = (Color) gradient.get(2); + Color c2 = (Color) gradient.get(3); + int mid = (int) (ratio * rect.height); + + Color gradientColor = getGradientColor(rect.width, mid, c1, c2); + int x = rect.x + rect.width / 2; + int y = rect.y + mid / 2; + Color buttonColor = robot.getPixelColor(x, y); + + if (!similarColors(buttonColor, gradientColor)) { + throw new RuntimeException("Button gradient is changed!"); + } + } + + private static void createAndShowGUI() { + + try { + UIManager.setLookAndFeel(new MetalLookAndFeel()); + } catch (Exception e) { + throw new RuntimeException(e); + } + + frame = new JFrame(); + frame.setSize(300, 300); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + JPanel panel = new JPanel(new BorderLayout()); + button = new JButton(""); + panel.add(button); + frame.getContentPane().add(panel); + frame.setVisible(true); + } + + private static Rectangle getButtonBounds() throws Exception { + Rectangle[] rectangles = new Rectangle[1]; + SwingUtilities.invokeAndWait(() -> { + rectangles[0] = button.getBounds(); + rectangles[0].setLocation(button.getLocationOnScreen()); + }); + return rectangles[0]; + } + + private static Color getGradientColor(int w, int h, Color c1, Color c2) { + GradientPaint gradient = new GradientPaint(0, 0, c1, 0, h, c2, true); + BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); + Graphics2D g = img.createGraphics(); + g.setPaint(gradient); + g.fillRect(0, 0, w, h); + g.dispose(); + return new Color(img.getRGB(w / 2, h / 2)); + } + + private static boolean similarColors(Color c1, Color c2) { + return similar(c1.getRed(), c2.getRed()) + && similar(c1.getGreen(), c2.getGreen()) + && similar(c1.getBlue(), c2.getBlue()); + } + + private static boolean similar(int i1, int i2) { + return Math.abs(i2 - i1) < 7; + } +} From b7149b5cc75b35754275e0634f962d409cb8339b Mon Sep 17 00:00:00 2001 From: Alexander Scherbatiy Date: Wed, 31 Aug 2016 12:49:03 +0300 Subject: [PATCH 050/110] 8153287: [PIT] [hidpi] java/awt/image/multiresolution/MultiresolutionIconTest failed (GTK+ and Nimbus L&F) Reviewed-by: serb, ssadetsky --- .../javax/swing/plaf/synth/SynthButtonUI.java | 58 +++++++++++-------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthButtonUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthButtonUI.java index 379bcd9a10a..07ee542ac16 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthButtonUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthButtonUI.java @@ -391,21 +391,8 @@ public class SynthButtonUI extends BasicButtonUI implements } private Icon getRolloverIcon(AbstractButton b, Icon defaultIcon) { - ButtonModel model = b.getModel(); - Icon icon = null; - if (model.isSelected()) { - icon = getIcon(b, b.getRolloverSelectedIcon(), null, - SynthConstants.MOUSE_OVER | SynthConstants.SELECTED); - if (icon == null) { - icon = getIcon(b, b.getSelectedIcon(), null, - SynthConstants.SELECTED); - } - } - if (icon == null) { - icon = getIcon(b, b.getRolloverIcon(), defaultIcon, - SynthConstants.MOUSE_OVER); - } - return icon; + return getSpecificIcon(b, b.getRolloverSelectedIcon(), b.getRolloverIcon(), + defaultIcon, SynthConstants.MOUSE_OVER); } private Icon getPressedIcon(AbstractButton b, Icon defaultIcon) { @@ -414,21 +401,44 @@ public class SynthButtonUI extends BasicButtonUI implements } private Icon getSynthDisabledIcon(AbstractButton b, Icon defaultIcon) { - ButtonModel model = b.getModel(); + return getSpecificIcon(b, b.getDisabledSelectedIcon(), b.getDisabledIcon(), + defaultIcon, SynthConstants.DISABLED); + } + + private Icon getSpecificIcon(AbstractButton b, Icon specificSelectedIcon, + Icon specificIcon, Icon defaultIcon, + int state) { + boolean selected = b.getModel().isSelected(); Icon icon = null; - if (model.isSelected()) { - icon = getIcon(b, b.getDisabledSelectedIcon(), null, - SynthConstants.DISABLED | SynthConstants.SELECTED); + + if (selected) { + icon = specificSelectedIcon; if (icon == null) { - icon = getIcon(b, b.getSelectedIcon(), null, - SynthConstants.SELECTED); + icon = b.getSelectedIcon(); } } + if (icon == null) { - icon = getIcon(b, b.getDisabledIcon(), defaultIcon, - SynthConstants.DISABLED); + icon = specificIcon; } - return icon; + + if (icon != null) { + return icon; + } + + if (defaultIcon == null || defaultIcon instanceof UIResource) { + if (selected) { + icon = getSynthIcon(b, state | SynthConstants.SELECTED); + if (icon == null) { + icon = getSynthIcon(b, SynthConstants.SELECTED); + } + } + if (icon == null) { + icon = getSynthIcon(b, state); + } + } + + return icon != null ? icon : defaultIcon; } /** From 0d1ad07556ac5e366a439bccd6dd0d0568cffce2 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Wed, 31 Aug 2016 13:40:06 -0700 Subject: [PATCH 051/110] 8164818: Reg. test java/awt/font/TextLayout/VisibleAdvance.java fails Reviewed-by: serb, psadhukhan --- .../share/native/libfontmanager/HBShaper.c | 2 +- .../native/libfontmanager/hb-jdk-font.cc | 20 ++++++++----------- .../share/native/libfontmanager/hb-jdk.h | 4 ++++ .../awt/font/TextLayout/VisibleAdvance.java | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/jdk/src/java.desktop/share/native/libfontmanager/HBShaper.c b/jdk/src/java.desktop/share/native/libfontmanager/HBShaper.c index d8de3e36d92..3b35e27efda 100644 --- a/jdk/src/java.desktop/share/native/libfontmanager/HBShaper.c +++ b/jdk/src/java.desktop/share/native/libfontmanager/HBShaper.c @@ -78,7 +78,7 @@ int storeGVData(JNIEnv* env, int i; float x=0, y=0; float startX, startY; - float scale = 1.0f/64.0f/devScale; + float scale = 1.0f / FloatToFixedScale / devScale; unsigned int* glyphs; float* positions; int initialCount, glyphArrayLen, posArrayLen, maxGlyphs, storeadv; diff --git a/jdk/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc b/jdk/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc index 93ac190b4d1..c65c673e4ae 100644 --- a/jdk/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc +++ b/jdk/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc @@ -55,10 +55,6 @@ hb_jdk_get_glyph (hb_font_t *font HB_UNUSED, return (*glyph != 0); } -// This is also define in freetypescaler.c and similar macros are -// in fontscalerdefs.h. Consider tidying this up. -#define FloatToF26Dot6(x) ((unsigned int) ((x)*64)) - static hb_position_t hb_jdk_get_glyph_h_advance (hb_font_t *font HB_UNUSED, void *font_data, @@ -84,7 +80,7 @@ hb_jdk_get_glyph_h_advance (hb_font_t *font HB_UNUSED, fadv *= jdkFontInfo->devScale; env->DeleteLocalRef(pt); - return FloatToF26Dot6(fadv); // should this round ? + return FloatToFixed(fadv); } static hb_position_t @@ -111,7 +107,7 @@ hb_jdk_get_glyph_v_advance (hb_font_t *font HB_UNUSED, fadv = env->GetFloatField(pt, sunFontIDs.yFID); env->DeleteLocalRef(pt); - return FloatToF26Dot6(fadv); // should this round ? + return FloatToFixed(fadv); } @@ -205,8 +201,8 @@ hb_jdk_get_glyph_contour_point (hb_font_t *font HB_UNUSED, *x = 0; *y = 0; return true; } - *x = FloatToF26Dot6(env->GetFloatField(pt, sunFontIDs.xFID)); - *y = FloatToF26Dot6(env->GetFloatField(pt, sunFontIDs.yFID)); + *x = FloatToFixed(env->GetFloatField(pt, sunFontIDs.xFID)); + *y = FloatToFixed(env->GetFloatField(pt, sunFontIDs.yFID)); env->DeleteLocalRef(pt); return true; @@ -325,8 +321,8 @@ static hb_font_t* _hb_jdk_font_create(JDKFontInfo *jdkFontInfo, _hb_jdk_get_font_funcs (), jdkFontInfo, (hb_destroy_func_t) _do_nothing); hb_font_set_scale (font, - FloatToF26Dot6(jdkFontInfo->ptSize*jdkFontInfo->devScale), - FloatToF26Dot6(jdkFontInfo->ptSize*jdkFontInfo->devScale)); + FloatToFixed(jdkFontInfo->ptSize*jdkFontInfo->devScale), + FloatToFixed(jdkFontInfo->ptSize*jdkFontInfo->devScale)); return font; } @@ -343,8 +339,8 @@ static hb_font_t* _hb_jdk_ct_font_create(JDKFontInfo *jdkFontInfo) { hb_face_destroy(face); hb_font_set_scale(font, - FloatToF26Dot6(jdkFontInfo->ptSize), - FloatToF26Dot6(jdkFontInfo->ptSize)); + FloatToFixed(jdkFontInfo->ptSize), + FloatToFixed(jdkFontInfo->ptSize)); return font; } #endif diff --git a/jdk/src/java.desktop/share/native/libfontmanager/hb-jdk.h b/jdk/src/java.desktop/share/native/libfontmanager/hb-jdk.h index 1cd8d5ba241..8c08fb036ed 100644 --- a/jdk/src/java.desktop/share/native/libfontmanager/hb-jdk.h +++ b/jdk/src/java.desktop/share/native/libfontmanager/hb-jdk.h @@ -48,6 +48,10 @@ typedef struct JDKFontInfo_Struct { } JDKFontInfo; +// Use 16.16 for better precision than 26.6 +#define FloatToFixedScale ((float)(1 << 16)) +#define FloatToFixed(f) ((unsigned int)((f) * FloatToFixedScale)) + /* * Note: * diff --git a/jdk/test/java/awt/font/TextLayout/VisibleAdvance.java b/jdk/test/java/awt/font/TextLayout/VisibleAdvance.java index c0ed438cee1..4598dfd21fa 100644 --- a/jdk/test/java/awt/font/TextLayout/VisibleAdvance.java +++ b/jdk/test/java/awt/font/TextLayout/VisibleAdvance.java @@ -29,7 +29,7 @@ import java.text.*; /* @test * @summary verify TextLine advance - * @bug 6582460 + * @bug 6582460 8164818 */ /* From 252779d212e5f299c86a668a3607c400908172ed Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Thu, 1 Sep 2016 10:21:29 +0530 Subject: [PATCH 052/110] 8165146: [PIT][TEST_BUG] Doubtful usability of java/awt/print/PrinterJob/TestMediaTraySelection.java Reviewed-by: prr --- jdk/test/java/awt/print/PrinterJob/TestMediaTraySelection.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/jdk/test/java/awt/print/PrinterJob/TestMediaTraySelection.java b/jdk/test/java/awt/print/PrinterJob/TestMediaTraySelection.java index 374928a56c5..9076c6b08cf 100644 --- a/jdk/test/java/awt/print/PrinterJob/TestMediaTraySelection.java +++ b/jdk/test/java/awt/print/PrinterJob/TestMediaTraySelection.java @@ -21,8 +21,7 @@ * questions. */ /* - * @test - * @bug 6357887 + * @bug 6357887 8165146 * @summary Verifies if selected printertray is used * @requires (os.family == "linux" | os.family == "solaris") * @run main/manual TestMediaTraySelection From 44ec255a91c2eb5ec65e0c29ea16bcee32ec7d25 Mon Sep 17 00:00:00 2001 From: Li Jiang Date: Thu, 1 Sep 2016 01:39:21 -0700 Subject: [PATCH 053/110] 8145952: ISO 4217 amendment 161 8164784: ISO 4217 amendment 162 Reviewed-by: naoto --- jdk/make/data/currency/CurrencyData.properties | 6 +++--- .../sun/util/resources/CurrencyNames.properties | 10 ++++++---- .../resources/ext/CurrencyNames_be_BY.properties | 1 + jdk/test/java/util/Currency/ValidateISO4217.java | 4 ++-- jdk/test/java/util/Currency/tablea1.txt | 8 ++++---- jdk/test/sun/text/resources/LocaleData | 14 ++++++++++---- jdk/test/sun/text/resources/LocaleDataTest.java | 2 +- 7 files changed, 27 insertions(+), 18 deletions(-) diff --git a/jdk/make/data/currency/CurrencyData.properties b/jdk/make/data/currency/CurrencyData.properties index 0288b04390b..2d25c95fee5 100644 --- a/jdk/make/data/currency/CurrencyData.properties +++ b/jdk/make/data/currency/CurrencyData.properties @@ -32,14 +32,14 @@ formatVersion=3 # Version of the currency code information in this class. # It is a serial number that accompanies with each amendment. -dataVersion=160 +dataVersion=162 # List of all valid ISO 4217 currency codes. # To ensure compatibility, do not remove codes. all=ADP020-AED784-AFA004-AFN971-ALL008-AMD051-ANG532-AOA973-ARS032-ATS040-AUD036-\ AWG533-AYM945-AZM031-AZN944-BAM977-BBD052-BDT050-BEF056-BGL100-BGN975-BHD048-BIF108-\ - BMD060-BND096-BOB068-BOV984-BRL986-BSD044-BTN064-BWP072-BYB112-BYR974-\ + BMD060-BND096-BOB068-BOV984-BRL986-BSD044-BTN064-BWP072-BYB112-BYR974-BYN933-\ BZD084-CAD124-CDF976-CHE947-CHF756-CHW948-CLF990-CLP152-CNY156-COP170-COU970-CRC188-CSD891-CUP192-CUC931-\ CVE132-CYP196-CZK203-DEM276-DJF262-DKK208-DOP214-DZD012-EEK233-EGP818-\ ERN232-ESP724-ETB230-EUR978-FIM246-FJD242-FKP238-FRF250-GBP826-GEL981-\ @@ -119,7 +119,7 @@ BD=BDT # BARBADOS BB=BBD # BELARUS -BY=BYR +BY=BYN # BELGIUM BE=EUR # BELIZE diff --git a/jdk/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties b/jdk/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties index b002202875b..c62d518e4b5 100644 --- a/jdk/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties +++ b/jdk/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties @@ -92,6 +92,7 @@ BSD=BSD BTN=BTN BWP=BWP BYB=BYB +BYN=BYN BYR=BYR BZD=BZD CAD=CAD @@ -310,8 +311,9 @@ brl=Brazilian Real bsd=Bahamian Dollar btn=Bhutanese Ngultrum bwp=Botswanan Pula -byb=Belarusian New Ruble (1994-1999) -byr=Belarusian Ruble +byb=Belarusian Ruble (1994-1999) +byn=Belarusian Ruble +byr=Belarusian Ruble (2000-2016) bzd=Belize Dollar cad=Canadian Dollar cdf=Congolese Franc @@ -399,7 +401,7 @@ mro=Mauritanian Ouguiya mtl=Maltese Lira mur=Mauritian Rupee mvr=Maldivian Rufiyaa -mwk=Malawian Kwacha +mwk=Malawian Malawi Kwacha mxn=Mexican Peso mxv=Mexican Investment Unit myr=Malaysian Ringgit @@ -414,7 +416,7 @@ npr=Nepalese Rupee nzd=New Zealand Dollar omr=Omani Rial pab=Panamanian Balboa -pen=Peruvian Nuevo Sol +pen=Peruvian Sol pgk=Papua New Guinean Kina php=Philippine Peso pkr=Pakistani Rupee diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_be_BY.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_be_BY.properties index 4651ad1c097..54cc2a62072 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_be_BY.properties +++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_be_BY.properties @@ -35,4 +35,5 @@ # This notice and attribution to Taligent may not be removed. # Taligent is a registered trademark of Taligent, Inc. +BYN=\u0420\u0443\u0431 BYR=\u0420\u0443\u0431 diff --git a/jdk/test/java/util/Currency/ValidateISO4217.java b/jdk/test/java/util/Currency/ValidateISO4217.java index 98fc0a00d8a..f482cfd66c8 100644 --- a/jdk/test/java/util/Currency/ValidateISO4217.java +++ b/jdk/test/java/util/Currency/ValidateISO4217.java @@ -23,7 +23,7 @@ /* * @test * @bug 4691089 4819436 4942982 5104960 6544471 6627549 7066203 7195759 - * 8039317 8074350 8074351 + * 8039317 8074350 8074351 8145952 * @summary Validate ISO 4217 data for Currency class. */ @@ -93,7 +93,7 @@ public class ValidateISO4217 { /* Codes that are obsolete, do not have related country */ static final String otherCodes = - "ADP-AFA-ATS-AYM-AZM-BEF-BGL-BOV-BYB-CHE-CHW-CLF-COU-CUC-CYP-DEM-EEK-ESP-FIM-FRF-GHC-GRD-GWP-IEP-ITL-LUF-MGF-MTL-MXV-MZM-NLG-PTE-ROL-RUR-SDD-SIT-SKK-SRG-TMM-TPE-TRL-VEF-UYI-USN-USS-VEB-XAG-XAU-XBA-XBB-XBC-XBD-XDR-XFO-XFU-XPD-XPT-XSU-XTS-XUA-XXX-YUM-ZMK-ZWD-ZWN-ZWR"; + "ADP-AFA-ATS-AYM-AZM-BEF-BGL-BOV-BYB-BYR-CHE-CHW-CLF-COU-CUC-CYP-DEM-EEK-ESP-FIM-FRF-GHC-GRD-GWP-IEP-ITL-LUF-MGF-MTL-MXV-MZM-NLG-PTE-ROL-RUR-SDD-SIT-SKK-SRG-TMM-TPE-TRL-VEF-UYI-USN-USS-VEB-XAG-XAU-XBA-XBB-XBC-XBD-XDR-XFO-XFU-XPD-XPT-XSU-XTS-XUA-XXX-YUM-ZMK-ZWD-ZWN-ZWR"; static boolean err = false; diff --git a/jdk/test/java/util/Currency/tablea1.txt b/jdk/test/java/util/Currency/tablea1.txt index dacc0fb5210..0ef755a7a87 100644 --- a/jdk/test/java/util/Currency/tablea1.txt +++ b/jdk/test/java/util/Currency/tablea1.txt @@ -1,12 +1,12 @@ # # -# Amendments up until ISO 4217 AMENDMENT NUMBER 160 -# (As of 19 June 2015) +# Amendments up until ISO 4217 AMENDMENT NUMBER 162 +# (As of 30 Auguest 2016) # # Version FILEVERSION=3 -DATAVERSION=160 +DATAVERSION=162 # ISO 4217 currency data AF AFN 971 2 @@ -28,7 +28,7 @@ BS BSD 44 2 BH BHD 48 3 BD BDT 50 2 BB BBD 52 2 -BY BYR 974 0 +BY BYN 933 2 BE EUR 978 2 BZ BZD 84 2 BJ XOF 952 0 diff --git a/jdk/test/sun/text/resources/LocaleData b/jdk/test/sun/text/resources/LocaleData index 53516a7ead4..a4bae5a9c21 100644 --- a/jdk/test/sun/text/resources/LocaleData +++ b/jdk/test/sun/text/resources/LocaleData @@ -6403,8 +6403,8 @@ CurrencyNames//bgn=Bulgarian Lev CurrencyNames//bif=Burundian Franc CurrencyNames//bob=Bolivian Boliviano CurrencyNames//btn=Bhutanese Ngultrum -CurrencyNames//byb=Belarusian New Ruble (1994-1999) -CurrencyNames//byr=Belarusian Ruble +CurrencyNames//byb=Belarusian Ruble (1994-1999) +CurrencyNames//byr=Belarusian Ruble (2000-2016) CurrencyNames//cdf=Congolese Franc CurrencyNames//clf=Chilean Unit of Account (UF) CurrencyNames//cny=Chinese Yuan @@ -6436,7 +6436,6 @@ CurrencyNames//mop=Macanese Pataca CurrencyNames//mro=Mauritanian Ouguiya CurrencyNames//mur=Mauritian Rupee CurrencyNames//mvr=Maldivian Rufiyaa -CurrencyNames//mwk=Malawian Kwacha CurrencyNames//mxv=Mexican Investment Unit CurrencyNames//mzm=Mozambican Metical (1980-2006) CurrencyNames//mzn=Mozambican Metical @@ -6444,7 +6443,6 @@ CurrencyNames//nad=Namibian Dollar CurrencyNames//nio=Nicaraguan C\u00f3rdoba CurrencyNames//nlg=Dutch Guilder CurrencyNames//omr=Omani Rial -CurrencyNames//pen=Peruvian Nuevo Sol CurrencyNames//pgk=Papua New Guinean Kina CurrencyNames//pkr=Pakistani Rupee CurrencyNames//pyg=Paraguayan Guarani @@ -8287,3 +8285,11 @@ FormatData/de/standalone.MonthAbbreviations/2=M\u00e4r # bug #8129361 CurrencyNames//hrk=Kuna + +# bug #8164784 +CurrencyNames//mwk=Malawian Malawi Kwacha +CurrencyNames//pen=Peruvian Sol + +# bug #8145952 +CurrencyNames//byn=Belarusian Ruble +CurrencyNames/be_BY/BYN=\u0420\u0443\u0431 diff --git a/jdk/test/sun/text/resources/LocaleDataTest.java b/jdk/test/sun/text/resources/LocaleDataTest.java index 6f1dca3e0d0..809cc55865f 100644 --- a/jdk/test/sun/text/resources/LocaleDataTest.java +++ b/jdk/test/sun/text/resources/LocaleDataTest.java @@ -37,7 +37,7 @@ * 7003124 7085757 7028073 7171028 7189611 8000983 7195759 8004489 8006509 * 7114053 7074882 7040556 8008577 8013836 8021121 6192407 6931564 8027695 * 8017142 8037343 8055222 8042126 8074791 8075173 8080774 8129361 8134916 - * 8145136 + * 8145136 8145952 8164784 * @summary Verify locale data * @modules java.base/sun.util.resources * @run main LocaleDataTest From 6d5b6597cdd5016769e150e69bc1787af4caf80f Mon Sep 17 00:00:00 2001 From: Alexander Scherbatiy Date: Thu, 1 Sep 2016 12:02:22 +0300 Subject: [PATCH 054/110] 8158411: Regression on Swingmark on 8u102 b03 comparing 8u102 b02 on several configs on win32 Reviewed-by: prr, ssadetsky --- .../windows/native/libawt/windows/ThemeReader.cpp | 14 +++++++++----- .../libawt/windows/awt_DesktopProperties.cpp | 15 ++++++++++----- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/ThemeReader.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/ThemeReader.cpp index b3d3e09ed65..c48ae8fbe31 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/ThemeReader.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/ThemeReader.cpp @@ -753,10 +753,15 @@ JNIEXPORT jobject JNICALL Java_sun_awt_windows_ThemeReader_getPosition } void rescale(SIZE *size) { - HWND hWnd = ::GetDesktopWindow(); - HDC hDC = ::GetDC(hWnd); - int dpiX = ::GetDeviceCaps(hDC, LOGPIXELSX); - int dpiY = ::GetDeviceCaps(hDC, LOGPIXELSY); + static int dpiX = -1; + static int dpiY = -1; + if (dpiX == -1 || dpiY == -1) { + HWND hWnd = ::GetDesktopWindow(); + HDC hDC = ::GetDC(hWnd); + dpiX = ::GetDeviceCaps(hDC, LOGPIXELSX); + dpiY = ::GetDeviceCaps(hDC, LOGPIXELSY); + ::ReleaseDC(hWnd, hDC); + } if (dpiX !=0 && dpiX != 96) { float invScaleX = 96.0f / dpiX; @@ -766,7 +771,6 @@ void rescale(SIZE *size) { float invScaleY = 96.0f / dpiY; size->cy = ROUND_TO_INT(size->cy * invScaleY); } - ::ReleaseDC(hWnd, hDC); } /* diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_DesktopProperties.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_DesktopProperties.cpp index 497d35dc350..608138fb2eb 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_DesktopProperties.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_DesktopProperties.cpp @@ -88,11 +88,16 @@ void AwtDesktopProperties::GetWindowsParameters() { } void getInvScale(float &invScaleX, float &invScaleY) { - HWND hWnd = ::GetDesktopWindow(); - HDC hDC = ::GetDC(hWnd); - int dpiX = ::GetDeviceCaps(hDC, LOGPIXELSX); - int dpiY = ::GetDeviceCaps(hDC, LOGPIXELSY); - ::ReleaseDC(hWnd, hDC); + static int dpiX = -1; + static int dpiY = -1; + if (dpiX == -1 || dpiY == -1) { + HWND hWnd = ::GetDesktopWindow(); + HDC hDC = ::GetDC(hWnd); + dpiX = ::GetDeviceCaps(hDC, LOGPIXELSX); + dpiY = ::GetDeviceCaps(hDC, LOGPIXELSY); + ::ReleaseDC(hWnd, hDC); + } + invScaleX = (dpiX == 0.0f) ? 1.0f : 96.0f / dpiX; invScaleY = (dpiY == 0.0f) ? 1.0f : 96.0f / dpiY; } From 63217bef37d32c1e3889c19f4168efcfacfe10db Mon Sep 17 00:00:00 2001 From: Prem Balakrishnan Date: Thu, 1 Sep 2016 16:18:14 +0530 Subject: [PATCH 055/110] 8144735: [hidpi] javax/swing/JWindow/ShapedAndTranslucentWindows/TranslucentPerPixelTranslucentGradient.java fails Reviewed-by: psadhukhan, vadim --- .../classes/sun/awt/windows/TranslucentWindowPainter.java | 6 +++--- .../TranslucentPerPixelTranslucentGradient.java | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/TranslucentWindowPainter.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/TranslucentWindowPainter.java index e57ce205a74..05043bd7525 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/TranslucentWindowPainter.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/TranslucentWindowPainter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, 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 @@ -303,10 +303,10 @@ abstract class TranslucentWindowPainter { if (bb instanceof DestSurfaceProvider) { Surface s = ((DestSurfaceProvider)bb).getDestSurface(); if (s instanceof AccelSurface) { - final int w = bb.getWidth(null); - final int h = bb.getHeight(null); final boolean arr[] = { false }; final AccelSurface as = (AccelSurface)s; + final int w = as.getBounds().width; + final int h = as.getBounds().height; RenderQueue rq = as.getContext().getRenderQueue(); rq.lock(); try { diff --git a/jdk/test/javax/swing/JWindow/ShapedAndTranslucentWindows/TranslucentPerPixelTranslucentGradient.java b/jdk/test/javax/swing/JWindow/ShapedAndTranslucentWindows/TranslucentPerPixelTranslucentGradient.java index 2137217b142..8022e8fff0b 100644 --- a/jdk/test/javax/swing/JWindow/ShapedAndTranslucentWindows/TranslucentPerPixelTranslucentGradient.java +++ b/jdk/test/javax/swing/JWindow/ShapedAndTranslucentWindows/TranslucentPerPixelTranslucentGradient.java @@ -25,6 +25,7 @@ import java.awt.*; /* * @test + * @bug 8144735 * @key headful * @summary Check if a per-pixel translucent and translucent window is dragged * and resized by mouse correctly From 347a38c28ddacc90ea1721f2484a27598f7c62dd Mon Sep 17 00:00:00 2001 From: Li Jiang Date: Thu, 1 Sep 2016 08:59:47 -0700 Subject: [PATCH 056/110] 8159408: duplicated data in rmic's javac.properties Reviewed-by: alanb --- .../share/classes/sun/tools/javac/resources/javac.properties | 2 -- 1 file changed, 2 deletions(-) diff --git a/jdk/src/jdk.rmic/share/classes/sun/tools/javac/resources/javac.properties b/jdk/src/jdk.rmic/share/classes/sun/tools/javac/resources/javac.properties index 2caf03fd1ea..5b754bb5d74 100644 --- a/jdk/src/jdk.rmic/share/classes/sun/tools/javac/resources/javac.properties +++ b/jdk/src/jdk.rmic/share/classes/sun/tools/javac/resources/javac.properties @@ -265,8 +265,6 @@ javac.err.unmatched.constr=\ No constructor matching {0} found in {1}. javac.err.wrong.number.args=\ Wrong number of arguments in {0}. -javac.err.wrong.number.args=\ - Wrong number of arguments in {0}. javac.err.forward.ref=\ Can''t make forward reference to {0} in {1}. javac.err.array.dim.missing=\ From 6f12a4ff0df3224f3a472e38c1f8e55809064b6a Mon Sep 17 00:00:00 2001 From: Phil Race Date: Thu, 1 Sep 2016 11:29:20 -0700 Subject: [PATCH 057/110] 8144015: [PIT] failures of text layout font tests 8144023: [PIT] failure of text measurements in javax/swing/text/html/parser/Parser/6836089/bug6836089.java 8145542: The case failed automatically and thrown java.lang.ArrayIndexOutOfBoundsException exception 8151725: [macosx] ArrayIndexOOB exception when displaying Devanagari text in JEditorPane 8144240: [macosx][PIT] AIOOB in closed/javax/swing/text/GlyphPainter2/6427244/bug6427244.java 8152680: Regression in GlyphVector.getGlyphCharIndex behaviour 8158924: Incorrect i18n text document layout 8041480: ArrayIndexOutOfBoundsException when JTable contains certain string Reviewed-by: serb, srl --- .../sun/font/ExtendedTextSourceLabel.java | 231 +++++++--------- .../share/native/libfontmanager/HBShaper.c | 164 ++++++------ .../GlyphVector/GetGlyphCharIndexTest.java | 44 ++++ .../TestLineBreakWithFontSub.java | 143 ++++++++++ .../font/TextLayout/LigatureCaretTest.java | 167 ++++++++++++ .../font/TextLayout/TestJustification.html | 52 ++++ .../font/TextLayout/TestJustification.java | 249 ++++++++++++++++++ .../javax/swing/text/DevanagariEditor.java | 36 +++ .../GlyphPainter2/6427244/bug6427244.java | 153 +++++++++++ 9 files changed, 1024 insertions(+), 215 deletions(-) create mode 100644 jdk/test/java/awt/font/GlyphVector/GetGlyphCharIndexTest.java create mode 100644 jdk/test/java/awt/font/LineBreakMeasurer/TestLineBreakWithFontSub.java create mode 100644 jdk/test/java/awt/font/TextLayout/LigatureCaretTest.java create mode 100644 jdk/test/java/awt/font/TextLayout/TestJustification.html create mode 100644 jdk/test/java/awt/font/TextLayout/TestJustification.java create mode 100644 jdk/test/javax/swing/text/DevanagariEditor.java create mode 100644 jdk/test/javax/swing/text/GlyphPainter2/6427244/bug6427244.java diff --git a/jdk/src/java.desktop/share/classes/sun/font/ExtendedTextSourceLabel.java b/jdk/src/java.desktop/share/classes/sun/font/ExtendedTextSourceLabel.java index 54c5382129c..67aee9e18db 100644 --- a/jdk/src/java.desktop/share/classes/sun/font/ExtendedTextSourceLabel.java +++ b/jdk/src/java.desktop/share/classes/sun/font/ExtendedTextSourceLabel.java @@ -550,13 +550,16 @@ class ExtendedTextSourceLabel extends ExtendedTextLabel implements Decoration.La return charinfo; } + private static final boolean DEBUG = FontUtilities.debugFonts(); /* * This takes the glyph info record obtained from the glyph vector and converts it into a similar record * adjusted to represent character data instead. For economy we don't use glyph info records in this processing. * * Here are some constraints: * - there can be more glyphs than characters (glyph insertion, perhaps based on normalization, has taken place) -* - there can not be fewer glyphs than characters (0xffff glyphs are inserted for characters ligaturized away) +* - there can be fewer glyphs than characters +* Some layout engines may insert 0xffff glyphs for characters ligaturized away, but +* not all do, and it cannot be relied upon. * - each glyph maps to a single character, when multiple glyphs exist for a character they all map to it, but * no two characters map to the same glyph * - multiple glyphs mapping to the same character need not be in sequence (thai, tamil have split characters) @@ -578,7 +581,8 @@ class ExtendedTextSourceLabel extends ExtendedTextLabel implements Decoration.La * * The algorithm works in the following way: * 1) we scan the glyphs ltr or rtl based on the bidi run direction -* 2) we can work in place, since we always consume a glyph for each char we write +* 2) Since the may be fewer glyphs than chars we cannot work in place. +* A new array is allocated for output. * a) if the line is ltr, we start writing at position 0 until we finish, there may be leftver space * b) if the line is rtl and 1-1, we start writing at position numChars/glyphs - 1 until we finish at 0 * c) otherwise if we don't finish at 0, we have to copy the data down @@ -594,7 +598,7 @@ class ExtendedTextSourceLabel extends ExtendedTextLabel implements Decoration.La * iii) the x advance is the distance to the maximum x + adv of all glyphs whose advance is not zero * iv) the y advance is the baseline * v) vis x,y,w,h tightly encloses the vis x,y,w,h of all the glyphs with nonzero w and h -* 4) we can make some simple optimizations if we know some things: +* 4) In the future, we can make some simple optimizations to avoid copying if we know some things: * a) if the mapping is 1-1, unidirectional, and there are no zero-adv glyphs, we just return the glyphinfo * b) if the mapping is 1-1, unidirectional, we just adjust the remaining glyphs to originate at right/left of the base * c) if the mapping is 1-1, we compute the base position and advance as we go, then go back to adjust the remaining glyphs @@ -625,23 +629,20 @@ class ExtendedTextSourceLabel extends ExtendedTextLabel implements Decoration.La System.out.println(source); } - /* - if ((gv.getDescriptionFlags() & 0x7) == 0) { - return glyphinfo; - } - */ - int numGlyphs = gv.getNumGlyphs(); if (numGlyphs == 0) { return glyphinfo; } int[] indices = gv.getGlyphCharIndices(0, numGlyphs, null); + float[] charInfo = new float[source.getLength() * numvals]; - boolean DEBUG = false; if (DEBUG) { System.err.println("number of glyphs: " + numGlyphs); + System.err.println("glyphinfo.len: " + glyphinfo.length); + System.err.println("indices.len: " + indices.length); for (int i = 0; i < numGlyphs; ++i) { System.err.println("g: " + i + + " v: " + gv.getGlyphCode(i) + ", x: " + glyphinfo[i*numvals+posx] + ", a: " + glyphinfo[i*numvals+advx] + ", n: " + indices[i]); @@ -650,22 +651,19 @@ class ExtendedTextSourceLabel extends ExtendedTextLabel implements Decoration.La int minIndex = indices[0]; // smallest index seen this cluster int maxIndex = minIndex; // largest index seen this cluster - int nextMin = 0; // expected smallest index for this cluster int cp = 0; // character position - int cx = 0; // character index (logical) + int cc = 0; int gp = 0; // glyph position int gx = 0; // glyph index (visual) int gxlimit = numGlyphs; // limit of gx, when we reach this we're done int pdelta = numvals; // delta for incrementing positions int xdelta = 1; // delta for incrementing indices - boolean ltr = (source.getLayoutFlags() & 0x1) == 0; - if (!ltr) { + boolean rtl = (source.getLayoutFlags() & 0x1) == 1; + if (rtl) { minIndex = indices[numGlyphs - 1]; maxIndex = minIndex; - nextMin = 0; // still logical - cp = glyphinfo.length - numvals; - cx = 0; // still logical + cp = charInfo.length - numvals; gp = glyphinfo.length - numvals; gx = numGlyphs - 1; gxlimit = -1; @@ -693,47 +691,36 @@ class ExtendedTextSourceLabel extends ExtendedTextLabel implements Decoration.La float cposl = 0, cposr = 0, cvisl = 0, cvist = 0, cvisr = 0, cvisb = 0; float baseline = 0; - // record if we have to copy data even when no cluster - boolean mustCopy = false; - while (gx != gxlimit) { // start of new cluster - boolean haveCopy = false; int clusterExtraGlyphs = 0; minIndex = indices[gx]; maxIndex = minIndex; + cposl = glyphinfo[gp + posx]; + cposr = cposl + glyphinfo[gp + advx]; + cvisl = glyphinfo[gp + visx]; + cvist = glyphinfo[gp + visy]; + cvisr = cvisl + glyphinfo[gp + visw]; + cvisb = cvist + glyphinfo[gp + vish]; + // advance to next glyph gx += xdelta; gp += pdelta; - /* - while (gx != gxlimit && (glyphinfo[gp + advx] == 0 || - minIndex != nextMin || indices[gx] <= maxIndex)) { - */ while (gx != gxlimit && ((glyphinfo[gp + advx] == 0) || - (minIndex != nextMin) || (indices[gx] <= maxIndex) || (maxIndex - minIndex > clusterExtraGlyphs))) { - // initialize base data first time through, using base glyph - if (!haveCopy) { - int gps = gp - pdelta; - cposl = glyphinfo[gps + posx]; - cposr = cposl + glyphinfo[gps + advx]; - cvisl = glyphinfo[gps + visx]; - cvist = glyphinfo[gps + visy]; - cvisr = cvisl + glyphinfo[gps + visw]; - cvisb = cvist + glyphinfo[gps + vish]; - - haveCopy = true; + ++clusterExtraGlyphs; // have an extra glyph in this cluster + if (DEBUG) { + System.err.println("gp=" +gp +" adv=" + glyphinfo[gp + advx] + + " gx="+ gx+ " i[gx]="+indices[gx] + + " clusterExtraGlyphs="+clusterExtraGlyphs); } - // have an extra glyph in this cluster - ++clusterExtraGlyphs; - // adjust advance only if new glyph has non-zero advance float radvx = glyphinfo[gp + advx]; if (radvx != 0) { @@ -764,110 +751,90 @@ class ExtendedTextSourceLabel extends ExtendedTextLabel implements Decoration.La // done with cluster, gx and gp are set for next glyph if (DEBUG) { - System.out.println("minIndex = " + minIndex + ", maxIndex = " + maxIndex); + System.err.println("minIndex = " + minIndex + ", maxIndex = " + maxIndex); } - nextMin = maxIndex + 1; + // save adjustments to the base character and do common adjustments. + charInfo[cp + posx] = cposl; + charInfo[cp + posy] = baseline; + charInfo[cp + advx] = cposr - cposl; + charInfo[cp + advy] = 0; + charInfo[cp + visx] = cvisl; + charInfo[cp + visy] = cvist; + charInfo[cp + visw] = cvisr - cvisl; + charInfo[cp + vish] = cvisb - cvist; + cc++; - // do common character adjustments - glyphinfo[cp + posy] = baseline; - glyphinfo[cp + advy] = 0; - - if (haveCopy) { - // save adjustments to the base character - glyphinfo[cp + posx] = cposl; - glyphinfo[cp + advx] = cposr - cposl; - glyphinfo[cp + visx] = cvisl; - glyphinfo[cp + visy] = cvist; - glyphinfo[cp + visw] = cvisr - cvisl; - glyphinfo[cp + vish] = cvisb - cvist; - - // compare number of chars read with number of glyphs read. - // if more glyphs than chars, set mustCopy to true, as we'll always have - // to copy the data from here on out. - if (maxIndex - minIndex < clusterExtraGlyphs) { - mustCopy = true; - } - - // Fix the characters that follow the base character. - // New values are all the same. Note we fix the number of characters - // we saw, not the number of glyphs we saw. - if (minIndex < maxIndex) { - if (!ltr) { - // if rtl, characters to left of base, else to right. reuse cposr. - cposr = cposl; - } - cvisr -= cvisl; // reuse, convert to deltas. - cvisb -= cvist; - - int iMinIndex = minIndex, icp = cp / 8; - - while (minIndex < maxIndex) { - ++minIndex; - cx += xdelta; - cp += pdelta; - - if (cp < 0 || cp >= glyphinfo.length) { - if (DEBUG) System.out.println("minIndex = " + iMinIndex + ", maxIndex = " + maxIndex + ", cp = " + icp); - } - - glyphinfo[cp + posx] = cposr; - glyphinfo[cp + posy] = baseline; - glyphinfo[cp + advx] = 0; - glyphinfo[cp + advy] = 0; - glyphinfo[cp + visx] = cvisl; - glyphinfo[cp + visy] = cvist; - glyphinfo[cp + visw] = cvisr; - glyphinfo[cp + vish] = cvisb; - } - } - - // no longer using this copy - haveCopy = false; - } else if (mustCopy) { - // out of synch, so we have to copy all the time now - int gpr = gp - pdelta; - - glyphinfo[cp + posx] = glyphinfo[gpr + posx]; - glyphinfo[cp + advx] = glyphinfo[gpr + advx]; - glyphinfo[cp + visx] = glyphinfo[gpr + visx]; - glyphinfo[cp + visy] = glyphinfo[gpr + visy]; - glyphinfo[cp + visw] = glyphinfo[gpr + visw]; - glyphinfo[cp + vish] = glyphinfo[gpr + vish]; + /* We may have consumed multiple glyphs for this char position. + * Map those extra consumed glyphs to char positions that would follow + * up to the index prior to that which begins the next cluster. + * If we have reached the last glyph (reached gxlimit) then we need to + * map remaining unmapped chars to the same location as the last one. + */ + int tgt; + if (gx == gxlimit) { + tgt = charInfo.length / numvals; + } else { + tgt = indices[gx]-1; } - // else glyphinfo is already at the correct character position, and is unchanged, so just leave it + if (DEBUG) { + System.err.println("gx=" + gx + " gxlimit=" + gxlimit + + " charInfo.len=" + charInfo.length + + " tgt=" + tgt + " cc=" + cc + " cp=" + cp); + } + while (cc < tgt) { + if (rtl) { + // if rtl, characters to left of base, else to right. reuse cposr. + cposr = cposl; + } + cvisr -= cvisl; // reuse, convert to deltas. + cvisb -= cvist; - // reset for new cluster - cp += pdelta; - cx += xdelta; - } + cp += pdelta; - if (mustCopy && !ltr) { - // data written to wrong end of array, need to shift down + if (cp < 0 || cp >= charInfo.length) { + if (DEBUG) { + System.err.println("Error : cp=" + cp + + " charInfo.length=" + charInfo.length); + } + break; + } - cp -= pdelta; // undo last increment, get start of valid character data in array - System.arraycopy(glyphinfo, cp, glyphinfo, 0, glyphinfo.length - cp); + if (DEBUG) { + System.err.println("Insert charIndex " + cc + " at pos="+cp); + } + charInfo[cp + posx] = cposr; + charInfo[cp + posy] = baseline; + charInfo[cp + advx] = 0; + charInfo[cp + advy] = 0; + charInfo[cp + visx] = cvisl; + charInfo[cp + visy] = cvist; + charInfo[cp + visw] = cvisr; + charInfo[cp + vish] = cvisb; + cc++; + } + cp += pdelta; // reset for new cluster } if (DEBUG) { - char[] chars = source.getChars(); - int start = source.getStart(); - int length = source.getLength(); - System.out.println("char info for " + length + " characters"); - for(int i = 0; i < length * numvals;) { - System.out.println(" ch: " + Integer.toHexString(chars[start + v2l(i / numvals)]) + - " x: " + glyphinfo[i++] + - " y: " + glyphinfo[i++] + - " xa: " + glyphinfo[i++] + - " ya: " + glyphinfo[i++] + - " l: " + glyphinfo[i++] + - " t: " + glyphinfo[i++] + - " w: " + glyphinfo[i++] + - " h: " + glyphinfo[i++]); + char[] chars = source.getChars(); + int start = source.getStart(); + int length = source.getLength(); + System.err.println("char info for " + length + " characters"); + + for (int i = 0; i < length * numvals;) { + System.err.println(" ch: " + Integer.toHexString(chars[start + v2l(i / numvals)]) + + " x: " + charInfo[i++] + + " y: " + charInfo[i++] + + " xa: " + charInfo[i++] + + " ya: " + charInfo[i++] + + " l: " + charInfo[i++] + + " t: " + charInfo[i++] + + " w: " + charInfo[i++] + + " h: " + charInfo[i++]); } } - - return glyphinfo; + return charInfo; } /** diff --git a/jdk/src/java.desktop/share/native/libfontmanager/HBShaper.c b/jdk/src/java.desktop/share/native/libfontmanager/HBShaper.c index 3b35e27efda..3b7a463ffdf 100644 --- a/jdk/src/java.desktop/share/native/libfontmanager/HBShaper.c +++ b/jdk/src/java.desktop/share/native/libfontmanager/HBShaper.c @@ -40,6 +40,7 @@ static jfieldID gvdFlagsFID = 0; static jfieldID gvdGlyphsFID = 0; static jfieldID gvdPositionsFID = 0; static jfieldID gvdIndicesFID = 0; +static jmethodID gvdGrowMID = 0; static int jniInited = 0; static void getFloat(JNIEnv* env, jobject pt, jfloat *x, jfloat *y) { @@ -63,73 +64,88 @@ static int init_JNI_IDs(JNIEnv *env) { CHECK_NULL_RETURN(gvdGlyphsFID = (*env)->GetFieldID(env, gvdClass, "_glyphs", "[I"), 0); CHECK_NULL_RETURN(gvdPositionsFID = (*env)->GetFieldID(env, gvdClass, "_positions", "[F"), 0); CHECK_NULL_RETURN(gvdIndicesFID = (*env)->GetFieldID(env, gvdClass, "_indices", "[I"), 0); + CHECK_NULL_RETURN(gvdGrowMID = (*env)->GetMethodID(env, gvdClass, "grow", "()V"), 0); jniInited = 1; return jniInited; } // gmask is the composite font slot mask // baseindex is to be added to the character (code point) index. -int storeGVData(JNIEnv* env, - jobject gvdata, jint slot, jint baseIndex, jobject startPt, - int glyphCount, hb_glyph_info_t *glyphInfo, - hb_glyph_position_t *glyphPos, hb_direction_t direction, - float devScale) { +jboolean storeGVData(JNIEnv* env, + jobject gvdata, jint slot, + jint baseIndex, int offset, jobject startPt, + int charCount, int glyphCount, hb_glyph_info_t *glyphInfo, + hb_glyph_position_t *glyphPos, float devScale) { - int i; + int i, needToGrow; float x=0, y=0; - float startX, startY; + float startX, startY, advX, advY; float scale = 1.0f / FloatToFixedScale / devScale; unsigned int* glyphs; float* positions; - int initialCount, glyphArrayLen, posArrayLen, maxGlyphs, storeadv; + int initialCount, glyphArrayLen, posArrayLen, maxGlyphs, storeadv, maxStore; unsigned int* indices; jarray glyphArray, posArray, inxArray; if (!init_JNI_IDs(env)) { - return 0; + return JNI_FALSE; } initialCount = (*env)->GetIntField(env, gvdata, gvdCountFID); - glyphArray = - (jarray)(*env)->GetObjectField(env, gvdata, gvdGlyphsFID); - posArray = - (jarray)(*env)->GetObjectField(env, gvdata, gvdPositionsFID); - - if (glyphArray == NULL || posArray == NULL) - { - JNU_ThrowArrayIndexOutOfBoundsException(env, ""); - return 0; - } - - // The Java code catches the IIOBE and expands the storage - // and re-invokes layout. I suppose this is expected to be rare - // because at least in a single threaded case there should be - // re-use of the same container, but it is a little wasteful/distateful. - glyphArrayLen = (*env)->GetArrayLength(env, glyphArray); - posArrayLen = (*env)->GetArrayLength(env, posArray); - maxGlyphs = glyphCount + initialCount; - if ((maxGlyphs > glyphArrayLen) || - (maxGlyphs * 2 + 2 > posArrayLen)) - { - JNU_ThrowArrayIndexOutOfBoundsException(env, ""); - return 0; - } + do { + glyphArray = (jarray)(*env)->GetObjectField(env, gvdata, gvdGlyphsFID); + posArray = (jarray)(*env)->GetObjectField(env, gvdata, gvdPositionsFID); + inxArray = (jarray)(*env)->GetObjectField(env, gvdata, gvdIndicesFID); + if (glyphArray == NULL || posArray == NULL || inxArray == NULL) { + JNU_ThrowArrayIndexOutOfBoundsException(env, ""); + return JNI_FALSE; + } + glyphArrayLen = (*env)->GetArrayLength(env, glyphArray); + posArrayLen = (*env)->GetArrayLength(env, posArray); + maxGlyphs = (charCount > glyphCount) ? charCount : glyphCount; + maxStore = maxGlyphs + initialCount; + needToGrow = (maxStore > glyphArrayLen) || + (maxStore * 2 + 2 > posArrayLen); + if (needToGrow) { + (*env)->CallVoidMethod(env, gvdata, gvdGrowMID); + if ((*env)->ExceptionCheck(env)) { + return JNI_FALSE; + } + } + } while (needToGrow); getFloat(env, startPt, &startX, &startY); glyphs = (unsigned int*)(*env)->GetPrimitiveArrayCritical(env, glyphArray, NULL); + if (glyphs == NULL) { + return JNI_FALSE; + } positions = (jfloat*)(*env)->GetPrimitiveArrayCritical(env, posArray, NULL); + if (positions == NULL) { + (*env)->ReleasePrimitiveArrayCritical(env, glyphArray, glyphs, 0); + return JNI_FALSE; + } + indices = + (unsigned int*)(*env)->GetPrimitiveArrayCritical(env, inxArray, NULL); + if (indices == NULL) { + (*env)->ReleasePrimitiveArrayCritical(env, glyphArray, glyphs, 0); + (*env)->ReleasePrimitiveArrayCritical(env, posArray, positions, 0); + return JNI_FALSE; + } + for (i = 0; i < glyphCount; i++) { int storei = i + initialCount; - int index = glyphInfo[i].codepoint | slot; - if (iReleasePrimitiveArrayCritical(env, glyphArray, glyphs, 0); (*env)->ReleasePrimitiveArrayCritical(env, posArray, positions, 0); - putFloat(env, startPt,positions[(storeadv*2)],positions[(storeadv*2)+1] ); - inxArray = - (jarray)(*env)->GetObjectField(env, gvdata, gvdIndicesFID); - indices = - (unsigned int*)(*env)->GetPrimitiveArrayCritical(env, inxArray, NULL); - for (i = 0; i < glyphCount; i++) { - int cluster = glyphInfo[i].cluster; - if (direction == HB_DIRECTION_LTR) { - // I need to understand what hb does when processing a substring - // I expected the cluster index to be from the start of the text - // to process. - // Instead it appears to be from the start of the whole thing. - indices[i+initialCount] = cluster; - } else { - indices[i+initialCount] = baseIndex + glyphCount -1 -i; - } - } (*env)->ReleasePrimitiveArrayCritical(env, inxArray, indices, 0); - (*env)->SetIntField(env, gvdata, gvdCountFID, initialCount+glyphCount); - return initialCount+glyphCount; + putFloat(env, startPt, advX, advY); + (*env)->SetIntField(env, gvdata, gvdCountFID, storeadv); + + return JNI_TRUE; } static float euclidianDistance(float a, float b) @@ -226,7 +229,9 @@ JDKFontInfo* } -#define TYPO_RTL 0x80000000 +#define TYPO_KERN 0x00000001 +#define TYPO_LIGA 0x00000002 +#define TYPO_RTL 0x80000000 JNIEXPORT jboolean JNICALL Java_sun_font_SunLayoutEngine_shape (JNIEnv *env, jclass cls, @@ -255,10 +260,11 @@ JNIEXPORT jboolean JNICALL Java_sun_font_SunLayoutEngine_shape hb_glyph_info_t *glyphInfo; hb_glyph_position_t *glyphPos; hb_direction_t direction = HB_DIRECTION_LTR; - hb_feature_t *features = NULL; + hb_feature_t *features = NULL; int featureCount = 0; - - int i; + char* kern = (flags & TYPO_KERN) ? "kern" : "-kern"; + char* liga = (flags & TYPO_LIGA) ? "liga" : "-liga"; + jboolean ret; unsigned int buflen; JDKFontInfo *jdkFontInfo = @@ -281,6 +287,8 @@ JNIEXPORT jboolean JNICALL Java_sun_font_SunLayoutEngine_shape direction = HB_DIRECTION_RTL; } hb_buffer_set_direction(buffer, direction); + hb_buffer_set_cluster_level(buffer, + HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS); chars = (*env)->GetCharArrayElements(env, text, NULL); if ((*env)->ExceptionCheck(env)) { @@ -293,36 +301,26 @@ JNIEXPORT jboolean JNICALL Java_sun_font_SunLayoutEngine_shape hb_buffer_add_utf16(buffer, chars, len, offset, limit-offset); + features = calloc(2, sizeof(hb_feature_t)); + if (features) { + hb_feature_from_string(kern, -1, &features[featureCount++]); + hb_feature_from_string(liga, -1, &features[featureCount++]); + } + hb_shape_full(hbfont, buffer, features, featureCount, 0); glyphCount = hb_buffer_get_length(buffer); glyphInfo = hb_buffer_get_glyph_infos(buffer, 0); glyphPos = hb_buffer_get_glyph_positions(buffer, &buflen); - for (i = 0; i < glyphCount; i++) { - int index = glyphInfo[i].codepoint; - int xadv = (glyphPos[i].x_advance); - int yadv = (glyphPos[i].y_advance); - } - // On "input" HB assigns a cluster index to each character in UTF-16. - // On output where a sequence of characters have been mapped to - // a glyph they are all mapped to the cluster index of the first character. - // The next cluster index will be that of the first character in the - // next cluster. So cluster indexes may 'skip' on output. - // This can also happen if there are supplementary code-points - // such that two UTF-16 characters are needed to make one codepoint. - // In RTL text you need to count down. - // So the following code tries to build the reverse map as expected - // by calling code. - storeGVData(env, gvdata, slot, baseIndex, startPt, - glyphCount, glyphInfo, glyphPos, direction, - jdkFontInfo->devScale); + ret = storeGVData(env, gvdata, slot, baseIndex, offset, startPt, + limit - offset, glyphCount, glyphInfo, glyphPos, + jdkFontInfo->devScale); hb_buffer_destroy (buffer); hb_font_destroy(hbfont); free((void*)jdkFontInfo); if (features != NULL) free(features); (*env)->ReleaseCharArrayElements(env, text, chars, JNI_ABORT); - - return JNI_TRUE; + return ret; } diff --git a/jdk/test/java/awt/font/GlyphVector/GetGlyphCharIndexTest.java b/jdk/test/java/awt/font/GlyphVector/GetGlyphCharIndexTest.java new file mode 100644 index 00000000000..1754e5f64cc --- /dev/null +++ b/jdk/test/java/awt/font/GlyphVector/GetGlyphCharIndexTest.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @summary Test getGlyphCharIndex() results from layout + * @bug 8152680 + * + +import java.awt.Font; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; + +public class GetGlyphCharIndexTest { + public static void main(String[] args) { + Font font = new Font(Font.MONOSPACED, Font.PLAIN, 12); + FontRenderContext frc = new FontRenderContext(null, false, false); + GlyphVector gv = font.layoutGlyphVector(frc, "abc".toCharArray(), 1, 3, + Font.LAYOUT_LEFT_TO_RIGHT); + int idx0 = gv.getGlyphCharIndex(0); + if (idx0 != 0) { + throw new RuntimeException("Expected 0, got " + idx0); + } + } +} diff --git a/jdk/test/java/awt/font/LineBreakMeasurer/TestLineBreakWithFontSub.java b/jdk/test/java/awt/font/LineBreakMeasurer/TestLineBreakWithFontSub.java new file mode 100644 index 00000000000..472fca810a5 --- /dev/null +++ b/jdk/test/java/awt/font/LineBreakMeasurer/TestLineBreakWithFontSub.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 1999, 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4175418 8158924 + * @author John Raley + * @summary This insures that bug 4175418: Font substitution in TextLayout / + * LineBreakMeasurer is inconsistent has been fixed. The problem was + * that text was measured in one Font, but lines were produced + * in a different font. + */ + +/* + * (C) Copyright IBM Corp. 1999, All Rights Reserved + */ + +import java.text.AttributedString; +import java.awt.font.LineBreakMeasurer; +import java.awt.font.TextLayout; +import java.awt.font.FontRenderContext; +import java.awt.font.TextAttribute; + +/** + * This insures that bug 4175418: Font substitution in TextLayout / + * LineBreakMeasurer is inconsistent has been fixed. The problem was + * that text was measured in one Font, but lines were produced + * in a different font. One symptom of this problem is that lines are + * either too short or too long. This test line-breaks a paragraph + * and checks the line lengths to make sure breaks were chosen well. + * This can be checked because the paragraph is so simple. + */ +public class TestLineBreakWithFontSub { + + public static void main(String[] args) { + + new TestLineBreakWithFontSub().test(); + System.out.println("Line break / font substitution test PASSED"); + } + + private static final String WORD = "word"; + private static final String SPACING = " "; + // The Hebrew character in this string can trigger font substitution + private static final String MIXED = "A\u05D0"; + + private static final int NUM_WORDS = 12; + + private static final FontRenderContext DEFAULT_FRC = + new FontRenderContext(null, false, false); + + public void test() { + + // construct a paragraph as follows: MIXED + [SPACING + WORD] + ... + StringBuffer text = new StringBuffer(MIXED); + for (int i=0; i < NUM_WORDS; i++) { + text.append(SPACING); + text.append(WORD); + } + + AttributedString attrString = new AttributedString(text.toString()); + attrString.addAttribute(TextAttribute.SIZE, new Float(24.0)); + + LineBreakMeasurer measurer = new LineBreakMeasurer(attrString.getIterator(), + DEFAULT_FRC); + + // get width of a space-word sequence, in context + int sequenceLength = WORD.length()+SPACING.length(); + measurer.setPosition(text.length() - sequenceLength); + + TextLayout layout = measurer.nextLayout(10000.0f); + + if (layout.getCharacterCount() != sequenceLength) { + throw new Error("layout length is incorrect!"); + } + + final float sequenceAdvance = layout.getVisibleAdvance(); + + float wrappingWidth = sequenceAdvance * 2; + + // now run test with a variety of widths + while (wrappingWidth < (sequenceAdvance*NUM_WORDS)) { + measurer.setPosition(0); + checkMeasurer(measurer, + wrappingWidth, + sequenceAdvance, + text.length()); + wrappingWidth += sequenceAdvance / 5; + } + } + + /** + * Iterate through measurer and check that every line is + * not too long and not too short, but just right. + */ + private void checkMeasurer(LineBreakMeasurer measurer, + float wrappingWidth, + float sequenceAdvance, + int endPosition) { + + do { + TextLayout layout = measurer.nextLayout(wrappingWidth); + float visAdvance = layout.getVisibleAdvance(); + + // Check that wrappingWidth-sequenceAdvance < visAdvance + // Also, if we're not at the end of the paragraph, + // check that visAdvance <= wrappingWidth + + if (visAdvance > wrappingWidth) { + // line is too long for given wrapping width + throw new Error("layout is too long"); + } + + if (measurer.getPosition() < endPosition) { + if (visAdvance <= wrappingWidth - sequenceAdvance) { + // line is too short for given wrapping width; + // another word would have fit + throw new Error("room for more words on line. diff=" + + (wrappingWidth - sequenceAdvance - visAdvance)); + } + } + } while (measurer.getPosition() != endPosition); + } +} diff --git a/jdk/test/java/awt/font/TextLayout/LigatureCaretTest.java b/jdk/test/java/awt/font/TextLayout/LigatureCaretTest.java new file mode 100644 index 00000000000..e59bccac996 --- /dev/null +++ b/jdk/test/java/awt/font/TextLayout/LigatureCaretTest.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 1998, 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4178145 8144015 +*/ + +/* + * Copyright 1998 IBM Corp. All Rights Reserved. + */ + +import java.awt.Color; +import java.awt.Font; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.font.TextAttribute; +import java.awt.font.TextLayout; +import java.awt.font.TextHitInfo; +import java.awt.font.FontRenderContext; +import java.util.Hashtable; + +/** + * This test ensures that TextLayout will not place a caret within + * an Arabic lam-alef ligature, and will correctly caret through + * bidirectional text with numbers. + */ + +public class LigatureCaretTest { + + public static void main(String[] args) { + + //testBidiWithNumbers(); + testLamAlef(); + System.out.println("LigatureCaretTest PASSED"); + } + + // These values are for TextLayout constructors + private static final Hashtable map = new Hashtable(); + static { + map.put(TextAttribute.FONT, new Font("Lucida Sans", Font.PLAIN, 24)); + } + private static final FontRenderContext frc = + new FontRenderContext(null, false, false); + + /** + * Caret through text mixed-direction text and check the results. + * If the test fails an Error is thrown. + * @exception an Error is thrown if the test fails + */ + public static void testBidiWithNumbers() { + + String bidiWithNumbers = "abc\u05D0\u05D1\u05D2123abc"; + // visual order for the text: + // abc123abc + + int[] carets = { 0, 1, 2, 3, 7, 8, 6, 5, 4, 9, 10, 11, 12 }; + TextLayout layout = new TextLayout(bidiWithNumbers, map, frc); + + // Caret through TextLayout in both directions and check results. + for (int i=0; i < carets.length-1; i++) { + + TextHitInfo hit = layout.getNextRightHit(carets[i]); + if (hit.getInsertionIndex() != carets[i+1]) { + throw new Error("right hit failed within layout"); + } + } + + if (layout.getNextRightHit(carets[carets.length-1]) != null) { + throw new Error("right hit failed at end of layout"); + } + + for (int i=carets.length-1; i > 0; i--) { + + TextHitInfo hit = layout.getNextLeftHit(carets[i]); + if (hit.getInsertionIndex() != carets[i-1]) { + throw new Error("left hit failed within layout"); + } + } + + if (layout.getNextLeftHit(carets[0]) != null) { + throw new Error("left hit failed at end of layout"); + } + } + + /** + * Ensure proper careting and hit-testing behavior with + * a lam-alef ligature. + * If the test fails, an Error is thrown. + * @exception an Error is thrown if the test fails + */ + public static void testLamAlef() { + + // lam-alef form a mandantory ligature. + final String lamAlef = "\u0644\u0627"; + final String ltrText = "abcd"; + + // Create a TextLayout with just a lam-alef sequence. There + // should only be two valid caret positions: one at + // insertion offset 0 and the other at insertion offset 2. + TextLayout layout = new TextLayout(lamAlef, map, frc); + + TextHitInfo hit; + + hit = layout.getNextLeftHit(0); + if (hit.getInsertionIndex() != 2) { + throw new Error("Left hit failed. Hit:" + hit); + } + + hit = layout.getNextRightHit(2); + if (hit.getInsertionIndex() != 0) { + throw new Error("Right hit failed. Hit:" + hit); + } + + hit = layout.hitTestChar(layout.getAdvance()/2, 0); + if (hit.getInsertionIndex() != 0 && hit.getInsertionIndex() != 2) { + throw new Error("Hit-test allowed incorrect caret. Hit:" + hit); + } + + + // Create a TextLayout with some left-to-right text + // before the lam-alef sequence. There should not be + // a caret position between the lam and alef. + layout = new TextLayout(ltrText+lamAlef, map, frc); + + final int ltrLen = ltrText.length(); + final int layoutLen = layout.getCharacterCount(); + + for (int i=0; i < ltrLen; i++) { + hit = layout.getNextRightHit(i); + if (hit.getInsertionIndex() != i+1) { + throw new Error("Right hit failed in ltr text."); + } + } + + hit = layout.getNextRightHit(ltrLen); + if (layoutLen != hit.getInsertionIndex()) { + throw new Error("Right hit failed at direction boundary."); + } + + hit = layout.getNextLeftHit(layoutLen); + if (hit.getInsertionIndex() != ltrLen) { + throw new Error("Left hit failed at end of text."); + } + } +} diff --git a/jdk/test/java/awt/font/TextLayout/TestJustification.html b/jdk/test/java/awt/font/TextLayout/TestJustification.html new file mode 100644 index 00000000000..c9e79f44cb2 --- /dev/null +++ b/jdk/test/java/awt/font/TextLayout/TestJustification.html @@ -0,0 +1,52 @@ + + + + +Test Justification + + + +

Test Justification

+
+

Five lines of text should appear, all justified to the same width, +followed by a sixth line containing only roman characters and no spaces +which is not justified, and instead is centered. +Carets should appear between all characters. Pass the test if this is +true. +

+ +alt="Your browser understands the <APPLET> tag but isn't running the applet, for some reason." +Your browser is completely ignoring the <APPLET> tag! + + + + diff --git a/jdk/test/java/awt/font/TextLayout/TestJustification.java b/jdk/test/java/awt/font/TextLayout/TestJustification.java new file mode 100644 index 00000000000..417ddd5adfc --- /dev/null +++ b/jdk/test/java/awt/font/TextLayout/TestJustification.java @@ -0,0 +1,249 @@ +/* + * Copyright (c) 1999, 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * + * See TestJustification.html for main test. + */ + +import java.applet.*; +import java.awt.*; +import java.awt.event.*; +import java.awt.font.*; +import java.awt.geom.*; +import java.text.*; + +public class TestJustification extends Applet { + JustificationPanel panel; + + public void init() { + setLayout(new BorderLayout()); + panel = new JustificationPanel("Bitstream Cyberbit"); + add("Center", panel); + } + + public void destroy() { + remove(panel); + } + + // calls system.exit, not for use in tests. + public static void main(String args[]) { + TestJustification justificationTest = new TestJustification(); + justificationTest.init(); + justificationTest.start(); + + Frame f = new Frame("Test Justification"); + f.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + + f.add("Center", justificationTest); + f.setSize(500, 500); + f.show(); + } + + public String getAppletInfo() { + return "Test TextLayout.getJustifiedLayout()"; + } + + static class JustificationPanel extends Panel { + TextLayout[] layouts; + String fontname; + float height; + float oldfsize; + + AttributedCharacterIterator lineText; + TextLayout[] lines; + int linecount; + float oldwidth; + + JustificationPanel(String fontname) { + this.fontname = fontname; + } + + private static final String[] texts = { + "This is an english Highlighting demo.", "Highlighting", + "This is an arabic \u0627\u0628\u062a\u062c \u062e\u0644\u0627\u062e demo.", "arabic \u0627\u0628\u062a\u062c", + "This is a hebrew \u05d0\u05d1\u05d2 \u05d3\u05d4\u05d5 demo.", "hebrew \u05d0\u05d1\u05d2", + "This is a cjk \u4e00\u4e01\u4e02\uac00\uac01\uc4fa\uf900\uf901\uf902 demo.", "cjk", + "NoSpaceCJK:\u4e00\u4e01\u4e02and\uac00\uac01\uc4faand\uf900\uf901\uf902", "No", + "NoSpaceRoman", "Space" + }; + + public void paint(Graphics g) { + Graphics2D g2d = (Graphics2D)g; + + Dimension d = getSize(); + Insets insets = getInsets(); + + float w = d.width - insets.left - insets.right; + float h = d.height - insets.top - insets.bottom; + int fsize = (int)w/25; + + FontRenderContext frc = g2d.getFontRenderContext(); + + if (layouts == null || fsize != oldfsize) { + oldfsize = fsize; + + Font f0 = new Font(fontname, Font.PLAIN, fsize); + Font f1 = new Font(fontname, Font.ITALIC, (int)(fsize * 1.5)); + + if (layouts == null) { + layouts = new TextLayout[texts.length / 2]; + } + + height = 0; + for (int i = 0; i < layouts.length; ++i) { + String text = texts[i*2]; + String target = texts[i*2+1]; + + AttributedString astr = new AttributedString(text); + astr.addAttribute(TextAttribute.FONT, f0, 0, text.length()); + + int start = text.indexOf(target); + int limit = start + target.length(); + astr.addAttribute(TextAttribute.FONT, f1, start, limit); + + TextLayout layout = new TextLayout(astr.getIterator(), frc); + + layout = layout.getJustifiedLayout(w - 20); + + layouts[i] = layout; + + height += layout.getAscent() + layout.getDescent() + layout.getLeading(); + } + } + + g2d.setColor(Color.white); + g2d.fill(new Rectangle.Float(insets.left, insets.top, w, h)); + + float basey = 20; + + for (int i = 0; i < layouts.length; ++i) { + TextLayout layout = layouts[i]; + + float la = layout.getAscent(); + float ld = layout.getDescent(); + float ll = layout.getLeading(); + float lw = layout.getAdvance(); + float lh = la + ld + ll; + float lx = (w - lw) / 2f; + float ly = basey + layout.getAscent(); + + g2d.setColor(Color.black); + g2d.translate(insets.left + lx, insets.top + ly); + + Rectangle2D bounds = new Rectangle2D.Float(0, -la, lw, lh); + g2d.draw(bounds); + + layout.draw(g2d, 0, 0); + + g2d.setColor(Color.red); + for (int j = 0, e = layout.getCharacterCount(); j <= e; ++j) { + Shape[] carets = layout.getCaretShapes(j, bounds); + g2d.draw(carets[0]); + } + + g2d.translate(-insets.left - lx, -insets.top - ly); + basey += layout.getAscent() + layout.getDescent() + layout.getLeading(); + } + + // add LineBreakMeasurer-generated layouts + + if (lineText == null) { + String text = "This is a long line of text that should be broken across multiple " + + "lines and then justified to fit the break width. This test should pass if " + + "these lines are justified to the same width, and fail otherwise. It should " + + "also format the hebrew (\u05d0\u05d1\u05d2 \u05d3\u05d4\u05d5) and arabic " + + "(\u0627\u0628\u062a\u062c \u062e\u0644\u0627\u062e) and CJK " + + "(\u4e00\u4e01\u4e02\uac00\uac01\uc4fa\u67b1\u67b2\u67b3\u67b4\u67b5\u67b6\u67b7" + + "\u67b8\u67b9) text correctly."; + + Float regular = new Float(16.0); + Float big = new Float(24.0); + AttributedString astr = new AttributedString(text); + astr.addAttribute(TextAttribute.SIZE, regular, 0, text.length()); + astr.addAttribute(TextAttribute.FAMILY, fontname, 0, text.length()); + + int ix = text.indexOf("broken"); + astr.addAttribute(TextAttribute.SIZE, big, ix, ix + 6); + ix = text.indexOf("hebrew"); + astr.addAttribute(TextAttribute.SIZE, big, ix, ix + 6); + ix = text.indexOf("arabic"); + astr.addAttribute(TextAttribute.SIZE, big, ix, ix + 6); + ix = text.indexOf("CJK"); + astr.addAttribute(TextAttribute.SIZE, big, ix, ix + 3); + + lineText = astr.getIterator(); + } + + float width = w - 20; + if (lines == null || width != oldwidth) { + oldwidth = width; + + lines = new TextLayout[10]; + linecount = 0; + + LineBreakMeasurer measurer = new LineBreakMeasurer(lineText, frc); + + for (;;) { + TextLayout layout = measurer.nextLayout(width); + if (layout == null) { + break; + } + + // justify all but last line + if (linecount > 0) { + lines[linecount - 1] = lines[linecount - 1].getJustifiedLayout(width); + } + + if (linecount == lines.length) { + TextLayout[] nlines = new TextLayout[lines.length * 2]; + System.arraycopy(lines, 0, nlines, 0, lines.length); + lines = nlines; + } + + lines[linecount++] = layout; + } + } + + float basex = insets.left + 10; + basey += 10; + g2d.setColor(Color.black); + + for (int i = 0; i < linecount; ++i) { + TextLayout layout = lines[i]; + + basey += layout.getAscent(); + float adv = layout.getAdvance(); + float dx = layout.isLeftToRight() ? 0 : width - adv; + + layout.draw(g2d, basex + dx, basey); + + basey += layout.getDescent() + layout.getLeading(); + } + } + } +} diff --git a/jdk/test/javax/swing/text/DevanagariEditor.java b/jdk/test/javax/swing/text/DevanagariEditor.java new file mode 100644 index 00000000000..3781a1beae7 --- /dev/null +++ b/jdk/test/javax/swing/text/DevanagariEditor.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8151725 + * @summary Tests no exception creating a JEditorPane with Devanagari + */ + +import javax.swing.JEditorPane; + +public class DevanagariEditor { + public static void main(String[] args) { + new JEditorPane().setText("\u0930\u093E\u0915\u094D\u0937\u0938"); + } +} diff --git a/jdk/test/javax/swing/text/GlyphPainter2/6427244/bug6427244.java b/jdk/test/javax/swing/text/GlyphPainter2/6427244/bug6427244.java new file mode 100644 index 00000000000..cc32aeb7690 --- /dev/null +++ b/jdk/test/javax/swing/text/GlyphPainter2/6427244/bug6427244.java @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2011, 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* @test + @bug 6427244 8144240 + @summary Test that pressing HOME correctly moves caret in I18N document. + @author Sergey Groznyh + @library ../../../regtesthelpers + @build JRobot Util TestCase + @run main bug6427244 +*/ + +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Shape; +import java.awt.event.KeyEvent; +import javax.swing.JFrame; +import javax.swing.JTextPane; +import javax.swing.SwingUtilities; +import javax.swing.text.Position; + +public class bug6427244 extends TestCase { + private static final JRobot ROBOT = JRobot.getRobot(); + + final static int TP_SIZE = 200; + final static String[] SPACES = new String[] { + "\u0020", // ASCII space + "\u2002", // EN space + "\u2003", // EM space + "\u2004", // THREE-PER-EM space + "\u2005", // ... etc. + "\u2006", + //"\u2007", + "\u2008", + "\u2009", + "\u200a", + "\u200b", + "\u205f", + "\u3000", + }; + final static String[] WORDS = new String[] { + "It", "is", "a", "long", "paragraph", "for", "testing", "GlyphPainter2\n\n", + }; + + public static void main(String[] args) { + bug6427244 t = new bug6427244(); + for (String space: SPACES) { + t.init(space); + t.runAllTests(); + } + + System.out.println("OK"); + } + + void init(final String space) { + try { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + String text = null; + for (String word: WORDS) { + if (text == null) { + text = ""; + } else { + text += space; + } + text += word; + } + tp = new JTextPane(); + tp.setText(text + + "Some arabic: \u062a\u0641\u0627\u062d and some not."); + if (jf == null) { + jf = new JFrame(); + jf.setTitle("bug6427244"); + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + jf.setSize(TP_SIZE, TP_SIZE); + jf.setVisible(true); + } + Container c = jf.getContentPane(); + c.removeAll(); + c.add(tp); + c.invalidate(); + c.validate(); + dim = c.getSize(); + } + }); + Util.blockTillDisplayed(tp); + ROBOT.waitForIdle(); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + public void testCaretPosition() { + Point p = tp.getLocationOnScreen(); + // the right-top corner position + p.x += (dim.width - 5); + p.y += 5; + ROBOT.mouseMove(p.x, p.y); + ROBOT.clickMouse(); + ROBOT.hitKey(KeyEvent.VK_HOME); + ROBOT.waitForIdle(); + // this will fail if caret moves out of the 1st line. + assertEquals(0, getCaretOrdinate()); + } + + int getCaretOrdinate() { + final int[] y = new int[1]; + try { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + Shape s; + try { + s = tp.getUI().getRootView(tp).modelToView( + tp.getCaretPosition(), tp.getBounds(), + Position.Bias.Forward); + } catch (Exception e) { + throw new RuntimeException(e); + } + y[0] = s.getBounds().y; + } + }); + } catch (Exception e) { + throw new RuntimeException(e); + } + return y[0]; + } + + JFrame jf; + JTextPane tp; + Dimension dim; +} From 49b420e58ae5ab896aadc8db2a71c50c13b97582 Mon Sep 17 00:00:00 2001 From: Dmitry Markov Date: Thu, 1 Sep 2016 22:17:48 +0300 Subject: [PATCH 058/110] 8050478: [macosx] Cursor not updating correctly after closing a modal dialog Reviewed-by: serb, alexsch --- .../sun/lwawt/macosx/CPlatformWindow.java | 8 ++ .../native/libawt_lwawt/awt/AWTWindow.m | 27 +++- .../ModalDialogEnterExitEventsTest.java | 129 ++++++++++++++++++ 3 files changed, 162 insertions(+), 2 deletions(-) create mode 100644 jdk/test/java/awt/Mouse/EnterExitEvents/ModalDialogEnterExitEventsTest.java diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java index 2842e02fd1e..cbbf3b193e9 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java @@ -63,6 +63,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo private static native void nativeSetNSWindowRepresentedFilename(long nsWindowPtr, String representedFilename); private static native void nativeSetEnabled(long nsWindowPtr, boolean isEnabled); private static native void nativeSynthesizeMouseEnteredExitedEvents(); + private static native void nativeSynthesizeMouseEnteredExitedEvents(long nsWindowPtr, int eventType); private static native void nativeDispose(long nsWindowPtr); private static native void nativeEnterFullScreenMode(long nsWindowPtr); private static native void nativeExitFullScreenMode(long nsWindowPtr); @@ -825,6 +826,13 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo return; } + if (blocked) { + // We are going to show a modal window. Previously displayed window will be + // blocked/disabled. So we have to send mouse exited event to it now, since + // all mouse events are discarded for blocked/disabled windows. + nativeSynthesizeMouseEnteredExitedEvents(getNSWindowPtr(), CocoaConstants.NSMouseExited); + } + nativeSetEnabled(getNSWindowPtr(), !blocked); checkBlockingAndOrder(); } diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m index 682769ac2d2..211be30d895 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m @@ -1333,9 +1333,9 @@ JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetTopmostPlatformWindowUnde /* * Class: sun_lwawt_macosx_CPlatformWindow * Method: nativeSynthesizeMouseEnteredExitedEvents - * Signature: (J)V + * Signature: ()V */ -JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSynthesizeMouseEnteredExitedEvents +JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSynthesizeMouseEnteredExitedEvents__ (JNIEnv *env, jclass clazz) { JNF_COCOA_ENTER(env); @@ -1347,6 +1347,29 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSynthesizeMou JNF_COCOA_EXIT(env); } +/* + * Class: sun_lwawt_macosx_CPlatformWindow + * Method: nativeSynthesizeMouseEnteredExitedEvents + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSynthesizeMouseEnteredExitedEvents__JI +(JNIEnv *env, jclass clazz, jlong windowPtr, jint eventType) +{ +JNF_COCOA_ENTER(env); + + if (eventType == NSMouseEntered || eventType == NSMouseExited) { + NSWindow *nsWindow = OBJC(windowPtr); + + [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ + [AWTWindow synthesizeMouseEnteredExitedEvents:nsWindow withType:eventType]; + }]; + } else { + [JNFException raise:env as:kIllegalArgumentException reason:"unknown event type"]; + } + +JNF_COCOA_EXIT(env); +} + /* * Class: sun_lwawt_macosx_CPlatformWindow * Method: _toggleFullScreenMode diff --git a/jdk/test/java/awt/Mouse/EnterExitEvents/ModalDialogEnterExitEventsTest.java b/jdk/test/java/awt/Mouse/EnterExitEvents/ModalDialogEnterExitEventsTest.java new file mode 100644 index 00000000000..147818d6db5 --- /dev/null +++ b/jdk/test/java/awt/Mouse/EnterExitEvents/ModalDialogEnterExitEventsTest.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key headful + * @bug 8050478 + * @summary Cursor not updating correctly after closing a modal dialog. + * The root cause of the issue was the lack of a mouse exit event + * during displaying of a modal dialog. + * @author Dmitry Markov + * @library ../../regtesthelpers + * @build Util + * @run main ModalDialogEnterExitEventsTest + */ + +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Robot; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.concurrent.atomic.AtomicInteger; + +import test.java.awt.regtesthelpers.Util; + +public class ModalDialogEnterExitEventsTest { + private static volatile AtomicInteger mouseEnterCount = new AtomicInteger(); + private static volatile AtomicInteger mouseExitCount = new AtomicInteger(); + + private static JFrame frame; + private static JButton openButton; + private static JButton closeButton; + + public static void main(String[] args) { + Robot robot = Util.createRobot(); + + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + createAndShowGUI(); + } + }); + Util.waitForIdle(robot); + + Util.clickOnComp(frame, robot, 500); + Util.waitForIdle(robot); + + mouseEnterCount.set(0); + mouseExitCount.set(0); + + Util.clickOnComp(openButton, robot, 500); + Util.waitForIdle(robot); + if (mouseExitCount.get() != 1) { + throw new RuntimeException("Test FAILED. Wrong number of MouseExited events = " + mouseExitCount.get()); + } + + Util.clickOnComp(closeButton, robot, 500); + Util.waitForIdle(robot); + if (mouseEnterCount.get() != 1) { + throw new RuntimeException("Test FAILED. Wrong number of MouseEntered events = "+ mouseEnterCount.get()); + } + } + + private static void createAndShowGUI() { + frame = new JFrame("ModalDialogEnterExitEventsTest"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setLayout(new FlowLayout()); + frame.addMouseListener(new MouseAdapter() { + @Override + public void mouseExited(MouseEvent e) { + mouseExitCount.getAndIncrement(); + } + + @Override + public void mouseEntered(MouseEvent e) { + mouseEnterCount.getAndIncrement(); + } + }); + openButton = new JButton("Open Dialog"); + openButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + JDialog dialog = new JDialog(frame, "Modal Dialog", true); + dialog.setLayout(new FlowLayout()); + closeButton = new JButton("Close"); + closeButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + dialog.dispose(); + } + }); + dialog.add(closeButton); + dialog.setSize(200, 200); + dialog.setLocationRelativeTo(null); + dialog.setVisible(true); + } + }); + frame.add(openButton); + frame.setExtendedState(Frame.MAXIMIZED_BOTH); + frame.setVisible(true); + } +} + From 84ec8b74f97ad4124334adc7253ce57baa3854e3 Mon Sep 17 00:00:00 2001 From: Semyon Sadetsky Date: Fri, 2 Sep 2016 10:31:49 +0300 Subject: [PATCH 059/110] 8164937: Remove code from SortingFocusTraversalPolicy that hacks into non-public Arrays.legacyMergeSort Reviewed-by: alexsch, serb --- .../swing/SortingFocusTraversalPolicy.java | 98 +++++++++++-------- .../java/awt/Focus/SortingFPT/JDK8048887.java | 4 +- 2 files changed, 59 insertions(+), 43 deletions(-) diff --git a/jdk/src/java.desktop/share/classes/javax/swing/SortingFocusTraversalPolicy.java b/jdk/src/java.desktop/share/classes/javax/swing/SortingFocusTraversalPolicy.java index 9057e80faad..d7f1ebcf034 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/SortingFocusTraversalPolicy.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/SortingFocusTraversalPolicy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, 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 @@ -26,15 +26,11 @@ package javax.swing; import java.awt.Component; import java.awt.Container; -import java.awt.Window; import java.util.*; import java.awt.FocusTraversalPolicy; import sun.util.logging.PlatformLogger; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import sun.security.action.GetPropertyAction; import java.security.AccessController; -import java.security.PrivilegedAction; /** * A FocusTraversalPolicy that determines traversal order by sorting the @@ -100,27 +96,10 @@ public class SortingFocusTraversalPolicy * See: JDK-8048887 */ private static final boolean legacySortingFTPEnabled; - private static final Method legacyMergeSortMethod; static { legacySortingFTPEnabled = "true".equals(AccessController.doPrivileged( new GetPropertyAction("swing.legacySortingFTPEnabled", "true"))); - legacyMergeSortMethod = legacySortingFTPEnabled ? - AccessController.doPrivileged(new PrivilegedAction() { - public Method run() { - try { - Method m = java.util.Arrays.class.getDeclaredMethod("legacyMergeSort", - new Class[]{Object[].class, - Comparator.class}); - m.setAccessible(true); - return m; - } catch (NoSuchMethodException e) { - // using default sorting algo - return null; - } - } - }) : - null; } /** @@ -169,30 +148,25 @@ public class SortingFocusTraversalPolicy private void enumerateAndSortCycle(Container focusCycleRoot, List cycle) { if (focusCycleRoot.isShowing()) { enumerateCycle(focusCycleRoot, cycle); - if (!legacySortingFTPEnabled || - !legacySort(cycle, comparator)) - { - Collections.sort(cycle, comparator); + if (legacySortingFTPEnabled) { + legacySort(cycle, comparator); + } else { + cycle.sort(comparator); } } } - private boolean legacySort(List l, Comparator c) { - if (legacyMergeSortMethod == null) - return false; - - Object[] a = l.toArray(); - try { - legacyMergeSortMethod.invoke(null, a, c); - } catch (IllegalAccessException | InvocationTargetException e) { - return false; + private void legacySort(List l, + Comparator c) { + if (c != null && l.size() > 1) { + Component[] a = l.toArray(new Component[l.size()]); + mergeSort(a.clone(), a, 0, a.length, 0, c); + ListIterator i = l.listIterator(); + for (Component e : a) { + i.next(); + i.set(e); + } } - ListIterator i = l.listIterator(); - for (Object e : a) { - i.next(); - i.set((Component)e); - } - return true; } @SuppressWarnings("deprecation") @@ -665,6 +639,48 @@ public class SortingFocusTraversalPolicy protected boolean accept(Component aComponent) { return fitnessTestPolicy.accept(aComponent); } + + // merge sort implementation copied from java.utils.Arrays + private void mergeSort(T[] src, T[] dest, + int low, int high, int off, + Comparator c) { + int length = high - low; + + // Insertion sort on smallest arrays + if (length < 7) { + for (int i=low; ilow && c.compare(dest[j-1], dest[j])>0; j--) { + T t = dest[j]; + dest[j] = dest[j-1]; + dest[j-1] = t; + } + return; + } + + // Recursively sort halves of dest into src + int destLow = low; + int destHigh = high; + low += off; + high += off; + int mid = (low + high) >>> 1; + mergeSort(dest, src, low, mid, -off, c); + mergeSort(dest, src, mid, high, -off, c); + + // If list is already sorted, just copy from src to dest. This is an + // optimization that results in faster sorts for nearly ordered lists. + if (c.compare(src[mid-1], src[mid]) <= 0) { + System.arraycopy(src, low, dest, destLow, length); + return; + } + + // Merge sorted halves (now in src) into dest + for(int i = destLow, p = low, q = mid; i < destHigh; i++) { + if (q >= high || p < mid && c.compare(src[p], src[q]) <= 0) + dest[i] = src[p++]; + else + dest[i] = src[q++]; + } + } } // Create our own subclass and change accept to public so that we can call diff --git a/jdk/test/java/awt/Focus/SortingFPT/JDK8048887.java b/jdk/test/java/awt/Focus/SortingFPT/JDK8048887.java index 01287068e8c..2cd3bdcd2ea 100644 --- a/jdk/test/java/awt/Focus/SortingFPT/JDK8048887.java +++ b/jdk/test/java/awt/Focus/SortingFPT/JDK8048887.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -23,7 +23,7 @@ /* @test - @bug 8048887 + @bug 8048887 8164937 @summary Tests SortingFTP for an exception caused by the tim-sort algo. @author anton.tarasov: area=awt.focus @run main JDK8048887 From c8c8826688901830952e05f388b01897dd0f19c5 Mon Sep 17 00:00:00 2001 From: Semyon Sadetsky Date: Fri, 2 Sep 2016 10:36:55 +0300 Subject: [PATCH 060/110] 8163100: [hidpi] Linux: display-wise scaling factor issues Reviewed-by: alexsch, serb --- jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java | 4 ++++ .../java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java | 3 ++- .../unix/native/common/awt/systemscale/systemScale.c | 2 +- .../unix/native/libawt_xawt/awt/awt_GraphicsEnv.c | 3 ++- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java index be362ae0781..77514760937 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java @@ -1570,6 +1570,10 @@ public final class XToolkit extends UNIXToolkit implements Runnable { Integer.valueOf(getMultiClickTime())); desktopProperties.put("awt.mouse.numButtons", Integer.valueOf(getNumberOfButtons())); + if(SunGraphicsEnvironment.isUIScaleEnabled()) { + addPropertyChangeListener("gnome.Xft/DPI", evt -> + localEnv.displayChanged()); + } } } diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java index 0f81f4e911f..346622e9e09 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java @@ -63,7 +63,7 @@ public final class X11GraphicsDevice extends GraphicsDevice private SunDisplayChanger topLevels = new SunDisplayChanger(); private DisplayMode origDisplayMode; private boolean shutdownHookRegistered; - private final int scale; + private int scale; public X11GraphicsDevice(int screennum) { this.screen = screennum; @@ -488,6 +488,7 @@ public final class X11GraphicsDevice extends GraphicsDevice * X11GraphicsEnvironment when the display mode has been changed. */ public synchronized void displayChanged() { + scale = initScaleFactor(); // On X11 the visuals do not change, and therefore we don't need // to reset the defaultConfig, config, doubleBufferVisuals, // neither do we need to reset the native data. diff --git a/jdk/src/java.desktop/unix/native/common/awt/systemscale/systemScale.c b/jdk/src/java.desktop/unix/native/common/awt/systemscale/systemScale.c index c8a5810370f..f7bea414e63 100644 --- a/jdk/src/java.desktop/unix/native/common/awt/systemscale/systemScale.c +++ b/jdk/src/java.desktop/unix/native/common/awt/systemscale/systemScale.c @@ -148,7 +148,7 @@ static double getDesktopScale(char *output_name) { void *scale = fp_g_variant_get_child_value(entry, 1); if (screen && scale) { char *name = fp_g_variant_get_string(screen, NULL); - if (name && strcmp(name, output_name)) { + if (name && !strcmp(name, output_name)) { result = fp_g_variant_get_int32(scale) / 8.; } fp_g_variant_unref(screen); diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c index 8339a195828..c1895cd29d7 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c @@ -2181,7 +2181,8 @@ static char *get_output_screen_name(JNIEnv *env, int screen) { JNIEXPORT jdouble JNICALL Java_sun_awt_X11GraphicsDevice_getNativeScaleFactor (JNIEnv *env, jobject this, jint screen) { - char *name = get_output_screen_name(env, screen); + // in case of Xinerama individual screen scales are not supported + char *name = get_output_screen_name(env, usingXinerama ? 0 : screen); double scale = getNativeScaleFactor(name); if (name) { free(name); From 02654e7d3dafbe748aed20808502d9b72adeebcc Mon Sep 17 00:00:00 2001 From: Martin Doerr Date: Mon, 5 Sep 2016 20:40:08 -0400 Subject: [PATCH 061/110] 8165018: Missing memory barrier for PPC64 in Unsafe_GetObjectVolatile Reviewed-by: kbarrett, dholmes --- hotspot/src/share/vm/prims/unsafe.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hotspot/src/share/vm/prims/unsafe.cpp b/hotspot/src/share/vm/prims/unsafe.cpp index 55a968170a5..2d836ccc160 100644 --- a/hotspot/src/share/vm/prims/unsafe.cpp +++ b/hotspot/src/share/vm/prims/unsafe.cpp @@ -324,6 +324,10 @@ UNSAFE_ENTRY(jobject, Unsafe_GetObjectVolatile(JNIEnv *env, jobject unsafe, jobj volatile oop v; + if (support_IRIW_for_not_multiple_copy_atomic_cpu) { + OrderAccess::fence(); + } + if (UseCompressedOops) { volatile narrowOop n = *(volatile narrowOop*) addr; (void)const_cast(v = oopDesc::decode_heap_oop(n)); From 848db998d9633625374c4a420f8c269a03c57591 Mon Sep 17 00:00:00 2001 From: Sharath Ballal Date: Tue, 6 Sep 2016 09:54:45 +0300 Subject: [PATCH 062/110] 8165114: stale reference to hotspot test Test8028623.java Remove Test8028623.java from hotspot/test/TEST.groups Reviewed-by: sla, dholmes --- hotspot/test/TEST.groups | 1 - 1 file changed, 1 deletion(-) diff --git a/hotspot/test/TEST.groups b/hotspot/test/TEST.groups index 2fdda388eea..fc1eae68feb 100644 --- a/hotspot/test/TEST.groups +++ b/hotspot/test/TEST.groups @@ -168,7 +168,6 @@ needs_compact3 = \ runtime/InternalApi/ThreadCpuTimesDeadlock.java \ runtime/NMT/JcmdSummaryDiff.java \ runtime/RedefineTests/RedefineAnnotations.java \ - serviceability/sa/jmap-hashcode/Test8028623.java \ serviceability/threads/TestFalseDeadLock.java \ compiler/codecache/jmx \ compiler/jsr292/RedefineMethodUsedByMultipleMethodHandles.java \ From a8147854b704570e301c1993b7db775101c11383 Mon Sep 17 00:00:00 2001 From: Rachel Protacio Date: Tue, 6 Sep 2016 16:29:32 -0400 Subject: [PATCH 063/110] 8161224: CONSTANT_NameAndType_info permits references to illegal names and descriptors Enforces proper format checking for NameAndType string content, and that the checking occurs even when not referenced in classfile Reviewed-by: coleenp, hseigel, ddmitriev --- .../share/vm/classfile/classFileParser.cpp | 85 ++++++++++--------- 1 file changed, 45 insertions(+), 40 deletions(-) diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index 30262696a8c..f53b428c046 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -95,7 +95,6 @@ #define JAVA_6_VERSION 50 // Used for backward compatibility reasons: -// - to check NameAndType_info signatures more aggressively // - to disallow argument and require ACC_STATIC for methods #define JAVA_7_VERSION 51 @@ -564,7 +563,7 @@ void ClassFileParser::parse_constant_pool(const ClassFileStream* const stream, break; } case JVM_CONSTANT_NameAndType: { - if (_need_verify && _major_version >= JAVA_7_VERSION) { + if (_need_verify) { const int sig_index = cp->signature_ref_index_at(index); const int name_index = cp->name_ref_index_at(index); const Symbol* const name = cp->symbol_at(name_index); @@ -572,9 +571,17 @@ void ClassFileParser::parse_constant_pool(const ClassFileStream* const stream, guarantee_property(sig->utf8_length() != 0, "Illegal zero length constant pool entry at %d in class %s", sig_index, CHECK); + guarantee_property(name->utf8_length() != 0, + "Illegal zero length constant pool entry at %d in class %s", + name_index, CHECK); + if (sig->byte_at(0) == JVM_SIGNATURE_FUNC) { + // Format check method name and signature + verify_legal_method_name(name, CHECK); verify_legal_method_signature(name, sig, CHECK); } else { + // Format check field name and signature + verify_legal_field_name(name, CHECK); verify_legal_field_signature(name, sig, CHECK); } } @@ -595,42 +602,32 @@ void ClassFileParser::parse_constant_pool(const ClassFileStream* const stream, const Symbol* const name = cp->symbol_at(name_ref_index); const Symbol* const signature = cp->symbol_at(signature_ref_index); if (tag == JVM_CONSTANT_Fieldref) { - verify_legal_field_name(name, CHECK); - if (_need_verify && _major_version >= JAVA_7_VERSION) { - // Signature is verified above, when iterating NameAndType_info. - // Need only to be sure it's non-zero length and the right type. + if (_need_verify) { + // Field name and signature are verified above, when iterating NameAndType_info. + // Need only to be sure signature is non-zero length and the right type. if (signature->utf8_length() == 0 || signature->byte_at(0) == JVM_SIGNATURE_FUNC) { - throwIllegalSignature( - "Field", name, signature, CHECK); + throwIllegalSignature("Field", name, signature, CHECK); } - } else { - verify_legal_field_signature(name, signature, CHECK); } } else { - verify_legal_method_name(name, CHECK); - if (_need_verify && _major_version >= JAVA_7_VERSION) { - // Signature is verified above, when iterating NameAndType_info. - // Need only to be sure it's non-zero length and the right type. + if (_need_verify) { + // Method name and signature are verified above, when iterating NameAndType_info. + // Need only to be sure signature is non-zero length and the right type. if (signature->utf8_length() == 0 || signature->byte_at(0) != JVM_SIGNATURE_FUNC) { - throwIllegalSignature( - "Method", name, signature, CHECK); + throwIllegalSignature("Method", name, signature, CHECK); } - } else { - verify_legal_method_signature(name, signature, CHECK); } - if (tag == JVM_CONSTANT_Methodref) { - // 4509014: If a class method name begins with '<', it must be "". - assert(name != NULL, "method name in constant pool is null"); - const unsigned int name_len = name->utf8_length(); - if (name_len != 0 && name->byte_at(0) == '<') { - if (name != vmSymbols::object_initializer_name()) { - classfile_parse_error( - "Bad method name at constant pool index %u in class file %s", - name_ref_index, CHECK); - } - } + // 4509014: If a class method name begins with '<', it must be "" + const unsigned int name_len = name->utf8_length(); + if (tag == JVM_CONSTANT_Methodref && + name_len != 0 && + name->byte_at(0) == '<' && + name != vmSymbols::object_initializer_name()) { + classfile_parse_error( + "Bad method name at constant pool index %u in class file %s", + name_ref_index, CHECK); } } break; @@ -4843,19 +4840,28 @@ const char* ClassFileParser::skip_over_field_signature(const char* signature, } } else { - // 4900761: For class version > 48, any unicode is allowed in class name. + // Skip leading 'L' and ignore first appearance of ';' length--; signature++; - while (length > 0 && signature[0] != ';') { - if (signature[0] == '.') { - classfile_parse_error("Class name contains illegal character '.' in descriptor in class file %s", CHECK_0); - } - length--; - signature++; - } - if (signature[0] == ';') { return signature + 1; } - } + char* c = strchr((char*) signature, ';'); + // Format check signature + if (c != NULL) { + ResourceMark rm(THREAD); + int newlen = c - (char*) signature; + char* sig = NEW_RESOURCE_ARRAY(char, newlen + 1); + strncpy(sig, signature, newlen); + sig[newlen] = '\0'; + bool legal = verify_unqualified_name(sig, newlen, LegalClass); + if (!legal) { + classfile_parse_error("Class name contains illegal character " + "in descriptor in class file %s", + CHECK_0); + return NULL; + } + return signature + newlen + 1; + } + } return NULL; } case JVM_SIGNATURE_ARRAY: @@ -4869,7 +4875,6 @@ const char* ClassFileParser::skip_over_field_signature(const char* signature, length--; void_ok = false; break; - default: return NULL; } From c271d835997242aede1f5a023034a0b7fe69ca37 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Wed, 7 Sep 2016 09:20:10 +0200 Subject: [PATCH 064/110] 8165292: The gc+task logging is repeated a lot, decreasing the usefulness of -Xlog:gc*=info Separate number of workers used debugging information from adaptive worker sizing log messages. Reviewed-by: ehelin, sjohanss, jmasa --- .../gc/cms/concurrentMarkSweepGeneration.cpp | 1 + .../src/share/vm/gc/cms/parNewGeneration.cpp | 2 + .../src/share/vm/gc/g1/g1CollectedHeap.cpp | 2 + .../src/share/vm/gc/g1/g1ConcurrentMark.cpp | 2 + hotspot/src/share/vm/gc/shared/workgroup.hpp | 2 +- hotspot/test/gc/TestNumWorkerOutput.java | 103 ++++++++++++++++++ 6 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 hotspot/test/gc/TestNumWorkerOutput.java diff --git a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp index 6d78865ac43..2a1be1af777 100644 --- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp @@ -3511,6 +3511,7 @@ bool CMSCollector::do_marking_mt() { conc_workers()->active_workers(), Threads::number_of_non_daemon_threads()); num_workers = conc_workers()->update_active_workers(num_workers); + log_info(gc,task)("Using %u workers of %u for marking", num_workers, conc_workers()->total_workers()); CompactibleFreeListSpace* cms_space = _cmsGen->cmsSpace(); diff --git a/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp index e8f606eecc8..ddc80ce3a76 100644 --- a/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp +++ b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp @@ -899,6 +899,8 @@ void ParNewGeneration::collect(bool full, workers->active_workers(), Threads::number_of_non_daemon_threads()); active_workers = workers->update_active_workers(active_workers); + log_info(gc,task)("Using %u workers of %u for evacuation", active_workers, workers->total_workers()); + _old_gen = gch->old_gen(); // If the next generation is too full to accommodate worst-case promotion diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index 7b6974c4f58..4543ee3e021 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -1332,6 +1332,7 @@ bool G1CollectedHeap::do_full_collection(bool explicit_gc, workers()->active_workers(), Threads::number_of_non_daemon_threads()); workers()->update_active_workers(n_workers); + log_info(gc,task)("Using %u workers of %u to rebuild remembered set", n_workers, workers()->total_workers()); ParRebuildRSTask rebuild_rs_task(this); workers()->run_task(&rebuild_rs_task); @@ -3068,6 +3069,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { workers()->active_workers(), Threads::number_of_non_daemon_threads()); workers()->update_active_workers(active_workers); + log_info(gc,task)("Using %u workers of %u for evacuation", active_workers, workers()->total_workers()); TraceCollectorStats tcs(g1mm()->incremental_collection_counters()); TraceMemoryManagerStats tms(false /* fullGC */, gc_cause()); diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp index 27f4071b7bf..2f14e088f3f 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp @@ -1035,6 +1035,8 @@ void G1ConcurrentMark::mark_from_roots() { // worker threads may currently exist and more may not be // available. active_workers = _parallel_workers->update_active_workers(active_workers); + log_info(gc, task)("Using %u workers of %u for marking", active_workers, _parallel_workers->total_workers()); + // Parallel task terminator is set in "set_concurrency_and_phase()" set_concurrency_and_phase(active_workers, true /* concurrent */); diff --git a/hotspot/src/share/vm/gc/shared/workgroup.hpp b/hotspot/src/share/vm/gc/shared/workgroup.hpp index 00eb705f683..20491b66536 100644 --- a/hotspot/src/share/vm/gc/shared/workgroup.hpp +++ b/hotspot/src/share/vm/gc/shared/workgroup.hpp @@ -162,7 +162,7 @@ class AbstractWorkGang : public CHeapObj { _active_workers = MIN2(v, _total_workers); add_workers(false /* exit_on_failure */); assert(v != 0, "Trying to set active workers to 0"); - log_info(gc, task)("GC Workers: using %d out of %d", _active_workers, _total_workers); + log_trace(gc, task)("%s: using %d out of %d workers", name(), _active_workers, _total_workers); return _active_workers; } diff --git a/hotspot/test/gc/TestNumWorkerOutput.java b/hotspot/test/gc/TestNumWorkerOutput.java new file mode 100644 index 00000000000..0f69bd7fd81 --- /dev/null +++ b/hotspot/test/gc/TestNumWorkerOutput.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test TestNumWorkerOutput + * @bug 8165292 + * @summary Check that when PrintGCDetails is enabled, gc,task output is printed only once per collection. + * @key gc + * @requires vm.gc=="null" + * @modules java.base/jdk.internal.misc + * @library /test/lib + * @build sun.hotspot.WhiteBox + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -XX:+UseConcMarkSweepGC TestNumWorkerOutput UseConcMarkSweepGC + * @run main/othervm -XX:+UseG1GC TestNumWorkerOutput UseG1GC + */ + +import sun.hotspot.WhiteBox; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import jdk.test.lib.Platform; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +import static jdk.test.lib.Asserts.*; + +public class TestNumWorkerOutput { + + public static void checkPatternOnce(String pattern, String what) throws Exception { + Pattern r = Pattern.compile(pattern); + Matcher m = r.matcher(what); + + if (!m.find()) { + throw new RuntimeException("Could not find pattern " + pattern + " in output"); + } + if (m.find()) { + throw new RuntimeException("Could find pattern " + pattern + " in output more than once"); + } + } + + public static void runTest(String gcArg) throws Exception { + final String[] arguments = { + "-Xbootclasspath/a:.", + "-XX:+UnlockExperimentalVMOptions", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "-XX:+" + gcArg, + "-Xmx10M", + "-XX:+PrintGCDetails", + GCTest.class.getName() + }; + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(arguments); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + output.shouldHaveExitValue(0); + + System.out.println(output.getStdout()); + + String stdout = output.getStdout(); + + checkPatternOnce(".*[info.*].*[gc,task.*].*GC\\(0\\) .*Using \\d+ workers of \\d+ for evacuation.*", stdout); + } + + public static void main(String[] args) throws Exception { + runTest(args[0]); + } + + static class GCTest { + private static final WhiteBox WB = WhiteBox.getWhiteBox(); + + public static Object holder; + + public static void main(String [] args) { + holder = new byte[100]; + WB.youngGC(); + System.out.println(holder); + } + } +} + From e8e6415b7a526f6b3fd53e3b94a29b5169d6a2bf Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Wed, 7 Sep 2016 07:19:48 -0400 Subject: [PATCH 065/110] 8058575: IllegalAccessError trying to access package-private class from VM anonymous class Put anonymous classes in unnamed package into host class's package. Throw exception if host class's package differs from anonymous class. Reviewed-by: coleenp, acorn --- .../share/vm/classfile/classFileParser.cpp | 62 +++++++- .../share/vm/classfile/classFileParser.hpp | 9 +- .../src/share/vm/classfile/klassFactory.cpp | 2 +- .../src/share/vm/classfile/klassFactory.hpp | 2 +- .../share/vm/classfile/systemDictionary.cpp | 2 +- .../share/vm/classfile/systemDictionary.hpp | 2 +- hotspot/src/share/vm/classfile/verifier.cpp | 2 +- hotspot/src/share/vm/oops/instanceKlass.hpp | 14 +- hotspot/src/share/vm/prims/unsafe.cpp | 13 +- hotspot/src/share/vm/runtime/reflection.cpp | 10 +- .../jsr292/CallSiteDepContextTest.java | 14 +- .../runtime/defineAnonClass/DefineAnon.java | 134 ++++++++++++++++++ .../runtime/defineAnonClass/NestedUnsafe.java | 91 ++++++++++++ .../defineAnonClass/NestedUnsafe2.java | 90 ++++++++++++ 14 files changed, 416 insertions(+), 31 deletions(-) create mode 100644 hotspot/test/runtime/defineAnonClass/DefineAnon.java create mode 100644 hotspot/test/runtime/defineAnonClass/NestedUnsafe.java create mode 100644 hotspot/test/runtime/defineAnonClass/NestedUnsafe2.java diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index a08af5587bc..5f0b1ca442a 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -5407,6 +5407,59 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, bool changed_by_loa debug_only(ik->verify();) } +// For an anonymous class that is in the unnamed package, move it to its host class's +// package by prepending its host class's package name to its class name and setting +// its _class_name field. +void ClassFileParser::prepend_host_package_name(const InstanceKlass* host_klass, TRAPS) { + ResourceMark rm(THREAD); + assert(strrchr(_class_name->as_C_string(), '/') == NULL, + "Anonymous class should not be in a package"); + const char* host_pkg_name = + ClassLoader::package_from_name(host_klass->name()->as_C_string(), NULL); + + if (host_pkg_name != NULL) { + size_t host_pkg_len = strlen(host_pkg_name); + int class_name_len = _class_name->utf8_length(); + char* new_anon_name = + NEW_RESOURCE_ARRAY(char, host_pkg_len + 1 + class_name_len); + // Copy host package name and trailing /. + strncpy(new_anon_name, host_pkg_name, host_pkg_len); + new_anon_name[host_pkg_len] = '/'; + // Append anonymous class name. The anonymous class name can contain odd + // characters. So, do a strncpy instead of using sprintf("%s..."). + strncpy(new_anon_name + host_pkg_len + 1, (char *)_class_name->base(), class_name_len); + + // Create a symbol and update the anonymous class name. + _class_name = SymbolTable::new_symbol(new_anon_name, + (int)host_pkg_len + 1 + class_name_len, + CHECK); + } +} + +// If the host class and the anonymous class are in the same package then do +// nothing. If the anonymous class is in the unnamed package then move it to its +// host's package. If the classes are in different packages then throw an IAE +// exception. +void ClassFileParser::fix_anonymous_class_name(TRAPS) { + assert(_host_klass != NULL, "Expected an anonymous class"); + + const jbyte* anon_last_slash = UTF8::strrchr(_class_name->base(), + _class_name->utf8_length(), '/'); + if (anon_last_slash == NULL) { // Unnamed package + prepend_host_package_name(_host_klass, CHECK); + } else { + if (!InstanceKlass::is_same_class_package(_host_klass->class_loader(), + _host_klass->name(), + _host_klass->class_loader(), + _class_name)) { + ResourceMark rm(THREAD); + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), + err_msg("Host class %s and anonymous class %s are in different packages", + _host_klass->name()->as_C_string(), _class_name->as_C_string())); + } + } +} + static bool relax_format_check_for(ClassLoaderData* loader_data) { bool trusted = (loader_data->is_the_null_class_loader_data() || SystemDictionary::is_platform_class_loader(loader_data->class_loader())); @@ -5422,7 +5475,7 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream, Symbol* name, ClassLoaderData* loader_data, Handle protection_domain, - const Klass* host_klass, + const InstanceKlass* host_klass, GrowableArray* cp_patches, Publicity pub_level, TRAPS) : @@ -5697,6 +5750,13 @@ void ClassFileParser::parse_stream(const ClassFileStream* const stream, return; } + // if this is an anonymous class fix up its name if it's in the unnamed + // package. Otherwise, throw IAE if it is in a different package than + // its host class. + if (_host_klass != NULL) { + fix_anonymous_class_name(CHECK); + } + // Verification prevents us from creating names with dots in them, this // asserts that that's the case. assert(is_internal_format(_class_name), "external class name format used internally"); diff --git a/hotspot/src/share/vm/classfile/classFileParser.hpp b/hotspot/src/share/vm/classfile/classFileParser.hpp index 4b6287588c3..8cc820a450a 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.hpp +++ b/hotspot/src/share/vm/classfile/classFileParser.hpp @@ -79,7 +79,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { const Symbol* _requested_name; Symbol* _class_name; mutable ClassLoaderData* _loader_data; - const Klass* _host_klass; + const InstanceKlass* _host_klass; GrowableArray* _cp_patches; // overrides for CP entries // Metadata created before the instance klass is created. Must be deallocated @@ -155,6 +155,9 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { ConstantPool* cp, TRAPS); + void prepend_host_package_name(const InstanceKlass* host_klass, TRAPS); + void fix_anonymous_class_name(TRAPS); + void fill_instance_klass(InstanceKlass* ik, bool cf_changed_in_CFLH, TRAPS); void set_klass(InstanceKlass* instance); @@ -474,7 +477,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { Symbol* name, ClassLoaderData* loader_data, Handle protection_domain, - const Klass* host_klass, + const InstanceKlass* host_klass, GrowableArray* cp_patches, Publicity pub_level, TRAPS); @@ -500,7 +503,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { bool is_anonymous() const { return _host_klass != NULL; } bool is_interface() const { return _access_flags.is_interface(); } - const Klass* host_klass() const { return _host_klass; } + const InstanceKlass* host_klass() const { return _host_klass; } const GrowableArray* cp_patches() const { return _cp_patches; } ClassLoaderData* loader_data() const { return _loader_data; } const Symbol* class_name() const { return _class_name; } diff --git a/hotspot/src/share/vm/classfile/klassFactory.cpp b/hotspot/src/share/vm/classfile/klassFactory.cpp index 4d08ea3329c..dc5f3963d1a 100644 --- a/hotspot/src/share/vm/classfile/klassFactory.cpp +++ b/hotspot/src/share/vm/classfile/klassFactory.cpp @@ -94,7 +94,7 @@ instanceKlassHandle KlassFactory::create_from_stream(ClassFileStream* stream, Symbol* name, ClassLoaderData* loader_data, Handle protection_domain, - const Klass* host_klass, + const InstanceKlass* host_klass, GrowableArray* cp_patches, TRAPS) { diff --git a/hotspot/src/share/vm/classfile/klassFactory.hpp b/hotspot/src/share/vm/classfile/klassFactory.hpp index 6783f2753a3..72dcc0dd6e4 100644 --- a/hotspot/src/share/vm/classfile/klassFactory.hpp +++ b/hotspot/src/share/vm/classfile/klassFactory.hpp @@ -72,7 +72,7 @@ class KlassFactory : AllStatic { Symbol* name, ClassLoaderData* loader_data, Handle protection_domain, - const Klass* host_klass, + const InstanceKlass* host_klass, GrowableArray* cp_patches, TRAPS); }; diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp index 70f9e6a169f..f3b667eaf43 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp @@ -1027,7 +1027,7 @@ Klass* SystemDictionary::parse_stream(Symbol* class_name, Handle class_loader, Handle protection_domain, ClassFileStream* st, - const Klass* host_klass, + const InstanceKlass* host_klass, GrowableArray* cp_patches, TRAPS) { diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp index 6dd7d20e456..bf10995a578 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp @@ -299,7 +299,7 @@ public: Handle class_loader, Handle protection_domain, ClassFileStream* st, - const Klass* host_klass, + const InstanceKlass* host_klass, GrowableArray* cp_patches, TRAPS); diff --git a/hotspot/src/share/vm/classfile/verifier.cpp b/hotspot/src/share/vm/classfile/verifier.cpp index 440257b9e79..ba58b175305 100644 --- a/hotspot/src/share/vm/classfile/verifier.cpp +++ b/hotspot/src/share/vm/classfile/verifier.cpp @@ -2786,7 +2786,7 @@ void ClassVerifier::verify_invoke_instructions( // direct interface relative to the host class have_imr_indirect = (have_imr_indirect && !is_same_or_direct_interface( - InstanceKlass::cast(current_class()->host_klass()), + current_class()->host_klass(), host_klass_type, ref_class_type)); } if (!subtype) { diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index da36a1422b4..e4eb9b3e4fe 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -619,8 +619,8 @@ class InstanceKlass: public Klass { objArrayOop signers() const; // host class - Klass* host_klass() const { - Klass** hk = (Klass**)adr_host_klass(); + InstanceKlass* host_klass() const { + InstanceKlass** hk = adr_host_klass(); if (hk == NULL) { return NULL; } else { @@ -628,9 +628,9 @@ class InstanceKlass: public Klass { return *hk; } } - void set_host_klass(const Klass* host) { + void set_host_klass(const InstanceKlass* host) { assert(is_anonymous(), "not anonymous"); - const Klass** addr = (const Klass**)adr_host_klass(); + const InstanceKlass** addr = (const InstanceKlass **)adr_host_klass(); assert(addr != NULL, "no reversed space"); if (addr != NULL) { *addr = host; @@ -1057,13 +1057,13 @@ public: } }; - Klass** adr_host_klass() const { + InstanceKlass** adr_host_klass() const { if (is_anonymous()) { - Klass** adr_impl = adr_implementor(); + InstanceKlass** adr_impl = (InstanceKlass **)adr_implementor(); if (adr_impl != NULL) { return adr_impl + 1; } else { - return end_of_nonstatic_oop_maps(); + return (InstanceKlass **)end_of_nonstatic_oop_maps(); } } else { return NULL; diff --git a/hotspot/src/share/vm/prims/unsafe.cpp b/hotspot/src/share/vm/prims/unsafe.cpp index 2d836ccc160..cdcdc7d80ee 100644 --- a/hotspot/src/share/vm/prims/unsafe.cpp +++ b/hotspot/src/share/vm/prims/unsafe.cpp @@ -783,6 +783,7 @@ UNSAFE_ENTRY(jclass, Unsafe_DefineClass0(JNIEnv *env, jobject unsafe, jstring na // define a class but do not make it known to the class loader or system dictionary // - host_class: supplies context for linkage, access control, protection domain, and class loader +// if host_class is itself anonymous then it is replaced with its host class. // - data: bytes of a class file, a raw memory address (length gives the number of bytes) // - cp_patches: where non-null entries exist, they replace corresponding CP entries in data @@ -791,8 +792,12 @@ UNSAFE_ENTRY(jclass, Unsafe_DefineClass0(JNIEnv *env, jobject unsafe, jstring na // link to any member of U. Just after U is loaded, the only way to use it is reflectively, // through java.lang.Class methods like Class.newInstance. +// The package of an anonymous class must either match its host's class's package or be in the +// unnamed package. If it is in the unnamed package then it will be put in its host class's +// package. +// + // Access checks for linkage sites within U continue to follow the same rules as for named classes. -// The package of an anonymous class is given by the package qualifier on the name under which it was loaded. // An anonymous class also has special privileges to access any member of its host class. // This is the main reason why this loading operation is unsafe. The purpose of this is to // allow language implementations to simulate "open classes"; a host class in effect gets @@ -874,9 +879,11 @@ Unsafe_DefineAnonymousClass_impl(JNIEnv *env, // Primitive types have NULL Klass* fields in their java.lang.Class instances. if (host_klass == NULL) { - THROW_0(vmSymbols::java_lang_IllegalArgumentException()); + THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Host class is null"); } + assert(host_klass->is_instance_klass(), "Host class must be an instance class"); + const char* host_source = host_klass->external_name(); Handle host_loader(THREAD, host_klass->class_loader()); Handle host_domain(THREAD, host_klass->protection_domain()); @@ -907,7 +914,7 @@ Unsafe_DefineAnonymousClass_impl(JNIEnv *env, host_loader, host_domain, &st, - host_klass, + InstanceKlass::cast(host_klass), cp_patches, CHECK_NULL); if (anonk == NULL) { diff --git a/hotspot/src/share/vm/runtime/reflection.cpp b/hotspot/src/share/vm/runtime/reflection.cpp index ae574a4edbf..b2fc1018828 100644 --- a/hotspot/src/share/vm/runtime/reflection.cpp +++ b/hotspot/src/share/vm/runtime/reflection.cpp @@ -412,13 +412,13 @@ oop Reflection::array_component_type(oop mirror, TRAPS) { return result; } -static bool under_host_klass(const InstanceKlass* ik, const Klass* host_klass) { +static bool under_host_klass(const InstanceKlass* ik, const InstanceKlass* host_klass) { DEBUG_ONLY(int inf_loop_check = 1000 * 1000 * 1000); for (;;) { - const Klass* hc = (const Klass*)ik->host_klass(); + const InstanceKlass* hc = ik->host_klass(); if (hc == NULL) return false; if (hc == host_klass) return true; - ik = InstanceKlass::cast(hc); + ik = hc; // There's no way to make a host class loop short of patching memory. // Therefore there cannot be a loop here unless there's another bug. @@ -436,8 +436,8 @@ static bool can_relax_access_check_for(const Klass* accessor, // If either is on the other's host_klass chain, access is OK, // because one is inside the other. - if (under_host_klass(accessor_ik, accessee) || - under_host_klass(accessee_ik, accessor)) + if (under_host_klass(accessor_ik, accessee_ik) || + under_host_klass(accessee_ik, accessor_ik)) return true; if ((RelaxAccessControlCheck && diff --git a/hotspot/test/compiler/jsr292/CallSiteDepContextTest.java b/hotspot/test/compiler/jsr292/CallSiteDepContextTest.java index 80650b97136..cc672bc124d 100644 --- a/hotspot/test/compiler/jsr292/CallSiteDepContextTest.java +++ b/hotspot/test/compiler/jsr292/CallSiteDepContextTest.java @@ -62,7 +62,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.IRETURN; public class CallSiteDepContextTest { static final Unsafe UNSAFE = Unsafe.getUnsafe(); static final MethodHandles.Lookup LOOKUP = MethodHandleHelper.IMPL_LOOKUP; - static final String CLASS_NAME = "java/lang/invoke/Test"; + static final String CLASS_NAME = "compiler/jsr292/Test"; static final String METHOD_NAME = "m"; static final MethodType TYPE = MethodType.methodType(int.class); @@ -129,8 +129,8 @@ public class CallSiteDepContextTest { } public static void testSharedCallSite() throws Throwable { - Class cls1 = UNSAFE.defineAnonymousClass(Object.class, getClassFile("CS_1"), null); - Class cls2 = UNSAFE.defineAnonymousClass(Object.class, getClassFile("CS_2"), null); + Class cls1 = UNSAFE.defineAnonymousClass(CallSiteDepContextTest.class, getClassFile("CS_1"), null); + Class cls2 = UNSAFE.defineAnonymousClass(CallSiteDepContextTest.class, getClassFile("CS_2"), null); MethodHandle[] mhs = new MethodHandle[] { LOOKUP.findStatic(cls1, METHOD_NAME, TYPE), @@ -151,7 +151,7 @@ public class CallSiteDepContextTest { execute(1, mh); // mcs.context == cls1 - Class cls1 = UNSAFE.defineAnonymousClass(Object.class, getClassFile("NonBound_1"), null); + Class cls1 = UNSAFE.defineAnonymousClass(CallSiteDepContextTest.class, getClassFile("NonBound_1"), null); MethodHandle mh1 = LOOKUP.findStatic(cls1, METHOD_NAME, TYPE); execute(1, mh1); @@ -170,8 +170,8 @@ public class CallSiteDepContextTest { mcs = new MutableCallSite(LOOKUP.findStatic(T.class, "f1", TYPE)); Class[] cls = new Class[] { - UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_1" + id), null), - UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_2" + id), null), + UNSAFE.defineAnonymousClass(CallSiteDepContextTest.class, getClassFile("GC_1" + id), null), + UNSAFE.defineAnonymousClass(CallSiteDepContextTest.class, getClassFile("GC_2" + id), null), }; MethodHandle[] mhs = new MethodHandle[] { @@ -185,7 +185,7 @@ public class CallSiteDepContextTest { execute(1, mhs); ref = new PhantomReference<>(cls[0], rq); - cls[0] = UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_3" + id), null); + cls[0] = UNSAFE.defineAnonymousClass(CallSiteDepContextTest.class, getClassFile("GC_3" + id), null); mhs[0] = LOOKUP.findStatic(cls[0], METHOD_NAME, TYPE); do { diff --git a/hotspot/test/runtime/defineAnonClass/DefineAnon.java b/hotspot/test/runtime/defineAnonClass/DefineAnon.java new file mode 100644 index 00000000000..f73b20dfc5f --- /dev/null +++ b/hotspot/test/runtime/defineAnonClass/DefineAnon.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test DefineAnon + * @bug 8058575 + * @library /testlibrary + * @modules java.base/jdk.internal.org.objectweb.asm + * java.management + * @compile -XDignore.symbol.file=true DefineAnon.java + * @run main/othervm p1.DefineAnon + */ + +package p1; + +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import jdk.internal.org.objectweb.asm.Opcodes; +import sun.misc.Unsafe; + + +class T { + static protected void test0() { System.out.println("test0 (public)"); } + static protected void test1() { System.out.println("test1 (protected)"); } + static /*package-private*/ void test2() { System.out.println("test2 (package)"); } + static private void test3() { System.out.println("test3 (private)"); } +} + +public class DefineAnon { + + private static Unsafe getUnsafe() { + try { + java.lang.reflect.Field singleoneInstanceField = Unsafe.class.getDeclaredField("theUnsafe"); + singleoneInstanceField.setAccessible(true); + return (Unsafe) singleoneInstanceField.get(null); + } catch (Throwable ex) { + throw new RuntimeException("Was unable to get Unsafe instance."); + } + } + + static Unsafe UNSAFE = DefineAnon.getUnsafe(); + + static Class getAnonClass(Class hostClass, final String className) { + final String superName = "java/lang/Object"; + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES); + cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_SUPER, className, null, superName, null); + + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC, "test", "()V", null, null); + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "p1/T", "test0", "()V", false); + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "p1/T", "test1", "()V", false); + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "p1/T", "test2", "()V", false); + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "p1/T", "test3", "()V", false); + mv.visitInsn(Opcodes.RETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + + final byte[] classBytes = cw.toByteArray(); + Class invokerClass = UNSAFE.defineAnonymousClass(hostClass, classBytes, new Object[0]); + UNSAFE.ensureClassInitialized(invokerClass); + return invokerClass; + } + + public static void main(String[] args) throws Throwable { + Throwable fail = null; + + // Anonymous class has the privileges of its host class, so test[0123] should all work. + System.out.println("Injecting from the same package (p1):"); + Class p1cls = getAnonClass(T.class, "p1/AnonClass"); + try { + p1cls.getMethod("test").invoke(null); + } catch (Throwable ex) { + ex.printStackTrace(); + fail = ex; // throw this to make test fail, since subtest failed + } + + // Anonymous class has different package name from host class. Should throw + // IllegalArgumentException. + System.out.println("Injecting from the wrong package (p2):"); + try { + Class p2cls = getAnonClass(DefineAnon.class, "p2/AnonClass"); + p2cls.getMethod("test").invoke(null); + System.out.println("Failed, did not get expected IllegalArgumentException"); + } catch (java.lang.IllegalArgumentException e) { + if (e.getMessage().contains("Host class p1/DefineAnon and anonymous class p2/AnonClass")) { + System.out.println("Got expected IllegalArgumentException: " + e.getMessage()); + } else { + throw new RuntimeException("Unexpected message: " + e.getMessage()); + } + } catch (Throwable ex) { + ex.printStackTrace(); + fail = ex; // throw this to make test fail, since subtest failed + } + + // Inject a class in the unnamed package into p1.T. It should be able + // to access all methods in p1.T. + System.out.println("Injecting unnamed package into correct host class:"); + try { + Class p3cls = getAnonClass(T.class, "AnonClass"); + p3cls.getMethod("test").invoke(null); + } catch (Throwable ex) { + ex.printStackTrace(); + fail = ex; // throw this to make test fail, since subtest failed + } + + // Try using an array class as the host class. This should throw IllegalArgumentException. + try { + Class p3cls = getAnonClass(String[].class, "AnonClass"); + throw new RuntimeException("Expected IllegalArgumentException not thrown"); + } catch (IllegalArgumentException ex) { + } + + if (fail != null) throw fail; // make test fail, since subtest failed + } +} diff --git a/hotspot/test/runtime/defineAnonClass/NestedUnsafe.java b/hotspot/test/runtime/defineAnonClass/NestedUnsafe.java new file mode 100644 index 00000000000..c25f29a0965 --- /dev/null +++ b/hotspot/test/runtime/defineAnonClass/NestedUnsafe.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8058575 + * @summary Creates an anonymous class inside of an anonymous class. + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.compiler + * java.management + * @run main p.NestedUnsafe + */ + +package p; + +import java.security.ProtectionDomain; +import java.io.InputStream; +import java.lang.*; +import jdk.test.lib.*; +import jdk.internal.misc.Unsafe; +import jdk.test.lib.unsafe.UnsafeHelper; + + +// Test that an anonymous class in package 'p' cannot define its own anonymous class +// in another package. +public class NestedUnsafe { + // The String concatenation should create the nested anonymous class. + static byte klassbuf[] = InMemoryJavaCompiler.compile("q.TestClass", + "package q; " + + "public class TestClass { " + + " public static void concat(String one, String two) throws Throwable { " + + " System.out.println(one + two);" + + " } } "); + + public static void main(String args[]) throws Exception { + Unsafe unsafe = UnsafeHelper.getUnsafe(); + + // The anonymous class calls defineAnonymousClass creating a nested anonymous class. + byte klassbuf2[] = InMemoryJavaCompiler.compile("p.TestClass2", + "package p; " + + "import jdk.internal.misc.Unsafe; " + + "public class TestClass2 { " + + " public static void doit() throws Throwable { " + + " Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe(); " + + " Class klass2 = unsafe.defineAnonymousClass(TestClass2.class, p.NestedUnsafe.klassbuf, new Object[0]); " + + " unsafe.ensureClassInitialized(klass2); " + + " Class[] dArgs = new Class[2]; " + + " dArgs[0] = String.class; " + + " dArgs[1] = String.class; " + + " try { " + + " klass2.getMethod(\"concat\", dArgs).invoke(null, \"CC\", \"DD\"); " + + " } catch (Throwable ex) { " + + " throw new RuntimeException(\"Exception: \" + ex.toString()); " + + " } " + + "} } ", + "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED"); + + Class klass2 = unsafe.defineAnonymousClass(p.NestedUnsafe.class, klassbuf2, new Object[0]); + try { + klass2.getMethod("doit").invoke(null); + throw new RuntimeException("Expected exception not thrown"); + } catch (Throwable ex) { + Throwable iae = ex.getCause(); + if (!iae.toString().contains( + "IllegalArgumentException: Host class p/NestedUnsafe and anonymous class q/TestClass")) { + throw new RuntimeException("Exception: " + iae.toString()); + } + } + } +} diff --git a/hotspot/test/runtime/defineAnonClass/NestedUnsafe2.java b/hotspot/test/runtime/defineAnonClass/NestedUnsafe2.java new file mode 100644 index 00000000000..33ec95a1005 --- /dev/null +++ b/hotspot/test/runtime/defineAnonClass/NestedUnsafe2.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8058575 + * @summary Creates an anonymous class inside of an anonymous class. + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.compiler + * java.management + * @run main p.NestedUnsafe2 + */ + +package p; + +import java.security.ProtectionDomain; +import java.io.InputStream; +import java.lang.*; +import jdk.test.lib.*; +import jdk.internal.misc.Unsafe; +import jdk.test.lib.unsafe.UnsafeHelper; + + +// Test that an anonymous class that gets put in its host's package cannot define +// an anonymous class in another package. +public class NestedUnsafe2 { + // The String concatenation should create the nested anonymous class. + public static byte klassbuf[] = InMemoryJavaCompiler.compile("q.TestClass", + "package q; " + + "public class TestClass { " + + " public static void concat(String one, String two) throws Throwable { " + + " System.out.println(one + two);" + + " } } "); + + public static void main(String args[]) throws Exception { + Unsafe unsafe = UnsafeHelper.getUnsafe(); + + // The anonymous class calls defineAnonymousClass creating a nested anonymous class. + byte klassbuf2[] = InMemoryJavaCompiler.compile("TestClass2", + "import jdk.internal.misc.Unsafe; " + + "public class TestClass2 { " + + " public static void doit() throws Throwable { " + + " Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe(); " + + " Class klass2 = unsafe.defineAnonymousClass(TestClass2.class, p.NestedUnsafe2.klassbuf, new Object[0]); " + + " unsafe.ensureClassInitialized(klass2); " + + " Class[] dArgs = new Class[2]; " + + " dArgs[0] = String.class; " + + " dArgs[1] = String.class; " + + " try { " + + " klass2.getMethod(\"concat\", dArgs).invoke(null, \"CC\", \"DD\"); " + + " } catch (Throwable ex) { " + + " throw new RuntimeException(\"Exception: \" + ex.toString()); " + + " } " + + "} } ", + "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED"); + + Class klass2 = unsafe.defineAnonymousClass(p.NestedUnsafe2.class, klassbuf2, new Object[0]); + try { + klass2.getMethod("doit").invoke(null); + throw new RuntimeException("Expected exception not thrown"); + } catch (Throwable ex) { + Throwable iae = ex.getCause(); + if (!iae.toString().contains( + "IllegalArgumentException: Host class p/NestedUnsafe2 and anonymous class q/TestClass")) { + throw new RuntimeException("Exception: " + iae.toString()); + } + } + } +} From af30b263449bd7aac6ec7f9aa14325090e9e7a0e Mon Sep 17 00:00:00 2001 From: Marcus Larsson Date: Wed, 7 Sep 2016 14:36:44 +0200 Subject: [PATCH 066/110] 8165226: Bad -Xloggc: arguments crashes the VM Reviewed-by: dsamersoff, sjohanss --- hotspot/src/share/vm/logging/logConfiguration.cpp | 1 + hotspot/src/share/vm/prims/jvmtiEnv.cpp | 10 +++------- hotspot/src/share/vm/runtime/arguments.cpp | 8 ++++++-- .../src/share/vm/services/classLoadingService.cpp | 14 ++++---------- 4 files changed, 14 insertions(+), 19 deletions(-) diff --git a/hotspot/src/share/vm/logging/logConfiguration.cpp b/hotspot/src/share/vm/logging/logConfiguration.cpp index 29a65cd3a1f..7842cbb34e2 100644 --- a/hotspot/src/share/vm/logging/logConfiguration.cpp +++ b/hotspot/src/share/vm/logging/logConfiguration.cpp @@ -385,6 +385,7 @@ bool LogConfiguration::parse_log_arguments(const char* outputstr, const char* decoratorstr, const char* output_options, outputStream* errstream) { + assert(errstream != NULL, "errstream can not be NULL"); if (outputstr == NULL || strlen(outputstr) == 0) { outputstr = "stdout"; } diff --git a/hotspot/src/share/vm/prims/jvmtiEnv.cpp b/hotspot/src/share/vm/prims/jvmtiEnv.cpp index f1c5f962b17..25ad11871fe 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp @@ -649,18 +649,14 @@ JvmtiEnv::GetErrorName(jvmtiError error, char** name_ptr) { jvmtiError JvmtiEnv::SetVerboseFlag(jvmtiVerboseFlag flag, jboolean value) { + LogLevelType level = value == 0 ? LogLevel::Off : LogLevel::Info; switch (flag) { case JVMTI_VERBOSE_OTHER: // ignore break; case JVMTI_VERBOSE_CLASS: - if (value == 0) { - LogConfiguration::parse_log_arguments("stdout", "class+unload=off", NULL, NULL, NULL); - LogConfiguration::parse_log_arguments("stdout", "class+load=off", NULL, NULL, NULL); - } else { - LogConfiguration::parse_log_arguments("stdout", "class+load=info", NULL, NULL, NULL); - LogConfiguration::parse_log_arguments("stdout", "class+unload=info", NULL, NULL, NULL); - } + LogConfiguration::configure_stdout(level, false, LOG_TAGS(class, unload)); + LogConfiguration::configure_stdout(level, false, LOG_TAGS(class, load)); break; case JVMTI_VERBOSE_GC: if (value == 0) { diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 18cd2374e3f..e897e9cdf50 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -33,8 +33,9 @@ #include "gc/shared/referenceProcessor.hpp" #include "gc/shared/taskqueue.hpp" #include "logging/log.hpp" -#include "logging/logTag.hpp" #include "logging/logConfiguration.hpp" +#include "logging/logStream.hpp" +#include "logging/logTag.hpp" #include "memory/allocation.inline.hpp" #include "memory/universe.inline.hpp" #include "oops/oop.inline.hpp" @@ -4176,7 +4177,10 @@ bool Arguments::handle_deprecated_print_gc_flags() { if (_gc_log_filename != NULL) { // -Xloggc was used to specify a filename const char* gc_conf = PrintGCDetails ? "gc*" : "gc"; - return LogConfiguration::parse_log_arguments(_gc_log_filename, gc_conf, NULL, NULL, NULL); + + LogTarget(Error, logging) target; + LogStreamCHeap errstream(target); + return LogConfiguration::parse_log_arguments(_gc_log_filename, gc_conf, NULL, NULL, &errstream); } else if (PrintGC || PrintGCDetails) { LogConfiguration::configure_stdout(LogLevel::Info, !PrintGCDetails, LOG_TAGS(gc)); } diff --git a/hotspot/src/share/vm/services/classLoadingService.cpp b/hotspot/src/share/vm/services/classLoadingService.cpp index 6d1f0cdb36f..185c04eeafa 100644 --- a/hotspot/src/share/vm/services/classLoadingService.cpp +++ b/hotspot/src/share/vm/services/classLoadingService.cpp @@ -183,11 +183,8 @@ size_t ClassLoadingService::compute_class_size(InstanceKlass* k) { bool ClassLoadingService::set_verbose(bool verbose) { MutexLocker m(Management_lock); // verbose will be set to the previous value - if (verbose) { - LogConfiguration::parse_log_arguments("stdout", "class+load=info", NULL, NULL, NULL); - } else { - LogConfiguration::parse_log_arguments("stdout", "class+load=off", NULL, NULL, NULL); - } + LogLevelType level = verbose ? LogLevel::Info : LogLevel::Off; + LogConfiguration::configure_stdout(level, false, LOG_TAGS(class, load)); reset_trace_class_unloading(); return verbose; } @@ -196,11 +193,8 @@ bool ClassLoadingService::set_verbose(bool verbose) { void ClassLoadingService::reset_trace_class_unloading() { assert(Management_lock->owned_by_self(), "Must own the Management_lock"); bool value = MemoryService::get_verbose() || ClassLoadingService::get_verbose(); - if (value) { - LogConfiguration::parse_log_arguments("stdout", "class+unload=info", NULL, NULL, NULL); - } else { - LogConfiguration::parse_log_arguments("stdout", "class+unload=off", NULL, NULL, NULL); - } + LogLevelType level = value ? LogLevel::Info : LogLevel::Off; + LogConfiguration::configure_stdout(level, false, LOG_TAGS(class, unload)); } GrowableArray* LoadedClassesEnumerator::_loaded_classes = NULL; From a900715bbf7d4892302f5598e1d1cb1482e62adc Mon Sep 17 00:00:00 2001 From: Frederic Parain Date: Wed, 7 Sep 2016 12:52:20 -0400 Subject: [PATCH 067/110] 8137035: nsk/stress/stack/stack tests got EXCEPTION_STACK_OVERFLOW on Windows 64 bit Reviewed-by: dholmes, dcubed, coleenp --- hotspot/src/cpu/x86/vm/globals_x86.hpp | 4 ++-- hotspot/src/os/windows/vm/os_windows.cpp | 19 +++++++++++-------- .../src/share/vm/runtime/interfaceSupport.hpp | 7 +++++++ 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/hotspot/src/cpu/x86/vm/globals_x86.hpp b/hotspot/src/cpu/x86/vm/globals_x86.hpp index 93aea2a18d7..925ae225476 100644 --- a/hotspot/src/cpu/x86/vm/globals_x86.hpp +++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp @@ -65,10 +65,10 @@ define_pd_global(intx, InlineSmallCode, 1000); #ifdef AMD64 // Very large C++ stack frames using solaris-amd64 optimized builds // due to lack of optimization caused by C++ compiler bugs -#define DEFAULT_STACK_SHADOW_PAGES (NOT_WIN64(20) WIN64_ONLY(6) DEBUG_ONLY(+2)) +#define DEFAULT_STACK_SHADOW_PAGES (NOT_WIN64(20) WIN64_ONLY(7) DEBUG_ONLY(+2)) // For those clients that do not use write socket, we allow // the min range value to be below that of the default -#define MIN_STACK_SHADOW_PAGES (NOT_WIN64(10) WIN64_ONLY(6) DEBUG_ONLY(+2)) +#define MIN_STACK_SHADOW_PAGES (NOT_WIN64(10) WIN64_ONLY(7) DEBUG_ONLY(+2)) #else #define DEFAULT_STACK_SHADOW_PAGES (4 DEBUG_ONLY(+5)) #define MIN_STACK_SHADOW_PAGES DEFAULT_STACK_SHADOW_PAGES diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 24b39189e76..17231d81849 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -2504,13 +2504,15 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { // It write enables the page immediately after protecting it // so just return. if (exception_code == EXCEPTION_ACCESS_VIOLATION) { - JavaThread* thread = (JavaThread*) t; - PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord; - address addr = (address) exceptionRecord->ExceptionInformation[1]; - if (os::is_memory_serialize_page(thread, addr)) { - // Block current thread until the memory serialize page permission restored. - os::block_on_serialize_page_trap(); - return EXCEPTION_CONTINUE_EXECUTION; + if (t != NULL && t->is_Java_thread()) { + JavaThread* thread = (JavaThread*) t; + PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord; + address addr = (address) exceptionRecord->ExceptionInformation[1]; + if (os::is_memory_serialize_page(thread, addr)) { + // Block current thread until the memory serialize page permission restored. + os::block_on_serialize_page_trap(); + return EXCEPTION_CONTINUE_EXECUTION; + } } } @@ -2564,7 +2566,7 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { } #endif if (thread->stack_guards_enabled()) { - if (_thread_in_Java) { + if (in_java) { frame fr; PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord; address addr = (address) exceptionRecord->ExceptionInformation[1]; @@ -2576,6 +2578,7 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { // Yellow zone violation. The o/s has unprotected the first yellow // zone page for us. Note: must call disable_stack_yellow_zone to // update the enabled status, even if the zone contains only one page. + assert(thread->thread_state() != _thread_in_vm, "Undersized StackShadowPages"); thread->disable_stack_yellow_reserved_zone(); // If not in java code, return and hope for the best. return in_java diff --git a/hotspot/src/share/vm/runtime/interfaceSupport.hpp b/hotspot/src/share/vm/runtime/interfaceSupport.hpp index 4d4d51b26a0..840d68e2444 100644 --- a/hotspot/src/share/vm/runtime/interfaceSupport.hpp +++ b/hotspot/src/share/vm/runtime/interfaceSupport.hpp @@ -219,6 +219,9 @@ class ThreadInVMfromJava : public ThreadStateTransition { trans_from_java(_thread_in_vm); } ~ThreadInVMfromJava() { + if (_thread->stack_yellow_reserved_zone_disabled()) { + _thread->enable_stack_yellow_reserved_zone(); + } trans(_thread_in_vm, _thread_in_Java); // Check for pending. async. exceptions or suspends. if (_thread->has_special_runtime_exit_condition()) _thread->handle_special_runtime_exit_condition(); @@ -306,6 +309,9 @@ class ThreadInVMfromJavaNoAsyncException : public ThreadStateTransition { trans_from_java(_thread_in_vm); } ~ThreadInVMfromJavaNoAsyncException() { + if (_thread->stack_yellow_reserved_zone_disabled()) { + _thread->enable_stack_yellow_reserved_zone(); + } trans(_thread_in_vm, _thread_in_Java); // NOTE: We do not check for pending. async. exceptions. // If we did and moved the pending async exception over into the @@ -314,6 +320,7 @@ class ThreadInVMfromJavaNoAsyncException : public ThreadStateTransition { // to the _thread_in_vm state. Instead we postpone the handling of // the async exception. + // Check for pending. suspends only. if (_thread->has_special_runtime_exit_condition()) _thread->handle_special_runtime_exit_condition(false); From 3c2621dbdd3e868cd81942e3041c214ff735dc8e Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Wed, 7 Sep 2016 15:25:21 -0400 Subject: [PATCH 068/110] 8165246: [REDO] InstanceKlass::_previous_version_count goes negative Make _has_previous_version a boolean that is set to true when previous version of a class is added or during class unloading call to purge_previous_versions Reviewed-by: gtriantafill, dcubed, sspitsyn --- .../share/vm/classfile/classLoaderData.cpp | 2 +- hotspot/src/share/vm/oops/instanceKlass.cpp | 179 ++++++++++-------- hotspot/src/share/vm/oops/instanceKlass.hpp | 14 +- .../RedefinePreviousVersions.java | 120 ++++++++++++ 4 files changed, 235 insertions(+), 80 deletions(-) create mode 100644 hotspot/test/runtime/RedefineTests/RedefinePreviousVersions.java diff --git a/hotspot/src/share/vm/classfile/classLoaderData.cpp b/hotspot/src/share/vm/classfile/classLoaderData.cpp index ba1191614b1..9dea595e3aa 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.cpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp @@ -966,7 +966,7 @@ bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive_closure, // Klasses to delete. bool walk_all_metadata = clean_previous_versions && JvmtiExport::has_redefined_a_class() && - InstanceKlass::has_previous_versions(); + InstanceKlass::has_previous_versions_and_reset(); MetadataOnStackMark md_on_stack(walk_all_metadata); // Save previous _unloading pointer for CMS which may add to unloading list before diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index 1385affc5df..aaebc235e9d 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -3365,88 +3365,119 @@ void InstanceKlass::set_init_state(ClassState state) { #if INCLUDE_JVMTI -// RedefineClasses() support for previous versions: -int InstanceKlass::_previous_version_count = 0; +// RedefineClasses() support for previous versions -// Purge previous versions before adding new previous versions of the class. -void InstanceKlass::purge_previous_versions(InstanceKlass* ik) { - if (ik->previous_versions() != NULL) { - // This klass has previous versions so see what we can cleanup - // while it is safe to do so. +// Globally, there is at least one previous version of a class to walk +// during class unloading, which is saved because old methods in the class +// are still running. Otherwise the previous version list is cleaned up. +bool InstanceKlass::_has_previous_versions = false; - int deleted_count = 0; // leave debugging breadcrumbs - int live_count = 0; - ClassLoaderData* loader_data = ik->class_loader_data(); - assert(loader_data != NULL, "should never be null"); +// Returns true if there are previous versions of a class for class +// unloading only. Also resets the flag to false. purge_previous_version +// will set the flag to true if there are any left, i.e., if there's any +// work to do for next time. This is to avoid the expensive code cache +// walk in CLDG::do_unloading(). +bool InstanceKlass::has_previous_versions_and_reset() { + bool ret = _has_previous_versions; + log_trace(redefine, class, iklass, purge)("Class unloading: has_previous_versions = %s", + ret ? "true" : "false"); + _has_previous_versions = false; + return ret; +} - ResourceMark rm; - log_trace(redefine, class, iklass, purge)("%s: previous versions", ik->external_name()); +// Purge previous versions before adding new previous versions of the class and +// during class unloading. +void InstanceKlass::purge_previous_version_list() { + assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint"); + assert(has_been_redefined(), "Should only be called for main class"); - // previous versions are linked together through the InstanceKlass - InstanceKlass* pv_node = ik->previous_versions(); - InstanceKlass* last = ik; - int version = 0; + // Quick exit. + if (previous_versions() == NULL) { + return; + } - // check the previous versions list - for (; pv_node != NULL; ) { + // This klass has previous versions so see what we can cleanup + // while it is safe to do so. - ConstantPool* pvcp = pv_node->constants(); - assert(pvcp != NULL, "cp ref was unexpectedly cleared"); + int deleted_count = 0; // leave debugging breadcrumbs + int live_count = 0; + ClassLoaderData* loader_data = class_loader_data(); + assert(loader_data != NULL, "should never be null"); - if (!pvcp->on_stack()) { - // If the constant pool isn't on stack, none of the methods - // are executing. Unlink this previous_version. - // The previous version InstanceKlass is on the ClassLoaderData deallocate list - // so will be deallocated during the next phase of class unloading. - log_trace(redefine, class, iklass, purge)("previous version " INTPTR_FORMAT " is dead", p2i(pv_node)); - // For debugging purposes. - pv_node->set_is_scratch_class(); - pv_node->class_loader_data()->add_to_deallocate_list(pv_node); - pv_node = pv_node->previous_versions(); - last->link_previous_versions(pv_node); - deleted_count++; - version++; - continue; - } else { - log_trace(redefine, class, iklass, purge)("previous version " INTPTR_FORMAT " is alive", p2i(pv_node)); - assert(pvcp->pool_holder() != NULL, "Constant pool with no holder"); - guarantee (!loader_data->is_unloading(), "unloaded classes can't be on the stack"); - live_count++; - } + ResourceMark rm; + log_trace(redefine, class, iklass, purge)("%s: previous versions", external_name()); - // At least one method is live in this previous version. - // Reset dead EMCP methods not to get breakpoints. - // All methods are deallocated when all of the methods for this class are no - // longer running. - Array* method_refs = pv_node->methods(); - if (method_refs != NULL) { - log_trace(redefine, class, iklass, purge)("previous methods length=%d", method_refs->length()); - for (int j = 0; j < method_refs->length(); j++) { - Method* method = method_refs->at(j); + // previous versions are linked together through the InstanceKlass + InstanceKlass* pv_node = previous_versions(); + InstanceKlass* last = this; + int version = 0; - if (!method->on_stack()) { - // no breakpoints for non-running methods - if (method->is_running_emcp()) { - method->set_running_emcp(false); - } - } else { - assert (method->is_obsolete() || method->is_running_emcp(), - "emcp method cannot run after emcp bit is cleared"); - log_trace(redefine, class, iklass, purge) - ("purge: %s(%s): prev method @%d in version @%d is alive", - method->name()->as_C_string(), method->signature()->as_C_string(), j, version); + // check the previous versions list + for (; pv_node != NULL; ) { + + ConstantPool* pvcp = pv_node->constants(); + assert(pvcp != NULL, "cp ref was unexpectedly cleared"); + + if (!pvcp->on_stack()) { + // If the constant pool isn't on stack, none of the methods + // are executing. Unlink this previous_version. + // The previous version InstanceKlass is on the ClassLoaderData deallocate list + // so will be deallocated during the next phase of class unloading. + log_trace(redefine, class, iklass, purge) + ("previous version " INTPTR_FORMAT " is dead.", p2i(pv_node)); + // For debugging purposes. + pv_node->set_is_scratch_class(); + // Unlink from previous version list. + assert(pv_node->class_loader_data() == loader_data, "wrong loader_data"); + InstanceKlass* next = pv_node->previous_versions(); + pv_node->link_previous_versions(NULL); // point next to NULL + last->link_previous_versions(next); + // Add to the deallocate list after unlinking + loader_data->add_to_deallocate_list(pv_node); + pv_node = next; + deleted_count++; + version++; + continue; + } else { + log_trace(redefine, class, iklass, purge)("previous version " INTPTR_FORMAT " is alive", p2i(pv_node)); + assert(pvcp->pool_holder() != NULL, "Constant pool with no holder"); + guarantee (!loader_data->is_unloading(), "unloaded classes can't be on the stack"); + live_count++; + // found a previous version for next time we do class unloading + _has_previous_versions = true; + } + + // At least one method is live in this previous version. + // Reset dead EMCP methods not to get breakpoints. + // All methods are deallocated when all of the methods for this class are no + // longer running. + Array* method_refs = pv_node->methods(); + if (method_refs != NULL) { + log_trace(redefine, class, iklass, purge)("previous methods length=%d", method_refs->length()); + for (int j = 0; j < method_refs->length(); j++) { + Method* method = method_refs->at(j); + + if (!method->on_stack()) { + // no breakpoints for non-running methods + if (method->is_running_emcp()) { + method->set_running_emcp(false); } + } else { + assert (method->is_obsolete() || method->is_running_emcp(), + "emcp method cannot run after emcp bit is cleared"); + log_trace(redefine, class, iklass, purge) + ("purge: %s(%s): prev method @%d in version @%d is alive", + method->name()->as_C_string(), method->signature()->as_C_string(), j, version); } } - // next previous version - last = pv_node; - pv_node = pv_node->previous_versions(); - version++; } - log_trace(redefine, class, iklass, purge) - ("previous version stats: live=%d, deleted=%d", - live_count, deleted_count); + // next previous version + last = pv_node; + pv_node = pv_node->previous_versions(); + version++; } + log_trace(redefine, class, iklass, purge) + ("previous version stats: live=%d, deleted=%d", live_count, deleted_count); } void InstanceKlass::mark_newly_obsolete_methods(Array* old_methods, @@ -3518,8 +3549,8 @@ void InstanceKlass::add_previous_version(instanceKlassHandle scratch_class, log_trace(redefine, class, iklass, add) ("adding previous version ref for %s, EMCP_cnt=%d", scratch_class->external_name(), emcp_method_count); - // Clean out old previous versions - purge_previous_versions(this); + // Clean out old previous versions for this class + purge_previous_version_list(); // Mark newly obsolete methods in remaining previous versions. An EMCP method from // a previous redefinition may be made obsolete by this redefinition. @@ -3536,8 +3567,6 @@ void InstanceKlass::add_previous_version(instanceKlassHandle scratch_class, // For debugging purposes. scratch_class->set_is_scratch_class(); scratch_class->class_loader_data()->add_to_deallocate_list(scratch_class()); - // Update count for class unloading. - _previous_version_count--; return; } @@ -3565,12 +3594,12 @@ void InstanceKlass::add_previous_version(instanceKlassHandle scratch_class, } // Add previous version if any methods are still running. - log_trace(redefine, class, iklass, add)("scratch class added; one of its methods is on_stack"); + // Set has_previous_version flag for processing during class unloading. + _has_previous_versions = true; + log_trace(redefine, class, iklass, add) ("scratch class added; one of its methods is on_stack."); assert(scratch_class->previous_versions() == NULL, "shouldn't have a previous version"); scratch_class->link_previous_versions(previous_versions()); link_previous_versions(scratch_class()); - // Update count for class unloading. - _previous_version_count++; } // end add_previous_version() #endif // INCLUDE_JVMTI diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index e4eb9b3e4fe..330f373f001 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -709,6 +709,7 @@ class InstanceKlass: public Klass { // RedefineClasses() support for previous versions: void add_previous_version(instanceKlassHandle ikh, int emcp_method_count); + void purge_previous_version_list(); InstanceKlass* previous_versions() const { return _previous_versions; } #else @@ -768,10 +769,15 @@ public: } private: - static int _previous_version_count; + static bool _has_previous_versions; public: - static void purge_previous_versions(InstanceKlass* ik); - static bool has_previous_versions() { return _previous_version_count > 0; } + static void purge_previous_versions(InstanceKlass* ik) { + if (ik->has_been_redefined()) { + ik->purge_previous_version_list(); + } + } + + static bool has_previous_versions_and_reset(); // JVMTI: Support for caching a class file before it is modified by an agent that can do retransformation void set_cached_class_file(JvmtiCachedClassFileData *data) { @@ -792,7 +798,7 @@ public: #else // INCLUDE_JVMTI static void purge_previous_versions(InstanceKlass* ik) { return; }; - static bool has_previous_versions() { return false; } + static bool has_previous_versions_and_reset() { return false; } void set_cached_class_file(JvmtiCachedClassFileData *data) { assert(data == NULL, "unexpected call with JVMTI disabled"); diff --git a/hotspot/test/runtime/RedefineTests/RedefinePreviousVersions.java b/hotspot/test/runtime/RedefineTests/RedefinePreviousVersions.java new file mode 100644 index 00000000000..45555dcf4ab --- /dev/null +++ b/hotspot/test/runtime/RedefineTests/RedefinePreviousVersions.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8165246 + * @summary Test has_previous_versions flag and processing during class unloading. + * @library /test/lib + * @modules java.base/jdk.internal.misc + * @modules java.compiler + * java.instrument + * jdk.jartool/sun.tools.jar + * @run main RedefineClassHelper + * @run main/othervm RedefinePreviousVersions test + */ + +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; + +public class RedefinePreviousVersions { + + public static String newB = + "class RedefinePreviousVersions$B {" + + "}"; + + static class B { } + + public static String newRunning = + "class RedefinePreviousVersions$Running {" + + " public static volatile boolean stop = true;" + + " static void localSleep() { }" + + " public static void infinite() { }" + + "}"; + + static class Running { + public static volatile boolean stop = false; + static void localSleep() { + try{ + Thread.currentThread().sleep(10);//sleep for 10 ms + } catch(InterruptedException ie) { + } + } + + public static void infinite() { + while (!stop) { localSleep(); } + } + } + + public static void main(String[] args) throws Exception { + + if (args.length > 0) { + + String jarFile = System.getProperty("test.src") + "/testcase.jar"; + + // java -javaagent:redefineagent.jar -Xlog:stuff RedefinePreviousVersions + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( "-javaagent:redefineagent.jar", + "-Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace", + "RedefinePreviousVersions"); + new OutputAnalyzer(pb.start()) + .shouldContain("Class unloading: has_previous_versions = false") + .shouldContain("Class unloading: has_previous_versions = true") + .shouldHaveExitValue(0); + return; + } + + // Redefine a class and create some garbage + // Since there are no methods running, the previous version is never added to the + // previous_version_list and the flag _has_previous_versions should stay false + RedefineClassHelper.redefineClass(B.class, newB); + + for (int i = 0; i < 10 ; i++) { + String s = new String("some garbage"); + System.gc(); + } + + // Start a class that has a method running + new Thread() { + public void run() { + Running.infinite(); + } + }.start(); + + // Since a method of newRunning is running, this class should be added to the previous_version_list + // of Running, and _has_previous_versions should return true at class unloading. + RedefineClassHelper.redefineClass(Running.class, newRunning); + + for (int i = 0; i < 10 ; i++) { + String s = new String("some garbage"); + System.gc(); + } + + // purge should clean everything up, except Xcomp it might not. + Running.stop = true; + + for (int i = 0; i < 10 ; i++) { + String s = new String("some garbage"); + System.gc(); + } + } +} From 1a8f8e22f1877155e24fdc36991b73997246c616 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Wed, 7 Sep 2016 16:43:32 -0400 Subject: [PATCH 069/110] 8165153: Crash in rebuild_cpu_to_node_map Use processor_count(), not active_processor_count() to determine physical number of CPUs Reviewed-by: rehn, cjplummer --- hotspot/src/os/linux/vm/os_linux.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 9248eb72e35..5aafe4b8474 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -2875,7 +2875,7 @@ void os::Linux::rebuild_cpu_to_node_map() { // in the library. const size_t BitsPerCLong = sizeof(long) * CHAR_BIT; - size_t cpu_num = os::active_processor_count(); + size_t cpu_num = processor_count(); size_t cpu_map_size = NCPUS / BitsPerCLong; size_t cpu_map_valid_size = MIN2((cpu_num + BitsPerCLong - 1) / BitsPerCLong, cpu_map_size); From 50fb03349c8fc71cff46b525aa67e8b204e49f64 Mon Sep 17 00:00:00 2001 From: Mikael Gerdin Date: Fri, 2 Sep 2016 16:45:16 +0200 Subject: [PATCH 070/110] 8161079: Default heap size causes native memory exhaustion on 32 bit Windows Reviewed-by: tschatzl, sjohanss --- hotspot/src/os/windows/vm/os_windows.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 17231d81849..d8034537e2d 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -3796,6 +3796,11 @@ void os::win32::initialize_system_info() { GlobalMemoryStatusEx(&ms); _physical_memory = ms.ullTotalPhys; + if (FLAG_IS_DEFAULT(MaxRAM)) { + // Adjust MaxRAM according to the maximum virtual address space available. + FLAG_SET_DEFAULT(MaxRAM, MIN2(MaxRAM, (uint64_t) ms.ullTotalVirtual)); + } + OSVERSIONINFOEX oi; oi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); GetVersionEx((OSVERSIONINFO*)&oi); From f0535f417c42087deae61bb84ad797972094ef6b Mon Sep 17 00:00:00 2001 From: Iris Clark Date: Fri, 2 Sep 2016 10:48:35 -0700 Subject: [PATCH 071/110] 8165269: (doc) Toolkit.isDynamicLayoutActive(): orphan '0' in first sentence Reviewed-by: alexsch --- jdk/src/java.desktop/share/classes/java/awt/Toolkit.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/java.desktop/share/classes/java/awt/Toolkit.java b/jdk/src/java.desktop/share/classes/java/awt/Toolkit.java index 76db7f06a30..9d00222ed2c 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Toolkit.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Toolkit.java @@ -208,7 +208,7 @@ public abstract class Toolkit { /** * Returns whether dynamic layout of Containers on resize is currently - * enabled on the underlying operating system and/or window manager). If the + * enabled on the underlying operating system and/or window manager. If the * platform supports it, {@code setDynamicLayout(boolean)} may be used to * programmatically enable or disable platform dynamic layout. Regardless of * whether that toggling is supported, or whether {@code true} or {@code From 92cf16b425ffe4336f5c0879d27ccda3983e7658 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Fri, 2 Sep 2016 11:29:02 -0700 Subject: [PATCH 072/110] 8154075: [TIFF] AIOOB Exception from TIFFLZWDecompressor For banded images make sure the step in the horizontal differencing predictor calculations for Deflate and LZW compression is unity (1) instead of the number of samples per pixel. Reviewed-by: prr --- .../plugins/tiff/TIFFDeflateDecompressor.java | 12 ++++++++---- .../imageio/plugins/tiff/TIFFLZWDecompressor.java | 14 ++++++++------ 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDeflateDecompressor.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDeflateDecompressor.java index ecbd38a4d3a..1ce7d56c1c7 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDeflateDecompressor.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDeflateDecompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -101,13 +101,17 @@ public class TIFFDeflateDecompressor extends TIFFDecompressor { if (predictor == BaselineTIFFTagSet.PREDICTOR_HORIZONTAL_DIFFERENCING) { + int step = planar || samplesPerPixel == 1 ? 1 : samplesPerPixel; + int samplesPerRow = step * srcWidth; + int off = bufOffset + step; for (int j = 0; j < srcHeight; j++) { - int count = bufOffset + samplesPerPixel * (j * srcWidth + 1); - for (int i=samplesPerPixel; i Date: Tue, 6 Sep 2016 13:03:00 +0300 Subject: [PATCH 073/110] 8155083: On Windows, usage of USER_ATTENTION_WINDOW depends on state setting order Reviewed-by: serb, ssadetsky --- jdk/src/java.desktop/share/classes/java/awt/Taskbar.java | 4 +--- .../java.desktop/share/classes/java/awt/peer/TaskbarPeer.java | 4 +--- .../windows/native/libawt/windows/awt_Taskbar.cpp | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/jdk/src/java.desktop/share/classes/java/awt/Taskbar.java b/jdk/src/java.desktop/share/classes/java/awt/Taskbar.java index 393d8a32ba2..22710085e83 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Taskbar.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Taskbar.java @@ -273,9 +273,7 @@ public class Taskbar { } /** - * Requests user attention to the specified window until it is activated. - * - * On an already active window requesting attention does nothing. + * Requests user attention to the specified window. * * @param w window * @throws SecurityException if a security manager exists and it denies the diff --git a/jdk/src/java.desktop/share/classes/java/awt/peer/TaskbarPeer.java b/jdk/src/java.desktop/share/classes/java/awt/peer/TaskbarPeer.java index 934a1c01538..bf31082fe92 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/peer/TaskbarPeer.java +++ b/jdk/src/java.desktop/share/classes/java/awt/peer/TaskbarPeer.java @@ -49,9 +49,7 @@ public interface TaskbarPeer { default void requestUserAttention(boolean enabled, final boolean critical) {} /** - * Requests user attention to the specified window until it is activated. - * - * On an already active window requesting attention does nothing. + * Requests user attention to the specified window. * * @param w window */ diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Taskbar.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Taskbar.cpp index 50c1ba85c2a..ebb07187322 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Taskbar.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Taskbar.cpp @@ -108,7 +108,7 @@ JNIEXPORT void JNICALL Java_sun_awt_windows_WTaskbarPeer_setProgressState JNIEXPORT void JNICALL Java_sun_awt_windows_WTaskbarPeer_flashWindow (JNIEnv *, jobject, jlong window) { - AwtWindow::FlashWindowEx((HWND) window, 3, 0, FLASHW_TIMERNOFG); + ::FlashWindow((HWND) window, TRUE); } /* From 2aac4c1f387418d69dc34f9b4fe6a7ef07f990f3 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Tue, 6 Sep 2016 08:32:50 -0700 Subject: [PATCH 074/110] 8165345: JDK macro definition re-defined by MacOS core framework Reviewed-by: serb --- .../share/native/libfontmanager/HBShaper.c | 2 +- .../share/native/libfontmanager/hb-jdk-font.cc | 16 ++++++++-------- .../share/native/libfontmanager/hb-jdk.h | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/jdk/src/java.desktop/share/native/libfontmanager/HBShaper.c b/jdk/src/java.desktop/share/native/libfontmanager/HBShaper.c index 3b7a463ffdf..95a92f221ad 100644 --- a/jdk/src/java.desktop/share/native/libfontmanager/HBShaper.c +++ b/jdk/src/java.desktop/share/native/libfontmanager/HBShaper.c @@ -80,7 +80,7 @@ jboolean storeGVData(JNIEnv* env, int i, needToGrow; float x=0, y=0; float startX, startY, advX, advY; - float scale = 1.0f / FloatToFixedScale / devScale; + float scale = 1.0f / HBFloatToFixedScale / devScale; unsigned int* glyphs; float* positions; int initialCount, glyphArrayLen, posArrayLen, maxGlyphs, storeadv, maxStore; diff --git a/jdk/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc b/jdk/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc index c65c673e4ae..2e41293a08f 100644 --- a/jdk/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc +++ b/jdk/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc @@ -80,7 +80,7 @@ hb_jdk_get_glyph_h_advance (hb_font_t *font HB_UNUSED, fadv *= jdkFontInfo->devScale; env->DeleteLocalRef(pt); - return FloatToFixed(fadv); + return HBFloatToFixed(fadv); } static hb_position_t @@ -107,7 +107,7 @@ hb_jdk_get_glyph_v_advance (hb_font_t *font HB_UNUSED, fadv = env->GetFloatField(pt, sunFontIDs.yFID); env->DeleteLocalRef(pt); - return FloatToFixed(fadv); + return HBFloatToFixed(fadv); } @@ -201,8 +201,8 @@ hb_jdk_get_glyph_contour_point (hb_font_t *font HB_UNUSED, *x = 0; *y = 0; return true; } - *x = FloatToFixed(env->GetFloatField(pt, sunFontIDs.xFID)); - *y = FloatToFixed(env->GetFloatField(pt, sunFontIDs.yFID)); + *x = HBFloatToFixed(env->GetFloatField(pt, sunFontIDs.xFID)); + *y = HBFloatToFixed(env->GetFloatField(pt, sunFontIDs.yFID)); env->DeleteLocalRef(pt); return true; @@ -321,8 +321,8 @@ static hb_font_t* _hb_jdk_font_create(JDKFontInfo *jdkFontInfo, _hb_jdk_get_font_funcs (), jdkFontInfo, (hb_destroy_func_t) _do_nothing); hb_font_set_scale (font, - FloatToFixed(jdkFontInfo->ptSize*jdkFontInfo->devScale), - FloatToFixed(jdkFontInfo->ptSize*jdkFontInfo->devScale)); + HBFloatToFixed(jdkFontInfo->ptSize*jdkFontInfo->devScale), + HBFloatToFixed(jdkFontInfo->ptSize*jdkFontInfo->devScale)); return font; } @@ -339,8 +339,8 @@ static hb_font_t* _hb_jdk_ct_font_create(JDKFontInfo *jdkFontInfo) { hb_face_destroy(face); hb_font_set_scale(font, - FloatToFixed(jdkFontInfo->ptSize), - FloatToFixed(jdkFontInfo->ptSize)); + HBFloatToFixed(jdkFontInfo->ptSize), + HBFloatToFixed(jdkFontInfo->ptSize)); return font; } #endif diff --git a/jdk/src/java.desktop/share/native/libfontmanager/hb-jdk.h b/jdk/src/java.desktop/share/native/libfontmanager/hb-jdk.h index 8c08fb036ed..b62c8b1553b 100644 --- a/jdk/src/java.desktop/share/native/libfontmanager/hb-jdk.h +++ b/jdk/src/java.desktop/share/native/libfontmanager/hb-jdk.h @@ -49,8 +49,8 @@ typedef struct JDKFontInfo_Struct { // Use 16.16 for better precision than 26.6 -#define FloatToFixedScale ((float)(1 << 16)) -#define FloatToFixed(f) ((unsigned int)((f) * FloatToFixedScale)) +#define HBFloatToFixedScale ((float)(1 << 16)) +#define HBFloatToFixed(f) ((unsigned int)((f) * HBFloatToFixedScale)) /* * Note: From ed5befdde8e160bb904a2c2376c88fc9bcba2576 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Tue, 6 Sep 2016 11:08:59 -0700 Subject: [PATCH 075/110] 8164899: Provide package access to setComponentMixingCutoutShape Reviewed-by: serb --- .../classes/com/sun/awt/AWTUtilities.java | 1 + .../share/classes/java/awt/Component.java | 92 +++++++++++++------ 2 files changed, 67 insertions(+), 26 deletions(-) diff --git a/jdk/src/java.desktop/share/classes/com/sun/awt/AWTUtilities.java b/jdk/src/java.desktop/share/classes/com/sun/awt/AWTUtilities.java index 1957fba5b8e..1ba10acd72f 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/awt/AWTUtilities.java +++ b/jdk/src/java.desktop/share/classes/com/sun/awt/AWTUtilities.java @@ -447,6 +447,7 @@ public final class AWTUtilities { * @param shape the new 'mixing-cutout' shape * @throws NullPointerException if the component argument is {@code null} */ + @Deprecated(since = "9") public static void setComponentMixingCutoutShape(Component component, Shape shape) { diff --git a/jdk/src/java.desktop/share/classes/java/awt/Component.java b/jdk/src/java.desktop/share/classes/java/awt/Component.java index 25c6ee2b1aa..228e14c93d2 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Component.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Component.java @@ -843,32 +843,7 @@ public abstract class Component implements ImageObserver, MenuContainer, return new Rectangle(comp.x, comp.y, comp.width, comp.height); } public void setMixingCutoutShape(Component comp, Shape shape) { - Region region = shape == null ? null : - Region.getInstance(shape, null); - - synchronized (comp.getTreeLock()) { - boolean needShowing = false; - boolean needHiding = false; - - if (!comp.isNonOpaqueForMixing()) { - needHiding = true; - } - - comp.mixingCutoutRegion = region; - - if (!comp.isNonOpaqueForMixing()) { - needShowing = true; - } - - if (comp.isMixingNeeded()) { - if (needHiding) { - comp.mixOnHiding(comp.isLightweight()); - } - if (needShowing) { - comp.mixOnShowing(); - } - } - } + comp.setMixingCutoutShape(shape); } public void setGraphicsConfiguration(Component comp, @@ -10238,6 +10213,71 @@ public abstract class Component implements ImageObserver, MenuContainer, return true; } + /** + * Sets a 'mixing-cutout' shape for the given component. + * + * By default a lightweight component is treated as an opaque rectangle for + * the purposes of the Heavyweight/Lightweight Components Mixing feature. + * This method enables developers to set an arbitrary shape to be cut out + * from heavyweight components positioned underneath the lightweight + * component in the z-order. + *

+ * The {@code shape} argument may have the following values: + *

    + *
  • {@code null} - reverts the default cutout shape (the rectangle equal + * to the component's {@code getBounds()}) + *
  • empty-shape - does not cut out anything from heavyweight + * components. This makes the given lightweight component effectively + * transparent. Note that descendants of the lightweight component still + * affect the shapes of heavyweight components. An example of an + * empty-shape is {@code new Rectangle()}. + *
  • non-empty-shape - the given shape will be cut out from + * heavyweight components. + *
+ *

+ * The most common example when the 'mixing-cutout' shape is needed is a + * glass pane component. The {@link JRootPane#setGlassPane()} method + * automatically sets the empty-shape as the 'mixing-cutout' shape + * for the given glass pane component. If a developer needs some other + * 'mixing-cutout' shape for the glass pane (which is rare), this must be + * changed manually after installing the glass pane to the root pane. + *

+ * Note that the 'mixing-cutout' shape neither affects painting, nor the + * mouse events handling for the given component. It is used exclusively + * for the purposes of the Heavyweight/Lightweight Components Mixing + * feature. + * + * @param shape the new 'mixing-cutout' shape + * @since 9 + */ + void setMixingCutoutShape(Shape shape) { + Region region = shape == null ? null : Region.getInstance(shape, null); + + synchronized (getTreeLock()) { + boolean needShowing = false; + boolean needHiding = false; + + if (!isNonOpaqueForMixing()) { + needHiding = true; + } + + mixingCutoutRegion = region; + + if (!isNonOpaqueForMixing()) { + needShowing = true; + } + + if (isMixingNeeded()) { + if (needHiding) { + mixOnHiding(isLightweight()); + } + if (needShowing) { + mixOnShowing(); + } + } + } + } + // ****************** END OF MIXING CODE ******************************** // Note that the method is overriden in the Window class, From 537661d271a06c1ef7e235563c88e4d43ae7ac44 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Thu, 8 Sep 2016 19:25:55 +0300 Subject: [PATCH 076/110] 8160570: [macosx] modal dialog can skip the activation/focus events Reviewed-by: serb, ssadetsky --- .../classes/sun/lwawt/LWWindowPeer.java | 1 + .../ModalDialogActivationTest.java | 96 +++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 jdk/test/java/awt/Focus/ModalDialogActivationTest/ModalDialogActivationTest.java diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java index 658be0638bb..12f9747d82c 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java @@ -187,6 +187,7 @@ public class LWWindowPeer updateAlwaysOnTopState(); updateMinimumSize(); + updateFocusableWindowState(); final Shape shape = getTarget().getShape(); if (shape != null) { diff --git a/jdk/test/java/awt/Focus/ModalDialogActivationTest/ModalDialogActivationTest.java b/jdk/test/java/awt/Focus/ModalDialogActivationTest/ModalDialogActivationTest.java new file mode 100644 index 00000000000..deff8ee33a4 --- /dev/null +++ b/jdk/test/java/awt/Focus/ModalDialogActivationTest/ModalDialogActivationTest.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; + +/* + @test + @bug 8160570 + @summary Tests that a modal dialog receives WINDOW_ACTIVATED & WINDOW_GAINED_FOCUS on first show. +*/ +public class ModalDialogActivationTest { + static final Object lock = new Object(); + static volatile boolean activated; + static volatile boolean focused; + + public static void main(String[] args) throws InterruptedException { + EventQueue.invokeLater(() -> runGUI()); + + long time = System.currentTimeMillis(); + synchronized (lock) { + while (!activated || !focused) { + lock.wait(5000); + if (System.currentTimeMillis() - time >= 5000) break; + } + } + if (!activated || !focused) { + throw new RuntimeException("Test FAILED: activated: " + activated + ", focused: " + focused); + } + System.out.println("Test PASSED"); + } + + static void runGUI() { + JFrame f = new JFrame("frame"); + final JDialog d = new MyModalDialog(f, "dialog"); + d.addWindowListener(new WindowAdapter() { + @Override + public void windowActivated(WindowEvent e) { + synchronized (lock) { + activated = true; + lock.notifyAll(); + } + } + }); + d.addWindowFocusListener(new WindowAdapter() { + @Override + public void windowGainedFocus(WindowEvent e) { + synchronized (lock) { + focused = true; + lock.notifyAll(); + } + } + }); + f.setVisible(true); + d.setVisible(true); + } + + static class MyModalDialog extends JDialog { + public MyModalDialog(Frame owner, String title)ª { + super(owner, title, true); + } + + @Override + public boolean getFocusableWindowState() { + try { + // let Toolkit thread go ahead + Thread.sleep(100); + } catch (InterruptedException ignore) { + } + return super.getFocusableWindowState(); + } + } +} From 84982a552aae9e33edb8c6f1740dbb02aa86a2ae Mon Sep 17 00:00:00 2001 From: Avik Niyogi Date: Fri, 9 Sep 2016 11:48:20 +0530 Subject: [PATCH 077/110] 8163274: [TEST_BUG][macosx] apparent regression: javax/swing/JColorChooser/Test7194184.java Reviewed-by: alexsch, rchamyal --- .../swing/JColorChooser/Test7194184.java | 81 +++++++++++-------- 1 file changed, 46 insertions(+), 35 deletions(-) diff --git a/jdk/test/javax/swing/JColorChooser/Test7194184.java b/jdk/test/javax/swing/JColorChooser/Test7194184.java index 460aefaf3b5..1c6dbbb4b37 100644 --- a/jdk/test/javax/swing/JColorChooser/Test7194184.java +++ b/jdk/test/javax/swing/JColorChooser/Test7194184.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -25,19 +25,15 @@ * Portions Copyright (c) 2012 IBM Corporation */ -/* - * @test - * @key headful - * @bug 7194184 +/* @test + @key headful + * @bug 7194184 8163274 * @summary Tests JColorChooser Swatch keyboard accessibility. - * @author Sean Chou * @library ../regtesthelpers * @build Util - * @run main Test7194184 + * @run main/timeout=500 Test7194184 */ - import java.awt.Component; -import java.awt.AWTException; import java.awt.Color; import java.awt.Robot; import java.awt.event.KeyEvent; @@ -46,66 +42,81 @@ import javax.swing.JColorChooser; import javax.swing.JFrame; import javax.swing.SwingUtilities; -import java.util.concurrent.Callable; +public class Test7194184 { -public class Test7194184 implements Runnable { private static JFrame frame; private static JColorChooser colorChooser; - private static Color selectedColor; + private static Color testColor; + private static Color newColor; + + private static Robot robot; public static void main(String[] args) throws Exception { - testKeyBoardAccess(); + robot = new Robot(); + robot.setAutoWaitForIdle(true); + createUI(); + accessRecentSwatch(); + runRobot(); + testColorChooser(); + cleanUpUI(); } - private static void testKeyBoardAccess() throws Exception { - Robot robot = new Robot(); - - SwingUtilities.invokeLater(new Test7194184()); - robot.waitForIdle(); - + private static void createUI() throws Exception { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - selectedColor = colorChooser.getColor(); + String title = getClass().getName(); + frame = new JFrame(title); + colorChooser = new JColorChooser(); + frame.add(colorChooser); + frame.pack(); + frame.setVisible(true); + } + }); + } + private static void accessRecentSwatch() throws Exception { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { Component recentSwatchPanel = Util.findSubComponent(colorChooser, "RecentSwatchPanel"); if (recentSwatchPanel == null) { throw new RuntimeException("RecentSwatchPanel not found"); } recentSwatchPanel.requestFocusInWindow(); + testColor = colorChooser.getColor(); + } }); + } - robot.waitForIdle(); - + private static void runRobot() { // Tab to move the focus to MainSwatch Util.hitKeys(robot, KeyEvent.VK_SHIFT, KeyEvent.VK_TAB); - // Select the color on right Util.hitKeys(robot, KeyEvent.VK_RIGHT); Util.hitKeys(robot, KeyEvent.VK_RIGHT); Util.hitKeys(robot, KeyEvent.VK_SPACE); - robot.waitForIdle(); + } + private static void testColorChooser() throws Exception { SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { - frame.dispose(); - if (selectedColor == colorChooser.getColor()) { + newColor = colorChooser.getColor(); + if (newColor == testColor) { throw new RuntimeException("JColorChooser misses keyboard accessibility"); } } }); } - public void run() { - String title = getClass().getName(); - frame = new JFrame(title); - colorChooser = new JColorChooser(); - - frame.add(colorChooser); - frame.pack(); - frame.setVisible(true); + private static void cleanUpUI() throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + frame.dispose(); + } + }); } - } From 189143f87c1dbf2b2d1d685bd38ba91efa01cee2 Mon Sep 17 00:00:00 2001 From: Prem Balakrishnan Date: Fri, 9 Sep 2016 13:15:10 +0530 Subject: [PATCH 078/110] 8009477: PageUp and PageDown keyboard buttons don't move slider indicator to next minor tick Reviewed-by: alexsch, aghaisas --- .../javax/swing/plaf/basic/BasicSliderUI.java | 9 +- .../JSlider/SliderTick/SliderTickTest.java | 181 ++++++++++++++++++ 2 files changed, 188 insertions(+), 2 deletions(-) create mode 100644 jdk/test/javax/swing/JSlider/SliderTick/SliderTickTest.java diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSliderUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSliderUI.java index 8dc00a15e6f..445483a1073 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSliderUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSliderUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -1603,13 +1603,18 @@ public class BasicSliderUI extends SliderUI{ blockIncrement = 1; } + int tickSpacing = getTickSpacing(); if (slider.getSnapToTicks()) { - int tickSpacing = getTickSpacing(); if (blockIncrement < tickSpacing) { blockIncrement = tickSpacing; } } + else { + if (tickSpacing > 0) { + blockIncrement = tickSpacing; + } + } int delta = blockIncrement * ((direction > 0) ? POSITIVE_SCROLL : NEGATIVE_SCROLL); slider.setValue(slider.getValue() + delta); diff --git a/jdk/test/javax/swing/JSlider/SliderTick/SliderTickTest.java b/jdk/test/javax/swing/JSlider/SliderTick/SliderTickTest.java new file mode 100644 index 00000000000..6832cf5832e --- /dev/null +++ b/jdk/test/javax/swing/JSlider/SliderTick/SliderTickTest.java @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + /* + * @test + * @bug 8009477 + * @summary Verify PageUp/PageDown key moves slider to Next/Previous minor tick. + * @run main/manual SliderTickTest + */ +import java.awt.Color; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.util.concurrent.CountDownLatch; +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; +import javax.swing.JButton; +import javax.swing.JFrame; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.concurrent.TimeUnit; +import javax.swing.JSlider; + +public class SliderTickTest { + + public static void main(String args[]) throws Exception { + final CountDownLatch latch = new CountDownLatch(1); + TestUI test = new TestUI(latch); + + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + try { + test.createUI(); + } catch (Exception ex) { + throw new RuntimeException("Exception while creating UI"); + } + } + }); + + boolean status = latch.await(5, TimeUnit.MINUTES); + + if (!status) { + System.out.println("Test timed out."); + } + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + try { + test.disposeUI(); + } catch (Exception ex) { + throw new RuntimeException("Exception while disposing UI"); + } + } + }); + + if (test.testResult == false) { + throw new RuntimeException("Test Failed."); + } + } +} + +class TestUI { + + private static JFrame mainFrame; + private static JPanel mainControlPanel; + + private static JTextArea instructionTextArea; + + private static JPanel resultButtonPanel; + private static JButton passButton; + private static JButton failButton; + + private static GridBagLayout layout; + private final CountDownLatch latch; + public boolean testResult = false; + + public TestUI(CountDownLatch latch) throws Exception { + this.latch = latch; + } + + public final void createUI() throws Exception { + + mainFrame = new JFrame("SliderTickTest"); + + layout = new GridBagLayout(); + mainControlPanel = new JPanel(layout); + resultButtonPanel = new JPanel(layout); + + GridBagConstraints gbc = new GridBagConstraints(); + + // Create Test instructions + String instructions + = "INSTRUCTIONS:" + + "\n Click PageUp/PageDown key. If the slider indicator" + + "\n moves to Next/Previous immediate minor tick, then " + + "\n test passes else failed."; + + instructionTextArea = new JTextArea(); + instructionTextArea.setText(instructions); + instructionTextArea.setEnabled(false); + instructionTextArea.setDisabledTextColor(Color.black); + instructionTextArea.setBackground(Color.white); + + gbc.gridx = 0; + gbc.gridy = 0; + gbc.fill = GridBagConstraints.HORIZONTAL; + mainControlPanel.add(instructionTextArea, gbc); + + JSlider slider = new JSlider(0, 50); + slider.setMajorTickSpacing(10); + slider.setMinorTickSpacing(2); + slider.setPaintTicks(true); + slider.setPaintLabels(true); + slider.setValue(30); + slider.setBorder(BorderFactory.createTitledBorder("Ticks")); + gbc.gridx = 0; + gbc.gridy = 1; + mainControlPanel.add(slider, gbc); + + passButton = new JButton("Pass"); + passButton.setActionCommand("Pass"); + passButton.addActionListener((ActionEvent e) -> { + testResult = true; + mainFrame.dispose(); + latch.countDown(); + + }); + failButton = new JButton("Fail"); + failButton.setActionCommand("Fail"); + failButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + testResult = false; + mainFrame.dispose(); + latch.countDown(); + } + }); + gbc.gridx = 0; + gbc.gridy = 0; + resultButtonPanel.add(passButton, gbc); + gbc.gridx = 1; + gbc.gridy = 0; + resultButtonPanel.add(failButton, gbc); + + gbc.gridx = 0; + gbc.gridy = 2; + mainControlPanel.add(resultButtonPanel, gbc); + + mainFrame.add(mainControlPanel); + mainFrame.pack(); + mainFrame.setVisible(true); + } + + public void disposeUI() { + mainFrame.setVisible(false); + mainFrame.dispose(); + } +} From 3d1c3e2f60de52c630f992b0b34546d20b3a0e13 Mon Sep 17 00:00:00 2001 From: Semyon Sadetsky Date: Fri, 9 Sep 2016 16:37:16 +0300 Subject: [PATCH 079/110] 8160054: The FileChooser didn't displayed large font with GTK LAF option Reviewed-by: alexsch, serb --- .../com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java | 2 +- .../classes/com/sun/java/swing/plaf/gtk/GTKStyle.java | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java index fea2b08309e..d0b66ba6f18 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java @@ -504,7 +504,7 @@ public class GTKLookAndFeel extends SynthLookAndFeel { public Object createValue(UIDefaults table) { GTKStyleFactory factory = (GTKStyleFactory)getStyleFactory(); GTKStyle style = (GTKStyle)factory.getStyle(null, region); - return style.getFontForState(null); + return style.getDefaultFont(); } } diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java index b3d32695d38..e4281dd6a86 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java @@ -282,7 +282,17 @@ class GTKStyle extends SynthStyle implements GTKConstants { return getColorForState(context, type); } + Font getDefaultFont() { + return font; + } + protected Font getFontForState(SynthContext context) { + Font propFont = UIManager + .getFont(context.getRegion().getName() + ".font"); + if (propFont != null) { + // if font property got a value then return it + return propFont; + } return font; } From b68b46b14fc0df0383abda26b085284f4fede3b7 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Sat, 10 Sep 2016 14:50:35 +0530 Subject: [PATCH 080/110] 4885375: Page Ranges 'To Page' field must be populated based on Pageable Reviewed-by: prr, jdv --- .../classes/sun/print/RasterPrinterJob.java | 4 + .../print/PrinterJob/PrintDlgPageable.java | 171 ++++++++++++++++++ 2 files changed, 175 insertions(+) create mode 100644 jdk/test/java/awt/print/PrinterJob/PrintDlgPageable.java diff --git a/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java b/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java index e2813a59544..0de841f6208 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java +++ b/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java @@ -1001,6 +1001,10 @@ public abstract class RasterPrinterJob extends PrinterJob { // temporarily add an attribute pointing back to this job. PrinterJobWrapper jobWrapper = new PrinterJobWrapper(this); attributes.add(jobWrapper); + PageRanges pgRng = (PageRanges)attributes.get(PageRanges.class); + if (pgRng == null && mDocument.getNumberOfPages() > 1) { + attributes.add(new PageRanges(1, mDocument.getNumberOfPages())); + } try { newService = ServiceUI.printDialog(gc, x, y, diff --git a/jdk/test/java/awt/print/PrinterJob/PrintDlgPageable.java b/jdk/test/java/awt/print/PrinterJob/PrintDlgPageable.java new file mode 100644 index 00000000000..f6a74f9f965 --- /dev/null +++ b/jdk/test/java/awt/print/PrinterJob/PrintDlgPageable.java @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * @test + * @bug 4885375 + * @summary Verifies if PageRanges To Field is populated based on Pageable + * for COMMON print dialog + * @run main/manual PrintDlgPageable + */ +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.Graphics; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.print.PageFormat; +import java.awt.print.Pageable; +import java.awt.print.Printable; +import java.awt.print.PrinterException; +import java.awt.print.PrinterJob; +import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.print.attribute.PrintRequestAttributeSet; +import javax.print.attribute.standard.DialogTypeSelection; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; + +public class PrintDlgPageable implements Printable { + + private static Thread mainThread; + private static boolean testPassed; + private static boolean testGeneratedInterrupt; + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(() -> { + doTest(PrintDlgPageable::printTest); + }); + mainThread = Thread.currentThread(); + try { + Thread.sleep(30000); + } catch (InterruptedException e) { + if (!testPassed && testGeneratedInterrupt) { + throw new RuntimeException("Print Dialog does not " + + "`reflect Copies or Page Ranges"); + } + } + if (!testGeneratedInterrupt) { + throw new RuntimeException("user has not executed the test"); + } + } + + private static void printTest() { + PrinterJob pj = PrinterJob.getPrinterJob(); + PageableHandler handler = new PageableHandler(); + pj.setPageable(handler); + + PrintRequestAttributeSet pSet = new HashPrintRequestAttributeSet(); + pSet.add(DialogTypeSelection.COMMON); + pj.printDialog(pSet); + } + + + public static synchronized void pass() { + testPassed = true; + testGeneratedInterrupt = true; + mainThread.interrupt(); + } + + public static synchronized void fail() { + testPassed = false; + testGeneratedInterrupt = true; + mainThread.interrupt(); + } + + private static void doTest(Runnable action) { + String description + = " Visual inspection of print dialog is required.\n" + + " A print dialog will be shown.\n " + + " Please verify Page Range is populated \n" + + " with \"From\" 1 and \"To\" 5.\n" + + " If ok, press PASS else press FAIL"; + + final JDialog dialog = new JDialog(); + dialog.setTitle("printSelectionTest"); + JTextArea textArea = new JTextArea(description); + textArea.setEditable(false); + final JButton testButton = new JButton("Start Test"); + final JButton passButton = new JButton("PASS"); + passButton.setEnabled(false); + passButton.addActionListener((e) -> { + dialog.dispose(); + pass(); + }); + final JButton failButton = new JButton("FAIL"); + failButton.setEnabled(false); + failButton.addActionListener((e) -> { + dialog.dispose(); + fail(); + }); + testButton.addActionListener((e) -> { + testButton.setEnabled(false); + action.run(); + passButton.setEnabled(true); + failButton.setEnabled(true); + }); + JPanel mainPanel = new JPanel(new BorderLayout()); + mainPanel.add(textArea, BorderLayout.CENTER); + JPanel buttonPanel = new JPanel(new FlowLayout()); + buttonPanel.add(testButton); + buttonPanel.add(passButton); + buttonPanel.add(failButton); + mainPanel.add(buttonPanel, BorderLayout.SOUTH); + dialog.add(mainPanel); + dialog.pack(); + dialog.setVisible(true); + dialog.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + System.out.println("main dialog closing"); + testGeneratedInterrupt = false; + mainThread.interrupt(); + } + }); + } + + @Override + public int print(Graphics g, PageFormat pf, int pi) throws PrinterException { + return NO_SUCH_PAGE; + } +} + +class PageableHandler implements Pageable { + + PageFormat pf = new PageFormat(); + + @Override + public int getNumberOfPages() { + return 5; + } + + @Override + public Printable getPrintable(int pageIndex) { + return new PrintDlgPageable(); + } + + @Override + public PageFormat getPageFormat(int pageIndex) { + return pf; + } +} From a99b7ce75978dbeb9a91a3bc533e00d82a09f30e Mon Sep 17 00:00:00 2001 From: Jayathirth D V Date: Mon, 12 Sep 2016 12:07:56 +0530 Subject: [PATCH 081/110] 4924727: reader.abort() method does not work when called inside imageStarted for PNG Reviewed-by: prr, serb, bpb --- jdk/make/mapfiles/libjpeg/mapfile-vers | 1 + .../imageio/plugins/bmp/BMPImageReader.java | 79 ++++---- .../imageio/plugins/gif/GIFImageReader.java | 15 +- .../imageio/plugins/jpeg/JPEGImageReader.java | 54 +++--- .../imageio/plugins/png/PNGImageReader.java | 47 +++-- .../imageio/plugins/tiff/TIFFImageReader.java | 22 ++- .../share/native/libjavajpeg/imageioJPEG.c | 19 ++ jdk/test/javax/imageio/ReadAbortTest.java | 181 ++++++++++++++++++ 8 files changed, 326 insertions(+), 92 deletions(-) create mode 100644 jdk/test/javax/imageio/ReadAbortTest.java diff --git a/jdk/make/mapfiles/libjpeg/mapfile-vers b/jdk/make/mapfiles/libjpeg/mapfile-vers index b82e7574598..22c132fbd72 100644 --- a/jdk/make/mapfiles/libjpeg/mapfile-vers +++ b/jdk/make/mapfiles/libjpeg/mapfile-vers @@ -42,6 +42,7 @@ SUNWprivate_1.1 { Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_resetReader; Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_disposeReader; Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_resetLibraryState; + Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_clearNativeReadAbortFlag; Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_initWriterIDs; Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_initJPEGImageWriter; Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_setDest; diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java index 2134f4b888d..67d1b5307ae 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, 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 @@ -749,6 +749,10 @@ public class BMPImageReader extends ImageReader implements BMPConstants { checkIndex(imageIndex); clearAbortRequest(); processImageStarted(imageIndex); + if (abortRequested()) { + processReadAborted(); + return bi; + } if (param == null) param = getDefaultReadParam(); @@ -1005,9 +1009,6 @@ public class BMPImageReader extends ImageReader implements BMPConstants { int j = isBottomUp ? (height -1)*bytesPerScanline : 0; for (int i=0; iabortFlag; } +JNIEXPORT void JNICALL +Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_clearNativeReadAbortFlag + (JNIEnv *env, + jobject this, + jlong ptr) { + + imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr); + + if (data == NULL) { + JNU_ThrowByName(env, + "java/lang/IllegalStateException", + "Attempting to use reader after dispose()"); + return; + } + + data->abortFlag = JNI_FALSE; + +} + JNIEXPORT void JNICALL Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_abortRead (JNIEnv *env, diff --git a/jdk/test/javax/imageio/ReadAbortTest.java b/jdk/test/javax/imageio/ReadAbortTest.java new file mode 100644 index 00000000000..7476dbe0de8 --- /dev/null +++ b/jdk/test/javax/imageio/ReadAbortTest.java @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + /* + * @test + * @bug 4924727 + * @summary Test verifies that if we call ImageReader.abort() in + * IIOReadProgressListener.imageStarted() or + * IIOReadProgressListener.imageProgress() are we + * calling IIOReadProgressListener.readAborted() for all readers. + * @run main ReadAbortTest + */ +import java.awt.image.BufferedImage; +import java.io.File; +import java.util.Iterator; +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.event.IIOReadProgressListener; +import javax.imageio.stream.ImageInputStream; +import java.awt.Color; +import java.awt.Graphics2D; +import java.nio.file.Files; + +public class ReadAbortTest implements IIOReadProgressListener { + + ImageReader reader = null; + ImageInputStream iis = null; + BufferedImage bimg = null; + File file; + boolean startAbort = false; + boolean startAborted = false; + boolean progressAbort = false; + boolean progressAborted = false; + Color srccolor = Color.red; + int width = 100; + int heght = 100; + + public ReadAbortTest(String format) throws Exception { + try { + System.out.println("Test for format " + format); + bimg = new BufferedImage(width, heght, + BufferedImage.TYPE_INT_RGB); + + Graphics2D g = bimg.createGraphics(); + g.setColor(srccolor); + g.fillRect(0, 0, width, heght); + g.dispose(); + + file = File.createTempFile("src_", "." + format, new File(".")); + ImageIO.write(bimg, format, file); + ImageInputStream iis = ImageIO.createImageInputStream(file); + + Iterator iter = ImageIO.getImageReaders(iis); + while (iter.hasNext()) { + reader = (ImageReader) iter.next(); + break; + } + reader.setInput(iis); + reader.addIIOReadProgressListener(this); + + // Abort reading in IIOReadProgressListener.imageStarted(). + startAbort = true; + bimg = reader.read(0); + startAbort = false; + + // Abort reading in IIOReadProgressListener.imageProgress(). + progressAbort = true; + bimg = reader.read(0); + progressAbort = false; + + iis.close(); + /* + * All abort requests from imageStarted,imageProgress and + * imageComplete from IIOReadProgressListener should be reached + * otherwise throw RuntimeException. + */ + if (!(startAborted + && progressAborted)) { + throw new RuntimeException("All IIOReadProgressListener abort" + + " requests are not processed for format " + + format); + } + } catch (Exception e) { + throw e; + } finally { + Files.delete(file.toPath()); + } + } + + /* + * Abstract methods that we need to implement from + * IIOReadProgressListener, and relevant for this test case. + */ + @Override + public void imageStarted(ImageReader source, int imageIndex) { + System.out.println("imageStarted called"); + if (startAbort) { + source.abort(); + } + } + + @Override + public void imageProgress(ImageReader source, float percentageDone) { + System.out.println("imageProgress called"); + if (progressAbort) { + source.abort(); + } + } + + @Override + public void readAborted(ImageReader source) { + System.out.println("readAborted called"); + // Verify IIOReadProgressListener.imageStarted() abort request. + if (startAbort) { + System.out.println("imageStarted aborted "); + startAborted = true; + } + + // Verify IIOReadProgressListener.imageProgress() abort request. + if (progressAbort) { + System.out.println("imageProgress aborted "); + progressAborted = true; + } + } + + public static void main(String args[]) throws Exception { + final String[] formats = {"bmp", "png", "gif", "jpg", "tif"}; + for (String format : formats) { + new ReadAbortTest(format); + } + } + + /* + * Remaining abstract methods that we need to implement from + * IIOReadProgressListener, but not relevant for this test case. + */ + @Override + public void imageComplete(ImageReader source) { + } + + @Override + public void sequenceStarted(ImageReader reader, int i) { + } + + @Override + public void sequenceComplete(ImageReader reader) { + } + + @Override + public void thumbnailStarted(ImageReader reader, int i, int i1) { + } + + @Override + public void thumbnailProgress(ImageReader reader, float f) { + } + + @Override + public void thumbnailComplete(ImageReader reader) { + } +} + From 3a0c7b8644958f4a15f3a6a60bf6cde9a12bd221 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Tue, 13 Sep 2016 13:40:32 +0530 Subject: [PATCH 082/110] 7064425: PageFormat Dialog has no owner window to reactivate 6948907: sun.print.DialogOwner does not support Dialogs as DialogOwner Reviewed-by: prr, jdv --- .../share/classes/sun/print/DialogOwner.java | 14 +- .../classes/sun/print/RasterPrinterJob.java | 31 ++-- .../classes/sun/awt/windows/WPrinterJob.java | 21 ++- .../TestPageDlgFrameAssociation.java | 166 ++++++++++++++++++ .../TestPrintDlgFrameAssociation.java | 165 +++++++++++++++++ 5 files changed, 378 insertions(+), 19 deletions(-) create mode 100644 jdk/test/java/awt/print/PrinterJob/TestPageDlgFrameAssociation.java create mode 100644 jdk/test/java/awt/print/PrinterJob/TestPrintDlgFrameAssociation.java diff --git a/jdk/src/java.desktop/share/classes/sun/print/DialogOwner.java b/jdk/src/java.desktop/share/classes/sun/print/DialogOwner.java index 3b29183e2f4..f3f50391754 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/DialogOwner.java +++ b/jdk/src/java.desktop/share/classes/sun/print/DialogOwner.java @@ -25,9 +25,11 @@ package sun.print; +import java.awt.Dialog; import javax.print.attribute.Attribute; import javax.print.attribute.PrintRequestAttribute; import java.awt.Frame; +import java.awt.Window; /** * Class DialogOwner is a printing attribute class that identifies @@ -42,7 +44,7 @@ import java.awt.Frame; public final class DialogOwner implements PrintRequestAttribute { - private Frame dlgOwner; + private Window dlgOwner; /** * Construct a new dialog owner attribute with the given frame. @@ -53,11 +55,19 @@ public final class DialogOwner dlgOwner = frame; } + /** + * Construct a new dialog owner attribute with the given dialog. + * + * @param dialog the dialog that owns the print dialog + */ + public DialogOwner(Dialog dialog) { + dlgOwner = dialog; + } /** * Returns the string table for class DialogOwner. */ - public Frame getOwner() { + public Window getOwner() { return dlgOwner; } diff --git a/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java b/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java index 0de841f6208..0a5e99c0bd5 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java +++ b/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java @@ -30,7 +30,6 @@ import java.io.FilePermission; import java.awt.Color; import java.awt.Dialog; import java.awt.Frame; -import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.GraphicsEnvironment; @@ -39,7 +38,6 @@ import java.awt.KeyboardFocusManager; import java.awt.Rectangle; import java.awt.Shape; import java.awt.geom.AffineTransform; -import java.awt.geom.Area; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; @@ -55,7 +53,6 @@ import java.awt.Window; import java.io.File; import java.io.IOException; import java.util.ArrayList; -import java.util.Enumeration; import java.util.Locale; import sun.awt.image.ByteInterleavedRaster; @@ -74,7 +71,6 @@ import javax.print.attribute.HashPrintRequestAttributeSet; import javax.print.attribute.PrintRequestAttributeSet; import javax.print.attribute.ResolutionSyntax; import javax.print.attribute.Size2DSyntax; -import javax.print.attribute.standard.Chromaticity; import javax.print.attribute.standard.Copies; import javax.print.attribute.standard.Destination; import javax.print.attribute.standard.DialogTypeSelection; @@ -96,11 +92,6 @@ import javax.print.attribute.standard.RequestingUserName; import javax.print.attribute.standard.SheetCollate; import javax.print.attribute.standard.Sides; -import sun.print.PageableDoc; -import sun.print.ServiceDialog; -import sun.print.SunPrinterJobService; -import sun.print.SunPageSelection; - /** * A class which rasterizes a printer job. * @@ -836,9 +827,16 @@ public abstract class RasterPrinterJob extends PrinterJob { Rectangle gcBounds = gc.getBounds(); int x = gcBounds.x+50; int y = gcBounds.y+50; - ServiceDialog pageDialog = new ServiceDialog(gc, x, y, service, - DocFlavor.SERVICE_FORMATTED.PAGEABLE, - attributes, (Frame)null); + ServiceDialog pageDialog; + if (w instanceof Frame) { + pageDialog = new ServiceDialog(gc, x, y, service, + DocFlavor.SERVICE_FORMATTED.PAGEABLE, + attributes,(Frame)w); + } else { + pageDialog = new ServiceDialog(gc, x, y, service, + DocFlavor.SERVICE_FORMATTED.PAGEABLE, + attributes, (Dialog)w); + } Rectangle dlgBounds = pageDialog.getBounds(); // if portion of dialog is not within the gc boundary @@ -944,6 +942,14 @@ public abstract class RasterPrinterJob extends PrinterJob { Window w = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow(); if (w != null) { grCfg = w.getGraphicsConfiguration(); + /* Add DialogOwner attribute to set the owner of this print dialog + * only if it is not set already + * (it might be set in java.awt.PrintJob.printDialog) + */ + if (attributes.get(DialogOwner.class) == null) { + attributes.add(w instanceof Frame ? new DialogOwner((Frame)w) : + new DialogOwner((Dialog)w)); + } } else { grCfg = GraphicsEnvironment.getLocalGraphicsEnvironment(). getDefaultScreenDevice().getDefaultConfiguration(); @@ -1018,6 +1024,7 @@ public abstract class RasterPrinterJob extends PrinterJob { attributes); } attributes.remove(PrinterJobWrapper.class); + attributes.remove(DialogOwner.class); if (newService == null) { return false; diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrinterJob.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrinterJob.java index 457393aeb5d..cfef03b9286 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrinterJob.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrinterJob.java @@ -478,9 +478,12 @@ public final class WPrinterJob extends RasterPrinterJob } DialogOwner dlgOwner = (DialogOwner)attributes.get(DialogOwner.class); - Frame ownerFrame = (dlgOwner != null) ? dlgOwner.getOwner() : null; + Window owner = (dlgOwner != null) ? dlgOwner.getOwner() : null; + + WPrintDialog dialog = (owner instanceof Frame) ? + new WPrintDialog((Frame)owner, this) : + new WPrintDialog((Dialog)owner, this); - WPrintDialog dialog = new WPrintDialog(ownerFrame, this); dialog.setRetVal(false); dialog.setVisible(true); boolean prv = dialog.getRetVal(); @@ -498,8 +501,9 @@ public final class WPrinterJob extends RasterPrinterJob title = rb.getString("dialog.printtofile"); } catch (MissingResourceException e) { } - FileDialog fileDialog = new FileDialog(ownerFrame, title, - FileDialog.SAVE); + FileDialog fileDialog = (owner instanceof Frame) ? + new FileDialog((Frame)owner, title, FileDialog.SAVE) : + new FileDialog((Dialog)owner, title, FileDialog.SAVE); URI destURI = dest.getURI(); // Old code destURI.getPath() would return null for "file:out.prn" @@ -531,10 +535,17 @@ public final class WPrinterJob extends RasterPrinterJob ((pFile != null) && (!pFile.exists() || (pFile.exists() && !pFile.canWrite())))) { - (new PrintToFileErrorDialog(ownerFrame, + if (owner instanceof Frame) { + (new PrintToFileErrorDialog((Frame)owner, ServiceDialog.getMsg("dialog.owtitle"), ServiceDialog.getMsg("dialog.writeerror")+" "+fullName, ServiceDialog.getMsg("button.ok"))).setVisible(true); + } else { + (new PrintToFileErrorDialog((Dialog)owner, + ServiceDialog.getMsg("dialog.owtitle"), + ServiceDialog.getMsg("dialog.writeerror")+" "+fullName, + ServiceDialog.getMsg("button.ok"))).setVisible(true); + } fileDialog.setVisible(true); fileName = fileDialog.getFile(); diff --git a/jdk/test/java/awt/print/PrinterJob/TestPageDlgFrameAssociation.java b/jdk/test/java/awt/print/PrinterJob/TestPageDlgFrameAssociation.java new file mode 100644 index 00000000000..32ee61ad1c6 --- /dev/null +++ b/jdk/test/java/awt/print/PrinterJob/TestPageDlgFrameAssociation.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * @test + * @bug 7064425 6948907 + * @summary Verifies if owner Frame is associated with page dialog of PrinterJob + * @run main/manual TestPageDlgFrameAssociation + */ +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Label; +import java.awt.Panel; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.print.PageFormat; +import java.awt.print.PrinterJob; +import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.print.attribute.PrintRequestAttributeSet; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; + +public class TestPageDlgFrameAssociation { + private static Thread mainThread; + private static boolean testPassed; + private static boolean testGeneratedInterrupt; + private static Button print; + private static Frame frame; + private static boolean start; + private static Thread t; + + public static void main(String args[]) throws Exception { + SwingUtilities.invokeAndWait(() -> { + doTest(TestPageDlgFrameAssociation::frameTest); + }); + mainThread = Thread.currentThread(); + try { + Thread.sleep(60000); + } catch (InterruptedException e) { + if (!testPassed && testGeneratedInterrupt) { + throw new RuntimeException("Page dialog not disposed." + + " Page dialog is not associated with owner Frame`"); + } + } + if (!testGeneratedInterrupt) { + throw new RuntimeException("user has not executed the test"); + } + } + + private static void frameTest() { + Panel panel =new Panel(); + + print = new Button("PageDialog"); + print.setActionCommand("PageDialog"); + print.addActionListener((e) -> { + PrinterJob job = PrinterJob.getPrinterJob(); + PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet(); + t.start(); + start = true; + PageFormat pf = job.pageDialog(aset); + }); + + panel.add(print); + + frame = new Frame("Test Frame"); + frame.setLayout (new BorderLayout ()); + frame.add(panel,"South"); + frame.pack(); + frame.setVisible(true); + + t = new Thread (() -> { + if (start) { + try { + Thread.sleep(5000); + } catch (InterruptedException ex) {} + frame.dispose(); + } + }); + } + + public static synchronized void pass() { + testPassed = true; + testGeneratedInterrupt = true; + mainThread.interrupt(); + } + + public static synchronized void fail() { + testPassed = false; + testGeneratedInterrupt = true; + mainThread.interrupt(); + } + + private static void doTest(Runnable action) { + String description + = " A Frame with PageDialog Button is shown. Press PageDialog.\n" + + " A page dialog will be shown. Do not press any button.\n" + + " After 5 secs the frame along with this page dialog will be disposed.\n" + + " If the page dialog is not disposed, press FAIL else press PASS"; + + final JDialog dialog = new JDialog(); + dialog.setTitle("printSelectionTest"); + JTextArea textArea = new JTextArea(description); + textArea.setEditable(false); + final JButton testButton = new JButton("Start Test"); + final JButton passButton = new JButton("PASS"); + passButton.setEnabled(false); + passButton.addActionListener((e) -> { + dialog.dispose(); + pass(); + }); + final JButton failButton = new JButton("FAIL"); + failButton.setEnabled(false); + failButton.addActionListener((e) -> { + dialog.dispose(); + fail(); + }); + testButton.addActionListener((e) -> { + testButton.setEnabled(false); + action.run(); + passButton.setEnabled(true); + failButton.setEnabled(true); + }); + JPanel mainPanel = new JPanel(new BorderLayout()); + mainPanel.add(textArea, BorderLayout.CENTER); + JPanel buttonPanel = new JPanel(new FlowLayout()); + buttonPanel.add(testButton); + buttonPanel.add(passButton); + buttonPanel.add(failButton); + mainPanel.add(buttonPanel, BorderLayout.SOUTH); + dialog.add(mainPanel); + dialog.pack(); + dialog.setVisible(true); + dialog.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + System.out.println("main dialog closing"); + testGeneratedInterrupt = false; + mainThread.interrupt(); + } + }); + } +} diff --git a/jdk/test/java/awt/print/PrinterJob/TestPrintDlgFrameAssociation.java b/jdk/test/java/awt/print/PrinterJob/TestPrintDlgFrameAssociation.java new file mode 100644 index 00000000000..d1d54307ab5 --- /dev/null +++ b/jdk/test/java/awt/print/PrinterJob/TestPrintDlgFrameAssociation.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * @test + * @bug 7064425 6948907 + * @summary Verifies if owner Frame is associated with print dialog of PrinterJob + * @run main/manual TestPrintDlgFrameAssociation + */ +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Label; +import java.awt.Panel; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.print.PrinterJob; +import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.print.attribute.PrintRequestAttributeSet; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; + +public class TestPrintDlgFrameAssociation { + private static Thread mainThread; + private static boolean testPassed; + private static boolean testGeneratedInterrupt; + private static Button print; + private static Frame frame; + private static boolean start; + private static Thread t; + + public static void main(String args[]) throws Exception { + SwingUtilities.invokeAndWait(() -> { + doTest(TestPrintDlgFrameAssociation::frameTest); + }); + mainThread = Thread.currentThread(); + try { + Thread.sleep(60000); + } catch (InterruptedException e) { + if (!testPassed && testGeneratedInterrupt) { + throw new RuntimeException("Print dialog not disposed." + + " Print dialog is not associated with owner Frame`"); + } + } + if (!testGeneratedInterrupt) { + throw new RuntimeException("user has not executed the test"); + } + } + + private static void frameTest() { + Panel panel =new Panel(); + + print = new Button("PrintDialog"); + print.setActionCommand("PrintDialog"); + print.addActionListener((e) -> { + PrinterJob job = PrinterJob.getPrinterJob(); + PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet(); + t.start(); + start = true; + job.printDialog(aset); + }); + + panel.add(print); + + frame = new Frame("Test Frame"); + frame.setLayout (new BorderLayout ()); + frame.add(panel,"South"); + frame.pack(); + frame.setVisible(true); + + t = new Thread (() -> { + if (start) { + try { + Thread.sleep(5000); + } catch (InterruptedException ex) {} + frame.dispose(); + } + }); + } + + public static synchronized void pass() { + testPassed = true; + testGeneratedInterrupt = true; + mainThread.interrupt(); + } + + public static synchronized void fail() { + testPassed = false; + testGeneratedInterrupt = true; + mainThread.interrupt(); + } + + private static void doTest(Runnable action) { + String description + = " A Frame with PrintDialog Button is shown. Press PrintDialog.\n" + + " A print dialog will be shown. Do not press any button.\n" + + " After 5 secs the frame along with this print dialog will be disposed.\n" + + " If the print dialog is not disposed, press FAIL else press PASS"; + + final JDialog dialog = new JDialog(); + dialog.setTitle("printSelectionTest"); + JTextArea textArea = new JTextArea(description); + textArea.setEditable(false); + final JButton testButton = new JButton("Start Test"); + final JButton passButton = new JButton("PASS"); + passButton.setEnabled(false); + passButton.addActionListener((e) -> { + dialog.dispose(); + pass(); + }); + final JButton failButton = new JButton("FAIL"); + failButton.setEnabled(false); + failButton.addActionListener((e) -> { + dialog.dispose(); + fail(); + }); + testButton.addActionListener((e) -> { + testButton.setEnabled(false); + action.run(); + passButton.setEnabled(true); + failButton.setEnabled(true); + }); + JPanel mainPanel = new JPanel(new BorderLayout()); + mainPanel.add(textArea, BorderLayout.CENTER); + JPanel buttonPanel = new JPanel(new FlowLayout()); + buttonPanel.add(testButton); + buttonPanel.add(passButton); + buttonPanel.add(failButton); + mainPanel.add(buttonPanel, BorderLayout.SOUTH); + dialog.add(mainPanel); + dialog.pack(); + dialog.setVisible(true); + dialog.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + System.out.println("main dialog closing"); + testGeneratedInterrupt = false; + mainThread.interrupt(); + } + }); + } +} From e4870c84e389bb48f7f91f4b3dd2a1e5ef9f565a Mon Sep 17 00:00:00 2001 From: Srikanth Adayapalam Date: Tue, 13 Sep 2016 19:32:03 +0530 Subject: [PATCH 083/110] 8138667: java.lang.IllegalAccessError: tried to access method (for a protected method) Reviewed-by: mcimadamore --- .../sun/tools/javac/comp/LambdaToMethod.java | 7 ++ .../ProtectedInaccessibleMethodRefTest.java | 71 +++++++++++++++++++ .../methodReference/pack/SuperClass.java | 40 +++++++++++ 3 files changed, 118 insertions(+) create mode 100644 langtools/test/tools/javac/lambda/methodReference/ProtectedInaccessibleMethodRefTest.java create mode 100644 langtools/test/tools/javac/lambda/methodReference/pack/SuperClass.java diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java index 9e691e3039b..b491f69019a 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java @@ -2256,6 +2256,12 @@ public class LambdaToMethod extends TreeTranslator { types.erasure(owner.enclClass().asType())); } + boolean isProtectedInSuperClassOfEnclosingClassInOtherPackage() { + return ((tree.sym.flags() & PROTECTED) != 0 && + tree.sym.packge() != owner.packge() && + !owner.enclClass().isSubClass(tree.sym.owner, types)); + } + /** * Signature polymorphic methods need special handling. * e.g. MethodHandle.invoke() MethodHandle.invokeExact() @@ -2293,6 +2299,7 @@ public class LambdaToMethod extends TreeTranslator { needsVarArgsConversion() || isArrayOp() || isPrivateInOtherClass() || + isProtectedInSuperClassOfEnclosingClassInOtherPackage() || !receiverAccessible() || (tree.getMode() == ReferenceMode.NEW && tree.kind != ReferenceKind.ARRAY_CTOR && diff --git a/langtools/test/tools/javac/lambda/methodReference/ProtectedInaccessibleMethodRefTest.java b/langtools/test/tools/javac/lambda/methodReference/ProtectedInaccessibleMethodRefTest.java new file mode 100644 index 00000000000..0ce71bfd750 --- /dev/null +++ b/langtools/test/tools/javac/lambda/methodReference/ProtectedInaccessibleMethodRefTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8138667 + * @summary Verify that javac emits suitable accessors when a method reference mentions a protected method that would need an accessor + * @run main ProtectedInaccessibleMethodRefTest + */ + + +import pack.SuperClass; + +import java.util.concurrent.Callable; + +public final class ProtectedInaccessibleMethodRefTest extends SuperClass { + + static String message = "NOT OK"; + + public void doTest() throws Exception { + new Callable() { + @Override + public Void call() throws Exception { + final Runnable r = ProtectedInaccessibleMethodRefTest.this::myDo; + r.run(); + return null; + } + }.call(); + + new Callable() { + @Override + public Void call() throws Exception { + final Runnable r = ProtectedInaccessibleMethodRefTest::myStaticDo; + r.run(); + return null; + } + }.call(); + } + + public void message(String s) { + message = s; + } + + public static void main(String[] args) throws Exception { + new ProtectedInaccessibleMethodRefTest().doTest(); + if (!message.equals("OK!")) + throw new AssertionError("Unexpected output"); + if (!sMessage.equals("OK!")) + throw new AssertionError("Unexpected output"); + } +} diff --git a/langtools/test/tools/javac/lambda/methodReference/pack/SuperClass.java b/langtools/test/tools/javac/lambda/methodReference/pack/SuperClass.java new file mode 100644 index 00000000000..5d2551daeb3 --- /dev/null +++ b/langtools/test/tools/javac/lambda/methodReference/pack/SuperClass.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package pack; + +public class SuperClass { + + public static String sMessage = "Not OK"; + + protected final void myDo() { + message("OK!"); + } + + protected static final void myStaticDo() { + sMessage = "OK!"; + } + + public void message(String s) { + } +} From 2b2b2f394e80dee26e366af559d3a86de9a1f122 Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Tue, 13 Sep 2016 20:59:28 +0530 Subject: [PATCH 084/110] 8163320: JAVA_VERSION in release file should come from java.base module Reviewed-by: mchung --- make/Images.gmk | 5 ----- 1 file changed, 5 deletions(-) diff --git a/make/Images.gmk b/make/Images.gmk index 75a8cb5e04b..a8967cc9f52 100644 --- a/make/Images.gmk +++ b/make/Images.gmk @@ -75,11 +75,6 @@ endef # Param 1 - The file containing the MODULES list define create-info-file - $(call info-file-item, "JAVA_VERSION", "$(VERSION_NUMBER)") - $(call info-file-item, "JAVA_FULL_VERSION", "$(VERSION_STRING)") - $(call info-file-item, "OS_NAME", "$(REQUIRED_OS_NAME)") - $(call info-file-item, "OS_VERSION", "$(REQUIRED_OS_VERSION)") - $(call info-file-item, "OS_ARCH", "$(OPENJDK_TARGET_CPU_LEGACY)") $(if $(JDK_ARCH_ABI_PROP_NAME), \ $(call info-file-item, "SUN_ARCH_ABI", "$(JDK_ARCH_ABI_PROP_NAME)")) $(call info-file-item, "SOURCE", "$(strip $(ALL_SOURCE_TIPS))") From 83dbcb5c1b79ef6b5fd1172805302af3d313ee8a Mon Sep 17 00:00:00 2001 From: Srikanth Adayapalam Date: Wed, 14 Sep 2016 20:00:20 +0530 Subject: [PATCH 085/110] 8160699: java.lang.VerifyError: Inconsistent stackmap frames at branch target Ensure out of scope locals are not treated as being alive Reviewed-by: mcimadamore --- .../classes/com/sun/tools/javac/jvm/Gen.java | 2 +- .../test/tools/javac/SwitchExitStateTest.java | 49 +++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 langtools/test/tools/javac/SwitchExitStateTest.java diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java index 6f479f26a8c..216f141873c 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java @@ -1232,7 +1232,7 @@ public class Gen extends JCTree.Visitor { Chain exit = switchEnv.info.exit; if (exit != null) { code.resolve(exit); - exit.state.defined.excludeFrom(code.nextreg); + exit.state.defined.excludeFrom(limit); } // If we have not set the default offset, we do so now. diff --git a/langtools/test/tools/javac/SwitchExitStateTest.java b/langtools/test/tools/javac/SwitchExitStateTest.java new file mode 100644 index 00000000000..4b9e0d61e07 --- /dev/null +++ b/langtools/test/tools/javac/SwitchExitStateTest.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8160699 + * @summary Verify that having finished executing a switch statement live locals are exactly the same as it was upon entry of the switch. + * @run main SwitchExitStateTest + */ + +public class SwitchExitStateTest { + public static void main(String[] args) throws Exception { + switch (0) { + case 0: + String a = ""; + break; + default: + throw new Exception("Unknown "); + } + + switch (0) { + case 0: + String b = ""; + break; + default: + throw new Exception("Unknown "); + } + } +} \ No newline at end of file From 89585eae4104998fbead2be446d002ba1ee13c15 Mon Sep 17 00:00:00 2001 From: Joe Wang Date: Wed, 14 Sep 2016 13:18:17 -0700 Subject: [PATCH 086/110] 8165784: Deprecate the internal Catalog API in JDK 9 Reviewed-by: dfuchs, rriggs --- .../xerces/internal/util/XMLCatalogResolver.java | 10 ++++++++++ .../sun/org/apache/xml/internal/resolver/Catalog.java | 9 +++++++++ .../apache/xml/internal/resolver/CatalogManager.java | 10 +++++++++- .../sun/org/apache/xml/internal/resolver/Resolver.java | 9 +++++++++ .../xml/internal/resolver/tools/CatalogResolver.java | 9 +++++++++ 5 files changed, 46 insertions(+), 1 deletion(-) diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/XMLCatalogResolver.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/XMLCatalogResolver.java index 627cbf47003..c488a9fa63e 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/XMLCatalogResolver.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/XMLCatalogResolver.java @@ -61,9 +61,19 @@ import com.sun.org.apache.xml.internal.resolver.readers.SAXCatalogReader; * catalog resolution outside of a parsing context. It may be shared * between several parsers and the application.

* + * @deprecated This class and the JDK internal Catalog API in package + * {@code com.sun.org.apache.xml.internal.resolver} + * is encapsulated in JDK 9. The entire implementation under the package is now + * deprecated and subject to removal in a future release. Users of the API should + * migrate to the {@linkplain javax.xml.catalog new public API}. + *

+ * The new Catalog API is supported throughout the JDK XML Processors, which allows + * the use of Catalog by simply setting a path to a Catalog file as a property. + * * @author Michael Glavassevich, IBM * */ +@Deprecated(since="9", forRemoval=true) public class XMLCatalogResolver implements XMLEntityResolver, EntityResolver2, LSResourceResolver { diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/Catalog.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/Catalog.java index 337dc96fe64..574049f45e2 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/Catalog.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/Catalog.java @@ -178,6 +178,14 @@ import javax.xml.parsers.SAXParserFactory; * * @see CatalogReader * @see CatalogEntry + * @deprecated The JDK internal Catalog API in package + * {@code com.sun.org.apache.xml.internal.resolver} + * is encapsulated in JDK 9. The entire implementation under the package is now + * deprecated and subject to removal in a future release. Users of the API + * should migrate to the {@linkplain javax.xml.catalog new public API}. + *

+ * The new Catalog API is supported throughout the JDK XML Processors, which allows + * the use of Catalog by simply setting a path to a Catalog file as a property. * * @author Norman Walsh * Norman.Walsh@Sun.COM @@ -187,6 +195,7 @@ import javax.xml.parsers.SAXParserFactory; *

Derived from public domain code originally published by Arbortext, * Inc.

*/ +@Deprecated(since="9", forRemoval=true) public class Catalog { /** The BASE Catalog Entry type. */ public static final int BASE = CatalogEntry.addEntryType("BASE", 1); diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/CatalogManager.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/CatalogManager.java index b5fccbf04aa..605735cf1a9 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/CatalogManager.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/CatalogManager.java @@ -110,13 +110,21 @@ import sun.reflect.misc.ReflectUtil; * * * @see Catalog + * @deprecated The JDK internal Catalog API in package + * {@code com.sun.org.apache.xml.internal.resolver} + * is encapsulated in JDK 9. The entire implementation under the package is now + * deprecated and subject to removal in a future release. Users of the API + * should migrate to the {@linkplain javax.xml.catalog new public API}. + *

+ * The new Catalog API is supported throughout the JDK XML Processors, which allows + * the use of Catalog by simply setting a path to a Catalog file as a property. * * @author Norman Walsh * Norman.Walsh@Sun.COM * * @version 1.0 */ - +@Deprecated(since="9", forRemoval=true) public class CatalogManager { private static final String pFiles = "xml.catalog.files"; private static final String pVerbosity = "xml.catalog.verbosity"; diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/Resolver.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/Resolver.java index d566895ccce..d50a4c262b2 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/Resolver.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/Resolver.java @@ -37,12 +37,21 @@ import com.sun.org.apache.xml.internal.resolver.readers.TR9401CatalogReader; * suffix-based matching and an external RFC2483 resolver. * * @see Catalog + * @deprecated The JDK internal Catalog API in package + * {@code com.sun.org.apache.xml.internal.resolver} + * is encapsulated in JDK 9. The entire implementation under the package is now + * deprecated and subject to removal in a future release. Users of the API + * should migrate to the {@linkplain javax.xml.catalog new public API}. + *

+ * The new Catalog API is supported throughout the JDK XML Processors, which allows + * the use of Catalog by simply setting a path to a Catalog file as a property. * * @author Norman Walsh * Norman.Walsh@Sun.COM * * @version 1.0 */ +@Deprecated(since="9", forRemoval=true) public class Resolver extends Catalog { /** * The URISUFFIX Catalog Entry type. diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/tools/CatalogResolver.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/tools/CatalogResolver.java index bf82547188b..10e49e7f247 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/tools/CatalogResolver.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/tools/CatalogResolver.java @@ -52,12 +52,21 @@ import com.sun.org.apache.xml.internal.resolver.helpers.FileURL; * @see Catalog * @see org.xml.sax.EntityResolver * @see javax.xml.transform.URIResolver + * @deprecated The JDK internal Catalog API in package + * {@code com.sun.org.apache.xml.internal.resolver} + * is encapsulated in JDK 9. The entire implementation under the package is now + * deprecated and subject to removal in a future release. Users of the API + * should migrate to the {@linkplain javax.xml.catalog new public API}. + *

+ * The new Catalog API is supported throughout the JDK XML Processors, which allows + * the use of Catalog by simply setting a path to a Catalog file as a property. * * @author Norman Walsh * Norman.Walsh@Sun.COM * * @version 1.0 */ +@Deprecated(since="9", forRemoval=true) public class CatalogResolver implements EntityResolver, URIResolver { /** Make the parser Namespace aware? */ public boolean namespaceAware = true; From 6aaba1c4aca5694f0af377526765eb078b279fff Mon Sep 17 00:00:00 2001 From: Phil Race Date: Wed, 14 Sep 2016 15:29:23 -0700 Subject: [PATCH 087/110] 8166068: test/java/awt/font/GlyphVector/GetGlyphCharIndexTest.java does not compile Reviewed-by: ddehaven, yan --- jdk/test/java/awt/font/GlyphVector/GetGlyphCharIndexTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/test/java/awt/font/GlyphVector/GetGlyphCharIndexTest.java b/jdk/test/java/awt/font/GlyphVector/GetGlyphCharIndexTest.java index 1754e5f64cc..6ec6a257ae8 100644 --- a/jdk/test/java/awt/font/GlyphVector/GetGlyphCharIndexTest.java +++ b/jdk/test/java/awt/font/GlyphVector/GetGlyphCharIndexTest.java @@ -24,7 +24,7 @@ /* @test * @summary Test getGlyphCharIndex() results from layout * @bug 8152680 - * + */ import java.awt.Font; import java.awt.font.FontRenderContext; From bc3449ccbe4b177146659587cad25e73eee15b60 Mon Sep 17 00:00:00 2001 From: Henry Jen Date: Fri, 16 Sep 2016 10:57:02 -0700 Subject: [PATCH 088/110] 8042148: Ensure that the java launcher help is consistent with the manpage where they report common information Reviewed-by: ksrini --- .../launcher/resources/launcher.properties | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties b/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties index 23fcac28865..b68e6a6a448 100644 --- a/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties +++ b/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties @@ -103,34 +103,42 @@ See http://www.oracle.com/technetwork/java/javase/documentation/index.html for m # Translators please note do not translate the options themselves java.launcher.X.usage=\ -\ -Xmixed mixed mode execution (default)\n\ -\ -Xint interpreted mode execution only\n\ +\ -Xbatch disable background compilation\n\ \ -Xbootclasspath/a:\n\ \ append to end of bootstrap class path\n\ +\ -Xcheck:jni perform additional checks for JNI functions\n\ +\ -Xcomp forces compilation of methods on first invocation\n\ +\ -Xdebug provided for backward compatibility\n\ \ -Xdiag show additional diagnostic messages\n\ \ -Xdiag:resolver show resolver diagnostic messages\n\ -\ -Xnoclassgc disable class garbage collection\n\ +\ -Xdisable-@files disable further argument file expansion\n\ +\ -Xfuture enable strictest checks, anticipating future default\n\ +\ -Xint interpreted mode execution only\n\ +\ -Xinternalversion\n\ +\ displays more detailed JVM version information than the\n\ +\ -version option\n\ \ -Xloggc: log GC status to a file with time stamps\n\ -\ -Xbatch disable background compilation\n\ +\ -Xmixed mixed mode execution (default)\n\ +\ -Xmn sets the initial and maximum size (in bytes) of the heap\n\ +\ for the young generation (nursery)\n\ \ -Xms set initial Java heap size\n\ \ -Xmx set maximum Java heap size\n\ -\ -Xss set java thread stack size\n\ +\ -Xnoclassgc disable class garbage collection\n\ \ -Xprof output cpu profiling data\n\ -\ -Xfuture enable strictest checks, anticipating future default\n\ \ -Xrs reduce use of OS signals by Java/VM (see documentation)\n\ -\ -Xcheck:jni perform additional checks for JNI functions\n\ -\ -Xshare:off do not attempt to use shared class data\n\ \ -Xshare:auto use shared class data if possible (default)\n\ +\ -Xshare:off do not attempt to use shared class data\n\ \ -Xshare:on require using shared class data, otherwise fail.\n\ \ -XshowSettings show all settings and continue\n\ \ -XshowSettings:all\n\ \ show all settings and continue\n\ -\ -XshowSettings:vm show all vm related settings and continue\n\ -\ -XshowSettings:properties\n\ -\ show all property settings and continue\n\ \ -XshowSettings:locale\n\ \ show all locale related settings and continue\n\ -\ -Xdisable-@files disable further argument file expansion\n\ +\ -XshowSettings:properties\n\ +\ show all property settings and continue\n\ +\ -XshowSettings:vm show all vm related settings and continue\n\ +\ -Xss set java thread stack size\n\ +\ -Xverify sets the mode of the bytecode verifier\n\ \ --add-reads =(,)*\n\ \ updates to read , regardless\n\ \ of module declaration. \n\ From 1a710e37d290af9907b9ccd83f26b3901661e80a Mon Sep 17 00:00:00 2001 From: Sergei Kovalev Date: Thu, 15 Sep 2016 16:28:26 +0300 Subject: [PATCH 089/110] 8166126: Missing dependecies on jdk.zipfs module for jdk/nio/zipfs/jarfs/JFSTester.java Reviewed-by: alanb --- jdk/test/jdk/nio/zipfs/jarfs/JFSTester.java | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/test/jdk/nio/zipfs/jarfs/JFSTester.java b/jdk/test/jdk/nio/zipfs/jarfs/JFSTester.java index 881e27dbd4f..78a663f7a7f 100644 --- a/jdk/test/jdk/nio/zipfs/jarfs/JFSTester.java +++ b/jdk/test/jdk/nio/zipfs/jarfs/JFSTester.java @@ -26,6 +26,7 @@ * @bug 8164389 * @summary walk entries in a jdk.nio.zipfs.JarFileSystem * @modules jdk.jartool/sun.tools.jar + * jdk.zipfs * @run testng JFSTester */ From f5e259928f1dec8575d27387c36ba614095a0b9a Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 15 Sep 2016 17:15:51 +0000 Subject: [PATCH 090/110] Added tag jdk-9+136 for changeset eecdf7525f79 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index c9694066072..e540680549f 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -378,3 +378,4 @@ a24702d4d5ab0015a5c553ed57f66fce7d85155e jdk-9+132 be1218f792a450dfb5d4b1f82616b9d95a6a732e jdk-9+133 065724348690eda41fc69112278d8da6dcde548c jdk-9+134 82b94cb5f342319d2cda77f9fa59703ad7fde576 jdk-9+135 +3ec350f5f32af249b59620d7e37b54bdcd77b233 jdk-9+136 From 35bb5b0369fe36d06d2b8c4e2edca5b651bdf2fd Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 15 Sep 2016 17:15:52 +0000 Subject: [PATCH 091/110] Added tag jdk-9+136 for changeset 36d7560ae09e --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index a52c2a2a2da..d842722fa52 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -538,3 +538,4 @@ e96b34b76d863ed1fa04e0eeb3f297ac17b490fd jdk-9+129 a25e0fb6033245ab075136e744d362ce765464cd jdk-9+133 b8b694c6b4d2ab0939aed7adaf0eec1ac321a085 jdk-9+134 3b1c4562953db47e36b237a500f368d5c9746d47 jdk-9+135 +a20da289f646ee44440695b81abc0548330e4ca7 jdk-9+136 From 442a201043dfad412a74edafb93dfebb595fe441 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 15 Sep 2016 17:15:52 +0000 Subject: [PATCH 092/110] Added tag jdk-9+136 for changeset 15d3983aba7a --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index 3b09618de85..e8dba874e9c 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -378,3 +378,4 @@ f7e1d5337c2e550fe553df7a3886bbed80292ecd jdk-9+131 2021bfedf1c478a4808a7711a6090682a12f4c0e jdk-9+133 1a497f5ca0cfd88115cc7daa8af8a62b8741caf2 jdk-9+134 094d0db606db976045f594dba47d4593b715cc81 jdk-9+135 +aa053a3faf266c12b4fd5272da431a3e08e4a3e3 jdk-9+136 From 0ff1230d99f1b3cde885bc7347b160fea93e00c4 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 15 Sep 2016 17:15:53 +0000 Subject: [PATCH 093/110] Added tag jdk-9+136 for changeset 73d7888a4878 --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 19adf3a8769..fa7e108ef76 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -378,3 +378,4 @@ e66cdc2de6b02443911d386fc9217b0d824d0686 jdk-9+130 9490ba2e5e41685c858a0ca2a6ec87611eb011c6 jdk-9+133 1c6c21d87aa459d82425e1fddc9ce8647aebde34 jdk-9+134 f695240370c77a25fed88225a392e7d530cb4d78 jdk-9+135 +f1eafcb0eb7182b937bc93f214d8cabd01ec4d59 jdk-9+136 From a442ce45f0b5138bc50e932a357bc9215ca10e8b Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 15 Sep 2016 17:15:53 +0000 Subject: [PATCH 094/110] Added tag jdk-9+136 for changeset ef1dfab6d082 --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 0217f716612..8fceda6eb06 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -381,3 +381,4 @@ fe4e11bd2423635dc0f5f5cb9a64eb2f2cce7f4c jdk-9+128 05e99eefda2b58d1ed176e411302d9d6b35dca16 jdk-9+133 ab1d78d395d4cb8be426ff181211da1a4085cf01 jdk-9+134 22631824f55128a7ab6605493b3001a37af6a168 jdk-9+135 +09ec13a99f50a4a346180d1e3b0fd8bc1ee399ce jdk-9+136 From db89d07f3888b965d2cbae067b15c8fd8dc0fea0 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 15 Sep 2016 17:15:55 +0000 Subject: [PATCH 095/110] Added tag jdk-9+136 for changeset 1cba2e436777 --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index cddf72d74e6..c5fe36cee08 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -378,3 +378,4 @@ aebfafc43714d5a27d5064d8a0011eaccde633cf jdk-9+131 7efa4b3477b2b93edbdb4abf827b74c6391f056e jdk-9+133 f08683786207a48b652266b3b7b908e6c863c3fc jdk-9+134 af5eb8f3ffd21288305a54ea177ffad75021a741 jdk-9+135 +c8f02f0ecbd7cd6700f47416e4b7e9d5ec20ad77 jdk-9+136 From 65394c3b90538da3f53b57312d4336a5efcaaef7 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 15 Sep 2016 17:15:55 +0000 Subject: [PATCH 096/110] Added tag jdk-9+136 for changeset 52b1009d3c64 --- nashorn/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/nashorn/.hgtags b/nashorn/.hgtags index afea5d568b8..26b80a32770 100644 --- a/nashorn/.hgtags +++ b/nashorn/.hgtags @@ -369,3 +369,4 @@ ee77c6b3713ab293e027ac3ea1cc16f86dac535f jdk-9+131 3a924b820d02b108cf57b51e145b5150d1eedcca jdk-9+133 e05400ba935753c77697af936db24657eb811022 jdk-9+134 cb00d5ef023a18a66fcb4311ed4474d4145c66e9 jdk-9+135 +f11b8f5c4ccbf9c87d283815abac6c0117fba3c0 jdk-9+136 From eb56700ebac510d6b1e3b4372d9bac72a7a3a931 Mon Sep 17 00:00:00 2001 From: Dan Smith Date: Fri, 16 Sep 2016 11:58:23 -0600 Subject: [PATCH 097/110] 8138822: Source version error missing version number Reviewed-by: jjg --- .../com/sun/tools/javac/comp/Annotate.java | 4 +++- .../repeatingAnnotations/WrongVersion.java | 23 +++++++++++++++++++ .../repeatingAnnotations/WrongVersion6.out | 2 ++ .../repeatingAnnotations/WrongVersion7.out | 2 ++ 4 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 langtools/test/tools/javac/annotations/repeatingAnnotations/WrongVersion.java create mode 100644 langtools/test/tools/javac/annotations/repeatingAnnotations/WrongVersion6.out create mode 100644 langtools/test/tools/javac/annotations/repeatingAnnotations/WrongVersion7.out diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java index e3d97b68752..bf43a6e5ad4 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java @@ -92,6 +92,7 @@ public class Annotate { private final Attribute theUnfinishedDefaultValue; private final boolean allowRepeatedAnnos; + private final String sourceName; protected Annotate(Context context) { context.put(annotateKey, this); @@ -114,6 +115,7 @@ public class Annotate { Source source = Source.instance(context); allowRepeatedAnnos = source.allowRepeatedAnnotations(); + sourceName = source.name; } /** Semaphore to delay annotation processing */ @@ -322,7 +324,7 @@ public class Annotate { if (annotated.containsKey(a.type.tsym)) { if (!allowRepeatedAnnos) { - log.error(DiagnosticFlag.SOURCE_LEVEL, a.pos(), "repeatable.annotations.not.supported.in.source"); + log.error(DiagnosticFlag.SOURCE_LEVEL, a.pos(), "repeatable.annotations.not.supported.in.source", sourceName); } ListBuffer l = annotated.get(a.type.tsym); l = l.append(c); diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongVersion.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongVersion.java new file mode 100644 index 00000000000..8b6efaade02 --- /dev/null +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongVersion.java @@ -0,0 +1,23 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8138822 + * @summary test that only Java 8+ allows repeating annotations + * @compile WrongVersion.java + * @compile -Xlint:-options -source 8 WrongVersion.java + * @compile/fail/ref=WrongVersion7.out -XDrawDiagnostics -Xlint:-options -source 7 WrongVersion.java + * @compile/fail/ref=WrongVersion6.out -XDrawDiagnostics -Xlint:-options -source 6 WrongVersion.java + */ +import java.lang.annotation.Repeatable; + +@Ann(1) @Ann(2) +class C { +} + +@Repeatable(AnnContainer.class) +@interface Ann { + int value(); +} + +@interface AnnContainer { + Ann[] value(); +} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongVersion6.out b/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongVersion6.out new file mode 100644 index 00000000000..6b6237b9d39 --- /dev/null +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongVersion6.out @@ -0,0 +1,2 @@ +WrongVersion.java:12:9: compiler.err.repeatable.annotations.not.supported.in.source: 1.6 +1 error diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongVersion7.out b/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongVersion7.out new file mode 100644 index 00000000000..fd649e00067 --- /dev/null +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongVersion7.out @@ -0,0 +1,2 @@ +WrongVersion.java:12:9: compiler.err.repeatable.annotations.not.supported.in.source: 1.7 +1 error From f4abd474cc927ca3c97f0d28156782370d55c748 Mon Sep 17 00:00:00 2001 From: Bhavesh Patel Date: Fri, 16 Sep 2016 12:17:44 -0700 Subject: [PATCH 098/110] 8166176: module search generates URLs with extra '/' Reviewed-by: jjg --- .../internal/doclets/formats/html/resources/search.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/search.js b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/search.js index 965a9914055..ada2c64cba2 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/search.js +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/search.js @@ -263,18 +263,18 @@ $(function() { if (ui.item.l !== noResult.l) { var url = ""; if (ui.item.category === catModules) { - url = "/" + ui.item.l + "-summary.html"; + url = ui.item.l + "-summary.html"; } else if (ui.item.category === catPackages) { url = ui.item.l.replace(/\./g, '/') + "/package-summary.html"; } else if (ui.item.category === catTypes) { if (ui.item.p === "") { - url = "/" + ui.item.l + ".html"; + url = ui.item.l + ".html"; } else { url = ui.item.p.replace(/\./g, '/') + "/" + ui.item.l + ".html"; } } else if (ui.item.category === catMembers) { if (ui.item.p === "") { - url = "/" + ui.item.c + ".html" + "#"; + url = ui.item.c + ".html" + "#"; } else { url = ui.item.p.replace(/\./g, '/') + "/" + ui.item.c + ".html" + "#"; } From f9d0a85678ea7e37dc918fafd77d809a09b4c9bc Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Sat, 17 Sep 2016 16:37:52 -0700 Subject: [PATCH 099/110] 8166237: jdk.jdi missing requires jdk.jdwp.agent Reviewed-by: alanb --- jdk/src/jdk.jdi/share/classes/module-info.java | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/src/jdk.jdi/share/classes/module-info.java b/jdk/src/jdk.jdi/share/classes/module-info.java index 668c5b57c7e..14e621c108b 100644 --- a/jdk/src/jdk.jdi/share/classes/module-info.java +++ b/jdk/src/jdk.jdi/share/classes/module-info.java @@ -25,6 +25,7 @@ module jdk.jdi { requires jdk.attach; + requires jdk.jdwp.agent; exports com.sun.jdi; exports com.sun.jdi.connect; From 14d689c4a69f7c4c1588b5aae3e1c23109260064 Mon Sep 17 00:00:00 2001 From: Nishit Jain Date: Sun, 18 Sep 2016 23:09:37 +0900 Subject: [PATCH 100/110] 8165984: ResourceBundle lookup fields not completely thread-safe Reviewed-by: okutsu, naoto --- .../share/classes/java/util/ListResourceBundle.java | 4 ++-- .../share/classes/java/util/PropertyResourceBundle.java | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/ListResourceBundle.java b/jdk/src/java.base/share/classes/java/util/ListResourceBundle.java index 860953fc271..4c4498e1b6b 100644 --- a/jdk/src/java.base/share/classes/java/util/ListResourceBundle.java +++ b/jdk/src/java.base/share/classes/java/util/ListResourceBundle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, 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 @@ -206,5 +206,5 @@ public abstract class ListResourceBundle extends ResourceBundle { lookup = temp; } - private Map lookup = null; + private volatile Map lookup = null; } diff --git a/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java b/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java index 3a481035c92..502b6a4bc79 100644 --- a/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java +++ b/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,8 +46,6 @@ import java.io.IOException; import java.nio.charset.MalformedInputException; import java.nio.charset.StandardCharsets; import java.nio.charset.UnmappableCharacterException; -import java.security.AccessController; -import java.util.Locale; import sun.security.action.GetPropertyAction; import sun.util.PropertyResourceBundleCharset; import sun.util.ResourceBundleEnumeration; @@ -236,5 +234,5 @@ public class PropertyResourceBundle extends ResourceBundle { // ==================privates==================== - private Map lookup; + private final Map lookup; } From ac462ed848d2b7c6eef2aabb5b6e74b747130d2f Mon Sep 17 00:00:00 2001 From: Srikanth Adayapalam Date: Mon, 19 Sep 2016 05:31:53 +0530 Subject: [PATCH 101/110] 8164742: ServiceConfigurationError on invoke of getServiceLoader method of StandardJavaFileManager Reviewed-by: jlahoda --- .../tools/crules/MutableFieldsAnalyzer.java | 4 +- .../tools/javac/file/JavacFileManager.java | 2 + .../JavacProcessingEnvironment.java | 6 +- .../sun/tools/javac/util/JDK9Wrappers.java | 79 +++++++++++++++ .../sun/tools/javac/util/ModuleHelper.java | 96 ++++--------------- .../T8003967/DetectMutableStaticFields.java | 4 +- .../FileManagerGetServiceLoaderTest.java | 50 ++++++++++ 7 files changed, 157 insertions(+), 84 deletions(-) create mode 100644 langtools/test/tools/javac/modules/FileManagerGetServiceLoaderTest.java diff --git a/langtools/make/tools/crules/MutableFieldsAnalyzer.java b/langtools/make/tools/crules/MutableFieldsAnalyzer.java index 538f7827dfa..0b082aca0ba 100644 --- a/langtools/make/tools/crules/MutableFieldsAnalyzer.java +++ b/langtools/make/tools/crules/MutableFieldsAnalyzer.java @@ -105,12 +105,12 @@ public class MutableFieldsAnalyzer extends AbstractCodingRulesAnalyzer { "configurationClass", "resolveRequiresAndUsesMethod"); ignoreFields("com.sun.tools.javac.util.JDK9Wrappers$Layer", "layerClass", "bootMethod", "defineModulesWithOneLoaderMethod", "configurationMethod"); + ignoreFields("com.sun.tools.javac.util.JDK9Wrappers$Module", + "addExportsMethod", "addUsesMethod", "getModuleMethod", "getUnnamedModuleMethod"); ignoreFields("com.sun.tools.javac.util.JDK9Wrappers$ServiceLoaderHelper", "loadMethod"); ignoreFields("com.sun.tools.javac.util.JDK9Wrappers$VMHelper", "vmClass", "getRuntimeArgumentsMethod"); - ignoreFields("com.sun.tools.javac.util.ModuleHelper", - "addExportsMethod", "getUnnamedModuleMethod", "getModuleMethod"); } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java index 4e3f4d78126..6a667bc7f3d 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java @@ -78,6 +78,7 @@ import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.JDK9Wrappers.Configuration; import com.sun.tools.javac.util.JDK9Wrappers.Layer; import com.sun.tools.javac.util.JDK9Wrappers.ModuleFinder; +import com.sun.tools.javac.util.JDK9Wrappers.Module; import com.sun.tools.javac.util.JDK9Wrappers.ServiceLoaderHelper; import static java.nio.file.FileVisitOption.FOLLOW_LINKS; @@ -957,6 +958,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil public ServiceLoader getServiceLoader(Location location, Class service) throws IOException { nullCheck(location); nullCheck(service); + Module.getModule(getClass()).addUses(service); if (location.isModuleLocation()) { Collection paths = locations.getLocation(location); ModuleFinder finder = ModuleFinder.of(paths.toArray(new Path[paths.size()])); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java index 431d5b09ec6..ce066f83a39 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java @@ -79,6 +79,7 @@ import com.sun.tools.javac.util.DefinedBy; import com.sun.tools.javac.util.DefinedBy.Api; import com.sun.tools.javac.util.Iterators; import com.sun.tools.javac.util.JCDiagnostic; +import com.sun.tools.javac.util.JDK9Wrappers.Module; import com.sun.tools.javac.util.JavacMessages; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.Log; @@ -119,7 +120,6 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea private final JavacTypes typeUtils; private final JavaCompiler compiler; private final Modules modules; - private final ModuleHelper moduleHelper; private final Types types; /** @@ -227,7 +227,6 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea enter = Enter.instance(context); initialCompleter = ClassFinder.instance(context).getCompleter(); chk = Check.instance(context); - moduleHelper = ModuleHelper.instance(context); initProcessorLoader(); defaultModule = source.allowModules() && options.isUnset("noModules") @@ -265,7 +264,8 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea ? fileManager.getClassLoader(ANNOTATION_PROCESSOR_PATH) : fileManager.getClassLoader(CLASS_PATH); - moduleHelper.addExports(processorClassLoader); + if (options.isSet("accessInternalAPI")) + ModuleHelper.addExports(Module.getModule(getClass()), Module.getUnnamedModule(processorClassLoader)); if (processorClassLoader != null && processorClassLoader instanceof Closeable) { compiler.closeables = compiler.closeables.prepend((Closeable) processorClassLoader); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/JDK9Wrappers.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/JDK9Wrappers.java index b933ee4b33a..8f3875ae63c 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/JDK9Wrappers.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/JDK9Wrappers.java @@ -129,6 +129,85 @@ public class JDK9Wrappers { } } + /** + * Wrapper class for java.lang.reflect.Module. To materialize a handle use the static factory + * methods Module#getModule(Class) or Module#getUnnamedModule(ClassLoader). + */ + public static class Module { + + private final Object theRealModule; + + private Module(Object module) { + this.theRealModule = module; + init(); + } + + public static Module getModule(Class clazz) { + try { + init(); + Object result = getModuleMethod.invoke(clazz, new Object[0]); + return new Module(result); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException + | SecurityException ex) { + throw new Abort(ex); + } + } + + public static Module getUnnamedModule(ClassLoader classLoader) { + try { + init(); + Object result = getUnnamedModuleMethod.invoke(classLoader, new Object[0]); + return new Module(result); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException + | SecurityException ex) { + throw new Abort(ex); + } + } + + public Module addExports(String pn, Module other) { + try { + addExportsMethod.invoke(theRealModule, new Object[] { pn, other.theRealModule}); + } catch (IllegalAccessException | InvocationTargetException ex) { + throw new Abort(ex); + } + return this; + } + + public Module addUses(Class st) { + try { + addUsesMethod.invoke(theRealModule, new Object[] { st }); + } catch (IllegalAccessException | InvocationTargetException ex) { + throw new Abort(ex); + } + return this; + } + + // ----------------------------------------------------------------------------------------- + // on java.lang.reflect.Module + private static Method addExportsMethod = null; + // on java.lang.reflect.Module + private static Method addUsesMethod = null; + // on java.lang.Class + private static Method getModuleMethod; + // on java.lang.ClassLoader + private static Method getUnnamedModuleMethod; + + private static void init() { + if (addExportsMethod == null) { + try { + Class moduleClass = Class.forName("java.lang.reflect.Module", false, null); + addUsesMethod = moduleClass.getDeclaredMethod("addUses", new Class[] { Class.class }); + addExportsMethod = moduleClass.getDeclaredMethod("addExports", + new Class[] { String.class, moduleClass }); + getModuleMethod = Class.class.getDeclaredMethod("getModule", new Class[0]); + getUnnamedModuleMethod = ClassLoader.class.getDeclaredMethod("getUnnamedModule", new Class[0]); + } catch (ClassNotFoundException | NoSuchMethodException | SecurityException ex) { + throw new Abort(ex); + } + } + } + } + /** * Wrapper class for java.lang.module.Configuration. */ diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ModuleHelper.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ModuleHelper.java index 2b34d095d02..dd0315e837c 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ModuleHelper.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ModuleHelper.java @@ -25,88 +25,30 @@ package com.sun.tools.javac.util; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; +import com.sun.tools.javac.util.JDK9Wrappers.Module; public class ModuleHelper { - /** The context key for the module helper. */ - protected static final Context.Key moduleHelperKey = new Context.Key<>(); - /** Get the JavaCompiler instance for this context. */ - public static ModuleHelper instance(Context context) { - ModuleHelper instance = context.get(moduleHelperKey); - if (instance == null) - instance = new ModuleHelper(context); - return instance; - } + private static final String[] javacInternalPackages = new String[] { + "com.sun.tools.javac.api", + "com.sun.tools.javac.code", + "com.sun.tools.javac.comp", + "com.sun.tools.javac.file", + "com.sun.tools.javac.jvm", + "com.sun.tools.javac.main", + "com.sun.tools.javac.model", + "com.sun.tools.javac.parser", + "com.sun.tools.javac.platform", + "com.sun.tools.javac.processing", + "com.sun.tools.javac.tree", + "com.sun.tools.javac.util", - public ModuleHelper(Context context) { - context.put(moduleHelperKey, this); - Options options = Options.instance(context); - allowAccessToInternalAPI = options.isSet("accessInternalAPI"); - } - - final boolean allowAccessToInternalAPI; - - private void exportPackageToModule(String packageName, Object target) - throws ClassNotFoundException, NoSuchMethodException, IllegalArgumentException, - InvocationTargetException, IllegalAccessException { - if (addExportsMethod == null) { - Class moduleClass = Class.forName("java.lang.reflect.Module"); - addExportsMethod = moduleClass.getDeclaredMethod("addExports", - new Class[] { String.class, moduleClass }); - } - addExportsMethod.invoke(from, new Object[] { packageName, target }); - } - - static final String[] javacInternalPackages = new String[] { - "com.sun.tools.javac.api", - "com.sun.tools.javac.code", - "com.sun.tools.javac.comp", - "com.sun.tools.javac.file", - "com.sun.tools.javac.jvm", - "com.sun.tools.javac.main", - "com.sun.tools.javac.model", - "com.sun.tools.javac.parser", - "com.sun.tools.javac.platform", - "com.sun.tools.javac.processing", - "com.sun.tools.javac.tree", - "com.sun.tools.javac.util", - - "com.sun.tools.doclint", + "com.sun.tools.doclint", }; - public void addExports(ClassLoader classLoader) { - try { - if (allowAccessToInternalAPI) { - if (from == null) { - if (getModuleMethod == null) { - getModuleMethod = Class.class.getDeclaredMethod("getModule", new Class[0]); - } - from = getModuleMethod.invoke(getClass(), new Object[0]); - } - if (getUnnamedModuleMethod == null) { - getUnnamedModuleMethod = ClassLoader.class.getDeclaredMethod("getUnnamedModule", new Class[0]); - } - Object target = getUnnamedModuleMethod.invoke(classLoader, new Object[0]); - for (String pack: javacInternalPackages) { - exportPackageToModule(pack, target); - } - } - } catch (Exception e) { - // do nothing + public static void addExports(Module from, Module to) { + for (String pack: javacInternalPackages) { + from.addExports(pack, to); } } - - // a module instance - private Object from = null; - - // on java.lang.reflect.Module - private static Method addExportsMethod = null; - - // on java.lang.ClassLoader - private static Method getUnnamedModuleMethod = null; - - // on java.lang.Class - private static Method getModuleMethod = null; -} +} \ No newline at end of file diff --git a/langtools/test/tools/javac/T8003967/DetectMutableStaticFields.java b/langtools/test/tools/javac/T8003967/DetectMutableStaticFields.java index a80877ed10d..82cff7badab 100644 --- a/langtools/test/tools/javac/T8003967/DetectMutableStaticFields.java +++ b/langtools/test/tools/javac/T8003967/DetectMutableStaticFields.java @@ -106,12 +106,12 @@ public class DetectMutableStaticFields { // The following static fields are used for caches of information obtained // by reflective lookup, to avoid explicit references that are not available // when running javac on JDK 8. - ignore("com/sun/tools/javac/util/ModuleHelper", - "addExportsMethod", "getModuleMethod", "getUnnamedModuleMethod"); ignore("com/sun/tools/javac/util/JDK9Wrappers$Configuration", "resolveRequiresAndUsesMethod", "configurationClass"); ignore("com/sun/tools/javac/util/JDK9Wrappers$Layer", "bootMethod", "defineModulesWithOneLoaderMethod", "configurationMethod", "layerClass"); + ignore("com/sun/tools/javac/util/JDK9Wrappers$Module", + "addExportsMethod", "addUsesMethod", "getModuleMethod", "getUnnamedModuleMethod"); ignore("com/sun/tools/javac/util/JDK9Wrappers$ModuleFinder", "moduleFinderClass", "ofMethod"); ignore("com/sun/tools/javac/util/JDK9Wrappers$ServiceLoaderHelper", diff --git a/langtools/test/tools/javac/modules/FileManagerGetServiceLoaderTest.java b/langtools/test/tools/javac/modules/FileManagerGetServiceLoaderTest.java new file mode 100644 index 00000000000..83288987f27 --- /dev/null +++ b/langtools/test/tools/javac/modules/FileManagerGetServiceLoaderTest.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8164742 + * @summary Test that jdk.compiler can materialize a service loader for arbitrary services + * @run main FileManagerGetServiceLoaderTest + */ + +import javax.tools.*; + +public class FileManagerGetServiceLoaderTest { + + public static void main(String... args) throws Exception { + + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null); + + /* FileManagerGetServiceLoaderTest.class is not really a service, but that is + immaterial to the test which just verifies addUses would have been called + so module boundary is not an issue for a class outside of jdk.compiler + */ + java.util.ServiceLoader loader = fm.getServiceLoader(StandardLocation.CLASS_PATH, + FileManagerGetServiceLoaderTest.class); + if (loader == null) { + throw new AssertionError("Could not obtain service loader"); + } + } +} From b32db3c78f95e0cc27773a8dc8dbab5f5aea82fb Mon Sep 17 00:00:00 2001 From: Joe Wang Date: Mon, 19 Sep 2016 14:21:15 -0700 Subject: [PATCH 102/110] 8166220: Catalog API: JAXP XML Processor Support - add StAX test coverage Reviewed-by: lancea --- .../jaxp/unittest/catalog/CatalogSupport.java | 34 ++++++-- .../unittest/catalog/CatalogSupport1.java | 31 +++++-- .../unittest/catalog/CatalogSupport2.java | 28 ++++++- .../unittest/catalog/CatalogSupport3.java | 28 ++++++- .../unittest/catalog/CatalogSupport4.java | 33 ++++++-- .../unittest/catalog/CatalogSupport5.java | 29 ++++++- .../unittest/catalog/CatalogSupportBase.java | 83 ++++++++++++++++--- 7 files changed, 227 insertions(+), 39 deletions(-) diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport.java b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport.java index 1078d7cd2c0..792cb13ee89 100644 --- a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport.java +++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport.java @@ -25,7 +25,7 @@ package catalog; import java.io.File; import java.io.StringReader; - +import javax.xml.stream.XMLResolver; import javax.xml.transform.Source; import javax.xml.transform.URIResolver; import javax.xml.transform.dom.DOMSource; @@ -42,7 +42,7 @@ import org.xml.sax.InputSource; /** * @test - * @bug 8158084 8162438 8162442 + * @bug 8158084 8162438 8162442 8166220 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest * @run testng/othervm -DrunSecMngr=true catalog.CatalogSupport * @run testng/othervm catalog.CatalogSupport @@ -113,6 +113,15 @@ public class CatalogSupport extends CatalogSupportBase { testDOM(setUseCatalog, useCatalog, catalog, xml, handler, expected); } + /* + Verifies the Catalog support on XMLStreamReader. + */ + @Test(dataProvider = "data_StAXA") + public void testStAXA(boolean setUseCatalog, boolean useCatalog, String catalog, + String xml, XMLResolver resolver, String expected) throws Exception { + testStAX(setUseCatalog, useCatalog, catalog, xml, resolver, expected); + } + /* Verifies the Catalog support on resolving DTD, xsd import and include in Schema files. @@ -212,6 +221,20 @@ public class CatalogSupport extends CatalogSupportBase { }; } + /* + DataProvider: for testing the StAX parser + Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string + */ + @DataProvider(name = "data_StAXA") + public Object[][] getDataStAX() { + + return new Object[][]{ + {false, true, xml_catalog, xml_system, null, expectedWCatalog}, + {false, true, xml_catalog, xml_system, null, expectedWResolver}, + {true, true, xml_catalog, xml_system, null, expectedWResolver} + }; + } + MyEntityHandler getMyEntityHandler(String elementName, String[] systemIds, InputSource... returnValues) { return new MyEntityHandler(systemIds, returnValues, elementName); } @@ -262,8 +285,8 @@ public class CatalogSupport extends CatalogSupportBase { SAXSource ss = new SAXSource(new InputSource(xml_val_test)); ss.setSystemId(xml_val_test_id); - StAXSource stax = getStaxSource(xml_val_test, xml_val_test_id); - StAXSource stax1 = getStaxSource(xml_val_test, xml_val_test_id); + StAXSource stax = getStaxSource(xml_val_test, xml_val_test_id, false, true, xml_catalog); + StAXSource stax1 = getStaxSource(xml_val_test, xml_val_test_id, false, true, xml_catalog); StreamSource source = new StreamSource(new File(xml_val_test)); @@ -271,8 +294,7 @@ public class CatalogSupport extends CatalogSupportBase { XmlInput[] returnValues = {new XmlInput(null, dtd_system, null), new XmlInput(null, xsd_val_test, null)}; LSResourceResolver resolver = new SourceResolver(null, systemIds, returnValues); - StAXSource stax2 = getStaxSource(xml_val_test, xml_val_test_id); - StAXSource stax3 = getStaxSource(xml_val_test, xml_val_test_id); + StAXSource stax2 = getStaxSource(xml_val_test, xml_val_test_id, false, true, xml_catalog); return new Object[][]{ // use catalog diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport1.java b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport1.java index 251a65fc779..03a54ef82be 100644 --- a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport1.java +++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport1.java @@ -30,6 +30,7 @@ import java.io.File; import java.io.StringReader; import javax.xml.catalog.CatalogFeatures.Feature; +import javax.xml.stream.XMLResolver; import javax.xml.transform.Source; import javax.xml.transform.URIResolver; import javax.xml.transform.dom.DOMSource; @@ -47,7 +48,7 @@ import org.xml.sax.InputSource; /* * @test - * @bug 8158084 8162438 8162442 + * @bug 8158084 8162438 8162442 8166220 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest * @run testng/othervm -DrunSecMngr=true catalog.CatalogSupport1 * @run testng/othervm catalog.CatalogSupport1 @@ -109,6 +110,15 @@ public class CatalogSupport1 extends CatalogSupportBase { testDOM(setUseCatalog, useCatalog, catalog, xml, handler, expected); } + /* + Verifies the Catalog support on XMLStreamReader. + */ + @Test(dataProvider = "data_StAXC") + public void testStAXC(boolean setUseCatalog, boolean useCatalog, String catalog, + String xml, XMLResolver resolver, String expected) throws Exception { + testStAX(setUseCatalog, useCatalog, catalog, xml, resolver, expected); + } + /* Verifies the Catalog support on resolving DTD, xsd import and include in Schema files. @@ -189,6 +199,18 @@ public class CatalogSupport1 extends CatalogSupportBase { }; } + /* + DataProvider: for testing the StAX parser + Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string + */ + @DataProvider(name = "data_StAXC") + public Object[][] getDataStAX() { + + return new Object[][]{ + {false, true, null, xml_system, null, expectedWCatalog}, + }; + } + /* DataProvider: for testing Schema validation Data: set use_catalog, use_catalog, catalog file, xsd file, a LSResourceResolver @@ -218,8 +240,8 @@ public class CatalogSupport1 extends CatalogSupportBase { SAXSource ss = new SAXSource(new InputSource(xml_val_test)); ss.setSystemId(xml_val_test_id); - StAXSource stax = getStaxSource(xml_val_test, xml_val_test_id); - StAXSource stax1 = getStaxSource(xml_val_test, xml_val_test_id); + StAXSource stax = getStaxSource(xml_val_test, xml_val_test_id, false, true, xml_catalog); + StAXSource stax1 = getStaxSource(xml_val_test, xml_val_test_id, false, true, xml_catalog); StreamSource source = new StreamSource(new File(xml_val_test)); @@ -227,8 +249,7 @@ public class CatalogSupport1 extends CatalogSupportBase { XmlInput[] returnValues = {new XmlInput(null, dtd_system, null), new XmlInput(null, xsd_val_test, null)}; LSResourceResolver resolver = new SourceResolver(null, systemIds, returnValues); - StAXSource stax2 = getStaxSource(xml_val_test, xml_val_test_id); - StAXSource stax3 = getStaxSource(xml_val_test, xml_val_test_id); + StAXSource stax2 = getStaxSource(xml_val_test, xml_val_test_id, false, true, xml_catalog); return new Object[][]{ // use catalog diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport2.java b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport2.java index 8332596e329..79e8809f329 100644 --- a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport2.java +++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport2.java @@ -30,6 +30,8 @@ import static jaxp.library.JAXPTestUtilities.setSystemProperty; import java.io.File; import java.io.IOException; import java.io.StringReader; +import javax.xml.stream.XMLResolver; +import javax.xml.stream.XMLStreamException; import javax.xml.transform.Source; import javax.xml.transform.TransformerException; import javax.xml.transform.URIResolver; @@ -50,7 +52,7 @@ import org.xml.sax.SAXParseException; /* * @test - * @bug 8158084 8162438 8162442 8163535 + * @bug 8158084 8162438 8162442 8163535 8166220 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest * @run testng/othervm -DrunSecMngr=true catalog.CatalogSupport2 * @run testng/othervm catalog.CatalogSupport2 @@ -128,6 +130,15 @@ public class CatalogSupport2 extends CatalogSupportBase { testDOM(setUseCatalog, useCatalog, catalog, xml, handler, expected); } + /* + Verifies the Catalog support on XMLStreamReader. + */ + @Test(dataProvider = "data_StAXC") + public void testStAXC(boolean setUseCatalog, boolean useCatalog, String catalog, + String xml, XMLResolver resolver, String expected) throws Exception { + testStAXNegative(setUseCatalog, useCatalog, catalog, xml, resolver, expected); + } + /* Verifies the Catalog support on resolving DTD, xsd import and include in Schema files. @@ -204,6 +215,17 @@ public class CatalogSupport2 extends CatalogSupportBase { }; } + /* + DataProvider: for testing the StAX parser + Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string + */ + @DataProvider(name = "data_StAXC") + public Object[][] getDataStAX() { + return new Object[][]{ + {false, true, xml_catalog, xml_system, null, "null"}, + }; + } + /* DataProvider: for testing Schema validation Data: set use_catalog, use_catalog, catalog file, xsd file, a LSResourceResolver @@ -233,8 +255,8 @@ public class CatalogSupport2 extends CatalogSupportBase { SAXSource ss = new SAXSource(new InputSource(xml_val_test)); ss.setSystemId(xml_val_test_id); - StAXSource stax = getStaxSource(xml_val_test, xml_val_test_id); - StAXSource stax1 = getStaxSource(xml_val_test, xml_val_test_id); + StAXSource stax = getStaxSource(xml_val_test, xml_val_test_id, false, true, xml_catalog); + StAXSource stax1 = getStaxSource(xml_val_test, xml_val_test_id, false, true, xml_catalog); StreamSource source = new StreamSource(new File(xml_val_test)); diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport3.java b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport3.java index 473ca119c90..8868b50b055 100644 --- a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport3.java +++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport3.java @@ -29,6 +29,8 @@ import static jaxp.library.JAXPTestUtilities.setSystemProperty; import java.io.File; import java.io.IOException; import java.io.StringReader; +import javax.xml.stream.XMLResolver; +import javax.xml.stream.XMLStreamException; import javax.xml.transform.Source; import javax.xml.transform.TransformerException; import javax.xml.transform.URIResolver; @@ -49,7 +51,7 @@ import org.xml.sax.SAXParseException; /* * @test - * @bug 8158084 8162438 8162442 8163535 + * @bug 8158084 8162438 8162442 8163535 8166220 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest * @run testng/othervm -DrunSecMngr=true catalog.CatalogSupport3 * @run testng/othervm catalog.CatalogSupport3 @@ -124,6 +126,15 @@ public class CatalogSupport3 extends CatalogSupportBase { testDOM(setUseCatalog, useCatalog, catalog, xml, handler, expected); } + /* + Verifies the Catalog support on XMLStreamReader. + */ + @Test(dataProvider = "data_StAXC") + public void testStAXC(boolean setUseCatalog, boolean useCatalog, String catalog, + String xml, XMLResolver resolver, String expected) throws Exception { + testStAXNegative(setUseCatalog, useCatalog, catalog, xml, resolver, expected); + } + /* Verifies the Catalog support on resolving DTD, xsd import and include in Schema files. @@ -205,6 +216,17 @@ public class CatalogSupport3 extends CatalogSupportBase { }; } + /* + DataProvider: for testing the StAX parser + Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string + */ + @DataProvider(name = "data_StAXC") + public Object[][] getDataStAX() { + return new Object[][]{ + {true, false, xml_catalog, xml_system, null, "null"}, + }; + } + /* DataProvider: for testing Schema validation Data: set use_catalog, use_catalog, catalog file, xsd file, a LSResourceResolver @@ -234,8 +256,8 @@ public class CatalogSupport3 extends CatalogSupportBase { SAXSource ss = new SAXSource(new InputSource(xml_val_test)); ss.setSystemId(xml_val_test_id); - StAXSource stax = getStaxSource(xml_val_test, xml_val_test_id); - StAXSource stax1 = getStaxSource(xml_val_test, xml_val_test_id); + StAXSource stax = getStaxSource(xml_val_test, xml_val_test_id, false, true, xml_catalog); + StAXSource stax1 = getStaxSource(xml_val_test, xml_val_test_id, false, true, xml_catalog); StreamSource source = new StreamSource(new File(xml_val_test)); diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport4.java b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport4.java index b565cf30853..2549b64c072 100644 --- a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport4.java +++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport4.java @@ -28,7 +28,7 @@ import static jaxp.library.JAXPTestUtilities.setSystemProperty; import java.io.File; import java.io.StringReader; - +import javax.xml.stream.XMLResolver; import javax.xml.transform.Source; import javax.xml.transform.URIResolver; import javax.xml.transform.dom.DOMSource; @@ -46,7 +46,7 @@ import org.xml.sax.InputSource; /** * @test - * @bug 8158084 8162438 8162442 + * @bug 8158084 8162438 8162442 8166220 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest * @run testng/othervm -DrunSecMngr=true catalog.CatalogSupport4 * @run testng/othervm catalog.CatalogSupport4 @@ -117,6 +117,15 @@ public class CatalogSupport4 extends CatalogSupportBase { testDOM(setUseCatalog, useCatalog, catalog, xml, handler, expected); } + /* + Verifies the Catalog support on XMLStreamReader. + */ + @Test(dataProvider = "data_StAXA") + public void testStAXA(boolean setUseCatalog, boolean useCatalog, String catalog, + String xml, XMLResolver resolver, String expected) throws Exception { + testStAX(setUseCatalog, useCatalog, catalog, xml, resolver, expected); + } + /* Verifies the Catalog support on resolving DTD, xsd import and include in Schema files. @@ -199,6 +208,18 @@ public class CatalogSupport4 extends CatalogSupportBase { }; } + /* + DataProvider: for testing the StAX parser + Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string + */ + @DataProvider(name = "data_StAXA") + public Object[][] getDataStAX() { + + return new Object[][]{ + {true, true, xml_catalog, xml_system, null, expectedWCatalog}, + }; + } + MyEntityHandler getMyEntityHandler(String elementName, String[] systemIds, InputSource... returnValues) { return new MyEntityHandler(systemIds, returnValues, elementName); } @@ -230,8 +251,8 @@ public class CatalogSupport4 extends CatalogSupportBase { SAXSource ss = new SAXSource(new InputSource(xml_val_test)); ss.setSystemId(xml_val_test_id); - StAXSource stax = getStaxSource(xml_val_test, xml_val_test_id); - StAXSource stax1 = getStaxSource(xml_val_test, xml_val_test_id); + StAXSource stax = getStaxSource(xml_val_test, xml_val_test_id, true, true, xml_catalog); + StAXSource stax1 = getStaxSource(xml_val_test, xml_val_test_id, true, true, xml_catalog); StreamSource source = new StreamSource(new File(xml_val_test)); @@ -241,8 +262,8 @@ public class CatalogSupport4 extends CatalogSupportBase { {false, true, true, ds, null, null, null, xml_catalog}, {true, false, true, ss, null, null, xml_catalog, null}, {false, true, true, ss, null, null, null, xml_catalog}, - {true, false, true, stax, null, null, xml_catalog, null}, - {false, true, true, stax1, null, null, null, xml_catalog}, + {true, false, true, stax, null, null, xml_catalog, xml_catalog}, + {false, true, true, stax1, null, null, xml_catalog, xml_catalog}, {true, false, true, source, null, null, xml_catalog, null}, {false, true, true, source, null, null, null, xml_catalog}, }; diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport5.java b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport5.java index 884f34ddb88..81da1749944 100644 --- a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport5.java +++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport5.java @@ -25,6 +25,8 @@ package catalog; import java.io.File; import java.io.StringReader; +import javax.xml.stream.XMLResolver; +import javax.xml.stream.XMLStreamException; import javax.xml.transform.Source; import javax.xml.transform.TransformerException; import javax.xml.transform.URIResolver; @@ -43,7 +45,7 @@ import org.xml.sax.SAXException; /* * @test - * @bug 8158084 8163232 + * @bug 8158084 8163232 8166220 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest * @run testng/othervm -DrunSecMngr=true catalog.CatalogSupport5 * @run testng/othervm catalog.CatalogSupport5 @@ -106,6 +108,15 @@ public class CatalogSupport5 extends CatalogSupportBase { testDOM(setUseCatalog, useCatalog, catalog, xml, handler, expected); } + /* + Verifies the Catalog support on XMLStreamReader. + */ + @Test(dataProvider = "data_StAXC", expectedExceptions = XMLStreamException.class) + public void testStAXC(boolean setUseCatalog, boolean useCatalog, String catalog, + String xml, XMLResolver resolver, String expected) throws Exception { + testStAX(setUseCatalog, useCatalog, catalog, xml, resolver, expected); + } + /* Verifies the Catalog support on resolving DTD, xsd import and include in Schema files. @@ -182,6 +193,18 @@ public class CatalogSupport5 extends CatalogSupportBase { }; } + /* + DataProvider: for testing the StAX parser + Data: set use_catalog, use_catalog, catalog file, xml file, handler, expected result string + */ + @DataProvider(name = "data_StAXC") + public Object[][] getDataStAX() { + + return new Object[][]{ + {false, true, xml_bogus_catalog, xml_system, null, expectedWCatalog}, + }; + } + /* DataProvider: for testing Schema validation Data: set use_catalog, use_catalog, catalog file, xsd file, a LSResourceResolver @@ -211,8 +234,8 @@ public class CatalogSupport5 extends CatalogSupportBase { SAXSource ss = new SAXSource(new InputSource(xml_val_test)); ss.setSystemId(xml_val_test_id); - StAXSource stax = getStaxSource(xml_val_test, xml_val_test_id); - StAXSource stax1 = getStaxSource(xml_val_test, xml_val_test_id); + StAXSource stax = getStaxSource(xml_val_test, xml_val_test_id, false, true, xml_catalog); + StAXSource stax1 = getStaxSource(xml_val_test, xml_val_test_id, false, true, xml_catalog); StreamSource source = new StreamSource(new File(xml_val_test)); diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupportBase.java b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupportBase.java index 87735104855..27bf6b4b661 100644 --- a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupportBase.java +++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupportBase.java @@ -318,6 +318,31 @@ public class CatalogSupportBase { assertEquals(expected, result.trim(), "Catalog support for DOM"); } + /* + Verifies the Catalog support on StAX parser. + */ + public void testStAX(boolean setUseCatalog, boolean useCatalog, String catalog, + String xml, XMLResolver resolver, String expected) throws Exception { + + XMLStreamReader streamReader = getStreamReader( + setUseCatalog, useCatalog, catalog, xml, resolver); + String text = getText(streamReader, XMLStreamConstants.CHARACTERS); + assertEquals(expected, text.trim(), "Catalog support for StAX"); + } + + /* + Verifies that the Catalog support for StAX parser is disabled when + USE_CATALOG == false. + */ + public void testStAXNegative(boolean setUseCatalog, boolean useCatalog, String catalog, + String xml, XMLResolver resolver, String expected) throws Exception { + + XMLStreamReader streamReader = getStreamReader( + setUseCatalog, useCatalog, catalog, xml, resolver); + String text = getText(streamReader, XMLStreamConstants.ENTITY_REFERENCE); + assertEquals(expected, text.trim(), "Catalog support for StAX"); + } + /* Verifies the Catalog support on resolving DTD, xsd import and include in Schema files. @@ -514,15 +539,24 @@ public class CatalogSupportBase { * * @param xmlFile the XML source file * @param xmlFileId the systemId of the source + * @param setUseCatalog a flag indicates whether USE_CATALOG shall be set + * through the factory + * @param useCatalog the value of USE_CATALOG + * @param catalog a catalog * @return a StAXSource * @throws XMLStreamException * @throws FileNotFoundException */ - StAXSource getStaxSource(String xmlFile, String xmlFileId) { + StAXSource getStaxSource(String xmlFile, String xmlFileId, boolean setUseCatalog, + boolean useCatalog, String catalog) { StAXSource ss = null; try { - ss = new StAXSource( - XMLInputFactory.newFactory().createXMLEventReader( + XMLInputFactory xif = XMLInputFactory.newFactory(); + if (setUseCatalog) { + xif.setProperty(XMLConstants.USE_CATALOG, useCatalog); + } + xif.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), catalog); + ss = new StAXSource(xif.createXMLEventReader( xmlFileId, new FileInputStream(xmlFile))); } catch (Exception e) {} @@ -531,6 +565,10 @@ public class CatalogSupportBase { /** * Creates an XMLStreamReader. + * + * @param setUseCatalog a flag indicates whether USE_CATALOG shall be set + * through the factory + * @param useCatalog the value of USE_CATALOG * @param catalog the path to a catalog * @param xml the xml to be parsed * @param resolver a resolver to be set on the reader @@ -542,9 +580,17 @@ public class CatalogSupportBase { String catalog, String xml, XMLResolver resolver) throws FileNotFoundException, XMLStreamException { XMLInputFactory factory = XMLInputFactory.newInstance(); - factory.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), catalog); + if (catalog != null) { + factory.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), catalog); + } + + factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, true); factory.setProperty(XMLInputFactory.IS_COALESCING, true); - factory.setProperty(XMLInputFactory.RESOLVER, resolver); + + if (resolver != null) { + factory.setProperty(XMLInputFactory.RESOLVER, resolver); + } + if (setUseCatalog) { factory.setProperty(XMLConstants.USE_CATALOG, useCatalog); } @@ -560,17 +606,28 @@ public class CatalogSupportBase { * @return the text of the first element * @throws XMLStreamException */ - String getText(XMLStreamReader streamReader) throws XMLStreamException { + String getText(XMLStreamReader streamReader, int type) throws XMLStreamException { + StringBuilder text = new StringBuilder(); + StringBuilder entityRef = new StringBuilder(); + while(streamReader.hasNext()){ - int eventType = streamReader.next() ; - if(eventType == XMLStreamConstants.START_ELEMENT){ - eventType = streamReader.next() ; - if(eventType == XMLStreamConstants.CHARACTERS){ - return streamReader.getText() ; - } + int eventType = streamReader.next(); + switch (eventType) { + case XMLStreamConstants.START_ELEMENT: + break; + case XMLStreamConstants.CHARACTERS: + text.append(streamReader.getText()); + break; + case XMLStreamConstants.ENTITY_REFERENCE: + entityRef.append(streamReader.getText()); + break; } } - return null; + if (type == XMLStreamConstants.CHARACTERS) { + return text.toString(); + } else { + return entityRef.toString(); + } } /** From bf6427a55aaf07bcb960713139477cb203c20d35 Mon Sep 17 00:00:00 2001 From: "J. Duke" Date: Wed, 5 Jul 2017 22:12:20 +0200 Subject: [PATCH 103/110] Added tag jdk-9+136 for changeset 1b4b5d01aa11 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 555f758c163..14aa9215059 100644 --- a/.hgtags +++ b/.hgtags @@ -378,3 +378,4 @@ e613affb88d178dc7c589f1679db113d589bddb4 jdk-9+130 e17429a7e843c4a4ed3651458d0f950970edcbcc jdk-9+133 a71210c0d9800eb6925b61ecd6198abd554f90ee jdk-9+134 e384420383a5b79fa0012ebcb25d8f83cff7f777 jdk-9+135 +1b4b5d01aa11edf24b6fadbe3d2f3e411e3b02cd jdk-9+136 From 73fbb10440ce0c0456ccc280301ab31b4a179072 Mon Sep 17 00:00:00 2001 From: John Jiang Date: Tue, 20 Sep 2016 10:32:52 +0800 Subject: [PATCH 104/110] 8165566: sun/security/ssl/SocketCreation/SocketCreation.java fails intermittently: Address already in use It takes every server to be allocated a free port. Reviewed-by: chegar --- .../ssl/SocketCreation/SocketCreation.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/jdk/test/sun/security/ssl/SocketCreation/SocketCreation.java b/jdk/test/sun/security/ssl/SocketCreation/SocketCreation.java index 65e41b56ac2..94f0323b6dc 100644 --- a/jdk/test/sun/security/ssl/SocketCreation/SocketCreation.java +++ b/jdk/test/sun/security/ssl/SocketCreation/SocketCreation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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 @@ -139,7 +139,7 @@ public class SocketCreation { (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); System.out.println("Server: Will call createServerSocket(int)"); - ServerSocket sslServerSocket = sslssf.createServerSocket(serverPort); + ServerSocket sslServerSocket = sslssf.createServerSocket(0); serverPort = sslServerSocket.getLocalPort(); System.out.println("Server: Will accept on SSL server socket..."); @@ -157,7 +157,7 @@ public class SocketCreation { (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); System.out.println("Server: Will call createServerSocket(int, int)"); - ServerSocket sslServerSocket = sslssf.createServerSocket(serverPort, + ServerSocket sslServerSocket = sslssf.createServerSocket(0, 1); serverPort = sslServerSocket.getLocalPort(); @@ -177,7 +177,7 @@ public class SocketCreation { System.out.println("Server: Will call createServerSocket(int, " + " int, InetAddress)"); - ServerSocket sslServerSocket = sslssf.createServerSocket(serverPort, + ServerSocket sslServerSocket = sslssf.createServerSocket(0, 1, InetAddress.getByName("localhost")); serverPort = sslServerSocket.getLocalPort(); @@ -203,14 +203,15 @@ public class SocketCreation { if (sslServerSocket.isBound()) throw new Exception("Server socket is already bound!"); - System.out.println("Server: Will bind SSL server socket to port " + - serverPort + "..."); - - sslServerSocket.bind(new java.net.InetSocketAddress(serverPort)); + sslServerSocket.bind(new java.net.InetSocketAddress(0)); if (!sslServerSocket.isBound()) throw new Exception("Server socket is not bound!"); + serverPort = sslServerSocket.getLocalPort(); + System.out.println("Server: Bound SSL server socket to port " + + serverPort + "..."); + serverReady = true; System.out.println("Server: Will accept on SSL server socket..."); @@ -224,11 +225,10 @@ public class SocketCreation { SSLSocketFactory sslsf = (SSLSocketFactory) SSLSocketFactory.getDefault(); - System.out.println("Server: Will create normal server socket bound" - + " to port " + serverPort + "..."); - - ServerSocket ss = new ServerSocket(serverPort); + ServerSocket ss = new ServerSocket(0); serverPort = ss.getLocalPort(); + System.out.println("Server: Created normal server socket bound" + + " to port " + serverPort + "..."); System.out.println("Server: Will accept on server socket..."); serverReady = true; Socket s = ss.accept(); From dd770672f8649267d1820e1336e6ae365833c839 Mon Sep 17 00:00:00 2001 From: Christoph Langer Date: Tue, 20 Sep 2016 08:46:33 +0200 Subject: [PATCH 105/110] 8166189: Fix for Bug 8165524 breaks AIX build Reviewed-by: simonis, goetz, mchung, cbensen, dsamersoff --- .../java.base/aix/native/libjli/java_md_aix.c | 85 +++++++++++++++++++ .../java.base/aix/native/libjli/java_md_aix.h | 47 ++++++++++ .../java.base/unix/native/libjli/java_md.h | 15 ++-- 3 files changed, 141 insertions(+), 6 deletions(-) create mode 100644 jdk/src/java.base/aix/native/libjli/java_md_aix.c create mode 100644 jdk/src/java.base/aix/native/libjli/java_md_aix.h diff --git a/jdk/src/java.base/aix/native/libjli/java_md_aix.c b/jdk/src/java.base/aix/native/libjli/java_md_aix.c new file mode 100644 index 00000000000..62cac20ef5d --- /dev/null +++ b/jdk/src/java.base/aix/native/libjli/java_md_aix.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016 SAP SE. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +#include +#include + +#include "java_md_aix.h" + +static unsigned char dladdr_buffer[0x4000]; + +static int fill_dll_info(void) { + return loadquery(L_GETINFO, dladdr_buffer, sizeof(dladdr_buffer)); +} + +static int dladdr_dont_reload(void *addr, Dl_info *info) { + const struct ld_info *p = (struct ld_info *)dladdr_buffer; + memset((void *)info, 0, sizeof(Dl_info)); + for (;;) { + if (addr >= p->ldinfo_textorg && + addr < (((char*)p->ldinfo_textorg) + p->ldinfo_textsize)) + { + info->dli_fname = p->ldinfo_filename; + return 1; + } + if (!p->ldinfo_next) { + break; + } + p = (struct ld_info *)(((char *)p) + p->ldinfo_next); + } + return 0; +} + +int dladdr(void *addr, Dl_info *info) { + static int loaded = 0; + int rc = 0; + void *addr0; + if (!addr) { + return rc; + } + if (!loaded) { + if (fill_dll_info() == -1) + return rc; + loaded = 1; + } + + // first try with addr on cached data + rc = dladdr_dont_reload(addr, info); + + // addr could be an AIX function descriptor, so try dereferenced version + if (rc == 0) { + addr0 = *((void **)addr); + rc = dladdr_dont_reload(addr0, info); + } + + // if we had no success until now, maybe loadquery info is outdated. + // refresh and retry + if (rc == 0) { + if (fill_dll_info() == -1) + return rc; + rc = dladdr_dont_reload(addr, info); + if (rc == 0) { + rc = dladdr_dont_reload(addr0, info); + } + } + return rc; +} diff --git a/jdk/src/java.base/aix/native/libjli/java_md_aix.h b/jdk/src/java.base/aix/native/libjli/java_md_aix.h new file mode 100644 index 00000000000..c8676ca6bde --- /dev/null +++ b/jdk/src/java.base/aix/native/libjli/java_md_aix.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016 SAP SE. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef JAVA_MD_AIX_H +#define JAVA_MD_AIX_H + +/* + * Very limited AIX port of dladdr() for libjli.so. + * + * We try to mimick dladdr(3) on Linux (see http://linux.die.net/man/3/dladdr) + * dladdr(3) is not POSIX but a GNU extension, and is not available on AIX. + * + * We only support Dl_info.dli_fname here as this is the only thing that is + * used of it by libjli.so. A more comprehensive port of dladdr can be found + * in the hotspot implementation which is not available at this place, though. + */ + +typedef struct { + const char *dli_fname; /* file path of loaded library */ + void *dli_fbase; /* unsupported */ + const char *dli_sname; /* unsupported */ + void *dli_saddr; /* unsupported */ +} Dl_info; + +int dladdr(void *addr, Dl_info *info); + +#endif /* JAVA_MD_AIX_H */ diff --git a/jdk/src/java.base/unix/native/libjli/java_md.h b/jdk/src/java.base/unix/native/libjli/java_md.h index ab99dbbdf66..8e95aced972 100644 --- a/jdk/src/java.base/unix/native/libjli/java_md.h +++ b/jdk/src/java.base/unix/native/libjli/java_md.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, 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 @@ -35,12 +35,12 @@ #include "manifest_info.h" #include "jli_util.h" -#define PATH_SEPARATOR ':' -#define FILESEP "/" -#define FILE_SEPARATOR '/' +#define PATH_SEPARATOR ':' +#define FILESEP "/" +#define FILE_SEPARATOR '/' #define IS_FILE_SEPARATOR(c) ((c) == '/') #ifndef MAXNAMELEN -#define MAXNAMELEN PATH_MAX +#define MAXNAMELEN PATH_MAX #endif #ifdef _LP64 @@ -59,10 +59,13 @@ static jboolean GetJVMPath(const char *jrepath, const char *jvmtype, static jboolean GetJREPath(char *path, jint pathsize, const char * arch, jboolean speculative); +#if defined(_AIX) +#include "java_md_aix.h" +#endif + #ifdef MACOSX #include "java_md_macosx.h" #else /* !MACOSX */ #include "java_md_solinux.h" #endif /* MACOSX */ - #endif /* JAVA_MD_H */ From 3b0d7a4511982c6f7a89a1b33fde893b0d9bb938 Mon Sep 17 00:00:00 2001 From: Sergei Kovalev Date: Tue, 20 Sep 2016 12:56:54 +0300 Subject: [PATCH 106/110] 8166285: Missing dependencies java.httpclient for tests from java/net pachage Reviewed-by: chegar --- .../net/URLClassLoader/definePackage/SplitPackage.java | 1 + jdk/test/java/net/httpclient/HeadersTest1.java | 10 +++++++--- jdk/test/java/net/httpclient/ProxyAuthTest.java | 1 + jdk/test/java/net/httpclient/whitebox/Driver.java | 1 + 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/jdk/test/java/net/URLClassLoader/definePackage/SplitPackage.java b/jdk/test/java/net/URLClassLoader/definePackage/SplitPackage.java index c31441d8b1a..f5af425be46 100644 --- a/jdk/test/java/net/URLClassLoader/definePackage/SplitPackage.java +++ b/jdk/test/java/net/URLClassLoader/definePackage/SplitPackage.java @@ -27,6 +27,7 @@ * @summary Test two URLClassLoader define Package object of the same name * @library /lib/testlibrary * @build CompilerUtils + * @modules jdk.compiler * @run testng SplitPackage */ diff --git a/jdk/test/java/net/httpclient/HeadersTest1.java b/jdk/test/java/net/httpclient/HeadersTest1.java index e3c892ef2c1..2c8540e9e83 100644 --- a/jdk/test/java/net/httpclient/HeadersTest1.java +++ b/jdk/test/java/net/httpclient/HeadersTest1.java @@ -23,9 +23,11 @@ * questions. */ -/** +/* * @test * @bug 8153142 + * @modules java.httpclient + * jdk.httpserver * @run main/othervm HeadersTest1 * @summary HeadersTest1 */ @@ -39,9 +41,11 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetSocketAddress; -import java.net.PasswordAuthentication; import java.net.URI; -import java.net.http.*; +import java.net.http.HttpClient; +import java.net.http.HttpHeaders; +import java.net.http.HttpResponse; +import java.net.http.HttpRequest; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.List; diff --git a/jdk/test/java/net/httpclient/ProxyAuthTest.java b/jdk/test/java/net/httpclient/ProxyAuthTest.java index 42bc0c709db..4301e06d708 100644 --- a/jdk/test/java/net/httpclient/ProxyAuthTest.java +++ b/jdk/test/java/net/httpclient/ProxyAuthTest.java @@ -26,6 +26,7 @@ * @test * @bug 8163561 * @modules java.base/sun.net.www + * java.httpclient * @summary Verify that Proxy-Authenticate header is correctly handled * * @run main/othervm ProxyAuthTest diff --git a/jdk/test/java/net/httpclient/whitebox/Driver.java b/jdk/test/java/net/httpclient/whitebox/Driver.java index fbbdb05dbed..b1cc54be137 100644 --- a/jdk/test/java/net/httpclient/whitebox/Driver.java +++ b/jdk/test/java/net/httpclient/whitebox/Driver.java @@ -24,5 +24,6 @@ /* * @test * @bug 8151299 + * @modules java.httpclient * @run testng java.httpclient/java.net.http.SelectorTest */ From 3e5ef4867fe60ab4e16244a32150e2f0dfa1cf5a Mon Sep 17 00:00:00 2001 From: Amy Lu Date: Wed, 21 Sep 2016 08:55:47 +0800 Subject: [PATCH 107/110] 8166248: tools/pack200/Pack200Test.java fails on Win32: Could not reserve enough space Reviewed-by: ksrini --- jdk/test/tools/pack200/Pack200Test.java | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/test/tools/pack200/Pack200Test.java b/jdk/test/tools/pack200/Pack200Test.java index 5c50da1e503..0c18de51899 100644 --- a/jdk/test/tools/pack200/Pack200Test.java +++ b/jdk/test/tools/pack200/Pack200Test.java @@ -24,6 +24,7 @@ /* * @test * @bug 6521334 6712743 8007902 8151901 + * @requires (sun.arch.data.model == "64" & os.maxMemory >= 4g) * @summary test general packer/unpacker functionality * using native and java unpackers * @compile -XDignore.symbol.file Utils.java Pack200Test.java From 0d0e86808b4d81a7a8cb39398ee5e46dbac2a301 Mon Sep 17 00:00:00 2001 From: Felix Yang Date: Wed, 21 Sep 2016 02:19:59 -0700 Subject: [PATCH 108/110] 8166359: java/net/URLPermission/nstest/lookup.sh fails if proxy is set since fix for JDK-8161016 Reviewed-by: chegar --- jdk/test/java/net/URLPermission/nstest/LookupTest.java | 3 ++- jdk/test/java/net/URLPermission/nstest/LookupTestHosts | 2 -- jdk/test/java/net/URLPermission/nstest/lookup.sh | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 jdk/test/java/net/URLPermission/nstest/LookupTestHosts diff --git a/jdk/test/java/net/URLPermission/nstest/LookupTest.java b/jdk/test/java/net/URLPermission/nstest/LookupTest.java index d5b9141c1d4..eebcff5249f 100644 --- a/jdk/test/java/net/URLPermission/nstest/LookupTest.java +++ b/jdk/test/java/net/URLPermission/nstest/LookupTest.java @@ -37,6 +37,7 @@ public class LookupTest { String url, boolean throwsSecException, boolean throwsIOException) { try { + ProxySelector.setDefault(null); URL u = new URL(url); System.err.println ("Connecting to " + u); URLConnection urlc = u.openConnection(); @@ -71,7 +72,7 @@ public class LookupTest { System.out.print(port); } else if (cmd.equals("-runtest")) { port = Integer.parseInt(args[1]); - String hostsFileName = System.getProperty("test.src", ".") + "/LookupTestHosts"; + String hostsFileName = System.getProperty("user.dir", ".") + "/LookupTestHosts"; System.setProperty("jdk.net.hosts.file", hostsFileName); addMappingToHostsFile("allowedAndFound.com", "127.0.0.1", hostsFileName, false); addMappingToHostsFile("notAllowedButFound.com", "99.99.99.99", hostsFileName, true); diff --git a/jdk/test/java/net/URLPermission/nstest/LookupTestHosts b/jdk/test/java/net/URLPermission/nstest/LookupTestHosts deleted file mode 100644 index 0e64bb8c49f..00000000000 --- a/jdk/test/java/net/URLPermission/nstest/LookupTestHosts +++ /dev/null @@ -1,2 +0,0 @@ -127.0.0.1 allowedAndFound.com -99.99.99.99 notAllowedButFound.com diff --git a/jdk/test/java/net/URLPermission/nstest/lookup.sh b/jdk/test/java/net/URLPermission/nstest/lookup.sh index 798e1c168f6..a6b495c9f35 100644 --- a/jdk/test/java/net/URLPermission/nstest/lookup.sh +++ b/jdk/test/java/net/URLPermission/nstest/lookup.sh @@ -48,6 +48,7 @@ cat << POLICY > policy grant { permission java.net.URLPermission "http://allowedAndFound.com:${port}/-", "*:*"; permission java.net.URLPermission "http://allowedButNotfound.com:${port}/-", "*:*"; + permission java.net.NetPermission "setProxySelector"; permission java.io.FilePermission "<>", "read,write,delete"; permission java.util.PropertyPermission "java.io.tmpdir", "read"; From 4e8fe41e356d11207237dd9b37298d10b86abf22 Mon Sep 17 00:00:00 2001 From: Alan Burlison Date: Wed, 21 Sep 2016 14:22:11 +0200 Subject: [PATCH 109/110] 8165161: Solaris: /usr/ccs /opt/sfw and /opt/csw are dead, references should be expunged Reviewed-by: rriggs, erikj --- jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c | 4 ++-- .../unix/native/libawt_xawt/awt/awt_GraphicsEnv.c | 2 +- .../share/classes/sun/security/pkcs11/Secmod.java | 2 +- jdk/test/jprt.config | 9 +++------ jdk/test/start-Xvfb.sh | 3 --- jdk/test/sun/security/smartcardio/README.txt | 8 ++++---- jdk/test/sun/security/tools/keytool/KeyToolTest.java | 4 ++-- jdk/test/tools/launcher/RunpathTest.java | 2 +- 8 files changed, 14 insertions(+), 20 deletions(-) diff --git a/jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c b/jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c index 27230858253..533584fdb7a 100644 --- a/jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c +++ b/jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c @@ -152,8 +152,8 @@ defaultPath(void) #ifdef __solaris__ /* These really are the Solaris defaults! */ return (geteuid() == 0 || getuid() == 0) ? - "/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin:/usr/sbin" : - "/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin:"; + "/usr/xpg4/bin:/usr/bin:/opt/SUNWspro/bin:/usr/sbin" : + "/usr/xpg4/bin:/usr/bin:/opt/SUNWspro/bin:"; #else return ":/bin:/usr/bin"; /* glibc */ #endif diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c index c1895cd29d7..7124f6127af 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c @@ -442,7 +442,7 @@ getAllConfigs (JNIEnv *env, int screen, AwtScreenDataPtr screenDataPtr) { #ifndef __linux__ /* SOLARIS */ if (xrenderLibHandle == NULL) { - xrenderLibHandle = dlopen("/usr/sfw/lib/libXrender.so.1", + xrenderLibHandle = dlopen("/usr/lib/libXrender.so.1", RTLD_LAZY | RTLD_GLOBAL); } #endif diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/Secmod.java b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/Secmod.java index cd11ad57fe9..262bbb9afd1 100644 --- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/Secmod.java +++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/Secmod.java @@ -45,7 +45,7 @@ import static sun.security.pkcs11.wrapper.PKCS11Constants.*; *

  *   Secmod secmod = Secmod.getInstance();
  *   if (secmod.isInitialized() == false) {
- *       secmod.initialize("/home/myself/.mozilla", "/usr/sfw/lib/mozilla");
+ *       secmod.initialize("/home/myself/.mozilla");
  *   }
  *
  *   Provider p = secmod.getModule(ModuleType.KEYSTORE).getProvider();
diff --git a/jdk/test/jprt.config b/jdk/test/jprt.config
index 3d6c975a398..9f438197ec3 100644
--- a/jdk/test/jprt.config
+++ b/jdk/test/jprt.config
@@ -82,15 +82,12 @@ if [ "${osname}" = SunOS ] ; then
     fi
 
     # Add basic solaris system paths
-    path4sdk=/usr/ccs/bin:/usr/ccs/lib:/usr/bin:/bin:/usr/sfw/bin
+    path4sdk=/usr/bin:/usr/gnu/bin
 
     # Find GNU make
-    make=/usr/sfw/bin/gmake
+    make=/usr/bin/gmake
     if [ ! -f ${make} ] ; then
-	make=/opt/sfw/bin/gmake
-	if [ ! -f ${make} ] ; then
-	    make=${slashjava}/devtools/${solaris_arch}/bin/gnumake
-        fi 
+	make=${slashjava}/devtools/${solaris_arch}/bin/gnumake
     fi
     fileMustExist "${make}" make
 
diff --git a/jdk/test/start-Xvfb.sh b/jdk/test/start-Xvfb.sh
index ea3d16c9997..ec6a4a2b1c7 100644
--- a/jdk/test/start-Xvfb.sh
+++ b/jdk/test/start-Xvfb.sh
@@ -59,9 +59,6 @@ else
   /usr/bin/nohup /usr/bin/X11/Xvfb -fbdir ${currentDir} -pixdepths 8 16 24 32 ${DISPLAY} > ${currentDir}/nohup.$$ 2>&1 &
 fi
 WM="/usr/bin/X11/fvwm2"
-if [ ! -x ${WM} ] ; then
-  WM="/opt/sfw/bin/fvwm2"
-fi
 #
 # Wait for Xvfb to initialize:
 sleep 5
diff --git a/jdk/test/sun/security/smartcardio/README.txt b/jdk/test/sun/security/smartcardio/README.txt
index 5efbb5fa33b..6a0953a61e3 100644
--- a/jdk/test/sun/security/smartcardio/README.txt
+++ b/jdk/test/sun/security/smartcardio/README.txt
@@ -1,17 +1,17 @@
 
 Rough hints for setting up MUSCLE on Solaris:
 
-Make sure you have libusb, usually in /usr/sfw:
+Make sure you have libusb, usually in /usr/lib:
 
-ls -l /usr/sfw/lib/libusb.so
-lrwxrwxrwx   1 root     other         11 Jan 12 16:02 /usr/sfw/lib/libusb.so -> libusb.so.1
+ls -l /usr/lib/libusb.so
+lrwxrwxrwx   1 root     other         11 Jan 12 16:02 /usr/lib/libusb.so -> libusb.so.1
 
 Get PCSC and CCID.
 -rwx------   1 user staff     529540 Jun 16 18:24 ccid-1.0.1.tar.gz
 -rwx------   1 user staff     842654 Jun 16 18:24 pcsc-lite-1.3.1.tar.gz
 
 Unpack pcsc
-Run ./configure --enable-libusb=/usr/sfw (??)
+Run ./configure --enable-libusb (??)
 gnumake
 Make /usr/local writeable for user
 gnumake install
diff --git a/jdk/test/sun/security/tools/keytool/KeyToolTest.java b/jdk/test/sun/security/tools/keytool/KeyToolTest.java
index a783c4e9dbd..7e19d510767 100644
--- a/jdk/test/sun/security/tools/keytool/KeyToolTest.java
+++ b/jdk/test/sun/security/tools/keytool/KeyToolTest.java
@@ -1761,7 +1761,7 @@ public class KeyToolTest {
         //PKCS#11 tests
 
         //   1. sccs edit cert8.db key3.db
-        //Runtime.getRuntime().exec("/usr/ccs/bin/sccs edit cert8.db key3.db");
+        //Runtime.getRuntime().exec("/usr/bin/sccs edit cert8.db key3.db");
         testOK("", p11Arg + ("-storepass test12 -genkey -alias genkey" +
                 " -dname cn=genkey -keysize 512 -keyalg rsa"));
         testOK("", p11Arg + "-storepass test12 -list");
@@ -1781,7 +1781,7 @@ public class KeyToolTest {
         testOK("", p11Arg + "-storepass test12 -list");
         assertTrue(out.indexOf("Your keystore contains 0 entries") != -1);
         //(check for empty database listing)
-        //Runtime.getRuntime().exec("/usr/ccs/bin/sccs unedit cert8.db key3.db");
+        //Runtime.getRuntime().exec("/usr/bin/sccs unedit cert8.db key3.db");
         remove("genkey.cert");
         remove("genkey.certreq");
         //  12. sccs unedit cert8.db key3.db
diff --git a/jdk/test/tools/launcher/RunpathTest.java b/jdk/test/tools/launcher/RunpathTest.java
index 26233b28561..00e757343c3 100644
--- a/jdk/test/tools/launcher/RunpathTest.java
+++ b/jdk/test/tools/launcher/RunpathTest.java
@@ -40,7 +40,7 @@ public class RunpathTest extends TestHelper {
     }
 
     final String findElfReader() {
-        String[] paths = {"/bin", "/sbin", "/usr/bin", "/usr/sbin", "/usr/ccs/bin"};
+        String[] paths = {"/usr/sbin", "/usr/bin"};
         final String cmd = isSolaris ? "elfdump" : "readelf";
         for (String x : paths) {
             File p = new File(x);

From 1c751c11fb5e54e0a402c5aa098b16290e9182c0 Mon Sep 17 00:00:00 2001
From: Sergei Kovalev 
Date: Wed, 21 Sep 2016 17:09:41 +0300
Subject: [PATCH 110/110] 8166450: smartcardio related tests failed on
 compilation during execution with jtreg tool

Reviewed-by: weijun
---
 jdk/test/sun/security/smartcardio/TestChannel.java         | 3 ++-
 jdk/test/sun/security/smartcardio/TestConnect.java         | 3 ++-
 jdk/test/sun/security/smartcardio/TestConnectAgain.java    | 3 ++-
 jdk/test/sun/security/smartcardio/TestControl.java         | 3 ++-
 jdk/test/sun/security/smartcardio/TestDefault.java         | 3 ++-
 jdk/test/sun/security/smartcardio/TestDirect.java          | 3 ++-
 jdk/test/sun/security/smartcardio/TestExclusive.java       | 3 ++-
 jdk/test/sun/security/smartcardio/TestMultiplePresent.java | 3 ++-
 jdk/test/sun/security/smartcardio/TestPresent.java         | 3 ++-
 jdk/test/sun/security/smartcardio/TestTransmit.java        | 3 ++-
 10 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/jdk/test/sun/security/smartcardio/TestChannel.java b/jdk/test/sun/security/smartcardio/TestChannel.java
index c7e022f7c21..90052158ca7 100644
--- a/jdk/test/sun/security/smartcardio/TestChannel.java
+++ b/jdk/test/sun/security/smartcardio/TestChannel.java
@@ -21,11 +21,12 @@
  * questions.
  */
 
-/**
+/*
  * @test
  * @bug 6239117
  * @summary test logical channels work
  * @author Andreas Sterbenz
+ * @modules java.smartcardio/javax.smartcardio
  * @run main/manual TestChannel
  */
 
diff --git a/jdk/test/sun/security/smartcardio/TestConnect.java b/jdk/test/sun/security/smartcardio/TestConnect.java
index 467939e1059..fa0631c98ad 100644
--- a/jdk/test/sun/security/smartcardio/TestConnect.java
+++ b/jdk/test/sun/security/smartcardio/TestConnect.java
@@ -21,11 +21,12 @@
  * questions.
  */
 
-/**
+/*
  * @test
  * @bug 6293769 6294527 6309280
  * @summary test connect() works
  * @author Andreas Sterbenz
+ * @modules java.smartcardio/javax.smartcardio
  * @run main/manual TestConnect
  */
 
diff --git a/jdk/test/sun/security/smartcardio/TestConnectAgain.java b/jdk/test/sun/security/smartcardio/TestConnectAgain.java
index f4e6af21cba..7f2343b2edd 100644
--- a/jdk/test/sun/security/smartcardio/TestConnectAgain.java
+++ b/jdk/test/sun/security/smartcardio/TestConnectAgain.java
@@ -21,11 +21,12 @@
  * questions.
  */
 
-/**
+/*
  * @test
  * @bug 6239117
  * @summary test connect works correctly if called multiple times/card removed
  * @author Andreas Sterbenz
+ * @modules java.smartcardio/javax.smartcardio
  * @run main/manual TestConnectAgain
  */
 
diff --git a/jdk/test/sun/security/smartcardio/TestControl.java b/jdk/test/sun/security/smartcardio/TestControl.java
index 682f715d1c4..fd1c936582e 100644
--- a/jdk/test/sun/security/smartcardio/TestControl.java
+++ b/jdk/test/sun/security/smartcardio/TestControl.java
@@ -21,11 +21,12 @@
  * questions.
  */
 
-/**
+/*
  * @test
  * @bug 6239117 6470320
  * @summary test if transmitControlCommand() works
  * @author Andreas Sterbenz
+ * @modules java.smartcardio/javax.smartcardio
  * @run main/manual TestControl
  */
 
diff --git a/jdk/test/sun/security/smartcardio/TestDefault.java b/jdk/test/sun/security/smartcardio/TestDefault.java
index 9f3a6660426..190b988e91b 100644
--- a/jdk/test/sun/security/smartcardio/TestDefault.java
+++ b/jdk/test/sun/security/smartcardio/TestDefault.java
@@ -21,11 +21,12 @@
  * questions.
  */
 
-/**
+/*
  * @test
  * @bug 6327047
  * @summary verify that TerminalFactory.getDefault() works
  * @author Andreas Sterbenz
+ * @modules java.smartcardio/javax.smartcardio
  * @run main/manual TestDefault
  */
 
diff --git a/jdk/test/sun/security/smartcardio/TestDirect.java b/jdk/test/sun/security/smartcardio/TestDirect.java
index 5c09ea907ab..bddc3093934 100644
--- a/jdk/test/sun/security/smartcardio/TestDirect.java
+++ b/jdk/test/sun/security/smartcardio/TestDirect.java
@@ -21,10 +21,11 @@
  * questions.
  */
 
-/**
+/*
  * @test
  * @bug 8046343
  * @summary Make sure that direct protocol is available
+ * @modules java.smartcardio/javax.smartcardio
  * @run main/manual TestDirect
  */
 
diff --git a/jdk/test/sun/security/smartcardio/TestExclusive.java b/jdk/test/sun/security/smartcardio/TestExclusive.java
index 9e4416ac6d9..cd451321f53 100644
--- a/jdk/test/sun/security/smartcardio/TestExclusive.java
+++ b/jdk/test/sun/security/smartcardio/TestExclusive.java
@@ -21,11 +21,12 @@
  * questions.
  */
 
-/**
+/*
  * @test
  * @bug 6239117
  * @summary verify that beginExclusive()/endExclusive() works
  * @author Andreas Sterbenz
+ * @modules java.smartcardio/javax.smartcardio
  * @run main/manual TestExclusive
  */
 
diff --git a/jdk/test/sun/security/smartcardio/TestMultiplePresent.java b/jdk/test/sun/security/smartcardio/TestMultiplePresent.java
index 15e320d2475..9fd2256bf09 100644
--- a/jdk/test/sun/security/smartcardio/TestMultiplePresent.java
+++ b/jdk/test/sun/security/smartcardio/TestMultiplePresent.java
@@ -21,11 +21,12 @@
  * questions.
  */
 
-/**
+/*
  * @test
  * @bug 6239117 6445367
  * @summary test that CardTerminals.waitForCard() works
  * @author Andreas Sterbenz
+ * @modules java.smartcardio/javax.smartcardio
  * @run main/manual TestMultiplePresent
  */
 
diff --git a/jdk/test/sun/security/smartcardio/TestPresent.java b/jdk/test/sun/security/smartcardio/TestPresent.java
index 1f499e97c12..fea98795d75 100644
--- a/jdk/test/sun/security/smartcardio/TestPresent.java
+++ b/jdk/test/sun/security/smartcardio/TestPresent.java
@@ -21,11 +21,12 @@
  * questions.
  */
 
-/**
+/*
  * @test
  * @bug 6293769 6294527
  * @summary test that the isCardPresent()/waitForX() APIs work correctly
  * @author Andreas Sterbenz
+ * @modules java.smartcardio/javax.smartcardio
  * @run main/manual TestPresent
  */
 
diff --git a/jdk/test/sun/security/smartcardio/TestTransmit.java b/jdk/test/sun/security/smartcardio/TestTransmit.java
index 85b32f6dd48..e233a4bb163 100644
--- a/jdk/test/sun/security/smartcardio/TestTransmit.java
+++ b/jdk/test/sun/security/smartcardio/TestTransmit.java
@@ -21,11 +21,12 @@
  * questions.
  */
 
-/**
+/*
  * @test
  * @bug 6293769 6294527
  * @summary test transmit() works
  * @author Andreas Sterbenz
+ * @modules java.smartcardio/javax.smartcardio
  * @run main/manual TestTransmit
  */