src/hotspot/share/gc/shared/preservedMarks.cpp
changeset 47216 71c04702a3d5
parent 39625 8702e5b9bfed
child 47885 5caa1d5f74c1
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  *
       
    23  */
       
    24 
       
    25 #include "precompiled.hpp"
       
    26 #include "gc/shared/preservedMarks.inline.hpp"
       
    27 #include "gc/shared/workgroup.hpp"
       
    28 #include "memory/allocation.inline.hpp"
       
    29 #include "memory/resourceArea.hpp"
       
    30 #include "utilities/macros.hpp"
       
    31 
       
    32 void PreservedMarks::restore() {
       
    33   while (!_stack.is_empty()) {
       
    34     const OopAndMarkOop elem = _stack.pop();
       
    35     elem.set_mark();
       
    36   }
       
    37   assert_empty();
       
    38 }
       
    39 
       
    40 void PreservedMarks::restore_and_increment(volatile size_t* const total_size_addr) {
       
    41   const size_t stack_size = size();
       
    42   restore();
       
    43   // Only do the atomic add if the size is > 0.
       
    44   if (stack_size > 0) {
       
    45     Atomic::add(stack_size, total_size_addr);
       
    46   }
       
    47 }
       
    48 
       
    49 #ifndef PRODUCT
       
    50 void PreservedMarks::assert_empty() {
       
    51   assert(_stack.is_empty(), "stack expected to be empty, size = " SIZE_FORMAT,
       
    52          _stack.size());
       
    53   assert(_stack.cache_size() == 0,
       
    54          "stack expected to have no cached segments, cache size = " SIZE_FORMAT,
       
    55          _stack.cache_size());
       
    56 }
       
    57 #endif // ndef PRODUCT
       
    58 
       
    59 void RemoveForwardedPointerClosure::do_object(oop obj) {
       
    60   if (obj->is_forwarded()) {
       
    61     PreservedMarks::init_forwarded_mark(obj);
       
    62   }
       
    63 }
       
    64 
       
    65 void PreservedMarksSet::init(uint num) {
       
    66   assert(_stacks == NULL && _num == 0, "do not re-initialize");
       
    67   assert(num > 0, "pre-condition");
       
    68   if (_in_c_heap) {
       
    69     _stacks = NEW_C_HEAP_ARRAY(Padded<PreservedMarks>, num, mtGC);
       
    70   } else {
       
    71     _stacks = NEW_RESOURCE_ARRAY(Padded<PreservedMarks>, num);
       
    72   }
       
    73   for (uint i = 0; i < num; i += 1) {
       
    74     ::new (_stacks + i) PreservedMarks();
       
    75   }
       
    76   _num = num;
       
    77 
       
    78   assert_empty();
       
    79 }
       
    80 
       
    81 class ParRestoreTask : public AbstractGangTask {
       
    82 private:
       
    83   PreservedMarksSet* const _preserved_marks_set;
       
    84   SequentialSubTasksDone _sub_tasks;
       
    85   volatile size_t* const _total_size_addr;
       
    86 
       
    87 public:
       
    88   virtual void work(uint worker_id) {
       
    89     uint task_id = 0;
       
    90     while (!_sub_tasks.is_task_claimed(/* reference */ task_id)) {
       
    91       _preserved_marks_set->get(task_id)->restore_and_increment(_total_size_addr);
       
    92     }
       
    93     _sub_tasks.all_tasks_completed();
       
    94   }
       
    95 
       
    96   ParRestoreTask(uint worker_num,
       
    97                  PreservedMarksSet* preserved_marks_set,
       
    98                  volatile size_t* total_size_addr)
       
    99       : AbstractGangTask("Parallel Preserved Mark Restoration"),
       
   100         _preserved_marks_set(preserved_marks_set),
       
   101         _total_size_addr(total_size_addr) {
       
   102     _sub_tasks.set_n_threads(worker_num);
       
   103     _sub_tasks.set_n_tasks(preserved_marks_set->num());
       
   104   }
       
   105 };
       
   106 
       
   107 
       
   108 void PreservedMarksSet::reclaim() {
       
   109   assert_empty();
       
   110 
       
   111   for (uint i = 0; i < _num; i += 1) {
       
   112     _stacks[i].~Padded<PreservedMarks>();
       
   113   }
       
   114 
       
   115   if (_in_c_heap) {
       
   116     FREE_C_HEAP_ARRAY(Padded<PreservedMarks>, _stacks);
       
   117   } else {
       
   118     // the array was resource-allocated, so nothing to do
       
   119   }
       
   120   _stacks = NULL;
       
   121   _num = 0;
       
   122 }
       
   123 
       
   124 #ifndef PRODUCT
       
   125 void PreservedMarksSet::assert_empty() {
       
   126   assert(_stacks != NULL && _num > 0, "should have been initialized");
       
   127   for (uint i = 0; i < _num; i += 1) {
       
   128     get(i)->assert_empty();
       
   129   }
       
   130 }
       
   131 #endif // ndef PRODUCT
       
   132 
       
   133 void SharedRestorePreservedMarksTaskExecutor::restore(PreservedMarksSet* preserved_marks_set,
       
   134                                                       volatile size_t* total_size_addr) {
       
   135   if (_workers == NULL) {
       
   136     for (uint i = 0; i < preserved_marks_set->num(); i += 1) {
       
   137       *total_size_addr += preserved_marks_set->get(i)->size();
       
   138       preserved_marks_set->get(i)->restore();
       
   139     }
       
   140   } else {
       
   141     ParRestoreTask task(_workers->active_workers(), preserved_marks_set, total_size_addr);
       
   142     _workers->run_task(&task);
       
   143   }
       
   144 }