From 5fb708eb4901497023944a4e468d2e0e6060f105 Mon Sep 17 00:00:00 2001 From: dcode Date: Wed, 17 Jun 2020 09:23:30 +0200 Subject: [PATCH 1/2] Fix assertion when trying to inline virtual (super) calls --- src/compiler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler.ts b/src/compiler.ts index 8e6ac83679..8aa2656146 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -6927,7 +6927,7 @@ export class Compiler extends DiagnosticEmitter { if (instance.hasDecorator(DecoratorFlags.UNSAFE)) this.checkUnsafe(reportNode); // Inline if explicitly requested - if (instance.hasDecorator(DecoratorFlags.INLINE)) { + if (instance.hasDecorator(DecoratorFlags.INLINE) && !instance.is(CommonFlags.VIRTUAL)) { assert(!instance.is(CommonFlags.STUB)); // doesn't make sense let inlineStack = this.inlineStack; if (inlineStack.includes(instance)) { From b420d165fcee0626b5fbf52cb3b97bfd11196bc9 Mon Sep 17 00:00:00 2001 From: dcode Date: Wed, 17 Jun 2020 13:38:28 +0200 Subject: [PATCH 2/2] inline super xy calls --- src/compiler.ts | 4 +- tests/compiler/super-inline.json | 5 + tests/compiler/super-inline.optimized.wat | 104 +++++++++++ tests/compiler/super-inline.ts | 14 ++ tests/compiler/super-inline.untouched.wat | 212 ++++++++++++++++++++++ 5 files changed, 336 insertions(+), 3 deletions(-) create mode 100644 tests/compiler/super-inline.json create mode 100644 tests/compiler/super-inline.optimized.wat create mode 100644 tests/compiler/super-inline.ts create mode 100644 tests/compiler/super-inline.untouched.wat diff --git a/src/compiler.ts b/src/compiler.ts index 8aa2656146..0c6614477d 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -6927,7 +6927,7 @@ export class Compiler extends DiagnosticEmitter { if (instance.hasDecorator(DecoratorFlags.UNSAFE)) this.checkUnsafe(reportNode); // Inline if explicitly requested - if (instance.hasDecorator(DecoratorFlags.INLINE) && !instance.is(CommonFlags.VIRTUAL)) { + if (instance.hasDecorator(DecoratorFlags.INLINE) && (!instance.is(CommonFlags.VIRTUAL) || reportNode.isCallOnSuper)) { assert(!instance.is(CommonFlags.STUB)); // doesn't make sense let inlineStack = this.inlineStack; if (inlineStack.includes(instance)) { @@ -6999,8 +6999,6 @@ export class Compiler extends DiagnosticEmitter { thisArg: ExpressionRef = 0, immediatelyDropped: bool = false ): ExpressionRef { - assert(!instance.is(CommonFlags.VIRTUAL)); - var module = this.module; var numArguments = operands ? operands.length : 0; var signature = instance.signature; diff --git a/tests/compiler/super-inline.json b/tests/compiler/super-inline.json new file mode 100644 index 0000000000..b1da366ff4 --- /dev/null +++ b/tests/compiler/super-inline.json @@ -0,0 +1,5 @@ +{ + "asc_flags": [ + "--runtime none" + ] +} \ No newline at end of file diff --git a/tests/compiler/super-inline.optimized.wat b/tests/compiler/super-inline.optimized.wat new file mode 100644 index 0000000000..d310e637fb --- /dev/null +++ b/tests/compiler/super-inline.optimized.wat @@ -0,0 +1,104 @@ +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $none_=>_none (func)) + (memory $0 0) + (global $~lib/rt/stub/offset (mut i32) (i32.const 0)) + (global $super-inline/foo (mut i32) (i32.const 0)) + (export "memory" (memory $0)) + (start $~start) + (func $~lib/rt/stub/__alloc (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + global.get $~lib/rt/stub/offset + i32.const 16 + i32.add + local.tee $3 + i32.const 16 + i32.add + local.tee $1 + memory.size + local.tee $4 + i32.const 16 + i32.shl + local.tee $2 + i32.gt_u + if + local.get $4 + local.get $1 + local.get $2 + i32.sub + i32.const 65535 + i32.add + i32.const -65536 + i32.and + i32.const 16 + i32.shr_u + local.tee $2 + local.get $4 + local.get $2 + i32.gt_s + select + memory.grow + i32.const 0 + i32.lt_s + if + local.get $2 + memory.grow + i32.const 0 + i32.lt_s + if + unreachable + end + end + end + local.get $1 + global.set $~lib/rt/stub/offset + local.get $3 + i32.const 16 + i32.sub + local.tee $1 + i32.const 16 + i32.store + local.get $1 + i32.const 1 + i32.store offset=4 + local.get $1 + local.get $0 + i32.store offset=8 + local.get $1 + i32.const 0 + i32.store offset=12 + local.get $3 + ) + (func $super-inline/Foo#constructor (param $0 i32) (result i32) + local.get $0 + if (result i32) + local.get $0 + else + i32.const 3 + call $~lib/rt/stub/__alloc + end + ) + (func $~start + i32.const 1024 + global.set $~lib/rt/stub/offset + i32.const 0 + call $super-inline/Foo#constructor + global.set $super-inline/foo + block $__inlined_func$super-inline/Foo#a@virtual + global.get $super-inline/foo + i32.const 8 + i32.sub + i32.load + i32.const 4 + i32.eq + br_if $__inlined_func$super-inline/Foo#a@virtual + end + i32.const 4 + call $~lib/rt/stub/__alloc + call $super-inline/Foo#constructor + drop + ) +) diff --git a/tests/compiler/super-inline.ts b/tests/compiler/super-inline.ts new file mode 100644 index 0000000000..de21923a04 --- /dev/null +++ b/tests/compiler/super-inline.ts @@ -0,0 +1,14 @@ +class Foo { + @inline + a(): i32 { return 1; } +} + +class Bar extends Foo { + a(): i32 { return super.a(); } // no AS228 +} + +var foo = new Foo(); +foo.a(); // AS228 + +var bar = new Bar(); +bar.a(); diff --git a/tests/compiler/super-inline.untouched.wat b/tests/compiler/super-inline.untouched.wat new file mode 100644 index 0000000000..798dcad8b1 --- /dev/null +++ b/tests/compiler/super-inline.untouched.wat @@ -0,0 +1,212 @@ +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (memory $0 0) + (table $0 1 funcref) + (global $~lib/rt/stub/startOffset (mut i32) (i32.const 0)) + (global $~lib/rt/stub/offset (mut i32) (i32.const 0)) + (global $super-inline/foo (mut i32) (i32.const 0)) + (global $super-inline/bar (mut i32) (i32.const 0)) + (global $~lib/heap/__heap_base i32 (i32.const 8)) + (export "memory" (memory $0)) + (start $~start) + (func $~lib/rt/stub/maybeGrowMemory (param $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + memory.size + local.set $1 + local.get $1 + i32.const 16 + i32.shl + local.set $2 + local.get $0 + local.get $2 + i32.gt_u + if + local.get $0 + local.get $2 + i32.sub + i32.const 65535 + i32.add + i32.const 65535 + i32.const -1 + i32.xor + i32.and + i32.const 16 + i32.shr_u + local.set $3 + local.get $1 + local.tee $4 + local.get $3 + local.tee $5 + local.get $4 + local.get $5 + i32.gt_s + select + local.set $4 + local.get $4 + memory.grow + i32.const 0 + i32.lt_s + if + local.get $3 + memory.grow + i32.const 0 + i32.lt_s + if + unreachable + end + end + end + local.get $0 + global.set $~lib/rt/stub/offset + ) + (func $~lib/rt/stub/__alloc (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + local.get $0 + i32.const 1073741808 + i32.gt_u + if + unreachable + end + global.get $~lib/rt/stub/offset + i32.const 16 + i32.add + local.set $2 + local.get $0 + i32.const 15 + i32.add + i32.const 15 + i32.const -1 + i32.xor + i32.and + local.tee $3 + i32.const 16 + local.tee $4 + local.get $3 + local.get $4 + i32.gt_u + select + local.set $5 + local.get $2 + local.get $5 + i32.add + call $~lib/rt/stub/maybeGrowMemory + local.get $2 + i32.const 16 + i32.sub + local.set $6 + local.get $6 + local.get $5 + i32.store + i32.const 1 + drop + local.get $6 + i32.const 1 + i32.store offset=4 + local.get $6 + local.get $1 + i32.store offset=8 + local.get $6 + local.get $0 + i32.store offset=12 + local.get $2 + ) + (func $~lib/rt/stub/__retain (param $0 i32) (result i32) + local.get $0 + ) + (func $super-inline/Foo#constructor (param $0 i32) (result i32) + local.get $0 + i32.eqz + if + i32.const 0 + i32.const 3 + call $~lib/rt/stub/__alloc + call $~lib/rt/stub/__retain + local.set $0 + end + local.get $0 + ) + (func $super-inline/Foo#a (param $0 i32) (result i32) + i32.const 1 + ) + (func $super-inline/Bar#constructor (param $0 i32) (result i32) + local.get $0 + i32.eqz + if + i32.const 0 + i32.const 4 + call $~lib/rt/stub/__alloc + call $~lib/rt/stub/__retain + local.set $0 + end + local.get $0 + call $super-inline/Foo#constructor + local.set $0 + local.get $0 + ) + (func $super-inline/Bar#a (param $0 i32) (result i32) + (local $1 i32) + local.get $0 + local.set $1 + i32.const 1 + ) + (func $start:super-inline + global.get $~lib/heap/__heap_base + i32.const 15 + i32.add + i32.const 15 + i32.const -1 + i32.xor + i32.and + global.set $~lib/rt/stub/startOffset + global.get $~lib/rt/stub/startOffset + global.set $~lib/rt/stub/offset + i32.const 0 + call $super-inline/Foo#constructor + global.set $super-inline/foo + global.get $super-inline/foo + call $super-inline/Foo#a@virtual + drop + i32.const 0 + call $super-inline/Bar#constructor + global.set $super-inline/bar + global.get $super-inline/bar + call $super-inline/Bar#a + drop + ) + (func $~start + call $start:super-inline + ) + (func $super-inline/Foo#a@virtual (param $0 i32) (result i32) + (local $1 i32) + block $default + block $case0 + local.get $0 + i32.const 8 + i32.sub + i32.load + local.set $1 + local.get $1 + i32.const 4 + i32.eq + br_if $case0 + br $default + end + local.get $0 + call $super-inline/Bar#a + return + end + local.get $0 + call $super-inline/Foo#a + ) +)