Skip to content

fix: Account for virtual stub finalization discovering more virtual calls #1569

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

Merged
merged 2 commits into from
Dec 8, 2020
Merged
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
10 changes: 7 additions & 3 deletions src/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -530,9 +530,13 @@ export class Compiler extends DiagnosticEmitter {
}
}
var virtualCalls = this.virtualCalls;
for (let _values = Set_values(virtualCalls), i = 0, k = _values.length; i < k; ++i) {
let instance = unchecked(_values[i]);
this.finalizeVirtualStub(instance);
while (virtualCalls.size) {
// finalizing a stub may discover more virtual calls, so do this in a loop
for (let _values = Set_values(virtualCalls), i = 0, k = _values.length; i < k; ++i) {
let instance = unchecked(_values[i]);
this.finalizeVirtualStub(instance);
virtualCalls.delete(instance);
}
}

// finalize runtime features
Expand Down
52 changes: 51 additions & 1 deletion tests/compiler/class-overloading.optimized.wat
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@
(data (i32.const 1228) "\02\00\00\00\01\00\00\00\00\00\00\00\01\00\00\00\02\00\00\00F")
(data (i32.const 1260) "\04\00\00\00\01\00\00\00\00\00\00\00\01\00\00\00\04\00\00\00I\00B")
(data (i32.const 1292) "\04\00\00\00\01\00\00\00\00\00\00\00\01\00\00\00\04\00\00\00I\00C")
(data (i32.const 1324) "\1e\00\00\00\01\00\00\00\00\00\00\00\01\00\00\00\1e\00\00\00n\00o\00t\00 \00i\00m\00p\00l\00e\00m\00e\00n\00t\00e\00d")
(global $class-overloading/which (mut i32) (i32.const 1056))
(global $~lib/rt/stub/offset (mut i32) (i32.const 0))
(global $class-overloading/a (mut i32) (i32.const 0))
(global $class-overloading/ia (mut i32) (i32.const 0))
(global $class-overloading/ic (mut i32) (i32.const 0))
(global $class-overloading/b2 (mut i32) (i32.const 0))
(global $~started (mut i32) (i32.const 0))
(export "_start" (func $~start))
(export "memory" (memory $0))
Expand Down Expand Up @@ -264,7 +266,8 @@
call $class-overloading/B#constructor
)
(func $start:class-overloading
i32.const 1324
(local $0 i32)
i32.const 1388
global.set $~lib/rt/stub/offset
i32.const 0
call $class-overloading/B#constructor
Expand Down Expand Up @@ -633,6 +636,53 @@
call $~lib/builtins/abort
unreachable
end
i32.const 14
call $~lib/rt/stub/__new
local.tee $0
if (result i32)
local.get $0
else
i32.const 13
call $~lib/rt/stub/__new
end
global.set $class-overloading/b2
block $__inlined_func$class-overloading/A2#foo@virtual
global.get $class-overloading/b2
i32.const 8
i32.sub
i32.load
i32.const 14
i32.eq
if
i32.const 15
call $~lib/rt/stub/__new
local.tee $0
if (result i32)
local.get $0
else
i32.const 16
call $~lib/rt/stub/__new
end
i32.const 8
i32.sub
i32.load
i32.const 15
i32.eq
br_if $__inlined_func$class-overloading/A2#foo@virtual
i32.const 1344
i32.const 1152
i32.const 186
i32.const 5
call $~lib/builtins/abort
unreachable
end
i32.const 1344
i32.const 1152
i32.const 198
i32.const 5
call $~lib/builtins/abort
unreachable
end
)
(func $~start
global.get $~started
Expand Down
32 changes: 32 additions & 0 deletions tests/compiler/class-overloading.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,35 @@ var ic: IC = new CC();
which = "";
ic.foo();
assert(which == "IC");

// Should make stubs for functions discovered when compiling other virtual stubs
class A1 {
public bar(): i32 {
return this.baz();
// 4) discovers A1#baz
}
public baz(): i32 {
throw new Error("not implemented");
// 5) discovers B1#baz (overload)
}
}
class B1 extends A1 {
public baz(): i32 {
return 3;
// 6) complete
}
}
class A2 {
foo(): i32 {
throw new Error("not implemented");
// 2) discovers B2#foo (overload)
}
}
class B2 extends A2 {
foo(): i32 {
return new B1().bar();
// 3) discovers B1#bar (alias of A1#bar)
}
}
var b2: A2 = new B2();
assert(b2.foo() == 3); // 1) discovers A2#foo
153 changes: 152 additions & 1 deletion tests/compiler/class-overloading.untouched.wat
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
(data (i32.const 204) "\02\00\00\00\01\00\00\00\00\00\00\00\01\00\00\00\02\00\00\00F\00")
(data (i32.const 236) "\04\00\00\00\01\00\00\00\00\00\00\00\01\00\00\00\04\00\00\00I\00B\00")
(data (i32.const 268) "\04\00\00\00\01\00\00\00\00\00\00\00\01\00\00\00\04\00\00\00I\00C\00")
(data (i32.const 300) "\1e\00\00\00\01\00\00\00\00\00\00\00\01\00\00\00\1e\00\00\00n\00o\00t\00 \00i\00m\00p\00l\00e\00m\00e\00n\00t\00e\00d\00")
(table $0 1 funcref)
(global $class-overloading/which (mut i32) (i32.const 32))
(global $~lib/rt/stub/startOffset (mut i32) (i32.const 0))
Expand All @@ -25,8 +26,9 @@
(global $class-overloading/c (mut i32) (i32.const 0))
(global $class-overloading/ia (mut i32) (i32.const 0))
(global $class-overloading/ic (mut i32) (i32.const 0))
(global $class-overloading/b2 (mut i32) (i32.const 0))
(global $~started (mut i32) (i32.const 0))
(global $~lib/memory/__heap_base i32 (i32.const 292))
(global $~lib/memory/__heap_base i32 (i32.const 352))
(export "_start" (func $~start))
(export "memory" (memory $0))
(func $~lib/rt/stub/computeSize (param $0 i32) (result i32)
Expand Down Expand Up @@ -589,6 +591,41 @@
end
local.get $0
)
(func $class-overloading/A2#constructor (param $0 i32) (result i32)
local.get $0
i32.eqz
if
i32.const 0
i32.const 13
call $~lib/rt/stub/__new
call $~lib/rt/stub/__retain
local.set $0
end
local.get $0
)
(func $class-overloading/B2#constructor (param $0 i32) (result i32)
local.get $0
i32.eqz
if
i32.const 0
i32.const 14
call $~lib/rt/stub/__new
call $~lib/rt/stub/__retain
local.set $0
end
local.get $0
call $class-overloading/A2#constructor
local.set $0
local.get $0
)
(func $class-overloading/A2#foo (param $0 i32) (result i32)
i32.const 320
i32.const 128
i32.const 198
i32.const 5
call $~lib/builtins/abort
unreachable
)
(func $start:class-overloading
(local $0 i32)
global.get $~lib/memory/__heap_base
Expand Down Expand Up @@ -1074,6 +1111,22 @@
call $~lib/builtins/abort
unreachable
end
i32.const 0
call $class-overloading/B2#constructor
global.set $class-overloading/b2
global.get $class-overloading/b2
call $class-overloading/A2#foo@virtual
i32.const 3
i32.eq
i32.eqz
if
i32.const 0
i32.const 128
i32.const 209
i32.const 1
call $~lib/builtins/abort
unreachable
end
)
(func $~start
global.get $~started
Expand Down Expand Up @@ -1402,4 +1455,102 @@
end
unreachable
)
(func $class-overloading/A1#constructor (param $0 i32) (result i32)
local.get $0
i32.eqz
if
i32.const 0
i32.const 16
call $~lib/rt/stub/__new
call $~lib/rt/stub/__retain
local.set $0
end
local.get $0
)
(func $class-overloading/B1#constructor (param $0 i32) (result i32)
local.get $0
i32.eqz
if
i32.const 0
i32.const 15
call $~lib/rt/stub/__new
call $~lib/rt/stub/__retain
local.set $0
end
local.get $0
call $class-overloading/A1#constructor
local.set $0
local.get $0
)
(func $class-overloading/A1#baz (param $0 i32) (result i32)
i32.const 320
i32.const 128
i32.const 186
i32.const 5
call $~lib/builtins/abort
unreachable
)
(func $class-overloading/A1#bar (param $0 i32) (result i32)
local.get $0
call $class-overloading/A1#baz@virtual
)
(func $class-overloading/B2#foo (param $0 i32) (result i32)
(local $1 i32)
(local $2 i32)
i32.const 0
call $class-overloading/B1#constructor
local.tee $1
call $class-overloading/A1#bar
local.set $2
local.get $1
call $~lib/rt/stub/__release
local.get $2
)
(func $class-overloading/A2#foo@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 14
i32.eq
br_if $case0
br $default
end
local.get $0
call $class-overloading/B2#foo
return
end
local.get $0
call $class-overloading/A2#foo
)
(func $class-overloading/B1#baz (param $0 i32) (result i32)
i32.const 3
)
(func $class-overloading/A1#baz@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 15
i32.eq
br_if $case0
br $default
end
local.get $0
call $class-overloading/B1#baz
return
end
local.get $0
call $class-overloading/A1#baz
)
)