@@ -417,9 +417,31 @@ impl Vm<'_> {
417417 . fold ( 0 , |slots, slot| slots | slot)
418418 }
419419
420+ pub ( super ) fn initial_realm_binding_slots (
421+ bytecode : & Bytecode ,
422+ local_upvalues : & [ Option < Upvalue > ] ,
423+ env : & CallEnv ,
424+ ) -> u128 {
425+ bytecode
426+ . locals
427+ . iter ( )
428+ . enumerate ( )
429+ . take ( u128:: BITS as usize )
430+ . filter_map ( |( slot, local) | {
431+ local_upvalues
432+ . get ( slot)
433+ . and_then ( Option :: as_ref)
434+ . is_some_and ( |cell| env. is_realm_binding_cell ( & local. name , cell) )
435+ . then_some ( 1_u128 << slot)
436+ } )
437+ . fold ( 0 , |slots, slot| slots | slot)
438+ }
439+
420440 pub ( super ) fn refresh_authoritative_slots ( & mut self ) {
421441 self . authoritative_slots =
422442 Self :: initial_authoritative_slots ( self . bytecode , & self . local_upvalues , & self . env ) ;
443+ self . realm_binding_slots =
444+ Self :: initial_realm_binding_slots ( self . bytecode , & self . local_upvalues , & self . env ) ;
423445 }
424446
425447 /// Keeps a module's exported binding cell current for name-based writes.
@@ -756,9 +778,9 @@ impl Vm<'_> {
756778 }
757779 match slot {
758780 Some ( slot) => self . assign_local ( slot, value) ,
759- None if is_strict => self . store_global_strict ( name. to_owned ( ) , value) ,
781+ None if is_strict => self . store_global_strict ( name, value) ,
760782 None => {
761- self . store_global_sloppy ( name. to_owned ( ) , value) ?;
783+ self . store_global_sloppy ( name, value) ?;
762784 self . record_sloppy_global_name ( name) ;
763785 Ok ( ( ) )
764786 }
@@ -818,9 +840,9 @@ impl Vm<'_> {
818840 match self . load_local ( object_slot) ? {
819841 Value :: Undefined => match slot {
820842 Some ( slot) => self . assign_local ( slot, value) ,
821- None if is_strict => self . store_global_strict ( name. to_owned ( ) , value) ,
843+ None if is_strict => self . store_global_strict ( name, value) ,
822844 None => {
823- self . store_global_sloppy ( name. to_owned ( ) , value) ?;
845+ self . store_global_sloppy ( name, value) ?;
824846 self . record_sloppy_global_name ( name) ;
825847 Ok ( ( ) )
826848 }
@@ -910,12 +932,14 @@ impl Vm<'_> {
910932
911933 #[ inline( never) ]
912934 fn load_local_slow ( & mut self , slot : usize ) -> Result < Value , RuntimeError > {
913- if let Some ( cell) = self . local_upvalues . get ( slot) . and_then ( Option :: as_ref)
914- && let Some ( local) = self . bytecode . locals . get ( slot)
915- && self . env . is_realm_binding_cell ( & local. name , cell)
916- && !self . realm . borrow ( ) . contains_key ( & local. name )
935+ if self . slot_is_realm_binding ( slot)
936+ && let Some ( cell) = self . local_upvalues . get ( slot) . and_then ( Option :: as_ref)
917937 {
918- let name = local. name . clone ( ) ;
938+ let value = cell. get ( ) ;
939+ if !value. is_uninitialized_lexical_marker ( ) {
940+ return Ok ( value) ;
941+ }
942+ let name = self . bytecode . locals [ slot] . name . clone ( ) ;
919943 if let Some ( value) = self . global_this_own_value ( & name) ? {
920944 return Ok ( value) ;
921945 }
@@ -1253,21 +1277,26 @@ impl Vm<'_> {
12531277 slot < u128:: BITS as usize && self . authoritative_slots & ( 1_u128 << slot) != 0
12541278 }
12551279
1280+ #[ inline( always) ]
1281+ pub ( super ) fn slot_is_realm_binding ( & self , slot : usize ) -> bool {
1282+ slot < u128:: BITS as usize && self . realm_binding_slots & ( 1_u128 << slot) != 0
1283+ }
1284+
12561285 pub ( super ) fn store_local_or_global_sloppy (
12571286 & mut self ,
12581287 slot : usize ,
1259- name : String ,
1288+ name : & str ,
12601289 value : Value ,
12611290 ) -> Result < ( ) , RuntimeError > {
1262- if self . env . has_module_import ( & name) {
1291+ if self . env . has_module_import ( name) {
12631292 return Err ( RuntimeError {
12641293 thrown : None ,
12651294 message : "TypeError: assignment to constant variable" . to_owned ( ) ,
12661295 } ) ;
12671296 }
12681297 // The inner name of a named function expression is immutable; a sloppy
12691298 // assignment to it is a silent no-op.
1270- if self . env . is_immutable_function_name ( & name) {
1299+ if self . env . is_immutable_function_name ( name) {
12711300 return Ok ( ( ) ) ;
12721301 }
12731302 let is_sloppy_global_fallback = self
@@ -1279,14 +1308,14 @@ impl Vm<'_> {
12791308 && self . locals . get ( slot) . is_some_and ( Option :: is_some)
12801309 && let Some ( Value :: Object ( global_this) ) = self . env . global_this ( )
12811310 {
1282- match global_this. write_existing_own_data_property ( & name, & value) {
1311+ match global_this. write_existing_own_data_property ( name, & value) {
12831312 OwnDataPropertyWrite :: Written => {
1284- self . invalidate_array_prototype_cache ( & name) ;
1285- if !self . env . replace_existing_realm ( & name, value. clone ( ) ) {
1286- self . env . insert_realm ( name. clone ( ) , value. clone ( ) ) ;
1313+ self . invalidate_array_prototype_cache ( name) ;
1314+ if !self . env . replace_existing_realm ( name, value. clone ( ) ) {
1315+ self . env . insert_realm ( name. to_owned ( ) , value. clone ( ) ) ;
12871316 }
12881317 self . locals [ slot] = Some ( value) ;
1289- self . sync_marked_dynamic_global ( & name) ;
1318+ self . sync_marked_dynamic_global ( name) ;
12901319 return Ok ( ( ) ) ;
12911320 }
12921321 OwnDataPropertyWrite :: ReadOnly => return Ok ( ( ) ) ,
@@ -1295,19 +1324,19 @@ impl Vm<'_> {
12951324 }
12961325 match self . locals . get ( slot) {
12971326 Some ( Some ( _) ) => {
1298- if self . local_slot_targets_non_writable_global ( slot, & name) {
1327+ if self . local_slot_targets_non_writable_global ( slot, name) {
12991328 return Ok ( ( ) ) ;
13001329 }
1301- if is_sloppy_global_fallback || self . has_realm_or_global_this_binding ( & name) {
1330+ if is_sloppy_global_fallback || self . has_realm_or_global_this_binding ( name) {
13021331 let syncs_global_snapshot = is_sloppy_global_fallback
1303- && self . captured_or_local_matches_global_this ( & name) ;
1332+ && self . captured_or_local_matches_global_this ( name) ;
13041333 if syncs_global_snapshot {
1305- self . record_sloppy_global_name ( & name) ;
1334+ self . record_sloppy_global_name ( name) ;
13061335 }
1307- self . store_realm_or_global_this_sloppy ( name. clone ( ) , value. clone ( ) ) ?;
1336+ self . store_realm_or_global_this_sloppy ( name. to_owned ( ) , value. clone ( ) ) ?;
13081337 self . store_local ( slot, value) ?;
13091338 if syncs_global_snapshot && let Some ( value) = self . locals [ slot] . clone ( ) {
1310- self . sync_global_this_own_property ( & name, value) ;
1339+ self . sync_global_this_own_property ( name, value) ;
13111340 }
13121341 } else {
13131342 self . store_local ( slot, value) ?;
@@ -1316,23 +1345,23 @@ impl Vm<'_> {
13161345 }
13171346 Some ( None ) => {
13181347 if is_sloppy_global_fallback {
1319- if self . local_slot_targets_non_writable_global ( slot, & name) {
1348+ if self . local_slot_targets_non_writable_global ( slot, name) {
13201349 return Ok ( ( ) ) ;
13211350 }
1322- let syncs_global_snapshot = self . captured_or_local_matches_global_this ( & name) ;
1351+ let syncs_global_snapshot = self . captured_or_local_matches_global_this ( name) ;
13231352 if syncs_global_snapshot {
1324- self . record_sloppy_global_name ( & name) ;
1353+ self . record_sloppy_global_name ( name) ;
13251354 }
1326- self . store_realm_or_global_this_sloppy ( name. clone ( ) , value. clone ( ) ) ?;
1355+ self . store_realm_or_global_this_sloppy ( name. to_owned ( ) , value. clone ( ) ) ?;
13271356 self . store_local ( slot, value) ?;
13281357 if syncs_global_snapshot && let Some ( value) = self . locals [ slot] . clone ( ) {
1329- self . sync_global_this_own_property ( & name, value) ;
1358+ self . sync_global_this_own_property ( name, value) ;
13301359 }
13311360 return Ok ( ( ) ) ;
13321361 }
1333- self . store_global_sloppy ( name. clone ( ) , value) ?;
1334- self . record_sloppy_global_name ( & name) ;
1335- let global_value = self . load_global ( & name) ?;
1362+ self . store_global_sloppy ( name, value) ?;
1363+ self . record_sloppy_global_name ( name) ;
1364+ let global_value = self . load_global ( name) ?;
13361365 let local = self . locals . get_mut ( slot) . ok_or_else ( || RuntimeError {
13371366 thrown : None ,
13381367 message : "bytecode local index out of bounds" . to_owned ( ) ,
0 commit comments