1 /*
2  * Copyright (c) 2020, 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 "asm/codeBuffer.hpp"
27 #include "asm/macroAssembler.hpp"
28 #include "opto/block.hpp"
29 #include "opto/constantTable.hpp"
30 #include "opto/machnode.hpp"
31 #include "opto/output.hpp"
32 
33 //=============================================================================
34 // Two Constant's are equal when the type and the value are equal.
operator ==(const Constant & other)35 bool ConstantTable::Constant::operator==(const Constant& other) {
36   if (type()          != other.type()         )  return false;
37   if (can_be_reused() != other.can_be_reused())  return false;
38   // For floating point values we compare the bit pattern.
39   switch (type()) {
40   case T_INT:
41   case T_FLOAT:   return (_v._value.i == other._v._value.i);
42   case T_LONG:
43   case T_DOUBLE:  return (_v._value.j == other._v._value.j);
44   case T_OBJECT:
45   case T_ADDRESS: return (_v._value.l == other._v._value.l);
46   case T_VOID:    return (_v._value.l == other._v._value.l);  // jump-table entries
47   case T_METADATA: return (_v._metadata == other._v._metadata);
48   default: ShouldNotReachHere(); return false;
49   }
50 }
51 
qsort_comparator(Constant * a,Constant * b)52 int ConstantTable::qsort_comparator(Constant* a, Constant* b) {
53   // sort descending
54   if (a->freq() > b->freq())  return -1;
55   if (a->freq() < b->freq())  return  1;
56   return 0;
57 }
58 
type_to_size_in_bytes(BasicType t)59 static int type_to_size_in_bytes(BasicType t) {
60   switch (t) {
61   case T_INT:     return sizeof(jint   );
62   case T_LONG:    return sizeof(jlong  );
63   case T_FLOAT:   return sizeof(jfloat );
64   case T_DOUBLE:  return sizeof(jdouble);
65   case T_METADATA: return sizeof(Metadata*);
66     // We use T_VOID as marker for jump-table entries (labels) which
67     // need an internal word relocation.
68   case T_VOID:
69   case T_ADDRESS:
70   case T_OBJECT:  return sizeof(jobject);
71   default:
72     ShouldNotReachHere();
73     return -1;
74   }
75 }
76 
calculate_offsets_and_size()77 void ConstantTable::calculate_offsets_and_size() {
78   // First, sort the array by frequencies.
79   _constants.sort(qsort_comparator);
80 
81 #ifdef ASSERT
82   // Make sure all jump-table entries were sorted to the end of the
83   // array (they have a negative frequency).
84   bool found_void = false;
85   for (int i = 0; i < _constants.length(); i++) {
86     Constant con = _constants.at(i);
87     if (con.type() == T_VOID)
88       found_void = true;  // jump-tables
89     else
90       assert(!found_void, "wrong sorting");
91   }
92 #endif
93 
94   int offset = 0;
95   for (int i = 0; i < _constants.length(); i++) {
96     Constant* con = _constants.adr_at(i);
97 
98     // Align offset for type.
99     int typesize = type_to_size_in_bytes(con->type());
100     offset = align_up(offset, typesize);
101     con->set_offset(offset);   // set constant's offset
102 
103     if (con->type() == T_VOID) {
104       MachConstantNode* n = (MachConstantNode*) con->get_jobject();
105       offset = offset + typesize * n->outcnt();  // expand jump-table
106     } else {
107       offset = offset + typesize;
108     }
109   }
110 
111   // Align size up to the next section start (which is insts; see
112   // CodeBuffer::align_at_start).
113   assert(_size == -1, "already set?");
114   _size = align_up(offset, (int)CodeEntryAlignment);
115 }
116 
emit(CodeBuffer & cb) const117 bool ConstantTable::emit(CodeBuffer& cb) const {
118   MacroAssembler _masm(&cb);
119   for (int i = 0; i < _constants.length(); i++) {
120     Constant con = _constants.at(i);
121     address constant_addr = NULL;
122     switch (con.type()) {
123     case T_INT:    constant_addr = _masm.int_constant(   con.get_jint()   ); break;
124     case T_LONG:   constant_addr = _masm.long_constant(  con.get_jlong()  ); break;
125     case T_FLOAT:  constant_addr = _masm.float_constant( con.get_jfloat() ); break;
126     case T_DOUBLE: constant_addr = _masm.double_constant(con.get_jdouble()); break;
127     case T_OBJECT: {
128       jobject obj = con.get_jobject();
129       int oop_index = _masm.oop_recorder()->find_index(obj);
130       constant_addr = _masm.address_constant((address) obj, oop_Relocation::spec(oop_index));
131       break;
132     }
133     case T_ADDRESS: {
134       address addr = (address) con.get_jobject();
135       constant_addr = _masm.address_constant(addr);
136       break;
137     }
138     // We use T_VOID as marker for jump-table entries (labels) which
139     // need an internal word relocation.
140     case T_VOID: {
141       MachConstantNode* n = (MachConstantNode*) con.get_jobject();
142       // Fill the jump-table with a dummy word.  The real value is
143       // filled in later in fill_jump_table.
144       address dummy = (address) n;
145       constant_addr = _masm.address_constant(dummy);
146       if (constant_addr == NULL) {
147         return false;
148       }
149       assert((constant_addr - _masm.code()->consts()->start()) == con.offset(),
150              "must be: %d == %d", (int)(constant_addr - _masm.code()->consts()->start()), (int)(con.offset()));
151 
152       // Expand jump-table
153       address last_addr = NULL;
154       for (uint j = 1; j < n->outcnt(); j++) {
155         last_addr = _masm.address_constant(dummy + j);
156         if (last_addr == NULL) {
157           return false;
158         }
159       }
160 #ifdef ASSERT
161       address start = _masm.code()->consts()->start();
162       address new_constant_addr = last_addr - ((n->outcnt() - 1) * sizeof(address));
163       // Expanding the jump-table could result in an expansion of the const code section.
164       // In that case, we need to check if the new constant address matches the offset.
165       assert((constant_addr - start == con.offset()) || (new_constant_addr - start == con.offset()),
166              "must be: %d == %d or %d == %d (after an expansion)", (int)(constant_addr - start), (int)(con.offset()),
167              (int)(new_constant_addr - start), (int)(con.offset()));
168 #endif
169       continue; // Loop
170     }
171     case T_METADATA: {
172       Metadata* obj = con.get_metadata();
173       int metadata_index = _masm.oop_recorder()->find_index(obj);
174       constant_addr = _masm.address_constant((address) obj, metadata_Relocation::spec(metadata_index));
175       break;
176     }
177     default: ShouldNotReachHere();
178     }
179 
180     if (constant_addr == NULL) {
181       return false;
182     }
183     assert((constant_addr - _masm.code()->consts()->start()) == con.offset(),
184             "must be: %d == %d", (int)(constant_addr - _masm.code()->consts()->start()), (int)(con.offset()));
185   }
186   return true;
187 }
188 
find_offset(Constant & con) const189 int ConstantTable::find_offset(Constant& con) const {
190   int idx = _constants.find(con);
191   guarantee(idx != -1, "constant must be in constant table");
192   int offset = _constants.at(idx).offset();
193   guarantee(offset != -1, "constant table not emitted yet?");
194   return offset;
195 }
196 
add(Constant & con)197 void ConstantTable::add(Constant& con) {
198   if (con.can_be_reused()) {
199     int idx = _constants.find(con);
200     if (idx != -1 && _constants.at(idx).can_be_reused()) {
201       _constants.adr_at(idx)->inc_freq(con.freq());  // increase the frequency by the current value
202       return;
203     }
204   }
205   (void) _constants.append(con);
206 }
207 
add(MachConstantNode * n,BasicType type,jvalue value)208 ConstantTable::Constant ConstantTable::add(MachConstantNode* n, BasicType type, jvalue value) {
209   Block* b = Compile::current()->cfg()->get_block_for_node(n);
210   Constant con(type, value, b->_freq);
211   add(con);
212   return con;
213 }
214 
add(Metadata * metadata)215 ConstantTable::Constant ConstantTable::add(Metadata* metadata) {
216   Constant con(metadata);
217   add(con);
218   return con;
219 }
220 
add(MachConstantNode * n,MachOper * oper)221 ConstantTable::Constant ConstantTable::add(MachConstantNode* n, MachOper* oper) {
222   jvalue value;
223   BasicType type = oper->type()->basic_type();
224   switch (type) {
225   case T_LONG:    value.j = oper->constantL(); break;
226   case T_FLOAT:   value.f = oper->constantF(); break;
227   case T_DOUBLE:  value.d = oper->constantD(); break;
228   case T_OBJECT:
229   case T_ADDRESS: value.l = (jobject) oper->constant(); break;
230   case T_METADATA: return add((Metadata*)oper->constant()); break;
231   default: guarantee(false, "unhandled type: %s", type2name(type));
232   }
233   return add(n, type, value);
234 }
235 
add_jump_table(MachConstantNode * n)236 ConstantTable::Constant ConstantTable::add_jump_table(MachConstantNode* n) {
237   jvalue value;
238   // We can use the node pointer here to identify the right jump-table
239   // as this method is called from Compile::Fill_buffer right before
240   // the MachNodes are emitted and the jump-table is filled (means the
241   // MachNode pointers do not change anymore).
242   value.l = (jobject) n;
243   Constant con(T_VOID, value, next_jump_table_freq(), false);  // Labels of a jump-table cannot be reused.
244   add(con);
245   return con;
246 }
247 
fill_jump_table(CodeBuffer & cb,MachConstantNode * n,GrowableArray<Label * > labels) const248 void ConstantTable::fill_jump_table(CodeBuffer& cb, MachConstantNode* n, GrowableArray<Label*> labels) const {
249   // If called from Compile::scratch_emit_size do nothing.
250   if (Compile::current()->output()->in_scratch_emit_size())  return;
251 
252   assert(labels.is_nonempty(), "must be");
253   assert((uint) labels.length() == n->outcnt(), "must be equal: %d == %d", labels.length(), n->outcnt());
254 
255   // Since MachConstantNode::constant_offset() also contains
256   // table_base_offset() we need to subtract the table_base_offset()
257   // to get the plain offset into the constant table.
258   int offset = n->constant_offset() - table_base_offset();
259 
260   MacroAssembler _masm(&cb);
261   address* jump_table_base = (address*) (_masm.code()->consts()->start() + offset);
262 
263   for (uint i = 0; i < n->outcnt(); i++) {
264     address* constant_addr = &jump_table_base[i];
265     assert(*constant_addr == (((address) n) + i), "all jump-table entries must contain adjusted node pointer: " INTPTR_FORMAT " == " INTPTR_FORMAT, p2i(*constant_addr), p2i(((address) n) + i));
266     *constant_addr = cb.consts()->target(*labels.at(i), (address) constant_addr);
267     cb.consts()->relocate((address) constant_addr, relocInfo::internal_word_type);
268   }
269 }
270