Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ospp][wip] Use the new weak reference processing API for the JikesRVM binding #145

Closed
6 tasks
fepicture opened this issue Jul 7, 2023 · 12 comments · Fixed by #150
Closed
6 tasks

[ospp][wip] Use the new weak reference processing API for the JikesRVM binding #145

fepicture opened this issue Jul 7, 2023 · 12 comments · Fixed by #150

Comments

@fepicture
Copy link
Contributor

this issue is tracking the weekly update on this project. also, mmtk@zulipchat has a sub-channel for this project discussion.

Motivation

shortly, porting the java-style jikesRVM to rust-lang is straightforward, but the reference processing is java-specific.
say, we expected a more general reference processing if we want to move forward to another language or gc mechanism.

Milestone

  • Compile and familiar code base
  • Refactor the weak ref handling mechanism
  • Run DaCapo benchmark and analyze the perf result
  • With previous perf result to optimize the current impl
  • Verify the impl correctness on CI
  • Write a doc

reference

#137
mmtk/mmtk-core#694
https://summer-ospp.ac.cn/org/prodetail/235730136

@fepicture
Copy link
Contributor Author

fepicture commented Jul 7, 2023

week 1

short

has successfully built the project on a pure ubuntu:22.04 docker image with the ci script
https://github.com/mmtk/mmtk-jikesrvm/blob/0651d4b02d04156f0a9092fc3f5890202e8d95be/.github/workflows/ci.yml
but fail on cargo msrv ( other script work well), I think this won't effect our progress.

Fetching index
Io Error: Cannot assign requested address (os error 99)

detail

the ci script uses the GitHub action image, which has many installed dependencies. since jikesRVM originally support a 32-bit platform, there we have to add the i386 toolchain in apt.

below is a partial from my bash history, I install the dependency one by one. say one error exists and then solve one error.
so, there is no full record. note: libssl-dev:i386 is really tricky, cargo build target is i386 that's we have to install libssl-dev:i386 instead libssl-dev x86_64. also, the jdk-8 may be in-compatible with your current version, be careful.

apt install python3 curl gcc make build-essential git wget
apt install ant temurin-8-jdk aclocal libtool  pkg-config libssl-dev:i386

take a quick glance in ci script:
the building entry is ./bin/buildit and follows with the install in localhost and config for mmtk.

update v1:

next week

familiar codebase, from jikesRVM register a weakreference to
may start from :
https://github.com/JikesRVM/JikesRVM/blob/master/rvm/src/org/jikesrvm/mm/mminterface/MemoryManager.java
https://github.com/JikesRVM/JikesRVM/blob/master/MMTk/src/org/mmtk/vm/ReferenceProcessor.java

update v2 && v3:

my building script with docker image ubuntu 22.10

fepicture@e97e98d

@fepicture
Copy link
Contributor Author

week 2

short

for jikesRVM original code base, I focus on the previous one called MemoryManager.java, and ReferenceProcessor.java
and will start a trial to replace the reference processing mechanism next week.

detail

those codes are the primary entry the jikesRVM delegate the gc work to mmtk framework. the implementation is directly wording side. truly I found the most useful doc is jikesrvm.org/UserGuide/, and jikesRVM originally did much work in spec, like java header layout boot image jit compiler and control flow optimization those things, which are interesting to me.

next week plan

Will start the first trial to remove the old reference processing. Currently, the binding for jikesRVM the reference processing will dump to the rust side process, we want to bypass this way and use the traditional and formal work in the original jikesRVM codebase. so, my basic idea is to set some code block to the Unimplement macro and guess which path the reference processing will take.

@fepicture
Copy link
Contributor Author

fepicture commented Jul 22, 2023

Update v1: The original report has been edited to improve grammar and make the language more formal.

week 3

short

The method mentioned last week was attempted but did not yield noticeable progress.

detail

I tried implementing the necessary methods with the unimplemented!() macro, but it panicked and did not display any meaningful stacktrace. This may be because the release version lacks debugging information. I even set rust-mmtk as debug instead of release, but still didn't have any progress. Discussion with wks indicated the stack unwinding is non-standard.

next week plan

