Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_base/ObjectCheck.cpp
5986 views
1
/*******************************************************************************
2
* Copyright (c) 1991, 2020 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
21
*******************************************************************************/
22
23
#include "ObjectCheck.hpp"
24
25
#include "ClassModel.hpp"
26
#include "GCExtensions.hpp"
27
#include "Heap.hpp"
28
#include "HeapRegionIterator.hpp"
29
#include "HeapRegionDescriptor.hpp"
30
#include "ObjectModel.hpp"
31
#include "SegmentIterator.hpp"
32
33
extern "C" {
34
/**
35
* Check if the pointer is a valid class. Helper function for j9gc_ext_check_is_valid_heap_object.
36
* @param javaVM
37
* @param ptr the pointer to check if it is a valid class
38
* @param flags set J9OBJECTCHECK_FLAGS_* to control checking behaviour.
39
* @return one of J9OBJECTCHECK_* depending if the class is valid, invalid or looks like a forwarded pointer
40
* @ingroup GC_Base
41
*/
42
static UDATA
43
isValidClass(J9JavaVM *javaVM, J9Class *ptr, UDATA flags) {
44
GC_SegmentIterator segmentIterator(javaVM->classMemorySegments, MEMORY_TYPE_RAM_CLASS);
45
J9MemorySegment *segment;
46
47
/* class field can't be NULL */
48
if (NULL == ptr) {
49
return J9OBJECTCHECK_INVALID;
50
}
51
52
/* check alignment */
53
if (0 != ((UDATA)ptr & (sizeof(UDATA) - 1))) {
54
return J9OBJECTCHECK_INVALID;
55
}
56
57
/* We are not guarantee to have exclusive access at this point -- we need to mutex
58
* so that we don't pick up a segment while it is being added.
59
*/
60
#if defined(J9VM_THR_PREEMPTIVE)
61
omrthread_monitor_enter(javaVM->classMemorySegments->segmentMutex);
62
#endif /* J9VM_THR_PREEMPTIVE */
63
64
/* try to find the segment that this class starts in */
65
while(NULL != (segment = segmentIterator.nextSegment())) {
66
/* is the pointer in this segment? */
67
if ((segment->heapBase <= (U_8 *)ptr) && ((U_8 *)ptr < segment->heapAlloc)) {
68
break;
69
}
70
}
71
72
#if defined(J9VM_THR_PREEMPTIVE)
73
omrthread_monitor_exit(javaVM->classMemorySegments->segmentMutex);
74
#endif /* J9VM_THR_PREEMPTIVE */
75
76
/* pointer is not in class segment */
77
if (NULL == segment) {
78
return J9OBJECTCHECK_INVALID;
79
}
80
81
/* ensure that the class header fits into the segment */
82
if ((segment->heapAlloc - (U_8 *)ptr) < (ptrdiff_t)sizeof(J9Class)) {
83
return J9OBJECTCHECK_INVALID;
84
}
85
86
return J9OBJECTCHECK_CLASS;
87
}
88
89
/**
90
* Check if the pointer is a valid object in the object heap.
91
* @param javaVM
92
* @param ptr the pointer to check if it is a valid object
93
* @param flags set J9OBJECTCHECK_FLAGS_* to control checking behaviour.
94
* @return one of J9OBJECTCHECK_* depending if the object is valid, invalid or looks like it was forwarded.
95
* @ingroup GC_Base
96
*/
97
UDATA
98
j9gc_ext_check_is_valid_heap_object(J9JavaVM *javaVM, J9Object *ptr, UDATA flags)
99
{
100
/* check alignment */
101
if (0 != ((UDATA)ptr & (sizeof(UDATA) - 1) )) {
102
return J9OBJECTCHECK_INVALID;
103
}
104
105
UDATA retVal = 0;
106
void *lowAddress = NULL;
107
void *highAddress = NULL;
108
/* look up the region containing the object for checking that it is correctly contained */
109
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);
110
MM_Heap *heap = extensions->heap;
111
MM_HeapRegionManager *regionManager = heap->getHeapRegionManager();
112
GC_HeapRegionIterator regionIterator(regionManager);
113
MM_HeapRegionDescriptor *region = NULL;
114
115
/* try to find the region that this class starts in */
116
while(NULL != (region = regionIterator.nextRegion())) {
117
/* is the pointer in this segment? */
118
lowAddress = region->getLowAddress();
119
highAddress = region->getHighAddress();
120
if ((lowAddress <= ptr) && (ptr < highAddress)) {
121
break;
122
}
123
}
124
125
/* pointer is not in a region, this may really be a pointer to a class */
126
if (NULL == region) {
127
return J9OBJECTCHECK_INVALID;
128
}
129
130
/* ensure that the object header fits into the segment */
131
if (((UDATA)highAddress - (UDATA)ptr) < J9JAVAVM_OBJECT_HEADER_SIZE(javaVM)) {
132
return J9OBJECTCHECK_INVALID;
133
}
134
135
/* NOTE: Individual fields of the header will be queried multiple times
136
* If they change underneath us, we may want to take a snapshot
137
* of the header before querying them
138
*/
139
140
/* ensure that its class is valid */
141
retVal = isValidClass(javaVM, J9GC_J9OBJECT_CLAZZ_VM(ptr, javaVM), flags);
142
if (J9OBJECTCHECK_CLASS != retVal) {
143
return retVal;
144
}
145
146
/* ensure that the shape is correct */
147
if (!extensions->objectModel.checkIndexableFlag(ptr)) {
148
return J9OBJECTCHECK_INVALID;
149
}
150
151
if (extensions->objectModel.isObjectArray(ptr)
152
|| extensions->objectModel.isPrimitiveArray(ptr)) {
153
/* ensure that the array size fits into the segment */
154
if (((UDATA)highAddress - (UDATA)ptr) < J9JAVAVM_CONTIGUOUS_HEADER_SIZE(javaVM)) {
155
return J9OBJECTCHECK_INVALID;
156
}
157
}
158
159
/* ensure that the full object fits into the segment
160
* This must be done after knowing the class is valid, as we reach into the class to get the instance size
161
* Note: there are two cases for getSizeInBytesWithHeader:
162
* IndexableObject: The size is retrieved from the buffered object in the fourth slot which has already been
163
* cached, and range checked.
164
* MixedObject: The size is retrieved from the buffered class pointer. The class pointer won't have changed
165
* since checking it to be valid, however the size itself within the class memory may have changed. Since
166
* this is a range check it "does not matter", we know we will be able to dereference the memory.
167
*/
168
if (((UDATA)highAddress - (UDATA)ptr) < extensions->objectModel.getSizeInBytesWithHeader(ptr)) {
169
return J9OBJECTCHECK_INVALID;
170
}
171
172
return J9OBJECTCHECK_OBJECT;
173
}
174
} /* extern "C" */
175
176