mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[rust] Use Rc<RefCell<>> for shared identifiers
Multiple Place instances can share a reference to a given Identifier in our JS implementation. For simplicity of the initial port I’m using Rc (for sharing) and RefCell (for runtime-checked mutability). This is the standard pattern for shared mutable references in Rust when you don’t need multi-threaded support. We don’t need HIR to be accessible by multiple threads so this is fine, if we do multiple threads it will be to parallelize compilation of separate functions. There are other idioms w less runtime overhead, such as Place holding an index into a separate vec of identifiers, but that would make the port much less straightforward.
This commit is contained in:
@@ -52,7 +52,7 @@ fn lower_statement<'a>(
|
||||
env: &'a Environment<'a>,
|
||||
builder: &mut Builder<'a>,
|
||||
stmt: Statement,
|
||||
label: Option<String<'a>>,
|
||||
_label: Option<String<'a>>,
|
||||
) -> Result<(), Diagnostic> {
|
||||
match stmt {
|
||||
Statement::BlockStatement(stmt) => {
|
||||
@@ -97,8 +97,6 @@ fn lower_statement<'a>(
|
||||
);
|
||||
}
|
||||
Statement::ExpressionStatement(stmt) => {
|
||||
// TODO: port the logic for emitting an ExpressionStatement instr if the instr
|
||||
// was a logical or conditional. is that even necessary anymore?
|
||||
lower_expression_to_temporary(env, builder, stmt.expression);
|
||||
}
|
||||
Statement::EmptyStatement(_) => {
|
||||
@@ -175,13 +173,13 @@ fn lower_value_to_temporary<'a>(
|
||||
return place;
|
||||
}
|
||||
let place = build_temporary_place(env, builder);
|
||||
builder.push(todo!("clone `place`"), value);
|
||||
builder.push(place.clone(), value);
|
||||
return place;
|
||||
}
|
||||
|
||||
/// Constructs a temporary Identifier and Place wrapper, which can be used as an Instruction lvalue
|
||||
/// or other places where a temporary target is required
|
||||
fn build_temporary_place<'a>(env: &'a Environment<'a>, builder: &mut Builder<'a>) -> Place<'a> {
|
||||
fn build_temporary_place<'a>(_env: &'a Environment<'a>, builder: &mut Builder<'a>) -> Place<'a> {
|
||||
Place {
|
||||
identifier: builder.make_temporary(),
|
||||
effect: None,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use bumpalo::collections::Vec;
|
||||
use estree::Identifier;
|
||||
use std::collections::HashSet;
|
||||
use std::{cell::RefCell, collections::HashSet, rc::Rc};
|
||||
|
||||
use hir::{
|
||||
BasicBlock, BlockId, BlockKind, Environment, GotoKind, Instruction, InstructionIdGenerator,
|
||||
InstructionValue, Place, Terminal, TerminalValue, Type, HIR,
|
||||
BasicBlock, BlockId, BlockKind, Environment, GotoKind, IdentifierData, Instruction,
|
||||
InstructionIdGenerator, InstructionValue, Place, Terminal, TerminalValue, Type, HIR,
|
||||
};
|
||||
use indexmap::IndexMap;
|
||||
|
||||
@@ -106,17 +106,19 @@ impl<'a> Builder<'a> {
|
||||
pub(crate) fn make_temporary(&self) -> hir::Identifier<'a> {
|
||||
hir::Identifier {
|
||||
id: self.environment.next_identifier_id(),
|
||||
mutable_range: Default::default(),
|
||||
name: None,
|
||||
scope: None,
|
||||
type_: Type::Var(self.environment.next_type_var_id()),
|
||||
data: Rc::new(RefCell::new(IdentifierData {
|
||||
mutable_range: Default::default(),
|
||||
scope: None,
|
||||
type_: Type::Var(self.environment.next_type_var_id()),
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolves the target for the given break label (if present), or returns the default
|
||||
/// break target given the current context. Returns a diagnostic if the label is
|
||||
/// provided but cannot be resolved.
|
||||
pub(crate) fn resolve_break(&self, label: Option<Identifier>) -> Result<BlockId, Diagnostic> {
|
||||
pub(crate) fn resolve_break(&self, _label: Option<Identifier>) -> Result<BlockId, Diagnostic> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -125,7 +127,7 @@ impl<'a> Builder<'a> {
|
||||
/// provided but cannot be resolved.
|
||||
pub(crate) fn resolve_continue(
|
||||
&self,
|
||||
label: Option<Identifier>,
|
||||
_label: Option<Identifier>,
|
||||
) -> Result<BlockId, Diagnostic> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::cell::Cell;
|
||||
|
||||
use bumpalo::Bump;
|
||||
|
||||
use crate::{BlockId, Features, IdentifierId, Registry};
|
||||
use crate::{BlockId, Features, IdentifierId, Registry, TypeVarId};
|
||||
|
||||
/// Stores all the contextual information about the top-level React function being
|
||||
/// compiled. Environments may not be reused between React functions, but *are*
|
||||
@@ -26,6 +26,8 @@ pub struct Environment<'a> {
|
||||
|
||||
/// The next available identifier id
|
||||
next_identifier_id: Cell<IdentifierId>,
|
||||
|
||||
next_type_var_id: Cell<TypeVarId>,
|
||||
}
|
||||
|
||||
impl<'a> Environment<'a> {
|
||||
@@ -36,6 +38,7 @@ impl<'a> Environment<'a> {
|
||||
registry,
|
||||
next_block_id: Cell::new(BlockId(0)),
|
||||
next_identifier_id: Cell::new(IdentifierId(0)),
|
||||
next_type_var_id: Cell::new(TypeVarId(0)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,4 +60,11 @@ impl<'a> Environment<'a> {
|
||||
self.next_identifier_id.set(id.next());
|
||||
id
|
||||
}
|
||||
|
||||
/// Get the next available type var
|
||||
pub fn next_type_var_id(&self) -> TypeVarId {
|
||||
let id = self.next_type_var_id.get();
|
||||
self.next_type_var_id.set(id.next());
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,15 @@ impl IdentifierId {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
|
||||
pub struct TypeVarId(pub(crate) u32);
|
||||
|
||||
impl TypeVarId {
|
||||
pub(crate) fn next(self) -> Self {
|
||||
Self(self.0 + 1)
|
||||
}
|
||||
}
|
||||
|
||||
/// Used to globally order the instructions and terminals within the scope
|
||||
/// of a given HIR value. Instructions and terminals are ordered using
|
||||
/// reverse postorder iteration of block instructions and their terminals.
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use bumpalo::collections::{String, Vec};
|
||||
|
||||
use crate::{IdentifierId, InstructionId, ScopeId, Type};
|
||||
@@ -20,7 +22,6 @@ pub enum InstructionValue<'a> {
|
||||
DeclareContext(DeclareContext<'a>),
|
||||
DeclareLocal(DeclareLocal<'a>),
|
||||
// Destructure(Destructure<'a>),
|
||||
// Expression(Expression<'a>),
|
||||
// Function(Function<'a>),
|
||||
// JsxFragment(JsxFragment<'a>),
|
||||
// JsxText(JsxText<'a>),
|
||||
@@ -104,6 +105,7 @@ pub struct StoreLocal<'a> {
|
||||
pub value: Place<'a>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Place<'a> {
|
||||
pub identifier: Identifier<'a>,
|
||||
pub effect: Option<Effect>,
|
||||
@@ -161,12 +163,16 @@ impl Effect {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Identifier<'a> {
|
||||
/// Uniquely identifiers this identifier
|
||||
pub id: IdentifierId,
|
||||
|
||||
pub name: Option<String<'a>>,
|
||||
|
||||
pub data: Rc<RefCell<IdentifierData>>,
|
||||
}
|
||||
|
||||
pub struct IdentifierData {
|
||||
pub mutable_range: MutableRange,
|
||||
|
||||
pub scope: Option<ReactiveScope>,
|
||||
@@ -187,6 +193,21 @@ pub struct MutableRange {
|
||||
pub end: InstructionId,
|
||||
}
|
||||
|
||||
impl MutableRange {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
start: InstructionId(0),
|
||||
end: InstructionId(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for MutableRange {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ReactiveScope {
|
||||
pub id: ScopeId,
|
||||
pub range: MutableRange,
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
use std::iter::Successors;
|
||||
|
||||
use crate::{instruction::Place, BlockId, InstructionId};
|
||||
|
||||
/// Terminals represent statements or expressions that affect control flow,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use crate::{FunctionId, ObjectId};
|
||||
use crate::{FunctionId, ObjectId, TypeVarId};
|
||||
|
||||
pub enum Type {
|
||||
Builtin(Box<BuiltinType>),
|
||||
Builtin(BuiltinType),
|
||||
// Phi(Box<PhiType>),
|
||||
// Var(Box<TypeVar>),
|
||||
Var(TypeVarId),
|
||||
// Poly(Box<PolyType>),
|
||||
// Prop(Box<PropType>),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user