Commit 206871bb authored by Kevin Modzelewski's avatar Kevin Modzelewski

Fix pyElements refcounting

parent 5692db49
...@@ -562,18 +562,7 @@ public: ...@@ -562,18 +562,7 @@ public:
BoxIteratorImpl* impl; BoxIteratorImpl* impl;
BoxIterator(BoxIteratorImpl* impl) : impl(impl) {} BoxIterator(BoxIteratorImpl* impl) : impl(impl) {}
BoxIterator(const BoxIterator& rhs) = default;
BoxIterator(BoxIterator&& rhs) {
impl = rhs.impl;
rhs.impl = NULL;
}
~BoxIterator() {
if (impl)
impl->~BoxIteratorImpl();
}
static llvm::iterator_range<BoxIterator> getRange(Box* container);
bool operator==(BoxIterator const& rhs) const { return impl->isSame(rhs.impl); } bool operator==(BoxIterator const& rhs) const { return impl->isSame(rhs.impl); }
bool operator!=(BoxIterator const& rhs) const { return !(*this == rhs); } bool operator!=(BoxIterator const& rhs) const { return !(*this == rhs); }
...@@ -586,6 +575,23 @@ public: ...@@ -586,6 +575,23 @@ public:
Box* operator*() { return impl->getValue(); } Box* operator*() { return impl->getValue(); }
}; };
// A custom "range" container that helps manage lifetimes. We need to free the underlying Impl object
// when the range loop is done; previously we had the iterator itself handle this, but that started
// to get complicated since they get copied around, and the management of the begin() and end() iterators
// is slightly different.
// So to simplify, have the range object take care of it.
class BoxIteratorRange {
private:
std::unique_ptr<BoxIteratorImpl> begin_impl;
BoxIteratorImpl* end_impl;
public:
BoxIteratorRange(std::unique_ptr<BoxIteratorImpl> begin, BoxIteratorImpl* end)
: begin_impl(std::move(begin)), end_impl(end) {}
BoxIterator begin() { return BoxIterator(begin_impl.get()); }
BoxIterator end() { return BoxIterator(end_impl); }
};
class HiddenClass; class HiddenClass;
extern HiddenClass* root_hcls; extern HiddenClass* root_hcls;
...@@ -676,7 +682,7 @@ public: ...@@ -676,7 +682,7 @@ public:
// Note: cls gets initialized in the new() function. // Note: cls gets initialized in the new() function.
BoxedClass* cls; BoxedClass* cls;
llvm::iterator_range<BoxIterator> pyElements(); BoxIteratorRange pyElements();
// For instances with hc attrs: // For instances with hc attrs:
size_t getHCAttrsOffset(); size_t getHCAttrsOffset();
......
...@@ -1195,13 +1195,13 @@ Box* zip(BoxedTuple* containers) { ...@@ -1195,13 +1195,13 @@ Box* zip(BoxedTuple* containers) {
if (containers->size() == 0) if (containers->size() == 0)
return rtn; return rtn;
std::vector<llvm::iterator_range<BoxIterator>> ranges; std::vector<BoxIteratorRange> ranges;
for (auto container : *containers) { for (auto container : *containers) {
ranges.push_back(container->pyElements()); ranges.push_back(container->pyElements());
} }
std::vector<BoxIterator> iterators; std::vector<BoxIterator> iterators;
for (auto range : ranges) { for (auto&& range : ranges) {
iterators.push_back(range.begin()); iterators.push_back(range.begin());
} }
...@@ -1307,13 +1307,14 @@ static BoxedClass* makeBuiltinException(BoxedClass* base, const char* name, int ...@@ -1307,13 +1307,14 @@ static BoxedClass* makeBuiltinException(BoxedClass* base, const char* name, int
BoxedClass* enumerate_cls; BoxedClass* enumerate_cls;
class BoxedEnumerate : public Box { class BoxedEnumerate : public Box {
private: private:
BoxIteratorRange range;
BoxIterator iterator, iterator_end; BoxIterator iterator, iterator_end;
int64_t idx; int64_t idx;
BoxedLong* idx_long; BoxedLong* idx_long;
public: public:
BoxedEnumerate(BoxIterator iterator_begin, BoxIterator iterator_end, int64_t idx, BoxedLong* idx_long) BoxedEnumerate(BoxIteratorRange range, int64_t idx, BoxedLong* idx_long)
: iterator(iterator_begin), iterator_end(iterator_end), idx(idx), idx_long(idx_long) {} : range(std::move(range)), iterator(range.begin()), iterator_end(range.end()), idx(idx), idx_long(idx_long) {}
DEFAULT_CLASS(enumerate_cls); DEFAULT_CLASS(enumerate_cls);
...@@ -1327,8 +1328,8 @@ public: ...@@ -1327,8 +1328,8 @@ public:
assert(PyLong_Check(start)); assert(PyLong_Check(start));
idx_long = (BoxedLong*)start; idx_long = (BoxedLong*)start;
} }
llvm::iterator_range<BoxIterator> range = obj->pyElements(); auto&& range = obj->pyElements();
return new BoxedEnumerate(range.begin(), range.end(), idx, idx_long); return new BoxedEnumerate(std::move(range), idx, idx_long);
} }
static Box* iter(Box* _self) noexcept { static Box* iter(Box* _self) noexcept {
......
...@@ -99,8 +99,23 @@ public: ...@@ -99,8 +99,23 @@ public:
} }
} }
BoxIteratorIndex(const BoxIteratorIndex& rhs) : obj(rhs.obj), index(rhs.index) { Py_XINCREF(obj); }
BoxIteratorIndex(BoxIteratorIndex&& rhs) : obj(rhs.obj), index(rhs.index) { Py_XINCREF(obj); }
BoxIteratorIndex& operator=(const BoxIteratorIndex& rhs) {
obj = rhs.obj;
index = rhs.index;
Py_XINCREF(obj);
return *this;
}
BoxIteratorIndex& operator=(BoxIteratorIndex&& rhs) {
obj = rhs.obj;
index = rhs.index;
Py_XINCREF(obj);
return *this;
}
~BoxIteratorIndex() { ~BoxIteratorIndex() {
Py_XDECREF(obj); Py_CLEAR(obj);
} }
void next() override { void next() override {
...@@ -130,25 +145,26 @@ public: ...@@ -130,25 +145,26 @@ public:
}; };
} }
llvm::iterator_range<BoxIterator> BoxIterator::getRange(Box* container) { BoxIteratorRange Box::pyElements() {
if (container->cls == list_cls) { if (this->cls == list_cls) {
using BoxIteratorList = BoxIteratorIndex<BoxedList>; using BoxIteratorList = BoxIteratorIndex<BoxedList>;
BoxIterator begin = new BoxIteratorList((BoxedList*)container); std::unique_ptr<BoxIteratorImpl> begin(new BoxIteratorList((BoxedList*)this));
BoxIterator end = BoxIteratorList::end(); BoxIteratorImpl* end = BoxIteratorList::end();
return llvm::iterator_range<BoxIterator>(std::move(begin), end); return BoxIteratorRange(std::move(begin), end);
} else if (container->cls == tuple_cls) { } else if (this->cls == tuple_cls) {
using BoxIteratorTuple = BoxIteratorIndex<BoxedTuple>; using BoxIteratorTuple = BoxIteratorIndex<BoxedTuple>;
BoxIterator begin = new BoxIteratorTuple((BoxedTuple*)container); std::unique_ptr<BoxIteratorImpl> begin(new BoxIteratorTuple((BoxedTuple*)this));
BoxIterator end = BoxIteratorTuple::end(); BoxIteratorImpl* end = BoxIteratorTuple::end();
return llvm::iterator_range<BoxIterator>(std::move(begin), end); return BoxIteratorRange(std::move(begin), end);
} else if (container->cls == str_cls) { } else if (this->cls == str_cls) {
using BoxIteratorString = BoxIteratorIndex<BoxedString>; using BoxIteratorString = BoxIteratorIndex<BoxedString>;
BoxIterator begin = new BoxIteratorString((BoxedString*)container); std::unique_ptr<BoxIteratorImpl> begin(new BoxIteratorString((BoxedString*)this));
BoxIterator end = BoxIteratorString::end(); BoxIteratorImpl* end = BoxIteratorString::end();
return llvm::iterator_range<BoxIterator>(std::move(begin), end); return BoxIteratorRange(std::move(begin), end);
} else {
std::unique_ptr<BoxIteratorImpl> begin(new BoxIteratorGeneric(this));
BoxIteratorImpl* end = BoxIteratorGeneric::end();
return BoxIteratorRange(std::move(begin), end);
} }
BoxIterator begin = new BoxIteratorGeneric(container);
BoxIterator end = BoxIteratorGeneric::end();
return llvm::iterator_range<BoxIterator>(std::move(begin), end);
} }
} }
...@@ -6283,10 +6283,6 @@ Box* getiter(Box* o) { ...@@ -6283,10 +6283,6 @@ Box* getiter(Box* o) {
return getiterHelper(o); return getiterHelper(o);
} }
llvm::iterator_range<BoxIterator> Box::pyElements() {
return BoxIterator::getRange(this);
}
void assertValidSlotIdentifier(Box* s) { void assertValidSlotIdentifier(Box* s) {
// Ported from `valid_identifier` in cpython // Ported from `valid_identifier` in cpython
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment