Skip to content

Commit 0ad9f8d

Browse files
data structure and vm op working
1 parent abd4a8f commit 0ad9f8d

File tree

4 files changed

+377
-0
lines changed

4 files changed

+377
-0
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright (c) 2023, 2023, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2023, 2023, Red Hat Inc. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation. Oracle designates this
9+
* particular file as subject to the "Classpath" exception as provided
10+
* by Oracle in the LICENSE file that accompanied this code.
11+
*
12+
* This code is distributed in the hope that it will be useful, but WITHOUT
13+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+
* version 2 for more details (a copy is included in the LICENSE file that
16+
* accompanied this code).
17+
*
18+
* You should have received a copy of the GNU General Public License version
19+
* 2 along with this work; if not, write to the Free Software Foundation,
20+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21+
*
22+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23+
* or visit www.oracle.com if you need additional information or have any
24+
* questions.
25+
*/
26+
27+
package com.oracle.svm.core.jfr.events;
28+
29+
import com.oracle.svm.core.Uninterruptible;
30+
import com.oracle.svm.core.jfr.HasJfrSupport;
31+
import com.oracle.svm.core.jfr.JfrEvent;
32+
import com.oracle.svm.core.jfr.JfrNativeEventWriter;
33+
import com.oracle.svm.core.jfr.JfrNativeEventWriterData;
34+
import com.oracle.svm.core.jfr.JfrNativeEventWriterDataAccess;
35+
import com.oracle.svm.core.jfr.JfrTicks;
36+
import com.oracle.svm.core.jfr.SubstrateJVM;
37+
import org.graalvm.compiler.word.Word;
38+
import org.graalvm.nativeimage.StackValue;
39+
import com.oracle.svm.core.thread.VMOperation;
40+
41+
import static com.oracle.svm.core.heap.RestrictHeapAccess.Access.NO_ALLOCATION;
42+
43+
public class ObjectCountEvent {
44+
/** Should only be called during garbage collection at a safepoint */
45+
// @com.oracle.svm.core.heap.RestrictHeapAccess(access = NO_ALLOCATION, reason = "Object Counting
46+
// must not allocate.")
47+
public static void emit(long startTick) {
48+
assert VMOperation.isInProgressAtSafepoint();
49+
if (HasJfrSupport.get()) {
50+
// TODO check here if we should emit before we do an expensive heap walk (similar to
51+
// objectAllocationSample)
52+
com.oracle.svm.core.jfr.events.ObjectCountEventSupport.countObjects();
53+
// For each object in data structure
54+
emit0(null, 0, 0);
55+
}
56+
}
57+
58+
@Uninterruptible(reason = "Accesses a JFR buffer.")
59+
private static void emit0(Class<?> clazz, long count, long size) {
60+
}
61+
}
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
/*
2+
* Copyright (c) 2023, 2023, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2023, 2023, Red Hat Inc. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation. Oracle designates this
9+
* particular file as subject to the "Classpath" exception as provided
10+
* by Oracle in the LICENSE file that accompanied this code.
11+
*
12+
* This code is distributed in the hope that it will be useful, but WITHOUT
13+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+
* version 2 for more details (a copy is included in the LICENSE file that
16+
* accompanied this code).
17+
*
18+
* You should have received a copy of the GNU General Public License version
19+
* 2 along with this work; if not, write to the Free Software Foundation,
20+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21+
*
22+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23+
* or visit www.oracle.com if you need additional information or have any
24+
* questions.
25+
*/
26+
27+
package com.oracle.svm.core.jfr.events;
28+
29+
import com.oracle.svm.core.Uninterruptible;
30+
import com.oracle.svm.core.UnmanagedMemoryUtil;
31+
import com.oracle.svm.core.thread.NativeVMOperation;
32+
import org.graalvm.nativeimage.Platform.HOSTED_ONLY;
33+
import org.graalvm.nativeimage.Platforms;
34+
import com.oracle.svm.core.thread.VMOperation.SystemEffect;
35+
import com.oracle.svm.core.thread.VMOperation;
36+
import com.oracle.svm.core.thread.NativeVMOperationData;
37+
import com.oracle.svm.core.heap.VMOperationInfos;
38+
import com.oracle.svm.core.heap.ObjectVisitor;
39+
import com.oracle.svm.core.heap.Heap;
40+
import org.graalvm.nativeimage.StackValue;
41+
import com.oracle.svm.core.hub.DynamicHub;
42+
import org.graalvm.word.WordFactory;
43+
import org.graalvm.nativeimage.c.struct.RawStructure;
44+
import org.graalvm.nativeimage.c.struct.RawField;
45+
import org.graalvm.word.Pointer;
46+
import com.oracle.svm.core.hub.LayoutEncoding;
47+
import com.oracle.svm.core.util.VMError;
48+
import org.graalvm.nativeimage.ImageSingletons;
49+
import org.graalvm.nativeimage.c.struct.SizeOf;
50+
import com.oracle.svm.core.hub.DynamicHubSupport;
51+
import org.graalvm.nativeimage.impl.UnmanagedMemorySupport;
52+
import org.graalvm.word.PointerBase;
53+
import com.oracle.svm.core.jfr.events.PointerArrayAccess;
54+
import com.oracle.svm.core.jfr.events.PointerArray;
55+
56+
public class ObjectCountEventSupport {
57+
private final static ObjectCountVisitor objectCountVisitor = new ObjectCountVisitor();
58+
private static final ObjectCountOperation objectCountOperation = new ObjectCountOperation();
59+
private static int debugCount1 = 0;
60+
61+
@Platforms(HOSTED_ONLY.class)
62+
ObjectCountEventSupport() {
63+
}
64+
65+
public static void countObjects() {
66+
assert VMOperation.isInProgressAtSafepoint();
67+
int size = SizeOf.get(ObjectCountVMOperationData.class);
68+
ObjectCountVMOperationData data = StackValue.get(size);
69+
UnmanagedMemoryUtil.fill((Pointer) data, WordFactory.unsigned(size), (byte) 0);
70+
PointerArray objectCounts = StackValue.get(PointerArray.class);
71+
// int initialCapacity = Heap.getHeap().getClassCount();
72+
// max type id:9218 classes count:7909
73+
int initialCapacity = ImageSingletons.lookup(DynamicHubSupport.class).getMaxTypeId();
74+
PointerArrayAccess.initialize(objectCounts, initialCapacity);
75+
76+
// Throw an error, otherwise we'll probably get a segfault later
77+
VMError.guarantee(objectCounts.getSize() == initialCapacity, "init not done properly");
78+
79+
data.setObjectCounts(objectCounts);
80+
objectCountOperation.enqueue(data);
81+
VMError.guarantee(debugCount1 > 2000, "debug count1 should be > 2000");
82+
83+
int sizeSum = 0;
84+
int countSum = 0;
85+
for (int i = 0; i < objectCounts.getSize(); i++) {
86+
ObjectCountData objectCountData = (ObjectCountData) PointerArrayAccess.get(objectCounts, i);
87+
if (objectCountData.isNull()) {
88+
continue;
89+
}
90+
countSum += objectCountData.getCount();
91+
sizeSum += objectCountData.getSize();
92+
if (objectCountData.getCount() > 0) {
93+
VMError.guarantee(objectCountData.getSize() > 0, "size should be > 0 if count is > 0");
94+
}
95+
}
96+
// *** Do NOT add prints. Segfault at index 2927
97+
VMError.guarantee(countSum > 0, "countSum should be >0");
98+
VMError.guarantee(sizeSum > 0, "sizeSum should be >0");
99+
100+
int typeId = DynamicHub.fromClass(String.class).getTypeID();
101+
ObjectCountData stringOcd = objectCounts.getData().addressOf(typeId).read();
102+
VMError.guarantee(stringOcd.getCount() > 0, "should have more than 1 String in heap");
103+
VMError.guarantee(stringOcd.getSize() > 0, "string size should be positive");
104+
PointerArrayAccess.freeData(objectCounts);
105+
}
106+
107+
private static class ObjectCountOperation extends NativeVMOperation {
108+
@Platforms(HOSTED_ONLY.class)
109+
ObjectCountOperation() {
110+
super(VMOperationInfos.get(ObjectCountOperation.class, "JFR count objects", SystemEffect.SAFEPOINT));
111+
}
112+
113+
@Override
114+
// @RestrictHeapAccess(access = NO_ALLOCATION, reason = "Must not allocate during GC.")
115+
protected void operate(NativeVMOperationData data) {
116+
ObjectCountVMOperationData objectCountVMOperationData = (ObjectCountVMOperationData) data;
117+
objectCountVisitor.initialize(objectCountVMOperationData.getObjectCounts());
118+
Heap.getHeap().walkImageHeapObjects(objectCountVisitor);
119+
}
120+
}
121+
122+
private static boolean initializeObjectCountData(PointerArray pointerArray, int idx) {
123+
ObjectCountData objectCountData = ImageSingletons.lookup(UnmanagedMemorySupport.class).malloc(SizeOf.unsigned(ObjectCountData.class));
124+
if (objectCountData.isNull()) {
125+
return false;
126+
}
127+
objectCountData.setCount(0);
128+
objectCountData.setSize(0);
129+
PointerArrayAccess.write(pointerArray, idx, objectCountData);
130+
return true;
131+
}
132+
133+
private static class ObjectCountVisitor implements ObjectVisitor {
134+
PointerArray objectCounts;
135+
136+
@Platforms(HOSTED_ONLY.class)
137+
ObjectCountVisitor() {
138+
}
139+
140+
public void initialize(PointerArray objectCounts) {
141+
this.objectCounts = objectCounts;
142+
}
143+
144+
@Override
145+
public boolean visitObject(Object obj) { // *** Can't allocate in here no matter what.
146+
assert VMOperation.isInProgressAtSafepoint();
147+
DynamicHub hub = DynamicHub.fromClass(obj.getClass());
148+
int typeId = hub.getTypeID();
149+
VMError.guarantee(typeId < objectCounts.getSize(), "Should not encounter a typeId out of scope of the array");
150+
151+
// create an ObjectCountData for this typeID if one doesn't already exist
152+
ObjectCountData objectCountData = objectCounts.getData().addressOf(typeId).read();
153+
if (objectCountData.isNull()) { // *** this is working as expected
154+
debugCount1++;
155+
if (!initializeObjectCountData(objectCounts, typeId)) {
156+
return false;
157+
}
158+
// read it again to refresh the value
159+
objectCountData = objectCounts.getData().addressOf(typeId).read();
160+
}
161+
162+
// Increase count
163+
objectCountData.setCount(objectCountData.getCount() + 1);
164+
165+
// Get size
166+
long size = objectCountData.getSize();
167+
// int layoutEncoding = KnownIntrinsics.readHub(obj).getLayoutEncoding();
168+
// if (LayoutEncoding.isArray(layoutEncoding)) {
169+
// int elementSize;
170+
// if (LayoutEncoding.isPrimitiveArray(layoutEncoding)) {
171+
// elementSize = LayoutEncoding.getArrayIndexScale(layoutEncoding);
172+
// } else {
173+
// elementSize = ConfigurationValues.getTarget().wordSize;
174+
// }
175+
// int length = ArrayLengthNode.arrayLength(obj);
176+
// size += WordFactory.unsigned(length).multiply(elementSize).rawValue();
177+
// } else if (LayoutEncoding.isPureInstance(layoutEncoding)) {
178+
// size += LayoutEncoding.getPureInstanceAllocationSize(layoutEncoding).rawValue();
179+
// } else if (LayoutEncoding.isHybrid(layoutEncoding)){
180+
// size += LayoutEncoding.getArrayBaseOffsetAsInt(layoutEncoding);
181+
// }
182+
size += uninterruptibleGetSize(obj); // there's also getSizeFromObjectInGC and
183+
// getMomentarySizeFromObject
184+
objectCountData.setSize(size);
185+
return true;
186+
}
187+
188+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
189+
private long uninterruptibleGetSize(Object obj) {
190+
return LayoutEncoding.getSizeFromObject(obj).rawValue();
191+
}
192+
}
193+
194+
@RawStructure
195+
private interface ObjectCountVMOperationData extends NativeVMOperationData {
196+
@RawField
197+
PointerArray getObjectCounts();
198+
199+
@RawField
200+
void setObjectCounts(PointerArray value);
201+
}
202+
203+
@RawStructure
204+
public interface ObjectCountData extends PointerBase {
205+
@RawField
206+
long getCount();
207+
208+
@RawField
209+
void setCount(long value);
210+
211+
@RawField
212+
long getSize();
213+
214+
@RawField
215+
void setSize(long value);
216+
}
217+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.oracle.svm.core.jfr.events;
2+
3+
import org.graalvm.nativeimage.c.struct.RawStructure;
4+
import org.graalvm.nativeimage.c.struct.RawField;
5+
import org.graalvm.nativeimage.c.type.WordPointer;
6+
import org.graalvm.word.PointerBase;
7+
8+
@RawStructure
9+
public interface PointerArray extends PointerBase {
10+
@RawField
11+
int getSize();
12+
13+
@RawField
14+
void setSize(int value);
15+
16+
@RawField
17+
WordPointer getData();
18+
19+
@RawField
20+
void setData(WordPointer value);
21+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright (c) 2023, 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. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.core.jfr.events;
26+
27+
import com.oracle.svm.core.config.ConfigurationValues;
28+
import org.graalvm.compiler.api.replacements.Fold;
29+
import org.graalvm.nativeimage.ImageSingletons;
30+
import org.graalvm.nativeimage.c.type.WordPointer;
31+
import org.graalvm.nativeimage.impl.UnmanagedMemorySupport;
32+
import org.graalvm.word.WordFactory;
33+
import org.graalvm.word.PointerBase;
34+
import org.graalvm.word.WordBase;
35+
import com.oracle.svm.core.jfr.events.PointerArray;
36+
37+
public class PointerArrayAccess {
38+
public static void initialize(PointerArray array, int initialCapacity) {
39+
WordPointer newData = ImageSingletons.lookup(UnmanagedMemorySupport.class).malloc(WordFactory.unsigned(initialCapacity).multiply(wordSize()));
40+
// UnmanagedMemoryUtil.fill((Pointer) newData, WordFactory.unsigned(initialCapacity), (byte) 0);
41+
// TODO newData may be null
42+
array.setData(newData);
43+
for (int i = 0; i < initialCapacity; i++) { // TODO why does this loop make any difference?
44+
array.getData().addressOf(i).write(WordFactory.nullPointer());
45+
}
46+
array.setSize(initialCapacity);
47+
}
48+
49+
public static PointerBase get(PointerArray array, int i) {
50+
assert i >= 0 && i < array.getSize();
51+
return array.getData().addressOf(i).read();
52+
}
53+
54+
public static void write(PointerArray array, int i, WordBase word) {
55+
assert i >= 0 && i < array.getSize();
56+
array.getData().addressOf(i).write(word);
57+
}
58+
59+
public static void freeData(PointerArray array) {
60+
if (array.isNull()) {
61+
return;
62+
}
63+
for (int i = 0; i < array.getSize(); i++) {
64+
PointerBase ptr = com.oracle.svm.core.jfr.events.PointerArrayAccess.get(array, i);
65+
if (ptr.isNonNull()) {
66+
ImageSingletons.lookup(UnmanagedMemorySupport.class).free(ptr);
67+
}
68+
}
69+
ImageSingletons.lookup(UnmanagedMemorySupport.class).free(array.getData());
70+
array.setData(WordFactory.nullPointer());
71+
array.setSize(0);
72+
}
73+
74+
@Fold
75+
static int wordSize() {
76+
return ConfigurationValues.getTarget().wordSize;
77+
}
78+
}

0 commit comments

Comments
 (0)