Commit Graph

253 Commits

Author SHA1 Message Date
Nicholas Nethercote
4f800b56d0 Clarify follow_inlining.
I found this confusing because it includes the root item, plus the
inlined items reachable from the root item. The new formulation
separates the two parts more clearly.
2023-06-02 13:07:30 +10:00
Nicholas Nethercote
3806bad6cf Simplify place_inlined_mono_items.
Currently it overwrites all the CGUs with new CGUs. But those new CGUs
are just copies of the old CGUs, possibly with some things added. This
commit changes things so that each CGU just gets added to in place,
which makes things simpler and clearer.
2023-06-02 13:07:30 +10:00
Nicholas Nethercote
f1fe797ee2 Change representation of UsageMap::used_map.
It currently uses ranges, which index into `UsageMap::used_items`. This
commit changes it to just use `Vec`, which is much simpler to construct
and use. This change does result in more allocations, but it is few
enough that the perf impact is negligible.
2023-06-02 13:07:30 +10:00
Nicholas Nethercote
5b0c56b333 Introduce UsageMap::user_map.
`UsageMap` contains `used_map`, which maps from an item to the item it
uses. This commit add `user_map`, which is the inverse.

We already compute this inverse, but later on, and it is only held as a
local variable. Its simpler and nicer to put it next to `used_map`.
2023-06-02 13:07:30 +10:00
Nicholas Nethercote
de2911f454 Overhaul CGU formation terminology.
Currently, the code uses multiple words to describe when a mono item `f`
uses a mono item `g`, all of which have problems.

- `f` references `g`: confusing because there are multiple kinds of use,
  e.g. "`f` calls `g`" is one, but "`f` takes a (`&T`-style) reference
  of `g`" is another, and that's two subtly different meanings of
  "reference" in play.

- `f` accesses `g`: meh, "accesses" makes me think of data, and this is
  code.

- `g` is a neighbor (or neighbour) of `f`: is verbose, and doesn't
  capture the directionality.

This commit changes the code to use "`f` uses `g`" everywhere. I think
it's better than the current terminology, and the consistency is
important.

Also, `InliningMap` is renamed `UsageMap` because (a) it was always
mostly about usage, and (b) the inlining information it did record was
removed in a recent commit.
2023-06-02 13:07:28 +10:00
Matthias Krüger
c6aec9459e
Rollup merge of #112155 - nnethercote:debug_dump, r=wesleywiser
Improve CGU debug printing.

- Add more total and per-CGU measurements.
- Ensure CGUs are sorted by name before the first `debug_dump` calls, for deterministic output.
- Print items within CGUs in sorted-by-name order, for deterministic output.
- Add some assertions and comments clarifying sortedness of CGUs at various points.