I'll first work on FinalizerProcessors which does not require a state machine to implement its logic. I'll also try printing logs directly since no references have been processed with the option enabled.
https://github.com/mmtk/mmtk-core/blob/47ee126f91f25b911498b3d49c35f672f5e935f9/src/util/options.rs#L665C5-L672

    // Should finalization be disabled?
    no_finalizer:          bool                 [env_var: true, command_line: true]  [always_valid] = false,
    // Should reference type processing be disabled?
    // If reference type processing is disabled, no weak reference processing work is scheduled,
    // and we expect a binding to treat weak references as strong references.
    // We disable weak reference processing by default, as we are still working on it. This will be changed to `false`
    // once weak reference processing is implemented properly.
    no_reference_types:    bool                 [env_var: true, command_line: true]  [always_valid] = true,

@fepicture
Copy link
Contributor Author

Week 4

Short

I have verified the current option for reference and finalizer processing and understand the design of the rustcall and jtoc_call attribute/macro mechanisms.

Detail

Previously, when I heard that we wanted to directly call the jikesRVM processing function, JNI and FFI were the first things that came to mind. However, even JNI introduces a significant overhead. After investigating the jtoc_call macro, I found that it makes these things easier.

The jtoc_call macro, located in mmtk/src/jtoc_call.rs, is responsible for handling the Rust side calling jikesRVM side functions. Here is a quick example of its usage:

fn schedule_finalization(tls: VMWorkerThread) {
    unsafe {
        jtoc_call!(SCHEDULE_FINALIZER_METHOD_OFFSET, tls);
    }
}

The SCHEDULE_FINALIZER_METHOD_OFFSET is a constant automatically generated by RustJTOC.java, and the constant can be found in mmtk/src/entrypoint.rs.

To register a new method, you need to add a new item with the specific name in jikesrvm/rvm/src/org/jikesrvm/runtime/Entrypoints.java. The item parsing is done in repos/jikesrvm/rvm/src/org/jikesrvm/runtime/EntrypointHelper.java.

