src/Stack.h
author David Anderson <dvander@alliedmods.net>
Wed Dec 26 17:19:49 2012 -0800 (2012-12-26)
changeset 243 3d94c73a824c
parent 230 fb3cd08bc7fb
child 263 ba85a47ee414
permissions -rw-r--r--
Fix build bustage.
dvander@47
     1
/* vim: set ts=4 sw=4 tw=99 et:
dvander@47
     2
 *
dvander@0
     3
 * Copyright (C) 2012 David Anderson
dvander@0
     4
 *
dvander@0
     5
 * This file is part of JITCraft.
dvander@0
     6
 *
dvander@0
     7
 * JITCraft is free software: you can redistribute it and/or modify it under
dvander@0
     8
 * the terms of the GNU General Public License as published by the Free
dvander@0
     9
 * Software Foundation, either version 3 of the License, or (at your option)
dvander@0
    10
 * any later version.
dvander@0
    11
 * 
dvander@0
    12
 * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
dvander@0
    13
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@0
    14
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
dvander@0
    15
 *
dvander@0
    16
 * You should have received a copy of the GNU General Public License along with
dvander@0
    17
 * JITCraft. If not, see http://www.gnu.org/licenses/.
dvander@0
    18
 */
dvander@0
    19
#ifndef _include_jc_stack_h_
dvander@0
    20
#define _include_jc_stack_h_
dvander@0
    21
dvander@0
    22
#include <stddef.h>
dvander@0
    23
#include "Utility.h"
dvander@0
    24
#include "Code.h"
dvander@26
    25
#include "Functions.h"
dvander@47
    26
#include "VirtualObjectVisitor.h"
dvander@0
    27
dvander@59
    28
