-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Use an array instead of a dict for local variables #2355
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@@ -668,17 +669,24 @@ impl<C: Constant> CodeObject<C> { | |||
} | |||
|
|||
pub fn map_bag<Bag: ConstantBag>(self, bag: &Bag) -> CodeObject<Bag::Constant> { | |||
let map_names = |names: Box<[C::Name]>| { | |||
names | |||
.into_vec() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
compiler/src/symboltable.rs
Outdated
} | ||
} | ||
impl<T> StackStack<T> { | ||
pub fn append<F, R>(&mut self, x: &mut T, f: F) -> R |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function itself seems like not appending something but the given f
do that, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I wasn't totally sure on the naming, cause this is kinda a weird data structure. It calls f()
in the context of x
being appended to the stack; f can append more once inside that context but append
is the one that actually calls push and pop. 🤷
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure how to call this but at lease append
gives wrong sense of the role of the method. Giving something weird or long name might be better than append.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed it to with_append
and added a doc comment.
vm/src/dictdatatype.rs
Outdated
@@ -275,6 +284,20 @@ impl<T: Clone> Dict<T> { | |||
Ok(ret) | |||
} | |||
|
|||
pub fn get2<K: DictKey>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
get2
doesn't look like the best name for this.
This is a sort of chained get and only used by frame.rs. I think these things implies this is not an expected feature as a method.
How about exposing _get_inner
as get_raw
(or somewhat common term in hash map libraries) as its low-level api and making a helper funciton in frame.rs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I renamed it get_chain; I could make it pub(crate)
if you want, but I think it's best to keep the dict implementation in the dict implementation- builtins::dict
already has all the logic regarding exact instance vs subclass checking, so I think it makes sense to keep it there rather than move it to frame
.
let scope = if self.code.flags.contains(bytecode::CodeFlags::NEW_LOCALS) { | ||
scope.new_child_scope(&vm.ctx) | ||
let locals = if self.code.flags.contains(bytecode::CodeFlags::NEW_LOCALS) { | ||
vm.ctx.new_dict() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what if locals is given but the flag is NEW_LOCALS? locals looks like not used in this case.
Is this possible scenario?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the cpython code for this basically ignores the passed locals
if that happens:
/* Most functions have CO_NEWLOCALS and CO_OPTIMIZED set. */
if ((code->co_flags & (CO_NEWLOCALS | CO_OPTIMIZED)) ==
(CO_NEWLOCALS | CO_OPTIMIZED))
; /* f_locals = NULL; will be set by PyFrame_FastToLocals() */
else if (code->co_flags & CO_NEWLOCALS) {
locals = PyDict_New();
if (locals == NULL) {
Py_DECREF(f);
return NULL;
}
f->f_locals = locals;
}
else {
if (locals == NULL)
locals = globals;
Py_INCREF(locals);
f->f_locals = locals;
}
if let Some(x) = self._get_inner(vm, key, hash)? { | ||
Ok(Some(x)) | ||
} else { | ||
other._get_inner(vm, key, hash) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if let Some(x) = self._get_inner(vm, key, hash)? { | |
Ok(Some(x)) | |
} else { | |
other._get_inner(vm, key, hash) | |
} | |
self._get_inner(vm, key, hash).or_else(|| other._get_inner(vm, key, hash)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
get_inner
returns Result<Option>
, I think if we wanted to use combinators it would be a bunch of transpose()
calls so I figured this would be the cleanest way to do it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, yep. I missed Result
. But not sure about transpose()
because Result is unwrappable.
How about this?
Ok(self._get_inner(vm, key, hash)?.or_else(|| other._get_inner(vm, key, hash)?))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ?
inside the or_else wouldn't return from the outer function, it would return from the closure
ed81105
to
217f2c3
Compare
217f2c3
to
04d50da
Compare
04d50da
to
34bb5f0
Compare
Didn't get as much of a speedup as I was hoping for, but this should improve memory usage. Specifically, I was running into a problem where closures defined in a function would never get deallocated so it would really slow down after like 50 iterations. I think this should fix that, since now it's just a cell. It entire scope being kept around, including the function itself (
locals()['bar'].outer_locals is locals()
), making a reference cycle that would never dealloc.I wasn't able to get it to cause a slowdown on my machine with the master branch version of the binary, but the real code that this was happening with runs in wasm, so I assume that has something to do with it.
Edit: Oh, duh, here: