diff -r 06a0015b6a5c -r 32ad0523b309 src/Stack.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/Stack.h Tue Jul 24 23:53:34 2012 -0700 @@ -0,0 +1,233 @@ +/* vim: set ts=4 sw=4 tw=99 et: + * + * Copyright (C) 2012 David Anderson + * + * This file is part of JITCraft. + * + * JITCraft is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * JITCraft. If not, see http://www.gnu.org/licenses/. + */ +#ifndef _include_jc_stack_h_ +#define _include_jc_stack_h_ + +#include +#include "Utility.h" +#include "Code.h" +#include "Functions.h" +#include "VirtualObjectVisitor.h" + +namespace ke { + +class Object; +class Array; +class Reference; +class Frame; +class Stack; +class Zone; +class Module; + +union LocalSlot +{ + int i32; + float f; + Address address; + Object *obj; + Array *array; + Reference *ref; + Function *fun; + Module *module; +}; + +struct Top +{ + LocalSlot *sp; + bytecode *pc; + Frame *fp; +}; + +class Frame +{ + friend class Stack; + + Frame *prev_; + bytecode *prevpc_; + union { + Function *fun_; + Native *native_; + Object *callee_; + }; + Code *code_; + Address lifoPosition_; + + public: + Frame(Frame *prev, bytecode *prevpc, Function *fun, Code *code, Address lifoPosition) + : prev_(prev), + prevpc_(prevpc), + fun_(fun), + code_(code), + lifoPosition_(lifoPosition) + { + } + + Frame(Frame *prev, bytecode *prevpc, Native *native, Address lifoPosition) + : prev_(prev), + prevpc_(prevpc), + native_(native), + code_(NULL), + lifoPosition_(lifoPosition) + { + } + + LocalSlot *locals() { + return reinterpret_cast(this + 1); + } + LocalSlot *stackBase() { + return locals() + code_->nlocals(); + } + Function *fun() const { + assert(fun_ && callee_->is(MapKind_Function)); + return fun_; + } + Function *maybeFun() const { + return (fun_ && callee_->is(MapKind_Function)) ? fun_ : NULL; + } + bool isNative() const { + return callee_ && callee_->is(MapKind_Native); + } + Native *native() const { + assert(isNative()); + return native_; + } + Code *code() const { + assert(code_); + return code_; + } + Frame *prev() const { + return prev_; + } + bytecode *prevpc() const { + return prevpc_; + } + Address lifoPosition() const { + return lifoPosition_; + } + LocalSlot &arg(unsigned slot) { + assert(slot < fun()->nargs()); + return *(reinterpret_cast(this) - slot - 1); + } + void accept(VirtualObjectVisitor *visitor); +}; + +// RAII object for calling a function from C++. +class InvokeArgs +{ + friend class Stack; + + Stack *stack_; + LocalSlot *args_; + unsigned nargs_; + + public: + InvokeArgs() + : stack_(NULL), + args_(NULL), + nargs_(0) + { + } + + ~InvokeArgs(); + + LocalSlot &arg(unsigned index) { + assert(index < nargs_); + return args_[nargs_ - index - 1]; + } +}; + +// RAII object for calling a native from C++. +class NativeArgs +{ + friend class Stack; + + Stack *stack_; + LocalSlot *argsBase_; + + public: + NativeArgs() + : stack_(NULL), + argsBase_(NULL) + { + } + + ~NativeArgs(); + + intptr_t *args() { + return reinterpret_cast(argsBase_); + } +}; + +class Stack +{ + friend class InvokeArgs; + friend class NativeArgs; + + private: + static const size_t STACK_SIZE = 1024 * 1024; + + public: + Stack(Zone *zone); + ~Stack(); + + bool initialize(); + + public: + Frame *pushInlineFrame(Handle fun); + Frame *popInlineFrame(); + + bool pushInvokeFrame(Handle fun, InvokeArgs &args); + bool pushModuleFrame(Handle module, InvokeArgs &args); + bool pushNativeFrame(Handle native, NativeArgs &args, unsigned argc); + + Top *top() { + return &top_; + } + bool isInCallStack(Handle module); + void accept(VirtualObjectVisitor *visitor); + + private: + void popInvokeFrame(InvokeArgs &args); + void popNativeFrame(NativeArgs &args); + + private: + Zone *zone_; + char *buffer_; + char *end_; + Top top_; +}; + +class StackIter +{ + bytecode *pc_; + Frame *fp_; + + public: + StackIter(Zone *zone); + + bool done() const; + const char *function() const; + unsigned lineNumber() const; + const char *source() const; + void prev(); +}; + +} + +#endif // _include_jc_stack_h_