An example, before:
```
INITIAL PARTITIONING (5 CodegenUnits, max=29, min=1, max/min=29.0):
CodegenUnit scev95ysd7g4b0z estimated size 2:
 - fn <() as std::process::Termination>::report [(External, Hidden)] [h082b15a6d07338dcE] estimated size 2

CodegenUnit 1j0frgtl72rsz24q estimated size 29:
 - fn std::rt::lang_start::<()>::{closure#0} [(External, Hidden)] [h695c7b5d6a212565E] estimated size 17
 - fn std::rt::lang_start::<()> [(External, Hidden)] [h4ca942948e9cb931E] estimated size 12

CodegenUnit 5dbzi1e5qm0d7kj2 estimated size 4:
 - fn <[closure@std::rt::lang_start<()>::{closure#0}] as std::ops::FnOnce<()>>::call_once - shim [(External, Hidden)] [h24eaa44f03b2b233E] estimated size 1
 - fn <fn() as std::ops::FnOnce<()>>::call_once - shim(fn()) [(External, Hidden)] [hf338f5339c3711acE] estimated size 1
 - fn <[closure@std::rt::lang_start<()>::{closure#0}] as std::ops::FnOnce<()>>::call_once - shim(vtable) [(External, Hidden)] [h595d414cbb7651d5E] estimated size 1
 - fn std::ptr::drop_in_place::<[closure@std::rt::lang_start<()>::{closure#0}]> - shim(None) [(External, Hidden)] [h17a19dcdb40600daE] estimated size 1

CodegenUnit 220m1mqa2mlbg7r3 estimated size 1:
 - fn main [(External, Hidden)] [hb29587cdb6db5f42E] estimated size 1

CodegenUnit 4ulbh241f7tvyn7x estimated size 6:
 - fn std::sys_common::backtrace::__rust_begin_short_backtrace::<fn(), ()> [(External, Hidden)] [h41dada2c21a1259dE] estimated size 6
```
and after:
```
INITIAL PARTITIONING (9 items, total_size=42; 5 CGUs, max_size=29, min_size=1, max_size/min_size=29.0):
- CGU[0] 1j0frgtl72rsz24q (2 items, size=29):
  - fn std::rt::lang_start::<()> [(External, Hidden)] [h4ca942948e9cb931E] (size=12)
  - fn std::rt::lang_start::<()>::{closure#0} [(External, Hidden)] [h695c7b5d6a212565E] (size=17)

- CGU[1] 220m1mqa2mlbg7r3 (1 items, size=1):
  - fn main [(External, Hidden)] [hb29587cdb6db5f42E] (size=1)

- CGU[2] 4ulbh241f7tvyn7x (1 items, size=6):
  - fn std::sys_common::backtrace::__rust_begin_short_backtrace::<fn(), ()> [(External, Hidden)] [h41dada2c21a1259dE] (size=6)

- CGU[3] 5dbzi1e5qm0d7kj2 (4 items, size=4):
  - fn <[closure@std::rt::lang_start<()>::{closure#0}] as std::ops::FnOnce<()>>::call_once - shim(vtable) [(External, Hidden)] [h595d414cbb7651d5E] (size=1)
  - fn <[closure@std::rt::lang_start<()>::{closure#0}] as std::ops::FnOnce<()>>::call_once - shim [(External, Hidden)] [h24eaa44f03b2b233E] (size=1)
  - fn <fn() as std::ops::FnOnce<()>>::call_once - shim(fn()) [(External, Hidden)] [hf338f5339c3711acE] (size=1)
  - fn std::ptr::drop_in_place::<[closure@std::rt::lang_start<()>::{closure#0}]> - shim(None) [(External, Hidden)] [h17a19dcdb40600daE] (size=1)

- CGU[4] scev95ysd7g4b0z (1 items, size=2):
  - fn <() as std::process::Termination>::report [(External, Hidden)] [h082b15a6d07338dcE] (size=2)
```

r? ``@wesleywiser``
2023-06-01 22:47:33 +02:00
Nicholas Nethercote
1191bea6ab Improve CGU debug printing.
- Add more total and per-CGU measurements.
- Ensure CGUs are sorted by name before the first `debug_dump` calls,
  for deterministic output.
- Print items within CGUs in sorted-by-name order, for deterministic
  output.
- Add some assertions and comments clarifying sortedness of CGUs at
  various points.

