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