jdk

Форк
0
/
metadataHandles.cpp 
172 строки · 6.3 Кб
1
/*
2
 * Copyright (c) 2019, 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
#include "precompiled.hpp"
25
#include "classfile/classLoaderData.hpp"
26
#include "jvmci/metadataHandles.hpp"
27
#include "runtime/atomic.hpp"
28

29
jmetadata MetadataHandles::allocate_metadata_handle(Metadata* obj) {
30
  assert(obj->is_valid() && obj->is_metadata(), "must be");
31

32
  if (_head == nullptr) {
33
    // This is the first allocation.
34
    _head = new MetadataHandleBlock();
35
    _last = _head;
36
    _num_blocks++;
37
  }
38

39
  HandleRecord* handle = get_handle();
40

41
  if (handle != nullptr) {
42
    handle->set_value(obj);
43
#ifdef METADATA_TRACK_NAMES
44
    handle->set_name(obj->print_value_string());
45
#endif
46
    return (jmetadata) handle;
47
  }
48

49
  // Check if an unused block follows last
50
  if (_last->_next != nullptr) {
51
    // update last and retry
52
    _last = _last->_next;
53
    return allocate_metadata_handle(obj);
54
  }
55

56
  // No space available, we have to rebuild free list or expand
57
  if (_allocate_before_rebuild == 0) {
58
    rebuild_free_list(); // updates _allocate_before_rebuild counter
59
  } else {
60
    // Append new block
61
    _last->_next = new MetadataHandleBlock();
62
    _last = _last->_next;
63
    _allocate_before_rebuild--;
64
    _num_blocks++;
65
  }
66
  return allocate_metadata_handle(obj);  // retry
67
}
68

69

70
void MetadataHandles::rebuild_free_list() {
71
  assert(_allocate_before_rebuild == 0 && _free_list == 0, "just checking");
72
  int free = 0;
73
  int blocks = 0;
74
  for (MetadataHandleBlock* current = _head; current != nullptr; current = current->_next) {
75
    for (int index = 0; index < current->_top; index++) {
76
      HandleRecord* handle = &(current->_handles)[index];
77
      if (handle->value() == nullptr) {
78
        // this handle was cleared out by a delete call, reuse it
79
        chain_free_list(handle);
80
        free++;
81
      }
82
    }
83
    // we should not rebuild free list if there are unused handles at the end
84
    assert(current->_top == MetadataHandleBlock::block_size_in_handles, "just checking");
85
    blocks++;
86
  }
87
  assert(_num_blocks == blocks, "%d != %d", _num_blocks, blocks);
88
  assert(_num_free_handles == free, "%d != %d", _num_free_handles, free);
89
  // Heuristic: if more than half of the handles are NOT free we rebuild next time
90
  // as well, otherwise we append a corresponding number of new blocks before
91
  // attempting a free list rebuild again.
92
  int total = blocks * MetadataHandleBlock::block_size_in_handles;
93
  int extra = total - 2*free;
94
  if (extra > 0) {
95
    // Not as many free handles as we would like - compute number of new blocks to append
96
    _allocate_before_rebuild = (extra + MetadataHandleBlock::block_size_in_handles - 1) / MetadataHandleBlock::block_size_in_handles;
97
  }
98
}
99

100
void MetadataHandles::clear() {
101
  _free_list = 0;
102
  _last = _head;
103
  if (_head != nullptr) {
104
    for (MetadataHandleBlock* block = _head; block != nullptr; block = block->_next) {
105
      block->_top = 0;
106
    }
107
  }
108
  _num_handles = 0;
109
  _num_free_handles = 0;
110
}
111

112
void MetadataHandles::metadata_do(void f(Metadata*)) {
113
  for (MetadataHandleBlock* current = _head; current != nullptr; current = current->_next) {
114
    for (int index = 0; index < current->_top; index++) {
115
      HandleRecord* root = &(current->_handles)[index];
116
      Metadata* value = root->value();
117
      // traverse heap pointers only, not deleted handles or free list
118
      // pointers
119
      if (value != nullptr && ((intptr_t) value & ptr_tag) == 0) {
120
        assert(value->is_valid(), "invalid metadata %s", current->get_name(index));
121
        f(value);
122
      }
123
    }
124
    // the next handle block is valid only if current block is full
125
    if (current->_top < MetadataHandleBlock::block_size_in_handles) {
126
      break;
127
    }
128
  }
129
}
130

131
// Visit any live metadata handles and clean them up.  Since clearing of these handles is driven by
132
// weak references they will be cleared at some point in the future when the reference cleaning logic is run.
133
void MetadataHandles::do_unloading() {
134
  for (MetadataHandleBlock* current = _head; current != nullptr; current = current->_next) {
135
    for (int index = 0; index < current->_top; index++) {
136
      HandleRecord* handle = &(current->_handles)[index];
137
      Metadata* value = handle->value();
138
      // traverse heap pointers only, not deleted handles or free list
139
      // pointers
140
      if (value != nullptr && ((intptr_t) value & ptr_tag) == 0) {
141
        Klass* klass = nullptr;
142
        if (value->is_klass()) {
143
          klass = (Klass*)value;
144
        } else if (value->is_method()) {
145
          Method* m = (Method*)value;
146
          klass = m->method_holder();
147
        } else if (value->is_constantPool()) {
148
          ConstantPool* cp = (ConstantPool*)value;
149
          klass = cp->pool_holder();
150
        } else {
151
          ShouldNotReachHere();
152
        }
153
        if (klass->class_loader_data()->is_unloading()) {
154
          // This needs to be marked so that it's no longer scanned
155
          // but can't be put on the free list yet. The
156
          // HandleCleaner will set this to null and
157
          // put it on the free list.
158
          jlong old_value = Atomic::cmpxchg((jlong*)handle, (jlong) value, (jlong) (ptr_tag));
159
          if (old_value == (jlong) value) {
160
            // Success
161
          } else {
162
            guarantee(old_value == 0, "only other possible value");
163
          }
164
        }
165
      }
166
    }
167
    // the next handle block is valid only if current block is full
168
    if (current->_top < MetadataHandleBlock::block_size_in_handles) {
169
      break;
170
    }
171
  }
172
}
173

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

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

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

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