mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-06-23 19:51:47 +00:00
progress
This commit is contained in:
@ -46,14 +46,14 @@
|
||||
|
||||
import { RTTI_BASE } from "builtins";
|
||||
import { RTTIData, RTTIFlags } from "common/rtti";
|
||||
import { E_INDEXOUTOFRANGE } from "../util/error";
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@unsafe @global
|
||||
export function __typeinfo(id: u32): RTTIFlags {
|
||||
var ptr = RTTI_BASE;
|
||||
return !id || id > load<u32>(ptr)
|
||||
? unreachable()
|
||||
: changetype<RTTIData>(ptr + id * offsetof<RTTIData>()).flags;
|
||||
if (!id || id > load<u32>(ptr)) throw new Error(E_INDEXOUTOFRANGE);
|
||||
return changetype<RTTIData>(ptr + id * offsetof<RTTIData>()).flags;
|
||||
}
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@ -79,7 +79,7 @@ export function __allocArray(length: i32, alignLog2: usize, id: u32, data: usize
|
||||
var array = __alloc(offsetof<i32[]>(), id);
|
||||
var bufferSize = <usize>length << alignLog2;
|
||||
var buffer = __alloc(bufferSize, idof<ArrayBuffer>());
|
||||
changetype<ArrayBufferView>(array).data = changetype<ArrayBuffer>(buffer); // TODO/RT: retains
|
||||
store<usize>(array, __retain(buffer), offsetof<ArrayBufferView>("data"));
|
||||
changetype<ArrayBufferView>(array).dataStart = buffer;
|
||||
changetype<ArrayBufferView>(array).dataLength = bufferSize;
|
||||
store<i32>(changetype<usize>(array), length, offsetof<i32[]>("length_"));
|
||||
|
@ -1,85 +1,2 @@
|
||||
import { AL_MASK, BLOCK, BLOCK_OVERHEAD, BLOCK_MAXSIZE } from "rt/common";
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@lazy
|
||||
var startOffset: usize = (HEAP_BASE + AL_MASK) & ~AL_MASK;
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@lazy
|
||||
var offset: usize = startOffset;
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@unsafe @global
|
||||
export function __alloc(size: usize, id: u32): usize {
|
||||
if (size > BLOCK_MAXSIZE) unreachable();
|
||||
var ptr = offset + BLOCK_OVERHEAD;
|
||||
var newPtr = (ptr + max<usize>(size, 1) + AL_MASK) & ~AL_MASK;
|
||||
var pagesBefore = memory.size();
|
||||
if (newPtr > <usize>pagesBefore << 16) {
|
||||
let pagesNeeded = ((newPtr - ptr + 0xffff) & ~0xffff) >>> 16;
|
||||
let pagesWanted = max(pagesBefore, pagesNeeded); // double memory
|
||||
if (memory.grow(pagesWanted) < 0) {
|
||||
if (memory.grow(pagesNeeded) < 0) unreachable(); // out of memory
|
||||
}
|
||||
}
|
||||
offset = newPtr;
|
||||
var block = changetype<BLOCK>(ptr - BLOCK_OVERHEAD);
|
||||
block.rtId = id;
|
||||
block.rtSize = size;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@unsafe @global
|
||||
export function __realloc(ref: usize, size: usize): usize {
|
||||
var block = changetype<BLOCK>(ref - BLOCK_OVERHEAD);
|
||||
var oldSize = <usize>block.rtSize;
|
||||
if (size > oldSize) {
|
||||
let newRef = __alloc(size, block.rtId);
|
||||
memory.copy(newRef, ref, oldSize);
|
||||
ref = newRef;
|
||||
} else {
|
||||
block.rtSize = size;
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@unsafe @global
|
||||
export function __free(ref: usize): void {
|
||||
}
|
||||
|
||||
// @ts-ignore: decorator
|
||||
// @unsafe @global
|
||||
// export function __reset(): void { // special
|
||||
// offset = startOffset;
|
||||
// }
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@global @unsafe
|
||||
export function __retain(ref: usize): usize {
|
||||
return ref;
|
||||
}
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@global @unsafe
|
||||
export function __release(ref: usize): void {
|
||||
}
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@global @unsafe
|
||||
function __visit(ref: usize, cookie: u32): void {
|
||||
}
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@global @unsafe
|
||||
function __retainRelease(ref: usize, oldRef: usize): usize {
|
||||
return ref;
|
||||
}
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@global @unsafe
|
||||
export function __collect(): void {
|
||||
}
|
||||
|
||||
export { __alloc, __realloc, __free, __retain, __release, __collect } from "rt/stub";
|
||||
export { __instanceof, __typeinfo } from "rt/common";
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { DEBUG, BLOCK_OVERHEAD, BLOCK } from "rt/common";
|
||||
import { DEBUG, BLOCK_OVERHEAD } from "rt/common";
|
||||
import { Block, freeBlock, ROOT } from "rt/tlsf";
|
||||
import { RTTIFlags } from "common/rtti";
|
||||
|
||||
@ -102,12 +102,16 @@ function increment(s: Block): void {
|
||||
var info = s.gcInfo;
|
||||
assert((info & ~REFCOUNT_MASK) == ((info + 1) & ~REFCOUNT_MASK)); // overflow
|
||||
s.gcInfo = info + 1;
|
||||
if (isDefined(ASC_RTRACE)) onIncrement(s);
|
||||
if (DEBUG) assert(!(s.mmInfo & 1)); // used
|
||||
}
|
||||
|
||||
/** Decrements the reference count of the specified block by one, possibly freeing it. */
|
||||
function decrement(s: Block): void {
|
||||
var info = s.gcInfo;
|
||||
var rc = info & REFCOUNT_MASK;
|
||||
if (isDefined(ASC_RTRACE)) onDecrement(s);
|
||||
if (DEBUG) assert(!(s.mmInfo & 1)); // used
|
||||
if (rc == 1) {
|
||||
__visit_members(changetype<usize>(s) + BLOCK_OVERHEAD, VISIT_DECREMENT);
|
||||
if (!(info & BUFFERED_MASK)) {
|
||||
@ -261,3 +265,11 @@ export function __retainRelease(ref: usize, oldRef: usize): usize {
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@external("rtrace", "retain")
|
||||
declare function onIncrement(s: Block): void;
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@external("rtrace", "release")
|
||||
declare function onDecrement(s: Block): void;
|
||||
|
83
std/assembly/rt/stub.ts
Normal file
83
std/assembly/rt/stub.ts
Normal file
@ -0,0 +1,83 @@
|
||||
import { AL_MASK, BLOCK, BLOCK_OVERHEAD, BLOCK_MAXSIZE } from "rt/common";
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@lazy
|
||||
var startOffset: usize = (HEAP_BASE + AL_MASK) & ~AL_MASK;
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@lazy
|
||||
var offset: usize = startOffset;
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@unsafe @global
|
||||
export function __alloc(size: usize, id: u32): usize {
|
||||
if (size > BLOCK_MAXSIZE) unreachable();
|
||||
var ptr = offset + BLOCK_OVERHEAD;
|
||||
var newPtr = (ptr + max<usize>(size, 1) + AL_MASK) & ~AL_MASK;
|
||||
var pagesBefore = memory.size();
|
||||
if (newPtr > <usize>pagesBefore << 16) {
|
||||
let pagesNeeded = ((newPtr - ptr + 0xffff) & ~0xffff) >>> 16;
|
||||
let pagesWanted = max(pagesBefore, pagesNeeded); // double memory
|
||||
if (memory.grow(pagesWanted) < 0) {
|
||||
if (memory.grow(pagesNeeded) < 0) unreachable(); // out of memory
|
||||
}
|
||||
}
|
||||
offset = newPtr;
|
||||
var block = changetype<BLOCK>(ptr - BLOCK_OVERHEAD);
|
||||
block.rtId = id;
|
||||
block.rtSize = size;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@unsafe @global
|
||||
export function __realloc(ref: usize, size: usize): usize {
|
||||
var block = changetype<BLOCK>(ref - BLOCK_OVERHEAD);
|
||||
var oldSize = <usize>block.rtSize;
|
||||
if (size > oldSize) {
|
||||
let newRef = __alloc(size, block.rtId);
|
||||
memory.copy(newRef, ref, oldSize);
|
||||
ref = newRef;
|
||||
} else {
|
||||
block.rtSize = size;
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@unsafe @global
|
||||
export function __free(ref: usize): void {
|
||||
}
|
||||
|
||||
// @ts-ignore: decorator
|
||||
// @unsafe @global
|
||||
// export function __reset(): void { // special
|
||||
// offset = startOffset;
|
||||
// }
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@global @unsafe
|
||||
export function __retain(ref: usize): usize {
|
||||
return ref;
|
||||
}
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@global @unsafe
|
||||
export function __release(ref: usize): void {
|
||||
}
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@global @unsafe
|
||||
function __visit(ref: usize, cookie: u32): void {
|
||||
}
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@global @unsafe
|
||||
function __retainRelease(ref: usize, oldRef: usize): usize {
|
||||
return ref;
|
||||
}
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@global @unsafe
|
||||
export function __collect(): void {
|
||||
}
|
@ -476,7 +476,7 @@ export function allocateBlock(root: Root, size: usize): Block {
|
||||
if (DEBUG) assert(block); // must be found now
|
||||
}
|
||||
if (DEBUG) assert((block.mmInfo & ~TAGS_MASK) >= payloadSize); // must fit
|
||||
block.gcInfo = 1; // RC=1
|
||||
block.gcInfo = 0; // RC=0
|
||||
// block.rtId = 0; // set by the caller (__alloc)
|
||||
block.rtSize = size;
|
||||
removeBlock(root, <Block>block);
|
||||
@ -520,6 +520,7 @@ export function reallocateBlock(root: Root, block: Block, size: usize): Block {
|
||||
memory.copy(changetype<usize>(newBlock) + BLOCK_OVERHEAD, changetype<usize>(block) + BLOCK_OVERHEAD, size);
|
||||
block.mmInfo = blockInfo | FREE;
|
||||
insertBlock(root, block);
|
||||
if (isDefined(ASC_RTRACE)) onFree(block);
|
||||
return newBlock;
|
||||
}
|
||||
|
||||
@ -529,6 +530,7 @@ export function freeBlock(root: Root, block: Block): void {
|
||||
assert(!(blockInfo & FREE)); // must be used (user might call through to this)
|
||||
block.mmInfo = blockInfo | FREE;
|
||||
insertBlock(root, block);
|
||||
if (isDefined(ASC_RTRACE)) onFree(block);
|
||||
}
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@ -559,3 +561,7 @@ export function __free(ref: usize): void {
|
||||
assert(ref != 0 && !(ref & AL_MASK)); // must exist and be aligned
|
||||
freeBlock(ROOT, changetype<Block>(ref - BLOCK_OVERHEAD));
|
||||
}
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@external("rtrace", "free")
|
||||
declare function onFree(s: Block): void;
|
||||
|
Reference in New Issue
Block a user