Skip to content

Commit

Permalink
refactor: split make queue
Browse files Browse the repository at this point in the history
  • Loading branch information
jerrykingxyz committed Apr 18, 2024
1 parent 4d8472c commit ca8aeed
Show file tree
Hide file tree
Showing 9 changed files with 962 additions and 1,113 deletions.
653 changes: 41 additions & 612 deletions crates/rspack_core/src/compiler/make/mod.rs

Large diffs are not rendered by default.

500 changes: 0 additions & 500 deletions crates/rspack_core/src/compiler/make/queue.rs

This file was deleted.

105 changes: 105 additions & 0 deletions crates/rspack_core/src/compiler/make/tasks/add.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
use rspack_error::Result;

use super::{build::BuildTask, MakeTaskContext};
use crate::{
module_graph::{ModuleGraph, ModuleGraphModule},
utils::task_loop::{Task, TaskResult, TaskType},
DependencyId, Module, ModuleIdentifier, ModuleProfile,
};

#[derive(Debug)]
pub struct AddTask {
pub original_module_identifier: Option<ModuleIdentifier>,
pub module: Box<dyn Module>,
pub module_graph_module: Box<ModuleGraphModule>,
pub dependencies: Vec<DependencyId>,
pub is_entry: bool,
pub current_profile: Option<Box<ModuleProfile>>,
}

impl Task<MakeTaskContext> for AddTask {
fn get_task_type(&self) -> TaskType {
TaskType::Sync
}
fn sync_run(self: Box<Self>, context: &mut MakeTaskContext) -> TaskResult<MakeTaskContext> {
if let Some(current_profile) = &self.current_profile {
current_profile.mark_integration_start();
}

let module_identifier = self.module.identifier();
let module_graph = &mut MakeTaskContext::get_module_graph(&mut context.module_graph_partial);

if self.module.as_self_module().is_some() {
let issuer = self
.module_graph_module
.get_issuer()
.identifier()
.expect("self module should have issuer");

set_resolved_module(
module_graph,
self.original_module_identifier,
self.dependencies,
*issuer,
)?;

// reused module
return Ok(vec![]);
}

if module_graph
.module_graph_module_by_identifier(&module_identifier)
.is_some()
{
set_resolved_module(
module_graph,
self.original_module_identifier,
self.dependencies,
module_identifier,
)?;

// reused module
return Ok(vec![]);
}

module_graph.add_module_graph_module(*self.module_graph_module);

set_resolved_module(
module_graph,
self.original_module_identifier,
self.dependencies,
module_identifier,
)?;

if self.is_entry {
context.entry_module_identifiers.insert(module_identifier);
}

if let Some(current_profile) = &self.current_profile {
current_profile.mark_integration_end();
}

tracing::trace!("Module added: {}", self.module.identifier());

Ok(vec![Box::new(BuildTask {
module: self.module,
current_profile: self.current_profile,
resolver_factory: context.resolver_factory.clone(),
compiler_options: context.compiler_options.clone(),
plugin_driver: context.plugin_driver.clone(),
cache: context.cache.clone(),
})])
}
}

fn set_resolved_module(
module_graph: &mut ModuleGraph,
original_module_identifier: Option<ModuleIdentifier>,
dependencies: Vec<DependencyId>,
module_identifier: ModuleIdentifier,
) -> Result<()> {
for dependency in dependencies {
module_graph.set_resolved_module(original_module_identifier, dependency, module_identifier)?;
}
Ok(())
}
230 changes: 230 additions & 0 deletions crates/rspack_core/src/compiler/make/tasks/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
use std::{collections::VecDeque, sync::Arc};

use rspack_error::{Diagnostic, IntoTWithDiagnosticArray};

