jitcraft/Stack.cpp
author David Anderson <dvander@alliedmods.net>
Sun Jul 08 16:49:17 2012 -0700 (2012-07-08)
changeset 63 dd57743d220e
parent 62 e04c5be84792
child 65 7c942b5adebc
permissions -rw-r--r--
Added support for forwards.
dvander@62
     1
/* vim: set ts=4 sw=4 tw=99 et:
dvander@62
     2
 *
dvander@62
     3
 * Copyright (C) 2012 David Anderson
dvander@62
     4
 *
dvander@62
     5
 * This file is part of JITCraft.
dvander@62
     6
 *
dvander@62
     7
 * JITCraft is free software: you can redistribute it and/or modify it under
dvander@62
     8
 * the terms of the GNU General Public License as published by the Free
dvander@62
     9
 * Software Foundation, either version 3 of the License, or (at your option)
dvander@62
    10
 * any later version.
dvander@62
    11
 * 
dvander@62
    12
 * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
dvander@62
    13
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@62
    14
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
dvander@62
    15
 *
dvander@62
    16
 * You should have received a copy of the GNU General Public License along with
dvander@62
    17
 * JITCraft. If not, see http://www.gnu.org/licenses/.
dvander@62
    18
 */
dvander@62
    19
#include <new>
dvander@62
    20
#include <stdlib.h>
dvander@62
    21
#include "Stack.h"
dvander@62
    22
#include "Zone.h"
dvander@62
    23
#include "Heap-inl.h"
dvander@62
    24
dvander@62
    25
using namespace ke;
dvander@62
    26
dvander@62
    27
Stack::Stack()
dvander@62
    28
  : buffer_(NULL),
dvander@62
    29
    end_(NULL),
dvander@62
    30
    top_(NULL)
dvander@62
    31
{
dvander@62
    32
}
dvander@62
    33
dvander@62
    34
Stack::~Stack()
dvander@62
    35
{
dvander@62
    36
    free(buffer_);
dvander@62
    37
}
dvander@62
    38
dvander@62
    39
bool
dvander@62
    40
Stack::initialize()
dvander@62
    41
{
dvander@62
    42
    buffer_ = (char *)malloc(STACK_SIZE);
dvander@62
    43
    if (!buffer_)
dvander@62
    44
        return false;
dvander@62
    45
dvander@62
    46
    top_ = NULL;
dvander@62
    47
    end_ = buffer_ + STACK_SIZE;
dvander@62
    48
    return true;
dvander@62
    49
}
dvander@62
    50
dvander@62
    51
static inline size_t
dvander@62
    52
SizeForCodeFrame(Code *code)
dvander@62
    53
{
dvander@62
    54
    return sizeof(Frame) + sizeof(LocalSlot) * (code->nlocals() + code->maxStackDepth());
dvander@62
    55
}
dvander@62
    56
dvander@62
    57
Frame *
dvander@62
    58
Stack::pushFrame(Function *fun)
dvander@62
    59
{
dvander@62
    60
    Code *code = fun->code();
dvander@62
    61
    size_t nbytes = SizeForCodeFrame(code);
dvander@62
    62
    if (reinterpret_cast<char *>(top_->sp) + nbytes >= end_)
dvander@62
    63
        return NULL;
dvander@62
    64
dvander@62
    65
    Frame *frame = reinterpret_cast<Frame *>(top_->sp);
dvander@62
    66
    new (frame) Frame(top_->fp, top_->pc, fun, code, ZONE()->heap().lifoPosition());
dvander@62
    67
    memset(frame->locals(), 0, sizeof(LocalSlot) * code->nlocals());
dvander@62
    68
dvander@62
    69
    top_->pc = frame->code()->start();
dvander@62
    70
    top_->sp = frame->stackBase();
dvander@62
    71
    top_->fp = frame;
dvander@62
    72
dvander@62
    73
    return frame;
dvander@62
    74
}
dvander@62
    75
dvander@62
    76
dvander@62
    77
Frame *
dvander@62
    78
