1 /*
   2  * Copyright (c) 2017, 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 #ifndef SHARE_VM_OOPS_VALUEARRAYKLASS_INLINE_HPP
  25 #define SHARE_VM_OOPS_VALUEARRAYKLASS_INLINE_HPP
  26 
  27 #include "memory/memRegion.hpp"
  28 #include "memory/iterator.inline.hpp"
  29 #include "oops/arrayKlass.hpp"
  30 #include "oops/klass.hpp"
  31 #include "oops/oop.inline.hpp"
  32 #include "oops/valueArrayKlass.hpp"
  33 #include "oops/valueArrayOop.hpp"
  34 #include "oops/valueKlass.hpp"
  35 #include "oops/valueKlass.inline.hpp"
  36 #include "utilities/macros.hpp"
  37 
  38 /*
  39  * Warning incomplete: requires embedded oops, not yet enabled, so consider this a "sketch-up" of oop iterators
  40  */
  41 
  42 template <bool nv, typename T, class OopClosureType>
  43 void ValueArrayKlass::oop_oop_iterate_elements_specialized(valueArrayOop a,
  44                                                            OopClosureType* closure) {
  45   assert(contains_oops(), "Nothing to iterate");
  46 
  47   const int shift = Klass::layout_helper_log2_element_size(layout_helper());
  48   const int addr_incr = 1 << shift;
  49   uintptr_t elem_addr = (uintptr_t) a->base();
  50   const uintptr_t stop_addr = elem_addr + ((uintptr_t)a->length() << shift);
  51   const int oop_offset = ((ValueKlass*)element_klass())->first_field_offset();
  52 
  53   while (elem_addr < stop_addr) {
  54     ((ValueKlass*)element_klass())->oop_iterate_specialized<nv, T>((address)(elem_addr - oop_offset), closure);
  55     elem_addr += addr_incr;
  56   }
  57 }
  58 
  59 template <bool nv, typename T, class OopClosureType>
  60 void ValueArrayKlass::oop_oop_iterate_elements_specialized_bounded(valueArrayOop a,
  61                                                                    OopClosureType* closure,
  62                                                                    void* lo, void* hi) {
  63   assert(contains_oops(), "Nothing to iterate");
  64 
  65   const int shift = Klass::layout_helper_log2_element_size(layout_helper());
  66   const int addr_incr = 1 << shift;
  67   uintptr_t elem_addr = (uintptr_t)a->base();
  68   uintptr_t stop_addr = elem_addr + ((uintptr_t)a->length() << shift);
  69   const int oop_offset = ((ValueKlass*)element_klass())->first_field_offset();
  70 
  71   if (elem_addr < (uintptr_t) lo) {
  72     uintptr_t diff = ((uintptr_t) lo) - elem_addr;
  73     elem_addr += (diff >> shift) << shift;
  74   }
  75   if (stop_addr > (uintptr_t) hi) {
  76     uintptr_t diff = stop_addr - ((uintptr_t) hi);
  77     stop_addr -= (diff >> shift) << shift;
  78   }
  79 
  80   const uintptr_t end = stop_addr;
  81   while (elem_addr < end) {
  82     ((ValueKlass*)element_klass())->oop_iterate_specialized_bounded<nv, T>((address)(elem_addr - oop_offset), closure, lo, hi);
  83     elem_addr += addr_incr;
  84   }
  85 }
  86 
  87 template <bool nv, class OopClosureType>
  88 void ValueArrayKlass::oop_oop_iterate_elements(valueArrayOop a, OopClosureType* closure) {
  89   if (contains_oops()) {
  90     if (UseCompressedOops) {
  91       oop_oop_iterate_elements_specialized<nv, narrowOop>(a, closure);
  92     } else {
  93       oop_oop_iterate_elements_specialized<nv, oop>(a, closure);
  94     }
  95   }
  96 }
  97 
  98 template <bool nv, typename OopClosureType>
  99 void ValueArrayKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
 100   assert(obj->is_valueArray(),"must be a value array");
 101 
 102   if (Devirtualizer<nv>::do_metadata(closure)) {
 103     Devirtualizer<nv>::do_klass(closure, obj->klass());
 104     Devirtualizer<nv>::do_klass(closure, ValueArrayKlass::cast(obj->klass())->element_klass());
 105   }
 106 
 107   oop_oop_iterate_elements<nv>(valueArrayOop(obj), closure);
 108 }
 109 
 110 template <bool nv, class OopClosureType>
 111 void ValueArrayKlass::oop_oop_iterate_elements_bounded(valueArrayOop a, OopClosureType* closure, MemRegion mr) {
 112   if (contains_oops()) {
 113     if (UseCompressedOops) {
 114       oop_oop_iterate_elements_specialized_bounded<nv, narrowOop>(a, closure, mr.start(), mr.end());
 115     } else {
 116       oop_oop_iterate_elements_specialized_bounded<nv, oop>(a, closure, mr.start(), mr.end());
 117     }
 118   }
 119 }
 120 
 121 
 122 template <bool nv, typename OopClosureType>
 123 void ValueArrayKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
 124   valueArrayOop a = valueArrayOop(obj);
 125   if (Devirtualizer<nv>::do_metadata(closure)) {
 126     Devirtualizer<nv>::do_klass(closure, a->klass());
 127     Devirtualizer<nv>::do_klass(closure, ValueArrayKlass::cast(obj->klass())->element_klass());
 128   }
 129   oop_oop_iterate_elements_bounded<nv>(a, closure, mr);
 130 }
 131 
 132 
 133 #define ALL_VALUE_ARRAY_KLASS_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix)    \
 134   OOP_OOP_ITERATE_DEFN(             ValueArrayKlass, OopClosureType, nv_suffix)  \
 135   OOP_OOP_ITERATE_DEFN_BOUNDED(     ValueArrayKlass, OopClosureType, nv_suffix)  \
 136   OOP_OOP_ITERATE_DEFN_NO_BACKWARDS(ValueArrayKlass, OopClosureType, nv_suffix)
 137 
 138 
 139 #endif // SHARE_VM_OOPS_VALUEARRAYKLASS_INLINE_HPP