This commit is contained in:
dcode
2019-03-27 14:43:35 +01:00
parent 3146f8f9e0
commit bb1609c9ea
91 changed files with 6426 additions and 11009 deletions

View File

@ -7,7 +7,7 @@ Common
------
* **__ref_collect**()<br />
Triggers a full garbage collection cycle.
Triggers a full garbage collection cycle. Also indicates the presence of a GC.
Tracing
-------
@ -24,14 +24,15 @@ Tracing
Reference counting
------------------
* **__ref_register**(ref: `usize`)<br />
Sets up a new reference. Implementation is optional for reference counting GCs.
* **__ref_retain**(ref: `usize`)<br />
Retains a reference, usually incrementing RC.
* **__ref_release**(ref: `usize`)<br />
Releases a reference, usually decrementing RC.
Reference counting may also implement `__ref_register` if necessary.
Typical patterns
----------------

View File

@ -1,8 +1,8 @@
// A dummy GC for looking at generated GC code without actually implementing it.
// A tracing dummy GC.
// @ts-ignore: decorator
@inline
const TRACE = false;
const TRACE = isDefined(GC_TRACE);
// @ts-ignore: decorator
@global @unsafe
@ -29,17 +29,3 @@ function __ref_link(ref: usize, parentRef: usize): void {
function __ref_unlink(ref: usize, parentRef: usize): void {
if (TRACE) trace("dummy.unlink", 2, ref, parentRef);
}
// Reference counting
// // @ts-ignore: decorator
// @global @unsafe
// function __ref_retain(ref: usize): void {
// if (TRACE) trace("dummy.retain", 1, ref);
// }
// // @ts-ignore: decorator
// @global @unsafe
// function __ref_release(ref: usize): void {
// if (TRACE) trace("dummy.release", 1, ref);
// }

View File

@ -0,0 +1,29 @@
// A reference counting dummy GC.
// @ts-ignore: decorator
@inline
const TRACE = isDefined(GC_TRACE);
// @ts-ignore: decorator
@global @unsafe
function __ref_register(ref: usize): void {
if (TRACE) trace("dummyrc.register", 1, ref);
}
// @ts-ignore: decorator
@global @unsafe
function __ref_collect(): void {
if (TRACE) trace("dummyrc.collect");
}
// @ts-ignore: decorator
@global @unsafe
function __ref_retain(ref: usize): void {
if (TRACE) trace("dummyrc.retain", 1, ref);
}
// @ts-ignore: decorator
@global @unsafe
function __ref_release(ref: usize): void {
if (TRACE) trace("dummyrc.release", 1, ref);
}

View File

@ -4,7 +4,7 @@
@inline
const TRACE = false;
import { ITERATEROOTS, HEADER_SIZE } from "../runtime";
import { iterateRoots, HEADER_SIZE } from "../runtime";
/** Collector states. */
const enum State {
@ -141,7 +141,7 @@ function step(): void {
}
case State.IDLE: {
if (TRACE) trace("gc~step/IDLE");
ITERATEROOTS((ref: usize): void => {
iterateRoots((ref: usize): void => {
var obj = refToObj(ref);
if (obj.color == white) obj.makeGray();
});
@ -165,7 +165,7 @@ function step(): void {
obj.hookFn(objToRef(obj));
} else {
if (TRACE) trace("gc~step/MARK finish");
ITERATEROOTS((ref: usize): void => {
iterateRoots((ref: usize): void => {
var obj = refToObj(ref);
if (obj.color == white) obj.makeGray();
});

View File

@ -39,12 +39,12 @@ export const HEADER_MAGIC: u32 = 0xA55E4B17;
/** Gets the computed unique class id of a class type. */
// @ts-ignore: decorator
@unsafe @builtin
export declare function CLASSID<T>(): u32;
export declare function classId<T>(): u32;
/** Iterates over all root objects of a reference type. */
// @ts-ignore: decorator
@unsafe @builtin
export declare function ITERATEROOTS(fn: (ref: usize) => void): void;
export declare function iterateRoots(fn: (ref: usize) => void): void;
/** Adjusts an allocation to actual block size. Primarily targets TLSF. */
export function ADJUSTOBLOCK(payloadSize: usize): usize {
@ -78,16 +78,6 @@ function allocate(payloadSize: usize): usize {
return changetype<usize>(header) + HEADER_SIZE;
}
/**
* Allocates an unmanaged struct-like object. This is used by the compiler as an abstraction
* to memory.allocate just in case, and is usually not used directly.
*/
// @ts-ignore: decorator
@unsafe @inline
export function ALLOCATE_UNMANAGED(size: usize): usize {
return memory.allocate(size);
}
/**
* Changes the size of a previously allocated, but not yet registered, runtime object, for
* example when a pre-allocated buffer turned out to be too small or too large. This works by
@ -153,7 +143,7 @@ function reallocate(ref: usize, newPayloadSize: usize): usize {
@unsafe @inline
export function REGISTER<T>(ref: usize): T {
if (!isReference<T>()) ERROR("reference expected");
return changetype<T>(register(ref, CLASSID<T>()));
return changetype<T>(register(ref, classId<T>()));
}
function register(ref: usize, classId: u32): usize {
@ -199,13 +189,13 @@ function discard(ref: usize): void {
// @ts-ignore: decorator
@unsafe @inline
export function MAKEARRAY<V>(capacity: i32, source: usize = 0): Array<V> {
return changetype<Array<V>>(makeArray(capacity, source, CLASSID<V[]>(), alignof<V>()));
return changetype<Array<V>>(makeArray(capacity, classId<V[]>(), alignof<V>(), source));
}
function makeArray(capacity: i32, source: usize, classId: u32, alignLog2: usize): usize {
var array = register(allocate(offsetof<i32[]>()), classId);
function makeArray(capacity: i32, cid: u32, alignLog2: usize, source: usize): usize {
var array = register(allocate(offsetof<i32[]>()), cid);
var bufferSize = <usize>capacity << alignLog2;
var buffer = register(allocate(<usize>capacity << alignLog2), CLASSID<ArrayBuffer>());
var buffer = register(allocate(<usize>capacity << alignLog2), classId<ArrayBuffer>());
changetype<ArrayBufferView>(array).data = changetype<ArrayBuffer>(buffer); // links
changetype<ArrayBufferView>(array).dataStart = buffer;
changetype<ArrayBufferView>(array).dataLength = bufferSize;