# HG changeset patch # User stefank # Date 1462308327 -7200 # Node ID b0c9cb06506ba64fd7653a21dae03f3f670afac1 # Parent 4e2bff1a546750612b0f53e403c22f1a4d638f7a 8141501: Problems with BitMap buffer management Reviewed-by: pliden, kbarrett diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/cpu/x86/vm/c1_LinearScan_x86.cpp --- a/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.cpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.cpp Tue May 03 22:45:27 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); diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/c1/c1_GraphBuilder.cpp --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Tue May 03 22:45:27 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 diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/c1/c1_IR.cpp --- a/hotspot/src/share/vm/c1/c1_IR.cpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/c1/c1_IR.cpp Tue May 03 22:45:27 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")); diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/c1/c1_IR.hpp --- a/hotspot/src/share/vm/c1/c1_IR.hpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/c1/c1_IR.hpp Tue May 03 22:45:27 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); diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/c1/c1_Instruction.cpp --- a/hotspot/src/share/vm/c1/c1_Instruction.cpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/c1/c1_Instruction.cpp Tue May 03 22:45:27 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)); diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/c1/c1_Instruction.hpp --- a/hotspot/src/share/vm/c1/c1_Instruction.hpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/c1/c1_Instruction.hpp Tue May 03 22:45:27 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); diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/c1/c1_LIRGenerator.hpp --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp Tue May 03 22:45:27 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(); } diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/c1/c1_LinearScan.cpp --- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp Tue May 03 22:45:27 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 diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/c1/c1_LinearScan.hpp --- a/hotspot/src/share/vm/c1/c1_LinearScan.hpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/c1/c1_LinearScan.hpp Tue May 03 22:45:27 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 diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/c1/c1_ValueSet.hpp --- a/hotspot/src/share/vm/c1/c1_ValueSet.hpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/c1/c1_ValueSet.hpp Tue May 03 22:45:27 2016 +0200 @@ -36,7 +36,7 @@ class ValueSet: public CompilationResourceObj { private: - BitMap _map; + ResourceBitMap _map; public: ValueSet(); diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/ci/ciMethod.cpp --- a/hotspot/src/share/vm/ci/ciMethod.cpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/ci/ciMethod.cpp Tue May 03 22:45:27 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. diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/ci/ciMethod.hpp --- a/hotspot/src/share/vm/ci/ciMethod.hpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/ci/ciMethod.hpp Tue May 03 22:45:27 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(); diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/classfile/classFileParser.cpp --- a/hotspot/src/share/vm/classfile/classFileParser.cpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Tue May 03 22:45:27 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; diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/compiler/methodLiveness.cpp --- a/hotspot/src/share/vm/compiler/methodLiveness.cpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/compiler/methodLiveness.cpp Tue May 03 22:45:27 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); diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/compiler/methodLiveness.hpp --- a/hotspot/src/share/vm/compiler/methodLiveness.hpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/compiler/methodLiveness.hpp Tue May 03 22:45:27 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; diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp --- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp Tue May 03 22:45:27 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(), diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp --- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp Tue May 03 22:45:27 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 diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/gc/cms/vmStructs_cms.hpp --- a/hotspot/src/share/vm/gc/cms/vmStructs_cms.hpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/gc/cms/vmStructs_cms.hpp Tue May 03 22:45:27 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*) \ diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp --- a/hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp Tue May 03 22:45:27 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), diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/gc/g1/g1CardLiveData.hpp --- a/hotspot/src/share/vm/gc/g1/g1CardLiveData.hpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/gc/g1/g1CardLiveData.hpp Tue May 03 22:45:27 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; diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/gc/g1/g1CardLiveData.inline.hpp --- a/hotspot/src/share/vm/gc/g1/g1CardLiveData.inline.hpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/gc/g1/g1CardLiveData.inline.hpp Tue May 03 22:45:27 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 { diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp Tue May 03 22:45:27 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); } diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp Tue May 03 22:45:27 2016 +0200 @@ -58,10 +58,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 diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/gc/g1/g1PageBasedVirtualSpace.cpp --- a/hotspot/src/share/vm/gc/g1/g1PageBasedVirtualSpace.cpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/gc/g1/g1PageBasedVirtualSpace.cpp Tue May 03 22:45:27 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 { diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/gc/g1/g1PageBasedVirtualSpace.hpp --- a/hotspot/src/share/vm/gc/g1/g1PageBasedVirtualSpace.hpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/gc/g1/g1PageBasedVirtualSpace.hpp Tue May 03 22:45:27 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 diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/gc/g1/g1RegionToSpaceMapper.cpp --- a/hotspot/src/share/vm/gc/g1/g1RegionToSpaceMapper.cpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/gc/g1/g1RegionToSpaceMapper.cpp Tue May 03 22:45:27 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) { diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/gc/g1/g1RegionToSpaceMapper.hpp --- a/hotspot/src/share/vm/gc/g1/g1RegionToSpaceMapper.hpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/gc/g1/g1RegionToSpaceMapper.hpp Tue May 03 22:45:27 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); diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/gc/g1/heapRegionManager.cpp --- a/hotspot/src/share/vm/gc/g1/heapRegionManager.cpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/gc/g1/heapRegionManager.cpp Tue May 03 22:45:27 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 { diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/gc/g1/heapRegionManager.hpp --- a/hotspot/src/share/vm/gc/g1/heapRegionManager.hpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/gc/g1/heapRegionManager.hpp Tue May 03 22:45:27 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; diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp --- a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp Tue May 03 22:45:27 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), diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/gc/g1/heapRegionRemSet.hpp --- a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.hpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.hpp Tue May 03 22:45:27 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; diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp --- a/hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp Tue May 03 22:45:27 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; } diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/gc/parallel/parMarkBitMap.hpp --- a/hotspot/src/share/vm/gc/parallel/parMarkBitMap.hpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/gc/parallel/parMarkBitMap.hpp Tue May 03 22:45:27 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; }; diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/oops/generateOopMap.cpp --- a/hotspot/src/share/vm/oops/generateOopMap.cpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/oops/generateOopMap.cpp Tue May 03 22:45:27 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) { diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/oops/generateOopMap.hpp --- a/hotspot/src/share/vm/oops/generateOopMap.hpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/oops/generateOopMap.hpp Tue May 03 22:45:27 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 (); diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/opto/parse.hpp --- a/hotspot/src/share/vm/opto/parse.hpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/opto/parse.hpp Tue May 03 22:45:27 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: diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/opto/parse1.cpp --- a/hotspot/src/share/vm/opto/parse1.cpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/opto/parse1.cpp Tue May 03 22:45:27 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)) { diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/runtime/vmStructs.cpp --- a/hotspot/src/share/vm/runtime/vmStructs.cpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Tue May 03 22:45:27 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, MetaspaceObj) \ declare_type(Array, 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) */\ diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/utilities/bitMap.cpp --- a/hotspot/src/share/vm/utilities/bitMap.cpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/utilities/bitMap.cpp Tue May 03 22:45:27 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::allocate(size_in_words); + } + void free(bm_word_t* map, idx_t size_in_words) const { + ArrayAllocator::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 +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 +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 +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 +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 +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 +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::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 + 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 + 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 + static void testResizeGrow() { + testResize(0); + testResize(128); + } - { - BitMap map(128, in_resource_area); - map.resize(BITMAP_SIZE, in_resource_area); - fillBitMap(map); + template + static void testResizeSame() { + testResize(BITMAP_SIZE); + } - BitMap map2(BITMAP_SIZE, in_resource_area); - fillBitMap(map2); - assert(map.is_same(map2), "could be"); - } + template + static void testResizeShrink() { + testResize(BITMAP_SIZE * 2); + } - { - BitMap map(BITMAP_SIZE, in_resource_area); - map.resize(BITMAP_SIZE, in_resource_area); - fillBitMap(map); + static void testResizeGrow() { + testResizeGrow(); + testResizeGrow(); + } - BitMap map2(BITMAP_SIZE, in_resource_area); - fillBitMap(map2); - assert(map.is_same(map2), "could be"); - } + static void testResizeSame() { + testResizeSame(); + testResizeSame(); + } + + static void testResizeShrink() { + testResizeShrink(); + testResizeShrink(); } - static void testResizeResource() { + static void testResize() { + testResizeGrow(); + testResizeSame(); + testResizeShrink(); + } + + template + 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(); + testInitialize(); + } - // Test the default behavior - testResize(false); + template + 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 + static void testReinitialize() { + testReinitialize(0); + testReinitialize(128); + testReinitialize(BITMAP_SIZE); + } + + static void testReinitialize() { + testReinitialize(); } 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) -{ -} diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/utilities/bitMap.hpp --- a/hotspot/src/share/vm/utilities/bitMap.hpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/utilities/bitMap.hpp Tue May 03 22:45:27 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 + 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 + 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 + 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 + 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 + 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 + 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(); diff -r 4e2bff1a5467 -r b0c9cb06506b hotspot/src/share/vm/utilities/bitMap.inline.hpp --- a/hotspot/src/share/vm/utilities/bitMap.inline.hpp Mon May 02 12:14:26 2016 -0400 +++ b/hotspot/src/share/vm/utilities/bitMap.inline.hpp Tue May 03 22:45:27 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() {