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