Index: html.t ================================================================== --- html.t +++ html.t @@ -1,13 +1,13 @@ -- vim: ft=terra local m={} local pstr = lib.mem.ptr(int8) -terra m.sanitize(txt: pstr, quo: bool) +terra m.sanitize(pool: &lib.mem.pool, txt: pstr, quo: bool) if txt.ptr == nil then return pstr.null() end if txt.ct == 0 then txt.ct = lib.str.sz(txt.ptr) end - var a: lib.str.acc a:init(txt.ct*1.3) + var a: lib.str.acc a:pool(pool,txt.ct*1.3) for i=0,txt.ct do if txt(i) == @'<' then a:lpush('<') elseif txt(i) == @'>' then a:lpush('>') elseif txt(i) == @'&' then a:lpush('&') elseif quo and txt(i) == @'"' then a:lpush('"') @@ -26,14 +26,14 @@ return arrayof(int8, m.hexdgt(i / 0x10), m.hexdgt(i % 0x10)) end -terra m.urlenc(txt: pstr, qparam: bool) +terra m.urlenc(pool: &lib.mem.pool, txt: pstr, qparam: bool) if txt.ptr == nil then return pstr.null() end if txt.ct == 0 then txt.ct = lib.str.sz(txt.ptr) end - var a: lib.str.acc a:init(txt.ct*1.3) + var a: lib.str.acc a:pool(pool,txt.ct*1.3) for i=0,txt.ct do if txt(i) == @' ' then a:lpush('+') elseif txt(i) == @'&' and not qparam then a:lpush('&') elseif (txt(i) < 0x2c or (txt(i) > @';' and txt(i) < @'@') or Index: mem.t ================================================================== --- mem.t +++ mem.t @@ -181,63 +181,109 @@ struct m.pool { -- implements growable memory pools. EVERY THREAD MUST HAVE ITS OWN storage: &opaque cursor: &opaque sz: intptr + debris: &m.pool } terra m.pool:cue(sz: intptr) if self.storage == nil then self.storage = m.heapa_raw(sz) self.cursor = self.storage self.sz = sz else if self.sz >= sz then return self end - var ofs = [&uint8](self.cursor) - [&uint8](self.storage) - self.storage = m.heapr_raw(self.storage, sz) - self.cursor = [&opaque]([&uint8](self.storage) + ofs) - self.sz = sz + var oldblock = @self + self:init(sz) + @self.debris = oldblock end return self end terra m.pool:init(sz: intptr) - self.storage = nil - self:cue(sz) + var b = m.heapa_raw(sz + sizeof(m.pool)) + self.storage = [&uint8](b) + sizeof(m.pool) + self.cursor = self.storage + self.sz = sz + self.debris = [&m.pool](b) + self.debris.storage = nil return self end -terra m.pool:free() - m.heapf(self.storage) +terra m.pool:free(): {} +lib.io.fmt('DRAINING POOL %p\n',self.storage) + if self.storage == nil then return end + if self.debris.storage ~= nil then self.debris:free() end + m.heapf(self.debris) -- storage + debris field allocated in one block self.storage = nil self.cursor = nil self.sz = 0 + self.debris = nil end terra m.pool:clear() + if self.debris.storage ~= nil then self.debris:free() end self.cursor = self.storage return self end terra m.pool:alloc_bytes(sz: intptr): &opaque var space = self.sz - ([&uint8](self.cursor) - [&uint8](self.storage)) - if space < sz then self:cue(space + sz + 256) end +lib.io.fmt('%p / %p @ allocating %llu bytes in %llu of space\n',self.storage,self.cursor,sz,space) + if space < sz then +lib.dbg('reserving more space') + self:cue(space + sz + 256) end var ptr = self.cursor self.cursor = [&opaque]([&uint8](self.cursor) + sz) return ptr end -m.pool.methods.alloc = macro(function(self,ty,sz) - return `[ty](self:alloc_bytes(sizeof(ty) * sz)) +terra m.pool:realloc_bytes(oldptr: &opaque, oldsz: intptr, newsz: intptr): &opaque + var space = self.sz - ([&uint8](self.cursor) - [&uint8](self.storage)) + var cur = [&uint8](self.cursor) + if cur - [&uint8](oldptr) == oldsz and newsz - oldsz < space then + lib.dbg('moving pool cursor') + cur = cur + (newsz - oldsz) + self.cursor = [&opaque](cur) + return oldptr + else + lib.dbg('copying pool object') + var new = self:alloc_bytes(newsz) + m.cpy(new, oldptr, oldsz) + return new + end +end + +m.pool.methods.alloc = macro(function(self,typ,sz) + local ty = typ:astype() + return `[m.ptr(ty)] { + ptr = [&ty](self:alloc_bytes(sizeof([ty]) * [sz])); + ct = [sz]; + } +end) + +m.pool.methods.realloc = macro(function(self,ptr,oldsz,newsz) + local ty = self.tree.type.type + return `[m.ptr(ty)] { + ptr = [&ty](self:realloc_bytes(ptr, + sizeof(ty) * oldsz, + sizeof(ty) * newsz)); + ct = sz; + } end) terra m.pool:frame() -- stack-style linear mgmt return self.cursor end terra m.pool:reset(frame: &opaque) - self.cursor = frame + if frame >= self.storage and frame <= self.cursor then + self.cursor = frame + else -- trying to rewind into a previous block! not possible + self.cursor = self.storage + end return self end return m Index: render/compose.t ================================================================== --- render/compose.t +++ render/compose.t @@ -14,11 +14,11 @@ form.content = lib.coalesce(edit.body, '') form.acl = edit.acl end if acc ~= nil then form:append(acc) return end - var cotxt = form:tostr() defer cotxt:free() + var cotxt = form:poolstr(&co.srv.pool) -- defer cotxt:free() var doc = [lib.srv.convo.page] { title = lib.str.plit 'compose'; body = cotxt; class = lib.str.plit 'compose'; Index: render/conf.t ================================================================== --- render/conf.t +++ render/conf.t @@ -30,28 +30,29 @@ for i, m in ipairs(mappings) do if lib.render.conf[m.render] then invoker = quote if path(1):cmp(lib.str.lit([m.url])) then var body = [lib.render.conf[m.render]] (co, path) - var a: lib.str.acc a:init(body.ct+48) + var a = co:stra(body.ct+48) if not body then a:lpush(['
the requested resource is not available.
']) panel = a:finalize() else a:lpush(['