Skip to content

Tackle the case of === #1111

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
213 changes: 156 additions & 57 deletions src/compiler.ts

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -779,7 +779,7 @@ export class Module {
): ExpressionRef {
if (type == NativeType.Auto) {
type = binaryen._BinaryenExpressionGetType(ifTrue);
assert(type == binaryen._BinaryenExpressionGetType(ifFalse));
// assert(type == binaryen._BinaryenExpressionGetType(ifFalse));
}
return binaryen._BinaryenSelect(this.ref, condition, ifTrue, ifFalse, type);
}
Expand Down
31 changes: 31 additions & 0 deletions src/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3118,6 +3118,37 @@ export class Function extends TypedElement {
}
}
}

/** Gets the value type of an unary operator overload. */
get unaryOverloadValueType(): Type {
if (this.is(CommonFlags.INSTANCE)) {
return assert(this.signature.thisType);
}
var parameterTypes = this.signature.parameterTypes;
assert(parameterTypes.length >= 1);
return parameterTypes[0];
}

/** Gets the left type of a binary operator overload. */
get binaryOverloadLeftType(): Type {
if (this.is(CommonFlags.INSTANCE)) {
return assert(this.signature.thisType);
}
var parameterTypes = this.signature.parameterTypes;
assert(parameterTypes.length >= 2);
return parameterTypes[0];
}

/** Gets the right type of a binary operator overload. */
get binaryOverloadRightType(): Type {
var parameterTypes = this.signature.parameterTypes;
if (this.is(CommonFlags.INSTANCE)) {
assert(parameterTypes.length >= 1);
return parameterTypes[0];
}
assert(parameterTypes.length >= 2);
return parameterTypes[1];
}
}

