jitcraft/Stack.cpp
author David Anderson <dvander@alliedmods.net>
Mon Jul 09 01:22:03 2012 -0700 (2012-07-09)
changeset 65 7c942b5adebc
parent 62 e04c5be84792
child 68 b40b0e18a918
permissions -rw-r--r--
Added ISPE-oriented API for invoking functions.
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@65
    29
    end_(NULL)
dvander@62
    30
{
dvander@62
    31
}
dvander@62
    32
dvander@62
    33
Stack::~Stack()
dvander@62
    34
{
dvander@62
    35
    free(buffer_);
dvander@62
    36
}
dvander@62
    37
dvander@62
    38
bool
dvander@62
    39
Stack::initialize()
dvander@62
    40
{
dvander@62
    41
    buffer_ = (char *)malloc(STACK_SIZE);
dvander@62
    42
    if (!buffer_)
dvander@62
    43
        return false;
dvander@62
    44
dvander@65
    45
    top_.sp = reinterpret_cast<LocalSlot *>(buffer_);
dvander@65
    46
    top_.pc = NULL;
dvander@65
    47
    top_.fp = NULL;
dvander@62
    48
    end_ = buffer_ + STACK_SIZE;
dvander@62
    49
    return true;
dvander@62
    50
}
dvander@62
    51
dvander@65
    52
InvokeArgs::~InvokeArgs()
dvander@65
    53
{
dvander@65
    54
    stack_->popInvokeFrame(*this);
dvander@65
    55
}
dvander@65
    56
dvander@62
    57
static inline size_t
dvander@62
    58
SizeForCodeFrame(Code *code)
dvander@62
    59
{
dvander@62
    60
    return sizeof(Frame) + sizeof(LocalSlot) * (code->nlocals() + code->maxStackDepth());
dvander@62
    61
}
dvander@62
    62
dvander@65
    63
bool
dvander@65
    64
Stack::pushInvokeFrame(Handle<Function> fun, InvokeArgs &args)
dvander@65
    65
{
dvander@65
    66
    size_t nbytes = SizeForCodeFrame(fun->code()) +
dvander@65
    67
                    sizeof(LocalSlot) * fun->nargs();
dvander@65
    68
    if (reinterpret_cast<char *>(top_.sp) + nbytes >= end_) {
dvander@65
    69
        assert(false);
dvander@65
    70
        return false;
dvander@65
    71
    }
dvander@65
    72
dvander@65
    73
    memset(top_.sp, 0, sizeof(LocalSlot) * fun->nargs());
dvander@65
    74
    args.args_ = top_.sp;
dvander@65
    75
    args.nargs_ = fun->nargs();
dvander@65
    76
    args.stack_ = this;
dvander@65
    77
    top_.sp += fun->nargs();
dvander@65
    78
    
dvander@65
    79
    Frame *frame = reinterpret_cast<Frame *>(top_.sp);
dvander@65
    80
    new (frame) Frame(top_.fp, top_.pc, fun, fun->code(), ZONE()->heap().lifoPosition());
dvander@65
    81
    
dvander@65
    82
    top_.pc = frame->code()->start();
dvander@65
    83
    top_.sp = frame->stackBase();
dvander@65
    84
    top_.fp = frame;
dvander@65
    85
dvander@65
    86
    return true;
dvander@65
    87
}
dvander@65
    88
dvander@62
    89
Frame *
dvander@65
    90
Stack::pushInlineFrame(Handle<Function> fun)
dvander@62
    91
{
dvander@62
    92
    Code *code = fun->code();
dvander@62
    93
    size_t nbytes = SizeForCodeFrame(code);
dvander@65
    94
    if (reinterpret_cast<char *>(top_.sp) + nbytes >= end_) {
dvander@65
    95
        assert(false);
dvander@62
    96
        return NULL;
dvander@65
    97
    }
dvander@62
    98
dvander@65
    99
    Frame *frame = reinterpret_cast<Frame *>(top_.sp);
dvander@65
   100
    new (frame) Frame(top_.fp, top_.pc, fun, code, ZONE()->heap().lifoPosition());
dvander@62
   101
    memset(frame->locals(), 0, sizeof(LocalSlot) * code->nlocals());
dvander@62
   102
dvander@65
   103
    top_.pc = frame->code()->start();
dvander@65
   104
    top_.sp = frame->stackBase();
dvander@65
   105
    top_.fp = frame;
dvander@62
   106
dvander@62
   107
    return frame;
dvander@62
   108
}
dvander@62
   109
dvander@62
   110
dvander@62
   111
Frame *
dvander@65
   112
