1/*
2 * Copyright (c) 1997, 2013, 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#include "precompiled.hpp"
26#include "classfile/symbolTable.hpp"
27#include "classfile/systemDictionary.hpp"
28#include "classfile/vmSymbols.hpp"
29#include "gc_interface/collectedHeap.hpp"
30#include "gc_interface/collectedHeap.inline.hpp"
31#include "memory/metadataFactory.hpp"
32#include "memory/resourceArea.hpp"
33#include "memory/universe.hpp"
34#include "memory/universe.inline.hpp"
35#include "oops/instanceKlass.hpp"
36#include "oops/klass.inline.hpp"
37#include "oops/objArrayKlass.hpp"
38#include "oops/oop.inline.hpp"
39#include "oops/typeArrayKlass.hpp"
40#include "oops/typeArrayOop.hpp"
41#include "runtime/handles.inline.hpp"
42#include "utilities/macros.hpp"
43
44bool TypeArrayKlass::compute_is_subtype_of(Klass* k) {
45  if (!k->oop_is_typeArray()) {
46    return ArrayKlass::compute_is_subtype_of(k);
47  }
48
49  TypeArrayKlass* tak = TypeArrayKlass::cast(k);
50  if (dimension() != tak->dimension()) return false;
51
52  return element_type() == tak->element_type();
53}
54
55TypeArrayKlass* TypeArrayKlass::create_klass(BasicType type,
56                                      const char* name_str, TRAPS) {
57  Symbol* sym = NULL;
58  if (name_str != NULL) {
59    sym = SymbolTable::new_permanent_symbol(name_str, CHECK_NULL);
60  }
61
62  ClassLoaderData* null_loader_data = ClassLoaderData::the_null_class_loader_data();
63
64  TypeArrayKlass* ak = TypeArrayKlass::allocate(null_loader_data, type, sym, CHECK_NULL);
65
66  // Add all classes to our internal class loader list here,
67  // including classes in the bootstrap (NULL) class loader.
68  // GC walks these as strong roots.
69  null_loader_data->add_class(ak);
70
71  // Call complete_create_array_klass after all instance variables have been initialized.
72  complete_create_array_klass(ak, ak->super(), CHECK_NULL);
73
74  return ak;
75}
76
77TypeArrayKlass* TypeArrayKlass::allocate(ClassLoaderData* loader_data, BasicType type, Symbol* name, TRAPS) {
78  assert(TypeArrayKlass::header_size() <= InstanceKlass::header_size(),
79      "array klasses must be same size as InstanceKlass");
80
81  int size = ArrayKlass::static_size(TypeArrayKlass::header_size());
82
83  return new (loader_data, size, THREAD) TypeArrayKlass(type, name);
84}
85
86TypeArrayKlass::TypeArrayKlass(BasicType type, Symbol* name) : ArrayKlass(name) {
87  set_layout_helper(array_layout_helper(type));
88  assert(oop_is_array(), "sanity");
89  assert(oop_is_typeArray(), "sanity");
90
91  set_max_length(arrayOopDesc::max_array_length(type));
92  assert(size() >= TypeArrayKlass::header_size(), "bad size");
93
94  set_class_loader_data(ClassLoaderData::the_null_class_loader_data());
95}
96
97typeArrayOop TypeArrayKlass::allocate_common(int length, bool do_zero, TRAPS) {
98  assert(log2_element_size() >= 0, "bad scale");
99  if (length >= 0) {
100    if (length <= max_length()) {
101      size_t size = typeArrayOopDesc::object_size(layout_helper(), length);
102      KlassHandle h_k(THREAD, this);
103      typeArrayOop t;
104      CollectedHeap* ch = Universe::heap();
105      if (do_zero) {
106        t = (typeArrayOop)CollectedHeap::array_allocate(h_k, (int)size, length, CHECK_NULL);
107      } else {
108        t = (typeArrayOop)CollectedHeap::array_allocate_nozero(h_k, (int)size, length, CHECK_NULL);
109      }
110      return t;
111    } else {
112      report_java_out_of_memory("Requested array size exceeds VM limit");
113      JvmtiExport::post_array_size_exhausted();
114      THROW_OOP_0(Universe::out_of_memory_error_array_size());
115    }
116  } else {
117    THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
118  }
119}
120
121oop TypeArrayKlass::multi_allocate(int rank, jint* last_size, TRAPS) {
122  // For typeArrays this is only called for the last dimension
123  assert(rank == 1, "just checking");
124  int length = *last_size;
125  return allocate(length, THREAD);
126}
127
128
129void TypeArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d, int dst_pos, int length, TRAPS) {
130  assert(s->is_typeArray(), "must be type array");
131
132  // Check destination
133  if (!d->is_typeArray() || element_type() != TypeArrayKlass::cast(d->klass())->element_type()) {
134    THROW(vmSymbols::java_lang_ArrayStoreException());
135  }
136
137  // Check is all offsets and lengths are non negative
138  if (src_pos < 0 || dst_pos < 0 || length < 0) {
139    THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
140  }
141  // Check if the ranges are valid
142  if  ( (((unsigned int) length + (unsigned int) src_pos) > (unsigned int) s->length())
143     || (((unsigned int) length + (unsigned int) dst_pos) > (unsigned int) d->length()) ) {
144    THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
145  }
146  // Check zero copy
147  if (length == 0)
148    return;
149
150  // This is an attempt to make the copy_array fast.
151  int l2es = log2_element_size();
152  int ihs = array_header_in_bytes() / wordSize;
153  char* src = (char*) ((oop*)s + ihs) + ((size_t)src_pos << l2es);
154  char* dst = (char*) ((oop*)d + ihs) + ((size_t)dst_pos << l2es);
155  Copy::conjoint_memory_atomic(src, dst, (size_t)length << l2es);
156}
157
158
159// create a klass of array holding typeArrays
160Klass* TypeArrayKlass::array_klass_impl(bool or_null, int n, TRAPS) {
161  int dim = dimension();
162  assert(dim <= n, "check order of chain");
163    if (dim == n)
164      return this;
165
166  if (higher_dimension() == NULL) {
167    if (or_null)  return NULL;
168
169    ResourceMark rm;
170    JavaThread *jt = (JavaThread *)THREAD;
171    {
172      MutexLocker mc(Compile_lock, THREAD);   // for vtables
173      // Atomic create higher dimension and link into list
174      MutexLocker mu(MultiArray_lock, THREAD);
175
176      if (higher_dimension() == NULL) {
177        Klass* oak = ObjArrayKlass::allocate_objArray_klass(
178              class_loader_data(), dim + 1, this, CHECK_NULL);
179        ObjArrayKlass* h_ak = ObjArrayKlass::cast(oak);
180        h_ak->set_lower_dimension(this);
181        OrderAccess::storestore();
182        set_higher_dimension(h_ak);
183        assert(h_ak->oop_is_objArray(), "incorrect initialization of ObjArrayKlass");
184      }
185    }
186  } else {
187    CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
188  }
189  ObjArrayKlass* h_ak = ObjArrayKlass::cast(higher_dimension());
190  if (or_null) {
191    return h_ak->array_klass_or_null(n);
192  }
193  return h_ak->array_klass(n, CHECK_NULL);
194}
195
196Klass* TypeArrayKlass::array_klass_impl(bool or_null, TRAPS) {
197  return array_klass_impl(or_null, dimension() +  1, THREAD);
198}
199
200int TypeArrayKlass::oop_size(oop obj) const {
201  assert(obj->is_typeArray(),"must be a type array");
202  typeArrayOop t = typeArrayOop(obj);
203  return t->object_size();
204}
205
206void TypeArrayKlass::oop_follow_contents(oop obj) {
207  assert(obj->is_typeArray(),"must be a type array");
208  // Performance tweak: We skip iterating over the klass pointer since we
209  // know that Universe::TypeArrayKlass never moves.
210}
211
212#if INCLUDE_ALL_GCS
213void TypeArrayKlass::oop_follow_contents(ParCompactionManager* cm, oop obj) {
214  assert(obj->is_typeArray(),"must be a type array");
215  // Performance tweak: We skip iterating over the klass pointer since we
216  // know that Universe::TypeArrayKlass never moves.
217}
218#endif // INCLUDE_ALL_GCS
219
220int TypeArrayKlass::oop_adjust_pointers(oop obj) {
221  assert(obj->is_typeArray(),"must be a type array");
222  typeArrayOop t = typeArrayOop(obj);
223  // Performance tweak: We skip iterating over the klass pointer since we
224  // know that Universe::TypeArrayKlass never moves.
225  return t->object_size();
226}
227
228int TypeArrayKlass::oop_oop_iterate(oop obj, ExtendedOopClosure* blk) {
229  assert(obj->is_typeArray(),"must be a type array");
230  typeArrayOop t = typeArrayOop(obj);
231  // Performance tweak: We skip iterating over the klass pointer since we
232  // know that Universe::TypeArrayKlass never moves.
233  return t->object_size();
234}
235
236int TypeArrayKlass::oop_oop_iterate_m(oop obj, ExtendedOopClosure* blk, MemRegion mr) {
237  assert(obj->is_typeArray(),"must be a type array");
238  typeArrayOop t = typeArrayOop(obj);
239  // Performance tweak: We skip iterating over the klass pointer since we
240  // know that Universe::TypeArrayKlass never moves.
241  return t->object_size();
242}
243
244#if INCLUDE_ALL_GCS
245void TypeArrayKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
246  ShouldNotReachHere();
247  assert(obj->is_typeArray(),"must be a type array");
248}
249
250int
251TypeArrayKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
252  assert(obj->is_typeArray(),"must be a type array");
253  return typeArrayOop(obj)->object_size();
254}
255#endif // INCLUDE_ALL_GCS
256
257void TypeArrayKlass::initialize(TRAPS) {
258  // Nothing to do. Having this function is handy since objArrayKlasses can be
259  // initialized by calling initialize on their bottom_klass, see ObjArrayKlass::initialize
260}
261
262const char* TypeArrayKlass::external_name(BasicType type) {
263  switch (type) {
264    case T_BOOLEAN: return "[Z";
265    case T_CHAR:    return "[C";
266    case T_FLOAT:   return "[F";
267    case T_DOUBLE:  return "[D";
268    case T_BYTE:    return "[B";
269    case T_SHORT:   return "[S";
270    case T_INT:     return "[I";
271    case T_LONG:    return "[J";
272    default: ShouldNotReachHere();
273  }
274  return NULL;
275}
276
277
278// Printing
279
280void TypeArrayKlass::print_on(outputStream* st) const {
281#ifndef PRODUCT
282  assert(is_klass(), "must be klass");
283  print_value_on(st);
284  Klass::print_on(st);
285#endif //PRODUCT
286}
287
288void TypeArrayKlass::print_value_on(outputStream* st) const {
289  assert(is_klass(), "must be klass");
290  st->print("{type array ");
291  switch (element_type()) {
292    case T_BOOLEAN: st->print("bool");    break;
293    case T_CHAR:    st->print("char");    break;
294    case T_FLOAT:   st->print("float");   break;
295    case T_DOUBLE:  st->print("double");  break;
296    case T_BYTE:    st->print("byte");    break;
297    case T_SHORT:   st->print("short");   break;
298    case T_INT:     st->print("int");     break;
299    case T_LONG:    st->print("long");    break;
300    default: ShouldNotReachHere();
301  }
302  st->print("}");
303}
304
305#ifndef PRODUCT
306
307static void print_boolean_array(typeArrayOop ta, int print_len, outputStream* st) {
308  for (int index = 0; index < print_len; index++) {
309    st->print_cr(" - %3d: %s", index, (ta->bool_at(index) == 0) ? "false" : "true");
310  }
311}
312
313
314static void print_char_array(typeArrayOop ta, int print_len, outputStream* st) {
315  for (int index = 0; index < print_len; index++) {
316    jchar c = ta->char_at(index);
317    st->print_cr(" - %3d: %x %c", index, c, isprint(c) ? c : ' ');
318  }
319}
320
321
322static void print_float_array(typeArrayOop ta, int print_len, outputStream* st) {
323  for (int index = 0; index < print_len; index++) {
324    st->print_cr(" - %3d: %g", index, ta->float_at(index));
325  }
326}
327
328
329static void print_double_array(typeArrayOop ta, int print_len, outputStream* st) {
330  for (int index = 0; index < print_len; index++) {
331    st->print_cr(" - %3d: %g", index, ta->double_at(index));
332  }
333}
334
335
336static void print_byte_array(typeArrayOop ta, int print_len, outputStream* st) {
337  for (int index = 0; index < print_len; index++) {
338    jbyte c = ta->byte_at(index);
339    st->print_cr(" - %3d: %x %c", index, c, isprint(c) ? c : ' ');
340  }
341}
342
343
344static void print_short_array(typeArrayOop ta, int print_len, outputStream* st) {
345  for (int index = 0; index < print_len; index++) {
346    int v = ta->ushort_at(index);
347    st->print_cr(" - %3d: 0x%x\t %d", index, v, v);
348  }
349}
350
351
352static void print_int_array(typeArrayOop ta, int print_len, outputStream* st) {
353  for (int index = 0; index < print_len; index++) {
354    jint v = ta->int_at(index);
355    st->print_cr(" - %3d: 0x%x %d", index, v, v);
356  }
357}
358
359
360static void print_long_array(typeArrayOop ta, int print_len, outputStream* st) {
361  for (int index = 0; index < print_len; index++) {
362    jlong v = ta->long_at(index);
363    st->print_cr(" - %3d: 0x%x 0x%x", index, high(v), low(v));
364  }
365}
366
367
368void TypeArrayKlass::oop_print_on(oop obj, outputStream* st) {
369  ArrayKlass::oop_print_on(obj, st);
370  typeArrayOop ta = typeArrayOop(obj);
371  int print_len = MIN2((intx) ta->length(), MaxElementPrintSize);
372  switch (element_type()) {
373    case T_BOOLEAN: print_boolean_array(ta, print_len, st); break;
374    case T_CHAR:    print_char_array(ta, print_len, st);    break;
375    case T_FLOAT:   print_float_array(ta, print_len, st);   break;
376    case T_DOUBLE:  print_double_array(ta, print_len, st);  break;
377    case T_BYTE:    print_byte_array(ta, print_len, st);    break;
378    case T_SHORT:   print_short_array(ta, print_len, st);   break;
379    case T_INT:     print_int_array(ta, print_len, st);     break;
380    case T_LONG:    print_long_array(ta, print_len, st);    break;
381    default: ShouldNotReachHere();
382  }
383  int remaining = ta->length() - print_len;
384  if (remaining > 0) {
385    st->print_cr(" - <%d more elements, increase MaxElementPrintSize to print>", remaining);
386  }
387}
388
389#endif // PRODUCT
390
391const char* TypeArrayKlass::internal_name() const {
392  return Klass::external_name();
393}
394