summaryrefslogtreecommitdiffstats
path: root/third_party/rust/jsparagus-stencil/src/script.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
commit43a97878ce14b72f0981164f87f2e35e14151312 (patch)
tree620249daf56c0258faa40cbdcf9cfba06de2a846 /third_party/rust/jsparagus-stencil/src/script.rs
parentInitial commit. (diff)
downloadfirefox-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.rs574
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()
+ }
+}