Skip to content

Commit 89023e3

Browse files
authored
Turbopack: handle non chunkable modules in module batches (#77282)
### What? Fix the handling of non-chunkable modules in module batches
1 parent 7c6f604 commit 89023e3

File tree

1 file changed

+54
-46
lines changed

1 file changed

+54
-46
lines changed

turbopack/crates/turbopack-core/src/module_graph/module_batches.rs

+54-46
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ type PreBatchIndex = usize;
186186

187187
#[derive(Hash, PartialEq, Eq, Clone, Debug)]
188188
enum PreBatchItem {
189-
ParallelModule(ResolvedVc<Box<dyn ChunkableModule>>),
189+
ParallelModule(ResolvedVc<Box<dyn Module>>),
190190
ParallelReference(PreBatchIndex),
191191
NonParallelEdge(ChunkingType, ResolvedVc<Box<dyn Module>>),
192192
}
@@ -212,7 +212,7 @@ struct TraversalState<'l> {
212212

213213
struct PreBatches {
214214
batches: Vec<PreBatch>,
215-
entries: FxHashMap<ResolvedVc<Box<dyn ChunkableModule>>, PreBatchIndex>,
215+
entries: FxHashMap<ResolvedVc<Box<dyn Module>>, PreBatchIndex>,
216216
single_module_entries: FxIndexSet<ResolvedVc<Box<dyn Module>>>,
217217
}
218218

@@ -227,9 +227,9 @@ impl PreBatches {
227227

228228
fn ensure_pre_batch_for_module(
229229
&mut self,
230-
module: ResolvedVc<Box<dyn ChunkableModule>>,
230+
module: ResolvedVc<Box<dyn Module>>,
231231
chunk_groups: &RoaringBitmapWrapper,
232-
queue: &mut VecDeque<(ResolvedVc<Box<dyn ChunkableModule>>, PreBatchIndex)>,
232+
queue: &mut VecDeque<(ResolvedVc<Box<dyn Module>>, PreBatchIndex)>,
233233
) -> PreBatchIndex {
234234
match self.entries.entry(module) {
235235
Entry::Vacant(e) => {
@@ -246,10 +246,10 @@ impl PreBatches {
246246

247247
async fn get_pre_batch_items(
248248
&mut self,
249-
entry: ResolvedVc<Box<dyn ChunkableModule>>,
249+
entry: ResolvedVc<Box<dyn Module>>,
250250
chunk_group_info: &ChunkGroupInfo,
251251
module_graph: &ModuleGraph,
252-
queue: &mut VecDeque<(ResolvedVc<Box<dyn ChunkableModule>>, PreBatchIndex)>,
252+
queue: &mut VecDeque<(ResolvedVc<Box<dyn Module>>, PreBatchIndex)>,
253253
) -> Result<Vec<PreBatchItem>> {
254254
let entry_chunk_groups = chunk_group_info
255255
.module_chunk_groups
@@ -266,43 +266,34 @@ impl PreBatches {
266266
&mut state,
267267
|parent_info, node, state| {
268268
let ty = parent_info.map_or(&ChunkingType::Parallel, |(_, ty)| ty);
269+
let module = node.module;
269270
if !ty.is_parallel() {
270271
state.items.push(PreBatchItem::NonParallelEdge(
271272
ty.without_inherit_async(),
272-
node.module,
273+
module,
273274
));
274275
return Ok(GraphTraversalAction::Exclude);
275276
}
276-
let Some(chunkable_module) = ResolvedVc::try_downcast(node.module) else {
277-
return Ok(GraphTraversalAction::Skip);
278-
};
279-
let chunk_groups = chunk_group_info
280-
.module_chunk_groups
281-
.get(&node.module)
282-
.context("all modules need to have chunk group info")?;
283-
if chunk_groups != entry_chunk_groups {
284-
let idx = state.this.ensure_pre_batch_for_module(
285-
chunkable_module,
286-
chunk_groups,
287-
queue,
288-
);
289-
state.items.push(PreBatchItem::ParallelReference(idx));
290-
return Ok(GraphTraversalAction::Exclude);
291-
}
292-
if visited.insert(chunkable_module) {
277+
if visited.insert(module) {
278+
let chunk_groups = chunk_group_info
279+
.module_chunk_groups
280+
.get(&module)
281+
.context("all modules need to have chunk group info")?;
282+
if chunk_groups != entry_chunk_groups {
283+
let idx =
284+
state
285+
.this
286+
.ensure_pre_batch_for_module(module, chunk_groups, queue);
287+
state.items.push(PreBatchItem::ParallelReference(idx));
288+
return Ok(GraphTraversalAction::Exclude);
289+
}
293290
Ok(GraphTraversalAction::Continue)
294291
} else {
295292
Ok(GraphTraversalAction::Exclude)
296293
}
297294
},
298-
|parent_info, node, state| {
299-
let ty = parent_info.map_or(&ChunkingType::Parallel, |(_, ty)| ty);
300-
let item = if let Some(chunkable_module) = ResolvedVc::try_downcast(node.module)
301-
{
302-
PreBatchItem::ParallelModule(chunkable_module)
303-
} else {
304-
PreBatchItem::NonParallelEdge(ty.without_inherit_async(), node.module)
305-
};
295+
|_, node, state| {
296+
let item = PreBatchItem::ParallelModule(node.module);
306297
state.items.push(item);
307298
},
308299
)
@@ -330,8 +321,7 @@ pub async fn compute_module_batches(
330321
let module_graph = module_graph.await?;
331322

332323
let mut pre_batches = PreBatches::new();
333-
let mut queue: VecDeque<(ResolvedVc<Box<dyn ChunkableModule>>, PreBatchIndex)> =
334-
VecDeque::new();
324+
let mut queue: VecDeque<(ResolvedVc<Box<dyn Module>>, PreBatchIndex)> = VecDeque::new();
335325

336326
// Start with the entries
337327
for chunk_group in &chunk_group_info.chunk_groups {
@@ -393,7 +383,7 @@ pub async fn compute_module_batches(
393383
pre_batches.single_module_entries.insert(*module);
394384
}
395385
}
396-
_ => {}
386+
PreBatchItem::ParallelReference(_) => {}
397387
}
398388
}
399389
}
@@ -513,28 +503,43 @@ pub async fn compute_module_batches(
513503

514504
let mut edges_count = 0;
515505

516-
// Since batches can only have references followed by a list of parallel modules, we need to
517-
// split batches that have modules before references.
506+
// Since batches can only have references followed by a list of parallel chunkable modules,
507+
// we need to split batches that have modules before references.
518508
for i in 0..pre_batches.batches.len() {
519509
let items = take(&mut pre_batches.batches[i].items);
520510
let mut new_items =
521511
FxIndexSet::with_capacity_and_hasher(items.len(), Default::default());
522512
enum Mode {
523-
ParallelModule,
513+
ParallelChunkableModule,
524514
Other,
525515
}
526516
let mut mode = Mode::Other;
527517
for item in items {
528-
match (&mode, &item) {
529-
(_, PreBatchItem::ParallelModule(_)) => {
530-
mode = Mode::ParallelModule;
518+
let chunkable_module = if let PreBatchItem::ParallelModule(module) = &item {
519+
ResolvedVc::try_downcast::<Box<dyn ChunkableModule>>(*module)
520+
} else {
521+
None
522+
};
523+
let item = if let PreBatchItem::ParallelModule(module) = item {
524+
if chunkable_module.is_some() {
525+
PreBatchItem::ParallelModule(module)
526+
} else {
527+
pre_batches.single_module_entries.insert(module);
528+
PreBatchItem::NonParallelEdge(ChunkingType::Parallel, module)
529+
}
530+
} else {
531+
item
532+
};
533+
match (&mode, chunkable_module) {
534+
(_, Some(_)) => {
535+
mode = Mode::ParallelChunkableModule;
531536
new_items.insert(item);
532537
}
533538
(Mode::Other, _) => {
534539
edges_count += 1;
535540
new_items.insert(item);
536541
}
537-
(Mode::ParallelModule, _) => {
542+
(Mode::ParallelChunkableModule, _) => {
538543
// Split the batch
539544
let idx = pre_batches.batches.len();
540545
let mut new_batch =
@@ -543,7 +548,7 @@ pub async fn compute_module_batches(
543548
pre_batches.batches.push(new_batch);
544549
edges_count += 1;
545550
new_items.insert(PreBatchItem::ParallelReference(idx));
546-
if matches!(item, PreBatchItem::ParallelModule(_)) {
551+
if chunkable_module.is_some() {
547552
new_items.insert(item);
548553
} else {
549554
edges_count += 1;
@@ -572,9 +577,12 @@ pub async fn compute_module_batches(
572577
.iter_mut()
573578
.enumerate()
574579
.map(async |(i, pre_batch)| {
575-
let mut modules = pre_batch.items.iter().filter_map(|item| match item {
576-
PreBatchItem::ParallelModule(module) => Some(*module),
577-
_ => None,
580+
let mut modules = pre_batch.items.iter().filter_map(|item| {
581+
if let PreBatchItem::ParallelModule(module) = item {
582+
ResolvedVc::try_downcast(*module)
583+
} else {
584+
None
585+
}
578586
});
579587
let Some(first) = modules.next() else {
580588
return Ok(ModuleOrBatch::None(i));

0 commit comments

Comments
 (0)