Logo Search packages:      
Sourcecode: kaya version File versions  Download package

VMState.h

#ifndef _VMSTATE_H // -*-C++-*-
#define _VMSTATE_H

/**
    Kaya run-time system
    Copyright (C) 2004, 2005 Edwin Brady

    This file is distributed under the terms of the GNU Lesser General
    Public Licence. See COPYING for licence.
*/

using namespace std;

#ifndef WIN32
#include <pthread.h>
#define GC_PTHREADS
#else
#include <io.h>
#define GC_WIN32_THREADS
#endif
#include <gc/gc_cpp.h>
#include <setjmp.h>

#include <map>
#include <stack>

#include "Heap.h"

/// Function map is global to all threads.
//extern map<int,func> m_funmap;

void initFunMap(int sz);
void addToFunMap(int id, func fn);
func getFn(int id);
int getFnID(func fn);

class Exception;

class VMState: public gc {
    friend class Exception;
public:
    VMState(bool panic=false);
    
    Value* doPop() {
      Value* tmp=*(--m_stackptr);
      *m_stackptr=NULL;
      return tmp;
    }

  // sometimes just shortening the stack so this is faster than doPop()
    void discardPop() {
        *(--m_stackptr) = NULL;
    }
  
    void push(Value* val) {
      // FIXME: Grow stack if necessary? Might be quite an overhead... maybe 
      // make it an option.
      *m_stackptr = val;
      m_stackptr++;
    }

    // Next ones are for efficiency
    void push2(Value* val, Value* val2);
    void push3(Value* val, Value* val2, Value* val3);
    void push4(Value* val, Value* val2, Value* val3,Value *val4);

    // Push then settop is common, so combine.
    void pushsettop(Value* val) {
      val->setPtr(*(--m_stackptr));
      *m_stackptr=NULL;
    }

    // Setting the top as a temp is also common.
    void tmpsettop(int val) {
      (*(--m_stackptr))->setInt(val);
      *m_stackptr=NULL;
    }

    void mkArray(int size);
    void finish();
    bool emptyStack();

/// Replace the top stack item with its ith argument.
/// Let's see if inlining helps
    void projarg(int i, int t)
    {
      Value*& topval = (*(m_stackptr-1));
#ifndef NOCHECK
      if (topval==NULL) {
      kaya_throw("Projecting from uninitialised value",1);
      }
      if (topval->getType()!=KVT_UNION) {
      kaya_throw("Attempt to project from non-Union",1);
      }
#endif
      Union* top = (Union*)topval->getRaw();
#ifndef NOCHECK
      if (U_TAG(top)!=t) {
      kaya_throw("Wrong constructor used for projection",1);
      }
      if (U_ARITY(top) <= i) {
      kaya_throw("Field out of range in projection; maybe a type error in unmarshal?",1);
      }
#endif
      topval=top->args[i];
      //    push(arg);
    }

    void goToIndex();

    void pushToIndex(Value* v)
    {
      int idx = v->getInt();
      (*(m_stackptr-1)) = (*(m_stackptr-1))->lookup(this,idx);
    }

/** Replace the top stack item with the contents of the second stack item,
    then remove both (mutation, not evaluation) */
    void setTop()
    {
      (*(m_stackptr-1))->setPtr((*(m_stackptr-2)));
      (*(m_stackptr-2)) = (*(m_stackptr-1));
      *(m_stackptr-1)=NULL;
      m_stackptr-=2;
    }

// Add the top stack value to the next one, then remove both.
    void addTop()
    {
      (*(m_stackptr-2))->addVal(*(m_stackptr-1));
      *(m_stackptr-1)=NULL;
      m_stackptr-=2;
    }

    void subTop()
    {
      (*(m_stackptr-2))->subVal(*(m_stackptr-1));
      *(m_stackptr-1)=NULL;
      m_stackptr-=2;
    }

    void mulTop()
    {
      (*(m_stackptr-2))->mulVal(*(m_stackptr-1));
      *(m_stackptr-1)=NULL;
      m_stackptr-=2;
    }

    void divTop()
    {
      (*(m_stackptr-2))->divVal(*(m_stackptr-1));
      *(m_stackptr-1)=NULL;
      m_stackptr-=2;
    }

    void appendTop()
    {
      // append top stack item onto top-1 stack item
      wchar_t* topstr = (*(--m_stackptr))->getString()->getVal();
      (*(m_stackptr-1))->getString()->append(topstr);
      *m_stackptr = NULL;
    }

    void appendTopInt()
    {
      // append top stack item onto top-1 stack item
      wchar_t topstr = (wchar_t)((*(--m_stackptr))->getInt());
      (*(m_stackptr-1))->getString()->append(topstr);
      *m_stackptr = NULL;
    }

    /// Return the top stack item.
    Value* topItem() {
      return (*(m_stackptr-1));
    }

    
    void pushglobal(Value**& globtable, int i);
    void createglobal(wchar_t* modid,int i);

    int tag();

    void readInt();
    void readStr();
    void doAppend();
    void doAppendChar(wchar_t x);
    void doAppendStr(wchar_t* x);
    void doAppendStr(char* x);
    void doEqExcept(bool inv);
    void doEqString(bool inv);
    void doEqString(bool inv, wchar_t* str);
    void doEqString(bool inv, char* str);
    bool doTopStrEq(wchar_t* str);
    bool doTopStrEq(char* str);

    void str2int();
    void int2str();
    void real2str();
    void str2real();
    void str2chr();
    void chr2str();
    void bool2str();
    void real2int();
    void int2real();

    void newjmp_buf();

    void kaya_throw(wchar_t* msg, int code);
    void kaya_throw(char* msg, int code);
    void throw_ex();
    jmp_buf* top_ex();
    void tried();
    void restore();

    void getindex();

    void pushgetindex(Value* v) {
      int idx = v->getInt();
      --m_stackptr;
      Value* array = *m_stackptr;
      Value* el = array->lookup(this,idx);
      push(el);
    }

    Value* mkstr(wchar_t* str);
    Value* mkint(void* i);

    void lineno(char* src, int ln); 
    void lineno(wchar_t* src, int ln); 
    void pushBT(char* src, char* mod, int ln);
    void pushBT(wchar_t* src, wchar_t* mod, int ln);
    void popBT();

    void memstat();

    int maxMemUsage() { 
      return m_maxmem; 
    }

    // Implement print via write
    void writestdout();

    void returnVal(Value* ret) { 
      m_return.setPtr(ret); 
    }

    Value* getReturnVal() { return &m_return; }

    // Throw divide by zero exception
    void divideByZero() {
      kaya_throw("Divide by zero",0);
    }

private:
    Value** m_valstack;
    Value** m_stackptr;
    CallStackEntry** m_btptr;

//    int m_stacksize;

    int m_stackalloc;
    int m_globalloc;

    struct StackData {
      Value** stackptr;
      CallStackEntry** csptr;
    };

    stack<jmp_buf*> m_except_stack;
    stack<StackData> m_stack_stack; // Stack size when an exception happens.

    // Tracing details
    CallStackEntry** m_backtrace;
    wchar_t* m_sourcefile;
    int m_lineno;

    int m_maxmem;

    Value m_return; // Place to put return values (sort of a register).
};

#endif // whole file

Generated by  Doxygen 1.6.0   Back to index