Commit graph

20952 commits

Author SHA1 Message Date
Ryan Macnak 578f95ad2e Roll double-conversion to 032fa6a7d2c319b20d3928f5d762648fa4029acf.
Bug: https://github.com/dart-lang/sdk/issues/47835
Change-Id: I5c2a278071f3c8e704754cc27fdd33a108eaf7dc
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/325543
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2023-09-13 14:54:27 +00:00
Ryan Macnak ea9656ba38 [test] XCode's nm not available on shards that haven't yet run main task.
Change-Id: Ib438cac3acf1842afb4d55a203d1f7a0c91f5918
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/325451
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Alexander Thomas <athom@google.com>
2023-09-13 10:27:59 +00:00
Martin Kustermann 781a8ef9c0 [vm] Mark external methods used in Pointer.asTypedList() with resulting type
It allows the compiler to propagate this information in TFA - which
may be beneficial for cases when those methods aren't inlined.

TEST=ci

Change-Id: I55711806800e2a56e83a42cd51be705b68c3a4f3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/324701
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Tess Strickland <sstrickl@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
2023-09-13 09:48:56 +00:00
Ryan Macnak 3a5a7106ee [build] Define DART_SHARED_LIB for elf_loader.cc.
This makes elf_loader.cc consistent with the other compilation units containing Dart_* functions. Addresses a Mac linker warning that these functions match the export glob but have hidden visibility.

TEST=build
Change-Id: I868c9940a7027c466c1173aa2db2fbeff6fe8999
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/325362
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2023-09-12 22:42:38 +00:00
Vyacheslav Egorov 5c320a108a [vm/compiler] Improve flow sensitivity of CP
Before running CP find all branches of form `Branch(v eq C)`,
where `eq` is one of `===`, `==`, `!==` or `!=` and `C` is
a constant and insert a redefinition of `v` in the true
successor which captures the information that `v` is equal
to `C` guaranteed by the branch.

SCCP algorithm can then use this information when propagating
constants. After SCCP all redefinitions inserted are removed
again.

We don't actually replace `v` with `C` in the dominated code
because this might lead to issues later, for example
it might result in redundant phis `phi(C, v)` (`C` flowing
from a predecessor where `v == C`) which are complicated
to eliminate again.

TEST=vm/dart/comparison_canonicalization_il_test

Cq-Include-Trybots: luci.dart.try:vm-aot-linux-release-x64-try,vm-aot-linux-debug-simarm_x64-try,vm-aot-linux-debug-x64-try,vm-aot-android-release-arm64c-try
Change-Id: I388dddb97b5e35f09d9904000c585864f27400f6
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/324980
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Slava Egorov <vegorov@google.com>
2023-09-12 22:39:25 +00:00
Ryan Macnak df54b81dd1 [vm] Remove dead ARMv5 code.
TEST=build
Change-Id: I44b41bb783b5f5cad221d4508fee18ff0a23afe7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/325144
Reviewed-by: Zach Anderson <zra@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Reviewed-by: William Hesse <whesse@google.com>
2023-09-12 16:22:19 +00:00
Vyacheslav Egorov 1a0e5dea69 [vm/service] Handle raw types in CollectStringifiedType
This function did not handle raw types correctly: it assumed that
TAV is always non-null, but VM replaces TAVs of form
`<dynamic, ..., dynamic>` with `null`. We needed to handle
this case specially.

Fixes https://github.com/dart-lang/sdk/issues/53453

TEST=service/evaluate_variable_of_raw_type_test

Change-Id: If0a2669fd722fb0e0871138a68814a751888f4b0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/325420
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Commit-Queue: Slava Egorov <vegorov@google.com>
Commit-Queue: Daco Harkes <dacoharkes@google.com>
Auto-Submit: Slava Egorov <vegorov@google.com>
2023-09-12 12:09:06 +00:00
Vyacheslav Egorov 7ff975c2e5 [vm/compiler] Fix InferredTypeMetadata::IsTrivial
`IsTrivial` is supposed to return true iff `ToCompileType` would
produce a trivial (dynamic) type. However `IsTrivial` was taking
some of the irrevant parts of the `InferredTypeMetadata` into
account - meaning that it returned `false` where it should have
returned `true`.

This lead us to assign useless `dynamic` result type to various `StaticCall`, some of these calls can later be lowered to
`LoadIndexed` instructions, which will then also get the `dynamic`
result type. This useless type will then take priority over more
precise element type which could be inferred by
`LoadIndexedInstr::ComputeType`

TEST=vm/dart/load_indexed_trivial_type_il_test

Cq-Include-Trybots: luci.dart.try:vm-aot-linux-release-x64-try,vm-aot-linux-debug-simarm_x64-try,vm-aot-linux-debug-x64-try,vm-aot-android-release-arm64c-try
Change-Id: I69ee965ba0d0ac85ede3989680371f0dda19d8a9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/325302
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Slava Egorov <vegorov@google.com>
2023-09-12 08:13:12 +00:00
Tess Strickland 3f53d22d43 [vm/compiler] Create leaf runtime entry for memmove.
Instead of making a StaticCall to _TypedListBase.nativeSetRange
inside _memMoveN, make a CCall to the memmove leaf runtime entry.

