Add some more API.
authorDavid Anderson <dvander@alliedmods.net>
Sun Jul 08 15:23:48 2012 -0700 (2012-07-08)
changeset 62e04c5be84792
parent 61 864e4b02a4c1
child 63 dd57743d220e
Add some more API.
include/keima.h
jitcraft/API.cpp
jitcraft/HashTable.h
jitcraft/Stack.cpp
jitcraft/Stack.h
jitcraft/jitcraft.vcxproj
jitcraft/main.cpp
     1.1 --- a/include/keima.h	Sun Jul 08 11:33:12 2012 -0700
     1.2 +++ b/include/keima.h	Sun Jul 08 15:23:48 2012 -0700
     1.3 @@ -182,19 +182,40 @@
     1.4      void operator delete(void *, size_t);
     1.5  };
     1.6  
     1.7 -class Module;
     1.8 +// A module represents a single compiled file, and contains functions and
     1.9 +// global variables for that file (as well as exported types).
    1.10 +class Module
    1.11 +{
    1.12 +  public:
    1.13 +};
    1.14 +
    1.15 +class Keima
    1.16 +{
    1.17 +  public:
    1.18 +    /*
    1.19 +     * Initializes the Keima engine. This must be called exactly once before any
    1.20 +     * other Keima functions are called. After this, it is safe to use Keima
    1.21 +     * on the calling thread.
    1.22 +     */
    1.23 +    static bool Initialize();
    1.24  
    1.25 -/*
    1.26 - * Initializes the Keima engine. This must be called exactly once before any
    1.27 - * other Keima functions are called. After this, it is safe to use Keima
    1.28 - * on the calling thread.
    1.29 - */
    1.30 -extern bool Initialize();
    1.31 +    /*
    1.32 +     * Shuts down the Keima engine and frees data structures on all threads.
    1.33 +     */
    1.34 +    static void Shutdown();
    1.35  
    1.36 -/*
    1.37 - * Shuts down the Keima engine and frees data structures on all threads.
    1.38 - */
    1.39 -extern void Shutdown();
    1.40 +    /*
    1.41 +     * Searches the call stack and returns true if the given module has any
    1.42 +     * active code running. This is an O(n) algorithm.
    1.43 +     */
    1.44 +    static bool IsInCallStack(Handle<Module> module);
    1.45 +
    1.46 +    /*
    1.47 +     * Reclaim as much memory as possible. This pauses the calling thread
    1.48 +     * until garbage collection completes.
    1.49 +     */
    1.50 +    static void CollectGarbage();
    1.51 +};
    1.52  
    1.53  /*
    1.54   * Compiles a file and returns a Module.
     2.1 --- a/jitcraft/API.cpp	Sun Jul 08 11:33:12 2012 -0700
     2.2 +++ b/jitcraft/API.cpp	Sun Jul 08 15:23:48 2012 -0700
     2.3 @@ -30,7 +30,7 @@
     2.4  using namespace ke;
     2.5  
     2.6  bool
     2.7 -Ke::Initialize()
     2.8 +Ke::Keima::Initialize()
     2.9  {
    2.10      SingleThreadedZone = new Zone();
    2.11      if (!SingleThreadedZone || !SingleThreadedZone->initialize())
    2.12 @@ -39,7 +39,7 @@
    2.13  }
    2.14  
    2.15  void
    2.16 -Ke::Shutdown()
    2.17 +Ke::Keima::Shutdown()
    2.18  {
    2.19      delete SingleThreadedZone;
    2.20      SingleThreadedZone = NULL;
    2.21 @@ -68,6 +68,12 @@
    2.22      return ZONE()->rootScopes().make(obj);
    2.23  }
    2.24  
    2.25 +template <typename From, typename To> static inline To *
    2.26 +Open(Ke::Handle<From> from)
    2.27 +{
    2.28 +    return *reinterpret_cast<To **>(*from);
    2.29 +}
    2.30 +
    2.31  template <typename From, typename To> static inline Ke::Local<To>
    2.32  ToLocal(Handle<From> from)
    2.33  {
    2.34 @@ -173,3 +179,16 @@
    2.35  {
    2.36      ZONE()->globalRoots()->decref(FromAPI(root));
    2.37  }
    2.38 +
    2.39 +bool
    2.40 +Ke::Keima::IsInCallStack(Handle<Module> argModule)
    2.41 +{
    2.42 +    ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(argModule));
    2.43 +    return ZONE()->stack().isInCallStack(module);
    2.44 +}
    2.45 +
    2.46 +void
    2.47 +Ke::Keima::CollectGarbage()
    2.48 +{
    2.49 +    ke::ZONE()->heap().reclaim();
    2.50 +}
     3.1 --- a/jitcraft/HashTable.h	Sun Jul 08 11:33:12 2012 -0700
     3.2 +++ b/jitcraft/HashTable.h	Sun Jul 08 15:23:48 2012 -0700
     3.3 @@ -314,7 +314,7 @@
     3.4      }
     3.5  
     3.6      void remove(Entry &e) {
     3.7 -        assert(!e.isLive());
     3.8 +        assert(e.isLive());
     3.9          e.setRemoved();
    3.10          ndeleted_++;
    3.11          nelements_--;
    3.12 @@ -412,8 +412,9 @@
    3.13          }
    3.14  
    3.15          void next() {
    3.16 -            while (i_ < end_ && !i_->isLive())
    3.17 +            do {
    3.18                  i_++;
    3.19 +            } while (i_ < end_ && !i_->isLive());
    3.20          }
    3.21      };
    3.22  };
     4.1 --- a/jitcraft/Stack.cpp	Sun Jul 08 11:33:12 2012 -0700
     4.2 +++ b/jitcraft/Stack.cpp	Sun Jul 08 15:23:48 2012 -0700
     4.3 @@ -1,152 +1,167 @@
     4.4 -/* vim: set ts=4 sw=4 tw=99 et:
     4.5 - *
     4.6 - * Copyright (C) 2012 David Anderson
     4.7 - *
     4.8 - * This file is part of JITCraft.
     4.9 - *
    4.10 - * JITCraft is free software: you can redistribute it and/or modify it under
    4.11 - * the terms of the GNU General Public License as published by the Free
    4.12 - * Software Foundation, either version 3 of the License, or (at your option)
    4.13 - * any later version.
    4.14 - * 
    4.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    4.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    4.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    4.18 - *
    4.19 - * You should have received a copy of the GNU General Public License along with
    4.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
    4.21 - */
    4.22 -#include <new>
    4.23 -#include <stdlib.h>
    4.24 -#include "Stack.h"
    4.25 -#include "Zone.h"
    4.26 -#include "Heap-inl.h"
    4.27 -
    4.28 -using namespace ke;
    4.29 -
    4.30 -Stack::Stack()
    4.31 -  : buffer_(NULL),
    4.32 -    end_(NULL),
    4.33 -    top_(NULL)
    4.34 -{
    4.35 -}
    4.36 -
    4.37 -Stack::~Stack()
    4.38 -{
    4.39 -    free(buffer_);
    4.40 -}
    4.41 -
    4.42 -bool
    4.43 -Stack::initialize()
    4.44 -{
    4.45 -    buffer_ = (char *)malloc(STACK_SIZE);
    4.46 -    if (!buffer_)
    4.47 -        return false;
    4.48 -
    4.49 -    top_ = NULL;
    4.50 -    end_ = buffer_ + STACK_SIZE;
    4.51 -    return true;
    4.52 -}
    4.53 -
    4.54 -static inline size_t
    4.55 -SizeForCodeFrame(Code *code)
    4.56 -{
    4.57 -    return sizeof(Frame) + sizeof(LocalSlot) * (code->nlocals() + code->maxStackDepth());
    4.58 -}
    4.59 -
    4.60 -Frame *
    4.61 -Stack::pushFrame(Function *fun)
    4.62 -{
    4.63 -    Code *code = fun->code();
    4.64 -    size_t nbytes = SizeForCodeFrame(code);
    4.65 -    if (reinterpret_cast<char *>(top_->sp) + nbytes >= end_)
    4.66 -        return NULL;
    4.67 -
    4.68 -    Frame *frame = reinterpret_cast<Frame *>(top_->sp);
    4.69 -    new (frame) Frame(top_->fp, top_->pc, fun, code, ZONE()->heap().lifoPosition());
    4.70 -    memset(frame->locals(), 0, sizeof(LocalSlot) * code->nlocals());
    4.71 -
    4.72 -    top_->pc = frame->code()->start();
    4.73 -    top_->sp = frame->stackBase();
    4.74 -    top_->fp = frame;
    4.75 -
    4.76 -    return frame;
    4.77 -}
    4.78 -
    4.79 -
    4.80 -Frame *
    4.81 -Stack::popFrame()
    4.82 -{
    4.83 -    ZONE()->heap().unwindLifo(top_->fp->lifoPosition());
    4.84 -
    4.85 -    Frame *prev = top_->fp->prev();
    4.86 -    Function *fun = top_->fp->maybeFun();
    4.87 -    Code *code = top_->fp->code();
    4.88 -
    4.89 -    size_t nbytes = sizeof(LocalSlot) * code->nlocals() +
    4.90 -                    sizeof(Frame) +
    4.91 -                    sizeof(LocalSlot) * (fun ? fun->nargs() : 0);
    4.92 -
    4.93 -    top_->pc = top_->fp->prevpc();
    4.94 -    top_->sp = reinterpret_cast<LocalSlot *>(reinterpret_cast<char *>(top_->sp) - nbytes);
    4.95 -    top_->fp = prev;
    4.96 -    return prev;
    4.97 -}
    4.98 -
    4.99 -void
   4.100 -Frame::accept(VirtualObjectVisitor *visitor)
   4.101 -{
   4.102 -    visitor->visit(reinterpret_cast<Object **>(&fun_));
   4.103 -    visitor->visit(reinterpret_cast<Object **>(&code_));
   4.104 -}
   4.105 -
   4.106 -static void
   4.107 -TraceFrame(VirtualObjectVisitor *visitor, Frame *fp, LocalSlot *sp, bytecode *pc)
   4.108 -{
   4.109 -    Code *code = fp->code();
   4.110 -    LocalSlot *slots = fp->locals();
   4.111 -
   4.112 -    // Trace local variables.
   4.113 -    for (unsigned i = 0; i < code->nlocals(); i++) {
   4.114 -        Type *type = code->localType(i);
   4.115 -        if (type->isTraceable())
   4.116 -            visitor->visit(&slots[i].obj);
   4.117 -    }
   4.118 -
   4.119 -    // Trace arguments, if a function call.
   4.120 -    if (Function *fun = fp->maybeFun()) {
   4.121 -        for (unsigned i = 0; i < fun->nargs(); i++) {
   4.122 -            Type *type = fun->argType(i);
   4.123 -            if (type->isTraceable())
   4.124 -                visitor->visit(&fp->arg(i).obj);
   4.125 -        }
   4.126 -    }
   4.127 -
   4.128 -    // Finally, trace stack slots. Not every gc-point in the bytecode will
   4.129 -    // have a safepoint; since they are actually uncommon, we don't emit
   4.130 -    // them unless at least one stack slot would be marked.
   4.131 -    if (uint8 *safepoint = code->safepointAt(code->pcToOffset(pc))) {
   4.132 -        LocalSlot *base = fp->stackBase();
   4.133 -        unsigned stackDepth = unsigned(sp - fp->stackBase());
   4.134 -        assert(stackDepth <= code->maxStackDepth());
   4.135 -
   4.136 -        for (unsigned i = 0; i < stackDepth; i++) {
   4.137 -            if (safepoint[i / 8] & (1 << (i % 8)))
   4.138 -                visitor->visit(&base[i].obj);
   4.139 -        }
   4.140 -    }
   4.141 -}
   4.142 -
   4.143 -void
   4.144 -Stack::accept(VirtualObjectVisitor *visitor)
   4.145 -{
   4.146 -    LocalSlot *sp = top_->sp;
   4.147 -    bytecode *pc = top_->pc;
   4.148 -
   4.149 -    for (Frame *frame = top_->fp; frame; frame = frame->prev()) {
   4.150 -        TraceFrame(visitor, frame, sp, pc);
   4.151 -        sp = reinterpret_cast<LocalSlot *>(frame);
   4.152 -        pc = frame->prevpc();
   4.153 -    }
   4.154 -}
   4.155 -
   4.156 +/* vim: set ts=4 sw=4 tw=99 et:
   4.157 + *
   4.158 + * Copyright (C) 2012 David Anderson
   4.159 + *
   4.160 + * This file is part of JITCraft.
   4.161 + *
   4.162 + * JITCraft is free software: you can redistribute it and/or modify it under
   4.163 + * the terms of the GNU General Public License as published by the Free
   4.164 + * Software Foundation, either version 3 of the License, or (at your option)
   4.165 + * any later version.
   4.166 + * 
   4.167 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
   4.168 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   4.169 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   4.170 + *
   4.171 + * You should have received a copy of the GNU General Public License along with
   4.172 + * JITCraft. If not, see http://www.gnu.org/licenses/.
   4.173 + */
   4.174 +#include <new>
   4.175 +#include <stdlib.h>
   4.176 +#include "Stack.h"
   4.177 +#include "Zone.h"
   4.178 +#include "Heap-inl.h"
   4.179 +
   4.180 +using namespace ke;
   4.181 +
   4.182 +Stack::Stack()
   4.183 +  : buffer_(NULL),
   4.184 +    end_(NULL),
   4.185 +    top_(NULL)
   4.186 +{
   4.187 +}
   4.188 +
   4.189 +Stack::~Stack()
   4.190 +{
   4.191 +    free(buffer_);
   4.192 +}
   4.193 +
   4.194 +bool
   4.195 +Stack::initialize()
   4.196 +{
   4.197 +    buffer_ = (char *)malloc(STACK_SIZE);
   4.198 +    if (!buffer_)
   4.199 +        return false;
   4.200 +
   4.201 +    top_ = NULL;
   4.202 +    end_ = buffer_ + STACK_SIZE;
   4.203 +    return true;
   4.204 +}
   4.205 +
   4.206 +static inline size_t
   4.207 +SizeForCodeFrame(Code *code)
   4.208 +{
   4.209 +    return sizeof(Frame) + sizeof(LocalSlot) * (code->nlocals() + code->maxStackDepth());
   4.210 +}
   4.211 +
   4.212 +Frame *
   4.213 +Stack::pushFrame(Function *fun)
   4.214 +{
   4.215 +    Code *code = fun->code();
   4.216 +    size_t nbytes = SizeForCodeFrame(code);
   4.217 +    if (reinterpret_cast<char *>(top_->sp) + nbytes >= end_)
   4.218 +        return NULL;
   4.219 +
   4.220 +    Frame *frame = reinterpret_cast<Frame *>(top_->sp);
   4.221 +    new (frame) Frame(top_->fp, top_->pc, fun, code, ZONE()->heap().lifoPosition());
   4.222 +    memset(frame->locals(), 0, sizeof(LocalSlot) * code->nlocals());
   4.223 +
   4.224 +    top_->pc = frame->code()->start();
   4.225 +    top_->sp = frame->stackBase();
   4.226 +    top_->fp = frame;
   4.227 +
   4.228 +    return frame;
   4.229 +}
   4.230 +
   4.231 +
   4.232 +Frame *
   4.233 +Stack::popFrame()
   4.234 +{
   4.235 +    ZONE()->heap().unwindLifo(top_->fp->lifoPosition());
   4.236 +
   4.237 +    Frame *prev = top_->fp->prev();
   4.238 +    Function *fun = top_->fp->maybeFun();
   4.239 +    Code *code = top_->fp->code();
   4.240 +
   4.241 +    size_t nbytes = sizeof(LocalSlot) * code->nlocals() +
   4.242 +                    sizeof(Frame) +
   4.243 +                    sizeof(LocalSlot) * (fun ? fun->nargs() : 0);
   4.244 +
   4.245 +    top_->pc = top_->fp->prevpc();
   4.246 +    top_->sp = reinterpret_cast<LocalSlot *>(reinterpret_cast<char *>(top_->sp) - nbytes);
   4.247 +    top_->fp = prev;
   4.248 +    return prev;
   4.249 +}
   4.250 +
   4.251 +void
   4.252 +Frame::accept(VirtualObjectVisitor *visitor)
   4.253 +{
   4.254 +    visitor->visit(reinterpret_cast<Object **>(&fun_));
   4.255 +    visitor->visit(reinterpret_cast<Object **>(&code_));
   4.256 +}
   4.257 +
   4.258 +static void
   4.259 +TraceFrame(VirtualObjectVisitor *visitor, Frame *fp, LocalSlot *sp, bytecode *pc)
   4.260 +{
   4.261 +    Code *code = fp->code();
   4.262 +    LocalSlot *slots = fp->locals();
   4.263 +
   4.264 +    // Trace local variables.
   4.265 +    for (unsigned i = 0; i < code->nlocals(); i++) {
   4.266 +        Type *type = code->localType(i);
   4.267 +        if (type->isTraceable())
   4.268 +            visitor->visit(&slots[i].obj);
   4.269 +    }
   4.270 +
   4.271 +    // Trace arguments, if a function call.
   4.272 +    if (Function *fun = fp->maybeFun()) {
   4.273 +        for (unsigned i = 0; i < fun->nargs(); i++) {
   4.274 +            Type *type = fun->argType(i);
   4.275 +            if (type->isTraceable())
   4.276 +                visitor->visit(&fp->arg(i).obj);
   4.277 +        }
   4.278 +    }
   4.279 +
   4.280 +    // Finally, trace stack slots. Not every gc-point in the bytecode will
   4.281 +    // have a safepoint; since they are actually uncommon, we don't emit
   4.282 +    // them unless at least one stack slot would be marked.
   4.283 +    if (uint8 *safepoint = code->safepointAt(code->pcToOffset(pc))) {
   4.284 +        LocalSlot *base = fp->stackBase();
   4.285 +        unsigned stackDepth = unsigned(sp - fp->stackBase());
   4.286 +        assert(stackDepth <= code->maxStackDepth());
   4.287 +
   4.288 +        for (unsigned i = 0; i < stackDepth; i++) {
   4.289 +            if (safepoint[i / 8] & (1 << (i % 8)))
   4.290 +                visitor->visit(&base[i].obj);
   4.291 +        }
   4.292 +    }
   4.293 +}
   4.294 +
   4.295 +void
   4.296 +Stack::accept(VirtualObjectVisitor *visitor)
   4.297 +{
   4.298 +    if (!top_)
   4.299 +        return;
   4.300 +
   4.301 +    LocalSlot *sp = top_->sp;
   4.302 +    bytecode *pc = top_->pc;
   4.303 +
   4.304 +    for (Frame *frame = top_->fp; frame; frame = frame->prev()) {
   4.305 +        TraceFrame(visitor, frame, sp, pc);
   4.306 +        sp = reinterpret_cast<LocalSlot *>(frame);
   4.307 +        pc = frame->prevpc();
   4.308 +    }
   4.309 +}
   4.310 +
   4.311 +bool
   4.312 +Stack::isInCallStack(Handle<Module> module)
   4.313 +{
   4.314 +    if (!top_)
   4.315 +        return false;
   4.316 +
   4.317 +    for (Frame *frame = top_->fp; frame; frame = frame->prev()) {
   4.318 +        if (frame->code()->module() == module)
   4.319 +            return true;
   4.320 +    }
   4.321 +    return false;
   4.322 +}
     5.1 --- a/jitcraft/Stack.h	Sun Jul 08 11:33:12 2012 -0700
     5.2 +++ b/jitcraft/Stack.h	Sun Jul 08 15:23:48 2012 -0700
     5.3 @@ -139,6 +139,7 @@
     5.4      Top begin() {
     5.5          return Top((LocalSlot *)buffer_);
     5.6      }
     5.7 +    bool isInCallStack(Handle<Module> module);
     5.8      void accept(VirtualObjectVisitor *visitor);
     5.9  };
    5.10  
     6.1 --- a/jitcraft/jitcraft.vcxproj	Sun Jul 08 11:33:12 2012 -0700
     6.2 +++ b/jitcraft/jitcraft.vcxproj	Sun Jul 08 15:23:48 2012 -0700
     6.3 @@ -90,6 +90,7 @@
     6.4        <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
     6.5        <ExceptionHandling>false</ExceptionHandling>
     6.6        <RuntimeTypeInfo>false</RuntimeTypeInfo>
     6.7 +      <Optimization>Disabled</Optimization>
     6.8      </ClCompile>
     6.9    </ItemDefinitionGroup>
    6.10    <ItemGroup>
     7.1 --- a/jitcraft/main.cpp	Sun Jul 08 11:33:12 2012 -0700
     7.2 +++ b/jitcraft/main.cpp	Sun Jul 08 15:23:48 2012 -0700
     7.3 @@ -68,7 +68,7 @@
     7.4          return 1;
     7.5      }
     7.6  
     7.7 -    if (!Ke::Initialize())
     7.8 +    if (!Ke::Keima::Initialize())
     7.9          return 1;
    7.10      {
    7.11          Ke::HandleScope scope;
    7.12 @@ -79,5 +79,5 @@
    7.13          Ke::Root<Ke::Module> root = Ke::Root<Ke::Module>::New(module);
    7.14      }
    7.15  
    7.16 -    Ke::Shutdown();
    7.17 +    Ke::Keima::Shutdown();
    7.18  }