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