//! 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()
}
}
Messung V0.5 in Prozent C=89 H=100 G=94
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet am 2026-06-19)
¤
*© Formatika GbR, Deutschland