Rename _TypedListBase._nativeSetRange to _setClampedRange, since
it's now only used when per-element clamping is necessary.

Fix the load optimizer so that loads of unboxed fields from freshly
allocated objects do not have the tagged null value forwarded
as their initial post-allocation value.

TEST=co19{,_2}/LibTest/typed_data lib{,_2}/typed_data
     corelib{,_2}/list_test
     vm/cc/LoadOptimizer_LoadDataFieldOfNewTypedData

Issue: https://github.com/dart-lang/sdk/issues/42072
Change-Id: Ib82e24a5b3287fa53099fffd3b563a27d777507e
Cq-Include-Trybots: luci.dart.try:vm-aot-linux-debug-simarm_x64-try,vm-aot-linux-debug-x64-try,vm-aot-linux-debug-x64c-try,vm-kernel-linux-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-linux-debug-x64-try,vm-linux-debug-x64c-try,vm-mac-debug-arm64-try,vm-aot-linux-release-simarm_x64-try,vm-aot-linux-release-x64-try,vm-aot-mac-release-arm64-try,vm-aot-msan-linux-release-x64-try,vm-msan-linux-release-x64-try,vm-aot-tsan-linux-release-x64-try,vm-tsan-linux-release-x64-try,vm-linux-release-x64-try,vm-mac-release-arm64-try,vm-kernel-precomp-linux-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/324080
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2023-09-11 21:25:09 +00:00
Ryan Macnak a4381f127c [vm, lib] Fix out-of-bounds access in BigInt.>>.
The library code and the intrisic code disagreed about the capacity of the result digits array. Compare similar adjustment for <<.

TEST=ci
Change-Id: I81395a242965d53de3a30f87637a6f1588300969
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/325122
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
2023-09-11 21:05:38 +00:00
Johnni Winther 4c1a94c0d3 [cfe] Embed tearoff in Extension(Type)MemberDescriptor
This simplifies handle the constructor/member and its corresponding
tearoff as a pair. Also it prepare for supporting tearoff of
extension type constructors and methods with the same name.

TEST=existing

Change-Id: Iea6cbc0250c8df6bd0f825068c1f3e865d938427
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/324202
Reviewed-by: Srujan Gaddam <srujzs@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
2023-09-11 13:35:10 +00:00
Jens Johansen c49f87382b [vm] Use specialized int set in heap snapshot tool
Currently the heap snapshot tool uses a regular Set<int> for storing
ints between 0 and the number of objects (n).

This CL instead introduces a specialized int set backed by a Uint8List
where each bit represents a number between 0 and n.

This specialized set is then created to fit the number of objects, so
even an empty set takes the same amount of space as a full set: about
125 kb per million possible values (or ~6 mb per 50 million).

For small sets thats a lot worse than before, but for big sets it's a
lot better. Runtime is also a lot better.

"Benchmarks" on a snapshot that's ~1.5GB:

Runtimes:

Before:
closure roots (or all after the first one): ~30s, ~19s, ~20s
eval and: ~5.5s, ~6.3, ~5.6
eval or: ~7.3s, ~6.5s, ~6.4s
eval minus: ~4.5s, ~6.4s, ~6.5s

With CL:
closure roots (or all after the first one): ~7.7s, ~4.3s, ~4.1s
eval and: ~0.2s, ~0.3s, ~0.2s
eval or: ~0.6s, ~0.6s, ~0.6s
eval minus: ~0.3s, ~0.2s, ~0.3s


Memory usage:

Before:

after loaded:
$ grep -E "VmPeak|VmSize|VmRSS" /proc/588700/status
VmPeak: 10293036 kB
VmSize:  9896880 kB
VmRSS:   9260604 kB

after all = closure roots
VmPeak: 12354840 kB
VmSize:  9529612 kB
VmRSS:   8898088 kB

after 2 x closure all
VmPeak: 13068580 kB
VmSize: 12478236 kB
VmRSS:  11891620 kB

after 3 x eval and
VmPeak: 18377540 kB
VmSize: 18376520 kB
VmRSS:  17803032 kB

after 3 x eval or
VmPeak: 19621712 kB
VmSize: 18114376 kB
VmRSS:  17491808 kB

after 3 x eval minus
VmPeak: 21522780 kB
VmSize: 21522272 kB
VmRSS:  20907724 kB


With CL:

after loaded:
$ grep -E "VmPeak|VmSize|VmRSS" /proc/594718/status
VmPeak: 10293560 kB
VmSize:  9967036 kB
VmRSS:   9323404 kB

after all = closure roots
VmPeak: 10293560 kB
VmSize:  9805272 kB
VmRSS:   9137364 kB

after 2 x closure all
VmPeak: 10868740 kB
VmSize: 10867208 kB
VmRSS:  10199784 kB

after 3 x eval and
VmPeak: 10906236 kB
VmSize: 10905728 kB
VmRSS:  10238424 kB

after 3 x eval or
VmPeak: 10925496 kB
VmSize: 10924988 kB
VmRSS:  10257388 kB

after 3 x eval minus

