make ref_unlink optional and itcm pass a simple test again

note: there's no marking yet
This commit is contained in:
dcode 2019-03-29 18:56:32 +01:00
parent a3aa9a3961
commit 6a790321aa
15 changed files with 5445 additions and 89 deletions

View File

@ -4041,6 +4041,7 @@ export function compileIterateRoots(compiler: Compiler): void {
var exprs = new Array<ExpressionRef>(); var exprs = new Array<ExpressionRef>();
var typeName = Signature.makeSignatureString([ Type.i32 ], Type.void); var typeName = Signature.makeSignatureString([ Type.i32 ], Type.void);
var typeRef = compiler.ensureFunctionType([ Type.i32 ], Type.void); var typeRef = compiler.ensureFunctionType([ Type.i32 ], Type.void);
var nativeSizeType = compiler.options.nativeSizeType;
for (let element of compiler.program.elementsByName.values()) { for (let element of compiler.program.elementsByName.values()) {
if (element.kind != ElementKind.GLOBAL) continue; if (element.kind != ElementKind.GLOBAL) continue;
@ -4053,34 +4054,39 @@ export function compileIterateRoots(compiler: Compiler): void {
) { ) {
if (global.is(CommonFlags.INLINED)) { if (global.is(CommonFlags.INLINED)) {
let value = global.constantIntegerValue; let value = global.constantIntegerValue;
exprs.push( if (i64_low(value) || i64_high(value)) {
module.createCallIndirect( exprs.push(
module.createGetLocal(0, NativeType.I32), module.createCallIndirect(
[ module.createGetLocal(0, NativeType.I32),
compiler.options.isWasm64 [
? module.createI64(i64_low(value), i64_high(value)) compiler.options.isWasm64
: module.createI32(i64_low(value)) ? module.createI64(i64_low(value), i64_high(value))
], : module.createI32(i64_low(value))
typeName ],
) typeName
); )
);
}
} else { } else {
exprs.push( exprs.push(
module.createCallIndirect( module.createIf(
module.createGetLocal(0, NativeType.I32), module.createTeeLocal(
[ 1,
module.createGetGlobal( module.createGetGlobal(global.internalName, nativeSizeType)
global.internalName, ),
compiler.options.nativeSizeType module.createCallIndirect(
) module.createGetLocal(0, NativeType.I32),
], [
typeName module.createGetLocal(1, nativeSizeType)
],
typeName
)
) )
); );
} }
} }
} }
module.addFunction("~iterateRoots", typeRef, [], module.addFunction("~iterateRoots", typeRef, [ nativeSizeType ],
exprs.length exprs.length
? module.createBlock(null, exprs) ? module.createBlock(null, exprs)
: module.createNop() : module.createNop()

View File

@ -8240,16 +8240,17 @@ export class Compiler extends DiagnosticEmitter {
var flow = this.currentFlow; var flow = this.currentFlow;
var tempValue = flow.getTempLocal(usizeType, false); var tempValue = flow.getTempLocal(usizeType, false);
var tempOldValue = flow.getTempLocal(usizeType, false); var tempOldValue = flow.getTempLocal(usizeType, false);
var handleOld: ExpressionRef; var handleOld: ExpressionRef = 0;
var handleNew: ExpressionRef; var handleNew: ExpressionRef;
var fn1: Function | null, fn2: Function | null; var fn1: Function | null, fn2: Function | null;
if (fn1 = program.linkRef) { // tracing if (fn1 = program.linkRef) { // tracing
tempParent = assert(tempParent); tempParent = assert(tempParent);
fn2 = assert(program.unlinkRef); if (fn2 = program.unlinkRef) {
handleOld = module.createCall(fn2.internalName, [ handleOld = module.createCall(fn2.internalName, [
module.createGetLocal(tempOldValue.index, nativeSizeType), module.createGetLocal(tempOldValue.index, nativeSizeType),
module.createGetLocal(tempParent.index, nativeSizeType) module.createGetLocal(tempParent.index, nativeSizeType)
], NativeType.None); ], NativeType.None);
}
handleNew = module.createCall(fn1.internalName, [ handleNew = module.createCall(fn1.internalName, [
module.createGetLocal(tempValue.index, nativeSizeType), module.createGetLocal(tempValue.index, nativeSizeType),
module.createGetLocal(tempParent.index, nativeSizeType) module.createGetLocal(tempParent.index, nativeSizeType)
@ -8268,7 +8269,8 @@ export class Compiler extends DiagnosticEmitter {
} }
flow.freeTempLocal(tempValue); flow.freeTempLocal(tempValue);
flow.freeTempLocal(tempOldValue); flow.freeTempLocal(tempOldValue);
if (!this.compileFunction(fn1) || !this.compileFunction(fn2)) return module.createUnreachable(); if (!this.compileFunction(fn1)) return module.createUnreachable();
if (fn2 && !this.compileFunction(fn2)) return module.createUnreachable();
// if (value != oldValue) { // if (value != oldValue) {
// if (oldValue !== null) unlink/release(oldValue[, parent]) // if (oldValue !== null) unlink/release(oldValue[, parent])
// [if (value !== null)] link/retain(value[, parent]) // [if (value !== null)] link/retain(value[, parent])
@ -8279,10 +8281,12 @@ export class Compiler extends DiagnosticEmitter {
module.createTeeLocal(tempOldValue.index, oldValueExpr) module.createTeeLocal(tempOldValue.index, oldValueExpr)
), ),
module.createBlock(null, [ module.createBlock(null, [
module.createIf( handleOld
module.createGetLocal(tempOldValue.index, nativeSizeType), ? module.createIf(
handleOld module.createGetLocal(tempOldValue.index, nativeSizeType),
), handleOld
)
: module.createNop(),
nullable nullable
? module.createIf( ? module.createIf(
module.createGetLocal(tempValue.index, nativeSizeType), module.createGetLocal(tempValue.index, nativeSizeType),

View File

@ -850,9 +850,10 @@ export class Program extends DiagnosticEmitter {
if (element = this.lookupGlobal("__ref_link")) { if (element = this.lookupGlobal("__ref_link")) {
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE); assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
this.linkRef = this.resolver.resolveFunction(<FunctionPrototype>element, null); this.linkRef = this.resolver.resolveFunction(<FunctionPrototype>element, null);
element = assert(this.lookupGlobal("__ref_unlink")); if (element = this.lookupGlobal("__ref_unlink")) {
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE); assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
this.unlinkRef = this.resolver.resolveFunction(<FunctionPrototype>element, null); this.unlinkRef = this.resolver.resolveFunction(<FunctionPrototype>element, null);
}
} else if (element = this.lookupGlobal("__ref_retain")) { } else if (element = this.lookupGlobal("__ref_retain")) {
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE); assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
this.retainRef = this.resolver.resolveFunction(<FunctionPrototype>element, null); this.retainRef = this.resolver.resolveFunction(<FunctionPrototype>element, null);

View File

@ -123,7 +123,7 @@ export class Array<T> extends ArrayBufferView {
store<T>(offset, value); store<T>(offset, value);
if (isNullable<T>()) { if (isNullable<T>()) {
if (isDefined(__ref_link)) { if (isDefined(__ref_link)) {
if (oldValue !== null) __ref_unlink(changetype<usize>(oldValue), changetype<usize>(this)); if (isDefined(__ref_unlink)) if (oldValue !== null) __ref_unlink(changetype<usize>(oldValue), changetype<usize>(this));
if (value !== null) __ref_link(changetype<usize>(value), changetype<usize>(this)); if (value !== null) __ref_link(changetype<usize>(value), changetype<usize>(this));
} else if (__ref_retain) { } else if (__ref_retain) {
if (oldValue !== null) __ref_release(changetype<usize>(oldValue)); if (oldValue !== null) __ref_release(changetype<usize>(oldValue));
@ -131,7 +131,7 @@ export class Array<T> extends ArrayBufferView {
} else assert(false); } else assert(false);
} else { } else {
if (isDefined(__ref_link)) { if (isDefined(__ref_link)) {
if (oldValue !== null) __ref_unlink(changetype<usize>(oldValue), changetype<usize>(this)); if (isDefined(__ref_unlink)) if (oldValue !== null) __ref_unlink(changetype<usize>(oldValue), changetype<usize>(this));
__ref_link(changetype<usize>(value), changetype<usize>(this)); __ref_link(changetype<usize>(value), changetype<usize>(this));
} else if (__ref_retain) { } else if (__ref_retain) {
if (oldValue !== null) __ref_release(changetype<usize>(oldValue)); if (oldValue !== null) __ref_release(changetype<usize>(oldValue));
@ -206,7 +206,7 @@ export class Array<T> extends ArrayBufferView {
if (isNullable<T>()) { if (isNullable<T>()) {
if (isDefined(__ref_link)) { if (isDefined(__ref_link)) {
if (value !== null) __ref_link(changetype<usize>(value), changetype<usize>(this)); if (value !== null) __ref_link(changetype<usize>(value), changetype<usize>(this));
if (oldValue !== null) __ref_unlink(changetype<usize>(oldValue), changetype<usize>(this)); if (isDefined(__ref_unlink)) if (oldValue !== null) __ref_unlink(changetype<usize>(oldValue), changetype<usize>(this));
} else if (__ref_retain) { } else if (__ref_retain) {
if (oldValue !== null) __ref_retain(changetype<usize>(value)); if (oldValue !== null) __ref_retain(changetype<usize>(value));
if (value !== null) __ref_release(changetype<usize>(oldValue)); if (value !== null) __ref_release(changetype<usize>(oldValue));
@ -214,7 +214,7 @@ export class Array<T> extends ArrayBufferView {
} else { } else {
if (isDefined(__ref_link)) { if (isDefined(__ref_link)) {
__ref_link(changetype<usize>(value), changetype<usize>(this)); __ref_link(changetype<usize>(value), changetype<usize>(this));
if (oldValue !== null) __ref_unlink(changetype<usize>(oldValue), changetype<usize>(this)); if (isDefined(__ref_unlink)) if (oldValue !== null) __ref_unlink(changetype<usize>(oldValue), changetype<usize>(this));
} else if (__ref_retain) { } else if (__ref_retain) {
__ref_retain(changetype<usize>(value)); __ref_retain(changetype<usize>(value));
if (oldValue !== null) __ref_release(changetype<usize>(oldValue)); if (oldValue !== null) __ref_release(changetype<usize>(oldValue));
@ -476,11 +476,11 @@ export class Array<T> extends ArrayBufferView {
if (isDefined(__ref_link)) { if (isDefined(__ref_link)) {
if (isNullable<T>()) { if (isNullable<T>()) {
if (ref) { if (ref) {
__ref_unlink(ref, changetype<usize>(this)); if (isDefined(__ref_unlink)) __ref_unlink(ref, changetype<usize>(this));
__ref_link(ref, changetype<usize>(result)); __ref_link(ref, changetype<usize>(result));
} }
} else { } else {
__ref_unlink(ref, changetype<usize>(this)); if (isDefined(__ref_unlink)) __ref_unlink(ref, changetype<usize>(this));
__ref_link(ref, changetype<usize>(result)); __ref_link(ref, changetype<usize>(result));
} }
} }

View File

@ -19,13 +19,13 @@ Tracing
Links a reference to a parent that is now referencing it. Links a reference to a parent that is now referencing it.
* **__ref_unlink**(ref: `usize`, parentRef: `usize`): `void`<br /> * **__ref_unlink**(ref: `usize`, parentRef: `usize`): `void`<br />
Unlinks a reference from a parent that was referencing it. Unlinks a reference from a parent that was referencing it. Implementation is optional.
Reference counting Reference counting
------------------ ------------------
* **__ref_register**(ref: `usize`): `void`<br /> * **__ref_register**(ref: `usize`): `void`<br />
Sets up a new reference. Implementation is optional for reference counting GCs. Sets up a new reference. Implementation is optional.
* **__ref_retain**(ref: `usize`): `void`<br /> * **__ref_retain**(ref: `usize`): `void`<br />
Retains a reference, usually incrementing RC. Retains a reference, usually incrementing RC.
@ -71,7 +71,7 @@ if (isNullable<T>()) {
if (ref !== oldRef) { if (ref !== oldRef) {
if (isNullable<T>()) { if (isNullable<T>()) {
if (isDefined(__ref_link)) { if (isDefined(__ref_link)) {
if (oldRef) __ref_unlink(oldRef, parentRef); if (isDefined(__ref_unlink)) if (oldRef) __ref_unlink(oldRef, parentRef);
if (ref) __ref_link(ref, parentRef); if (ref) __ref_link(ref, parentRef);
} else if (isDefined(__ref_retain)) { } else if (isDefined(__ref_retain)) {
if (oldRef) __ref_release(oldRef); if (oldRef) __ref_release(oldRef);
@ -79,7 +79,7 @@ if (ref !== oldRef) {
} else assert(false); } else assert(false);
} else { } else {
if (isDefined(__ref_link)) { if (isDefined(__ref_link)) {
if (oldRef) __ref_unlink(oldRef, parentRef); // * if (isDefined(__ref_unlink)) if (oldRef) __ref_unlink(oldRef, parentRef); // *
__ref_link(ref, parentRef); __ref_link(ref, parentRef);
} else if (isDefined(__ref_retain)) { } else if (isDefined(__ref_retain)) {
if (oldRef) __ref_release(oldRef); // * if (oldRef) __ref_release(oldRef); // *
@ -94,13 +94,15 @@ if (ref !== oldRef) {
```ts ```ts
if (isNullable<T>()) { if (isNullable<T>()) {
if (ref) { if (ref) {
if (isDefined(__ref_link)) __ref_unlink(ref, parentRef); if (isDefined(__ref_link)) {
else if (isDefined(__ref_retain)) __ref_release(ref); if (isDefined(__ref_unlink)) __ref_unlink(ref, parentRef);
} else if (isDefined(__ref_retain)) __ref_release(ref);
else assert(false); else assert(false);
} }
} else { } else {
if (isDefined(__ref_link)) __ref_unlink(ref, parentRef); if (isDefined(__ref_link)) {
else if (isDefined(__ref_retain)) __ref_release(ref); if (isDefined(__ref_unlink)) __ref_unlink(ref, parentRef);
} else if (isDefined(__ref_retain)) __ref_release(ref);
else assert(false); else assert(false);
} }
``` ```

View File

@ -1,11 +1,14 @@
// common // common
declare function __ref_collect(): void; declare function __ref_collect(): void;
declare function __ref_register(ref: usize): void;
// tracing // tracing
declare function __ref_register(ref: usize): void;
declare function __ref_link(ref: usize, parentRef: usize): void; declare function __ref_link(ref: usize, parentRef: usize): void;
declare function __ref_unlink(ref: usize, parentRef: usize): void; declare function __ref_unlink(ref: usize, parentRef: usize): void;
// reference counting // reference counting
declare function __ref_retain(ref: usize): void; declare function __ref_retain(ref: usize): void;
declare function __ref_release(ref: usize): void; declare function __ref_release(ref: usize): void;
// debugging
declare const GC_TRACE: bool;

View File

@ -2,7 +2,7 @@
// @ts-ignore: decorator // @ts-ignore: decorator
@inline @inline
const TRACE = false; const TRACE = isDefined(GC_TRACE);
import { iterateRoots, HEADER_SIZE } from "../runtime"; import { iterateRoots, HEADER_SIZE } from "../runtime";
@ -85,14 +85,14 @@ var iter: ManagedObject;
unlink(): void { unlink(): void {
var next = this.next; var next = this.next;
var prev = this.prev; var prev = this.prev;
if (TRACE) trace(" unlink", 3, objToRef(prev), objToRef(this), objToRef(next)); if (TRACE) trace(" unlink [pref, ref, next]", 3, objToRef(prev), objToRef(this), objToRef(next));
next.prev = prev; next.prev = prev;
prev.next = next; prev.next = next;
} }
/** Marks this object as gray, that is reachable with unscanned children. */ /** Marks this object as gray, that is reachable with unscanned children. */
makeGray(): void { makeGray(): void {
if (TRACE) trace(" makeGray", 1, objToRef(this)); if (TRACE) trace(" makeGray", 1, objToRef(this));
const gray = 2; const gray = 2;
if (this == iter) iter = this.prev; if (this == iter) iter = this.prev;
this.unlink(); this.unlink();
@ -107,7 +107,7 @@ var iter: ManagedObject;
/** Inserts an object. */ /** Inserts an object. */
push(obj: ManagedObject): void { push(obj: ManagedObject): void {
var prev = this.prev; var prev = this.prev;
if (TRACE) trace(" push", 3, objToRef(prev), objToRef(obj), objToRef(this)); if (TRACE) trace(" push [prev, ref, next]", 3, objToRef(prev), objToRef(obj), objToRef(this));
obj.next = this; obj.next = this;
obj.prev = prev; obj.prev = prev;
prev.next = obj; prev.next = obj;
@ -116,7 +116,7 @@ var iter: ManagedObject;
/** Clears this list. */ /** Clears this list. */
clear(): void { clear(): void {
if (TRACE) trace(" clear", 1, objToRef(this)); if (TRACE) trace(" clear", 1, objToRef(this));
this.nextWithColor = changetype<usize>(this); this.nextWithColor = changetype<usize>(this);
this.prev = this; this.prev = this;
} }
@ -127,32 +127,36 @@ function step(): void {
var obj: ManagedObject; var obj: ManagedObject;
switch (state) { switch (state) {
case State.INIT: { case State.INIT: {
if (TRACE) trace("gc~step/INIT"); if (TRACE) trace("itcm~step/INIT");
fromSpace = changetype<ManagedObjectList>(memory.allocate(HEADER_SIZE)); fromSpace = changetype<ManagedObjectList>(memory.allocate(HEADER_SIZE));
if (TRACE) trace(" fromSpace =", 1, objToRef(fromSpace));
fromSpace.classId = -1; // would error fromSpace.classId = -1; // would error
fromSpace.payloadSize = 0;
fromSpace.clear(); fromSpace.clear();
toSpace = changetype<ManagedObjectList>(memory.allocate(HEADER_SIZE)); toSpace = changetype<ManagedObjectList>(memory.allocate(HEADER_SIZE));
if (TRACE) trace(" toSpace =", 1, objToRef(toSpace));
toSpace.classId = -1; // would error toSpace.classId = -1; // would error
toSpace.payloadSize = 0;
toSpace.clear(); toSpace.clear();
iter = toSpace; iter = toSpace;
state = State.IDLE; state = State.IDLE;
if (TRACE) trace("gc~state = IDLE"); if (TRACE) trace("itcm~state = IDLE");
// fall-through // fall-through
} }
case State.IDLE: { case State.IDLE: {
if (TRACE) trace("gc~step/IDLE"); if (TRACE) trace("itcm~step/IDLE");
iterateRoots((ref: usize): void => { iterateRoots((ref: usize): void => {
var obj = refToObj(ref); var obj = refToObj(ref);
if (obj.color == white) obj.makeGray(); if (obj.color == white) obj.makeGray();
}); });
state = State.MARK; state = State.MARK;
if (TRACE) trace("gc~state = MARK"); if (TRACE) trace("itcm~state = MARK");
break; break;
} }
case State.MARK: { case State.MARK: {
obj = iter.next; obj = iter.next;
if (obj !== toSpace) { if (obj !== toSpace) {
if (TRACE) trace("gc~step/MARK iterate", 1, objToRef(obj)); if (TRACE) trace("itcm~step/MARK iterate", 1, objToRef(obj));
iter = obj; iter = obj;
obj.color = i32(!white); obj.color = i32(!white);
// if (TRACE) { // if (TRACE) {
@ -164,7 +168,7 @@ function step(): void {
// } // }
obj.hookFn(objToRef(obj)); obj.hookFn(objToRef(obj));
} else { } else {
if (TRACE) trace("gc~step/MARK finish"); if (TRACE) trace("itcm~step/MARK finish");
iterateRoots((ref: usize): void => { iterateRoots((ref: usize): void => {
var obj = refToObj(ref); var obj = refToObj(ref);
if (obj.color == white) obj.makeGray(); if (obj.color == white) obj.makeGray();
@ -177,7 +181,7 @@ function step(): void {
white = i32(!white); white = i32(!white);
iter = from.next; iter = from.next;
state = State.SWEEP; state = State.SWEEP;
if (TRACE) trace("gc~state = SWEEP"); if (TRACE) trace("itcm~state = SWEEP");
} }
} }
break; break;
@ -185,14 +189,14 @@ function step(): void {
case State.SWEEP: { case State.SWEEP: {
obj = iter; obj = iter;
if (obj !== toSpace) { if (obj !== toSpace) {
if (TRACE) trace("gc~step/SWEEP free", 1, objToRef(obj)); if (TRACE) trace("itcm~step/SWEEP free", 1, objToRef(obj));
iter = obj.next; iter = obj.next;
if (changetype<usize>(obj) >= HEAP_BASE) memory.free(changetype<usize>(obj)); if (changetype<usize>(obj) >= HEAP_BASE) memory.free(changetype<usize>(obj));
} else { } else {
if (TRACE) trace("gc~step/SWEEP finish"); if (TRACE) trace("itcm~step/SWEEP finish");
toSpace.clear(); toSpace.clear();
state = State.IDLE; state = State.IDLE;
if (TRACE) trace("gc~state = IDLE"); if (TRACE) trace("itcm~state = IDLE");
} }
break; break;
} }
@ -245,7 +249,7 @@ export function __ref_link(ref: usize, parentRef: usize): void {
} }
// @ts-ignore: decorator // @ts-ignore: decorator
@global @unsafe // @global @unsafe
export function __ref_unlink(ref: usize, parentRef: usize): void { // export function __ref_unlink(ref: usize, parentRef: usize): void {
if (TRACE) trace("itcm.unlink", 2, ref, parentRef); // if (TRACE) trace("itcm.unlink", 2, ref, parentRef);
} // }

View File

@ -47,8 +47,9 @@ export class FixedArray<T> {
if (value !== oldValue) { if (value !== oldValue) {
store<T>(offset, value); store<T>(offset, value);
if (oldValue !== null) { if (oldValue !== null) {
if (isDefined(__ref_link)) __ref_unlink(changetype<usize>(oldValue), changetype<usize>(this)); if (isDefined(__ref_link)) {
else if (isDefined(__ref_retain)) __ref_release(changetype<usize>(oldValue)); if (isDefined(__ref_unlink)) __ref_unlink(changetype<usize>(oldValue), changetype<usize>(this));
} else if (isDefined(__ref_retain)) __ref_release(changetype<usize>(oldValue));
else assert(false); else assert(false);
} }
if (isNullable<T>()) { if (isNullable<T>()) {

View File

@ -39,8 +39,9 @@ export namespace gc {
if (root.has(ref)) { if (root.has(ref)) {
root.delete(ref); root.delete(ref);
if (implemented) { if (implemented) {
if (isDefined(__ref_link)) __ref_unlink(ref, changetype<usize>(root)); if (isDefined(__ref_link)) {
else if (isDefined(__ref_retain)) __ref_release(ref); if (isDefined(__ref_unlink)) __ref_unlink(ref, changetype<usize>(root));
} else if (isDefined(__ref_retain)) __ref_release(ref);
else assert(false); else assert(false);
} }
} }

View File

@ -111,8 +111,9 @@ export class Map<K,V> {
entry.value = value; entry.value = value;
if (isNullable<V>()) { if (isNullable<V>()) {
if (oldValue !== null) { if (oldValue !== null) {
if (isDefined(__ref_link)) __ref_unlink(changetype<usize>(oldValue), changetype<usize>(this)); if (isDefined(__ref_link)) {
else if (isDefined(__ref_retain)) __ref_release(changetype<usize>(oldValue)); if (isDefined(__ref_unlink)) __ref_unlink(changetype<usize>(oldValue), changetype<usize>(this));
} else if (isDefined(__ref_retain)) __ref_release(changetype<usize>(oldValue));
else assert(false); else assert(false);
} }
if (value !== null) { if (value !== null) {
@ -122,7 +123,7 @@ export class Map<K,V> {
} }
} else { } else {
if (isDefined(__ref_link)) { if (isDefined(__ref_link)) {
__ref_unlink(changetype<usize>(oldValue), changetype<usize>(this)); if (isDefined(__ref_unlink)) __ref_unlink(changetype<usize>(oldValue), changetype<usize>(this));
__ref_link(changetype<usize>(value), changetype<usize>(this)); __ref_link(changetype<usize>(value), changetype<usize>(this));
} else if (isDefined(__ref_retain)) { } else if (isDefined(__ref_retain)) {
__ref_release(changetype<usize>(oldValue)); __ref_release(changetype<usize>(oldValue));
@ -189,13 +190,15 @@ export class Map<K,V> {
let oldKey = entry.key; let oldKey = entry.key;
if (isNullable<K>()) { if (isNullable<K>()) {
if (oldKey !== null) { if (oldKey !== null) {
if (isDefined(__ref_link)) __ref_unlink(changetype<usize>(oldKey), changetype<usize>(this)); if (isDefined(__ref_link)) {
else if (isDefined(__ref_retain)) __ref_release(changetype<usize>(oldKey)); if (isDefined(__ref_unlink)) __ref_unlink(changetype<usize>(oldKey), changetype<usize>(this));
} else if (isDefined(__ref_retain)) __ref_release(changetype<usize>(oldKey));
else assert(false); else assert(false);
} }
} else { } else {
if (isDefined(__ref_link)) __ref_unlink(changetype<usize>(oldKey), changetype<usize>(this)); if (isDefined(__ref_link)) {
else if (isDefined(__ref_retain)) __ref_release(changetype<usize>(oldKey)); if (isDefined(__ref_unlink)) __ref_unlink(changetype<usize>(oldKey), changetype<usize>(this));
} else if (isDefined(__ref_retain)) __ref_release(changetype<usize>(oldKey));
else assert(false); else assert(false);
} }
} }
@ -203,13 +206,15 @@ export class Map<K,V> {
let oldValue = entry.key; let oldValue = entry.key;
if (isNullable<V>()) { if (isNullable<V>()) {
if (oldValue !== null) { if (oldValue !== null) {
if (isDefined(__ref_link)) __ref_unlink(changetype<usize>(oldValue), changetype<usize>(this)); if (isDefined(__ref_link)) {
else if (isDefined(__ref_retain)) __ref_release(changetype<usize>(oldValue)); if (isDefined(__ref_unlink)) __ref_unlink(changetype<usize>(oldValue), changetype<usize>(this));
} else if (isDefined(__ref_retain)) __ref_release(changetype<usize>(oldValue));
else assert(false); else assert(false);
} }
} else { } else {
if (isDefined(__ref_link)) __ref_unlink(changetype<usize>(oldValue), changetype<usize>(this)); if (isDefined(__ref_link)) {
else if (isDefined(__ref_retain)) __ref_release(changetype<usize>(oldValue)); if (isDefined(__ref_unlink)) __ref_unlink(changetype<usize>(oldValue), changetype<usize>(this));
} else if (isDefined(__ref_retain)) __ref_release(changetype<usize>(oldValue));
else assert(false); else assert(false);
} }
} }

View File

@ -137,13 +137,15 @@ export class Set<K> {
key = entry.key; // exact, e.g. string key = entry.key; // exact, e.g. string
if (isNullable<K>()) { if (isNullable<K>()) {
if (key !== null) { if (key !== null) {
if (isDefined(__ref_link)) __ref_unlink(changetype<usize>(key), changetype<usize>(this)); if (isDefined(__ref_link)) {
else if (isDefined(__ref_retain)) __ref_release(changetype<usize>(key)); if (isDefined(__ref_unlink)) __ref_unlink(changetype<usize>(key), changetype<usize>(this));
} else if (isDefined(__ref_retain)) __ref_release(changetype<usize>(key));
else assert(false); else assert(false);
} }
} else { } else {
if (isDefined(__ref_link)) __ref_unlink(changetype<usize>(key), changetype<usize>(this)); if (isDefined(__ref_link)) {
else if (isDefined(__ref_retain)) __ref_release(changetype<usize>(key)); if (isDefined(__ref_unlink)) __ref_unlink(changetype<usize>(key), changetype<usize>(this));
} else if (isDefined(__ref_retain)) __ref_release(changetype<usize>(key));
else assert(false); else assert(false);
} }
} }

View File

@ -293,7 +293,9 @@ tests.forEach(filename => {
} }
}); });
console.log("- " + colorsUtil.green("instantiate OK") + " (" + asc.formatTime(runTime) + ")"); console.log("- " + colorsUtil.green("instantiate OK") + " (" + asc.formatTime(runTime) + ")");
console.log("\n " + Object.keys(exports).map(key => "[" + (typeof exports[key]).substring(0, 3) + "] " + key).join("\n ")); console.log("\n " + Object.keys(exports).map(key => {
return "[" + (typeof exports[key]).substring(0, 3) + "] " + key + " = " + exports[key]
}).join("\n "));
} catch (e) { } catch (e) {
console.log("- " + colorsUtil.red("instantiate ERROR: ") + e.stack); console.log("- " + colorsUtil.red("instantiate ERROR: ") + e.stack);
failed = true; failed = true;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,26 @@
@global const GC_TRACE = true;
import "allocator/arena";
import "collector/itcm";
import { HEADER_SIZE } from "runtime";
assert(HEADER_SIZE == 16);
assert(gc.implemented);
gc.collect(); // trigger init
class Ref {}
trace("# ref = new Ref()");
var ref = new Ref();
trace("# arr = new Array(1)");
var arr = new Array<Ref | null>(1);
trace("# arr[0] = ref");
arr[0] = ref;
trace("# arr[0] = null");
arr[0] = null;
// TODO...
@start export function main(): void {}

File diff suppressed because it is too large Load Diff