78 TypeArrayKlass::TypeArrayKlass(BasicType type, Symbol* name) : ArrayKlass(name, ID) {
79 set_layout_helper(array_layout_helper(type));
80 assert(is_array_klass(), "sanity");
81 assert(is_typeArray_klass(), "sanity");
82
83 set_max_length(arrayOopDesc::max_array_length(type));
84 assert(size() >= TypeArrayKlass::header_size(), "bad size");
85
86 set_class_loader_data(ClassLoaderData::the_null_class_loader_data());
87 }
88
89 typeArrayOop TypeArrayKlass::allocate_common(int length, bool do_zero, TRAPS) {
90 assert(log2_element_size() >= 0, "bad scale");
91 check_array_allocation_length(length, max_length(), CHECK_NULL);
92 size_t size = typeArrayOopDesc::object_size(layout_helper(), length);
93 return (typeArrayOop)Universe::heap()->array_allocate(this, (int)size, length,
94 do_zero, CHECK_NULL);
95 }
96
97 oop TypeArrayKlass::multi_allocate(int rank, jint* last_size, TRAPS) {
98 // For typeArrays this is only called for the last dimension
99 assert(rank == 1, "just checking");
100 int length = *last_size;
101 return allocate(length, THREAD);
102 }
103
104
105 void TypeArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d, int dst_pos, int length, TRAPS) {
106 assert(s->is_typeArray(), "must be type array");
107
108 // Check destination type.
109 if (!d->is_typeArray()) {
110 ResourceMark rm(THREAD);
111 stringStream ss;
112 if (d->is_objArray()) {
113 ss.print("arraycopy: type mismatch: can not copy %s[] into object array[]",
114 type2name_tab[ArrayKlass::cast(s->klass())->element_type()]);
115 } else {
116 ss.print("arraycopy: destination type %s is not an array", d->klass()->external_name());
117 }
118 THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string());
154 type2name_tab[ArrayKlass::cast(s->klass())->element_type()], s->length());
155 } else {
156 ss.print("arraycopy: last destination index %u out of bounds for %s[%d]",
157 (unsigned int) length + (unsigned int) dst_pos,
158 type2name_tab[ArrayKlass::cast(d->klass())->element_type()], d->length());
159 }
160 THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
161 }
162 // Check zero copy
163 if (length == 0)
164 return;
165
166 // This is an attempt to make the copy_array fast.
167 int l2es = log2_element_size();
168 size_t src_offset = arrayOopDesc::base_offset_in_bytes(element_type()) + ((size_t)src_pos << l2es);
169 size_t dst_offset = arrayOopDesc::base_offset_in_bytes(element_type()) + ((size_t)dst_pos << l2es);
170 ArrayAccess<ARRAYCOPY_ATOMIC>::arraycopy<void>(s, src_offset, d, dst_offset, (size_t)length << l2es);
171 }
172
173 // create a klass of array holding typeArrays
174 Klass* TypeArrayKlass::array_klass_impl(bool or_null, int n, TRAPS) {
175 int dim = dimension();
176 assert(dim <= n, "check order of chain");
177 if (dim == n)
178 return this;
179
180 // lock-free read needs acquire semantics
181 if (higher_dimension_acquire() == NULL) {
182 if (or_null) return NULL;
183
184 ResourceMark rm;
185 JavaThread *jt = (JavaThread *)THREAD;
186 {
187 // Atomic create higher dimension and link into list
188 MutexLocker mu(MultiArray_lock, THREAD);
189
190 if (higher_dimension() == NULL) {
191 Klass* oak = ObjArrayKlass::allocate_objArray_klass(
192 class_loader_data(), dim + 1, this, CHECK_NULL);
193 ObjArrayKlass* h_ak = ObjArrayKlass::cast(oak);
194 h_ak->set_lower_dimension(this);
195 // use 'release' to pair with lock-free load
196 release_set_higher_dimension(h_ak);
197 assert(h_ak->is_objArray_klass(), "incorrect initialization of ObjArrayKlass");
198 }
199 }
200 } else {
201 CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
202 }
203 ObjArrayKlass* h_ak = ObjArrayKlass::cast(higher_dimension());
204 if (or_null) {
205 return h_ak->array_klass_or_null(n);
206 }
207 return h_ak->array_klass(n, THREAD);
208 }
209
210 Klass* TypeArrayKlass::array_klass_impl(bool or_null, TRAPS) {
211 return array_klass_impl(or_null, dimension() + 1, THREAD);
212 }
213
214 int TypeArrayKlass::oop_size(oop obj) const {
215 assert(obj->is_typeArray(),"must be a type array");
216 typeArrayOop t = typeArrayOop(obj);
217 return t->object_size();
218 }
219
220 void TypeArrayKlass::initialize(TRAPS) {
221 // Nothing to do. Having this function is handy since objArrayKlasses can be
222 // initialized by calling initialize on their bottom_klass, see ObjArrayKlass::initialize
223 }
224
225 const char* TypeArrayKlass::external_name(BasicType type) {
226 switch (type) {
227 case T_BOOLEAN: return "[Z";
228 case T_CHAR: return "[C";
229 case T_FLOAT: return "[F";
230 case T_DOUBLE: return "[D";
231 case T_BYTE: return "[B";
|
78 TypeArrayKlass::TypeArrayKlass(BasicType type, Symbol* name) : ArrayKlass(name, ID) {
79 set_layout_helper(array_layout_helper(type));
80 assert(is_array_klass(), "sanity");
81 assert(is_typeArray_klass(), "sanity");
82
83 set_max_length(arrayOopDesc::max_array_length(type));
84 assert(size() >= TypeArrayKlass::header_size(), "bad size");
85
86 set_class_loader_data(ClassLoaderData::the_null_class_loader_data());
87 }
88
89 typeArrayOop TypeArrayKlass::allocate_common(int length, bool do_zero, TRAPS) {
90 assert(log2_element_size() >= 0, "bad scale");
91 check_array_allocation_length(length, max_length(), CHECK_NULL);
92 size_t size = typeArrayOopDesc::object_size(layout_helper(), length);
93 return (typeArrayOop)Universe::heap()->array_allocate(this, (int)size, length,
94 do_zero, CHECK_NULL);
95 }
96
97 oop TypeArrayKlass::multi_allocate(int rank, jint* last_size, TRAPS) {
98 assert(rank == 1, "just checking");
99 int length = *last_size;
100 return allocate(length, THREAD);
101 }
102
103
104 void TypeArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d, int dst_pos, int length, TRAPS) {
105 assert(s->is_typeArray(), "must be type array");
106
107 // Check destination type.
108 if (!d->is_typeArray()) {
109 ResourceMark rm(THREAD);
110 stringStream ss;
111 if (d->is_objArray()) {
112 ss.print("arraycopy: type mismatch: can not copy %s[] into object array[]",
113 type2name_tab[ArrayKlass::cast(s->klass())->element_type()]);
114 } else {
115 ss.print("arraycopy: destination type %s is not an array", d->klass()->external_name());
116 }
117 THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string());
153 type2name_tab[ArrayKlass::cast(s->klass())->element_type()], s->length());
154 } else {
155 ss.print("arraycopy: last destination index %u out of bounds for %s[%d]",
156 (unsigned int) length + (unsigned int) dst_pos,
157 type2name_tab[ArrayKlass::cast(d->klass())->element_type()], d->length());
158 }
159 THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
160 }
161 // Check zero copy
162 if (length == 0)
163 return;
164
165 // This is an attempt to make the copy_array fast.
166 int l2es = log2_element_size();
167 size_t src_offset = arrayOopDesc::base_offset_in_bytes(element_type()) + ((size_t)src_pos << l2es);
168 size_t dst_offset = arrayOopDesc::base_offset_in_bytes(element_type()) + ((size_t)dst_pos << l2es);
169 ArrayAccess<ARRAYCOPY_ATOMIC>::arraycopy<void>(s, src_offset, d, dst_offset, (size_t)length << l2es);
170 }
171
172 // create a klass of array holding typeArrays
173 Klass* TypeArrayKlass::array_klass_impl(ArrayStorageProperties storage_props, bool or_null, int n, TRAPS) {
174 assert(storage_props.is_empty(), "Didn't expect storage properties");
175 int dim = dimension();
176 assert(dim <= n, "check order of chain");
177 if (dim == n)
178 return this;
179
180 // lock-free read needs acquire semantics
181 if (higher_dimension_acquire() == NULL) {
182 if (or_null) return NULL;
183
184 ResourceMark rm;
185 JavaThread *jt = (JavaThread *)THREAD;
186 {
187 // Atomic create higher dimension and link into list
188 MutexLocker mu(MultiArray_lock, THREAD);
189
190 if (higher_dimension() == NULL) {
191 Klass* oak = ObjArrayKlass::allocate_objArray_klass(
192 ArrayStorageProperties::empty, dim + 1, this, CHECK_NULL);
193 ObjArrayKlass* h_ak = ObjArrayKlass::cast(oak);
194 h_ak->set_lower_dimension(this);
195 // use 'release' to pair with lock-free load
196 release_set_higher_dimension(h_ak);
197 assert(h_ak->is_objArray_klass(), "incorrect initialization of ObjArrayKlass");
198 }
199 }
200 } else {
201 CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
202 }
203 ObjArrayKlass* h_ak = ObjArrayKlass::cast(higher_dimension());
204 if (or_null) {
205 return h_ak->array_klass_or_null(storage_props, n);
206 }
207 return h_ak->array_klass(storage_props, n, THREAD);
208 }
209
210 Klass* TypeArrayKlass::array_klass_impl(ArrayStorageProperties storage_props, bool or_null, TRAPS) {
211 return array_klass_impl(storage_props, or_null, dimension() + 1, THREAD);
212 }
213
214 int TypeArrayKlass::oop_size(oop obj) const {
215 assert(obj->is_typeArray(),"must be a type array");
216 typeArrayOop t = typeArrayOop(obj);
217 return t->object_size();
218 }
219
220 void TypeArrayKlass::initialize(TRAPS) {
221 // Nothing to do. Having this function is handy since objArrayKlasses can be
222 // initialized by calling initialize on their bottom_klass, see ObjArrayKlass::initialize
223 }
224
225 const char* TypeArrayKlass::external_name(BasicType type) {
226 switch (type) {
227 case T_BOOLEAN: return "[Z";
228 case T_CHAR: return "[C";
229 case T_FLOAT: return "[F";
230 case T_DOUBLE: return "[D";
231 case T_BYTE: return "[B";
|