Skip to content

Commit b6ff1e0

Browse files
authored
Properly handle OOM error (#136)
1 parent 7734d3e commit b6ff1e0

File tree

7 files changed

+44
-8
lines changed

7 files changed

+44
-8
lines changed

mmtk/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ lazy_static = "1.1"
2020
# - change branch
2121
# - change repo name
2222
# But other changes including adding/removing whitespaces in commented lines may break the CI.
23-
mmtk = { git = "https://github.com/mmtk/mmtk-core.git", rev = "29afb0c2fc8896db95e967062a892d39589bae4d" }
23+
mmtk = { git = "https://github.com/mmtk/mmtk-core.git", rev = "c38365be73e83dfd8a41e901d4537e87e0eb0ffe" }
2424
# Uncomment the following to build locally
2525
# mmtk = { path = "../repos/mmtk-core" }
2626

mmtk/src/collection.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use mmtk::scheduler::WorkBucketStage;
22
use mmtk::scheduler::{ProcessEdgesWork, ScanStackRoot};
3+
use mmtk::util::alloc::AllocationError;
34
use mmtk::util::opaque_pointer::*;
45
use mmtk::vm::{Collection, GCThreadContext, Scanning, VMBinding};
56
use mmtk::{Mutator, MutatorContext};
@@ -75,6 +76,12 @@ impl Collection<OpenJDK> for VMCollection {
7576
// unimplemented!()
7677
}
7778

79+
fn out_of_memory(tls: VMThread, err_kind: AllocationError) {
80+
unsafe {
81+
((*UPCALLS).out_of_memory)(tls, err_kind);
82+
}
83+
}
84+
7885
fn schedule_finalization(_tls: VMWorkerThread) {
7986
unsafe {
8087
((*UPCALLS).schedule_finalizer)();

mmtk/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ extern crate lazy_static;
1313
use std::ptr::null_mut;
1414

1515
use libc::{c_char, c_void, uintptr_t};
16+
use mmtk::util::alloc::AllocationError;
1617
use mmtk::util::opaque_pointer::*;
1718
use mmtk::util::{Address, ObjectReference};
1819
use mmtk::vm::VMBinding;
@@ -46,6 +47,7 @@ pub struct OpenJDK_Upcalls {
4647
pub resume_mutators: extern "C" fn(tls: VMWorkerThread),
4748
pub spawn_gc_thread: extern "C" fn(tls: VMThread, kind: libc::c_int, ctx: *mut libc::c_void),
4849
pub block_for_gc: extern "C" fn(),
50+
pub out_of_memory: extern "C" fn(tls: VMThread, err_kind: AllocationError),
4951
pub get_next_mutator: extern "C" fn() -> *mut Mutator<OpenJDK>,
5052
pub reset_mutator_iterator: extern "C" fn(),
5153
pub compute_static_roots: extern "C" fn(trace: *mut c_void, tls: OpaquePointer),

openjdk/mmtk.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ extern "C" {
1212
typedef void* MMTk_Mutator;
1313
typedef void* MMTk_TraceLocal;
1414

15+
// This has the same layout as mmtk::util::alloc::AllocationError
16+
typedef enum {
17+
HeapOutOfMemory,
18+
MmapOutOfMemory,
19+
} MMTkAllocationError;
20+
1521
extern const uintptr_t GLOBAL_SIDE_METADATA_BASE_ADDRESS;
1622
extern const uintptr_t GLOBAL_SIDE_METADATA_VM_BASE_ADDRESS;
1723
extern const uintptr_t GLOBAL_ALLOC_BIT_ADDRESS;
@@ -102,6 +108,7 @@ typedef struct {
102108
void (*resume_mutators) (void *tls);
103109
void (*spawn_collector_thread) (void *tls, int kind, void *ctx);
104110
void (*block_for_gc) ();
111+
void (*out_of_memory) (void *tls, MMTkAllocationError err_kind);
105112
void* (*get_next_mutator) ();
106113
void (*reset_mutator_iterator) ();
107114
void (*compute_static_roots) (void* trace, void* tls);

openjdk/mmtkHeap.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ jint MMTkHeap::initialize() {
114114

115115
_companion_thread = new MMTkVMCompanionThread();
116116
if (!os::create_thread(_companion_thread, os::pgc_thread)) {
117-
printf("Failed to create thread");
117+
fprintf(stderr, "Failed to create thread");
118118
guarantee(false, "panic");
119119
}
120120
os::start_thread(_companion_thread);
@@ -503,9 +503,6 @@ void MMTkHeap::scan_roots(OopClosure& cl) {
503503

504504
HeapWord* MMTkHeap::mem_allocate(size_t size, bool* gc_overhead_limit_was_exceeded) {
505505
HeapWord* obj = Thread::current()->third_party_heap_mutator.alloc(size << LogHeapWordSize);
506-
// post_alloc(Thread::current()->mmtk_mutator(), obj_ptr, NULL, size << LogHeapWordSize, 0);
507-
// printf("offset: %ld\n", ((size_t) &Thread::current()->third_party_heap_mutator) - ((size_t) Thread::current()));
508-
guarantee(obj, "MMTk gave us null!");
509506
return obj;
510507
}
511508

openjdk/mmtkMutator.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@ HeapWord* MMTkMutatorContext::alloc(size_t bytes, Allocator allocator) {
1919

2020
// FIXME: Proper use of slow-path api
2121
HeapWord* o = (HeapWord*) ::alloc((MMTk_Mutator) this, bytes, HeapWordSize, 0, allocator);
22-
// Post allococation. Currently we are only calling post_alloc in slowpath here.
23-
// TODO: We also need to call them in the fastpath.
24-
::post_alloc((MMTk_Mutator) this, o, bytes, allocator);
22+
// Post allocation hooks. Note that we can get a nullptr from mmtk core in the case of OOM.
23+
// Hence, only call post allocation hooks if we have a proper object.
24+
if (o != nullptr) {
25+
::post_alloc((MMTk_Mutator) this, o, bytes, allocator);
26+
}
2527
return o;
2628
}
2729

openjdk/mmtkUpcalls.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "runtime/thread.hpp"
4040
#include "runtime/threadSMR.hpp"
4141
#include "runtime/vmThread.hpp"
42+
#include "utilities/debug.hpp"
4243

4344
static size_t mmtk_start_the_world_count = 0;
4445

@@ -131,6 +132,25 @@ static void mmtk_block_for_gc() {
131132
log_debug(gc)("Thread (id=%d) resumed after GC finished.", Thread::current()->osthread()->thread_id());
132133
}
133134

135+
static void mmtk_out_of_memory(void* tls, MMTkAllocationError err_kind) {
136+
switch (err_kind) {
137+
case HeapOutOfMemory :
138+
// Note that we have to do nothing for the case that the Java heap is too small. Since mmtk-core already
139+
// returns a nullptr back to the JVM, it automatically triggers an OOM exception since the JVM checks for
140+
// OOM every (slowpath) allocation [1]. In fact, if we report and throw an OOM exception here, the VM will
141+
// complain since a pending exception bit was already set when it was trying to check for OOM [2]. Hence,
142+
// it is best to let the JVM take care of reporting OOM itself.
143+
//
144+
// [1]: https://github.com/mmtk/openjdk/blob/e4dbe9909fa5c21685a20a1bc541fcc3b050dac4/src/hotspot/share/gc/shared/memAllocator.cpp#L83
145+
// [2]: https://github.com/mmtk/openjdk/blob/e4dbe9909fa5c21685a20a1bc541fcc3b050dac4/src/hotspot/share/gc/shared/memAllocator.cpp#L117
146+
break;
147+
case MmapOutOfMemory :
148+
// Abort the VM immediately due to insufficient system resources.
149+
vm_exit_out_of_memory(0, OOM_MMAP_ERROR, "MMTk: Unable to acquire more memory from the OS. Out of system resources.");
150+
break;
151+
}
152+
}
153+
134154
static void* mmtk_get_mmtk_mutator(void* tls) {
135155
return (void*) &((Thread*) tls)->third_party_heap_mutator;
136156
}
@@ -304,6 +324,7 @@ OpenJDK_Upcalls mmtk_upcalls = {
304324
mmtk_resume_mutators,
305325
mmtk_spawn_collector_thread,
306326
mmtk_block_for_gc,
327+
mmtk_out_of_memory,
307328
mmtk_get_next_mutator,
308329
mmtk_reset_mutator_iterator,
309330
mmtk_compute_static_roots,

0 commit comments

Comments
 (0)