jitcraft/Stack.h
author David Anderson <dvander@alliedmods.net>
Wed Jun 27 02:21:56 2012 -0700 (2012-06-27)
changeset 4 633176823669
parent 1 27f12e2fc369
child 10 0c3bcd50e361
permissions -rw-r--r--
Add support for float variables and basic math.
     1 /*
     2  * Copyright (C) 2012 David Anderson
     3  *
     4  * This file is part of JITCraft.
     5  *
     6  * JITCraft is free software: you can redistribute it and/or modify it under
     7  * the terms of the GNU General Public License as published by the Free
     8  * Software Foundation, either version 3 of the License, or (at your option)
     9  * any later version.
    10  * 
    11  * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    13  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    14  *
    15  * You should have received a copy of the GNU General Public License along with
    16  * JITCraft. If not, see http://www.gnu.org/licenses/.
    17  */
    18 #ifndef _include_jc_stack_h_
    19 #define _include_jc_stack_h_
    20 
    21 #include <stddef.h>
    22 #include "Utility.h"
    23 #include "Code.h"
    24 #include "UnsafeArray.h"
    25 
    26 namespace jc {
    27     
    28 union LocalSlot
    29 {
    30     int i32;
    31     float f;
    32     void *p;
    33     UnsafeArray *unsafeArray;
    34 };
    35 
    36 struct Top
    37 {
    38     LocalSlot *sp;
    39     bytecode *pc;
    40 
    41     Top(LocalSlot *sp, bytecode *pc)
    42       : sp(sp), pc(pc)
    43     {
    44     }
    45 
    46     Top(LocalSlot *sp)
    47       : sp(sp), pc(NULL)
    48     {
    49     }
    50 };
    51 
    52 class Frame
    53 {
    54     friend class Stack;
    55 
    56     Frame *prev_;
    57     bytecode *prevpc_;
    58     Code *code_;
    59     void *prevUnsafeStack_;
    60 
    61   public:
    62     Frame(Frame *prev, bytecode *prevpc, Code *code, void *prevUnsafeStack)
    63       : prev_(prev),
    64         prevpc_(prevpc),
    65         code_(code),
    66         prevUnsafeStack_(prevUnsafeStack)
    67     {
    68     }
    69 
    70     LocalSlot *locals() {
    71         return reinterpret_cast<LocalSlot *>(this + 1);
    72     }
    73     LocalSlot *stackBase() {
    74         return locals() + code_->nlocals();
    75     }
    76     Code *code() const {
    77         return code_;
    78     }
    79     Frame *prev() const {
    80         return prev_;
    81     }
    82     bytecode *prevpc() const {
    83         return prevpc_;
    84     }
    85     void *prevUnsafeStack() const {
    86         return prevUnsafeStack_;
    87     }
    88     LocalSlot &arg(unsigned slot) {
    89         assert(slot < code()->nargs());
    90         return *(reinterpret_cast<LocalSlot *>(this) - slot - 1);
    91     }
    92 };
    93 
    94 class Stack
    95 {
    96     char *buffer_;
    97     char *end_;
    98     Top *top_;
    99 
   100   private:
   101     static const size_t STACK_SIZE = 1024 * 1024;
   102 
   103   public:
   104     Stack();
   105     ~Stack();
   106 
   107     bool initialize();
   108 
   109   public:
   110     Frame *pushFrame(Frame *prev, Code *code);
   111     Frame *popFrame(Frame *frame);
   112 
   113     Top *top() {
   114         return top_;
   115     }
   116     void setTop(Top *top) {
   117         top_ = top;
   118     }
   119     Top begin() {
   120         return Top((LocalSlot *)buffer_);
   121     }
   122 };
   123 
   124 // The unsafe stack is designed for structures which interop unsafely with C++.
   125 // In this stack, buffers can be overrun, even inside the VM - but with two
   126 // caveats:
   127 //
   128 //  The unsafe stack cannot hold safe references.
   129 //  Indirect reads and writes from the unsafe stack cannot escape the unsafe
   130 //  stack.
   131 class UnsafeStack
   132 {
   133     char *buffer_;
   134     char *pos_;
   135     char *end_;
   136 
   137   private:
   138     static const size_t STACK_SIZE = 1024 * 1024;
   139 
   140   public:
   141     UnsafeStack();
   142     ~UnsafeStack();
   143     bool initialize();
   144 
   145   public:
   146     void *position() const {
   147         return pos_;
   148     }
   149     void *allocate(size_t nbytes) {
   150         nbytes = Align(nbytes, kMallocAlignment);
   151 
   152         if (pos_ + nbytes > end_) {
   153             assert(false);
   154             return NULL;
   155         }
   156 
   157         void *ptr = buffer_;
   158         pos_ += nbytes;
   159         return ptr;
   160     }
   161 
   162     void unwind(void *to) {
   163         char *p = (char *)to;
   164         assert(p < pos_ && p >= buffer_);
   165         pos_ = p;
   166     }
   167 };
   168 
   169 }
   170 
   171 #endif // _include_jc_stack_h_