1 /*
  2  * Copyright (c) 2000, 2023, 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 #ifndef SHARE_OOPS_ARRAY_HPP
 26 #define SHARE_OOPS_ARRAY_HPP
 27 
 28 #include "runtime/atomic.hpp"
 29 #include "utilities/align.hpp"
 30 #include "utilities/exceptions.hpp"
 31 #include "utilities/globalDefinitions.hpp"
 32 #include "utilities/ostream.hpp"
 33 
 34 // Array for metadata allocation
 35 
 36 template <typename T>
 37 class Array: public MetaspaceObj {
 38   friend class ArchiveBuilder;
 39   friend class MetadataFactory;
 40   friend class VMStructs;
 41   friend class JVMCIVMStructs;
 42   friend class MethodHandleCompiler;           // special case
 43   friend class WhiteBox;
 44   friend class FieldInfoStream;
 45 protected:
 46   int _length;                                 // the number of array elements
 47   T   _data[1];                                // the array memory
 48 
 49   void initialize(int length) {
 50     _length = length;
 51   }
 52 
 53  private:
 54   NONCOPYABLE(Array);
 55 
 56   inline void* operator new(size_t size, ClassLoaderData* loader_data, int length, TRAPS) throw();
 57 
 58   static size_t byte_sizeof(int length, size_t elm_byte_size) {
 59     return sizeof(Array<T>) + MAX2(length - 1, 0) * elm_byte_size;
 60   }
 61   static size_t byte_sizeof(int length) { return byte_sizeof(length, sizeof(T)); }
 62 
 63   // WhiteBox API helper.
 64   // Can't distinguish between array of length 0 and length 1,
 65   // will always return 0 in those cases.
 66   static int bytes_to_length(size_t bytes)       {
 67     assert(is_aligned(bytes, BytesPerWord), "Must be, for now");
 68 
 69     if (sizeof(Array<T>) >= bytes) {
 70       return 0;
 71     }
 72 
 73     size_t left = bytes - sizeof(Array<T>);
 74     assert(is_aligned(left, sizeof(T)), "Must be");
 75 
 76     size_t elements = left / sizeof(T);
 77     assert(elements <= (size_t)INT_MAX, "number of elements " SIZE_FORMAT "doesn't fit into an int.", elements);
 78 
 79     int length = (int)elements;
 80 
 81     assert((size_t)size(length) * BytesPerWord == (size_t)bytes,
 82            "Expected: " SIZE_FORMAT " got: " SIZE_FORMAT,
 83            bytes, (size_t)size(length) * BytesPerWord);
 84 
 85     return length;
 86   }
 87 
 88   explicit Array(int length) : _length(length) {
 89     assert(length >= 0, "illegal length");
 90   }
 91 
 92   Array(int length, T init) : _length(length) {
 93     assert(length >= 0, "illegal length");
 94     for (int i = 0; i < length; i++) {
 95       data()[i] = init;
 96     }
 97   }
 98 
 99  public:
100 
101   // standard operations
102   int  length() const                 { return _length; }
103 
104   T* data() {
105     return reinterpret_cast<T*>(
106       reinterpret_cast<char*>(this) + base_offset_in_bytes());
107   }
108 
109   const T* data() const {
110     return reinterpret_cast<const T*>(
111       reinterpret_cast<const char*>(this) + base_offset_in_bytes());
112   }
113 
114   bool is_empty() const               { return length() == 0; }
115 
116   int index_of(const T& x) const {
117     int i = length();
118     while (i-- > 0 && data()[i] != x) ;
119 
120     return i;
121   }
122 
123   // sort the array.
124   bool contains(const T& x) const      { return index_of(x) >= 0; }
125 
126   T    at(int i) const                 { assert(i >= 0 && i< _length, "oob: 0 <= %d < %d", i, _length); return data()[i]; }
127   void at_put(const int i, const T& x) { assert(i >= 0 && i< _length, "oob: 0 <= %d < %d", i, _length); data()[i] = x; }
128   T*   adr_at(const int i)             { assert(i >= 0 && i< _length, "oob: 0 <= %d < %d", i, _length); return &data()[i]; }
129   int  find(const T& x)                { return index_of(x); }
130 
131   T at_acquire(const int i)            { return Atomic::load_acquire(adr_at(i)); }
132   void release_at_put(int i, T x)      { Atomic::release_store(adr_at(i), x); }
133 
134   static int size(int length) {
135     size_t bytes = align_up(byte_sizeof(length), BytesPerWord);
136     size_t words = bytes / BytesPerWord;
137 
138     assert(words <= INT_MAX, "Overflow: " SIZE_FORMAT, words);
139 
140     return (int)words;
141   }
142   int size() {
143     return size(_length);
144   }
145 
146   static int length_offset_in_bytes() { return (int) (offset_of(Array<T>, _length)); }
147   // Note, this offset don't have to be wordSize aligned.
148   static int base_offset_in_bytes() { return (int) (offset_of(Array<T>, _data)); };
149 
150   // FIXME: How to handle this?
151   void print_value_on(outputStream* st) const {
152     st->print("Array<T>(" PTR_FORMAT ")", p2i(this));
153   }
154 
155 #ifndef PRODUCT
156   void print(outputStream* st) {
157      for (int i = 0; i< _length; i++) {
158        st->print_cr("%d: " INTPTR_FORMAT, i, (intptr_t)at(i));
159      }
160   }
161   void print() { print(tty); }
162 #endif // PRODUCT
163 };
164 
165 
166 #endif // SHARE_OOPS_ARRAY_HPP