Commit c9598857 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Different approach for tracking ic gc references

1) instead of hooking loadConst to automatically find GC references,
   add an API for specifically saying that a reference needs to be tracked
   (I think/hope there aren't more that do this)
2) change the way we store the gc references so that it's O(#references) to
   scan them instead of O(#ics).
parent adb9ad0c
......@@ -84,6 +84,9 @@ uint8_t* ICSlotRewrite::getSlotStart() {
return (uint8_t*)ic->start_addr + ic_entry->idx * ic->getSlotSize();
}
// Map of gc pointers -> number of ics that point tot hem.
static llvm::DenseMap<void*, int> ic_gc_references;
void ICSlotRewrite::commit(CommitHook* hook, std::vector<void*> gc_references) {
bool still_valid = true;
for (int i = 0; i < dependencies.size(); i++) {
......@@ -120,7 +123,16 @@ void ICSlotRewrite::commit(CommitHook* hook, std::vector<void*> gc_references) {
// if (VERBOSITY()) printf("Commiting to %p-%p\n", start, start + ic->slot_size);
memcpy(slot_start, buf, ic->getSlotSize());
for (auto p : ic_entry->gc_references) {
int& i = ic_gc_references[p];
if (i == 1)
ic_gc_references.erase(p);
else
--i;
}
ic_entry->gc_references = std::move(gc_references);
for (auto p : ic_entry->gc_references)
ic_gc_references[p]++;
ic->times_rewritten++;
......@@ -344,10 +356,15 @@ bool ICInfo::isMegamorphic() {
}
void ICInfo::visitGCReferences(gc::GCVisitor* v) {
for (auto&& p : ic_gc_references) {
v->visitNonRelocatable(p.first);
}
#if MOVING_GC
for (const auto& p : ics_list) {
for (auto& slot : p->slots) {
v->visitNonRelocatableRange(&slot.gc_references[0], &slot.gc_references[slot.gc_references.size()]);
}
}
#endif
}
}
......@@ -716,6 +716,11 @@ void Rewriter::_trap() {
assembler->trap();
}
void Rewriter::addGCReference(void* obj) {
assert(gc::isValidGCObject(obj));
gc_references.push_back(obj);
}
RewriterVar* Rewriter::loadConst(int64_t val, Location dest) {
STAT_TIMER(t0, "us_timer_rewriter", 10);
......
......@@ -554,6 +554,11 @@ public:
const char* debugName() { return rewrite->debugName(); }
// Register that this rewrite will embed a reference to a particular gc object.
// TODO: come up with an implementation that is performant enough that we can automatically
// infer these from loadConst calls.
void addGCReference(void* obj);
void trap();
RewriterVar* loadConst(int64_t val, Location loc = Location::any());
// has_side_effects: whether this call could have "side effects". the exact side effects we've
......
......@@ -546,8 +546,8 @@ static void visitRoots(GCVisitor& visitor) {
}
GC_TRACE_LOG("Looking at generated code pointers\n");
#if MOVING_GC
ICInfo::visitGCReferences(&visitor);
#if MOVING_GC
CompiledFunction::visitAllCompiledFunctions(&visitor);
#endif
}
......
......@@ -532,8 +532,15 @@ Box* getattrFuncInternal(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args,
// value is fixed.
if (!PyString_CheckExact(_str) && !PyUnicode_CheckExact(_str))
rewrite_args = NULL;
else
else {
if (PyString_CheckExact(_str) && PyString_CHECK_INTERNED(_str) == SSTATE_INTERNED_IMMORTAL) {
// can avoid keeping the extra gc reference
} else {
rewrite_args->rewriter->addGCReference(_str);
}
rewrite_args->arg2->addGuard((intptr_t)arg2);
}
}
try {
......
# Regression test: make sure we guard / invalidate our getattr() rewrites:
class C(object):
pass
c = C()
for i in xrange(100):
setattr(c, "attr%d" % i, i)
def f():
for j in xrange(2, 10):
t = 0
for i in xrange(2000):
for k in xrange(j):
t += getattr(c, "attr%d" % k)
print t
f()
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