jdk

Форк
0
/
handles.cpp 
212 строк · 8.2 Кб
1
/*
2
 * Copyright (c) 1997, 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 "memory/allocation.inline.hpp"
27
#include "oops/constantPool.hpp"
28
#include "oops/method.hpp"
29
#include "oops/oop.inline.hpp"
30
#include "runtime/handles.inline.hpp"
31
#include "runtime/javaThread.hpp"
32

33
#ifdef ASSERT
34
#define assert_handle_mark_nesting()                                                     \
35
  assert(_handle_mark_nesting > 1, "memory leak: allocating handle outside HandleMark"); \
36
  assert(_no_handle_mark_nesting == 0, "allocating handle inside NoHandleMark");         \
37

38

39
oop* HandleArea::allocate_handle(oop obj) {
40
  assert_handle_mark_nesting();
41
  assert(oopDesc::is_oop(obj), "not an oop: " INTPTR_FORMAT, p2i(obj));
42
  return real_allocate_handle(obj);
43
}
44

45
oop* HandleArea::allocate_null_handle() {
46
  assert_handle_mark_nesting();
47
  return real_allocate_handle(nullptr);
48
}
49
#endif
50

51
// Copy constructors and destructors for metadata handles
52
// These do too much to inline.
53
#define DEF_METADATA_HANDLE_FN_NOINLINE(name, type) \
54
name##Handle::name##Handle(const name##Handle &h) {                    \
55
  _value = h._value;                                                   \
56
  if (_value != nullptr) {                                             \
57
    assert(_value->is_valid(), "obj is valid");                        \
58
    if (h._thread != nullptr) {                                        \
59
      assert(h._thread == Thread::current(), "thread must be current");\
60
      _thread = h._thread;                                             \
61
    } else {                                                           \
62
      _thread = Thread::current();                                     \
63
    }                                                                  \
64
    assert(_thread->is_in_live_stack((address)this), "not on stack?"); \
65
    _thread->metadata_handles()->push((Metadata*)_value);              \
66
  } else {                                                             \
67
    _thread = nullptr;                                                 \
68
  }                                                                    \
69
}                                                                      \
70
name##Handle& name##Handle::operator=(const name##Handle &s) {         \
71
  remove();                                                            \
72
  _value = s._value;                                                   \
73
  if (_value != nullptr) {                                             \
74
    assert(_value->is_valid(), "obj is valid");                        \
75
    if (s._thread != nullptr) {                                        \
76
      assert(s._thread == Thread::current(), "thread must be current");\
77
      _thread = s._thread;                                             \
78
    } else {                                                           \
79
      _thread = Thread::current();                                     \
80
    }                                                                  \
81
    assert(_thread->is_in_live_stack((address)this), "not on stack?"); \
82
    _thread->metadata_handles()->push((Metadata*)_value);              \
83
  } else {                                                             \
84
    _thread = nullptr;                                                 \
85
  }                                                                    \
86
  return *this;                                                        \
87
}                                                                      \
88
inline void name##Handle::remove() {                                   \
89
  if (_value != nullptr) {                                             \
90
    int i = _thread->metadata_handles()->find_from_end((Metadata*)_value); \
91
    assert(i!=-1, "not in metadata_handles list");                     \
92
    _thread->metadata_handles()->remove_at(i);                         \
93
  }                                                                    \
94
}                                                                      \
95
name##Handle::~name##Handle () { remove(); }                           \
96

97
DEF_METADATA_HANDLE_FN_NOINLINE(method, Method)
98
DEF_METADATA_HANDLE_FN_NOINLINE(constantPool, ConstantPool)
99

100

101
static uintx chunk_oops_do(OopClosure* f, Chunk* chunk, char* chunk_top) {
102
  oop* bottom = (oop*) chunk->bottom();
103
  oop* top    = (oop*) chunk_top;
104
  uintx handles_visited = top - bottom;
105
  assert(top >= bottom && top <= (oop*) chunk->top(), "just checking");
106
  // during GC phase 3, a handle may be a forward pointer that
107
  // is not yet valid, so loosen the assertion
108
  while (bottom < top) {
109
    f->do_oop(bottom++);
110
  }
111
  return handles_visited;
112
}
113

114
void HandleArea::oops_do(OopClosure* f) {
115
  uintx handles_visited = 0;
116
  // First handle the current chunk. It is filled to the high water mark.
117
  handles_visited += chunk_oops_do(f, _chunk, _hwm);
118
  // Then handle all previous chunks. They are completely filled.
119
  Chunk* k = _first;
120
  while(k != _chunk) {
121
    handles_visited += chunk_oops_do(f, k, k->top());
122
    k = k->next();
123
  }
124

125
  if (_prev != nullptr) _prev->oops_do(f);
126
}
127

128
void HandleMark::initialize(Thread* thread) {
129
  _thread = thread;  // Not the current thread during thread creation.
130
  // Save area
131
  _area  = thread->handle_area();
132
  // Save current top
133
  _chunk = _area->_chunk;
134
  _hwm   = _area->_hwm;
135
  _max   = _area->_max;
136
  _size_in_bytes = _area->_size_in_bytes;
137
  debug_only(_area->_handle_mark_nesting++);
138
  assert(_area->_handle_mark_nesting > 0, "must stack allocate HandleMarks");
139

140
  // Link this in the thread
141
  set_previous_handle_mark(thread->last_handle_mark());
142
  thread->set_last_handle_mark(this);
143
}
144

145
HandleMark::~HandleMark() {
146
  assert(_area == _thread->handle_area(), "sanity check");
147
  assert(_area->_handle_mark_nesting > 0, "must stack allocate HandleMarks" );
148

149
  pop_and_restore();
150
#ifdef ASSERT
151
  // clear out first chunk (to detect allocation bugs)
152
  if (ZapVMHandleArea) {
153
    memset(_hwm, badHandleValue, _max - _hwm);
154
  }
155
#endif
156

157
  // Unlink this from the thread
158
  _thread->set_last_handle_mark(previous_handle_mark());
159
}
160

161
void HandleMark::chop_later_chunks() {
162
  // reset arena size before delete chunks. Otherwise, the total
163
  // arena size could exceed total chunk size
164
  _area->set_size_in_bytes(size_in_bytes());
165
  Chunk::next_chop(_chunk);
166
}
167

168
void* HandleMark::operator new(size_t size) throw() {
169
  return AllocateHeap(size, mtThread);
170
}
171

172
void* HandleMark::operator new [] (size_t size) throw() {
173
  return AllocateHeap(size, mtThread);
174
}
175

176
void HandleMark::operator delete(void* p) {
177
  FreeHeap(p);
178
}
179

180
void HandleMark::operator delete[](void* p) {
181
  FreeHeap(p);
182
}
183

184
#ifdef ASSERT
185

186
NoHandleMark::NoHandleMark() {
187
  HandleArea* area = Thread::current()->handle_area();
188
  area->_no_handle_mark_nesting++;
189
  assert(area->_no_handle_mark_nesting > 0, "must stack allocate NoHandleMark" );
190
}
191

192

193
NoHandleMark::~NoHandleMark() {
194
  HandleArea* area = Thread::current()->handle_area();
195
  assert(area->_no_handle_mark_nesting > 0, "must stack allocate NoHandleMark" );
196
  area->_no_handle_mark_nesting--;
197
}
198

199

200
ResetNoHandleMark::ResetNoHandleMark() {
201
  HandleArea* area = Thread::current()->handle_area();
202
  _no_handle_mark_nesting = area->_no_handle_mark_nesting;
203
  area->_no_handle_mark_nesting = 0;
204
}
205

206

207
ResetNoHandleMark::~ResetNoHandleMark() {
208
  HandleArea* area = Thread::current()->handle_area();
209
  area->_no_handle_mark_nesting = _no_handle_mark_nesting;
210
}
211

212
#endif // ASSERT
213

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

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

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

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