VmPeak: 10944756 kB
VmSize: 10944248 kB
VmRSS:  10276672 kB
Change-Id: I8d0b65fa51ac2bd4696c4d2782c4423966a7fbae
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/324682
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Jens Johansen <jensj@google.com>
2023-09-11 10:48:46 +00:00
Tess Strickland 959f21ab40 [vm/compiler] Use a block size of 16 bytes for ARM64 MemoryCopy.
TEST=vm/cc/IRTest_Memory, co19{,_2}/LibTest/typed_data,
     lib{,_2}/typed_data, corelib{,_2}/list_test

Issue: https://github.com/dart-lang/sdk/issues/42072

Cq-Include-Trybots: luci.dart.try:vm-mac-debug-arm64-try,vm-aot-linux-release-simarm64-try,vm-aot-mac-release-arm64-try,vm-linux-release-simarm64-try,vm-mac-release-arm64-try,vm-aot-android-release-arm64c-try,vm-ffi-android-debug-arm64c-try,vm-ffi-qemu-linux-release-arm-try,vm-ffi-qemu-linux-release-riscv64-try,vm-linux-debug-simriscv64-try,vm-linux-release-simarm-try
Change-Id: Ife645a1d09be862d74e198162b124e657878280a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/324683
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
2023-09-11 09:24:19 +00:00
Vyacheslav Egorov 00d883f459 [vm/compiler] Improve integer equality comparisons
Consider for example the following two functions

    f0(int value) => value == 0 ? ... : ...;
    f1(List<int> list) => list[0] == 1 ? ... : ...;

before this change we would produce a `BoxInt64(value)` followed by
`StrictCompare` in `f0` and `UnboxInt64` followed by `EqualityCompare`
in `f1`. However the decisions should be reversed: when comparing
unboxed values we should lean on `EqualityCompare` and when
comparing boxed values when smis are involved we should lean
on `StrictCompare`.

This change adjusts specialization and canonicalization rules to achieve
that: we prefer to emit `EqualityCompare` when specializing and then
add rule to collapse it back into `StrictCompare` if we discover that
is going to be more optimal (e.g. allows to avoid boxing).

TEST=vm/dart/aot_prefer_equality_comparison_il_test

Cq-Include-Trybots: luci.dart.try:vm-aot-linux-release-x64-try,vm-aot-linux-debug-simarm_x64-try,vm-aot-linux-debug-x64-try,vm-aot-android-release-arm64c-try
Change-Id: I953a346f22702debc61b84b745d2a9fab58a9ca5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/324981
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Slava Egorov <vegorov@google.com>
2023-09-11 07:56:47 +00:00
Nate Biggs a503edf481 [cfe] Fix kernel (de-)serialization missing field offset on FieldInitializer.
We are experiencing diffs in Dart2JS source maps in `--test-mode` which does a serialization round trip. JS that should map to default parameters is instead mapping to the surrounding `Constructor` member since the FieldInitializer's offset is getting dropped.

This is affecting any Dart2JS split action build since those all end of serialiaing and deserializing the kernel. Any other tools using this serialization would also be affected.

TEST=Existing/will add in follow up.

Bug: https://github.com/dart-lang/sdk/issues/53466
Change-Id: Ibeccf9153c78e6c358806c7ded4dbc2dea49d8e6
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/325020
Commit-Queue: Nate Biggs <natebiggs@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
2023-09-08 18:53:39 +00:00
Johnni Winther 1da590fc3f Fix type promotion of late final fields on DDC and dart2wasm.
When the CFE compiles code for DDC or dart2wasm, it lowers late final
fields to synthetic getters. In order to ensure that accesses to these
fields can still be type promoted, a flag is added to the kernel
`Procedure` class, to indicate that a getter was produced by lowering
a late final field. When deciding whether a property access is
promotable, the CFE checks this flag; if it's set, it treats the
getter like a field.

Includes a language test validating the fix.

Fixes https://github.com/dart-lang/sdk/issues/53462.

TEST=tests/language/inference_update_2/late_field_test.dart

Change-Id: I98b81f04a3342d851060e5b2a7265323b93bb4e3
Bug: https://github.com/dart-lang/sdk/issues/53462
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/324767
Reviewed-by: Slava Egorov <vegorov@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
2023-09-08 14:02:00 +00:00
Ryan Macnak fcda00866c [build] Export all symbols for the sanitizers.
This lets the sanitizers intercept any symbol. It's not worth trying to track which symbols the sanitizers are interested in. The sanitizer builds are not distributed so concerns about incompatibility, access to internals or size do not apply.

TEST=tsan
Bug: https://github.com/dart-lang/sdk/issues/53440
Change-Id: I59d137f4c15863cd27af857bfca4c53d847f2b90
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/324566
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
2023-09-07 15:03:08 +00:00
Tess Strickland 3bbe27eadf [vm/compiler] Perform word-sized copies in MemoryMove when possible.
When copying elements that are smaller than words on non-X86
architectures, only copy element by element until the remaining elements
can be copied in word-sized chunks, and then do so.

TEST=vm/cc/IRTest_Memory, co19{,_2}/LibTest/typed_data,
     lib{,_2}/typed_data, corelib{,_2}/list_test