An example, before:
```
INITIAL PARTITIONING (5 CodegenUnits, max=29, min=1, max/min=29.0):
CodegenUnit scev95ysd7g4b0z estimated size 2:
 - fn <() as std::process::Termination>::report [(External, Hidden)] [h082b15a6d07338dcE] estimated size 2

CodegenUnit 1j0frgtl72rsz24q estimated size 29:
 - fn std::rt::lang_start::<()>::{closure#0} [(External, Hidden)] [h695c7b5d6a212565E] estimated size 17
 - fn std::rt::lang_start::<()> [(External, Hidden)] [h4ca942948e9cb931E] estimated size 12

CodegenUnit 5dbzi1e5qm0d7kj2 estimated size 4:
 - fn <[closure@std::rt::lang_start<()>::{closure#0}] as std::ops::FnOnce<()>>::call_once - shim [(External, Hidden)] [h24eaa44f03b2b233E] estimated size 1
 - fn <fn() as std::ops::FnOnce<()>>::call_once - shim(fn()) [(External, Hidden)] [hf338f5339c3711acE] estimated size 1
 - fn <[closure@std::rt::lang_start<()>::{closure#0}] as std::ops::FnOnce<()>>::call_once - shim(vtable) [(External, Hidden)] [h595d414cbb7651d5E] estimated size 1
 - fn std::ptr::drop_in_place::<[closure@std::rt::lang_start<()>::{closure#0}]> - shim(None) [(External, Hidden)] [h17a19dcdb40600daE] estimated size 1

CodegenUnit 220m1mqa2mlbg7r3 estimated size 1:
 - fn main [(External, Hidden)] [hb29587cdb6db5f42E] estimated size 1

CodegenUnit 4ulbh241f7tvyn7x estimated size 6:
 - fn std::sys_common::backtrace::__rust_begin_short_backtrace::<fn(), ()> [(External, Hidden)] [h41dada2c21a1259dE] estimated size 6
```
and after:
```
INITIAL PARTITIONING (9 items, total_size=42; 5 CGUs, max_size=29, min_size=1, max_size/min_size=29.0):
- CGU[0] 1j0frgtl72rsz24q (2 items, size=29):
  - fn std::rt::lang_start::<()> [(External, Hidden)] [h4ca942948e9cb931E] (size=12)
  - fn std::rt::lang_start::<()>::{closure#0} [(External, Hidden)] [h695c7b5d6a212565E] (size=17)

- CGU[1] 220m1mqa2mlbg7r3 (1 items, size=1):
  - fn main [(External, Hidden)] [hb29587cdb6db5f42E] (size=1)

- CGU[2] 4ulbh241f7tvyn7x (1 items, size=6):
  - fn std::sys_common::backtrace::__rust_begin_short_backtrace::<fn(), ()> [(External, Hidden)] [h41dada2c21a1259dE] (size=6)

- CGU[3] 5dbzi1e5qm0d7kj2 (4 items, size=4):
  - fn <[closure@std::rt::lang_start<()>::{closure#0}] as std::ops::FnOnce<()>>::call_once - shim(vtable) [(External, Hidden)] [h595d414cbb7651d5E] (size=1)
  - fn <[closure@std::rt::lang_start<()>::{closure#0}] as std::ops::FnOnce<()>>::call_once - shim [(External, Hidden)] [h24eaa44f03b2b233E] (size=1)
  - fn <fn() as std::ops::FnOnce<()>>::call_once - shim(fn()) [(External, Hidden)] [hf338f5339c3711acE] (size=1)
  - fn std::ptr::drop_in_place::<[closure@std::rt::lang_start<()>::{closure#0}]> - shim(None) [(External, Hidden)] [h17a19dcdb40600daE] (size=1)

- CGU[4] scev95ysd7g4b0z (1 items, size=2):
  - fn <() as std::process::Termination>::report [(External, Hidden)] [h082b15a6d07338dcE] (size=2)
```
2023-06-01 11:31:22 +10:00
Nicholas Nethercote
cc21d9aa52 Don't compute inlining status of mono items in advance.
We record inlining status for mono items in `MonoItems`, and then
transfer it to `InliningMap`, for later use in
`InliningMap::with_inlining_candidates`.

But we can just compute inlining status directly in
`InliningMap::with_inlining_candidates`, because the mono item is right
there. There's no need to compute it in advance.

This commit changes the code to do that, removing the need for
`MonoItems` and `InliningMap::inlines`. This does result in more calls
to `instantiation_mode` (one per static occurrence) but the performance
effect is negligible.
2023-05-31 21:53:31 +10:00
Matthias Krüger
7ca941f18e
Rollup merge of #112053 - nnethercote:rm-Zcpu-partitioning-strategy, r=wesleywiser
Remove `-Zcgu-partitioning-strategy`.

This option was introduced three years ago, but it's never been meaningfully used, and `default` is the only acceptable value.

Also, I think the `Partition` trait presents an interface that is too closely tied to the existing strategy and would probably be wrong for other strategies. (My rule of thumb is to not make something generic until there are at least two instances of it, to avoid this kind of problem.)

Also, I don't think providing multiple partitioning strategies to the user is a good idea, because the compiler already has enough obscure knobs.

This commit removes the option, along with the `Partition` trait, and the `Partitioner` and `DefaultPartitioning` types. I left the existing code in `compiler/rustc_monomorphize/src/partitioning/default.rs`, though I could be persuaded that moving it into
`compiler/rustc_monomorphize/src/partitioning/mod.rs` is better.