var nextFunctionTarget = 0;
Expand Down
15 changes: 7 additions & 8 deletions std/assembly/array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ function ensureSize(array: usize, minSize: usize, alignLog2: u32): void {
let newCapacity = minSize << alignLog2;
let newData = __realloc(oldData, newCapacity); // keeps RC
memory.fill(newData + oldCapacity, 0, newCapacity - oldCapacity);
if (newData !== oldData) { // oldData has been free'd
if (changetype<usize>(newData) != changetype<usize>(oldData)) { // oldData has been free'd
store<usize>(array, newData, offsetof<ArrayBufferView>("buffer"));
store<usize>(array, newData, offsetof<ArrayBufferView>("dataStart"));
}
Expand All @@ -43,7 +43,10 @@ export class Array<T> {
private length_: i32;

static isArray<U>(value: U): bool {
return isReference<U>() ? builtin_isArray(value) && value !== null : false;
if (isReference<U>()) {
return value instanceof Array && changetype<usize>(value) != 0;
}
return false;
}

static create<T>(capacity: i32 = 0): Array<T> {
Expand Down Expand Up @@ -224,7 +227,7 @@ export class Array<T> {

concat(other: Array<T>): Array<T> {
var thisLen = this.length_;
var otherLen = select(0, other.length_, other === null);
var otherLen = select(0, other.length_, changetype<usize>(other) == 0);
var outLen = thisLen + otherLen;
if (<u32>outLen > <u32>BLOCK_MAXSIZE >>> alignof<T>()) throw new Error(E_INVALIDLENGTH);
var out = changetype<Array<T>>(__allocArray(outLen, alignof<T>(), idof<Array<T>>())); // retains
Expand Down Expand Up @@ -483,11 +486,7 @@ export class Array<T> {
if (isBoolean<T>()) return joinBooleanArray(dataStart, length, separator);
if (isInteger<T>()) return joinIntegerArray<T>(dataStart, length, separator);
if (isFloat<T>()) return joinFloatArray<T>(dataStart, length, separator);

if (ASC_SHRINK_LEVEL < 1) {
if (isString<T>()) return joinStringArray(dataStart, length, separator);
}
// For rest objects and arrays use general join routine
Comment on lines -486 to -490
Copy link
Member

@MaxGraey MaxGraey Feb 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, this conditional guard potentially decreased code size so recommend leave as is

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, not sure about this one as well. Removed it because joinReferenceArray wasn't compatible with strings anymore, but there's probably something better we can do.

if (isString<T>()) return joinStringArray(dataStart, length, separator);
if (isReference<T>()) return joinReferenceArray<T>(dataStart, length, separator);
ERROR("unspported element type");
return <string>unreachable();
Expand Down
30 changes: 16 additions & 14 deletions std/assembly/arraybuffer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,23 @@ export abstract class ArrayBufferView {
@sealed export class ArrayBuffer {

static isView<T>(value: T): bool {
if (isNullable<T>()) {
if (value === null) return false;
if (isReference<T>()) {
if (isNullable<T>()) {
if (!changetype<usize>(value)) return false;
}
if (value instanceof Int8Array) return true;
if (value instanceof Uint8Array) return true;
if (value instanceof Uint8ClampedArray) return true;
if (value instanceof Int16Array) return true;
if (value instanceof Uint16Array) return true;
if (value instanceof Int32Array) return true;
if (value instanceof Uint32Array) return true;
if (value instanceof Int64Array) return true;
if (value instanceof Uint64Array) return true;
if (value instanceof Float32Array) return true;
if (value instanceof Float64Array) return true;
if (value instanceof DataView) return true;
}
if (value instanceof Int8Array) return true;
if (value instanceof Uint8Array) return true;
if (value instanceof Uint8ClampedArray) return true;
if (value instanceof Int16Array) return true;
if (value instanceof Uint16Array) return true;
if (value instanceof Int32Array) return true;
if (value instanceof Uint32Array) return true;
if (value instanceof Int64Array) return true;
if (value instanceof Uint64Array) return true;
if (value instanceof Float32Array) return true;
if (value instanceof Float64Array) return true;
if (value instanceof DataView) return true;
return false;
}

Expand Down
2 changes: 1 addition & 1 deletion std/assembly/map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export class Map<K,V> {
}

has(key: K): bool {
return this.find(key, HASH<K>(key)) !== null;
return changetype<usize>(this.find(key, HASH<K>(key))) != 0;
}

@operator("[]")
Expand Down
10 changes: 5 additions & 5 deletions std/assembly/rt/pure.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { DEBUG, BLOCK_OVERHEAD } from "rt/common";
import { Block, freeBlock, ROOT } from "rt/tlsf";
import { Block, freeBlock, Root, ROOT } from "rt/tlsf";
import { TypeinfoFlags } from "shared/typeinfo";
import { onincrement, ondecrement, onfree, onalloc } from "./rtrace";

Expand Down Expand Up @@ -124,10 +124,10 @@ function decrement(s: Block): void {
__visit_members(changetype<usize>(s) + BLOCK_OVERHEAD, VISIT_DECREMENT);
if (isDefined(__GC_ALL_ACYCLIC)) {
if (DEBUG) assert(!(info & BUFFERED_MASK));
freeBlock(ROOT, s);
freeBlock(changetype<Root>(ROOT), s);
} else {
if (!(info & BUFFERED_MASK)) {
freeBlock(ROOT, s);
freeBlock(changetype<Root>(ROOT), s);
} else {
s.gcInfo = BUFFERED_MASK | COLOR_BLACK | 0;
}
Expand Down Expand Up @@ -205,7 +205,7 @@ export function __collect(): void {
cur += sizeof<usize>();
} else {
if ((info & COLOR_MASK) == COLOR_BLACK && !(info & REFCOUNT_MASK)) {
freeBlock(ROOT, s);
freeBlock(changetype<Root>(ROOT), s);
} else {
s.gcInfo = info & ~BUFFERED_MASK;
}
Expand Down Expand Up @@ -261,7 +261,7 @@ function collectWhite(s: Block): void {
if ((info & COLOR_MASK) == COLOR_WHITE && !(info & BUFFERED_MASK)) {
s.gcInfo = (info & ~COLOR_MASK) | COLOR_BLACK;
__visit_members(changetype<usize>(s) + BLOCK_OVERHEAD, VISIT_COLLECTWHITE);
freeBlock(ROOT, s);
freeBlock(changetype<Root>(ROOT), s);
}
}

Expand Down
4 changes: 2 additions & 2 deletions std/assembly/rt/tlsf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ import { REFCOUNT_MASK } from "./pure";
// │ tail │ ◄────┘
// └───────────────────────────────────────────────────────────────┘ SIZE ┘
// S: Small blocks map
@unmanaged class Root {
@unmanaged export class Root {
/** First level bitmap. */
flMap: usize;
}
Expand All @@ -141,7 +141,7 @@ import { REFCOUNT_MASK } from "./pure";
@inline const ROOT_SIZE: usize = HL_END + sizeof<usize>();

// @ts-ignore: decorator
@lazy export var ROOT: Root;
@lazy export var ROOT: Root | null;

/** Gets the second level map of the specified first level. */
// @ts-ignore: decorator
Expand Down
2 changes: 1 addition & 1 deletion std/assembly/set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export class Set<T> {

@operator("[]")
has(key: T): bool {
return this.find(key, HASH<T>(key)) !== null;
return changetype<usize>(this.find(key, HASH<T>(key))) != 0;
}

add(key: T): this {
Expand Down
40 changes: 20 additions & 20 deletions std/assembly/staticarray.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,22 @@ export class StaticArray<T> {
static fromArray<T>(source: Array<T>): StaticArray<T> {
var length = source.length;
var outSize = <usize>length << alignof<T>();
var out = __alloc(outSize, idof<StaticArray<T>>());
var outPtr = __alloc(outSize, idof<StaticArray<T>>());
var srcPtr = load<usize>(changetype<usize>(source), offsetof<Array<T>>("dataStart"));
if (isManaged<T>()) {
let sourcePtr = source.dataStart;
for (let i = 0; i < length; ++i) {
let off = <usize>i << alignof<T>();
store<usize>(out + off, __retain(load<usize>(sourcePtr + off)));
store<usize>(outPtr + off, __retain(load<usize>(srcPtr + off)));
}
} else {
memory.copy(out, source.dataStart, outSize);
memory.copy(outPtr, srcPtr, outSize);
}
return changetype<StaticArray<T>>(out);
return changetype<StaticArray<T>>(outPtr);
}

static concat<T>(source: StaticArray<T>, other: StaticArray<T>): StaticArray<T> {
var sourceLen = source.length;
var otherLen = select(0, other.length, other === null);
var otherLen = select(0, other.length, changetype<usize>(other) == 0);
var outLen = sourceLen + otherLen;
if (<u32>outLen > <u32>BLOCK_MAXSIZE >>> alignof<T>()) throw new Error(E_INVALIDLENGTH);
var out = changetype<StaticArray<T>>(__alloc(<usize>outLen << alignof<T>(), idof<StaticArray<T>>())); // retains
Expand Down Expand Up @@ -166,28 +166,28 @@ export class StaticArray<T> {

concat(other: Array<T>): Array<T> {
var thisLen = this.length;
var otherLen = select(0, other.length, other === null);
var otherLen = select(0, other.length, changetype<usize>(other) == 0);
var outLen = thisLen + otherLen;
if (<u32>outLen > <u32>BLOCK_MAXSIZE >>> alignof<T>()) throw new Error(E_INVALIDLENGTH);
var out = changetype<Array<T>>(__allocArray(outLen, alignof<T>(), idof<Array<T>>())); // retains
var outStart = out.dataStart;
var outPtr = load<usize>(changetype<usize>(out), offsetof<Array<T>>("dataStart"));
var otherPtr = load<usize>(changetype<usize>(other), offsetof<Array<T>>("dataStart"));
var thisSize = <usize>thisLen << alignof<T>();
if (isManaged<T>()) {
let thisStart = changetype<usize>(this);
for (let offset: usize = 0; offset < thisSize; offset += sizeof<T>()) {
let ref = load<usize>(thisStart + offset);
store<usize>(outStart + offset, __retain(ref));
store<usize>(outPtr + offset, __retain(ref));
}
outStart += thisSize;
let otherStart = other.dataStart;
outPtr += thisSize;
let otherSize = <usize>otherLen << alignof<T>();
for (let offset: usize = 0; offset < otherSize; offset += sizeof<T>()) {
let ref = load<usize>(otherStart + offset);
store<usize>(outStart + offset, __retain(ref));
let ref = load<usize>(otherPtr + offset);
store<usize>(outPtr + offset, __retain(ref));
}
} else {
memory.copy(outStart, changetype<usize>(this), thisSize);
memory.copy(outStart + thisSize, other.dataStart, <usize>otherLen << alignof<T>());
memory.copy(outPtr, changetype<usize>(this), thisSize);
memory.copy(outPtr + thisSize, otherPtr, <usize>otherLen << alignof<T>());
}
return out;
}
Expand All @@ -198,18 +198,18 @@ export class StaticArray<T> {
end = end < 0 ? max(end + length, 0) : min(end , length);
length = max(end - start, 0);
var slice = changetype<Array<T>>(__allocArray(length, alignof<T>(), idof<Array<T>>())); // retains
var sliceBase = slice.dataStart;
var thisBase = changetype<usize>(this) + (<usize>start << alignof<T>());
var slicePtr = load<usize>(changetype<usize>(slice), offsetof<Array<T>>("dataStart"));
var thisPtr = changetype<usize>(this) + (<usize>start << alignof<T>());
if (isManaged<T>()) {
let off = <usize>0;
let end = <usize>length << alignof<usize>();
while (off < end) {
let ref = load<usize>(thisBase + off);
store<usize>(sliceBase + off, __retain(ref));
let ref = load<usize>(thisPtr + off);
store<usize>(slicePtr + off, __retain(ref));
off += sizeof<usize>();
}
} else {
memory.copy(sliceBase, thisBase, length << alignof<T>());
memory.copy(slicePtr, thisPtr, length << alignof<T>());
}
return slice;
}
Expand Down
Loading