Issue: https://github.com/dart-lang/sdk/issues/42072

Cq-Include-Trybots: luci.dart.try:vm-aot-linux-debug-simarm_x64-try,vm-aot-linux-debug-simriscv64-try,vm-linux-debug-simriscv64-try,vm-mac-debug-arm64-try,vm-aot-linux-release-simarm64-try,vm-aot-linux-release-simarm_x64-try,vm-aot-mac-release-arm64-try,vm-ffi-qemu-linux-release-riscv64-try,vm-ffi-qemu-linux-release-arm-try,vm-linux-release-simarm-try,vm-linux-release-simarm64-try,vm-mac-release-arm64-try,vm-aot-android-release-arm64c-try,vm-ffi-android-debug-arm64c-try
Change-Id: I61eab310b92a6bc5ebd88fa63d562103d887cb74
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/324280
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2023-09-07 14:11:19 +00:00
Ryan Macnak bb464cab79 [vm] Avoid linker warnings for run_vm_tests.
```
ld64.lld: warning: cannot export hidden symbol Dart_ActivationFrameInfo
>>> defined in obj/runtime/vm/run_vm_tests.debugger_api_impl_test.o
```

Namespace the former API functions retained for testing so they don't match the export glob Dart_*.

TEST=build
Change-Id: I4b7ed4125ef25cc33b6d4073399b0824019a1e01
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/324568
Reviewed-by: Alexander Aprelev <aam@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
2023-09-06 21:46:00 +00:00
Ryan Macnak ec70ca424e [test] Update the dart_2 copy of flutter_regress_91370_il_test.
Cf. 72e8b555aa.

Bug: https://github.com/dart-lang/sdk/issues/53442
Change-Id: I1a8d09bc64dc51175bb96e92b6a5d17c36398333
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/324563
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
2023-09-06 19:22:47 +00:00
Ryan Macnak 194951a41f [vm] Remove library lookup caches.
The library name cache is dead.

The library exported name cache is used indirectly through Dart_Invoke etc, and is practically only used for one-shot lookups like `main` or the embedder's startup hooks. The lookups that were worth caching now happen in the Dart frontend instead of the VM.

Cf. b9045af57b

TEST=ci
Change-Id: Ibd8bd30fbba3e9af32e3fbf3c5c4ced51a8d15d7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/324401
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
2023-09-06 18:11:58 +00:00
Ryan Macnak 428dd41b8c [vm] Don't leak strings when given non-normalized, unrecognized, repeated flags.
TEST=lsan
Bug: https://github.com/dart-lang/sdk/issues/53441
Change-Id: I09630ed20c96b82f0fc908a9fea008b682121424
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/324564
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
2023-09-06 18:10:33 +00:00
Alexander Aprelev 2df8b46b92 [gardening] Do not reset file_modified callback - it was never set.
Attempt to reset it results in diagnostic message returned, leak detected by asan.

BUG=https://github.com/dart-lang/sdk/issues/53443
TEST=ci

Change-Id: I52242d8b45e9891abfbfea27ff2bc97f833ad6dc
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/324562
Commit-Queue: Alexander Aprelev <aam@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2023-09-06 16:44:58 +00:00
Ryan Macnak b2773528d0 [vm, reload] Mark call to _nativeSetRange as no-rebind.
This is a magical direct call, not a Dart language static call. Don't attempt to re-lookup.

TEST=reload
Bug: https://github.com/dart-lang/sdk/issues/53430
Change-Id: I4b0fd2491f7d41e5f6180970abbd43e871bd18b5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/324263
Reviewed-by: Tess Strickland <sstrickl@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
2023-09-06 16:19:48 +00:00
Daco Harkes 69afe5a407 [gardening] Skip exported_symbols_test.dart on sanitizers
Closes: https://github.com/dart-lang/sdk/issues/53438
Change-Id: I6fdb362de688d01b28b600c4aab232a966ef4082
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/324283
Auto-Submit: Daco Harkes <dacoharkes@google.com>
Commit-Queue: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
2023-09-06 09:18:32 +00:00
Ryan Macnak 53fb57ea5e [vm, io] Restore global destructors for normal shutdown path.
Cf. ef4984566b.

TEST=samples/hello_world
Bug: https://github.com/dart-lang/samples/issues/195
Change-Id: I05cac92500a912c5d3e0771f626878decac18a9b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/324267
Reviewed-by: Brian Quinlan <bquinlan@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
2023-09-05 22:15:58 +00:00
Ryan Macnak b8ee3a9996 [build] Don't export all symbols to the dynamic table.
We were exporting all symbols to the dynamic table so that they could be looked up using `dladdr` for the profiler and backtracer. The symbols include our statically-linked libcxx, which can create trouble when another DSO has a different version of libcxx. Now we export only the VM embedding API functions (`Dart_*`) and use a specially produced table to do the symbolization.

TEST=runtime/tests/vm/dart/exported_symbols_test.dart
TEST=runtime/tests/vm/dart/symbolized_crash_test.dart
Bug: https://github.com/dart-lang/sdk/issues/53267
Change-Id: I2ee494fba86f67127ba0f6f402622f01a4662207
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/323702
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
2023-09-05 21:47:59 +00:00
Ryan Macnak 72e8b555aa [vm, compiler] Add TestRangeInstr.
- Avoid Smi tagging for CID checks.
 - Use one branch for CID range checks.

