Skip to content

Commit edd3f52

Browse files
authored
chore: Reduce size of Lazy. (#601)
Motivation: By making Lazy an empty abstract class, we can reduce the size of Val. refs: #319
1 parent d3333cb commit edd3f52

3 files changed

Lines changed: 28 additions & 18 deletions

File tree

sjsonnet/src/sjsonnet/Val.scala

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,20 @@ import scala.reflect.ClassTag
1212
/**
1313
* [[Lazy]] models lazy evaluation within a Jsonnet program. Lazily evaluated dictionary values,
1414
* array contents, or function parameters are all wrapped in [[Lazy]] and only truly evaluated
15-
* on-demand
15+
* on-demand. [[Val]] also extends [[Lazy]] so that already-evaluated values can be stored directly
16+
* in [[Array[Lazy]]] without wrapper overhead.
1617
*/
17-
abstract class Lazy {
18-
protected var cached: Val = _
19-
def compute(): Val
20-
final def force: Val = {
21-
if (cached == null) cached = compute()
22-
cached
23-
}
18+
trait Lazy {
19+
def force: Val
2420
}
2521

2622
/**
2723
* Thread-safe implementation that discards the compute function after initialization.
2824
*/
2925
final class LazyWithComputeFunc(@volatile private var computeFunc: () => Val) extends Lazy {
30-
def compute(): Val = {
26+
private var cached: Val = _
27+
def force: Val = {
28+
if (cached != null) return cached
3129
val f = computeFunc
3230
if (f != null) { // we won the race to initialize
3331
val result = f()
@@ -47,8 +45,7 @@ final class LazyWithComputeFunc(@volatile private var computeFunc: () => Val) ex
4745
* array contents are lazy, and the tree can contain functions.
4846
*/
4947
sealed abstract class Val extends Lazy {
50-
cached = this // avoid a megamorphic call to compute() when forcing
51-
final def compute(): Val = this
48+
final def force: Val = this
5249

5350
def pos: Position
5451
def prettyName: String

sjsonnet/src/sjsonnet/stdlib/ArrayModule.scala

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,9 @@ object ArrayModule extends AbstractFunctionModule {
166166
pos: Position): Val.Arr = {
167167
Val.Arr(
168168
pos,
169-
arg.map(v => (() => _func.apply1(v, pos.noOffset)(ev, TailstrictModeDisabled)): Lazy)
169+
arg.map(v =>
170+
new LazyWithComputeFunc(() => _func.apply1(v, pos.noOffset)(ev, TailstrictModeDisabled))
171+
)
170172
)
171173
}
172174

@@ -184,7 +186,9 @@ object ArrayModule extends AbstractFunctionModule {
184186
while (i < a.length) {
185187
val x = arr(i)
186188
val idx = Val.Num(pos, i)
187-
a(i) = () => func.apply2(idx, x, pos.noOffset)(ev, TailstrictModeDisabled)
189+
a(i) = new LazyWithComputeFunc(() =>
190+
func.apply2(idx, x, pos.noOffset)(ev, TailstrictModeDisabled)
191+
)
188192
i += 1
189193
}
190194
Val.Arr(pos, a)
@@ -414,7 +418,11 @@ object ArrayModule extends AbstractFunctionModule {
414418
if (!filter_func.apply1(i, pos.noOffset)(ev, TailstrictModeDisabled).asBoolean) {
415419
None
416420
} else {
417-
Some[Lazy](() => map_func.apply1(i, pos.noOffset)(ev, TailstrictModeDisabled))
421+
Some[Lazy](
422+
new LazyWithComputeFunc(() =>
423+
map_func.apply1(i, pos.noOffset)(ev, TailstrictModeDisabled)
424+
)
425+
)
418426
}
419427
}
420428
)
@@ -451,8 +459,9 @@ object ArrayModule extends AbstractFunctionModule {
451459
var i = 0
452460
while (i < sz) {
453461
val forcedI = i
454-
a(i) =
455-
() => func.apply1(Val.Num(pos, forcedI), pos.noOffset)(ev, TailstrictModeDisabled)
462+
a(i) = new LazyWithComputeFunc(() =>
463+
func.apply1(Val.Num(pos, forcedI), pos.noOffset)(ev, TailstrictModeDisabled)
464+
)
456465
i += 1
457466
}
458467
a

sjsonnet/src/sjsonnet/stdlib/ObjectModule.scala

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,11 @@ object ObjectModule extends AbstractFunctionModule {
105105
val k = allKeys(i)
106106
val v = new Val.Obj.Member(false, Visibility.Normal, deprecatedSkipAsserts = true) {
107107
def invoke(self: Val.Obj, sup: Val.Obj, fs: FileScope, ev: EvalScope): Val =
108-
func.apply2(Val.Str(pos, k), () => obj.value(k, pos.noOffset)(ev), pos.noOffset)(
108+
func.apply2(
109+
Val.Str(pos, k),
110+
new LazyWithComputeFunc(() => obj.value(k, pos.noOffset)(ev)),
111+
pos.noOffset
112+
)(
109113
ev,
110114
TailstrictModeDisabled
111115
)
@@ -135,7 +139,7 @@ object ObjectModule extends AbstractFunctionModule {
135139
Val.Arr(
136140
pos,
137141
keys.map { k =>
138-
(() => v1.value(k, pos.noOffset)(ev)): Lazy
142+
new LazyWithComputeFunc(() => v1.value(k, pos.noOffset)(ev))
139143
}
140144
)
141145

0 commit comments

Comments
 (0)