diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /third_party/rust/jsparagus-stencil/src/script.rs | |
parent | Initial commit. (diff) | |
download | firefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz firefox-43a97878ce14b72f0981164f87f2e35e14151312.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/jsparagus-stencil/src/script.rs')
-rw-r--r-- | third_party/rust/jsparagus-stencil/src/script.rs | 574 |
1 files changed, 574 insertions, 0 deletions
diff --git a/third_party/rust/jsparagus-stencil/src/script.rs b/third_party/rust/jsparagus-stencil/src/script.rs new file mode 100644 index 0000000000..ab97b88177 --- /dev/null +++ b/third_party/rust/jsparagus-stencil/src/script.rs @@ -0,0 +1,574 @@ +//! The result of emitter + +use crate::frame_slot::FrameSlot; +use crate::function::FunctionFlags; +use crate::gcthings::GCThing; +use crate::scope::ScopeIndex; +use crate::scope_notes::ScopeNote; +use ast::source_atom_set::SourceAtomSetIndex; + +// WARNING +// The following section is generated by update_stencil.py. +// Do mot modify manually. +// +// @@@@ BEGIN TYPES @@@@ +#[derive(Debug, Clone, Copy)] +pub enum ImmutableScriptFlagsEnum { + #[allow(dead_code)] + IsForEval = 1 << 0, + #[allow(dead_code)] + IsModule = 1 << 1, + #[allow(dead_code)] + IsFunction = 1 << 2, + #[allow(dead_code)] + SelfHosted = 1 << 3, + #[allow(dead_code)] + ForceStrict = 1 << 4, + #[allow(dead_code)] + HasNonSyntacticScope = 1 << 5, + #[allow(dead_code)] + NoScriptRval = 1 << 6, + #[allow(dead_code)] + TreatAsRunOnce = 1 << 7, + #[allow(dead_code)] + Strict = 1 << 8, + #[allow(dead_code)] + HasModuleGoal = 1 << 9, + #[allow(dead_code)] + HasInnerFunctions = 1 << 10, + #[allow(dead_code)] + HasDirectEval = 1 << 11, + #[allow(dead_code)] + BindingsAccessedDynamically = 1 << 12, + #[allow(dead_code)] + HasCallSiteObj = 1 << 13, + #[allow(dead_code)] + IsAsync = 1 << 14, + #[allow(dead_code)] + IsGenerator = 1 << 15, + #[allow(dead_code)] + FunHasExtensibleScope = 1 << 16, + #[allow(dead_code)] + FunctionHasThisBinding = 1 << 17, + #[allow(dead_code)] + NeedsHomeObject = 1 << 18, + #[allow(dead_code)] + IsDerivedClassConstructor = 1 << 19, + #[allow(dead_code)] + IsSyntheticFunction = 1 << 20, + #[allow(dead_code)] + UseMemberInitializers = 1 << 21, + #[allow(dead_code)] + HasRest = 1 << 22, + #[allow(dead_code)] + NeedsFunctionEnvironmentObjects = 1 << 23, + #[allow(dead_code)] + FunctionHasExtraBodyVarScope = 1 << 24, + #[allow(dead_code)] + ShouldDeclareArguments = 1 << 25, + #[allow(dead_code)] + NeedsArgsObj = 1 << 26, + #[allow(dead_code)] + HasMappedArgsObj = 1 << 27, + #[allow(dead_code)] + IsInlinableLargeFunction = 1 << 28, + #[allow(dead_code)] + FunctionHasNewTargetBinding = 1 << 29, +} + +#[derive(Debug, Clone, Copy)] +pub enum MutableScriptFlagsEnum { + #[allow(dead_code)] + HasRunOnce = 1 << 8, + #[allow(dead_code)] + HasBeenCloned = 1 << 9, + #[allow(dead_code)] + HasScriptCounts = 1 << 10, + #[allow(dead_code)] + HasDebugScript = 1 << 11, + #[allow(dead_code)] + AllowRelazify = 1 << 14, + #[allow(dead_code)] + SpewEnabled = 1 << 15, + #[allow(dead_code)] + NeedsFinalWarmUpCount = 1 << 16, + #[allow(dead_code)] + BaselineDisabled = 1 << 17, + #[allow(dead_code)] + IonDisabled = 1 << 18, + #[allow(dead_code)] + Uninlineable = 1 << 19, + #[allow(dead_code)] + FailedBoundsCheck = 1 << 21, + #[allow(dead_code)] + HadLICMInvalidation = 1 << 22, + #[allow(dead_code)] + HadReorderingBailout = 1 << 23, + #[allow(dead_code)] + HadEagerTruncationBailout = 1 << 24, + #[allow(dead_code)] + FailedLexicalCheck = 1 << 25, + #[allow(dead_code)] + HadSpeculativePhiBailout = 1 << 26, + #[allow(dead_code)] + HadUnboxFoldingBailout = 1 << 27, +} + +// @@@@ END TYPES @@@@ + +#[derive(Debug)] +pub struct ImmutableScriptFlags { + value: u32, +} + +impl ImmutableScriptFlags { + pub fn new() -> Self { + Self { value: 0 } + } + + pub fn from_raw(bits: u32) -> Self { + Self { value: bits } + } + + pub fn set(&mut self, bit: ImmutableScriptFlagsEnum) { + self.value |= bit as u32; + } + + pub fn has(&self, bit: ImmutableScriptFlagsEnum) -> bool { + (self.value & bit as u32) != 0 + } + + pub fn reset(&mut self, bit: ImmutableScriptFlagsEnum) { + self.value &= !(bit as u32) + } +} + +impl From<ImmutableScriptFlags> for u32 { + fn from(flags: ImmutableScriptFlags) -> u32 { + flags.value + } +} + +/// Maps to js::ImmutableScriptData in m-c/js/src/vm/SharedStencil.h. +#[derive(Debug)] +pub struct ImmutableScriptData { + pub main_offset: u32, + pub nfixed: FrameSlot, + pub nslots: u32, + pub body_scope_index: u32, + pub num_ic_entries: u32, + pub fun_length: u16, + pub bytecode: Vec<u8>, + pub scope_notes: Vec<ScopeNote>, + // TODO: Add resume_offsets and try_notes. +} + +/// Index into ImmutableScriptDataList.scripts. +#[derive(Debug, Clone, Copy)] +pub struct ImmutableScriptDataIndex { + index: usize, +} + +impl ImmutableScriptDataIndex { + fn new(index: usize) -> Self { + Self { index } + } +} + +impl From<ImmutableScriptDataIndex> for usize { + fn from(index: ImmutableScriptDataIndex) -> usize { + index.index + } +} + +/// List of ImmutableScriptData. +#[derive(Debug)] +pub struct ImmutableScriptDataList { + /// Uses Option to allow `allocate()` and `populate()` to be called + /// separately. + items: Vec<Option<ImmutableScriptData>>, +} + +impl ImmutableScriptDataList { + pub fn new() -> Self { + Self { items: Vec::new() } + } + + pub fn push(&mut self, script: ImmutableScriptData) -> ImmutableScriptDataIndex { + let index = self.items.len(); + self.items.push(Some(script)); + ImmutableScriptDataIndex::new(index) + } + + pub fn allocate(&mut self) -> ImmutableScriptDataIndex { + let index = self.items.len(); + self.items.push(None); + ImmutableScriptDataIndex::new(index) + } + + pub fn populate(&mut self, index: ImmutableScriptDataIndex, script: ImmutableScriptData) { + self.items[usize::from(index)].replace(script); + } +} + +impl From<ImmutableScriptDataList> for Vec<ImmutableScriptData> { + fn from(list: ImmutableScriptDataList) -> Vec<ImmutableScriptData> { + list.items + .into_iter() + .map(|g| g.expect("Should be populated")) + .collect() + } +} + +#[derive(Debug, Clone)] +pub struct SourceExtent { + pub source_start: u32, + pub source_end: u32, + pub to_string_start: u32, + pub to_string_end: u32, + + pub lineno: u32, + pub column: u32, +} + +impl SourceExtent { + fn new() -> Self { + Self { + source_start: 0, + source_end: 0, + to_string_start: 0, + to_string_end: 0, + + lineno: 0, + column: 0, + } + } + + pub fn top_level_script(length: u32, lineno: u32, column: u32) -> Self { + Self { + source_start: 0, + source_end: length, + to_string_start: 0, + to_string_end: length, + + lineno, + column, + } + } +} + +/// Maps to js::frontend::ScriptStencil in m-c/js/src/frontend/Stencil.h. +#[derive(Debug)] +pub struct ScriptStencil { + // Fields for BaseScript. + // Used by: + // * Global script + // * Eval + // * Module + // * non-lazy Function (except asm.js module) + // * lazy Function (cannot be asm.js module) + /// See `BaseScript::immutableFlags_`. + pub immutable_flags: ImmutableScriptFlags, + + /// For top level script and non-lazy function script, + /// this is a list of GC things referred by bytecode and scope. + /// + /// For lazy function script, this contains the list of inner functions, + /// followed by the list of names defined and closed over by inner script. + /// The list of names are delimited by GCThing::Null for each scope. + /// + /// The order of scopes are depth-first post-order, and names inside each + /// scope is in not defined. + /// + /// Trailing scopes without any names are omitted for space efficiency. + pub gcthings: Vec<GCThing>, + + /// See `BaseScript::sharedData_`. + pub immutable_script_data: Option<ImmutableScriptDataIndex>, + + /// The location of this script in the source. + pub extent: SourceExtent, + + // Fields for JSFunction. + // Used by: + // * non-lazy Function + // * lazy Function + // * asm.js module + /// The explicit or implicit name of the function. The FunctionFlags + /// indicate the kind of name. + pub fun_name: Option<SourceAtomSetIndex>, + + /// See `JSFunction::nargs_`. + pub fun_nargs: u16, + + /// See: `FunctionFlags`. + pub fun_flags: FunctionFlags, + + /// If this ScriptStencil refers to a lazy child of the function being + /// compiled, this field holds the child's immediately enclosing scope's + /// index. Once compilation succeeds, we will store the scope pointed by + /// this in the child's BaseScript. (Debugger may become confused if lazy + /// scripts refer to partially initialized enclosing scopes, so we must + /// avoid storing the scope in the BaseScript until compilation has + /// completed successfully.) + pub lazy_function_enclosing_scope_index: Option<ScopeIndex>, + + /// This function is a standalone function that is not syntactically part of + /// another script. Eg. Created by `new Function("")`. + pub is_standalone_function: bool, + + /// This is set by the emitter of the enclosing script when a + /// reference to this function is generated. + pub was_function_emitted: bool, + + /// This function should be marked as a singleton. It is expected to be + /// defined at most once. This is a heuristic only and does not affect + /// correctness. + pub is_singleton_function: bool, +} + +impl ScriptStencil { + fn empty_top_level_script() -> Self { + Self { + immutable_flags: ImmutableScriptFlags::new(), + gcthings: Vec::new(), + immutable_script_data: None, + extent: SourceExtent::new(), + fun_name: None, + fun_nargs: 0, + fun_flags: FunctionFlags::empty(), + lazy_function_enclosing_scope_index: None, + is_standalone_function: false, + was_function_emitted: false, + is_singleton_function: false, + } + } + + pub fn top_level_script( + gcthings: Vec<GCThing>, + immutable_script_data: ImmutableScriptDataIndex, + extent: SourceExtent, + ) -> Self { + Self { + immutable_flags: ImmutableScriptFlags::new(), + gcthings, + immutable_script_data: Some(immutable_script_data), + extent, + fun_name: None, + fun_nargs: 0, + fun_flags: FunctionFlags::empty(), + lazy_function_enclosing_scope_index: None, + is_standalone_function: false, + was_function_emitted: false, + is_singleton_function: false, + } + } + + pub fn lazy_function( + extent: SourceExtent, + fun_name: Option<SourceAtomSetIndex>, + is_generator: bool, + is_async: bool, + fun_flags: FunctionFlags, + lazy_function_enclosing_scope_index: Option<ScopeIndex>, + ) -> Self { + let mut flags = ImmutableScriptFlagsEnum::IsFunction as u32; + if is_generator { + flags |= ImmutableScriptFlagsEnum::IsGenerator as u32; + } + if is_async { + flags |= ImmutableScriptFlagsEnum::IsAsync as u32; + } + + Self { + immutable_flags: ImmutableScriptFlags::from_raw(flags), + gcthings: Vec::new(), + immutable_script_data: None, + extent, + fun_name, + fun_nargs: 0, + fun_flags, + lazy_function_enclosing_scope_index, + is_standalone_function: false, + was_function_emitted: false, + is_singleton_function: false, + } + } + + pub fn is_function(&self) -> bool { + self.immutable_flags + .has(ImmutableScriptFlagsEnum::IsFunction) + } + + pub fn is_non_lazy_function(&self) -> bool { + self.is_function() && self.immutable_script_data.is_some() + } + + pub fn is_lazy_function(&self) -> bool { + self.is_function() && self.immutable_script_data.is_none() + } + + pub fn set_function_has_this_binding(&mut self) { + debug_assert!(self.is_lazy_function()); + self.immutable_flags + .set(ImmutableScriptFlagsEnum::FunctionHasThisBinding); + } + + pub fn set_has_rest(&mut self) { + debug_assert!(self.is_lazy_function()); + self.immutable_flags.set(ImmutableScriptFlagsEnum::HasRest); + } + + pub fn set_needs_function_environment_objects(&mut self) { + debug_assert!(self.is_lazy_function()); + self.immutable_flags + .set(ImmutableScriptFlagsEnum::NeedsFunctionEnvironmentObjects); + } + + pub fn set_function_has_extra_body_var_scope(&mut self) { + debug_assert!(self.is_lazy_function()); + self.immutable_flags + .set(ImmutableScriptFlagsEnum::FunctionHasExtraBodyVarScope); + } + + pub fn set_should_declare_arguments(&mut self) { + debug_assert!(self.is_lazy_function()); + self.immutable_flags + .set(ImmutableScriptFlagsEnum::ShouldDeclareArguments); + } + + pub fn set_needs_args_obj(&mut self) { + debug_assert!(self.is_lazy_function()); + self.immutable_flags + .set(ImmutableScriptFlagsEnum::NeedsArgsObj); + } + + pub fn set_has_mapped_args_obj(&mut self) { + debug_assert!(self.is_lazy_function()); + self.immutable_flags + .set(ImmutableScriptFlagsEnum::HasMappedArgsObj); + } + + pub fn set_function_has_new_target_binding(&mut self) { + debug_assert!(self.is_lazy_function()); + self.immutable_flags + .set(ImmutableScriptFlagsEnum::FunctionHasNewTargetBinding); + } + + pub fn is_arrow_function(&self) -> bool { + self.is_function() && self.fun_flags.is_arrow() + } + + pub fn set_fun_name(&mut self, name: SourceAtomSetIndex) { + debug_assert!(self.is_function()); + self.fun_name = Some(name); + } + + pub fn fun_name<'a>(&'a self) -> &'a Option<SourceAtomSetIndex> { + debug_assert!(self.is_function()); + &self.fun_name + } + + pub fn add_fun_nargs(&mut self) { + debug_assert!(self.is_function()); + self.fun_nargs += 1; + } + + /// source_start should point the start of parameter for functions. + pub fn set_source_starts(&mut self, source_start: usize) { + self.extent.source_start = source_start as u32; + } + + /// to_string_end should point the end of function body for function, + /// and the end of class for constructor. + pub fn set_to_string_end(&mut self, to_string_end: usize) { + self.extent.to_string_end = to_string_end as u32; + } + + /// source_end should point the end of function body. + pub fn set_source_end(&mut self, source_end: usize) { + self.extent.source_end = source_end as u32; + } + + pub fn set_function_emitted(&mut self) { + self.was_function_emitted = true; + } + + pub fn push_inner_function(&mut self, fun: ScriptStencilIndex) { + self.immutable_flags + .set(ImmutableScriptFlagsEnum::HasInnerFunctions); + self.gcthings.push(GCThing::Function(fun)); + } + + pub fn push_closed_over_bindings(&mut self, name: SourceAtomSetIndex) { + debug_assert!(self.is_lazy_function()); + self.gcthings.push(GCThing::Atom(name)); + } + + pub fn push_closed_over_bindings_delimiter(&mut self) { + debug_assert!(self.is_lazy_function()); + self.gcthings.push(GCThing::Null); + } +} + +/// Index into ScriptStencilList.scripts. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct ScriptStencilIndex { + index: usize, +} + +impl ScriptStencilIndex { + fn new(index: usize) -> Self { + Self { index } + } +} + +impl From<ScriptStencilIndex> for usize { + fn from(index: ScriptStencilIndex) -> usize { + index.index + } +} + +/// List of stencil scripts. +#[derive(Debug)] +pub struct ScriptStencilList { + scripts: Vec<ScriptStencil>, +} + +impl ScriptStencilList { + pub fn new() -> Self { + Self { + scripts: Vec::new(), + } + } + + pub fn new_with_empty_top_level() -> Self { + Self { + scripts: vec![ScriptStencil::empty_top_level_script()], + } + } + + pub fn push(&mut self, script: ScriptStencil) -> ScriptStencilIndex { + let index = self.scripts.len(); + self.scripts.push(script); + ScriptStencilIndex::new(index) + } + + pub fn get<'a>(&'a self, index: ScriptStencilIndex) -> &'a ScriptStencil { + &self.scripts[usize::from(index)] + } + + pub fn get_mut<'a>(&'a mut self, index: ScriptStencilIndex) -> &'a mut ScriptStencil { + &mut self.scripts[usize::from(index)] + } + + pub fn set_top_level(&mut self, top_level: ScriptStencil) { + self.scripts[0] = top_level; + } +} + +impl From<ScriptStencilList> for Vec<ScriptStencil> { + fn from(list: ScriptStencilList) -> Vec<ScriptStencil> { + list.scripts.into_iter().collect() + } +} |