dart2js.aot.arm64 20744832 -> 20690216 (-54k)

TEST=ci
Change-Id: I0690bd98774ffc2f24758b1a303c605b57da65b0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/323231
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
2023-09-05 19:56:07 +00:00
Tess Strickland b94d3f730d [vm/compiler] Move setRange bounds checking entirely into Dart.
The bounds checking was implemented in Dart previously, but this
removes _checkSetRangeArguments, inlining it into
_TypedListBase.setRange, renames _checkBoundsAndMemcpyN to _memMoveN
since it no longer performs bounds checking, and also removes the now
unneeded bounds checking from the native function TypedData_setRange.

TEST=co19{,_2}/LibTest/typed_data lib{,_2}/typed_data
     corelib{,_2}/list_test

Issue: https://github.com/dart-lang/sdk/issues/42072
Cq-Include-Trybots: luci.dart.try:vm-aot-linux-debug-simarm_x64-try,vm-aot-linux-debug-x64-try,vm-aot-linux-debug-x64c-try,vm-kernel-linux-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-linux-debug-x64-try,vm-linux-debug-x64c-try,vm-mac-debug-arm64-try,vm-aot-linux-release-simarm_x64-try,vm-aot-linux-release-x64-try,vm-aot-mac-release-arm64-try,vm-linux-release-x64-try,vm-mac-release-arm64-try,vm-kernel-precomp-linux-release-x64-try
Change-Id: I85ec751708f603f68729f4109d7339dd8407ae77
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/324102
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2023-09-05 17:10:51 +00:00
Tess Strickland c93f924c82 [vm/compiler] Further optimize setRange on TypedData receivers.
When setRange is called on a TypedData receiver and the source is also
a TypedData object with the same element size and clamping is not
required, the VM implementation now calls _boundsCheckAndMemcpyN for
element size N. The generated IL for these methods performs the copy
using the MemoryCopy instruction (mostly, see the note below).

Since the two TypedData objects might have the same underlying
buffer, the CL adds a can_overlap flag to the MemoryCopy instruction
which checks for overlapping regions. If can_overlap is set, then
the copy is performed backwards instead of forwards when needed
to ensure that elements of the source region are read before
they are overwritten.

The existing uses of the MemoryCopy instruction are adjusted as
follows:
* The IL generated for copyRangeFromUint8ListToOneByteString
  passes false for can_overlap, as all uses currently ensure that
  the OneByteString is non-external and thus cannot overlap.
* The IL generated for _memCopy, used by the FFI library, passes
  true for can_overlap, as there is no guarantee that the regions
  pointed at by the Pointer objects do not overlap.

The MemoryCopy instruction has also been adjusted so that all numeric
inputs (the two start offsets and the length) are either boxed or
unboxed instead of just the length. This exposed an issue
in the inliner, where unboxed constants in the callee graph were
replaced with boxed constants when inlining into the caller graph,
since withList calls setRange with constant starting offsets of 0.
Now the representation of constants in the callee graph are preserved
when inlining the callee graph into the caller graph.

Fixes https://github.com/dart-lang/sdk/issues/51237 by using TMP
and TMP2 for the LDP/STP calls in the 16-byte element size case, so no
temporaries need to be allocated for the instruction.

On ARM when not unrolling the memory copy loop, uses TMP and a single
additional temporary for LDM/STM calls in the 8-byte and 16-byte
element cases, with the latter just using two LDM/STM calls within
the loop, a different approach than the one described in
https://github.com/dart-lang/sdk/issues/51229 .

Note: Once the number of elements being copied reaches a certain
threshold (1048576 on X86, 256 otherwise), _boundsCheckAndMemcpyN
instead calls _nativeSetRange, which is a native call that uses memmove
from the standard C library for non-clamped inputs. It does this
because the code currently emitted for MemoryCopy performs poorly
compared to the more optimized memmove implementation when copying
larger regions of memory.

Notable benchmark changes for dart-aot:
* X64
  * TypedDataDuplicate.*.fromList improvement from ~13%-~250%
  * Uf8Encode.*.10 improvement from ~50%-~75%
  * MapCopy.Map.*.of.Map.* improvement from ~13%-~65%
  * MemoryCopy.*.setRange.* improvement from ~13%-~500%
* ARM7
  * Uf8Encode.*.10 improvement from ~35%-~70%
  * MapCopy.Map.*.of.Map.* improvement from ~6%-~75%
  * MemoryCopy.*.setRange.{8,64} improvement from ~22%-~500%
    * Improvement of ~100%-~200% for MemoryCopy.512.setRange.*.Double
    * Regression of ~40% for MemoryCopy.512.setRange.*.Uint8
    * Regression of ~85% for MemoryCopy.4096.setRange.*.Uint8
