Skip to content

Commit

Permalink
Fixing devirtualization of ClassGetVirtual for vacuous case
Browse files Browse the repository at this point in the history
  • Loading branch information
titzer committed Jun 19, 2024
1 parent 0ac69d4 commit 5f44a40
Show file tree
Hide file tree
Showing 22 changed files with 722 additions and 4 deletions.
2 changes: 1 addition & 1 deletion aeneas/src/ir/Normalization.v3
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ class ReachabilityNormalizer(config: NormalizerConfig, ra: ReachabilityAnalyzer)
if (rv.mtable != null) return;
var rm = rv.raMethod, rc = ra.getClass(rm.receiver);
var size = rc.maxClassId - rc.minClassId;
if (ra.compiler.RaDevirtualize && size < 2) return; // no need for an mtable
if (ra.compiler.RaDevirtualize && size == 1) return; // no need for an mtable
var table = Array<IrMethod>.new(size), mtable = IrMtable.new(rm.norm, rc.minClassId, table);
rv.mtable = mtable;

Expand Down
5 changes: 4 additions & 1 deletion aeneas/src/ir/SsaNormalizer.v3
Original file line number Diff line number Diff line change
Expand Up @@ -198,11 +198,14 @@ class SsaRaNormalizer extends SsaRebuilder {
mapN(i_old, [funcRef(extractMethodRef(orig, method).1), obj]);
}
ClassGetVirtual(method) => {
var t = extractVirtualRef(orig, method), obj = genRef1(args[0]);
var t = extractVirtualRef(orig, method), obj = genRef1(args[0]), m = t.1;
if (t.2) { // still a virtual dispatch
mapN(i_old, [curBlock.opGetSelector(t.1, obj), obj]);
} else {
addNullCheck(i_old, obj);
if (m.member.facts.M_ABSTRACT) {
return mapN(i_old, [newGraph.nullConst(AnyFunction.TYPE), newGraph.nullConst(AnyRef.TYPE)]);
}
mapN(i_old, [funcRef(t.1), obj]);
}
}
Expand Down
1 change: 1 addition & 0 deletions aeneas/src/mach/MachBackend.v3
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ class SsaMachGen(context: SsaContext, mach: MachProgram, regSet: MachRegSet, w:
var render: StringBuilder -> StringBuilder;
if (context.spec != null) context.spec.render(out);
else if (context.method != null) context.method.renderLong(out);
if (CLOptions.PRINT_PATCH.val) out.put1(" @ 0x%x", w.posAddr());
out.outln();
// print instructions
var indent = 1;
Expand Down
2 changes: 1 addition & 1 deletion aeneas/src/main/Version.v3
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@

// Updated by VCS scripts. DO NOT EDIT.
component Version {
def version: string = "III-7.1739";
def version: string = "III-7.1740";
var buildData: string;
}
6 changes: 5 additions & 1 deletion aeneas/src/x86-64/X86_64Backend.v3
Original file line number Diff line number Diff line change
Expand Up @@ -300,13 +300,17 @@ class X86_64Backend extends MachBackend {
return frame;
}
def patchCodeAddr(w: DataWriter, a: Addr, posAddr: int) {
var abs = mach.absolute(a);
if (CLOptions.PRINT_PATCH.val) {
TerminalBuffer.new()
.puts("patch-code @0x")
.putx(posAddr)
.puts(" <- ")
.putcv(a, null)
.outt();
}
var abs = mach.absolute(a);
if (CLOptions.PRINT_PATCH.val) {
TerminalBuffer.new()
.puts(" = 0x")
.putx(abs)
.outln();
Expand Down
54 changes: 54 additions & 0 deletions test/core/zcha00.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//@execute 0=18

var global = 0;

class Base {
def m() { global = 18; }
}

class A extends Base {
}

class A1 extends A {
def m() { global = 19; }
}

class A2 extends A {
}

class B extends Base {
def m() { global = 20; }
}

class B1 extends B {
def m() { global = 21; }
}

class B2 extends B {
}

def run(f: void -> void) {
f();
}

def dispatch(obj: Base) {
match (obj) {
x: A1 => run(x.m);
x: A2 => run(x.m);
x: A => run(x.m);
x: B1 => run(x.m);
x: B2 => run(x.m);
x: B => run(x.m);
x: Base => run(x.m);
}
}

def objs = [
Base.new()
];

def main(a: int) -> int {
global = 0;
dispatch(objs[a]);
return global;
}
40 changes: 40 additions & 0 deletions test/core/zcha01.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//@execute 0=18

var global = 0;

class Base {
def m() { global = 18; }
}

class A extends Base {
}

class A1 extends A {
def m() { global = 19; }
}

class A2 extends A {
}

def run(f: void -> void) {
f();
}

def dispatch(obj: Base) {
match (obj) {
x: A1 => run(x.m);
x: A2 => run(x.m);
x: A => run(x.m);
x: Base => run(x.m);
}
}

def objs = [
Base.new()
];

def main(a: int) -> int {
global = 0;
dispatch(objs[a]);
return global;
}
50 changes: 50 additions & 0 deletions test/core/zcha02.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//@execute 0=18

var global = 0;

class Base {
def m() { global = 18; }
}

class A extends Base {
}

class A1 extends A {
def m() { global = 19; }
}

class A2 extends A {
}

class B extends Base {
def m() { global = 20; }
}

class B1 extends B {
def m() { global = 21; }
}

def run(f: void -> void) {
f();
}

def dispatch(obj: Base) {
match (obj) {
x: A1 => run(x.m);
x: A2 => run(x.m);
x: A => run(x.m);
x: B1 => run(x.m);
x: B => run(x.m);
x: Base => run(x.m);
}
}

def objs = [
Base.new()
];

def main(a: int) -> int {
global = 0;
dispatch(objs[a]);
return global;
}
46 changes: 46 additions & 0 deletions test/core/zcha03.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//@execute 0=18

var global = 0;

class Base {
def m() { global = 18; }
}

class A extends Base {
}

class A1 extends A {
def m() { global = 19; }
}

class B extends Base {
def m() { global = 20; }
}

class B1 extends B {
def m() { global = 21; }
}

def run(f: void -> void) {
f();
}

def dispatch(obj: Base) {
match (obj) {
x: A1 => run(x.m);
x: A => run(x.m);
x: B1 => run(x.m);
x: B => run(x.m);
x: Base => run(x.m);
}
}

def objs = [
Base.new()
];

def main(a: int) -> int {
global = 0;
dispatch(objs[a]);
return global;
}
45 changes: 45 additions & 0 deletions test/core/zcha04.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//@execute 0=18

var global = 0;

class Base {
def m() { global = 18; }
}

class A extends Base {
}

class A1 extends A {
def m() { global = 19; }
}

class B extends Base {
def m() { global = 20; }
}

class B1 extends B {
}

def run(f: void -> void) {
f();
}

def dispatch(obj: Base) {
match (obj) {
x: A1 => run(x.m);
x: A => run(x.m);
x: B1 => run(x.m);
x: B => run(x.m);
x: Base => run(x.m);
}
}

def objs = [
Base.new()
];

def main(a: int) -> int {
global = 0;
dispatch(objs[a]);
return global;
}
41 changes: 41 additions & 0 deletions test/core/zcha05.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//@execute 0=18

var global = 0;

class Base {
def m() { global = 18; }
}

class A extends Base {
}

class A1 extends A {
def m() { global = 19; }
}

class B extends Base {
def m() { global = 20; }
}

def run(f: void -> void) {
f();
}

def dispatch(obj: Base) {
match (obj) {
x: A1 => run(x.m);
x: A => run(x.m);
x: B => run(x.m);
x: Base => run(x.m);
}
}

def objs = [
Base.new()
];

def main(a: int) -> int {
global = 0;
dispatch(objs[a]);
return global;
}
45 changes: 45 additions & 0 deletions test/core/zcha06.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//@execute 0=18

var global = 0;

class Base {
def m() { global = 18; }
}

class A extends Base {
}

class A1 extends A {
def m() { global = 19; }
}

class B extends Base {
}

class B1 extends B {
def m() { global = 21; }
}

def run(f: void -> void) {
f();
}

def dispatch(obj: Base) {
match (obj) {
x: A1 => run(x.m);
x: A => run(x.m);
x: B1 => run(x.m);
x: B => run(x.m);
x: Base => run(x.m);
}
}

def objs = [
Base.new()
];

def main(a: int) -> int {
global = 0;
dispatch(objs[a]);
return global;
}
Loading

0 comments on commit 5f44a40

Please sign in to comment.