Skip to content

Commit 7efbc5c

Browse files
authored
Introduce JikesRVM-specific object accessor types (#177)
The main purpose of this PR is make a clear distinction between the `ObjectReference` type in JikesRVM and the `ObjectReference` type in mmtk-core. This PR introduced `JikesObj`, a Rust type that represents the JikesRVM-level `ObjectReference`. It needs an explicit conversion to convert to/from the MMTk-level `ObjectReference` types. The interface between mmtk-core and the mmtk-jikesrvm binding is refactored to do fewer things with the MMTk-level `ObjectReference`. - Trait methods that pass `ObjectReference` to the binding, notably the methods in `ObjectModel`, now simply convert the MMTk-level `ObjectReference` to `JikesObj`, and then call methods of `JikesObj`. - Concrete methods for accessing object headers, fields, and layout information are now implemented by `JikesObj` (and other wrapper types including `TIB` and `RVMType`). - The `JikesRVMSlot` trait now does the conversion between `JikesObj` and the MMTk-level `ObjectReference` when loading or storing a slot. This allows us to change the definition of the MMTk-level `ObjectReference` in the future, while concrete methods of `JikesObj` still use offset constants relative to the JikesRVM-level `ObjectReference` which will not change. The interface between the Rust part and the Java part of the binding are refactored to involve `JikesObj` only. - API functions in `api.rs` accept `JikesObj` parameters from JikesRVM and return `JikeObj` to JikesRVM where JikesRVM uses the JikesRVM-level `ObjectReference`. - We wrap all JTOC calls into strongly-typed Rust functions, and make the weakly-typed `jtoc_call!` macro private to the wrappers. In this way, we ensure none of the API functions or JTOC calls leak the MMTk-level `ObjectReference` values to JikesRVM, or accidentally interpret a JikesRVM-level `ObjectReference` as an MMTk-level `ObjectReference`. We also do some obvious refactoring that makes the code more readable.: - Encapsulated many field-loading statements in the form of `(addr + XXXX_OFFSET)::load<T>()` into dedicated methods. - Encapsulated the code for determining the overhead of hash fields into a function `JikesObj::hashcode_overhead` and simplified many methods that depend on that. - Renaming "edge" to "slot" in `RustScanThread.java`. And obvious bug fixes: - The call to `DO_REFERENCE_PROCESSING_HELPER_SCAN_METHOD_OFFSET` used to erroneously interpret 0 as `true`. This has been fixed by relying on the conversion trait. - `scan_boot_image_sanity` used to declare an immutable array and let unsafe `jtoc_call!` code modify it. The array is now defined as mutable. Related issues and PRs: - This PR is the 1st step of #178 - It will ultimately allow mmtk/mmtk-core#1170 to be implemented.
1 parent c5007a0 commit 7efbc5c

14 files changed

+869
-589
lines changed

jikesrvm/rvm/src/org/jikesrvm/mm/mminterface/RustScanThread.java

+29-31
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@
109109
private GCMapIterator iterator;
110110
@Untraced
111111
private boolean processCodeLocations;
112-
private Address report_edges;
113-
private Address report_edges_extra_data;
112+
private Address reportSlots;
113+
private Address reportSlotsExtraData;
114114
@Untraced
115115
private RVMThread thread;
116116
private Address ip, fp, prevFp, initialIPLoc, topFrame;
@@ -120,7 +120,7 @@
120120
private boolean failed;
121121
private boolean reinstallReturnBarrier;
122122

123-
private Address edges;
123+
private Address slots;
124124
private Word size = Word.zero();
125125
// The buffer size agreed between the Rust part and the Java part of the binding.
126126
// See the constant SLOTS_BUFFER_CAPACITY in scanning.rs.
@@ -135,15 +135,15 @@
135135
* Scan a thread, placing the addresses of pointers into supplied buffers.
136136
*
137137
* @param thread The thread to be scanned
138-
* @param report_edges The native call-back function to use for reporting locations.
139-
* @param report_edges_extra_data Extra data passed to the report_edges call-back.
138+
* @param reportSlots The native call-back function to use for reporting locations.
139+
* @param reportSlotsExtraData Extra data passed to the reportSlots call-back.
140140
* @param processCodeLocations Should code locations be processed?
141141
* @param newRootsSufficient Is a partial stack scan sufficient, or must we do a full scan?
142142
*/
143143
@Entrypoint
144144
public static void scanThread(RVMThread thread,
145-
Address report_edges,
146-
Address report_edges_extra_data,
145+
Address reportSlots,
146+
Address reportSlotsExtraData,
147147
boolean processCodeLocations,
148148
boolean newRootsSufficient) {
149149
if (DEFAULT_VERBOSITY >= 1) {
@@ -158,7 +158,7 @@ public static void scanThread(RVMThread thread,
158158
Address fp = regs.getInnermostFramePointer();
159159
regs.clear();
160160
regs.setInnermost(ip,fp);
161-
scanThread(thread, report_edges, report_edges_extra_data, processCodeLocations, gprs, Address.zero(), newRootsSufficient);
161+
scanThread(thread, reportSlots, reportSlotsExtraData, processCodeLocations, gprs, Address.zero(), newRootsSufficient);
162162
}
163163

164164
/**
@@ -167,8 +167,8 @@ public static void scanThread(RVMThread thread,
167167
* structure.
168168
*
169169
* @param thread The thread to be scanned
170-
* @param report_edges The native call-back function to use for reporting locations.
171-
* @param report_edges_extra_data Extra data passed to the report_edges call-back.
170+
* @param reportSlots The native call-back function to use for reporting locations.
171+
* @param reportSlotsExtraData Extra data passed to the reportSlots call-back.
172172
* @param processCodeLocations Should code locations be processed?
173173
* @param gprs The general purpose registers associated with the
174174
* stack being scanned (normally extracted from the thread).
@@ -177,8 +177,8 @@ public static void scanThread(RVMThread thread,
177177
* @param newRootsSufficent Is a partial stack scan sufficient, or must we do a full scan?
178178
*/
179179
private static void scanThread(RVMThread thread,
180-
Address report_edges,
181-
Address report_edges_extra_data,
180+
Address reportSlots,
181+
Address reportSlotsExtraData,
182182
boolean processCodeLocations,
183183
Address gprs,
184184
Address topFrame,
@@ -211,25 +211,25 @@ private static void scanThread(RVMThread thread,
211211
}
212212

213213
/* scan the stack */
214-
scanner.startScan(report_edges, report_edges_extra_data, processCodeLocations, thread, gprs, ip, fp, initialIPLoc, topFrame, sentinelFp);
214+
scanner.startScan(reportSlots, reportSlotsExtraData, processCodeLocations, thread, gprs, ip, fp, initialIPLoc, topFrame, sentinelFp);
215215
}
216216

217217
@Inline
218-
private void reportEdge(Address edge) {
218+
private void reportSlot(Address slot) {
219219
// Push value
220220
Word cursor = this.size;
221221
this.size = cursor.plus(Word.one());
222-
if (VM.VerifyAssertions) VM._assert(!this.edges.isZero());
223-
this.edges.plus(cursor.toInt() << LOG_BYTES_IN_WORD).store(edge);
222+
if (VM.VerifyAssertions) VM._assert(!this.slots.isZero());
223+
this.slots.plus(cursor.toInt() << LOG_BYTES_IN_WORD).store(slot);
224224
// Flush if full
225225
if (cursor.GE(SLOTS_BUFFER_CAPACITY)) {
226226
flush();
227227
}
228228
}
229229

230230
private void flush() {
231-
if (!edges.isZero() && !size.isZero()) {
232-
edges = sysCall.sysDynamicCall3(report_edges, edges.toWord(), size, report_edges_extra_data.toWord());
231+
if (!slots.isZero() && !size.isZero()) {
232+
slots = sysCall.sysDynamicCall3(reportSlots, slots.toWord(), size, reportSlotsExtraData.toWord());
233233
size = Word.zero();
234234
}
235235
}
@@ -244,8 +244,8 @@ private void flush() {
244244
* The various state associated with stack scanning is captured by
245245
* instance variables of this type, which are initialized here.
246246
*
247-
* @param report_edges The native call-back function to use for reporting locations.
248-
* @param report_edges_extra_data Extra data passed to the report_edges call-back.
247+
* @param reportSlots The native call-back function to use for reporting locations.
248+
* @param reportSlotsExtraData Extra data passed to the reportSlots call-back.
249249
* @param processCodeLocations whether to process parts of the thread
250250
* that could point to code (e.g. exception registers).
251251
* @param thread Thread for the thread whose stack is being scanned
@@ -261,16 +261,16 @@ private void flush() {
261261
* if this is to be inferred from the thread (normally the case).
262262
* @param sentinelFp The frame pointer at which the stack scan should stop.
263263
*/
264-
private void startScan(Address report_edges,
265-
Address report_edges_extra_data,
264+
private void startScan(Address reportSlots,
265+
Address reportSlotsExtraData,
266266
boolean processCodeLocations,
267267
RVMThread thread, Address gprs, Address ip,
268268
Address fp, Address initialIPLoc, Address topFrame,
269269
Address sentinelFp) {
270-
this.report_edges = report_edges;
271-
this.report_edges_extra_data = report_edges_extra_data;
270+
this.reportSlots = reportSlots;
271+
this.reportSlotsExtraData = reportSlotsExtraData;
272272
this.size = Word.zero();
273-
this.edges = sysCall.sysDynamicCall3(report_edges, Word.zero(), Word.zero(), report_edges_extra_data.toWord());
273+
this.slots = sysCall.sysDynamicCall3(reportSlots, Word.zero(), Word.zero(), reportSlotsExtraData.toWord());
274274

275275
this.processCodeLocations = processCodeLocations;
276276
this.thread = thread;
@@ -289,8 +289,8 @@ private void startScan(Address report_edges,
289289
VM.sysFail("Error encountered while scanning stack");
290290
}
291291
flush();
292-
if (!edges.isZero()) {
293-
sysCall.release_buffer(edges);
292+
if (!slots.isZero()) {
293+
sysCall.release_buffer(slots);
294294
}
295295
}
296296

@@ -395,8 +395,7 @@ private void processCodeLocation(ObjectReference code, Address ipLoc) {
395395
if (!failed) failed = true;
396396
}
397397
}
398-
reportEdge(ipLoc);
399-
// sysCall.sysProcessInteriorEdge(trace, code, ipLoc, true);
398+
reportSlot(ipLoc);
400399
}
401400

402401
/***********************************************************************
@@ -503,8 +502,7 @@ private void scanFrameForObjects(int verbosity) {
503502
refaddr = iterator.getNextReferenceAddress()) {
504503
if (VALIDATE_REFS) checkReference(refaddr, verbosity);
505504
if (verbosity >= 4) dumpRef(refaddr, verbosity);
506-
reportEdge(refaddr);
507-
// reportDelayedRootEdge(trace, refaddr);
505+
reportSlot(refaddr);
508506
}
509507
}
510508

mmtk/Cargo.lock

+42-29
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mmtk/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ log = {version = "0.4", features = ["max_level_trace", "release_max_level_off"]
2828
# - change branch/rev
2929
# - change repo name
3030
# But other changes including adding/removing whitespaces in commented lines may break the CI.
31-
mmtk = { git = "https://github.com/mmtk/mmtk-core.git", rev = "160b7702fccda133c9407234821ad35103623179" }
31+
mmtk = { git = "https://github.com/mmtk/mmtk-core.git", rev = "b3385b85fe1adf96ce820b0ceae1efdcaafa9120" }
3232
# Uncomment the following to build locally - if you change the path locally, do not commit the change in a PR
3333
# mmtk = { path = "../repos/mmtk-core" }
3434

0 commit comments

Comments
 (0)