It is possible to instantiate a tear-off of generic function with type
arguments which are equivalent (equal) but not identical, for example
[int] and [int*]. So, operator== on closures changed to compare
delayed type arguments of implicit closures for equality.
Fixes https://github.com/dart-lang/sdk/issues/46836
TEST=language/closure/identity_equality_tearoff_test (in weak mode)
Change-Id: I610eb226a7a244deb6415f8d92f74e941371bb50
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/209266
Reviewed-by: Tess Strickland <sstrickl@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
There could be multiple instances of implicit static closures due to
instantiations at run time:
void foo<T>(T x) {}
void bar<T>() {
void Function(T) myfoo1 = foo;
void Function(T) myfoo2 = foo;
print(myfoo1 == myfoo2);
}
This change fixes equality to handle this case.
TEST=language/generic_methods/explicit_instantiated_tearoff_test
TEST=language/constructor/tear_off_test
Issue https://github.com/dart-lang/sdk/issues/46231
Issue https://github.com/dart-lang/sdk/issues/46487
Change-Id: I485acc5444d19860ef4d8ebeec2e540fe57776d6
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/208981
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Closures created via Closure::New() set the delayed type arguments to
the null type argument vector for non-generic closure functions and to
the empty type argument vector for generic closure functions. However,
closures created via the method extractor stub would always have the
empty type argument vector for delayed type arguments. Make the two
consistent by creating two method extractor stubs, one for generic
extracted methods and one for non-generic ones.
With this change, Closure::IsGeneric simply compares the delayed type
arguments against the empty type argument vector. This change also makes
method extraction for non-generic functions slightly faster, since the
delayed type arguments field is not changed post-allocation.
The old version of Closure::IsGeneric was the only use of
Closure::NumTypeParameters, so remove the latter method.
Related cleanups:
* Use similar checks for Class::IsGeneric and FunctionType::IsGeneric,
since they only have non-null type_parameters fields when generic.
For Class::IsGeneric, this avoids having to fetch the current thread
if the class declaration has been loaded.
* Refactor methods that read packed fields in FunctionType into two
methods, a static method that takes a FunctionTypePtr and an instance
method that calls the static method. Replace the methods in Function
that also directly read FunctionType packed fields with delegations to
the static methods.
* Rework Closure_equals to avoid unneeded handle allocation in certain
cases for non-equal closures.
* Replace cases that allocates a handle for the closure function only
for retrieving the signature with calls to Closure::signature().
TEST=language_2/closure/tearoff_dynamic_test
language_2/regress/regress45890_test
Cq-Include-Trybots: luci.dart.try:vm-kernel-linux-debug-x64-try,vm-kernel-linux-debug-x64c-try,vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-x64c-try,vm-kernel-reload-rollback-linux-debug-x64-try,vm-kernel-reload-linux-debug-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-nnbd-linux-release-simarm-try,vm-kernel-nnbd-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-nnbd-linux-release-simarm64-try,vm-kernel-linux-debug-simarm64c-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-nnbd-linux-debug-simarm_x64-try
Change-Id: I29c8859c3350ed7b3f1a8f71d82a4393496b7c2b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/206820
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Currently we have things called XPtr which are not what you get from ptr().
Old world:
handle->raw() returns RawObject* (tagged)
raw_obj->ptr() returns RawObject* (untagged)
After 6fe15f6df9:
handle->raw() returns ObjectPtr
obj_ptr->ptr() returns ObjectLayout*
New world:
handle->ptr() returns ObjectPtr
obj_ptr->untag() returns UntaggedObject*
TEST=ci
Change-Id: I6c7f34014cf20737607caaf84979838300d12df2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/149367
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
DartEntry::InvokeCallable (and DartEntry::InvokeClosure) are only called
for dynamic invocations. Instead of making it the responsibility of the
caller to check the callable function if it can't receive dynamic
invocation, move the call to DoArgumentTypesMatch into
DartEntry::InvokeCallable.
Since all current callers of these and related functions already have a
handle on the current thread, thread it through instead of retrieving it
via Thread::Current().
Cq-Include-Trybots: luci.dart.try:vm-kernel-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-nnbd-linux-debug-x64-try
Change-Id: I5f9260b0edace5b4017aa235a980a802405a2f1b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/168020
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Clement Skau <cskau@google.com>
This works around bugs in UndefinedBehaviorSanitizer and Clang.
Bug: b/28638298
Change-Id: I6be595f9664516019d28017d24559583a1ae3a21
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/144354
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
Static methods and constructors may receive unboxed parameters.
This change adds a bitmap to the RawFunction object indicating
which parameters are unboxed and their types. Also, the stack frame
bitmap was updated to include new bits for those parameters.
The ArgumentsDescriptor object was updated to store not only the number
of arguments, but also their size, since 32-bit platforms would use two
words for each int64 and double value.
In addition, static methods that return non-nullable integers
and doubles may return these values unboxed.
Dart AOT x64:
TypedData.Uint8ClampedListViewVarBench +11.73%
DeltaBlue +9.32%
Meteor (Intel Xeon) +4.64%
Flutter release android-armv8:
velocity_tracker_bench -2.32% (less is better)
flutter_gallery_readonlydata_size +0.18%
flutter_gallery_total_size +0.13%
flutter_gallery_instructions_size +0.12%
Issue https://github.com/dart-lang/sdk/issues/33549
Change-Id: I97e310f8f30213920af2333fbdedf193d03db5c3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135313
Commit-Queue: Victor Agnez Lima <victoragnez@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
This reverts commit 61b5ba7ecf.
Reason for revert: found a counter-example for deep cloning: https://dart-review.googlesource.com/c/sdk/+/70681
Original change's description:
> [vm] Deep clone context when cloning closure
>
> _SyncIterable::iterator clones unerlying sync* closure to create a new
> Iterator using _Closure._clone(). _Closure._clone() was cloning only
> 1 level of context, relying on a particular context structure.
>
> In bytecode, contexts are allocated in a different way, so sync*
> functions could have more then 1 level of contexts. In such case,
> parent contexts were not cloned in _Closure._clone() and were shared
> between Iterator instances.
>
> This CL adds deep cloning of contexts into _Closure._clone() native method
> in order to handle arbitrary number of levels of contexts in a closure.
>
> Fixes language_2/syncstar_yield_test test in bytecode mode.
>
> Change-Id: Ic5ced4c32fc2e21726db76608cd3a7db7e553472
> Reviewed-on: https://dart-review.googlesource.com/70600
> Reviewed-by: Régis Crelier <regis@google.com>
> Commit-Queue: Alexander Markov <alexmarkov@google.com>
TBR=rmacnak@google.com,alexmarkov@google.com,regis@google.com
# Not skipping CQ checks because original CL landed > 1 day ago.
Change-Id: I9f6116069cbec022ad86ef4cbf6801c603b4ab15
Reviewed-on: https://dart-review.googlesource.com/70700
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
_SyncIterable::iterator clones unerlying sync* closure to create a new
Iterator using _Closure._clone(). _Closure._clone() was cloning only
1 level of context, relying on a particular context structure.
In bytecode, contexts are allocated in a different way, so sync*
functions could have more then 1 level of contexts. In such case,
parent contexts were not cloned in _Closure._clone() and were shared
between Iterator instances.
This CL adds deep cloning of contexts into _Closure._clone() native method
in order to handle arbitrary number of levels of contexts in a closure.
Fixes language_2/syncstar_yield_test test in bytecode mode.
Change-Id: Ic5ced4c32fc2e21726db76608cd3a7db7e553472
Reviewed-on: https://dart-review.googlesource.com/70600
Reviewed-by: Régis Crelier <regis@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
New folder structure (nested under vm/):
- compiler/
- jit/ - JIT specific code
- aot/ - AOT specific code
- backend/ - all middle-end and back-end code (IL, flow graph)
- assembler/ - assemblers and disassemblers
- frontend/ - front ends (AST -> IL, Kernel -> IL)
compiler/README.md would be the documentation root for the compiler
pipeline
Bug: https://github.com/dart-lang/sdk/issues/30575
Change-Id: I2dfd9688793bff737f7632ddc77fca766875ce36
Reviewed-on: https://dart-review.googlesource.com/2940
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
Commit-Queue: Vyacheslav Egorov <vegorov@google.com>
This is the re-application of 44e8da3ecd
with fixes:
* Dartanalyzer error is fixed in the new test isolate/message4_test
* The new test is skipped in the status file in dart2j/non-d8 modes,
issue #30247 is created.
* Minor tweak of Closure_equals: other.IsClosure() is tested earlier.
Original CL review:
https://codereview.chromium.org/2989493002/
Original CL description:
This CL introduces a new Function kind, kImplicitClosureFunction, in
order to simplify check for implicit closures and make it more
efficient.
This CL also fixes Function::IsImplicitStaticClosureFunction(RawFunction*)
to correctly handle implicit closures created from static native
functions.
Closes#30203.
As the result of a faster check for implicit closures and slight
refactoring of Closure_equals, micro-benchmark exercising Closure_equals
speeds up from 9618ms to 6700ms for implicit closures case and
insignificantly for other cases.
R=zra@google.com
Review-Url: https://codereview.chromium.org/2987703002 .
This CL introduces a new Function kind, kImplicitClosureFunction, in
order to simplify check for implicit closures and make it more
efficient.
This CL also fixes Function::IsImplicitStaticClosureFunction(RawFunction*)
to correctly handle implicit closures created from static native
functions.
Closes#30203.
As the result of a faster check for implicit closures and slight
refactoring of Closure_equals, micro-benchmark exercising Closure_equals
speeds up from 9618ms to 6700ms for implicit closures case and
insignificantly for other cases.
R=zra@google.com
Review-Url: https://codereview.chromium.org/2989493002 .
This CL includes the following fixes:
* Fix for incorrect non-nullable assumption about _Closure._hash field.
* Add error handling into BecomeMapTraits::Hash.
* Correct assertions for validating layout of Closure objects.
* Add identityHashCode to the list of VM entry points in precompiler.
Closes#30211.
Original code review:
https://codereview.chromium.org/2983823002/
Original CL description:
This performance improvement is inspired by Flutter listeners stored in
the HashSet (see ObserverList) and frequently checked using
HashSet.contains(). If there are many such listeners and they are
implicit instance closures (for example, created by
'new Listenable.merge(...)'), HashSet.contains() becomes very slow.
It spends a lot of time in Closure_equals native method due to hash
collisions between closure objects with same function
but different receivers.
This CL improves hashCode() calculation for implicit instance closures
by mixing function hashcode with identity hashcode of the receiver.
For explicit closures and static implicit closures hashCode() is
improved by using identityHashCode() of a closure object.
Also, hashcode is calculated once and cached in each closure instance.
The size of a closure instance doesn't grow up because there was unused
word-size padding both on 32-bit and 64-bit architectures.
The execution time of the following micro-benchmark is reduced from
47665ms to 135ms on my Linux/x64 box.
-------------------------------------
import "dart:collection";
class Foo {
int _a;
Foo(this._a);
void bar() {}
}
main() {
HashSet hs = new HashSet();
for (int i = 0; i < 1000; ++i) {
hs.add(new Foo(i).bar);
}
var watch = new Stopwatch()..start();
for (int i = 0; i < 1000; ++i) {
for (var c in hs) {
hs.contains(c);
}
}
int time = watch.elapsedMilliseconds;
print("Time: ${time}ms\n");
}
-------------------------------------
R=zra@google.com
Review-Url: https://codereview.chromium.org/2988493002 .
This performance improvement is inspired by Flutter listeners stored in
the HashSet (see ObserverList) and frequently checked using
HashSet.contains(). If there are many such listeners and they are
implicit instance closures (for example, created by
'new Listenable.merge(...)'), HashSet.contains() becomes very slow.
It spends a lot of time in Closure_equals native method due to hash
collisions between closure objects with same function
but different receivers.
This CL improves hashCode() calculation for implicit instance closures
by mixing function hashcode with identity hashcode of the receiver.
For explicit closures and static implicit closures hashCode() is
improved by using identityHashCode() of a closure object.
Also, hashcode is calculated once and cached in each closure instance.
The size of a closure instance doesn't grow up because there was unused
word-size padding both on 32-bit and 64-bit architectures.
The execution time of the following micro-benchmark is reduced from
47665ms to 135ms on my Linux/x64 box.
-------------------------------------
import "dart:collection";
class Foo {
int _a;
Foo(this._a);
void bar() {}
}
main() {
HashSet hs = new HashSet();
for (int i = 0; i < 1000; ++i) {
hs.add(new Foo(i).bar);
}
var watch = new Stopwatch()..start();
for (int i = 0; i < 1000; ++i) {
for (var c in hs) {
hs.contains(c);
}
}
int time = watch.elapsedMilliseconds;
print("Time: ${time}ms\n");
}
-------------------------------------
R=rmacnak@google.com, zra@google.com
Review-Url: https://codereview.chromium.org/2983823002 .
Add function_type_arguments field in closure instances.
Lots of other smaller changes, also related to generic function semantics.
This is still work in progress, with a change of direction in the design:
The type argument vector of a generic function will be prepended with the type
arguments of enclosing generic functions. The re-allocation and concatenation
will be done in nested generic function's prolog. This will greatly simplify
instantiation of types at run time without having to search the context for
parent function's type arguments. However, a closure instance now requires an
additional field. On the other hand, type parameters do not require a
parent_level field anymore.
R=rmacnak@google.com
Review-Url: https://codereview.chromium.org/2818273002 .
They were used as the class of closure instances and as the type class of
function types.
All closure instances now have class _Closure and function types are represented
by a new class FunctionType extending AbstractType.
Fix issue 24567 and add regression test.
R=asiva@google.com, rmacnak@google.com
Review URL: https://codereview.chromium.org/1584223006 .
By inserting the necessary checks for null inside the callee
at the AST level, the code generation of == operations can be
greatly simplified.
This is a performance-neutral change and a step for allowing
generic inlining of arbitrary == methods. So far we could only
inline them for a common set of types in the flow graph
optimizer.
R=srdjan@google.com
Review URL: https://codereview.chromium.org//24203004
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@28084 260f80e4-7a28-3924-810f-c04153c831b5