1.1 --- a/jitcraft/Stack.cpp Sun Jul 08 11:33:12 2012 -0700
1.2 +++ b/jitcraft/Stack.cpp Sun Jul 08 15:23:48 2012 -0700
1.3 @@ -1,152 +1,167 @@
1.4 -/* vim: set ts=4 sw=4 tw=99 et:
1.5 - *
1.6 - * Copyright (C) 2012 David Anderson
1.7 - *
1.8 - * This file is part of JITCraft.
1.9 - *
1.10 - * JITCraft is free software: you can redistribute it and/or modify it under
1.11 - * the terms of the GNU General Public License as published by the Free
1.12 - * Software Foundation, either version 3 of the License, or (at your option)
1.13 - * any later version.
1.14 - *
1.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
1.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
1.18 - *
1.19 - * You should have received a copy of the GNU General Public License along with
1.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
1.21 - */
1.22 -#include <new>
1.23 -#include <stdlib.h>
1.24 -#include "Stack.h"
1.25 -#include "Zone.h"
1.26 -#include "Heap-inl.h"
1.27 -
1.28 -using namespace ke;
1.29 -
1.30 -Stack::Stack()
1.31 - : buffer_(NULL),
1.32 - end_(NULL),
1.33 - top_(NULL)
1.34 -{
1.35 -}
1.36 -
1.37 -Stack::~Stack()
1.38 -{
1.39 - free(buffer_);
1.40 -}
1.41 -
1.42 -bool
1.43 -Stack::initialize()
1.44 -{
1.45 - buffer_ = (char *)malloc(STACK_SIZE);
1.46 - if (!buffer_)
1.47 - return false;
1.48 -
1.49 - top_ = NULL;
1.50 - end_ = buffer_ + STACK_SIZE;
1.51 - return true;
1.52 -}
1.53 -
1.54 -static inline size_t
1.55 -SizeForCodeFrame(Code *code)
1.56 -{
1.57 - return sizeof(Frame) + sizeof(LocalSlot) * (code->nlocals() + code->maxStackDepth());
1.58 -}
1.59 -
1.60 -Frame *
1.61 -Stack::pushFrame(Function *fun)
1.62 -{
1.63 - Code *code = fun->code();
1.64 - size_t nbytes = SizeForCodeFrame(code);
1.65 - if (reinterpret_cast<char *>(top_->sp) + nbytes >= end_)
1.66 - return NULL;
1.67 -
1.68 - Frame *frame = reinterpret_cast<Frame *>(top_->sp);
1.69 - new (frame) Frame(top_->fp, top_->pc, fun, code, ZONE()->heap().lifoPosition());
1.70 - memset(frame->locals(), 0, sizeof(LocalSlot) * code->nlocals());
1.71 -
1.72 - top_->pc = frame->code()->start();
1.73 - top_->sp = frame->stackBase();
1.74 - top_->fp = frame;
1.75 -
1.76 - return frame;
1.77 -}
1.78 -
1.79 -
1.80 -Frame *
1.81 -Stack::popFrame()
1.82 -{
1.83 - ZONE()->heap().unwindLifo(top_->fp->lifoPosition());
1.84 -
1.85 - Frame *prev = top_->fp->prev();
1.86 - Function *fun = top_->fp->maybeFun();
1.87 - Code *code = top_->fp->code();
1.88 -
1.89 - size_t nbytes = sizeof(LocalSlot) * code->nlocals() +
1.90 - sizeof(Frame) +
1.91 - sizeof(LocalSlot) * (fun ? fun->nargs() : 0);
1.92 -
1.93 - top_->pc = top_->fp->prevpc();
1.94 - top_->sp = reinterpret_cast<LocalSlot *>(reinterpret_cast<char *>(top_->sp) - nbytes);
1.95 - top_->fp = prev;
1.96 - return prev;
1.97 -}
1.98 -
1.99 -void
1.100 -Frame::accept(VirtualObjectVisitor *visitor)
1.101 -{
1.102 - visitor->visit(reinterpret_cast<Object **>(&fun_));
1.103 - visitor->visit(reinterpret_cast<Object **>(&code_));
1.104 -}
1.105 -
1.106 -static void
1.107 -TraceFrame(VirtualObjectVisitor *visitor, Frame *fp, LocalSlot *sp, bytecode *pc)
1.108 -{
1.109 - Code *code = fp->code();
1.110 - LocalSlot *slots = fp->locals();
1.111 -
1.112 - // Trace local variables.
1.113 - for (unsigned i = 0; i < code->nlocals(); i++) {
1.114 - Type *type = code->localType(i);
1.115 - if (type->isTraceable())
1.116 - visitor->visit(&slots[i].obj);
1.117 - }
1.118 -
1.119 - // Trace arguments, if a function call.
1.120 - if (Function *fun = fp->maybeFun()) {
1.121 - for (unsigned i = 0; i < fun->nargs(); i++) {
1.122 - Type *type = fun->argType(i);
1.123 - if (type->isTraceable())
1.124 - visitor->visit(&fp->arg(i).obj);
1.125 - }
1.126 - }
1.127 -
1.128 - // Finally, trace stack slots. Not every gc-point in the bytecode will
1.129 - // have a safepoint; since they are actually uncommon, we don't emit
1.130 - // them unless at least one stack slot would be marked.
1.131 - if (uint8 *safepoint = code->safepointAt(code->pcToOffset(pc))) {
1.132 - LocalSlot *base = fp->stackBase();
1.133 - unsigned stackDepth = unsigned(sp - fp->stackBase());
1.134 - assert(stackDepth <= code->maxStackDepth());
1.135 -
1.136 - for (unsigned i = 0; i < stackDepth; i++) {
1.137 - if (safepoint[i / 8] & (1 << (i % 8)))
1.138 - visitor->visit(&base[i].obj);
1.139 - }
1.140 - }
1.141 -}
1.142 -
1.143 -void
1.144 -Stack::accept(VirtualObjectVisitor *visitor)
1.145 -{
1.146 - LocalSlot *sp = top_->sp;
1.147 - bytecode *pc = top_->pc;
1.148 -
1.149 - for (Frame *frame = top_->fp; frame; frame = frame->prev()) {
1.150 - TraceFrame(visitor, frame, sp, pc);
1.151 - sp = reinterpret_cast<LocalSlot *>(frame);
1.152 - pc = frame->prevpc();
1.153 - }
1.154 -}
1.155 -
1.156 +/* vim: set ts=4 sw=4 tw=99 et:
1.157 + *
1.158 + * Copyright (C) 2012 David Anderson
1.159 + *
1.160 + * This file is part of JITCraft.
1.161 + *
1.162 + * JITCraft is free software: you can redistribute it and/or modify it under
1.163 + * the terms of the GNU General Public License as published by the Free
1.164 + * Software Foundation, either version 3 of the License, or (at your option)
1.165 + * any later version.
1.166 + *
1.167 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
1.168 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.169 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
1.170 + *
1.171 + * You should have received a copy of the GNU General Public License along with
1.172 + * JITCraft. If not, see http://www.gnu.org/licenses/.
1.173 + */
1.174 +#include <new>
1.175 +#include <stdlib.h>
1.176 +#include "Stack.h"
1.177 +#include "Zone.h"
1.178 +#include "Heap-inl.h"
1.179 +
1.180 +using namespace ke;
1.181 +
1.182 +Stack::Stack()
1.183 + : buffer_(NULL),
1.184 + end_(NULL),
1.185 + top_(NULL)
1.186 +{
1.187 +}
1.188 +
1.189 +Stack::~Stack()
1.190 +{
1.191 + free(buffer_);
1.192 +}
1.193 +
1.194 +bool
1.195 +Stack::initialize()
1.196 +{
1.197 + buffer_ = (char *)malloc(STACK_SIZE);
1.198 + if (!buffer_)
1.199 + return false;
1.200 +
1.201 + top_ = NULL;
1.202 + end_ = buffer_ + STACK_SIZE;
1.203 + return true;
1.204 +}
1.205 +
1.206 +static inline size_t
1.207 +SizeForCodeFrame(Code *code)
1.208 +{
1.209 + return sizeof(Frame) + sizeof(LocalSlot) * (code->nlocals() + code->maxStackDepth());
1.210 +}
1.211 +
1.212 +Frame *
1.213 +Stack::pushFrame(Function *fun)
1.214 +{
1.215 + Code *code = fun->code();
1.216 + size_t nbytes = SizeForCodeFrame(code);
1.217 + if (reinterpret_cast<char *>(top_->sp) + nbytes >= end_)
1.218 + return NULL;
1.219 +
1.220 + Frame *frame = reinterpret_cast<Frame *>(top_->sp);
1.221 + new (frame) Frame(top_->fp, top_->pc, fun, code, ZONE()->heap().lifoPosition());
1.222 + memset(frame->locals(), 0, sizeof(LocalSlot) * code->nlocals());
1.223 +
1.224 + top_->pc = frame->code()->start();
1.225 + top_->sp = frame->stackBase();
1.226 + top_->fp = frame;
1.227 +
1.228 + return frame;
1.229 +}
1.230 +
1.231 +
1.232 +Frame *
1.233 +Stack::popFrame()
1.234 +{
1.235 + ZONE()->heap().unwindLifo(top_->fp->lifoPosition());
1.236 +
1.237 + Frame *prev = top_->fp->prev();
1.238 + Function *fun = top_->fp->maybeFun();
1.239 + Code *code = top_->fp->code();
1.240 +
1.241 + size_t nbytes = sizeof(LocalSlot) * code->nlocals() +
1.242 + sizeof(Frame) +
1.243 + sizeof(LocalSlot) * (fun ? fun->nargs() : 0);
1.244 +
1.245 + top_->pc = top_->fp->prevpc();
1.246 + top_->sp = reinterpret_cast<LocalSlot *>(reinterpret_cast<char *>(top_->sp) - nbytes);
1.247 + top_->fp = prev;
1.248 + return prev;
1.249 +}
1.250 +
1.251 +void
1.252 +Frame::accept(VirtualObjectVisitor *visitor)
1.253 +{
1.254 + visitor->visit(reinterpret_cast<Object **>(&fun_));
1.255 + visitor->visit(reinterpret_cast<Object **>(&code_));
1.256 +}
1.257 +
1.258 +static void
1.259 +TraceFrame(VirtualObjectVisitor *visitor, Frame *fp, LocalSlot *sp, bytecode *pc)
1.260 +{
1.261 + Code *code = fp->code();
1.262 + LocalSlot *slots = fp->locals();
1.263 +
1.264 + // Trace local variables.
1.265 + for (unsigned i = 0; i < code->nlocals(); i++) {
1.266 + Type *type = code->localType(i);
1.267 + if (type->isTraceable())
1.268 + visitor->visit(&slots[i].obj);
1.269 + }
1.270 +
1.271 + // Trace arguments, if a function call.
1.272 + if (Function *fun = fp->maybeFun()) {
1.273 + for (unsigned i = 0; i < fun->nargs(); i++) {
1.274 + Type *type = fun->argType(i);
1.275 + if (type->isTraceable())
1.276 + visitor->visit(&fp->arg(i).obj);
1.277 + }
1.278 + }
1.279 +
1.280 + // Finally, trace stack slots. Not every gc-point in the bytecode will
1.281 + // have a safepoint; since they are actually uncommon, we don't emit
1.282 + // them unless at least one stack slot would be marked.
1.283 + if (uint8 *safepoint = code->safepointAt(code->pcToOffset(pc))) {
1.284 + LocalSlot *base = fp->stackBase();
1.285 + unsigned stackDepth = unsigned(sp - fp->stackBase());
1.286 + assert(stackDepth <= code->maxStackDepth());
1.287 +
1.288 + for (unsigned i = 0; i < stackDepth; i++) {
1.289 + if (safepoint[i / 8] & (1 << (i % 8)))
1.290 + visitor->visit(&base[i].obj);
1.291 + }
1.292 + }
1.293 +}
1.294 +
1.295 +void
1.296 +Stack::accept(VirtualObjectVisitor *visitor)
1.297 +{
1.298 + if (!top_)
1.299 + return;
1.300 +
1.301 + LocalSlot *sp = top_->sp;
1.302 + bytecode *pc = top_->pc;
1.303 +
1.304 + for (Frame *frame = top_->fp; frame; frame = frame->prev()) {
1.305 + TraceFrame(visitor, frame, sp, pc);
1.306 + sp = reinterpret_cast<LocalSlot *>(frame);
1.307 + pc = frame->prevpc();
1.308 + }
1.309 +}
1.310 +
1.311 +bool
1.312 +Stack::isInCallStack(Handle<Module> module)
1.313 +{
1.314 + if (!top_)
1.315 + return false;
1.316 +
1.317 + for (Frame *frame = top_->fp; frame; frame = frame->prev()) {
1.318 + if (frame->code()->module() == module)
1.319 + return true;
1.320 + }
1.321 + return false;
1.322 +}