diff -r 864e4b02a4c1 -r e04c5be84792 jitcraft/Stack.cpp --- a/jitcraft/Stack.cpp Sun Jul 08 11:33:12 2012 -0700 +++ b/jitcraft/Stack.cpp Sun Jul 08 15:23:48 2012 -0700 @@ -1,152 +1,167 @@ -/* vim: set ts=4 sw=4 tw=99 et: - * - * Copyright (C) 2012 David Anderson - * - * This file is part of JITCraft. - * - * JITCraft is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free - * Software Foundation, either version 3 of the License, or (at your option) - * any later version. - * - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with - * JITCraft. If not, see http://www.gnu.org/licenses/. - */ -#include -#include -#include "Stack.h" -#include "Zone.h" -#include "Heap-inl.h" - -using namespace ke; - -Stack::Stack() - : buffer_(NULL), - end_(NULL), - top_(NULL) -{ -} - -Stack::~Stack() -{ - free(buffer_); -} - -bool -Stack::initialize() -{ - buffer_ = (char *)malloc(STACK_SIZE); - if (!buffer_) - return false; - - top_ = NULL; - end_ = buffer_ + STACK_SIZE; - return true; -} - -static inline size_t -SizeForCodeFrame(Code *code) -{ - return sizeof(Frame) + sizeof(LocalSlot) * (code->nlocals() + code->maxStackDepth()); -} - -Frame * -Stack::pushFrame(Function *fun) -{ - Code *code = fun->code(); - size_t nbytes = SizeForCodeFrame(code); - if (reinterpret_cast(top_->sp) + nbytes >= end_) - return NULL; - - Frame *frame = reinterpret_cast(top_->sp); - new (frame) Frame(top_->fp, top_->pc, fun, code, ZONE()->heap().lifoPosition()); - memset(frame->locals(), 0, sizeof(LocalSlot) * code->nlocals()); - - top_->pc = frame->code()->start(); - top_->sp = frame->stackBase(); - top_->fp = frame; - - return frame; -} - - -Frame * -Stack::popFrame() -{ - ZONE()->heap().unwindLifo(top_->fp->lifoPosition()); - - Frame *prev = top_->fp->prev(); - Function *fun = top_->fp->maybeFun(); - Code *code = top_->fp->code(); - - size_t nbytes = sizeof(LocalSlot) * code->nlocals() + - sizeof(Frame) + - sizeof(LocalSlot) * (fun ? fun->nargs() : 0); - - top_->pc = top_->fp->prevpc(); - top_->sp = reinterpret_cast(reinterpret_cast(top_->sp) - nbytes); - top_->fp = prev; - return prev; -} - -void -Frame::accept(VirtualObjectVisitor *visitor) -{ - visitor->visit(reinterpret_cast(&fun_)); - visitor->visit(reinterpret_cast(&code_)); -} - -static void -TraceFrame(VirtualObjectVisitor *visitor, Frame *fp, LocalSlot *sp, bytecode *pc) -{ - Code *code = fp->code(); - LocalSlot *slots = fp->locals(); - - // Trace local variables. - for (unsigned i = 0; i < code->nlocals(); i++) { - Type *type = code->localType(i); - if (type->isTraceable()) - visitor->visit(&slots[i].obj); - } - - // Trace arguments, if a function call. - if (Function *fun = fp->maybeFun()) { - for (unsigned i = 0; i < fun->nargs(); i++) { - Type *type = fun->argType(i); - if (type->isTraceable()) - visitor->visit(&fp->arg(i).obj); - } - } - - // Finally, trace stack slots. Not every gc-point in the bytecode will - // have a safepoint; since they are actually uncommon, we don't emit - // them unless at least one stack slot would be marked. - if (uint8 *safepoint = code->safepointAt(code->pcToOffset(pc))) { - LocalSlot *base = fp->stackBase(); - unsigned stackDepth = unsigned(sp - fp->stackBase()); - assert(stackDepth <= code->maxStackDepth()); - - for (unsigned i = 0; i < stackDepth; i++) { - if (safepoint[i / 8] & (1 << (i % 8))) - visitor->visit(&base[i].obj); - } - } -} - -void -Stack::accept(VirtualObjectVisitor *visitor) -{ - LocalSlot *sp = top_->sp; - bytecode *pc = top_->pc; - - for (Frame *frame = top_->fp; frame; frame = frame->prev()) { - TraceFrame(visitor, frame, sp, pc); - sp = reinterpret_cast(frame); - pc = frame->prevpc(); - } -} - +/* vim: set ts=4 sw=4 tw=99 et: + * + * Copyright (C) 2012 David Anderson + * + * This file is part of JITCraft. + * + * JITCraft is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * JITCraft. If not, see http://www.gnu.org/licenses/. + */ +#include +#include +#include "Stack.h" +#include "Zone.h" +#include "Heap-inl.h" + +using namespace ke; + +Stack::Stack() + : buffer_(NULL), + end_(NULL), + top_(NULL) +{ +} + +Stack::~Stack() +{ + free(buffer_); +} + +bool +Stack::initialize() +{ + buffer_ = (char *)malloc(STACK_SIZE); + if (!buffer_) + return false; + + top_ = NULL; + end_ = buffer_ + STACK_SIZE; + return true; +} + +static inline size_t +SizeForCodeFrame(Code *code) +{ + return sizeof(Frame) + sizeof(LocalSlot) * (code->nlocals() + code->maxStackDepth()); +} + +Frame * +Stack::pushFrame(Function *fun) +{ + Code *code = fun->code(); + size_t nbytes = SizeForCodeFrame(code); + if (reinterpret_cast(top_->sp) + nbytes >= end_) + return NULL; + + Frame *frame = reinterpret_cast(top_->sp); + new (frame) Frame(top_->fp, top_->pc, fun, code, ZONE()->heap().lifoPosition()); + memset(frame->locals(), 0, sizeof(LocalSlot) * code->nlocals()); + + top_->pc = frame->code()->start(); + top_->sp = frame->stackBase(); + top_->fp = frame; + + return frame; +} + + +Frame * +Stack::popFrame() +{ + ZONE()->heap().unwindLifo(top_->fp->lifoPosition()); + + Frame *prev = top_->fp->prev(); + Function *fun = top_->fp->maybeFun(); + Code *code = top_->fp->code(); + + size_t nbytes = sizeof(LocalSlot) * code->nlocals() + + sizeof(Frame) + + sizeof(LocalSlot) * (fun ? fun->nargs() : 0); + + top_->pc = top_->fp->prevpc(); + top_->sp = reinterpret_cast(reinterpret_cast(top_->sp) - nbytes); + top_->fp = prev; + return prev; +} + +void +Frame::accept(VirtualObjectVisitor *visitor) +{ + visitor->visit(reinterpret_cast(&fun_)); + visitor->visit(reinterpret_cast(&code_)); +} + +static void +TraceFrame(VirtualObjectVisitor *visitor, Frame *fp, LocalSlot *sp, bytecode *pc) +{ + Code *code = fp->code(); + LocalSlot *slots = fp->locals(); + + // Trace local variables. + for (unsigned i = 0; i < code->nlocals(); i++) { + Type *type = code->localType(i); + if (type->isTraceable()) + visitor->visit(&slots[i].obj); + } + + // Trace arguments, if a function call. + if (Function *fun = fp->maybeFun()) { + for (unsigned i = 0; i < fun->nargs(); i++) { + Type *type = fun->argType(i); + if (type->isTraceable()) + visitor->visit(&fp->arg(i).obj); + } + } + + // Finally, trace stack slots. Not every gc-point in the bytecode will + // have a safepoint; since they are actually uncommon, we don't emit + // them unless at least one stack slot would be marked. + if (uint8 *safepoint = code->safepointAt(code->pcToOffset(pc))) { + LocalSlot *base = fp->stackBase(); + unsigned stackDepth = unsigned(sp - fp->stackBase()); + assert(stackDepth <= code->maxStackDepth()); + + for (unsigned i = 0; i < stackDepth; i++) { + if (safepoint[i / 8] & (1 << (i % 8))) + visitor->visit(&base[i].obj); + } + } +} + +void +Stack::accept(VirtualObjectVisitor *visitor) +{ + if (!top_) + return; + + LocalSlot *sp = top_->sp; + bytecode *pc = top_->pc; + + for (Frame *frame = top_->fp; frame; frame = frame->prev()) { + TraceFrame(visitor, frame, sp, pc); + sp = reinterpret_cast(frame); + pc = frame->prevpc(); + } +} + +bool +Stack::isInCallStack(Handle module) +{ + if (!top_) + return false; + + for (Frame *frame = top_->fp; frame; frame = frame->prev()) { + if (frame->code()->module() == module) + return true; + } + return false; +}