r? ``@wesleywiser``
2023-05-31 07:07:00 +02:00
Nicholas Nethercote
5ed014977e Rename partitioning/mod.rs as partitioning.rs.
Because it's now the only file within
`compiler/rustc_monomorphize/src/partitioning/`.
2023-05-30 17:48:55 +10:00
Nicholas Nethercote
66cf072ac8 Merge default.rs into mod.rs.
Within `compiler/rustc_monomorphize/src/partitioning/`, because the
previous commit removed the need for `default.rs` to be a separate file.
2023-05-30 17:48:54 +10:00
Nicholas Nethercote
97d4a38de9 Remove -Zcgu-partitioning-strategy.
This option was introduced three years ago, but it's never been
meaningfully used, and `default` is the only acceptable value.

Also, I think the `Partition` trait presents an interface that is too
closely tied to the existing strategy and would probably be wrong for
other strategies. (My rule of thumb is to not make something generic
until there are at least two instances of it, to avoid this kind of
problem.)

Also, I don't think providing multiple partitioning strategies to the
user is a good idea, because the compiler already has enough obscure
knobs.

This commit removes the option, along with the `Partition` trait, and
the `Partitioner` and `DefaultPartitioning` types. I left the existing
code in `compiler/rustc_monomorphize/src/partitioning/default.rs`,
though I could be persuaded that moving it into
`compiler/rustc_monomorphize/src/partitioning/mod.rs` is better.
2023-05-30 17:48:49 +10:00
lcnr
08d149ca85 EarlyBinder::new -> EarlyBinder::bind 2023-05-29 13:46:10 +02:00
Kyle Matsuda
03534ac8b7 Replace EarlyBinder(x) with EarlyBinder::new(x) 2023-05-28 10:44:50 -06:00
Nicholas Nethercote
e6b99a6521 Add struct for the return type of place_root_mono_items.
As per review request.
2023-05-26 07:28:02 +10:00
Nicholas Nethercote
86754cd8f2 Remove some unnecessary pub markers. 2023-05-25 14:27:37 +10:00
Nicholas Nethercote
59c5259bc9 Add a clarifying comment.
This is something that took me some time to figure out.
2023-05-24 12:33:35 +10:00
Nicholas Nethercote
20de2ba759 Remove {Pre,Post}InliningPartitioning.
I find that these structs obfuscate the code. Removing them and just
passing the individual fields around makes the `Partition` method
signatures a little longer, but makes the data flow much clearer. E.g.

- `codegen_units` is mutable all the way through.
- `codegen_units`'s length is changed by `merge_codegen_units`, but only
  the individual elements are changed by `place_inlined_mono_items` and
  `internalize_symbols`.
- `roots`, `internalization_candidates`, and `mono_item_placements` are
  all immutable after creation, and all used by just one of the four
  methods.
2023-05-24 12:33:35 +10:00
Nicholas Nethercote
b39b7098ea Remove the merging module.
Three of the four methods in `DefaultPartitioning` are defined in
`default.rs`. But `merge_codegen_units` is defined in a separate module,
`merging`, even though it's less than 100 lines of code and roughly the
same size as the other three methods. (Also, the `merging` module
currently sits alongside `default`, when it should be a submodule of
`default`, adding to the confusion.)

In #74275 this explanation was given:

> I pulled this out into a separate module since it seemed like we might
> want a few different merge algorithms to choose from.

But in the three years since there have been no additional merging
algorithms, and there is no mechanism for choosing between different
merging algorithms. (There is a mechanism,
`-Zcgu-partitioning-strategy`, for choosing between different
partitioning strategies, but the merging algorithm is just one piece of
a partitioning strategy.)

This commit merges `merging` into `default`, making the code easier to
navigate and read.
2023-05-24 12:25:58 +10:00
Nicholas Nethercote
e26c0c92bd Inline and remove numbered_codegen_unit_name.
It is small and has a single call site, and this change will facilitate
the next commit.
2023-05-24 10:05:15 +10:00
Nicholas Nethercote
1bb957efc6 Improve CGU partitioning debug output.
- Pass a slice instead of an iterator to `debug_dump`.
- For each CGU set, print: the number of CGUs, the max and min size, and
  the ratio of the max and min size (which indicates how evenly sized
  they are).
