//===--- PolymorphicCalls.swift -------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// /* This benchmark is used to check the performance of polymorphic invocations. Essentially, it checks how good a compiler can optimize virtual calls of class methods in cases where multiple sub-classes of a given class are available. In particular, this benchmark would benefit from a good devirtualization. In case of applying a speculative devirtualization, it would be benefit from applying a jump-threading in combination with the speculative devirtualization. */ import TestsUtils public let benchmarks = [ BenchmarkInfo( name: "PolymorphicCalls", runFunction: run_PolymorphicCalls, tags: [.abstraction, .cpubench] ), ] public class A { let b: B init(b:B) { self.b = b } public func run1() -> Int { return b.f1() + b.f2() + b.f3() } public func run2() -> Int { return b.run() } } // B has no known subclasses public class B { let x: Int init(x:Int) { self.x = x } public func f1() -> Int { return x + 1 } public func f2() -> Int { return x + 11 } public func f3() -> Int { return x + 111 } public func run() -> Int { return f1() + f2() + f3() } } public class A1 { let b: B1 public init(b:B1) { self.b = b } public func run1() -> Int { return b.f1() + b.f2() + b.f3() } public func run2() -> Int { return b.run() } } // B1 has 1 known subclass public class B1 { func f1() -> Int { return 0 } func f2() -> Int { return 0 } func f3() -> Int { return 0 } public func run() -> Int { return f1() + f2() + f3() } } public class C1: B1 { let x: Int init(x:Int) { self.x = x } override public func f1() -> Int { return x + 2 } override public func f2() -> Int { return x + 22 } override public func f3() -> Int { return x + 222 } } public class A2 { let b:B2 public init(b:B2) { self.b = b } public func run1() -> Int { return b.f1() + b.f2() + b.f3() } public func run2() -> Int { return b.run() } } // B2 has 2 known subclasses public class B2 { func f1() -> Int { return 0 } func f2() -> Int { return 0 } func f3() -> Int { return 0 } public func run() -> Int { return f1() + f2() + f3() } } public class C2 : B2 { let x: Int init(x:Int) { self.x = x } override public func f1() -> Int { return x + 3 } override public func f2() -> Int { return x + 33 } override public func f3() -> Int { return x + 333 } } public class D2 : B2 { let x: Int init(x:Int) { self.x = x } override public func f1() -> Int { return x + 4 } override public func f2() -> Int { return x + 44 } override public func f3() -> Int { return x + 444 } } public class A3 { let b: B3 public init(b:B3) { self.b = b } public func run1() -> Int { return b.f1() + b.f2() + b.f3() } public func run2() -> Int { return b.run() } } // B3 has 3 known subclasses public class B3 { func f1() -> Int { return 0 } func f2() -> Int { return 0 } func f3() -> Int { return 0 } public func run() -> Int { return f1() + f2() + f3() } } public class C3: B3 { let x: Int init(x:Int) { self.x = x } override public func f1() -> Int { return x + 5 } override public func f2() -> Int { return x + 55 } override public func f3() -> Int { return x + 555 } } public class D3: B3 { let x: Int init(x:Int) { self.x = x } override public func f1() -> Int { return x + 6 } override public func f2() -> Int { return x + 66 } override public func f3() -> Int { return x + 666 } } public class E3:B3 { let x: Int init(x:Int) { self.x = x } override public func f1() -> Int { return x + 7 } override public func f2() -> Int { return x + 77 } override public func f3() -> Int { return x + 777 } } public class F3 : B3 { let x: Int init(x:Int) { self.x = x } override public func f1() -> Int { return x + 8 } override public func f2() -> Int { return x + 88 } override public func f3() -> Int { return x + 888 }} // Test the cost of polymorphic method invocation // on a class without any subclasses @inline(never) func test(_ a:A, _ upTo: Int) -> Int64 { var cnt: Int64 = 0 for _ in 0.. Int64 { var cnt: Int64 = 0 for _ in 0.. Int64 { var cnt: Int64 = 0 for _ in 0.. Int64 { var cnt: Int64 = 0 for _ in 0.. Int64 { var cnt: Int64 = 0 for _ in 0..