use super::{process_dependencies::ProcessDependenciesTask, MakeTaskContext};
use crate::{
cache::Cache,
utils::task_loop::{Task, TaskResult, TaskType},
AsyncDependenciesBlock, BoxDependency, BuildContext, BuildResult, CompilerContext,
CompilerOptions, DependencyParents, Module, ModuleProfile, ResolverFactory, SharedPluginDriver,
};

#[derive(Debug)]
pub struct BuildTask {
pub module: Box<dyn Module>,
pub current_profile: Option<Box<ModuleProfile>>,
pub resolver_factory: Arc<ResolverFactory>,
pub compiler_options: Arc<CompilerOptions>,
pub plugin_driver: SharedPluginDriver,
pub cache: Arc<Cache>,
}

#[async_trait::async_trait]
impl Task<MakeTaskContext> for BuildTask {
fn get_task_type(&self) -> TaskType {
TaskType::Async
}
async fn async_run(self: Box<Self>) -> TaskResult<MakeTaskContext> {
let Self {
compiler_options,
resolver_factory,
plugin_driver,
cache,
current_profile,
mut module,
} = *self;
if let Some(current_profile) = &current_profile {
current_profile.mark_building_start();
}

let (build_result, is_cache_valid) = cache
.build_module_occasion
.use_cache(&mut module, |module| async {
plugin_driver
.compilation_hooks
.build_module
.call(module)
.await?;

let result = module
.build(
BuildContext {
compiler_context: CompilerContext {
options: compiler_options.clone(),
resolver_factory: resolver_factory.clone(),
module: module.identifier(),
module_context: module.as_normal_module().and_then(|m| m.get_context()),
module_source_map_kind: module.get_source_map_kind().clone(),
plugin_driver: plugin_driver.clone(),
cache: cache.clone(),
},
plugin_driver: plugin_driver.clone(),
compiler_options: &compiler_options,
},
None,
)
.await;

plugin_driver
.compilation_hooks
.succeed_module
.call(module)
.await?;

result.map(|t| {
let diagnostics = module
.clone_diagnostics()
.into_iter()
.map(|d| d.with_module_identifier(Some(module.identifier())))
.collect();
(t.with_diagnostic(diagnostics), module)
})
})
.await?;

if is_cache_valid {
plugin_driver
.compilation_hooks
.still_valid_module
.call(&mut module)
.await?;
}

if let Some(current_profile) = &current_profile {
current_profile.mark_building_end();
}

build_result.map::<Vec<Box<dyn Task<MakeTaskContext>>>, _>(|build_result| {
let (build_result, diagnostics) = build_result.split_into_parts();
vec![Box::new(BuildResultTask {
module,
build_result: Box::new(build_result),
diagnostics,
current_profile,
from_cache: is_cache_valid,
})]
})
}
}

#[derive(Debug)]
struct BuildResultTask {
pub module: Box<dyn Module>,
pub build_result: Box<BuildResult>,
pub diagnostics: Vec<Diagnostic>,
pub current_profile: Option<Box<ModuleProfile>>,
pub from_cache: bool,
}

