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