* ARM8
  * Uf8Encode.*.10 improvement from ~35%-~70%
  * MapCopy.Map.*.of.Map.* improvement from ~7%-~75%
  * MemoryCopy.*.setRange.{8,64} improvement from ~22%-~500%
    * Improvement of ~75%-~160% for MemoryCopy.512.setRange.*.Double
    * Regression of ~40% for MemoryCopy.512.setRange.*.Uint8
    * Regression of ~85% for MemoryCopy.4096.setRange.*.Uint8

TEST=vm/cc/IRTest_Memory, co19{,_2}/LibTest/typed_data,
     lib{,_2}/typed_data, corelib{,_2}/list_test

Issue: https://github.com/dart-lang/sdk/issues/42072
Issue: b/294114694
Issue: b/259315681

Change-Id: Ic75521c5fe10b952b5b9ce5f2020c7e3f03672a9
Cq-Include-Trybots: luci.dart.try:vm-aot-linux-debug-simarm_x64-try,vm-aot-linux-debug-simriscv64-try,vm-aot-linux-debug-x64-try,vm-aot-linux-debug-x64c-try,vm-kernel-linux-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-linux-debug-ia32-try,vm-linux-debug-simriscv64-try,vm-linux-debug-x64-try,vm-linux-debug-x64c-try,vm-mac-debug-arm64-try,vm-mac-debug-x64-try,vm-aot-linux-release-simarm64-try,vm-aot-linux-release-simarm_x64-try,vm-aot-linux-release-x64-try,vm-aot-mac-release-arm64-try,vm-aot-mac-release-x64-try,vm-ffi-qemu-linux-release-riscv64-try,vm-ffi-qemu-linux-release-arm-try,vm-aot-msan-linux-release-x64-try,vm-msan-linux-release-x64-try,vm-aot-tsan-linux-release-x64-try,vm-tsan-linux-release-x64-try,vm-linux-release-ia32-try,vm-linux-release-simarm-try,vm-linux-release-simarm64-try,vm-linux-release-x64-try,vm-mac-release-arm64-try,vm-mac-release-x64-try,vm-kernel-precomp-linux-release-x64-try,vm-aot-android-release-arm64c-try,vm-ffi-android-debug-arm64c-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/319521
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2023-09-04 14:38:27 +00:00
Tess Strickland 429ba99568 [vm/compiler] Only print traces when the flow graph should be printed.
When either the --trace-optimization or --trace-load-optimization
flags are used, only print those traces if the associated flow graph
would be printed (i.e., it matches the filter given by
--print-flow-graph-filter, or no filter is given).

TEST=ci

Change-Id: Ibfb72455de483fe471a5eb0261a5e803578f0bb2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/323600
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2023-09-01 10:39:46 +00:00
Alexander Aprelev 2f457d1a8a [vm/debugger] Use RwLock instead of SafepointRwLock, get rid of RunUnderLockIfNeeded.
RwLock, rather that SafepointRwLock, is okay to use for these two breakpoint_locations and single_stepping_set locks because they are short-lived, should not spawn over the safepoint.
TEST=ci

Change-Id: Iba83291978ba7980d0c6fd0a0a2cf2174c801359
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/323202
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Alexander Aprelev <aam@google.com>
2023-08-31 19:52:23 +00:00
Vyacheslav Egorov 46ac1f653f [vm] Treat Future.then(..., onError:...) as catch all handler
Commit a52f2b9 which reworked awaiter stack unwinding and its
integration with debugger introduced the following regression:
it stopped treating `Future` listeners which had both `onValue`
and `onError` callbacks as catch all exception handlers. Only
listners with `onError` callback (those created with
`Future.onError`) were treated as a catch all handler.

This meant that debugger started to treat exceptions in the
code below as uncaught:

```
Future<void> foo() {
  await 0;
  throw '';
}

await foo().then(..., onError: (e, st) {

});
```

This change fixes this regression by checking if
`FutureListener.state & stateCatchError != 0` instead of
more narrow `FutureListener.state == stateCatchError` which
only detects listeners which only catch errors but do not
handle values. The new predicate matches
`FutureListener.handlesError`.

This relands 38e0046cad
with a fix to ensure that we correctly detect `onError`
callbacks which simply forward to a suspended async
function. We do this by marking FutureListener's that originate
from `await` using a bit in the state.

Fixes https://github.com/dart-lang/sdk/issues/53334

TEST=service/pause_on_unhandled_async_exceptions{_zones,}_test

Fixed: 53334
CoreLibraryReviewExempt: No fundamental changes to _FutureListener implementation, just additional bit to detect that this listener originates from await
Change-Id: I90385fc619cbb52925e075dd5c7b171a31ca4cab
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/323481
Commit-Queue: Slava Egorov <vegorov@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
2023-08-31 11:47:54 +00:00
Siva Annamalai 98b9b6c07c Revert "[vm] Treat Future.then(..., onError:...) as catch all handler"
This reverts commit 38e0046cad.

Reason for revert: https://github.com/flutter/flutter/issues/133677

