Repository: vercel/next.js
Pull request: [turbopack] Delete `FunctionId`

## Delete the `FunctionId` type

This is only used to map to/from global names,  we can just do that directly and remove some indirection.

This is a tiny cleanup following https://github.com/vercel/next.js/pull/80695 which made functionids irrelevant to most  of the runtime.

Closes PACK-4886

Changed files:
filename: turbopack/crates/turbo-tasks/src/backend.rs
patch: @@ -213,9 +213,7 @@ mod ser {
                 unreachable!();
             };
             let mut state = serializer.serialize_seq(Some(2))?;
-            // It would be a little tricky but we _could_ store the function id on the native_fn so
-            // that instead of a hashmap lookup this would be a memory access on the NativeFn
-            state.serialize_element(&registry::get_function_id(native_fn))?;
+            state.serialize_element(&registry::get_function_global_name(native_fn))?;
             let arg = *arg;
             let arg = native_fn.arg_meta.as_serialize(arg);
             state.serialize_element(arg)?;
@@ -237,10 +235,10 @@ mod ser {
                 where
                     A: serde::de::SeqAccess<'de>,
                 {
-                    let fn_id = seq
+                    let fn_name = seq
                         .next_element()?
                         .ok_or_else(|| serde::de::Error::invalid_length(0, &self))?;
-                    let native_fn = registry::get_function(fn_id);
+                    let native_fn = registry::get_function_by_global_name(fn_name);
                     let seed = native_fn.arg_meta.deserialization_seed();
                     let arg = seq
                         .next_element_seed(seed)?

filename: turbopack/crates/turbo-tasks/src/id.rs
patch: @@ -113,7 +113,6 @@ macro_rules! define_id {
 }
 
 define_id!(TaskId: u32, derive(Serialize, Deserialize), serde(transparent));
-define_id!(FunctionId: u32);
 define_id!(ValueTypeId: u32);
 define_id!(TraitTypeId: u32);
 define_id!(BackendJobId: u32);
@@ -202,12 +201,6 @@ macro_rules! make_serializable {
     };
 }
 
-make_serializable!(
-    FunctionId,
-    registry::get_function_global_name,
-    registry::get_function_id_by_global_name,
-    FunctionIdVisitor
-);
 make_serializable!(
     ValueTypeId,
     registry::get_value_type_global_name,

filename: turbopack/crates/turbo-tasks/src/lib.rs
patch: @@ -94,8 +94,7 @@ pub use completion::{Completion, Completions};
 pub use display::ValueToString;
 pub use effect::{ApplyEffectsContext, Effects, apply_effects, effect, get_effects};
 pub use id::{
-    ExecutionId, FunctionId, LocalTaskId, SessionId, TRANSIENT_TASK_BIT, TaskId, TraitTypeId,
-    ValueTypeId,
+    ExecutionId, LocalTaskId, SessionId, TRANSIENT_TASK_BIT, TaskId, TraitTypeId, ValueTypeId,
 };
 pub use invalidation::{
     DynamicEqHash, InvalidationReason, InvalidationReasonKind, InvalidationReasonSet, Invalidator,

filename: turbopack/crates/turbo-tasks/src/registry.rs
patch: @@ -1,25 +1,21 @@
-use std::{fmt::Debug, hash::Hash, num::NonZeroU64, ops::Deref};
+use std::{fmt::Debug, hash::Hash, num::NonZeroU64, ops::Deref, sync::RwLock};
 
 use dashmap::mapref::entry::Entry;
 use once_cell::sync::Lazy;
+use rustc_hash::FxHashMap;
 
 use crate::{
     FxDashMap, TraitType, ValueType,
-    id::{FunctionId, TraitTypeId, ValueTypeId},
+    id::{TraitTypeId, ValueTypeId},
     id_factory::IdFactory,
     native_function::NativeFunction,
     no_move_vec::NoMoveVec,
 };
 
-static FUNCTION_ID_FACTORY: IdFactory<FunctionId> = IdFactory::new_const(
-    FunctionId::MIN.to_non_zero_u64(),
-    FunctionId::MAX.to_non_zero_u64(),
-);
-static FUNCTIONS_BY_NAME: Lazy<FxDashMap<&'static str, FunctionId>> = Lazy::new(FxDashMap::default);
-static FUNCTIONS_BY_VALUE: Lazy<FxDashMap<&'static NativeFunction, FunctionId>> =
-    Lazy::new(FxDashMap::default);
-static FUNCTIONS: Lazy<NoMoveVec<(&'static NativeFunction, &'static str)>> =
-    Lazy::new(NoMoveVec::new);
+static NAME_TO_FUNCTION: Lazy<RwLock<FxHashMap<&'static str, &'static NativeFunction>>> =
+    Lazy::new(RwLock::default);
+static FUNCTION_TO_NAME: Lazy<RwLock<FxHashMap<&'static NativeFunction, &'static str>>> =
+    Lazy::new(RwLock::default);
 
 static VALUE_TYPE_ID_FACTORY: IdFactory<ValueTypeId> = IdFactory::new_const(
     ValueTypeId::MIN.to_non_zero_u64(),
@@ -80,31 +76,23 @@ where
     }
 }
 
+/// Registers a function so it is available for persistence
 pub fn register_function(global_name: &'static str, func: &'static NativeFunction) {
-    register_thing(
-        global_name,
-        func,
-        &FUNCTION_ID_FACTORY,
-        &FUNCTIONS,
-        &FUNCTIONS_BY_NAME,
-        &FUNCTIONS_BY_VALUE,
+    let prev = FUNCTION_TO_NAME.write().unwrap().insert(func, global_name);
+    debug_assert!(prev.is_none(), "function {global_name} registered twice?");
+    let prev = NAME_TO_FUNCTION.write().unwrap().insert(global_name, func);
+    debug_assert!(
+        prev.is_none(),
+        "registration mappings for {global_name} are inconsistent!"
     );
 }
 
-pub fn get_function_id(func: &'static NativeFunction) -> FunctionId {
-    get_thing_id(func, &FUNCTIONS_BY_VALUE)
-}
-
-pub fn get_function_id_by_global_name(global_name: &str) -> Option<FunctionId> {
-    FUNCTIONS_BY_NAME.get(global_name).map(|x| *x)
-}
-
-pub fn get_function(id: FunctionId) -> &'static NativeFunction {
-    FUNCTIONS.get(*id as usize).unwrap().0
+pub fn get_function_by_global_name(global_name: &str) -> &'static NativeFunction {
+    NAME_TO_FUNCTION.read().unwrap().get(global_name).unwrap()
 }
 
-pub fn get_function_global_name(id: FunctionId) -> &'static str {
-    FUNCTIONS.get(*id as usize).unwrap().1
+pub fn get_function_global_name(func: &'static NativeFunction) -> &'static str {
+    FUNCTION_TO_NAME.read().unwrap().get(&func).unwrap()
 }
 
 pub fn register_value_type(

filename: turbopack/crates/turbo-tasks/src/task_statistics.rs
patch: @@ -73,7 +73,7 @@ impl Serialize for TaskStatistics {
     {
         let mut map = serializer.serialize_map(Some(self.inner.len()))?;
         for entry in &self.inner {
-            let key = registry::get_function_global_name(registry::get_function_id(entry.key()));
+            let key = registry::get_function_global_name(entry.key());
             map.serialize_entry(key, entry.value())?;
         }
         map.end()