integrate

This commit is contained in:
dcode 2019-03-09 00:40:03 +01:00
parent 911a4bbaf2
commit 0ad9d560e0
7 changed files with 33 additions and 19 deletions

View File

@ -474,6 +474,9 @@ export namespace BuiltinSymbols {
export const memory_fill = "~lib/memory/memory.fill"; export const memory_fill = "~lib/memory/memory.fill";
// std/gc.ts // std/gc.ts
export const iterateRoots = "~lib/gc/iterateRoots"; export const iterateRoots = "~lib/gc/iterateRoots";
// internals
export const rt_classid = "~lib/builtins/__rt_classid";
export const rt_iterateroots = "~lib/builtins/__rt_iterateroots";
} }
/** Compiles a call to a built-in function. */ /** Compiles a call to a built-in function. */
@ -3591,9 +3594,17 @@ export function compileCall(
return module.createUnary(op, arg0); return module.createUnary(op, arg0);
} }
// === GC integration ========================================================================= // === Internal runtime =======================================================================
case BuiltinSymbols.iterateRoots: { case BuiltinSymbols.rt_classid: {
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
compiler.currentType = Type.u32;
if (!type) return module.createUnreachable();
let classReference = type.classReference;
if (!classReference) return module.createUnreachable();
return module.createI32(classReference.prototype.classId);
}
case BuiltinSymbols.rt_iterateroots: {
if ( if (
checkTypeAbsent(typeArguments, reportNode, prototype) | checkTypeAbsent(typeArguments, reportNode, prototype) |
checkArgsRequired(operands, 1, reportNode, compiler) checkArgsRequired(operands, 1, reportNode, compiler)

View File

@ -344,6 +344,9 @@ export class Program extends DiagnosticEmitter {
/** Memory allocation function. */ /** Memory allocation function. */
memoryAllocateInstance: Function | null = null; memoryAllocateInstance: Function | null = null;
/** Next class id. */
nextClassId: u32 = 1;
// gc integration // gc integration
/** Whether a garbage collector is present or not. */ /** Whether a garbage collector is present or not. */
@ -2355,7 +2358,7 @@ export class FunctionPrototype extends DeclaredElement {
/** Constructs a new function prototype. */ /** Constructs a new function prototype. */
constructor( constructor(
/** Simple na,e */ /** Simple name */
name: string, name: string,
/** Parent element, usually a file, namespace or class (if a method). */ /** Parent element, usually a file, namespace or class (if a method). */
parent: Element, parent: Element,
@ -2792,6 +2795,8 @@ export class ClassPrototype extends DeclaredElement {
overloadPrototypes: Map<OperatorKind, FunctionPrototype> = new Map(); overloadPrototypes: Map<OperatorKind, FunctionPrototype> = new Map();
/** Already resolved instances. */ /** Already resolved instances. */
instances: Map<string,Class> | null = null; instances: Map<string,Class> | null = null;
/** Unique class id. */
classId: u32 = 0;
constructor( constructor(
/** Simple name. */ /** Simple name. */
@ -2813,6 +2818,8 @@ export class ClassPrototype extends DeclaredElement {
declaration declaration
); );
this.decoratorFlags = decoratorFlags; this.decoratorFlags = decoratorFlags;
this.classId = u32(this.program.nextClassId++);
assert(this.classId); // must not wrap around to 0
} }
/** Gets the associated type parameter nodes. */ /** Gets the associated type parameter nodes. */

View File

@ -501,3 +501,6 @@ export namespace v8x16 {
} }
@builtin export declare function start(): void; @builtin export declare function start(): void;
@builtin export declare function __rt_classid<T>(): u32;
@builtin export declare function __rt_iterateroots(fn: (ref: usize) => void): void;

View File

@ -12,7 +12,6 @@
@inline export const HEADER_SIZE: usize = (offsetof<ManagedObject>() + AL_MASK) & ~AL_MASK; @inline export const HEADER_SIZE: usize = (offsetof<ManagedObject>() + AL_MASK) & ~AL_MASK;
import { AL_MASK, MAX_SIZE_32 } from "../internal/allocator"; import { AL_MASK, MAX_SIZE_32 } from "../internal/allocator";
import { iterateRoots } from "../gc";
/** Collector states. */ /** Collector states. */
const enum State { const enum State {
@ -142,7 +141,7 @@ function step(): void {
} }
case State.IDLE: { case State.IDLE: {
if (TRACE) trace("gc~step/IDLE"); if (TRACE) trace("gc~step/IDLE");
iterateRoots(__gc_mark); __rt_iterateroots(__gc_mark);
state = State.MARK; state = State.MARK;
if (TRACE) trace("gc~state = MARK"); if (TRACE) trace("gc~state = MARK");
break; break;
@ -163,7 +162,7 @@ function step(): void {
obj.hookFn(objToRef(obj)); obj.hookFn(objToRef(obj));
} else { } else {
if (TRACE) trace("gc~step/MARK finish"); if (TRACE) trace("gc~step/MARK finish");
iterateRoots(__gc_mark); __rt_iterateroots(__gc_mark);
obj = iter.next; obj = iter.next;
if (obj === toSpace) { if (obj === toSpace) {
let from = fromSpace; let from = fromSpace;

View File

@ -1,7 +1,5 @@
/* tslint:disable */ /* tslint:disable */
@builtin export declare function iterateRoots(fn: (ref: usize) => void): void;
export namespace gc { export namespace gc {
export function collect(): void { export function collect(): void {

View File

@ -25,7 +25,7 @@ export class HEADER {
@inline export const HEADER_MAGIC: u32 = 0xA55E4B17; @inline export const HEADER_MAGIC: u32 = 0xA55E4B17;
/** Aligns an allocation to actual block size. */ /** Aligns an allocation to actual block size. */
function ALIGN(payloadSize: usize): usize { export function ALIGN(payloadSize: usize): usize {
// round up to power of 2, e.g. with HEADER_SIZE=8: // round up to power of 2, e.g. with HEADER_SIZE=8:
// 0 -> 2^3 = 8 // 0 -> 2^3 = 8
// 1..8 -> 2^4 = 16 // 1..8 -> 2^4 = 16
@ -36,7 +36,7 @@ function ALIGN(payloadSize: usize): usize {
} }
/** Gets to the common runtime header of the specified reference. */ /** Gets to the common runtime header of the specified reference. */
function UNREF(ref: usize): HEADER { export function UNREF(ref: usize): HEADER {
assert(ref >= HEAP_BASE + HEADER_SIZE); // must be a heap object assert(ref >= HEAP_BASE + HEADER_SIZE); // must be a heap object
var header = changetype<HEADER>(ref - HEADER_SIZE); var header = changetype<HEADER>(ref - HEADER_SIZE);
assert(header.classId == HEADER_MAGIC); // must be unregistered assert(header.classId == HEADER_MAGIC); // must be unregistered
@ -96,14 +96,10 @@ export function FREE(ref: usize): void {
memory.free(changetype<usize>(header)); memory.free(changetype<usize>(header));
} }
function CLASSID<T>(): u32 {
return 1;
}
/** Registers a managed object with GC. Cannot be changed anymore afterwards. */ /** Registers a managed object with GC. Cannot be changed anymore afterwards. */
export function REGISTER<T>(ref: usize, parentRef: usize): void { export function REGISTER<T>(ref: usize, parentRef: usize): void {
var header = UNREF(ref); var header = UNREF(ref);
header.classId = CLASSID<T>(); header.classId = __rt_classid<T>();
if (GC) __REGISTER_IMPL(ref, parentRef); if (GC) __REGISTER_IMPL(ref, parentRef);
} }

View File

@ -142,7 +142,7 @@ declare namespace i8 {
export function parseInt(string: string, radix?: i32): i8; export function parseInt(string: string, radix?: i32): i8;
} }
/** Converts any other numeric value to a 16-bit signed integer. */ /** Converts any other numeric value to a 16-bit signed integer. */
declare function i16(value: i8 | i16 | i32 | isize | u8 | u16 | u32 | usize | bool | f32 | f64): i8; declare function i16(value: i8 | i16 | i32 | isize | u8 | u16 | u32 | usize | bool | f32 | f64): i16;
declare namespace i16 { declare namespace i16 {
/** Smallest representable value. */ /** Smallest representable value. */
export const MIN_VALUE: i16; export const MIN_VALUE: i16;
@ -178,7 +178,7 @@ declare namespace isize {
export function parseInt(string: string, radix?: i32): isize; export function parseInt(string: string, radix?: i32): isize;
} }
/** Converts any other numeric value to an 8-bit unsigned integer. */ /** Converts any other numeric value to an 8-bit unsigned integer. */
declare function u8(value: i8 | i16 | i32 | isize | u8 | u16 | u32 | usize | bool | f32 | f64): i8; declare function u8(value: i8 | i16 | i32 | isize | u8 | u16 | u32 | usize | bool | f32 | f64): u8;
declare namespace u8 { declare namespace u8 {
/** Smallest representable value. */ /** Smallest representable value. */
export const MIN_VALUE: u8; export const MIN_VALUE: u8;
@ -190,7 +190,7 @@ declare namespace u8 {
export function parseInt(string: string, radix?: i32): u8; export function parseInt(string: string, radix?: i32): u8;
} }
/** Converts any other numeric value to a 16-bit unsigned integer. */ /** Converts any other numeric value to a 16-bit unsigned integer. */
declare function u16(value: i8 | i16 | i32 | isize | u8 | u16 | u32 | usize | bool | f32 | f64): i8; declare function u16(value: i8 | i16 | i32 | isize | u8 | u16 | u32 | usize | bool | f32 | f64): u16;
declare namespace u16 { declare namespace u16 {
/** Smallest representable value. */ /** Smallest representable value. */
export const MIN_VALUE: u16; export const MIN_VALUE: u16;
@ -202,7 +202,7 @@ declare namespace u16 {
export function parseInt(string: string, radix?: i32): u16; export function parseInt(string: string, radix?: i32): u16;
} }
/** Converts any other numeric value to a 32-bit unsigned integer. */ /** Converts any other numeric value to a 32-bit unsigned integer. */
declare function u32(value: i8 | i16 | i32 | isize | u8 | u16 | u32 | usize | bool | f32 | f64): i32; declare function u32(value: i8 | i16 | i32 | isize | u8 | u16 | u32 | usize | bool | f32 | f64): u32;
declare namespace u32 { declare namespace u32 {
/** Smallest representable value. */ /** Smallest representable value. */
export const MIN_VALUE: u32; export const MIN_VALUE: u32;