src/Stack.h
changeset 263 ba85a47ee414
parent 230 fb3cd08bc7fb
     1.1 --- a/src/Stack.h	Mon Jun 10 00:46:29 2013 +0100
     1.2 +++ b/src/Stack.h	Mon Jun 10 01:04:43 2013 +0100
     1.3 @@ -1,246 +1,246 @@
     1.4 -/* vim: set ts=4 sw=4 tw=99 et:
     1.5 - *
     1.6 - * Copyright (C) 2012 David Anderson
     1.7 - *
     1.8 - * This file is part of JITCraft.
     1.9 - *
    1.10 - * JITCraft is free software: you can redistribute it and/or modify it under
    1.11 - * the terms of the GNU General Public License as published by the Free
    1.12 - * Software Foundation, either version 3 of the License, or (at your option)
    1.13 - * any later version.
    1.14 - * 
    1.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    1.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    1.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    1.18 - *
    1.19 - * You should have received a copy of the GNU General Public License along with
    1.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
    1.21 - */
    1.22 -#ifndef _include_jc_stack_h_
    1.23 -#define _include_jc_stack_h_
    1.24 -
    1.25 -#include <stddef.h>
    1.26 -#include "Utility.h"
    1.27 -#include "Code.h"
    1.28 -#include "Functions.h"
    1.29 -#include "VirtualObjectVisitor.h"
    1.30 -
    1.31 -namespace ke {
    1.32 -
    1.33 -class Object;
    1.34 -class Array;
    1.35 -class Reference;
    1.36 -class Frame;
    1.37 -class Stack;
    1.38 -class Zone;
    1.39 -class Module;
    1.40 -    
    1.41 -union LocalSlot
    1.42 -{
    1.43 -    int i32;
    1.44 -    float f;
    1.45 -    Address address;
    1.46 -    Object *obj;
    1.47 -    Array *array;
    1.48 -    Reference *ref;
    1.49 -    Function *fun;
    1.50 -    Module *module;
    1.51 -};
    1.52 -
    1.53 -struct Top
    1.54 -{
    1.55 -    LocalSlot *sp;
    1.56 -    bytecode *pc;
    1.57 -    Frame *fp;
    1.58 -};
    1.59 -
    1.60 -class Frame
    1.61 -{
    1.62 -    friend class Stack;
    1.63 -
    1.64 -    Frame *prev_;
    1.65 -    bytecode *prevpc_;
    1.66 -    union {
    1.67 -        Function *fun_;
    1.68 -        Native *native_;
    1.69 -        Object *callee_;
    1.70 -    };
    1.71 -    Code *code_;
    1.72 -
    1.73 -    // Position of the LIFO stack at function entry.
    1.74 -    Address lifoPosition_;
    1.75 -    
    1.76 -    // Loop nesting level, for LIFO stack balancing. LIFO stack balancing
    1.77 -    // is not strictly required, but it helps to avoid unnecessary waste,
    1.78 -    // since once the LIFO stack is depleted, we must use the heap instead.
    1.79 -    unsigned loopDepth_;
    1.80 -
    1.81 -  public:
    1.82 -    Frame(Frame *prev, bytecode *prevpc, Function *fun, Code *code, Address lifoPosition)
    1.83 -      : prev_(prev),
    1.84 -        prevpc_(prevpc),
    1.85 -        fun_(fun),
    1.86 -        code_(code),
    1.87 -        lifoPosition_(lifoPosition),
    1.88 -        loopDepth_(0)
    1.89 -    {
    1.90 -    }
    1.91 -
    1.92 -    Frame(Frame *prev, bytecode *prevpc, Native *native, Address lifoPosition)
    1.93 -      : prev_(prev),
    1.94 -        prevpc_(prevpc),
    1.95 -        native_(native),
    1.96 -        code_(NULL),
    1.97 -        lifoPosition_(lifoPosition)
    1.98 -    {
    1.99 -    }
   1.100 -
   1.101 -    Address *loopStack() {
   1.102 -        return reinterpret_cast<Address *>(this + 1);
   1.103 -    }
   1.104 -    LocalSlot *locals() {
   1.105 -        return reinterpret_cast<LocalSlot *>(loopStack() + code_->maxLoopDepth());
   1.106 -    }
   1.107 -    LocalSlot *stackBase() {
   1.108 -        return locals() + code_->nlocals();
   1.109 -    }
   1.110 -    Function *fun() const {
   1.111 -        assert(fun_ && callee_->is(MapKind_Function));
   1.112 -        return fun_;
   1.113 -    }
   1.114 -    Function *maybeFun() const {
   1.115 -        return (fun_ && callee_->is(MapKind_Function)) ? fun_ : NULL;
   1.116 -    }
   1.117 -    bool isNative() const {
   1.118 -        return callee_ && callee_->is(MapKind_Native);
   1.119 -    }
   1.120 -    Native *native() const {
   1.121 -        assert(isNative());
   1.122 -        return native_;
   1.123 -    }
   1.124 -    Code *code() const {
   1.125 -        assert(code_);
   1.126 -        return code_;
   1.127 -    }
   1.128 -    Frame *prev() const {
   1.129 -        return prev_;
   1.130 -    }
   1.131 -    bytecode *prevpc() const {
   1.132 -        return prevpc_;
   1.133 -    }
   1.134 -    Address lifoPosition() const {
   1.135 -        return lifoPosition_;
   1.136 -    }
   1.137 -    LocalSlot &arg(unsigned slot) {
   1.138 -        assert(slot < fun()->nargs());
   1.139 -        return *(reinterpret_cast<LocalSlot *>(this) - slot - 1);
   1.140 -    }
   1.141 -    void enterLoop(Zone *zone);
   1.142 -    void leaveLoop(Zone *zone);
   1.143 -    void accept(VirtualObjectVisitor *visitor);
   1.144 -};
   1.145 -
   1.146 -// RAII object for calling a function from C++.
   1.147 -class InvokeArgs
   1.148 -{
   1.149 -    friend class Stack;
   1.150 -
   1.151 -    Stack *stack_;
   1.152 -    LocalSlot *args_;
   1.153 -    unsigned nargs_;
   1.154 -
   1.155 -  public:
   1.156 -    InvokeArgs()
   1.157 -      : stack_(NULL),
   1.158 -        args_(NULL),
   1.159 -        nargs_(0)
   1.160 -    {
   1.161 -    }
   1.162 -
   1.163 -    ~InvokeArgs();
   1.164 -
   1.165 -    LocalSlot &arg(unsigned index) {
   1.166 -        assert(index < nargs_);
   1.167 -        return args_[nargs_ - index - 1];
   1.168 -    }
   1.169 -};
   1.170 -
   1.171 -// RAII object for calling a native from C++.
   1.172 -class NativeArgs
   1.173 -{
   1.174 -    friend class Stack;
   1.175 -
   1.176 -    Stack *stack_;
   1.177 -    LocalSlot *argsBase_;
   1.178 -
   1.179 -  public:
   1.180 -    NativeArgs()
   1.181 -      : stack_(NULL),
   1.182 -        argsBase_(NULL)
   1.183 -    {
   1.184 -    }
   1.185 -
   1.186 -    ~NativeArgs();
   1.187 -
   1.188 -    intptr_t *args() {
   1.189 -        return reinterpret_cast<intptr_t *>(argsBase_);
   1.190 -    }
   1.191 -};
   1.192 -
   1.193 -class Stack
   1.194 -{
   1.195 -    friend class InvokeArgs;
   1.196 -    friend class NativeArgs;
   1.197 -
   1.198 -  private:
   1.199 -    static const size_t STACK_SIZE = 1024 * 1024;
   1.200 -
   1.201 -  public:
   1.202 -    Stack(Zone *zone);
   1.203 -    ~Stack();
   1.204 -
   1.205 -    bool initialize();
   1.206 -
   1.207 -  public:
   1.208 -    Frame *pushInlineFrame(Handle<Function> fun);
   1.209 -    Frame *popInlineFrame();
   1.210 -
   1.211 -    bool pushInvokeFrame(Handle<Function> fun, InvokeArgs &args);
   1.212 -    bool pushModuleFrame(Handle<Module> module, InvokeArgs &args);
   1.213 -    bool pushNativeFrame(Handle<Native> native, NativeArgs &args, unsigned argc);
   1.214 -
   1.215 -    Top *top() {
   1.216 -        return &top_;
   1.217 -    }
   1.218 -    bool isInCallStack(Handle<Module> module);
   1.219 -    void accept(VirtualObjectVisitor *visitor);
   1.220 -
   1.221 -  private:
   1.222 -    void popInvokeFrame(InvokeArgs &args);
   1.223 -    void popNativeFrame(NativeArgs &args);
   1.224 -
   1.225 -  private:
   1.226 -    Zone *zone_;
   1.227 -    char *buffer_;
   1.228 -    char *end_;
   1.229 -    Top top_;
   1.230 -};
   1.231 -
   1.232 -class StackIter
   1.233 -{
   1.234 -    bytecode *pc_;
   1.235 -    Frame *fp_;
   1.236 -
   1.237 -  public:
   1.238 -    StackIter(Zone *zone);
   1.239 -
   1.240 -    bool done() const;
   1.241 -    const char *function() const;
   1.242 -    unsigned lineNumber() const;
   1.243 -    const char *source() const;
   1.244 -    void prev();
   1.245 -};
   1.246 -
   1.247 -}
   1.248 -
   1.249 -#endif // _include_jc_stack_h_
   1.250 +/* vim: set ts=4 sw=4 tw=99 et:
   1.251 + *
   1.252 + * Copyright (C) 2012 David Anderson
   1.253 + *
   1.254 + * This file is part of JITCraft.
   1.255 + *
   1.256 + * JITCraft is free software: you can redistribute it and/or modify it under
   1.257 + * the terms of the GNU General Public License as published by the Free
   1.258 + * Software Foundation, either version 3 of the License, or (at your option)
   1.259 + * any later version.
   1.260 + * 
   1.261 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
   1.262 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   1.263 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   1.264 + *
   1.265 + * You should have received a copy of the GNU General Public License along with
   1.266 + * JITCraft. If not, see http://www.gnu.org/licenses/.
   1.267 + */
   1.268 +#ifndef _include_jc_stack_h_
   1.269 +#define _include_jc_stack_h_
   1.270 +
   1.271 +#include <stddef.h>
   1.272 +#include "Utility.h"
   1.273 +#include "Code.h"
   1.274 +#include "Functions.h"
   1.275 +#include "VirtualObjectVisitor.h"
   1.276 +
   1.277 +namespace ke {
   1.278 +
   1.279 +class Object;
   1.280 +class Array;
   1.281 +class Reference;
   1.282 +class Frame;
   1.283 +class Stack;
   1.284 +class Zone;
   1.285 +class Module;
   1.286 +    
   1.287 +union LocalSlot
   1.288 +{
   1.289 +    int i32;
   1.290 +    float f;
   1.291 +    Address address;
   1.292 +    Object *obj;
   1.293 +    Array *array;
   1.294 +    Reference *ref;
   1.295 +    Function *fun;
   1.296 +    Module *module;
   1.297 +};
   1.298 +
   1.299 +struct Top
   1.300 +{
   1.301 +    LocalSlot *sp;
   1.302 +    bytecode *pc;
   1.303 +    Frame *fp;
   1.304 +};
   1.305 +
   1.306 +class Frame
   1.307 +{
   1.308 +    friend class Stack;
   1.309 +
   1.310 +    Frame *prev_;
   1.311 +    bytecode *prevpc_;
   1.312 +    union {
   1.313 +        Function *fun_;
   1.314 +        Native *native_;
   1.315 +        Object *callee_;
   1.316 +    };
   1.317 +    Code *code_;
   1.318 +
   1.319 +    // Position of the LIFO stack at function entry.
   1.320 +    Address lifoPosition_;
   1.321 +    
   1.322 +    // Loop nesting level, for LIFO stack balancing. LIFO stack balancing
   1.323 +    // is not strictly required, but it helps to avoid unnecessary waste,
   1.324 +    // since once the LIFO stack is depleted, we must use the heap instead.
   1.325 +    unsigned loopDepth_;
   1.326 +
   1.327 +  public:
   1.328 +    Frame(Frame *prev, bytecode *prevpc, Function *fun, Code *code, Address lifoPosition)
   1.329 +      : prev_(prev),
   1.330 +        prevpc_(prevpc),
   1.331 +        fun_(fun),
   1.332 +        code_(code),
   1.333 +        lifoPosition_(lifoPosition),
   1.334 +        loopDepth_(0)
   1.335 +    {
   1.336 +    }
   1.337 +
   1.338 +    Frame(Frame *prev, bytecode *prevpc, Native *native, Address lifoPosition)
   1.339 +      : prev_(prev),
   1.340 +        prevpc_(prevpc),
   1.341 +        native_(native),
   1.342 +        code_(NULL),
   1.343 +        lifoPosition_(lifoPosition)
   1.344 +    {
   1.345 +    }
   1.346 +
   1.347 +    Address *loopStack() {
   1.348 +        return reinterpret_cast<Address *>(this + 1);
   1.349 +    }
   1.350 +    LocalSlot *locals() {
   1.351 +        return reinterpret_cast<LocalSlot *>(loopStack() + code_->maxLoopDepth());
   1.352 +    }
   1.353 +    LocalSlot *stackBase() {
   1.354 +        return locals() + code_->nlocals();
   1.355 +    }
   1.356 +    Function *fun() const {
   1.357 +        assert(fun_ && callee_->is(MapKind_Function));
   1.358 +        return fun_;
   1.359 +    }
   1.360 +    Function *maybeFun() const {
   1.361 +        return (fun_ && callee_->is(MapKind_Function)) ? fun_ : NULL;
   1.362 +    }
   1.363 +    bool isNative() const {
   1.364 +        return callee_ && callee_->is(MapKind_Native);
   1.365 +    }
   1.366 +    Native *native() const {
   1.367 +        assert(isNative());
   1.368 +        return native_;
   1.369 +    }
   1.370 +    Code *code() const {
   1.371 +        assert(code_);
   1.372 +        return code_;
   1.373 +    }
   1.374 +    Frame *prev() const {
   1.375 +        return prev_;
   1.376 +    }
   1.377 +    bytecode *prevpc() const {
   1.378 +        return prevpc_;
   1.379 +    }
   1.380 +    Address lifoPosition() const {
   1.381 +        return lifoPosition_;
   1.382 +    }
   1.383 +    LocalSlot &arg(unsigned slot) {
   1.384 +        assert(slot < fun()->nargs());
   1.385 +        return *(reinterpret_cast<LocalSlot *>(this) - slot - 1);
   1.386 +    }
   1.387 +    void enterLoop(Zone *zone);
   1.388 +    void leaveLoop(Zone *zone);
   1.389 +    void accept(VirtualObjectVisitor *visitor);
   1.390 +};
   1.391 +
   1.392 +// RAII object for calling a function from C++.
   1.393 +class InvokeArgs
   1.394 +{
   1.395 +    friend class Stack;
   1.396 +
   1.397 +    Stack *stack_;
   1.398 +    LocalSlot *args_;
   1.399 +    unsigned nargs_;
   1.400 +
   1.401 +  public:
   1.402 +    InvokeArgs()
   1.403 +      : stack_(NULL),
   1.404 +        args_(NULL),
   1.405 +        nargs_(0)
   1.406 +    {
   1.407 +    }
   1.408 +
   1.409 +    ~InvokeArgs();
   1.410 +
   1.411 +    LocalSlot &arg(unsigned index) {
   1.412 +        assert(index < nargs_);
   1.413 +        return args_[nargs_ - index - 1];
   1.414 +    }
   1.415 +};
   1.416 +
   1.417 +// RAII object for calling a native from C++.
   1.418 +class NativeArgs
   1.419 +{
   1.420 +    friend class Stack;
   1.421 +
   1.422 +    Stack *stack_;
   1.423 +    LocalSlot *argsBase_;
   1.424 +
   1.425 +  public:
   1.426 +    NativeArgs()
   1.427 +      : stack_(NULL),
   1.428 +        argsBase_(NULL)
   1.429 +    {
   1.430 +    }
   1.431 +
   1.432 +    ~NativeArgs();
   1.433 +
   1.434 +    intptr_t *args() {
   1.435 +        return reinterpret_cast<intptr_t *>(argsBase_);
   1.436 +    }
   1.437 +};
   1.438 +
   1.439 +class Stack
   1.440 +{
   1.441 +    friend class InvokeArgs;
   1.442 +    friend class NativeArgs;
   1.443 +
   1.444 +  private:
   1.445 +    static const size_t STACK_SIZE = 1024 * 1024;
   1.446 +
   1.447 +  public:
   1.448 +    Stack(Zone *zone);
   1.449 +    ~Stack();
   1.450 +
   1.451 +    bool initialize();
   1.452 +
   1.453 +  public:
   1.454 +    Frame *pushInlineFrame(Handle<Function> fun);
   1.455 +    Frame *popInlineFrame();
   1.456 +
   1.457 +    bool pushInvokeFrame(Handle<Function> fun, InvokeArgs &args);
   1.458 +    bool pushModuleFrame(Handle<Module> module, InvokeArgs &args);
   1.459 +    bool pushNativeFrame(Handle<Native> native, NativeArgs &args, unsigned argc);
   1.460 +
   1.461 +    Top *top() {
   1.462 +        return &top_;
   1.463 +    }
   1.464 +    bool isInCallStack(Handle<Module> module);
   1.465 +    void accept(VirtualObjectVisitor *visitor);
   1.466 +
   1.467 +  private:
   1.468 +    void popInvokeFrame(InvokeArgs &args);
   1.469 +    void popNativeFrame(NativeArgs &args);
   1.470 +
   1.471 +  private:
   1.472 +    Zone *zone_;
   1.473 +    char *buffer_;
   1.474 +    char *end_;
   1.475 +    Top top_;
   1.476 +};
   1.477 +
   1.478 +class StackIter
   1.479 +{
   1.480 +    bytecode *pc_;
   1.481 +    Frame *fp_;
   1.482 +
   1.483 +  public:
   1.484 +    StackIter(Zone *zone);
   1.485 +
   1.486 +    bool done() const;
   1.487 +    const char *function() const;
   1.488 +    unsigned lineNumber() const;
   1.489 +    const char *source() const;
   1.490 +    void prev();
   1.491 +};
   1.492 +
   1.493 +}
   1.494 +
   1.495 +#endif // _include_jc_stack_h_