- Print a `FINAL` entry, showing the absolute final results.
2023-05-19 08:48:28 +10:00
Nicholas Nethercote
1551495d32 Fix an ICE in CGU dumping code. 2023-05-19 08:48:28 +10:00
John Kåre Alsaker
54b582a0e8 Finish move of query.rs 2023-05-17 01:57:21 +02:00
John Kåre Alsaker
fff20a703d Move expansion of query macros in rustc_middle to rustc_middle::query 2023-05-15 08:49:13 +02:00
Kyle Matsuda
82f57c16b7 use EarlyBinder in tcx.(try_)subst_mir_and_normalize_erasing_regions 2023-05-06 22:32:39 -06:00
Kyle Matsuda
e5d10cdbc3 make (try_)subst_and_normalize_erasing_regions take EarlyBinder 2023-05-06 22:32:39 -06:00
bors
6f8c0557e0 Auto merge of #110806 - WaffleLapkin:unmkI, r=lcnr
Replace `tcx.mk_trait_ref` with `TraitRef::new`

First step in implementing https://github.com/rust-lang/compiler-team/issues/616
r? `@lcnr`
2023-05-04 05:54:09 +00:00
Ben Kimock
f08f903fa9 Box AssertKind 2023-05-01 23:12:41 -04:00
Boxy
842419712a rename needs_subst to has_param 2023-04-27 08:35:19 +01:00
Maybe Waffle
4f2532fb53 Switch ty::TraitRef::from_lang_item from using TyCtxtAt to TyCtxt and a Span 2023-04-26 10:55:11 +00:00
Maybe Waffle
46b01abbcd Replace tcx.mk_trait_ref with ty::TraitRef::new 2023-04-25 16:12:44 +00:00
bors
3462f79e94 Auto merge of #108118 - oli-obk:lazy_typeck, r=cjgillot
Run various queries from other queries instead of explicitly in phases

These are just legacy leftovers from when rustc didn't have a query system. While there are more cleanups of this sort that can be done here, I want to land them in smaller steps.

This phased order of query invocations was already a lie, as any query that looks at types (e.g. the wf checks run before) can invoke e.g. const eval which invokes borrowck, which invokes typeck, ...
2023-04-23 13:34:31 +00:00
bors
ccb6290e43 Auto merge of #110567 - JohnBobbo96:monomorphize-dyn-dispatch, r=b-naber
Remove some uses of dynamic dispatch during monomorphization/partitioning.

This removes a few uses of dynamic dispatch and instead uses generics, as well as an enum to allow for other partitioning methods to be added later.
2023-04-22 07:43:43 +00:00
Oli Scherer
1ce80e210d Allow LocalDefId as the argument to def_path_str 2023-04-21 22:27:20 +00:00
Camille GILLOT
b275d2c30b Remove WithOptconstParam. 2023-04-20 17:48:32 +00:00
John Bobbo
8a7a020a2a
Remove a few uses of dynamic dispatch during
monomorphization/partitioning with the use of
an enum.
2023-04-19 18:21:40 -07:00
bors
d7f9e81650 Auto merge of #110407 - Nilstrieb:fluent-macro, r=davidtwco
Add `rustc_fluent_macro` to decouple fluent from `rustc_macros`

