void SuBlock::persist() { if (persisted) return; if (frame->fn != fn) except_err("orphaned block!"); // won't need to copy locals if another block persist has already done so if (within(tls().proc->stack, frame->local)) { // save locals on heap - only done once per call/frame Value* old_locals = frame->local; int n = frame->fn->nlocals * sizeof (Value); frame->local = (Value*) memcpy(new char[n], frame->local, n); // update any other active frames pointing to the same locals // i.e. nested blocks within one parent frame for (Frame* f = tls().proc->fp; f > tls().proc->frames; --f) if (f->local == old_locals) f->local = frame->local; } // save frame on heap frame = (Frame*) memcpy(new Frame, frame, sizeof (Frame)); persisted = true; }
Dbms* dbms() { if (isclient()) { if (! tls().thedbms) { if (Fibers::inMain()) tls().thedbms = dbms_remote(server_ip); else { try { tls().thedbms = dbms_remote_async(server_ip); } catch (const Except& e) { throw Except(e, "thread failed to connect to db server: " + e.gcstr()); } tls().thedbms->auth(Fibers::main_dbms()->token()); } } return tls().thedbms; } else { static Dbms* local = dbms_local(); return local; } }
char* callStackString() { OstreamStr stk; gcstring indent = ""; for (Frame* f = tls().proc->fp; f > tls().proc->frames; --f) { stk << endl << indent; if (f->fn) stk << f->fn; else if (f->prim) stk << f->prim; indent += " "; } return stk.str(); }
Except::Except(gcstring x) : SuString(x.trim()), fp_fn_(tls().proc ? tls().proc->fp->fn : 0), is_block_return(x == "block return") { if (x.has_prefix("block") && (x == "block:continue" || x == "block:break" || is_block_return)) { static SuObject* empty = new SuObject; calls_ = empty; if (is_block_return) verify(fp_fn_); } else { TRACE(EXCEPTIONS, "throwing: " << x); calls_ = copyCallStack(); } }
void MacroAssembler::get_thread(Register thread) { movl(thread, rsp); shrl(thread, PAGE_SHIFT); ExternalAddress tls_base((address)ThreadLocalStorage::sp_map_addr()); Address index(noreg, thread, Address::times_4); ArrayAddress tls(tls_base, index); movptr(thread, tls); }
void SockBuffer::log_stats() const { LOG(INFO) << "read_limit_==" << (read_limit_ ? "true" : "false"); LOG(INFO) << "octets_read_==" << octets_read_; LOG(INFO) << "octets_written_==" << octets_written_; log_totals(); if (tls()) { LOG(INFO) << tls_info(); } }
// this is a wrapper that runs inside the fiber to catch exceptions static void _stdcall thread(void* arg) { Proc p; tls().proc = &p; ThreadCloser closer; try { ThreadInfo* ti = static_cast<ThreadInfo*>(arg); ti->fn.call(ti->fn, CALL); } catch (const Except& e) { errlog("ERROR uncaught in thread:", e.str(), e.callstack()); } }
SuObject* copyCallStack() { static Value qqq = new SuString("???"); SuObject* calls = new SuObject; if (! tls().proc || ! tls().proc->fp) return calls; for (Frame* f = tls().proc->fp; f > tls().proc->frames; --f) { SuObject* call = new SuObject; SuObject* vars = new SuObject; if (f->fn) { call->put("fn", f->fn); int i = 0, n = 0; TRY(i = f->fn->source(f->ip - f->fn->code - 1, &n)); call->put("src_i", i); call->put("src_n", n); for (i = 0; i < f->fn->nlocals; ++i) if (f->local[i]) { Value value = qqq; TRY(value = f->local[i]); TRY(vars->put(symbol(f->fn->locals[i]), value)); } if (f->self) vars->put("this", f->self); } else if (f->prim) { TRY(call->put("fn", f->prim)); } call->put("locals", vars); calls->add(call); } return calls; }
Value SuBlock::call(Value self, Value member, short nargs, short nargnames, ushort* argnames, int each) { if (member == CALL) { if (frame->fn != fn) except_err("orphaned block!"); args(nargs, nargnames, argnames, each); Framer framer(frame, pc, first, nparams, self.ptr() == this ? frame->self : self); return tls().proc->fp->run(); } else return Func::call(self, member, nargs, nargnames, argnames, each); }
Value SuFunction::call(Value self, Value member, short nargs, short nargnames, short* argnames, int each) { static Value Disasm("Disasm"); static Value Source("Source"); if (member == CALL) { args(nargs, nargnames, argnames, each); if (flags) dotParams(self); Framer frame(this, self); return tls().proc->fp->run(); } else if (member == Disasm) { NOARGS("function.Disasm()"); OstreamStr oss; disasm(oss); return new SuString(oss.str()); } else if (member == Source) { return new SuString(src); } else return Func::call(self, member, nargs, nargnames, argnames, each); }
void set_session_view(const gcstring& name, const gcstring& def) { if (!tls().session_views) tls().session_views = new SesViews; (*tls().session_views)[name] = def; }
void remove_session_view(const gcstring& name) { if (tls().session_views) tls().session_views->erase(name); }
gcstring get_session_view(const gcstring& name) { if (tls().session_views) if (gcstring* p = tls().session_views->find(name)) return *p; return ""; }
~ThreadCloser() { delete tls().thedbms; tls().thedbms = nullptr; Fibers::end(); }