Stack::popFrame()
dvander@62
    79
{
dvander@62
    80
    ZONE()->heap().unwindLifo(top_->fp->lifoPosition());
dvander@62
    81
dvander@62
    82
    Frame *prev = top_->fp->prev();
dvander@62
    83
    Function *fun = top_->fp->maybeFun();
dvander@62
    84
    Code *code = top_->fp->code();
dvander@62
    85
dvander@62
    86
    size_t nbytes = sizeof(LocalSlot) * code->nlocals() +
dvander@62
    87
                    sizeof(Frame) +
dvander@62
    88
                    sizeof(LocalSlot) * (fun ? fun->nargs() : 0);
dvander@62
    89
dvander@62
    90
    top_->pc = top_->fp->prevpc();
dvander@62
    91
    top_->sp = reinterpret_cast<LocalSlot *>(reinterpret_cast<char *>(top_->sp) - nbytes);
dvander@62
    92
    top_->fp = prev;
dvander@62
    93
    return prev;
dvander@62
    94
}
dvander@62
    95
dvander@62
    96
void
dvander@62
    97
Frame::accept(VirtualObjectVisitor *visitor)
dvander@62
    98
{
dvander@62
    99
    visitor->visit(reinterpret_cast<Object **>(&fun_));
dvander@62
   100
    visitor->visit(reinterpret_cast<Object **>(&code_));
dvander@62
   101
}
dvander@62
   102
dvander@62
   103
static void
dvander@62
   104
TraceFrame(VirtualObjectVisitor *visitor, Frame *fp, LocalSlot *sp, bytecode *pc)
dvander@62
   105
{
dvander@62
   106
    Code *code = fp->code();
dvander@62
   107
    LocalSlot *slots = fp->locals();
dvander@62
   108
dvander@62
   109
    // Trace local variables.
dvander@62
   110
    for (unsigned i = 0; i < code->nlocals(); i++) {
dvander@62
   111
        Type *type = code->localType(i);
dvander@62
   112
        if (type->isTraceable())
dvander@62
   113
            visitor->visit(&slots[i].obj);
dvander@62
   114
    }
dvander@62
   115
dvander@62
   116
    // Trace arguments, if a function call.
dvander@62
   117
    if (Function *fun = fp->maybeFun()) {
dvander@62
   118
        for (unsigned i = 0; i < fun->nargs(); i++) {
dvander@62
   119
            Type *type = fun->argType(i);
dvander@62
   120
            if (type->isTraceable())
dvander@62
   121
                visitor->visit(&fp->arg(i).obj);
dvander@62
   122
        }
dvander@62
   123
    }
dvander@62
   124
dvander@62
   125
    // Finally, trace stack slots. Not every gc-point in the bytecode will
dvander@62
   126
    // have a safepoint; since they are actually uncommon, we don't emit
dvander@62
   127
    // them unless at least one stack slot would be marked.
dvander@62
   128
    if (uint8 *safepoint = code->safepointAt(code->pcToOffset(pc))) {
dvander@62
   129
        LocalSlot *base = fp->stackBase();
dvander@62
   130
        unsigned stackDepth = unsigned(sp - fp->stackBase());
dvander@62
   131
        assert(stackDepth <= code->maxStackDepth());
dvander@62
   132
dvander@62
   133
        for (unsigned i = 0; i < stackDepth; i++) {
dvander@62
   134
            if (safepoint[i / 8] & (1 << (i % 8)))
dvander@62
   135
                visitor->visit(&base[i].obj);
dvander@62
   136
        }
dvander@62
   137
    }
dvander@62
   138
}
dvander@62
   139
dvander@62
   140
void
dvander@62
   141
Stack::accept(VirtualObjectVisitor *visitor)
dvander@62
   142
{
dvander@62
   143
    if (!top_)
dvander@62
   144
        return;
dvander@62
   145
dvander@62
   146
    LocalSlot *sp = top_->sp;
dvander@62
   147
    bytecode *pc = top_->pc;
dvander@62
   148
dvander@62
   149
    for (Frame *frame = top_->fp; frame; frame = frame->prev()) {
dvander@62
   150
        TraceFrame(visitor, frame, sp, pc);
dvander@62
   151
        sp = reinterpret_cast<LocalSlot *>(frame);
dvander@62
   152
        pc = frame->prevpc();
dvander@62
   153
    }
dvander@62
   154
}
dvander@62
   155
dvander@62
   156
bool
dvander@62
   157
Stack::isInCallStack(Handle<Module> module)
dvander@62
   158
{
dvander@62
   159
    if (!top_)
dvander@62
   160
        return false;
dvander@62
   161
dvander@62
   162
    for (Frame *frame = top_->fp; frame; frame = frame->prev()) {
dvander@62
   163
        if (frame->code()->module() == module)
dvander@62
   164
            return true;
dvander@62
   165
    }
dvander@62
   166
    return false;
dvander@62
   167
}