@@ -72,7 +72,7 @@ pub fn destroy(self: *Self) void {
72
72
}
73
73
74
74
fn init (self : * Self , allocator : Allocator , vm : * VirtualMachine ) ! void {
75
- var old_space = try Space .init (self , allocator , "old space" , InitialOldSpaceSize );
75
+ var old_space = Space .lazyInit (self , "old space" , InitialOldSpaceSize );
76
76
errdefer old_space .deinit (allocator );
77
77
78
78
var from_space = try Space .init (self , allocator , "from space" , NewSpaceSize );
@@ -101,13 +101,6 @@ fn init(self: *Self, allocator: Allocator, vm: *VirtualMachine) !void {
101
101
self .from_space .scavenge_target = & self .to_space ;
102
102
self .from_space .tenure_target = & self .old_space ;
103
103
self .eden .tenure_target = & self .from_space ;
104
-
105
- if (GC_DEBUG ) {
106
- std .debug .print ("Heap.init: Eden is {*}-{*}\n " , .{ self .eden .memory .ptr , self .eden .memory .ptr + self .eden .memory .len });
107
- std .debug .print ("Heap.init: From space is {*}-{*}\n " , .{ self .from_space .memory .ptr , self .from_space .memory .ptr + self .from_space .memory .len });
108
- std .debug .print ("Heap.init: To space is {*}-{*}\n " , .{ self .to_space .memory .ptr , self .to_space .memory .ptr + self .to_space .memory .len });
109
- std .debug .print ("Heap.init: Old space is {*}-{*}\n " , .{ self .old_space .memory .ptr , self .old_space .memory .ptr + self .old_space .memory .len });
110
- }
111
104
}
112
105
113
106
fn deinit (self : * Self ) void {
@@ -294,13 +287,18 @@ const Space = struct {
294
287
/// A reference back to the heap.
295
288
heap : * Self ,
296
289
290
+ /// If true, then memory is undefined, and the next time an allocation is
291
+ /// requested the memory space should be allocated.
292
+ lazy_allocate : bool = true ,
293
+ /// The size of this memory space.
294
+ size : usize ,
297
295
/// The raw memory contents of the space. The space capacity can be learned
298
- /// with `memory.len`.
299
- memory : []u64 ,
296
+ /// with `memory.len`. Uninitialized while `lazy_allocate` is true.
297
+ memory : []u64 = undefined ,
300
298
/// A slice of the current object segment in this space.
301
- object_segment : []u64 ,
299
+ object_segment : []u64 = undefined ,
302
300
/// A slice of the current byte array segment in this space.
303
- byte_array_segment : []u64 ,
301
+ byte_array_segment : []u64 = undefined ,
304
302
/// The set of objects which reference an object in this space. When a
305
303
/// constant or assignable slot from a previous space references this space,
306
304
/// it is added to this set; when it starts referencing another space, it is
@@ -347,27 +345,43 @@ const Space = struct {
347
345
previous : ? * const NewerGenerationLink ,
348
346
};
349
347
348
+ pub fn lazyInit (heap : * Self , comptime name : [* :0 ]const u8 , size : usize ) Space {
349
+ return Space {
350
+ .heap = heap ,
351
+ .name = name ,
352
+ .size = size ,
353
+ .remembered_set = .{},
354
+ .finalization_set = .{},
355
+ .tracked_set = .{},
356
+ };
357
+ }
358
+
350
359
pub fn init (heap : * Self , allocator : Allocator , comptime name : [* :0 ]const u8 , size : usize ) ! Space {
351
- var memory = try allocator .alloc (u64 , size / @sizeOf (u64 ));
360
+ var self = lazyInit (heap , name , size );
361
+ try self .allocateMemory (allocator );
362
+ return self ;
363
+ }
364
+
365
+ fn allocateMemory (self : * Space , allocator : Allocator ) ! void {
366
+ var memory = try allocator .alloc (u64 , @divExact (self .size , @sizeOf (u64 )));
352
367
353
368
// REVIEW: When Zig fixes its zero-length arrays to not create a slice
354
369
// with an undefined address, get rid of this and just use
355
370
// memory[0..0].
356
371
var runtime_zero : usize = 0 ;
357
372
358
- return Space {
359
- .heap = heap ,
360
- .memory = memory ,
361
- .object_segment = memory [0.. runtime_zero ],
362
- .byte_array_segment = (memory .ptr + memory .len )[0.. runtime_zero ],
363
- .remembered_set = .{},
364
- .finalization_set = .{},
365
- .tracked_set = .{},
366
- .name = name ,
367
- };
373
+ self .lazy_allocate = false ;
374
+ self .memory = memory ;
375
+ self .object_segment = memory [0.. runtime_zero ];
376
+ self .byte_array_segment = (memory .ptr + memory .len )[0.. runtime_zero ];
377
+
378
+ if (GC_DEBUG ) std .debug .print ("Heap.init: {s} is {*}-{*}\n " , .{ self .name , self .memory .ptr , self .memory .ptr + self .memory .len });
368
379
}
369
380
370
381
pub fn deinit (self : * Space , allocator : Allocator ) void {
382
+ if (self .lazy_allocate )
383
+ return ;
384
+
371
385
// Finalize everything that needs to be finalized.
372
386
var finalization_it = self .finalization_set .iterator ();
373
387
while (finalization_it .next ()) | entry | {
@@ -741,6 +755,9 @@ const Space = struct {
741
755
/// Allocates the requested amount in bytes in the object segment of this
742
756
/// space, garbage collecting if there is not enough space.
743
757
pub fn allocateInObjectSegment (self : * Space , allocator : Allocator , size : usize ) ! [* ]u64 {
758
+ if (self .lazy_allocate )
759
+ try self .allocateMemory (allocator );
760
+
744
761
if (self .freeMemory () < size ) try self .collectGarbage (allocator , size );
745
762
746
763
const size_in_words = @divExact (size , @sizeOf (u64 ));
@@ -757,6 +774,9 @@ const Space = struct {
757
774
/// Allocates the requested amount in bytes in the byte vector segment of
758
775
/// this space, garbage collecting if there is not enough space.
759
776
pub fn allocateInByteVectorSegment (self : * Space , allocator : Allocator , size : usize ) ! [* ]u64 {
777
+ if (self .lazy_allocate )
778
+ try self .allocateMemory (allocator );
779
+
760
780
if (self .freeMemory () < size ) try self .collectGarbage (allocator , size );
761
781
762
782
const size_in_words = @divExact (size , @sizeOf (u64 ));
0 commit comments