impl Task<MakeTaskContext> for BuildResultTask {
fn get_task_type(&self) -> TaskType {
TaskType::Sync
}
fn sync_run(self: Box<Self>, context: &mut MakeTaskContext) -> TaskResult<MakeTaskContext> {
let BuildResultTask {
mut module,
build_result,
diagnostics,
current_profile,
from_cache,
} = *self;

if let Some(counter) = &mut context.build_cache_counter {
if from_cache {
counter.hit();
} else {
counter.miss();
}
}

let module_graph = &mut MakeTaskContext::get_module_graph(&mut context.module_graph_partial);
if context.compiler_options.builtins.tree_shaking.enable() {
context
.optimize_analyze_result_map
.insert(module.identifier(), build_result.analyze_result);
}

if !diagnostics.is_empty() {
context.make_failed_module.insert(module.identifier());
}

tracing::trace!("Module built: {}", module.identifier());
context.diagnostics.extend(diagnostics);
module_graph
.get_optimization_bailout_mut(&module.identifier())
.extend(build_result.optimization_bailouts);
context
.file_dependencies
.extend(build_result.build_info.file_dependencies.clone());
context
.context_dependencies
.extend(build_result.build_info.context_dependencies.clone());
context
.missing_dependencies
.extend(build_result.build_info.missing_dependencies.clone());
context
.build_dependencies
.extend(build_result.build_info.build_dependencies.clone());

let mut queue = VecDeque::new();
let mut all_dependencies = vec![];
let mut handle_block = |dependencies: Vec<BoxDependency>,
blocks: Vec<AsyncDependenciesBlock>,
current_block: Option<AsyncDependenciesBlock>|
-> Vec<AsyncDependenciesBlock> {
for dependency in dependencies {
let dependency_id = *dependency.id();
if current_block.is_none() {
module.add_dependency_id(dependency_id);
}
all_dependencies.push(dependency_id);
module_graph.set_parents(
dependency_id,
DependencyParents {
block: current_block.as_ref().map(|block| block.identifier()),
module: module.identifier(),
},
);
module_graph.add_dependency(dependency);
}
if let Some(current_block) = current_block {
module.add_block_id(current_block.identifier());
module_graph.add_block(current_block);
}
blocks
};
let blocks = handle_block(build_result.dependencies, build_result.blocks, None);
queue.extend(blocks);

while let Some(mut block) = queue.pop_front() {
let dependencies = block.take_dependencies();
let blocks = handle_block(dependencies, block.take_blocks(), Some(block));
queue.extend(blocks);
}

{
let mgm = module_graph
.module_graph_module_by_identifier_mut(&module.identifier())
.expect("Failed to get mgm");
mgm.__deprecated_all_dependencies = all_dependencies.clone();
if let Some(current_profile) = current_profile {
mgm.set_profile(current_profile);
}
}

let module_identifier = module.identifier();

module.set_build_info(build_result.build_info);
module.set_build_meta(build_result.build_meta);

let resolve_options = module.get_resolve_options();
module_graph.add_module(module);

Ok(vec![Box::new(ProcessDependenciesTask {
dependencies: all_dependencies,
original_module_identifier: module_identifier,
resolve_options,
})])
}
}
43 changes: 43 additions & 0 deletions crates/rspack_core/src/compiler/make/tasks/clean.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use super::MakeTaskContext;
use crate::{
utils::task_loop::{Task, TaskResult, TaskType},
ModuleIdentifier,
};

pub struct CleanTask {
pub module_identifier: ModuleIdentifier,
}

impl Task<MakeTaskContext> for CleanTask {
fn get_task_type(&self) -> TaskType {
TaskType::Sync
}
fn sync_run(self: Box<Self>, context: &mut MakeTaskContext) -> TaskResult<MakeTaskContext> {
let module_identifier = self.module_identifier;
let module_graph = &mut MakeTaskContext::get_module_graph(&mut context.module_graph_partial);
let Some(mgm) = module_graph.module_graph_module_by_identifier(&module_identifier) else {
tracing::trace!("Module is cleaned: {}", module_identifier);
return Ok(vec![]);
};

if !mgm.incoming_connections().is_empty() {
tracing::trace!("Module is used: {}", module_identifier);
return Ok(vec![]);
}

let dependent_module_identifiers: Vec<ModuleIdentifier> = module_graph
.get_module_all_depended_modules(&module_identifier)
.expect("should have module")
.into_iter()
.copied()
.collect();
module_graph.revoke_module(&module_identifier);

let mut res: Vec<Box<dyn Task<MakeTaskContext>>> =
Vec::with_capacity(dependent_module_identifiers.len());
for module_identifier in dependent_module_identifiers {
res.push(Box::new(CleanTask { module_identifier }))
}
Ok(res)
}
}
Loading

0 comments on commit ca8aeed

Please sign in to comment.