Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit676130f

Browse files
committed
Use refcells in frames to solve frame mutability problem.
1 parent4dd6592 commit676130f

File tree

4 files changed

+47
-61
lines changed

4 files changed

+47
-61
lines changed

‎tests/snippets/getframe.py‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ def test_function():
1111
assertsys._getframe().f_localsisnotlocals_dict
1212
assertsys._getframe().f_locals['x']==17
1313
assertsys._getframe(1).f_locals['foo']=='bar'
14-
print(sys._getframe(1).f_locals)
1514

1615
test_function()
1716

‎vm/src/frame.rs‎

Lines changed: 43 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,13 @@ enum BlockType {
4545
},
4646
}
4747

48-
#[derive(Clone)]
4948
pubstructFrame{
5049
pubcode: bytecode::CodeObject,
5150
// We need 1 stack per frame
5251
stack:RefCell<Vec<PyObjectRef>>,// The main data frame of the stack machine
53-
blocks:Vec<Block>,// Block frames, for controlling loops and exceptions
52+
blocks:RefCell<Vec<Block>>,// Block frames, for controlling loops and exceptions
5453
publocals:PyObjectRef,// Variables
55-
publasti:usize,// index of last instruction ran
54+
publasti:RefCell<usize>,// index of last instruction ran
5655
}
5756

5857
// Running a frame can result in one of the below:
@@ -80,15 +79,15 @@ impl Frame {
8079
Frame{
8180
code: objcode::get_value(&code),
8281
stack:RefCell::new(vec![]),
83-
blocks:vec![],
82+
blocks:RefCell::new(vec![]),
8483
// save the callargs as locals
8584
// globals: locals.clone(),
8685
locals,
87-
lasti:0,
86+
lasti:RefCell::new(0),
8887
}
8988
}
9089