namespace ke {
dvander@12
    29
dvander@12
    30
class Object;
dvander@12
    31
class Array;
dvander@14
    32
class Reference;
dvander@47
    33
class Frame;
dvander@65
    34
class Stack;
dvander@69
    35
class Zone;
dvander@73
    36
class Module;
dvander@0
    37
    
dvander@0
    38
union LocalSlot
dvander@0
    39
{
dvander@0
    40
    int i32;
dvander@4
    41
    float f;
dvander@12
    42
    Address address;
dvander@12
    43
    Object *obj;
dvander@12
    44
    Array *array;
dvander@14
    45
    Reference *ref;
dvander@73
    46
    Function *fun;
dvander@73
    47
    Module *module;
dvander@0
    48
};
dvander@0
    49
dvander@0
    50
struct Top
dvander@0
    51
{
dvander@0
    52
    LocalSlot *sp;
dvander@0
    53
    bytecode *pc;
dvander@47
    54
    Frame *fp;
dvander@0
    55
};
dvander@0
    56
dvander@0
    57
class Frame
dvander@0
    58
{
dvander@0
    59
    friend class Stack;
dvander@0
    60
dvander@0
    61
    Frame *prev_;
dvander@0
    62
    bytecode *prevpc_;
dvander@68
    63
    union {
dvander@68
    64
        Function *fun_;
dvander@68
    65
        Native *native_;
dvander@68
    66
        Object *callee_;
dvander@68
    67
    };
dvander@0
    68
    Code *code_;
dvander@230
    69
dvander@230
    70
    // Position of the LIFO stack at function entry.
dvander@12
    71
    Address lifoPosition_;
dvander@230
    72
    
dvander@230
    73
    // Loop nesting level, for LIFO stack balancing. LIFO stack balancing
dvander@230
    74
    // is not strictly required, but it helps to avoid unnecessary waste,
dvander@230
    75
    // since once the LIFO stack is depleted, we must use the heap instead.
dvander@230
    76
    unsigned loopDepth_;
dvander@0
    77
dvander@0
    78
  public:
dvander@26
    79
    Frame(Frame *prev, bytecode *prevpc, Function *fun, Code *code, Address lifoPosition)
dvander@0
    80
      : prev_(prev),
dvander@0
    81
        prevpc_(prevpc),
dvander@26
    82
        fun_(fun),
dvander@1
    83
        code_(code),
dvander@230
    84
        lifoPosition_(lifoPosition),
dvander@230
    85
        loopDepth_(0)
dvander@0
    86
    {
dvander@0
    87
    }
dvander@0
    88
dvander@68
    89
    Frame(Frame *prev, bytecode *prevpc, Native *native, Address lifoPosition)
dvander@68
    90
      : prev_(prev),
dvander@68
    91
        prevpc_(prevpc),
dvander@68
    92
        native_(native),
dvander@68
    93
        code_(NULL),
dvander@68
    94
        lifoPosition_(lifoPosition)
dvander@68
    95
    {
dvander@68
    96
    }
dvander@68
    97
dvander@230
    98
    Address *loopStack() {
dvander@230
    99
        return reinterpret_cast<Address *>(this + 1);
dvander@230
   100
    }
dvander@0
   101
    LocalSlot *locals() {
dvander@230
   102
        return reinterpret_cast<LocalSlot *>(loopStack() + code_->maxLoopDepth());
dvander@0
   103
    }
dvander@0
   104
    LocalSlot *stackBase() {
dvander@0
   105
        return locals() + code_->nlocals();
dvander@0
   106
    }
dvander@26
   107
    Function *fun() const {
dvander@68
   108
        assert(fun_ && callee_->is(MapKind_Function));
dvander@26
   109
        return fun_;
dvander@26
   110
    }
dvander@26
   111
    Function *maybeFun() const {
dvander@68
   112
        return (fun_ && callee_->is(MapKind_Function)) ? fun_ : NULL;
dvander@68
   113
    }
dvander@68
   114
    bool isNative() const {
dvander@68
   115
        return callee_ && callee_->is(MapKind_Native);
dvander@26
   116
    }
dvander@69
   117
    Native *native() const {
dvander@69
   118
        assert(isNative());
dvander@69
   119
        return native_;
dvander@69
   120
    }
dvander@0
   121
    Code *code() const {
dvander@68
   122
        assert(code_);
dvander@0
   123
        return code_;
dvander@0
   124
    }
dvander@0
   125
    Frame *prev() const {
dvander@0
   126
        return prev_;
dvander@0
   127
    }
dvander@0
   128
    bytecode *prevpc() const {
dvander@0
   129
        return prevpc_;
dvander@0
   130
    }
dvander@12
   131
    Address lifoPosition() const {
dvander@12
   132
        return lifoPosition_;
dvander@1
   133
    }
dvander@0
   134
    LocalSlot &arg(unsigned slot) {
dvander@26
   135
        assert(slot < fun()->nargs());
dvander@0
   136
        return *(reinterpret_cast<LocalSlot *>(this) - slot - 1);
dvander@0
   137
    }
dvander@230
   138
    void enterLoop(Zone *zone);
dvander@230
   139
    void leaveLoop(Zone *zone);
dvander@47
   140
    void accept(VirtualObjectVisitor *visitor);
dvander@0
   141
};
dvander@0
   142
dvander@65
   143
// RAII object for calling a function from C++.
dvander@65
   144
class InvokeArgs
dvander@65
   145
{
dvander@65
   146
    friend class Stack;
dvander@65
   147
dvander@65
   148
    Stack *stack_;
dvander@65
   149
    LocalSlot *args_;
dvander@65
   150
    unsigned nargs_;
dvander@65
   151
dvander@65
   152
  public:
dvander@65
   153
    InvokeArgs()
dvander@65
   154
      : stack_(NULL),
dvander@65
   155
        args_(NULL),
dvander@65
   156
        nargs_(0)
dvander@65
   157
    {
dvander@65
   158
    }
dvander@65
   159
dvander@65
   160
    ~InvokeArgs();
dvander@65
   161
dvander@65
   162
    LocalSlot &arg(unsigned index) {
dvander@65
   163
        assert(index < nargs_);
dvander@65
   164
        return args_[nargs_ - index - 1];
dvander@65
   165
    }
dvander@65
   166
};
dvander@65
   167
dvander@68
   168
// RAII object for calling a native from C++.
dvander@68
   169
class NativeArgs
dvander@68
   170
{
dvander@68
   171
    friend class Stack;
dvander@68
   172
dvander@68
   173
    Stack *stack_;
dvander@68
   174
    LocalSlot *argsBase_;
dvander@68
   175
dvander@68
   176
  public:
dvander@68
   177
    NativeArgs()
dvander@68
   178
      : stack_(NULL),
dvander@68
   179
        argsBase_(NULL)
dvander@68
   180
    {
dvander@68
   181
    }
dvander@68
   182
dvander@68
   183
    ~NativeArgs();
dvander@68
   184
dvander@68
   185
    intptr_t *args() {
dvander@86
   186
        return reinterpret_cast<intptr_t *>(argsBase_);
dvander@68
   187
    }
dvander@68
   188
};
dvander@68
   189
dvander@0
   190
class Stack
dvander@0
   191
{
dvander@65
   192
    friend class InvokeArgs;
dvander@68
   193
    friend class NativeArgs;
dvander@0
   194
dvander@0
   195
  private:
dvander@0
   196
    static const size_t STACK_SIZE = 1024 * 1024;
dvander@0
   197
dvander@0
   198
  public:
dvander@69
   199
    Stack(Zone *zone);
dvander@0
   200
    ~Stack();
dvander@0
   201
dvander@0
   202
    bool initialize();
dvander@0
   203
dvander@0
   204
  public:
dvander@65
   205
    Frame *pushInlineFrame(Handle<Function> fun);
dvander@65
   206
    Frame *popInlineFrame();
dvander@65
   207
dvander@65
   208
    bool pushInvokeFrame(Handle<Function> fun, InvokeArgs &args);
dvander@85
   209
    bool pushModuleFrame(Handle<Module> module, InvokeArgs &args);
dvander@68
   210
    bool pushNativeFrame(Handle<Native> native, NativeArgs &args, unsigned argc);
dvander@0
   211
dvander@0
   212
    Top *top() {
dvander@65
   213
        return &top_;
dvander@0
   214
    }
dvander@62
   215
    bool isInCallStack(Handle<Module> module);
dvander@47
   216
    void accept(VirtualObjectVisitor *visitor);
dvander@65
   217
dvander@65
   218
  private:
dvander@65
   219
    void popInvokeFrame(InvokeArgs &args);
dvander@68
   220
    void popNativeFrame(NativeArgs &args);
dvander@65
   221
dvander@65
   222
  private:
dvander@69
   223
    Zone *zone_;
dvander@65
   224
    char *buffer_;
dvander@65
   225
    char *end_;
dvander@65
   226
    Top top_;
dvander@0
   227
};
dvander@0
   228
dvander@69
   229
class StackIter
dvander@69
   230
{
dvander@69
   231
    bytecode *pc_;
dvander@69
   232
    Frame *fp_;
dvander@69
   233
dvander@69
   234
  public:
dvander@69
   235
    StackIter(Zone *zone);
dvander@69
   236
dvander@69
   237
    bool done() const;
dvander@69
   238
    const char *function() const;
dvander@69
   239
    unsigned lineNumber() const;
dvander@69
   240
    const char *source() const;
dvander@69
   241
    void prev();
dvander@69
   242
};
dvander@69
   243
dvander@0
   244
}
dvander@0
   245
dvander@0
   246
#endif // _include_jc_stack_h_