void OprofileJITEventListener::NotifyObjectEmitted(const llvm::ObjectImage& Obj) { if (VERBOSITY() >= 1) printf("An object has been emitted:\n"); llvm::error_code code; for (llvm::object::symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols(); I != E;) { llvm::object::SymbolRef::Type type; code = I->getType(type); assert(!code); if (type == llvm::object::SymbolRef::ST_Function) { llvm::StringRef name; uint64_t addr, size; code = I->getName(name); assert(!code); code = I->getAddress(addr); assert(!code); code = I->getSize(size); assert(!code); if (VERBOSITY() >= 1) printf("registering with oprofile: %s %p 0x%lx\n", name.data(), (void*)addr, size); int r = op_write_native_code(agent, name.data(), addr, (void*)addr, size); assert(r == 0); //} else { // llvm::StringRef name; // code = I->getName(name); // assert(!code); // printf("Skipping %s\n", name.data()); } ++I; } }
void Heap::freeUnmarked() { long bytes_freed = 0; for (int bidx = 0; bidx < NUM_BUCKETS; bidx++) { bytes_freed += freeChain(heads[bidx]); bytes_freed += freeChain(full_heads[bidx]); } LargeObj *cur = large_head; while (cur) { void *p = cur->data; GCObjectHeader* header = headerFromObject(p); if (isMarked(header)) { clearMark(header); } else { if (VERBOSITY() >= 2) printf("Freeing %p\n", p); bytes_freed += cur->mmap_size(); *cur->prev = cur->next; if (cur->next) cur->next->prev = cur->prev; LargeObj *to_free = cur; cur = cur->next; _freeLargeObj(to_free); continue; } cur = cur->next; } if (VERBOSITY("gc") >= 2) if (bytes_freed) printf("Freed %ld bytes\n", bytes_freed); }
static Box* importSub(const std::string* name, Box* parent_module) { BoxedList* path_list; if (parent_module == NULL) { path_list = getSysPath(); if (path_list == NULL || path_list->cls != list_cls) { raiseExcHelper(RuntimeError, "sys.path must be a list of directory names"); } } else { path_list = static_cast<BoxedList*>(parent_module->getattr("__path__", NULL)); if (path_list == NULL || path_list->cls != list_cls) { raiseExcHelper(ImportError, "No module named %s", name->c_str()); } } llvm::SmallString<128> joined_path; for (int i = 0; i < path_list->size; i++) { Box* _p = path_list->elts->elts[i]; if (_p->cls != str_cls) continue; BoxedString* p = static_cast<BoxedString*>(_p); joined_path.clear(); llvm::sys::path::append(joined_path, p->s, *name + ".py"); std::string fn(joined_path.str()); if (VERBOSITY() >= 2) printf("Searching for %s at %s...\n", name->c_str(), fn.c_str()); bool exists; llvm::error_code code = llvm::sys::fs::exists(joined_path.str(), exists); assert(LLVM_SYS_FS_EXISTS_CODE_OKAY(code)); if (!exists) continue; if (VERBOSITY() >= 1) printf("Importing %s from %s\n", name->c_str(), fn.c_str()); BoxedModule* module = createAndRunModule(*name, fn); return module; } if (*name == "test") { return importTestExtension(); } raiseExcHelper(ImportError, "No module named %s", name->c_str()); }
/* * Answer if this is an AXFR or IXFR query. */ query_state_type answer_axfr_ixfr(struct nsd *nsd, struct query *q) { struct acl_options *acl = NULL; /* Is it AXFR? */ switch (q->qtype) { case TYPE_AXFR: if (q->tcp) { struct zone_options* zone_opt; zone_opt = zone_options_find(nsd->options, q->qname); if(!zone_opt || acl_check_incoming(zone_opt->pattern->provide_xfr, q, &acl)==-1) { if (verbosity >= 2) { char a[128]; addr2str(&q->addr, a, sizeof(a)); VERBOSITY(2, (LOG_INFO, "axfr for %s from %s refused, %s", dname_to_string(q->qname, NULL), a, acl?"blocked":"no acl matches")); } DEBUG(DEBUG_XFRD,1, (LOG_INFO, "axfr refused, %s", acl?"blocked":"no acl matches")); if (!zone_opt) { RCODE_SET(q->packet, RCODE_NOTAUTH); } else { RCODE_SET(q->packet, RCODE_REFUSE); } return QUERY_PROCESSED; } DEBUG(DEBUG_XFRD,1, (LOG_INFO, "axfr admitted acl %s %s", acl->ip_address_spec, acl->key_name?acl->key_name:"NOKEY")); if (verbosity >= 1) { char a[128]; addr2str(&q->addr, a, sizeof(a)); VERBOSITY(1, (LOG_INFO, "%s for %s from %s", (q->qtype==TYPE_AXFR?"axfr":"ixfr"), dname_to_string(q->qname, NULL), a)); } return query_axfr(nsd, q); } /** Fallthrough: AXFR over UDP queries are discarded. */ /* fallthrough */ case TYPE_IXFR: RCODE_SET(q->packet, RCODE_IMPL); return QUERY_PROCESSED; default: return QUERY_DISCARDED; } }
// Determines whether to dispatch to cleanup code or an exception handler based on the action table. // Doesn't need exception info b/c in Pyston we assume all handlers catch all exceptions. // // Returns the switch value to be passed into the landing pad, which selects which handler gets run in the case of // multiple `catch' blocks, or is 0 to run cleanup code. static inline int64_t determine_action(const lsda_info_t* info, const call_site_entry_t* entry) { // No action means there are destructors/cleanup to run, but no exception handlers. const uint8_t* p = first_action(info, entry); if (!p) return CLEANUP_ACTION; // Read a chain of actions. if (VERBOSITY("cxx_unwind") >= 5) { printf(" reading action chain\n"); } // When we see a cleanup action, we *don't* immediately take it. Rather, we remember that we should clean up if none // of the other actions matched. bool saw_cleanup = false; do { ASSERT(p >= info->action_table, "malformed LSDA"); ptrdiff_t offset = p - info->action_table; int64_t type_filter; p = next_action(p, &type_filter); if (VERBOSITY("cxx_unwind") >= 5) { if (p) printf(" %ld: filter %ld next %ld\n", offset, type_filter, p - info->action_table); else printf(" %ld: filter %ld end\n", offset, type_filter); } if (0 == type_filter) { // A type_filter of 0 indicates a cleanup. saw_cleanup = true; } else { // Otherwise, the type_filter is supposed to be interpreted by looking up information in the types table and // comparing it against the type of the exception thrown. In Pyston, however, every exception handler // handles all exceptions, so we ignore the type information entirely and just run the handler. // // I don't fully understand negative type filters. For now we don't implement them. See // http://www.airs.com/blog/archives/464 for some information. RELEASE_ASSERT(type_filter > 0, "negative type filters unimplemented"); return type_filter; } } while (p); if (saw_cleanup) return CLEANUP_ACTION; // We ran through the whole action chain and none applied, *and* there was no cleanup indicated. What do we do? // This can't happen currently, but I think the answer is probably panic(). RELEASE_ASSERT(0, "action chain exhausted and no cleanup indicated"); }
void PprofJITEventListener::NotifyObjectEmitted(const llvm::ObjectImage& Obj) { llvm::error_code code; for (llvm::object::symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols(); I != E;) { llvm::object::SymbolRef::Type type; code = I->getType(type); assert(!code); if (type == llvm::object::SymbolRef::ST_Function) { llvm::StringRef name; uint64_t addr, size; code = I->getName(name); assert(!code); code = I->getAddress(addr); assert(!code); code = I->getSize(size); assert(!code); // fprintf(of, "%lx-%lx: %s\n", addr, addr + size, name.data()); // if (VERBOSITY() >= 1) // printf("%lx-%lx: %s\n", addr, addr + size, name.data()); fprintf(of, "%lx %lx %s\n", addr, addr + size, name.data()); if (VERBOSITY() >= 1) printf("%lx %lx %s\n", addr, addr + size, name.data()); } ++I; } }
uint8_t readByte() { ensure(1); assert(end > start); if (VERBOSITY("parsing") >= 2) printf("readByte, now %d %d\n", start+1, end); return buf[start++]; }
extern "C" void __cxa_throw(void* exc_obj, std::type_info* tinfo, void (*dtor)(void*)) { static pyston::StatCounter num_cxa_throw("num_cxa_throw"); num_cxa_throw.log(); assert(!pyston::in_cleanup_code); assert(exc_obj); RELEASE_ASSERT(tinfo == &EXCINFO_TYPE_INFO, "can't throw a non-ExcInfo value! type info: %p", tinfo); if (VERBOSITY("cxx_unwind") >= 4) printf("***** __cxa_throw() *****\n"); pyston::ExcInfo* exc_data = (pyston::ExcInfo*)exc_obj; checkExcInfo(exc_data); ASSERT(!pyston::is_unwinding, "We don't support throwing exceptions in destructors!"); pyston::is_unwinding = true; #if STAT_TIMERS pyston::StatTimer::overrideCounter(unwinding_stattimer); #endif // let unwinding.cpp know we've started unwinding pyston::logException(exc_data); pyston::unwind(exc_data); }
static inline NORETURN void resume(unw_cursor_t* cursor, const uint8_t* landing_pad, int64_t switch_value, const ExcInfo* exc_data) { checkExcInfo(exc_data); assert(landing_pad); if (VERBOSITY("cxx_unwind") >= 4) printf(" * RESUMED: ip %p switch_value %ld\n", (const void*)landing_pad, (long)switch_value); if (0 != switch_value) { // The exception handler will call __cxa_begin_catch, which stops this timer and logs it. per_thread_resume_catch_timer.restart("resume_catch", 20); } else { // The cleanup code will call _Unwind_Resume, which will stop this timer and log it. // TODO: am I sure cleanup code can't raise exceptions? maybe have an assert! per_thread_cleanup_timer.restart("cleanup", 20); #ifndef NDEBUG in_cleanup_code = true; #endif } // set rax to pointer to exception object // set rdx to the switch_value (0 for cleanup, otherwise an index indicating which exception handler to use) // // NB. assumes x86-64. maybe I should use __builtin_eh_return_data_regno() here? // but then, need to translate into UNW_* values somehow. not clear how. check(unw_set_reg(cursor, UNW_X86_64_RAX, (unw_word_t)exc_data)); check(unw_set_reg(cursor, UNW_X86_64_RDX, switch_value)); // resume! check(unw_set_reg(cursor, UNW_REG_IP, (unw_word_t)landing_pad)); unw_resume(cursor); RELEASE_ASSERT(0, "unw_resume returned!"); }
static int xfrd_handle_incoming_notify(xfrd_zone_t* zone, xfrd_soa_t* soa) { if(soa && zone->soa_disk_acquired && zone->state != xfrd_zone_expired && compare_serial(ntohl(soa->serial),ntohl(zone->soa_disk.serial)) <= 0) { DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd: ignored notify %s %u old serial, zone valid " "(soa disk serial %u)", zone->apex_str, ntohl(soa->serial), ntohl(zone->soa_disk.serial))); return 0; /* ignore notify with old serial, we have a valid zone */ } if(soa == 0) { zone->soa_notified.serial = 0; } else if (zone->soa_notified_acquired == 0 || zone->soa_notified.serial == 0 || compare_serial(ntohl(soa->serial), ntohl(zone->soa_notified.serial)) > 0) { zone->soa_notified = *soa; } zone->soa_notified_acquired = xfrd_time(); if(zone->state == xfrd_zone_ok) { xfrd_set_zone_state(zone, xfrd_zone_refreshing); } /* transfer right away */ VERBOSITY(1, (LOG_INFO, "Handle incoming notify for zone %s", zone->apex_str)); return 1; }
static long freeChain(Block* head) { long bytes_freed = 0; while (head) { int num_objects = head->numObjects(); int first_obj = head->minObjIndex(); int atoms_per_obj = head->atomsPerObj(); for (int obj_idx = first_obj; obj_idx < num_objects; obj_idx++) { int atom_idx = obj_idx * atoms_per_obj; int bitmap_idx = atom_idx / 64; int bitmap_bit = atom_idx % 64; uint64_t mask = 1L << bitmap_bit; if (head->isfree[bitmap_idx] & mask) continue; void *p = &head->atoms[atom_idx]; GCObjectHeader* header = headerFromObject(p); if (isMarked(header)) { clearMark(header); } else { if (VERBOSITY() >= 2) printf("Freeing %p\n", p); //assert(p != (void*)0x127000d960); // the main module bytes_freed += head->size; head->isfree[bitmap_idx] |= mask; } } head = head->next; } return bytes_freed; }
bool visitICmpInst(ICmpInst& inst) { // errs() << "got icmp instruction! " << inst << '\n'; bool changed = false; if (inst.getPredicate() == CmpInst::ICMP_EQ) { assert(inst.getNumOperands() == 2); if (inst.getOperand(1) == processing) { inst.swapOperands(); changed = true; any_changes = true; } assert(dyn_cast<Instruction>(inst.getOperand(0)) == processing); Value* other = inst.getOperand(1); if (isa<ConstantPointerNull>(other)) { if (VERBOSITY("opt") >= 2) { errs() << inst << '\n'; errs() << "replacing with false!\n"; } Value* new_value = ConstantInt::getFalse(other->getContext()); inst.replaceAllUsesWith(new_value); inst.eraseFromParent(); changed = true; any_changes = true; } } return changed; }
AST* readASTMisc(BufferedReader *reader) { uint8_t type = reader->readByte(); if (VERBOSITY("parsing") >= 2) printf("type = %d\n", type); if (type == 0) return NULL; uint8_t checkbyte = reader->readByte(); assert(checkbyte == 0xae); switch (type) { case AST_TYPE::alias: return read_alias(reader); case AST_TYPE::arguments: return read_arguments(reader); case AST_TYPE::comprehension: return read_comprehension(reader); case AST_TYPE::keyword: return read_keyword(reader); case AST_TYPE::Module: return read_module(reader); default: fprintf(stderr, "Unknown node type (parser.cpp:" STRINGIFY(__LINE__) "): %d\n", type); exit(1); break; } }
/** write a zone */ static int write_zone(udb_base* udb, udb_ptr* z, zone_type* zone) { /* write all domains in the zone */ domain_type* walk; rrset_type* rrset; unsigned long n = 0, c = 0; time_t t = time(NULL); /* count domains: for pct logging */ for(walk=zone->apex; walk && domain_is_subdomain(walk, zone->apex); walk=domain_next(walk)) { n++; } /* write them */ for(walk=zone->apex; walk && domain_is_subdomain(walk, zone->apex); walk=domain_next(walk)) { /* write all rrsets (in the zone) for this domain */ for(rrset=walk->rrsets; rrset; rrset=rrset->next) { if(rrset->zone == zone) { if(!write_rrset(udb, z, rrset)) return 0; } } /* only check every ... domains, and print pct */ if(++c % ZONEC_PCT_COUNT == 0 && time(NULL) > t + ZONEC_PCT_TIME) { t = time(NULL); VERBOSITY(1, (LOG_INFO, "write %s %d %%", zone->opts->name, (int)(c*((unsigned long)100)/n))); } } return 1; }
void BufferedReader::readAndInternStringVector(std::vector<InternedString>& v) { int num_elts = readShort(); if (VERBOSITY("parsing") >= 3) printf("%d elts to read\n", num_elts); for (int i = 0; i < num_elts; i++) { v.push_back(readAndInternString()); } }
void fill() { memmove(buf, buf+start, end-start); end -= start; start = 0; end += fread(buf + end, 1, BUFSIZE - end, fp); if (VERBOSITY("parsing") >= 2) printf("filled, now at %d-%d\n", start, end); }
static void readExprVector(std::vector<AST_expr*> &vec, BufferedReader *reader) { int num_elts = reader->readShort(); if (VERBOSITY("parsing") >= 2) printf("%d elts to read\n", num_elts); for (int i = 0; i < num_elts; i++) { vec.push_back(readASTExpr(reader)); } }
static void readStringVector(std::vector<std::string>& vec, BufferedReader* reader) { int num_elts = reader->readShort(); if (VERBOSITY("parsing") >= 3) printf("%d elts to read\n", num_elts); for (int i = 0; i < num_elts; i++) { vec.push_back(readString(reader)); } }
AST_expr* readASTExpr(BufferedReader* reader) { uint8_t type = reader->readByte(); if (VERBOSITY("parsing") >= 2) printf("type = %d\n", type); if (type == 0) return NULL; uint8_t checkbyte = reader->readByte(); assert(checkbyte == 0xae); switch (type) { case AST_TYPE::Attribute: return read_attribute(reader); case AST_TYPE::BinOp: return read_binop(reader); case AST_TYPE::BoolOp: return read_boolop(reader); case AST_TYPE::Call: return read_call(reader); case AST_TYPE::Compare: return read_compare(reader); case AST_TYPE::Dict: return read_dict(reader); case AST_TYPE::DictComp: return read_dictcomp(reader); case AST_TYPE::IfExp: return read_ifexp(reader); case AST_TYPE::Index: return read_index(reader); case AST_TYPE::Lambda: return read_lambda(reader); case AST_TYPE::List: return read_list(reader); case AST_TYPE::ListComp: return read_listcomp(reader); case AST_TYPE::Name: return read_name(reader); case AST_TYPE::Num: return read_num(reader); case AST_TYPE::Repr: return read_repr(reader); case AST_TYPE::Slice: return read_slice(reader); case AST_TYPE::Str: return read_str(reader); case AST_TYPE::Subscript: return read_subscript(reader); case AST_TYPE::Tuple: return read_tuple(reader); case AST_TYPE::UnaryOp: return read_unaryop(reader); default: fprintf(stderr, "Unknown expr node type (parser.cpp:" STRINGIFY(__LINE__) "): %d\n", type); abort(); break; } }
PhiAnalysis::PhiAnalysis(VRegMap<DefinednessAnalysis::DefinitionLevel> initial_map, CFGBlock* initial_block, bool initials_need_phis, LivenessAnalysis* liveness) : definedness(), empty_set(initial_map.numVregs()), liveness(liveness) { auto cfg = initial_block->cfg; auto&& vreg_info = cfg->getVRegInfo(); // I think this should always be the case -- if we're going to generate phis for the initial block, // then we should include the initial arguments as an extra entry point. assert(initials_need_phis == (initial_block->predecessors.size() > 0)); int num_vregs = initial_map.numVregs(); assert(num_vregs == vreg_info.getTotalNumOfVRegs()); definedness.run(liveness->getCodeConstants(), std::move(initial_map), initial_block); Timer _t("PhiAnalysis()", 10); for (const auto& p : definedness.defined_at_end) { CFGBlock* block = p.first; assert(!required_phis.count(block)); VRegSet& required = required_phis.insert(std::make_pair(block, VRegSet(num_vregs))).first->second; int npred = 0; for (CFGBlock* pred : block->predecessors) { if (definedness.defined_at_end.count(pred)) npred++; } if (npred > 1 || (initials_need_phis && block == initial_block)) { for (CFGBlock* pred : block->predecessors) { if (!definedness.defined_at_end.count(pred)) continue; const VRegSet& defined = definedness.getDefinedVregsAtEnd(pred); for (int vreg : defined) { if (!required[vreg] && liveness->isLiveAtEnd(vreg, pred)) { // printf("%d-%d %s\n", pred->idx, block->idx, vreg_info.getName(vreg).c_str()); required.set(vreg); } } } } if (VERBOSITY() >= 3) { printf("Phis required at end of %d:", block->idx); for (auto vreg : required) { printf(" %s", vreg_info.getName(vreg).c_str()); } printf("\n"); } } static StatCounter us_phis("us_compiling_analysis_phis"); us_phis.log(_t.end()); }
AST_Module* read_module(BufferedReader *reader) { if (VERBOSITY("parsing") >= 2) printf("reading module\n"); AST_Module *rtn = new AST_Module(); readStmtVector(rtn->body, reader); rtn->col_offset = -1; rtn->lineno = -1; return rtn; }
static void readMiscVector(std::vector<T*> &vec, BufferedReader *reader) { int num_elts = reader->readShort(); if (VERBOSITY("parsing") >= 2) printf("%d elts to read\n", num_elts); for (int i = 0; i < num_elts; i++) { AST* read = readASTMisc(reader); assert(read->type == T::TYPE); vec.push_back(static_cast<T*>(read)); } }
bool handleBool(LoadInst *li, GlobalVariable *gv) { if (VERBOSITY()) { llvm::errs() << "Constant-folding this load: " << *li << '\n'; } if (gv->getName() == "True") li->replaceAllUsesWith(embedConstantPtr(True, g.llvm_bool_type_ptr)); else li->replaceAllUsesWith(embedConstantPtr(False, g.llvm_bool_type_ptr)); return true; }
extern "C" char* reoptCompiledFunc(CompiledFunction *cf) { if (VERBOSITY("irgen") >= 1) printf("In reoptCompiledFunc, %p, %ld\n", cf, cf->times_called); stat_reopt.log(); assert(cf->effort < EffortLevel::MAXIMAL); assert(cf->clfunc->versions.size()); CompiledFunction *new_cf = _doReopt(cf, (EffortLevel::EffortLevel(cf->effort + 1))); assert(!new_cf->is_interpreted); return (char*)new_cf->code; }
void runCollection() { static StatCounter sc("gc_collections"); sc.log(); ncollections++; if (VERBOSITY("gc") >= 2) printf("Collection #%d\n", ncollections); Timer _t("collecting", /*min_usec=*/10000); markPhase(); sweepPhase(); if (VERBOSITY("gc") >= 2) printf("Collection #%d done\n\n", ncollections); long us = _t.end(); static StatCounter sc_us("gc_collections_us"); sc_us.log(us); }
// Takes the value that resume() sent us in RAX, and returns a pointer to the exception object actually thrown. In our // case, these are the same, and should always be &pyston::exception_ferry. extern "C" void* __cxa_begin_catch(void* exc_obj_in) noexcept { assert(exc_obj_in); pyston::us_unwind_resume_catch.log(pyston::per_thread_resume_catch_timer.end()); if (VERBOSITY("cxx_unwind") >= 4) printf("***** __cxa_begin_catch() *****\n"); pyston::ExcInfo* e = (pyston::ExcInfo*)exc_obj_in; checkExcInfo(e); return e; }
static void compileIR(CompiledFunction* cf, EffortLevel::EffortLevel effort) { assert(cf); assert(cf->func); // g.engine->finalizeOBject(); if (VERBOSITY("irgen") >= 1) { printf("Compiling...\n"); // g.cur_module->dump(); } void* compiled = NULL; if (effort > EffortLevel::INTERPRETED) { Timer _t("to jit the IR"); #if LLVMREV < 215967 g.engine->addModule(cf->func->getParent()); #else g.engine->addModule(std::unique_ptr<llvm::Module>(cf->func->getParent())); #endif compiled = (void*)g.engine->getFunctionAddress(cf->func->getName()); assert(compiled); cf->llvm_code = embedConstantPtr(compiled, cf->func->getType()); long us = _t.end(); static StatCounter us_jitting("us_compiling_jitting"); us_jitting.log(us); static StatCounter num_jits("num_jits"); num_jits.log(); } else { // HAX just get it for now; this is just to make sure everything works //(void*)g.func_registry.getFunctionAddress(cf->func->getName()); } cf->code = compiled; if (VERBOSITY("irgen") >= 1) { printf("Compiled function to %p\n", compiled); } StackMap* stackmap = parseStackMap(); patchpoints::processStackmap(stackmap); }
void runCollection() { static StatCounter sc("gc_collections"); sc.log(); ncollections++; if (VERBOSITY("gc") >= 2) printf("Collection #%d\n", ncollections); Timer _t("collecting", /*min_usec=*/10000); markPhase(); std::list<Box*, StlCompatAllocator<Box*>> weakly_referenced; sweepPhase(weakly_referenced); for (auto o : weakly_referenced) { PyWeakReference** list = (PyWeakReference**)PyObject_GET_WEAKREFS_LISTPTR(o); while (PyWeakReference* head = *list) { assert(isValidGCObject(head)); if (head->wr_object != Py_None) { _PyWeakref_ClearRef(head); if (head->wr_callback) { runtimeCall(head->wr_callback, ArgPassSpec(1), reinterpret_cast<Box*>(head), NULL, NULL, NULL, NULL); head->wr_callback = NULL; } } } } if (VERBOSITY("gc") >= 2) printf("Collection #%d done\n\n", ncollections); long us = _t.end(); static StatCounter sc_us("gc_collections_us"); sc_us.log(us); // dumpHeapStatistics(); }
void runCollection() { static StatCounter sc("gc_collections"); sc.log(); if (VERBOSITY("gc") >= 2) printf("Collection #%d\n", ++ncollections); //if (ncollections == 754) { //raise(SIGTRAP); //} markPhase(); sweepPhase(); }
extern "C" void _Unwind_Resume(struct _Unwind_Exception* _exc) { assert(pyston::in_cleanup_code); #ifndef NDEBUG pyston::in_cleanup_code = false; #endif pyston::us_unwind_cleanup.log(pyston::per_thread_cleanup_timer.end()); if (VERBOSITY("cxx_unwind") >= 4) printf("***** _Unwind_Resume() *****\n"); // we give `_exc' type `struct _Unwind_Exception*' because unwind.h demands it; it's not actually accurate pyston::ExcInfo* data = (pyston::ExcInfo*)_exc; pyston::unwind(data); }