Skip to content
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

WIP - Performance improvement to global initialization checker #21514

Draft
wants to merge 22 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
9460eb7
Widen values in assignment
liufengyun Aug 20, 2024
6b95450
Implement garbage collection
liufengyun Aug 20, 2024
5cbc51b
Add footprint optimization based on separation logic
liufengyun Aug 23, 2024
78c8c4a
Fix crash in footprint computation
liufengyun Aug 23, 2024
7b861a1
Fix another crash in footprint computation
liufengyun Aug 23, 2024
cf1515f
Fix crash with footprint comput related to local var
liufengyun Aug 23, 2024
75c5ff0
Move comment closer to code
liufengyun Aug 23, 2024
cb485c0
Only perform footprint optimization when caching result
liufengyun Aug 23, 2024
0af7e00
More efficient reachability computation
liufengyun Aug 29, 2024
9f61f34
Fix crash due to out-of-band return values using return keyword
liufengyun Aug 29, 2024
86e39de
Fix bug in capture analysis of closures
liufengyun Aug 29, 2024
a8dbaeb
Fix typo
liufengyun Sep 3, 2024
3e69d03
Elided object access should return Bottom
liufengyun Sep 3, 2024
a84a8d1
Return values already included in result
liufengyun Sep 3, 2024
4dd781c
Tolerate missing address error
liufengyun Sep 9, 2024
77fc613
Don't crash if address is missing
liufengyun Sep 9, 2024
c418982
Avoid stackoverflow in printing internal errors
liufengyun Sep 9, 2024
19d92aa
Don't apply memory optimization for constructor calls
liufengyun Sep 9, 2024
47f944d
Flatten captured variables in lambdas using the correct environment
liufengyun Sep 9, 2024
08b4e66
Add test for footprint optimization related to secondary constructor
liufengyun Sep 15, 2024
59e5412
Add debug facility for gc
liufengyun Sep 18, 2024
6de4e60
Join heaps properly
liufengyun Sep 22, 2024
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
338 changes: 283 additions & 55 deletions compiler/src/dotty/tools/dotc/transform/init/Objects.scala

Large diffs are not rendered by default.

5 changes: 0 additions & 5 deletions compiler/src/dotty/tools/dotc/transform/init/Util.scala
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,3 @@ object Util:

// A concrete class may not be instantiated if the self type is not satisfied
instantiable && cls.enclosingPackageClass != defn.StdLibPatchesPackage.moduleClass

/** Whether the class or its super class/trait contains any mutable fields? */
def isMutable(cls: ClassSymbol)(using Context): Boolean =
cls.classInfo.decls.exists(_.is(Flags.Mutable)) ||
cls.parentSyms.exists(parentCls => isMutable(parentCls.asClass))
17 changes: 17 additions & 0 deletions tests/init-global/pos/footprint-2nd-ctor.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
class Box[T](var value: T)

class A:
var box = new Box[Int](10)

def update(n: Int) =
box.value = n

def this(n: Int) =
this()
box.value = n

class B(n: Int) extends A(n):
this.update(n * n)

object A:
val a = new B(20)
6 changes: 6 additions & 0 deletions tests/init-global/pos/footprint-local.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
object A:
val f = foo()
val a = f()
def foo(): () => Int =
var x = 10
() => x
15 changes: 15 additions & 0 deletions tests/init-global/pos/footprint.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class Box(var x: String)

object A:
val a = new Box("a")
val c = foo()
def foo(): Box = C.c

object B:
val b = new Box("b")
val a = bar()

def bar(): Box = A.a

object C:
val c = new Box("c")
26 changes: 26 additions & 0 deletions tests/init-global/pos/footprint2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
class BreakControl extends Throwable

object Breaks:
private val breakException = new BreakControl

def breakable(op: => Unit): Unit =
try op catch { case ex: BreakControl if ex eq breakException => }

def break(): Nothing = throw breakException

object A:
val n = foo("hello")
def foo(s: String): Int =
val len = s.length
var i = 0

while (i < len) {
Breaks.breakable {
val c = s.charAt(i)

if c == '\n' then Breaks.break()
}
i += 1
}

i
26 changes: 26 additions & 0 deletions tests/init-global/pos/sconfig-array.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import java.{lang => jl}

final class ConfigValueType private (val name: String, val ordinal: Int)

object ConfigValueType:
final val OBJECT = new ConfigValueType("OBJECT", 0)
final val LIST = new ConfigValueType("LIST", 1)
final val NUMBER = new ConfigValueType("NUMBER", 2)
final val BOOLEAN = new ConfigValueType("BOOLEAN", 3)
final val NULL = new ConfigValueType("NULL", 4)
final val STRING = new ConfigValueType("STRING", 5)

final val _values: Array[ConfigValueType] =
Array(OBJECT, LIST, NUMBER, BOOLEAN, NULL, STRING)

def values: Array[ConfigValueType] = _values.clone()

def valueOf(name: String): ConfigValueType =
_values.find(_.name == name).getOrElse {
throw new IllegalArgumentException(
"No enum const ConfigValueType." + name
)
}

object Usage:
val c = ConfigValueType.valueOf("LIST")
89 changes: 89 additions & 0 deletions tests/init-global/pos/sconfig.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
abstract class B

class C(var o: () => B | Int) extends B

class D(var o: () => B | Int) extends B

object A:
def f1(a: () => B, i: Int): () => B =
var c = () => if i % 2 == 0 then new C(a) else new D(a)
c = f2(c, i + 1)
c = f1(c, i + 1)
c

def f2(a: () => B, i: Int): () => B =
var c = () => if i % 2 == 0 then new C(a) else new D(a)
c = f3(c, i + 1)
c

def f3(a: () => B, i: Int): () => B =
var c = () => if i % 2 == 0 then new C(a) else new D(a)
c = f4(c, i + 1)
c

def f4(a: () => B, i: Int): () => B =
var c = () => if i % 2 == 0 then new C(a) else new D(a)
c = f5(c, i + 1)
c

def f5(a: () => B, i: Int): () => B =
var c = () => if i % 2 == 0 then new C(a) else new D(a)
c = f6(c, i + 1)
c

def f6(a: () => B, i: Int): () => B =
var c = () => if i % 2 == 0 then new C(a) else new D(a)
c = f7(c, i + 1)
c

def f7(a: () => B, i: Int): () => B =
var c = () => if i % 2 == 0 then new C(a) else new D(a)
c = f8(c, i + 1)
c

def f8(a: () => B, i: Int): () => B =
var c = () => if i % 2 == 0 then new C(a) else new D(a)
c = f9(c, i + 1)
c

def f9(a: () => B, i: Int): () => B =
var c = () => if i % 2 == 0 then new C(a) else new D(a)
c = f10(c, i + 1)
c

def f10(a: () => B, i: Int): () => B =
var c = () => if i % 2 == 0 then new C(a) else new D(a)
c = f11(c, i + 1)
c

def f11(a: () => B, i: Int): () => B =
var c = () => if i % 2 == 0 then new C(a) else new D(a)
c = f12(c, i + 1)
c

def f12(a: () => B, i: Int): () => B =
var c = () => if i % 2 == 0 then new C(a) else new D(a)
c = f13(c, i + 1)
c

def f13(a: () => B, i: Int): () => B =
var c = () => if i % 2 == 0 then new C(a) else new D(a)
c = f14(c, i + 1) // non-termination if use f1
c

def f14(a: () => B, i: Int): () => B =
var c = () => if i % 2 == 0 then new C(a) else new D(a)
c = f15(c, i + 1)
c

def f15(a: () => B, i: Int): () => B =
var c = () => if i % 2 == 0 then new C(a) else new D(a)
c = f16(c, i + 1)
c

def f16(a: () => B, i: Int): () => B =
var c = () => if i % 2 == 0 then new C(a) else new D(a)
c = f1(c, i + 1)
c

val c = f1(() => new C(() => 3), 10)
Loading