Fluent, with all the icu4x it brings in, takes quite some time to compile. `fluent_messages!` is only needed in further downstream rustc crates, but is blocking more upstream crates like `rustc_index`. By splitting it out, we allow `rustc_macros` to be compiled earlier, which speeds up `x check compiler` by about 5 seconds (and even more after the needless dependency on `serde_json` is removed from `rustc_data_structures`).
2023-04-19 08:26:47 +00:00
Nilstrieb
b5d3d970fa Add rustc_fluent_macro to decouple fluent from rustc_macros
Fluent, with all the icu4x it brings in, takes quite some time to
compile. `fluent_messages!` is only needed in further downstream rustc
crates, but is blocking more upstream crates like `rustc_index`. By
splitting it out, we allow `rustc_macros` to be compiled earlier, which
speeds up `x check compiler` by about 5 seconds (and even more after the
needless dependency on `serde_json` is removed from
`rustc_data_structures`).
2023-04-18 18:56:22 +00:00
Josh Soref
e09d0d2a29 Spelling - compiler
* account
* achieved
* advising
* always
* ambiguous
* analysis
* annotations
* appropriate
* build
* candidates
* cascading
* category
* character
* clarification
* compound
* conceptually
* constituent
* consts
* convenience
* corresponds
* debruijn
* debug
* debugable
* debuggable
* deterministic
* discriminant
* display
* documentation
* doesn't
* ellipsis
* erroneous
* evaluability
* evaluate
* evaluation
* explicitly
* fallible
* fulfill
* getting
* has
* highlighting
* illustrative
* imported
* incompatible
* infringing
* initialized
* into
* intrinsic
* introduced
* javascript
* liveness
* metadata
* monomorphization
* nonexistent
* nontrivial
* obligation
* obligations
* offset
* opaque
* opportunities
* opt-in
* outlive
* overlapping
* paragraph
* parentheses
* poisson
* precisely
* predecessors
* predicates
* preexisting
* propagated
* really
* reentrant
* referent
* responsibility
* rustonomicon
* shortcircuit
* simplifiable
* simplifications
* specify
* stabilized
* structurally
* suggestibility
* translatable
* transmuting
* two
* unclosed
* uninhabited
* visibility
* volatile
* workaround

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-17 16:09:18 -04:00
Matthias Krüger
d666f6bf22 fix clippy::{filter_map_identiy, map_identity, manual_flatten} 2023-04-15 18:56:25 +02:00
DaniPopes
677357d32b
Fix typos in compiler 2023-04-10 22:02:52 +02:00
Gary Guo
e3f2edc75b Rename Abort terminator to Terminate
Unify terminology used in unwind action and terminator, and reflect
the fact that a nounwind panic is triggered instead of an immediate
abort is triggered for this terminator.
2023-04-06 09:34:16 +01:00
Gary Guo
0a5dac3062 Add UnwindAction::Terminate 2023-04-06 09:34:16 +01:00
Nilstrieb
59f394bf86
Rollup merge of #109846 - matthiaskrgr:clippy2023_04_III, r=Nilstrieb
more clippy::complexity fixes (iter_kv_map, map_flatten, nonminimal_bool)
2023-04-02 10:08:35 +02:00
Matthias Krüger
ac229c2819 fix clippy::iter_kv_map 2023-04-01 23:44:16 +02:00
Matthias Krüger
8ef3bf29fe a couple clippy::complexity fixes
map_identity
filter_next
option_as_ref_deref
unnecessary_find_map
redundant_slicing
unnecessary_unwrap
bool_comparison
derivable_impls
manual_flatten
needless_borrowed_reference
2023-04-01 23:16:33 +02:00
bors
eb3e9c1f45 Auto merge of #109762 - scottmcm:variantdef-indexvec, r=WaffleLapkin
Update `ty::VariantDef` to use `IndexVec<FieldIdx, FieldDef>`

And while doing the updates for that, also uses `FieldIdx` in `ProjectionKind::Field` and `TypeckResults::field_indices`.

There's more places that could use it (like `rustc_const_eval` and `LayoutS`), but I tried to keep this PR from exploding to *even more* places.

Part 2/? of https://github.com/rust-lang/compiler-team/issues/606
2023-03-31 03:36:18 +00:00
Michael Goulet
249198c1f8
Rollup merge of #109758 - nnethercote:parallel-cleanups, r=cjgillot
Parallel compiler cleanups

A few small improvements I found while looking closely at this code.

r? `@cjgillot`

cc `@Zoxc,` `@SparrowLii`
2023-03-30 12:42:21 -07:00
Scott McMurray
4abb455529 Update ty::VariantDef to use IndexVec<FieldIdx, FieldDef>
And while doing the updates for that, also uses `FieldIdx` in `ProjectionKind::Field` and `TypeckResults::field_indices`.

There's more places that could use it (like `rustc_const_eval` and `LayoutS`), but I tried to keep this PR from exploding to *even more* places.

Part 2/? of https://github.com/rust-lang/compiler-team/issues/606
2023-03-30 09:23:40 -07:00
Nicholas Nethercote
eeb5b782a6 Improve the rustc_data_structures::sync module doc comment.
Also, `MTRef<'a, T>` is a typedef for a reference to a `T`, but in
practice it's only used (and useful) in combination with `MTLock`, i.e.
`MTRef<'a, MTLock<T>>`. So this commit changes it to be a typedef for a
reference to an `MTLock<T>`, and renames it as `MTLockRef`. I think this
clarifies things, because I found `MTRef` quite puzzling at first.
2023-03-30 21:14:37 +11:00