Add some more API.
Add some more API.
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 }