8141501: Problems with BitMap buffer management
authorstefank
Tue, 03 May 2016 22:45:27 +0200
changeset 38177 b0c9cb06506b
parent 38175 4e2bff1a5467
child 38178 0860ff91a12e
8141501: Problems with BitMap buffer management Reviewed-by: pliden, kbarrett
hotspot/src/cpu/x86/vm/c1_LinearScan_x86.cpp
hotspot/src/share/vm/c1/c1_GraphBuilder.cpp
hotspot/src/share/vm/c1/c1_IR.cpp
hotspot/src/share/vm/c1/c1_IR.hpp
hotspot/src/share/vm/c1/c1_Instruction.cpp
hotspot/src/share/vm/c1/c1_Instruction.hpp
hotspot/src/share/vm/c1/c1_LIRGenerator.hpp
hotspot/src/share/vm/c1/c1_LinearScan.cpp
hotspot/src/share/vm/c1/c1_LinearScan.hpp
hotspot/src/share/vm/c1/c1_ValueSet.hpp
hotspot/src/share/vm/ci/ciMethod.cpp
hotspot/src/share/vm/ci/ciMethod.hpp
hotspot/src/share/vm/classfile/classFileParser.cpp
hotspot/src/share/vm/compiler/methodLiveness.cpp
hotspot/src/share/vm/compiler/methodLiveness.hpp
hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp
hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp
hotspot/src/share/vm/gc/cms/vmStructs_cms.hpp
hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp
hotspot/src/share/vm/gc/g1/g1CardLiveData.hpp
hotspot/src/share/vm/gc/g1/g1CardLiveData.inline.hpp
hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp
hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp
hotspot/src/share/vm/gc/g1/g1PageBasedVirtualSpace.cpp
hotspot/src/share/vm/gc/g1/g1PageBasedVirtualSpace.hpp
hotspot/src/share/vm/gc/g1/g1RegionToSpaceMapper.cpp
hotspot/src/share/vm/gc/g1/g1RegionToSpaceMapper.hpp
hotspot/src/share/vm/gc/g1/heapRegionManager.cpp
hotspot/src/share/vm/gc/g1/heapRegionManager.hpp
hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp
hotspot/src/share/vm/gc/g1/heapRegionRemSet.hpp
hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp
hotspot/src/share/vm/gc/parallel/parMarkBitMap.hpp
hotspot/src/share/vm/oops/generateOopMap.cpp
hotspot/src/share/vm/oops/generateOopMap.hpp
hotspot/src/share/vm/opto/parse.hpp
hotspot/src/share/vm/opto/parse1.cpp
hotspot/src/share/vm/runtime/vmStructs.cpp
hotspot/src/share/vm/utilities/bitMap.cpp
hotspot/src/share/vm/utilities/bitMap.hpp
hotspot/src/share/vm/utilities/bitMap.inline.hpp
--- 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);
--- 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
--- 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"));
--- 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);
--- 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));
--- 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);
--- 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();
   }
 
--- 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
 
--- 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
--- 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();
--- 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.
--- 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();
--- 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;
--- 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);
--- 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;
--- 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(),
--- 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
--- 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*)             \
--- 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),
--- 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;
 
--- 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 {
--- 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);
 }
--- 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
--- 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 {
--- 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
--- 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) {
--- 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);
--- 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 {
--- 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;
--- 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),
--- 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;
 
--- 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;
   }
 
--- 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;
 };
--- 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) {
--- 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               ();
--- 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:
 
--- 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)) {
--- 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<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/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<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	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 <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	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() {