jitcraft/Stack.cpp
changeset 62 e04c5be84792
parent 59 b7d61ddb3c8d
child 65 7c942b5adebc
     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 +}