Original change's description:
> [vm] Treat Future.then(..., onError:...) as catch all handler
>
> Commit a52f2b9 which reworked awaiter stack unwinding and its
> integration with debugger introduced the following regression:
> it stopped treating `Future` listeners which had both `onValue`
> and `onError` callbacks as catch all exception handlers. Only
> listners with `onError` callback (those created with
> `Future.onError`) were treated as a catch all handler.
>
> This meant that debugger started to treat exceptions in the
> code below as uncaught:
>
> ```
> Future<void> foo() {
>   await 0;
>   throw '';
> }
>
> await foo().then(..., onError: (e, st) {
>
> });
> ```
>
> This change fixes this regression by checking if
> `FutureListener.state & stateCatchError != 0` instead of
> more narrow `FutureListener.state == stateCatchError` which
> only detects listeners which only catch errors but do not
> handle values. The new predicate matches
> `FutureListener.handlesError`.
>
> Fixes https://github.com/dart-lang/sdk/issues/53334
>
> TEST=service/pause_on_unhandled_async_exceptions_test
>
> Fixed: 53334
> Change-Id: I374114b7a7b2ef86b7ed6bf7d5e7cf71ba6054dc
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/323280
> Reviewed-by: Alexander Markov <alexmarkov@google.com>
> Reviewed-by: Ben Konyi <bkonyi@google.com>
> Commit-Queue: Slava Egorov <vegorov@google.com>

Change-Id: Id20a6929aac93511173c7467caee91e2488696ed
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/323429
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Commit-Queue: Siva Annamalai <asiva@google.com>
Reviewed-by: Ben Konyi <bkonyi@google.com>
2023-08-30 18:24:46 +00:00
Alexander Markov b9045af57b [vm] Cleanup lookups in the library import
Lookup in the library import can be very slow and it is not needed
most of the time. This change makes Library::Lookup{Class,Function,Field}[AllowPrivate]
lookups local in the library and cleans up related or unused code.

TEST=ci

Change-Id: If5a99bce7d712ce3a898395f74d4febac0311048
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/323221
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2023-08-30 17:18:53 +00:00
Tess Strickland d6e0590255 [vm/test] Avoid temporary changes to disassemble_optimized under TSAN.
Don't temporarily set FLAG_disassemble_optimized using SetFlagScope
in tests when using TSAN, as it doesn't change the behavior. It only
adds extra output from the test for debugging purposes, and its use
under TSAN can cause flaky results from the TSAN trybot.

TEST=ci

Fixes: https://github.com/dart-lang/sdk/issues/53384
Cq-Include-Trybots: luci.dart.try:vm-tsan-linux-release-x64-try
Change-Id: Ifa97c8784ca84316c784cb772b1a12ad8123a090
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/323362
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Auto-Submit: Tess Strickland <sstrickl@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2023-08-30 14:34:37 +00:00
Vyacheslav Egorov 38e0046cad [vm] Treat Future.then(..., onError:...) as catch all handler
Commit a52f2b9 which reworked awaiter stack unwinding and its
integration with debugger introduced the following regression:
it stopped treating `Future` listeners which had both `onValue`
and `onError` callbacks as catch all exception handlers. Only
listners with `onError` callback (those created with
`Future.onError`) were treated as a catch all handler.

This meant that debugger started to treat exceptions in the
code below as uncaught:

```
Future<void> foo() {
  await 0;
  throw '';
}

await foo().then(..., onError: (e, st) {

});
```

This change fixes this regression by checking if
`FutureListener.state & stateCatchError != 0` instead of
more narrow `FutureListener.state == stateCatchError` which
only detects listeners which only catch errors but do not
handle values. The new predicate matches
`FutureListener.handlesError`.

Fixes https://github.com/dart-lang/sdk/issues/53334

TEST=service/pause_on_unhandled_async_exceptions_test

Fixed: 53334
Change-Id: I374114b7a7b2ef86b7ed6bf7d5e7cf71ba6054dc
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/323280
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Ben Konyi <bkonyi@google.com>
Commit-Queue: Slava Egorov <vegorov@google.com>
2023-08-29 20:08:43 +00:00
Alexander Markov 8a85dac792 [vm/compiler] Avoid searching static functions in the imported libraries
References to members are fully resolved in kernel. So, when
looking for a static function in the library scope, there is no need to
search in the imported libraries.

Searching in the imported libraries could be very slow as they can be
huge (e.g. the whole Flutter framework).

Fixes https://github.com/flutter/flutter/issues/133195
TEST=manually verified repro from https://github.com/flutter/flutter/issues/133195

Change-Id: Ia7e19a6ceaac291192c34b96587dad5cb4b80aad
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/323201
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
2023-08-29 17:19:30 +00:00
Alexander Aprelev 01c0ddd2f8 [vm/debugger] Use RwLocker instead of SafepointRwLocker when managing code breakpoints.
RwLocker is sufficient here because code breakpoints lock doesn't get carried through the safepoint.

BUG=https://github.com/dart-lang/sdk/issues/53342
TEST=break_on_function_*

