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