extern "C" Box* listSetitemSlice(BoxedList* self, BoxedSlice* slice, Box* v) { LOCK_REGION(self->lock.asWrite()); assert(self->cls == list_cls); assert(slice->cls == slice_cls); i64 start, stop, step; parseSlice(slice, self->size, &start, &stop, &step); RELEASE_ASSERT(step == 1, "step sizes must be 1 for now"); assert(0 <= start && start < self->size); ASSERT(0 <= stop && stop <= self->size, "%ld %ld", self->size, stop); assert(start <= stop); ASSERT(v->cls == list_cls, "unsupported %s", getTypeName(v)->c_str()); BoxedList* lv = static_cast<BoxedList*>(v); int delts = lv->size - (stop - start); int remaining_elts = self->size - stop; self->ensure(delts); memmove(self->elts->elts + start + lv->size, self->elts->elts + stop, remaining_elts * sizeof(Box*)); for (int i = 0; i < lv->size; i++) { Box* r = lv->elts->elts[i]; self->elts->elts[start + i] = r; } self->size += delts; return None; }
void* compilePartialFunc(OSRExit* exit) { LOCK_REGION(codegen_rwlock.asWrite()); assert(exit); assert(exit->parent_cf); assert(exit->parent_cf->effort < EffortLevel::MAXIMAL); stat_osrexits.log(); // if (VERBOSITY("irgen") >= 1) printf("In compilePartialFunc, handling %p\n", exit); assert(exit->parent_cf->clfunc); CompiledFunction*& new_cf = exit->parent_cf->clfunc->osr_versions[exit->entry]; if (new_cf == NULL) { EffortLevel::EffortLevel new_effort = EffortLevel::MAXIMAL; if (exit->parent_cf->effort == EffortLevel::INTERPRETED) new_effort = EffortLevel::MINIMAL; // EffortLevel::EffortLevel new_effort = (EffortLevel::EffortLevel)(exit->parent_cf->effort + 1); // new_effort = EffortLevel::MAXIMAL; CompiledFunction* compiled = compileFunction(exit->parent_cf->clfunc, exit->parent_cf->spec, new_effort, exit->entry); assert(compiled = new_cf); } return new_cf->code; }
extern "C" Box* listInsert(BoxedList* self, Box* idx, Box* v) { if (idx->cls != int_cls) { raiseExcHelper(TypeError, "an integer is required"); } LOCK_REGION(self->lock.asWrite()); int64_t n = static_cast<BoxedInt*>(idx)->n; if (n < 0) n = self->size + n; if (n >= self->size) { listAppendInternal(self, v); } else { if (n < 0) n = 0; assert(0 <= n && n < self->size); self->ensure(1); memmove(self->elts->elts + n + 1, self->elts->elts + n, (self->size - n) * sizeof(Box*)); self->size++; self->elts->elts[n] = v; } return None; }
void compileAndRunModule(AST_Module* m, BoxedModule* bm) { CompiledFunction* cf; { // scope for limiting the locked region: LOCK_REGION(codegen_rwlock.asWrite()); Timer _t("for compileModule()"); bm->future_flags = getFutureFlags(m, bm->fn.c_str()); ScopingAnalysis* scoping = runScopingAnalysis(m); SourceInfo* si = new SourceInfo(bm, scoping, m, m->body); si->cfg = computeCFG(si, m->body); si->liveness = computeLivenessInfo(si->cfg); si->phis = computeRequiredPhis(si->arg_names, si->cfg, si->liveness, si->getScopeInfo()); CLFunction* cl_f = new CLFunction(0, 0, false, false, si); EffortLevel::EffortLevel effort = initialEffort(); cf = compileFunction(cl_f, new FunctionSpecialization(VOID), effort, NULL); assert(cf->clfunc->versions.size()); } if (cf->is_interpreted) interpretFunction(cf->func, 0, NULL, NULL, NULL, NULL, NULL, NULL); else ((void (*)())cf->code)(); }
extern "C" Box* listPop(BoxedList* self, Box* idx) { LOCK_REGION(self->lock.asWrite()); if (idx == None) { if (self->size == 0) { raiseExcHelper(IndexError, "pop from empty list"); } self->size--; Box* rtn = self->elts->elts[self->size]; return rtn; } if (idx->cls != int_cls) { raiseExcHelper(TypeError, "an integer is required"); } int64_t n = static_cast<BoxedInt*>(idx)->n; if (n < 0) n = self->size + n; if (n < 0 || n >= self->size) { if (self->size == 0) fprintf(stderr, "IndexError: pop from empty list\n"); else fprintf(stderr, "IndexError: pop index out of range\n"); raiseExcHelper(IndexError, ""); } Box* rtn = self->elts->elts[n]; memmove(self->elts->elts + n, self->elts->elts + n + 1, (self->size - n - 1) * sizeof(Box*)); self->size--; return rtn; }
Box* listSort1(BoxedList* self) { LOCK_REGION(self->lock.asWrite()); assert(self->cls == list_cls); std::sort<Box**, PyLt>(self->elts->elts, self->elts->elts + self->size, PyLt()); return None; }
extern "C" Box* listGetitemSlice(BoxedList* self, BoxedSlice* slice) { LOCK_REGION(self->lock.asRead()); assert(self->cls == list_cls); assert(slice->cls == slice_cls); i64 start, stop, step, length; parseSlice(slice, self->size, &start, &stop, &step, &length); return _listSlice(self, start, stop, step, length); }
Box* listNe(BoxedList* self, Box* rhs) { if (rhs->cls != list_cls) { return NotImplemented; } LOCK_REGION(self->lock.asRead()); return _listCmp(self, static_cast<BoxedList*>(rhs), AST_TYPE::NotEq); }
Box* listReverse(BoxedList* self) { LOCK_REGION(self->lock.asWrite()); assert(self->cls == list_cls); for (int i = 0, j = self->size - 1; i < j; i++, j--) { Box* e = self->elts->elts[i]; self->elts->elts[i] = self->elts->elts[j]; self->elts->elts[j] = e; } return None; }
extern "C" Box* listSetitemSlice(BoxedList* self, BoxedSlice* slice, Box* v) { LOCK_REGION(self->lock.asWrite()); assert(self->cls == list_cls); assert(slice->cls == slice_cls); i64 start = 0, stop = self->size, step = 1; sliceIndex(slice->start, &start); sliceIndex(slice->stop, &stop); sliceIndex(slice->step, &step); RELEASE_ASSERT(step == 1, "step sizes must be 1 for now"); // Logic from PySequence_GetSlice: if (start < 0) start += self->size; if (stop < 0) stop += self->size; // Logic from list_ass_slice: if (start < 0) start = 0; else if (start > self->size) start = self->size; if (stop < start) stop = start; else if (stop > self->size) stop = self->size; assert(0 <= start && start <= stop && stop <= self->size); RELEASE_ASSERT(v->cls == list_cls, "unsupported %s", getTypeName(v)->c_str()); BoxedList* lv = static_cast<BoxedList*>(v); RELEASE_ASSERT(self->elts != lv->elts, "Slice self-assignment currently unsupported"); int delts = lv->size - (stop - start); int remaining_elts = self->size - stop; self->ensure(delts); memmove(self->elts->elts + start + lv->size, self->elts->elts + stop, remaining_elts * sizeof(Box*)); for (int i = 0; i < lv->size; i++) { Box* r = lv->elts->elts[i]; self->elts->elts[start + i] = r; } self->size += delts; return None; }
extern "C" Box* listGetitemUnboxed(BoxedList* self, int64_t n) { LOCK_REGION(self->lock.asRead()); assert(self->cls == list_cls); if (n < 0) n = self->size + n; if (n < 0 || n >= self->size) { raiseExcHelper(IndexError, "list index out of range"); } Box* rtn = self->elts->elts[n]; return rtn; }
Box* listContains(BoxedList* self, Box* elt) { LOCK_REGION(self->lock.asRead()); int size = self->size; for (int i = 0; i < size; i++) { Box* e = self->elts->elts[i]; Box* cmp = compareInternal(e, elt, AST_TYPE::Eq, NULL); bool b = nonzero(cmp); if (b) return True; } return False; }
extern "C" Box* listDelitemInt(BoxedList* self, BoxedInt* slice) { LOCK_REGION(self->lock.asWrite()); int64_t n = slice->n; if (n < 0) n = self->size + n; if (n < 0 || n >= self->size) { raiseExcHelper(IndexError, "list index out of range"); } memmove(self->elts->elts + n, self->elts->elts + n + 1, (self->size - n - 1) * sizeof(Box*)); self->size--; return None; }
SmallArena::ThreadBlockCache::~ThreadBlockCache() { LOCK_REGION(heap->lock); for (int i = 0; i < NUM_BUCKETS; i++) { while (Block* b = cache_free_heads[i]) { removeFromLLAndNull(b); insertIntoLL(&small->heads[i], b); } while (Block* b = cache_full_heads[i]) { removeFromLLAndNull(b); insertIntoLL(&small->full_heads[i], b); } } }
extern "C" Box* listDelitem(BoxedList* self, Box* slice) { LOCK_REGION(self->lock.asWrite()); Box* rtn; if (isSubclass(slice->cls, int_cls)) { rtn = listDelitemInt(self, static_cast<BoxedInt*>(slice)); } else if (slice->cls == slice_cls) { rtn = listDelitemSlice(self, static_cast<BoxedSlice*>(slice)); } else { raiseExcHelper(TypeError, "list indices must be integers, not %s", getTypeName(slice)->c_str()); } self->shrink(); return rtn; }
Box* listCount(BoxedList* self, Box* elt) { LOCK_REGION(self->lock.asRead()); int size = self->size; int count = 0; for (int i = 0; i < size; i++) { Box* e = self->elts->elts[i]; Box* cmp = compareInternal(e, elt, AST_TYPE::Eq, NULL); bool b = nonzero(cmp); if (b) count++; } return boxInt(count); }
GCAllocation* LargeArena::alloc(size_t size) { registerGCManagedBytes(size); LOCK_REGION(heap->lock); // printf ("allocLarge %zu\n", size); LargeObj* obj = _alloc(size + sizeof(GCAllocation) + sizeof(LargeObj)); obj->size = size; nullNextPrev(obj); insertIntoLL(&head, obj); return obj->data; }
Box* listIndex(BoxedList* self, Box* elt) { LOCK_REGION(self->lock.asRead()); int size = self->size; for (int i = 0; i < size; i++) { Box* e = self->elts->elts[i]; Box* cmp = compareInternal(e, elt, AST_TYPE::Eq, NULL); bool b = nonzero(cmp); if (b) return boxInt(i); } BoxedString* tostr = static_cast<BoxedString*>(repr(elt)); raiseExcHelper(ValueError, "%s is not in list", tostr->s.c_str()); }
extern "C" Box* listRepr(BoxedList* self) { LOCK_REGION(self->lock.asRead()); // TODO highly inefficient with all the string copying std::ostringstream os; os << '['; for (int i = 0; i < self->size; i++) { if (i > 0) os << ", "; BoxedString* s = static_cast<BoxedString*>(self->elts->elts[i]->reprIC()); os << s->s; } os << ']'; return new BoxedString(os.str()); }
extern "C" Box* listSetitemInt(BoxedList* self, BoxedInt* slice, Box* v) { // I think r lock is ok here, since we don't change the list structure: LOCK_REGION(self->lock.asRead()); assert(self->cls == list_cls); assert(isSubclass(slice->cls, int_cls)); int64_t n = slice->n; if (n < 0) n = self->size + n; if (n < 0 || n >= self->size) { raiseExcHelper(IndexError, "list index out of range"); } self->elts->elts[n] = v; return None; }
Box* listIAdd(BoxedList* self, Box* _rhs) { if (_rhs->cls != list_cls) { raiseExcHelper(TypeError, "can only concatenate list (not \"%s\") to list", getTypeName(_rhs)->c_str()); } LOCK_REGION(self->lock.asWrite()); BoxedList* rhs = static_cast<BoxedList*>(_rhs); int s1 = self->size; int s2 = rhs->size; self->ensure(s1 + s2); memcpy(self->elts->elts + s1, rhs->elts->elts, sizeof(rhs->elts->elts[0]) * s2); self->size = s1 + s2; return self; }
extern "C" Box* listDelitemSlice(BoxedList* self, BoxedSlice* slice) { LOCK_REGION(self->lock.asWrite()); i64 start, stop, step; parseSlice(slice, self->size, &start, &stop, &step); RELEASE_ASSERT(step == 1, "step sizes must be 1 for now"); assert(0 <= start && start < self->size); ASSERT(0 <= stop && stop <= self->size, "%ld %ld", self->size, stop); assert(start <= stop); int remaining_elts = self->size - stop; memmove(self->elts->elts + start, self->elts->elts + stop, remaining_elts * sizeof(Box*)); self->size -= (stop - start); return None; }
GCAllocation* SmallArena::_alloc(size_t rounded_size, int bucket_idx) { Block** free_head = &heads[bucket_idx]; Block** full_head = &full_heads[bucket_idx]; static __thread ThreadBlockCache* cache = NULL; if (!cache) cache = thread_caches.get(); Block** cache_head = &cache->cache_free_heads[bucket_idx]; // static __thread int gc_allocs = 0; // if (++gc_allocs == 128) { // static StatCounter sc_total("gc_allocs"); // sc_total.log(128); // gc_allocs = 0; //} while (true) { while (Block* cache_block = *cache_head) { GCAllocation* rtn = _allocFromBlock(cache_block); if (rtn) return rtn; removeFromLLAndNull(cache_block); insertIntoLL(&cache->cache_full_heads[bucket_idx], cache_block); } // Not very useful to count the cache misses if we don't count the total attempts: // static StatCounter sc_fallback("gc_allocs_cachemiss"); // sc_fallback.log(); LOCK_REGION(heap->lock); assert(*cache_head == NULL); // should probably be called allocBlock: Block* myblock = _claimBlock(rounded_size, &heads[bucket_idx]); assert(myblock); assert(!myblock->next); assert(!myblock->prev); // printf("%d claimed new block %p with %d objects\n", threading::gettid(), myblock, myblock->numObjects()); insertIntoLL(cache_head, myblock); } }
Box* listRemove(BoxedList* self, Box* elt) { LOCK_REGION(self->lock.asWrite()); assert(self->cls == list_cls); for (int i = 0; i < self->size; i++) { Box* e = self->elts->elts[i]; Box* cmp = compareInternal(e, elt, AST_TYPE::Eq, NULL); bool b = nonzero(cmp); if (b) { memmove(self->elts->elts + i, self->elts->elts + i + 1, (self->size - i - 1) * sizeof(Box*)); self->size--; return None; } } raiseExcHelper(ValueError, "list.remove(x): x not in list"); }
Box* listIAdd(BoxedList* self, Box* _rhs) { LOCK_REGION(self->lock.asWrite()); if (_rhs->cls == list_cls) { // This branch is safe if self==rhs: BoxedList* rhs = static_cast<BoxedList*>(_rhs); int s1 = self->size; int s2 = rhs->size; self->ensure(s1 + s2); memcpy(self->elts->elts + s1, rhs->elts->elts, sizeof(rhs->elts->elts[0]) * s2); self->size = s1 + s2; return self; } RELEASE_ASSERT(_rhs != self, "unsupported"); for (auto* b : _rhs->pyElements()) listAppendInternal(self, b); return self; }
/// Reoptimizes the given function version at the new effort level. /// The cf must be an active version in its parents CLFunction; the given /// version will be replaced by the new version, which will be returned. static CompiledFunction* _doReopt(CompiledFunction* cf, EffortLevel::EffortLevel new_effort) { LOCK_REGION(codegen_rwlock.asWrite()); assert(cf->clfunc->versions.size()); assert(cf); assert(cf->entry_descriptor == NULL && "We can't reopt an osr-entry compile!"); assert(cf->spec); CLFunction* clfunc = cf->clfunc; assert(clfunc); assert(new_effort > cf->effort); FunctionList& versions = clfunc->versions; for (int i = 0; i < versions.size(); i++) { if (versions[i] == cf) { versions.erase(versions.begin() + i); CompiledFunction* new_cf = compileFunction(clfunc, cf->spec, new_effort, NULL); // this pushes the new CompiledVersion to the back of the version list cf->dependent_callsites.invalidateAll(); return new_cf; } } printf("Couldn't find a version; %ld exist:\n", versions.size()); for (auto cf : versions) { printf("%p\n", cf); } assert(0 && "Couldn't find a version to reopt! Probably reopt'd already?"); abort(); }
Box* listMul(BoxedList* self, Box* rhs) { if (rhs->cls != int_cls) { raiseExcHelper(TypeError, "can't multiply sequence by non-int of type '%s'", getTypeName(rhs)->c_str()); } LOCK_REGION(self->lock.asRead()); int n = static_cast<BoxedInt*>(rhs)->n; int s = self->size; BoxedList* rtn = new BoxedList(); rtn->ensure(n * s); if (s == 1) { for (int i = 0; i < n; i++) { listAppendInternal(rtn, self->elts->elts[0]); } } else { for (int i = 0; i < n; i++) { listAppendArrayInternal(rtn, &self->elts->elts[0], s); } } return rtn; }