1 /*
2  * Copyright (c) 1999, 2017, 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 "ci/ciArray.hpp"
27 #include "ci/ciArrayKlass.hpp"
28 #include "ci/ciConstant.hpp"
29 #include "ci/ciKlass.hpp"
30 #include "ci/ciUtilities.inline.hpp"
31 #include "oops/objArrayOop.inline.hpp"
32 #include "oops/oop.inline.hpp"
33 #include "oops/typeArrayOop.inline.hpp"
34 
35 // ciArray
36 //
37 // This class represents an arrayOop in the HotSpot virtual
38 // machine.
fixup_element_type(BasicType bt)39 static BasicType fixup_element_type(BasicType bt) {
40   if (bt == T_ARRAY)    return T_OBJECT;
41   if (bt == T_BOOLEAN)  return T_BYTE;
42   return bt;
43 }
44 
element_value_impl(BasicType elembt,arrayOop ary,int index)45 ciConstant ciArray::element_value_impl(BasicType elembt,
46                                        arrayOop ary,
47                                        int index) {
48   if (ary == NULL)
49     return ciConstant();
50   assert(ary->is_array(), "");
51   if (index < 0 || index >= ary->length())
52     return ciConstant();
53   ArrayKlass* ak = (ArrayKlass*) ary->klass();
54   BasicType abt = ak->element_type();
55   if (fixup_element_type(elembt) !=
56       fixup_element_type(abt))
57     return ciConstant();
58   switch (elembt) {
59   case T_ARRAY:
60   case T_OBJECT:
61     {
62       assert(ary->is_objArray(), "");
63       objArrayOop objary = (objArrayOop) ary;
64       oop elem = objary->obj_at(index);
65       ciEnv* env = CURRENT_ENV;
66       ciObject* box = env->get_object(elem);
67       return ciConstant(T_OBJECT, box);
68     }
69   default:
70     break;
71   }
72   assert(ary->is_typeArray(), "");
73   typeArrayOop tary = (typeArrayOop) ary;
74   jint value = 0;
75   switch (elembt) {
76   case T_LONG:          return ciConstant(tary->long_at(index));
77   case T_FLOAT:         return ciConstant(tary->float_at(index));
78   case T_DOUBLE:        return ciConstant(tary->double_at(index));
79   default:              return ciConstant();
80   case T_BYTE:          value = tary->byte_at(index);           break;
81   case T_BOOLEAN:       value = tary->byte_at(index) & 1;       break;
82   case T_SHORT:         value = tary->short_at(index);          break;
83   case T_CHAR:          value = tary->char_at(index);           break;
84   case T_INT:           value = tary->int_at(index);            break;
85   }
86   return ciConstant(elembt, value);
87 }
88 
89 // ------------------------------------------------------------------
90 // ciArray::element_value
91 //
92 // Current value of an element.
93 // Returns T_ILLEGAL if there is no element at the given index.
element_value(int index)94 ciConstant ciArray::element_value(int index) {
95   BasicType elembt = element_basic_type();
96   GUARDED_VM_ENTRY(
97     return element_value_impl(elembt, get_arrayOop(), index);
98   )
99 }
100 
101 // ------------------------------------------------------------------
102 // ciArray::element_value_by_offset
103 //
104 // Current value of an element at the specified offset.
105 // Returns T_ILLEGAL if there is no element at the given offset.
element_value_by_offset(intptr_t element_offset)106 ciConstant ciArray::element_value_by_offset(intptr_t element_offset) {
107   BasicType elembt = element_basic_type();
108   intptr_t shift  = exact_log2(type2aelembytes(elembt));
109   intptr_t header = arrayOopDesc::base_offset_in_bytes(elembt);
110   intptr_t index = (element_offset - header) >> shift;
111   intptr_t offset = header + ((intptr_t)index << shift);
112   if (offset != element_offset || index != (jint)index || index < 0 || index >= length()) {
113     return ciConstant();
114   }
115   return element_value((jint) index);
116 }
117 
118 // ------------------------------------------------------------------
119 // ciArray::print_impl
120 //
121 // Implementation of the print method.
print_impl(outputStream * st)122 void ciArray::print_impl(outputStream* st) {
123   st->print(" length=%d type=", length());
124   klass()->print(st);
125 }
126