In EntrypointHelper::getMethod, the routing is done to EntrypointHelper::getMember, and the more detailed field and method parsing is done in repos/jikesrvm/rvm/src/org/jikesrvm/classloader/**.

RVMMethod.java is used to resolve the various data member identifiers.

Next week's plan

In our future expectations, the finalizer should be considered the same as a reference type for processing. I will copy the following code:

fn process_weak_refs(
    _worker: &mut GCWorker<VM>,
    _tracer_context: impl ObjectTracerContext<VM>,
) -> bool {
    false
}

and register the necessary function in jikesRVM through the tracer_context internal function, and solve any potential cases.

@fepicture
Copy link
Contributor Author

sorry for the late report. The best time to report is after the weekly sync meeting.

Week 5

Short Summary

  1. Added a backtrace and found the call chain to finalize the processor
  2. Conducted experiments to verify the GC mechanism

Details

Investigated the call chain for finalizing the processor

I previously added a throw backtrace on the Java side, and further, I noticed that we can simply use the IDE to search function symbols like sysAddFinalizer and sysGetFinalizedObject. For more details, I posted an analysis in the Notion doc here: https://obtainable-ninja-5fc.notion.site/code-read-weak-ref-95255e090767414198b92be1395eba0a

// repos/jikesrvm/rvm/src/org/jikesrvm/runtime/SysCall.java:428
  @Inline
  public void sysAddFinalizer(Object object) {
    add_finalizer(ObjectReference.fromObject(object));
  }
  @Inline
  public Object sysGetFinalizedObject() {
    return get_finalized_object().toObject();
  }

Experiments to verify GC mechanism

Basically, finalization means the object is no longer reachable by any mutator. The below while loop tries to ensure the soft reference has been processed, but this code has a bit of trickiness since we also implement the finalize() methods. I ran the jikesRVM multiple times, and the result is not the same - sometimes it will continue to iterate thousands of times, and sometimes only iterate very few times.

Click me
import java.lang.ref.SoftReference;

public class SoftReferenceTest {

    private static class BigObject {
        byte[] memoryEater = new byte[10 * 1024 * 1024]; // 10 MB

        @Override
        protected void finalize() throws Throwable {
            super.finalize();
            System.out.println("BigObject has been finalized");
        }
    }

    public static void main(String[] args) {
        BigObject obj = new BigObject();
        SoftReference<BigObject> softRef = new SoftReference<BigObject>(obj);

        obj = null;

        int counter = 0;

        // soft ref 
        
        while (softRef.get() != null) {
            System.out.println("Trying to create another BigObject: " + (++counter));
            try {
                BigObject anotherBigObject = new BigObject();
            } catch (OutOfMemoryError e) {
                System.out.println("OutOfMemoryError thrown!");
                break;
            }
        }

        System.out.println("Soft reference has been cleared after " + counter + " BigObject allocations");
    }
}

Next week plans

as talking previously, I will remove the rust route code and say we have to handle the relation, trace_local used in jikesRVM scanning, and trace_object in rust mmtk side.

if (hasFinalizer) {
--  if (VM.BuildWithRustMMTk) {
--    sysCall.sysAddFinalizer(newObj);
--  } else {
    MemoryManager.addFinalizer(newObj);
  }
}

the whole logic is

Click me
// mmtk-core/src/scheduler/gc_work.rs:392
impl<E: ProcessEdgesWork> GCWork<E::VM> for VMProcessWeakRefs<E> {
    fn do_work(&mut self, worker: &mut GCWorker<E::VM>, _mmtk: &'static MMTK<E::VM>) {
        trace!("VMProcessWeakRefs");

        let stage = WorkBucketStage::VMRefClosure;

        let need_to_repeat = {
            let tracer_factory = ProcessEdgesWorkTracerContext::<E> {
                stage,
                phantom_data: PhantomData,
            };
            <E::VM as VMBinding>::VMScanning::process_weak_refs(worker, tracer_factory) <== here call our impl
        };

        if need_to_repeat {
            // Schedule Self as the new sentinel so we'll call `process_weak_refs` again after the
            // current transitive closure.
            let new_self = Box::new(Self::new());

            worker.scheduler().work_buckets[stage].set_sentinel(new_self);
        }
    }
}

// mmtk/src/scanning.rs:62
impl Scanning<JikesRVM> for VMScanning {
 ....
      fn process_weak_refs(
        _worker: &mut GCWorker<JikesRVM>, // worker -> thread
        _tracer_context: impl ObjectTracerContext<JikesRVM>,
    ) -> bool {

        -> 
        {
            rust side -> call java side   <===== here we jump to java side process
           object {finalizablprocessor.scan()} <=== This relies on TraceLocal. we intend a conversion internally in TraceLocal.
            // also, need to check the global instance finalize processor whether has been registered.


        }
        false
    }
} 

@fepicture
Copy link
Contributor Author

fepicture commented Aug 17, 2023

Week 6

Short Summary

Completed integration of jtoc_call and RustSyscall interactions.

Details

For adding a jtoc_call:

We need to register a method in jikesrvm/rvm/src/org/jikesrvm/runtime/Entrypoints.java and pass a static method like below (swift):

// jikesrvm/rvm/src/org/jikesrvm/runtime/Entrypoints.java
  public static final NormalMethod swiftMethod = 
            getMethod(org.jikesrvm.mm.mminterface.MemoryManager.class, "swift", "()V");
            
// repos/jikesrvm/rvm/src/org/jikesrvm/mm/mminterface/MemoryManager.java
  @Entrypoint
  public static void swift() {
    VM.sysWriteln("[java] repos/j/rvm/src/org/j/mm/mminter/memorymanager.java:swift");
  }
  
// mmtk/src/collection.rs
    fn schedule_finalization(tls: VMWorkerThread) {
        unsafe {
            jtoc_call!(SWIFT_METHOD_OFFSET, tls); // the jtoc_call accepts `tls` as context.

            jtoc_call!(SCHEDULE_FINALIZER_METHOD_OFFSET, tls);
        }
    }

The jtoc_call accepts tls as the context.

For adding a RustSyscall:

Same as above, but needs extra extern declaration.

// repos/jikesrvm/rvm/src/org/jikesrvm/mm/mminterface/MemoryManager.java
  @Interruptible
  public static void addWeakReference(WeakReference<?> obj, Object referent) {
    if (VM.BuildWithRustMMTk) {
      sysCall.sysHellWorld(); // => this will switch to rust side. 
      sysCall.sysHelloWorld(); // => this function is registered in repos/jikesrvm/tools/bootloader/sysMMTk.c:8
    }


// repos/jikesrvm/rvm/src/org/jikesrvm/runtime/SysCall.java
  @Inline
  public void sysHellWorld() {
    hell_world();
  }

  @RustSysCall
  @SysCallTemplate
  public abstract void hell_world();

// repos/jikesrvm/rvm/src/org/jikesrvm/runtime/BootRecord.java
  public Address hell_worldRIP;
  
// mmtk/api/mmtk.h
  EXTERNAL void hell_world();
  
// mmtk/src/api.rs
  #[no_mangle]
  pub extern "C" fn hell_world() {
      println!("[rust] hell world from mmtk/src/api.rs:hell_world")
  }

Next Week Plans

As previously discussed, gcwork will call process_weak_refs in the VM impl. We need to switch to the Java side referenceprocessor/finalizerprocessor.scan(). Thus, I will try to make the scan method static and attempt to simplify the API.

@fepicture
Copy link
Contributor Author

Week 7

Short

I have attempted to implement Java and Rust interoperability for call interaction, but the API design needs revisiting.
mmtk/jikesrvm@master...fepicture:jikesrvm:refactor_finalize_processor

Detailed

The referenceprocessor/finalizerprocessor.scan() relies on tracelocal in jikesRVM. As we previously discussed, we want to implement the detailed logic in tracelocal so it can switch to Rust side functions (this is reasonable since the majority of tracelocal is not suitable for the new Rust side APIs). To enable code reuse, with the help of my mentor, I decided to create a high-level abstraction over tracelocal:

Current:

finalizerprocessor.scan(TraceLocal, boolean is_nursery)

Proposed change:

++ interface FinalizableProcessorTracer {
++  boolean isLive(ObjectReference object); // weak ref-> live dead undeterminde -> reachable
++  ObjectReference getForwardedFinalizable(ObjectReference object);  
++  ObjectReference retainForFinalize(ObjectReference object);
++ }

public abstract class TraceLocal extends TransitiveClosure implements FinalizableProcessorTracer {

public final class RustTraceLocal implements FinalizableProcessorTracer {

I now need to implement the 3 API usages in jikesRVM. More specifically, I need to call Rust and return to Java safely and correctly. trace_object needs a tracer, and passing *mut libc::c_void requires a way to keep the cast working properly. I may reference this usage: https://github.com/mmtk/mmtk-openjdk/blob/129c88905c39fb4167dd25ed299cc2abd8c09572/mmtk/src/scanning.rs#L26C13-L26C20

Next Week Plan

Implement the 3 calls and complete basic verification tests.

@fepicture
Copy link
Contributor Author

Week 8

This week I am busy with my work. Working overtime in the office to deliver an urgent product to the customer :<

@fepicture
Copy link
Contributor Author

Week 9

Short

This week, I have done pretests from my mentor which are intended to help me implement pointer conversion without losing type information. I also took some time to review the PR https://github.com/mmtk/mmtk-jikesrvm/pull/114/files.

Detailed

In our expected scenario, we currently have to implement retainforfinalizer, which requests trace_object(tracer, ref) in this style. The problem now is how can we correctly do the trace_object. I intend to use the same approach as in sysCall.sysDynamicCall_k, thus that JikesRVM will not be aware of the callback's existence.

Below is a snippet from the repo: https://github.com/fepicture/c-rust

// https://github.com/fepicture/c-rust/blob/3d97607325b35820593aed64243b32a874c3e778/src/main.rs#L38-L55

extern "C" fn closure_internal<F: FnMut(i32)>(num: i32, closure: *mut c_void) {
    let closure: &mut F = unsafe { &mut *(closure as *mut F) };
    closure(num); // here do the closure, this is same in sysDynamicCall
}

extern "C" fn for_each_number<F: FnMut(i32)>(mut closure: F) {
    let closure_ptr: *mut c_void = &mut closure as *mut F as *mut c_void;
    unsafe { for_each_interesting_number(closure_internal::<F>, closure_ptr) };
}

fn pretest3_callback_from_callback() {
    println!("\nbelow is pretest3_callback_from_callback");

    for_each_number(|num| {
        println!("Received number: {}", num);
    });
}

next week plan

Take more time in finalizer, and try to finish it ASAP

@fepicture
Copy link
Contributor Author

Week 10

Short

I've completed the first take on the finalizer replacement. It currently passes my simple test, but I still have some questions.
er

Detailed

After conducting the pretest as previously discussed, I gained a deeper understanding of type conversion. Following the steps mentioned above, I utilized sysDynamicCall2 in JikesRVM to trace_object. Everything seems to be functioning as expected. However, I encountered a blockage at ObjectTracerContext::TracerType. I do not find a simple and valid way to make compiler know the typeinfo.

// /root/.cargo/git/checkouts/mmtk-core-3306bdeb8eb4322b/269408b/src/vm/scanning.rs:50
pub trait ObjectTracerContext<VM: VMBinding>: Clone + Send + 'static {
    /// The concrete `ObjectTracer` type.
    ///
    /// FIXME: The current code functions due to the unsafe method `ProcessEdgesWork::set_worker`.
    /// The tracer should borrow the worker passed to `with_queuing_tracer` during its lifetime.
    /// For this reason, `TracerType` should have a `<'w>` lifetime parameter.
    /// Generic Associated Types (GAT) was stabilized in Rust 1.65.
    /// We should consider updating our toolchain version.
    type TracerType: ObjectTracer;

Currently, I am passing the type info into another function outside of the implementation, as shown below:

// https://github.com/fepicture/mmtk-jikesrvm/blob/ee1e732f47c74520d313dd6777ba898e16881d2c/mmtk/src/scanning.rs#L182-L207
impl Scanning<JikesRVM> for VMScanning {
    fn process_weak_refs(
        _worker: &mut GCWorker<JikesRVM>,
        _tracer_context: impl ObjectTracerContext<JikesRVM>,
    ) -> bool {
        process_weak_refs_inner(_worker, _tracer_context)
    }
}

fn process_weak_refs_inner<C>(_worker: &mut GCWorker<JikesRVM>, _tracer_context: C) -> bool
where
    C: ObjectTracerContext<JikesRVM>,
{
    let tls = _worker.tls;
    _tracer_context.with_tracer(_worker, |tracer| {
        unsafe {
            jtoc_call!(
                DO_FINALIZABLE_PROCESSOR_SCAN_METHOD_OFFSET,
                tls,
                trace_object_callback_for_jikesrvm::<C::TracerType>,
                tracer as *mut _ as *mut libc::c_void,
                0
            );
        }
    });
    false
}

Next Week

I'll investigate the cause of this semispace error report and address the issue with the nursery (currently, we're passing false to skip this variable).

@fepicture
Copy link
Contributor Author

fepicture commented Sep 23, 2023

update v1: add need_retain is_nursery source

Week 11

Short

I resolved last week's error by increasing the maximum heap allocation (-Xmx). Additionally, I began foundational work on merging the reference processor and finalizer processor functionalities.

Detailed

While running the test suite in ci-test-wek-ref.sh, I encountered an "Out of Memory" error. As mentioned above, this issue was rectified by augmenting the heap memory allocation. Notably, the lusearch test suite ran successfully without requiring any modifications. The jython test suite also passed once I expanded the allocated memory to -Xmx300M (using the semispace configuration). As of now, all test suites have passed successfully.

Regarding the merger of functionalities, I examined JikesRVM's handling of the reference processor more closely. The three types of references are founded on the same class, necessitating a state machine-like approach to navigate through the four types based on their reference strength. This can be executed either on the Java side or on the Rust side.

  private static final ReferenceProcessor softReferenceProcessor =
    new ReferenceProcessor(Semantics.SOFT);
  private static final ReferenceProcessor weakReferenceProcessor =
    new ReferenceProcessor(Semantics.WEAK);
  private static final ReferenceProcessor phantomReferenceProcessor =
    new ReferenceProcessor(Semantics.PHANTOM);

To meet the requirements of referenceprocessor.scan(), I updated the higher-level API for RustTraceLocal as follows:

public interface FinalizableProcessorTracer {
  boolean isLive(ObjectReference object); // From weak ref -> live/dead undetermined -> reachable
  ObjectReference getForwardedFinalizable(ObjectReference object);
  ObjectReference getForwardedReferent(ObjectReference object);
  ObjectReference getForwardedReference(ObjectReference object);
  ObjectReference retainReferent(ObjectReference object);
  ObjectReference retainForFinalize(ObjectReference object);
}

Plans for Next Week

I aim to continue working on integrating the four types of references.
the scan method needs is_nursery and need_retain two extra status.
is_nursery can be found in

    mmtk
            .get_plan()
            .generational()
            .unwrap()
            .is_current_gc_nursery() 

need_retain is refer to the soft reference, we can track is_emergency_collection in mmtk-core/src/plan/global.rs

    fn is_emergency_collection(&self) -> bool {
      self.base().emergency_collection.load(Ordering::Relaxed)
  }

retain will try to keep the context in memory. if is not is_emergency_collection, means there’s a lot of free heap space, objects, especially those wrapped in soft references, can be retained longer.

@fepicture
Copy link
Contributor Author

Week 12

Brief Overview

Presently, the PR is ready for review. I have developed a delegator class that utilizes an enum as its internal phase and iterates as the reference strengthening works, functioning like a state machine. However, I needed to increase the maximum heap usage to ensure the Dacapo test suite passes. CI is failing since the jikesrvm code has not been merged (ummm..). Perhaps I should utilize conditional compilation?

Detailed Explanation

mmtk-jikesrvm

Modifications to the mmtk-jikesrvm repository encompass three key aspects:

  1. Removal/Movement: I have removed some old bind APIs, marking them as unimplement, or directly removing them.
  2. Implementation: I implemented the process_weak_ref and forward_weak_ref methods. These will be invoked in the work bucket and act as an entry point for the original process in jikesrvm.
  3. Configuration Update: Lastly, the CI heap configuration has been updated.

jikesrvm

The changes in the jikesrvm repository are somewhat more extensive. To summarize, we initiate from the Rust MMTk side entry, which proceeds into a static method by upcall. This static method is designed to navigate to the specific reference processor scan method.

// mmtk/src/scanning.rs:220
tracer_context.with_tracer(worker, |tracer| unsafe {
    scan_result = jtoc_call!(
        DO_REFERENCE_PROCESSOR_DELEGATOR_SCAN_METHOD_OFFSET,
        tls,
        trace_object_callback_for_jikesrvm::<C::TracerType>,
        tracer as *mut _ as *mut libc::c_void,
        is_nursery as i32,
        need_retain as i32
    );
});
// rvm/src/org/jikesrvm/mm/mminterface/MemoryManager.java:1208
@Entrypoint
public static boolean doReferenceProcessorDelegatorScan(Address traceObjectCallback, Address tracer, boolean isNursery, boolean needRetain) {
    return org.mmtk.vm.VM.referenceProcessorDelegator.scan(traceObjectCallback, tracer, isNursery, needRetain);
}
// MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/ReferenceProcessorDelegator.java:88
@Override
@UninterruptibleNoWarn
public boolean scan(Address traceObjectCallback, Address tracer, boolean isNursery, boolean needRetain) {
    RustTraceLocal trace = new RustTraceLocal(traceObjectCallback, tracer);

    if (phaseId == Phase.PREPARE) {
        phaseId = Phase.SOFT_REFS;
    }

    if (phaseId == Phase.SOFT_REFS) {
        org.mmtk.vm.VM.softReferences.scan(trace, isNursery, needRetain);
        phaseId = Phase.WEAK_REFS;
        return true;
    } else if (phaseId == Phase.WEAK_REFS) {
        org.mmtk.vm.VM.weakReferences.scan(trace, isNursery, needRetain);
        phaseId = Phase.FINALIZABLE;
        return true;
    } else if (phaseId == Phase.FINALIZABLE) {
        org.mmtk.vm.VM.finalizableProcessor.scan(trace, isNursery);
        phaseId = Phase.PHANTOM_REFS;
        return true;
    } else if (phaseId == Phase.PHANTOM_REFS) {
        org.mmtk.vm.VM.phantomReferences.scan(trace, isNursery, needRetain);
        phaseId = Phase.PREPARE;
        return false;
    } else {
        VM.sysFail("unreachable");
        return false;
    }
}

@wks wks closed this as completed in #150 Oct 25, 2023
wks added a commit that referenced this issue Oct 25, 2023
_edit v1: sync latest status, i have finish the reference processor and
integrate together._
_edit v2: update with binding PR link._

fix #145 
mmtk-jikesrvm PR #150
jikesRVM PR mmtk/jikesrvm#16

Modifications to the mmtk-jikesrvm repository encompass three key
aspects:

1. I have removed some old bind APIs, marking them as unimplement, or
directly removing them.
2. I implemented the process_weak_ref and forward_weak_ref methods.
These will be invoked in the work bucket and act as an entry point for
the original process in jikesrvm.
3. Lastly, the CI heap configuration has been updated.

---------

Co-authored-by: Yi Lin <qinsoon@gmail.com>
Co-authored-by: Kunshan Wang <wks1986@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant