mirror of
https://github.com/dart-lang/sdk
synced 2024-10-07 14:20:02 +00:00
[dart2js] lazyFinal can use a variable for the result.
Returning the value is faster than reading the holder slot on V8. Some benchmarks which read a lazy final in a tight loop are up to 40% faster. JSC and SM unchanged. Change-Id: I72afa456160469e4ccfe6ab80f8a53694133d794 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/220132 Commit-Queue: Stephen Adams <sra@google.com> Reviewed-by: Mayank Patke <fishythefish@google.com>
This commit is contained in:
parent
7bc9ca5ee9
commit
405734f18b
|
@ -189,11 +189,12 @@ function lazy(holder, name, getterName, initializer) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a lazy final field that uses non-nullable initialization semantics.
|
// Creates a lazy final static field that uses non-nullable initialization
|
||||||
|
// semantics.
|
||||||
//
|
//
|
||||||
// A lazy field has a storage entry, [name], which holds the value, and a
|
// A lazy final field has a storage entry, [name], which holds the value, and a
|
||||||
// getter ([getterName]) to access the field. If the field wasn't set before
|
// getter ([getterName]) to access the field. The field is initialized on first
|
||||||
// the first access, it is initialized with the [initializer].
|
// access with the [initializer].
|
||||||
function lazyFinal(holder, name, getterName, initializer) {
|
function lazyFinal(holder, name, getterName, initializer) {
|
||||||
var uninitializedSentinel = holder;
|
var uninitializedSentinel = holder;
|
||||||
holder[name] = uninitializedSentinel;
|
holder[name] = uninitializedSentinel;
|
||||||
|
@ -201,12 +202,21 @@ function lazyFinal(holder, name, getterName, initializer) {
|
||||||
if (holder[name] === uninitializedSentinel) {
|
if (holder[name] === uninitializedSentinel) {
|
||||||
var value = initializer();
|
var value = initializer();
|
||||||
if (holder[name] !== uninitializedSentinel) {
|
if (holder[name] !== uninitializedSentinel) {
|
||||||
|
// Since there is no setter, the only way to get here is via bounded
|
||||||
|
// recursion, where `initializer` calls the lazy final getter.
|
||||||
#throwLateFieldADI(name);
|
#throwLateFieldADI(name);
|
||||||
}
|
}
|
||||||
holder[name] = value;
|
holder[name] = value;
|
||||||
}
|
}
|
||||||
holder[getterName] = function() { return this[name]; };
|
// TODO(sra): Does the value need to be stored in the holder at all?
|
||||||
return holder[name];
|
// Potentially a call to the getter could be replaced with an access to
|
||||||
|
// holder slot if dominated by a previous call to the getter. Does the
|
||||||
|
// optimizer do this? If so, within a single function, the dominance
|
||||||
|
// relations should allow a local copy via GVN, so it is not that valuable
|
||||||
|
// an optimization for a `final` static variable.
|
||||||
|
var finalValue = holder[name];
|
||||||
|
holder[getterName] = function() { return finalValue; };
|
||||||
|
return finalValue;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue