@@ -99,7 +99,7 @@ pub struct Frame {
99
99
100
100
pub fastlocals : PyMutex < Box < [ Option < PyObjectRef > ] > > ,
101
101
pub ( crate ) cells_frees : Box < [ PyCellRef ] > ,
102
- pub locals : PyDictRef ,
102
+ pub locals : PyObjectRef ,
103
103
pub globals : PyDictRef ,
104
104
pub builtins : PyDictRef ,
105
105
@@ -179,7 +179,7 @@ impl FrameRef {
179
179
f ( exec)
180
180
}
181
181
182
- pub fn locals ( & self , vm : & VirtualMachine ) -> PyResult < PyDictRef > {
182
+ pub fn locals ( & self , vm : & VirtualMachine ) -> PyResult < PyObjectRef > {
183
183
let locals = & self . locals ;
184
184
let code = & * * self . code ;
185
185
let map = & code. varnames ;
@@ -275,7 +275,7 @@ struct ExecutingFrame<'a> {
275
275
code : & ' a PyRef < PyCode > ,
276
276
fastlocals : & ' a PyMutex < Box < [ Option < PyObjectRef > ] > > ,
277
277
cells_frees : & ' a [ PyCellRef ] ,
278
- locals : & ' a PyDictRef ,
278
+ locals : & ' a PyObjectRef ,
279
279
globals : & ' a PyDictRef ,
280
280
builtins : & ' a PyDictRef ,
281
281
object : & ' a FrameRef ,
@@ -496,12 +496,15 @@ impl ExecutingFrame<'_> {
496
496
}
497
497
bytecode:: Instruction :: LoadNameAny ( idx) => {
498
498
let name = & self . code . names [ * idx as usize ] ;
499
- let x = self . locals . get_item_option ( name. clone ( ) , vm) ?;
500
- let x = match x {
499
+ // Try using locals as dict first, if not, fallback to generic method.
500
+ let x = match self . locals . clone ( ) . downcast_exact :: < PyDict > ( vm) {
501
+ Ok ( d) => d. get_item_option ( name. clone ( ) , vm) ?,
502
+ Err ( o) => o. get_item ( name. clone ( ) , vm) . ok ( ) ,
503
+ } ;
504
+ self . push_value ( match x {
501
505
Some ( x) => x,
502
506
None => self . load_global_or_builtin ( name, vm) ?,
503
- } ;
504
- self . push_value ( x) ;
507
+ } ) ;
505
508
Ok ( None )
506
509
}
507
510
bytecode:: Instruction :: LoadGlobal ( idx) => {
@@ -521,14 +524,17 @@ impl ExecutingFrame<'_> {
521
524
bytecode:: Instruction :: LoadClassDeref ( i) => {
522
525
let i = * i as usize ;
523
526
let name = self . code . freevars [ i - self . code . cellvars . len ( ) ] . clone ( ) ;
524
- let value = if let Some ( value) = self . locals . get_item_option ( name, vm) ? {
525
- value
526
- } else {
527
- self . cells_frees [ i]
528
- . get ( )
529
- . ok_or_else ( || self . unbound_cell_exception ( i, vm) ) ?
527
+ // Try using locals as dict first, if not, fallback to generic method.
528
+ let value = match self . locals . clone ( ) . downcast_exact :: < PyDict > ( vm) {
529
+ Ok ( d) => d. get_item_option ( name, vm) ?,
530
+ Err ( o) => o. get_item ( name, vm) . ok ( ) ,
530
531
} ;
531
- self . push_value ( value) ;
532
+ self . push_value ( match value {
533
+ Some ( v) => v,
534
+ None => self . cells_frees [ i]
535
+ . get ( )
536
+ . ok_or_else ( || self . unbound_cell_exception ( i, vm) ) ?,
537
+ } ) ;
532
538
Ok ( None )
533
539
}
534
540
bytecode:: Instruction :: StoreFast ( idx) => {
@@ -717,7 +723,15 @@ impl ExecutingFrame<'_> {
717
723
}
718
724
bytecode:: Instruction :: YieldFrom => self . execute_yield_from ( vm) ,
719
725
bytecode:: Instruction :: SetupAnnotation => {
720
- if !self . locals . contains_key ( "__annotations__" , vm) {
726
+ // Try using locals as dict first, if not, fallback to generic method.
727
+ let has_annotations = match self . locals . clone ( ) . downcast_exact :: < PyDict > ( vm) {
728
+ Ok ( d) => d. contains_key ( "__annotations__" , vm) ,
729
+ Err ( o) => {
730
+ let needle = vm. new_pyobj ( "__annotations__" ) ;
731
+ self . _in ( vm, needle, o) ?
732
+ }
733
+ } ;
734
+ if !has_annotations {
721
735
self . locals
722
736
. set_item ( "__annotations__" , vm. ctx . new_dict ( ) . into ( ) , vm) ?;
723
737
}
@@ -1822,15 +1836,11 @@ impl fmt::Debug for Frame {
1822
1836
. map ( |elem| format ! ( "\n > {:?}" , elem) )
1823
1837
. collect :: < String > ( ) ;
1824
1838
// TODO: fix this up
1825
- let dict = self . locals . clone ( ) ;
1826
- let local_str = dict
1827
- . into_iter ( )
1828
- . map ( |elem| format ! ( "\n {:?} = {:?}" , elem. 0 , elem. 1 ) )
1829
- . collect :: < String > ( ) ;
1839
+ let locals = self . locals . clone ( ) ;
1830
1840
write ! (
1831
1841
f,
1832
- "Frame Object {{ \n Stack:{}\n Blocks:{}\n Locals:{}\n }}" ,
1833
- stack_str, block_str, local_str
1842
+ "Frame Object {{ \n Stack:{}\n Blocks:{}\n Locals:{:? }\n }}" ,
1843
+ stack_str, block_str, locals
1834
1844
)
1835
1845
}
1836
1846
}
0 commit comments