1 /*
  2  * Copyright (c) 2000, 2024, 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   inline void* operator new(size_t size, ClassLoaderData* loader_data, int length) throw();
 59 
 60 // Work-around -- see JDK-8331086
 61   inline void* operator new(size_t size, int length, MEMFLAGS flags) throw();
 62 
 63   static size_t byte_sizeof(int length, size_t elm_byte_size) {
 64     return sizeof(Array<T>) + MAX2(length - 1, 0) * elm_byte_size;
 65   }
 66   static size_t byte_sizeof(int length) { return byte_sizeof(length, sizeof(T)); }
 67 
 68   // WhiteBox API helper.
 69   // Can't distinguish between array of length 0 and length 1,
 70   // will always return 0 in those cases.
 71   static int bytes_to_length(size_t bytes)       {
 72     assert(is_aligned(bytes, BytesPerWord), "Must be, for now");
 73 
 74     if (sizeof(Array<T>) >= bytes) {
 75       return 0;
 76     }
 77 
 78     size_t left = bytes - sizeof(Array<T>);
 79     assert(is_aligned(left, sizeof(T)), "Must be");
 80 
 81     size_t elements = left / sizeof(T);
 82     assert(elements <= (size_t)INT_MAX, "number of elements " SIZE_FORMAT "doesn't fit into an int.", elements);
 83 
 84     int length = (int)elements;
 85 
 86     assert((size_t)size(length) * BytesPerWord == (size_t)bytes,
 87            "Expected: " SIZE_FORMAT " got: " SIZE_FORMAT,
 88            bytes, (size_t)size(length) * BytesPerWord);
 89 
 90     return length;
 91   }
 92 
 93   explicit Array(int length) : _length(length) {
 94     assert(length >= 0, "illegal length");
 95   }
 96 
 97   Array(int length, T init) : _length(length) {
 98     assert(length >= 0, "illegal length");
 99     for (int i = 0; i < length; i++) {
100       data()[i] = init;
101     }
102   }
103 
104  public:
105 
106   // standard operations
107   int  length() const                 { return _length; }
108 
109   T* data() {
110     return reinterpret_cast<T*>(
111       reinterpret_cast<char*>(this) + base_offset_in_bytes());
112   }
113 
114   const T* data() const {
115     return reinterpret_cast<const T*>(
116       reinterpret_cast<const char*>(this) + base_offset_in_bytes());
117   }
118 
119   bool is_empty() const               { return length() == 0; }
120 
121   int index_of(const T& x) const {
122     int i = length();
123     while (i-- > 0 && data()[i] != x) ;
124 
125     return i;
126   }
127 
128   // sort the array.
129   bool contains(const T& x) const      { return index_of(x) >= 0; }
130 
131   T    at(int i) const                 { assert(i >= 0 && i< _length, "oob: 0 <= %d < %d", i, _length); return data()[i]; }
132   void at_put(const int i, const T& x) { assert(i >= 0 && i< _length, "oob: 0 <= %d < %d", i, _length); data()[i] = x; }
133   T*   adr_at(const int i)             { assert(i >= 0 && i< _length, "oob: 0 <= %d < %d", i, _length); return &data()[i]; }
134   int  find(const T& x)                { return index_of(x); }
135 
136   T at_acquire(const int i)            { return Atomic::load_acquire(adr_at(i)); }
137   void release_at_put(int i, T x)      { Atomic::release_store(adr_at(i), x); }
138 
139   static int size(int length) {
140     size_t bytes = align_up(byte_sizeof(length), BytesPerWord);
141     size_t words = bytes / BytesPerWord;
142 
143     assert(words <= INT_MAX, "Overflow: " SIZE_FORMAT, words);
144 
145     return (int)words;
146   }
147   int size() {
148     return size(_length);
149   }
150 
151   static int length_offset_in_bytes() { return (int) (offset_of(Array<T>, _length)); }
152   // Note, this offset don't have to be wordSize aligned.
153   static int base_offset_in_bytes() { return (int) (offset_of(Array<T>, _data)); };
154 
155   // FIXME: How to handle this?
156   void print_value_on(outputStream* st) const {
157     st->print("Array<T>(" PTR_FORMAT ")", p2i(this));
158   }
159 
160 #ifndef PRODUCT
161   void print(outputStream* st) {
162      for (int i = 0; i< _length; i++) {
163        st->print_cr("%d: " INTPTR_FORMAT, i, (intptr_t)at(i));
164      }
165   }
166   void print() { print(tty); }
167 #endif // PRODUCT
168 };
169 
170 
171 #endif // SHARE_OOPS_ARRAY_HPP