Stack::popInlineFrame()
dvander@62
   113
{
dvander@65
   114
    ZONE()->heap().unwindLifo(top_.fp->lifoPosition());
dvander@62
   115
dvander@65
   116
    Frame *prev = top_.fp->prev();
dvander@65
   117
    Function *fun = top_.fp->maybeFun();
dvander@65
   118
    Code *code = top_.fp->code();
dvander@62
   119
dvander@62
   120
    size_t nbytes = sizeof(LocalSlot) * code->nlocals() +
dvander@62
   121
                    sizeof(Frame) +
dvander@62
   122
                    sizeof(LocalSlot) * (fun ? fun->nargs() : 0);
dvander@62
   123
dvander@65
   124
    top_.pc = top_.fp->prevpc();
dvander@65
   125
    top_.sp = reinterpret_cast<LocalSlot *>(reinterpret_cast<char *>(top_.sp) - nbytes);
dvander@65
   126
    top_.fp = prev;
dvander@62
   127
    return prev;
dvander@62
   128
}
dvander@62
   129
dvander@62
   130
void
dvander@65
   131
Stack::popInvokeFrame(InvokeArgs &args)
dvander@65
   132
{
dvander@65
   133
    ZONE()->heap().unwindLifo(top_.fp->lifoPosition());
dvander@65
   134
dvander@65
   135
    top_.pc = top_.fp->prevpc();
dvander@65
   136
    top_.sp = args.args_;
dvander@65
   137
    top_.fp = top_.fp->prev();
dvander@65
   138
}
dvander@65
   139
dvander@65
   140
void
dvander@62
   141
Frame::accept(VirtualObjectVisitor *visitor)
dvander@62
   142
{
dvander@62
   143
    visitor->visit(reinterpret_cast<Object **>(&fun_));
dvander@62
   144
    visitor->visit(reinterpret_cast<Object **>(&code_));
dvander@62
   145
}
dvander@62
   146
dvander@62
   147
static void
dvander@62
   148
TraceFrame(VirtualObjectVisitor *visitor, Frame *fp, LocalSlot *sp, bytecode *pc)
dvander@62
   149
{
dvander@62
   150
    Code *code = fp->code();
dvander@62
   151
    LocalSlot *slots = fp->locals();
dvander@62
   152
dvander@62
   153
    // Trace local variables.
dvander@62
   154
    for (unsigned i = 0; i < code->nlocals(); i++) {
dvander@62
   155
        Type *type = code->localType(i);
dvander@62
   156
        if (type->isTraceable())
dvander@62
   157
            visitor->visit(&slots[i].obj);
dvander@62
   158
    }
dvander@62
   159
dvander@65
   160
    // Trace arguments, if a function call. Note that this means we usually
dvander@65
   161
    // mark arguments twice, once on the caller side and once on the callee.
dvander@65
   162
    // This makes it easier to deal with invoke frames which have no caller.
dvander@62
   163
    if (Function *fun = fp->maybeFun()) {
dvander@62
   164
        for (unsigned i = 0; i < fun->nargs(); i++) {
dvander@62
   165
            Type *type = fun->argType(i);
dvander@62
   166
            if (type->isTraceable())
dvander@62
   167
                visitor->visit(&fp->arg(i).obj);
dvander@62
   168
        }
dvander@62
   169
    }
dvander@62
   170
dvander@62
   171
    // Finally, trace stack slots. Not every gc-point in the bytecode will
dvander@62
   172
    // have a safepoint; since they are actually uncommon, we don't emit
dvander@62
   173
    // them unless at least one stack slot would be marked.
dvander@62
   174
    if (uint8 *safepoint = code->safepointAt(code->pcToOffset(pc))) {
dvander@62
   175
        LocalSlot *base = fp->stackBase();
dvander@62
   176
        unsigned stackDepth = unsigned(sp - fp->stackBase());
dvander@62
   177
        assert(stackDepth <= code->maxStackDepth());
dvander@62
   178
dvander@62
   179
        for (unsigned i = 0; i < stackDepth; i++) {
dvander@62
   180
            if (safepoint[i / 8] & (1 << (i % 8)))
dvander@62
   181
                visitor->visit(&base[i].obj);
dvander@62
   182
        }
dvander@62
   183
    }
dvander@62
   184
}
dvander@62
   185
dvander@62
   186
void
dvander@62
   187
Stack::accept(VirtualObjectVisitor *visitor)
dvander@62
   188
{
dvander@65
   189
    LocalSlot *sp = top_.sp;
dvander@65
   190
    bytecode *pc = top_.pc;
dvander@62
   191
dvander@65
   192
    for (Frame *frame = top_.fp; frame; frame = frame->prev()) {
dvander@62
   193
        TraceFrame(visitor, frame, sp, pc);
dvander@62
   194
        sp = reinterpret_cast<LocalSlot *>(frame);
dvander@62
   195
        pc = frame->prevpc();
dvander@62
   196
    }
dvander@62
   197
}
dvander@62
   198
dvander@62
   199
bool
dvander@62
   200
Stack::isInCallStack(Handle<Module> module)
dvander@62
   201
{
dvander@65
   202
    for (Frame *frame = top_.fp; frame; frame = frame->prev()) {
dvander@62
   203
        if (frame->code()->module() == module)
dvander@62
   204
            return true;
dvander@62
   205
    }
dvander@62
   206
    return false;
dvander@62
   207
}
dvander@65
   208
dvander@65
   209