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