Change-Id: I8045f773ab987af2bcc016c75c9cb24d35aabf10
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/323060
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Alexander Aprelev <aam@google.com>
2023-08-29 16:19:40 +00:00
Liam Appelbe dd26db6d45 [vm/ffi] Fix copypasta in Fuchsia arm64 FFI callback stub
Change-Id: Iaecf7d9d8f8fc9bef0104c4239906c5c4220b537
Fixes: https://github.com/dart-lang/sdk/issues/53296
TEST=CI (though this specific code path is untested)
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/322100
Commit-Queue: Liam Appelbe <liama@google.com>
Auto-Submit: Liam Appelbe <liama@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2023-08-28 20:52:02 +00:00
Ryan Macnak 7f9362fb42 [vm, compiler] Avoid extra branch on ARM to handle double comparisons with NaN.
TEST=ci
Change-Id: Ie73a5e11da0fe085a209a6a8f684aaf1f77b696f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/322800
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
2023-08-28 20:16:57 +00:00
Emmanuel Pellereau a675a79f39 Revert "Reland "[vm, gc] Mark through new-space.""
This reverts commit 095171e937.

Reason for revert: breaks google3 (b/296014654)

Original change's description:
> Reland "[vm, gc] Mark through new-space."
>
>  - Adjust allocation stub write barrier elimination compensation to check if result is no longer in an active TLAB.
>
> TEST=ci
> Change-Id: I5d24602ae76ee861f2d009d67272251b04da3592
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/322448
> Commit-Queue: Ryan Macnak <rmacnak@google.com>
> Reviewed-by: Siva Annamalai <asiva@google.com>

Change-Id: I73b60f799dda755028b65653ac21f27c13e009e3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/322682
Reviewed-by: Tess Strickland <sstrickl@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Emmanuel Pellereau <emmanuelp@google.com>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Reviewed-by: Ivan Inozemtsev <iinozemtsev@google.com>
Reviewed-by: Alexander Thomas <athom@google.com>
Commit-Queue: Ivan Inozemtsev <iinozemtsev@google.com>
2023-08-28 14:34:21 +00:00
Jonas Termansen c9f8d41cd1 [infra] Use actual package names in the generated package config.
Fixes: b/297182119
Tested: Commit queue
Change-Id: I2935dacd9d879c474eaa31d85e67cb7b2bdff769
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/322321
Commit-Queue: Jonas Termansen <sortie@google.com>
Reviewed-by: Alexander Thomas <athom@google.com>
2023-08-28 10:29:48 +00:00
Ryan Macnak 095171e937 Reland "[vm, gc] Mark through new-space."
- Adjust allocation stub write barrier elimination compensation to check if result is no longer in an active TLAB.

TEST=ci
Change-Id: I5d24602ae76ee861f2d009d67272251b04da3592
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/322448
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
2023-08-25 21:13:02 +00:00
Ryan Macnak 708f098c4f [vm, compiler] Add option to suppress obfuscation of type names for some hierarchy.
This behaves like applying @pragma("vm:keep-name") to the hiearchy.

TEST=ci
Bug: b/285175418
Change-Id: Ibd543d294bebbfbb60f4e5d62d5e83f3aec841e7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/322582
Reviewed-by: Slava Egorov <vegorov@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
2023-08-25 18:55:32 +00:00
Daco Harkes 3094d06f81 [gardening] Disassembler print missing position information
When trying to disassemble, we should have position information.
However, when it's missing it would be better to show this instead of
crashing. The CFE validator should validate that position information
is included everywhere.

TEST=tests/language/unsorted/disassemble_test.dart

Bug: https://github.com/dart-lang/sdk/issues/53348
Change-Id: I94142ef4c875d2738141ee8fd0def309469ca92d
Cq-Include-Trybots: luci.dart.try:vm-linux-debug-ia32-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/322663
Reviewed-by: Martin Kustermann <kustermann@google.com>
2023-08-25 15:25:17 +00:00
Daco Harkes 1de6b6dce1 [gardening] Fix run_appended_aot_snapshot_test
https://dart-review.googlesource.com/c/sdk/+/322521 Removed the
`enableAsserts` argument from `generateAotSnapshot` but didn't update
the callsites in this test.

Change-Id: Ibde9a60a6129fb50b6af74d4d5603be95e6d14f9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/322640
Commit-Queue: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2023-08-25 08:05:08 +00:00
Liam Appelbe e8d7425c4e [vm/ffi] Closure callbacks for sync callbacks
Bug: https://github.com/dart-lang/sdk/issues/52689
Change-Id: I54be397cfbf8519fe5b5a51b793fe46d602124d9
Fixes: https://github.com/dart-lang/sdk/issues/52689
Bug: https://github.com/dart-lang/sdk/issues/53096
TEST=isolate_local_function_callbacks_test.dart, plus generated tests and additions to existing tests
CoreLibraryReviewExempt: The isolate and FFI packages are VM-only
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/317060
Commit-Queue: Liam Appelbe <liama@google.com>
Reviewed-by: Liam Appelbe <liama@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2023-08-25 03:35:44 +00:00
Ryan Macnak 5eb4444c50 [vm, gc] More stress tests.
TEST=ci
Change-Id: Id6795c33815886e7c45871a919f88dfab4be350d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/322371
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
2023-08-24 21:46:28 +00:00
Ryan Macnak 7040faf81f [vm, compiler] Remove dead parameter from EnsureIsNewOrRemembered.
TEST=ci
Change-Id: I4d6fbcc9557857bb5172b8dc1e7384a7a2c01398
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/322370
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
2023-08-24 17:25:30 +00:00