jdk

Форк
0
/
vmSymbols.cpp 
299 строк · 10.1 Кб
1
/*
2
 * Copyright (c) 1997, 2024, 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 "cds/cdsConfig.hpp"
27
#include "cds/serializeClosure.hpp"
28
#include "classfile/symbolTable.hpp"
29
#include "classfile/vmSymbols.hpp"
30
#include "compiler/compilerDirectives.hpp"
31
#include "jvm.h"
32
#include "memory/allocation.inline.hpp"
33
#include "memory/oopFactory.hpp"
34
#include "memory/metaspaceClosure.hpp"
35
#include "oops/oop.inline.hpp"
36
#include "runtime/handles.inline.hpp"
37
#include "runtime/signature.hpp"
38
#include "utilities/xmlstream.hpp"
39

40

41
Symbol* vmSymbols::_type_signatures[T_VOID+1] = { nullptr /*, nullptr...*/ };
42

43
inline int compare_symbol(const Symbol* a, const Symbol* b) {
44
  if (a == b)  return 0;
45
  // follow the natural address order:
46
  return (address)a > (address)b ? +1 : -1;
47
}
48

49
static vmSymbolID vm_symbol_index[vmSymbols::number_of_symbols()];
50
extern "C" {
51
  static int compare_vmsymbol_sid(const void* void_a, const void* void_b) {
52
    const Symbol* a = Symbol::vm_symbol_at(*((vmSymbolID*) void_a));
53
    const Symbol* b = Symbol::vm_symbol_at(*((vmSymbolID*) void_b));
54
    return compare_symbol(a, b);
55
  }
56
}
57

58
#ifdef ASSERT
59
#define VM_SYMBOL_ENUM_NAME_BODY(name, string) #name "\0"
60
static const char* vm_symbol_enum_names =
61
  VM_SYMBOLS_DO(VM_SYMBOL_ENUM_NAME_BODY, VM_ALIAS_IGNORE)
62
  "\0";
63
static const char* vm_symbol_enum_name(vmSymbolID sid) {
64
  const char* string = &vm_symbol_enum_names[0];
65
  int skip = vmSymbols::as_int(sid) - vmSymbols::as_int(vmSymbolID::FIRST_SID);
66
  for (; skip != 0; skip--) {
67
    size_t skiplen = strlen(string);
68
    if (skiplen == 0)  return "<unknown>";  // overflow
69
    string += skiplen+1;
70
  }
71
  return string;
72
}
73
#endif //ASSERT
74

75
// Put all the VM symbol strings in one place.
76
// Makes for a more compact libjvm.
77
#define VM_SYMBOL_BODY(name, string) string "\0"
78
static const char* vm_symbol_bodies = VM_SYMBOLS_DO(VM_SYMBOL_BODY, VM_ALIAS_IGNORE);
79

80
void vmSymbols::initialize() {
81
  assert(SID_LIMIT <= (1<<log2_SID_LIMIT), "must fit in this bitfield");
82
  assert(SID_LIMIT*5 > (1<<log2_SID_LIMIT), "make the bitfield smaller, please");
83
  assert(vmIntrinsics::FLAG_LIMIT <= (1 << vmIntrinsics::log2_FLAG_LIMIT), "must fit in this bitfield");
84

85
  if (!CDSConfig::is_using_archive()) {
86
    const char* string = &vm_symbol_bodies[0];
87
    for (auto index : EnumRange<vmSymbolID>{}) {
88
      Symbol* sym = SymbolTable::new_permanent_symbol(string);
89
      Symbol::_vm_symbols[as_int(index)] = sym;
90
      string += strlen(string); // skip string body
91
      string += 1;              // skip trailing null
92
    }
93

94
    _type_signatures[T_BYTE]    = byte_signature();
95
    _type_signatures[T_CHAR]    = char_signature();
96
    _type_signatures[T_DOUBLE]  = double_signature();
97
    _type_signatures[T_FLOAT]   = float_signature();
98
    _type_signatures[T_INT]     = int_signature();
99
    _type_signatures[T_LONG]    = long_signature();
100
    _type_signatures[T_SHORT]   = short_signature();
101
    _type_signatures[T_BOOLEAN] = bool_signature();
102
    _type_signatures[T_VOID]    = void_signature();
103
#ifdef ASSERT
104
    for (int i = (int)T_BOOLEAN; i < (int)T_VOID+1; i++) {
105
      Symbol* s = _type_signatures[i];
106
      if (s == nullptr)  continue;
107
      SignatureStream ss(s, false);
108
      assert(ss.type() == i, "matching signature");
109
      assert(!ss.is_reference(), "no single-char signature for T_OBJECT, etc.");
110
    }
111
#endif
112
  }
113

114
#ifdef ASSERT
115
  // Check for duplicates:
116

117
  for (auto i1 : EnumRange<vmSymbolID>{}) {
118
    Symbol* sym = symbol_at(i1);
119
    for (auto i2 : EnumRange<vmSymbolID>{vmSymbolID::FIRST_SID, i1}) {
120
      if (i2 != i1 && symbol_at(i2) == sym) {
121
        tty->print("*** Duplicate VM symbol SIDs %s(%d) and %s(%d): \"",
122
                   vm_symbol_enum_name(i2), as_int(i2),
123
                   vm_symbol_enum_name(i1), as_int(i1));
124
        sym->print_symbol_on(tty);
125
        tty->print_cr("\"");
126
      }
127
    }
128
  }
129
#endif //ASSERT
130

131
  // Create an index for find_id:
132
  {
133
    for (auto index : EnumRange<vmSymbolID>{}) {
134
      vm_symbol_index[as_int(index)] = index;
135
    }
136
    int num_sids = SID_LIMIT-FIRST_SID;
137
    qsort(&vm_symbol_index[FIRST_SID], num_sids, sizeof(vm_symbol_index[0]),
138
          compare_vmsymbol_sid);
139
  }
140

141
#ifdef ASSERT
142
  {
143
    // Spot-check correspondence between strings, symbols, and enums:
144
    assert(Symbol::_vm_symbols[NO_SID] == nullptr, "must be");
145
    const char* str = "java/lang/Object";
146
    TempNewSymbol jlo = SymbolTable::new_permanent_symbol(str);
147
    assert(strncmp(str, (char*)jlo->base(), jlo->utf8_length()) == 0, "");
148
    assert(jlo == java_lang_Object(), "");
149
    vmSymbolID sid = VM_SYMBOL_ENUM_NAME(java_lang_Object);
150
    assert(find_sid(jlo) == sid, "");
151
    assert(symbol_at(sid) == jlo, "");
152

153
    // Make sure find_sid produces the right answer in each case.
154
    for (auto index : EnumRange<vmSymbolID>{}) {
155
      Symbol* sym = symbol_at(index);
156
      sid = find_sid(sym);
157
      assert(sid == index, "symbol index works");
158
      // Note:  If there are duplicates, this assert will fail.
159
      // A "Duplicate VM symbol" message will have already been printed.
160
    }
161

162
    // The string "format" happens (at the moment) not to be a vmSymbol,
163
    // though it is a method name in java.lang.String.
164
    str = "format";
165
    TempNewSymbol fmt = SymbolTable::new_permanent_symbol(str);
166
    sid = find_sid(fmt);
167
    assert(sid == vmSymbolID::NO_SID, "symbol index works (negative test)");
168
  }
169
#endif
170
}
171

172

173
#ifndef PRODUCT
174
const char* vmSymbols::name_for(vmSymbolID sid) {
175
  if (sid == vmSymbolID::NO_SID)
176
    return "NO_SID";
177
  const char* string = &vm_symbol_bodies[0];
178
  for (auto index : EnumRange<vmSymbolID>{}) {
179
    if (index == sid)
180
      return string;
181
    string += strlen(string); // skip string body
182
    string += 1;              // skip trailing null
183
  }
184
  return "BAD_SID";
185
}
186
#endif
187

188

189

190
void vmSymbols::symbols_do(SymbolClosure* f) {
191
  for (auto index : EnumRange<vmSymbolID>{}) {
192
    f->do_symbol(&Symbol::_vm_symbols[as_int(index)]);
193
  }
194
  for (int i = 0; i < T_VOID+1; i++) {
195
    f->do_symbol(&_type_signatures[i]);
196
  }
197
}
198

199
void vmSymbols::metaspace_pointers_do(MetaspaceClosure *closure) {
200
  for (auto index : EnumRange<vmSymbolID>{}) {
201
    closure->push(&Symbol::_vm_symbols[as_int(index)]);
202
  }
203
  for (int i = 0; i < T_VOID+1; i++) {
204
    closure->push(&_type_signatures[i]);
205
  }
206
}
207

