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