annotate src/share/vm/oops/valueKlass.cpp @ 12964:d16eda688d5d

Initial valhalla/jdk10 merge for runtime and interpreter
author fparain
date Wed, 26 Apr 2017 13:37:50 -0400
parents
children 4cd1b06ce224
rev   line source
fparain@12964 1 /*
fparain@12964 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
fparain@12964 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
fparain@12964 4 *
fparain@12964 5 * This code is free software; you can redistribute it and/or modify it
fparain@12964 6 * under the terms of the GNU General Public License version 2 only, as
fparain@12964 7 * published by the Free Software Foundation.
fparain@12964 8 *
fparain@12964 9 * This code is distributed in the hope that it will be useful, but WITHOUT
fparain@12964 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
fparain@12964 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
fparain@12964 12 * version 2 for more details (a copy is included in the LICENSE file that
fparain@12964 13 * accompanied this code).
fparain@12964 14 *
fparain@12964 15 * You should have received a copy of the GNU General Public License version
fparain@12964 16 * 2 along with this work; if not, write to the Free Software Foundation,
fparain@12964 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
fparain@12964 18 *
fparain@12964 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
fparain@12964 20 * or visit www.oracle.com if you need additional information or have any
fparain@12964 21 * questions.
fparain@12964 22 *
fparain@12964 23 */
fparain@12964 24
fparain@12964 25 #include "precompiled.hpp"
fparain@12964 26 #include "interpreter/interpreter.hpp"
fparain@12964 27 #include "oops/oop.inline.hpp"
fparain@12964 28 #include "oops/fieldStreams.hpp"
fparain@12964 29 #include "oops/method.hpp"
fparain@12964 30 #include "oops/objArrayKlass.hpp"
fparain@12964 31 #include "oops/valueKlass.hpp"
fparain@12964 32 #include "oops/valueArrayKlass.hpp"
fparain@12964 33 #include "utilities/copy.hpp"
fparain@12964 34
fparain@12964 35 int ValueKlass::first_field_offset() const {
fparain@12964 36 #ifdef ASSERT
fparain@12964 37 int first_offset = INT_MAX;
fparain@12964 38 for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
fparain@12964 39 if (fs.offset() < first_offset) first_offset= fs.offset();
fparain@12964 40 }
fparain@12964 41 #endif
fparain@12964 42 int base_offset = instanceOopDesc::base_offset_in_bytes();
fparain@12964 43 // The first field of value types is aligned on a long boundary
fparain@12964 44 base_offset = align_size_up(base_offset, BytesPerLong);
fparain@12964 45 assert(base_offset = first_offset, "inconsistent offsets");
fparain@12964 46 return base_offset;
fparain@12964 47 }
fparain@12964 48
fparain@12964 49 int ValueKlass::raw_value_byte_size() const {
fparain@12964 50 int heapOopAlignedSize = nonstatic_field_size() << LogBytesPerHeapOop;
fparain@12964 51 // If bigger than 64 bits or needs oop alignment, then use jlong aligned
fparain@12964 52 // which for values should be jlong aligned, asserts in raw_field_copy otherwise
fparain@12964 53 if (heapOopAlignedSize >= longSize || contains_oops()) {
fparain@12964 54 return heapOopAlignedSize;
fparain@12964 55 }
fparain@12964 56 // Small primitives...
fparain@12964 57 // If a few small basic type fields, return the actual size, i.e.
fparain@12964 58 // 1 byte = 1
fparain@12964 59 // 2 byte = 2
fparain@12964 60 // 3 byte = 4, because pow2 needed for element stores
fparain@12964 61 int first_offset = first_field_offset();
fparain@12964 62 int last_offset = 0; // find the last offset, add basic type size
fparain@12964 63 for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
fparain@12964 64 if (fs.offset() > last_offset) {
fparain@12964 65 int tsz = 0;
fparain@12964 66 BasicType type = fs.field_descriptor().field_type();
fparain@12964 67 if (is_java_primitive(type)) {
fparain@12964 68 tsz = type2aelembytes(type);
fparain@12964 69 } else if (type == T_VALUETYPE) {
fparain@12964 70 // Not just primitives. Layout aligns embedded value, so use jlong aligned it is
fparain@12964 71 return heapOopAlignedSize;
fparain@12964 72 } else {
fparain@12964 73 guarantee(0, "Unknown type %d", type);
fparain@12964 74 }
fparain@12964 75 assert(tsz > 0, "Invariant");
fparain@12964 76 last_offset = fs.offset() + tsz;
fparain@12964 77 }
fparain@12964 78 }
fparain@12964 79 assert(last_offset > first_offset, "Invariant");
fparain@12964 80 return 1 << upper_log2(last_offset - first_offset);
fparain@12964 81 }
fparain@12964 82
fparain@12964 83 bool ValueKlass::is_atomic() {
fparain@12964 84 return (nonstatic_field_size() * heapOopSize) <= longSize;
fparain@12964 85 }
fparain@12964 86
fparain@12964 87 int ValueKlass::nonstatic_oop_count() {
fparain@12964 88 int oops = 0;
fparain@12964 89 int map_count = nonstatic_oop_map_count();
fparain@12964 90 OopMapBlock* block = start_of_nonstatic_oop_maps();
fparain@12964 91 OopMapBlock* end = block + map_count;
fparain@12964 92 while (block != end) {
fparain@12964 93 oops += block->count();
fparain@12964 94 block++;
fparain@12964 95 }
fparain@12964 96 return oops;
fparain@12964 97 }
fparain@12964 98
fparain@12964 99 // Arrays of...
fparain@12964 100
fparain@12964 101 bool ValueKlass::flatten_array() {
fparain@12964 102 if (!ValueArrayFlatten) {
fparain@12964 103 return false;
fparain@12964 104 }
fparain@12964 105
fparain@12964 106 int elem_bytes = raw_value_byte_size();
fparain@12964 107 // Too big
fparain@12964 108 if ((ValueArrayElemMaxFlatSize >= 0) && (elem_bytes > ValueArrayElemMaxFlatSize)) {
fparain@12964 109 return false;
fparain@12964 110 }
fparain@12964 111 // Too many embedded oops
fparain@12964 112 if ((ValueArrayElemMaxFlatOops >= 0) && (nonstatic_oop_count() > ValueArrayElemMaxFlatOops)) {
fparain@12964 113 return false;
fparain@12964 114 }
fparain@12964 115
fparain@12964 116 return true;
fparain@12964 117 }
fparain@12964 118
fparain@12964 119
fparain@12964 120 Klass* ValueKlass::array_klass_impl(bool or_null, int n, TRAPS) {
fparain@12964 121 if (!flatten_array()) {
fparain@12964 122 return InstanceKlass::array_klass_impl(or_null, n, THREAD);
fparain@12964 123 }
fparain@12964 124
fparain@12964 125 // Basically the same as instanceKlass, but using "ValueArrayKlass::allocate_klass"
fparain@12964 126 if (array_klasses() == NULL) {
fparain@12964 127 if (or_null) return NULL;
fparain@12964 128
fparain@12964 129 ResourceMark rm;
fparain@12964 130 JavaThread *jt = (JavaThread *)THREAD;
fparain@12964 131 {
fparain@12964 132 // Atomic creation of array_klasses
fparain@12964 133 MutexLocker mc(Compile_lock, THREAD); // for vtables
fparain@12964 134 MutexLocker ma(MultiArray_lock, THREAD);
fparain@12964 135
fparain@12964 136 // Check if update has already taken place
fparain@12964 137 if (array_klasses() == NULL) {
fparain@12964 138 Klass* ak;
fparain@12964 139 if (is_atomic() || (!ValueArrayAtomicAccess)) {
fparain@12964 140 ak = ValueArrayKlass::allocate_klass(this, CHECK_NULL);
fparain@12964 141 } else {
fparain@12964 142 ak = ObjArrayKlass::allocate_objArray_klass(class_loader_data(), 1, this, CHECK_NULL);
fparain@12964 143 }
fparain@12964 144 set_array_klasses(ak);
fparain@12964 145 }
fparain@12964 146 }
fparain@12964 147 }
fparain@12964 148 // _this will always be set at this point
fparain@12964 149 ArrayKlass* ak = ArrayKlass::cast(array_klasses());
fparain@12964 150 if (or_null) {
fparain@12964 151 return ak->array_klass_or_null(n);
fparain@12964 152 }
fparain@12964 153 return ak->array_klass(n, THREAD);
fparain@12964 154 }
fparain@12964 155
fparain@12964 156 Klass* ValueKlass::array_klass_impl(bool or_null, TRAPS) {
fparain@12964 157 return array_klass_impl(or_null, 1, THREAD);
fparain@12964 158 }
fparain@12964 159
fparain@12964 160 void ValueKlass::raw_field_copy(void* src, void* dst, size_t raw_byte_size) {
fparain@12964 161 /*
fparain@12964 162 * Try not to shear fields even if not an atomic store...
fparain@12964 163 *
fparain@12964 164 * First 3 cases handle value array store, otherwise works on the same basis
fparain@12964 165 * as JVM_Clone, at this size data is aligned. The order of primitive types
fparain@12964 166 * is largest to smallest, and it not possible for fields to stradle long
fparain@12964 167 * copy boundaries.
fparain@12964 168 *
fparain@12964 169 * If MT without exclusive access, possible to observe partial value store,
fparain@12964 170 * but not partial primitive and reference field values
fparain@12964 171 */
fparain@12964 172 switch (raw_byte_size) {
fparain@12964 173 case 1:
fparain@12964 174 *((jbyte*) dst) = *(jbyte*)src;
fparain@12964 175 break;
fparain@12964 176 case 2:
fparain@12964 177 *((jshort*) dst) = *(jshort*)src;
fparain@12964 178 break;
fparain@12964 179 case 4:
fparain@12964 180 *((jint*) dst) = *(jint*) src;
fparain@12964 181 break;
fparain@12964 182 default:
fparain@12964 183 assert(raw_byte_size % sizeof(jlong) == 0, "Unaligned raw_byte_size");
fparain@12964 184 Copy::conjoint_jlongs_atomic((jlong*)src, (jlong*)dst, raw_byte_size >> LogBytesPerLong);
fparain@12964 185 }
fparain@12964 186 }
fparain@12964 187
fparain@12964 188 /*
fparain@12964 189 * Store the value of this klass contained with src into dst.
fparain@12964 190 *
fparain@12964 191 * This operation is appropriate for use from vastore, vaload and putfield (for values)
fparain@12964 192 *
fparain@12964 193 * GC barriers currently can lock with no safepoint check and allocate c-heap,
fparain@12964 194 * so raw point is "safe" for now.
fparain@12964 195 *
fparain@12964 196 * Going forward, look to use machine generated (stub gen or bc) version for most used klass layouts
fparain@12964 197 *
fparain@12964 198 */
fparain@12964 199 void ValueKlass::value_store(void* src, void* dst, size_t raw_byte_size, bool dst_heap, bool dst_uninitialized) {
fparain@12964 200 if (contains_oops() && dst_heap) {
fparain@12964 201 // src/dst aren't oops, need offset to adjust oop map offset
fparain@12964 202 const address dst_oop_addr = ((address) dst) - first_field_offset();
fparain@12964 203
fparain@12964 204 // Pre-barriers...
fparain@12964 205 OopMapBlock* map = start_of_nonstatic_oop_maps();
fparain@12964 206 OopMapBlock* const end = map + nonstatic_oop_map_count();
fparain@12964 207 while (map != end) {
fparain@12964 208 // Shame we can't just use the existing oop iterator...src/dst aren't oop
fparain@12964 209 address doop_address = dst_oop_addr + map->offset();
fparain@12964 210 if (UseCompressedOops) {
fparain@12964 211 oopDesc::bs()->write_ref_array_pre((narrowOop*) doop_address, map->count(), dst_uninitialized);
fparain@12964 212 } else {
fparain@12964 213 oopDesc::bs()->write_ref_array_pre((oop*) doop_address, map->count(), dst_uninitialized);
fparain@12964 214 }
fparain@12964 215 map++;
fparain@12964 216 }
fparain@12964 217
fparain@12964 218 raw_field_copy(src, dst, raw_byte_size);
fparain@12964 219
fparain@12964 220 // Post-barriers...
fparain@12964 221 map = start_of_nonstatic_oop_maps();
fparain@12964 222 while (map != end) {
fparain@12964 223 address doop_address = dst_oop_addr + map->offset();
fparain@12964 224 oopDesc::bs()->write_ref_array((HeapWord*) doop_address, map->count());
fparain@12964 225 map++;
fparain@12964 226 }
fparain@12964 227 } else { // Primitive-only case...
fparain@12964 228 raw_field_copy(src, dst, raw_byte_size);
fparain@12964 229 }
fparain@12964 230 }
fparain@12964 231
fparain@12964 232 oop ValueKlass::derive_value_type_copy(Handle src, InstanceKlass* target_klass, TRAPS) {
fparain@12964 233 assert(InstanceKlass::cast(src->klass())->derive_value_type_klass() == target_klass, "Not this DVT");
fparain@12964 234
fparain@12964 235 // Allocate new for safety, simply reinstalling the klass pointer is a little too risky
fparain@12964 236 target_klass->initialize(CHECK_0);
fparain@12964 237 instanceOop value = target_klass->allocate_instance(CHECK_0);
fparain@12964 238 value_store(data_for_oop(src()), data_for_oop(value), true, true);
fparain@12964 239 return value;
fparain@12964 240 }