91-
pubfnrun(&mutself,vm:&mutVirtualMachine) ->Result<ExecutionResult,PyObjectRef>{
90+
pubfnrun(&self,vm:&mutVirtualMachine) ->Result<ExecutionResult,PyObjectRef>{
9291
let filename =&self.code.source_path.to_string();
9392

9493
// This is the name of the object being run:
@@ -142,16 +141,16 @@ impl Frame {
142141
value
143142
}
144143

145-
pubfnfetch_instruction(&mutself) -> bytecode::Instruction{
144+
pubfnfetch_instruction(&self) -> bytecode::Instruction{
146145
// TODO: an immutable reference is enough, we should not
147146
// clone the instruction.
148-
let ins2 =self.code.instructions[self.lasti].clone();
149-
self.lasti +=1;
147+
let ins2 =self.code.instructions[*self.lasti.borrow()].clone();
148+
*self.lasti.borrow_mut() +=1;
150149
ins2
151150
}
152151

153152
// Execute a single instruction:
154-
fnexecute_instruction(&mutself,vm:&mutVirtualMachine) ->FrameResult{
153+
fnexecute_instruction(&self,vm:&mutVirtualMachine) ->FrameResult{
155154
let instruction =self.fetch_instruction();
156155
{
157156
trace!("=======");
@@ -344,7 +343,7 @@ impl Frame {
344343
match next_obj{
345344
Some(value) =>{
346345
// Set back program counter:
347-
self.lasti -=1;
346+
*self.lasti.borrow_mut() -=1;
348347
Ok(Some(ExecutionResult::Yield(value)))
349348
}
350349
None =>{
@@ -662,7 +661,7 @@ impl Frame {
662661
}
663662

664663
fnget_elements(
665-
&mutself,
664+
&self,
666665
vm:&mutVirtualMachine,
667666
size:usize,
668667
unpack:bool,
@@ -683,7 +682,7 @@ impl Frame {
683682
}
684683

685684
fnimport(
686-
&mutself,
685+
&self,
687686
vm:&mutVirtualMachine,
688687
module:&str,
689688
symbol:&Option<String>,
@@ -701,7 +700,7 @@ impl Frame {
701700
Ok(None)
702701
}
703702

704-
fnimport_star(&mutself,vm:&mutVirtualMachine,module:&str) ->FrameResult{
703+
fnimport_star(&self,vm:&mutVirtualMachine,module:&str) ->FrameResult{
705704
let current_path ={
706705
letmut source_pathbuf =PathBuf::from(&self.code.source_path);
707706
source_pathbuf.pop();
@@ -719,7 +718,7 @@ impl Frame {
719718
}
720719

721720
// Unwind all blocks:
722-
fnunwind_blocks(&mutself,vm:&mutVirtualMachine) ->Option<PyObjectRef>{
721+
fnunwind_blocks(&self,vm:&mutVirtualMachine) ->Option<PyObjectRef>{
723722
whileletSome(block) =self.pop_block(){
724723
match block.typ{
725724
BlockType::Loop{ ..} =>{}
@@ -743,9 +742,9 @@ impl Frame {
743742
None
744743
}
745744

746-
fnunwind_loop(&mutself,vm:&mutVirtualMachine) ->Block{
745+
fnunwind_loop(&self,vm:&mutVirtualMachine) ->Block{
747746
loop{
748-
let block =self.current_block().cloned().expect("not in a loop");
747+
let block =self.current_block().expect("not in a loop");
749748
match block.typ{
750749
BlockType::Loop{ ..} =>break block,
751750
BlockType::TryExcept{ ..} =>{
@@ -765,11 +764,7 @@ impl Frame {
765764
}
766765
}
767766

768-
fnunwind_exception(
769-
&mutself,
770-
vm:&mutVirtualMachine,
771-
exc:PyObjectRef,
772-
) ->Option<PyObjectRef>{
767+
fnunwind_exception(&self,vm:&mutVirtualMachine,exc:PyObjectRef) ->Option<PyObjectRef>{
773768
// unwind block stack on exception and find any handlers:
774769
whileletSome(block) =self.pop_block(){
775770
match block.typ{
@@ -837,13 +832,13 @@ impl Frame {
837832
vm.call_method(context_manager,"__exit__", args)
838833
}
839834

840-
fnstore_name(&mutself,vm:&mutVirtualMachine,name:&str) ->FrameResult{
835+
fnstore_name(&self,vm:&mutVirtualMachine,name:&str) ->FrameResult{
841836
let obj =self.pop_value();
842837
vm.ctx.set_attr(&self.locals, name, obj);
843838
Ok(None)
844839
}
845840

846-
fndelete_name(&mutself,vm:&mutVirtualMachine,name:&str) ->FrameResult{
841+
fndelete_name(&self,vm:&mutVirtualMachine,name:&str) ->FrameResult{
847842
let locals =matchself.locals.payload{
848843
PyObjectPayload::Scope{ref scope} => scope.borrow().locals.clone(),
849844
_ =>panic!("We really expect our scope to be a scope!"),
@@ -855,7 +850,7 @@ impl Frame {
855850
Ok(None)
856851
}
857852

858-
fnload_name(&mutself,vm:&mutVirtualMachine,name:&str) ->FrameResult{
853+
fnload_name(&self,vm:&mutVirtualMachine,name:&str) ->FrameResult{
859854
// Lookup name in scope and put it onto the stack!
860855
letmut scope =self.locals.clone();
861856
loop{
@@ -874,33 +869,33 @@ impl Frame {
874869
}
875870
}
876871

877-
fnsubscript(&mutself,vm:&mutVirtualMachine,a:PyObjectRef,b:PyObjectRef) ->PyResult{
872+
fnsubscript(&self,vm:&mutVirtualMachine,a:PyObjectRef,b:PyObjectRef) ->PyResult{
878873
vm.call_method(&a,"__getitem__",vec![b])
879874
}
880875

881-
fnexecute_store_subscript(&mutself,vm:&mutVirtualMachine) ->FrameResult{
876+
fnexecute_store_subscript(&self,vm:&mutVirtualMachine) ->FrameResult{
882877
let idx =self.pop_value();
883878
let obj =self.pop_value();
884879
let value =self.pop_value();
885880
vm.call_method(&obj,"__setitem__",vec![idx, value])?;
886881
Ok(None)
887882
}
888883

889-
fnexecute_delete_subscript(&mutself,vm:&mutVirtualMachine) ->FrameResult{
884+
fnexecute_delete_subscript(&self,vm:&mutVirtualMachine) ->FrameResult{
890885
let idx =self.pop_value();
891886
let obj =self.pop_value();
892887
vm.call_method(&obj,"__delitem__",vec![idx])?;
893888
Ok(None)
894889
}
895890

896-
fnjump(&mutself,label: bytecode::Label){
891+
fnjump(&self,label: bytecode::Label){
897892
let target_pc =self.code.label_map[&label];
898893
trace!("program counter from {:?} to {:?}",self.lasti, target_pc);
899-
self.lasti = target_pc;
894+
*self.lasti.borrow_mut() = target_pc;
900895
}
901896

902897
fnexecute_binop(
903-
&mutself,
898+
&self,
904899
vm:&mutVirtualMachine,
905900
op:&bytecode::BinaryOperator,
906901
inplace:bool,
@@ -943,11 +938,7 @@ impl Frame {
943938
Ok(None)
944939
}
945940

946-
fnexecute_unop(
947-
&mutself,
948-
vm:&mutVirtualMachine,
949-
op:&bytecode::UnaryOperator,
950-
) ->FrameResult{
941+
fnexecute_unop(&self,vm:&mutVirtualMachine,op:&bytecode::UnaryOperator) ->FrameResult{
951942
let a =self.pop_value();
952943
let value =match*op{
953944
bytecode::UnaryOperator::Minus => vm.call_method(&a,"__neg__",vec![])?,
@@ -968,7 +959,7 @@ impl Frame {
968959

969960
// https://docs.python.org/3/reference/expressions.html#membership-test-operations
970961
fn_membership(
971-
&mutself,
962+
&self,
972963
vm:&mutVirtualMachine,
973964
needle:PyObjectRef,
974965
haystack:&PyObjectRef,
@@ -978,12 +969,7 @@ impl Frame {
978969
// not implemented.
979970
}
980971

981-
fn_in(
982-
&mutself,
983-
vm:&mutVirtualMachine,
984-
needle:PyObjectRef,
985-
haystack:PyObjectRef,
986-
) ->PyResult{
972+
fn_in(&self,vm:&mutVirtualMachine,needle:PyObjectRef,haystack:PyObjectRef) ->PyResult{
987973
matchself._membership(vm, needle,&haystack){
988974
Ok(found) =>Ok(found),
989975
Err(_) =>Err(vm.new_type_error(format!(
@@ -994,7 +980,7 @@ impl Frame {
994980
}
995981

996982
fn_not_in(
997-
&mutself,
983+
&self,
998984
vm:&mutVirtualMachine,
999985
needle:PyObjectRef,
1000986
haystack:PyObjectRef,
@@ -1020,7 +1006,7 @@ impl Frame {
10201006
}
10211007

10221008
fnexecute_compare(
1023-
&mutself,
1009+
&self,
10241010
vm:&mutVirtualMachine,
10251011
op:&bytecode::ComparisonOperator,
10261012
) ->FrameResult{
@@ -1043,47 +1029,47 @@ impl Frame {
10431029
Ok(None)
10441030
}
10451031

1046-
fnload_attr(&mutself,vm:&mutVirtualMachine,attr_name:&str) ->FrameResult{
1032+
fnload_attr(&self,vm:&mutVirtualMachine,attr_name:&str) ->FrameResult{
10471033
let parent =self.pop_value();
10481034
let attr_name = vm.new_str(attr_name.to_string());
10491035
let obj = vm.get_attribute(parent, attr_name)?;
10501036
self.push_value(obj);
10511037
Ok(None)
10521038
}
10531039

1054-
fnstore_attr(&mutself,vm:&mutVirtualMachine,attr_name:&str) ->FrameResult{
1040+
fnstore_attr(&self,vm:&mutVirtualMachine,attr_name:&str) ->FrameResult{
10551041
let parent =self.pop_value();
10561042
let value =self.pop_value();
10571043
vm.ctx.set_attr(&parent, attr_name, value);
10581044
Ok(None)
10591045
}
10601046

1061-
fndelete_attr(&mutself,vm:&mutVirtualMachine,attr_name:&str) ->FrameResult{
1047+
fndelete_attr(&self,vm:&mutVirtualMachine,attr_name:&str) ->FrameResult{
10621048
let parent =self.pop_value();
10631049
let name = vm.ctx.new_str(attr_name.to_string());
10641050
vm.del_attr(&parent, name)?;
10651051
Ok(None)
10661052
}
10671053

10681054
pubfnget_lineno(&self) -> ast::Location{
1069-
self.code.locations[self.lasti].clone()
1055+
self.code.locations[*self.lasti.borrow()].clone()
10701056
}
10711057

1072-
fnpush_block(&mutself,typ:BlockType){
1073-
self.blocks.push(Block{
1058+
fnpush_block(&self,typ:BlockType){
1059+
self.blocks.borrow_mut().push(Block{
10741060
typ,
10751061
level:self.stack.borrow().len(),
10761062
});
10771063
}
10781064

1079-
fnpop_block(&mutself) ->Option<Block>{
1080-
let block =self.blocks.pop()?;
1065+
fnpop_block(&self) ->Option<Block>{
1066+
let block =self.blocks.borrow_mut().pop()?;
10811067
self.stack.borrow_mut().truncate(block.level);
10821068
Some(block)
10831069
}
10841070

1085-
fncurrent_block(&self) ->Option<&Block>{
1086-
self.blocks.last()
1071+
fncurrent_block(&self) ->Option<Block>{
1072+
self.blocks.borrow().last().cloned()
10871073
}
10881074

10891075
pubfnpush_value(&self,obj:PyObjectRef){
@@ -1094,7 +1080,7 @@ impl Frame {
10941080
self.stack.borrow_mut().pop().unwrap()
10951081
}
10961082

1097-
fnpop_multiple(&mutself,count:usize) ->Vec<PyObjectRef>{
1083+
fnpop_multiple(&self,count:usize) ->Vec<PyObjectRef>{
10981084
letmut objs:Vec<PyObjectRef> =Vec::new();
10991085
for _xin0..count{
11001086
objs.push(self.pop_value());
@@ -1123,6 +1109,7 @@ impl fmt::Debug for Frame {
11231109
.join("");
11241110
let block_str =self
11251111
.blocks
1112+
.borrow()
11261113
.iter()
11271114
.map(|elem|format!("\n > {:?}", elem))
11281115
.collect::<Vec<_>>()

‎vm/src/obj/objframe.rs‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,12 @@ fn frame_flocals(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
4141

4242
fnframe_fcode(vm:&mutVirtualMachine,args:PyFuncArgs) ->PyResult{
4343
arg_check!(vm, args, required =[(frame,Some(vm.ctx.frame_type()))]);
44-
Ok(vm.ctx.new_code_object(get_value(frame).code))
44+
Ok(vm.ctx.new_code_object(get_value(frame).code.clone()))
4545
}
4646

47-
pubfnget_value(obj:&PyObjectRef) ->Frame{
47+
pubfnget_value(obj:&PyObjectRef) ->&Frame{
4848
ifletPyObjectPayload::Frame{ frame} =&obj.payload{
49-
frame.clone()
49+
frame
5050
}else{
5151
panic!("Inner error getting int {:?}", obj);
5252
}

‎vm/src/vm.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ impl VirtualMachine {
8282

8383
pubfnrun_frame(&mutself,frame:PyObjectRef) ->Result<ExecutionResult,PyObjectRef>{
8484
self.frames.push(frame.clone());
85-
letmutframe = objframe::get_value(&frame);
85+
let frame = objframe::get_value(&frame);
8686
let result = frame.run(self);
8787
self.frames.pop();
8888
result

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp