--- a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp Wed May 04 10:06:00 2016 +0200
@@ -825,17 +825,6 @@
return start;
}
- // The following routine generates a subroutine to throw an asynchronous
- // UnknownError when an unsafe access gets a fault that could not be
- // reasonably prevented by the programmer. (Example: SIGBUS/OBJERR.)
- //
- address generate_handler_for_unsafe_access() {
- StubCodeMark mark(this, "StubRoutines", "handler_for_unsafe_access");
- address start = __ function_entry();
- __ unimplemented("StubRoutines::handler_for_unsafe_access", 93);
- return start;
- }
-
#if !defined(PRODUCT)
// Wrapper which calls oopDesc::is_oop_or_null()
// Only called by MacroAssembler::verify_oop
@@ -3111,8 +3100,6 @@
StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError), false);
StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call), false);
- StubRoutines::_handler_for_unsafe_access_entry = generate_handler_for_unsafe_access();
-
// support for verify_oop (must happen after universe_init)
StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop();
--- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Wed May 04 10:06:00 2016 +0200
@@ -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
@@ -64,20 +64,6 @@
// -------------------------------------------------------------------------------------------------------------------------
// Stub Code definitions
-static address handle_unsafe_access() {
- JavaThread* thread = JavaThread::current();
- address pc = thread->saved_exception_pc();
- address npc = thread->saved_exception_npc();
- // pc is the instruction which we must emulate
- // doing a no-op is fine: return garbage from the load
-
- // request an async exception
- thread->set_pending_unsafe_access_error();
-
- // return address of next instruction to execute
- return npc;
-}
-
class StubGenerator: public StubCodeGenerator {
private:
@@ -746,62 +732,6 @@
Label _atomic_add_stub; // called from other stubs
- //------------------------------------------------------------------------------------------------------------------------
- // The following routine generates a subroutine to throw an asynchronous
- // UnknownError when an unsafe access gets a fault that could not be
- // reasonably prevented by the programmer. (Example: SIGBUS/OBJERR.)
- //
- // Arguments :
- //
- // trapping PC: O7
- //
- // Results:
- // posts an asynchronous exception, skips the trapping instruction
- //
-
- address generate_handler_for_unsafe_access() {
- StubCodeMark mark(this, "StubRoutines", "handler_for_unsafe_access");
- address start = __ pc();
-
- const int preserve_register_words = (64 * 2);
- Address preserve_addr(FP, (-preserve_register_words * wordSize) + STACK_BIAS);
-
- Register Lthread = L7_thread_cache;
- int i;
-
- __ save_frame(0);
- __ mov(G1, L1);
- __ mov(G2, L2);
- __ mov(G3, L3);
- __ mov(G4, L4);
- __ mov(G5, L5);
- for (i = 0; i < 64; i += 2) {
- __ stf(FloatRegisterImpl::D, as_FloatRegister(i), preserve_addr, i * wordSize);
- }
-
- address entry_point = CAST_FROM_FN_PTR(address, handle_unsafe_access);
- BLOCK_COMMENT("call handle_unsafe_access");
- __ call(entry_point, relocInfo::runtime_call_type);
- __ delayed()->nop();
-
- __ mov(L1, G1);
- __ mov(L2, G2);
- __ mov(L3, G3);
- __ mov(L4, G4);
- __ mov(L5, G5);
- for (i = 0; i < 64; i += 2) {
- __ ldf(FloatRegisterImpl::D, preserve_addr, as_FloatRegister(i), i * wordSize);
- }
-
- __ verify_thread();
-
- __ jmp(O0, 0);
- __ delayed()->restore();
-
- return start;
- }
-
-
// Support for uint StubRoutine::Sparc::partial_subtype_check( Klass sub, Klass super );
// Arguments :
//
@@ -5380,9 +5310,6 @@
StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError));
StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call));
- StubRoutines::_handler_for_unsafe_access_entry =
- generate_handler_for_unsafe_access();
-
// support for verify_oop (must happen after universe_init)
StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop_subroutine();
--- a/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.cpp Wed May 04 10:06:00 2016 +0200
@@ -67,7 +67,7 @@
// register information would be incorrect.
if (b->number_of_preds() > 1) {
int id = b->first_lir_instruction_id();
- BitMap regs(FrameMap::nof_fpu_regs);
+ ResourceBitMap regs(FrameMap::nof_fpu_regs);
regs.clear();
iw.walk_to(id); // walk after the first instruction (always a label) of the block
@@ -1069,7 +1069,7 @@
// clean up stack first so that there are no dead values on the stack
if (ComputeExactFPURegisterUsage) {
FpuStackSim* cur_sim = sim();
- BitMap live_fpu_regs = block->sux_at(0)->fpu_register_usage();
+ ResourceBitMap live_fpu_regs = block->sux_at(0)->fpu_register_usage();
assert(live_fpu_regs.size() == FrameMap::nof_fpu_regs, "missing register usage");
merge_cleanup_fpu_stack(instrs, cur_sim, live_fpu_regs);
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86_sin.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86_sin.cpp Wed May 04 10:06:00 2016 +0200
@@ -380,7 +380,7 @@
ALIGNED_(8) juint StubRoutines::x86::_NEG_ZERO[] =
{
- 0x00000000UL, 0x3c800000UL
+ 0x00000000UL, 0x80000000UL
};
void MacroAssembler::fast_sin(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, Register eax, Register ebx, Register ecx, Register edx, Register tmp1, Register tmp2, Register tmp3, Register tmp4) {
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp Wed May 04 10:06:00 2016 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -63,21 +63,6 @@
// -------------------------------------------------------------------------------------------------------------------------
// Stub Code definitions
-static address handle_unsafe_access() {
- JavaThread* thread = JavaThread::current();
- address pc = thread->saved_exception_pc();
- // pc is the instruction which we must emulate
- // doing a no-op is fine: return garbage from the load
- // therefore, compute npc
- address npc = Assembler::locate_next_instruction(pc);
-
- // request an async exception
- thread->set_pending_unsafe_access_error();
-
- // return address of next instruction to execute
- return npc;
-}
-
class StubGenerator: public StubCodeGenerator {
private:
@@ -623,27 +608,6 @@
}
- //---------------------------------------------------------------------------
- // The following routine generates a subroutine to throw an asynchronous
- // UnknownError when an unsafe access gets a fault that could not be
- // reasonably prevented by the programmer. (Example: SIGBUS/OBJERR.)
- address generate_handler_for_unsafe_access() {
- StubCodeMark mark(this, "StubRoutines", "handler_for_unsafe_access");
- address start = __ pc();
-
- __ push(0); // hole for return address-to-be
- __ pusha(); // push registers
- Address next_pc(rsp, RegisterImpl::number_of_registers * BytesPerWord);
- BLOCK_COMMENT("call handle_unsafe_access");
- __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, handle_unsafe_access)));
- __ movptr(next_pc, rax); // stuff next address
- __ popa();
- __ ret(0); // jump to next address
-
- return start;
- }
-
-
//----------------------------------------------------------------------------------------------------
// Non-destructive plausibility checks for oops
@@ -3865,9 +3829,6 @@
// These are currently used by Solaris/Intel
StubRoutines::_atomic_xchg_entry = generate_atomic_xchg();
- StubRoutines::_handler_for_unsafe_access_entry =
- generate_handler_for_unsafe_access();
-
// platform dependent
create_control_words();
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Wed May 04 10:06:00 2016 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, 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
@@ -61,21 +61,6 @@
// Stub Code definitions
-static address handle_unsafe_access() {
- JavaThread* thread = JavaThread::current();
- address pc = thread->saved_exception_pc();
- // pc is the instruction which we must emulate
- // doing a no-op is fine: return garbage from the load
- // therefore, compute npc
- address npc = Assembler::locate_next_instruction(pc);
-
- // request an async exception
- thread->set_pending_unsafe_access_error();
-
- // return address of next instruction to execute
- return npc;
-}
-
class StubGenerator: public StubCodeGenerator {
private:
@@ -989,32 +974,6 @@
return start;
}
- // The following routine generates a subroutine to throw an
- // asynchronous UnknownError when an unsafe access gets a fault that
- // could not be reasonably prevented by the programmer. (Example:
- // SIGBUS/OBJERR.)
- address generate_handler_for_unsafe_access() {
- StubCodeMark mark(this, "StubRoutines", "handler_for_unsafe_access");
- address start = __ pc();
-
- __ push(0); // hole for return address-to-be
- __ pusha(); // push registers
- Address next_pc(rsp, RegisterImpl::number_of_registers * BytesPerWord);
-
- // FIXME: this probably needs alignment logic
-
- __ subptr(rsp, frame::arg_reg_save_area_bytes);
- BLOCK_COMMENT("call handle_unsafe_access");
- __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, handle_unsafe_access)));
- __ addptr(rsp, frame::arg_reg_save_area_bytes);
-
- __ movptr(next_pc, rax); // stuff next address
- __ popa();
- __ ret(0); // jump to next address
-
- return start;
- }
-
// Non-destructive plausibility checks for oops
//
// Arguments:
@@ -5136,9 +5095,6 @@
StubRoutines::_atomic_add_ptr_entry = generate_atomic_add_ptr();
StubRoutines::_fence_entry = generate_orderaccess_fence();
- StubRoutines::_handler_for_unsafe_access_entry =
- generate_handler_for_unsafe_access();
-
// platform dependent
StubRoutines::x86::_get_previous_fp_entry = generate_get_previous_fp();
StubRoutines::x86::_get_previous_sp_entry = generate_get_previous_sp();
--- a/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp Wed May 04 10:06:00 2016 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright 2007, 2008, 2010, 2015 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -261,10 +261,6 @@
StubRoutines::_atomic_add_entry = ShouldNotCallThisStub();
StubRoutines::_atomic_add_ptr_entry = ShouldNotCallThisStub();
StubRoutines::_fence_entry = ShouldNotCallThisStub();
-
- // amd64 does this here, sparc does it in generate_all()
- StubRoutines::_handler_for_unsafe_access_entry =
- ShouldNotCallThisStub();
}
void generate_all() {
--- a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp Wed May 04 10:06:00 2016 +0200
@@ -392,11 +392,9 @@
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
CompiledMethod* nm = cb->as_compiled_method_or_null();
if (nm != NULL && nm->has_unsafe_access()) {
- // We don't really need a stub here! Just set the pending exeption and
- // continue at the next instruction after the faulting read. Returning
- // garbage from this read is ok.
- thread->set_pending_unsafe_access_error();
- os::Aix::ucontext_set_pc(uc, pc + 4);
+ address next_pc = pc + 4;
+ next_pc = SharedRuntime::handle_unsafe_access(thread, next_pc);
+ os::Aix::ucontext_set_pc(uc, next_pc);
return 1;
}
}
@@ -415,11 +413,9 @@
}
else if (thread->thread_state() == _thread_in_vm &&
sig == SIGBUS && thread->doing_unsafe_access()) {
- // We don't really need a stub here! Just set the pending exeption and
- // continue at the next instruction after the faulting read. Returning
- // garbage from this read is ok.
- thread->set_pending_unsafe_access_error();
- os::Aix::ucontext_set_pc(uc, pc + 4);
+ address next_pc = pc + 4;
+ next_pc = SharedRuntime::handle_unsafe_access(thread, next_pc);
+ os::Aix::ucontext_set_pc(uc, next_pc);
return 1;
}
}
--- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Wed May 04 10:06:00 2016 +0200
@@ -584,7 +584,8 @@
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL;
if (nm != NULL && nm->has_unsafe_access()) {
- stub = StubRoutines::handler_for_unsafe_access();
+ address next_pc = Assembler::locate_next_instruction(pc);
+ stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
}
}
else
@@ -655,7 +656,8 @@
} else if (thread->thread_state() == _thread_in_vm &&
sig == SIGBUS && /* info->si_code == BUS_OBJERR && */
thread->doing_unsafe_access()) {
- stub = StubRoutines::handler_for_unsafe_access();
+ address next_pc = Assembler::locate_next_instruction(pc);
+ stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
}
// jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in
--- a/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp Wed May 04 10:06:00 2016 +0200
@@ -226,23 +226,6 @@
extern "C" void FetchNResume () ;
#endif
-// An operation in Unsafe has faulted. We're going to return to the
-// instruction after the faulting load or store. We also set
-// pending_unsafe_access_error so that at some point in the future our
-// user will get a helpful message.
-static address handle_unsafe_access(JavaThread* thread, address pc) {
- // pc is the instruction which we must emulate
- // doing a no-op is fine: return garbage from the load
- // therefore, compute npc
- address npc = pc + NativeCall::instruction_size;
-
- // request an async exception
- thread->set_pending_unsafe_access_error();
-
- // return address of next instruction to execute
- return npc;
-}
-
extern "C" JNIEXPORT int
JVM_handle_linux_signal(int sig,
siginfo_t* info,
@@ -387,7 +370,8 @@
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL;
if (nm != NULL && nm->has_unsafe_access()) {
- stub = handle_unsafe_access(thread, pc);
+ address next_pc = pc + NativeCall::instruction_size;
+ stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
}
}
else
@@ -408,7 +392,8 @@
} else if (thread->thread_state() == _thread_in_vm &&
sig == SIGBUS && /* info->si_code == BUS_OBJERR && */
thread->doing_unsafe_access()) {
- stub = handle_unsafe_access(thread, pc);
+ address next_pc = pc + NativeCall::instruction_size;
+ stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
}
// jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in
--- a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp Wed May 04 10:06:00 2016 +0200
@@ -366,11 +366,9 @@
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL;
if (nm != NULL && nm->has_unsafe_access()) {
- // We don't really need a stub here! Just set the pending exeption and
- // continue at the next instruction after the faulting read. Returning
- // garbage from this read is ok.
- thread->set_pending_unsafe_access_error();
- os::Linux::ucontext_set_pc(uc, pc + 4);
+ address next_pc = pc + 4;
+ next_pc = SharedRuntime::handle_unsafe_access(thread, next_pc);
+ os::Linux::ucontext_set_pc(uc, next_pc);
return true;
}
}
@@ -385,10 +383,8 @@
}
else if (thread->thread_state() == _thread_in_vm &&
sig == SIGBUS && thread->doing_unsafe_access()) {
- // We don't really need a stub here! Just set the pending exeption and
- // continue at the next instruction after the faulting read. Returning
- // garbage from this read is ok.
- thread->set_pending_unsafe_access_error();
+ address next_pc = pc + 4;
+ next_pc = SharedRuntime::handle_unsafe_access(thread, next_pc);
os::Linux::ucontext_set_pc(uc, pc + 4);
return true;
}
--- a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp Wed May 04 10:06:00 2016 +0200
@@ -433,14 +433,14 @@
return false;
}
-inline static bool checkByteBuffer(address pc, address* stub) {
+inline static bool checkByteBuffer(address pc, address npc, address* stub) {
// BugId 4454115: A read from a MappedByteBuffer can fault
// here if the underlying file has been truncated.
// Do not crash the VM in such a case.
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
CompiledMethod* nm = cb->as_compiled_method_or_null();
if (nm != NULL && nm->has_unsafe_access()) {
- *stub = StubRoutines::handler_for_unsafe_access();
+ *stub = SharedRuntime::handle_unsafe_access(thread, npc);
return true;
}
return false;
@@ -613,7 +613,7 @@
if (sig == SIGBUS &&
thread->thread_state() == _thread_in_vm &&
thread->doing_unsafe_access()) {
- stub = StubRoutines::handler_for_unsafe_access();
+ stub = SharedRuntime::handle_unsafe_access(thread, npc);
}
if (thread->thread_state() == _thread_in_Java) {
@@ -625,7 +625,7 @@
break;
}
- if ((sig == SIGBUS) && checkByteBuffer(pc, &stub)) {
+ if ((sig == SIGBUS) && checkByteBuffer(pc, npc, &stub)) {
break;
}
--- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Wed May 04 10:06:00 2016 +0200
@@ -420,7 +420,8 @@
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL;
if (nm != NULL && nm->has_unsafe_access()) {
- stub = StubRoutines::handler_for_unsafe_access();
+ address next_pc = Assembler::locate_next_instruction(pc);
+ stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
}
}
else
@@ -469,7 +470,8 @@
} else if (thread->thread_state() == _thread_in_vm &&
sig == SIGBUS && /* info->si_code == BUS_OBJERR && */
thread->doing_unsafe_access()) {
- stub = StubRoutines::handler_for_unsafe_access();
+ address next_pc = Assembler::locate_next_instruction(pc);
+ stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
}
// jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in
--- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Wed May 04 10:06:00 2016 +0200
@@ -441,7 +441,7 @@
if (thread->thread_state() == _thread_in_vm) {
if (sig == SIGBUS && info->si_code == BUS_OBJERR && thread->doing_unsafe_access()) {
- stub = StubRoutines::handler_for_unsafe_access();
+ stub = SharedRuntime::handle_unsafe_access(thread, npc);
}
}
@@ -480,7 +480,7 @@
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
CompiledMethod* nm = cb->as_compiled_method_or_null();
if (nm != NULL && nm->has_unsafe_access()) {
- stub = StubRoutines::handler_for_unsafe_access();
+ stub = SharedRuntime::handle_unsafe_access(thread, npc);
}
}
--- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Wed May 04 10:06:00 2016 +0200
@@ -503,7 +503,8 @@
if (thread->thread_state() == _thread_in_vm) {
if (sig == SIGBUS && info->si_code == BUS_OBJERR && thread->doing_unsafe_access()) {
- stub = StubRoutines::handler_for_unsafe_access();
+ address next_pc = Assembler::locate_next_instruction(pc);
+ stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
}
}
@@ -520,7 +521,8 @@
if (cb != NULL) {
CompiledMethod* nm = cb->as_compiled_method_or_null();
if (nm != NULL && nm->has_unsafe_access()) {
- stub = StubRoutines::handler_for_unsafe_access();
+ address next_pc = Assembler::locate_next_instruction(pc);
+ stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
}
}
}
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Wed May 04 10:06:00 2016 +0200
@@ -50,11 +50,11 @@
BlockList* _bci2block; // mapping from bci to blocks for GraphBuilder
// fields used by mark_loops
- BitMap _active; // for iteration of control flow graph
- BitMap _visited; // for iteration of control flow graph
- intArray _loop_map; // caches the information if a block is contained in a loop
- int _next_loop_index; // next free loop number
- int _next_block_number; // for reverse postorder numbering of blocks
+ ResourceBitMap _active; // for iteration of control flow graph
+ ResourceBitMap _visited; // for iteration of control flow graph
+ intArray _loop_map; // caches the information if a block is contained in a loop
+ int _next_loop_index; // next free loop number
+ int _next_block_number; // for reverse postorder numbering of blocks
// accessors
Compilation* compilation() const { return _compilation; }
@@ -227,7 +227,7 @@
// Without it, backward branches could jump to a bci where no block was created
// during bytecode iteration. This would require the creation of a new block at the
// branch target and a modification of the successor lists.
- BitMap bci_block_start = method()->bci_block_start();
+ const BitMap& bci_block_start = method()->bci_block_start();
ciBytecodeStream s(method());
while (s.next() != ciBytecodeStream::EOBC()) {
@@ -355,8 +355,8 @@
void BlockListBuilder::mark_loops() {
ResourceMark rm;
- _active = BitMap(BlockBegin::number_of_blocks()); _active.clear();
- _visited = BitMap(BlockBegin::number_of_blocks()); _visited.clear();
+ _active.initialize(BlockBegin::number_of_blocks());
+ _visited.initialize(BlockBegin::number_of_blocks());
_loop_map = intArray(BlockBegin::number_of_blocks(), BlockBegin::number_of_blocks(), 0);
_next_loop_index = 0;
_next_block_number = _blocks.length();
@@ -364,6 +364,10 @@
// recursively iterate the control flow graph
mark_loops(_bci2block->at(0), false);
assert(_next_block_number >= 0, "invalid block numbers");
+
+ // Remove dangling Resource pointers before the ResourceMark goes out-of-scope.
+ _active.resize(0);
+ _visited.resize(0);
}
void BlockListBuilder::make_loop_header(BlockBegin* block) {
@@ -3076,7 +3080,7 @@
Value local;
// find all the locals that the interpreter thinks contain live oops
- const BitMap live_oops = method()->live_local_oops_at_bci(osr_bci);
+ const ResourceBitMap live_oops = method()->live_local_oops_at_bci(osr_bci);
// compute the offset into the locals so that we can treat the buffer
// as if the locals were still in the interpreter frame
--- a/hotspot/src/share/vm/c1/c1_IR.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/c1/c1_IR.cpp Wed May 04 10:06:00 2016 +0200
@@ -460,14 +460,14 @@
BlockList* _linear_scan_order; // the resulting list of blocks in correct order
- BitMap _visited_blocks; // used for recursive processing of blocks
- BitMap _active_blocks; // used for recursive processing of blocks
- BitMap _dominator_blocks; // temproary BitMap used for computation of dominator
- intArray _forward_branches; // number of incoming forward branches for each block
- BlockList _loop_end_blocks; // list of all loop end blocks collected during count_edges
- BitMap2D _loop_map; // two-dimensional bit set: a bit is set if a block is contained in a loop
- BlockList _work_list; // temporary list (used in mark_loops and compute_order)
- BlockList _loop_headers;
+ ResourceBitMap _visited_blocks; // used for recursive processing of blocks
+ ResourceBitMap _active_blocks; // used for recursive processing of blocks
+ ResourceBitMap _dominator_blocks; // temproary BitMap used for computation of dominator
+ intArray _forward_branches; // number of incoming forward branches for each block
+ BlockList _loop_end_blocks; // list of all loop end blocks collected during count_edges
+ BitMap2D _loop_map; // two-dimensional bit set: a bit is set if a block is contained in a loop
+ BlockList _work_list; // temporary list (used in mark_loops and compute_order)
+ BlockList _loop_headers;
Compilation* _compilation;
@@ -535,7 +535,7 @@
_loop_end_blocks(8),
_work_list(8),
_linear_scan_order(NULL), // initialized later with correct size
- _loop_map(0, 0), // initialized later with correct size
+ _loop_map(0), // initialized later with correct size
_compilation(c)
{
TRACE_LINEAR_SCAN(2, tty->print_cr("***** computing linear-scan block order"));
--- a/hotspot/src/share/vm/c1/c1_IR.hpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/c1/c1_IR.hpp Wed May 04 10:06:00 2016 +0200
@@ -151,7 +151,7 @@
bool _wrote_volatile; // has written volatile field
BlockBegin* _start; // the start block, successsors are method entries
- BitMap _requires_phi_function; // bit is set if phi functions at loop headers are necessary for a local variable
+ ResourceBitMap _requires_phi_function; // bit is set if phi functions at loop headers are necessary for a local variable
// helper functions
BlockBegin* build_graph(Compilation* compilation, int osr_bci);
--- a/hotspot/src/share/vm/c1/c1_Instruction.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/c1/c1_Instruction.cpp Wed May 04 10:06:00 2016 +0200
@@ -787,7 +787,7 @@
TRACE_PHI(tty->print_cr("creating phi-function %c%d for stack %d", new_state->stack_at(index)->type()->tchar(), new_state->stack_at(index)->id(), index));
}
- BitMap requires_phi_function = new_state->scope()->requires_phi_function();
+ BitMap& requires_phi_function = new_state->scope()->requires_phi_function();
for_each_local_value(new_state, index, new_value) {
bool requires_phi = requires_phi_function.at(index) || (new_value->type()->is_double_word() && requires_phi_function.at(index + 1));
--- a/hotspot/src/share/vm/c1/c1_Instruction.hpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/c1/c1_Instruction.hpp Wed May 04 10:06:00 2016 +0200
@@ -1596,8 +1596,8 @@
int _flags; // the flags associated with this block
// fields used by BlockListBuilder
- int _total_preds; // number of predecessors found by BlockListBuilder
- BitMap _stores_to_locals; // bit is set when a local variable is stored in the block
+ int _total_preds; // number of predecessors found by BlockListBuilder
+ ResourceBitMap _stores_to_locals; // bit is set when a local variable is stored in the block
// SSA specific fields: (factor out later)
BlockList _successors; // the successors of this block
@@ -1614,15 +1614,15 @@
Label _label; // the label associated with this block
LIR_List* _lir; // the low level intermediate representation for this block
- BitMap _live_in; // set of live LIR_Opr registers at entry to this block
- BitMap _live_out; // set of live LIR_Opr registers at exit from this block
- BitMap _live_gen; // set of registers used before any redefinition in this block
- BitMap _live_kill; // set of registers defined in this block
-
- BitMap _fpu_register_usage;
- intArray* _fpu_stack_state; // For x86 FPU code generation with UseLinearScan
- int _first_lir_instruction_id; // ID of first LIR instruction in this block
- int _last_lir_instruction_id; // ID of last LIR instruction in this block
+ ResourceBitMap _live_in; // set of live LIR_Opr registers at entry to this block
+ ResourceBitMap _live_out; // set of live LIR_Opr registers at exit from this block
+ ResourceBitMap _live_gen; // set of registers used before any redefinition in this block
+ ResourceBitMap _live_kill; // set of registers defined in this block
+
+ ResourceBitMap _fpu_register_usage;
+ intArray* _fpu_stack_state; // For x86 FPU code generation with UseLinearScan
+ int _first_lir_instruction_id; // ID of first LIR instruction in this block
+ int _last_lir_instruction_id; // ID of last LIR instruction in this block
void iterate_preorder (boolArray& mark, BlockClosure* closure);
void iterate_postorder(boolArray& mark, BlockClosure* closure);
@@ -1693,11 +1693,11 @@
Label* label() { return &_label; }
LIR_List* lir() const { return _lir; }
int exception_handler_pco() const { return _exception_handler_pco; }
- BitMap& live_in() { return _live_in; }
- BitMap& live_out() { return _live_out; }
- BitMap& live_gen() { return _live_gen; }
- BitMap& live_kill() { return _live_kill; }
- BitMap& fpu_register_usage() { return _fpu_register_usage; }
+ ResourceBitMap& live_in() { return _live_in; }
+ ResourceBitMap& live_out() { return _live_out; }
+ ResourceBitMap& live_gen() { return _live_gen; }
+ ResourceBitMap& live_kill() { return _live_kill; }
+ ResourceBitMap& fpu_register_usage() { return _fpu_register_usage; }
intArray* fpu_stack_state() const { return _fpu_stack_state; }
int first_lir_instruction_id() const { return _first_lir_instruction_id; }
int last_lir_instruction_id() const { return _last_lir_instruction_id; }
@@ -1718,16 +1718,16 @@
void substitute_sux(BlockBegin* old_sux, BlockBegin* new_sux);
void set_lir(LIR_List* lir) { _lir = lir; }
void set_exception_handler_pco(int pco) { _exception_handler_pco = pco; }
- void set_live_in (BitMap map) { _live_in = map; }
- void set_live_out (BitMap map) { _live_out = map; }
- void set_live_gen (BitMap map) { _live_gen = map; }
- void set_live_kill (BitMap map) { _live_kill = map; }
- void set_fpu_register_usage(BitMap map) { _fpu_register_usage = map; }
+ void set_live_in (const ResourceBitMap& map) { _live_in = map; }
+ void set_live_out (const ResourceBitMap& map) { _live_out = map; }
+ void set_live_gen (const ResourceBitMap& map) { _live_gen = map; }
+ void set_live_kill(const ResourceBitMap& map) { _live_kill = map; }
+ void set_fpu_register_usage(const ResourceBitMap& map) { _fpu_register_usage = map; }
void set_fpu_stack_state(intArray* state) { _fpu_stack_state = state; }
void set_first_lir_instruction_id(int id) { _first_lir_instruction_id = id; }
void set_last_lir_instruction_id(int id) { _last_lir_instruction_id = id; }
void increment_total_preds(int n = 1) { _total_preds += n; }
- void init_stores_to_locals(int locals_count) { _stores_to_locals = BitMap(locals_count); _stores_to_locals.clear(); }
+ void init_stores_to_locals(int locals_count) { _stores_to_locals.initialize(locals_count); }
// generic
virtual void state_values_do(ValueVisitor* f);
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp Wed May 04 10:06:00 2016 +0200
@@ -470,7 +470,7 @@
: _compilation(compilation)
, _method(method)
, _virtual_register_number(LIR_OprDesc::vreg_base)
- , _vreg_flags(NULL, 0, num_vreg_flags) {
+ , _vreg_flags(num_vreg_flags) {
init();
}
--- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp Wed May 04 10:06:00 2016 +0200
@@ -88,7 +88,7 @@
, _has_info(0)
, _has_call(0)
, _scope_value_cache(0) // initialized later with correct length
- , _interval_in_loop(0, 0) // initialized later with correct length
+ , _interval_in_loop(0) // initialized later with correct length
, _cached_blocks(*ir->linear_scan_order())
#ifdef X86
, _fpu_stack_allocator(NULL)
@@ -524,8 +524,8 @@
assert(idx == num_instructions, "must match");
assert(idx * 2 == op_id, "must match");
- _has_call = BitMap(num_instructions); _has_call.clear();
- _has_info = BitMap(num_instructions); _has_info.clear();
+ _has_call.initialize(num_instructions);
+ _has_info.initialize(num_instructions);
}
@@ -568,8 +568,8 @@
for (int i = 0; i < num_blocks; i++) {
BlockBegin* block = block_at(i);
- BitMap live_gen(live_size); live_gen.clear();
- BitMap live_kill(live_size); live_kill.clear();
+ ResourceBitMap live_gen(live_size); live_gen.clear();
+ ResourceBitMap live_kill(live_size); live_kill.clear();
if (block->is_set(BlockBegin::exception_entry_flag)) {
// Phi functions at the begin of an exception handler are
@@ -715,8 +715,8 @@
block->set_live_gen (live_gen);
block->set_live_kill(live_kill);
- block->set_live_in (BitMap(live_size)); block->live_in().clear();
- block->set_live_out (BitMap(live_size)); block->live_out().clear();
+ block->set_live_in (ResourceBitMap(live_size)); block->live_in().clear();
+ block->set_live_out (ResourceBitMap(live_size)); block->live_out().clear();
TRACE_LINEAR_SCAN(4, tty->print("live_gen B%d ", block->block_id()); print_bitmap(block->live_gen()));
TRACE_LINEAR_SCAN(4, tty->print("live_kill B%d ", block->block_id()); print_bitmap(block->live_kill()));
@@ -741,7 +741,7 @@
bool change_occurred;
bool change_occurred_in_block;
int iteration_count = 0;
- BitMap live_out(live_set_size()); live_out.clear(); // scratch set for calculations
+ ResourceBitMap live_out(live_set_size()); live_out.clear(); // scratch set for calculations
// Perform a backward dataflow analysis to compute live_out and live_in for each block.
// The loop is executed until a fixpoint is reached (no changes in an iteration)
@@ -775,7 +775,7 @@
if (!block->live_out().is_same(live_out)) {
// A change occurred. Swap the old and new live out sets to avoid copying.
- BitMap temp = block->live_out();
+ ResourceBitMap temp = block->live_out();
block->set_live_out(live_out);
live_out = temp;
@@ -787,7 +787,7 @@
if (iteration_count == 0 || change_occurred_in_block) {
// live_in(block) is the union of live_gen(block) with (live_out(block) & !live_kill(block))
// note: live_in has to be computed only in first iteration or if live_out has changed!
- BitMap live_in = block->live_in();
+ ResourceBitMap live_in = block->live_in();
live_in.set_from(block->live_out());
live_in.set_difference(block->live_kill());
live_in.set_union(block->live_gen());
@@ -826,7 +826,7 @@
#endif
// check that the live_in set of the first block is empty
- BitMap live_in_args(ir()->start()->live_in().size());
+ ResourceBitMap live_in_args(ir()->start()->live_in().size());
live_in_args.clear();
if (!ir()->start()->live_in().is_same(live_in_args)) {
#ifdef ASSERT
@@ -1317,7 +1317,7 @@
assert(block_to == instructions->at(instructions->length() - 1)->id(), "must be");
// Update intervals for registers live at the end of this block;
- BitMap live = block->live_out();
+ ResourceBitMap live = block->live_out();
int size = (int)live.size();
for (int number = (int)live.get_next_one_offset(0, size); number < size; number = (int)live.get_next_one_offset(number + 1, size)) {
assert(live.at(number), "should not stop here otherwise");
@@ -1717,7 +1717,7 @@
const int num_regs = num_virtual_regs();
const int size = live_set_size();
- const BitMap live_at_edge = to_block->live_in();
+ const ResourceBitMap live_at_edge = to_block->live_in();
// visit all registers where the live_at_edge bit is set
for (int r = (int)live_at_edge.get_next_one_offset(0, size); r < size; r = (int)live_at_edge.get_next_one_offset(r + 1, size)) {
@@ -1774,8 +1774,8 @@
int num_blocks = block_count();
MoveResolver move_resolver(this);
- BitMap block_completed(num_blocks); block_completed.clear();
- BitMap already_resolved(num_blocks); already_resolved.clear();
+ ResourceBitMap block_completed(num_blocks); block_completed.clear();
+ ResourceBitMap already_resolved(num_blocks); already_resolved.clear();
int i;
for (i = 0; i < num_blocks; i++) {
@@ -3397,7 +3397,7 @@
for (int i = 0; i < num_blocks; i++) {
BlockBegin* block = block_at(i);
- BitMap live_at_edge = block->live_in();
+ ResourceBitMap live_at_edge = block->live_in();
// visit all registers where the live_at_edge bit is set
for (int r = (int)live_at_edge.get_next_one_offset(0, size); r < size; r = (int)live_at_edge.get_next_one_offset(r + 1, size)) {
@@ -3749,7 +3749,7 @@
}
- BitMap used_regs(LinearScan::nof_regs + allocator()->frame_map()->argcount() + allocator()->max_spills());
+ ResourceBitMap used_regs(LinearScan::nof_regs + allocator()->frame_map()->argcount() + allocator()->max_spills());
used_regs.clear();
if (!_multiple_reads_allowed) {
for (i = 0; i < _mapping_from.length(); i++) {
@@ -6317,7 +6317,7 @@
void ControlFlowOptimizer::delete_jumps_to_return(BlockList* code) {
#ifdef ASSERT
- BitMap return_converted(BlockBegin::number_of_blocks());
+ ResourceBitMap return_converted(BlockBegin::number_of_blocks());
return_converted.clear();
#endif
--- a/hotspot/src/share/vm/c1/c1_LinearScan.hpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/c1/c1_LinearScan.hpp Wed May 04 10:06:00 2016 +0200
@@ -140,8 +140,8 @@
LIR_OpArray _lir_ops; // mapping from LIR_Op id to LIR_Op node
BlockBeginArray _block_of_op; // mapping from LIR_Op id to the BlockBegin containing this instruction
- BitMap _has_info; // bit set for each LIR_Op id that has a CodeEmitInfo
- BitMap _has_call; // bit set for each LIR_Op id that destroys all caller save registers
+ ResourceBitMap _has_info; // bit set for each LIR_Op id that has a CodeEmitInfo
+ ResourceBitMap _has_call; // bit set for each LIR_Op id that destroys all caller save registers
BitMap2D _interval_in_loop; // bit set for each virtual register that is contained in each loop
// cached debug info to prevent multiple creation of same object
--- a/hotspot/src/share/vm/c1/c1_ValueSet.hpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/c1/c1_ValueSet.hpp Wed May 04 10:06:00 2016 +0200
@@ -36,7 +36,7 @@
class ValueSet: public CompilationResourceObj {
private:
- BitMap _map;
+ ResourceBitMap _map;
public:
ValueSet();
--- a/hotspot/src/share/vm/ci/ciMethod.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp Wed May 04 10:06:00 2016 +0200
@@ -443,12 +443,12 @@
// gc'ing an interpreter frame we need to use its viewpoint during
// OSR when loading the locals.
-BitMap ciMethod::live_local_oops_at_bci(int bci) {
+ResourceBitMap ciMethod::live_local_oops_at_bci(int bci) {
VM_ENTRY_MARK;
InterpreterOopMap mask;
OopMapCache::compute_one_oop_map(get_Method(), bci, &mask);
int mask_size = max_locals();
- BitMap result(mask_size);
+ ResourceBitMap result(mask_size);
result.clear();
int i;
for (i = 0; i < mask_size ; i++ ) {
@@ -463,7 +463,7 @@
// ciMethod::bci_block_start
//
// Marks all bcis where a new basic block starts
-const BitMap ciMethod::bci_block_start() {
+const BitMap& ciMethod::bci_block_start() {
check_is_loaded();
if (_liveness == NULL) {
// Create the liveness analyzer.
--- a/hotspot/src/share/vm/ci/ciMethod.hpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/ci/ciMethod.hpp Wed May 04 10:06:00 2016 +0200
@@ -36,7 +36,6 @@
class ciMethodBlocks;
class MethodLiveness;
-class BitMap;
class Arena;
class BCEscapeAnalyzer;
class InlineTree;
@@ -233,10 +232,10 @@
// used when gc'ing an interpreter frame we need to use its viewpoint
// during OSR when loading the locals.
- BitMap live_local_oops_at_bci(int bci);
+ ResourceBitMap live_local_oops_at_bci(int bci);
#ifdef COMPILER1
- const BitMap bci_block_start();
+ const BitMap& bci_block_start();
#endif
ciTypeFlow* get_flow_analysis();
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Wed May 04 10:06:00 2016 +0200
@@ -3967,7 +3967,7 @@
next_nonstatic_padded_offset += ContendedPaddingWidth;
// collect all contended groups
- BitMap bm(cp->size());
+ ResourceBitMap bm(cp->size());
for (AllFieldStream fs(_fields, cp); !fs.done(); fs.next()) {
// skip already laid out fields
if (fs.is_offset_set()) continue;
--- a/hotspot/src/share/vm/compiler/methodLiveness.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/compiler/methodLiveness.cpp Wed May 04 10:06:00 2016 +0200
@@ -131,13 +131,13 @@
MethodLiveness::MethodLiveness(Arena* arena, ciMethod* method)
#ifdef COMPILER1
- : _bci_block_start((uintptr_t*)arena->Amalloc((method->code_size() >> LogBitsPerByte) + 1), method->code_size())
+ : _bci_block_start(arena, method->code_size())
#endif
{
_arena = arena;
_method = method;
_bit_map_size_bits = method->max_locals();
- _bit_map_size_words = (_bit_map_size_bits / sizeof(unsigned int)) + 1;
+
#ifdef COMPILER1
_bci_block_start.clear();
@@ -475,7 +475,7 @@
bci = 0;
}
- MethodLivenessResult answer((BitMap::bm_word_t*)NULL,0);
+ MethodLivenessResult answer;
if (_block_count > 0) {
if (TimeLivenessAnalysis) _time_total.start();
@@ -574,16 +574,11 @@
MethodLiveness::BasicBlock::BasicBlock(MethodLiveness *analyzer, int start, int limit) :
- _gen((uintptr_t*)analyzer->arena()->Amalloc(BytesPerWord * analyzer->bit_map_size_words()),
- analyzer->bit_map_size_bits()),
- _kill((uintptr_t*)analyzer->arena()->Amalloc(BytesPerWord * analyzer->bit_map_size_words()),
- analyzer->bit_map_size_bits()),
- _entry((uintptr_t*)analyzer->arena()->Amalloc(BytesPerWord * analyzer->bit_map_size_words()),
- analyzer->bit_map_size_bits()),
- _normal_exit((uintptr_t*)analyzer->arena()->Amalloc(BytesPerWord * analyzer->bit_map_size_words()),
- analyzer->bit_map_size_bits()),
- _exception_exit((uintptr_t*)analyzer->arena()->Amalloc(BytesPerWord * analyzer->bit_map_size_words()),
- analyzer->bit_map_size_bits()),
+ _gen(analyzer->arena(), analyzer->bit_map_size_bits()),
+ _kill(analyzer->arena(), analyzer->bit_map_size_bits()),
+ _entry(analyzer->arena(), analyzer->bit_map_size_bits()),
+ _normal_exit(analyzer->arena(), analyzer->bit_map_size_bits()),
+ _exception_exit(analyzer->arena(), analyzer->bit_map_size_bits()),
_last_bci(-1) {
_analyzer = analyzer;
_start_bci = start;
@@ -991,17 +986,16 @@
}
}
-bool MethodLiveness::BasicBlock::merge_normal(BitMap other) {
+bool MethodLiveness::BasicBlock::merge_normal(const BitMap& other) {
return _normal_exit.set_union_with_result(other);
}
-bool MethodLiveness::BasicBlock::merge_exception(BitMap other) {
+bool MethodLiveness::BasicBlock::merge_exception(const BitMap& other) {
return _exception_exit.set_union_with_result(other);
}
MethodLivenessResult MethodLiveness::BasicBlock::get_liveness_at(ciMethod* method, int bci) {
- MethodLivenessResult answer(NEW_RESOURCE_ARRAY(BitMap::bm_word_t, _analyzer->bit_map_size_words()),
- _analyzer->bit_map_size_bits());
+ MethodLivenessResult answer(_analyzer->bit_map_size_bits());
answer.set_is_valid();
#ifndef ASSERT
@@ -1013,8 +1007,8 @@
#ifdef ASSERT
ResourceMark rm;
- BitMap g(_gen.size()); g.set_from(_gen);
- BitMap k(_kill.size()); k.set_from(_kill);
+ ResourceBitMap g(_gen.size()); g.set_from(_gen);
+ ResourceBitMap k(_kill.size()); k.set_from(_kill);
#endif
if (_last_bci != bci || trueInDebug) {
ciBytecodeStream bytes(method);
--- a/hotspot/src/share/vm/compiler/methodLiveness.hpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/compiler/methodLiveness.hpp Wed May 04 10:06:00 2016 +0200
@@ -30,18 +30,18 @@
class ciMethod;
-class MethodLivenessResult : public BitMap {
+class MethodLivenessResult : public ResourceBitMap {
private:
bool _is_valid;
public:
- MethodLivenessResult(BitMap::bm_word_t* map, idx_t size_in_bits)
- : BitMap(map, size_in_bits)
+ MethodLivenessResult()
+ : ResourceBitMap()
, _is_valid(false)
{}
MethodLivenessResult(idx_t size_in_bits)
- : BitMap(size_in_bits)
+ : ResourceBitMap(size_in_bits)
, _is_valid(false)
{}
@@ -66,23 +66,23 @@
int _limit_bci;
// The liveness at the start of the block;
- BitMap _entry;
+ ArenaBitMap _entry;
// The summarized liveness effects of our direct successors reached
// by normal control flow
- BitMap _normal_exit;
+ ArenaBitMap _normal_exit;
// The summarized liveness effects of our direct successors reached
// by exceptional control flow
- BitMap _exception_exit;
+ ArenaBitMap _exception_exit;
// These members hold the results of the last call to
// compute_gen_kill_range(). _gen is the set of locals
// used before they are defined in the range. _kill is the
// set of locals defined before they are used.
- BitMap _gen;
- BitMap _kill;
- int _last_bci;
+ ArenaBitMap _gen;
+ ArenaBitMap _kill;
+ int _last_bci;
// A list of all blocks which could come directly before this one
// in normal (non-exceptional) control flow. We propagate liveness
@@ -100,11 +100,11 @@
// Our successors call this method to merge liveness information into
// our _normal_exit member.
- bool merge_normal(BitMap other);
+ bool merge_normal(const BitMap& other);
// Our successors call this method to merge liveness information into
// our _exception_exit member.
- bool merge_exception(BitMap other);
+ bool merge_exception(const BitMap& other);
// This helper routine is used to help compute the gen/kill pair for
// the block. It is also used to answer queries.
@@ -181,7 +181,6 @@
// The size of a BitMap.
int _bit_map_size_bits;
- int _bit_map_size_words;
// A list of all BasicBlocks.
BasicBlock **_block_list;
@@ -198,7 +197,7 @@
#ifdef COMPILER1
// bcis where blocks start are marked
- BitMap _bci_block_start;
+ ArenaBitMap _bci_block_start;
#endif // COMPILER1
// -- Graph construction & Analysis
@@ -218,7 +217,6 @@
// And accessors.
int bit_map_size_bits() const { return _bit_map_size_bits; }
- int bit_map_size_words() const { return _bit_map_size_words; }
// Work list manipulation routines. Called internally by BasicBlock.
BasicBlock *work_list_get();
@@ -270,7 +268,7 @@
MethodLivenessResult get_liveness_at(int bci);
#ifdef COMPILER1
- const BitMap get_bci_block_start() const { return _bci_block_start; }
+ const BitMap& get_bci_block_start() const { return _bci_block_start; }
#endif // COMPILER1
static void print_times() PRODUCT_RETURN;
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp Wed May 04 10:06:00 2016 +0200
@@ -5666,10 +5666,9 @@
}
assert(_virtual_space.committed_size() == brs.size(),
"didn't reserve backing store for all of CMS bit map?");
- _bm.set_map((BitMap::bm_word_t*)_virtual_space.low());
assert(_virtual_space.committed_size() << (_shifter + LogBitsPerByte) >=
_bmWordSize, "inconsistency in bit map sizing");
- _bm.set_size(_bmWordSize >> _shifter);
+ _bm = BitMapView((BitMap::bm_word_t*)_virtual_space.low(), _bmWordSize >> _shifter);
// bm.clear(); // can we rely on getting zero'd memory? verify below
assert(isAllClear(),
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp Wed May 04 10:06:00 2016 +0200
@@ -83,13 +83,12 @@
class CMSBitMap VALUE_OBJ_CLASS_SPEC {
friend class VMStructs;
- HeapWord* _bmStartWord; // base address of range covered by map
- size_t _bmWordSize; // map size (in #HeapWords covered)
- const int _shifter; // shifts to convert HeapWord to bit position
+ HeapWord* _bmStartWord; // base address of range covered by map
+ size_t _bmWordSize; // map size (in #HeapWords covered)
+ const int _shifter; // shifts to convert HeapWord to bit position
VirtualSpace _virtual_space; // underlying the bit map
- BitMap _bm; // the bit map itself
- public:
- Mutex* const _lock; // mutex protecting _bm;
+ BitMapView _bm; // the bit map itself
+ Mutex* const _lock; // mutex protecting _bm;
public:
// constructor
--- a/hotspot/src/share/vm/gc/cms/vmStructs_cms.hpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/gc/cms/vmStructs_cms.hpp Wed May 04 10:06:00 2016 +0200
@@ -33,7 +33,7 @@
\
nonstatic_field(CMSBitMap, _bmWordSize, size_t) \
nonstatic_field(CMSBitMap, _shifter, const int) \
- nonstatic_field(CMSBitMap, _bm, BitMap) \
+ nonstatic_field(CMSBitMap, _bm, BitMapView) \
nonstatic_field(CMSBitMap, _virtual_space, VirtualSpace) \
nonstatic_field(CMSCollector, _markBitMap, CMSBitMap) \
nonstatic_field(ConcurrentMarkSweepGeneration, _cmsSpace, CompactibleFreeListSpace*) \
--- a/hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp Wed May 04 10:06:00 2016 +0200
@@ -95,8 +95,8 @@
// information.
class G1CardLiveDataHelper VALUE_OBJ_CLASS_SPEC {
private:
- BitMap _region_bm;
- BitMap _card_bm;
+ BitMapView _region_bm;
+ BitMapView _card_bm;
// The card number of the bottom of the G1 heap.
// Used in biasing indices into accounting card bitmaps.
@@ -393,11 +393,11 @@
}
class G1ClearCardLiveDataTask : public AbstractGangTask {
- BitMap _bitmap;
- size_t _num_chunks;
- size_t _cur_chunk;
+ BitMapView _bitmap;
+ size_t _num_chunks;
+ size_t _cur_chunk;
public:
- G1ClearCardLiveDataTask(BitMap bitmap, size_t num_tasks) :
+ G1ClearCardLiveDataTask(const BitMapView& bitmap, size_t num_tasks) :
AbstractGangTask("G1 Clear Card Live Data"),
_bitmap(bitmap),
_num_chunks(num_tasks),
--- a/hotspot/src/share/vm/gc/g1/g1CardLiveData.hpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1CardLiveData.hpp Wed May 04 10:06:00 2016 +0200
@@ -65,15 +65,15 @@
size_t _live_regions_size_in_bits;
// The bits in this bitmap contain for every card whether it contains
// at least part of at least one live object.
- BitMap live_cards_bm() const { return BitMap(_live_cards, _live_cards_size_in_bits); }
+ BitMapView live_cards_bm() const { return BitMapView(_live_cards, _live_cards_size_in_bits); }
// The bits in this bitmap indicate that a given region contains some live objects.
- BitMap live_regions_bm() const { return BitMap(_live_regions, _live_regions_size_in_bits); }
+ BitMapView live_regions_bm() const { return BitMapView(_live_regions, _live_regions_size_in_bits); }
// Allocate a "large" bitmap from virtual memory with the given size in bits.
bm_word_t* allocate_large_bitmap(size_t size_in_bits);
void free_large_bitmap(bm_word_t* map, size_t size_in_bits);
- inline BitMap live_card_bitmap(uint region);
+ inline BitMapView live_card_bitmap(uint region);
inline bool is_card_live_at(BitMap::idx_t idx) const;
--- a/hotspot/src/share/vm/gc/g1/g1CardLiveData.inline.hpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1CardLiveData.inline.hpp Wed May 04 10:06:00 2016 +0200
@@ -29,8 +29,8 @@
#include "utilities/bitMap.inline.hpp"
#include "utilities/globalDefinitions.hpp"
-inline BitMap G1CardLiveData::live_card_bitmap(uint region) {
- return BitMap(_live_cards + ((size_t)region * _cards_per_region >> LogBitsPerWord), _cards_per_region);
+inline BitMapView G1CardLiveData::live_card_bitmap(uint region) {
+ return BitMapView(_live_cards + ((size_t)region * _cards_per_region >> LogBitsPerWord), _cards_per_region);
}
inline bool G1CardLiveData::is_card_live_at(BitMap::idx_t idx) const {
--- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp Wed May 04 10:06:00 2016 +0200
@@ -110,8 +110,7 @@
_bmStartWord = heap.start();
_bmWordSize = heap.word_size();
- _bm.set_map((BitMap::bm_word_t*) storage->reserved().start());
- _bm.set_size(_bmWordSize >> _shifter);
+ _bm = BitMapView((BitMap::bm_word_t*) storage->reserved().start(), _bmWordSize >> _shifter);
storage->set_mapping_changed_listener(&_listener);
}
--- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp Wed May 04 10:06:00 2016 +0200
@@ -59,10 +59,10 @@
class G1CMBitMapRO VALUE_OBJ_CLASS_SPEC {
protected:
- HeapWord* _bmStartWord; // base address of range covered by map
- size_t _bmWordSize; // map size (in #HeapWords covered)
- const int _shifter; // map to char or bit
- BitMap _bm; // the bit map itself
+ HeapWord* _bmStartWord; // base address of range covered by map
+ size_t _bmWordSize; // map size (in #HeapWords covered)
+ const int _shifter; // map to char or bit
+ BitMapView _bm; // the bit map itself
public:
// constructor
--- a/hotspot/src/share/vm/gc/g1/g1PageBasedVirtualSpace.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1PageBasedVirtualSpace.cpp Wed May 04 10:06:00 2016 +0200
@@ -75,19 +75,15 @@
vmassert(_committed.size() == 0, "virtual space initialized more than once");
BitMap::idx_t size_in_pages = rs.size() / page_size;
- _committed.resize(size_in_pages, /* in_resource_area */ false);
+ _committed.initialize(size_in_pages);
if (_special) {
- _dirty.resize(size_in_pages, /* in_resource_area */ false);
+ _dirty.initialize(size_in_pages);
}
_tail_size = used_size % _page_size;
}
G1PageBasedVirtualSpace::~G1PageBasedVirtualSpace() {
- release();
-}
-
-void G1PageBasedVirtualSpace::release() {
// This does not release memory it never reserved.
// Caller must release via rs.release();
_low_boundary = NULL;
@@ -96,8 +92,6 @@
_executable = false;
_page_size = 0;
_tail_size = 0;
- _committed.resize(0, false);
- _dirty.resize(0, false);
}
size_t G1PageBasedVirtualSpace::committed_size() const {
--- a/hotspot/src/share/vm/gc/g1/g1PageBasedVirtualSpace.hpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1PageBasedVirtualSpace.hpp Wed May 04 10:06:00 2016 +0200
@@ -57,13 +57,13 @@
size_t _page_size;
// Bitmap used for verification of commit/uncommit operations.
- BitMap _committed;
+ CHeapBitMap _committed;
// Bitmap used to keep track of which pages are dirty or not for _special
// spaces. This is needed because for those spaces the underlying memory
// will only be zero filled the first time it is committed. Calls to commit
// will use this bitmap and return whether or not the memory is zero filled.
- BitMap _dirty;
+ CHeapBitMap _dirty;
// Indicates that the entire space has been committed and pinned in memory,
// os::commit_memory() or os::uncommit_memory() have no function.
@@ -139,8 +139,6 @@
return x;
}
- void release();
-
void check_for_contiguity() PRODUCT_RETURN;
// Debugging
--- a/hotspot/src/share/vm/gc/g1/g1RegionToSpaceMapper.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1RegionToSpaceMapper.cpp Wed May 04 10:06:00 2016 +0200
@@ -34,11 +34,12 @@
size_t used_size,
size_t page_size,
size_t region_granularity,
+ size_t commit_factor,
MemoryType type) :
_storage(rs, used_size, page_size),
_region_granularity(region_granularity),
_listener(NULL),
- _commit_map() {
+ _commit_map(rs.size() * commit_factor / region_granularity) {
guarantee(is_power_of_2(page_size), "must be");
guarantee(is_power_of_2(region_granularity), "must be");
@@ -59,11 +60,10 @@
size_t alloc_granularity,
size_t commit_factor,
MemoryType type) :
- G1RegionToSpaceMapper(rs, actual_size, page_size, alloc_granularity, type),
+ G1RegionToSpaceMapper(rs, actual_size, page_size, alloc_granularity, commit_factor, type),
_pages_per_region(alloc_granularity / (page_size * commit_factor)) {
guarantee(alloc_granularity >= page_size, "allocation granularity smaller than commit granularity");
- _commit_map.resize(rs.size() * commit_factor / alloc_granularity, /* in_resource_area */ false);
}
virtual void commit_regions(uint start_idx, size_t num_regions) {
@@ -103,12 +103,11 @@
size_t alloc_granularity,
size_t commit_factor,
MemoryType type) :
- G1RegionToSpaceMapper(rs, actual_size, page_size, alloc_granularity, type),
+ G1RegionToSpaceMapper(rs, actual_size, page_size, alloc_granularity, commit_factor, type),
_regions_per_page((page_size * commit_factor) / alloc_granularity), _refcounts() {
guarantee((page_size * commit_factor) >= alloc_granularity, "allocation granularity smaller than commit granularity");
_refcounts.initialize((HeapWord*)rs.base(), (HeapWord*)(rs.base() + align_size_up(rs.size(), page_size)), page_size);
- _commit_map.resize(rs.size() * commit_factor / alloc_granularity, /* in_resource_area */ false);
}
virtual void commit_regions(uint start_idx, size_t num_regions) {
--- a/hotspot/src/share/vm/gc/g1/g1RegionToSpaceMapper.hpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1RegionToSpaceMapper.hpp Wed May 04 10:06:00 2016 +0200
@@ -49,9 +49,9 @@
size_t _region_granularity;
// Mapping management
- BitMap _commit_map;
+ CHeapBitMap _commit_map;
- G1RegionToSpaceMapper(ReservedSpace rs, size_t used_size, size_t page_size, size_t region_granularity, MemoryType type);
+ G1RegionToSpaceMapper(ReservedSpace rs, size_t used_size, size_t page_size, size_t region_granularity, size_t commit_factor, MemoryType type);
void fire_on_commit(uint start_idx, size_t num_regions, bool zero_filled);
public:
@@ -62,9 +62,7 @@
void set_mapping_changed_listener(G1MappingChangedListener* listener) { _listener = listener; }
- virtual ~G1RegionToSpaceMapper() {
- _commit_map.resize(0, /* in_resource_area */ false);
- }
+ virtual ~G1RegionToSpaceMapper() {}
bool is_committed(uintptr_t idx) const {
return _commit_map.at(idx);
--- a/hotspot/src/share/vm/gc/g1/heapRegionManager.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/gc/g1/heapRegionManager.cpp Wed May 04 10:06:00 2016 +0200
@@ -51,8 +51,7 @@
MemRegion reserved = heap_storage->reserved();
_regions.initialize(reserved.start(), reserved.end(), HeapRegion::GrainBytes);
- _available_map.resize(_regions.length(), false);
- _available_map.clear();
+ _available_map.initialize(_regions.length());
}
bool HeapRegionManager::is_available(uint region) const {
--- a/hotspot/src/share/vm/gc/g1/heapRegionManager.hpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/gc/g1/heapRegionManager.hpp Wed May 04 10:06:00 2016 +0200
@@ -83,7 +83,7 @@
// Each bit in this bitmap indicates that the corresponding region is available
// for allocation.
- BitMap _available_map;
+ CHeapBitMap _available_map;
// The number of regions committed in the heap.
uint _num_committed;
--- a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp Wed May 04 10:06:00 2016 +0200
@@ -43,7 +43,7 @@
friend class HeapRegionRemSetIterator;
HeapRegion* _hr;
- BitMap _bm;
+ CHeapBitMap _bm;
jint _occupied;
// next pointer for free/allocated 'all' list
@@ -69,7 +69,7 @@
PerRegionTable(HeapRegion* hr) :
_hr(hr),
_occupied(0),
- _bm(HeapRegion::CardsPerRegion, false /* in-resource-area */),
+ _bm(HeapRegion::CardsPerRegion),
_collision_list_next(NULL), _next(NULL), _prev(NULL)
{}
@@ -259,8 +259,7 @@
OtherRegionsTable::OtherRegionsTable(HeapRegion* hr, Mutex* m) :
_g1h(G1CollectedHeap::heap()),
_hr(hr), _m(m),
- _coarse_map(G1CollectedHeap::heap()->max_regions(),
- false /* in-resource-area */),
+ _coarse_map(G1CollectedHeap::heap()->max_regions()),
_fine_grain_regions(NULL),
_first_all_fine_prts(NULL), _last_all_fine_prts(NULL),
_n_fine_entries(0), _n_coarse_entries(0),
--- a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.hpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.hpp Wed May 04 10:06:00 2016 +0200
@@ -79,7 +79,7 @@
HeapRegion* _hr;
// These are protected by "_m".
- BitMap _coarse_map;
+ CHeapBitMap _coarse_map;
size_t _n_coarse_entries;
static jint _n_coarsenings;
--- a/hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp Wed May 04 10:06:00 2016 +0200
@@ -59,10 +59,8 @@
_region_start = covered_region.start();
_region_size = covered_region.word_size();
BitMap::bm_word_t* map = (BitMap::bm_word_t*)_virtual_space->reserved_low_addr();
- _beg_bits.set_map(map);
- _beg_bits.set_size(bits / 2);
- _end_bits.set_map(map + words / 2);
- _end_bits.set_size(bits / 2);
+ _beg_bits = BitMapView(map, bits / 2);
+ _end_bits = BitMapView(map + words / 2, bits / 2);
return true;
}
--- a/hotspot/src/share/vm/gc/parallel/parMarkBitMap.hpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/gc/parallel/parMarkBitMap.hpp Wed May 04 10:06:00 2016 +0200
@@ -182,8 +182,8 @@
HeapWord* _region_start;
size_t _region_size;
- BitMap _beg_bits;
- BitMap _end_bits;
+ BitMapView _beg_bits;
+ BitMapView _end_bits;
PSVirtualSpace* _virtual_space;
size_t _reserved_byte_size;
};
--- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp Wed May 04 10:06:00 2016 +0200
@@ -1929,7 +1929,7 @@
ParCompactionManager* const cm =
ParCompactionManager::manager_array(int(i));
assert(cm->marking_stack()->is_empty(), "should be empty");
- assert(cm->region_stack()->is_empty(), "should be empty");
+ assert(cm->region_stack()->is_empty(), "Region stack " SIZE_FORMAT " is not empty", i);
}
#endif // ASSERT
@@ -2370,10 +2370,8 @@
// Once a thread has drained it's stack, it should try to steal regions from
// other threads.
- if (parallel_gc_threads > 1) {
- for (uint j = 0; j < parallel_gc_threads; j++) {
- q->enqueue(new StealRegionCompactionTask(terminator_ptr));
- }
+ for (uint j = 0; j < parallel_gc_threads; j++) {
+ q->enqueue(new StealRegionCompactionTask(terminator_ptr));
}
}
--- a/hotspot/src/share/vm/oops/generateOopMap.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/oops/generateOopMap.cpp Wed May 04 10:06:00 2016 +0200
@@ -378,11 +378,10 @@
// Basicblock handling methods
//
-void GenerateOopMap ::initialize_bb() {
+void GenerateOopMap::initialize_bb() {
_gc_points = 0;
_bb_count = 0;
- _bb_hdr_bits.clear();
- _bb_hdr_bits.resize(method()->code_size());
+ _bb_hdr_bits.reinitialize(method()->code_size());
}
void GenerateOopMap::bb_mark_fct(GenerateOopMap *c, int bci, int *data) {
@@ -1041,13 +1040,7 @@
assert(new_method_size >= method()->code_size() + delta,
"new method size is too small");
- BitMap::bm_word_t* new_bb_hdr_bits =
- NEW_RESOURCE_ARRAY(BitMap::bm_word_t,
- BitMap::word_align_up(new_method_size));
- _bb_hdr_bits.set_map(new_bb_hdr_bits);
- _bb_hdr_bits.set_size(new_method_size);
- _bb_hdr_bits.clear();
-
+ _bb_hdr_bits.reinitialize(new_method_size);
for(int k = 0; k < _bb_count; k++) {
if (_basic_blocks[k]._bci > bci) {
--- a/hotspot/src/share/vm/oops/generateOopMap.hpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/oops/generateOopMap.hpp Wed May 04 10:06:00 2016 +0200
@@ -350,7 +350,7 @@
BasicBlock * _basic_blocks; // Array of basicblock info
int _gc_points;
int _bb_count;
- BitMap _bb_hdr_bits;
+ ResourceBitMap _bb_hdr_bits;
// Basicblocks methods
void initialize_bb ();
--- a/hotspot/src/share/vm/opto/parse.hpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/opto/parse.hpp Wed May 04 10:06:00 2016 +0200
@@ -168,7 +168,7 @@
// Use init_node/init_graph to initialize Blocks.
// Block() : _live_locals((uintptr_t*)NULL,0) { ShouldNotReachHere(); }
- Block() : _live_locals(NULL,0) { ShouldNotReachHere(); }
+ Block() : _live_locals() { ShouldNotReachHere(); }
public:
--- a/hotspot/src/share/vm/opto/parse1.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/opto/parse1.cpp Wed May 04 10:06:00 2016 +0200
@@ -261,7 +261,7 @@
Node *locals_addr = basic_plus_adr(osr_buf, osr_buf, (max_locals-1)*wordSize);
// find all the locals that the interpreter thinks contain live oops
- const BitMap live_oops = method()->live_local_oops_at_bci(osr_bci());
+ const ResourceBitMap live_oops = method()->live_local_oops_at_bci(osr_bci());
for (index = 0; index < max_locals; index++) {
if (!live_locals.at(index)) {
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Wed May 04 10:06:00 2016 +0200
@@ -1762,6 +1762,21 @@
return callee_method;
}
+address SharedRuntime::handle_unsafe_access(JavaThread* thread, address next_pc) {
+ // The faulting unsafe accesses should be changed to throw the error
+ // synchronously instead. Meanwhile the faulting instruction will be
+ // skipped over (effectively turning it into a no-op) and an
+ // asynchronous exception will be raised which the thread will
+ // handle at a later point. If the instruction is a load it will
+ // return garbage.
+
+ // Request an async exception.
+ thread->set_pending_unsafe_access_error();
+
+ // Return address of next instruction to execute.
+ return next_pc;
+}
+
#ifdef ASSERT
void SharedRuntime::check_member_name_argument_is_last_argument(const methodHandle& method,
const BasicType* sig_bt,
--- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp Wed May 04 10:06:00 2016 +0200
@@ -522,6 +522,8 @@
static address handle_wrong_method_abstract(JavaThread* thread);
static address handle_wrong_method_ic_miss(JavaThread* thread);
+ static address handle_unsafe_access(JavaThread* thread, address next_pc);
+
#ifndef PRODUCT
// Collect and print inline cache miss statistics
--- a/hotspot/src/share/vm/runtime/stubRoutines.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp Wed May 04 10:06:00 2016 +0200
@@ -55,7 +55,6 @@
address StubRoutines::_throw_NullPointerException_at_call_entry = NULL;
address StubRoutines::_throw_StackOverflowError_entry = NULL;
address StubRoutines::_throw_delayed_StackOverflowError_entry = NULL;
-address StubRoutines::_handler_for_unsafe_access_entry = NULL;
jint StubRoutines::_verify_oop_count = 0;
address StubRoutines::_verify_oop_subroutine_entry = NULL;
address StubRoutines::_atomic_xchg_entry = NULL;
--- a/hotspot/src/share/vm/runtime/stubRoutines.hpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp Wed May 04 10:06:00 2016 +0200
@@ -111,7 +111,6 @@
static address _throw_NullPointerException_at_call_entry;
static address _throw_StackOverflowError_entry;
static address _throw_delayed_StackOverflowError_entry;
- static address _handler_for_unsafe_access_entry;
static address _atomic_xchg_entry;
static address _atomic_xchg_ptr_entry;
@@ -288,10 +287,6 @@
static address throw_StackOverflowError_entry() { return _throw_StackOverflowError_entry; }
static address throw_delayed_StackOverflowError_entry() { return _throw_delayed_StackOverflowError_entry; }
- // Exceptions during unsafe access - should throw Java exception rather
- // than crash.
- static address handler_for_unsafe_access() { return _handler_for_unsafe_access_entry; }
-
static address atomic_xchg_entry() { return _atomic_xchg_entry; }
static address atomic_xchg_ptr_entry() { return _atomic_xchg_ptr_entry; }
static address atomic_store_entry() { return _atomic_store_entry; }
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Wed May 04 10:06:00 2016 +0200
@@ -1594,7 +1594,6 @@
declare_type(TenuredGeneration, CardGeneration) \
declare_toplevel_type(GenCollectorPolicy) \
declare_toplevel_type(Space) \
- declare_toplevel_type(BitMap) \
declare_type(CompactibleSpace, Space) \
declare_type(ContiguousSpace, CompactibleSpace) \
declare_type(OffsetTableContigSpace, ContiguousSpace) \
@@ -2238,6 +2237,9 @@
declare_type(Array<Klass*>, MetaspaceObj) \
declare_type(Array<Method*>, MetaspaceObj) \
\
+ declare_toplevel_type(BitMap) \
+ declare_type(BitMapView, BitMap) \
+ \
declare_integer_type(AccessFlags) /* FIXME: wrong type (not integer) */\
declare_toplevel_type(address) /* FIXME: should this be an integer type? */\
declare_integer_type(BasicType) /* FIXME: wrong type (not integer) */\
--- a/hotspot/src/share/vm/runtime/vm_version.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/runtime/vm_version.cpp Wed May 04 10:06:00 2016 +0200
@@ -289,6 +289,7 @@
unsigned int switch_pt) {
if (FLAG_IS_DEFAULT(ParallelGCThreads)) {
assert(ParallelGCThreads == 0, "Default ParallelGCThreads is not 0");
+ unsigned int threads;
// For very large machines, there are diminishing returns
// for large numbers of worker threads. Instead of
// hogging the whole system, use a fraction of the workers for every
@@ -296,9 +297,20 @@
// and a chosen fraction of 5/8
// use 8 + (72 - 8) * (5/8) == 48 worker threads.
unsigned int ncpus = (unsigned int) os::active_processor_count();
- return (ncpus <= switch_pt) ?
- ncpus :
- (switch_pt + ((ncpus - switch_pt) * num) / den);
+ threads = (ncpus <= switch_pt) ?
+ ncpus :
+ (switch_pt + ((ncpus - switch_pt) * num) / den);
+#ifndef _LP64
+ // On 32-bit binaries the virtual address space available to the JVM
+ // is usually limited to 2-3 GB (depends on the platform).
+ // Do not use up address space with too many threads (stacks and per-thread
+ // data). Note that x86 apps running on Win64 have 2 stacks per thread.
+ // GC may more generally scale down threads by max heap size (etc), but the
+ // consequences of over-provisioning threads are higher on 32-bit JVMS,
+ // so add hard limit here:
+ threads = MIN2(threads, (2*switch_pt));
+#endif
+ return threads;
} else {
return ParallelGCThreads;
}
--- a/hotspot/src/share/vm/utilities/bitMap.cpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/utilities/bitMap.cpp Wed May 04 10:06:00 2016 +0200
@@ -28,13 +28,144 @@
#include "runtime/atomic.inline.hpp"
#include "utilities/bitMap.inline.hpp"
#include "utilities/copy.hpp"
+#include "utilities/debug.hpp"
STATIC_ASSERT(sizeof(BitMap::bm_word_t) == BytesPerWord); // "Implementation assumption."
-BitMap::BitMap(idx_t size_in_bits, bool in_resource_area) :
- _map(NULL), _size(0)
-{
- resize(size_in_bits, in_resource_area);
+typedef BitMap::bm_word_t bm_word_t;
+typedef BitMap::idx_t idx_t;
+
+class ResourceBitMapAllocator : StackObj {
+ public:
+ bm_word_t* allocate(idx_t size_in_words) const {
+ return NEW_RESOURCE_ARRAY(bm_word_t, size_in_words);
+ }
+ void free(bm_word_t* map, idx_t size_in_words) const {
+ // Don't free resource allocated arrays.
+ }
+};
+
+class CHeapBitMapAllocator : StackObj {
+ public:
+ bm_word_t* allocate(size_t size_in_words) const {
+ return ArrayAllocator<bm_word_t, mtInternal>::allocate(size_in_words);
+ }
+ void free(bm_word_t* map, idx_t size_in_words) const {
+ ArrayAllocator<bm_word_t, mtInternal>::free(map, size_in_words);
+ }
+};
+
+class ArenaBitMapAllocator : StackObj {
+ Arena* _arena;
+
+ public:
+ ArenaBitMapAllocator(Arena* arena) : _arena(arena) {}
+ bm_word_t* allocate(idx_t size_in_words) const {
+ return (bm_word_t*)_arena->Amalloc(size_in_words * BytesPerWord);
+ }
+ void free(bm_word_t* map, idx_t size_in_words) const {
+ // ArenaBitMaps currently don't free memory.
+ }
+};
+
+template <class Allocator>
+BitMap::bm_word_t* BitMap::reallocate(const Allocator& allocator, bm_word_t* old_map, idx_t old_size_in_bits, idx_t new_size_in_bits) {
+ size_t old_size_in_words = calc_size_in_words(old_size_in_bits);
+ size_t new_size_in_words = calc_size_in_words(new_size_in_bits);
+
+ bm_word_t* map = NULL;
+
+ if (new_size_in_words > 0) {
+ map = allocator.allocate(new_size_in_words);
+
+ Copy::disjoint_words((HeapWord*)old_map, (HeapWord*) map,
+ MIN2(old_size_in_words, new_size_in_words));
+
+ if (new_size_in_words > old_size_in_words) {
+ clear_range_of_words(map, old_size_in_words, new_size_in_words);
+ }
+ }
+
+ if (old_map != NULL) {
+ allocator.free(old_map, old_size_in_words);
+ }
+
+ return map;
+}
+
+template <class Allocator>
+bm_word_t* BitMap::allocate(const Allocator& allocator, idx_t size_in_bits) {
+ // Reuse reallocate to ensure that the new memory is cleared.
+ return reallocate(allocator, NULL, 0, size_in_bits);
+}
+
+template <class Allocator>
+void BitMap::free(const Allocator& allocator, bm_word_t* map, idx_t size_in_bits) {
+ bm_word_t* ret = reallocate(allocator, map, size_in_bits, 0);
+ assert(ret == NULL, "Reallocate shouldn't have allocated");
+}
+
+template <class Allocator>
+void BitMap::resize(const Allocator& allocator, idx_t new_size_in_bits) {
+ bm_word_t* new_map = reallocate(allocator, map(), size(), new_size_in_bits);
+
+ update(new_map, new_size_in_bits);
+}
+
+template <class Allocator>
+void BitMap::initialize(const Allocator& allocator, idx_t size_in_bits) {
+ assert(map() == NULL, "precondition");
+ assert(size() == 0, "precondition");
+
+ resize(allocator, size_in_bits);
+}
+
+template <class Allocator>
+void BitMap::reinitialize(const Allocator& allocator, idx_t new_size_in_bits) {
+ // Remove previous bits.
+ resize(allocator, 0);
+
+ initialize(allocator, new_size_in_bits);
+}
+
+ResourceBitMap::ResourceBitMap(idx_t size_in_bits)
+ : BitMap(allocate(ResourceBitMapAllocator(), size_in_bits), size_in_bits) {
+}
+
+void ResourceBitMap::resize(idx_t new_size_in_bits) {
+ BitMap::resize(ResourceBitMapAllocator(), new_size_in_bits);
+}
+
+void ResourceBitMap::initialize(idx_t size_in_bits) {
+ BitMap::initialize(ResourceBitMapAllocator(), size_in_bits);
+}
+
+void ResourceBitMap::reinitialize(idx_t size_in_bits) {
+ BitMap::reinitialize(ResourceBitMapAllocator(), size_in_bits);
+}
+
+ArenaBitMap::ArenaBitMap(Arena* arena, idx_t size_in_bits)
+ : BitMap(allocate(ArenaBitMapAllocator(arena), size_in_bits), size_in_bits) {
+}
+
+CHeapBitMap::CHeapBitMap(idx_t size_in_bits)
+ : BitMap(allocate(CHeapBitMapAllocator(), size_in_bits), size_in_bits) {
+}
+
+CHeapBitMap::~CHeapBitMap() {
+ free(CHeapBitMapAllocator(), map(), size());
+}
+
+void CHeapBitMap::resize(idx_t new_size_in_bits) {
+ BitMap::resize(CHeapBitMapAllocator(), new_size_in_bits);
+}
+
+void CHeapBitMap::initialize(idx_t size_in_bits) {
+ BitMap::initialize(CHeapBitMapAllocator(), size_in_bits);
+}
+
+void CHeapBitMap::reinitialize(idx_t size_in_bits) {
+ BitMap::reinitialize(CHeapBitMapAllocator(), size_in_bits);
}
#ifdef ASSERT
@@ -49,25 +180,6 @@
}
#endif // #ifdef ASSERT
-void BitMap::resize(idx_t size_in_bits, bool in_resource_area) {
- idx_t old_size_in_words = size_in_words();
- bm_word_t* old_map = map();
-
- _size = size_in_bits;
- idx_t new_size_in_words = size_in_words();
- if (in_resource_area) {
- _map = NEW_RESOURCE_ARRAY(bm_word_t, new_size_in_words);
- Copy::disjoint_words((HeapWord*)old_map, (HeapWord*) _map,
- MIN2(old_size_in_words, new_size_in_words));
- } else {
- _map = ArrayAllocator<bm_word_t, mtInternal>::reallocate(old_map, old_size_in_words, new_size_in_words);
- }
-
- if (new_size_in_words > old_size_in_words) {
- clear_range_of_words(old_size_in_words, new_size_in_words);
- }
-}
-
void BitMap::pretouch() {
os::pretouch_memory(word_addr(0), word_addr(size()));
}
@@ -205,13 +317,6 @@
return value ? par_set_bit(bit) : par_clear_bit(bit);
}
-void BitMap::at_put_grow(idx_t offset, bool value) {
- if (offset >= size()) {
- resize(2 * MAX2(size(), offset));
- }
- at_put(offset, value);
-}
-
void BitMap::at_put_range(idx_t start_offset, idx_t end_offset, bool value) {
if (value) {
set_range(start_offset, end_offset);
@@ -532,93 +637,116 @@
class TestBitMap : public AllStatic {
const static BitMap::idx_t BITMAP_SIZE = 1024;
- static void fillBitMap(BitMap& map) {
+
+ template <class ResizableBitMapClass>
+ static void fillBitMap(ResizableBitMapClass& map) {
map.set_bit(1);
map.set_bit(3);
map.set_bit(17);
map.set_bit(512);
}
- static void testResize(bool in_resource_area) {
- {
- BitMap map(0, in_resource_area);
- map.resize(BITMAP_SIZE, in_resource_area);
- fillBitMap(map);
+ template <class ResizableBitMapClass>
+ static void testResize(BitMap::idx_t start_size) {
+ ResourceMark rm;
+
+ ResizableBitMapClass map(start_size);
+ map.resize(BITMAP_SIZE);
+ fillBitMap(map);
- BitMap map2(BITMAP_SIZE, in_resource_area);
- fillBitMap(map2);
- assert(map.is_same(map2), "could be");
- }
+ ResizableBitMapClass map2(BITMAP_SIZE);
+ fillBitMap(map2);
+ assert(map.is_same(map2), "could be");
+ }
+
+ template <class ResizableBitMapClass>
+ static void testResizeGrow() {
+ testResize<ResizableBitMapClass>(0);
+ testResize<ResizableBitMapClass>(128);
+ }
- {
- BitMap map(128, in_resource_area);
- map.resize(BITMAP_SIZE, in_resource_area);
- fillBitMap(map);
+ template <class ResizableBitMapClass>
+ static void testResizeSame() {
+ testResize<ResizableBitMapClass>(BITMAP_SIZE);
+ }
- BitMap map2(BITMAP_SIZE, in_resource_area);
- fillBitMap(map2);
- assert(map.is_same(map2), "could be");
- }
+ template <class ResizableBitMapClass>
+ static void testResizeShrink() {
+ testResize<ResizableBitMapClass>(BITMAP_SIZE * 2);
+ }
- {
- BitMap map(BITMAP_SIZE, in_resource_area);
- map.resize(BITMAP_SIZE, in_resource_area);
- fillBitMap(map);
+ static void testResizeGrow() {
+ testResizeGrow<ResourceBitMap>();
+ testResizeGrow<CHeapBitMap>();
+ }
- BitMap map2(BITMAP_SIZE, in_resource_area);
- fillBitMap(map2);
- assert(map.is_same(map2), "could be");
- }
+ static void testResizeSame() {
+ testResizeSame<ResourceBitMap>();
+ testResizeSame<CHeapBitMap>();
+ }
+
+ static void testResizeShrink() {
+ testResizeShrink<ResourceBitMap>();
+ testResizeShrink<CHeapBitMap>();
}
- static void testResizeResource() {
+ static void testResize() {
+ testResizeGrow();
+ testResizeSame();
+ testResizeShrink();
+ }
+
+ template <class InitializableBitMapClass>
+ static void testInitialize() {
ResourceMark rm;
- testResize(true);
+
+ InitializableBitMapClass map;
+ map.initialize(BITMAP_SIZE);
+ fillBitMap(map);
+
+ InitializableBitMapClass map2(BITMAP_SIZE);
+ fillBitMap(map2);
+ assert(map.is_same(map2), "could be");
}
- static void testResizeNonResource() {
- const size_t bitmap_bytes = BITMAP_SIZE / BitsPerByte;
+ static void testInitialize() {
+ testInitialize<ResourceBitMap>();
+ testInitialize<CHeapBitMap>();
+ }
- // Test the default behavior
- testResize(false);
+ template <class ReinitializableBitMapClass>
+ static void testReinitialize(BitMap::idx_t init_size) {
+ ResourceMark rm;
+
+ ReinitializableBitMapClass map(init_size);
+ map.reinitialize(BITMAP_SIZE);
+ fillBitMap(map);
- {
- // Make sure that AllocatorMallocLimit is larger than our allocation request
- // forcing it to call standard malloc()
- SizeTFlagSetting fs(ArrayAllocatorMallocLimit, bitmap_bytes * 4);
- testResize(false);
- }
- {
- // Make sure that AllocatorMallocLimit is smaller than our allocation request
- // forcing it to call mmap() (or equivalent)
- SizeTFlagSetting fs(ArrayAllocatorMallocLimit, bitmap_bytes / 4);
- testResize(false);
- }
+ ReinitializableBitMapClass map2(BITMAP_SIZE);
+ fillBitMap(map2);
+ assert(map.is_same(map2), "could be");
+ }
+
+ template <class ReinitializableBitMapClass>
+ static void testReinitialize() {
+ testReinitialize<ReinitializableBitMapClass>(0);
+ testReinitialize<ReinitializableBitMapClass>(128);
+ testReinitialize<ReinitializableBitMapClass>(BITMAP_SIZE);
+ }
+
+ static void testReinitialize() {
+ testReinitialize<ResourceBitMap>();
}
public:
static void test() {
- testResizeResource();
- testResizeNonResource();
+ testResize();
+ testInitialize();
+ testReinitialize();
}
-
};
void TestBitMap_test() {
TestBitMap::test();
}
#endif
-
-
-BitMap2D::BitMap2D(bm_word_t* map, idx_t size_in_slots, idx_t bits_per_slot)
- : _bits_per_slot(bits_per_slot)
- , _map(map, size_in_slots * bits_per_slot)
-{
-}
-
-
-BitMap2D::BitMap2D(idx_t size_in_slots, idx_t bits_per_slot)
- : _bits_per_slot(bits_per_slot)
- , _map(size_in_slots * bits_per_slot)
-{
-}
--- a/hotspot/src/share/vm/utilities/bitMap.hpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/utilities/bitMap.hpp Wed May 04 10:06:00 2016 +0200
@@ -33,6 +33,16 @@
// Operations for bitmaps represented as arrays of unsigned integers.
// Bit offsets are numbered from 0 to size-1.
+// The "abstract" base BitMap class.
+//
+// The constructor and destructor are protected to prevent
+// creation of BitMap instances outside of the BitMap class.
+//
+// The BitMap class doesn't use virtual calls on purpose,
+// this ensures that we don't get a vtable unnecessarily.
+//
+// The allocation of the backing storage for the BitMap are handled by
+// the subclasses. BitMap doesn't allocate or delete backing storage.
class BitMap VALUE_OBJ_CLASS_SPEC {
friend class BitMap2D;
@@ -50,10 +60,6 @@
bm_word_t* _map; // First word in bitmap
idx_t _size; // Size of bitmap (in bits)
- // Puts the given value at the given offset, using resize() to size
- // the bitmap appropriately if needed using factor-of-two expansion.
- void at_put_grow(idx_t index, bool value);
-
protected:
// Return the position of bit within the word that contains it (e.g., if
// bitmap words are 32 bits, return a number 0 <= n <= 31).
@@ -97,6 +103,8 @@
void set_large_range_of_words (idx_t beg, idx_t end);
void clear_large_range_of_words (idx_t beg, idx_t end);
+ static void clear_range_of_words(bm_word_t* map, idx_t beg, idx_t end);
+
// The index of the first full word in a range.
idx_t word_index_round_up(idx_t bit) const;
@@ -110,46 +118,69 @@
static idx_t num_set_bits(bm_word_t w);
static idx_t num_set_bits_from_table(unsigned char c);
- public:
+ // Allocation Helpers.
+
+ // Allocates and clears the bitmap memory.
+ template <class Allocator>
+ static bm_word_t* allocate(const Allocator&, idx_t size_in_bits);
- // Constructs a bitmap with no map, and size 0.
- BitMap() : _map(NULL), _size(0) {}
+ // Reallocates and clears the new bitmap memory.
+ template <class Allocator>
+ static bm_word_t* reallocate(const Allocator&, bm_word_t* map, idx_t old_size_in_bits, idx_t new_size_in_bits);
+
+ // Free the bitmap memory.
+ template <class Allocator>
+ static void free(const Allocator&, bm_word_t* map, idx_t size_in_bits);
+
+ // Protected functions, that are used by BitMap sub-classes that support them.
- // Constructs a bitmap with the given map and size.
- BitMap(bm_word_t* map, idx_t size_in_bits) :_map(map), _size(size_in_bits) {}
+ // Resize the backing bitmap memory.
+ //
+ // Old bits are transfered to the new memory
+ // and the extended memory is cleared.
+ template <class Allocator>
+ void resize(const Allocator& allocator, idx_t new_size_in_bits);
- // Constructs an empty bitmap of the given size (that is, this clears the
- // new bitmap). Allocates the map array in resource area if
- // "in_resource_area" is true, else in the C heap.
- BitMap(idx_t size_in_bits, bool in_resource_area = true);
+ // Set up and clear the bitmap memory.
+ //
+ // Precondition: The bitmap was default constructed and has
+ // not yet had memory allocated via resize or (re)initialize.
+ template <class Allocator>
+ void initialize(const Allocator& allocator, idx_t size_in_bits);
+
+ // Set up and clear the bitmap memory.
+ //
+ // Can be called on previously initialized bitmaps.
+ template <class Allocator>
+ void reinitialize(const Allocator& allocator, idx_t new_size_in_bits);
// Set the map and size.
- void set_map(bm_word_t* map) { _map = map; }
- void set_size(idx_t size_in_bits) { _size = size_in_bits; }
+ void update(bm_word_t* map, idx_t size) {
+ _map = map;
+ _size = size;
+ }
- // Allocates necessary data structure, either in the resource area
- // or in the C heap, as indicated by "in_resource_area."
- // Preserves state currently in bit map by copying data.
- // Zeros any newly-addressable bits.
- // If "in_resource_area" is false, frees the current map.
- // (Note that this assumes that all calls to "resize" on the same BitMap
- // use the same value for "in_resource_area".)
- void resize(idx_t size_in_bits, bool in_resource_area = true);
+ // Protected constructor and destructor.
+ BitMap(bm_word_t* map, idx_t size_in_bits) : _map(map), _size(size_in_bits) {}
+ ~BitMap() {}
+ public:
// Pretouch the entire range of memory this BitMap covers.
void pretouch();
// Accessing
- idx_t size() const { return _size; }
- idx_t size_in_bytes() const { return size_in_words() * BytesPerWord; }
- idx_t size_in_words() const {
- return calc_size_in_words(size());
- }
-
static idx_t calc_size_in_words(size_t size_in_bits) {
return word_index(size_in_bits + BitsPerWord - 1);
}
+ static idx_t calc_size_in_bytes(size_t size_in_bits) {
+ return calc_size_in_words(size_in_bits) * BytesPerWord;
+ }
+
+ idx_t size() const { return _size; }
+ idx_t size_in_words() const { return calc_size_in_words(size()); }
+ idx_t size_in_bytes() const { return calc_size_in_bytes(size()); }
+
bool at(idx_t index) const {
verify_index(index);
return (*word_addr(index) & bit_mask(index)) != 0;
@@ -279,6 +310,88 @@
#endif
};
+// A concrete implementation of the the "abstract" BitMap class.
+//
+// The BitMapView is used when the backing storage is managed externally.
+class BitMapView : public BitMap {
+ public:
+ BitMapView() : BitMap(NULL, 0) {}
+ BitMapView(bm_word_t* map, idx_t size_in_bits) : BitMap(map, size_in_bits) {}
+};
+
+// A BitMap with storage in a ResourceArea.
+class ResourceBitMap : public BitMap {
+ friend class TestBitMap;
+
+ public:
+ ResourceBitMap() : BitMap(NULL, 0) {}
+ // Clears the bitmap memory.
+ ResourceBitMap(idx_t size_in_bits);
+
+ // Resize the backing bitmap memory.
+ //
+ // Old bits are transfered to the new memory
+ // and the extended memory is cleared.
+ void resize(idx_t new_size_in_bits);
+
+ // Set up and clear the bitmap memory.
+ //
+ // Precondition: The bitmap was default constructed and has
+ // not yet had memory allocated via resize or initialize.
+ void initialize(idx_t size_in_bits);
+
+ // Set up and clear the bitmap memory.
+ //
+ // Can be called on previously initialized bitmaps.
+ void reinitialize(idx_t size_in_bits);
+};
+
+// A BitMap with storage in a specific Arena.
+class ArenaBitMap : public BitMap {
+ public:
+ // Clears the bitmap memory.
+ ArenaBitMap(Arena* arena, idx_t size_in_bits);
+
+ private:
+ // Don't allow copy or assignment.
+ ArenaBitMap(const ArenaBitMap&);
+ ArenaBitMap& operator=(const ArenaBitMap&);
+};
+
+// A BitMap with storage in the CHeap.
+class CHeapBitMap : public BitMap {
+ friend class TestBitMap;
+
+ private:
+ // Don't allow copy or assignment, to prevent the
+ // allocated memory from leaking out to other instances.
+ CHeapBitMap(const CHeapBitMap&);
+ CHeapBitMap& operator=(const CHeapBitMap&);
+
+ public:
+ CHeapBitMap() : BitMap(NULL, 0) {}
+ // Clears the bitmap memory.
+ CHeapBitMap(idx_t size_in_bits);
+ ~CHeapBitMap();
+
+ // Resize the backing bitmap memory.
+ //
+ // Old bits are transfered to the new memory
+ // and the extended memory is cleared.
+ void resize(idx_t new_size_in_bits);
+
+ // Set up and clear the bitmap memory.
+ //
+ // Precondition: The bitmap was default constructed and has
+ // not yet had memory allocated via resize or initialize.
+ void initialize(idx_t size_in_bits);
+
+ // Set up and clear the bitmap memory.
+ //
+ // Can be called on previously initialized bitmaps.
+ void reinitialize(idx_t size_in_bits);
+};
+
// Convenience class wrapping BitMap which provides multiple bits per slot.
class BitMap2D VALUE_OBJ_CLASS_SPEC {
public:
@@ -286,8 +399,8 @@
typedef BitMap::bm_word_t bm_word_t; // Element type of array that
// represents the bitmap.
private:
- BitMap _map;
- idx_t _bits_per_slot;
+ ResourceBitMap _map;
+ idx_t _bits_per_slot;
idx_t bit_index(idx_t slot_index, idx_t bit_within_slot_index) const {
return slot_index * _bits_per_slot + bit_within_slot_index;
@@ -299,10 +412,12 @@
public:
// Construction. bits_per_slot must be greater than 0.
- BitMap2D(bm_word_t* map, idx_t size_in_slots, idx_t bits_per_slot);
+ BitMap2D(idx_t bits_per_slot) :
+ _map(), _bits_per_slot(bits_per_slot) {}
// Allocates necessary data structure in resource area. bits_per_slot must be greater than 0.
- BitMap2D(idx_t size_in_slots, idx_t bits_per_slot);
+ BitMap2D(idx_t size_in_slots, idx_t bits_per_slot) :
+ _map(size_in_slots * bits_per_slot), _bits_per_slot(bits_per_slot) {}
idx_t size_in_bits() {
return _map.size();
--- a/hotspot/src/share/vm/utilities/bitMap.inline.hpp Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/src/share/vm/utilities/bitMap.inline.hpp Wed May 04 10:06:00 2016 +0200
@@ -121,18 +121,18 @@
for (idx_t i = beg; i < end; ++i) map[i] = ~(bm_word_t)0;
}
-
-inline void BitMap::clear_range_of_words(idx_t beg, idx_t end) {
- bm_word_t* map = _map;
+inline void BitMap::clear_range_of_words(bm_word_t* map, idx_t beg, idx_t end) {
for (idx_t i = beg; i < end; ++i) map[i] = 0;
}
+inline void BitMap::clear_range_of_words(idx_t beg, idx_t end) {
+ clear_range_of_words(_map, beg, end);
+}
inline void BitMap::clear() {
clear_range_of_words(0, size_in_words());
}
-
inline void BitMap::par_clear_range(idx_t beg, idx_t end, RangeSizeHint hint) {
if (hint == small_range && end - beg == 1) {
par_at_put(beg, false);
@@ -359,7 +359,12 @@
inline void BitMap2D::at_put_grow(idx_t slot_index, idx_t bit_within_slot_index, bool value) {
verify_bit_within_slot_index(bit_within_slot_index);
- _map.at_put_grow(bit_index(slot_index, bit_within_slot_index), value);
+
+ idx_t bit = bit_index(slot_index, bit_within_slot_index);
+ if (bit >= _map.size()) {
+ _map.resize(2 * MAX2(_map.size(), bit));
+ }
+ _map.at_put(bit, value);
}
inline void BitMap2D::clear() {
--- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData00.java Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData00.java Wed May 04 10:06:00 2016 +0200
@@ -25,6 +25,7 @@
* @test TestShrinkAuxiliaryData00
* @bug 8038423 8061715
* @summary Checks that decommitment occurs for JVM with different
+ * @ignore 8155957
* G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
* @requires vm.gc=="G1" | vm.gc=="null"
* @requires vm.opt.AggressiveOpts=="false" | vm.opt.AggressiveOpts=="null"
--- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData05.java Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData05.java Wed May 04 10:06:00 2016 +0200
@@ -26,6 +26,7 @@
* @bug 8038423 8061715 8078405
* @summary Checks that decommitment occurs for JVM with different
* G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
+ * @ignore 8155957
* @requires vm.gc=="G1" | vm.gc=="null"
* @requires vm.opt.AggressiveOpts=="false" | vm.opt.AggressiveOpts=="null"
* @library /testlibrary /test/lib
--- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData10.java Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData10.java Wed May 04 10:06:00 2016 +0200
@@ -26,6 +26,7 @@
* @bug 8038423 8061715 8078405
* @summary Checks that decommitment occurs for JVM with different
* G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
+ * @ignore 8155957
* @requires vm.gc=="G1" | vm.gc=="null"
* @requires vm.opt.AggressiveOpts=="false" | vm.opt.AggressiveOpts=="null"
* @library /testlibrary /test/lib
--- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData15.java Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData15.java Wed May 04 10:06:00 2016 +0200
@@ -26,6 +26,7 @@
* @bug 8038423 8061715 8078405
* @summary Checks that decommitment occurs for JVM with different
* G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
+ * @ignore 8155957
* @requires vm.gc=="G1" | vm.gc=="null"
* @requires vm.opt.AggressiveOpts=="false" | vm.opt.AggressiveOpts=="null"
* @library /testlibrary /test/lib
--- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData20.java Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData20.java Wed May 04 10:06:00 2016 +0200
@@ -26,6 +26,7 @@
* @bug 8038423 8061715 8078405
* @summary Checks that decommitment occurs for JVM with different
* G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
+ * @ignore 8155957
* @requires vm.gc=="G1" | vm.gc=="null"
* @requires vm.opt.AggressiveOpts=="false" | vm.opt.AggressiveOpts=="null"
* @library /testlibrary /test/lib
--- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData25.java Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData25.java Wed May 04 10:06:00 2016 +0200
@@ -26,6 +26,7 @@
* @bug 8038423 8061715 8078405
* @summary Checks that decommitment occurs for JVM with different
* G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
+ * @ignore 8155957
* @requires vm.gc=="G1" | vm.gc=="null"
* @requires vm.opt.AggressiveOpts=="false" | vm.opt.AggressiveOpts=="null"
* @library /testlibrary /test/lib
--- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData30.java Tue May 03 12:33:10 2016 +0200
+++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData30.java Wed May 04 10:06:00 2016 +0200
@@ -26,6 +26,7 @@
* @bug 8038423 8061715 8078405
* @summary Checks that decommitment occurs for JVM with different
* G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
+ * @ignore 8155957
* @requires vm.gc=="G1" | vm.gc=="null"
* @requires vm.opt.AggressiveOpts=="false" | vm.opt.AggressiveOpts=="null"
* @library /testlibrary /test/lib