208
void vmSymbols::serialize(SerializeClosure* soc) {
209
  soc->do_ptrs((void**)&Symbol::_vm_symbols[FIRST_SID],
210
                 (SID_LIMIT - FIRST_SID) * sizeof(Symbol::_vm_symbols[0]));
211
  soc->do_ptrs((void**)_type_signatures, sizeof(_type_signatures));
212
}
213

214
#ifndef PRODUCT
215
static uint find_sid_calls, find_sid_probes;
216
// (Typical counts are calls=7000 and probes=17000.)
217
#endif
218

219
vmSymbolID vmSymbols::find_sid(const Symbol* symbol) {
220
  static int mid_hint = FIRST_SID+1;
221
  // Handle the majority of misses by a bounds check.
222
  // Then, use a binary search over the index.
223
  // Expected trip count is less than log2_SID_LIMIT, about eight.
224
  // This is slow but acceptable, given that calls are not
225
  // dynamically common.  (Method*::intrinsic_id has a cache.)
226
  NOT_PRODUCT(find_sid_calls++);
227
  int min = FIRST_SID, max = SID_LIMIT - 1;
228
  vmSymbolID sid = vmSymbolID::NO_SID, sid1;
229
  int cmp1;
230
  sid1 = vm_symbol_index[min];
231
  cmp1 = compare_symbol(symbol, Symbol::vm_symbol_at(sid1));
232
  if (cmp1 <= 0) {              // before the first
233
    if (cmp1 == 0)  sid = sid1;
234
  } else {
235
    sid1 = vm_symbol_index[max];
236
    cmp1 = compare_symbol(symbol, symbol_at(sid1));
237
    if (cmp1 >= 0) {            // after the last
238
      if (cmp1 == 0)  sid = sid1;
239
    } else {
240
      // After checking the extremes, do a binary search.
241
      ++min; --max;             // endpoints are done
242
      int mid = mid_hint;       // start at previous success
243
      while (max >= min) {
244
        assert(mid >= min && mid <= max, "");
245
        NOT_PRODUCT(find_sid_probes++);
246
        sid1 = vm_symbol_index[mid];
247
        cmp1 = compare_symbol(symbol, symbol_at(sid1));
248
        if (cmp1 == 0) {
249
          mid_hint = mid;
250
          sid = sid1;
251
          break;
252
        }
253
        if (cmp1 < 0)
254
          max = mid - 1;        // symbol < symbol_at(sid)
255
        else
256
          min = mid + 1;
257

258
        // Pick a new probe point:
259
        mid = (max + min) / 2;
260
      }
261
    }
262
  }
263

264
#ifdef ASSERT
265
  if (sid == vmSymbolID::NO_SID) {
266
    return sid;
267
  }
268

269
  // Perform the exhaustive self-check the first 1000 calls,
270
  // and every 100 calls thereafter.
271
  static int find_sid_check_count = -2000;
272
  if ((uint)++find_sid_check_count > (uint)100) {
273
    if (find_sid_check_count > 0)  find_sid_check_count = 0;
274

275
    // Make sure this is the right answer, using linear search.
276
    // (We have already proven that there are no duplicates in the list.)
277
    vmSymbolID sid2 = vmSymbolID::NO_SID;
278
    for (auto index : EnumRange<vmSymbolID>{}) {
279
      Symbol* sym2 = symbol_at(index);
280
      if (sym2 == symbol) {
281
        sid2 = index;
282
        break;
283
      }
284
    }
285
    // Unless it's a duplicate, assert that the sids are the same.
286
    if (Symbol::_vm_symbols[as_int(sid)] != Symbol::_vm_symbols[as_int(sid2)]) {
287
      assert(sid == sid2, "binary same as linear search");
288
    }
289
  }
290
#endif //ASSERT
291

292
  return sid;
293
}
294

295
vmSymbolID vmSymbols::find_sid(const char* symbol_name) {
296
  Symbol* symbol = SymbolTable::probe(symbol_name, (int) strlen(symbol_name));
297
  if (symbol == nullptr)  return vmSymbolID::NO_SID;
298
  return find_sid(symbol);
299
}
300

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

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

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

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