jdk

Форк
0
/
constantTable.cpp 
314 строк · 12.1 Кб
1
/*
2
 * Copyright (c) 2020, 2023, 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.
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
  if (is_array() || other.is_array()) {
39
    if (is_array() != other.is_array() ||
40
        get_array()->length() != other.get_array()->length()) {
41
      return false;
42
    }
43
    for (int i = 0; i < get_array()->length(); i++) {
44
      jvalue ele1 = get_array()->at(i);
45
      jvalue ele2 = other.get_array()->at(i);
46
      bool is_eq;
47
      switch (type()) {
48
        case T_BOOLEAN: is_eq = ele1.z == ele2.z; break;
49
        case T_BYTE:    is_eq = ele1.b == ele2.b; break;
50
        case T_CHAR:    is_eq = ele1.c == ele2.c; break;
51
        case T_SHORT:   is_eq = ele1.s == ele2.s; break;
52
        case T_INT:     is_eq = ele1.i == ele2.i; break;
53
        case T_LONG:    is_eq = ele1.j == ele2.j; break;
54
        case T_FLOAT:   is_eq = jint_cast(ele1.f)  == jint_cast(ele2.f);  break;
55
        case T_DOUBLE:  is_eq = jlong_cast(ele1.d) == jlong_cast(ele2.d); break;
56
        default: ShouldNotReachHere(); is_eq = false;
57
      }
58
      if (!is_eq) {
59
        return false;
60
      }
61
    }
62
    return true;
63
  }
64
  // For floating point values we compare the bit pattern.
65
  switch (type()) {
66
  case T_INT:     return (_v._value.i == other._v._value.i);
67
  case T_FLOAT:   return jint_cast(_v._value.f) == jint_cast(other._v._value.f);
68
  case T_LONG:    return (_v._value.j == other._v._value.j);
69
  case T_DOUBLE:  return jlong_cast(_v._value.d) == jlong_cast(other._v._value.d);
70
  case T_OBJECT:
71
  case T_ADDRESS: return (_v._value.l == other._v._value.l);
72
  case T_VOID:    return (_v._value.l == other._v._value.l);  // jump-table entries
73
  case T_METADATA: return (_v._metadata == other._v._metadata);
74
  default: ShouldNotReachHere(); return false;
75
  }
76
}
77

78
int ConstantTable::qsort_comparator(Constant* a, Constant* b) {
79
  // sort descending
80
  if (a->freq() > b->freq())  return -1;
81
  if (a->freq() < b->freq())  return  1;
82
  return 0;
83
}
84

85
static int constant_size(ConstantTable::Constant* con) {
86
  if (con->is_array()) {
87
    return type2aelembytes(con->type()) * con->get_array()->length();
88
  }
89
  switch (con->type()) {
90
  case T_INT:     return sizeof(jint   );
91
  case T_LONG:    return sizeof(jlong  );
92
  case T_FLOAT:   return sizeof(jfloat );
93
  case T_DOUBLE:  return sizeof(jdouble);
94
  case T_METADATA: return sizeof(Metadata*);
95
    // We use T_VOID as marker for jump-table entries (labels) which
96
    // need an internal word relocation.
97
  case T_VOID:
98
  case T_ADDRESS:
99
  case T_OBJECT:  return sizeof(jobject);
100
  default:
101
    ShouldNotReachHere();
102
    return -1;
103
  }
104
}
105

106
void ConstantTable::calculate_offsets_and_size() {
107
  // First, sort the array by frequencies.
108
  _constants.sort(qsort_comparator);
109

110
#ifdef ASSERT
111
  // Make sure all jump-table entries were sorted to the end of the
112
  // array (they have a negative frequency).
113
  bool found_void = false;
114
  for (int i = 0; i < _constants.length(); i++) {
115
    Constant con = _constants.at(i);
116
    if (con.type() == T_VOID)
117
      found_void = true;  // jump-tables
118
    else
119
      assert(!found_void, "wrong sorting");
120
  }
121
#endif
122

123
  int offset = 0;
124
  for (int i = 0; i < _constants.length(); i++) {
125
    Constant* con = _constants.adr_at(i);
126

127
    // Align offset for type.
128
    int typesize = constant_size(con);
129
    assert(typesize <= 8 || con->is_array(), "sanity");
130
    offset = align_up(offset, con->alignment());
131
    con->set_offset(offset);   // set constant's offset
132

133
    if (con->type() == T_VOID) {
134
      MachConstantNode* n = (MachConstantNode*) con->get_jobject();
135
      offset = offset + typesize * n->outcnt();  // expand jump-table
136
    } else {
137
      offset = offset + typesize;
138
    }
139
  }
140

141
  // Align size up to the next section start (which is insts; see
142
  // CodeBuffer::align_at_start).
143
  assert(_size == -1, "already set?");
144
  _size = align_up(offset, (int)CodeEntryAlignment);
145
}
146

147
bool ConstantTable::emit(C2_MacroAssembler* masm) const {
148
  for (int i = 0; i < _constants.length(); i++) {
149
    Constant con = _constants.at(i);
150
    address constant_addr = nullptr;
151
    if (con.is_array()) {
152
      constant_addr = masm->array_constant(con.type(), con.get_array(), con.alignment());
153
    } else {
154
      switch (con.type()) {
155
      case T_INT:    constant_addr = masm->int_constant(   con.get_jint()   ); break;
156
      case T_LONG:   constant_addr = masm->long_constant(  con.get_jlong()  ); break;
157
      case T_FLOAT:  constant_addr = masm->float_constant( con.get_jfloat() ); break;
158
      case T_DOUBLE: constant_addr = masm->double_constant(con.get_jdouble()); break;
159
      case T_OBJECT: {
160
        jobject obj = con.get_jobject();
161
        int oop_index = masm->oop_recorder()->find_index(obj);
162
        constant_addr = masm->address_constant((address) obj, oop_Relocation::spec(oop_index));
163
        break;
164
      }
165
      case T_ADDRESS: {
166
        address addr = (address) con.get_jobject();
167
        constant_addr = masm->address_constant(addr);
168
        break;
169
      }
170
      // We use T_VOID as marker for jump-table entries (labels) which
171
      // need an internal word relocation.
172
      case T_VOID: {
173
        MachConstantNode* n = (MachConstantNode*) con.get_jobject();
174
        // Fill the jump-table with a dummy word.  The real value is
175
        // filled in later in fill_jump_table.
176
        address dummy = (address) n;
177
        constant_addr = masm->address_constant(dummy);
178
        if (constant_addr == nullptr) {
179
          return false;
180
        }
181
        assert((constant_addr - masm->code()->consts()->start()) == con.offset(),
182
              "must be: %d == %d", (int)(constant_addr - masm->code()->consts()->start()), (int)(con.offset()));
183

184
        // Expand jump-table
185
        address last_addr = nullptr;
186
        for (uint j = 1; j < n->outcnt(); j++) {
187
          last_addr = masm->address_constant(dummy + j);
188
          if (last_addr == nullptr) {
189
            return false;
190
          }
191
        }
192
#ifdef ASSERT
193
        address start = masm->code()->consts()->start();
194
        address new_constant_addr = last_addr - ((n->outcnt() - 1) * sizeof(address));
195
        // Expanding the jump-table could result in an expansion of the const code section.
196
        // In that case, we need to check if the new constant address matches the offset.
197
        assert((constant_addr - start == con.offset()) || (new_constant_addr - start == con.offset()),
198
              "must be: %d == %d or %d == %d (after an expansion)", (int)(constant_addr - start), (int)(con.offset()),
199
              (int)(new_constant_addr - start), (int)(con.offset()));
200
#endif
201
        continue; // Loop
202
      }
203
      case T_METADATA: {
204
        Metadata* obj = con.get_metadata();
205
        int metadata_index = masm->oop_recorder()->find_index(obj);
206
        constant_addr = masm->address_constant((address) obj, metadata_Relocation::spec(metadata_index));
207
        break;
208
      }
209
      default: ShouldNotReachHere();
210
      }
211
    }
212

213
    if (constant_addr == nullptr) {
214
      return false;
215
    }
216
    assert((constant_addr - masm->code()->consts()->start()) == con.offset(),
217
            "must be: %d == %d", (int)(constant_addr - masm->code()->consts()->start()), (int)(con.offset()));
218
  }
219
  return true;
220
}
221

222
int ConstantTable::find_offset(Constant& con) const {
223
  int idx = _constants.find(con);
224
  guarantee(idx != -1, "constant must be in constant table");
225
  int offset = _constants.at(idx).offset();
226
  guarantee(offset != -1, "constant table not emitted yet?");
227
  return offset;
228
}
229

230
void ConstantTable::add(Constant& con) {
231
  if (con.can_be_reused()) {
232
    int idx = _constants.find(con);
233
    if (idx != -1 && _constants.at(idx).can_be_reused()) {
234
      _constants.adr_at(idx)->inc_freq(con.freq());  // increase the frequency by the current value
235
      return;
236
    }
237
  }
238
  (void) _constants.append(con);
239
}
240

241
ConstantTable::Constant ConstantTable::add(MachConstantNode* n, BasicType type, jvalue value) {
242
  Block* b = Compile::current()->cfg()->get_block_for_node(n);
243
  Constant con(type, value, b->_freq);
244
  add(con);
245
  return con;
246
}
247

248
ConstantTable::Constant ConstantTable::add(Metadata* metadata) {
249
  Constant con(metadata);
250
  add(con);
251
  return con;
252
}
253

254
ConstantTable::Constant ConstantTable::add(MachConstantNode* n, BasicType bt,
255
                                           GrowableArray<jvalue>* array, int alignment) {
256
  Constant con(bt, array, alignment);
257
  add(con);
258
  return con;
259
}
260

261
ConstantTable::Constant ConstantTable::add(MachConstantNode* n, BasicType bt,
262
                                           GrowableArray<jvalue>* array) {
263
  return add(n, bt, array, array->length() * type2aelembytes(bt));
264
}
265

266
ConstantTable::Constant ConstantTable::add(MachConstantNode* n, MachOper* oper) {
267
  jvalue value;
268
  BasicType type = oper->type()->basic_type();
269
  switch (type) {
270
  case T_LONG:    value.j = oper->constantL(); break;
271
  case T_INT:     value.i = oper->constant();  break;
272
  case T_FLOAT:   value.f = oper->constantF(); break;
273
  case T_DOUBLE:  value.d = oper->constantD(); break;
274
  case T_OBJECT:
275
  case T_ADDRESS: value.l = (jobject) oper->constant(); break;
276
  case T_METADATA: return add((Metadata*)oper->constant()); break;
277
  default: guarantee(false, "unhandled type: %s", type2name(type));
278
  }
279
  return add(n, type, value);
280
}
281

282
ConstantTable::Constant ConstantTable::add_jump_table(MachConstantNode* n) {
283
  jvalue value;
284
  // We can use the node pointer here to identify the right jump-table
285
  // as this method is called from Compile::Fill_buffer right before
286
  // the MachNodes are emitted and the jump-table is filled (means the
287
  // MachNode pointers do not change anymore).
288
  value.l = (jobject) n;
289
  Constant con(T_VOID, value, next_jump_table_freq(), false);  // Labels of a jump-table cannot be reused.
290
  add(con);
291
  return con;
292
}
293

294
void ConstantTable::fill_jump_table(C2_MacroAssembler* masm, MachConstantNode* n, GrowableArray<Label*> labels) const {
295
  // If called from Compile::scratch_emit_size do nothing.
296
  if (Compile::current()->output()->in_scratch_emit_size())  return;
297

298
  assert(labels.is_nonempty(), "must be");
299
  assert((uint) labels.length() == n->outcnt(), "must be equal: %d == %d", labels.length(), n->outcnt());
300

301
  // Since MachConstantNode::constant_offset() also contains
302
  // table_base_offset() we need to subtract the table_base_offset()
303
  // to get the plain offset into the constant table.
304
  int offset = n->constant_offset() - table_base_offset();
305

306
  address* jump_table_base = (address*) (masm->code()->consts()->start() + offset);
307

308
  for (uint i = 0; i < n->outcnt(); i++) {
309
    address* constant_addr = &jump_table_base[i];
310
    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));
311
    *constant_addr = masm->code()->consts()->target(*labels.at(i), (address) constant_addr);
312
    masm->code()->consts()->relocate((address) constant_addr, relocInfo::internal_word_type);
313
  }
314
}
315

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.