mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-06-16 08:21:44 +00:00
optimize array literal init, warn on unsupported inlining
This commit is contained in:
@ -72,8 +72,11 @@ export class Array<T> extends ArrayBufferView {
|
||||
@operator("[]=") // unchecked is built-in
|
||||
private __set(index: i32, value: T): void {
|
||||
ensureCapacity(this, index + 1, alignof<T>());
|
||||
store<T>(this.dataStart + (<usize>index << alignof<T>()), value);
|
||||
if (isManaged<T>()) LINK(value, this);
|
||||
store<T>(this.dataStart + (<usize>index << alignof<T>()),
|
||||
isManaged<T>()
|
||||
? LINK<T,this>(value, this)
|
||||
: value
|
||||
);
|
||||
if (index >= this.length_) this.length_ = index + 1;
|
||||
}
|
||||
|
||||
@ -131,8 +134,11 @@ export class Array<T> extends ArrayBufferView {
|
||||
var newLength = this.length_ + 1;
|
||||
ensureCapacity(this, newLength, alignof<T>());
|
||||
this.length_ = newLength;
|
||||
store<T>(this.dataStart + (<usize>(newLength - 1) << alignof<T>()), element);
|
||||
if (isManaged<T>()) LINK(element, this);
|
||||
store<T>(this.dataStart + (<usize>(newLength - 1) << alignof<T>()),
|
||||
isManaged<T>()
|
||||
? LINK<T,this>(element, this)
|
||||
: element
|
||||
);
|
||||
return newLength;
|
||||
}
|
||||
|
||||
@ -146,15 +152,13 @@ export class Array<T> extends ArrayBufferView {
|
||||
let thisStart = this.dataStart;
|
||||
for (let offset: usize = 0; offset < thisSize; offset += sizeof<T>()) {
|
||||
let element = load<T>(thisStart + offset);
|
||||
store<T>(outStart + offset, element);
|
||||
LINK(element, out);
|
||||
store<T>(outStart + offset, LINK<T,Array<T>>(element, out));
|
||||
}
|
||||
let otherStart = other.dataStart;
|
||||
let otherSize = <usize>otherLen << alignof<T>();
|
||||
for (let offset: usize = 0; offset < otherSize; offset += sizeof<T>()) {
|
||||
let element = load<T>(otherStart + offset);
|
||||
store<T>(outStart + thisSize + offset, element);
|
||||
LINK(element, out);
|
||||
store<T>(outStart + thisSize + offset, LINK<T,Array<T>>(element, out));
|
||||
}
|
||||
} else {
|
||||
memory.copy(outStart, this.dataStart, thisSize);
|
||||
@ -211,8 +215,11 @@ export class Array<T> extends ArrayBufferView {
|
||||
for (let index = 0; index < min(length, this.length_); ++index) {
|
||||
let value = load<T>(this.dataStart + (<usize>index << alignof<T>()));
|
||||
let result = callbackfn(value, index, this);
|
||||
store<U>(outStart + (<usize>index << alignof<U>()), result);
|
||||
if (isManaged<U>()) LINK(result, out);
|
||||
store<U>(outStart + (<usize>index << alignof<U>()),
|
||||
isManaged<U>()
|
||||
? LINK<U,Array<U>>(result, out)
|
||||
: result
|
||||
);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
@ -283,8 +290,11 @@ export class Array<T> extends ArrayBufferView {
|
||||
base,
|
||||
<usize>(newLength - 1) << alignof<T>()
|
||||
);
|
||||
store<T>(base, element);
|
||||
if (isManaged<T>()) LINK(element, this);
|
||||
store<T>(base,
|
||||
isManaged<T>()
|
||||
? LINK<T,this>(element, this)
|
||||
: element
|
||||
);
|
||||
this.length_ = newLength;
|
||||
return newLength;
|
||||
}
|
||||
@ -300,8 +310,11 @@ export class Array<T> extends ArrayBufferView {
|
||||
for (let i = 0; i < length; ++i) {
|
||||
let offset = <usize>i << alignof<T>();
|
||||
let element = load<T>(thisBase + offset);
|
||||
store<T>(sliceBase + offset, element);
|
||||
if (isManaged<T>()) LINK(element, slice);
|
||||
store<T>(sliceBase + offset,
|
||||
isManaged<T>()
|
||||
? LINK<T,Array<T>>(element, slice)
|
||||
: element
|
||||
);
|
||||
}
|
||||
return slice;
|
||||
}
|
||||
@ -316,8 +329,11 @@ export class Array<T> extends ArrayBufferView {
|
||||
var thisBase = thisStart + (<usize>start << alignof<T>());
|
||||
for (let i = 0; i < deleteCount; ++i) {
|
||||
let element = load<T>(thisBase + (<usize>i << alignof<T>()));
|
||||
store<T>(spliceStart + (<usize>i << alignof<T>()), element);
|
||||
if (isManaged<T>()) LINK(element, splice);
|
||||
store<T>(spliceStart + (<usize>i << alignof<T>()),
|
||||
isManaged<T>()
|
||||
? LINK<T,Array<T>>(element, splice)
|
||||
: element
|
||||
);
|
||||
}
|
||||
memory.copy(
|
||||
splice.dataStart,
|
||||
|
@ -2,7 +2,7 @@ import { ALLOCATE, REGISTER, HEADER, HEADER_SIZE, MAX_BYTELENGTH } from "./runti
|
||||
|
||||
@sealed export class ArrayBuffer {
|
||||
|
||||
@inline static isView<T>(value: T): bool {
|
||||
static isView<T>(value: T): bool {
|
||||
if (value) {
|
||||
if (value instanceof Int8Array) return true;
|
||||
if (value instanceof Uint8Array) return true;
|
||||
|
@ -58,14 +58,17 @@ export declare function isConstant(expression: void): bool;
|
||||
@builtin
|
||||
export declare function isManaged<T>(value?: T): bool;
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@inline
|
||||
export function isNaN<T>(value: T): bool { return value != value; }
|
||||
export function isNaN<T extends number>(value: T): bool {
|
||||
if (!isFloat<T>()) {
|
||||
if (!isInteger<T>()) ERROR("numeric type expected");
|
||||
}
|
||||
return value != value;
|
||||
}
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@inline
|
||||
export function isFinite<T>(value: T): bool {
|
||||
// @ts-ignore: type
|
||||
export function isFinite<T extends number>(value: T): bool {
|
||||
if (!isFloat<T>()) {
|
||||
if (!isInteger<T>()) ERROR("numeric type expected");
|
||||
}
|
||||
return value - value == 0;
|
||||
}
|
||||
|
||||
|
@ -119,15 +119,18 @@ export class Map<K,V> {
|
||||
entry = changetype<MapEntry<K,V>>(
|
||||
changetype<usize>(entries) + this.entriesOffset++ * ENTRY_SIZE<K,V>()
|
||||
);
|
||||
entry.key = key;
|
||||
entry.value = value;
|
||||
// link with the map (entry is unmanaged)
|
||||
entry.key = isManaged<K>()
|
||||
? LINK<K,this>(key, this)
|
||||
: key;
|
||||
entry.value = isManaged<V>()
|
||||
? LINK<V,this>(value, this)
|
||||
: value;
|
||||
++this.entriesCount;
|
||||
// link with previous entry in bucket
|
||||
let bucketPtrBase = changetype<usize>(this.buckets) + <usize>(hashCode & this.bucketsMask) * BUCKET_SIZE;
|
||||
entry.taggedNext = load<usize>(bucketPtrBase);
|
||||
store<usize>(bucketPtrBase, changetype<usize>(entry));
|
||||
if (isManaged<K>()) LINK(key, this);
|
||||
if (isManaged<V>()) LINK(value, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,10 +137,11 @@ function doRegister(ref: usize, classId: u32): usize {
|
||||
/** Links a registered object with the (registered) object now referencing it. */
|
||||
// @ts-ignore: decorator
|
||||
@unsafe @inline
|
||||
export function LINK<T,TParent>(ref: T, parentRef: TParent): void {
|
||||
if (!isReference<T>()) ERROR("reference expected");
|
||||
if (!isReference<TParent>()) ERROR("reference expected");
|
||||
export function LINK<T,TParent>(ref: T, parentRef: TParent): T {
|
||||
if (!isManaged<T>()) ERROR("managed reference expected");
|
||||
if (!isManaged<TParent>()) ERROR("managed reference expected");
|
||||
doLink(changetype<usize>(ref), changetype<usize>(parentRef));
|
||||
return ref;
|
||||
}
|
||||
|
||||
function doLink(ref: usize, parentRef: usize): void {
|
||||
|
@ -88,11 +88,11 @@ export class Set<K> {
|
||||
}
|
||||
|
||||
has(key: K): bool {
|
||||
return this.find(key, HASH(key)) !== null;
|
||||
return this.find(key, HASH<K>(key)) !== null;
|
||||
}
|
||||
|
||||
add(key: K): void {
|
||||
var hashCode = HASH(key);
|
||||
var hashCode = HASH<K>(key);
|
||||
var entry = this.find(key, hashCode);
|
||||
if (!entry) {
|
||||
// check if rehashing is necessary
|
||||
@ -108,13 +108,15 @@ export class Set<K> {
|
||||
entry = changetype<SetEntry<K>>(
|
||||
changetype<usize>(entries) + this.entriesOffset++ * ENTRY_SIZE<K>()
|
||||
);
|
||||
entry.key = key;
|
||||
// link with the set itself (entry is unmanaged)
|
||||
entry.key = isManaged<K>()
|
||||
? LINK<K,this>(key, this)
|
||||
: key;
|
||||
++this.entriesCount;
|
||||
// link with previous entry in bucket
|
||||
let bucketPtrBase = changetype<usize>(this.buckets) + <usize>(hashCode & this.bucketsMask) * BUCKET_SIZE;
|
||||
entry.taggedNext = load<usize>(bucketPtrBase);
|
||||
store<usize>(bucketPtrBase, changetype<usize>(entry));
|
||||
if (isManaged<K>()) LINK(key, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -362,8 +362,12 @@ import { compareImpl, parse, CharCode, isWhiteSpaceOrLineTerminator } from "./ut
|
||||
charStr,
|
||||
load<u16>(changetype<usize>(this) + (<usize>i << 1))
|
||||
);
|
||||
store<usize>(resultStart + (<usize>i << alignof<usize>()), REGISTER<String>(charStr)); // result[i] = charStr
|
||||
if (isManaged<String>()) LINK(changetype<String>(charStr), result);
|
||||
// result[i] = charStr
|
||||
store<String>(resultStart + (<usize>i << alignof<usize>()),
|
||||
isManaged<String>()
|
||||
? LINK<String,Array<String>>(REGISTER<String>(charStr), result)
|
||||
: REGISTER<String>(charStr)
|
||||
);
|
||||
}
|
||||
return result;
|
||||
} else if (!length) {
|
||||
|
@ -620,8 +620,8 @@ export function dtoa_core(buffer: usize, value: f64): i32 {
|
||||
|
||||
export function dtoa(value: f64): String {
|
||||
if (value == 0) return "0.0";
|
||||
if (!isFinite(value)) {
|
||||
if (isNaN(value)) return "NaN";
|
||||
if (!isFinite<f64>(value)) {
|
||||
if (isNaN<f64>(value)) return "NaN";
|
||||
return select<String>("-Infinity", "Infinity", value < 0);
|
||||
}
|
||||
var temp = ALLOCATE(MAX_DOUBLE_LENGTH << 1);
|
||||
@ -681,8 +681,8 @@ export function dtoa_stream(buffer: usize, offset: usize, value: f64): u32 {
|
||||
store<u16>(buffer, CharCode._0, 4);
|
||||
return 3;
|
||||
}
|
||||
if (!isFinite(value)) {
|
||||
if (isNaN(value)) {
|
||||
if (!isFinite<f64>(value)) {
|
||||
if (isNaN<f64>(value)) {
|
||||
store<u16>(buffer, CharCode.N);
|
||||
store<u16>(buffer, CharCode.a, 2);
|
||||
store<u16>(buffer, CharCode.N, 4);
|
||||
|
Reference in New Issue
Block a user