summaryrefslogtreecommitdiffstats
path: root/third_party/rust/jsparagus-emitter/src/emitter.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/jsparagus-emitter/src/emitter.rs
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--third_party/rust/jsparagus-emitter/src/emitter.rs1461
1 files changed, 1461 insertions, 0 deletions
diff --git a/third_party/rust/jsparagus-emitter/src/emitter.rs b/third_party/rust/jsparagus-emitter/src/emitter.rs
new file mode 100644
index 0000000000..1bcefab1ae
--- /dev/null
+++ b/third_party/rust/jsparagus-emitter/src/emitter.rs
@@ -0,0 +1,1461 @@
+//! Low-level bytecode emitter, used by ast_builder.
+//!
+//! This API makes it easy to emit correct individual bytecode instructions.
+
+// Most of this functionality isn't used yet.
+#![allow(dead_code)]
+
+use ast::source_atom_set::SourceAtomSetIndex;
+use byteorder::{ByteOrder, LittleEndian};
+use std::cmp;
+use std::collections::HashMap;
+use std::convert::TryFrom;
+use std::convert::TryInto;
+use std::fmt;
+use stencil::bytecode_offset::{BytecodeOffset, BytecodeOffsetDiff};
+use stencil::frame_slot::FrameSlot;
+use stencil::gcthings::{GCThingIndex, GCThingList};
+use stencil::opcode::Opcode;
+use stencil::regexp::RegExpIndex;
+use stencil::scope::ScopeIndex;
+use stencil::scope_notes::{ScopeNoteIndex, ScopeNoteList};
+use stencil::script::{
+ ImmutableScriptData, ImmutableScriptDataList, ScriptStencil, ScriptStencilIndex, SourceExtent,
+};
+
+// WARNING
+// The following section is generated by update_stencil.py.
+// Do mot modify manually.
+//
+// @@@@ BEGIN TYPES @@@@
+#[derive(Debug, Clone, Copy)]
+pub enum AsyncFunctionResolveKind {
+ Fulfill = 0,
+ Reject = 1,
+}
+
+#[derive(Debug, Clone, Copy)]
+pub enum CheckIsObjectKind {
+ IteratorNext = 0,
+ IteratorReturn = 1,
+ IteratorThrow = 2,
+ GetIterator = 3,
+ GetAsyncIterator = 4,
+}
+
+#[derive(Debug, Clone, Copy)]
+pub enum CompletionKind {
+ Normal = 0,
+ Return = 1,
+ Throw = 2,
+}
+
+#[derive(Debug, Clone, Copy)]
+pub enum FunctionPrefixKind {
+ None = 0,
+ Get = 1,
+ Set = 2,
+}
+
+#[derive(Debug, Clone, Copy)]
+pub enum GeneratorResumeKind {
+ Next = 0,
+ Throw = 1,
+ Return = 2,
+}
+
+#[derive(Debug, Clone, Copy)]
+pub enum ThrowMsgKind {
+ AssignToCall = 0,
+ IteratorNoThrow = 1,
+ CantDeleteSuper = 2,
+ PrivateDoubleInit = 3,
+ PrivateBrandDoubleInit = 4,
+ MissingPrivateOnGet = 5,
+ MissingPrivateOnSet = 6,
+ AssignToPrivateMethod = 7,
+ DecoratorInvalidReturnType = 8,
+}
+
+#[derive(Debug, Clone, Copy)]
+pub enum ThrowCondition {
+ ThrowHas = 0,
+ ThrowHasNot = 1,
+ OnlyCheckRhs = 2,
+}
+
+#[derive(Debug, Clone, Copy)]
+pub enum TryNoteKind {
+ Catch = 0,
+ Finally = 1,
+ ForIn = 2,
+ Destructuring = 3,
+ ForOf = 4,
+ ForOfIterClose = 5,
+ Loop = 6,
+}
+
+#[derive(Debug, Clone, Copy)]
+pub enum SymbolCode {
+ IsConcatSpreadable = 0,
+ Iterator = 1,
+ Match = 2,
+ Replace = 3,
+ Search = 4,
+ Species = 5,
+ HasInstance = 6,
+ Split = 7,
+ ToPrimitive = 8,
+ ToStringTag = 9,
+ Unscopables = 10,
+ AsyncIterator = 11,
+ MatchAll = 12,
+}
+
+#[derive(Debug, Clone, Copy)]
+pub enum SrcNoteType {
+ Null = 0,
+ AssignOp = 1,
+ ColSpan = 2,
+ NewLine = 3,
+ SetLine = 4,
+ Breakpoint = 5,
+ StepSep = 6,
+ Unused7 = 7,
+ XDelta = 8,
+}
+
+// @@@@ END TYPES @@@@
+
+#[allow(non_camel_case_types)]
+pub type u24 = u32;
+
+/// Low-level bytecode emitter.
+pub struct InstructionWriter {
+ bytecode: Vec<u8>,
+
+ /// To de-duplicate atoms in gcthings list, note the index for each atom.
+ atom_to_gcindex_map: HashMap<SourceAtomSetIndex, GCThingIndex>,
+
+ gcthings: GCThingList,
+ scope_notes: ScopeNoteList,
+
+ last_jump_target_offset: Option<BytecodeOffset>,
+
+ main_offset: BytecodeOffset,
+
+ /// The maximum number of fixed frame slots.
+ max_fixed_slots: FrameSlot,
+
+ /// Stack depth after the instructions emitted so far.
+ stack_depth: usize,
+
+ /// Maximum stack_depth at any point in the instructions emitted so far.
+ maximum_stack_depth: usize,
+
+ body_scope_index: Option<GCThingIndex>,
+
+ /// Number of JOF_IC instructions emitted so far.
+ num_ic_entries: usize,
+}
+
+#[derive(Debug)]
+pub struct EmitOptions {
+ pub no_script_rval: bool,
+ pub extent: SourceExtent,
+}
+impl EmitOptions {
+ pub fn new(extent: SourceExtent) -> Self {
+ Self {
+ no_script_rval: false,
+ extent,
+ }
+ }
+}
+
+/// The error of bytecode-compilation.
+#[derive(Clone, Debug)]
+pub enum EmitError {
+ NotImplemented(&'static str),
+}
+
+impl fmt::Display for EmitError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ EmitError::NotImplemented(message) => write!(f, "not implemented: {}", message),
+ }
+ }
+}
+
+impl InstructionWriter {
+ pub fn new() -> Self {
+ Self {
+ bytecode: Vec::new(),
+ gcthings: GCThingList::new(),
+ atom_to_gcindex_map: HashMap::new(),
+ scope_notes: ScopeNoteList::new(),
+ last_jump_target_offset: None,
+ main_offset: BytecodeOffset::from(0usize),
+ max_fixed_slots: FrameSlot::new(0),
+ stack_depth: 0,
+ maximum_stack_depth: 0,
+ body_scope_index: None,
+ num_ic_entries: 0,
+ }
+ }
+
+ fn write_i8(&mut self, value: i8) {
+ self.write_u8(value as u8);
+ }
+
+ fn write_u8(&mut self, value: u8) {
+ self.bytecode.push(value);
+ }
+
+ fn write_u16(&mut self, value: u16) {
+ self.bytecode.extend_from_slice(&value.to_le_bytes());
+ }
+
+ fn write_u24(&mut self, value: u24) {
+ let slice = value.to_le_bytes();
+ assert!(slice.len() == 4 && slice[3] == 0);
+ self.bytecode.extend_from_slice(&slice[0..3]);
+ }
+
+ fn write_i32(&mut self, value: i32) {
+ self.bytecode.extend_from_slice(&value.to_le_bytes());
+ }
+
+ fn write_u32(&mut self, value: u32) {
+ self.bytecode.extend_from_slice(&value.to_le_bytes());
+ }
+
+ fn write_g_c_thing_index(&mut self, value: GCThingIndex) {
+ self.write_u32(usize::from(value) as u32);
+ }
+
+ fn write_offset(&mut self, offset: i32) {
+ self.write_i32(offset);
+ }
+
+ fn write_bytecode_offset_diff(&mut self, offset: BytecodeOffsetDiff) {
+ self.write_i32(i32::from(offset));
+ }
+
+ fn write_f64(&mut self, val: f64) {
+ self.bytecode
+ .extend_from_slice(&val.to_bits().to_le_bytes());
+ }
+
+ fn write_ic_index(&mut self) {
+ self.write_u32(self.num_ic_entries.try_into().unwrap());
+ }
+
+ fn emit_op(&mut self, opcode: Opcode) {
+ let nuses: isize = opcode.nuses();
+ assert!(nuses >= 0);
+ self.emit_op_common(opcode, nuses as usize);
+ }
+
+ fn emit_argc_op(&mut self, opcode: Opcode, argc: u16) {
+ assert!(opcode.has_argc());
+ assert_eq!(opcode.nuses(), -1);
+ let nuses = match opcode {
+ Opcode::Call
+ | Opcode::CallIgnoresRv
+ | Opcode::Eval
+ | Opcode::CallIter
+ | Opcode::StrictEval => {
+ // callee, this, arguments...
+ 2 + (argc as usize)
+ }
+
+ Opcode::New | Opcode::SuperCall => {
+ // callee, isConstructing, arguments..., newtarget
+ 2 + (argc as usize) + 1
+ }
+
+ _ => panic!("Unsupported opcode"),
+ };
+ self.emit_op_common(opcode, nuses);
+ }
+
+ fn emit_pop_n_op(&mut self, opcode: Opcode, n: u16) {
+ assert_eq!(opcode.nuses(), -1);
+ debug_assert_eq!(opcode, Opcode::PopN);
+ self.emit_op_common(opcode, n as usize);
+ }
+
+ fn emit_op_common(&mut self, opcode: Opcode, nuses: usize) {
+ assert!(
+ self.stack_depth >= nuses as usize,
+ "InstructionWriter misuse! Not enough arguments on the stack."
+ );
+ self.stack_depth -= nuses as usize;
+
+ let ndefs = opcode.ndefs();
+ if ndefs > 0 {
+ self.stack_depth += ndefs;
+ if self.stack_depth > self.maximum_stack_depth {
+ self.maximum_stack_depth = self.stack_depth;
+ }
+ }
+
+ if opcode.has_ic_entry() {
+ self.num_ic_entries += 1;
+ }
+
+ self.bytecode.push(opcode.to_byte());
+ }
+
+ fn set_last_jump_target_offset(&mut self, target: BytecodeOffset) {
+ self.last_jump_target_offset = Some(target);
+ }
+
+ fn get_end_of_bytecode(&mut self, offset: BytecodeOffset) -> usize {
+ // find the offset after the end of bytecode associated with this offset.
+ let target_opcode = Opcode::try_from(self.bytecode[offset.offset]).unwrap();
+ offset.offset + target_opcode.instruction_length()
+ }
+
+ pub fn emit_jump_target_and_patch(&mut self, jumplist: &Vec<BytecodeOffset>) {
+ let mut target = self.bytecode_offset();
+ let last_jump = self.last_jump_target_offset;
+ match last_jump {
+ Some(offset) => {
+ if self.get_end_of_bytecode(offset) != target.offset {
+ self.jump_target();
+ self.set_last_jump_target_offset(target);
+ } else {
+ target = offset;
+ }
+ }
+ None => {
+ self.jump_target();
+ self.set_last_jump_target_offset(target);
+ }
+ }
+
+ for jump in jumplist {
+ self.patch_jump_to_target(target, *jump);
+ }
+ }
+
+ pub fn patch_jump_to_target(&mut self, target: BytecodeOffset, jump: BytecodeOffset) {
+ let diff = target.diff_from(jump).into();
+ let index = jump.offset + 1;
+ // FIXME: Use native endian instead of little endian
+ LittleEndian::write_i32(&mut self.bytecode[index..index + 4], diff);
+ }
+
+ pub fn bytecode_offset(&mut self) -> BytecodeOffset {
+ BytecodeOffset::from(self.bytecode.len())
+ }
+
+ pub fn stack_depth(&self) -> usize {
+ self.stack_depth
+ }
+
+ pub fn set_stack_depth(&mut self, depth: usize) {
+ self.stack_depth = depth;
+ }
+
+ // Public methods to emit each instruction.
+
+ pub fn emit_boolean(&mut self, value: bool) {
+ self.emit_op(if value { Opcode::True } else { Opcode::False });
+ }
+
+ pub fn emit_unary_op(&mut self, opcode: Opcode) {
+ assert!(opcode.is_simple_unary_operator());
+ self.emit_op(opcode);
+ }
+
+ pub fn emit_binary_op(&mut self, opcode: Opcode) {
+ assert!(opcode.is_simple_binary_operator());
+ debug_assert_eq!(opcode.nuses(), 2);
+ debug_assert_eq!(opcode.ndefs(), 1);
+ self.emit_op(opcode);
+ }
+
+ pub fn table_switch(
+ &mut self,
+ _len: i32,
+ _low: i32,
+ _high: i32,
+ _first_resume_index: u24,
+ ) -> Result<(), EmitError> {
+ Err(EmitError::NotImplemented("TODO: table_switch"))
+ }
+
+ pub fn numeric(&mut self, value: f64) {
+ if value.is_finite() && value.fract() == 0.0 {
+ if i8::min_value() as f64 <= value && value <= i8::max_value() as f64 {
+ match value as i8 {
+ 0 => self.zero(),
+ 1 => self.one(),
+ i => self.int8(i),
+ }
+ return;
+ }
+ if 0.0 <= value {
+ if value <= u16::max_value() as f64 {
+ self.uint16(value as u16);
+ return;
+ }
+ if value <= 0x00ffffff as f64 {
+ self.uint24(value as u24);
+ return;
+ }
+ }
+ if i32::min_value() as f64 <= value && value <= i32::max_value() as f64 {
+ self.int32(value as i32);
+ return;
+ }
+ }
+ self.double_(value);
+ }
+
+ // WARNING
+ // The following section is generated by update_stencil.py.
+ // Do mot modify manually.
+ //
+ // @@@@ BEGIN METHODS @@@@
+ pub fn undefined(&mut self) {
+ self.emit_op(Opcode::Undefined);
+ }
+
+ pub fn null(&mut self) {
+ self.emit_op(Opcode::Null);
+ }
+
+ pub fn int32(&mut self, val: i32) {
+ self.emit_op(Opcode::Int32);
+ self.write_i32(val);
+ }
+
+ pub fn zero(&mut self) {
+ self.emit_op(Opcode::Zero);
+ }
+
+ pub fn one(&mut self) {
+ self.emit_op(Opcode::One);
+ }
+
+ pub fn int8(&mut self, val: i8) {
+ self.emit_op(Opcode::Int8);
+ self.write_i8(val);
+ }
+
+ pub fn uint16(&mut self, val: u16) {
+ self.emit_op(Opcode::Uint16);
+ self.write_u16(val);
+ }
+
+ pub fn uint24(&mut self, val: u24) {
+ self.emit_op(Opcode::Uint24);
+ self.write_u24(val);
+ }
+
+ pub fn double_(&mut self, val: f64) {
+ self.emit_op(Opcode::Double);
+ self.write_f64(val);
+ }
+
+ pub fn big_int(&mut self, big_int_index: u32) {
+ self.emit_op(Opcode::BigInt);
+ self.write_u32(big_int_index);
+ }
+
+ pub fn string(&mut self, atom_index: GCThingIndex) {
+ self.emit_op(Opcode::String);
+ self.write_g_c_thing_index(atom_index);
+ }
+
+ pub fn symbol(&mut self, symbol: u8) {
+ self.emit_op(Opcode::Symbol);
+ self.write_u8(symbol);
+ }
+
+ pub fn typeof_(&mut self) {
+ self.emit_op(Opcode::Typeof);
+ }
+
+ pub fn typeof_expr(&mut self) {
+ self.emit_op(Opcode::TypeofExpr);
+ }
+
+ pub fn inc(&mut self) {
+ self.emit_op(Opcode::Inc);
+ }
+
+ pub fn dec(&mut self) {
+ self.emit_op(Opcode::Dec);
+ }
+
+ pub fn to_property_key(&mut self) {
+ self.emit_op(Opcode::ToPropertyKey);
+ }
+
+ pub fn to_numeric(&mut self) {
+ self.emit_op(Opcode::ToNumeric);
+ }
+
+ pub fn to_string(&mut self) {
+ self.emit_op(Opcode::ToString);
+ }
+
+ pub fn is_null_or_undefined(&mut self) {
+ self.emit_op(Opcode::IsNullOrUndefined);
+ }
+
+ pub fn global_this(&mut self) {
+ self.emit_op(Opcode::GlobalThis);
+ }
+
+ pub fn non_syntactic_global_this(&mut self) {
+ self.emit_op(Opcode::NonSyntacticGlobalThis);
+ }
+
+ pub fn new_target(&mut self) {
+ self.emit_op(Opcode::NewTarget);
+ }
+
+ pub fn dynamic_import(&mut self) {
+ self.emit_op(Opcode::DynamicImport);
+ }
+
+ pub fn import_meta(&mut self) {
+ self.emit_op(Opcode::ImportMeta);
+ }
+
+ pub fn new_init(&mut self) {
+ self.emit_op(Opcode::NewInit);
+ }
+
+ pub fn new_object(&mut self, shape_index: GCThingIndex) {
+ self.emit_op(Opcode::NewObject);
+ self.write_g_c_thing_index(shape_index);
+ }
+
+ pub fn object(&mut self, object_index: GCThingIndex) {
+ self.emit_op(Opcode::Object);
+ self.write_g_c_thing_index(object_index);
+ }
+
+ pub fn obj_with_proto(&mut self) {
+ self.emit_op(Opcode::ObjWithProto);
+ }
+
+ pub fn init_prop(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::InitProp);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn init_hidden_prop(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::InitHiddenProp);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn init_locked_prop(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::InitLockedProp);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn init_elem(&mut self) {
+ self.emit_op(Opcode::InitElem);
+ }
+
+ pub fn init_hidden_elem(&mut self) {
+ self.emit_op(Opcode::InitHiddenElem);
+ }
+
+ pub fn init_locked_elem(&mut self) {
+ self.emit_op(Opcode::InitLockedElem);
+ }
+
+ pub fn init_prop_getter(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::InitPropGetter);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn init_hidden_prop_getter(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::InitHiddenPropGetter);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn init_elem_getter(&mut self) {
+ self.emit_op(Opcode::InitElemGetter);
+ }
+
+ pub fn init_hidden_elem_getter(&mut self) {
+ self.emit_op(Opcode::InitHiddenElemGetter);
+ }
+
+ pub fn init_prop_setter(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::InitPropSetter);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn init_hidden_prop_setter(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::InitHiddenPropSetter);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn init_elem_setter(&mut self) {
+ self.emit_op(Opcode::InitElemSetter);
+ }
+
+ pub fn init_hidden_elem_setter(&mut self) {
+ self.emit_op(Opcode::InitHiddenElemSetter);
+ }
+
+ pub fn get_prop(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::GetProp);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn get_elem(&mut self) {
+ self.emit_op(Opcode::GetElem);
+ }
+
+ pub fn set_prop(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::SetProp);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn strict_set_prop(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::StrictSetProp);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn set_elem(&mut self) {
+ self.emit_op(Opcode::SetElem);
+ }
+
+ pub fn strict_set_elem(&mut self) {
+ self.emit_op(Opcode::StrictSetElem);
+ }
+
+ pub fn del_prop(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::DelProp);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn strict_del_prop(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::StrictDelProp);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn del_elem(&mut self) {
+ self.emit_op(Opcode::DelElem);
+ }
+
+ pub fn strict_del_elem(&mut self) {
+ self.emit_op(Opcode::StrictDelElem);
+ }
+
+ pub fn has_own(&mut self) {
+ self.emit_op(Opcode::HasOwn);
+ }
+
+ pub fn check_private_field(&mut self, throw_condition: ThrowCondition, msg_kind: ThrowMsgKind) {
+ self.emit_op(Opcode::CheckPrivateField);
+ self.write_u8(throw_condition as u8);
+ self.write_u8(msg_kind as u8);
+ }
+
+ pub fn new_private_name(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::NewPrivateName);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn super_base(&mut self) {
+ self.emit_op(Opcode::SuperBase);
+ }
+
+ pub fn get_prop_super(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::GetPropSuper);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn get_elem_super(&mut self) {
+ self.emit_op(Opcode::GetElemSuper);
+ }
+
+ pub fn set_prop_super(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::SetPropSuper);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn strict_set_prop_super(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::StrictSetPropSuper);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn set_elem_super(&mut self) {
+ self.emit_op(Opcode::SetElemSuper);
+ }
+
+ pub fn strict_set_elem_super(&mut self) {
+ self.emit_op(Opcode::StrictSetElemSuper);
+ }
+
+ pub fn iter(&mut self) {
+ self.emit_op(Opcode::Iter);
+ }
+
+ pub fn more_iter(&mut self) {
+ self.emit_op(Opcode::MoreIter);
+ }
+
+ pub fn is_no_iter(&mut self) {
+ self.emit_op(Opcode::IsNoIter);
+ }
+
+ pub fn end_iter(&mut self) {
+ self.emit_op(Opcode::EndIter);
+ }
+
+ pub fn close_iter(&mut self, kind: CompletionKind) {
+ self.emit_op(Opcode::CloseIter);
+ self.write_u8(kind as u8);
+ }
+
+ pub fn check_is_obj(&mut self, kind: CheckIsObjectKind) {
+ self.emit_op(Opcode::CheckIsObj);
+ self.write_u8(kind as u8);
+ }
+
+ pub fn check_obj_coercible(&mut self) {
+ self.emit_op(Opcode::CheckObjCoercible);
+ }
+
+ pub fn to_async_iter(&mut self) {
+ self.emit_op(Opcode::ToAsyncIter);
+ }
+
+ pub fn mutate_proto(&mut self) {
+ self.emit_op(Opcode::MutateProto);
+ }
+
+ pub fn new_array(&mut self, length: u32) {
+ self.emit_op(Opcode::NewArray);
+ self.write_u32(length);
+ }
+
+ pub fn init_elem_array(&mut self, index: u32) {
+ self.emit_op(Opcode::InitElemArray);
+ self.write_u32(index);
+ }
+
+ pub fn init_elem_inc(&mut self) {
+ self.emit_op(Opcode::InitElemInc);
+ }
+
+ pub fn hole(&mut self) {
+ self.emit_op(Opcode::Hole);
+ }
+
+ pub fn reg_exp(&mut self, regexp_index: GCThingIndex) {
+ self.emit_op(Opcode::RegExp);
+ self.write_g_c_thing_index(regexp_index);
+ }
+
+ pub fn lambda(&mut self, func_index: GCThingIndex) {
+ self.emit_op(Opcode::Lambda);
+ self.write_g_c_thing_index(func_index);
+ }
+
+ pub fn set_fun_name(&mut self, prefix_kind: FunctionPrefixKind) {
+ self.emit_op(Opcode::SetFunName);
+ self.write_u8(prefix_kind as u8);
+ }
+
+ pub fn init_home_object(&mut self) {
+ self.emit_op(Opcode::InitHomeObject);
+ }
+
+ pub fn check_class_heritage(&mut self) {
+ self.emit_op(Opcode::CheckClassHeritage);
+ }
+
+ pub fn fun_with_proto(&mut self, func_index: GCThingIndex) {
+ self.emit_op(Opcode::FunWithProto);
+ self.write_g_c_thing_index(func_index);
+ }
+
+ pub fn builtin_object(&mut self, kind: u8) {
+ self.emit_op(Opcode::BuiltinObject);
+ self.write_u8(kind);
+ }
+
+ pub fn call(&mut self, argc: u16) {
+ self.emit_argc_op(Opcode::Call, argc);
+ self.write_u16(argc);
+ }
+
+ pub fn call_content(&mut self, argc: u16) {
+ self.emit_argc_op(Opcode::CallContent, argc);
+ self.write_u16(argc);
+ }
+
+ pub fn call_iter(&mut self, argc: u16) {
+ self.emit_argc_op(Opcode::CallIter, argc);
+ self.write_u16(argc);
+ }
+
+ pub fn call_content_iter(&mut self, argc: u16) {
+ self.emit_argc_op(Opcode::CallContentIter, argc);
+ self.write_u16(argc);
+ }
+
+ pub fn call_ignores_rv(&mut self, argc: u16) {
+ self.emit_argc_op(Opcode::CallIgnoresRv, argc);
+ self.write_u16(argc);
+ }
+
+ pub fn spread_call(&mut self) {
+ self.emit_op(Opcode::SpreadCall);
+ }
+
+ pub fn optimize_spread_call(&mut self) {
+ self.emit_op(Opcode::OptimizeSpreadCall);
+ }
+
+ pub fn eval(&mut self, argc: u16) {
+ self.emit_argc_op(Opcode::Eval, argc);
+ self.write_u16(argc);
+ }
+
+ pub fn spread_eval(&mut self) {
+ self.emit_op(Opcode::SpreadEval);
+ }
+
+ pub fn strict_eval(&mut self, argc: u16) {
+ self.emit_argc_op(Opcode::StrictEval, argc);
+ self.write_u16(argc);
+ }
+
+ pub fn strict_spread_eval(&mut self) {
+ self.emit_op(Opcode::StrictSpreadEval);
+ }
+
+ pub fn implicit_this(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::ImplicitThis);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn call_site_obj(&mut self, object_index: GCThingIndex) {
+ self.emit_op(Opcode::CallSiteObj);
+ self.write_g_c_thing_index(object_index);
+ }
+
+ pub fn is_constructing(&mut self) {
+ self.emit_op(Opcode::IsConstructing);
+ }
+
+ pub fn new_(&mut self, argc: u16) {
+ self.emit_argc_op(Opcode::New, argc);
+ self.write_u16(argc);
+ }
+
+ pub fn new_content(&mut self, argc: u16) {
+ self.emit_argc_op(Opcode::NewContent, argc);
+ self.write_u16(argc);
+ }
+
+ pub fn super_call(&mut self, argc: u16) {
+ self.emit_argc_op(Opcode::SuperCall, argc);
+ self.write_u16(argc);
+ }
+
+ pub fn spread_new(&mut self) {
+ self.emit_op(Opcode::SpreadNew);
+ }
+
+ pub fn spread_super_call(&mut self) {
+ self.emit_op(Opcode::SpreadSuperCall);
+ }
+
+ pub fn super_fun(&mut self) {
+ self.emit_op(Opcode::SuperFun);
+ }
+
+ pub fn check_this_reinit(&mut self) {
+ self.emit_op(Opcode::CheckThisReinit);
+ }
+
+ pub fn generator(&mut self) {
+ self.emit_op(Opcode::Generator);
+ }
+
+ pub fn initial_yield(&mut self, resume_index: u24) {
+ self.emit_op(Opcode::InitialYield);
+ self.write_u24(resume_index);
+ }
+
+ pub fn after_yield(&mut self) {
+ self.emit_op(Opcode::AfterYield);
+ self.write_ic_index();
+ }
+
+ pub fn final_yield_rval(&mut self) {
+ self.emit_op(Opcode::FinalYieldRval);
+ }
+
+ pub fn yield_(&mut self, resume_index: u24) {
+ self.emit_op(Opcode::Yield);
+ self.write_u24(resume_index);
+ }
+
+ pub fn is_gen_closing(&mut self) {
+ self.emit_op(Opcode::IsGenClosing);
+ }
+
+ pub fn async_await(&mut self) {
+ self.emit_op(Opcode::AsyncAwait);
+ }
+
+ pub fn async_resolve(&mut self, fulfill_or_reject: AsyncFunctionResolveKind) {
+ self.emit_op(Opcode::AsyncResolve);
+ self.write_u8(fulfill_or_reject as u8);
+ }
+
+ pub fn await_(&mut self, resume_index: u24) {
+ self.emit_op(Opcode::Await);
+ self.write_u24(resume_index);
+ }
+
+ pub fn can_skip_await(&mut self) {
+ self.emit_op(Opcode::CanSkipAwait);
+ }
+
+ pub fn maybe_extract_await_value(&mut self) {
+ self.emit_op(Opcode::MaybeExtractAwaitValue);
+ }
+
+ pub fn resume_kind(&mut self, resume_kind: GeneratorResumeKind) {
+ self.emit_op(Opcode::ResumeKind);
+ self.write_u8(resume_kind as u8);
+ }
+
+ pub fn check_resume_kind(&mut self) {
+ self.emit_op(Opcode::CheckResumeKind);
+ }
+
+ pub fn resume(&mut self) {
+ self.emit_op(Opcode::Resume);
+ }
+
+ pub fn jump_target(&mut self) {
+ self.emit_op(Opcode::JumpTarget);
+ self.write_ic_index();
+ }
+
+ pub fn loop_head(&mut self, depth_hint: u8) {
+ self.emit_op(Opcode::LoopHead);
+ self.write_ic_index();
+ self.write_u8(depth_hint);
+ }
+
+ pub fn goto_(&mut self, offset: BytecodeOffsetDiff) {
+ self.emit_op(Opcode::Goto);
+ self.write_bytecode_offset_diff(offset);
+ }
+
+ pub fn jump_if_false(&mut self, forward_offset: BytecodeOffsetDiff) {
+ self.emit_op(Opcode::JumpIfFalse);
+ self.write_bytecode_offset_diff(forward_offset);
+ }
+
+ pub fn jump_if_true(&mut self, offset: BytecodeOffsetDiff) {
+ self.emit_op(Opcode::JumpIfTrue);
+ self.write_bytecode_offset_diff(offset);
+ }
+
+ pub fn and_(&mut self, forward_offset: BytecodeOffsetDiff) {
+ self.emit_op(Opcode::And);
+ self.write_bytecode_offset_diff(forward_offset);
+ }
+
+ pub fn or_(&mut self, forward_offset: BytecodeOffsetDiff) {
+ self.emit_op(Opcode::Or);
+ self.write_bytecode_offset_diff(forward_offset);
+ }
+
+ pub fn coalesce(&mut self, forward_offset: BytecodeOffsetDiff) {
+ self.emit_op(Opcode::Coalesce);
+ self.write_bytecode_offset_diff(forward_offset);
+ }
+
+ pub fn case_(&mut self, forward_offset: BytecodeOffsetDiff) {
+ self.emit_op(Opcode::Case);
+ self.write_bytecode_offset_diff(forward_offset);
+ }
+
+ pub fn default_(&mut self, forward_offset: BytecodeOffsetDiff) {
+ self.emit_op(Opcode::Default);
+ self.write_bytecode_offset_diff(forward_offset);
+ }
+
+ pub fn return_(&mut self) {
+ self.emit_op(Opcode::Return);
+ }
+
+ pub fn get_rval(&mut self) {
+ self.emit_op(Opcode::GetRval);
+ }
+
+ pub fn set_rval(&mut self) {
+ self.emit_op(Opcode::SetRval);
+ }
+
+ pub fn ret_rval(&mut self) {
+ self.emit_op(Opcode::RetRval);
+ }
+
+ pub fn check_return(&mut self) {
+ self.emit_op(Opcode::CheckReturn);
+ }
+
+ pub fn throw_(&mut self) {
+ self.emit_op(Opcode::Throw);
+ }
+
+ pub fn throw_msg(&mut self, msg_number: ThrowMsgKind) {
+ self.emit_op(Opcode::ThrowMsg);
+ self.write_u8(msg_number as u8);
+ }
+
+ pub fn throw_set_const(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::ThrowSetConst);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn try_(&mut self) {
+ self.emit_op(Opcode::Try);
+ }
+
+ pub fn try_destructuring(&mut self) {
+ self.emit_op(Opcode::TryDestructuring);
+ }
+
+ pub fn exception(&mut self) {
+ self.emit_op(Opcode::Exception);
+ }
+
+ pub fn finally(&mut self) {
+ self.emit_op(Opcode::Finally);
+ }
+
+ pub fn uninitialized(&mut self) {
+ self.emit_op(Opcode::Uninitialized);
+ }
+
+ pub fn init_lexical(&mut self, localno: u24) {
+ self.emit_op(Opcode::InitLexical);
+ self.write_u24(localno);
+ }
+
+ pub fn init_g_lexical(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::InitGLexical);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn init_aliased_lexical(&mut self, hops: u8, slot: u24) {
+ self.emit_op(Opcode::InitAliasedLexical);
+ self.write_u8(hops);
+ self.write_u24(slot);
+ }
+
+ pub fn check_lexical(&mut self, localno: u24) {
+ self.emit_op(Opcode::CheckLexical);
+ self.write_u24(localno);
+ }
+
+ pub fn check_aliased_lexical(&mut self, hops: u8, slot: u24) {
+ self.emit_op(Opcode::CheckAliasedLexical);
+ self.write_u8(hops);
+ self.write_u24(slot);
+ }
+
+ pub fn check_this(&mut self) {
+ self.emit_op(Opcode::CheckThis);
+ }
+
+ pub fn bind_g_name(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::BindGName);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn bind_name(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::BindName);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn get_name(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::GetName);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn get_g_name(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::GetGName);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn get_arg(&mut self, argno: u16) {
+ self.emit_op(Opcode::GetArg);
+ self.write_u16(argno);
+ }
+
+ pub fn get_local(&mut self, localno: u24) {
+ self.emit_op(Opcode::GetLocal);
+ self.write_u24(localno);
+ }
+
+ pub fn get_aliased_var(&mut self, hops: u8, slot: u24) {
+ self.emit_op(Opcode::GetAliasedVar);
+ self.write_u8(hops);
+ self.write_u24(slot);
+ }
+
+ pub fn get_aliased_debug_var(&mut self, hops: u8, slot: u24) {
+ self.emit_op(Opcode::GetAliasedDebugVar);
+ self.write_u8(hops);
+ self.write_u24(slot);
+ }
+
+ pub fn get_import(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::GetImport);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn get_bound_name(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::GetBoundName);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn get_intrinsic(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::GetIntrinsic);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn callee(&mut self) {
+ self.emit_op(Opcode::Callee);
+ }
+
+ pub fn env_callee(&mut self, num_hops: u8) {
+ self.emit_op(Opcode::EnvCallee);
+ self.write_u8(num_hops);
+ }
+
+ pub fn set_name(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::SetName);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn strict_set_name(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::StrictSetName);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn set_g_name(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::SetGName);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn strict_set_g_name(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::StrictSetGName);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn set_arg(&mut self, argno: u16) {
+ self.emit_op(Opcode::SetArg);
+ self.write_u16(argno);
+ }
+
+ pub fn set_local(&mut self, localno: u24) {
+ self.emit_op(Opcode::SetLocal);
+ self.write_u24(localno);
+ }
+
+ pub fn set_aliased_var(&mut self, hops: u8, slot: u24) {
+ self.emit_op(Opcode::SetAliasedVar);
+ self.write_u8(hops);
+ self.write_u24(slot);
+ }
+
+ pub fn set_intrinsic(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::SetIntrinsic);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn push_lexical_env(&mut self, lexical_scope_index: GCThingIndex) {
+ self.emit_op(Opcode::PushLexicalEnv);
+ self.write_g_c_thing_index(lexical_scope_index);
+ }
+
+ pub fn pop_lexical_env(&mut self) {
+ self.emit_op(Opcode::PopLexicalEnv);
+ }
+
+ pub fn debug_leave_lexical_env(&mut self) {
+ self.emit_op(Opcode::DebugLeaveLexicalEnv);
+ }
+
+ pub fn recreate_lexical_env(&mut self, lexical_scope_index: GCThingIndex) {
+ self.emit_op(Opcode::RecreateLexicalEnv);
+ self.write_g_c_thing_index(lexical_scope_index);
+ }
+
+ pub fn freshen_lexical_env(&mut self, lexical_scope_index: GCThingIndex) {
+ self.emit_op(Opcode::FreshenLexicalEnv);
+ self.write_g_c_thing_index(lexical_scope_index);
+ }
+
+ pub fn push_class_body_env(&mut self, lexical_scope_index: GCThingIndex) {
+ self.emit_op(Opcode::PushClassBodyEnv);
+ self.write_g_c_thing_index(lexical_scope_index);
+ }
+
+ pub fn push_var_env(&mut self, scope_index: GCThingIndex) {
+ self.emit_op(Opcode::PushVarEnv);
+ self.write_g_c_thing_index(scope_index);
+ }
+
+ pub fn enter_with(&mut self, static_with_index: GCThingIndex) {
+ self.emit_op(Opcode::EnterWith);
+ self.write_g_c_thing_index(static_with_index);
+ }
+
+ pub fn leave_with(&mut self) {
+ self.emit_op(Opcode::LeaveWith);
+ }
+
+ pub fn bind_var(&mut self) {
+ self.emit_op(Opcode::BindVar);
+ }
+
+ pub fn global_or_eval_decl_instantiation(&mut self, last_fun: u32) {
+ self.emit_op(Opcode::GlobalOrEvalDeclInstantiation);
+ self.write_u32(last_fun);
+ }
+
+ pub fn del_name(&mut self, name_index: GCThingIndex) {
+ self.emit_op(Opcode::DelName);
+ self.write_g_c_thing_index(name_index);
+ }
+
+ pub fn arguments(&mut self) {
+ self.emit_op(Opcode::Arguments);
+ }
+
+ pub fn rest(&mut self) {
+ self.emit_op(Opcode::Rest);
+ }
+
+ pub fn function_this(&mut self) {
+ self.emit_op(Opcode::FunctionThis);
+ }
+
+ pub fn pop(&mut self) {
+ self.emit_op(Opcode::Pop);
+ }
+
+ pub fn pop_n(&mut self, n: u16) {
+ self.emit_pop_n_op(Opcode::PopN, n);
+ self.write_u16(n);
+ }
+
+ pub fn dup(&mut self) {
+ self.emit_op(Opcode::Dup);
+ }
+
+ pub fn dup2(&mut self) {
+ self.emit_op(Opcode::Dup2);
+ }
+
+ pub fn dup_at(&mut self, n: u24) {
+ self.emit_op(Opcode::DupAt);
+ self.write_u24(n);
+ }
+
+ pub fn swap(&mut self) {
+ self.emit_op(Opcode::Swap);
+ }
+
+ pub fn pick(&mut self, n: u8) {
+ self.emit_op(Opcode::Pick);
+ self.write_u8(n);
+ }
+
+ pub fn unpick(&mut self, n: u8) {
+ self.emit_op(Opcode::Unpick);
+ self.write_u8(n);
+ }
+
+ pub fn nop(&mut self) {
+ self.emit_op(Opcode::Nop);
+ }
+
+ pub fn lineno(&mut self, lineno: u32) {
+ self.emit_op(Opcode::Lineno);
+ self.write_u32(lineno);
+ }
+
+ pub fn nop_destructuring(&mut self) {
+ self.emit_op(Opcode::NopDestructuring);
+ }
+
+ pub fn force_interpreter(&mut self) {
+ self.emit_op(Opcode::ForceInterpreter);
+ }
+
+ pub fn debug_check_self_hosted(&mut self) {
+ self.emit_op(Opcode::DebugCheckSelfHosted);
+ }
+
+ pub fn debugger(&mut self) {
+ self.emit_op(Opcode::Debugger);
+ }
+
+ // @@@@ END METHODS @@@@
+
+ pub fn get_atom_gcthing_index(&mut self, atom: SourceAtomSetIndex) -> GCThingIndex {
+ match self.atom_to_gcindex_map.get(&atom) {
+ Some(index) => *index,
+ None => {
+ let index = self.gcthings.push_atom(atom);
+ self.atom_to_gcindex_map.insert(atom, index);
+ index
+ }
+ }
+ }
+
+ pub fn get_function_gcthing_index(&mut self, fun_index: ScriptStencilIndex) -> GCThingIndex {
+ self.gcthings.push_function(fun_index)
+ }
+
+ pub fn get_regexp_gcthing_index(&mut self, regexp_index: RegExpIndex) -> GCThingIndex {
+ self.gcthings.push_regexp(regexp_index)
+ }
+
+ fn update_max_frame_slots(&mut self, max_frame_slots: FrameSlot) {
+ self.max_fixed_slots = cmp::max(self.max_fixed_slots, max_frame_slots);
+ }
+
+ pub fn enter_global_scope(&mut self, scope_index: ScopeIndex) {
+ let index = self.gcthings.push_scope(scope_index);
+ self.body_scope_index = Some(index);
+ }
+
+ pub fn leave_global_scope(&self) {}
+
+ pub fn enter_lexical_scope(
+ &mut self,
+ scope_index: ScopeIndex,
+ parent_scope_note_index: Option<ScopeNoteIndex>,
+ next_frame_slot: FrameSlot,
+ needs_environment_object: bool,
+ ) -> ScopeNoteIndex {
+ self.update_max_frame_slots(next_frame_slot);
+
+ let gcthing_index = self.gcthings.push_scope(scope_index);
+ let offset = self.bytecode_offset();
+ let note_index =
+ self.scope_notes
+ .enter_scope(gcthing_index, offset, parent_scope_note_index);
+
+ if needs_environment_object {
+ self.push_lexical_env(gcthing_index);
+ }
+
+ note_index
+ }
+
+ pub fn leave_lexical_scope(&mut self, index: ScopeNoteIndex, needs_environment_object: bool) {
+ self.emit_leave_lexical_scope(needs_environment_object);
+ let offset = self.bytecode_offset();
+ self.scope_notes.leave_scope(index, offset);
+ }
+
+ fn emit_leave_lexical_scope(&mut self, needs_environment_object: bool) {
+ if needs_environment_object {
+ self.pop_lexical_env();
+ } else {
+ self.debug_leave_lexical_env();
+ }
+ }
+
+ pub fn enter_scope_hole_from_lexical(
+ &mut self,
+ maybe_hole_scope_note_index: &Option<ScopeNoteIndex>,
+ parent_scope_note_index: Option<ScopeNoteIndex>,
+ needs_environment_object: bool,
+ ) -> ScopeNoteIndex {
+ self.emit_leave_lexical_scope(needs_environment_object);
+ self.enter_scope_hole(maybe_hole_scope_note_index, parent_scope_note_index)
+ }
+
+ fn enter_scope_hole(
+ &mut self,
+ maybe_hole_scope_note_index: &Option<ScopeNoteIndex>,
+ parent_scope_note_index: Option<ScopeNoteIndex>,
+ ) -> ScopeNoteIndex {
+ let offset = self.bytecode_offset();
+
+ let gcthing_index = match maybe_hole_scope_note_index {
+ Some(index) => self.scope_notes.get_scope_hole_gcthing_index(index),
+ None => self
+ .body_scope_index
+ .expect("we should have a body scope index"),
+ };
+
+ self.scope_notes
+ .enter_scope(gcthing_index, offset, parent_scope_note_index)
+ }
+
+ pub fn leave_scope_hole(&mut self, index: ScopeNoteIndex) {
+ let offset = self.bytecode_offset();
+ self.scope_notes.leave_scope(index, offset);
+ }
+
+ pub fn switch_to_main(&mut self) {
+ self.main_offset = self.bytecode_offset();
+ }
+
+ pub fn into_stencil(
+ self,
+ script_data_list: &mut ImmutableScriptDataList,
+ extent: SourceExtent,
+ ) -> Result<ScriptStencil, EmitError> {
+ let main_offset: usize = self.main_offset.into();
+ let nfixed: u32 = self.max_fixed_slots.into();
+ let nslots = nfixed as usize + self.maximum_stack_depth;
+
+ let immutable_script_data = script_data_list.push(ImmutableScriptData {
+ main_offset: main_offset
+ .try_into()
+ .map_err(|_| EmitError::NotImplemented("Throwing allocation overflow"))?,
+ nfixed: self.max_fixed_slots,
+ nslots: nslots
+ .try_into()
+ .map_err(|_| EmitError::NotImplemented("Throwing JSMSG_NEED_DIET"))?,
+ body_scope_index: usize::from(self.body_scope_index.expect("body scope should be set"))
+ .try_into()
+ .map_err(|_| EmitError::NotImplemented("Throwing allocation overflow"))?,
+ num_ic_entries: self.num_ic_entries.try_into().unwrap(),
+ fun_length: 0,
+
+ bytecode: self.bytecode,
+ scope_notes: self.scope_notes.into(),
+ });
+
+ Ok(ScriptStencil::top_level_script(
+ self.gcthings.into(),
+ immutable_script_data,
+ extent,
+ ))
+ }
+}