1 /* 2 * Copyright (c) 2017, 2019, 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_VALUEKLASS_HPP 26 #define SHARE_VM_OOPS_VALUEKLASS_HPP 27 28 #include "classfile/javaClasses.hpp" 29 #include "oops/instanceKlass.hpp" 30 #include "oops/method.hpp" 31 //#include "oops/oop.inline.hpp" 32 33 // A ValueKlass is a specialized InstanceKlass for value types. 34 35 36 class ValueKlass: public InstanceKlass { 37 friend class VMStructs; 38 friend class InstanceKlass; 39 40 private: 41 42 // Constructor 43 ValueKlass(const ClassFileParser& parser); 44 45 ValueKlassFixedBlock* valueklass_static_block() const { 46 address adr_jf = adr_value_fields_klasses(); 47 if (adr_jf != NULL) { 48 return (ValueKlassFixedBlock*)(adr_jf + this->java_fields_count() * sizeof(Klass*)); 49 } 50 51 address adr_fing = adr_fingerprint(); 52 if (adr_fing != NULL) { 53 return (ValueKlassFixedBlock*)(adr_fingerprint() + sizeof(u8)); 54 } 55 56 InstanceKlass** adr_host = adr_unsafe_anonymous_host(); 57 if (adr_host != NULL) { 58 return (ValueKlassFixedBlock*)(adr_host + 1); 59 } 60 61 Klass* volatile* adr_impl = adr_implementor(); 62 if (adr_impl != NULL) { 63 return (ValueKlassFixedBlock*)(adr_impl + 1); 64 } 65 66 return (ValueKlassFixedBlock*)end_of_nonstatic_oop_maps(); 67 } 68 69 address adr_extended_sig() const { 70 assert(_adr_valueklass_fixed_block != NULL, "Should have been initialized"); 71 return ((address)_adr_valueklass_fixed_block) + in_bytes(byte_offset_of(ValueKlassFixedBlock, _extended_sig)); 72 } 73 74 address adr_return_regs() const { 75 ValueKlassFixedBlock* vkst = valueklass_static_block(); 76 return ((address)_adr_valueklass_fixed_block) + in_bytes(byte_offset_of(ValueKlassFixedBlock, _return_regs)); 77 } 78 79 // pack and unpack handlers for value types return 80 address adr_pack_handler() const { 81 assert(_adr_valueklass_fixed_block != NULL, "Should have been initialized"); 82 return ((address)_adr_valueklass_fixed_block) + in_bytes(byte_offset_of(ValueKlassFixedBlock, _pack_handler)); 83 } 84 85 address adr_pack_handler_jobject() const { 86 assert(_adr_valueklass_fixed_block != NULL, "Should have been initialized"); 87 return ((address)_adr_valueklass_fixed_block) + in_bytes(byte_offset_of(ValueKlassFixedBlock, _pack_handler_jobject)); 88 } 89 90 address adr_unpack_handler() const { 91 assert(_adr_valueklass_fixed_block != NULL, "Should have been initialized"); 92 return ((address)_adr_valueklass_fixed_block) + in_bytes(byte_offset_of(ValueKlassFixedBlock, _unpack_handler)); 93 } 94 95 address adr_default_value_offset() const { 96 assert(_adr_valueklass_fixed_block != NULL, "Should have been initialized"); 97 return ((address)_adr_valueklass_fixed_block) + in_bytes(default_value_offset_offset()); 98 } 99 100 address adr_value_array_klass() const { 101 assert(_adr_valueklass_fixed_block != NULL, "Should have been initialized"); 102 return ((address)_adr_valueklass_fixed_block) + in_bytes(byte_offset_of(ValueKlassFixedBlock, _value_array_klass)); 103 } 104 105 Klass* get_value_array_klass() const { 106 return *(Klass**)adr_value_array_klass(); 107 } 108 109 Klass* acquire_value_array_klass() const { 110 return OrderAccess::load_acquire((Klass**)adr_value_array_klass()); 111 } 112 113 Klass* allocate_value_array_klass(TRAPS); 114 115 address adr_alignment() const { 116 assert(_adr_valueklass_fixed_block != NULL, "Should have been initialized"); 117 return ((address)_adr_valueklass_fixed_block) + in_bytes(byte_offset_of(ValueKlassFixedBlock, _alignment)); 118 } 119 120 address adr_first_field_offset() const { 121 assert(_adr_valueklass_fixed_block != NULL, "Should have been initialized"); 122 return ((address)_adr_valueklass_fixed_block) + in_bytes(byte_offset_of(ValueKlassFixedBlock, _first_field_offset)); 123 } 124 125 address adr_exact_size_in_bytes() const { 126 assert(_adr_valueklass_fixed_block != NULL, "Should have been initialized"); 127 return ((address)_adr_valueklass_fixed_block) + in_bytes(byte_offset_of(ValueKlassFixedBlock, _exact_size_in_bytes)); 128 } 129 130 public: 131 int get_alignment() const { 132 return *(int*)adr_alignment(); 133 } 134 135 void set_alignment(int alignment) { 136 *(int*)adr_alignment() = alignment; 137 } 138 139 int first_field_offset() const { 140 int offset = *(int*)adr_first_field_offset(); 141 assert(offset != 0, "Must be initialized before use"); 142 return *(int*)adr_first_field_offset(); 143 } 144 145 void set_first_field_offset(int offset) { 146 *(int*)adr_first_field_offset() = offset; 147 } 148 149 int get_exact_size_in_bytes() const { 150 return *(int*)adr_exact_size_in_bytes(); 151 } 152 153 void set_exact_size_in_bytes(int exact_size) { 154 *(int*)adr_exact_size_in_bytes() = exact_size; 155 } 156 157 int first_field_offset_old(); 158 159 private: 160 int collect_fields(GrowableArray<SigEntry>* sig, int base_off = 0); 161 162 void cleanup_blobs(); 163 164 165 protected: 166 // Returns the array class for the n'th dimension 167 Klass* array_klass_impl(ArrayStorageProperties storage_props, bool or_null, int n, TRAPS); 168 169 // Returns the array class with this class as element type 170 Klass* array_klass_impl(ArrayStorageProperties storage_props, bool or_null, TRAPS); 171 172 // Specifically flat array klass 173 Klass* value_array_klass(ArrayStorageProperties storage_props, bool or_null, int rank, TRAPS); 174 175 public: 176 // Type testing 177 bool is_value_slow() const { return true; } 178 179 // value_mirror is the primary mirror 180 oop value_mirror() const { return java_lang_Class::inline_type_mirror(java_mirror()); } 181 oop indirect_mirror() const { return java_lang_Class::indirect_type_mirror(java_mirror()); } 182 183 // Casting from Klass* 184 static ValueKlass* cast(Klass* k); 185 186 // Use this to return the size of an instance in heap words 187 // Implementation is currently simple because all value types are allocated 188 // in Java heap like Java objects. 189 virtual int size_helper() const { 190 return layout_helper_to_size_helper(layout_helper()); 191 } 192 193 // Metadata iterators 194 void array_klasses_do(void f(Klass* k)); 195 196 // allocate_instance() allocates a stand alone value in the Java heap 197 // initialized to default value (cleared memory) 198 instanceOop allocate_instance(TRAPS); 199 // allocates a stand alone value buffer in the Java heap 200 // DOES NOT have memory cleared, user MUST initialize payload before 201 // returning to Java (i.e.: value_copy) 202 instanceOop allocate_instance_buffer(TRAPS); 203 204 // minimum number of bytes occupied by nonstatic fields, HeapWord aligned or pow2 205 int raw_value_byte_size(); 206 207 address data_for_oop(oop o) const; 208 oop oop_for_data(address data) const; 209 210 // Query if h/w provides atomic load/store 211 bool is_atomic(); 212 213 bool flatten_array(); 214 215 bool contains_oops() const { return nonstatic_oop_map_count() > 0; } 216 int nonstatic_oop_count(); 217 218 // General store methods 219 // 220 // Normally loads and store methods would be found in *Oops classes, but since values can be 221 // "in-lined" (flattened) into containing oops, these methods reside here in ValueKlass. 222 // 223 // "value_copy_*_to_new_*" assume new memory (i.e. IS_DEST_UNINITIALIZED for write barriers) 224 225 void value_copy_payload_to_new_oop(void* src, oop dst); 226 void value_copy_oop_to_new_oop(oop src, oop dst); 227 void value_copy_oop_to_new_payload(oop src, void* dst); 228 void value_copy_oop_to_payload(oop src, void* dst); 229 230 oop read_flattened_field(oop obj, int offset, TRAPS); 231 void write_flattened_field(oop obj, int offset, oop value, TRAPS); 232 233 // oop iterate raw value type data pointer (where oop_addr may not be an oop, but backing/array-element) 234 template <typename T, class OopClosureType> 235 inline void oop_iterate_specialized(const address oop_addr, OopClosureType* closure); 236 237 template <typename T, class OopClosureType> 238 inline void oop_iterate_specialized_bounded(const address oop_addr, OopClosureType* closure, void* lo, void* hi); 239 240 // calling convention support 241 void initialize_calling_convention(TRAPS); 242 Array<SigEntry>* extended_sig() const { 243 return *((Array<SigEntry>**)adr_extended_sig()); 244 } 245 Array<VMRegPair>* return_regs() const { 246 return *((Array<VMRegPair>**)adr_return_regs()); 247 } 248 bool is_scalarizable() const; 249 bool can_be_returned_as_fields() const; 250 void save_oop_fields(const RegisterMap& map, GrowableArray<Handle>& handles) const; 251 void restore_oop_results(RegisterMap& map, GrowableArray<Handle>& handles) const; 252 oop realloc_result(const RegisterMap& reg_map, const GrowableArray<Handle>& handles, TRAPS); 253 static ValueKlass* returned_value_klass(const RegisterMap& reg_map); 254 255 address pack_handler() const { 256 return *(address*)adr_pack_handler(); 257 } 258 259 address unpack_handler() const { 260 return *(address*)adr_unpack_handler(); 261 } 262 263 // pack and unpack handlers. Need to be loadable from generated code 264 // so at a fixed offset from the base of the klass pointer. 265 static ByteSize pack_handler_offset() { 266 return byte_offset_of(ValueKlassFixedBlock, _pack_handler); 267 } 268 269 static ByteSize pack_handler_jobject_offset() { 270 return byte_offset_of(ValueKlassFixedBlock, _pack_handler_jobject); 271 } 272 273 static ByteSize unpack_handler_offset() { 274 return byte_offset_of(ValueKlassFixedBlock, _unpack_handler); 275 } 276 277 static ByteSize default_value_offset_offset() { 278 return byte_offset_of(ValueKlassFixedBlock, _default_value_offset); 279 } 280 281 static ByteSize first_field_offset_offset() { 282 return byte_offset_of(ValueKlassFixedBlock, _first_field_offset); 283 } 284 285 void set_default_value_offset(int offset) { 286 *((int*)adr_default_value_offset()) = offset; 287 } 288 289 int default_value_offset() { 290 int offset = *((int*)adr_default_value_offset()); 291 assert(offset != 0, "must not be called if not initialized"); 292 return offset; 293 } 294 295 void set_default_value(oop val) { 296 java_mirror()->obj_field_put(default_value_offset(), val); 297 indirect_mirror()->obj_field_put(default_value_offset(), val); 298 } 299 300 oop default_value(); 301 void deallocate_contents(ClassLoaderData* loader_data); 302 static void cleanup(ValueKlass* ik) ; 303 304 // Verification 305 void verify_on(outputStream* st); 306 void oop_verify_on(oop obj, outputStream* st); 307 308 }; 309 310 #endif /* SHARE_VM_OOPS_VALUEKLASS_HPP */