1 /*
  2  * Copyright (c) 2017, 2020, 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_VM_OOPS_INLINEKLASS_HPP
 26 #define SHARE_VM_OOPS_INLINEKLASS_HPP
 27 
 28 #include "classfile/javaClasses.hpp"
 29 #include "oops/instanceKlass.hpp"
 30 #include "oops/method.hpp"
 31 #include "runtime/registerMap.hpp"
 32 //#include "oops/oop.inline.hpp"
 33 
 34 // An InlineKlass is a specialized InstanceKlass for inline types.
 35 
 36 
 37 class InlineKlass: public InstanceKlass {
 38   friend class VMStructs;
 39   friend class InstanceKlass;
 40 
 41  public:
 42   InlineKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); }
 43 
 44  private:
 45 
 46   // Constructor
 47   InlineKlass(const ClassFileParser& parser);
 48 
 49   inline InlineKlassFixedBlock* inlineklass_static_block() const;
 50   inline address adr_return_regs() const;
 51 
 52   address adr_extended_sig() const {
 53     assert(_adr_inlineklass_fixed_block != NULL, "Should have been initialized");
 54     return ((address)_adr_inlineklass_fixed_block) + in_bytes(byte_offset_of(InlineKlassFixedBlock, _extended_sig));
 55   }
 56 
 57   // pack and unpack handlers for inline types return
 58   address adr_pack_handler() const {
 59     assert(_adr_inlineklass_fixed_block != NULL, "Should have been initialized");
 60     return ((address)_adr_inlineklass_fixed_block) + in_bytes(byte_offset_of(InlineKlassFixedBlock, _pack_handler));
 61   }
 62 
 63   address adr_pack_handler_jobject() const {
 64     assert(_adr_inlineklass_fixed_block != NULL, "Should have been initialized");
 65     return ((address)_adr_inlineklass_fixed_block) + in_bytes(byte_offset_of(InlineKlassFixedBlock, _pack_handler_jobject));
 66   }
 67 
 68   address adr_unpack_handler() const {
 69     assert(_adr_inlineklass_fixed_block != NULL, "Should have been initialized");
 70     return ((address)_adr_inlineklass_fixed_block) + in_bytes(byte_offset_of(InlineKlassFixedBlock, _unpack_handler));
 71   }
 72 
 73   address adr_default_value_offset() const {
 74     assert(_adr_inlineklass_fixed_block != NULL, "Should have been initialized");
 75     return ((address)_adr_inlineklass_fixed_block) + in_bytes(default_value_offset_offset());
 76   }
 77 
 78   ArrayKlass* volatile* adr_null_free_inline_array_klasses() const {
 79     assert(_adr_inlineklass_fixed_block != NULL, "Should have been initialized");
 80     return (ArrayKlass* volatile*) ((address)_adr_inlineklass_fixed_block) + in_bytes(byte_offset_of(InlineKlassFixedBlock, _null_free_inline_array_klasses));
 81   }
 82 
 83   ArrayKlass* null_free_inline_array_klasses() const {
 84     return *adr_null_free_inline_array_klasses();
 85   }
 86 
 87   address adr_alignment() const {
 88     assert(_adr_inlineklass_fixed_block != NULL, "Should have been initialized");
 89     return ((address)_adr_inlineklass_fixed_block) + in_bytes(byte_offset_of(InlineKlassFixedBlock, _alignment));
 90   }
 91 
 92   address adr_first_field_offset() const {
 93     assert(_adr_inlineklass_fixed_block != NULL, "Should have been initialized");
 94     return ((address)_adr_inlineklass_fixed_block) + in_bytes(byte_offset_of(InlineKlassFixedBlock, _first_field_offset));
 95   }
 96 
 97   address adr_exact_size_in_bytes() const {
 98     assert(_adr_inlineklass_fixed_block != NULL, "Should have been initialized");
 99     return ((address)_adr_inlineklass_fixed_block) + in_bytes(byte_offset_of(InlineKlassFixedBlock, _exact_size_in_bytes));
100   }
101 
102  public:
103   int get_alignment() const {
104     return *(int*)adr_alignment();
105   }
106 
107   void set_alignment(int alignment) {
108     *(int*)adr_alignment() = alignment;
109   }
110 
111   int first_field_offset() const {
112     int offset = *(int*)adr_first_field_offset();
113     assert(offset != 0, "Must be initialized before use");
114     return *(int*)adr_first_field_offset();
115   }
116 
117   void set_first_field_offset(int offset) {
118     *(int*)adr_first_field_offset() = offset;
119   }
120 
121   int get_exact_size_in_bytes() const {
122     return *(int*)adr_exact_size_in_bytes();
123   }
124 
125   void set_exact_size_in_bytes(int exact_size) {
126     *(int*)adr_exact_size_in_bytes() = exact_size;
127   }
128 
129   int first_field_offset_old();
130 
131   virtual void remove_unshareable_info();
132   virtual void remove_java_mirror();
133   virtual void restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, PackageEntry* pkg_entry, TRAPS);
134   virtual void metaspace_pointers_do(MetaspaceClosure* it);
135 
136  private:
137   int collect_fields(GrowableArray<SigEntry>* sig, int base_off = 0);
138 
139   void cleanup_blobs();
140 
141  public:
142   // Type testing
143   bool is_inline_klass_slow() const        { return true; }
144 
145   // ref and val mirror
146   oop ref_mirror() const { return java_mirror(); }
147   oop val_mirror() const { return java_lang_Class::secondary_mirror(java_mirror()); }
148 
149   // naming
150   const char* ref_signature_name() const {
151     return InstanceKlass::signature_name_of_carrier(JVM_SIGNATURE_CLASS);
152   }
153   const char* val_signature_name() const {
154     return InstanceKlass::signature_name_of_carrier(JVM_SIGNATURE_INLINE_TYPE);
155   }
156 
157   // Iterators
158   virtual void array_klasses_do(void f(Klass* k));
159   virtual void array_klasses_do(void f(Klass* k, TRAPS), TRAPS);
160 
161   // Casting from Klass*
162   static InlineKlass* cast(Klass* k);
163 
164   // Use this to return the size of an instance in heap words.
165   // Note that this size only applies to heap allocated stand-alone instances.
166   virtual int size_helper() const {
167     return layout_helper_to_size_helper(layout_helper());
168   }
169 
170   // allocate_instance() allocates a stand alone value in the Java heap
171   // initialized to default value (cleared memory)
172   instanceOop allocate_instance(TRAPS);
173   // allocates a stand alone inline buffer in the Java heap
174   // DOES NOT have memory cleared, user MUST initialize payload before
175   // returning to Java (i.e.: inline_copy)
176   instanceOop allocate_instance_buffer(TRAPS);
177 
178   address data_for_oop(oop o) const;
179 
180   // Query if this class promises atomicity one way or another
181   bool is_atomic() { return is_naturally_atomic() || is_declared_atomic(); }
182 
183   bool flatten_array();
184 
185   bool contains_oops() const { return nonstatic_oop_map_count() > 0; }
186   int nonstatic_oop_count();
187 
188   // null free inline arrays...
189   //
190 
191   // null free inline array klass, akin to InstanceKlass::array_klass()
192   // Returns the array class for the n'th dimension
193   Klass* null_free_inline_array_klass(int n, TRAPS);
194   Klass* null_free_inline_array_klass_or_null(int n);
195 
196   // Returns the array class with this class as element type
197   Klass* null_free_inline_array_klass(TRAPS);
198   Klass* null_free_inline_array_klass_or_null();
199 
200 
201   // General store methods
202   //
203   // Normally loads and store methods would be found in *Oops classes, but since values can be
204   // "in-lined" (flattened) into containing oops, these methods reside here in InlineKlass.
205   //
206   // "inline_copy_*_to_new_*" assume new memory (i.e. IS_DEST_UNINITIALIZED for write barriers)
207 
208   void inline_copy_payload_to_new_oop(void* src, oop dst);
209   void inline_copy_oop_to_new_oop(oop src, oop dst);
210   void inline_copy_oop_to_new_payload(oop src, void* dst);
211   void inline_copy_oop_to_payload(oop src, void* dst);
212 
213   oop read_inlined_field(oop obj, int offset, TRAPS);
214   void write_inlined_field(oop obj, int offset, oop value, TRAPS);
215 
216   // oop iterate raw inline type data pointer (where oop_addr may not be an oop, but backing/array-element)
217   template <typename T, class OopClosureType>
218   inline void oop_iterate_specialized(const address oop_addr, OopClosureType* closure);
219 
220   template <typename T, class OopClosureType>
221   inline void oop_iterate_specialized_bounded(const address oop_addr, OopClosureType* closure, void* lo, void* hi);
222 
223   // calling convention support
224   void initialize_calling_convention(TRAPS);
225   Array<SigEntry>* extended_sig() const {
226     return *((Array<SigEntry>**)adr_extended_sig());
227   }
228   inline Array<VMRegPair>* return_regs() const;
229   bool can_be_passed_as_fields() const;
230   bool can_be_returned_as_fields(bool init = false) const;
231   void save_oop_fields(const RegisterMap& map, GrowableArray<Handle>& handles) const;
232   void restore_oop_results(RegisterMap& map, GrowableArray<Handle>& handles) const;
233   oop realloc_result(const RegisterMap& reg_map, const GrowableArray<Handle>& handles, TRAPS);
234   static InlineKlass* returned_inline_klass(const RegisterMap& reg_map);
235 
236   address pack_handler() const {
237     return *(address*)adr_pack_handler();
238   }
239 
240   address unpack_handler() const {
241     return *(address*)adr_unpack_handler();
242   }
243 
244   // pack and unpack handlers. Need to be loadable from generated code
245   // so at a fixed offset from the base of the klass pointer.
246   static ByteSize pack_handler_offset() {
247     return byte_offset_of(InlineKlassFixedBlock, _pack_handler);
248   }
249 
250   static ByteSize pack_handler_jobject_offset() {
251     return byte_offset_of(InlineKlassFixedBlock, _pack_handler_jobject);
252   }
253 
254   static ByteSize unpack_handler_offset() {
255     return byte_offset_of(InlineKlassFixedBlock, _unpack_handler);
256   }
257 
258   static ByteSize default_value_offset_offset() {
259     return byte_offset_of(InlineKlassFixedBlock, _default_value_offset);
260   }
261 
262   static ByteSize first_field_offset_offset() {
263     return byte_offset_of(InlineKlassFixedBlock, _first_field_offset);
264   }
265 
266   void set_default_value_offset(int offset) {
267     *((int*)adr_default_value_offset()) = offset;
268   }
269 
270   int default_value_offset() {
271     int offset = *((int*)adr_default_value_offset());
272     assert(offset != 0, "must not be called if not initialized");
273     return offset;
274   }
275 
276   void set_default_value(oop val) {
277     java_mirror()->obj_field_put(default_value_offset(), val);
278   }
279 
280   oop default_value();
281   void deallocate_contents(ClassLoaderData* loader_data);
282   static void cleanup(InlineKlass* ik) ;
283 
284   // Verification
285   void verify_on(outputStream* st);
286   void oop_verify_on(oop obj, outputStream* st);
287 
288 };
289 
290 #endif /* SHARE_VM_OOPS_INLINEKLASS_HPP */