Removed jitcraft/, added AMBuild scripts for making libkeima.
Removed jitcraft/, added AMBuild scripts for making libkeima.
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/configure.py Tue Jul 24 23:54:14 2012 -0700
1.3 @@ -0,0 +1,11 @@
1.4 +# vim: set ts=2 sw=2 tw=99 noet:
1.5 +import sys
1.6 +import ambuild.runner as runner
1.7 +
1.8 +run = runner.Runner()
1.9 +run.options.add_option('--enable-debug', action='store_const', const='1', dest='debug',
1.10 + help='Enable debugging symbols')
1.11 +run.options.add_option('--enable-optimize', action='store_const', const='1', dest='opt',
1.12 + help='Enable optimization')
1.13 +run.options.add_option('--arch', dest='arch', help='Architecture (x86, x64)')
1.14 +run.Configure(sys.path[0])
2.1 --- a/jitcraft/API.cpp Tue Jul 24 23:53:34 2012 -0700
2.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2.3 @@ -1,483 +0,0 @@
2.4 -/* vim: set ts=4 sw=4 tw=99 et:
2.5 - *
2.6 - * Copyright (C) 2012 David Anderson
2.7 - *
2.8 - * This file is part of JITCraft.
2.9 - *
2.10 - * JITCraft is free software: you can redistribute it and/or modify it under
2.11 - * the terms of the GNU General Public License as published by the Free
2.12 - * Software Foundation, either version 3 of the License, or (at your option)
2.13 - * any later version.
2.14 - *
2.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
2.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
2.18 - *
2.19 - * You should have received a copy of the GNU General Public License along with
2.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
2.21 - */
2.22 -#include "../include/keima.h"
2.23 -#include "Zone.h"
2.24 -#include "RootScopes.h"
2.25 -#include "CompileContext.h"
2.26 -#include "Parser.h"
2.27 -#include "Scopes.h"
2.28 -#include "SemanticAnalysis.h"
2.29 -#include "BytecodeCompiler.h"
2.30 -#include "Modules.h"
2.31 -#include "GlobalRoots.h"
2.32 -#include "Reference.h"
2.33 -#include "Array.h"
2.34 -#include "Interpreter.h"
2.35 -#include "Stack.h"
2.36 -#include "Strings.h"
2.37 -
2.38 -using namespace ke;
2.39 -
2.40 -bool
2.41 -Ke::Keima::Initialize()
2.42 -{
2.43 - SingleThreadedZone = new Zone();
2.44 - if (!SingleThreadedZone || !SingleThreadedZone->initialize())
2.45 - return false;
2.46 - return true;
2.47 -}
2.48 -
2.49 -void
2.50 -Ke::Keima::Shutdown()
2.51 -{
2.52 - delete SingleThreadedZone;
2.53 - SingleThreadedZone = NULL;
2.54 -}
2.55 -
2.56 -Ke::HandleScope::HandleScope()
2.57 - : zone_(ke::ZONE()),
2.58 - position_(zone_->rootScopes().position()),
2.59 - prev_(*zone_->rootScopes().scope())
2.60 -{
2.61 - *zone_->rootScopes().scope() = this;
2.62 -}
2.63 -
2.64 -Ke::HandleScope::~HandleScope()
2.65 -{
2.66 - zone_->rootScopes().unwind(position_);
2.67 - *zone_->rootScopes().scope() = prev_;
2.68 -}
2.69 -
2.70 -ke::Object **
2.71 -Ke::HandleScope::CreateHandle(ke::Object *obj)
2.72 -{
2.73 - if (!obj)
2.74 - return NULL;
2.75 -
2.76 - return ZONE()->rootScopes().make(obj);
2.77 -}
2.78 -
2.79 -template <typename From, typename To> static inline To *
2.80 -Open(Ke::Handle<From> from)
2.81 -{
2.82 - return *reinterpret_cast<To **>(*from);
2.83 -}
2.84 -
2.85 -template <typename From, typename To> static inline To *
2.86 -Open(From *from)
2.87 -{
2.88 - return *reinterpret_cast<To **>(from);
2.89 -}
2.90 -
2.91 -template <typename From, typename To> static inline Ke::Local<To>
2.92 -ToLocal(From *from)
2.93 -{
2.94 - return Ke::Local<To>(reinterpret_cast<To *>(Ke::HandleScope::CreateHandle(from)));
2.95 -}
2.96 -
2.97 -static ke::Module *
2.98 -CompileFromSource(CompileContext &cc, const char *path, const char *stream, size_t length)
2.99 -{
2.100 - Parser parser(ZONE(), cc, stream, length);
2.101 - ParseTree *tree = parser.parse();
2.102 - if (!tree)
2.103 - return NULL;
2.104 - tree->dump(stdout);
2.105 -
2.106 - if (!Scope::Bind(cc, tree))
2.107 - return NULL;
2.108 -
2.109 - SemanticAnalysis semantics(ZONE(), cc, tree);
2.110 - if (!semantics.analyze())
2.111 - return NULL;
2.112 -
2.113 - Scope::Allocate(tree);
2.114 -
2.115 - BytecodeCompiler compiler(ZONE(), tree, NULL);
2.116 - ke::Local<Module> module(ke::ZONE(), compiler.compile());
2.117 - if (!module)
2.118 - return NULL;
2.119 -
2.120 - ke::InvokeArgs args;
2.121 - if (!ke::ZONE()->stack().pushModuleFrame(module, args))
2.122 - return NULL;
2.123 - if (!ke::Interpret(ke::ZONE(), NULL, NULL))
2.124 - return NULL;
2.125 -
2.126 - return module;
2.127 -}
2.128 -
2.129 -Ke::Local<Ke::Module>
2.130 -Ke::Compile(const char *path)
2.131 -{
2.132 - RootScope roots(ZONE());
2.133 - CompileContext cc(ZONE(), path);
2.134 -
2.135 - char *bytes = NULL;
2.136 - size_t length;
2.137 - {
2.138 - FILE *fp = fopen(path, "rb");
2.139 - if (!fp) {
2.140 - cc.reportError(SourcePosition(), Message_CantOpenFile);
2.141 - return Ke::Local<Ke::Module>();
2.142 - }
2.143 -
2.144 - if (fseek(fp, 0, SEEK_END)) {
2.145 - cc.reportError(SourcePosition(), Message_ErrorSeekingFile);
2.146 - fclose(fp);
2.147 - return Ke::Local<Ke::Module>();;
2.148 - }
2.149 - long size = ftell(fp);
2.150 - if (size < 0) {
2.151 - cc.reportError(SourcePosition(), Message_ErrorSeekingFile);
2.152 - fclose(fp);
2.153 - return Ke::Local<Ke::Module>();;
2.154 - }
2.155 - rewind(fp);
2.156 - length = size_t(size);
2.157 - bytes = new char[length + 1];
2.158 - if (fread(bytes, 1, length, fp) != length) {
2.159 - cc.reportError(SourcePosition(), Message_ErrorReadingFile);
2.160 - fclose(fp);
2.161 - delete [] bytes;
2.162 - return Ke::Local<Ke::Module>();;
2.163 - }
2.164 - fclose(fp);
2.165 - }
2.166 -
2.167 - ke::Local<ke::Module> module(ZONE(), CompileFromSource(cc, path, bytes, length));
2.168 - delete [] bytes;
2.169 - if (!module)
2.170 - return Ke::Local<Ke::Module>();
2.171 -
2.172 - ke::Local<ke::String> pathstr(ZONE(), ke::String::New(ZONE(), path, Heap::Tenure_Old));
2.173 - if (!pathstr)
2.174 - return Ke::Local<Ke::Module>();
2.175 -
2.176 - module->setPath(pathstr);
2.177 - return ToLocal<ke::Module, Ke::Module>(module);
2.178 -}
2.179 -
2.180 -void
2.181 -Ke::Keima::InstallMessageReporter(Ke::IMessageReporter *reporter)
2.182 -{
2.183 - ZONE()->installErrorReporter(reporter);
2.184 -}
2.185 -
2.186 -class StackFrameIterator : public Ke::IStackFrameIterator
2.187 -{
2.188 - StackIter iter_;
2.189 -
2.190 - public:
2.191 - StackFrameIterator()
2.192 - : iter_(ZONE())
2.193 - {
2.194 - }
2.195 -
2.196 - virtual bool done() {
2.197 - return iter_.done();
2.198 - }
2.199 -
2.200 - const char *function() {
2.201 - return iter_.function();
2.202 - }
2.203 -
2.204 - const char *source() {
2.205 - return iter_.source();
2.206 - }
2.207 -
2.208 - unsigned lineNumber() {
2.209 - return iter_.lineNumber();
2.210 - }
2.211 -
2.212 - void prev() {
2.213 - iter_.prev();
2.214 - }
2.215 -};
2.216 -
2.217 -Ke::IStackFrameIterator *
2.218 -Ke::Keima::NewStackFrameIterator()
2.219 -{
2.220 - return new StackFrameIterator();
2.221 -}
2.222 -
2.223 -static inline ke::HeapRoot *
2.224 -FromAPI(ke::HeapRoot *from)
2.225 -{
2.226 - ke::Address address = reinterpret_cast<ke::Address>(from);
2.227 - address -= offsetof(ke::HeapRoot, obj);
2.228 - return reinterpret_cast<ke::HeapRoot *>(address);
2.229 -}
2.230 -
2.231 -ke::HeapRoot *
2.232 -Ke::Internals::NewHeapRoot(ke::Object **ptr)
2.233 -{
2.234 - ke::Local<ke::Object> obj(ZONE(), *ptr);
2.235 - ke::HeapRoot *root = ke::ZONE()->globalRoots()->create(obj);
2.236 - if (!root)
2.237 - return NULL;
2.238 -
2.239 - // Compute an interior pointer, so it looks like a Handle to an object.
2.240 - return reinterpret_cast<ke::HeapRoot *>(&root->obj);
2.241 -}
2.242 -
2.243 -void
2.244 -Ke::Internals::IncRef(ke::HeapRoot *root)
2.245 -{
2.246 - ZONE()->globalRoots()->incref(FromAPI(root));
2.247 -}
2.248 -
2.249 -void
2.250 -Ke::Internals::DecRef(ke::HeapRoot *root)
2.251 -{
2.252 - ZONE()->globalRoots()->decref(FromAPI(root));
2.253 -}
2.254 -
2.255 -bool
2.256 -Ke::Keima::IsInCallStack(Handle<Module> argModule)
2.257 -{
2.258 - ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(argModule));
2.259 - return ZONE()->stack().isInCallStack(module);
2.260 -}
2.261 -
2.262 -void
2.263 -Ke::Keima::CollectGarbage()
2.264 -{
2.265 - ke::ZONE()->heap().reclaim();
2.266 -}
2.267 -
2.268 -unsigned
2.269 -Ke::Module::numPublics()
2.270 -{
2.271 - ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(this));
2.272 - if (!module->publics())
2.273 - return 0;
2.274 - return module->publics()->length();
2.275 -}
2.276 -
2.277 -Ke::Local<Ke::Function>
2.278 -Ke::Module::getPublic(unsigned index)
2.279 -{
2.280 - ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(this));
2.281 - ke::Local<ke::Function> fun(ke::ZONE(), ke::Function::cast(module->publics()->at(index)));
2.282 - return ToLocal<ke::Function, Ke::Function>(fun);
2.283 -}
2.284 -
2.285 -unsigned
2.286 -Ke::Module::numNatives()
2.287 -{
2.288 - ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(this));
2.289 - if (!module->natives())
2.290 - return 0;
2.291 - return module->natives()->length();
2.292 -}
2.293 -
2.294 -Ke::Local<Ke::Native>
2.295 -Ke::Module::getNative(unsigned index)
2.296 -{
2.297 - ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(this));
2.298 - ke::Local<ke::Native> fun(ke::ZONE(), ke::Native::cast(module->natives()->at(index)));
2.299 - return ToLocal<ke::Native, Ke::Native>(fun);
2.300 -}
2.301 -
2.302 -void
2.303 -Ke::Module::setNativeIdentity(void *identity)
2.304 -{
2.305 - ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(this));
2.306 - module->setNativeIdentity(identity);
2.307 -}
2.308 -
2.309 -unsigned
2.310 -Ke::String::length()
2.311 -{
2.312 - ke::Local<ke::String> obj(ke::ZONE(), Open<Ke::String, ke::String>(this));
2.313 - return obj->length();
2.314 -}
2.315 -
2.316 -const char *
2.317 -Ke::String::chars()
2.318 -{
2.319 - ke::Local<ke::String> obj(ke::ZONE(), Open<Ke::String, ke::String>(this));
2.320 - return obj->chars();
2.321 -}
2.322 -
2.323 -Ke::Local<Ke::String>
2.324 -Ke::Function::name()
2.325 -{
2.326 - ke::Local<ke::Function> fun(ke::ZONE(), Open<Ke::Function, ke::Function>(this));
2.327 - return ToLocal<ke::String, Ke::String>(fun->name());
2.328 -}
2.329 -
2.330 -Ke::Local<Ke::String>
2.331 -Ke::Native::name()
2.332 -{
2.333 - ke::Local<ke::Native> native(ke::ZONE(), Open<Ke::Native, ke::Native>(this));
2.334 - return ToLocal<ke::String, Ke::String>(native->name());
2.335 -}
2.336 -
2.337 -void
2.338 -Ke::Native::bind(void *function)
2.339 -{
2.340 - ke::Local<ke::Native> native(ke::ZONE(), Open<Ke::Native, ke::Native>(this));
2.341 - native->bind(function);
2.342 -}
2.343 -
2.344 -static inline bool
2.345 -CheckInvokeType(const Ke::Parameter ¶m, Type *type)
2.346 -{
2.347 - switch (param.type()) {
2.348 - case Ke::Parameter::Array:
2.349 - return type->isArray() &&
2.350 - type->levels() == 1 &&
2.351 - type->contained()->isPrimitive() &&
2.352 - (type->contained()->primitive() != PrimitiveType_Char);
2.353 - case Ke::Parameter::CharArray:
2.354 - return type->isCharArray();
2.355 - case Ke::Parameter::Float:
2.356 - return type->isFloat();
2.357 - case Ke::Parameter::FloatRef:
2.358 - return type->isReference() && type->contained()->isFloat();
2.359 - case Ke::Parameter::Int:
2.360 - return type->isInt32();
2.361 - case Ke::Parameter::IntRef:
2.362 - return type->isReference() && type->contained()->isInt32();
2.363 - default:
2.364 - return false;
2.365 - }
2.366 -}
2.367 -
2.368 -bool
2.369 -Ke::Keima::CheckInvokeTypes(Ke::Handle<Ke::Function> argFun, const Ke::Parameter *params, unsigned nparams)
2.370 -{
2.371 - ke::Local<ke::Function> fun(ke::ZONE(), Open<Ke::Function, ke::Function>(argFun));
2.372 -
2.373 - if (fun->nargs() != nparams)
2.374 - return false;
2.375 -
2.376 - for (unsigned i = 0; i < nparams; i++) {
2.377 - if (!CheckInvokeType(params[i], fun->argType(i)))
2.378 - return false;
2.379 - }
2.380 -
2.381 - // Functions can only return tagged cells, for ISPE1-compatible Invoke().
2.382 - ke::Local<ke::Type> returnType(ke::ZONE(), fun->type()->returnType());
2.383 - if ((!returnType->isPrimitive() && !returnType->isVoid()) || returnType->isTraceable())
2.384 - return false;
2.385 -
2.386 - return true;
2.387 -}
2.388 -
2.389 -bool
2.390 -Ke::Keima::Invoke(Handle<Function> argFun, const Parameter *params, unsigned nparams, int *retval)
2.391 -{
2.392 - assert(CheckInvokeTypes(argFun, params, nparams));
2.393 -
2.394 - ke::Local<ke::Function> fun(ke::ZONE(), Open<Ke::Function, ke::Function>(argFun));
2.395 -
2.396 - if (fun->nargs() != nparams) {
2.397 - // :TODO: report error
2.398 - assert(false);
2.399 - return false;
2.400 - }
2.401 -
2.402 - ke::InvokeArgs args;
2.403 - if (!ke::ZONE()->stack().pushInvokeFrame(fun, args))
2.404 - return false;
2.405 -
2.406 - for (unsigned i = 0; i < nparams; i++) {
2.407 - ke::LocalSlot &slot = args.arg(i);
2.408 - switch (params[i].type()) {
2.409 - case Ke::Parameter::Int:
2.410 - slot.i32 = params[i].i32();
2.411 - break;
2.412 -
2.413 - case Ke::Parameter::Float:
2.414 - slot.f = params[i].f();
2.415 - break;
2.416 -
2.417 - case Ke::Parameter::IntRef:
2.418 - if (params[i].writeback()) {
2.419 - slot.ref = Reference::NewStack(ke::ZONE(), params[i].i32p(), Heap::Tenure_Stack);
2.420 - } else {
2.421 - LocalSlot other;
2.422 - other.i32 = *params[i].i32p();
2.423 - slot.ref = Reference::NewStack(ke::ZONE(), other, Heap::Tenure_Stack);
2.424 - }
2.425 - if (!slot.ref)
2.426 - return false;
2.427 - break;
2.428 -
2.429 - case Ke::Parameter::FloatRef:
2.430 - if (params[i].writeback()) {
2.431 - slot.ref = Reference::NewStack(ke::ZONE(), params[i].fp(), Heap::Tenure_Stack);
2.432 - } else {
2.433 - LocalSlot other;
2.434 - other.f = *params[i].fp();
2.435 - slot.ref = Reference::NewStack(ke::ZONE(), other, Heap::Tenure_Stack);
2.436 - }
2.437 - if (!slot.ref)
2.438 - return false;
2.439 - break;
2.440 -
2.441 - case Ke::Parameter::Array:
2.442 - {
2.443 - ke::Local<ke::ArrayMap> map(ke::ZONE(), ke::ZONE()->genericArrayMap());
2.444 - if (params[i].writeback()) {
2.445 - slot.obj = Array::NewExternal(ke::ZONE(), map, params[i].length(),
2.446 - params[i].buffer(), Heap::Tenure_Stack);
2.447 - if (!slot.obj)
2.448 - return false;
2.449 - } else {
2.450 - Array *array = Array::New(ke::ZONE(), map, params[i].length(), Heap::Tenure_Stack);
2.451 - if (!slot.obj)
2.452 - return false;
2.453 - memcpy(array->vec(), params[i].buffer(), params[i].length() * sizeof(int));
2.454 - }
2.455 - break;
2.456 - }
2.457 -
2.458 - case Ke::Parameter::CharArray:
2.459 - {
2.460 - ke::Local<ke::ArrayMap> map(ke::ZONE(), ke::ZONE()->charArrayMap());
2.461 - if (params[i].writeback()) {
2.462 - slot.obj = Array::NewExternal(ke::ZONE(), map, params[i].length(),
2.463 - params[i].buffer(), Heap::Tenure_Stack);
2.464 - if (!slot.obj)
2.465 - return false;
2.466 - } else {
2.467 - Array *array = Array::New(ke::ZONE(), map, params[i].length(), Heap::Tenure_Stack);
2.468 - if (!slot.obj)
2.469 - return false;
2.470 - memcpy(array->vec(), params[i].buffer(), params[i].length() * sizeof(char));
2.471 - }
2.472 - break;
2.473 - }
2.474 - }
2.475 - }
2.476 -
2.477 - LocalSlot result;
2.478 - if (!Interpret(ke::ZONE(), NULL, &result))
2.479 - return false;
2.480 -
2.481 - if (fun->type()->returnType()->isVoid())
2.482 - result.i32 = 0;
2.483 -
2.484 - *retval = result.i32;
2.485 - return true;
2.486 -}
3.1 --- a/jitcraft/AST.h Tue Jul 24 23:53:34 2012 -0700
3.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
3.3 @@ -1,873 +0,0 @@
3.4 -/*
3.5 - * Copyright (C) 2012 David Anderson
3.6 - *
3.7 - * This file is part of JITCraft.
3.8 - *
3.9 - * JITCraft is free software: you can redistribute it and/or modify it under
3.10 - * the terms of the GNU General Public License as published by the Free
3.11 - * Software Foundation, either version 3 of the License, or (at your option)
3.12 - * any later version.
3.13 - *
3.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
3.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
3.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
3.17 - *
3.18 - * You should have received a copy of the GNU General Public License along with
3.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
3.20 - */
3.21 -#ifndef _include_jitcraft_ast_h_
3.22 -#define _include_jitcraft_ast_h_
3.23 -
3.24 -#include "PoolAllocator.h"
3.25 -#include "Token.h"
3.26 -#include "NameBinding.h"
3.27 -#include "Vector.h"
3.28 -
3.29 -namespace ke {
3.30 -
3.31 -#define ASTKINDS(_) \
3.32 - _(VariableDeclaration) \
3.33 - _(ForStatement) \
3.34 - _(ReturnStatement) \
3.35 - _(IntegerLiteral) \
3.36 - _(FloatLiteral) \
3.37 - _(StringLiteral) \
3.38 - _(BinaryExpression) \
3.39 - _(BlockStatement) \
3.40 - _(Assignment) \
3.41 - _(NameProxy) \
3.42 - _(ExpressionStatement) \
3.43 - _(FunctionStatement) \
3.44 - _(CallExpression) \
3.45 - _(IfStatement) \
3.46 - _(IndexExpression) \
3.47 - _(EnumStatement) \
3.48 - _(WhileStatement) \
3.49 - _(BreakStatement) \
3.50 - _(ContinueStatement) \
3.51 - _(IncDecExpression) \
3.52 - _(UnaryExpression) \
3.53 - _(TernaryExpression)
3.54 -
3.55 -// Forward declarations.
3.56 -#define _(name) class name;
3.57 -ASTKINDS(_)
3.58 -#undef _
3.59 -
3.60 -class AstVisitor;
3.61 -
3.62 -// Interface for AST nodes.
3.63 -class AstNode : public PoolObject
3.64 -{
3.65 - SourcePosition pos_;
3.66 -
3.67 - public:
3.68 - enum Kind {
3.69 -# define _(name) k##name,
3.70 - ASTKINDS(_)
3.71 -# undef _
3.72 - AstKind_Invalid
3.73 - };
3.74 -
3.75 - AstNode(const SourcePosition &pos)
3.76 - : pos_(pos)
3.77 - {
3.78 - }
3.79 -
3.80 - virtual Kind kind() const = 0;
3.81 -
3.82 -#define _(name) bool is##name() { return kind() == k##name; } \
3.83 - name *to##name() { assert(is##name()); return (name *)this; }
3.84 - ASTKINDS(_)
3.85 -#undef _
3.86 -
3.87 - virtual void accept(AstVisitor *visitor) = 0;
3.88 -
3.89 - const SourcePosition &pos() const {
3.90 - return pos_;
3.91 - }
3.92 -};
3.93 -
3.94 -class AstVisitor
3.95 -{
3.96 - public:
3.97 -#define _(name) virtual void visit(name *node) = 0;
3.98 - ASTKINDS(_)
3.99 -#undef _
3.100 -};
3.101 -
3.102 -class NameLocation
3.103 -{
3.104 - public:
3.105 - enum Kind {
3.106 - LOCAL
3.107 - };
3.108 -
3.109 - static NameLocation Local(VariableDeclaration *decl) {
3.110 - NameLocation loc;
3.111 - loc.kind_ = LOCAL;
3.112 - loc.u_.decl = decl;
3.113 - return loc;
3.114 - }
3.115 -
3.116 - Kind kind() const {
3.117 - return kind_;
3.118 - }
3.119 -
3.120 - VariableDeclaration *local() const {
3.121 - assert(kind() == LOCAL);
3.122 - return u_.decl;
3.123 - }
3.124 -
3.125 - private:
3.126 - Kind kind_;
3.127 - union {
3.128 - VariableDeclaration *decl;
3.129 - } u_;
3.130 -};
3.131 -
3.132 -class Statement : public AstNode
3.133 -{
3.134 - public:
3.135 - Statement(const SourcePosition &pos)
3.136 - : AstNode(pos)
3.137 - {
3.138 - }
3.139 -};
3.140 -
3.141 -class Expression : public AstNode
3.142 -{
3.143 - ScopedRoot<Type> type_;
3.144 -
3.145 - public:
3.146 - Expression(const SourcePosition &pos)
3.147 - : AstNode(pos),
3.148 - type_(NULL)
3.149 - {
3.150 - }
3.151 -
3.152 - void setType(Type *type) {
3.153 - type_ = type;
3.154 - }
3.155 - Type *type() const {
3.156 - return type_;
3.157 - }
3.158 -};
3.159 -
3.160 -typedef PoolList<Statement *> StatementList;
3.161 -typedef PoolList<Expression *> ExpressionList;
3.162 -
3.163 -class VariableDeclaration : public Statement
3.164 -{
3.165 - Variable *variable_;
3.166 - Expression *initialization_;
3.167 - ExpressionList *postDimensions_;
3.168 - ScopedRoot<String> tag_;
3.169 -
3.170 - public:
3.171 - VariableDeclaration(const SourcePosition &pos, Variable *var, Handle<String> tag,
3.172 - ExpressionList *postDimensions, Expression *initialization)
3.173 - : Statement(pos),
3.174 - variable_(var),
3.175 - initialization_(initialization),
3.176 - postDimensions_(postDimensions),
3.177 - tag_(tag)
3.178 - {
3.179 - }
3.180 -
3.181 - String *tag() const {
3.182 - return tag_;
3.183 - }
3.184 - Kind kind() const {
3.185 - return kVariableDeclaration;
3.186 - }
3.187 - Variable *variable() const {
3.188 - return variable_;
3.189 - }
3.190 - Expression *initialization() const {
3.191 - return initialization_;
3.192 - }
3.193 - ExpressionList *postDimensions() const {
3.194 - return postDimensions_;
3.195 - }
3.196 - void accept(AstVisitor *visitor) {
3.197 - visitor->visit(this);
3.198 - }
3.199 -};
3.200 -
3.201 -class Parameter : public PoolObject
3.202 -{
3.203 - Variable *variable_;
3.204 - ScopedRoot<String> tag_;
3.205 - bool reference_;
3.206 - bool const_;
3.207 - ExpressionList *dimensions_;
3.208 -
3.209 - public:
3.210 - Parameter(Variable *var, Handle<String> tag, bool reference, bool isConst, ExpressionList *dimensions)
3.211 - : variable_(var),
3.212 - tag_(tag),
3.213 - reference_(reference),
3.214 - const_(isConst),
3.215 - dimensions_(dimensions)
3.216 - {
3.217 - }
3.218 -
3.219 - String *tag() const {
3.220 - return tag_;
3.221 - }
3.222 - Variable *variable() const {
3.223 - return variable_;
3.224 - }
3.225 - bool reference() const {
3.226 - return reference_;
3.227 - }
3.228 - ExpressionList *dimensions() const {
3.229 - return dimensions_;
3.230 - }
3.231 - bool isConst() const {
3.232 - return const_;
3.233 - }
3.234 -};
3.235 -
3.236 -class NameProxy : public Expression
3.237 -{
3.238 - ScopedRoot<String> name_;
3.239 - BoundName *binding_;
3.240 -
3.241 - public:
3.242 - NameProxy(const SourcePosition &pos, Handle<String> name, BoundName *binding)
3.243 - : Expression(pos),
3.244 - name_(name),
3.245 - binding_(binding)
3.246 - {
3.247 - }
3.248 -
3.249 - Kind kind() const {
3.250 - return kNameProxy;
3.251 - }
3.252 - String *name() const {
3.253 - return name_;
3.254 - }
3.255 - void accept(AstVisitor *visitor) {
3.256 - visitor->visit(this);
3.257 - }
3.258 - BoundName *binding() const {
3.259 - return binding_;
3.260 - }
3.261 - void bind(BoundName *name) {
3.262 - assert(!binding());
3.263 - binding_ = name;
3.264 - }
3.265 -};
3.266 -
3.267 -class IntegerLiteral : public Expression
3.268 -{
3.269 - int value_;
3.270 -
3.271 - public:
3.272 - IntegerLiteral(const SourcePosition &pos, int value)
3.273 - : Expression(pos),
3.274 - value_(value)
3.275 - {
3.276 - }
3.277 -
3.278 - Kind kind() const {
3.279 - return kIntegerLiteral;
3.280 - }
3.281 - int value() const {
3.282 - return value_;
3.283 - }
3.284 - void accept(AstVisitor *visitor) {
3.285 - visitor->visit(this);
3.286 - }
3.287 -};
3.288 -
3.289 -class FloatLiteral : public Expression
3.290 -{
3.291 - double value_;
3.292 -
3.293 - public:
3.294 - FloatLiteral(const SourcePosition &pos, double value)
3.295 - : Expression(pos),
3.296 - value_(value)
3.297 - {
3.298 - }
3.299 -
3.300 - Kind kind() const {
3.301 - return kFloatLiteral;
3.302 - }
3.303 - double value() const {
3.304 - return value_;
3.305 - }
3.306 - void accept(AstVisitor *visitor) {
3.307 - visitor->visit(this);
3.308 - }
3.309 -};
3.310 -
3.311 -class StringLiteral : public Expression
3.312 -{
3.313 - ScopedRoot<ByteArray> string_;
3.314 -
3.315 - public:
3.316 - StringLiteral(const SourcePosition &pos, ByteArray *array)
3.317 - : Expression(pos),
3.318 - string_(array)
3.319 - {
3.320 - }
3.321 -
3.322 - Kind kind() const {
3.323 - return kStringLiteral;
3.324 - }
3.325 - ByteArray *string() const {
3.326 - return string_;
3.327 - }
3.328 - void accept(AstVisitor *visitor) {
3.329 - visitor->visit(this);
3.330 - }
3.331 -};
3.332 -
3.333 -class UnaryExpression : public Expression
3.334 -{
3.335 - Expression *expression_;
3.336 - TokenKind token_;
3.337 -
3.338 - public:
3.339 - UnaryExpression(const SourcePosition &pos, TokenKind token, Expression *expr)
3.340 - : Expression(pos),
3.341 - expression_(expr),
3.342 - token_(token)
3.343 - {
3.344 - }
3.345 -
3.346 - Kind kind() const {
3.347 - return kUnaryExpression;
3.348 - }
3.349 - Expression *expression() const {
3.350 - return expression_;
3.351 - }
3.352 - TokenKind token() const {
3.353 - return token_;
3.354 - }
3.355 - void accept(AstVisitor *visitor) {
3.356 - visitor->visit(this);
3.357 - }
3.358 -};
3.359 -
3.360 -class BinaryExpression : public Expression
3.361 -{
3.362 - Expression *left_;
3.363 - Expression *right_;
3.364 - TokenKind token_;
3.365 -
3.366 - public:
3.367 - BinaryExpression(const SourcePosition &pos, TokenKind token, Expression *left, Expression *right)
3.368 - : Expression(pos),
3.369 - left_(left),
3.370 - right_(right),
3.371 - token_(token)
3.372 - {
3.373 - }
3.374 -
3.375 - Kind kind() const {
3.376 - return kBinaryExpression;
3.377 - }
3.378 - Expression *left() const {
3.379 - return left_;
3.380 - }
3.381 - Expression *right() const {
3.382 - return right_;
3.383 - }
3.384 - TokenKind token() const {
3.385 - return token_;
3.386 - }
3.387 - void accept(AstVisitor *visitor) {
3.388 - visitor->visit(this);
3.389 - }
3.390 -};
3.391 -
3.392 -class TernaryExpression : public Expression
3.393 -{
3.394 - Expression *condition_;
3.395 - Expression *left_;
3.396 - Expression *right_;
3.397 -
3.398 - public:
3.399 - TernaryExpression(const SourcePosition &pos, Expression *condition, Expression *left, Expression *right)
3.400 - : Expression(pos),
3.401 - condition_(condition),
3.402 - left_(left),
3.403 - right_(right)
3.404 - {
3.405 - }
3.406 -
3.407 - Kind kind() const {
3.408 - return kTernaryExpression;
3.409 - }
3.410 - Expression *condition() const {
3.411 - return condition_;
3.412 - }
3.413 - Expression *left() const {
3.414 - return left_;
3.415 - }
3.416 - Expression *right() const {
3.417 - return right_;
3.418 - }
3.419 - void accept(AstVisitor *visitor) {
3.420 - visitor->visit(this);
3.421 - }
3.422 -};
3.423 -
3.424 -class IndexExpression : public Expression
3.425 -{
3.426 - Expression *left_;
3.427 - Expression *right_;
3.428 -
3.429 - public:
3.430 - IndexExpression(const SourcePosition &pos, Expression *left, Expression *right)
3.431 - : Expression(pos),
3.432 - left_(left),
3.433 - right_(right)
3.434 - {
3.435 - }
3.436 -
3.437 - Kind kind() const {
3.438 - return kIndexExpression;
3.439 - }
3.440 - Expression *left() const {
3.441 - return left_;
3.442 - }
3.443 - Expression *right() const {
3.444 - return right_;
3.445 - }
3.446 - void accept(AstVisitor *visitor) {
3.447 - visitor->visit(this);
3.448 - }
3.449 -};
3.450 -
3.451 -class CallExpression : public Expression
3.452 -{
3.453 - Expression *callee_;
3.454 - ExpressionList *arguments_;
3.455 -
3.456 - public:
3.457 - CallExpression(const SourcePosition &pos, Expression *callee, ExpressionList *arguments)
3.458 - : Expression(pos),
3.459 - callee_(callee),
3.460 - arguments_(arguments)
3.461 - {
3.462 - }
3.463 -
3.464 - Kind kind() const {
3.465 - return kCallExpression;
3.466 - }
3.467 - Expression *callee() const {
3.468 - return callee_;
3.469 - }
3.470 - ExpressionList *arguments() const {
3.471 - return arguments_;
3.472 - }
3.473 - void accept(AstVisitor *visitor) {
3.474 - visitor->visit(this);
3.475 - }
3.476 -};
3.477 -
3.478 -class ForStatement : public Statement
3.479 -{
3.480 - Scope *scope_;
3.481 - Statement *initialization_;
3.482 - Expression *condition_;
3.483 - Statement *update_;
3.484 - Statement *body_;
3.485 -
3.486 - public:
3.487 - ForStatement(const SourcePosition &pos, Scope *scope, Statement *initialization,
3.488 - Expression *condition, Statement *update, Statement *body)
3.489 - : Statement(pos),
3.490 - scope_(scope),
3.491 - initialization_(initialization),
3.492 - condition_(condition),
3.493 - update_(update),
3.494 - body_(body)
3.495 - {
3.496 - }
3.497 -
3.498 - Kind kind() const {
3.499 - return kForStatement;
3.500 - }
3.501 - Statement *initialization() const {
3.502 - return initialization_;
3.503 - }
3.504 - Scope *scope() const {
3.505 - return scope_;
3.506 - }
3.507 - Expression *condition() const {
3.508 - return condition_;
3.509 - }
3.510 - Statement *update() const {
3.511 - return update_;
3.512 - }
3.513 - Statement *body() const {
3.514 - return body_;
3.515 - }
3.516 - void accept(AstVisitor *visitor) {
3.517 - visitor->visit(this);
3.518 - }
3.519 -};
3.520 -
3.521 -class WhileStatement : public Statement
3.522 -{
3.523 - TokenKind token_;
3.524 - Expression *condition_;
3.525 - Statement *body_;
3.526 -
3.527 - public:
3.528 - WhileStatement(const SourcePosition &pos, TokenKind kind, Expression *condition, Statement *body)
3.529 - : Statement(pos),
3.530 - token_(kind),
3.531 - condition_(condition),
3.532 - body_(body)
3.533 - {
3.534 - }
3.535 -
3.536 - Kind kind() const {
3.537 - return kWhileStatement;
3.538 - }
3.539 - TokenKind token() const {
3.540 - return token_;
3.541 - }
3.542 - Expression *condition() const {
3.543 - return condition_;
3.544 - }
3.545 - Statement *body() const {
3.546 - return body_;
3.547 - }
3.548 - void accept(AstVisitor *visitor) {
3.549 - visitor->visit(this);
3.550 - }
3.551 -};
3.552 -
3.553 -class ReturnStatement : public Statement
3.554 -{
3.555 - Expression *expression_;
3.556 -
3.557 - public:
3.558 - ReturnStatement(const SourcePosition &pos, Expression *expression)
3.559 - : Statement(pos),
3.560 - expression_(expression)
3.561 - {
3.562 - }
3.563 -
3.564 - Kind kind() const {
3.565 - return kReturnStatement;
3.566 - }
3.567 - Expression *expression() const {
3.568 - return expression_;
3.569 - }
3.570 - void accept(AstVisitor *visitor) {
3.571 - visitor->visit(this);
3.572 - }
3.573 -};
3.574 -
3.575 -class BreakStatement : public Statement
3.576 -{
3.577 - public:
3.578 - BreakStatement(const SourcePosition &pos)
3.579 - : Statement(pos)
3.580 - {
3.581 - }
3.582 -
3.583 - Kind kind() const {
3.584 - return kBreakStatement;
3.585 - }
3.586 - void accept(AstVisitor *visitor) {
3.587 - visitor->visit(this);
3.588 - }
3.589 -};
3.590 -
3.591 -class ContinueStatement : public Statement
3.592 -{
3.593 - public:
3.594 - ContinueStatement(const SourcePosition &pos)
3.595 - : Statement(pos)
3.596 - {
3.597 - }
3.598 -
3.599 - Kind kind() const {
3.600 - return kContinueStatement;
3.601 - }
3.602 - void accept(AstVisitor *visitor) {
3.603 - visitor->visit(this);
3.604 - }
3.605 -};
3.606 -
3.607 -class Assignment : public Expression
3.608 -{
3.609 - TokenKind token_;
3.610 - Expression *lvalue_;
3.611 - Expression *expression_;
3.612 -
3.613 - public:
3.614 - Assignment(const SourcePosition &pos, TokenKind token, Expression *left, Expression *right)
3.615 - : Expression(pos),
3.616 - token_(token),
3.617 - lvalue_(left),
3.618 - expression_(right)
3.619 - {
3.620 - }
3.621 -
3.622 - Kind kind() const {
3.623 - return kAssignment;
3.624 - }
3.625 - TokenKind token() const {
3.626 - return token_;
3.627 - }
3.628 - Expression *lvalue() const {
3.629 - return lvalue_;
3.630 - }
3.631 - Expression *expression() const {
3.632 - return expression_;
3.633 - }
3.634 - void accept(AstVisitor *visitor) {
3.635 - visitor->visit(this);
3.636 - }
3.637 -};
3.638 -
3.639 -class ExpressionStatement : public Statement
3.640 -{
3.641 - Expression *expression_;
3.642 -
3.643 - public:
3.644 - ExpressionStatement(Expression *expression)
3.645 - : Statement(expression->pos()),
3.646 - expression_(expression)
3.647 - {
3.648 - }
3.649 -
3.650 - Kind kind() const {
3.651 - return kExpressionStatement;
3.652 - }
3.653 - Expression *expression() const {
3.654 - return expression_;
3.655 - }
3.656 - void accept(AstVisitor *visitor) {
3.657 - visitor->visit(this);
3.658 - }
3.659 -};
3.660 -
3.661 -class BlockStatement : public Statement
3.662 -{
3.663 - Scope *scope_;
3.664 - StatementList *statements_;
3.665 -
3.666 - public:
3.667 - BlockStatement(const SourcePosition &pos, Scope *scope, StatementList *statements)
3.668 - : Statement(pos),
3.669 - scope_(scope),
3.670 - statements_(statements)
3.671 - {
3.672 - }
3.673 -
3.674 - Kind kind() const {
3.675 - return kBlockStatement;
3.676 - }
3.677 - Scope *scope() const {
3.678 - return scope_;
3.679 - }
3.680 - StatementList *statements() const {
3.681 - return statements_;
3.682 - }
3.683 - void accept(AstVisitor *visitor) {
3.684 - visitor->visit(this);
3.685 - }
3.686 -};
3.687 -
3.688 -typedef PoolList<Parameter *> ParameterList;
3.689 -
3.690 -class FunctionStatement : public Statement
3.691 -{
3.692 - Scope *scope_;
3.693 - NamedFunction *fun_;
3.694 - Statement *body_;
3.695 - ParameterList *parameters_;
3.696 - bool explicitReturn_;
3.697 -
3.698 - public:
3.699 - FunctionStatement(const SourcePosition &pos, Scope *scope, NamedFunction *fun, Statement *body,
3.700 - ParameterList *parameters, bool explicitReturn)
3.701 - : Statement(pos),
3.702 - scope_(scope),
3.703 - fun_(fun),
3.704 - body_(body),
3.705 - parameters_(parameters),
3.706 - explicitReturn_(explicitReturn)
3.707 - {
3.708 - }
3.709 -
3.710 - Kind kind() const {
3.711 - return kFunctionStatement;
3.712 - }
3.713 - Scope *scope() const {
3.714 - return scope_;
3.715 - }
3.716 - NamedFunction *fun() const {
3.717 - return fun_;
3.718 - }
3.719 - Statement *body() const {
3.720 - return body_;
3.721 - }
3.722 - ParameterList *parameters() const {
3.723 - return parameters_;
3.724 - }
3.725 - void accept(AstVisitor *visitor) {
3.726 - visitor->visit(this);
3.727 - }
3.728 - bool hasExplicitReturn() const {
3.729 - return explicitReturn_;
3.730 - }
3.731 -};
3.732 -
3.733 -class IfStatement : public Statement
3.734 -{
3.735 - Expression *condition_;
3.736 - Statement *ifTrue_;
3.737 - Statement *ifFalse_;
3.738 -
3.739 - public:
3.740 - IfStatement(const SourcePosition &pos, Expression *condition, Statement *ifTrue)
3.741 - : Statement(pos),
3.742 - condition_(condition),
3.743 - ifTrue_(ifTrue),
3.744 - ifFalse_(NULL)
3.745 - {
3.746 - }
3.747 -
3.748 - Kind kind() const {
3.749 - return kIfStatement;
3.750 - }
3.751 - Expression *condition() const {
3.752 - return condition_;
3.753 - }
3.754 - Statement *ifTrue() const {
3.755 - return ifTrue_;
3.756 - }
3.757 - Statement *ifFalse() const {
3.758 - return ifFalse_;
3.759 - }
3.760 - void setIfFalse(Statement *ifFalse) {
3.761 - ifFalse_ = ifFalse;
3.762 - }
3.763 - void accept(AstVisitor *visitor) {
3.764 - visitor->visit(this);
3.765 - }
3.766 -};
3.767 -
3.768 -class EnumStatement : public Statement
3.769 -{
3.770 - ScopedRoot<String> name_;
3.771 -
3.772 - public:
3.773 - struct Entry {
3.774 - NamedConstant *name;
3.775 - Expression *expr;
3.776 -
3.777 - Entry(NamedConstant *name, Expression *expr)
3.778 - : name(name),
3.779 - expr(expr)
3.780 - {
3.781 - }
3.782 - };
3.783 -
3.784 - typedef PoolList<Entry> EntryList;
3.785 -
3.786 - public:
3.787 - EnumStatement(const SourcePosition &pos, Handle<String> name, EntryList *entries)
3.788 - : Statement(pos),
3.789 - name_(name),
3.790 - entries_(entries)
3.791 - {
3.792 - }
3.793 -
3.794 - Kind kind() const {
3.795 - return kEnumStatement;
3.796 - }
3.797 - String *name() const {
3.798 - return name_;
3.799 - }
3.800 - EntryList *entries() const {
3.801 - return entries_;
3.802 - }
3.803 - void accept(AstVisitor *visitor) {
3.804 - visitor->visit(this);
3.805 - }
3.806 -
3.807 - private:
3.808 - EntryList *entries_;
3.809 -};
3.810 -
3.811 -class IncDecExpression : public Expression
3.812 -{
3.813 - TokenKind token_;
3.814 - Expression *expression_;
3.815 - bool postfix_;
3.816 -
3.817 - public:
3.818 - IncDecExpression(const SourcePosition &pos, TokenKind token, Expression *expression, bool postfix)
3.819 - : Expression(pos),
3.820 - token_(token),
3.821 - expression_(expression),
3.822 - postfix_(postfix)
3.823 - {
3.824 - }
3.825 -
3.826 - Kind kind() const {
3.827 - return kIncDecExpression;
3.828 - }
3.829 - TokenKind token() const {
3.830 - return token_;
3.831 - }
3.832 - Expression *expression() const {
3.833 - return expression_;
3.834 - }
3.835 - bool postfix() const {
3.836 - return postfix_;
3.837 - }
3.838 - void accept(AstVisitor *visitor) {
3.839 - visitor->visit(this);
3.840 - }
3.841 -};
3.842 -
3.843 -class Scope;
3.844 -
3.845 -typedef PoolList<NameProxy *> NameProxyList;
3.846 -
3.847 -class ParseTree : public PoolObject
3.848 -{
3.849 - StatementList *statements_;
3.850 - Scope *scope_;
3.851 - NameProxyList *unbound_;
3.852 -
3.853 - public:
3.854 - ParseTree(Scope *scope, StatementList *statements, NameProxyList *unbound)
3.855 - : statements_(statements),
3.856 - scope_(scope),
3.857 - unbound_(unbound)
3.858 - {
3.859 - }
3.860 -
3.861 - void dump(FILE *fp);
3.862 -
3.863 - StatementList *statements() const {
3.864 - return statements_;
3.865 - }
3.866 - Scope *scope() const {
3.867 - return scope_;
3.868 - }
3.869 - NameProxyList *unbound() const {
3.870 - return unbound_;
3.871 - }
3.872 -};
3.873 -
3.874 -}
3.875 -
3.876 -#endif // _include_jitcraft_ast_h_
4.1 --- a/jitcraft/AllocatorPolicies.h Tue Jul 24 23:53:34 2012 -0700
4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
4.3 @@ -1,45 +0,0 @@
4.4 -/*
4.5 - * Copyright (C) 2012 David Anderson
4.6 - *
4.7 - * This file is part of JITCraft.
4.8 - *
4.9 - * JITCraft is free software: you can redistribute it and/or modify it under
4.10 - * the terms of the GNU General Public License as published by the Free
4.11 - * Software Foundation, either version 3 of the License, or (at your option)
4.12 - * any later version.
4.13 - *
4.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
4.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
4.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
4.17 - *
4.18 - * You should have received a copy of the GNU General Public License along with
4.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
4.20 - */
4.21 -#ifndef _include_jc_allocators_h_
4.22 -#define _include_jc_allocators_h_
4.23 -
4.24 -#include <stdlib.h>
4.25 -
4.26 -namespace ke {
4.27 -
4.28 -class ZoneAllocatorPolicy
4.29 -{
4.30 - protected:
4.31 - void reportOutOfMemory();
4.32 - void reportAllocationOverflow();
4.33 -
4.34 - public:
4.35 - void free(void *memory) {
4.36 - ::free(memory);
4.37 - }
4.38 - void *malloc(size_t bytes) {
4.39 - void *ptr = ::malloc(bytes);
4.40 - if (!ptr)
4.41 - reportOutOfMemory();
4.42 - return ptr;
4.43 - }
4.44 -};
4.45 -
4.46 -}
4.47 -
4.48 -#endif // _include_jc_allocators_h_
5.1 --- a/jitcraft/Array.cpp Tue Jul 24 23:53:34 2012 -0700
5.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
5.3 @@ -1,77 +0,0 @@
5.4 -/*
5.5 - * Copyright (C) 2012 David Anderson
5.6 - *
5.7 - * This file is part of JITCraft.
5.8 - *
5.9 - * JITCraft is free software: you can redistribute it and/or modify it under
5.10 - * the terms of the GNU General Public License as published by the Free
5.11 - * Software Foundation, either version 3 of the License, or (at your option)
5.12 - * any later version.
5.13 - *
5.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
5.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
5.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
5.17 - *
5.18 - * You should have received a copy of the GNU General Public License along with
5.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
5.20 - */
5.21 -#include "Array.h"
5.22 -#include "Heap.h"
5.23 -#include "Zone.h"
5.24 -#include "Heap-inl.h"
5.25 -
5.26 -using namespace ke;
5.27 -
5.28 -ArrayMap *
5.29 -ArrayMap::New(Zone *zone, Handle<Type> type, Handle<ArrayMap> contained)
5.30 -{
5.31 - Local<Map> obj(zone, zone->allocateMap(MapKind_Array, sizeof(ArrayMap), MapKind_MetaArray));
5.32 - if (!obj)
5.33 - return NULL;
5.34 -
5.35 - Local<ArrayMap> map(zone, ArrayMap::cast(obj));
5.36 - map->type_ = type;
5.37 - map->contained_ = contained;
5.38 - return map;
5.39 -}
5.40 -
5.41 -static inline size_t
5.42 -SizeFor(Type *type, unsigned elements)
5.43 -{
5.44 - if (type->levels() > 1)
5.45 - return sizeof(Array) + elements * sizeof(ke::Object *);
5.46 - if (type->contained()->isInt32())
5.47 - return sizeof(Array) + elements * sizeof(int);
5.48 - if (type->contained()->primitive() == PrimitiveType_Char)
5.49 - return sizeof(Array) + elements * sizeof(char);
5.50 - assert(type->contained()->isFloat());
5.51 - return elements * sizeof(float);
5.52 -}
5.53 -
5.54 -Array *
5.55 -Array::New(Zone *zone, Handle<ArrayMap> map, uint32 elements, Heap::Tenure tenure)
5.56 -{
5.57 - size_t elementBytes = SizeFor(map->type(), elements);
5.58 - size_t bytes = sizeof(Array) + elementBytes;
5.59 - Local<Array> array(zone, Array::cast(zone->allocate(map, bytes, tenure)));
5.60 - if (!array)
5.61 - return NULL;
5.62 -
5.63 - array->nelements_ = elements;
5.64 - array->elements_ = (Array *)array + 1;
5.65 - memset(array->elements_, 0, elementBytes);
5.66 - return array;
5.67 -}
5.68 -
5.69 -Array *
5.70 -Array::NewExternal(Zone *zone, Handle<ArrayMap> map, uint32 nelements, void *buffer,
5.71 - Heap::Tenure tenure)
5.72 -{
5.73 - Local<Array> array(zone, Array::cast(zone->allocate(map, sizeof(Array), tenure)));
5.74 - if (!array)
5.75 - return NULL;
5.76 -
5.77 - array->nelements_ = nelements;
5.78 - array->elements_ = buffer;
5.79 - return array;
5.80 -}
6.1 --- a/jitcraft/Array.h Tue Jul 24 23:53:34 2012 -0700
6.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
6.3 @@ -1,204 +0,0 @@
6.4 -/*
6.5 - * Copyright (C) 2012 David Anderson
6.6 - *
6.7 - * This file is part of JITCraft.
6.8 - *
6.9 - * JITCraft is free software: you can redistribute it and/or modify it under
6.10 - * the terms of the GNU General Public License as published by the Free
6.11 - * Software Foundation, either version 3 of the License, or (at your option)
6.12 - * any later version.
6.13 - *
6.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
6.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
6.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
6.17 - *
6.18 - * You should have received a copy of the GNU General Public License along with
6.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
6.20 - */
6.21 -#ifndef _include_jitcraft_array_h_
6.22 -#define _include_jitcraft_array_h_
6.23 -
6.24 -#include "Heap.h"
6.25 -#include "Handles.h"
6.26 -#include "Types.h"
6.27 -
6.28 -namespace ke {
6.29 -
6.30 -class ArrayMap;
6.31 -
6.32 -class Array : public Object
6.33 -{
6.34 - friend class ArrayMap;
6.35 -
6.36 - uint32 nelements_;
6.37 - void *elements_;
6.38 -
6.39 - public:
6.40 - static Array *New(Zone *zone, Handle<ArrayMap> map, uint32 elements,
6.41 - Heap::Tenure = Heap::Tenure_Default);
6.42 - static Array *NewExternal(Zone *zone, Handle<ArrayMap> map, uint32 nelements,
6.43 - void *elements, Heap::Tenure = Heap::Tenure_Default);
6.44 -
6.45 - uint32 nelements() {
6.46 - return nelements_;
6.47 - }
6.48 - void *vec() {
6.49 - return elements_;
6.50 - }
6.51 -
6.52 - inline int *int32Vec();
6.53 - inline float *floatVec();
6.54 - inline Object **objVec();
6.55 - inline char *chars();
6.56 -
6.57 - inline Type *type();
6.58 - inline size_t elementSize();
6.59 -
6.60 - int readInt32(size_t index) {
6.61 - assert(index < nelements());
6.62 - return int32Vec()[index];
6.63 - }
6.64 - void writeInt32(size_t index, int i) {
6.65 - assert(index < nelements());
6.66 - int32Vec()[index] = i;
6.67 - }
6.68 - char readChar(size_t index) {
6.69 - assert(index < nelements());
6.70 - return chars()[index];
6.71 - }
6.72 - void writeChar(size_t index, char c) {
6.73 - assert(index < nelements());
6.74 - chars()[index] = c;
6.75 - }
6.76 - float readFloat(size_t index) {
6.77 - assert(index < nelements());
6.78 - return floatVec()[index];
6.79 - }
6.80 - void writeFloat(size_t index, float f) {
6.81 - assert(index < nelements());
6.82 - floatVec()[index] = f;
6.83 - }
6.84 - inline void *slotPtr(size_t index);
6.85 - Object *readObject(size_t index) {
6.86 - assert(index < nelements());
6.87 - return objVec()[index];
6.88 - }
6.89 - void writeObject(Zone *zone, size_t index, Object *ptr) {
6.90 - assert(index < nelements());
6.91 - write(zone, &objVec()[index], ptr);
6.92 - }
6.93 -
6.94 - bool isExternal() {
6.95 - // Inline arrays always have their elements pointing at the next slot.
6.96 - Address buffer = reinterpret_cast<Address>(elements_);
6.97 - return buffer != reinterpret_cast<Address>(this + 1);
6.98 - }
6.99 -
6.100 - static inline size_t SizeOf(Array *array) {
6.101 - if (array->isExternal())
6.102 - return sizeof(Array);
6.103 - return sizeof(Array) + array->nelements() * array->elementSize();
6.104 - }
6.105 -
6.106 - static Array *cast(Object *obj) {
6.107 - assert(!obj || obj->is(MapKind_Array));
6.108 - return reinterpret_cast<Array *>(obj);
6.109 - }
6.110 -};
6.111 -
6.112 -class ArrayMap : public Map
6.113 -{
6.114 - Barriered<Type> type_;
6.115 - Barriered<ArrayMap> contained_;
6.116 -
6.117 - public:
6.118 - static ArrayMap *New(Zone *zone, Handle<Type> type, Handle<ArrayMap> contained);
6.119 -
6.120 - Type *type() {
6.121 - return type_;
6.122 - }
6.123 - ArrayMap *contained() {
6.124 - return contained_;
6.125 - }
6.126 -
6.127 - // GC Descriptor.
6.128 - static inline size_t offsetOfType() {
6.129 - return offsetof(ArrayMap, type_);
6.130 - }
6.131 - static inline size_t offsetOfContained() {
6.132 - return offsetof(ArrayMap, contained_);
6.133 - }
6.134 - // End GC Descriptor.
6.135 -
6.136 - static ArrayMap *cast(Object *obj) {
6.137 - assert(!obj || obj->is(MapKind_MetaArray));
6.138 - return reinterpret_cast<ArrayMap *>(obj);
6.139 - }
6.140 -};
6.141 -
6.142 -inline int *
6.143 -Array::int32Vec()
6.144 -{
6.145 - assert(type()->levels() == 1);
6.146 - assert(type()->contained()->isInt32());
6.147 - return reinterpret_cast<int *>(vec());
6.148 -}
6.149 -
6.150 -inline float *
6.151 -Array::floatVec()
6.152 -{
6.153 - assert(type()->levels() == 1);
6.154 - assert(type()->contained()->isFloat());
6.155 - return reinterpret_cast<float *>(vec());
6.156 -}
6.157 -
6.158 -inline Object **
6.159 -Array::objVec()
6.160 -{
6.161 - assert(type()->levels() > 1);
6.162 - return reinterpret_cast<Object **>(vec());
6.163 -}
6.164 -
6.165 -inline void *
6.166 -Array::slotPtr(size_t index)
6.167 -{
6.168 - assert(type()->contained()->primitive() == PrimitiveType_Int32 ||
6.169 - type()->contained()->primitive() == PrimitiveType_Float);
6.170 - assert(index < nelements());
6.171 - return reinterpret_cast<int *>(vec()) + index;
6.172 -}
6.173 -
6.174 -inline char *
6.175 -Array::chars()
6.176 -{
6.177 - assert(type()->levels() == 1);
6.178 - assert(type()->contained()->primitive() == PrimitiveType_Char);
6.179 - return reinterpret_cast<char *>(vec());
6.180 -}
6.181 -
6.182 -inline Type *
6.183 -Array::type()
6.184 -{
6.185 - return ArrayMap::cast(map())->type();
6.186 -}
6.187 -
6.188 -inline size_t
6.189 -Array::elementSize()
6.190 -{
6.191 - assert(type()->isArray());
6.192 - if (type()->contained()->isArray())
6.193 - return sizeof(Object *);
6.194 - switch (type()->contained()->primitive()) {
6.195 - case PrimitiveType_Float:
6.196 - return sizeof(float);
6.197 - case PrimitiveType_Int32:
6.198 - return sizeof(int);
6.199 - default:
6.200 - assert(type()->contained()->primitive() == PrimitiveType_Char);
6.201 - return sizeof(char);
6.202 - }
6.203 -}
6.204 -
6.205 -}
6.206 -
6.207 -#endif // _include_jitcraft_array_h_
7.1 --- a/jitcraft/Barriers.h Tue Jul 24 23:53:34 2012 -0700
7.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
7.3 @@ -1,93 +0,0 @@
7.4 -/*
7.5 - * Copyright (C) 2012 David Anderson
7.6 - *
7.7 - * This file is part of JITCraft.
7.8 - *
7.9 - * JITCraft is free software: you can redistribute it and/or modify it under
7.10 - * the terms of the GNU General Public License as published by the Free
7.11 - * Software Foundation, either version 3 of the License, or (at your option)
7.12 - * any later version.
7.13 - *
7.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
7.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
7.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
7.17 - *
7.18 - * You should have received a copy of the GNU General Public License along with
7.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
7.20 - */
7.21 -#ifndef _include_jitcraft_barriers_h_
7.22 -#define _include_jitcraft_barriers_h_
7.23 -
7.24 -namespace ke {
7.25 -
7.26 -class Object;
7.27 -
7.28 -// Used to store unbarriered heap locations.
7.29 -template <typename T>
7.30 -class Unbarriered
7.31 -{
7.32 - T *obj_;
7.33 -
7.34 - public:
7.35 - Unbarriered()
7.36 - : obj_(NULL)
7.37 - {
7.38 - }
7.39 -
7.40 - T *operator ->() const {
7.41 - return operator *();
7.42 - }
7.43 - T *operator *() const {
7.44 - return static_cast<T *>(obj_);
7.45 - }
7.46 - Unbarriered &operator =(T *obj) {
7.47 - obj_ = obj;
7.48 - return *this;
7.49 - }
7.50 - Object **address() {
7.51 - return reinterpret_cast<Object **>(&obj_);
7.52 - }
7.53 - operator bool () const {
7.54 - return !!obj_;
7.55 - }
7.56 - operator T*() const {
7.57 - return static_cast<T *>(obj_);
7.58 - }
7.59 -};
7.60 -
7.61 -// Used to store unbarriered heap locations.
7.62 -template <typename T>
7.63 -class Barriered
7.64 -{
7.65 - T *obj_;
7.66 -
7.67 - public:
7.68 - Barriered()
7.69 - : obj_(NULL)
7.70 - {
7.71 - }
7.72 -
7.73 - T *operator ->() const {
7.74 - return operator *();
7.75 - }
7.76 - T *operator *() const {
7.77 - return static_cast<T *>(obj_);
7.78 - }
7.79 - Barriered &operator =(T *obj) {
7.80 - obj_ = obj;
7.81 - return *this;
7.82 - }
7.83 - Object **addr() {
7.84 - return reinterpret_cast<Object **>(&obj_);
7.85 - }
7.86 - operator bool () const {
7.87 - return !!obj_;
7.88 - }
7.89 - operator T*() const {
7.90 - return static_cast<T *>(obj_);
7.91 - }
7.92 -};
7.93 -
7.94 -}
7.95 -
7.96 -#endif // _include_jitcraft_barriers_h_
8.1 --- a/jitcraft/BytecodeCompiler.cpp Tue Jul 24 23:53:34 2012 -0700
8.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
8.3 @@ -1,1096 +0,0 @@
8.4 -/* vim: set ts=4 sw=4 tw=99 et:
8.5 - *
8.6 - * Copyright (C) 2012 David Anderson
8.7 - *
8.8 - * This file is part of JITCraft.
8.9 - *
8.10 - * JITCraft is free software: you can redistribute it and/or modify it under
8.11 - * the terms of the GNU General Public License as published by the Free
8.12 - * Software Foundation, either version 3 of the License, or (at your option)
8.13 - * any later version.
8.14 - *
8.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
8.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
8.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
8.18 - *
8.19 - * You should have received a copy of the GNU General Public License along with
8.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
8.21 - */
8.22 -#include "BytecodeCompiler.h"
8.23 -#include "Scopes.h"
8.24 -#include "Modules.h"
8.25 -#include "Types.h"
8.26 -#include "Array.h"
8.27 -#include "Strings.h"
8.28 -#include "Zone.h"
8.29 -#include "Environments.h"
8.30 -#include "Heap-inl.h"
8.31 -
8.32 -using namespace ke;
8.33 -
8.34 -typedef BytecodeEmitter::Label Label;
8.35 -
8.36 -#define __ emitter_.
8.37 -
8.38 -BytecodeCompiler::BytecodeCompiler(Zone *zone, ParseTree *tree, ModuleData *module)
8.39 - : zone_(zone),
8.40 - tree_(tree),
8.41 - emitter_(zone->pool()),
8.42 - moduleData_(module),
8.43 - locals_(NULL),
8.44 - scope_(NULL),
8.45 - loop_(NULL)
8.46 -{
8.47 -}
8.48 -
8.49 -static inline TokenKind
8.50 -ToCompare(Expression *expr)
8.51 -{
8.52 - if (expr->isBinaryExpression()) {
8.53 - BinaryExpression *b = expr->toBinaryExpression();
8.54 - if (b->token() >= TOK_EQUALS && b->token() <= TOK_OR)
8.55 - return b->token();
8.56 - } else if (expr->isUnaryExpression()) {
8.57 - UnaryExpression *u = expr->toUnaryExpression();
8.58 - if (u->token() == TOK_NOT)
8.59 - return TOK_NOT;
8.60 - }
8.61 - return TOK_EOF;
8.62 -}
8.63 -
8.64 -static inline Opcode
8.65 -CompareTokenToJump(TokenKind kind)
8.66 -{
8.67 - switch (kind) {
8.68 - case TOK_EQUALS:
8.69 - return OP_JEQ;
8.70 - case TOK_NOTEQUALS:
8.71 - return OP_JNE;
8.72 - case TOK_GT:
8.73 - return OP_JG;
8.74 - case TOK_GE:
8.75 - return OP_JGE;
8.76 - case TOK_LT:
8.77 - return OP_JL;
8.78 - default:
8.79 - assert(kind == TOK_LE);
8.80 - return OP_JLE;
8.81 - }
8.82 -}
8.83 -
8.84 -static inline Opcode
8.85 -TokenToOpcode(TokenKind kind)
8.86 -{
8.87 - switch (kind) {
8.88 - case TOK_PLUS:
8.89 - return OP_ADD;
8.90 - case TOK_MINUS:
8.91 - return OP_SUB;
8.92 - case TOK_STAR:
8.93 - return OP_MUL;
8.94 - case TOK_SLASH:
8.95 - return OP_DIV;
8.96 - case TOK_PERCENT:
8.97 - return OP_MOD;
8.98 - case TOK_SHR:
8.99 - return OP_SHR;
8.100 - case TOK_USHR:
8.101 - return OP_USHR;
8.102 - case TOK_SHL:
8.103 - return OP_SHL;
8.104 - case TOK_BITAND:
8.105 - return OP_BITAND;
8.106 - case TOK_BITOR:
8.107 - return OP_BITOR;
8.108 - case TOK_GT:
8.109 - return OP_GT;
8.110 - case TOK_GE:
8.111 - return OP_GE;
8.112 - case TOK_LT:
8.113 - return OP_LT;
8.114 - case TOK_LE:
8.115 - return OP_LE;
8.116 - case TOK_EQUALS:
8.117 - return OP_EQ;
8.118 - case TOK_NOTEQUALS:
8.119 - return OP_NE;
8.120 - default:
8.121 - assert(kind == TOK_BITXOR);
8.122 - return OP_BITXOR;
8.123 - }
8.124 -}
8.125 -
8.126 -void
8.127 -BytecodeCompiler::recordLifoSlot(Scope *scope)
8.128 -{
8.129 - if (!scope)
8.130 - return;
8.131 -
8.132 - if (Variable *var = scope->lifoSlot()) {
8.133 - locals_->set(zone_, var->slot(), var->type());
8.134 - __ savelifo(var->slot());
8.135 - }
8.136 -}
8.137 -
8.138 -void
8.139 -BytecodeCompiler::unwindTo(Scope *scope)
8.140 -{
8.141 - // Note: we only need to unwind to the outermost scope's LIFO slot.
8.142 - Variable *var = NULL;
8.143 - for (Scope *current = scope_; current != scope; current = current->enclosing()) {
8.144 - if (Variable *slot = current->lifoSlot())
8.145 - var = slot;
8.146 - }
8.147 -
8.148 - if (var)
8.149 - __ unwindlifo(var->slot());
8.150 -}
8.151 -
8.152 -void
8.153 -BytecodeCompiler::visit(NameProxy *name)
8.154 -{
8.155 - switch (name->binding()->kind()) {
8.156 - case BoundName::VARIABLE:
8.157 - {
8.158 - Variable *var = name->binding()->toVariable();
8.159 -
8.160 - if (var->location() == Variable::STACK) {
8.161 - __ getlocal(var);
8.162 - assert(!name->type()->isReference());
8.163 - } else if (var->location() == Variable::ENVIRONMENT) {
8.164 - getEnvSlot(var);
8.165 - } else {
8.166 - assert(var->location() == Variable::PARAMETER);
8.167 - __ getarg(var);
8.168 -
8.169 - // If this argument is actually a reference, dereference it now.
8.170 - if (var->type()->isReference())
8.171 - __ getref(var->type()->contained()->primitive());
8.172 - }
8.173 - break;
8.174 - }
8.175 -
8.176 - case BoundName::FUNCTION:
8.177 - {
8.178 - NamedFunction *fun = name->binding()->toNamedFunction();
8.179 - __ module();
8.180 - __ getmodule_fn(fun->slot());
8.181 - break;
8.182 - }
8.183 -
8.184 - default:
8.185 - {
8.186 - NamedConstant *constant = name->binding()->toNamedConstant();
8.187 - __ int_(constant->value().toInt());
8.188 - break;
8.189 - }
8.190 - }
8.191 -}
8.192 -
8.193 -void
8.194 -BytecodeCompiler::visit(ExpressionStatement *node)
8.195 -{
8.196 - // Expressions leave their value on the top of the stack, so we make sure
8.197 - // to balance the stack if they're used as a statement.
8.198 - node->expression()->accept(this);
8.199 - if (!node->expression()->type()->isVoid())
8.200 - __ pop();
8.201 -}
8.202 -
8.203 -void
8.204 -BytecodeCompiler::visit(Assignment *node)
8.205 -{
8.206 - // The first step is three sub-steps:
8.207 - //
8.208 - // (1) Bind the left-hand side.
8.209 - // -- If a cumulative operation (+=, etc):
8.210 - // (2) Save a copy of the binding on the stack.
8.211 - // (3) Dereference the binding to get a value.
8.212 - //
8.213 - if (node->lvalue()->isNameProxy()) {
8.214 - NameProxy *proxy = node->lvalue()->toNameProxy();
8.215 - Variable *var = proxy->binding()->toVariable();
8.216 -
8.217 - // Bind.
8.218 - if (var->type()->isReference() || var->type()->isArray())
8.219 - __ get(var);
8.220 -
8.221 - // Get the value if needed.
8.222 - if (node->token() != TOK_ASSIGN) {
8.223 - // += etc is not allowed on arrays.
8.224 - assert(!var->type()->isArray());
8.225 -
8.226 - if (var->type()->isReference()) {
8.227 - __ dup();
8.228 - __ getref(var->type()->contained()->primitive());
8.229 - } else {
8.230 - __ get(var);
8.231 - }
8.232 - }
8.233 - } else {
8.234 - IndexExpression *index = node->lvalue()->toIndexExpression();
8.235 - __ note_position(index->pos());
8.236 -
8.237 - // Note: Eventually, watch out for a whole here. An expression like:
8.238 - //
8.239 - // (a[4] = (5, a = []))
8.240 - //
8.241 - // Could shrink array, so we need to either bind a[i] to a Reference,
8.242 - // or keep the bounds check near the set. This is just a semantic
8.243 - // decision.
8.244 - index->left()->accept(this);
8.245 - index->right()->accept(this);
8.246 -
8.247 - if (node->token() != TOK_ASSIGN) {
8.248 - __ dup2();
8.249 - __ bounds();
8.250 - if (node->type()->isArray())
8.251 - __ getarray_o();
8.252 - else
8.253 - __ getarray(node->type()->primitive());
8.254 - }
8.255 - }
8.256 -
8.257 - if (node->token() == TOK_ASSIGN) {
8.258 - node->expression()->accept(this);
8.259 - } else {
8.260 - visitForALU(node->type(), node->expression());
8.261 -
8.262 - TokenKind alu = TokenKind(int(node->token()) - (TOK_ASSIGN_ADD - TOK_PLUS));
8.263 - __ note_position(node->pos());
8.264 - __ binary(TokenToOpcode(alu));
8.265 - }
8.266 -
8.267 - // Emit the store.
8.268 - if (node->expression()->type()->isArray()) {
8.269 - // Unlike references, which can only be computed from a NamePRoxy,
8.270 - // arrays can be computed from multiple lvalue types.
8.271 - __ note_position(node->pos());
8.272 - __ arraycopy();
8.273 - } else if (node->lvalue()->isNameProxy()) {
8.274 - NameProxy *proxy = node->lvalue()->toNameProxy();
8.275 - Variable *var = proxy->binding()->toVariable();
8.276 -
8.277 - if (var->type()->isReference())
8.278 - __ setref(var->type()->contained()->primitive());
8.279 - else
8.280 - __ set(var);
8.281 - } else {
8.282 - IndexExpression *index = node->lvalue()->toIndexExpression();
8.283 - // :TODO: get rid of the BOUNDS instruction, embed it in g/setarray*?
8.284 - // We can't emit it here because the stack is slightly out of position.
8.285 - // __ bounds();
8.286 - __ setarray(index->left()->type()->contained()->primitive());
8.287 - }
8.288 -}
8.289 -
8.290 -void
8.291 -BytecodeCompiler::visit(IncDecExpression *node)
8.292 -{
8.293 - // In the postfix case, the logic looks like:
8.294 - // (1) Bind -> REF
8.295 - // (2) Dup -> REF REF
8.296 - // (3) Fetch -> REF VAL
8.297 - // (4) Swap -> VAL REF
8.298 - // (5) Pick -> VAL REF VAL
8.299 - // (6) Add -> VAL REF VAL+1
8.300 - // (7) Store -> VAL VAL+1
8.301 - // (8) Drop -> VAL
8.302 - //
8.303 - // In the prefix case, the logic looks like:
8.304 - // (1) Bind -> REF
8.305 - // (2) Dup -> REF REF
8.306 - // (3) Fetch -> REF VAL
8.307 - // --
8.308 - // --
8.309 - // (6) Add -> REF VAL+1
8.310 - // (7) Store -> VAL+1
8.311 - // --
8.312 - //
8.313 - // This is squirrely enough such that we don't bother sharing too much
8.314 - // with the above.
8.315 - //
8.316 - // Note: We simulate a "Pick" operation with a dup2+pop.
8.317 -
8.318 - // This is steps (1) to (5).
8.319 - Expression *expr = node->expression();
8.320 - if (expr->isNameProxy()) {
8.321 - NameProxy *proxy = expr->toNameProxy();
8.322 - Variable *var = proxy->binding()->toVariable();
8.323 -
8.324 - // Bind.
8.325 - if (var->type()->isReference() || var->type()->isArray())
8.326 - __ get(var);
8.327 -
8.328 - // Dup and fetch.
8.329 - if (var->type()->isReference()) {
8.330 - __ dup();
8.331 - __ getref(node->type()->primitive());
8.332 - if (node->postfix()) {
8.333 - __ swap();
8.334 - __ pick2();
8.335 - }
8.336 - } else {
8.337 - assert(!var->type()->isArray());
8.338 - __ get(var);
8.339 - if (node->postfix())
8.340 - __ dup();
8.341 - }
8.342 - } else {
8.343 - IndexExpression *index = expr->toIndexExpression();
8.344 - __ note_position(index->pos());
8.345 -
8.346 - index->left()->accept(this);
8.347 - index->right()->accept(this);
8.348 -
8.349 - assert(!node->type()->isArray());
8.350 - __ bounds();
8.351 - __ dup2();
8.352 - __ getarray(node->type()->primitive());
8.353 -
8.354 - if (node->postfix()) {
8.355 - // The stack looks like this now:
8.356 - // ARRAY INDEX VALUE
8.357 - //
8.358 - // So we must use a PICK operation to rotate the stack into position.
8.359 - __ roll3(); // INDEX VALUE ARRAY
8.360 - __ roll3(); // VALUE ARRAY INDEX
8.361 - __ pick3(); // VALUE ARRAY INDEX VALUE
8.362 - }
8.363 - }
8.364 -
8.365 - // Perform step (6).
8.366 - if (node->type()->isFloat()) {
8.367 - __ float_(1.0);
8.368 - } else {
8.369 - assert(node->type()->isInt32());
8.370 - __ int_(1);
8.371 - }
8.372 -
8.373 - __ note_position(node->pos());
8.374 - if (node->token() == TOK_INCREMENT)
8.375 - __ binary(OP_ADD);
8.376 - else
8.377 - __ binary(OP_SUB);
8.378 -
8.379 - // Perform step (7).
8.380 - if (expr->isNameProxy()) {
8.381 - NameProxy *proxy = expr->toNameProxy();
8.382 - Variable *var = proxy->binding()->toVariable();
8.383 -
8.384 - if (var->type()->isReference())
8.385 - __ setref(node->type()->primitive());
8.386 - else
8.387 - __ set(var);
8.388 - } else {
8.389 - __ setarray(node->type()->primitive());
8.390 - }
8.391 -
8.392 - // Perform step (8).
8.393 - if (node->postfix())
8.394 - __ pop();
8.395 -}
8.396 -
8.397 -void
8.398 -BytecodeCompiler::visitForALU(Type *needed, Expression *node)
8.399 -{
8.400 - node->accept(this);
8.401 - if (needed->isFloat() && !node->type()->isFloat())
8.402 - __ cvt_i2f();
8.403 - else
8.404 - assert(needed->primitive() == node->type()->primitive());
8.405 -}
8.406 -
8.407 -static inline Type *
8.408 -GetCoercionType(TokenKind tok, Type *left, Type *right)
8.409 -{
8.410 - if (left->isFloat())
8.411 - return left;
8.412 - return right;
8.413 -}
8.414 -
8.415 -void
8.416 -BytecodeCompiler::visit(UnaryExpression *node)
8.417 -{
8.418 - switch (node->token()) {
8.419 - case TOK_MINUS:
8.420 - {
8.421 - Local<Type> type(zone_, node->expression()->type());
8.422 - node->expression()->accept(this);
8.423 -
8.424 - if (node->type()->isFloat())
8.425 - __ neg_f();
8.426 - else
8.427 - __ neg();
8.428 - break;
8.429 - }
8.430 -
8.431 - case TOK_NOT:
8.432 - {
8.433 - Local<Type> type(zone_, node->expression()->type());
8.434 - node->expression()->accept(this);
8.435 -
8.436 - if (node->type()->isFloat())
8.437 - __ not_f();
8.438 - else
8.439 - __ not_();
8.440 - break;
8.441 - }
8.442 -
8.443 - default:
8.444 - assert(node->token() == TOK_TILDE);
8.445 - node->expression()->accept(this);
8.446 - __ bitnot();
8.447 - break;
8.448 - }
8.449 -}
8.450 -
8.451 -void
8.452 -BytecodeCompiler::visit(BinaryExpression *node)
8.453 -{
8.454 - if (node->token() == TOK_AND || node->token() == TOK_OR) {
8.455 - Label success, failure, done;
8.456 - visitForTest(node, &success, &failure, &success);
8.457 - __ bind(&success);
8.458 - __ int_(1);
8.459 - __ drop(1); // Otherwise, the stack depth will be +1 too much.
8.460 - __ jump(&done);
8.461 - __ bind(&failure);
8.462 - __ int_(0);
8.463 - __ bind(&done);
8.464 - return;
8.465 - }
8.466 -
8.467 - Local<Type> leftType(zone_, node->left()->type());
8.468 - Local<Type> rightType(zone_, node->right()->type());
8.469 - Local<Type> coerce(zone_, GetCoercionType(node->token(), leftType, rightType));
8.470 -
8.471 - visitForALU(coerce, node->left());
8.472 - visitForALU(coerce, node->right());
8.473 -
8.474 - Opcode op = TokenToOpcode(node->token());
8.475 - if (node->type()->isFloat())
8.476 - op = (Opcode)(int(op) + (OP_ADD_F - OP_ADD));
8.477 -
8.478 - __ note_position(node->pos());
8.479 - __ binary(op);
8.480 -}
8.481 -
8.482 -void
8.483 -BytecodeCompiler::visit(IndexExpression *node)
8.484 -{
8.485 - node->left()->accept(this);
8.486 - node->right()->accept(this);
8.487 - __ note_position(node->pos());
8.488 - __ bounds();
8.489 -
8.490 - if (node->type()->isArray())
8.491 - __ getarray_o();
8.492 - else
8.493 - __ getarray(node->type()->primitive());
8.494 -}
8.495 -
8.496 -void
8.497 -BytecodeCompiler::visit(ReturnStatement *node)
8.498 -{
8.499 - if (node->expression()) {
8.500 - node->expression()->accept(this);
8.501 - __ return_();
8.502 - } else {
8.503 - __ returnvoid();
8.504 - }
8.505 -}
8.506 -
8.507 -void
8.508 -BytecodeCompiler::visitForTest(Expression *expression,
8.509 - Label *trueBranch,
8.510 - Label *falseBranch,
8.511 - Label *fallthrough)
8.512 -{
8.513 - TokenKind token = ToCompare(expression);
8.514 - if (token == TOK_EOF || token == TOK_NOT) {
8.515 - if (token == TOK_EOF)
8.516 - expression->accept(this);
8.517 - else
8.518 - expression->toUnaryExpression()->expression()->accept(this);
8.519 -
8.520 - bool jumpOnTrue = (fallthrough == falseBranch) ^ (token == TOK_NOT);
8.521 -
8.522 - Opcode op = jumpOnTrue ? OP_JT : OP_JF;
8.523 - if (expression->type()->isFloat())
8.524 - op = (Opcode)(int(op) + (OP_JL_F - OP_JL));
8.525 -
8.526 - if (fallthrough == falseBranch)
8.527 - __ j(op, trueBranch);
8.528 - else
8.529 - __ j(op, falseBranch);
8.530 - return;
8.531 - }
8.532 -
8.533 - BinaryExpression *binary = expression->toBinaryExpression();
8.534 -
8.535 - if (token == TOK_AND || token == TOK_OR) {
8.536 - Label next;
8.537 - if (token == TOK_AND)
8.538 - visitForTest(binary->left(), &next, falseBranch, &next);
8.539 - else
8.540 - visitForTest(binary->left(), trueBranch, &next, &next);
8.541 - __ bind(&next);
8.542 - visitForTest(binary->right(), trueBranch, falseBranch, fallthrough);
8.543 - return;
8.544 - }
8.545 -
8.546 - Opcode op = CompareTokenToJump(token);
8.547 - if (fallthrough == trueBranch)
8.548 - op = Invert(op);
8.549 -
8.550 - Local<Type> leftType(zone_, binary->left()->type());
8.551 - Local<Type> rightType(zone_, binary->right()->type());
8.552 - Local<Type> coerce(zone_, GetCoercionType(binary->token(), leftType, rightType));
8.553 -
8.554 - visitForALU(coerce, binary->left());
8.555 - visitForALU(coerce, binary->right());
8.556 - if (coerce->isFloat())
8.557 - op = (Opcode)(int(op) + (OP_JL_F - OP_JL));
8.558 -
8.559 - if (fallthrough == trueBranch)
8.560 - __ j(op, falseBranch);
8.561 - else
8.562 - __ j(op, trueBranch);
8.563 -}
8.564 -
8.565 -void
8.566 -BytecodeCompiler::visit(ForStatement *node)
8.567 -{
8.568 - AutoEnterScope forScope(this, node->scope());
8.569 -
8.570 - recordLifoSlot(node->scope());
8.571 -
8.572 - Label join, update;
8.573 - LoopScope loop(scope_, &join, &update, &loop_);
8.574 -
8.575 - if (node->initialization())
8.576 - node->initialization()->accept(this);
8.577 -
8.578 - Label header, test;
8.579 - if (node->condition())
8.580 - __ jump(&test);
8.581 -
8.582 - __ bind(&header);
8.583 - node->body()->accept(this);
8.584 -
8.585 - __ bind(&update);
8.586 - if (node->update())
8.587 - node->update()->accept(this);
8.588 -
8.589 - if (node->condition()) {
8.590 - __ bind(&test);
8.591 - visitForTest(node->condition(), &header, &join, &join);
8.592 - } else {
8.593 - __ jump(&header);
8.594 - }
8.595 -
8.596 - __ bind(&join);
8.597 -
8.598 - if (node->scope())
8.599 - unwindTo(node->scope()->enclosing());
8.600 - assert(__ stackDepth() == 0);
8.601 -}
8.602 -
8.603 -void
8.604 -BytecodeCompiler::visit(WhileStatement *node)
8.605 -{
8.606 - Label header, join;
8.607 -
8.608 - __ bind(&header);
8.609 -
8.610 - LoopScope loop(scope_, &join, &header, &loop_);
8.611 -
8.612 - if (node->token() == TOK_WHILE) {
8.613 - Label body;
8.614 -
8.615 - visitForTest(node->condition(), &body, &join, &body);
8.616 - __ bind(&body);
8.617 - node->body()->accept(this);
8.618 - __ jump(&header);
8.619 - } else {
8.620 - node->body()->accept(this);
8.621 - visitForTest(node->condition(), &header, &join, &join);
8.622 - }
8.623 -
8.624 - __ bind(&join);
8.625 -}
8.626 -
8.627 -void
8.628 -BytecodeCompiler::visit(BreakStatement *node)
8.629 -{
8.630 - unwindTo(loop_->scope());
8.631 - __ jump(loop_->break_());
8.632 -}
8.633 -
8.634 -void
8.635 -BytecodeCompiler::visit(ContinueStatement *node)
8.636 -{
8.637 - unwindTo(loop_->scope());
8.638 - __ jump(loop_->continue_());
8.639 -}
8.640 -
8.641 -void
8.642 -BytecodeCompiler::visit(BlockStatement *node)
8.643 -{
8.644 - AutoEnterScope blockScope(this, node->scope());
8.645 -
8.646 - recordLifoSlot(node->scope());
8.647 -
8.648 - for (size_t i = 0; i < node->statements()->length(); i++) {
8.649 - Statement *statement = node->statements()->at(i);
8.650 - statement->accept(this);
8.651 - assert(__ stackDepth() == 0);
8.652 - }
8.653 -
8.654 - // We don't bother emitting an "unwind" instruction for function scopes,
8.655 - // since this is taken care of by the calling convention.
8.656 - if (node->scope() && node->scope()->enclosing()->kind() != Scope::FUNCTION)
8.657 - unwindTo(node->scope()->enclosing());
8.658 -}
8.659 -
8.660 -void
8.661 -BytecodeCompiler::visit(IntegerLiteral *node)
8.662 -{
8.663 - __ int_(node->value());
8.664 -}
8.665 -
8.666 -void
8.667 -BytecodeCompiler::visit(FloatLiteral *node)
8.668 -{
8.669 - __ float_((float)node->value());
8.670 -}
8.671 -
8.672 -static inline ArrayMap *
8.673 -BuildArrayMap(Zone *zone, Handle<Type> type)
8.674 -{
8.675 - Local<ArrayMap> contained(zone);
8.676 - if (type->levels() > 1) {
8.677 - Local<Type> containedType(zone, type->contained());
8.678 - contained = BuildArrayMap(zone, containedType);
8.679 - if (!contained)
8.680 - return NULL;
8.681 - }
8.682 -
8.683 - return ArrayMap::New(zone, type, contained);
8.684 -}
8.685 -
8.686 -void
8.687 -BytecodeCompiler::visit(StringLiteral *node)
8.688 -{
8.689 - Local<Type> type(zone_, node->type());
8.690 - Local<ArrayMap> map(zone_, BuildArrayMap(zone_, type));
8.691 - if (!map)
8.692 - return;
8.693 -
8.694 - Local<Array> array(zone_, Array::New(zone_, map, node->string()->length(), Heap::Tenure_Old));
8.695 - if (!array)
8.696 - return;
8.697 -
8.698 - assert(array->nelements() >= node->string()->length());
8.699 - memcpy(array->chars(), node->string()->raw(), node->string()->length() * sizeof(char));
8.700 -
8.701 - __ note_position(node->pos());
8.702 - __ object(array);
8.703 -}
8.704 -
8.705 -void
8.706 -BytecodeCompiler::getEnvSlot(Variable *var)
8.707 -{
8.708 - assert(var->scope()->kind() == Scope::GLOBAL);
8.709 - __ getglobal(var);
8.710 -}
8.711 -
8.712 -void
8.713 -BytecodeCompiler::setEnvSlot(Variable *var)
8.714 -{
8.715 - assert(var->scope()->kind() == Scope::GLOBAL);
8.716 - __ setglobal(var);
8.717 -}
8.718 -
8.719 -void
8.720 -BytecodeCompiler::visit(VariableDeclaration *node)
8.721 -{
8.722 - Variable *var = node->variable();
8.723 -
8.724 - Local<Type> type(zone_, var->type());
8.725 - if (type->isArray()) {
8.726 - Local<ArrayMap> map(zone_, BuildArrayMap(zone_, type));
8.727 - __ note_position(node->pos());
8.728 - if (var->scope()->kind() == Scope::GLOBAL)
8.729 - __ newarray(map, Heap::Tenure_Old);
8.730 - else if (var->needsHeapAllocation())
8.731 - __ newarray(map, Heap::Tenure_Default);
8.732 - else
8.733 - __ newarray(map, Heap::Tenure_Stack);
8.734 -
8.735 - if (node->initialization()) {
8.736 - node->initialization()->accept(this);
8.737 - __ note_position(node->pos());
8.738 - __ arraycopy();
8.739 - }
8.740 - } else {
8.741 - if (node->initialization()) {
8.742 - node->initialization()->accept(this);
8.743 - } else {
8.744 - if (!node->postDimensions())
8.745 - __ int_(0);
8.746 - }
8.747 - }
8.748 -
8.749 - if (var->location() == Variable::STACK) {
8.750 - __ setlocal(var);
8.751 - locals_->set(zone_, var->slot(), var->type());
8.752 - } else {
8.753 - assert(var->location() == Variable::ENVIRONMENT);
8.754 - setEnvSlot(var);
8.755 - }
8.756 -
8.757 - __ pop();
8.758 -}
8.759 -
8.760 -void
8.761 -BytecodeCompiler::visit(CallExpression *node)
8.762 -{
8.763 - Local<Type> funType(zone_, node->callee()->type());
8.764 -
8.765 - // Sniff out natives, which have a specific opcode and are guaranteed to
8.766 - // be called via name proxy.
8.767 - NamedFunction *native = NULL;
8.768 - if (funType->isNative()) {
8.769 - native = node->callee()->toNameProxy()->binding()->toNamedFunction();
8.770 - }
8.771 -
8.772 - for (size_t i = node->arguments()->length() - 1; i < node->arguments()->length(); i--) {
8.773 - Expression *arg = node->arguments()->at(i);
8.774 -
8.775 - // We need to compute a reference if the parameter was in the form:
8.776 - // f(&a)
8.777 - // Note this form does not allow: f({})
8.778 - //
8.779 - // We also need to compute references for all variadic native
8.780 - // arguments, but arrays and references are already in the
8.781 - // appropriate form.
8.782 - Local<Type> given(zone_, arg->type());
8.783 - bool mustPushReference = false;
8.784 - if (i >= funType->parameters()->length()) {
8.785 - assert(funType->isNative() && funType->isNativeVariadic());
8.786 - mustPushReference = !given->isArray() && !given->isReference();
8.787 - } else if (funType->parameterAt(i)->isReference()) {
8.788 - mustPushReference = !given->isReference();
8.789 - }
8.790 -
8.791 - // If a native is passed to a native, it must only be one level deep.
8.792 - assert(!funType->isNative() || !given->isArray() || given->levels() == 1);
8.793 -
8.794 - if (mustPushReference) {
8.795 - if (arg->isNameProxy()) {
8.796 - // :TODO: test with functions and globals
8.797 - // Compute a reference to the name.
8.798 - Variable *var = arg->toNameProxy()->binding()->toVariable();
8.799 - __ note_position(node->pos());
8.800 - __ newref(var);
8.801 - } else if (arg->isIndexExpression()) {
8.802 - IndexExpression *expr = arg->toIndexExpression();
8.803 - expr->left()->accept(this);
8.804 - expr->right()->accept(this);
8.805 - __ note_position(expr->pos());
8.806 - __ bounds();
8.807 - __ arrayref_lifo();
8.808 - } else {
8.809 - // We don't know how to, or can't, build a direct reference to
8.810 - // this type. Make an indirect one, by taking the top of the
8.811 - // stack and boxing it up.
8.812 - arg->accept(this);
8.813 - __ note_position(node->pos());
8.814 - __ slotref_lifo();
8.815 - }
8.816 - } else {
8.817 - arg->accept(this);
8.818 - }
8.819 - }
8.820 -
8.821 - __ note_position(node->pos());
8.822 - if (native) {
8.823 - __ callnative(native->slot(), node->arguments()->length());
8.824 - __ drop(node->arguments()->length());
8.825 - } else {
8.826 - node->callee()->accept(this);
8.827 - __ call(funType);
8.828 - __ drop(node->arguments()->length() + 1);
8.829 - }
8.830 -}
8.831 -
8.832 -void
8.833 -BytecodeCompiler::visit(TernaryExpression *node)
8.834 -{
8.835 - Label success, failure, join;
8.836 -
8.837 - visitForTest(node->condition(), &success, &failure, &success);
8.838 - __ bind(&success);
8.839 - node->left()->accept(this);
8.840 - __ drop(1);
8.841 - __ jump(&join);
8.842 - __ bind(&failure);
8.843 - node->right()->accept(this);
8.844 - __ bind(&join);
8.845 -}
8.846 -
8.847 -void
8.848 -BytecodeCompiler::visit(IfStatement *node)
8.849 -{
8.850 - Label join;
8.851 - if (!node->ifFalse()) {
8.852 - Label success;
8.853 -
8.854 - visitForTest(node->condition(), &success, &join, &success);
8.855 - __ bind(&success);
8.856 - node->ifTrue()->accept(this);
8.857 - } else {
8.858 - Label success, next;
8.859 -
8.860 - visitForTest(node->condition(), &success, &next, &success);
8.861 - __ bind(&success);
8.862 - node->ifTrue()->accept(this);
8.863 - __ jump(&join);
8.864 - __ bind(&next);
8.865 - node->ifFalse()->accept(this);
8.866 - }
8.867 -
8.868 - __ bind(&join);
8.869 -}
8.870 -
8.871 -void
8.872 -BytecodeCompiler::visit(FunctionStatement *node)
8.873 -{
8.874 - if (node->fun()->isNative()) {
8.875 - assert(!moduleData_->natives->at(node->fun()->slot()));
8.876 -
8.877 - Local<Type> type(zone_, node->fun()->type());
8.878 - Local<String> name(zone_, node->fun()->name());
8.879 - Local<Native> native(zone_, Native::New(zone_, type, name));
8.880 - if (!native)
8.881 - return;
8.882 -
8.883 - moduleData_->natives->set(zone_, node->fun()->slot(), native);
8.884 - return;
8.885 - }
8.886 -
8.887 - // If the function has no body, then it's just a declaration.
8.888 - if (!node->body()) {
8.889 - assert(node->fun()->isForward() || node->fun()->isPublic());
8.890 - return;
8.891 - }
8.892 -
8.893 - BytecodeCompiler child(zone_, tree_, moduleData_);
8.894 - Local<Function> fun(zone_, child.compileFunction(moduleData_, node));
8.895 - if (!fun)
8.896 - return;
8.897 -
8.898 - assert(!moduleData_->module->getFunction(node->fun()->slot()));
8.899 - moduleData_->module->setFunction(zone_, node->fun()->slot(), fun);
8.900 -}
8.901 -
8.902 -void
8.903 -BytecodeCompiler::visit(EnumStatement *node)
8.904 -{
8.905 - // :TODO: eventually, we'll export these.
8.906 -}
8.907 -
8.908 -Code *
8.909 -BytecodeCompiler::compileCode(Scope *scope, unsigned lineno)
8.910 -{
8.911 - // STOP doubles as RETURNVOID.
8.912 - __ stop();
8.913 -
8.914 - if (__ oom() || zone_->hasPendingException())
8.915 - return NULL;
8.916 -
8.917 - Local<ByteArray> bytes(zone_, ByteArray::New(zone_, __ length() * sizeof(bytecode), Heap::Tenure_Old));
8.918 - if (!bytes)
8.919 - return NULL;
8.920 - memcpy(bytes->raw(), __ buffer(), __ length());
8.921 -
8.922 - for (size_t i = 0; i < scope->maxContainedLocals(); i++)
8.923 - assert(locals_->at(i));
8.924 -
8.925 - Local<FixedArray> objects(zone_, FixedArray::New(zone_, __ objects()->length(), Heap::Tenure_Old));
8.926 - if (!objects)
8.927 - return NULL;
8.928 -
8.929 - for (size_t i = 0; i < __ objects()->length(); i++)
8.930 - objects->set(zone_, i, *(__ objects()->at(i)));
8.931 -
8.932 - Local<ByteArray> safepoints(zone_);
8.933 -
8.934 - // If any stack slots hold gc pointers at potential failure points in the
8.935 - // bytecode, record them now. We do this by building a list of tuples;
8.936 - // each tuple contains the pc offset, and a bitset containing which stack
8.937 - // slots must be scanned by the gc.
8.938 - if (__ oopRecords()->length()) {
8.939 - size_t bytesPerSafepoint = Code::BytesPerSafepoint(__ maxStackDepth());
8.940 - size_t gcmapSize = bytesPerSafepoint * __ oopRecords()->length();
8.941 - safepoints = ByteArray::New(zone_, gcmapSize, Heap::Tenure_Old);
8.942 - if (!safepoints)
8.943 - return NULL;
8.944 -
8.945 - Address cursor = safepoints->raw();
8.946 - for (size_t i = 0; i < __ oopRecords()->length(); i++) {
8.947 - OopRecord *record = __ oopRecords()->at(i);
8.948 - assert(record->depth <= __ maxStackDepth());
8.949 -
8.950 - *reinterpret_cast<unsigned *>(cursor) = record->offset;
8.951 -
8.952 - unsigned char *bits = reinterpret_cast<unsigned char *>(cursor + sizeof(unsigned));
8.953 - for (unsigned i = 0; i < record->depth; i++)
8.954 - bits[i / 8] |= (1 << (i % 8));
8.955 -
8.956 - cursor += bytesPerSafepoint;
8.957 - }
8.958 -
8.959 - assert(cursor == safepoints->raw() + gcmapSize);
8.960 - }
8.961 -
8.962 - Local<ByteArray> sourcemap(zone_);
8.963 - if (__ sourcemapLength()) {
8.964 - sourcemap = ByteArray::New(zone_, __ sourcemapLength(), Heap::Tenure_Old);
8.965 - if (!sourcemap)
8.966 - return NULL;
8.967 -
8.968 - memcpy(sourcemap->raw(), __ sourcemap(), __ sourcemapLength());
8.969 - }
8.970 -
8.971 - Local<Code> code(zone_);
8.972 -
8.973 - code = Code::New(zone_,
8.974 - bytes,
8.975 - locals_,
8.976 - objects,
8.977 - __ maxStackDepth(),
8.978 - moduleData_->module,
8.979 - safepoints,
8.980 - sourcemap,
8.981 - lineno);
8.982 - return code;
8.983 -}
8.984 -
8.985 -Function *
8.986 -BytecodeCompiler::compileFunction(ModuleData *module, FunctionStatement *node)
8.987 -{
8.988 - // Note: No need to record a life slot here, since it's part of the Frame.
8.989 - AutoEnterScope functionScope(this, node->scope());
8.990 -
8.991 - // Set the initial line, because line mappings are deltas.
8.992 - __ setFirstLine(node->pos().line);
8.993 - locals_ = FixedArray::New(zone_, node->scope()->maxContainedLocals(), Heap::Tenure_Old);
8.994 -
8.995 - node->body()->accept(this);
8.996 -
8.997 - unsigned nargs = node->scope()->numArguments();
8.998 - Local<FixedArray> args(zone_, FixedArray::New(zone_, nargs, Heap::Tenure_Old));
8.999 - if (!args)
8.1000 - return NULL;
8.1001 -
8.1002 - for (size_t i = 0; i < node->scope()->numArguments(); i++)
8.1003 - args->set(zone_, i, node->scope()->getArgument(i)->type());
8.1004 -
8.1005 -
8.1006 - Local<Code> code(zone_, compileCode(node->scope(), node->pos().line));
8.1007 - if (!code)
8.1008 - return NULL;
8.1009 -
8.1010 - Local<Type> type(zone_, node->fun()->type());
8.1011 - Local<String> name(zone_, node->fun()->name());
8.1012 - Local<Function> fun(zone_, Function::New(zone_, code, type, name, node->pos()));
8.1013 - if (!fun)
8.1014 - return NULL;
8.1015 -
8.1016 - // If this function had a forward, export it as a named public.
8.1017 - if (node->fun()->isPublic()) {
8.1018 - assert(node->fun()->isPublic());
8.1019 - ScopedRoot<Function> root(fun);
8.1020 - if (!root)
8.1021 - return NULL;
8.1022 - if (!moduleData_->publics.append(root))
8.1023 - return NULL;
8.1024 - }
8.1025 -
8.1026 - Disassemble(code, stdout);
8.1027 -
8.1028 - return fun;
8.1029 -}
8.1030 -
8.1031 -Module *
8.1032 -BytecodeCompiler::compile()
8.1033 -{
8.1034 - AutoEnterScope scope(this, tree_->scope());
8.1035 -
8.1036 - ModuleData moduleData;
8.1037 -
8.1038 - moduleData_ = &moduleData;
8.1039 - moduleData_->module = Module::New(zone_, tree_->scope()->numFunctions());
8.1040 -
8.1041 - if (!moduleData_)
8.1042 - return NULL;
8.1043 -
8.1044 - moduleData_->natives = FixedArray::New(zone_, tree_->scope()->numNatives(), Heap::Tenure_Old);
8.1045 - if (!moduleData_->natives)
8.1046 - return NULL;
8.1047 -
8.1048 - for (size_t i = 0; i < tree_->statements()->length(); i++) {
8.1049 - Statement *statement = tree_->statements()->at(i);
8.1050 - statement->accept(this);
8.1051 - }
8.1052 -
8.1053 - if (zone_->hasPendingException())
8.1054 - return NULL;
8.1055 -
8.1056 -#ifndef NDEBUG
8.1057 - for (size_t i = 0; i < tree_->scope()->numFunctions(); i++)
8.1058 - assert(moduleData_->module->getFunction(i));
8.1059 - for (size_t i = 0; i < tree_->scope()->numNatives(); i++)
8.1060 - assert(moduleData_->natives->at(i));
8.1061 -#endif
8.1062 -
8.1063 - if (moduleData_->publics.length()) {
8.1064 - Local<Function> fun(zone_);
8.1065 - Local<FixedArray> list(zone_, FixedArray::New(zone_, moduleData_->publics.length(),
8.1066 - Heap::Tenure_Old));
8.1067 - if (!list)
8.1068 - return NULL;
8.1069 -
8.1070 - for (size_t i = 0; i < moduleData_->publics.length(); i++)
8.1071 - list->set(zone_, i, moduleData_->publics[i]);
8.1072 -
8.1073 - moduleData_->module->setPublics(list);
8.1074 - }
8.1075 -
8.1076 - moduleData_->module->setNatives(moduleData_->natives);
8.1077 -
8.1078 - if (scope_->numEnvironmentVars()) {
8.1079 - Local<EnvironmentMap> globalMap(zone_, scope_->createEnvironmentMap(zone_));
8.1080 - if (!globalMap)
8.1081 - return NULL;
8.1082 -
8.1083 - Local<Environment> environment(zone_, Environment::New(zone_, globalMap));
8.1084 - if (!environment)
8.1085 - return NULL;
8.1086 -
8.1087 - moduleData_->module->setEnvironment(environment);
8.1088 - }
8.1089 -
8.1090 - Local<Code> code(zone_, compileCode(tree_->scope(), 1));
8.1091 - if (!code)
8.1092 - return NULL;
8.1093 -
8.1094 - Disassemble(code, stdout);
8.1095 -
8.1096 - moduleData_->module->setCode(code);
8.1097 -
8.1098 - return moduleData_->module;
8.1099 -}
9.1 --- a/jitcraft/BytecodeCompiler.h Tue Jul 24 23:53:34 2012 -0700
9.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
9.3 @@ -1,149 +0,0 @@
9.4 -/* vim: set ts=4 sw=4 tw=99 et:
9.5 - *
9.6 - * Copyright (C) 2012 David Anderson
9.7 - *
9.8 - * This file is part of JITCraft.
9.9 - *
9.10 - * JITCraft is free software: you can redistribute it and/or modify it under
9.11 - * the terms of the GNU General Public License as published by the Free
9.12 - * Software Foundation, either version 3 of the License, or (at your option)
9.13 - * any later version.
9.14 - *
9.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
9.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
9.18 - *
9.19 - * You should have received a copy of the GNU General Public License along with
9.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
9.21 - */
9.22 -#ifndef _include_bytecode_compiler_h_
9.23 -#define _include_bytecode_compiler_h_
9.24 -
9.25 -#include "AST.h"
9.26 -#include "BytecodeEmitter.h"
9.27 -#include "Functions.h"
9.28 -
9.29 -namespace ke {
9.30 -
9.31 -class Module;
9.32 -
9.33 -struct ModuleData
9.34 -{
9.35 - ScopedRoot<Module> module;
9.36 - PoolList<ScopedRoot<Function> > publics;
9.37 - ScopedRoot<FixedArray> natives;
9.38 -};
9.39 -
9.40 -class BytecodeCompiler : public AstVisitor
9.41 -{
9.42 - Zone *zone_;
9.43 - ParseTree *tree_;
9.44 - BytecodeEmitter emitter_;
9.45 - ScopedRoot<FixedArray> locals_;
9.46 - Scope *scope_;
9.47 - ModuleData *moduleData_;
9.48 -
9.49 - class LoopScope
9.50 - {
9.51 - Scope *scope_;
9.52 - BytecodeEmitter::Label *bk_;
9.53 - BytecodeEmitter::Label *ct_;
9.54 - LoopScope **prevp_;
9.55 - LoopScope *prev_;
9.56 -
9.57 - public:
9.58 - LoopScope(Scope *scope, BytecodeEmitter::Label *bk, BytecodeEmitter::Label *ct,
9.59 - LoopScope **prevp)
9.60 - : scope_(scope),
9.61 - bk_(bk),
9.62 - ct_(ct),
9.63 - prevp_(prevp),
9.64 - prev_(*prevp)
9.65 - {
9.66 - *prevp_ = this;
9.67 - }
9.68 -
9.69 - ~LoopScope()
9.70 - {
9.71 - *prevp_ = prev_;
9.72 - }
9.73 -
9.74 - BytecodeEmitter::Label *break_() {
9.75 - return bk_;
9.76 - }
9.77 - BytecodeEmitter::Label *continue_() {
9.78 - return ct_;
9.79 - }
9.80 - Scope *scope() {
9.81 - return scope_;
9.82 - }
9.83 - };
9.84 -
9.85 - LoopScope *loop_;
9.86 -
9.87 - public:
9.88 - class AutoEnterScope
9.89 - {
9.90 - BytecodeCompiler *bc_;
9.91 - Scope *saved_;
9.92 -
9.93 - public:
9.94 - AutoEnterScope(BytecodeCompiler *bc, Scope *scope)
9.95 - : bc_(bc),
9.96 - saved_(bc->scope_)
9.97 - {
9.98 - if (scope)
9.99 - bc->scope_ = scope;
9.100 - }
9.101 - ~AutoEnterScope() {
9.102 - bc_->scope_ = saved_;
9.103 - }
9.104 - };
9.105 -
9.106 - private:
9.107 - void recordLifoSlot(Scope *scope);
9.108 - void unwindTo(Scope *scope);
9.109 - void visitForTest(Expression *expression,
9.110 - BytecodeEmitter::Label *trueBranch,
9.111 - BytecodeEmitter::Label *falseBranch,
9.112 - BytecodeEmitter::Label *fallthrough);
9.113 - Code *compileCode(Scope *scope, unsigned lineno);
9.114 - Function *compileFunction(ModuleData *module, FunctionStatement *fun);
9.115 - void visitForALU(Type *needed, Expression *node);
9.116 -
9.117 - void getEnvSlot(Variable *var);
9.118 - void setEnvSlot(Variable *var);
9.119 -
9.120 - public:
9.121 - BytecodeCompiler(Zone *zone, ParseTree *tree, ModuleData *module);
9.122 -
9.123 - Module *compile();
9.124 -
9.125 - public:
9.126 - void visit(NameProxy *name);
9.127 - void visit(Assignment *node);
9.128 - void visit(BinaryExpression *node);
9.129 - void visit(ReturnStatement *node);
9.130 - void visit(ForStatement *node);
9.131 - void visit(BlockStatement *node);
9.132 - void visit(VariableDeclaration *node);
9.133 - void visit(IntegerLiteral *node);
9.134 - void visit(FloatLiteral *node);
9.135 - void visit(StringLiteral *node);
9.136 - void visit(ExpressionStatement *node);
9.137 - void visit(FunctionStatement *node);
9.138 - void visit(CallExpression *node);
9.139 - void visit(IfStatement *node);
9.140 - void visit(IndexExpression *node);
9.141 - void visit(EnumStatement *node);
9.142 - void visit(WhileStatement *node);
9.143 - void visit(BreakStatement *node);
9.144 - void visit(ContinueStatement *node);
9.145 - void visit(IncDecExpression *node);
9.146 - void visit(UnaryExpression *node);
9.147 - void visit(TernaryExpression *node);
9.148 -};
9.149 -
9.150 -}
9.151 -
9.152 -#endif // _include_bytecode_generator_h_
10.1 --- a/jitcraft/BytecodeEmitter.cpp Tue Jul 24 23:53:34 2012 -0700
10.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
10.3 @@ -1,114 +0,0 @@
10.4 -/* vim: set ts=4 sw=4 tw=99 et:
10.5 - *
10.6 - * Copyright (C) 2012 David Anderson
10.7 - *
10.8 - * This file is part of JITCraft.
10.9 - *
10.10 - * JITCraft is free software: you can redistribute it and/or modify it under
10.11 - * the terms of the GNU General Public License as published by the Free
10.12 - * Software Foundation, either version 3 of the License, or (at your option)
10.13 - * any later version.
10.14 - *
10.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
10.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
10.18 - *
10.19 - * You should have received a copy of the GNU General Public License along with
10.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
10.21 - */
10.22 -#include <stdlib.h>
10.23 -#include "BytecodeEmitter.h"
10.24 -#include "Utility.h"
10.25 -#include "Types.h"
10.26 -#include "Zone.h"
10.27 -
10.28 -using namespace ke;
10.29 -
10.30 -BytecodeEmitter::BytecodeEmitter(PoolAllocator &pool)
10.31 - : pool_(pool),
10.32 - buffer_(inline_buffer_),
10.33 - buffer_pos_(buffer_),
10.34 - buffer_end_(buffer_pos_ + ARRAY_LENGTH(inline_buffer_)),
10.35 - oom_(false),
10.36 - maxStackDepth_(0)
10.37 -{
10.38 - lastCodePosition_ = 0;
10.39 - firstLine_ = 1;
10.40 -}
10.41 -
10.42 -bool
10.43 -BytecodeEmitter::growBuffer(size_t nbytes)
10.44 -{
10.45 - if (oom_) {
10.46 - buffer_pos_ = buffer_;
10.47 - return false;
10.48 - }
10.49 -
10.50 - size_t newSize = size_t((buffer_end_ - buffer_) * 2);
10.51 - if (newSize >= MAX_LENGTH) {
10.52 - oom_ = true;
10.53 - buffer_pos_ = buffer_;
10.54 - ZONE()->reportOutOfMemory();
10.55 - return false;
10.56 - }
10.57 -
10.58 - bytecode *newBuffer;
10.59 - if (buffer_ == inline_buffer_)
10.60 - newBuffer = (bytecode *)malloc(nbytes);
10.61 - else
10.62 - newBuffer = (bytecode *)realloc(buffer_, newSize);
10.63 -
10.64 - // If we can't allocate a buffer, reset the buffer to the start and set
10.65 - // a flag to indicate out-of-memory.
10.66 - if (!newBuffer) {
10.67 - oom_ = true;
10.68 - buffer_pos_ = buffer_;
10.69 - ZONE()->reportOutOfMemory();
10.70 - return false;
10.71 - }
10.72 -
10.73 - buffer_pos_ = newBuffer + size_t(buffer_pos_ - buffer_);
10.74 - buffer_ = newBuffer;
10.75 - buffer_end_ = buffer_ + newSize;
10.76 - return true;
10.77 -}
10.78 -
10.79 -void
10.80 -BytecodeEmitter::recordOops()
10.81 -{
10.82 - OopRecord *record = new (pool_) OopRecord(oopMap_.length(), position());
10.83 -
10.84 - record->slots = (bool *)pool_.allocate(record->depth);
10.85 - if (!record->slots) {
10.86 - oom_ = true;
10.87 - return;
10.88 - }
10.89 -
10.90 - bool hadOops = false;
10.91 - for (size_t i = 0; i < oopMap_.length(); i++) {
10.92 - bool bit = oopMap_[i];
10.93 - record->slots[i] = bit;
10.94 - hadOops |= bit;
10.95 - }
10.96 -
10.97 - if (!hadOops)
10.98 - return;
10.99 -
10.100 - oom_ &= oopRecords_.append(record);
10.101 -}
10.102 -
10.103 -void
10.104 -BytecodeEmitter::note_position(const SourcePosition &pos)
10.105 -{
10.106 - assert(pos.line > 0);
10.107 - assert(unsigned(pos.line) >= firstLine_);
10.108 -
10.109 - unsigned lineDelta = unsigned(pos.line) - firstLine_;
10.110 - unsigned pcDelta = unsigned(position()) - lastCodePosition_;
10.111 -
10.112 - sourcemap_.writeUint32(pcDelta);
10.113 - sourcemap_.writeUint32(lineDelta);
10.114 - sourcemap_.writeUint32(pos.col);
10.115 -
10.116 - lastCodePosition_ = unsigned(position());
10.117 -}
11.1 --- a/jitcraft/BytecodeEmitter.h Tue Jul 24 23:53:34 2012 -0700
11.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
11.3 @@ -1,626 +0,0 @@
11.4 -/* vim: set ts=4 sw=4 tw=99 et:
11.5 - *
11.6 - * Copyright (C) 2012 David Anderson
11.7 - *
11.8 - * This file is part of JITCraft.
11.9 - *
11.10 - * JITCraft is free software: you can redistribute it and/or modify it under
11.11 - * the terms of the GNU General Public License as published by the Free
11.12 - * Software Foundation, either version 3 of the License, or (at your option)
11.13 - * any later version.
11.14 - *
11.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
11.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
11.18 - *
11.19 - * You should have received a copy of the GNU General Public License along with
11.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
11.21 - */
11.22 -#ifndef _include_bytecode_emitter_h_
11.23 -#define _include_bytecode_emitter_h_
11.24 -
11.25 -#include <assert.h>
11.26 -#include <limits.h>
11.27 -#include "Opcodes.h"
11.28 -#include "NameBinding.h"
11.29 -#include "Handles.h"
11.30 -#include "CompactBuffer.h"
11.31 -
11.32 -namespace ke {
11.33 -
11.34 -class Type;
11.35 -class Map;
11.36 -
11.37 -typedef PoolList<ScopedRoot<Object>> ObjectList;
11.38 -
11.39 -struct OopRecord : public PoolObject
11.40 -{
11.41 - unsigned depth;
11.42 - unsigned offset;
11.43 - bool *slots;
11.44 -
11.45 - OopRecord(unsigned length, unsigned offset)
11.46 - : depth(length),
11.47 - offset(offset),
11.48 - slots(NULL)
11.49 - {
11.50 - }
11.51 -};
11.52 -
11.53 -class BytecodeEmitter
11.54 -{
11.55 - private:
11.56 - PoolAllocator &pool_;
11.57 -
11.58 - bytecode *buffer_;
11.59 - bytecode *buffer_pos_;
11.60 - bytecode *buffer_end_;
11.61 - bytecode inline_buffer_[512];
11.62 - bool oom_;
11.63 - unsigned maxStackDepth_;
11.64 - ObjectList objects_;
11.65 - PoolList<bool> oopMap_;
11.66 - PoolList<OopRecord *> oopRecords_;
11.67 - CompactBufferWriter sourcemap_;
11.68 - unsigned lastCodePosition_;
11.69 - unsigned firstLine_;
11.70 -
11.71 - private:
11.72 - // The maximum size of a code object must be such that the distance between
11.73 - // two instructions fits into a signed, 31-bit integer. This ensures that
11.74 - // all code-bounded buffers (like the number of object literals or
11.75 - // safepoints) does not need to be bounds checked. It also means we can add
11.76 - // any two offsets and be guaranteed that they don't overflow.
11.77 - static const size_t MAX_LENGTH = INT_MAX / 2;
11.78 -
11.79 - private:
11.80 - bool growBuffer(size_t bytes);
11.81 -
11.82 - // Checking the return value is not necessary, since the inline buffer is
11.83 - // used as a ballast.
11.84 - bool ensure(size_t bytes) {
11.85 - if (buffer_pos_ + bytes > buffer_end_)
11.86 - return growBuffer(bytes);
11.87 - return true;
11.88 - }
11.89 -
11.90 - void writeUint8(unsigned value) {
11.91 - assert(value <= UCHAR_MAX);
11.92 - *buffer_pos_++ = value;
11.93 - }
11.94 - void writeFloat(float value) {
11.95 - *(float *)buffer_pos_ = value;
11.96 - buffer_pos_ += sizeof(float);
11.97 - }
11.98 - void writeInt32(int value) {
11.99 - *(int *)buffer_pos_ = value;
11.100 - buffer_pos_ += sizeof(int);
11.101 - }
11.102 - void writeUint32(unsigned value) {
11.103 - *(unsigned *)buffer_pos_ = value;
11.104 - buffer_pos_ += sizeof(unsigned);
11.105 - }
11.106 - void writeOp(Opcode op) {
11.107 - if (oom_)
11.108 - return;
11.109 -
11.110 - writeUint8(op);
11.111 - for (int i = 0; i < OpcodeInfo[op].nuses; i++)
11.112 - oopMap_.pop();
11.113 - for (int i = 0; i < OpcodeInfo[op].ndefs; i++)
11.114 - oopMap_.append(false);
11.115 - if (oopMap_.length() > maxStackDepth_)
11.116 - maxStackDepth_ = oopMap_.length();
11.117 - }
11.118 - void writeObject(Object *obj) {
11.119 - writeUint32(objects_.length());
11.120 - ScopedRoot<Object> root(obj);
11.121 - if (!objects_.append(root))
11.122 - oom_ = true;
11.123 - }
11.124 -
11.125 - int position() const {
11.126 - assert(buffer_pos_ - buffer_ < INT_MAX / 2);
11.127 - return int(buffer_pos_ - buffer_);
11.128 - }
11.129 -
11.130 - public:
11.131 - BytecodeEmitter(PoolAllocator &pool);
11.132 -
11.133 - bytecode *buffer() const {
11.134 - return buffer_;
11.135 - }
11.136 - unsigned length() const {
11.137 - return unsigned(buffer_pos_ - buffer_);
11.138 - }
11.139 - bool oom() const {
11.140 - return oom_ || sourcemap_.oom();
11.141 - }
11.142 - unsigned stackDepth() const {
11.143 - return oopMap_.length();
11.144 - }
11.145 - unsigned maxStackDepth() const {
11.146 - return maxStackDepth_;
11.147 - }
11.148 - const ObjectList *objects() const {
11.149 - return &objects_;
11.150 - }
11.151 - PoolList<OopRecord *> *oopRecords() {
11.152 - return &oopRecords_;
11.153 - }
11.154 -
11.155 - void drop(unsigned amt) {
11.156 - assert(amt <= stackDepth());
11.157 - for (unsigned i = 0; i < amt; i++)
11.158 - oopMap_.pop();
11.159 - }
11.160 -
11.161 - void note_position(const SourcePosition &pos);
11.162 - uint8 *sourcemap() const {
11.163 - return sourcemap_.buffer();
11.164 - }
11.165 - size_t sourcemapLength() const {
11.166 - return sourcemap_.length();
11.167 - }
11.168 - void setFirstLine(unsigned line) {
11.169 - assert(!sourcemap_.length());
11.170 - firstLine_ = line;
11.171 - }
11.172 -
11.173 - public:
11.174 - // A label represents a local control-flow target in the bytecode. A label
11.175 - // may be in three states:
11.176 - //
11.177 - // (1) Empty - the label is not used yet.
11.178 - // (2) Pending - the label has incoming jumps, but the actual location of
11.179 - // is not yet known. The list of jumps is threaded through
11.180 - // the four bytes reserved for each emitted jump target. In
11.181 - // this case, the offset field is the location of the most
11.182 - // recently emitted incoming jump.
11.183 - // (3) Bound - the label's position has been pinned.
11.184 - //
11.185 - // A jump can be emitted to a label in any state. Binding a label
11.186 - // immediately backpatches all pending incoming jumps. A label must be
11.187 - // bound if it is used.
11.188 - class Label
11.189 - {
11.190 - int offset_ : 31;
11.191 - bool bound_ : 1;
11.192 -
11.193 - void setOffset(int offset) {
11.194 - offset_ = offset;
11.195 - assert(offset_ == offset);
11.196 - }
11.197 -
11.198 - public:
11.199 - static const int INVALID_OFFSET = -1;
11.200 -
11.201 - public:
11.202 - Label()
11.203 - : offset_(INVALID_OFFSET),
11.204 - bound_(false)
11.205 - {
11.206 - }
11.207 - ~Label()
11.208 - {
11.209 - assert(bound_ || offset_ == INVALID_OFFSET);
11.210 - }
11.211 -
11.212 - bool bound() const {
11.213 - return bound_;
11.214 - }
11.215 - int offset() const {
11.216 - return offset_;
11.217 - }
11.218 - void bind(int offset) {
11.219 - assert(!bound_);
11.220 - setOffset(offset);
11.221 - bound_ = true;
11.222 - }
11.223 - int link(int offset) {
11.224 - assert(!bound_);
11.225 - int old = offset_;
11.226 - setOffset(offset);
11.227 - return old;
11.228 - }
11.229 - };
11.230 -
11.231 - private:
11.232 - int patchJumpAt(int at, int to) {
11.233 - assert(at >= 0 && at < position());
11.234 - int old = *(int *)(buffer_ + at + 1);
11.235 - *(int *)(buffer_ + at + 1) = (to - at);
11.236 - return old;
11.237 - }
11.238 -
11.239 - void singleByteOp(Opcode op) {
11.240 - assert(OpcodeInfo[op].length == 1);
11.241 - ensure(OpcodeInfo[op].length);
11.242 - writeOp(op);
11.243 - }
11.244 -
11.245 - // Mark a stack slot as having an object pointer.
11.246 - void markOop(unsigned depth, bool oop = true) {
11.247 - if (oom_)
11.248 - return;
11.249 - oopMap_[oopMap_.length() - depth] = oop;
11.250 - }
11.251 - bool getOop(unsigned depth) {
11.252 - if (oom_)
11.253 - return false;
11.254 - return oopMap_[oopMap_.length() - depth];
11.255 - }
11.256 -
11.257 - // Mark the current bytecode position as either re-entrant (meaning, it
11.258 - // can leave the interpreter or call to another function), or causing GC.
11.259 - // This will record which stack slots have objects and associate that
11.260 - // information with the current pc.
11.261 - void recordOops();
11.262 -
11.263 - public:
11.264 - void int_(int value) {
11.265 - ensure(OP_INT);
11.266 - writeOp(OP_INT);
11.267 - writeInt32(value);
11.268 - }
11.269 - void return_() {
11.270 - ensure(OP_RETURN);
11.271 - writeOp(OP_RETURN);
11.272 - }
11.273 - void getlocal(Variable *var) {
11.274 - ensure(OP_GETLOCAL_LENGTH);
11.275 - writeOp(OP_GETLOCAL);
11.276 - writeUint32(var->slot());
11.277 -
11.278 - if (var->type()->isTraceable())
11.279 - markOop(1);
11.280 - }
11.281 - void setlocal(Variable *var) {
11.282 - ensure(OP_SETLOCAL_LENGTH);
11.283 - writeOp(OP_SETLOCAL);
11.284 - writeUint32(var->slot());
11.285 -
11.286 - if (var->type()->isTraceable())
11.287 - markOop(1);
11.288 - }
11.289 - void getarg(Variable *var) {
11.290 - ensure(OP_GETARG_LENGTH);
11.291 - writeOp(OP_GETARG);
11.292 - writeUint32(var->slot());
11.293 -
11.294 - if (var->type()->isTraceable())
11.295 - markOop(1);
11.296 - }
11.297 - void setarg(Variable *var) {
11.298 - ensure(OP_SETARG_LENGTH);
11.299 - writeOp(OP_SETARG);
11.300 - writeUint32(var->slot());
11.301 -
11.302 - if (var->type()->isTraceable())
11.303 - markOop(1);
11.304 - }
11.305 -
11.306 - void j(Opcode op, Label *label) {
11.307 - // Since jumps can skip around the stream, do not try to do anything
11.308 - // in a potentially truncated state.
11.309 - if (oom())
11.310 - return;
11.311 -
11.312 - assert(op >= OP_JL && op <= OP_JUMP);
11.313 - ensure(OP_JUMP_LENGTH);
11.314 -
11.315 - if (label->bound()) {
11.316 - // We can immediately emit this jump.
11.317 - int distance = label->offset() - position();
11.318 - writeOp(op);
11.319 - writeInt32(distance);
11.320 - } else {
11.321 - // We can't emit this jump yet. Add a placeholder.
11.322 - int old = label->link(position());
11.323 - writeOp(op);
11.324 - writeInt32(old);
11.325 - }
11.326 - }
11.327 - void bind(Label *label) {
11.328 - if (oom())
11.329 - return;
11.330 -
11.331 - assert(!label->bound());
11.332 -
11.333 - int offset = label->offset();
11.334 - while (offset != Label::INVALID_OFFSET)
11.335 - offset = patchJumpAt(offset, position());
11.336 -
11.337 - label->bind(position());
11.338 - }
11.339 - void jump(Label *label) {
11.340 - j(OP_JUMP, label);
11.341 - }
11.342 -
11.343 - void binary(Opcode op) {
11.344 - singleByteOp(op);
11.345 - }
11.346 -
11.347 - void pop() {
11.348 - singleByteOp(OP_POP);
11.349 - }
11.350 - void stop() {
11.351 - singleByteOp(OP_STOP);
11.352 - }
11.353 - void call(Handle<Type> fun) {
11.354 - recordOops();
11.355 - ensure(OP_CALL_LENGTH);
11.356 - writeOp(OP_CALL);
11.357 -
11.358 - if (fun->returnType()->isVoid())
11.359 - drop(1);
11.360 - else if (fun->returnType()->isTraceable())
11.361 - markOop(1);
11.362 - }
11.363 - void callnative(unsigned index, unsigned argc) {
11.364 - recordOops();
11.365 - ensure(OP_CALLNATIVE_LENGTH);
11.366 - writeOp(OP_CALLNATIVE);
11.367 - writeUint32(index);
11.368 - writeUint32(argc);
11.369 - }
11.370 -
11.371 - void getarray(PrimitiveType type) {
11.372 - switch (type) {
11.373 - case PrimitiveType_Float:
11.374 - singleByteOp(OP_GETARRAY_F);
11.375 - break;
11.376 - case PrimitiveType_Int32:
11.377 - singleByteOp(OP_GETARRAY_I);
11.378 - break;
11.379 - default:
11.380 - assert(type == PrimitiveType_Char);
11.381 - singleByteOp(OP_GETARRAY_C);
11.382 - break;
11.383 - }
11.384 - }
11.385 - void setarray(PrimitiveType type) {
11.386 - switch (type) {
11.387 - case PrimitiveType_Float:
11.388 - singleByteOp(OP_SETARRAY_F);
11.389 - break;
11.390 - case PrimitiveType_Int32:
11.391 - singleByteOp(OP_SETARRAY_I);
11.392 - break;
11.393 - default:
11.394 - assert(type == PrimitiveType_Char);
11.395 - singleByteOp(OP_SETARRAY_C);
11.396 - break;
11.397 - }
11.398 - }
11.399 -
11.400 - void getglobal(Variable *var) {
11.401 - ensure(OP_GETGLOBAL_F_LENGTH);
11.402 - if (var->type()->isPrimitive()) {
11.403 - switch (var->type()->primitive()) {
11.404 - case PrimitiveType_Float:
11.405 - writeOp(OP_GETGLOBAL_F);
11.406 - break;
11.407 - default:
11.408 - assert(var->type()->primitive() == PrimitiveType_Int32);
11.409 - writeOp(OP_GETGLOBAL_I);
11.410 - break;
11.411 - }
11.412 - } else {
11.413 - writeOp(OP_GETGLOBAL_O);
11.414 - markOop(1);
11.415 - }
11.416 - writeUint32(var->slot());
11.417 - }
11.418 - void setglobal(Variable *var) {
11.419 - ensure(OP_SETGLOBAL_F_LENGTH);
11.420 - if (var->type()->isPrimitive()) {
11.421 - switch (var->type()->primitive()) {
11.422 - case PrimitiveType_Float:
11.423 - writeOp(OP_SETGLOBAL_F);
11.424 - break;
11.425 - default:
11.426 - assert(var->type()->primitive() == PrimitiveType_Int32);
11.427 - writeOp(OP_SETGLOBAL_I);
11.428 - break;
11.429 - }
11.430 - } else {
11.431 - writeOp(OP_SETGLOBAL_O);
11.432 - }
11.433 - writeUint32(var->slot());
11.434 - }
11.435 -
11.436 - void getarray_o() {
11.437 - singleByteOp(OP_GETARRAY_O);
11.438 - markOop(1);
11.439 - }
11.440 - void bounds() {
11.441 - singleByteOp(OP_BOUNDS);
11.442 - markOop(2);
11.443 - }
11.444 - void float_(float value) {
11.445 - ensure(OP_FLOAT_LENGTH);
11.446 - writeOp(OP_FLOAT);
11.447 - writeFloat(value);
11.448 - }
11.449 - void cvt_i2f() {
11.450 - singleByteOp(OP_CVT_I2F);
11.451 - }
11.452 - void newarray(Handle<Map> map, Heap::Tenure tenure) {
11.453 - recordOops();
11.454 - ensure(OP_NEWARRAY_LENGTH);
11.455 - writeOp(OP_NEWARRAY);
11.456 - writeUint8(tenure);
11.457 - writeObject(map);
11.458 - markOop(1);
11.459 - }
11.460 - void savelifo(unsigned slot) {
11.461 - ensure(OP_SAVELIFO_LENGTH);
11.462 - writeOp(OP_SAVELIFO);
11.463 - writeUint32(slot);
11.464 - }
11.465 - void unwindlifo(unsigned slot) {
11.466 - ensure(OP_UNWINDLIFO_LENGTH);
11.467 - writeOp(OP_UNWINDLIFO);
11.468 - writeUint32(slot);
11.469 - }
11.470 - void newref(Variable *var) {
11.471 - recordOops();
11.472 - if (var->location() == Variable::STACK) {
11.473 - ensure(OP_VARREF_LIFO_LENGTH);
11.474 - writeOp(OP_VARREF_LIFO);
11.475 - } else {
11.476 - assert(var->location() == Variable::PARAMETER);
11.477 - ensure(OP_ARGREF_LIFO_LENGTH);
11.478 - writeOp(OP_ARGREF_LIFO);
11.479 - }
11.480 - writeUint32(var->slot());
11.481 - markOop(1);
11.482 - }
11.483 -
11.484 - void slotref_lifo() {
11.485 - recordOops();
11.486 - singleByteOp(OP_SLOTREF_LIFO);
11.487 - markOop(1);
11.488 - }
11.489 - void arrayref_lifo() {
11.490 - recordOops();
11.491 - singleByteOp(OP_ARRAYREF_LIFO);
11.492 - markOop(1);
11.493 - }
11.494 - void getref(PrimitiveType type) {
11.495 - if (type == PrimitiveType_Int32) {
11.496 - singleByteOp(OP_GETREF_I);
11.497 - } else {
11.498 - assert(type == PrimitiveType_Float);
11.499 - singleByteOp(OP_GETREF_F);
11.500 - }
11.501 - }
11.502 - void setref(PrimitiveType type) {
11.503 - if (type == PrimitiveType_Int32) {
11.504 - singleByteOp(OP_SETREF_I);
11.505 - } else {
11.506 - assert(type == PrimitiveType_Float);
11.507 - singleByteOp(OP_SETREF_F);
11.508 - }
11.509 - }
11.510 - void object(Handle<Object> obj) {
11.511 - ensure(OP_OBJECT_LENGTH);
11.512 - writeOp(OP_OBJECT);
11.513 - writeObject(obj);
11.514 - markOop(1);
11.515 - }
11.516 - void arraycopy() {
11.517 - singleByteOp(OP_ARRAYCOPY);
11.518 - markOop(1);
11.519 - }
11.520 -
11.521 - void dup() {
11.522 - bool oop = getOop(1);
11.523 - singleByteOp(OP_DUP);
11.524 - markOop(1, oop);
11.525 - }
11.526 - void dup2() {
11.527 - bool oop2 = getOop(2);
11.528 - bool oop1 = getOop(1);
11.529 -
11.530 - singleByteOp(OP_DUP2);
11.531 -
11.532 - markOop(2, oop2);
11.533 - markOop(1, oop1);
11.534 - }
11.535 - void swap() {
11.536 - bool oop2 = getOop(2);
11.537 - bool oop1 = getOop(1);
11.538 -
11.539 - singleByteOp(OP_SWAP);
11.540 -
11.541 - markOop(2, oop1);
11.542 - markOop(1, oop2);
11.543 - }
11.544 - void roll3() {
11.545 - bool oop3 = getOop(3);
11.546 - bool oop2 = getOop(2);
11.547 - bool oop1 = getOop(1);
11.548 -
11.549 - singleByteOp(OP_ROLL3);
11.550 -
11.551 - markOop(3, oop2);
11.552 - markOop(2, oop1);
11.553 - markOop(1, oop3);
11.554 - }
11.555 - void pick2() {
11.556 - bool oop2 = getOop(2);
11.557 - bool oop1 = getOop(1);
11.558 -
11.559 - singleByteOp(OP_PICK2);
11.560 -
11.561 - markOop(3, oop2);
11.562 - markOop(2, oop1);
11.563 - markOop(1, oop2);
11.564 - }
11.565 - void pick3() {
11.566 - bool oop3 = getOop(3);
11.567 - bool oop2 = getOop(2);
11.568 - bool oop1 = getOop(1);
11.569 -
11.570 - singleByteOp(OP_PICK3);
11.571 -
11.572 - markOop(4, oop3);
11.573 - markOop(3, oop2);
11.574 - markOop(2, oop1);
11.575 - markOop(1, oop3);
11.576 - }
11.577 -
11.578 - void returnvoid() {
11.579 - singleByteOp(OP_RETURNVOID);
11.580 - }
11.581 - void module() {
11.582 - singleByteOp(OP_MODULE);
11.583 - markOop(1);
11.584 - }
11.585 - void getmodule_fn(unsigned index) {
11.586 - ensure(OP_GETMODULE_FN_LENGTH);
11.587 - writeOp(OP_GETMODULE_FN);
11.588 - writeUint32(index);
11.589 - markOop(1);
11.590 - }
11.591 - void bitnot() {
11.592 - singleByteOp(OP_BITNOT);
11.593 - }
11.594 - void not_() {
11.595 - singleByteOp(OP_NOT);
11.596 - }
11.597 - void not_f() {
11.598 - singleByteOp(OP_NOT_F);
11.599 - }
11.600 - void neg() {
11.601 - singleByteOp(OP_NEG);
11.602 - }
11.603 - void neg_f() {
11.604 - singleByteOp(OP_NEG_F);
11.605 - }
11.606 -
11.607 - // Helpers.
11.608 - void get(Variable *var) {
11.609 - if (var->location() == Variable::STACK) {
11.610 - getlocal(var);
11.611 - } else {
11.612 - assert(var->location() == Variable::PARAMETER);
11.613 - getarg(var);
11.614 - }
11.615 - }
11.616 - void set(Variable *var) {
11.617 - assert(!var->type()->isReference());
11.618 - if (var->location() == Variable::STACK) {
11.619 - setlocal(var);
11.620 - } else {
11.621 - assert(var->location() == Variable::PARAMETER);
11.622 - setarg(var);
11.623 - }
11.624 - }
11.625 -};
11.626 -
11.627 -}
11.628 -
11.629 -#endif // _include_bytecode_emitter_h_
12.1 --- a/jitcraft/Code.h Tue Jul 24 23:53:34 2012 -0700
12.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
12.3 @@ -1,127 +0,0 @@
12.4 -/* vim: set ts=4 sw=4 tw=99 et:
12.5 - *
12.6 - * Copyright (C) 2012 David Anderson
12.7 - *
12.8 - * This file is part of JITCraft.
12.9 - *
12.10 - * JITCraft is free software: you can redistribute it and/or modify it under
12.11 - * the terms of the GNU General Public License as published by the Free
12.12 - * Software Foundation, either version 3 of the License, or (at your option)
12.13 - * any later version.
12.14 - *
12.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
12.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12.18 - *
12.19 - * You should have received a copy of the GNU General Public License along with
12.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
12.21 - */
12.22 -#ifndef _include_jc_code_h_
12.23 -#define _include_jc_code_h_
12.24 -
12.25 -#include "Opcodes.h"
12.26 -#include "Barriers.h"
12.27 -#include "Heap.h"
12.28 -#include "Types.h"
12.29 -#include "FixedArray.h"
12.30 -#include "Token.h"
12.31 -
12.32 -namespace ke {
12.33 -
12.34 -class Module;
12.35 -class Type;
12.36 -
12.37 -// A code object contains the bytecode compiled from a function (or global
12.38 -// script), as well as all information needed to interpret or JIT-compile
12.39 -// the bytecode.
12.40 -class Code : public Object
12.41 -{
12.42 - Barriered<Module> module_;
12.43 - Barriered<ByteArray> bytecode_;
12.44 - Barriered<FixedArray> locals_;
12.45 - Barriered<FixedArray> objects_;
12.46 - Barriered<ByteArray> safepoints_;
12.47 - Barriered<ByteArray> sourcemap_;
12.48 - unsigned maxStackDepth_;
12.49 - unsigned lineNumber_;
12.50 -
12.51 - public:
12.52 - static inline size_t BytesPerSafepoint(size_t stackDepth) {
12.53 - return (Align(stackDepth, 8) / 8) + sizeof(unsigned);
12.54 - }
12.55 -
12.56 - public:
12.57 - static Code *New(Zone *zone, Handle<ByteArray> bytecode, Handle<FixedArray> locals,
12.58 - Handle<FixedArray> objects, unsigned maxStackDepth, Handle<Module> module,
12.59 - Handle<ByteArray> safepoints, Handle<ByteArray> sourcemap,
12.60 - unsigned lineNumber);
12.61 -
12.62 - Module *module() {
12.63 - return module_;
12.64 - }
12.65 - bytecode *start() {
12.66 - return bytecode_->raw();
12.67 - }
12.68 - unsigned length() {
12.69 - return bytecode_->length();
12.70 - }
12.71 - Type *localType(size_t index) {
12.72 - return Type::cast(locals_->at(index));
12.73 - }
12.74 - unsigned nlocals() {
12.75 - return locals_ ? locals_->length() : 0;
12.76 - }
12.77 - unsigned maxStackDepth() {
12.78 - return maxStackDepth_;
12.79 - }
12.80 - Map *map(size_t index) {
12.81 - return Map::cast(objects_->at(index));
12.82 - }
12.83 - Object *object(size_t index) {
12.84 - return objects_->at(index);
12.85 - }
12.86 - ByteArray *safepoints() {
12.87 - return safepoints_;
12.88 - }
12.89 - uint8 *safepointAt(unsigned pcOffset);
12.90 -
12.91 - unsigned pcToOffset(bytecode *pc) {
12.92 - assert(pc >= start() && pc < start() + length());
12.93 - return pc - start();
12.94 - }
12.95 -
12.96 - SourcePosition pcToSource(unsigned pc);
12.97 - unsigned lineNumber() {
12.98 - return lineNumber_;
12.99 - }
12.100 -
12.101 - // GC Descriptor.
12.102 - static inline size_t offsetOfModule() {
12.103 - return offsetof(Code, module_);
12.104 - }
12.105 - static inline size_t offsetOfBytecode() {
12.106 - return offsetof(Code, bytecode_);
12.107 - }
12.108 - static inline size_t offsetOfLocals() {
12.109 - return offsetof(Code, locals_);
12.110 - }
12.111 - static inline size_t offsetOfObjects() {
12.112 - return offsetof(Code, objects_);
12.113 - }
12.114 - static inline size_t offsetOfSafepoints() {
12.115 - return offsetof(Code, safepoints_);
12.116 - }
12.117 - static inline size_t offsetOfSourceMap() {
12.118 - return offsetof(Code, sourcemap_);
12.119 - }
12.120 - // End GC Descriptor.
12.121 -
12.122 - static Code *cast(Object *obj) {
12.123 - assert(!obj || obj->is(MapKind_Code));
12.124 - return reinterpret_cast<Code *>(obj);
12.125 - }
12.126 -};
12.127 -
12.128 -}
12.129 -
12.130 -#endif // _include_jc_code_h_
13.1 --- a/jitcraft/CompactBuffer.h Tue Jul 24 23:53:34 2012 -0700
13.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
13.3 @@ -1,100 +0,0 @@
13.4 -/* vim: set ts=4 sw=4 tw=99 et:
13.5 - *
13.6 - * Copyright (C) 2012 David Anderson
13.7 - *
13.8 - * This file is part of JITCraft.
13.9 - *
13.10 - * JITCraft is free software: you can redistribute it and/or modify it under
13.11 - * the terms of the GNU General Public License as published by the Free
13.12 - * Software Foundation, either version 3 of the License, or (at your option)
13.13 - * any later version.
13.14 - *
13.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
13.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13.18 - *
13.19 - * You should have received a copy of the GNU General Public License along with
13.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
13.21 - */
13.22 -#ifndef _include_jc_compact_buffer_h_
13.23 -#define _include_jc_compact_buffer_h_
13.24 -
13.25 -#include "AllocatorPolicies.h"
13.26 -#include "Utility.h"
13.27 -#include "Vector.h"
13.28 -
13.29 -namespace ke {
13.30 -
13.31 -class CompactBufferReader
13.32 -{
13.33 - const uint8 *pos_;
13.34 - const uint8 *end_;
13.35 -
13.36 - public:
13.37 - CompactBufferReader(const uint8 *start, const uint8 *end)
13.38 - : pos_(start),
13.39 - end_(end)
13.40 - {
13.41 - }
13.42 -
13.43 - uint8 readUint8() {
13.44 - assert(pos_ < end_);
13.45 - return *pos_++;
13.46 - }
13.47 -
13.48 - uint32 readUint32() {
13.49 - uint32 value = 0;
13.50 - uint32 shift = 0;
13.51 -
13.52 - uint8 byte;
13.53 - do {
13.54 - byte = readUint8();
13.55 - value |= (byte >> 1) << shift;
13.56 - shift += 7;
13.57 - } while (byte & 1);
13.58 -
13.59 - assert(shift < 32);
13.60 - return value;
13.61 - }
13.62 -
13.63 - bool done() const {
13.64 - return pos_ == end_;
13.65 - }
13.66 -};
13.67 -
13.68 -class CompactBufferWriter
13.69 -{
13.70 - Vector<uint8, ZoneAllocatorPolicy> buffer_;
13.71 - bool enoughMemory_;
13.72 -
13.73 - public:
13.74 - CompactBufferWriter()
13.75 - : enoughMemory_(true)
13.76 - {
13.77 - }
13.78 -
13.79 - void writeUint8(unsigned value) {
13.80 - enoughMemory_ &= buffer_.append(value);
13.81 - }
13.82 - void writeUint32(unsigned value) {
13.83 - do {
13.84 - writeUint8(((value & 0x7F) << 1) | (value > 0x7F));
13.85 - value >>= 7;
13.86 - } while (value);
13.87 - }
13.88 -
13.89 - uint8 *buffer() const {
13.90 - return buffer_.buffer();
13.91 - }
13.92 - size_t length() const {
13.93 - return buffer_.length();
13.94 - }
13.95 -
13.96 - bool oom() const {
13.97 - return !enoughMemory_;
13.98 - }
13.99 -};
13.100 -
13.101 -}
13.102 -
13.103 -#endif // _include_jc_compact_buffer_h_
14.1 --- a/jitcraft/CompileContext.cpp Tue Jul 24 23:53:34 2012 -0700
14.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
14.3 @@ -1,56 +0,0 @@
14.4 -/*
14.5 - * Copyright (C) 2012 David Anderson
14.6 - *
14.7 - * This file is part of JITCraft.
14.8 - *
14.9 - * JITCraft is free software: you can redistribute it and/or modify it under
14.10 - * the terms of the GNU General Public License as published by the Free
14.11 - * Software Foundation, either version 3 of the License, or (at your option)
14.12 - * any later version.
14.13 - *
14.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
14.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14.17 - *
14.18 - * You should have received a copy of the GNU General Public License along with
14.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
14.20 - */
14.21 -#include <stdio.h>
14.22 -#include "Scanner.h"
14.23 -#include "CompileContext.h"
14.24 -#include "Zone.h"
14.25 -
14.26 -using namespace ke;
14.27 -
14.28 -CompileContext::CompileContext(Zone *zone, const char *file)
14.29 - : zone_(zone),
14.30 - failures_(0),
14.31 - file_(file)
14.32 -{
14.33 -}
14.34 -
14.35 -CompileContext::~CompileContext()
14.36 -{
14.37 - if (failures_)
14.38 - zone_->endCompilationErrors();
14.39 -}
14.40 -
14.41 -void
14.42 -CompileContext::reportErrorVa(const SourcePosition &pos, Message msg, va_list ap)
14.43 -{
14.44 - if (!failures_)
14.45 - zone_->beginCompilationErrors(file_);
14.46 -
14.47 - zone_->reportCompilationError(msg, pos.line, pos.col, ap);
14.48 -
14.49 - failures_++;
14.50 -}
14.51 -
14.52 -void
14.53 -CompileContext::reportError(const SourcePosition &pos, Message msg, ...)
14.54 -{
14.55 - va_list ap;
14.56 - va_start(ap, msg);
14.57 - reportErrorVa(pos, msg, ap);
14.58 - va_end(ap);
14.59 -}
15.1 --- a/jitcraft/CompileContext.h Tue Jul 24 23:53:34 2012 -0700
15.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
15.3 @@ -1,49 +0,0 @@
15.4 -/*
15.5 - * Copyright (C) 2012 David Anderson
15.6 - *
15.7 - * This file is part of JITCraft.
15.8 - *
15.9 - * JITCraft is free software: you can redistribute it and/or modify it under
15.10 - * the terms of the GNU General Public License as published by the Free
15.11 - * Software Foundation, either version 3 of the License, or (at your option)
15.12 - * any later version.
15.13 - *
15.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
15.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15.17 - *
15.18 - * You should have received a copy of the GNU General Public License along with
15.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
15.20 - */
15.21 -#ifndef _include_jitcraft_compile_context_h_
15.22 -#define _include_jitcraft_compile_context_h_
15.23 -
15.24 -#include <stdarg.h>
15.25 -#include "Messages.h"
15.26 -
15.27 -namespace ke {
15.28 -
15.29 -class Zone;
15.30 -struct SourcePosition;
15.31 -
15.32 -class CompileContext
15.33 -{
15.34 - Zone *zone_;
15.35 - unsigned failures_;
15.36 - const char *file_;
15.37 -
15.38 - public:
15.39 - CompileContext(Zone *zone, const char *file);
15.40 - ~CompileContext();
15.41 -
15.42 - void reportErrorVa(const SourcePosition &pos, Message msg, va_list ap);
15.43 - void reportError(const SourcePosition &pos, Message msg, ...);
15.44 -
15.45 - unsigned failures() const {
15.46 - return failures_;
15.47 - }
15.48 -};
15.49 -
15.50 -}
15.51 -
15.52 -#endif // _include_jitcraft_compile_context_h_
16.1 --- a/jitcraft/Environments.cpp Tue Jul 24 23:53:34 2012 -0700
16.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
16.3 @@ -1,97 +0,0 @@
16.4 -/*
16.5 - * Copyright (C) 2012 David Anderson
16.6 - *
16.7 - * This file is part of JITCraft.
16.8 - *
16.9 - * JITCraft is free software: you can redistribute it and/or modify it under
16.10 - * the terms of the GNU General Public License as published by the Free
16.11 - * Software Foundation, either version 3 of the License, or (at your option)
16.12 - * any later version.
16.13 - *
16.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
16.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16.17 - *
16.18 - * You should have received a copy of the GNU General Public License along with
16.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
16.20 - */
16.21 -#include "Utility.h"
16.22 -#include "Environments.h"
16.23 -#include "Structures.h"
16.24 -#include "FixedArray.h"
16.25 -#include "Zone.h"
16.26 -#include "NameBinding.h"
16.27 -
16.28 -using namespace ke;
16.29 -
16.30 -EnvironmentSlotDescriptorArray *
16.31 -EnvironmentSlotDescriptorArray::New(Zone *zone, unsigned nslots)
16.32 -{
16.33 - size_t bytesNeeded = sizeof(EnvironmentSlotDescriptorArray) +
16.34 - sizeof(EnvironmentSlotDescriptor) * nslots;
16.35 -
16.36 - Local<EnvironmentSlotDescriptorArray> array(zone);
16.37 - Local<Map> map(zone, zone->getMap(MapKind_EnvironmentSlotDescriptorArray));
16.38 -
16.39 - array = EnvironmentSlotDescriptorArray::cast(zone->allocate(map, bytesNeeded, Heap::Tenure_Old));
16.40 - if (!array)
16.41 - return NULL;
16.42 -
16.43 - // We zero the array for safety, since we could GC or fail before initialization.
16.44 - array->length_ = nslots;
16.45 - memset(array->slots(), 0, sizeof(EnvironmentSlotDescriptor) * nslots);
16.46 - return array;
16.47 -}
16.48 -
16.49 -Environment *
16.50 -Environment::New(Zone *zone, Handle<EnvironmentMap> map, Heap::Tenure tenure)
16.51 -{
16.52 - size_t bytesNeeded = sizeof(Environment) + map->structureSize();
16.53 - Local<Environment> env(zone, Environment::cast(zone->allocate(map, bytesNeeded, tenure)));
16.54 - if (!env)
16.55 - return NULL;
16.56 -
16.57 - // Initialize when called from C++, to make sure object slots are NULL.
16.58 - memset((Object *)env + 1, 0, map->structureSize());
16.59 - return env;
16.60 -}
16.61 -
16.62 -EnvironmentMap *
16.63 -EnvironmentMap::New(Zone *zone, unsigned nvars, Variable **vars)
16.64 -{
16.65 - StructureBufferBuilder structure;
16.66 -
16.67 - Local<EnvironmentSlotDescriptorArray> slots(zone);
16.68 - slots = EnvironmentSlotDescriptorArray::New(zone, nvars);
16.69 - if (!slots)
16.70 - return NULL;
16.71 -
16.72 - // Build the descriptor table, mapping each slot to an offset and type.
16.73 - Local<Type> type(zone);
16.74 - for (unsigned i = 0; i < nvars; i++) {
16.75 - assert(vars[i]->slot() == i);
16.76 - type = vars[i]->type();
16.77 -
16.78 - EnvironmentSlotDescriptor &desc = slots->slots()[i];
16.79 - if (!structure.add(type, &desc.offset))
16.80 - return NULL;
16.81 -
16.82 - desc.type = type;
16.83 - }
16.84 -
16.85 - // Allocate the actual map now.
16.86 - size_t bytesNeeded = sizeof(EnvironmentMap) + structure.traceableOffsetCount() * sizeof(unsigned);
16.87 - Local<EnvironmentMap> map(zone);
16.88 -
16.89 - map = EnvironmentMap::cast(zone->allocateMap(MapKind_Environment, bytesNeeded, MapKind_MetaEnvironment));
16.90 - if (!map)
16.91 - return NULL;
16.92 -
16.93 - // Fill in the map fields, and copy the traceable offsets structure.
16.94 - map->structureSize_ = structure.structureSize();
16.95 - map->traceOffsetCount_ = structure.traceableOffsetCount();
16.96 - map->slots_ = slots;
16.97 - memcpy(const_cast<unsigned *>(map->traceOffsets()), structure.offsets(), sizeof(unsigned) * structure.traceableOffsetCount());
16.98 -
16.99 - return map;
16.100 -}
17.1 --- a/jitcraft/Environments.h Tue Jul 24 23:53:34 2012 -0700
17.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
17.3 @@ -1,168 +0,0 @@
17.4 -/*
17.5 - * Copyright (C) 2012 David Anderson
17.6 - *
17.7 - * This file is part of JITCraft.
17.8 - *
17.9 - * JITCraft is free software: you can redistribute it and/or modify it under
17.10 - * the terms of the GNU General Public License as published by the Free
17.11 - * Software Foundation, either version 3 of the License, or (at your option)
17.12 - * any later version.
17.13 - *
17.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
17.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17.17 - *
17.18 - * You should have received a copy of the GNU General Public License along with
17.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
17.20 - */
17.21 -#ifndef _include_ke_environment_h_
17.22 -#define _include_ke_environment_h_
17.23 -
17.24 -#include "Objects.h"
17.25 -#include "Handles.h"
17.26 -#include "Heap.h"
17.27 -#include "FixedArray.h"
17.28 -
17.29 -namespace ke {
17.30 -
17.31 -class EnvironmentMap;
17.32 -class Variable;
17.33 -class ByteArray;
17.34 -class Type;
17.35 -
17.36 -// An environment represents the lexical environment of a code or function
17.37 -// object. It used for variables which may be accessed outside a function's
17.38 -// normal activation (i.e., upvars).
17.39 -//
17.40 -// A module uses an Environment to store its global variables.
17.41 -class Environment : public Object
17.42 -{
17.43 - template <typename T>
17.44 - inline T *pointerToSlot(unsigned slot);
17.45 -
17.46 - public:
17.47 - static Environment *New(Zone *zone, Handle<EnvironmentMap> map, Heap::Tenure tenure = Heap::Tenure_Default);
17.48 -
17.49 - inline EnvironmentMap *map();
17.50 - inline size_t size();
17.51 -
17.52 - float getFloat(unsigned slot) {
17.53 - return *pointerToSlot<float>(slot);
17.54 - }
17.55 - int getInt32(unsigned slot) {
17.56 - return *pointerToSlot<int>(slot);
17.57 - }
17.58 - Object *getObject(unsigned slot) {
17.59 - return *pointerToSlot<Object *>(slot);
17.60 - }
17.61 - void setFloat(unsigned slot, float f) {
17.62 - *pointerToSlot<float>(slot) = f;
17.63 - }
17.64 - void setInt32(unsigned slot, int i) {
17.65 - *pointerToSlot<int>(slot) = i;
17.66 - }
17.67 - void setObject(unsigned slot, Object *obj) {
17.68 - // :TODO: write barrier
17.69 - *pointerToSlot<Object *>(slot) = obj;
17.70 - }
17.71 -
17.72 - static inline size_t offsetOfSlotOffset(unsigned offset) {
17.73 - return sizeof(Environment) + offset;
17.74 - }
17.75 -
17.76 - static inline Environment *cast(Object *obj) {
17.77 - assert(!obj || obj->is(MapKind_Environment));
17.78 - return reinterpret_cast<Environment *>(obj);
17.79 - }
17.80 -};
17.81 -
17.82 -struct EnvironmentSlotDescriptor
17.83 -{
17.84 - Barriered<Type> type;
17.85 - unsigned offset;
17.86 -};
17.87 -
17.88 -class EnvironmentSlotDescriptorArray : public Object
17.89 -{
17.90 - unsigned length_;
17.91 -
17.92 - public:
17.93 - static EnvironmentSlotDescriptorArray *New(Zone *zone, unsigned length);
17.94 -
17.95 - EnvironmentSlotDescriptor *slots() {
17.96 - return reinterpret_cast<EnvironmentSlotDescriptor *>(this + 1);
17.97 - }
17.98 - EnvironmentSlotDescriptor &at(unsigned slot) {
17.99 - assert(slot < length_);
17.100 - return slots()[slot];
17.101 - }
17.102 - unsigned length() {
17.103 - return length_;
17.104 - }
17.105 - unsigned size() {
17.106 - return Align(sizeof(*this) + length() * sizeof(EnvironmentSlotDescriptorArray),
17.107 - kObjectAlignment);
17.108 - }
17.109 -
17.110 - static inline EnvironmentSlotDescriptorArray *cast(Object *obj) {
17.111 - assert(!obj || obj->is(MapKind_EnvironmentSlotDescriptorArray));
17.112 - return reinterpret_cast<EnvironmentSlotDescriptorArray *>(obj);
17.113 - }
17.114 -};
17.115 -
17.116 -class EnvironmentMap : public Map
17.117 -{
17.118 - unsigned structureSize_;
17.119 - unsigned traceOffsetCount_;
17.120 - Barriered<EnvironmentSlotDescriptorArray> slots_;
17.121 -
17.122 - public:
17.123 - static EnvironmentMap *New(Zone *zone, unsigned nvars, Variable **vars);
17.124 -
17.125 - unsigned structureSize() {
17.126 - return structureSize_;
17.127 - }
17.128 - unsigned traceOffsetCount() {
17.129 - return traceOffsetCount_;
17.130 - }
17.131 - const unsigned *traceOffsets() {
17.132 - return reinterpret_cast<unsigned *>(this + 1);
17.133 - }
17.134 - size_t size() {
17.135 - return Align(sizeof(EnvironmentMap) + sizeof(unsigned) * traceOffsetCount(), kObjectAlignment);
17.136 - }
17.137 - EnvironmentSlotDescriptor &slotDescriptor(unsigned slot) {
17.138 - return slots_->at(slot);
17.139 - }
17.140 -
17.141 - static inline size_t offsetOfSlots() {
17.142 - return offsetof(EnvironmentMap, slots_);
17.143 - }
17.144 -
17.145 - static inline EnvironmentMap *cast(Object *obj) {
17.146 - assert(!obj || obj->is(MapKind_MetaEnvironment));
17.147 - return reinterpret_cast<EnvironmentMap *>(obj);
17.148 - }
17.149 -};
17.150 -
17.151 -size_t
17.152 -Environment::size()
17.153 -{
17.154 - return Align(sizeof(Environment) + map()->structureSize(), kObjectAlignment);
17.155 -}
17.156 -
17.157 -EnvironmentMap *
17.158 -Environment::map()
17.159 -{
17.160 - return EnvironmentMap::cast(Object::map());
17.161 -}
17.162 -
17.163 -template <typename T> T *
17.164 -Environment::pointerToSlot(unsigned slot)
17.165 -{
17.166 - return reinterpret_cast<T *>(reinterpret_cast<char *>(this + 1) + map()->slotDescriptor(slot).offset);
17.167 -}
17.168 -
17.169 -}
17.170 -
17.171 -#endif // _include_ke_environment_h_
18.1 --- a/jitcraft/Exception.cpp Tue Jul 24 23:53:34 2012 -0700
18.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
18.3 @@ -1,31 +0,0 @@
18.4 -
18.5 -/*
18.6 - * Copyright (C) 2012 David Anderson
18.7 - *
18.8 - * This file is part of JITCraft.
18.9 - *
18.10 - * JITCraft is free software: you can redistribute it and/or modify it under
18.11 - * the terms of the GNU General Public License as published by the Free
18.12 - * Software Foundation, either version 3 of the License, or (at your option)
18.13 - * any later version.
18.14 - *
18.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
18.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18.18 - *
18.19 - * You should have received a copy of the GNU General Public License along with
18.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
18.21 - */
18.22 -#include "Utility.h"
18.23 -#include "Messages.h"
18.24 -
18.25 -using namespace ke;
18.26 -
18.27 -const MessageInfo ke::Messages[] =
18.28 -{
18.29 -#define MSG(Name, Type, String) \
18.30 - { MessageType_##Type, String },
18.31 -# include "Messages.tbl"
18.32 -#undef MSG
18.33 - { MessageType_SyntaxError, NULL }
18.34 -};
19.1 --- a/jitcraft/FixedArray.cpp Tue Jul 24 23:53:34 2012 -0700
19.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
19.3 @@ -1,76 +0,0 @@
19.4 -/*
19.5 - * Copyright (C) 2012 David Anderson
19.6 - *
19.7 - * This file is part of JITCraft.
19.8 - *
19.9 - * JITCraft is free software: you can redistribute it and/or modify it under
19.10 - * the terms of the GNU General Public License as published by the Free
19.11 - * Software Foundation, either version 3 of the License, or (at your option)
19.12 - * any later version.
19.13 - *
19.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
19.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19.17 - *
19.18 - * You should have received a copy of the GNU General Public License along with
19.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
19.20 - */
19.21 -#include <limits.h>
19.22 -#include "FixedArray.h"
19.23 -#include "Zone.h"
19.24 -#include "Heap-inl.h"
19.25 -
19.26 -using namespace ke;
19.27 -
19.28 -static const unsigned kMaxFixedArrayLength = ((INT_MAX - sizeof(FixedArray)) / sizeof(ke::Object *));
19.29 -
19.30 -FixedArray *
19.31 -FixedArray::New(Zone *zone, unsigned length, Heap::Tenure tenure)
19.32 -{
19.33 - if (length >= kMaxFixedArrayLength) {
19.34 - zone->reportError(Message_ArrayTooBig);
19.35 - return NULL;
19.36 - }
19.37 -
19.38 - Local<FixedArray> array(zone, FixedArray::cast(zone->allocate(MapKind_FixedArray, SizeFor(length), tenure)));
19.39 - if (!array)
19.40 - return NULL;
19.41 -
19.42 - array->length_ = length;
19.43 - memset(array->vec(), 0, length * sizeof(Object *));
19.44 - return array;
19.45 -}
19.46 -
19.47 -ByteArray *
19.48 -ByteArray::New(Zone *zone, unsigned length, Heap::Tenure tenure)
19.49 -{
19.50 - if (length >= kMaxFixedArrayLength) {
19.51 - zone->reportError(Message_ArrayTooBig);
19.52 - return NULL;
19.53 - }
19.54 -
19.55 - Local<ByteArray> array(zone, ByteArray::cast(zone->allocate(MapKind_ByteArray, SizeFor(length), tenure)));
19.56 - if (!array)
19.57 - return NULL;
19.58 -
19.59 - array->length_ = length;
19.60 - memset(array->raw(), 0, length);
19.61 - return array;
19.62 -}
19.63 -
19.64 -ByteArray *
19.65 -ByteArray::New(Zone *zone, Handle<Map> map, unsigned length, Heap::Tenure tenure)
19.66 -{
19.67 - if (length >= kMaxFixedArrayLength) {
19.68 - zone->reportError(Message_ArrayTooBig);
19.69 - return NULL;
19.70 - }
19.71 -
19.72 - Local<ByteArray> array(zone, ByteArray::cast(zone->allocate(map, SizeFor(length), tenure)));
19.73 - if (!array)
19.74 - return NULL;
19.75 -
19.76 - array->length_ = length;
19.77 - memset(array->raw(), 0, length);
19.78 - return array;
19.79 -}
20.1 --- a/jitcraft/FixedArray.h Tue Jul 24 23:53:34 2012 -0700
20.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
20.3 @@ -1,89 +0,0 @@
20.4 -/* vim: set ts=4 sw=4 tw=99 et
20.5 - *
20.6 - * Copyright (C) 2012 David Anderson
20.7 - *
20.8 - * This file is part of JITCraft.
20.9 - *
20.10 - * JITCraft is free software: you can redistribute it and/or modify it under
20.11 - * the terms of the GNU General Public License as published by the Free
20.12 - * Software Foundation, either version 3 of the License, or (at your option)
20.13 - * any later version.
20.14 - *
20.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
20.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
20.18 - *
20.19 - * You should have received a copy of the GNU General Public License along with
20.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
20.21 - */
20.22 -#ifndef _include_jitcraft_fixedarray_h_
20.23 -#define _include_jitcraft_fixedarray_h_
20.24 -
20.25 -#include "Heap.h"
20.26 -
20.27 -namespace ke {
20.28 -
20.29 -// A fixed-length array that contains Object * slots.
20.30 -class FixedArray : public Object
20.31 -{
20.32 - uint32 length_;
20.33 -
20.34 - private:
20.35 - Object **vec() {
20.36 - return reinterpret_cast<Object **>(this + 1);
20.37 - }
20.38 -
20.39 - public:
20.40 - static FixedArray *New(Zone *zone, unsigned length, Heap::Tenure tenure);
20.41 -
20.42 - unsigned length() {
20.43 - return length_;
20.44 - }
20.45 - Object *at(size_t i) {
20.46 - assert(i < length());
20.47 - return vec()[i];
20.48 - }
20.49 - void set(Zone *zone, size_t i, Object *obj) {
20.50 - assert(i < length());
20.51 - write(zone, &vec()[i], obj);
20.52 - }
20.53 -
20.54 - static size_t SizeFor(unsigned length) {
20.55 - return sizeof(FixedArray) + sizeof(Object *) * length;
20.56 - }
20.57 -
20.58 - static inline FixedArray *cast(Object *obj) {
20.59 - assert(!obj || obj->is(MapKind_FixedArray));
20.60 - return reinterpret_cast<FixedArray *>(obj);
20.61 - }
20.62 -};
20.63 -
20.64 -// A fixed-length array containing raw bytes.
20.65 -class ByteArray : public Object
20.66 -{
20.67 - uint32 length_;
20.68 -
20.69 - public:
20.70 - static ByteArray *New(Zone *zone, unsigned length, Heap::Tenure tenure = Heap::Tenure_Default);
20.71 - static ByteArray *New(Zone *zone, Handle<Map> map, unsigned length, Heap::Tenure tenure = Heap::Tenure_Default);
20.72 -
20.73 - unsigned length() {
20.74 - return length_;
20.75 - }
20.76 - Address raw() {
20.77 - return reinterpret_cast<uint8 *>(this + 1);
20.78 - }
20.79 -
20.80 - static size_t SizeFor(unsigned length) {
20.81 - return Align(sizeof(ByteArray) + sizeof(uint8) * length, kObjectAlignment);
20.82 - }
20.83 -
20.84 - static inline ByteArray *cast(Object *obj) {
20.85 - assert(!obj || obj->is(MapKind_ByteArray));
20.86 - return reinterpret_cast<ByteArray *>(obj);
20.87 - }
20.88 -};
20.89 -
20.90 -}
20.91 -
20.92 -#endif // _include_jitcraft_fixedarray_h_
21.1 --- a/jitcraft/Functions.cpp Tue Jul 24 23:53:34 2012 -0700
21.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
21.3 @@ -1,51 +0,0 @@
21.4 -/*
21.5 - * Copyright (C) 2012 David Anderson
21.6 - *
21.7 - * This file is part of JITCraft.
21.8 - *
21.9 - * JITCraft is free software: you can redistribute it and/or modify it under
21.10 - * the terms of the GNU General Public License as published by the Free
21.11 - * Software Foundation, either version 3 of the License, or (at your option)
21.12 - * any later version.
21.13 - *
21.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
21.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
21.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
21.17 - *
21.18 - * You should have received a copy of the GNU General Public License along with
21.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
21.20 - */
21.21 -#include "Functions.h"
21.22 -#include "Modules.h"
21.23 -#include "Zone.h"
21.24 -#include "Heap-inl.h"
21.25 -
21.26 -using namespace ke;
21.27 -
21.28 -Function *
21.29 -Function::New(Zone *zone, Handle<Code> code, Handle<Type> type, Handle<String> name,
21.30 - const SourcePosition &pos)
21.31 -{
21.32 - Function *fun = Function::cast(zone->allocate(MapKind_Function, sizeof(Function), Heap::Tenure_Old));
21.33 - if (!fun)
21.34 - return NULL;
21.35 -
21.36 - fun->code_ = code;
21.37 - fun->pos_ = pos;
21.38 - fun->type_ = type;
21.39 - fun->name_ = name;
21.40 - return fun;
21.41 -}
21.42 -
21.43 -Native *
21.44 -Native::New(Zone *zone, Handle<Type> type, Handle<String> name)
21.45 -{
21.46 - Native *fun = Native::cast(zone->allocate(MapKind_Native, sizeof(Native), Heap::Tenure_Old));
21.47 - if (!fun)
21.48 - return NULL;
21.49 -
21.50 - fun->type_ = type;
21.51 - fun->name_ = name;
21.52 - fun->function_ = NULL;
21.53 - return fun;
21.54 -}
22.1 --- a/jitcraft/Functions.h Tue Jul 24 23:53:34 2012 -0700
22.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
22.3 @@ -1,122 +0,0 @@
22.4 -/*
22.5 - * Copyright (C) 2012 David Anderson
22.6 - *
22.7 - * This file is part of JITCraft.
22.8 - *
22.9 - * JITCraft is free software: you can redistribute it and/or modify it under
22.10 - * the terms of the GNU General Public License as published by the Free
22.11 - * Software Foundation, either version 3 of the License, or (at your option)
22.12 - * any later version.
22.13 - *
22.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
22.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
22.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
22.17 - *
22.18 - * You should have received a copy of the GNU General Public License along with
22.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
22.20 - */
22.21 -#ifndef _include_jitcraft_function_h_
22.22 -#define _include_jitcraft_function_h_
22.23 -
22.24 -#include "Heap.h"
22.25 -#include "Barriers.h"
22.26 -#include "Token.h"
22.27 -#include "Types.h"
22.28 -
22.29 -namespace ke {
22.30 -
22.31 -class Code;
22.32 -class Module;
22.33 -class Type;
22.34 -class String;
22.35 -
22.36 -class Function : public Object
22.37 -{
22.38 - Barriered<Code> code_;
22.39 - Barriered<Type> type_;
22.40 - Barriered<String> name_;
22.41 - SourcePosition pos_;
22.42 -
22.43 - public:
22.44 - static Function *New(Zone *zone, Handle<Code> code, Handle<Type> type, Handle<String> name,
22.45 - const SourcePosition &pos);
22.46 -
22.47 - Code *code() const {
22.48 - return code_;
22.49 - }
22.50 - Type *type() const {
22.51 - return type_;
22.52 - }
22.53 - String *name() const {
22.54 - return name_;
22.55 - }
22.56 - const SourcePosition &pos() {
22.57 - return pos_;
22.58 - }
22.59 - unsigned nargs() {
22.60 - return type()->parameters()->length();
22.61 - }
22.62 - Type *argType(size_t index) {
22.63 - return type()->parameterAt(index);
22.64 - }
22.65 -
22.66 - // Begin GC Descriptor.
22.67 - static inline size_t offsetOfCode() {
22.68 - return offsetof(Function, code_);
22.69 - }
22.70 - static inline size_t offsetOfType() {
22.71 - return offsetof(Function, type_);
22.72 - }
22.73 - static inline size_t offsetOfName() {
22.74 - return offsetof(Function, name_);
22.75 - }
22.76 - // End GC Descriptor.
22.77 -
22.78 - static inline Function *cast(Object *obj) {
22.79 - assert(!obj || obj->is(MapKind_Function));
22.80 - return reinterpret_cast<Function *>(obj);
22.81 - }
22.82 -};
22.83 -
22.84 -// A Native is a function with a very specialized calling convention, intended
22.85 -// for earlier ISourcePawnEngine API compatibility.
22.86 -class Native : public Object
22.87 -{
22.88 - Barriered<Type> type_;
22.89 - Barriered<String> name_;
22.90 - void *function_;
22.91 -
22.92 - public:
22.93 - static Native *New(Zone *zone, Handle<Type> type, Handle<String> name);
22.94 -
22.95 - void *function() {
22.96 - return function_;
22.97 - }
22.98 - Type *type() {
22.99 - return type_;
22.100 - }
22.101 - String *name() {
22.102 - return name_;
22.103 - }
22.104 - void bind(void *function) {
22.105 - function_ = function;
22.106 - }
22.107 -
22.108 - // Begin GC Descriptor.
22.109 - static inline size_t offsetOfType() {
22.110 - return offsetof(Native, type_);
22.111 - }
22.112 - static inline size_t offsetOfName() {
22.113 - return offsetof(Native, name_);
22.114 - }
22.115 - // End GC Descriptor.
22.116 -
22.117 - static inline Native *cast(Object *obj) {
22.118 - assert(!obj || obj->is(MapKind_Native));
22.119 - return reinterpret_cast<Native *>(obj);
22.120 - }
22.121 -};
22.122 -
22.123 -}
22.124 -
22.125 -#endif // _include_jitcraft_function_h_
23.1 --- a/jitcraft/GlobalRoots.cpp Tue Jul 24 23:53:34 2012 -0700
23.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
23.3 @@ -1,81 +0,0 @@
23.4 -/*
23.5 - * Copyright (C) 2004-2012 David Anderson
23.6 - *
23.7 - * This file is part of SourcePawn.
23.8 - *
23.9 - * SourcePawn is free software: you can redistribute it and/or modify it under
23.10 - * the terms of the GNU General Public License as published by the Free
23.11 - * Software Foundation, either version 3 of the License, or (at your option)
23.12 - * any later version.
23.13 - *
23.14 - * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
23.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
23.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
23.17 - *
23.18 - * You should have received a copy of the GNU General Public License along with
23.19 - * SourcePawn. If not, see http://www.gnu.org/licenses/.
23.20 - */
23.21 -#include "GlobalRoots.h"
23.22 -#include "Zone.h"
23.23 -
23.24 -using namespace ke;
23.25 -
23.26 -GlobalRoots::GlobalRoots(Zone *zone)
23.27 - : zone_(zone)
23.28 -{
23.29 -}
23.30 -
23.31 -GlobalRoots::~GlobalRoots()
23.32 -{
23.33 - InlineList<HeapRoot>::iterator iter = roots_.begin();
23.34 - while (iter != roots_.end()) {
23.35 - HeapRoot *root = *iter;
23.36 - iter = roots_.erase(iter);
23.37 - delete root;
23.38 - }
23.39 -}
23.40 -
23.41 -bool
23.42 -GlobalRoots::initialize()
23.43 -{
23.44 - return true;
23.45 -}
23.46 -
23.47 -void
23.48 -GlobalRoots::accept(VirtualObjectVisitor *visitor)
23.49 -{
23.50 - for (InlineList<HeapRoot>::iterator iter = roots_.begin(); iter != roots_.end(); iter++)
23.51 - visitor->visit(&iter->obj);
23.52 -}
23.53 -
23.54 -HeapRoot *
23.55 -GlobalRoots::create(Handle<Object> obj)
23.56 -{
23.57 - HeapRoot *root = new HeapRoot();
23.58 - if (!root) {
23.59 - ZONE()->reportOutOfMemory();
23.60 - return NULL;
23.61 - }
23.62 -
23.63 - root->obj = obj;
23.64 - root->refcount = 1;
23.65 -
23.66 - roots_.append(root);
23.67 - return root;
23.68 -}
23.69 -
23.70 -void
23.71 -GlobalRoots::incref(HeapRoot *root)
23.72 -{
23.73 - root->refcount++;
23.74 -}
23.75 -
23.76 -void
23.77 -GlobalRoots::decref(HeapRoot *root)
23.78 -{
23.79 - assert(root->refcount > 0);
23.80 - if (--root->refcount == 0) {
23.81 - roots_.remove(root);
23.82 - delete root;
23.83 - }
23.84 -}
24.1 --- a/jitcraft/GlobalRoots.h Tue Jul 24 23:53:34 2012 -0700
24.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
24.3 @@ -1,61 +0,0 @@
24.4 -/*
24.5 - * Copyright (C) 2004-2012 David Anderson
24.6 - *
24.7 - * This file is part of SourcePawn.
24.8 - *
24.9 - * SourcePawn is free software: you can redistribute it and/or modify it under
24.10 - * the terms of the GNU General Public License as published by the Free
24.11 - * Software Foundation, either version 3 of the License, or (at your option)
24.12 - * any later version.
24.13 - *
24.14 - * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
24.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
24.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
24.17 - *
24.18 - * You should have received a copy of the GNU General Public License along with
24.19 - * SourcePawn. If not, see http://www.gnu.org/licenses/.
24.20 - */
24.21 -#ifndef _include_ke_global_roots_h_
24.22 -#define _include_ke_global_roots_h_
24.23 -
24.24 -#include "Handles.h"
24.25 -#include "InlineList.h"
24.26 -#include "VirtualObjectVisitor.h"
24.27 -
24.28 -namespace ke {
24.29 -
24.30 -class Zone;
24.31 -class Object;
24.32 -
24.33 -class HeapRoot : public InlineListNode<HeapRoot>
24.34 -{
24.35 - public:
24.36 - Object *obj;
24.37 - intptr_t refcount;
24.38 -};
24.39 -
24.40 -class GlobalRoots
24.41 -{
24.42 - Zone *zone_;
24.43 -
24.44 - public:
24.45 - GlobalRoots(Zone *zone);
24.46 - ~GlobalRoots();
24.47 -
24.48 - bool initialize();
24.49 -
24.50 - // The caller must immediately incref this.
24.51 - HeapRoot *create(Handle<Object> ptr);
24.52 -
24.53 - void incref(HeapRoot *root);
24.54 - void decref(HeapRoot *root);
24.55 -
24.56 - void accept(VirtualObjectVisitor *visitor);
24.57 -
24.58 - private:
24.59 - InlineList<HeapRoot> roots_;
24.60 -};
24.61 -
24.62 -}
24.63 -
24.64 -#endif // _include_ke_global_roots_h_
25.1 --- a/jitcraft/Handles-inl.h Tue Jul 24 23:53:34 2012 -0700
25.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
25.3 @@ -1,62 +0,0 @@
25.4 -/*
25.5 - * Copyright (C) 2012 David Anderson
25.6 - *
25.7 - * This file is part of JITCraft.
25.8 - *
25.9 - * JITCraft is free software: you can redistribute it and/or modify it under
25.10 - * the terms of the GNU General Public License as published by the Free
25.11 - * Software Foundation, either version 3 of the License, or (at your option)
25.12 - * any later version.
25.13 - *
25.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
25.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
25.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
25.17 - *
25.18 - * You should have received a copy of the GNU General Public License along with
25.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
25.20 - */
25.21 -#ifndef _include_jitcraft_rooting_inl_h_
25.22 -#define _include_jitcraft_rooting_inl_h_
25.23 -
25.24 -#include "Heap.h"
25.25 -
25.26 -namespace ke {
25.27 -
25.28 -template <typename T>
25.29 -Local<T>::Local(Environment *env)
25.30 - : zone_(env->zone()), thing_(NULL)
25.31 -{
25.32 - prev_ = zone_->registerThingLocal(toRaw());
25.33 -}
25.34 -
25.35 -template <typename T>
25.36 -Local<T>::Local(Environment *env, T *thing)
25.37 - : zone_(env->zone()), thing_(thing)
25.38 -{
25.39 - prev_ = zone_->registerThingLocal(toRaw());
25.40 -}
25.41 -
25.42 -template <typename T>
25.43 -Local<T>::Local(Zone *zone)
25.44 - : zone_(zone), thing_(NULL)
25.45 -{
25.46 - prev_ = zone_->registerThingLocal(toRaw());
25.47 -}
25.48 -
25.49 -template <typename T>
25.50 -Local<T>::Local(Zone *zone, T *thing)
25.51 - : zone_(zone), thing_(thing)
25.52 -{
25.53 - prev_ = zone_->registerThingLocal(toRaw());
25.54 -}
25.55 -
25.56 -
25.57 -template <typename T>
25.58 -Local<T>::~Local()
25.59 -{
25.60 - zone_->deregisterThingLocal(toRaw(), prev_);
25.61 -}
25.62 -
25.63 -}
25.64 -
25.65 -#endif // _include_jitcraft_rooting_inl_h_
26.1 --- a/jitcraft/Handles.h Tue Jul 24 23:53:34 2012 -0700
26.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
26.3 @@ -1,204 +0,0 @@
26.4 -/* vim: set ts=4 sw=4 tw=99 et:
26.5 - *
26.6 - * Copyright (C) 2012 David Anderson
26.7 - *
26.8 - * This file is part of JITCraft.
26.9 - *
26.10 - * JITCraft is free software: you can redistribute it and/or modify it under
26.11 - * the terms of the GNU General Public License as published by the Free
26.12 - * Software Foundation, either version 3 of the License, or (at your option)
26.13 - * any later version.
26.14 - *
26.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
26.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
26.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
26.18 - *
26.19 - * You should have received a copy of the GNU General Public License along with
26.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
26.21 - */
26.22 -#ifndef _include_jitcraft_rooting_h_
26.23 -#define _include_jitcraft_rooting_h_
26.24 -
26.25 -#include <stdlib.h>
26.26 -
26.27 -namespace ke {
26.28 -
26.29 -class Zone;
26.30 -class Object;
26.31 -
26.32 -template <typename T> class Local;
26.33 -template <typename T> class ScopedRoot;
26.34 -
26.35 -/*
26.36 - * Internal handles work differently from API handles. An API handle is a
26.37 - * root, whereas as an internal handle points to a rooted location. This
26.38 - * subtle difference makes handles easy for embedders, but somewhat
26.39 - * cumbersome internally.
26.40 - */
26.41 -template <typename T>
26.42 -class Handle
26.43 -{
26.44 - T * const *thingp_;
26.45 -
26.46 - public:
26.47 - Handle(const Handle &other) {
26.48 - thingp_ = other.address();
26.49 - }
26.50 - template <typename S> Handle(const Handle<S> &handle) {
26.51 - typeCheck<S>();
26.52 - thingp_ = reinterpret_cast<T * const *>(handle.address());
26.53 - }
26.54 - template <typename S> inline Handle(const Local<S> &local);
26.55 - template <typename S> inline Handle(const ScopedRoot<S> &root);
26.56 -
26.57 - public:
26.58 - T *operator ->() {
26.59 - return *thingp_;
26.60 - }
26.61 - T *operator *() {
26.62 - return *thingp_;
26.63 - }
26.64 - operator T *() { return *thingp_; }
26.65 - operator bool() const {
26.66 - return thingp_ && *thingp_;
26.67 - }
26.68 - T * const *address() const {
26.69 - return thingp_;
26.70 - }
26.71 -
26.72 - private:
26.73 - template <typename S>
26.74 - void typeCheck() {
26.75 -#ifndef NDEBUG
26.76 - T *v1 = NULL;
26.77 - S *v2 = NULL;
26.78 - v1 = v2;
26.79 - (void)v1;
26.80 -#endif
26.81 - }
26.82 -};
26.83 -
26.84 -template <typename T>
26.85 -class Local
26.86 -{
26.87 - friend class Zone;
26.88 -
26.89 - Zone *zone_;
26.90 - T *thing_;
26.91 - Local<Object> *prev_;
26.92 -
26.93 - Local<Object> *prev() {
26.94 - return prev_;
26.95 - }
26.96 - Local<Object> *toRaw() {
26.97 - return reinterpret_cast<Local<Object>*>(this);
26.98 - }
26.99 -
26.100 - public:
26.101 - // These are implemented in Zone.h.
26.102 - inline explicit Local(Zone *zone, T *thing = NULL);
26.103 - inline ~Local();
26.104 -
26.105 - const Local &operator =(T *thing) {
26.106 - thing_ = thing;
26.107 - return *this;
26.108 - }
26.109 - T *operator ->() const {
26.110 - return operator *();
26.111 - }
26.112 - T *operator *() const {
26.113 - return thing_;
26.114 - }
26.115 - operator bool () const {
26.116 - return !!thing_;
26.117 - }
26.118 - bool operator !=(const Local &other) {
26.119 - return thing_ != other.thing_;
26.120 - }
26.121 -
26.122 - Object **address() {
26.123 - return (Object **)&thing_;
26.124 - }
26.125 - Object * const *address() const {
26.126 - return (Object * const *)&thing_;
26.127 - }
26.128 - T **ref() {
26.129 - return &thing_;
26.130 - }
26.131 - operator T *() {
26.132 - return thing_;
26.133 - }
26.134 -
26.135 - private:
26.136 - // Disallow heap allocation.
26.137 - void *operator new(size_t size);
26.138 - void *operator new[](size_t size);
26.139 -
26.140 - // Disallow copy construction.
26.141 - Local(const Local<T> &other);
26.142 - Local &operator =(const Local &other);
26.143 -};
26.144 -
26.145 -// A ScopedRoot is a special kind of handle for storing references on the
26.146 -// heap in bulk.
26.147 -template <typename T>
26.148 -class ScopedRoot
26.149 -{
26.150 - T **thingp_;
26.151 -
26.152 - private:
26.153 - // This is implemented in Zone.h.
26.154 - inline T **make(T *other);
26.155 -
26.156 - void assign(T *other) {
26.157 - *thingp_ = other;
26.158 - }
26.159 -
26.160 - public:
26.161 - ScopedRoot();
26.162 -
26.163 - // This is implemented in Zone.h.
26.164 - inline ScopedRoot(T *thing);
26.165 -
26.166 - ScopedRoot &operator =(const ScopedRoot<T> &other) {
26.167 - assign(*other);
26.168 - return *this;
26.169 - }
26.170 - ScopedRoot &operator =(T *other) {
26.171 - assign(other);
26.172 - return *this;
26.173 - }
26.174 - T *operator ->() const {
26.175 - return operator *();
26.176 - }
26.177 - T *operator *() const {
26.178 - return *thingp_;
26.179 - }
26.180 - operator T *() const {
26.181 - return *thingp_;
26.182 - }
26.183 - operator bool () const {
26.184 - return !!*thingp_;
26.185 - }
26.186 - T **address() const {
26.187 - return thingp_;
26.188 - }
26.189 -};
26.190 -
26.191 -template <typename T> template <typename S> inline
26.192 -Handle<T>::Handle(const Local<S> &local)
26.193 -{
26.194 - typeCheck<S>();
26.195 - thingp_ = reinterpret_cast<T * const *>(local.address());
26.196 -}
26.197 -
26.198 -template <typename T> template <typename S> inline
26.199 -Handle<T>::Handle(const ScopedRoot<S> &root)
26.200 -{
26.201 - typeCheck<S>();
26.202 - thingp_ = reinterpret_cast<T * const *>(root.address());
26.203 -}
26.204 -
26.205 -}
26.206 -
26.207 -#endif // _include_jitcraft_rooting_h_
27.1 --- a/jitcraft/HashTable.h Tue Jul 24 23:53:34 2012 -0700
27.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
27.3 @@ -1,424 +0,0 @@
27.4 -/*
27.5 - * Copyright (C) 2012 David Anderson
27.6 - *
27.7 - * This file is part of JITCraft.
27.8 - *
27.9 - * JITCraft is free software: you can redistribute it and/or modify it under
27.10 - * the terms of the GNU General Public License as published by the Free
27.11 - * Software Foundation, either version 3 of the License, or (at your option)
27.12 - * any later version.
27.13 - *
27.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
27.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
27.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
27.17 - *
27.18 - * You should have received a copy of the GNU General Public License along with
27.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
27.20 - */
27.21 -#ifndef _INCLUDE_KEIMA_HASHTABLE_H_
27.22 -#define _INCLUDE_KEIMA_HASHTABLE_H_
27.23 -
27.24 -#include <new>
27.25 -#include <limits.h>
27.26 -#include "Utility.h"
27.27 -
27.28 -namespace ke {
27.29 -
27.30 -template <typename T>
27.31 -class HashTableEntry
27.32 -{
27.33 - uint32 hash_;
27.34 - T t_;
27.35 -
27.36 - public:
27.37 - static const uint32 kFreeHash = 0;
27.38 - static const uint32 kRemovedHash = 1;
27.39 -
27.40 - public:
27.41 - void setHash(uint32 hash) {
27.42 - hash_ = hash;
27.43 - }
27.44 - uint32 hash() const {
27.45 - return hash_;
27.46 - }
27.47 - void setRemoved() {
27.48 - hash_ = kRemovedHash;
27.49 - t_ = T();
27.50 - }
27.51 - void construct() {
27.52 - hash_ = kFreeHash;
27.53 - new (&t_) T();
27.54 - }
27.55 - void destruct() {
27.56 - t_.~T();
27.57 - }
27.58 - bool removed() const {
27.59 - return hash_ == kRemovedHash;
27.60 - }
27.61 - bool free() const {
27.62 - return hash_ == kFreeHash;
27.63 - }
27.64 - bool isLive() const {
27.65 - return hash_ > kRemovedHash;
27.66 - }
27.67 - T &payload() {
27.68 - return t_;
27.69 - }
27.70 - bool sameHash(uint32 hash) const {
27.71 - return hash_ == hash;
27.72 - }
27.73 -};
27.74 -
27.75 -template <typename HashPolicy, typename AllocPolicy>
27.76 -class HashTable : public AllocPolicy
27.77 -{
27.78 - friend class iterator;
27.79 -
27.80 - typedef typename HashPolicy::Payload Payload;
27.81 - typedef HashTableEntry<Payload> Entry;
27.82 -
27.83 - uint32 capacity_;
27.84 - uint32 nelements_;
27.85 - uint32 ndeleted_;
27.86 - Entry *table_;
27.87 - uint32 minCapacity_;
27.88 -
27.89 - private:
27.90 - static const uint32 kMinCapacity = 16;
27.91 - static const uint32 kMaxCapacity = INT_MAX / sizeof(Entry);
27.92 -
27.93 - template <typename Key>
27.94 - uint32 computeHash(const Key &key) {
27.95 - // Multiply by golden ratio.
27.96 - uint32 hash = HashPolicy::hash(key) * 0x9E3779B9;
27.97 - if (hash == Entry::kFreeHash || hash == Entry::kRemovedHash)
27.98 - hash += 2;
27.99 - return hash;
27.100 - }
27.101 -
27.102 - Entry *createTable(uint32 capacity) {
27.103 - assert(capacity <= kMaxCapacity);
27.104 -
27.105 - Entry *table = (Entry *)this->malloc(capacity * sizeof(Entry));
27.106 - if (!table)
27.107 - return NULL;
27.108 -
27.109 - for (size_t i = 0; i < capacity; i++)
27.110 - table[i].construct();
27.111 -
27.112 - return table;
27.113 - }
27.114 -
27.115 - public:
27.116 - class Result
27.117 - {
27.118 - friend class HashTable;
27.119 -
27.120 - Entry *entry_;
27.121 -
27.122 - Entry &entry() {
27.123 - return *entry_;
27.124 - }
27.125 -
27.126 - public:
27.127 - Result(Entry *entry)
27.128 - : entry_(entry)
27.129 - { }
27.130 -
27.131 - Payload * operator ->() {
27.132 - return entry_->payload();
27.133 - }
27.134 - Payload & operator *() {
27.135 - return entry_->payload();
27.136 - }
27.137 -
27.138 - bool found() const {
27.139 - return entry_->isLive();
27.140 - }
27.141 - };
27.142 -
27.143 - class Insert : public Result
27.144 - {
27.145 - uint32 hash_;
27.146 -
27.147 - public:
27.148 - Insert(Entry *entry, uint32 hash)
27.149 - : Result(entry),
27.150 - hash_(hash)
27.151 - {
27.152 - }
27.153 -
27.154 - uint32 hash() const {
27.155 - return hash_;
27.156 - }
27.157 - };
27.158 -
27.159 - private:
27.160 - class Probulator {
27.161 - uint32 hash_;
27.162 - uint32 capacity_;
27.163 -
27.164 - public:
27.165 - Probulator(uint32 hash, uint32 capacity)
27.166 - : hash_(hash),
27.167 - capacity_(capacity)
27.168 - {
27.169 - assert(IsPowerOfTwo(capacity_));
27.170 - }
27.171 -
27.172 - uint32 entry() const {
27.173 - return hash_ & (capacity_ - 1);
27.174 - }
27.175 - uint32 next() {
27.176 - hash_++;
27.177 - return entry();
27.178 - }
27.179 - };
27.180 -
27.181 - bool underloaded() const {
27.182 - // Check if the table is underloaded: < 25% entries used.
27.183 - return (capacity_ > kMinCapacity) && (nelements_ + ndeleted_ < capacity_ / 4);
27.184 - }
27.185 - bool overloaded() const {
27.186 - // Grow if the table is overloaded: > 75% entries used.
27.187 - return (nelements_ + ndeleted_) > ((capacity_ / 2) + (capacity_ / 4));
27.188 - }
27.189 -
27.190 - bool shrink() {
27.191 - if ((capacity_ >> 1) < minCapacity_)
27.192 - return true;
27.193 - return changeCapacity(capacity_ >> 1);
27.194 - }
27.195 -
27.196 - bool grow() {
27.197 - assert(IsPowerOfTwo(kMaxCapacity));
27.198 - if (capacity_ >= kMaxCapacity) {
27.199 - this->reportAllocationOverflow();
27.200 - return false;
27.201 - }
27.202 - return changeCapacity(capacity_ << 1);
27.203 - }
27.204 -
27.205 - bool changeCapacity(uint32 newCapacity) {
27.206 - assert(newCapacity <= kMaxCapacity);
27.207 -
27.208 - Entry *newTable = createTable(newCapacity);
27.209 - if (!newTable)
27.210 - return false;
27.211 -
27.212 - Entry *oldTable = table_;
27.213 - uint32 oldCapacity = capacity_;
27.214 -
27.215 - table_ = newTable;
27.216 - capacity_ = newCapacity;
27.217 - ndeleted_ = 0;
27.218 -
27.219 - for (uint32 i = 0; i < oldCapacity; i++) {
27.220 - Entry &oldEntry = oldTable[i];
27.221 - if (oldEntry.isLive()) {
27.222 - Insert p = insertUnique(oldEntry.hash());
27.223 - p.entry().setHash(p.hash());
27.224 - p.entry().payload() = oldEntry.payload();
27.225 - }
27.226 - oldEntry.destruct();
27.227 - }
27.228 - this->free(oldTable);
27.229 -
27.230 - return true;
27.231 - }
27.232 -
27.233 - // For use when the key is known to be unique.
27.234 - Insert insertUnique(uint32 hash) {
27.235 - Probulator probulator(hash, capacity_);
27.236 -
27.237 - Entry *e = &table_[probulator.entry()];
27.238 - for (;;) {
27.239 - if (e->free() || e->removed())
27.240 - break;
27.241 - e = &table_[probulator.next()];
27.242 - }
27.243 -
27.244 - return Insert(e, hash);
27.245 - }
27.246 -
27.247 - template <typename Key>
27.248 - Result lookup(const Key &key) {
27.249 - uint32 hash = computeHash(key);
27.250 - Probulator probulator(hash, capacity_);
27.251 -
27.252 - Entry *e = &table_[probulator.entry()];
27.253 - for (;;) {
27.254 - if (e->free())
27.255 - break;
27.256 - if (e->isLive() &&
27.257 - e->sameHash(hash) &&
27.258 - HashPolicy::matches(key, e->payload()))
27.259 - {
27.260 - return Result(e);
27.261 - }
27.262 - e = &table_[probulator.next()];
27.263 - }
27.264 -
27.265 - return Result(e);
27.266 - }
27.267 -
27.268 - template <typename Key>
27.269 - Insert lookupForAdd(const Key &key) {
27.270 - uint32 hash = computeHash(key);
27.271 - Probulator probulator(hash, capacity_);
27.272 -
27.273 - Entry *e = &table_[probulator.entry()];
27.274 - for (;;) {
27.275 - if (!e->isLive())
27.276 - break;
27.277 - if (e->sameHash(hash) && HashPolicy::matches(key, e->payload()))
27.278 - break;
27.279 - e = &table_[probulator.next()];
27.280 - }
27.281 -
27.282 - return Insert(e, hash);
27.283 - }
27.284 -
27.285 - bool add(Insert &i) {
27.286 - assert(!i.found());
27.287 -
27.288 - // If the entry is deleted, just re-use the slot.
27.289 - if (i.entry().removed()) {
27.290 - ndeleted_--;
27.291 - return true;
27.292 - }
27.293 -
27.294 - // Otherwise, see if we're at max capacity.
27.295 - if (nelements_ == kMaxCapacity) {
27.296 - this->reportAllocationOverflow();
27.297 - return false;
27.298 - }
27.299 -
27.300 - // Check if the table is over or underloaded. The table is always at
27.301 - // least 25% free, so this check is enough to guarantee one free slot.
27.302 - // (Without one free slot, insertion search could infinite loop.)
27.303 - uint32 oldCapacity = capacity_;
27.304 - if (!checkDensity())
27.305 - return false;
27.306 -
27.307 - // If the table changed size, we need to find a new insertion point.
27.308 - // Note that a removed entry is impossible: either we caught it above,
27.309 - // or we just resized and no entries are removed.
27.310 - if (capacity_ != oldCapacity)
27.311 - i = insertUnique(i.hash());
27.312 -
27.313 - i.entry().setHash(i.hash());
27.314 - nelements_++;
27.315 -
27.316 - return true;
27.317 - }
27.318 -
27.319 - void remove(Entry &e) {
27.320 - assert(e.isLive());
27.321 - e.setRemoved();
27.322 - ndeleted_++;
27.323 - nelements_--;
27.324 - }
27.325 -
27.326 - public:
27.327 - HashTable(AllocPolicy ap)
27.328 - : AllocPolicy(ap),
27.329 - capacity_(0),
27.330 - nelements_(0),
27.331 - ndeleted_(0),
27.332 - table_(NULL),
27.333 - minCapacity_(kMinCapacity)
27.334 - {
27.335 - }
27.336 -
27.337 - ~HashTable()
27.338 - {
27.339 - for (uint32 i = 0; i < capacity_; i++)
27.340 - table_[i].destruct();
27.341 - this->free(table_);
27.342 - }
27.343 -
27.344 - bool init(uint32 capacity = 0) {
27.345 - if (capacity < kMinCapacity)
27.346 - capacity = kMinCapacity;
27.347 - else if (capacity > kMaxCapacity)
27.348 - capacity = kMaxCapacity;
27.349 -
27.350 - minCapacity_ = capacity;
27.351 -
27.352 - assert(IsPowerOfTwo(capacity));
27.353 - capacity_ = capacity;
27.354 -
27.355 - table_ = createTable(capacity_);
27.356 - if (!table_)
27.357 - return false;
27.358 -
27.359 - return true;
27.360 - }
27.361 -
27.362 - template <typename Key>
27.363 - Result find(const Key &key) {
27.364 - return lookup(key);
27.365 - }
27.366 -
27.367 - template <typename Key>
27.368 - Insert findForAdd(const Key &key) {
27.369 - return lookupForAdd(key);
27.370 - }
27.371 -
27.372 - bool add(Insert &i, const Payload &payload) {
27.373 - if (!add(i))
27.374 - return false;
27.375 - *i = payload;
27.376 - return true;
27.377 - }
27.378 -
27.379 - bool checkDensity() {
27.380 - if (underloaded())
27.381 - return shrink();
27.382 - if (overloaded())
27.383 - return grow();
27.384 - return true;
27.385 - }
27.386 -
27.387 - public:
27.388 - class iterator
27.389 - {
27.390 - HashTable *table_;
27.391 - Entry *i_;
27.392 - Entry *end_;
27.393 -
27.394 - public:
27.395 - iterator(HashTable *table)
27.396 - : table_(table),
27.397 - i_(table->table_),
27.398 - end_(table->table_ + table->capacity_)
27.399 - {
27.400 - while (i_ < end_ && !i_->isLive())
27.401 - i_++;
27.402 - }
27.403 -
27.404 - bool empty() const {
27.405 - return i_ == end_;
27.406 - }
27.407 -
27.408 - void erase() {
27.409 - assert(!empty());
27.410 - table_->remove(*i_);
27.411 - }
27.412 -
27.413 - const Payload &operator *() const {
27.414 - return i_->payload();
27.415 - }
27.416 -
27.417 - void next() {
27.418 - do {
27.419 - i_++;
27.420 - } while (i_ < end_ && !i_->isLive());
27.421 - }
27.422 - };
27.423 -};
27.424 -
27.425 -}
27.426 -
27.427 -#endif // _INCLUDE_KEIMA_HASHTABLE_H_
28.1 --- a/jitcraft/Heap-inl.h Tue Jul 24 23:53:34 2012 -0700
28.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
28.3 @@ -1,118 +0,0 @@
28.4 -/* vim: set ts=4 sw=4 tw=99 et:
28.5 - *
28.6 - * Copyright (C) 2012 David Anderson
28.7 - *
28.8 - * This file is part of JITCraft.
28.9 - *
28.10 - * JITCraft is free software: you can redistribute it and/or modify it under
28.11 - * the terms of the GNU General Public License as published by the Free
28.12 - * Software Foundation, either version 3 of the License, or (at your option)
28.13 - * any later version.
28.14 - *
28.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
28.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
28.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
28.18 - *
28.19 - * You should have received a copy of the GNU General Public License along with
28.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
28.21 - */
28.22 -#ifndef _include_jitcraft_heap_inl_h_
28.23 -#define _include_jitcraft_heap_inl_h_
28.24 -
28.25 -#include "Heap.h"
28.26 -#include "Spaces-inl.h"
28.27 -
28.28 -namespace ke {
28.29 -
28.30 -static inline Object *
28.31 -InitAddressIntoObject(Address address, Map *map)
28.32 -{
28.33 - uintptr_t untagged = reinterpret_cast<uintptr_t>(address);
28.34 - assert(IsAligned(untagged, kObjectAlignment));
28.35 -
28.36 - Object *obj = reinterpret_cast<Object *>(address);
28.37 - obj->init(map);
28.38 - return obj;
28.39 -}
28.40 -
28.41 -inline Address
28.42 -Heap::newObject(size_t bytes, Tenure age)
28.43 -{
28.44 - if (bytes >= HeapChunk::kLargeObjectThreshold)
28.45 - return newLargeObject(bytes);
28.46 -
28.47 - if (age == Tenure_Stack) {
28.48 - if (Address addr = newStackObject(bytes))
28.49 - return addr;
28.50 - }
28.51 -
28.52 -#if 0
28.53 - if (age == Tenure_Default) {
28.54 - if (Address addr = newSpace_.allocate(bytes))
28.55 - return addr;
28.56 -
28.57 - scavenge();
28.58 - if (Address addr = newSpace_.allocate(bytes))
28.59 - return addr;
28.60 - }
28.61 -#endif
28.62 -
28.63 - // Try an old-space allocation.
28.64 - if (Address addr = newOldObject(bytes))
28.65 - return addr;
28.66 -
28.67 - // Uh-oh - perform a last-ditch collection.
28.68 - reclaim();
28.69 -
28.70 - return newOldObject(bytes);
28.71 -}
28.72 -
28.73 -inline Object *
28.74 -Heap::allocate(Handle<Map> map, size_t bytes, Tenure age)
28.75 -{
28.76 - size_t actualBytes = Align(bytes, kObjectAlignment);
28.77 -
28.78 - // All objects must be at least two words.
28.79 - assert(actualBytes >= sizeof(Object *) * 2);
28.80 -
28.81 - Address address = newObject(actualBytes, age);
28.82 - if (!address) {
28.83 - reportOutOfMemory();
28.84 - return NULL;
28.85 - }
28.86 - return InitAddressIntoObject(address, map);
28.87 -}
28.88 -
28.89 -inline Address
28.90 -Heap::newStackObject(size_t bytes)
28.91 -{
28.92 - return lifoSpace_.allocate(bytes);
28.93 -}
28.94 -
28.95 -inline Address
28.96 -Heap::newOldObject(size_t bytes)
28.97 -{
28.98 - return oldSpace_.allocate(bytes);
28.99 -}
28.100 -
28.101 -inline Address
28.102 -Heap::newLargeObject(size_t bytes)
28.103 -{
28.104 - if (Address address = largeSpace_.allocate(bytes))
28.105 - return address;
28.106 -
28.107 - reclaim();
28.108 -
28.109 - return largeSpace_.allocate(bytes);
28.110 -}
28.111 -
28.112 -inline void
28.113 -Object::write(Zone *zone, Object **ptr, Object *obj)
28.114 -{
28.115 - *ptr = obj;
28.116 -}
28.117 -
28.118 -}
28.119 -
28.120 -#endif // _include_jitcraft_heap_inl_h_
28.121 -
29.1 --- a/jitcraft/Heap.cpp Tue Jul 24 23:53:34 2012 -0700
29.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
29.3 @@ -1,372 +0,0 @@
29.4 -/* vim: set ts=4 sw=4 tw=99 et:
29.5 - *
29.6 - * Copyright (C) 2012 David Anderson
29.7 - *
29.8 - * This file is part of JITCraft.
29.9 - *
29.10 - * JITCraft is free software: you can redistribute it and/or modify it under
29.11 - * the terms of the GNU General Public License as published by the Free
29.12 - * Software Foundation, either version 3 of the License, or (at your option)
29.13 - * any later version.
29.14 - *
29.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
29.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
29.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
29.18 - *
29.19 - * You should have received a copy of the GNU General Public License along with
29.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
29.21 - */
29.22 -#include "Heap.h"
29.23 -#include "Heap-inl.h"
29.24 -#include "Spaces-inl.h"
29.25 -#include "VirtualObjectVisitor.h"
29.26 -#include "ObjectVisitor.h"
29.27 -#include "Zone.h"
29.28 -#include "StringPool.h"
29.29 -
29.30 -using namespace ke;
29.31 -
29.32 -static const size_t kMarkStackSize = 256 * kKB;
29.33 -
29.34 -Heap::Heap(Zone *zone)
29.35 - : zone_(zone),
29.36 - markStack_(NULL),
29.37 - oldSpace_(zone),
29.38 - mapSpace_(zone)
29.39 -{
29.40 -}
29.41 -
29.42 -bool
29.43 -Heap::initialize()
29.44 -{
29.45 - if (!lifoSpace_.initialize())
29.46 - return false;
29.47 - if (!oldSpace_.initialize())
29.48 - return false;
29.49 - if (!mapSpace_.initialize())
29.50 - return false;
29.51 - if (!largeSpace_.initialize())
29.52 - return false;
29.53 -
29.54 - markStack_ = malloc(kMarkStackSize);
29.55 - if (!markStack_)
29.56 - return false;
29.57 -
29.58 - if ((metaMap_ = allocateMap(MapKind_Meta, sizeof(Map))) == NULL)
29.59 - return false;
29.60 - metaMap_->init(metaMap_);
29.61 -
29.62 - return true;
29.63 -}
29.64 -
29.65 -Heap::~Heap()
29.66 -{
29.67 - free(markStack_);
29.68 -}
29.69 -
29.70 -Map *
29.71 -Heap::allocateMap(MapKind kind, size_t bytes)
29.72 -{
29.73 - size_t actualBytes = Align(bytes, kObjectAlignment);
29.74 -
29.75 - Address addr = mapSpace_.allocate(actualBytes);
29.76 - if (!addr) {
29.77 - reportOutOfMemory();
29.78 - return NULL;
29.79 - }
29.80 -
29.81 - // Note that we use a NULL type initially, and reinterpret-cast to get
29.82 - // the Type pointer, so we can allocate the self-referencing meta type.
29.83 - Object *obj = InitAddressIntoObject(addr, NULL);
29.84 - Map *map = reinterpret_cast<Map *>(obj);
29.85 - map->setKind(kind);
29.86 - return map;
29.87 -}
29.88 -
29.89 -// To avoid marking recursively, we use a worklist to manage the marking
29.90 -// process. Algorithm:
29.91 -//
29.92 -// (1) While the mark stack is not empty:
29.93 -// (a) Remove object |o| from the mark stack.
29.94 -// (b) For each reference |p| in object |o|,
29.95 -// (i) Mark |p| as Black.
29.96 -// (ii) Push |p| onto the mark stack.
29.97 -// (iv) If the mark stack overflowde, mark |p| as Grey.
29.98 -//
29.99 -// We run this algorithm after pushing every root object onto the mark stack.
29.100 -// After all roots have been processed, it may be that the mark stack
29.101 -// overflowed. In this case, we use the following algorithm:
29.102 -//
29.103 -// (1) while the mark stack has overflowed:
29.104 -// (a) Search the heap for grey objects, adding as many as possible to the
29.105 -// mark stack.
29.106 -// (b) Run the mark-stack-emptying algorithm above.
29.107 -//
29.108 -// This algorithm is guaranteed to terminate, because even if there are more
29.109 -// grey objects than mark stack capacity, we eventually all objects will
29.110 -// become grey, and grey objects are not re-pushed onto the mark stack. Thus,
29.111 -// eventually, all objects will become black.
29.112 -//
29.113 -namespace ke {
29.114 -class MarkStack
29.115 -{
29.116 - Object **base_;
29.117 - Object **top_;
29.118 - Object **end_;
29.119 - bool overflowed_;
29.120 -
29.121 - public:
29.122 - MarkStack(Object **base, Object **end)
29.123 - : base_(base),
29.124 - top_(base),
29.125 - end_(end),
29.126 - overflowed_(false)
29.127 - {
29.128 - }
29.129 -
29.130 - void pushBlack(Object *ptr) {
29.131 - assert(HeapChunk::IsBlack(HeapChunk::GetMarkBit(ptr)));
29.132 - if (top_ >= end_) {
29.133 - MarkBit bit = HeapChunk::GetMarkBit(ptr);
29.134 - HeapChunk::BlackToGrey(bit);
29.135 - overflowed_ = true;
29.136 - return;
29.137 - }
29.138 - *top_++ = ptr;
29.139 - }
29.140 -
29.141 - Object *pop() {
29.142 - assert(!empty());
29.143 - return *--top_;
29.144 - }
29.145 - bool overflowed() const {
29.146 - return overflowed_;
29.147 - }
29.148 - bool empty() const {
29.149 - return base_ == top_;
29.150 - }
29.151 - void reset() {
29.152 - assert(empty());
29.153 - overflowed_ = true;
29.154 - }
29.155 -};
29.156 -} // namespace ke
29.157 -
29.158 -// Iterates over an object's body, pushing its referenced objects onto the
29.159 -// mark stack.
29.160 -class MarkingVisitor : public ObjectVisitor<VirtualObjectVisitor>
29.161 -{
29.162 - MarkStack &stack_;
29.163 -
29.164 - public:
29.165 - MarkingVisitor(MarkStack &stack)
29.166 - : stack_(stack)
29.167 - {
29.168 - }
29.169 -
29.170 - void visit(Object **ptr) {
29.171 - if (!*ptr)
29.172 - return;
29.173 -
29.174 - Object *obj = *ptr;
29.175 -
29.176 - // If the object is grey, we'll find it later when searching the heap.
29.177 - // If the object is black, it's already been scsanned.
29.178 - MarkBit bit = HeapChunk::GetMarkBit(obj);
29.179 - if (HeapChunk::IsBlackOrGrey(bit))
29.180 - return;
29.181 -
29.182 - // Place the object in the stack and optimistically mark it black. If
29.183 - // the stack overflows, it'll become grey instead.
29.184 - HeapChunk::WhiteToBlack(bit);
29.185 - stack_.pushBlack(obj);
29.186 - }
29.187 -};
29.188 -
29.189 -static void
29.190 -ProcessMarkStack(MarkStack &stack)
29.191 -{
29.192 - MarkingVisitor visitor(stack);
29.193 -
29.194 - while (!stack.empty()) {
29.195 - Object *obj = stack.pop();
29.196 - assert(HeapChunk::IsBlack(HeapChunk::GetMarkBit(obj)));
29.197 -
29.198 - visitor.iterate(obj);
29.199 - }
29.200 -}
29.201 -
29.202 -class RootMarkingVisitor : public VirtualObjectVisitor
29.203 -{
29.204 - MarkStack &stack_;
29.205 - MarkingVisitor visitor_;
29.206 -
29.207 - public:
29.208 - RootMarkingVisitor(MarkStack &stack)
29.209 - : stack_(stack),
29.210 - visitor_(stack)
29.211 - {
29.212 - }
29.213 -
29.214 - void visit(Object **ptr) {
29.215 - // Flush the stack after every new root. Note that the root gets pushed
29.216 - // as black; that's okay. If the mark stack overflows, its children are
29.217 - // guaranteed to be at least grey.
29.218 - visitor_.visit(ptr);
29.219 - ProcessMarkStack(stack_);
29.220 - }
29.221 -};
29.222 -
29.223 -typedef ChunkObjectIteratorBase<ObjectSizeEvaluator> ChunkObjectIterator;
29.224 -
29.225 -static inline bool
29.226 -EnqueueGreyObject(MarkStack &stack, Object *obj)
29.227 -{
29.228 - assert(!stack.overflowed());
29.229 - MarkBit bit = HeapChunk::GetMarkBit(obj);
29.230 - if (HeapChunk::IsGrey(bit)) {
29.231 - HeapChunk::GreyToBlack(bit);
29.232 - stack.pushBlack(obj);
29.233 - return !stack.overflowed();
29.234 - }
29.235 - return true;
29.236 -}
29.237 -
29.238 -static void
29.239 -EnqueueGreyObjectsInChunks(MarkStack &stack, ChunkObjectIterator iter)
29.240 -{
29.241 - for (Object *obj = iter.next(); obj; obj = iter.next()) {
29.242 - if (!EnqueueGreyObject(stack, obj))
29.243 - return;
29.244 - }
29.245 -}
29.246 -
29.247 -static void
29.248 -EnqueueGreyObjectsInLargeChunks(MarkStack &stack, HeapChunk *first)
29.249 -{
29.250 - for (HeapChunk *chunk = first; chunk; chunk = chunk->next()) {
29.251 - Object *obj = reinterpret_cast<Object *>(chunk->first());
29.252 - if (!EnqueueGreyObject(stack, obj))
29.253 - return;
29.254 - }
29.255 -}
29.256 -
29.257 -void
29.258 -Heap::findGreyObjects(MarkStack &stack)
29.259 -{
29.260 - EnqueueGreyObjectsInChunks(stack, lifoSpace_.begin(ObjectSizeEvaluator()));
29.261 - if (stack.overflowed())
29.262 - return;
29.263 -
29.264 - EnqueueGreyObjectsInChunks(stack, mapSpace_.begin(ObjectSizeEvaluator()));
29.265 - if (stack.overflowed())
29.266 - return;
29.267 -
29.268 - EnqueueGreyObjectsInChunks(stack, oldSpace_.begin(ObjectSizeEvaluator()));
29.269 - if (stack.overflowed())
29.270 - return;
29.271 -
29.272 - EnqueueGreyObjectsInLargeChunks(stack, largeSpace_.first());
29.273 - if (stack.overflowed())
29.274 - return;
29.275 -}
29.276 -
29.277 -void
29.278 -Heap::mark()
29.279 -{
29.280 - Object **qbase = reinterpret_cast<Object **>(markStack_);
29.281 - Object **qend = qbase + (kMarkStackSize / sizeof(Object *));
29.282 - MarkStack stack(qbase, qend);
29.283 - RootMarkingVisitor visitor(stack);
29.284 -
29.285 - // Attempt to mark all objects reachable from the root set.
29.286 - zone_->accept(&visitor);
29.287 - assert(stack.empty());
29.288 -
29.289 - // If the stack overflowed, we need to look through the entire heap for
29.290 - // grey objects to rescan. We keep doing this until there are no grey
29.291 - // objects left.
29.292 - while (stack.overflowed()) {
29.293 - stack.reset();
29.294 - findGreyObjects(stack);
29.295 - ProcessMarkStack(stack);
29.296 - }
29.297 -}
29.298 -
29.299 -// Use the mark bits to scan for live objects, and mark the regions in
29.300 -// between them as free.
29.301 -static void
29.302 -SweepOldSpaceChunk(OldSpace *space, HeapChunk *chunk)
29.303 -{
29.304 - uint32 *markbits = chunk->markBits();
29.305 - uint32 *markbitsEnd = markbits + HeapChunk::kMarkWords;
29.306 - Address freeStart = chunk->first();
29.307 -
29.308 - // Scoot up to the first usable markword. Since memory is reserved for
29.309 - // mark bits, not all addresses are allocatable, so quite a few of the
29.310 - // initial mark bits are wasted. (1KB of mark bytes on x86.)
29.311 - markbits = HeapChunk::GetMarkBit(reinterpret_cast<Object *>(chunk->first())).word();
29.312 -
29.313 - uint32 bits = *markbits;
29.314 - for (;;) {
29.315 - while (bits) {
29.316 - uint32 bit = FindRightmostBit(bits);
29.317 - Address object = HeapChunk::FromMarkBit(chunk, markbits, bit);
29.318 -
29.319 - assert(object >= freeStart);
29.320 - if (freeStart != object)
29.321 - space->markRegionFree(freeStart, object - freeStart);
29.322 -
29.323 - Object *obj = reinterpret_cast<Object *>(object);
29.324 - freeStart = object + SizeOfObject(obj, obj->map());
29.325 -
29.326 - // Since black is 10, we never need to clear the next bit.
29.327 - bits &= ~(1 << bit);
29.328 - }
29.329 - markbits++;
29.330 - bits = *markbits;
29.331 - if (markbits >= markbitsEnd)
29.332 - break;
29.333 - }
29.334 -
29.335 - if (freeStart == chunk->base())
29.336 - chunk->setEmpty();
29.337 - else if (freeStart != chunk->end())
29.338 - space->markRegionFree(freeStart, chunk->end() - freeStart);
29.339 -}
29.340 -
29.341 -static void
29.342 -SweepOldSpace(OldSpace *space)
29.343 -{
29.344 - space->resetFreeList();
29.345 - for (HeapChunk *chunk = space->first(); chunk; chunk = chunk->next()) {
29.346 - SweepOldSpaceChunk(space, chunk);
29.347 - chunk->resetMarkBits();
29.348 - }
29.349 - space->freeUnusedPages();
29.350 -}
29.351 -
29.352 -void
29.353 -Heap::sweep()
29.354 -{
29.355 - // Before destroying mark bits, sweep weak roots.
29.356 - zone_->symbols()->sweep();
29.357 -
29.358 - // Note: we don't bother sweeping the LIFO space.
29.359 - SweepOldSpace(&mapSpace_);
29.360 - SweepOldSpace(&oldSpace_);
29.361 - largeSpace_.sweep();
29.362 -}
29.363 -
29.364 -void
29.365 -Heap::reclaim()
29.366 -{
29.367 - mark();
29.368 - sweep();
29.369 -}
29.370 -
29.371 -void
29.372 -Heap::reportOutOfMemory()
29.373 -{
29.374 - zone_->reportOutOfMemory();
29.375 -}
30.1 --- a/jitcraft/Heap.h Tue Jul 24 23:53:34 2012 -0700
30.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
30.3 @@ -1,143 +0,0 @@
30.4 -/* vim: set ts=4 sw=4 tw=99 et:
30.5 - *
30.6 - * Copyright (C) 2012 David Anderson
30.7 - *
30.8 - * This file is part of JITCraft.
30.9 - *
30.10 - * JITCraft is free software: you can redistribute it and/or modify it under
30.11 - * the terms of the GNU General Public License as published by the Free
30.12 - * Software Foundation, either version 3 of the License, or (at your option)
30.13 - * any later version.
30.14 - *
30.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
30.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
30.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
30.18 - *
30.19 - * You should have received a copy of the GNU General Public License along with
30.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
30.21 - */
30.22 -#ifndef _include_jitcraft_heap_h_
30.23 -#define _include_jitcraft_heap_h_
30.24 -
30.25 -#include "Utility.h"
30.26 -#include "Spaces.h"
30.27 -#include "Barriers.h"
30.28 -#include "Objects.h"
30.29 -#include "Handles.h"
30.30 -
30.31 -namespace ke {
30.32 -
30.33 -class Zone;
30.34 -class MarkStack;
30.35 -
30.36 -// Heap-allocated objects go here. Heaps are thread-local. The heap contains
30.37 -// four spaces:
30.38 -//
30.39 -// LIFO Space: Used for objects that may be stack-allocated.
30.40 -// Old Space: Used for objects that are expected to be long-lived, or that
30.41 -// survive one collection.
30.42 -// Large Space: Used for objects that are so large they should never be
30.43 -// moved between spaces.
30.44 -//
30.45 -// ALLOCATING AN OBJECT DOES NOT ZERO ITS MEMORY.
30.46 -// ALLOCATING AN OBJECT DOES NOT ZERO ITS MEMORY!
30.47 -//
30.48 -// ---------------------------------------------------------------------------
30.49 -//
30.50 -// The following is a high-level overview of how garbage collection works in
30.51 -// Keima. Detailed notes are present in Heap.cpp.
30.52 -//
30.53 -// THE TRI-COLOR INVARIANT: Via an object's mark bits, we maintain the
30.54 -// property that an object that has been fully marked may never reference a
30.55 -// dead object. Objects exist in three states during collection: unmarked
30.56 -// (white), scheduled for marking (grey), and fully marked (black).
30.57 -//
30.58 -// When initiating collection, all objects are white. Objects in the root
30.59 -// set are made grey. The marking process takes grey objects and marks that
30.60 -// each child object is live: if the child is white, it becomes grey. Once
30.61 -// all children are grey or black, the parent grey object can become black,
30.62 -// as it has been fully traversed.
30.63 -//
30.64 -// The result of this process is that when there are no more grey objects,
30.65 -// then we are guaranteed that all black objects are live, and all white
30.66 -// objects are dead.
30.67 -//
30.68 -// MAJOR COLLECTIONS are performed periodically, when either a given memory
30.69 -// threshold has been reached, or when requested by the host application.
30.70 -// They are also performed if no memory can be allocated.
30.71 -//
30.72 -// Major collections are extremely slow; they require full heap traversal,
30.73 -// which can take more than a second on very large heaps. However, they
30.74 -// have the greatest chance at reclaiming all syntactically dead objects.
30.75 -//
30.76 -// SWEEPING is performed after major collections. The free space in between
30.77 -// live objects is added to a free list. Tenured allocations are then
30.78 -// performed in the free space, if possible.
30.79 -//
30.80 -class Heap
30.81 -{
30.82 - Zone *zone_;
30.83 - HeapStack lifoSpace_;
30.84 - OldSpace mapSpace_;
30.85 - OldSpace oldSpace_;
30.86 - LargeObjectSpace largeSpace_;
30.87 -
30.88 - Map *metaMap_;
30.89 -
30.90 - // This is a big hunk o' memory used for marking iteratively. Eventually,
30.91 - // this will be replaced by the inactive semispace in the nursery.
30.92 - void *markStack_;
30.93 -
30.94 - public:
30.95 - enum Tenure {
30.96 - // Default, objects go into the nursery.
30.97 - Tenure_Default,
30.98 -
30.99 - // If objects are proven to not escape the stack, they can go into
30.100 - // a LIFO arena. Allocation on the LIFO arena is not guaranteed to
30.101 - // succeed; thus, objects may still be allocated in other arenas.
30.102 - Tenure_Stack,
30.103 -
30.104 - // Objects that should not go into the nursery (i.e. are expected
30.105 - // to be long-living) go here.
30.106 - Tenure_Old
30.107 - };
30.108 -
30.109 - private:
30.110 - inline Address newLargeObject(size_t bytes);
30.111 - inline Address newOldObject(size_t bytes);
30.112 - inline Address newStackObject(size_t bytes);
30.113 - inline Address newObject(size_t bytes, Tenure pretenure);
30.114 -
30.115 - private:
30.116 - void findGreyObjects(MarkStack &stack);
30.117 - void mark();
30.118 - void sweep();
30.119 -
30.120 - void reportOutOfMemory();
30.121 -
30.122 - public:
30.123 - Heap(Zone *zone);
30.124 - ~Heap();
30.125 - bool initialize();
30.126 -
30.127 - inline Object *allocate(Handle<Map> map, size_t byes, Tenure pretenure);
30.128 - Map *allocateMap(MapKind kind, size_t bytes);
30.129 -
30.130 - Map *metaMap() {
30.131 - return metaMap_;
30.132 - }
30.133 - inline Address lifoPosition() const {
30.134 - return lifoSpace_.position();
30.135 - }
30.136 - inline void unwindLifo(Address to) {
30.137 - lifoSpace_.unwind(to);
30.138 - }
30.139 -
30.140 - // Perform a full garbage collection.
30.141 - void reclaim();
30.142 -};
30.143 -
30.144 -}
30.145 -
30.146 -#endif //_include_jitcraft_heap_h_
31.1 --- a/jitcraft/InlineList.h Tue Jul 24 23:53:34 2012 -0700
31.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
31.3 @@ -1,129 +0,0 @@
31.4 -/*
31.5 - * Copyright (C) 2004-2012 David Anderson
31.6 - *
31.7 - * This file is part of SourcePawn.
31.8 - *
31.9 - * SourcePawn is free software: you can redistribute it and/or modify it under
31.10 - * the terms of the GNU General Public License as published by the Free
31.11 - * Software Foundation, either version 3 of the License, or (at your option)
31.12 - * any later version.
31.13 - *
31.14 - * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
31.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
31.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
31.17 - *
31.18 - * You should have received a copy of the GNU General Public License along with
31.19 - * SourcePawn. If not, see http://www.gnu.org/licenses/.
31.20 - */
31.21 -#ifndef _include_ke_inline_list_h_
31.22 -#define _include_ke_inline_list_h_
31.23 -
31.24 -#include <stddef.h>
31.25 -
31.26 -namespace ke {
31.27 -
31.28 -template <typename T> class InlineList;
31.29 -
31.30 -template <typename T>
31.31 -class InlineListNode
31.32 -{
31.33 - friend class InlineList<T>;
31.34 -
31.35 - public:
31.36 - InlineListNode()
31.37 - : next_(NULL),
31.38 - prev_(NULL)
31.39 - {
31.40 - }
31.41 -
31.42 - InlineListNode(InlineListNode *next, InlineListNode *prev)
31.43 - : next_(next),
31.44 - prev_(prev)
31.45 - {
31.46 - }
31.47 -
31.48 - protected:
31.49 - InlineListNode *next_;
31.50 - InlineListNode *prev_;
31.51 -};
31.52 -
31.53 -template <typename T>
31.54 -class InlineList
31.55 -{
31.56 - typedef InlineListNode<T> Node;
31.57 -
31.58 - Node head_;
31.59 -
31.60 - public:
31.61 - InlineList()
31.62 - : head_(&head_, &head_)
31.63 - {
31.64 - }
31.65 -
31.66 - public:
31.67 - class iterator
31.68 - {
31.69 - friend class InlineList;
31.70 - Node *iter_;
31.71 -
31.72 - public:
31.73 - iterator(Node *iter)
31.74 - : iter_(iter)
31.75 - {
31.76 - }
31.77 -
31.78 - iterator & operator++() {
31.79 - iter_ = iter_->next_;
31.80 - return *this;
31.81 - }
31.82 - iterator operator ++(int) {
31.83 - iterator old(*this);
31.84 - iter_ = iter_->next_;
31.85 - return old;
31.86 - }
31.87 - T * operator *() {
31.88 - return static_cast<T *>(iter_);
31.89 - }
31.90 - T * operator ->() {
31.91 - return static_cast<T *>(iter_);
31.92 - }
31.93 - bool operator !=(const iterator &where) const {
31.94 - return iter_ != where.iter_;
31.95 - }
31.96 - bool operator ==(const iterator &where) const {
31.97 - return iter_ == where.iter_;
31.98 - }
31.99 - iterator prev() const {
31.100 - return iterator(iter_->prev_);
31.101 - }
31.102 - iterator next() const {
31.103 - return iterator(iter_->next_);
31.104 - }
31.105 - };
31.106 -
31.107 - iterator begin() {
31.108 - return iterator(head_.next_);
31.109 - }
31.110 - iterator end() {
31.111 - return iterator(&head_);
31.112 - }
31.113 - void append(Node *t) {
31.114 - t->prev_ = head_.prev_;
31.115 - t->next_ = &head_;
31.116 - head_.prev_->next_ = t;
31.117 - head_.prev_ = t;
31.118 - }
31.119 - iterator erase(iterator i) {
31.120 - iterator next = ++i;
31.121 - remove(i.iter_);
31.122 - return next;
31.123 - }
31.124 - void remove(Node *t) {
31.125 - t->prev_->next_ = t->next_;
31.126 - t->next_->prev_ = t->prev_;
31.127 - }
31.128 -};
31.129 -
31.130 -}
31.131 -
31.132 -#endif // _include_ke_inline_list_h_
32.1 --- a/jitcraft/Interpreter.cpp Tue Jul 24 23:53:34 2012 -0700
32.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
32.3 @@ -1,937 +0,0 @@
32.4 -/* vim: set ts=4 sw=4 tw=99 et:
32.5 - *
32.6 - * Copyright (C) 2012 David Anderson
32.7 - *
32.8 - * This file is part of JITCraft.
32.9 - *
32.10 - * JITCraft is free software: you can redistribute it and/or modify it under
32.11 - * the terms of the GNU General Public License as published by the Free
32.12 - * Software Foundation, either version 3 of the License, or (at your option)
32.13 - * any later version.
32.14 - *
32.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
32.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
32.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
32.18 - *
32.19 - * You should have received a copy of the GNU General Public License along with
32.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
32.21 - */
32.22 -#include "Interpreter.h"
32.23 -#include "Modules.h"
32.24 -#include "Zone.h"
32.25 -#include "Types.h"
32.26 -#include "Array.h"
32.27 -#include "Reference.h"
32.28 -#include "Strings.h"
32.29 -#include "Environments.h"
32.30 -#include "Heap-inl.h"
32.31 -
32.32 -using namespace ke;
32.33 -
32.34 -#define PUSH_I32(top, value) \
32.35 - do { \
32.36 - top.sp->i32 = value; \
32.37 - top.sp++; \
32.38 - } while (0)
32.39 -
32.40 -#define PUSH_F(top, value) \
32.41 - do { \
32.42 - top.sp->f = value; \
32.43 - top.sp++; \
32.44 - } while (0)
32.45 -
32.46 -static inline int
32.47 -POP_I32(Top &top)
32.48 -{
32.49 - int value = top.sp[-1].i32;
32.50 - top.sp--;
32.51 - return value;
32.52 -}
32.53 -
32.54 -static inline float
32.55 -POP_F(Top &top)
32.56 -{
32.57 - float value = top.sp[-1].f;
32.58 - top.sp--;
32.59 - return value;
32.60 -}
32.61 -
32.62 -// Pawn's original semantics specify some kind of floor operation, so
32.63 -// (8 / -3 == -3) and (-8 / 3 == -1). The SourcePawn 1 compiler (spcomp) uses
32.64 -// the upstream algorithm when constant folding. However the SourcePawn 1 JIT
32.65 -// does not. My guess is that Borja freaked out seeing the 13-instruction x86
32.66 -// sequence necessary to get this functionality (I vaguely recall a thread
32.67 -// where we discussed this with Mark Peter? But the ITB forums are gone...),
32.68 -// and we just decided to break the damn thing. So SP1 was inconsistent, but
32.69 -// we are not. And for completeness, we assert that the C compiler does the
32.70 -// right thing, since C89 leaves it unspecified.
32.71 -STATIC_ASSERT(8 / -3 == -2);
32.72 -STATIC_ASSERT(-8 / 3 == -2);
32.73 -
32.74 -static inline bool
32.75 -PushNewRef(Zone *zone, Top &top, void *location, Heap::Tenure tenure)
32.76 -{
32.77 - Reference *ref = Reference::NewStack(zone, location, tenure);
32.78 - if (!ref)
32.79 - return false;
32.80 - top.sp->ref = ref;
32.81 - top.sp++;
32.82 - return true;
32.83 -}
32.84 -
32.85 -// Generate an array with completely static sizes.
32.86 -static Array *
32.87 -GenerateArray(Zone *zone, Handle<ArrayMap> map, Heap::Tenure tenure)
32.88 -{
32.89 - assert(map->type()->elements() != -1);
32.90 -
32.91 - Local<Array> array(zone, Array::New(zone, map, map->type()->elements(), tenure));
32.92 - if (!array)
32.93 - return NULL;
32.94 -
32.95 - if (map->type()->levels() == 1)
32.96 - return array;
32.97 -
32.98 - Local<ArrayMap> contained(zone, map->contained());
32.99 - Local<Array> sub(zone);
32.100 - for (unsigned i = 0; i < unsigned(map->type()->elements()); i++) {
32.101 - sub = GenerateArray(zone, contained, tenure);
32.102 - if (!sub)
32.103 - return NULL;
32.104 - array->writeObject(zone, i, sub);
32.105 - }
32.106 -
32.107 - return array;
32.108 -}
32.109 -
32.110 -static bool
32.111 -CopyArray(Zone *zone, Array *source, Array *dest)
32.112 -{
32.113 - assert(source->type()->levels() == 1);
32.114 - assert(dest->type()->levels() == 1);
32.115 - assert(source->type()->contained()->primitive() ==
32.116 - dest->type()->contained()->primitive());
32.117 - assert(source->nelements() >= dest->nelements());
32.118 - assert(dest->elementSize() == source->elementSize());
32.119 -
32.120 - memcpy(source->vec(), dest->vec(), dest->nelements() * dest->elementSize());
32.121 - return true;
32.122 -}
32.123 -
32.124 -static bool
32.125 -InvokeNative(Zone *zone, Handle<Native> native, void *identity, LocalSlot *args, unsigned argc,
32.126 - int *result)
32.127 -{
32.128 - NativeArgs guard;
32.129 -
32.130 - if (!zone->stack().pushNativeFrame(native, guard, argc + 1))
32.131 - return false;
32.132 -
32.133 - intptr_t *cells = guard.args();
32.134 -
32.135 - // params[0] == argc, in ISPE
32.136 - cells[0] = argc;
32.137 -
32.138 - // Pass the formal arguments.
32.139 - Local<Type> type(zone, native->type());
32.140 - Local<Type> param(zone);
32.141 - for (unsigned i = 0; i < type->parameters()->length(); i++) {
32.142 - param = type->parameterAt(i);
32.143 -
32.144 - // For floats, we rely on the aliasing of |i32| and |f|.
32.145 - LocalSlot &arg = args[-int(i) - 1];
32.146 - if (param->isInt32() || param->isFloat()) {
32.147 - cells[i + 1] = arg.i32;
32.148 - } else if (param->isReference()) {
32.149 - cells[i + 1] = reinterpret_cast<intptr_t>(arg.ref->location());
32.150 - } else {
32.151 - assert(param->isArray());
32.152 - cells[i + 1] = reinterpret_cast<intptr_t>(arg.array->vec());
32.153 - }
32.154 - }
32.155 -
32.156 - // For variadic arguments, the compiler left either arrays or references.
32.157 - for (unsigned i = type->parameters()->length(); i < argc; i++) {
32.158 - LocalSlot &arg = args[-int(i) - 1];
32.159 -
32.160 - if (arg.obj->is(MapKind_Reference)) {
32.161 - cells[i + 1] = reinterpret_cast<intptr_t>(arg.ref->location());
32.162 - } else {
32.163 - assert(arg.obj->is(MapKind_Array));
32.164 - cells[i + 1] = reinterpret_cast<intptr_t>(arg.array->vec());
32.165 - }
32.166 - }
32.167 -
32.168 - typedef intptr_t (*INVOKE)(void *, intptr_t *);
32.169 - INVOKE invoke = (INVOKE)native->function();
32.170 - *result = invoke(identity, cells);
32.171 -
32.172 - return !zone->hasPendingException();
32.173 -}
32.174 -
32.175 -bool
32.176 -ke::Interpret(Zone *zone, Frame *entryFrame, LocalSlot *result)
32.177 -{
32.178 - Top &top = *zone->stack().top();
32.179 - if (!entryFrame)
32.180 - entryFrame = top.fp;
32.181 -
32.182 - LocalSlot *locals = entryFrame->locals();
32.183 -
32.184 - for (;;) {
32.185 - Opcode op = Opcode(*top.pc);
32.186 - switch (op) {
32.187 -
32.188 -case OP_NOP:
32.189 - break;
32.190 -
32.191 -case OP_INT:
32.192 - PUSH_I32(top, READ_INT32(top.pc));
32.193 - break;
32.194 -
32.195 -case OP_FLOAT:
32.196 - PUSH_F(top, READ_FLOAT(top.pc));
32.197 - break;
32.198 -
32.199 -case OP_RETURN:
32.200 -case OP_RETURNVOID:
32.201 -case OP_STOP:
32.202 -{
32.203 - if (op == OP_RETURN)
32.204 - *result = *--top.sp;
32.205 -
32.206 - if (top.fp == entryFrame)
32.207 - goto done;
32.208 -
32.209 - // This must not GC.
32.210 - zone->stack().popInlineFrame();
32.211 - locals = top.fp->locals();
32.212 -
32.213 - if (op == OP_RETURN)
32.214 - *top.sp++ = *result;
32.215 -
32.216 - top.pc += OpcodeInfo[*top.pc].length;
32.217 - continue;
32.218 -}
32.219 -
32.220 -case OP_POP:
32.221 -{
32.222 - top.sp--;
32.223 - break;
32.224 -}
32.225 -
32.226 -#define RELATIONAL_JUMP(op) \
32.227 - { \
32.228 - int right = POP_I32(top); \
32.229 - int left = POP_I32(top); \
32.230 - if (left op right) { \
32.231 - top.pc += READ_INT32(top.pc); \
32.232 - continue; \
32.233 - } \
32.234 - }
32.235 -
32.236 -case OP_JL:
32.237 - RELATIONAL_JUMP(<);
32.238 - break;
32.239 -
32.240 -case OP_JLE:
32.241 - RELATIONAL_JUMP(<=);
32.242 - break;
32.243 -
32.244 -case OP_JG:
32.245 - RELATIONAL_JUMP(>);
32.246 - break;
32.247 -
32.248 -case OP_JGE:
32.249 - RELATIONAL_JUMP(>=);
32.250 - break;
32.251 -
32.252 -case OP_JEQ:
32.253 - RELATIONAL_JUMP(==);
32.254 - break;
32.255 -
32.256 -case OP_JNE:
32.257 - RELATIONAL_JUMP(!=);
32.258 - break;
32.259 -
32.260 -#undef RELATIONAL_JUMP
32.261 -
32.262 -case OP_JT:
32.263 -{
32.264 - int value = POP_I32(top);
32.265 - if (value) {
32.266 - top.pc += READ_INT32(top.pc);
32.267 - continue;
32.268 - }
32.269 - break;
32.270 -}
32.271 -
32.272 -case OP_JF:
32.273 -{
32.274 - int value = POP_I32(top);
32.275 - if (!value) {
32.276 - top.pc += READ_INT32(top.pc);
32.277 - continue;
32.278 - }
32.279 - break;
32.280 -}
32.281 -
32.282 -#define RELATIONAL_JUMP_F(op) \
32.283 - { \
32.284 - float right = POP_F(top); \
32.285 - float left = POP_F(top); \
32.286 - if (left op right) { \
32.287 - top.pc += READ_INT32(top.pc); \
32.288 - continue; \
32.289 - } \
32.290 - }
32.291 -
32.292 -case OP_JL_F:
32.293 - RELATIONAL_JUMP_F(<);
32.294 - break;
32.295 -
32.296 -case OP_JLE_F:
32.297 - RELATIONAL_JUMP_F(<=);
32.298 - break;
32.299 -
32.300 -case OP_JG_F:
32.301 - RELATIONAL_JUMP_F(>);
32.302 - break;
32.303 -
32.304 -case OP_JGE_F:
32.305 - RELATIONAL_JUMP_F(>=);
32.306 - break;
32.307 -
32.308 -case OP_JEQ_F:
32.309 - RELATIONAL_JUMP_F(==);
32.310 - break;
32.311 -
32.312 -case OP_JNE_F:
32.313 - RELATIONAL_JUMP_F(!=);
32.314 - break;
32.315 -
32.316 -case OP_JT_F:
32.317 -{
32.318 - float value = POP_F(top);
32.319 - if (value) {
32.320 - top.pc += READ_INT32(top.pc);
32.321 - continue;
32.322 - }
32.323 - break;
32.324 -}
32.325 -
32.326 -case OP_JF_F:
32.327 -{
32.328 - float value = POP_F(top);
32.329 - if (!value) {
32.330 - top.pc += READ_INT32(top.pc);
32.331 - continue;
32.332 - }
32.333 - break;
32.334 -}
32.335 -
32.336 -case OP_JUMP:
32.337 - top.pc += READ_INT32(top.pc);
32.338 - continue;
32.339 -
32.340 -case OP_GETLOCAL:
32.341 -{
32.342 - int slot = READ_INT32(top.pc);
32.343 - *top.sp++ = locals[slot];
32.344 - break;
32.345 -}
32.346 -
32.347 -case OP_SETLOCAL:
32.348 -{
32.349 - int slot = READ_INT32(top.pc);
32.350 - locals[slot] = top.sp[-1];
32.351 - break;
32.352 -}
32.353 -
32.354 -case OP_ADD:
32.355 -{
32.356 - top.sp[-2].i32 = top.sp[-2].i32 + top.sp[-1].i32;
32.357 - top.sp--;
32.358 - break;
32.359 -}
32.360 -
32.361 -case OP_SUB:
32.362 -{
32.363 - top.sp[-2].i32 = top.sp[-2].i32 - top.sp[-1].i32;
32.364 - top.sp--;
32.365 - break;
32.366 -}
32.367 -
32.368 -case OP_MUL:
32.369 -{
32.370 - top.sp[-2].i32 = top.sp[-2].i32 * top.sp[-1].i32;
32.371 - top.sp--;
32.372 - break;
32.373 -}
32.374 -
32.375 -case OP_DIV:
32.376 -{
32.377 - if (top.sp[-1].i32 == 0) {
32.378 - zone->reportError(Message_IntegerDivideByZero);
32.379 - goto error;
32.380 - }
32.381 - top.sp[-2].i32 = top.sp[-2].i32 / top.sp[-1].i32;
32.382 - top.sp--;
32.383 - break;
32.384 -}
32.385 -
32.386 -case OP_MOD:
32.387 -{
32.388 - if (top.sp[-1].i32 == 0) {
32.389 - zone->reportError(Message_IntegerDivideByZero);
32.390 - goto error;
32.391 - }
32.392 - top.sp[-2].i32 = top.sp[-2].i32 % top.sp[-1].i32;
32.393 - top.sp--;
32.394 - break;
32.395 -}
32.396 -
32.397 -case OP_LT:
32.398 -{
32.399 - top.sp[-2].i32 = top.sp[-2].i32 < top.sp[-1].i32;
32.400 - top.sp--;
32.401 - break;
32.402 -}
32.403 -
32.404 -case OP_LE:
32.405 -{
32.406 - top.sp[-2].i32 = top.sp[-2].i32 <= top.sp[-1].i32;
32.407 - top.sp--;
32.408 - break;
32.409 -}
32.410 -
32.411 -case OP_GT:
32.412 -{
32.413 - top.sp[-2].i32 = top.sp[-2].i32 > top.sp[-1].i32;
32.414 - top.sp--;
32.415 - break;
32.416 -}
32.417 -
32.418 -case OP_GE:
32.419 -{
32.420 - top.sp[-2].i32 = top.sp[-2].i32 >= top.sp[-1].i32;
32.421 - top.sp--;
32.422 - break;
32.423 -}
32.424 -
32.425 -case OP_EQ:
32.426 -{
32.427 - top.sp[-2].i32 = (top.sp[-2].i32 == top.sp[-1].i32);
32.428 - top.sp--;
32.429 - break;
32.430 -}
32.431 -
32.432 -case OP_NE:
32.433 -{
32.434 - top.sp[-2].i32 = (top.sp[-2].i32 != top.sp[-1].i32);
32.435 - top.sp--;
32.436 - break;
32.437 -}
32.438 -
32.439 -case OP_ADD_F:
32.440 -{
32.441 - top.sp[-2].f = top.sp[-2].f + top.sp[-1].f;
32.442 - top.sp--;
32.443 - break;
32.444 -}
32.445 -
32.446 -case OP_SUB_F:
32.447 -{
32.448 - top.sp[-2].f = top.sp[-2].f - top.sp[-1].f;
32.449 - top.sp--;
32.450 - break;
32.451 -}
32.452 -
32.453 -case OP_MUL_F:
32.454 -{
32.455 - top.sp[-2].f = top.sp[-2].f * top.sp[-1].f;
32.456 - top.sp--;
32.457 - break;
32.458 -}
32.459 -
32.460 -case OP_DIV_F:
32.461 -{
32.462 - top.sp[-2].f = top.sp[-2].f / top.sp[-1].f;
32.463 - top.sp--;
32.464 - break;
32.465 -}
32.466 -
32.467 -case OP_LT_F:
32.468 -{
32.469 - top.sp[-2].f = top.sp[-2].f < top.sp[-1].f;
32.470 - top.sp--;
32.471 - break;
32.472 -}
32.473 -
32.474 -case OP_LE_F:
32.475 -{
32.476 - top.sp[-2].f = top.sp[-2].f <= top.sp[-1].f;
32.477 - top.sp--;
32.478 - break;
32.479 -}
32.480 -
32.481 -case OP_GT_F:
32.482 -{
32.483 - top.sp[-2].f = top.sp[-2].f > top.sp[-1].f;
32.484 - top.sp--;
32.485 - break;
32.486 -}
32.487 -
32.488 -case OP_GE_F:
32.489 -{
32.490 - top.sp[-2].f = top.sp[-2].f >= top.sp[-1].f;
32.491 - top.sp--;
32.492 - break;
32.493 -}
32.494 -
32.495 -case OP_EQ_F:
32.496 -{
32.497 - top.sp[-2].i32 = (top.sp[-2].f == top.sp[-1].f);
32.498 - top.sp--;
32.499 - break;
32.500 -}
32.501 -
32.502 -case OP_NE_F:
32.503 -{
32.504 - top.sp[-2].i32 = (top.sp[-2].f != top.sp[-1].f);
32.505 - top.sp--;
32.506 - break;
32.507 -}
32.508 -
32.509 -case OP_SHL:
32.510 -{
32.511 - top.sp[-2].i32 = top.sp[-2].i32 << top.sp[-1].i32;
32.512 - top.sp--;
32.513 - break;
32.514 -}
32.515 -
32.516 -case OP_SHR:
32.517 -{
32.518 - top.sp[-2].i32 = top.sp[-2].i32 >> top.sp[-1].i32;
32.519 - top.sp--;
32.520 - break;
32.521 -}
32.522 -
32.523 -case OP_USHR:
32.524 -{
32.525 - top.sp[-2].i32 = unsigned(top.sp[-2].i32) << unsigned(top.sp[-1].i32);
32.526 - top.sp--;
32.527 - break;
32.528 -}
32.529 -
32.530 -case OP_BITAND:
32.531 -{
32.532 - top.sp[-2].i32 = top.sp[-2].i32 & top.sp[-1].i32;
32.533 - top.sp--;
32.534 - break;
32.535 -}
32.536 -
32.537 -case OP_BITOR:
32.538 -{
32.539 - top.sp[-2].i32 = top.sp[-2].i32 | top.sp[-1].i32;
32.540 - top.sp--;
32.541 - break;
32.542 -}
32.543 -
32.544 -case OP_BITXOR:
32.545 -{
32.546 - top.sp[-2].i32 = top.sp[-2].i32 ^ top.sp[-1].i32;
32.547 - top.sp--;
32.548 - break;
32.549 -}
32.550 -
32.551 -case OP_BITNOT:
32.552 -{
32.553 - top.sp[-1].i32 = ~top.sp[-1].i32;
32.554 - break;
32.555 -}
32.556 -
32.557 -case OP_NOT:
32.558 -{
32.559 - top.sp[-1].i32 = top.sp[-1].i32 ? 0 : 1;
32.560 - break;
32.561 -}
32.562 -
32.563 -case OP_NOT_F:
32.564 -{
32.565 - top.sp[-1].i32 = top.sp[-1].f ? 0 : 1;
32.566 - break;
32.567 -}
32.568 -
32.569 -case OP_NEG:
32.570 -{
32.571 - top.sp[-1].i32 = -top.sp[-1].i32;
32.572 - break;
32.573 -}
32.574 -
32.575 -case OP_NEG_F:
32.576 -{
32.577 - top.sp[-1].f = -top.sp[-1].f;
32.578 - break;
32.579 -}
32.580 -
32.581 -case OP_CALL:
32.582 -{
32.583 - Local<Function> newFun(zone, top.sp[-1].fun);
32.584 - top.sp--;
32.585 -
32.586 - if (!zone->stack().pushInlineFrame(newFun))
32.587 - goto error;
32.588 -
32.589 - locals = top.fp->locals();
32.590 - continue;
32.591 -}
32.592 -
32.593 -case OP_GETARG:
32.594 -{
32.595 - unsigned slot = READ_UINT32(top.pc);
32.596 - *top.sp++ = top.fp->arg(slot);
32.597 - break;
32.598 -}
32.599 -
32.600 -case OP_SETARG:
32.601 -{
32.602 - unsigned slot = READ_UINT32(top.pc);
32.603 - top.fp->arg(slot) = *--top.sp;
32.604 - break;
32.605 -}
32.606 -
32.607 -case OP_BOUNDS:
32.608 -{
32.609 - Array *array = top.sp[-2].array;
32.610 - int index = top.sp[-1].i32;
32.611 - if (index < 0 || unsigned(index) >= array->nelements()) {
32.612 - zone->reportError(Message_ArrayIndexOutOfBounds, index, array->nelements());
32.613 - goto error;
32.614 - }
32.615 - break;
32.616 -}
32.617 -
32.618 -case OP_GETARRAY_I:
32.619 -{
32.620 - Array *array = top.sp[-2].array;
32.621 - int index = top.sp[-1].i32;
32.622 - top.sp[-2].i32 = array->readInt32(index);
32.623 - top.sp--;
32.624 - break;
32.625 -}
32.626 -
32.627 -case OP_GETARRAY_F:
32.628 -{
32.629 - Array *array = top.sp[-2].array;
32.630 - int index = top.sp[-1].i32;
32.631 - top.sp[-2].f = array->readFloat(index);
32.632 - top.sp--;
32.633 - break;
32.634 -}
32.635 -
32.636 -case OP_GETARRAY_C:
32.637 -{
32.638 - Array *array = top.sp[-2].array;
32.639 - int index = top.sp[-1].i32;
32.640 - top.sp[-2].i32 = array->readChar(index);
32.641 - top.sp--;
32.642 - break;
32.643 -}
32.644 -
32.645 -case OP_SETARRAY_I:
32.646 -{
32.647 - Array *array = top.sp[-3].array;
32.648 - int index = top.sp[-2].i32;
32.649 - array->writeInt32(index, top.sp[-1].i32);
32.650 - top.sp[-3] = top.sp[-1];
32.651 - top.sp -= 2;
32.652 - break;
32.653 -}
32.654 -
32.655 -case OP_SETARRAY_F:
32.656 -{
32.657 - Array *array = top.sp[-3].array;
32.658 - int index = top.sp[-2].i32;
32.659 - array->writeFloat(index, top.sp[-1].f);
32.660 - top.sp[-3] = top.sp[-1];
32.661 - top.sp -= 2;
32.662 - break;
32.663 -}
32.664 -
32.665 -case OP_SETARRAY_C:
32.666 -{
32.667 - Array *array = top.sp[-3].array;
32.668 - int index = top.sp[-2].i32;
32.669 - array->writeChar(index, top.sp[-1].i32);
32.670 - top.sp[-3] = top.sp[-1];
32.671 - top.sp -= 2;
32.672 - break;
32.673 -}
32.674 -
32.675 -case OP_GETARRAY_O:
32.676 -{
32.677 - Array *array = top.sp[-2].array;
32.678 - int index = top.sp[-1].i32;
32.679 - top.sp[-2].array = Array::cast(array->readObject(index));
32.680 - top.sp--;
32.681 - break;
32.682 -}
32.683 -
32.684 -case OP_CVT_I2F:
32.685 -{
32.686 - int ival = POP_I32(top);
32.687 - float fval = (float)ival;
32.688 - PUSH_F(top, fval);
32.689 - break;
32.690 -}
32.691 -
32.692 -case OP_NEWARRAY:
32.693 -{
32.694 - Heap::Tenure tenure = (Heap::Tenure)top.pc[1];
32.695 - Local<ArrayMap> map(zone, ArrayMap::cast(top.fp->code()->map(READ_UINT32(top.pc + 1))));
32.696 - Array *array = GenerateArray(zone, map, tenure);
32.697 - if (!array)
32.698 - goto error;
32.699 - top.sp->obj = array;
32.700 - top.sp++;
32.701 - break;
32.702 -}
32.703 -
32.704 -case OP_SAVELIFO:
32.705 -{
32.706 - unsigned slot = READ_UINT32(top.pc);
32.707 - locals[slot].address = zone->heap().lifoPosition();
32.708 - break;
32.709 -}
32.710 -
32.711 -case OP_UNWINDLIFO:
32.712 -{
32.713 - unsigned slot = READ_UINT32(top.pc);
32.714 - zone->heap().unwindLifo(locals[slot].address);
32.715 - break;
32.716 -}
32.717 -
32.718 -case OP_VARREF_LIFO:
32.719 -{
32.720 - unsigned slot = READ_UINT32(top.pc);
32.721 - if (!PushNewRef(zone, top, &locals[slot], Heap::Tenure_Stack))
32.722 - goto error;
32.723 - break;
32.724 -}
32.725 -
32.726 -case OP_ARGREF_LIFO:
32.727 -{
32.728 - unsigned slot = READ_UINT32(top.pc);
32.729 - if (!PushNewRef(zone, top, &top.fp->arg(slot), Heap::Tenure_Stack))
32.730 - goto error;
32.731 - break;
32.732 -}
32.733 -
32.734 -case OP_ARRAYREF_LIFO:
32.735 -{
32.736 - Local<Array> array(zone, top.sp[-2].array);
32.737 - Local<Reference> ref(zone, Reference::NewArray(zone, array, top.sp[-1].i32, Heap::Tenure_Stack));
32.738 - if (!ref)
32.739 - goto error;
32.740 - top.sp[-2].ref = ref;
32.741 - top.sp--;
32.742 - break;
32.743 -}
32.744 -
32.745 -case OP_SLOTREF_LIFO:
32.746 -{
32.747 - Reference *ref = Reference::NewStack(zone, top.sp[-1], Heap::Tenure_Stack);
32.748 - if (!ref)
32.749 - goto error;
32.750 - top.sp[-1].ref = ref;
32.751 - break;
32.752 -}
32.753 -
32.754 -case OP_GETREF_I:
32.755 -{
32.756 - top.sp[-1].i32 = top.sp[-1].ref->getInt();
32.757 - break;
32.758 -}
32.759 -
32.760 -case OP_SETREF_I:
32.761 -{
32.762 - top.sp[-2].ref->setInt(top.sp[-1].i32);
32.763 - top.sp[-2].i32 = top.sp[-1].i32;
32.764 - top.sp--;
32.765 - break;
32.766 -}
32.767 -
32.768 -case OP_GETREF_F:
32.769 -{
32.770 - top.sp[-1].f = top.sp[-1].ref->getFloat();
32.771 - break;
32.772 -}
32.773 -
32.774 -case OP_SETREF_F:
32.775 -{
32.776 - top.sp[-2].ref->setFloat(top.sp[-1].f);
32.777 - top.sp[-2].f = top.sp[-1].f;
32.778 - break;
32.779 -}
32.780 -
32.781 -case OP_OBJECT:
32.782 -{
32.783 - top.sp->obj = top.fp->code()->object(READ_UINT32(top.pc));
32.784 - top.sp++;
32.785 - break;
32.786 -}
32.787 -
32.788 -case OP_ARRAYCOPY:
32.789 -{
32.790 - // Note for this assignment opcode, we return the left-hand side, not the
32.791 - // right, since in this case the result of the expression could be different.
32.792 - if (!CopyArray(zone, top.sp[-2].array, top.sp[-1].array))
32.793 - goto error;
32.794 - top.sp--;
32.795 - break;
32.796 -}
32.797 -
32.798 -case OP_DUP:
32.799 -{
32.800 - top.sp++;
32.801 - top.sp[-1] = top.sp[-2];
32.802 - break;
32.803 -}
32.804 -
32.805 -case OP_DUP2:
32.806 -{
32.807 - top.sp += 2;
32.808 - top.sp[-2] = top.sp[-4];
32.809 - top.sp[-1] = top.sp[-3];
32.810 - break;
32.811 -}
32.812 -
32.813 -case OP_SWAP:
32.814 -{
32.815 - LocalSlot slot = top.sp[-2];
32.816 - top.sp[-2] = top.sp[-1];
32.817 - top.sp[-1] = slot;
32.818 - break;
32.819 -}
32.820 -
32.821 -case OP_ROLL3:
32.822 -{
32.823 - LocalSlot slot = top.sp[-3];
32.824 - top.sp[-3] = top.sp[-2];
32.825 - top.sp[-2] = top.sp[-1];
32.826 - top.sp[-1] = slot;
32.827 - break;
32.828 -}
32.829 -
32.830 -case OP_PICK2:
32.831 -{
32.832 - top.sp++;
32.833 - top.sp[-1] = top.sp[-3];
32.834 - break;
32.835 -}
32.836 -
32.837 -case OP_PICK3:
32.838 -{
32.839 - top.sp++;
32.840 - top.sp[-1] = top.sp[-4];
32.841 - break;
32.842 -}
32.843 -
32.844 -case OP_CALLNATIVE:
32.845 -{
32.846 - unsigned index = READ_UINT32(top.pc);
32.847 - unsigned argc = READ_UINT32(top.pc + 4);
32.848 -
32.849 - Local<Native> native(zone, Native::cast(top.fp->code()->module()->natives()->at(index)));
32.850 - if (!native->function()) {
32.851 - zone->reportError(Message_NativeNotBound, native->name()->chars());
32.852 - goto error;
32.853 - }
32.854 -
32.855 - int result;
32.856 - void *nativeIdentity = top.fp->code()->module()->nativeIdentity();
32.857 - if (!InvokeNative(zone, native, nativeIdentity, top.sp, argc, &result))
32.858 - goto error;
32.859 -
32.860 - top.sp -= argc;
32.861 - PUSH_I32(top, result);
32.862 - break;
32.863 -}
32.864 -
32.865 -case OP_MODULE:
32.866 -{
32.867 - top.sp++;
32.868 - top.sp[-1].module = top.fp->code()->module();
32.869 - break;
32.870 -}
32.871 -
32.872 -case OP_GETMODULE_FN:
32.873 -{
32.874 - top.sp[-1].fun = top.sp[-1].module->getFunction(READ_UINT32(top.pc));
32.875 - break;
32.876 -}
32.877 -
32.878 -case OP_GETGLOBAL_I:
32.879 -{
32.880 - unsigned slot = READ_UINT32(top.pc);
32.881 - top.sp++;
32.882 - top.sp[-1].i32 = top.fp->code()->module()->environment()->getInt32(slot);
32.883 - break;
32.884 -}
32.885 -
32.886 -case OP_GETGLOBAL_F:
32.887 -{
32.888 - unsigned slot = READ_UINT32(top.pc);
32.889 - top.sp++;
32.890 - top.sp[-1].f = top.fp->code()->module()->environment()->getFloat(slot);
32.891 - break;
32.892 -}
32.893 -
32.894 -case OP_GETGLOBAL_O:
32.895 -{
32.896 - unsigned slot = READ_UINT32(top.pc);
32.897 - top.sp++;
32.898 - top.sp[-1].obj = top.fp->code()->module()->environment()->getObject(slot);
32.899 - break;
32.900 -}
32.901 -
32.902 -case OP_SETGLOBAL_I:
32.903 -{
32.904 - unsigned slot = READ_UINT32(top.pc);
32.905 - top.fp->code()->module()->environment()->setInt32(slot, top.sp[-1].i32);
32.906 - break;
32.907 -}
32.908 -
32.909 -case OP_SETGLOBAL_F:
32.910 -{
32.911 - unsigned slot = READ_UINT32(top.pc);
32.912 - top.fp->code()->module()->environment()->setFloat(slot, top.sp[-1].f);
32.913 - break;
32.914 -}
32.915 -
32.916 -case OP_SETGLOBAL_O:
32.917 -{
32.918 - unsigned slot = READ_UINT32(top.pc);
32.919 - top.fp->code()->module()->environment()->setObject(slot, top.sp[-1].obj);
32.920 - break;
32.921 -}
32.922 -
32.923 -default:
32.924 - assert(false);
32.925 - return false;
32.926 -
32.927 - }
32.928 -
32.929 - top.pc += OpcodeInfo[op].length;
32.930 - }
32.931 -
32.932 -done:
32.933 - return true;
32.934 -
32.935 -error:
32.936 - // Unwind frames until we can continue.
32.937 - while (top.fp != entryFrame)
32.938 - zone->stack().popInlineFrame();
32.939 - return false;
32.940 -}
33.1 --- a/jitcraft/Interpreter.h Tue Jul 24 23:53:34 2012 -0700
33.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
33.3 @@ -1,29 +0,0 @@
33.4 -/*
33.5 - * Copyright (C) 2012 David Anderson
33.6 - *
33.7 - * This file is part of JITCraft.
33.8 - *
33.9 - * JITCraft is free software: you can redistribute it and/or modify it under
33.10 - * the terms of the GNU General Public License as published by the Free
33.11 - * Software Foundation, either version 3 of the License, or (at your option)
33.12 - * any later version.
33.13 - *
33.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
33.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
33.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
33.17 - *
33.18 - * You should have received a copy of the GNU General Public License along with
33.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
33.20 - */
33.21 -#ifndef _include_jc_interpreter_h_
33.22 -#define _include_jc_interpreter_h_
33.23 -
33.24 -#include "Stack.h"
33.25 -
33.26 -namespace ke {
33.27 -
33.28 -bool Interpret(Zone *zone, Frame *frame, LocalSlot *result);
33.29 -
33.30 -}
33.31 -
33.32 -#endif // _include_jc_interpreter_h_
34.1 --- a/jitcraft/Makefile.in Tue Jul 24 23:53:34 2012 -0700
34.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
34.3 @@ -1,96 +0,0 @@
34.4 -#vim: set ft=make:
34.5 -
34.6 -CXX=@CXX@
34.7 -CXXFLAGS=@CXXFLAGS@
34.8 -srcdir=@srcdir@
34.9 -VPATH=${srcdir}
34.10 -TOOLS=${srcdir}/../build
34.11 -CXXVENDOR=@CXXVENDOR@
34.12 -PLATFORM="@PLATFORM@"
34.13 -NULL =
34.14 -
34.15 -INCLUDES +=
34.16 -CXXFLAGS += $(INCLUDES)
34.17 -BASECXXFLAGS = -Wall -Werror -Wno-null-arithmetic -Wno-invalid-offsetof -g3 -O0
34.18 -
34.19 -CPPSRCS = \
34.20 - Array.cpp \
34.21 - BytecodeCompiler.cpp \
34.22 - BytecodeEmitter.cpp \
34.23 - CompileContext.cpp \
34.24 - Exception.cpp \
34.25 - FixedArray.cpp \
34.26 - Functions.cpp \
34.27 - Heap.cpp \
34.28 - Interpreter.cpp \
34.29 - Modules.cpp \
34.30 - NameBinding.cpp \
34.31 - Parser.cpp \
34.32 - Opcodes.cpp \
34.33 - PoolAllocator.cpp \
34.34 - Reference.cpp \
34.35 - RootScopes.cpp \
34.36 - Scanner.cpp \
34.37 - Scopes.cpp \
34.38 - SemanticAnalysis.cpp \
34.39 - Spaces.cpp \
34.40 - Stack.cpp \
34.41 - TypeManager.cpp \
34.42 - Types.cpp \
34.43 - Zone.cpp \
34.44 - main.cpp \
34.45 - $(NULL)
34.46 -
34.47 -ifeq ("darwin", $(PLATFORM))
34.48 -CPPSRCS += \
34.49 - Platform-Posix.cpp \
34.50 - $(NULL)
34.51 -endif
34.52 -ifeq ("linux", $(PLATFORM))
34.53 -CPPSRCS += \
34.54 - Platform-Posix.cpp \
34.55 - $(NULL)
34.56 -endif
34.57 -
34.58 -default: all
34.59 -
34.60 -OBJECTS := $(CPPSRCS:%.cpp=%.o)
34.61 -
34.62 -ifeq ($(CXXVENDOR), microsoft)
34.63 -
34.64 -CXXFLAGS += /DWIN32 /D_WINDOWS
34.65 -
34.66 -%.o: %.cpp
34.67 - $(CXX) $(CXXFLAGS) /Fo$@ /c /TP /nologo $<
34.68 -else
34.69 -
34.70 -%.o: %.cpp
34.71 - $(CXX) $(BASECXXFLAGS) $(CXXFLAGS) -c -o $@ -Wp,-MD,.deps/$(patsubst %.o,%.d,$@) $<
34.72 -
34.73 -endif
34.74 -
34.75 -#$(CXX) $(BASECXXFLAGS) $(CXXFLAGS) -c -o $@ -Wp,-MD,.deps/$(basename $(@F)).pp $<
34.76 -
34.77 -DEPEND_FILES := $(strip $(wildcard .deps/*.d))
34.78 -
34.79 -ifneq (,$(DEPEND_FILES))
34.80 -DEPEND_RESULTS = $(shell $(TOOLS)/mddepend.pl - $(DEPEND_FILES))
34.81 -$(eval $(DEPEND_RESULTS))
34.82 -endif
34.83 -
34.84 -all: foobar
34.85 -
34.86 -foobar: libfoobar.a main.o
34.87 - $(CXX) main.o libfoobar.a -lpthread -o foobar
34.88 -
34.89 -libfoobar.a: $(OBJECTS)
34.90 - $(AR) -crs libfoobar.a $(OBJECTS)
34.91 -
34.92 -FORCE:
34.93 -
34.94 -clean:
34.95 - rm -f .deps/*.d
34.96 - rm -f *.o
34.97 - rm -f libfoobar.a
34.98 - rm -f foobar
34.99 -
35.1 --- a/jitcraft/Messages.h Tue Jul 24 23:53:34 2012 -0700
35.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
35.3 @@ -1,48 +0,0 @@
35.4 -/*
35.5 - * Copyright (C) 2012 David Anderson
35.6 - *
35.7 - * This file is part of JITCraft.
35.8 - *
35.9 - * JITCraft is free software: you can redistribute it and/or modify it under
35.10 - * the terms of the GNU General Public License as published by the Free
35.11 - * Software Foundation, either version 3 of the License, or (at your option)
35.12 - * any later version.
35.13 - *
35.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
35.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
35.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
35.17 - *
35.18 - * You should have received a copy of the GNU General Public License along with
35.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
35.20 - */
35.21 -#ifndef _include_jitcraft_messages_h_
35.22 -#define _include_jitcraft_messages_h_
35.23 -
35.24 -namespace ke {
35.25 -
35.26 -enum MessageType
35.27 -{
35.28 - MessageType_SyntaxError,
35.29 - MessageType_TypeError,
35.30 - MessageType_SystemError
35.31 -};
35.32 -
35.33 -enum Message
35.34 -{
35.35 -#define MSG(Name, Type, String) Message_##Name,
35.36 -# include "Messages.tbl"
35.37 -#undef MSG
35.38 - MessageType_Total
35.39 -};
35.40 -
35.41 -struct MessageInfo
35.42 -{
35.43 - MessageType type;
35.44 - const char *format;
35.45 -};
35.46 -
35.47 -extern const MessageInfo Messages[];
35.48 -
35.49 -}
35.50 -
35.51 -#endif // _include_jitcraft_messages_h_
36.1 --- a/jitcraft/Messages.tbl Tue Jul 24 23:53:34 2012 -0700
36.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
36.3 @@ -1,62 +0,0 @@
36.4 -MSG(UnterminatedComment, SyntaxError, "unterminated comment")
36.5 -MSG(UnexpectedCharacter, SyntaxError, "unexpected character '%c' (code %02X)")
36.6 -MSG(UnterminatedString, SyntaxError, "unterminated string")
36.7 -MSG(UnknownEscapeCode, SyntaxError, "unknown escape code '%c'")
36.8 -MSG(ExpectedDigitForFloat, SyntaxError, "expected digit in float literal, got '%c'")
36.9 -MSG(WrongToken, SyntaxError, "expected token '%s', got '%s'")
36.10 -MSG(ExpectedExpression, SyntaxError, "expected expression, got '%s'")
36.11 -MSG(RedeclaredName, SyntaxError, "name '%s' was redeclared (previous at line %d, col %d)")
36.12 -MSG(ExpectedLValue, SyntaxError, "impossible assignment, expected l-value")
36.13 -MSG(MaximumArrayDepth, SyntaxError, "maximum array dimension depth exceeded")
36.14 -MSG(ArrayInitializerDepth, SyntaxError, "array declaration and initializer have different dimension counts")
36.15 -MSG(BadArraySize, SyntaxError, "array size must be positive")
36.16 -MSG(ArraySizeTooBig, SyntaxError, "array size is too big")
36.17 -MSG(EnumFieldNotConstant, SyntaxError, "enum fields must be constant integers")
36.18 -MSG(BreakOutsideLoop, SyntaxError, "break occurs outside any loop")
36.19 -MSG(ContinueOutsideLoop, SyntaxError, "continue occurs outside any loop")
36.20 -MSG(InvalidEnumName, SyntaxError, "invalid enumeration name")
36.21 -MSG(IndexMustBeInteger, SyntaxError, "array index must be integer")
36.22 -MSG(IndexBaseMustBeArray, SyntaxError, "cannot index into non-array")
36.23 -MSG(ArrayIsNotBoolean, SyntaxError, "cannot convert an array to boolean")
36.24 -MSG(CalleeNotFunction, SyntaxError, "callee is not a function")
36.25 -MSG(ArgumentCountMismatch, SyntaxError, "argument counts do not match")
36.26 -MSG(CannotAssignArrayToScalar, SyntaxError, "cannot coerce an array to a scalar")
36.27 -MSG(UnsupportedType, SyntaxError, "unsupported type")
36.28 -MSG(TagMismatch, SyntaxError, "tag mismatch (expected '%s', got '%s')")
36.29 -MSG(ArrayDimensionsMismatch, SyntaxError, "number of array dimensions does not match")
36.30 -MSG(ExpectedArray, SyntaxError, "expected array")
36.31 -MSG(ArrayDimensionSizeMismatch, SyntaxError, "array dimension sizes do not match (level %d)")
36.32 -MSG(ArrayDimensionNotInteger, SyntaxError, "array dimension size must be an integer expression")
36.33 -MSG(ArrayNotSupported, SyntaxError, "array declaration not yet supported")
36.34 -MSG(ArrayInitializerUnknown, SyntaxError, "array initialized size is not known")
36.35 -MSG(DynamicArrayHasInitializer, SyntaxError, "dynamic arrays cannot have initializers")
36.36 -MSG(ArraySizeNotSpecified, SyntaxError, "array size was not specified")
36.37 -MSG(ArraySizeCannotBeDetermined, SyntaxError, "array size cannot be determined from initializer")
36.38 -MSG(ArrayAssignmentTooBig, SyntaxError, "destination array is too small")
36.39 -MSG(CannotDeclareStringCell, SyntaxError, "cannot declare a String cell")
36.40 -MSG(BinaryTypeError, SyntaxError, "operator '%s' does not support types '%s' and '%s'")
36.41 -MSG(ArraySizeNotKnown, SyntaxError, "array size is not known")
36.42 -MSG(UnaryTypeError, SyntaxError, "operator '%s' does not support type '%s'")
36.43 -MSG(CantOpenFile, SyntaxError, "cannot open file")
36.44 -MSG(ErrorSeekingFile, SyntaxError, "error seeking file")
36.45 -MSG(ErrorReadingFile, SyntaxError, "error reading file")
36.46 -MSG(ExpectedGlobal, SyntaxError, "expected global variable or function")
36.47 -MSG(ForwardNotImplemented, SyntaxError, "forward '%s' not implemented")
36.48 -MSG(ForwardDeclareMismatches, SyntaxError, "declaration does not match original forward signature")
36.49 -MSG(ArrayCantBeReference, SyntaxError, "a parameter cannot be both an array and a reference")
36.50 -MSG(ArraySizeMustBeConstant, SyntaxError, "array size must be a constant integer")
36.51 -MSG(ReferenceIsConstant, SyntaxError, "cannot assign to a constant lvalue")
36.52 -MSG(MultiArrayInNative, SyntaxError, "multidimensional arrays cannot be passed to natives")
36.53 -MSG(InvalidVarArgs, SyntaxError, "varargs cannot be const or ref")
36.54 -MSG(VarArgsOutsideNative, SyntaxError, "variadic arguments can only be specified on natives")
36.55 -MSG(ArrayTooBig, TypeError, "array size is too large")
36.56 -MSG(IntegerDivideByZero, TypeError, "integer divide by zero")
36.57 -MSG(ArrayIndexOutOfBounds, TypeError, "array index %d is out of bounds [0, %d)")
36.58 -MSG(NativeNotBound, TypeError, "attempted to call unbound native \"%s\"")
36.59 -MSG(AllocationOverflow, SystemError, "allocation request overflowed")
36.60 -MSG(TooMuchRecursion, SystemError, "stack overflow: too much recursion")
36.61 -MSG(MissingReturnValue, SyntaxError, "tagged function must return a value")
36.62 -MSG(NotAllPathsReturnValue, SyntaxError, "not all paths through function return a value")
36.63 -MSG(UsedVoidReturn, SyntaxError, "return value expected, but function does not return a value")
36.64 -MSG(FunctionDoesNotReturnValue, SyntaxError, "cannot use the result of a function with no return value")
36.65 -MSG(IdentifierNotFound, SyntaxError, "identifier '%s' could not be found")
36.66 \ No newline at end of file
37.1 --- a/jitcraft/Modules.cpp Tue Jul 24 23:53:34 2012 -0700
37.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
37.3 @@ -1,43 +0,0 @@
37.4 -/*
37.5 - * Copyright (C) 2012 David Anderson
37.6 - *
37.7 - * This file is part of JITCraft.
37.8 - *
37.9 - * JITCraft is free software: you can redistribute it and/or modify it under
37.10 - * the terms of the GNU General Public License as published by the Free
37.11 - * Software Foundation, either version 3 of the License, or (at your option)
37.12 - * any later version.
37.13 - *
37.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
37.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
37.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
37.17 - *
37.18 - * You should have received a copy of the GNU General Public License along with
37.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
37.20 - */
37.21 -#include "Modules.h"
37.22 -#include "Zone.h"
37.23 -#include "Heap.h"
37.24 -#include "Heap-inl.h"
37.25 -
37.26 -using namespace ke;
37.27 -
37.28 -Module *
37.29 -Module::New(Zone *zone, unsigned nfunctions)
37.30 -{
37.31 - Local<Module> module(zone, Module::cast(zone->allocate(MapKind_Module, sizeof(Module), Heap::Tenure_Old)));
37.32 - if (!module)
37.33 - return NULL;
37.34 -
37.35 - Local<FixedArray> functions(zone, FixedArray::New(zone, nfunctions, Heap::Tenure_Old));
37.36 - if (!functions)
37.37 - return NULL;
37.38 -
37.39 - module->functions_ = functions;
37.40 - module->file_ = NULL;
37.41 - module->publics_ = NULL;
37.42 - module->natives_ = NULL;
37.43 - module->environment_ = NULL;
37.44 - module->nativeIdentity_ = NULL;
37.45 - return module;
37.46 -}
38.1 --- a/jitcraft/Modules.h Tue Jul 24 23:53:34 2012 -0700
38.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
38.3 @@ -1,119 +0,0 @@
38.4 -/*
38.5 - * Copyright (C) 2012 David Anderson
38.6 - *
38.7 - * This file is part of JITCraft.
38.8 - *
38.9 - * JITCraft is free software: you can redistribute it and/or modify it under
38.10 - * the terms of the GNU General Public License as published by the Free
38.11 - * Software Foundation, either version 3 of the License, or (at your option)
38.12 - * any later version.
38.13 - *
38.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
38.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
38.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
38.17 - *
38.18 - * You should have received a copy of the GNU General Public License along with
38.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
38.20 - */
38.21 -#ifndef _include_jc_module_h_
38.22 -#define _include_jc_module_h_
38.23 -
38.24 -#include "Heap.h"
38.25 -#include "Code.h"
38.26 -#include "Functions.h"
38.27 -
38.28 -namespace ke {
38.29 -
38.30 -class Environment;
38.31 -
38.32 -class Module : public Object
38.33 -{
38.34 - Barriered<FixedArray> functions_;
38.35 - Barriered<FixedArray> publics_;
38.36 - Barriered<FixedArray> natives_;
38.37 - Barriered<String> file_;
38.38 - Barriered<Environment> environment_;
38.39 - Barriered<Code> code_;
38.40 - void *nativeIdentity_;
38.41 -
38.42 - public:
38.43 - static Module *New(Zone *zone, unsigned nfunctions);
38.44 -
38.45 - Function *getFunction(size_t i) {
38.46 - return Function::cast(functions_->at(i));
38.47 - }
38.48 - void setFunction(Zone *zone, size_t i, Function *fun) {
38.49 - assert(!functions_->at(i));
38.50 - assert(fun);
38.51 - functions_->set(zone, i, fun);
38.52 - }
38.53 -
38.54 - FixedArray *publics() {
38.55 - return publics_;
38.56 - }
38.57 - FixedArray *natives() {
38.58 - return natives_;
38.59 - }
38.60 - String *file() {
38.61 - return file_;
38.62 - }
38.63 - Environment *environment() {
38.64 - return environment_;
38.65 - }
38.66 - Code *code() {
38.67 - return code_;
38.68 - }
38.69 -
38.70 - void setPublics(Handle<FixedArray> publics) {
38.71 - publics_ = publics;
38.72 - }
38.73 - void setNatives(Handle<FixedArray> natives) {
38.74 - natives_ = natives;
38.75 - }
38.76 - void setPath(Handle<String> path) {
38.77 - file_ = path;
38.78 - }
38.79 - void setEnvironment(Handle<Environment> environment) {
38.80 - environment_ = environment;
38.81 - }
38.82 - void setCode(Handle<Code> code) {
38.83 - code_ = code;
38.84 - }
38.85 -
38.86 - void *nativeIdentity() {
38.87 - return nativeIdentity_;
38.88 - }
38.89 - void setNativeIdentity(void *identity) {
38.90 - nativeIdentity_ = identity;
38.91 - }
38.92 -
38.93 - // Begin GC Descriptor.
38.94 - static inline size_t offsetOfFunctions() {
38.95 - return offsetof(Module, functions_);
38.96 - }
38.97 - static inline size_t offsetOfPublics() {
38.98 - return offsetof(Module, publics_);
38.99 - }
38.100 - static inline size_t offsetOfNatives() {
38.101 - return offsetof(Module, natives_);
38.102 - }
38.103 - static inline size_t offsetOfFile() {
38.104 - return offsetof(Module, file_);
38.105 - }
38.106 - static inline size_t offsetOfEnvironment() {
38.107 - return offsetof(Module, environment_);
38.108 - }
38.109 - static inline size_t offsetOfCode() {
38.110 - return offsetof(Module, code_);
38.111 - }
38.112 - // End GC Descriptor.
38.113 -
38.114 - static inline Module *cast(Object *obj) {
38.115 - assert(!obj || obj->is(MapKind_Module));
38.116 - return reinterpret_cast<Module *>(obj);
38.117 - }
38.118 -};
38.119 -
38.120 -}
38.121 -
38.122 -#endif // _include_jc_module_h_
39.1 --- a/jitcraft/NameBinding.cpp Tue Jul 24 23:53:34 2012 -0700
39.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
39.3 @@ -1,51 +0,0 @@
39.4 -/*
39.5 - * Copyright (C) 2012 David Anderson
39.6 - *
39.7 - * This file is part of JITCraft.
39.8 - *
39.9 - * JITCraft is free software: you can redistribute it and/or modify it under
39.10 - * the terms of the GNU General Public License as published by the Free
39.11 - * Software Foundation, either version 3 of the License, or (at your option)
39.12 - * any later version.
39.13 - *
39.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
39.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
39.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
39.17 - *
39.18 - * You should have received a copy of the GNU General Public License along with
39.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
39.20 - */
39.21 -#include "NameBinding.h"
39.22 -#include "Strings.h"
39.23 -#include "Zone.h"
39.24 -#include "Scopes.h"
39.25 -
39.26 -using namespace ke;
39.27 -
39.28 -BoundName::BoundName(Scope *scope, Handle<String> name, const SourcePosition &pos)
39.29 - : scope_(scope),
39.30 - name_(name),
39.31 - type_(NULL),
39.32 - pos_(pos)
39.33 -{
39.34 -}
39.35 -
39.36 -NamedFunction::NamedFunction(Scope *scope, Handle<String> name, const SourcePosition &pos,
39.37 - TokenKind token)
39.38 - : BoundName(scope, name, pos),
39.39 - token_(token),
39.40 - isVariadicNative_(false)
39.41 -{
39.42 -}
39.43 -
39.44 -Variable::Variable(Scope *scope, Handle<String> name, const SourcePosition &pos)
39.45 - : BoundName(scope, name, pos),
39.46 - location_(UNALLOCATED)
39.47 -{
39.48 -}
39.49 -
39.50 -bool
39.51 -Variable::needsHeapAllocation()
39.52 -{
39.53 - return scope()->kind() == Scope::GLOBAL;
39.54 -}
40.1 --- a/jitcraft/NameBinding.h Tue Jul 24 23:53:34 2012 -0700
40.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
40.3 @@ -1,211 +0,0 @@
40.4 -/*
40.5 - * Copyright (C) 2012 David Anderson
40.6 - *
40.7 - * This file is part of JITCraft.
40.8 - *
40.9 - * JITCraft is free software: you can redistribute it and/or modify it under
40.10 - * the terms of the GNU General Public License as published by the Free
40.11 - * Software Foundation, either version 3 of the License, or (at your option)
40.12 - * any later version.
40.13 - *
40.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
40.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
40.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
40.17 - *
40.18 - * You should have received a copy of the GNU General Public License along with
40.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
40.20 - */
40.21 -#ifndef _include_name_binding_h_
40.22 -#define _include_name_binding_h_
40.23 -
40.24 -#include "PoolAllocator.h"
40.25 -#include "Types.h"
40.26 -#include "Scanner.h"
40.27 -
40.28 -namespace ke {
40.29 -
40.30 -class Variable;
40.31 -class NamedFunction;
40.32 -class Scope;
40.33 -class Type;
40.34 -class NamedEnum;
40.35 -class NamedConstant;
40.36 -class String;
40.37 -
40.38 -class BoundName : public PoolObject
40.39 -{
40.40 - Scope *scope_;
40.41 - ScopedRoot<String> name_;
40.42 - ScopedRoot<Type> type_;
40.43 -
40.44 - protected:
40.45 - SourcePosition pos_;
40.46 -
40.47 - public:
40.48 - enum Kind {
40.49 - VARIABLE,
40.50 - FUNCTION,
40.51 - ENUM,
40.52 - CONSTANT
40.53 - };
40.54 -
40.55 - BoundName(Scope *scope, Handle<String> name, const SourcePosition &pos);
40.56 -
40.57 - virtual Kind kind() const = 0;
40.58 -
40.59 - String *name() const {
40.60 - return name_;
40.61 - }
40.62 - Scope *scope() const {
40.63 - return scope_;
40.64 - }
40.65 - Variable *toVariable() {
40.66 - assert(kind() == VARIABLE);
40.67 - return reinterpret_cast<Variable *>(this);
40.68 - }
40.69 - NamedFunction *toNamedFunction() {
40.70 - assert(kind() == FUNCTION);
40.71 - return reinterpret_cast<NamedFunction *>(this);
40.72 - }
40.73 - NamedConstant *toNamedConstant() {
40.74 - assert(kind() == CONSTANT);
40.75 - return reinterpret_cast<NamedConstant *>(this);
40.76 - }
40.77 - Type *type() const {
40.78 - return type_;
40.79 - }
40.80 - void setType(Handle<Type> type) {
40.81 - type_ = type;
40.82 - }
40.83 - const SourcePosition &pos() {
40.84 - return pos_;
40.85 - }
40.86 -};
40.87 -
40.88 -class NamedFunction : public BoundName
40.89 -{
40.90 - unsigned slot_;
40.91 - TokenKind token_;
40.92 - ScopedRoot<Type> forwardType_;
40.93 - bool isVariadicNative_;
40.94 -
40.95 - public:
40.96 - NamedFunction(Scope *scope, Handle<String> name, const SourcePosition &pos, TokenKind token);
40.97 -
40.98 - Kind kind() const {
40.99 - return FUNCTION;
40.100 - }
40.101 - void allocate(unsigned slot) {
40.102 - slot_ = slot;
40.103 - }
40.104 - bool isForward() const {
40.105 - return token_ == TOK_FORWARD;
40.106 - }
40.107 - bool isPublic() const {
40.108 - return token_ == TOK_PUBLIC;
40.109 - }
40.110 - bool isNative() const {
40.111 - return token_ == TOK_NATIVE;
40.112 - }
40.113 - void setForwardType(Handle<Type> type) {
40.114 - forwardType_ = type;
40.115 - }
40.116 - Type *forwardType() {
40.117 - return forwardType_;
40.118 - }
40.119 - void setImplemented(const SourcePosition &at) {
40.120 - token_ = TOK_PUBLIC;
40.121 - pos_ = at;
40.122 - }
40.123 - void markNativeVariadic() {
40.124 - assert(token_ == TOK_NATIVE);
40.125 - isVariadicNative_ = true;
40.126 - }
40.127 - bool isNativeVariadic() {
40.128 - assert(token_ == TOK_NATIVE);
40.129 - return isVariadicNative_;
40.130 - }
40.131 - unsigned slot() const {
40.132 - return slot_;
40.133 - }
40.134 -};
40.135 -
40.136 -class NamedEnum : public BoundName
40.137 -{
40.138 - public:
40.139 - NamedEnum(Scope *scope, Handle<String> name, const SourcePosition &pos)
40.140 - : BoundName(scope, name, pos)
40.141 - {
40.142 - }
40.143 -
40.144 - Kind kind() const {
40.145 - return ENUM;
40.146 - }
40.147 -};
40.148 -
40.149 -class NamedConstant : public BoundName
40.150 -{
40.151 - BoxedPrimitive value_;
40.152 - Type *type_;
40.153 -
40.154 - public:
40.155 - NamedConstant(Scope *scope, Handle<String> name, const SourcePosition &pos)
40.156 - : BoundName(scope, name, pos),
40.157 - type_(NULL)
40.158 - {
40.159 - }
40.160 -
40.161 - Kind kind() const {
40.162 - return CONSTANT;
40.163 - }
40.164 - void set(Type *type, const BoxedPrimitive &value) {
40.165 - value_ = value;
40.166 - type_ = type;
40.167 - }
40.168 - Type *type() const {
40.169 - return type_;
40.170 - }
40.171 - BoxedPrimitive value() const {
40.172 - return value_;
40.173 - }
40.174 -};
40.175 -
40.176 -class Variable : public BoundName
40.177 -{
40.178 - public:
40.179 - enum Location {
40.180 - UNALLOCATED,
40.181 - STACK,
40.182 - PARAMETER,
40.183 - ENVIRONMENT
40.184 - };
40.185 -
40.186 - Variable(Scope *scope, Handle<String> name, const SourcePosition &pos);
40.187 -
40.188 - Kind kind() const {
40.189 - return VARIABLE;
40.190 - }
40.191 - bool unallocated() const {
40.192 - return location() == UNALLOCATED;
40.193 - }
40.194 - void allocate(Location location, unsigned slot) {
40.195 - location_ = location;
40.196 - slot_ = slot;
40.197 - }
40.198 - Location location() const {
40.199 - return location_;
40.200 - }
40.201 - unsigned slot() const {
40.202 - assert(!unallocated());
40.203 - return slot_;
40.204 - }
40.205 - bool needsHeapAllocation();
40.206 -
40.207 - private:
40.208 - Location location_;
40.209 - unsigned slot_;
40.210 -};
40.211 -
40.212 -}
40.213 -
40.214 -#endif // _include_name_binding_h_
41.1 --- a/jitcraft/ObjectVisitor.h Tue Jul 24 23:53:34 2012 -0700
41.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
41.3 @@ -1,269 +0,0 @@
41.4 -/* vim: set ts=4 sw=4 tw=99 et:
41.5 - *
41.6 - * Copyright (C) 2012 David Anderson
41.7 - *
41.8 - * This file is part of JITCraft.
41.9 - *
41.10 - * JITCraft is free software: you can redistribute it and/or modify it under
41.11 - * the terms of the GNU General Public License as published by the Free
41.12 - * Software Foundation, either version 3 of the License, or (at your option)
41.13 - * any later version.
41.14 - *
41.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
41.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
41.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
41.18 - *
41.19 - * You should have received a copy of the GNU General Public License along with
41.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
41.21 - */
41.22 -#ifndef _include_jc_object_visitor_h_
41.23 -#define _include_jc_object_visitor_h_
41.24 -
41.25 -#include "Objects.h"
41.26 -#include "Types.h"
41.27 -#include "FixedArray.h"
41.28 -#include "Code.h"
41.29 -#include "Reference.h"
41.30 -#include "Modules.h"
41.31 -#include "Functions.h"
41.32 -#include "Array.h"
41.33 -#include "Strings.h"
41.34 -#include "Environments.h"
41.35 -
41.36 -namespace ke {
41.37 -
41.38 -// An ObjectVisitor is used for traversing object references in the heap. Since
41.39 -// this pattern must be lightning fast, we avoid virtual dispatch by forcing
41.40 -// visitors to compose themselves with the visiting logic.
41.41 -template <typename T>
41.42 -class ObjectVisitor : public T
41.43 -{
41.44 - private:
41.45 - void visitField(Object *obj, size_t offset) {
41.46 - this->visit(reinterpret_cast<Object **>(Address(obj) + offset));
41.47 - }
41.48 -
41.49 - size_t iterateType(Object *obj) {
41.50 - visitField(obj, Type::offsetOfContained());
41.51 - visitField(obj, Type::offsetOfReturnType());
41.52 - visitField(obj, Type::offsetOfParameters());
41.53 - visitField(obj, Type::offsetOfTag());
41.54 - return sizeof(Type);
41.55 - }
41.56 -
41.57 - size_t iterateFixedArray(FixedArray *array) {
41.58 - unsigned length = array->length();
41.59 - Object **ptr = reinterpret_cast<Object **>(array + 1);
41.60 - for (unsigned i = 0; i < length; i++)
41.61 - this->visit(ptr + i);
41.62 - return FixedArray::SizeFor(length);
41.63 - }
41.64 -
41.65 - size_t iterateByteArray(ByteArray *array) {
41.66 - return ByteArray::SizeFor(array->length());
41.67 - }
41.68 -
41.69 - size_t iterateCode(Object *obj) {
41.70 - visitField(obj, Code::offsetOfModule());
41.71 - visitField(obj, Code::offsetOfBytecode());
41.72 - visitField(obj, Code::offsetOfLocals());
41.73 - visitField(obj, Code::offsetOfObjects());
41.74 - visitField(obj, Code::offsetOfSafepoints());
41.75 - visitField(obj, Code::offsetOfSourceMap());
41.76 - return sizeof(Code);
41.77 - }
41.78 -
41.79 - size_t iterateReference(Object *obj) {
41.80 - visitField(obj, Reference::offsetOfBase());
41.81 - return sizeof(Reference);
41.82 - }
41.83 -
41.84 - size_t iterateModule(Object *obj) {
41.85 - visitField(obj, Module::offsetOfFunctions());
41.86 - visitField(obj, Module::offsetOfPublics());
41.87 - visitField(obj, Module::offsetOfNatives());
41.88 - visitField(obj, Module::offsetOfFile());
41.89 - visitField(obj, Module::offsetOfEnvironment());
41.90 - visitField(obj, Module::offsetOfCode());
41.91 - return sizeof(Module);
41.92 - }
41.93 -
41.94 - size_t iterateFunction(Object *obj) {
41.95 - visitField(obj, Function::offsetOfCode());
41.96 - visitField(obj, Function::offsetOfType());
41.97 - visitField(obj, Function::offsetOfName());
41.98 - return sizeof(Function);
41.99 - }
41.100 -
41.101 - size_t iterateNative(Object *obj) {
41.102 - visitField(obj, Native::offsetOfType());
41.103 - visitField(obj, Native::offsetOfName());
41.104 - return sizeof(Native);
41.105 - }
41.106 -
41.107 - size_t iterateString(Object *obj) {
41.108 - return String::SizeFor(String::cast(obj)->length());
41.109 - }
41.110 -
41.111 - size_t iterateArray(Array *array, ArrayMap *map) {
41.112 - assert(map->type()->isArray());
41.113 - if (map->contained()) {
41.114 - unsigned length = array->nelements();
41.115 - Object **vec = array->objVec();
41.116 - for (unsigned i = 0; i < length; i++)
41.117 - this->visit(vec + i);
41.118 - }
41.119 - return Array::SizeOf(array);
41.120 - }
41.121 -
41.122 - size_t iterateArrayMap(ArrayMap *map) {
41.123 - visitField(map, ArrayMap::offsetOfType());
41.124 - visitField(map, ArrayMap::offsetOfContained());
41.125 - return sizeof(ArrayMap);
41.126 - }
41.127 -
41.128 - size_t iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray *env) {
41.129 - unsigned length = env->length();
41.130 - EnvironmentSlotDescriptor *desc = env->slots();
41.131 - for (unsigned i = 0; i < length; i++)
41.132 - this->visit(desc->type.addr());
41.133 - return env->size();
41.134 - }
41.135 -
41.136 - size_t iterateEnvironmentMap(EnvironmentMap *map) {
41.137 - visitField(map, EnvironmentMap::offsetOfSlots());
41.138 - return map->size();
41.139 - }
41.140 -
41.141 - size_t iterateEnvironment(Environment *env) {
41.142 - EnvironmentMap *map = env->map();
41.143 - const unsigned *offsets = map->traceOffsets();
41.144 - unsigned noffsets = map->traceOffsetCount();
41.145 - for (unsigned i = 0; i < noffsets; i++)
41.146 - visitField(env, Environment::offsetOfSlotOffset(offsets[i]));
41.147 - return env->size();
41.148 - }
41.149 -
41.150 - public:
41.151 - size_t iterate(Object *obj) {
41.152 - visitField(obj, Object::offsetOfMap());
41.153 - return iterate(obj, obj->map());
41.154 - }
41.155 -
41.156 - size_t iterate(Object *obj, Map *map) {
41.157 - switch (map->kind()) {
41.158 - case MapKind_Type:
41.159 - return iterateType(obj);
41.160 -
41.161 - case MapKind_FixedArray:
41.162 - return iterateFixedArray(FixedArray::cast(obj));
41.163 -
41.164 - case MapKind_ByteArray:
41.165 - return iterateByteArray(ByteArray::cast(obj));
41.166 -
41.167 - case MapKind_Code:
41.168 - return iterateCode(obj);
41.169 -
41.170 - case MapKind_Reference:
41.171 - return iterateReference(obj);
41.172 -
41.173 - case MapKind_Module:
41.174 - return iterateModule(obj);
41.175 -
41.176 - case MapKind_Function:
41.177 - return iterateFunction(obj);
41.178 -
41.179 - case MapKind_String:
41.180 - return iterateString(obj);
41.181 -
41.182 - case MapKind_Array:
41.183 - return Align(iterateArray(Array::cast(obj), ArrayMap::cast(map)), kObjectAlignment);
41.184 -
41.185 - case MapKind_EnvironmentSlotDescriptorArray:
41.186 - return iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray::cast(obj));
41.187 -
41.188 - case MapKind_Environment:
41.189 - return iterateEnvironment(Environment::cast(obj));
41.190 -
41.191 - case MapKind_Native:
41.192 - return iterateNative(obj);
41.193 -
41.194 - case MapKind_MetaArray:
41.195 - return iterateArrayMap(ArrayMap::cast(obj));
41.196 -
41.197 - case MapKind_MetaEnvironment:
41.198 - return iterateEnvironmentMap(EnvironmentMap::cast(obj));
41.199 -
41.200 - default:
41.201 - assert(map->kind() == MapKind_Meta);
41.202 - return sizeof(Map);
41.203 - }
41.204 - }
41.205 -};
41.206 -
41.207 -static inline size_t
41.208 -SizeOfObject(Object *obj, Map *map)
41.209 -{
41.210 - switch (map->kind()) {
41.211 - case MapKind_Type:
41.212 - return sizeof(Type);
41.213 -
41.214 - case MapKind_FixedArray:
41.215 - return FixedArray::SizeFor(FixedArray::cast(obj)->length());
41.216 -
41.217 - case MapKind_ByteArray:
41.218 - return ByteArray::SizeFor(ByteArray::cast(obj)->length());
41.219 -
41.220 - case MapKind_Code:
41.221 - return sizeof(Code);
41.222 -
41.223 - case MapKind_Reference:
41.224 - return sizeof(Reference);
41.225 -
41.226 - case MapKind_Module:
41.227 - return sizeof(Module);
41.228 -
41.229 - case MapKind_Function:
41.230 - return sizeof(Function);
41.231 -
41.232 - case MapKind_String:
41.233 - return String::SizeFor(String::cast(obj)->length());
41.234 -
41.235 - case MapKind_Native:
41.236 - return sizeof(Native);
41.237 -
41.238 - case MapKind_Array:
41.239 - return Align(Array::SizeOf(Array::cast(obj)), kObjectAlignment);
41.240 -
41.241 - case MapKind_EnvironmentSlotDescriptorArray:
41.242 - return EnvironmentSlotDescriptorArray::cast(obj)->size();
41.243 -
41.244 - case MapKind_Environment:
41.245 - return Environment::cast(obj)->size();
41.246 -
41.247 - case MapKind_MetaArray:
41.248 - return sizeof(ArrayMap);
41.249 -
41.250 - case MapKind_MetaEnvironment:
41.251 - return EnvironmentMap::cast(obj)->size();
41.252 -
41.253 - case MapKind_FreeRegion:
41.254 - return *reinterpret_cast<size_t *>(reinterpret_cast<Address>(obj + 1));
41.255 -
41.256 - default:
41.257 - assert(map->kind() == MapKind_Meta);
41.258 - return sizeof(Map);
41.259 - }
41.260 -}
41.261 -
41.262 -class ObjectSizeEvaluator
41.263 -{
41.264 - public:
41.265 - size_t operator()(Object *obj, Map *map) {
41.266 - return SizeOfObject(obj, map);
41.267 - }
41.268 -};
41.269 -
41.270 -}
41.271 -
41.272 -#endif // _include_jc_object_visitor_h_
42.1 --- a/jitcraft/Objects.h Tue Jul 24 23:53:34 2012 -0700
42.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
42.3 @@ -1,119 +0,0 @@
42.4 -/* vim: set ts=4 sw=4 tw=99 et:
42.5 - *
42.6 - * Copyright (C) 2012 David Anderson
42.7 - *
42.8 - * This file is part of JITCraft.
42.9 - *
42.10 - * JITCraft is free software: you can redistribute it and/or modify it under
42.11 - * the terms of the GNU General Public License as published by the Free
42.12 - * Software Foundation, either version 3 of the License, or (at your option)
42.13 - * any later version.
42.14 - *
42.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
42.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
42.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
42.18 - *
42.19 - * You should have received a copy of the GNU General Public License along with
42.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
42.21 - */
42.22 -#ifndef _include_jitcraft_objects_h_
42.23 -#define _include_jitcraft_objects_h_
42.24 -
42.25 -#include "Utility.h"
42.26 -#include "Spaces.h"
42.27 -#include "Barriers.h"
42.28 -
42.29 -namespace ke {
42.30 -
42.31 -class Zone;
42.32 -
42.33 -// Garbage-collection objects require a header to describe their layout. This
42.34 -// header is called a "map". The different kinds of maps are enumerated below.
42.35 -class Map;
42.36 -
42.37 -enum MapKind
42.38 -{
42.39 - // Represents Type objects.
42.40 - MapKind_Type,
42.41 -
42.42 - // Represents basic data structures. When adding to this, don't forget
42.43 - // to update Zone::initialize(), or you'll get a NULL crash trying to
42.44 - // allocate, since these maps are cached.
42.45 - MapKind_FixedArray,
42.46 - MapKind_ByteArray,
42.47 - MapKind_Code,
42.48 - MapKind_Reference,
42.49 - MapKind_Module,
42.50 - MapKind_Function,
42.51 - MapKind_String,
42.52 - MapKind_Native,
42.53 - MapKind_FreeRegion, // Special map denoting freed space.
42.54 - MapKind_EnvironmentSlotDescriptorArray,
42.55 - MapKind_Environment,
42.56 -
42.57 - // Used to represent Arrays. This does not have a canonical map.
42.58 - MapKind_Array,
42.59 -
42.60 - // These represent special Map subclasses that require special tracing.
42.61 - MapKinds_Special,
42.62 - MapKind_Meta, // (default map class)
42.63 - MapKind_MetaArray, // ArrayMap instances
42.64 - MapKind_MetaEnvironment, // EnvironmentMap instances
42.65 - MapKinds_EndSpecial,
42.66 -
42.67 - MapKinds_Total
42.68 -};
42.69 -
42.70 -// All garbage collected objects must inherit from GCObject. Note that using
42.71 -// virtual functions is illegal, as the |map| field would be displaced.
42.72 -class Object
42.73 -{
42.74 - Barriered<Map> map_;
42.75 -
42.76 - public:
42.77 - void init(Map *map) {
42.78 - map_ = map;
42.79 - }
42.80 -
42.81 - Map *map() {
42.82 - return map_;
42.83 - }
42.84 - inline bool is(MapKind map);
42.85 -
42.86 - inline void write(Zone *zone, Object **ptr, Object *value);
42.87 -
42.88 - static inline size_t offsetOfMap() {
42.89 - return offsetof(Object, map_);
42.90 - }
42.91 -};
42.92 -
42.93 -// Maps describe the layout of GCObjects. Every GCObject requires a map.
42.94 -class Map : public Object
42.95 -{
42.96 - MapKind kind_;
42.97 -
42.98 - public:
42.99 - void setKind(MapKind kind) {
42.100 - kind_ = kind;
42.101 - }
42.102 - MapKind kind() {
42.103 - return kind_;
42.104 - }
42.105 -
42.106 - static inline Map *cast(Object *obj) {
42.107 - // Note that ArrayMap is a map, but a special one: since it is non-
42.108 - assert(obj->map()->kind() > MapKinds_Special &&
42.109 - obj->map()->kind() < MapKinds_EndSpecial);
42.110 - return reinterpret_cast<Map *>(obj);
42.111 - }
42.112 -};
42.113 -
42.114 -inline bool
42.115 -Object::is(MapKind kind)
42.116 -{
42.117 - return map()->kind() == kind;
42.118 -}
42.119 -
42.120 -}
42.121 -
42.122 -#endif //_include_jitcraft_objects_h_
43.1 --- a/jitcraft/Opcodes.cpp Tue Jul 24 23:53:34 2012 -0700
43.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
43.3 @@ -1,311 +0,0 @@
43.4 -/* vim: set ts=4 sw=4 tw=99 et:
43.5 - *
43.6 - * Copyright (C) 2012 David Anderson
43.7 - *
43.8 - * This file is part of JITCraft.
43.9 - *
43.10 - * JITCraft is free software: you can redistribute it and/or modify it under
43.11 - * the terms of the GNU General Public License as published by the Free
43.12 - * Software Foundation, either version 3 of the License, or (at your option)
43.13 - * any later version.
43.14 - *
43.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
43.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
43.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
43.18 - *
43.19 - * You should have received a copy of the GNU General Public License along with
43.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
43.21 - */
43.22 -#include <stdlib.h>
43.23 -#include "Opcodes.h"
43.24 -#include "Utility.h"
43.25 -#include "Code.h"
43.26 -#include "Zone.h"
43.27 -#include "Array.h"
43.28 -#include "Strings.h"
43.29 -#include "CompactBuffer.h"
43.30 -#include "Heap-inl.h"
43.31 -
43.32 -using namespace ke;
43.33 -
43.34 -OpInfo ke::OpcodeInfo[] =
43.35 -{
43.36 -#define OPDEF(name, number, text, length, uses, defs) \
43.37 - {text, length, uses, defs},
43.38 -#include "Opcodes.tbl"
43.39 -#undef OPDEF
43.40 -};
43.41 -
43.42 -Code *
43.43 -Code::New(Zone *zone, Handle<ByteArray> bytecode, Handle<FixedArray> locals,
43.44 - Handle<FixedArray> objects, unsigned maxStackDepth, Handle<Module> module,
43.45 - Handle<ByteArray> safepoints, Handle<ByteArray> sourcemap,
43.46 - unsigned lineNumber)
43.47 -{
43.48 - Local<Code> code(zone, Code::cast(zone->allocate(MapKind_Code, sizeof(Code), Heap::Tenure_Old)));
43.49 - if (!code)
43.50 - return NULL;
43.51 -
43.52 - code->bytecode_ = bytecode;
43.53 - code->locals_ = locals;
43.54 - code->objects_ = objects;
43.55 - code->maxStackDepth_ = maxStackDepth;
43.56 - code->module_ = module;
43.57 - code->safepoints_ = safepoints;
43.58 - code->sourcemap_ = sourcemap;
43.59 - code->lineNumber_ = lineNumber;
43.60 - return code;
43.61 -}
43.62 -
43.63 -static int
43.64 -CompareSafepoints(const void *a, const void *b)
43.65 -{
43.66 - const unsigned *sa = reinterpret_cast<const unsigned *>(a);
43.67 - const unsigned *sb = reinterpret_cast<const unsigned *>(b);
43.68 - if (*sa > *sb)
43.69 - return 1;
43.70 - if (*sa == *sb)
43.71 - return 0;
43.72 - return -1;
43.73 -}
43.74 -
43.75 -uint8 *
43.76 -Code::safepointAt(unsigned pcOffset)
43.77 -{
43.78 - // Only specific opcodes may have safepoints. Asking for a safepoint at
43.79 - // any other position indicates a failure to mark that position as a
43.80 - // safepoint, which is a bug.
43.81 - Opcode op = Opcode(*(start() + pcOffset));
43.82 - assert(op == OP_CALL || op == OP_NEWARRAY || op == OP_VARREF_LIFO ||
43.83 - op == OP_ARGREF_LIFO || op == OP_SLOTREF_LIFO || op == OP_ARRAYREF_LIFO ||
43.84 - op == OP_ARRAYCOPY);
43.85 -
43.86 - if (!safepoints_)
43.87 - return NULL;
43.88 -
43.89 - size_t bytesPerSafepoint = BytesPerSafepoint(maxStackDepth());
43.90 - assert(!(safepoints_->length() % bytesPerSafepoint));
43.91 -
43.92 - size_t count = safepoints_->length() / bytesPerSafepoint;
43.93 -
43.94 - void *result = bsearch(&pcOffset,
43.95 - safepoints_->raw(),
43.96 - count,
43.97 - bytesPerSafepoint,
43.98 - CompareSafepoints);
43.99 -
43.100 - if (!result)
43.101 - return NULL;
43.102 -
43.103 - assert(*reinterpret_cast<unsigned *>(result) == pcOffset);
43.104 -
43.105 - return Address(result) + sizeof(unsigned);
43.106 -}
43.107 -
43.108 -SourcePosition
43.109 -Code::pcToSource(unsigned pc)
43.110 -{
43.111 - assert(pc < bytecode_->length());
43.112 -
43.113 - CompactBufferReader reader(sourcemap_->raw(), sourcemap_->raw() + sourcemap_->length());
43.114 -
43.115 - unsigned line = 1;
43.116 - unsigned col = 0;
43.117 - unsigned curPc = 0;
43.118 - while (!reader.done()) {
43.119 - curPc += reader.readUint32();
43.120 - if (curPc > pc)
43.121 - break;
43.122 -
43.123 - line = reader.readUint32();
43.124 - col = reader.readUint32();
43.125 - }
43.126 -
43.127 - return SourcePosition(lineNumber_ + line, col);
43.128 -}
43.129 -
43.130 -// All jumps must be the same length.
43.131 -STATIC_ASSERT(OP_JL_LENGTH == OP_JUMP_LENGTH);
43.132 -STATIC_ASSERT(OP_JLE_LENGTH == OP_JUMP_LENGTH);
43.133 -STATIC_ASSERT(OP_JG_LENGTH == OP_JUMP_LENGTH);
43.134 -STATIC_ASSERT(OP_JGE_LENGTH == OP_JUMP_LENGTH);
43.135 -STATIC_ASSERT(OP_JEQ_LENGTH == OP_JUMP_LENGTH);
43.136 -STATIC_ASSERT(OP_JNE_LENGTH == OP_JUMP_LENGTH);
43.137 -STATIC_ASSERT(OP_JT_LENGTH == OP_JUMP_LENGTH);
43.138 -STATIC_ASSERT(OP_JF_LENGTH == OP_JUMP_LENGTH);
43.139 -
43.140 -void
43.141 -ke::Disassemble(Code *code, FILE *fp)
43.142 -{
43.143 - bytecode *pc = code->start();
43.144 - for (;;) {
43.145 - Opcode op = Opcode(*pc);
43.146 -
43.147 - fprintf(fp, "%-4d %s ", int(pc - code->start()), OpcodeInfo[op].name);
43.148 -
43.149 - switch (op) {
43.150 - case OP_NOP:
43.151 - case OP_RETURN:
43.152 - case OP_RETURNVOID:
43.153 - case OP_ADD:
43.154 - case OP_SUB:
43.155 - case OP_MUL:
43.156 - case OP_DIV:
43.157 - case OP_ADD_F:
43.158 - case OP_SUB_F:
43.159 - case OP_MUL_F:
43.160 - case OP_DIV_F:
43.161 - case OP_CVT_I2F:
43.162 - case OP_POP:
43.163 - case OP_GETARRAY_I:
43.164 - case OP_SETARRAY_I:
43.165 - case OP_GETARRAY_F:
43.166 - case OP_SETARRAY_F:
43.167 - case OP_GETARRAY_C:
43.168 - case OP_SETARRAY_C:
43.169 - case OP_GETARRAY_O:
43.170 - case OP_BOUNDS:
43.171 - case OP_SHL:
43.172 - case OP_SHR:
43.173 - case OP_USHR:
43.174 - case OP_BITAND:
43.175 - case OP_BITOR:
43.176 - case OP_BITXOR:
43.177 - case OP_GETREF_I:
43.178 - case OP_SETREF_I:
43.179 - case OP_GETREF_F:
43.180 - case OP_SETREF_F:
43.181 - case OP_SLOTREF_LIFO:
43.182 - case OP_ARRAYREF_LIFO:
43.183 - case OP_ARRAYCOPY:
43.184 - case OP_DUP:
43.185 - case OP_DUP2:
43.186 - case OP_SWAP:
43.187 - case OP_ROLL3:
43.188 - case OP_PICK2:
43.189 - case OP_PICK3:
43.190 - case OP_CALL:
43.191 - case OP_MODULE:
43.192 - case OP_LT:
43.193 - case OP_LE:
43.194 - case OP_GE:
43.195 - case OP_GT:
43.196 - case OP_EQ:
43.197 - case OP_NE:
43.198 - case OP_LT_F:
43.199 - case OP_LE_F:
43.200 - case OP_GE_F:
43.201 - case OP_GT_F:
43.202 - case OP_EQ_F:
43.203 - case OP_NE_F:
43.204 - case OP_BITNOT:
43.205 - case OP_NOT:
43.206 - case OP_NOT_F:
43.207 - case OP_NEG:
43.208 - case OP_NEG_F:
43.209 - case OP_MOD:
43.210 - break;
43.211 -
43.212 - case OP_STOP:
43.213 - fprintf(fp, "\n");
43.214 - break;
43.215 -
43.216 - case OP_INT:
43.217 - fprintf(fp, "%d", READ_INT32(pc));
43.218 - break;
43.219 -
43.220 - case OP_FLOAT:
43.221 - fprintf(fp, "%f", READ_FLOAT(pc));
43.222 - break;
43.223 -
43.224 - case OP_JL:
43.225 - case OP_JLE:
43.226 - case OP_JG:
43.227 - case OP_JGE:
43.228 - case OP_JEQ:
43.229 - case OP_JNE:
43.230 - case OP_JT:
43.231 - case OP_JF:
43.232 - case OP_JL_F:
43.233 - case OP_JLE_F:
43.234 - case OP_JG_F:
43.235 - case OP_JGE_F:
43.236 - case OP_JEQ_F:
43.237 - case OP_JNE_F:
43.238 - case OP_JT_F:
43.239 - case OP_JF_F:
43.240 - case OP_JUMP:
43.241 - fprintf(fp, "%u (%+d)", unsigned((pc + READ_INT32(pc)) - code->start()), READ_INT32(pc));
43.242 - break;
43.243 -
43.244 - case OP_NEWARRAY:
43.245 - {
43.246 - Heap::Tenure tenure = (Heap::Tenure)pc[1];
43.247 - ArrayMap *map = ArrayMap::cast(code->map(READ_UINT32(pc + 1)));
43.248 - fprintf(fp, "%s:", map->type()->innermost()->tag()
43.249 - ? map->type()->innermost()->tag()->chars()
43.250 - : "_");
43.251 - for (; map; map = map->contained()) {
43.252 - Type *type = map->type();
43.253 - fprintf(fp, "[%d]", type->elements());
43.254 - }
43.255 - if (tenure == Heap::Tenure_Stack)
43.256 - fprintf(fp, " ; lifo");
43.257 - else if (tenure == Heap::Tenure_Old)
43.258 - fprintf(fp, " ; pretenured");
43.259 - break;
43.260 - }
43.261 -
43.262 - case OP_GETLOCAL:
43.263 - case OP_SETLOCAL:
43.264 - case OP_GETARG:
43.265 - case OP_SETARG:
43.266 - case OP_SAVELIFO:
43.267 - case OP_UNWINDLIFO:
43.268 - case OP_VARREF_LIFO:
43.269 - case OP_ARGREF_LIFO:
43.270 - case OP_OBJECT:
43.271 - case OP_GETMODULE_FN:
43.272 - case OP_GETGLOBAL_I:
43.273 - case OP_GETGLOBAL_F:
43.274 - case OP_GETGLOBAL_O:
43.275 - case OP_SETGLOBAL_I:
43.276 - case OP_SETGLOBAL_F:
43.277 - case OP_SETGLOBAL_O:
43.278 - fprintf(fp, "%u", READ_UINT32(pc));
43.279 - break;
43.280 -
43.281 - case OP_CALLNATIVE:
43.282 - fprintf(fp, "%u %u", READ_UINT32(pc), READ_UINT32(pc + 4));
43.283 - break;
43.284 -
43.285 - default:
43.286 - // Unknown opcode!
43.287 - assert(false);
43.288 - return;
43.289 - }
43.290 -
43.291 - if (op == OP_STOP)
43.292 - break;
43.293 -
43.294 - fprintf(fp, "\n");
43.295 - pc += OpcodeInfo[op].length;
43.296 - assert(pc < code->start() + code->length());
43.297 - }
43.298 -
43.299 - fprintf(fp, "\nSafepoints:\n");
43.300 - ByteArray *safepoints = code->safepoints();
43.301 - if (safepoints) {
43.302 - size_t nsafepoints = safepoints->length() / Code::BytesPerSafepoint(code->maxStackDepth());
43.303 - for (size_t i = 0; i < nsafepoints; i++) {
43.304 - Address address = safepoints->raw() + Code::BytesPerSafepoint(code->maxStackDepth()) * i;
43.305 - fprintf(fp, "%4d: ", *reinterpret_cast<unsigned *>(address));
43.306 - unsigned char *bits = (unsigned char *)(address + sizeof(unsigned));
43.307 - for (unsigned j = 0; j < code->maxStackDepth(); j++) {
43.308 - if (bits[j / 8] & (1 << (j % 8)))
43.309 - fprintf(fp, "%d ", j);
43.310 - }
43.311 - fprintf(fp, "\n");
43.312 - }
43.313 - }
43.314 -}
44.1 --- a/jitcraft/Opcodes.h Tue Jul 24 23:53:34 2012 -0700
44.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
44.3 @@ -1,94 +0,0 @@
44.4 -/*
44.5 - * Copyright (C) 2012 David Anderson
44.6 - *
44.7 - * This file is part of JITCraft.
44.8 - *
44.9 - * JITCraft is free software: you can redistribute it and/or modify it under
44.10 - * the terms of the GNU General Public License as published by the Free
44.11 - * Software Foundation, either version 3 of the License, or (at your option)
44.12 - * any later version.
44.13 - *
44.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
44.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
44.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
44.17 - *
44.18 - * You should have received a copy of the GNU General Public License along with
44.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
44.20 - */
44.21 -#ifndef _include_opcodes_h_
44.22 -#define _include_opcodes_h_
44.23 -
44.24 -#include <assert.h>
44.25 -#include <stdio.h>
44.26 -
44.27 -namespace ke {
44.28 -
44.29 -enum Opcode
44.30 -{
44.31 -#define OPDEF(name, number, text, length, uses, defs) \
44.32 - name = number,
44.33 -#include "Opcodes.tbl"
44.34 -#undef OPDEF
44.35 - OPCODES_TOTAL
44.36 -};
44.37 -
44.38 -#define OPDEF(name, number, text, length, uses, defs) \
44.39 -static const unsigned name##_LENGTH = length;
44.40 -#include "Opcodes.tbl"
44.41 -#undef OPDEF
44.42 -
44.43 -struct OpInfo
44.44 -{
44.45 - const char *name;
44.46 - int length;
44.47 - int nuses;
44.48 - int ndefs;
44.49 -};
44.50 -
44.51 -typedef unsigned char bytecode;
44.52 -
44.53 -extern OpInfo OpcodeInfo[];
44.54 -
44.55 -static inline Opcode
44.56 -Invert(Opcode op)
44.57 -{
44.58 - switch (op) {
44.59 - case OP_JEQ:
44.60 - return OP_JNE;
44.61 - case OP_JNE:
44.62 - return OP_JEQ;
44.63 - case OP_JG:
44.64 - return OP_JLE;
44.65 - case OP_JGE:
44.66 - return OP_JL;
44.67 - case OP_JL:
44.68 - return OP_JGE;
44.69 - default:
44.70 - assert(op == OP_JLE);
44.71 - return OP_JG;
44.72 - }
44.73 -}
44.74 -
44.75 -static inline int
44.76 -READ_INT32(bytecode *pc)
44.77 -{
44.78 - return *reinterpret_cast<int *>(pc + 1);
44.79 -}
44.80 -static inline unsigned
44.81 -READ_UINT32(bytecode *pc)
44.82 -{
44.83 - return *reinterpret_cast<unsigned *>(pc + 1);
44.84 -}
44.85 -static inline float
44.86 -READ_FLOAT(bytecode *pc)
44.87 -{
44.88 - return *reinterpret_cast<float *>(pc + 1);
44.89 -}
44.90 -
44.91 -class Code;
44.92 -
44.93 -void Disassemble(Code *code, FILE *fp);
44.94 -
44.95 -}
44.96 -
44.97 -#endif // _include_opcodes_h_
45.1 --- a/jitcraft/Opcodes.tbl Tue Jul 24 23:53:34 2012 -0700
45.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
45.3 @@ -1,246 +0,0 @@
45.4 -/* vim: set ts=4 sw=4 tw=99 et:
45.5 - *
45.6 - * Copyright (C) 2012 David Anderson
45.7 - *
45.8 - * This file is part of JITCraft.
45.9 - *
45.10 - * JITCraft is free software: you can redistribute it and/or modify it under
45.11 - * the terms of the GNU General Public License as published by the Free
45.12 - * Software Foundation, either version 3 of the License, or (at your option)
45.13 - * any later version.
45.14 - *
45.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
45.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
45.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
45.18 - *
45.19 - * You should have received a copy of the GNU General Public License along with
45.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
45.21 - */
45.22 -// Opcode macros:
45.23 -// NAME NUMBER TEXT LENGTH USES DEFS
45.24 -//
45.25 -// Type suffixes:
45.26 -// I = 32-bit integer
45.27 -// F = 32-bit IEEE-754 float
45.28 -// O = object reference
45.29 -
45.30 -// No operation.
45.31 -OPDEF(OP_NOP, 0, "nop", 1, 0, 0)
45.32 -
45.33 -// Pushes a signed integer immediate onto the stack.
45.34 -OPDEF(OP_INT, 1, "int", 5, 0, 1)
45.35 -
45.36 -// Returns from the current routine, propagating the value at the top of the
45.37 -// stack to the caller.
45.38 -OPDEF(OP_RETURN, 2, "return", 1, 1, 0)
45.39 -
45.40 -// Stack transitions for these comparison ops:
45.41 -// rhs = pop()
45.42 -// lhs = pop()
45.43 -// if (lhs COMPARE rhs)
45.44 -// goto target (immediate, relative to the beginning of the jump instruction)
45.45 -OPDEF(OP_JL, 3, "jl", 5, 2, 0)
45.46 -OPDEF(OP_JLE, 4, "jle", 5, 2, 0)
45.47 -OPDEF(OP_JG, 5, "jg", 5, 2, 0)
45.48 -OPDEF(OP_JGE, 6, "jge", 5, 2, 0)
45.49 -OPDEF(OP_JEQ, 7, "jeq", 5, 2, 0)
45.50 -OPDEF(OP_JNE, 8, "jne", 5, 2, 0)
45.51 -
45.52 -// value = pop()
45.53 -// if (value == [true, false])
45.54 -// goto target
45.55 -OPDEF(OP_JT, 9, "jt", 5, 1, 0)
45.56 -OPDEF(OP_JF, 10, "jf", 5, 1, 0)
45.57 -
45.58 -OPDEF(OP_JL_F, 11, "jl.f", 5, 2, 0)
45.59 -OPDEF(OP_JLE_F, 12, "jle.f", 5, 2, 0)
45.60 -OPDEF(OP_JG_F, 13, "jg.f", 5, 2, 0)
45.61 -OPDEF(OP_JGE_F, 14, "jge.f", 5, 2, 0)
45.62 -OPDEF(OP_JEQ_F, 15, "jeq.f", 5, 2, 0)
45.63 -OPDEF(OP_JNE_F, 16, "jne.f", 5, 2, 0)
45.64 -OPDEF(OP_JT_F, 17, "jt.f", 5, 1, 0)
45.65 -OPDEF(OP_JF_F, 18, "jf.f", 5, 1, 0)
45.66 -
45.67 -// Unconditional jump.
45.68 -OPDEF(OP_JUMP, 19, "jump", 5, 0, 0)
45.69 -
45.70 -// Gets or sets the value of a local variable onto the stack. The local
45.71 -// variable is given by an immediate index.
45.72 -OPDEF(OP_GETLOCAL, 20, "getlocal", 5, 0, 1)
45.73 -OPDEF(OP_SETLOCAL, 21, "setlocal", 5, 1, 1)
45.74 -
45.75 -// Stack transitions for these binary operators:
45.76 -// rhs = pop()
45.77 -// lhs = pop()
45.78 -// push(lhs OP rhs)
45.79 -OPDEF(OP_ADD, 22, "add", 1, 2, 1)
45.80 -OPDEF(OP_SUB, 23, "sub", 1, 2, 1)
45.81 -OPDEF(OP_MUL, 24, "mul", 1, 2, 1)
45.82 -OPDEF(OP_DIV, 25, "div", 1, 2, 1)
45.83 -OPDEF(OP_MOD, 26, "mod", 1, 2, 1)
45.84 -
45.85 -OPDEF(OP_LT, 27, "lt", 1, 2, 1)
45.86 -OPDEF(OP_LE, 28, "le", 1, 2, 1)
45.87 -OPDEF(OP_GE, 29, "ge", 1, 2, 1)
45.88 -OPDEF(OP_GT, 30, "gt", 1, 2, 1)
45.89 -OPDEF(OP_EQ, 31, "eq", 1, 2, 1)
45.90 -OPDEF(OP_NE, 32, "ne", 1, 2, 1)
45.91 -
45.92 -OPDEF(OP_NOT, 33, "not", 1, 1, 1)
45.93 -OPDEF(OP_NEG, 34, "neg", 1, 1, 1)
45.94 -
45.95 -OPDEF(OP_POP, 35, "pop", 1, 1, 0)
45.96 -
45.97 -// Unconditional terminator placed at the end of code. If a function returns
45.98 -// void, this acts as a RETURNVOID. Otherwise, it must be unreachable.
45.99 -OPDEF(OP_STOP, 36, "stop", 1, 0, 0)
45.100 -
45.101 -// Call a function with N arguments. The target function must be the last item
45.102 -// on the stack.
45.103 -OPDEF(OP_CALL, 37, "call", 1, -1, 1)
45.104 -
45.105 -// Similar to GET/LOCAL, except for arguments.
45.106 -OPDEF(OP_GETARG, 38, "getarg", 5, 0, 1)
45.107 -OPDEF(OP_SETARG, 39, "setarg", 5, 1, 1)
45.108 -
45.109 -// Reads or writes an integer element to an unsafe array.
45.110 -// index = pop()
45.111 -// ref = pop()
45.112 -// ref[index]
45.113 -//
45.114 -OPDEF(OP_GETARRAY_I, 40, "getarray.i", 1, 2, 1)
45.115 -OPDEF(OP_SETARRAY_I, 41, "setarray.i", 1, 3, 1)
45.116 -OPDEF(OP_GETARRAY_F, 42, "getarray.f", 1, 2, 1)
45.117 -OPDEF(OP_SETARRAY_F, 43, "setarray.f", 1, 3, 1)
45.118 -OPDEF(OP_GETARRAY_C, 44, "getarray.c", 1, 2, 1)
45.119 -OPDEF(OP_SETARRAY_C, 45, "setarray.c", 1, 3, 1)
45.120 -OPDEF(OP_GETARRAY_O, 46, "getarray.o", 1, 2, 1)
45.121 -
45.122 -// Allocate an array. The HeapTenure is stored as a byte following pc. The
45.123 -// ArrayMap to use is specified as an index into the script's Map table.
45.124 -//
45.125 -// Format:
45.126 -// [u8 op] [u32 index]
45.127 -OPDEF(OP_NEWARRAY, 47, "newarray", 6, 0, 1)
45.128 -
45.129 -// Performs a bounds check on an unsafe array.
45.130 -//
45.131 -// index = pop()
45.132 -// array = pop()
45.133 -// push(array)
45.134 -// push(index)
45.135 -OPDEF(OP_BOUNDS, 48, "bounds", 1, 2, 2)
45.136 -
45.137 -// Pushes a 32-bit IEEE-754 floating point immediate onto the stack.
45.138 -OPDEF(OP_FLOAT, 49, "float", 5, 0, 1)
45.139 -
45.140 -// Converts an integer to a 32-bit IEEE-754 floating point immediate.
45.141 -OPDEF(OP_CVT_I2F, 50, "cvt.i2f", 1, 1, 1)
45.142 -
45.143 -// Stack transitions for these binary operators:
45.144 -// rhs = pop()
45.145 -// lhs = pop()
45.146 -// push(lhs OP rhs)
45.147 -OPDEF(OP_ADD_F, 51, "add.f", 1, 2, 1)
45.148 -OPDEF(OP_SUB_F, 52, "sub.f", 1, 2, 1)
45.149 -OPDEF(OP_MUL_F, 53, "mul.f", 1, 2, 1)
45.150 -OPDEF(OP_DIV_F, 54, "div.f", 1, 2, 1)
45.151 -OPDEF(OP_UNUSED1, 55, "unused0", 1, 0, 0)
45.152 -
45.153 -OPDEF(OP_LT_F, 56, "lt.f", 1, 2, 1)
45.154 -OPDEF(OP_LE_F, 57, "le.f", 1, 2, 1)
45.155 -OPDEF(OP_GE_F, 58, "ge.f", 1, 2, 1)
45.156 -OPDEF(OP_GT_F, 59, "gt.f", 1, 2, 1)
45.157 -OPDEF(OP_EQ_F, 60, "eq.f", 1, 2, 1)
45.158 -OPDEF(OP_NE_F, 61, "ne.f", 1, 2, 1)
45.159 -
45.160 -OPDEF(OP_NOT_F, 62, "not.f", 1, 1, 1)
45.161 -OPDEF(OP_NEG_F, 63, "neg.f", 1, 1, 1)
45.162 -
45.163 -// Bitwise operators.
45.164 -OPDEF(OP_SHL, 64, "shl", 1, 2, 1)
45.165 -OPDEF(OP_SHR, 65, "shr", 1, 2, 1)
45.166 -OPDEF(OP_USHR, 66, "ushr", 1, 2, 1)
45.167 -OPDEF(OP_BITAND, 67, "bitand", 1, 2, 1)
45.168 -OPDEF(OP_BITOR, 68, "bitor", 1, 2, 1)
45.169 -OPDEF(OP_BITXOR, 69, "bitxor", 1, 2, 1)
45.170 -OPDEF(OP_BITNOT, 70, "bitnot", 1, 1, 1)
45.171 -
45.172 -// Saves or restores the position of the LIFO heap to/from a local slot.
45.173 -OPDEF(OP_SAVELIFO, 71, "savelifo", 5, 0, 0)
45.174 -OPDEF(OP_UNWINDLIFO, 72, "unwindlifo", 5, 0, 0)
45.175 -
45.176 -// Composes a variable reference to a stack slot or argument.
45.177 -OPDEF(OP_VARREF_LIFO, 73, "varref.lifo", 5, 0, 1)
45.178 -OPDEF(OP_ARGREF_LIFO, 74, "argref.lifo", 5, 0, 1)
45.179 -OPDEF(OP_SLOTREF_LIFO, 75, "slotref.lifo", 1, 1, 1)
45.180 -OPDEF(OP_ARRAYREF_LIFO, 76, "arrayref.lifo",1, 2, 1)
45.181 -OPDEF(OP_GETREF_I, 77, "getref.i", 1, 1, 1)
45.182 -OPDEF(OP_SETREF_I, 78, "setref.i", 1, 2, 1)
45.183 -OPDEF(OP_GETREF_F, 79, "getref.f", 1, 1, 1)
45.184 -OPDEF(OP_SETREF_F, 80, "setref.f", 1, 2, 1)
45.185 -
45.186 -// Pushes an object reference onto the stack.
45.187 -OPDEF(OP_OBJECT, 81, "object", 5, 0, 1)
45.188 -
45.189 -// Performs an array-to-array assignment.
45.190 -// Left = pop()
45.191 -// Right = pop()
45.192 -// copy(Left, Right)
45.193 -// push(Left)
45.194 -OPDEF(OP_ARRAYCOPY, 82, "arraycopy", 1, 2, 1)
45.195 -
45.196 -// Duplicates the top item on the stack.
45.197 -OPDEF(OP_DUP, 83, "dup", 1, 1, 2)
45.198 -
45.199 -// Duplicates the top two items on the stack.
45.200 -OPDEF(OP_DUP2, 84, "dup2", 1, 2, 4)
45.201 -
45.202 -// Swaps the two items at the top of the stack.
45.203 -OPDEF(OP_SWAP, 85, "swap", 1, 2, 2)
45.204 -
45.205 -// Roll operation is the same as Forth. It steals a value on the stack,
45.206 -// shifting all stack values down, and then places the stolen value back at
45.207 -// the top of the stack.
45.208 -//
45.209 -// p = sp[-3]
45.210 -// sp[-3] = sp[-2]
45.211 -// sp[-2] = sp[-1]
45.212 -// sp[-1] = p
45.213 -OPDEF(OP_ROLL3, 86, "roll3", 1, 3, 3)
45.214 -
45.215 -// Pick operation is the same as Forth. It pushes a copy of a slot at a
45.216 -// specific depth.
45.217 -//
45.218 -// push(sp[-n])
45.219 -OPDEF(OP_PICK2, 87, "pick2", 1, 2, 3)
45.220 -OPDEF(OP_PICK3, 88, "pick3", 1, 3, 4)
45.221 -
45.222 -// Calls a native function. During the course of calling a native, arguments
45.223 -// on the stack are re-pushed to match the cell-based native calling
45.224 -// convention expected by ISourcePawnEngine.
45.225 -//
45.226 -// Unlike the normal CALL instruction, natives take truly variadic arguments
45.227 -// and so we must specify the number of arguments. The format is:
45.228 -//
45.229 -// [u8 Opcode] [u32 Index] [u32 ArgCount]
45.230 -//
45.231 -OPDEF(OP_CALLNATIVE, 89, "callnative", 9, -1, 1)
45.232 -
45.233 -// Returns from a function that does return a value.
45.234 -OPDEF(OP_RETURNVOID, 90, "returnvoid", 1, 0, 0)
45.235 -
45.236 -// Loads the module of the running function.
45.237 -OPDEF(OP_MODULE, 91, "module", 1, 0, 1)
45.238 -
45.239 -// Loads a function from a module object. The operand is the slot number
45.240 -// in the module.
45.241 -OPDEF(OP_GETMODULE_FN, 92, "getmodule.fn", 5, 1, 1)
45.242 -
45.243 -// Opcodes for accessing an environment slot in the global scope.
45.244 -OPDEF(OP_SETGLOBAL_I, 93, "setglobal.i", 5, 1, 1)
45.245 -OPDEF(OP_SETGLOBAL_F, 94, "setglobal.f", 5, 1, 1)
45.246 -OPDEF(OP_SETGLOBAL_O, 95, "setglobal.o", 5, 1, 1)
45.247 -OPDEF(OP_GETGLOBAL_I, 96, "getglobal.i", 5, 0, 1)
45.248 -OPDEF(OP_GETGLOBAL_F, 97, "getglobal.f", 5, 0, 1)
45.249 -OPDEF(OP_GETGLOBAL_O, 98, "getglobal.o", 5, 0, 1)
45.250 \ No newline at end of file
46.1 --- a/jitcraft/Parser.cpp Tue Jul 24 23:53:34 2012 -0700
46.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
46.3 @@ -1,1314 +0,0 @@
46.4 -/* vim: set ts=4 sw=4 tw=99 et:
46.5 - *
46.6 - * Copyright (C) 2012 David Anderson
46.7 - *
46.8 - * This file is part of JITCraft.
46.9 - *
46.10 - * JITCraft is free software: you can redistribute it and/or modify it under
46.11 - * the terms of the GNU General Public License as published by the Free
46.12 - * Software Foundation, either version 3 of the License, or (at your option)
46.13 - * any later version.
46.14 - *
46.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
46.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
46.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
46.18 - *
46.19 - * You should have received a copy of the GNU General Public License along with
46.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
46.21 - */
46.22 -#include "Zone.h"
46.23 -#include "Parser.h"
46.24 -#include "FixedArray.h"
46.25 -#include "Heap.h"
46.26 -#include "Strings.h"
46.27 -#include "Heap-inl.h"
46.28 -
46.29 -using namespace ke;
46.30 -
46.31 -Parser::Parser(Zone *zone, CompileContext &cc, const char *stream, size_t length)
46.32 - : zone_(zone),
46.33 - cc_(cc),
46.34 - pool_(zone_->pool()),
46.35 - scanner_(cc, stream, length),
46.36 - scope_(NULL),
46.37 - unbound_(NULL)
46.38 -{
46.39 - unbound_ = new (pool_) PoolList<NameProxy *>();
46.40 -}
46.41 -
46.42 -bool
46.43 -Parser::match(TokenKind kind)
46.44 -{
46.45 - if (scanner_.peek() != kind)
46.46 - return false;
46.47 - scanner_.scan();
46.48 - return true;
46.49 -}
46.50 -
46.51 -bool
46.52 -Parser::matchSemicolon()
46.53 -{
46.54 - return expect(TOK_SEMICOLON);
46.55 -}
46.56 -
46.57 -bool
46.58 -Parser::expect(TokenKind kind)
46.59 -{
46.60 - TokenKind got = scanner_.scan();
46.61 - if (got == kind)
46.62 - return true;
46.63 - cc_.reportError(scanner_.begin(), Message_WrongToken, TokenNames[kind], TokenNames[got]);
46.64 - return false;
46.65 -}
46.66 -
46.67 -Scope *
46.68 -Parser::enterScope(Scope::Kind kind)
46.69 -{
46.70 - scope_ = new (pool_) Scope(pool_, kind, scope_);
46.71 - if (!scope_->initialize())
46.72 - return NULL;
46.73 - return scope_;
46.74 -}
46.75 -
46.76 -NameProxy *
46.77 -Parser::bind(Handle<String> name)
46.78 -{
46.79 - BoundName *bound = scope_->lookup(name);
46.80 - NameProxy *proxy = new (pool_) NameProxy(scanner_.begin(), name, bound);
46.81 - if (!bound && !unbound_->append(proxy))
46.82 - return NULL;
46.83 - return proxy;
46.84 -}
46.85 -
46.86 -bool
46.87 -Parser::matchName(String **name, TokenKind kind)
46.88 -{
46.89 - assert(kind == TOK_NAME || kind == TOK_LABEL);
46.90 - *name = NULL;
46.91 - if (!match(kind))
46.92 - return false;
46.93 - *name = zone_->makeSymbol(scanner_.literal(), scanner_.literal_length());
46.94 - return true;
46.95 -}
46.96 -
46.97 -String *
46.98 -Parser::expectName()
46.99 -{
46.100 - if (!expect(TOK_NAME))
46.101 - return NULL;
46.102 - return zone_->makeSymbol(scanner_.literal(), scanner_.literal_length());
46.103 -}
46.104 -
46.105 -void
46.106 -Parser::redeclarationError(BoundName *other)
46.107 -{
46.108 - cc_.reportError(scanner_.begin(), Message_RedeclaredName, other->name()->chars(),
46.109 - other->pos().line, other->pos().col);
46.110 -}
46.111 -
46.112 -Expression *
46.113 -Parser::primitive()
46.114 -{
46.115 - TokenKind kind = scanner_.peek();
46.116 - switch (kind) {
46.117 - case TOK_NAME:
46.118 - {
46.119 - Local<String> name(zone_, expectName());
46.120 - if (!name)
46.121 - return NULL;
46.122 - return bind(name);
46.123 - }
46.124 -
46.125 - case TOK_FLOAT_LITERAL:
46.126 - {
46.127 - scanner_.scan();
46.128 - double value = Scanner::ParseDouble(scanner_.literal());
46.129 - return new (pool_) FloatLiteral(scanner_.begin(), value);
46.130 - }
46.131 -
46.132 - case TOK_INTEGER_LITERAL:
46.133 - {
46.134 - scanner_.scan();
46.135 - int value = atoi(scanner_.literal());
46.136 - return new (pool_) IntegerLiteral(scanner_.begin(), value);
46.137 - }
46.138 -
46.139 - case TOK_STRING_LITERAL:
46.140 - {
46.141 - scanner_.scan();
46.142 - Local<ByteArray> array(zone_, ByteArray::New(zone_, scanner_.literal_length() + 1));
46.143 - if (!array)
46.144 - return NULL;
46.145 - memcpy(array->raw(), scanner_.literal(), scanner_.literal_length() + 1);
46.146 - return new (pool_) StringLiteral(scanner_.begin(), array);
46.147 - }
46.148 -
46.149 - default:
46.150 - {
46.151 - if (kind != TOK_ERROR)
46.152 - cc_.reportError(scanner_.begin(), Message_ExpectedExpression, TokenNames[kind]);
46.153 - return NULL;
46.154 - }
46.155 - }
46.156 -}
46.157 -
46.158 -Expression *
46.159 -Parser::prefix()
46.160 -{
46.161 - switch (scanner_.peek()) {
46.162 - case TOK_LPAREN:
46.163 - {
46.164 - scanner_.scan();
46.165 - Expression *expr = expression();
46.166 - if (!expr)
46.167 - return NULL;
46.168 - if (!expect(TOK_RPAREN))
46.169 - return NULL;
46.170 - return expr;
46.171 - }
46.172 -
46.173 - default:
46.174 - return primitive();
46.175 - }
46.176 -}
46.177 -
46.178 -Expression *
46.179 -Parser::call(Expression *callee)
46.180 -{
46.181 - ExpressionList *arguments = new (pool_) ExpressionList();
46.182 -
46.183 - SourcePosition pos = scanner_.begin();
46.184 - expect(TOK_LPAREN);
46.185 -
46.186 - if (!match(TOK_RPAREN)) {
46.187 - while (true) {
46.188 - Expression *expr = expression();
46.189 - if (!expr)
46.190 - return NULL;
46.191 -
46.192 - if (!arguments->append(expr))
46.193 - return NULL;
46.194 -
46.195 - if (!match(TOK_COMMA))
46.196 - break;
46.197 - }
46.198 -
46.199 - if (!expect(TOK_RPAREN))
46.200 - return NULL;
46.201 - }
46.202 -
46.203 - return new (pool_) CallExpression(pos, callee, arguments);
46.204 -}
46.205 -
46.206 -Expression *
46.207 -Parser::index(Expression *left)
46.208 -{
46.209 - expect(TOK_LBRACKET);
46.210 -
46.211 - SourcePosition pos = scanner_.begin();
46.212 - Expression *expr = expression();
46.213 - if (!expr)
46.214 - return NULL;
46.215 -
46.216 - if (!expect(TOK_RBRACKET))
46.217 - return NULL;
46.218 -
46.219 - return new (pool_) IndexExpression(pos, left, expr);
46.220 -}
46.221 -
46.222 -Expression *
46.223 -Parser::primary()
46.224 -{
46.225 - Expression *expr = prefix();
46.226 - if (!expr)
46.227 - return NULL;
46.228 -
46.229 - for (;;) {
46.230 - switch (scanner_.peek()) {
46.231 - case TOK_LPAREN:
46.232 - expr = call(expr);
46.233 - if (!expr)
46.234 - return NULL;
46.235 - break;
46.236 -
46.237 - case TOK_LBRACKET:
46.238 - expr = index(expr);
46.239 - if (!expr)
46.240 - return NULL;
46.241 - break;
46.242 -
46.243 - default:
46.244 - return expr;
46.245 - }
46.246 - }
46.247 -}
46.248 -
46.249 -Expression *
46.250 -Parser::unary()
46.251 -{
46.252 - TokenKind token = scanner_.peek();
46.253 -
46.254 - SourcePosition pos = scanner_.begin();
46.255 - switch (token) {
46.256 - case TOK_INCREMENT:
46.257 - case TOK_DECREMENT:
46.258 - {
46.259 - scanner_.scan();
46.260 - Expression *expr = expression();
46.261 - if (!expr)
46.262 - return NULL;
46.263 - return new (pool_) IncDecExpression(pos, token, expr, false);
46.264 - }
46.265 -
46.266 - case TOK_MINUS:
46.267 - case TOK_NOT:
46.268 - case TOK_TILDE:
46.269 - {
46.270 - scanner_.scan();
46.271 - Expression *expr = expression();
46.272 - if (!expr)
46.273 - return NULL;
46.274 - return new (pool_) UnaryExpression(pos, token, expr);
46.275 - }
46.276 -
46.277 - default:
46.278 - break;
46.279 - }
46.280 -
46.281 - Expression *expr = primary();
46.282 -
46.283 - token = scanner_.peek();
46.284 - if (token == TOK_INCREMENT || token == TOK_DECREMENT) {
46.285 - scanner_.scan();
46.286 - return new (pool_) IncDecExpression(pos, token, expr, true);
46.287 - }
46.288 -
46.289 - return expr;
46.290 -}
46.291 -
46.292 -Expression *
46.293 -Parser::multiplication()
46.294 -{
46.295 - Expression *left = unary();
46.296 - do {
46.297 - if (!match(TOK_SLASH) && !match(TOK_STAR) && !match(TOK_PERCENT))
46.298 - break;
46.299 - SourcePosition pos = scanner_.begin();
46.300 - TokenKind kind = scanner_.last();
46.301 - Expression *right = unary();
46.302 - if (!right)
46.303 - return NULL;
46.304 - left = new (pool_) BinaryExpression(pos, kind, left, right);
46.305 - } while (left);
46.306 - return left;
46.307 -}
46.308 -
46.309 -Expression *
46.310 -Parser::addition()
46.311 -{
46.312 - Expression *left = multiplication();
46.313 - while (left) {
46.314 - if (!match(TOK_PLUS) && !match(TOK_MINUS))
46.315 - break;
46.316 - SourcePosition pos = scanner_.begin();
46.317 - TokenKind kind = scanner_.last();
46.318 - Expression *right = multiplication();
46.319 - if (!right)
46.320 - return NULL;
46.321 - left = new (pool_) BinaryExpression(pos, kind, left, right);
46.322 - }
46.323 - return left;
46.324 -}
46.325 -
46.326 -Expression *
46.327 -Parser::shift()
46.328 -{
46.329 - Expression *left = addition();
46.330 - while (left) {
46.331 - if (!match(TOK_SHL) && !match(TOK_SHR) && !match(TOK_USHR))
46.332 - break;
46.333 - SourcePosition pos = scanner_.begin();
46.334 - TokenKind kind = scanner_.last();
46.335 - Expression *right = addition();
46.336 - if (!right)
46.337 - return NULL;
46.338 - left = new (pool_) BinaryExpression(pos, kind, left, right);
46.339 - }
46.340 - return left;
46.341 -}
46.342 -
46.343 -Expression *
46.344 -Parser::bitand_()
46.345 -{
46.346 - Expression *left = shift();
46.347 - while (left) {
46.348 - if (!match(TOK_BITAND))
46.349 - break;
46.350 - SourcePosition pos = scanner_.begin();
46.351 - Expression *right = shift();
46.352 - if (!right)
46.353 - return NULL;
46.354 - left = new (pool_) BinaryExpression(pos, TOK_BITAND, left, right);
46.355 - }
46.356 - return left;
46.357 -}
46.358 -
46.359 -Expression *
46.360 -Parser::bitxor()
46.361 -{
46.362 - Expression *left = bitand_();
46.363 - while (left) {
46.364 - if (!match(TOK_BITXOR))
46.365 - break;
46.366 - SourcePosition pos = scanner_.begin();
46.367 - Expression *right = shift();
46.368 - if (!right)
46.369 - return NULL;
46.370 - left = new (pool_) BinaryExpression(pos, TOK_BITXOR, left, right);
46.371 - }
46.372 - return left;
46.373 -}
46.374 -
46.375 -Expression *
46.376 -Parser::bitor_()
46.377 -{
46.378 - Expression *left = bitxor();
46.379 - while (left) {
46.380 - if (!match(TOK_BITOR))
46.381 - break;
46.382 - SourcePosition pos = scanner_.begin();
46.383 - Expression *right = bitxor();
46.384 - if (!right)
46.385 - return NULL;
46.386 - left = new (pool_) BinaryExpression(pos, TOK_BITOR, left, right);
46.387 - }
46.388 - return left;
46.389 -}
46.390 -
46.391 -Expression *
46.392 -Parser::relational()
46.393 -{
46.394 - Expression *left = bitor_();
46.395 - while (left) {
46.396 - TokenKind kind = scanner_.peek();
46.397 - if (kind < TOK_LT || kind > TOK_GE)
46.398 - break;
46.399 - scanner_.scan();
46.400 - SourcePosition pos = scanner_.begin();
46.401 - Expression *right = shift();
46.402 - if (!right)
46.403 - return NULL;
46.404 - left = new (pool_) BinaryExpression(pos, kind, left, right);
46.405 - }
46.406 - return left;
46.407 -}
46.408 -
46.409 -Expression *
46.410 -Parser::equals()
46.411 -{
46.412 - Expression *left = relational();
46.413 - while (left) {
46.414 - if (!match(TOK_EQUALS) && !match(TOK_NOTEQUALS))
46.415 - break;
46.416 - TokenKind kind = scanner_.last();
46.417 - SourcePosition pos = scanner_.begin();
46.418 - Expression *right = relational();
46.419 - if (!right)
46.420 - return NULL;
46.421 - left = new (pool_) BinaryExpression(pos, kind, left, right);
46.422 - }
46.423 - return left;
46.424 -}
46.425 -
46.426 -Expression *
46.427 -Parser::and_()
46.428 -{
46.429 - Expression *left = equals();
46.430 - while (left) {
46.431 - if (!match(TOK_AND))
46.432 - break;
46.433 - SourcePosition pos = scanner_.begin();
46.434 - Expression *right = equals();
46.435 - if (!right)
46.436 - return NULL;
46.437 - left = new (pool_) BinaryExpression(pos, TOK_AND, left, right);
46.438 - }
46.439 - return left;
46.440 -}
46.441 -
46.442 -Expression *
46.443 -Parser::or_()
46.444 -{
46.445 - Expression *left = and_();
46.446 - while (left) {
46.447 - if (!match(TOK_OR))
46.448 - break;
46.449 - SourcePosition pos = scanner_.begin();
46.450 - Expression *right = and_();
46.451 - if (!right)
46.452 - return NULL;
46.453 - left = new (pool_) BinaryExpression(pos, TOK_OR, left, right);
46.454 - }
46.455 - return left;
46.456 -}
46.457 -
46.458 -Expression *
46.459 -Parser::ternary()
46.460 -{
46.461 - Expression *cond = or_();
46.462 - if (!cond)
46.463 - return NULL;
46.464 -
46.465 - if (!match(TOK_QMARK))
46.466 - return cond;
46.467 -
46.468 - SourcePosition pos = scanner_.begin();
46.469 - Expression *left = expression();
46.470 - if (!left)
46.471 - return NULL;
46.472 -
46.473 - if (!expect(TOK_COLON))
46.474 - return NULL;
46.475 -
46.476 - Expression *right = expression();
46.477 - if (!right)
46.478 - return NULL;
46.479 -
46.480 - return new (pool_) TernaryExpression(pos, cond, left, right);
46.481 -}
46.482 -
46.483 -Expression *
46.484 -Parser::assignment()
46.485 -{
46.486 - Expression *left = ternary();
46.487 - while (left) {
46.488 - TokenKind token = scanner_.peek();
46.489 - if (token != TOK_ASSIGN && (token < TOK_ASSIGN_ADD || token > TOK_ASSIGN_SHL))
46.490 - break;
46.491 - scanner_.scan();
46.492 - SourcePosition pos = scanner_.begin();
46.493 - Expression *expr = ternary();
46.494 - if (!expr)
46.495 - return NULL;
46.496 -
46.497 - left = new (pool_) Assignment(pos, token, left, expr);
46.498 - }
46.499 - return left;
46.500 -}
46.501 -
46.502 -Expression *
46.503 -Parser::expression()
46.504 -{
46.505 - return assignment();
46.506 -}
46.507 -
46.508 -Statement *
46.509 -Parser::while_()
46.510 -{
46.511 - SourcePosition pos = scanner_.begin();
46.512 - scanner_.scan();
46.513 -
46.514 - if (!expect(TOK_LPAREN))
46.515 - return NULL;
46.516 -
46.517 - Expression *condition = expression();
46.518 - if (!condition)
46.519 - return NULL;
46.520 -
46.521 - if (!expect(TOK_RPAREN))
46.522 - return NULL;
46.523 -
46.524 - // Inside a loop, we force the creation of a scope object. Normally, we
46.525 - // will cull scopes if they have no variables. However inside a loop,
46.526 - // function calls that take references may compute a LIFO object, and to
46.527 - // avoid temporarily leaking many such objects, we ensure that a scope
46.528 - // is present so a LIFO slot can be allocated.
46.529 - if (!enterScope(Scope::BLOCK))
46.530 - return NULL;
46.531 -
46.532 - Statement *body;
46.533 - if (scanner_.peek() == TOK_LBRACE)
46.534 - body = block(scope_);
46.535 - else
46.536 - body = localStatement();
46.537 - if (!body)
46.538 - return NULL;
46.539 -
46.540 - scope_ = scope_->enclosing();
46.541 - return new (pool_) WhileStatement(pos, TOK_WHILE, condition, body);
46.542 -}
46.543 -
46.544 -Statement *
46.545 -Parser::do_()
46.546 -{
46.547 - SourcePosition pos = scanner_.begin();
46.548 - scanner_.scan();
46.549 -
46.550 - // See the comment in ::while_() as to why we force a scope.
46.551 - if (!enterScope(Scope::BLOCK))
46.552 - return NULL;
46.553 -
46.554 - Statement *body;
46.555 - if (scanner_.peek() == TOK_LBRACE)
46.556 - body = block(scope_);
46.557 - else
46.558 - body = localStatement();
46.559 - if (!body)
46.560 - return NULL;
46.561 -
46.562 - scope_ = scope_->enclosing();
46.563 -
46.564 - if (!expect(TOK_WHILE))
46.565 - return NULL;
46.566 -
46.567 - if (!expect(TOK_LPAREN))
46.568 - return NULL;
46.569 - Expression *condition = expression();
46.570 - if (!condition)
46.571 - return NULL;
46.572 - if (!expect(TOK_RPAREN))
46.573 - return NULL;
46.574 -
46.575 - return new (pool_) WhileStatement(pos, TOK_DO, condition, body);
46.576 -}
46.577 -
46.578 -Statement *
46.579 -Parser::forStatement()
46.580 -{
46.581 - SourcePosition pos = scanner_.begin();
46.582 - scanner_.scan();
46.583 - if (!expect(TOK_LPAREN))
46.584 - return NULL;
46.585 -
46.586 - Statement *decl = NULL;
46.587 - if (!match(TOK_SEMICOLON)) {
46.588 - if (scanner_.peek() == TOK_NEW) {
46.589 - if (!enterScope(Scope::BLOCK))
46.590 - return NULL;
46.591 - if ((decl = variableDeclaration()) == NULL)
46.592 - return NULL;
46.593 - } else {
46.594 - if ((decl = expressionStatement()) == NULL)
46.595 - return NULL;
46.596 - }
46.597 - if (!expect(TOK_SEMICOLON))
46.598 - return NULL;
46.599 - }
46.600 -
46.601 - Expression *condition = NULL;
46.602 - if (!match(TOK_SEMICOLON)) {
46.603 - if ((condition = expression()) == NULL)
46.604 - return NULL;
46.605 - if (!expect(TOK_SEMICOLON))
46.606 - return NULL;
46.607 - }
46.608 -
46.609 - Statement *update = NULL;
46.610 - if (!match(TOK_RPAREN)) {
46.611 - if ((update = expressionStatement()) == NULL)
46.612 - return NULL;
46.613 - if (!expect(TOK_RPAREN))
46.614 - return NULL;
46.615 - }
46.616 -
46.617 - // See the comment in ::while_() as to why we force a scope.
46.618 - if (!enterScope(Scope::BLOCK))
46.619 - return NULL;
46.620 -
46.621 - Statement *body;
46.622 - if (scanner_.peek() == TOK_LBRACE)
46.623 - body = block(scope_);
46.624 - else
46.625 - body = localStatement();
46.626 - if (!body)
46.627 - return NULL;
46.628 -
46.629 - scope_ = scope_->enclosing();
46.630 -
46.631 - Scope *declScope = NULL;
46.632 - if (decl && decl->isVariableDeclaration()) {
46.633 - declScope = scope_->unlinkIfEmpty();
46.634 - scope_ = scope_->enclosing();
46.635 - }
46.636 - return new (pool_) ForStatement(pos, declScope, decl, condition, update, body);
46.637 -}
46.638 -
46.639 -VariableDeclaration *
46.640 -Parser::variableDeclaration()
46.641 -{
46.642 - if (!expect(TOK_NEW))
46.643 - return NULL;
46.644 -
46.645 - Local<String> tag(zone_);
46.646 - if (matchName(tag.ref(), TOK_LABEL) && !tag)
46.647 - return NULL;
46.648 -
46.649 - Local<String> name(zone_, expectName());
46.650 - if (!name)
46.651 - return NULL;
46.652 -
46.653 - if (BoundName *other = scope_->localLookup(name)) {
46.654 - redeclarationError(other);
46.655 - return NULL;
46.656 - }
46.657 -
46.658 - Variable *var = scope_->declareVariable(name, scanner_.begin());
46.659 - if (!var)
46.660 - return NULL;
46.661 -
46.662 - ExpressionList *postDimensions = NULL;
46.663 - if (scanner_.peek() == TOK_LBRACKET) {
46.664 - postDimensions = new (pool_) ExpressionList();
46.665 - while (match(TOK_LBRACKET)) {
46.666 - Expression *dim = expression();
46.667 - if (!dim)
46.668 - return NULL;
46.669 -
46.670 - if (!expect(TOK_RBRACKET))
46.671 - return NULL;
46.672 -
46.673 - if (!postDimensions->append(dim))
46.674 - return NULL;
46.675 - }
46.676 - }
46.677 -
46.678 - Expression *expr = NULL;
46.679 - if (match(TOK_ASSIGN)) {
46.680 - if ((expr = expression()) == NULL)
46.681 - return NULL;
46.682 - }
46.683 -
46.684 - return new (pool_) VariableDeclaration(var->pos(), var, tag, postDimensions, expr);
46.685 -}
46.686 -
46.687 -Statement *
46.688 -Parser::returnStatement()
46.689 -{
46.690 - SourcePosition pos = scanner_.begin();
46.691 - if (!expect(TOK_RETURN))
46.692 - return NULL;
46.693 -
46.694 - Expression *expr = NULL;
46.695 - if (scanner_.peek() != TOK_SEMICOLON) {
46.696 - if ((expr = expression()) == NULL)
46.697 - return NULL;
46.698 -
46.699 - // We only care about non-void returns when determining whether a
46.700 - // tagless function is non-void.
46.701 - encounteredReturn_ = true;
46.702 - }
46.703 -
46.704 - return new (pool_) ReturnStatement(pos, expr);
46.705 -}
46.706 -
46.707 -Statement *
46.708 -Parser::expressionStatement()
46.709 -{
46.710 - Expression *left = assignment();
46.711 - if (!left)
46.712 - return NULL;
46.713 -
46.714 - return new (pool_) ExpressionStatement(left);
46.715 -}
46.716 -
46.717 -Statement *
46.718 -Parser::block(Scope *scope)
46.719 -{
46.720 - if (!expect(TOK_LBRACE))
46.721 - return NULL;
46.722 -
46.723 - SourcePosition pos = scanner_.begin();
46.724 - if (!scope && !enterScope(Scope::BLOCK))
46.725 - return NULL;
46.726 -
46.727 - StatementList *statements = new (pool_) StatementList();
46.728 - while (!match(TOK_RBRACE)) {
46.729 - Statement *statement = localStatement();
46.730 - if (statement == NULL)
46.731 - return NULL;
46.732 - if (!statements->append(statement))
46.733 - return NULL;
46.734 - }
46.735 -
46.736 - if (!scope) {
46.737 - scope = scope_->unlinkIfEmpty();
46.738 - scope_ = scope_->enclosing();
46.739 - }
46.740 - BlockStatement *block = new (pool_) BlockStatement(pos, scope, statements);
46.741 - return block;
46.742 -}
46.743 -
46.744 -Statement *
46.745 -Parser::if_()
46.746 -{
46.747 - expect(TOK_IF);
46.748 -
46.749 - SourcePosition pos = scanner_.begin();
46.750 - if (!expect(TOK_LPAREN))
46.751 - return NULL;
46.752 -
46.753 - Expression *cond = expression();
46.754 - if (!cond)
46.755 - return NULL;
46.756 -
46.757 - if (!expect(TOK_RPAREN))
46.758 - return NULL;
46.759 -
46.760 - Statement *ifTrue = localStatement();
46.761 - if (!ifTrue)
46.762 - return NULL;
46.763 -
46.764 - IfStatement *outer = new (pool_) IfStatement(pos, cond, ifTrue);
46.765 -
46.766 - IfStatement *last = outer;
46.767 - while (match(TOK_ELSE)) {
46.768 - if (!match(TOK_IF)) {
46.769 - Statement *ifFalse = localStatement();
46.770 - if (!ifFalse)
46.771 - return NULL;
46.772 -
46.773 - last->setIfFalse(ifFalse);
46.774 - break;
46.775 - }
46.776 -
46.777 - SourcePosition pos = scanner_.begin();
46.778 - if (!expect(TOK_LPAREN))
46.779 - return NULL;
46.780 -
46.781 - Expression *otherCond = expression();
46.782 - if (!otherCond)
46.783 - return NULL;
46.784 -
46.785 - if (!expect(TOK_RPAREN))
46.786 - return NULL;
46.787 -
46.788 - Statement *otherIfTrue = localStatement();
46.789 - if (!otherIfTrue)
46.790 - return NULL;
46.791 -
46.792 - IfStatement *inner = new (pool_) IfStatement(pos, otherCond, otherIfTrue);
46.793 - last->setIfFalse(inner);
46.794 - last = inner;
46.795 - }
46.796 -
46.797 - return outer;
46.798 -}
46.799 -
46.800 -Statement *
46.801 -Parser::localStatement()
46.802 -{
46.803 - Statement *statement = NULL;
46.804 -
46.805 - // Statements which must be followed by a semicolon will break out of the
46.806 - // switch. If they may end in BlockStatements, they'll immediately return.
46.807 -
46.808 - switch (scanner_.peek()) {
46.809 - case TOK_NEW:
46.810 - if ((statement = variableDeclaration()) == NULL)
46.811 - return NULL;
46.812 - break;
46.813 -
46.814 - case TOK_FOR:
46.815 - return forStatement();
46.816 -
46.817 - case TOK_WHILE:
46.818 - return while_();
46.819 -
46.820 - case TOK_BREAK:
46.821 - scanner_.scan();
46.822 - statement = new (pool_) BreakStatement(scanner_.begin());
46.823 - break;
46.824 -
46.825 - case TOK_CONTINUE:
46.826 - scanner_.scan();
46.827 - statement = new (pool_) ContinueStatement(scanner_.begin());
46.828 - break;
46.829 -
46.830 - case TOK_DO:
46.831 - if ((statement = do_()) == NULL)
46.832 - return NULL;
46.833 - break;
46.834 -
46.835 - case TOK_RETURN:
46.836 - if ((statement = returnStatement()) == NULL)
46.837 - return NULL;
46.838 - break;
46.839 -
46.840 - case TOK_ENUM:
46.841 - if ((statement = enum_()) == NULL)
46.842 - return NULL;
46.843 - break;
46.844 -
46.845 - case TOK_IF:
46.846 - return if_();
46.847 -
46.848 - case TOK_LBRACE:
46.849 - return block();
46.850 -
46.851 - default:
46.852 - break;
46.853 - }
46.854 -
46.855 - if (!statement) {
46.856 - if ((statement = expressionStatement()) == NULL)
46.857 - return NULL;
46.858 - }
46.859 -
46.860 - if (!expect(TOK_SEMICOLON))
46.861 - return NULL;
46.862 -
46.863 - return statement;
46.864 -}
46.865 -
46.866 -Statement *
46.867 -Parser::enum_()
46.868 -{
46.869 - expect(TOK_ENUM);
46.870 -
46.871 - SourcePosition pos = scanner_.begin();
46.872 -
46.873 - Local<String> name(zone_);
46.874 - if (matchName(name.ref())) {
46.875 - if (!name)
46.876 - return NULL;
46.877 -
46.878 - if (BoundName *other = scope_->localLookup(name)) {
46.879 - redeclarationError(other);
46.880 - return NULL;
46.881 - }
46.882 -
46.883 - if (!scope_->declareEnum(name, scanner_.begin()))
46.884 - return NULL;
46.885 - }
46.886 -
46.887 - EnumStatement::EntryList *entries = new (pool_) EnumStatement::EntryList();
46.888 -
46.889 - if (!expect(TOK_LBRACE))
46.890 - return NULL;
46.891 -
46.892 - do {
46.893 - if (scanner_.peek() == TOK_RBRACE)
46.894 - break;
46.895 -
46.896 - Local<String> name(zone_, expectName());
46.897 - if (!name)
46.898 - return NULL;
46.899 -
46.900 - if (BoundName *other = scope_->localLookup(name)) {
46.901 - redeclarationError(other);
46.902 - return NULL;
46.903 - }
46.904 -
46.905 - NamedConstant *constant = scope_->declareConstant(name, scanner_.begin());
46.906 - if (!constant)
46.907 - return NULL;
46.908 -
46.909 - Expression *expr = NULL;
46.910 - if (match(TOK_ASSIGN)) {
46.911 - if ((expr = expression()) == NULL)
46.912 - return NULL;
46.913 - }
46.914 -
46.915 - if (!entries->append(EnumStatement::Entry(constant, expr)))
46.916 - return NULL;
46.917 - } while (match(TOK_COMMA));
46.918 - if (!expect(TOK_RBRACE))
46.919 - return NULL;
46.920 -
46.921 - return new (pool_) EnumStatement(pos, name, entries);
46.922 -}
46.923 -
46.924 -Statement *
46.925 -Parser::function(TokenKind token)
46.926 -{
46.927 - Local<String> name(zone_, expectName());
46.928 - if (!name)
46.929 - return NULL;
46.930 -
46.931 - SourcePosition pos = scanner_.begin();
46.932 -
46.933 - // The function name goes into the outer (global) scope.
46.934 - assert(!scope_->enclosing());
46.935 -
46.936 - NamedFunction *fun;
46.937 - if (BoundName *other = scope_->localLookup(name)) {
46.938 - // We allow a redeclaration if the new type is a public, and the old
46.939 - // type was a forward. However, the forward must come first.
46.940 - if (other->kind() != BoundName::FUNCTION) {
46.941 - redeclarationError(other);
46.942 - return NULL;
46.943 - }
46.944 -
46.945 - fun = other->toNamedFunction();
46.946 - if (!fun->isForward() || token != TOK_PUBLIC) {
46.947 - redeclarationError(other);
46.948 - return NULL;
46.949 - }
46.950 -
46.951 - // We've got the same name, but the original is a forward, so let it
46.952 - // slide and re-use the original declaration.
46.953 - fun->setImplemented(scanner_.begin());
46.954 - } else {
46.955 - fun = scope_->declareFunction(name, scanner_.begin(), token);
46.956 - if (!fun)
46.957 - return NULL;
46.958 - }
46.959 -
46.960 - Scope *scope = enterScope(Scope::FUNCTION);
46.961 - if (!scope)
46.962 - return NULL;
46.963 -
46.964 - ParameterList *parameters = new (pool_) ParameterList();
46.965 -
46.966 - if (!expect(TOK_LPAREN))
46.967 - return NULL;
46.968 - if (!match(TOK_RPAREN)) {
46.969 - while (true) {
46.970 - bool isConst = match(TOK_CONST);
46.971 - bool ref = match(TOK_AMPERSAND);
46.972 -
46.973 - SourcePosition begin = scanner_.begin();
46.974 - Local<String> tag(zone_);
46.975 - if (matchName(tag.ref(), TOK_LABEL) && !tag)
46.976 - return NULL;
46.977 -
46.978 - if (match(TOK_ELLIPSES)) {
46.979 - if (isConst || ref) {
46.980 - cc_.reportError(begin, Message_InvalidVarArgs);
46.981 - return NULL;
46.982 - }
46.983 -
46.984 - if (token != TOK_NATIVE) {
46.985 - cc_.reportError(begin, Message_VarArgsOutsideNative);
46.986 - return NULL;
46.987 - }
46.988 -
46.989 - fun->markNativeVariadic();
46.990 - break;
46.991 - }
46.992 -
46.993 - Local<String> name(zone_, expectName());
46.994 - if (!name)
46.995 - return NULL;
46.996 -
46.997 - if (BoundName *other = scope_->localLookup(name)) {
46.998 - redeclarationError(other);
46.999 - return NULL;
46.1000 - }
46.1001 - Variable *arg = scope_->declareArgument(name, scanner_.begin());
46.1002 - if (!arg)
46.1003 - return NULL;
46.1004 -
46.1005 - // Look for dimensions.
46.1006 - ExpressionList *postDimensions = NULL;
46.1007 - while (match(TOK_LBRACKET)) {
46.1008 - if (!postDimensions)
46.1009 - postDimensions = new (pool_) ExpressionList();
46.1010 -
46.1011 - Expression *dim = NULL;
46.1012 - if (!match(TOK_RBRACKET)) {
46.1013 - if ((dim = expression()) == NULL)
46.1014 - return NULL;
46.1015 - if (!expect(TOK_RBRACKET))
46.1016 - return NULL;
46.1017 - }
46.1018 -
46.1019 - if (!postDimensions->append(dim))
46.1020 - return NULL;
46.1021 - }
46.1022 -
46.1023 - Parameter *parameter = new (pool_) Parameter(arg, tag, ref, isConst, postDimensions);
46.1024 - if (!parameters->append(parameter))
46.1025 - return NULL;
46.1026 -
46.1027 - if (!match(TOK_COMMA))
46.1028 - break;
46.1029 - }
46.1030 - if (!expect(TOK_RPAREN))
46.1031 - return NULL;
46.1032 - }
46.1033 -
46.1034 - encounteredReturn_ = false;
46.1035 -
46.1036 - Statement *body = NULL;
46.1037 - if (token != TOK_FORWARD && token != TOK_NATIVE) {
46.1038 - body = block();
46.1039 - if (!body)
46.1040 - return NULL;
46.1041 - }
46.1042 -
46.1043 - scope_ = scope_->enclosing();
46.1044 - return new (pool_) FunctionStatement(pos, scope, fun, body, parameters, encounteredReturn_);
46.1045 -}
46.1046 -
46.1047 -ParseTree *
46.1048 -Parser::parse()
46.1049 -{
46.1050 - StatementList *statements = new (pool_) StatementList();
46.1051 -
46.1052 - if (!enterScope(Scope::GLOBAL))
46.1053 - return NULL;
46.1054 -
46.1055 - for (;;) {
46.1056 - Statement *statement = NULL;
46.1057 -
46.1058 - switch (scanner_.peek()) {
46.1059 - case TOK_ERROR:
46.1060 - return NULL;
46.1061 -
46.1062 - case TOK_EOF:
46.1063 - break;
46.1064 -
46.1065 - case TOK_NAME:
46.1066 - if ((statement = function(TOK_NAME)) == NULL)
46.1067 - return NULL;
46.1068 - break;
46.1069 -
46.1070 - case TOK_FORWARD:
46.1071 - case TOK_PUBLIC:
46.1072 - case TOK_NATIVE:
46.1073 - {
46.1074 - TokenKind kind = scanner_.scan();
46.1075 - if ((statement = function(kind)) == NULL)
46.1076 - return NULL;
46.1077 - if ((kind == TOK_FORWARD || kind == TOK_NATIVE) && !matchSemicolon())
46.1078 - return NULL;
46.1079 - break;
46.1080 - }
46.1081 -
46.1082 - case TOK_NEW:
46.1083 - {
46.1084 - if ((statement = variableDeclaration()) == NULL)
46.1085 - return NULL;
46.1086 - if (!matchSemicolon())
46.1087 - return NULL;
46.1088 - break;
46.1089 - }
46.1090 -
46.1091 - case TOK_ENUM:
46.1092 - if ((statement = enum_()) == NULL)
46.1093 - return NULL;
46.1094 - if (!matchSemicolon())
46.1095 - return NULL;
46.1096 - break;
46.1097 -
46.1098 - default:
46.1099 - cc_.reportError(scanner_.begin(), Message_ExpectedGlobal);
46.1100 - return NULL;
46.1101 - }
46.1102 -
46.1103 - if (!statement)
46.1104 - break;
46.1105 -
46.1106 - if (!statements->append(statement))
46.1107 - return NULL;
46.1108 - }
46.1109 -
46.1110 - return new (pool_) ParseTree(scope_, statements, unbound_);
46.1111 -}
46.1112 -
46.1113 -class AstPrinter : public AstVisitor
46.1114 -{
46.1115 - FILE *fp_;
46.1116 - size_t level_;
46.1117 -
46.1118 - private:
46.1119 - void prefix() {
46.1120 - for (size_t i = 0; i < level_; i++)
46.1121 - fprintf(fp_, " ");
46.1122 - }
46.1123 - void indent() {
46.1124 - level_++;
46.1125 - }
46.1126 - void unindent() {
46.1127 - level_--;
46.1128 - }
46.1129 -
46.1130 - public:
46.1131 - AstPrinter(FILE *fp)
46.1132 - : fp_(fp),
46.1133 - level_(0)
46.1134 - {
46.1135 - }
46.1136 -
46.1137 - void visit(NameProxy *name) {
46.1138 - prefix();
46.1139 - fprintf(fp_, "[ NameProxy (%s)%s\n", name->name()->chars(),
46.1140 - (name->binding() ? "" : " unbound"));
46.1141 - }
46.1142 - void visit(CallExpression *node) {
46.1143 - prefix();
46.1144 - fprintf(fp_, "[ CallExpression\n");
46.1145 - indent();
46.1146 - node->callee()->accept(this);
46.1147 - for (size_t i = 0; i < node->arguments()->length(); i++)
46.1148 - node->arguments()->at(i)->accept(this);
46.1149 - unindent();
46.1150 - }
46.1151 - void visit(FunctionStatement *node) {
46.1152 - prefix();
46.1153 - fprintf(fp_, "[ FunctionStatement (%s)\n", node->fun()->name()->chars());
46.1154 - indent();
46.1155 - if (node->body())
46.1156 - node->body()->accept(this);
46.1157 - unindent();
46.1158 - }
46.1159 - void visit(ExpressionStatement *node) {
46.1160 - prefix();
46.1161 - fprintf(fp_, "[ ExpressionStatement\n");
46.1162 - indent();
46.1163 - node->expression()->accept(this);
46.1164 - unindent();
46.1165 - }
46.1166 - void visit(Assignment *node) {
46.1167 - prefix();
46.1168 - fprintf(fp_, "[ Assignment\n");
46.1169 - indent();
46.1170 - node->lvalue()->accept(this);
46.1171 - node->expression()->accept(this);
46.1172 - unindent();
46.1173 - }
46.1174 - void visit(TernaryExpression *node) {
46.1175 - prefix();
46.1176 - fprintf(fp_, "[ TernaryExpression\n");
46.1177 - indent();
46.1178 - node->condition()->accept(this);
46.1179 - node->left()->accept(this);
46.1180 - node->right()->accept(this);
46.1181 - unindent();
46.1182 - }
46.1183 - void visit(BinaryExpression *node) {
46.1184 - prefix();
46.1185 - fprintf(fp_, "[ BinaryExpression (%s)\n", TokenNames[node->token()]);
46.1186 - indent();
46.1187 - node->left()->accept(this);
46.1188 - node->right()->accept(this);
46.1189 - unindent();
46.1190 - }
46.1191 - void visit(UnaryExpression *node) {
46.1192 - prefix();
46.1193 - fprintf(fp_, "[ UnaryExpression (%s)\n", TokenNames[node->token()]);
46.1194 - indent();
46.1195 - node->expression()->accept(this);
46.1196 - unindent();
46.1197 - }
46.1198 - void visit(ReturnStatement *node) {
46.1199 - prefix();
46.1200 - fprintf(fp_, "[ ReturnStatement\n");
46.1201 - indent();
46.1202 - if (node->expression())
46.1203 - node->expression()->accept(this);
46.1204 - unindent();
46.1205 - }
46.1206 - void visit(ForStatement *node) {
46.1207 - prefix();
46.1208 - fprintf(fp_, "[ ForStatement\n");
46.1209 - indent();
46.1210 - if (node->initialization())
46.1211 - node->initialization()->accept(this);
46.1212 - if (node->condition())
46.1213 - node->condition()->accept(this);
46.1214 - if (node->update())
46.1215 - node->update()->accept(this);
46.1216 - node->body()->accept(this);
46.1217 - unindent();
46.1218 - }
46.1219 - void visit(BlockStatement *node) {
46.1220 - prefix();
46.1221 - fprintf(fp_, "[ BlockStatement\n");
46.1222 - indent();
46.1223 - for (size_t i = 0; i < node->statements()->length(); i++)
46.1224 - node->statements()->at(i)->accept(this);
46.1225 - unindent();
46.1226 - }
46.1227 - void visit(VariableDeclaration *node) {
46.1228 - prefix();
46.1229 - fprintf(fp_, "[ VariableDeclaration (%s)\n", node->variable()->name()->chars());
46.1230 - indent();
46.1231 - if (node->initialization())
46.1232 - node->initialization()->accept(this);
46.1233 - unindent();
46.1234 - }
46.1235 - void visit(IntegerLiteral *node) {
46.1236 - prefix();
46.1237 - fprintf(fp_, "[ IntegerLiteral (%d)\n", node->value());
46.1238 - }
46.1239 - void visit(FloatLiteral *node) {
46.1240 - prefix();
46.1241 - fprintf(fp_, "[ FloatLiteral (%f)\n", node->value());
46.1242 - }
46.1243 - void visit(IfStatement *node) {
46.1244 - prefix();
46.1245 - fprintf(fp_, "[ IfStatement\n");
46.1246 - indent();
46.1247 - node->ifTrue()->accept(this);
46.1248 - if (node->ifFalse())
46.1249 - node->ifFalse()->accept(this);
46.1250 - unindent();
46.1251 - }
46.1252 - void visit(IndexExpression *node) {
46.1253 - prefix();
46.1254 - fprintf(fp_, "[ IndexExpression\n");
46.1255 - indent();
46.1256 - node->left()->accept(this);
46.1257 - node->right()->accept(this);
46.1258 - unindent();
46.1259 - }
46.1260 - void visit(EnumStatement *node) {
46.1261 - prefix();
46.1262 - fprintf(fp_, "[ EnumStatement (%s)\n", node->name() ? node->name()->chars() : "<anonymous>");
46.1263 - indent();
46.1264 - for (size_t i = 0; i < node->entries()->length(); i++) {
46.1265 - prefix();
46.1266 - fprintf(fp_, "%s =\n", node->entries()->at(i).name->name()->chars());
46.1267 - if (node->entries()->at(i).expr) {
46.1268 - indent();
46.1269 - node->entries()->at(i).expr->accept(this);
46.1270 - unindent();
46.1271 - }
46.1272 - }
46.1273 - unindent();
46.1274 - }
46.1275 - void visit(WhileStatement *node) {
46.1276 - prefix();
46.1277 - fprintf(fp_, "[ WhileStatement (%s)\n",
46.1278 - (node->token() == TOK_DO) ? "do" : "while");
46.1279 - indent();
46.1280 - if (node->token() == TOK_DO) {
46.1281 - node->condition()->accept(this);
46.1282 - node->body()->accept(this);
46.1283 - } else {
46.1284 - node->condition()->accept(this);
46.1285 - node->body()->accept(this);
46.1286 - }
46.1287 - unindent();
46.1288 - }
46.1289 - void visit(BreakStatement *node) {
46.1290 - prefix();
46.1291 - fprintf(fp_, "[ BreakStatement\n");
46.1292 - }
46.1293 - void visit(ContinueStatement *node) {
46.1294 - prefix();
46.1295 - fprintf(fp_, "[ ContinueStatement\n");
46.1296 - }
46.1297 - void visit(StringLiteral *node) {
46.1298 - prefix();
46.1299 - fprintf(fp_, "[ StringLiteral\n");
46.1300 - }
46.1301 - void visit(IncDecExpression *node) {
46.1302 - prefix();
46.1303 - fprintf(fp_, "[ IncDecExpression (postfix=%d)\n", node->postfix());
46.1304 - indent();
46.1305 - node->expression()->accept(this);
46.1306 - unindent();
46.1307 - }
46.1308 -};
46.1309 -
46.1310 -void
46.1311 -ParseTree::dump(FILE *fp)
46.1312 -{
46.1313 - AstPrinter printer(fp);
46.1314 -
46.1315 - for (size_t i = 0; i < statements_->length(); i++)
46.1316 - statements_->at(i)->accept(&printer);
46.1317 -}
47.1 --- a/jitcraft/Parser.h Tue Jul 24 23:53:34 2012 -0700
47.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
47.3 @@ -1,91 +0,0 @@
47.4 -/*
47.5 - * Copyright (C) 2012 David Anderson
47.6 - *
47.7 - * This file is part of JITCraft.
47.8 - *
47.9 - * JITCraft is free software: you can redistribute it and/or modify it under
47.10 - * the terms of the GNU General Public License as published by the Free
47.11 - * Software Foundation, either version 3 of the License, or (at your option)
47.12 - * any later version.
47.13 - *
47.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
47.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
47.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
47.17 - *
47.18 - * You should have received a copy of the GNU General Public License along with
47.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
47.20 - */
47.21 -#ifndef _include_jitcraft_parser_h_
47.22 -#define _include_jitcraft_parser_h_
47.23 -
47.24 -#include <stdio.h>
47.25 -#include "AST.h"
47.26 -#include "Scanner.h"
47.27 -#include "Scopes.h"
47.28 -#include "Strings.h"
47.29 -
47.30 -namespace ke {
47.31 -
47.32 -class Parser
47.33 -{
47.34 - Zone *zone_;
47.35 - CompileContext &cc_;
47.36 - PoolAllocator &pool_;
47.37 - Scanner scanner_;
47.38 - Scope *scope_;
47.39 - PoolList<NameProxy *> *unbound_;
47.40 - bool encounteredReturn_;
47.41 -
47.42 - private:
47.43 - void redeclarationError(BoundName *name);
47.44 - bool match(TokenKind kind);
47.45 - bool expect(TokenKind kind);
47.46 - bool matchSemicolon();
47.47 -
47.48 - Scope *enterScope(Scope::Kind kind);
47.49 -
47.50 - VariableDeclaration *variableDeclaration();
47.51 - bool matchName(String **name, TokenKind kind = TOK_NAME);
47.52 - String *expectName();
47.53 - NameProxy *bind(Handle<String> name);
47.54 - Expression *primitive();
47.55 - Expression *call(Expression *callee);
47.56 - Expression *index(Expression *left);
47.57 - Expression *prefix();
47.58 - Expression *primary();
47.59 - Expression *unary();
47.60 - Expression *multiplication();
47.61 - Expression *addition();
47.62 - Expression *shift();
47.63 - Expression *bitand_();
47.64 - Expression *bitxor();
47.65 - Expression *bitor_();
47.66 - Expression *relational();
47.67 - Expression *equals();
47.68 - Expression *and_();
47.69 - Expression *or_();
47.70 - Expression *ternary();
47.71 - Expression *assignment();
47.72 - Expression *expression();
47.73 -
47.74 - Statement *enum_();
47.75 - Statement *if_();
47.76 - Statement *block(Scope *scope = NULL);
47.77 - Statement *function(TokenKind tok);
47.78 - Statement *expressionStatement();
47.79 - Statement *while_();
47.80 - Statement *do_();
47.81 - Statement *forStatement();
47.82 - Statement *localStatement();
47.83 - Statement *globalStatement();
47.84 - Statement *returnStatement();
47.85 -
47.86 - public:
47.87 - Parser(Zone *zone, CompileContext &cc, const char *stream, size_t length);
47.88 -
47.89 - ParseTree *parse();
47.90 -};
47.91 -
47.92 -}
47.93 -
47.94 -#endif // _include_jitcraft_parser_h_
48.1 --- a/jitcraft/Platform-Posix.cpp Tue Jul 24 23:53:34 2012 -0700
48.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
48.3 @@ -1,101 +0,0 @@
48.4 -/* vim: set ts=4 sw=4 tw=99 et:
48.5 - *
48.6 - * Copyright (C) 2012 David Anderson
48.7 - *
48.8 - * This file is part of JITCraft.
48.9 - *
48.10 - * JITCraft is free software: you can redistribute it and/or modify it under
48.11 - * the terms of the GNU General Public License as published by the Free
48.12 - * Software Foundation, either version 3 of the License, or (at your option)
48.13 - * any later version.
48.14 - *
48.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
48.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
48.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
48.18 - *
48.19 - * You should have received a copy of the GNU General Public License along with
48.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
48.21 - */
48.22 -#include <sys/mman.h>
48.23 -#include "Platform.h"
48.24 -
48.25 -using namespace jc;
48.26 -
48.27 -static inline int
48.28 -ToProtBits(OS::Protection prot)
48.29 -{
48.30 - switch (prot) {
48.31 - case OS::Prot_ReadWrite:
48.32 - return PROT_READ | PROT_WRITE;
48.33 - case OS::Prot_ReadWriteExecute:
48.34 - return PROT_READ | PROT_WRITE | PROT_EXEC;
48.35 - default:
48.36 - assert(prot == OS::Prot_ReadExecute);
48.37 - return PROT_READ | PROT_EXEC;
48.38 - }
48.39 -}
48.40 -
48.41 -Address
48.42 -OS::MapMemory(size_t amount, MapMode mode, Protection prot_)
48.43 -{
48.44 - int prot = ToProtBits(prot_);
48.45 - void *addr = mmap(NULL, amount, prot, MAP_ANON | MAP_PRIVATE, -1, 0);
48.46 - if (addr == MAP_FAILED)
48.47 - return NULL;
48.48 -
48.49 - return Address(addr);
48.50 -}
48.51 -
48.52 -bool
48.53 -OS::CommitMemory(Address address, size_t amount, Protection prot_)
48.54 -{
48.55 - return true;
48.56 -}
48.57 -
48.58 -void
48.59 -OS::UnmapMemory(Address address, size_t size)
48.60 -{
48.61 - munmap(address, size);
48.62 -}
48.63 -
48.64 -OS::AlignableMapping
48.65 -OS::MapAlignedMemory(size_t amount, size_t alignment, MapMode mode)
48.66 -{
48.67 - assert(amount >= alignment);
48.68 - assert(IsPowerOfTwo(alignment));
48.69 -
48.70 - if (alignment == kPageAlignment) {
48.71 - Address address = MapMemory(amount, mode, Prot_ReadWrite);
48.72 - if (!address)
48.73 - return AlignableMapping();
48.74 - return AlignableMapping(address, alignment, amount);
48.75 - }
48.76 -
48.77 - size_t requested = Min(amount * 2, amount + 2 * alignment);
48.78 - Address address = MapMemory(amount, mode, Prot_ReadWrite);
48.79 - if (!address)
48.80 - return AlignableMapping();
48.81 -
48.82 - size_t begin = 0;
48.83 - Address aligned = AlignedBase(address, alignment);
48.84 - if (!IsAligned(address, alignment)) {
48.85 - // Shave off the first part of the unaligned region.
48.86 - aligned += alignment;
48.87 - begin = size_t(aligned - address);
48.88 - UnmapAlignedMemory(address, begin);
48.89 - }
48.90 -
48.91 - if (requested - begin > amount) {
48.92 - // Shave off the last part of the unaligned region.
48.93 - UnmapAlignedMemory(address + amount, requested - amount - begin);
48.94 - }
48.95 -
48.96 - return AlignableMapping(aligned, alignment, amount);
48.97 -}
48.98 -
48.99 -void
48.100 -OS::UnmapAlignedMemory(Address address, size_t size)
48.101 -{
48.102 - OS::UnmapMemory(address, size);
48.103 -}
48.104 -
49.1 --- a/jitcraft/Platform-Windows.cpp Tue Jul 24 23:53:34 2012 -0700
49.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
49.3 @@ -1,111 +0,0 @@
49.4 -/* vim: set ts=4 sw=4 tw=99 et:
49.5 - *
49.6 - * Copyright (C) 2012 David Anderson
49.7 - *
49.8 - * This file is part of JITCraft.
49.9 - *
49.10 - * JITCraft is free software: you can redistribute it and/or modify it under
49.11 - * the terms of the GNU General Public License as published by the Free
49.12 - * Software Foundation, either version 3 of the License, or (at your option)
49.13 - * any later version.
49.14 - *
49.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
49.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
49.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
49.18 - *
49.19 - * You should have received a copy of the GNU General Public License along with
49.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
49.21 - */
49.22 -
49.23 -// :TODO: move into utility-style include
49.24 -#define WIN32_LEAN_AND_MEAN
49.25 -#include <Windows.h>
49.26 -#include "Platform.h"
49.27 -
49.28 -using namespace ke;
49.29 -
49.30 -static inline DWORD
49.31 -ToProtBits(OS::Protection prot)
49.32 -{
49.33 - switch (prot) {
49.34 - case OS::Prot_ReadWrite:
49.35 - return PAGE_READWRITE;
49.36 - case OS::Prot_ReadWriteExecute:
49.37 - return PAGE_EXECUTE_READWRITE;
49.38 - default:
49.39 - assert(prot == OS::Prot_ReadExecute);
49.40 - return PAGE_EXECUTE_READ;
49.41 - }
49.42 -}
49.43 -
49.44 -Address
49.45 -OS::MapMemory(size_t amount, MapMode mode, Protection prot_)
49.46 -{
49.47 - DWORD prot = ToProtBits(prot_);
49.48 - DWORD type = MEM_RESERVE;
49.49 - if (mode == Map_Commit)
49.50 - type |= MEM_COMMIT;
49.51 -
49.52 - return (Address)VirtualAlloc(NULL, amount, type, prot);
49.53 -}
49.54 -
49.55 -bool
49.56 -OS::CommitMemory(Address address, size_t amount, Protection prot_)
49.57 -{
49.58 - DWORD prot = ToProtBits(prot_);
49.59 - return !!VirtualAlloc(address, amount, MEM_COMMIT, prot);
49.60 -}
49.61 -
49.62 -void
49.63 -OS::UnmapMemory(Address address, size_t size)
49.64 -{
49.65 - VirtualFree(address, 0, MEM_RELEASE);
49.66 -}
49.67 -
49.68 -static Address
49.69 -MapMemoryAt(Address address, size_t amount, OS::MapMode mode, OS::Protection prot_)
49.70 -{
49.71 - DWORD bits = ToProtBits(prot_);
49.72 - DWORD flags = MEM_RESERVE;
49.73 - if (mode == OS::Map_Commit)
49.74 - flags |= MEM_COMMIT;
49.75 -
49.76 - return (Address)VirtualAlloc((LPVOID)address, amount, flags, bits);
49.77 -}
49.78 -
49.79 -OS::AlignableMapping
49.80 -OS::MapAlignedMemory(size_t amount, size_t alignment, MapMode mode)
49.81 -{
49.82 - Address addr = MapMemory(amount, mode, OS::Prot_ReadWrite);
49.83 - if (!addr)
49.84 - return AlignableMapping(NULL, alignment, 0);
49.85 -
49.86 - if (!IsAligned(addr, alignment)) {
49.87 - UnmapMemory(addr, amount);
49.88 -
49.89 - // Try to grab the next available aligned address.
49.90 - addr = AlignedBase(addr, alignment);
49.91 - addr = MapMemoryAt(addr + alignment, amount, mode, OS::Prot_ReadWrite);
49.92 - while (!addr) {
49.93 - // Try to over-allocate to get the right region. This can race
49.94 - // with other threads; we expect this to be rare. If this turns
49.95 - // out to be a problem, the API is set up such that we can just
49.96 - // return two pointers: the base, and the aligned address into
49.97 - // the over-allocated region.
49.98 - addr = MapMemory(amount + alignment, mode, OS::Prot_ReadWrite);
49.99 - if (!addr)
49.100 - return AlignableMapping(NULL, alignment, 0);
49.101 - UnmapMemory(addr, amount + alignment);
49.102 - addr = AlignedBase(addr, alignment);
49.103 - addr = MapMemoryAt(addr + alignment, amount, mode, OS::Prot_ReadWrite);
49.104 - }
49.105 - }
49.106 -
49.107 - return AlignableMapping(addr, alignment, amount);
49.108 -}
49.109 -
49.110 -void
49.111 -OS::UnmapAlignedMemory(Address address, size_t size)
49.112 -{
49.113 - OS::UnmapMemory(address, size);
49.114 -}
50.1 --- a/jitcraft/Platform.h Tue Jul 24 23:53:34 2012 -0700
50.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
50.3 @@ -1,91 +0,0 @@
50.4 -/* vim: set ts=4 sw=4 tw=99 et:
50.5 - *
50.6 - * Copyright (C) 2012 David Anderson
50.7 - *
50.8 - * This file is part of JITCraft.
50.9 - *
50.10 - * JITCraft is free software: you can redistribute it and/or modify it under
50.11 - * the terms of the GNU General Public License as published by the Free
50.12 - * Software Foundation, either version 3 of the License, or (at your option)
50.13 - * any later version.
50.14 - *
50.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
50.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
50.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
50.18 - *
50.19 - * You should have received a copy of the GNU General Public License along with
50.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
50.21 - */
50.22 -#ifndef _include_jitcraft_platform_h_
50.23 -#define _include_jitcraft_platform_h_
50.24 -
50.25 -#include "Utility.h"
50.26 -
50.27 -namespace ke {
50.28 -
50.29 -namespace OS {
50.30 - enum Protection {
50.31 - Prot_ReadWrite, // rw-, for the heap
50.32 - Prot_ReadExecute, // r-x, for code
50.33 - Prot_ReadWriteExecute // rwx, if disabling r-x for code.
50.34 - };
50.35 -
50.36 - enum MapMode {
50.37 - Map_Reserve, // don't ask for actual pages yet
50.38 - Map_Commit // ask for pages right away
50.39 - };
50.40 -
50.41 - Address MapMemory(size_t amount, MapMode mode, Protection prot);
50.42 - bool CommitMemory(Address address, size_t amount, Protection prot);
50.43 - void UnmapMemory(Address address, size_t size);
50.44 -
50.45 - class AlignableMapping {
50.46 - Address base_;
50.47 - Address aligned_;
50.48 - size_t size_;
50.49 -
50.50 - public:
50.51 - AlignableMapping(Address ptr, size_t alignment, size_t size)
50.52 - : base_(ptr),
50.53 - size_(size)
50.54 - {
50.55 - aligned_ = base_;
50.56 - if (!IsAligned(aligned_, alignment))
50.57 - aligned_ = AlignedBase(aligned_, alignment) + alignment;
50.58 - }
50.59 -
50.60 - AlignableMapping() : base_(NULL), aligned_(NULL), size_(0)
50.61 - {
50.62 - }
50.63 -
50.64 - Address base() const {
50.65 - return base_;
50.66 - }
50.67 - bool isValid() const {
50.68 - return !!base_;
50.69 - }
50.70 - size_t size() const {
50.71 - return size_;
50.72 - }
50.73 - Address aligned() const {
50.74 - return aligned_;
50.75 - }
50.76 - };
50.77 -
50.78 - // MapAlignedMemory is guaranteed to return zeroed memory.
50.79 - AlignableMapping MapAlignedMemory(size_t amount, size_t alignment, MapMode mode);
50.80 - void UnmapAlignedMemory(Address address, size_t size);
50.81 -
50.82 - // The default alignment of memory returned via MapMemory().
50.83 - // :TODO: better ifdefs
50.84 -#ifdef _MSC_VER
50.85 - static const size_t kPageAlignment = 64 * kKB;
50.86 -#else
50.87 - static const size_t kPageAlignment = 4 * kKB;
50.88 -#endif
50.89 -
50.90 -}
50.91 -
50.92 -}
50.93 -
50.94 -#endif // _include_jitcraft_platform_h_
51.1 --- a/jitcraft/PoolAllocator.cpp Tue Jul 24 23:53:34 2012 -0700
51.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
51.3 @@ -1,129 +0,0 @@
51.4 -/*
51.5 - * Copyright (C) 2012 David Anderson
51.6 - *
51.7 - * This file is part of JITCraft.
51.8 - *
51.9 - * JITCraft is free software: you can redistribute it and/or modify it under
51.10 - * the terms of the GNU General Public License as published by the Free
51.11 - * Software Foundation, either version 3 of the License, or (at your option)
51.12 - * any later version.
51.13 - *
51.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
51.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
51.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
51.17 - *
51.18 - * You should have received a copy of the GNU General Public License along with
51.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
51.20 - */
51.21 -#include <assert.h>
51.22 -#include <stdlib.h>
51.23 -#include <new>
51.24 -#include "PoolAllocator.h"
51.25 -#include "Zone.h"
51.26 -
51.27 -using namespace ke;
51.28 -
51.29 -PoolAllocator::PoolAllocator()
51.30 - : reserved_(NULL),
51.31 - last_(NULL)
51.32 -{
51.33 -}
51.34 -
51.35 -PoolAllocator::~PoolAllocator()
51.36 -{
51.37 - unwind(NULL);
51.38 - if (reserved_)
51.39 - free(reserved_);
51.40 -}
51.41 -
51.42 -char *
51.43 -PoolAllocator::enter()
51.44 -{
51.45 - if (!last_)
51.46 - return NULL;
51.47 - return last_->ptr;
51.48 -}
51.49 -
51.50 -void
51.51 -PoolAllocator::leave(char *pos)
51.52 -{
51.53 - unwind(pos);
51.54 -}
51.55 -
51.56 -void
51.57 -PoolAllocator::unwind(char *pos)
51.58 -{
51.59 - while (last_) {
51.60 - if (pos && pos >= last_->base && pos < last_->end)
51.61 - break;
51.62 - Pool *prev = last_->prev;
51.63 - {
51.64 - if (last_->size() <= kMaxReserveSize &&
51.65 - (!reserved_ || reserved_->size() < last_->size()))
51.66 - {
51.67 - if (reserved_)
51.68 - free(reserved_);
51.69 - reserved_ = last_;
51.70 - } else {
51.71 - free(last_);
51.72 - }
51.73 - }
51.74 - last_ = prev;
51.75 - }
51.76 -
51.77 - if (!last_) {
51.78 - assert(!pos);
51.79 - return;
51.80 - }
51.81 -
51.82 - last_->ptr = pos;
51.83 -}
51.84 -
51.85 -void *
51.86 -PoolAllocator::slowAllocate(size_t actualBytes)
51.87 -{
51.88 - size_t bytesNeeded = actualBytes + sizeof(Pool);
51.89 - if (bytesNeeded < kDefaultPoolSize)
51.90 - bytesNeeded = kDefaultPoolSize;
51.91 -
51.92 - Pool *pool;
51.93 - if (reserved_ && reserved_->size() >= bytesNeeded) {
51.94 - pool = reserved_;
51.95 - reserved_ = NULL;
51.96 - } else {
51.97 - pool = (Pool *)malloc(bytesNeeded);
51.98 - if (!pool) {
51.99 - ZONE()->reportOutOfMemory();
51.100 - return NULL;
51.101 - }
51.102 - pool->base = (char *)(pool + 1);
51.103 - pool->end = (char *)pool + bytesNeeded;
51.104 - }
51.105 - pool->ptr = pool->base + actualBytes;
51.106 - pool->prev = last_;
51.107 - last_ = pool;
51.108 - return pool->base;
51.109 -}
51.110 -
51.111 -void
51.112 -PoolAllocationPolicy::reportOutOfMemory()
51.113 -{
51.114 - ZONE()->reportOutOfMemory();
51.115 -}
51.116 -
51.117 -void
51.118 -PoolAllocationPolicy::reportAllocationOverflow()
51.119 -{
51.120 - ZONE()->reportError(Message_AllocationOverflow);
51.121 -}
51.122 -
51.123 -void *
51.124 -PoolAllocationPolicy::malloc(size_t bytes)
51.125 -{
51.126 - return ZONE()->pool().allocate(bytes);
51.127 -}
51.128 -
51.129 -void
51.130 -PoolAllocationPolicy::free(void *ptr)
51.131 -{
51.132 -}
52.1 --- a/jitcraft/PoolAllocator.h Tue Jul 24 23:53:34 2012 -0700
52.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
52.3 @@ -1,136 +0,0 @@
52.4 -/*
52.5 - * Copyright (C) 2012 David Anderson
52.6 - *
52.7 - * This file is part of JITCraft.
52.8 - *
52.9 - * JITCraft is free software: you can redistribute it and/or modify it under
52.10 - * the terms of the GNU General Public License as published by the Free
52.11 - * Software Foundation, either version 3 of the License, or (at your option)
52.12 - * any later version.
52.13 - *
52.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
52.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
52.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
52.17 - *
52.18 - * You should have received a copy of the GNU General Public License along with
52.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
52.20 - */
52.21 -#ifndef _include_jitcraft_pool_allocator_h_
52.22 -#define _include_jitcraft_pool_allocator_h_
52.23 -
52.24 -#include <new>
52.25 -#include <stddef.h>
52.26 -#include <limits.h>
52.27 -#include "Utility.h"
52.28 -#include "Vector.h"
52.29 -
52.30 -namespace ke {
52.31 -
52.32 -// Allocates memory in chunks that are not freed until the entire allocator
52.33 -// is freed. This is intended for use with large, temporary data structures.
52.34 -class PoolAllocator
52.35 -{
52.36 - friend class PoolAllocationScope;
52.37 -
52.38 - struct Pool {
52.39 - char *base;
52.40 - char *ptr;
52.41 - char *end;
52.42 - Pool *prev;
52.43 -
52.44 - size_t size() const {
52.45 - return size_t(end - base);
52.46 - }
52.47 - };
52.48 -
52.49 - static const size_t kDefaultPoolSize = 8 * 1024;
52.50 - static const size_t kMaxReserveSize = 64 * 1024;
52.51 -
52.52 - private:
52.53 - Pool *reserved_;
52.54 - Pool *last_;
52.55 -
52.56 - private:
52.57 - void unwind(char *pos);
52.58 - void *slowAllocate(size_t actualBytes);
52.59 -
52.60 - public:
52.61 - PoolAllocator();
52.62 - ~PoolAllocator();
52.63 -
52.64 - void *allocate(size_t bytes) {
52.65 - // Guarantee malloc alignment.
52.66 - size_t actualBytes = Align(bytes, kMallocAlignment);
52.67 - if (!last_ || (size_t(last_->end - last_->ptr) < actualBytes))
52.68 - return slowAllocate(actualBytes);
52.69 - char *ptr = last_->ptr;
52.70 - last_->ptr += actualBytes;
52.71 - return ptr;
52.72 - }
52.73 -
52.74 - char *enter();
52.75 - void leave(char *position);
52.76 -};
52.77 -
52.78 -class PoolScope
52.79 -{
52.80 - PoolAllocator &pool_;
52.81 - char *position_;
52.82 -
52.83 - public:
52.84 - PoolScope(PoolAllocator &allocator)
52.85 - : pool_(allocator),
52.86 - position_(allocator.enter())
52.87 - {
52.88 - }
52.89 - ~PoolScope()
52.90 - {
52.91 - pool_.leave(position_);
52.92 - }
52.93 -};
52.94 -
52.95 -class PoolObject
52.96 -{
52.97 - public:
52.98 - void *operator new(size_t size, PoolAllocator &pool) {
52.99 - return pool.allocate(size);
52.100 - }
52.101 - void *operator new [](size_t size, PoolAllocator &pool) {
52.102 - return pool.allocate(size);
52.103 - }
52.104 -
52.105 - // Using delete on pool-allocated objects is illegal.
52.106 - void operator delete(void *ptr, PoolAllocator &pool) {
52.107 - assert(false);
52.108 - }
52.109 - void operator delete [](void *ptr, PoolAllocator &pool) {
52.110 - assert(false);
52.111 - }
52.112 -};
52.113 -
52.114 -class PoolAllocationPolicy
52.115 -{
52.116 - protected:
52.117 - void reportAllocationOverflow();
52.118 - void reportOutOfMemory();
52.119 -
52.120 - public:
52.121 - void *malloc(size_t bytes);
52.122 - void free(void *ptr);
52.123 -};
52.124 -
52.125 -template <typename T>
52.126 -class PoolList
52.127 - : public Vector<T, PoolAllocationPolicy>,
52.128 - public PoolObject
52.129 -{
52.130 - public:
52.131 - PoolList()
52.132 - : Vector(PoolAllocationPolicy())
52.133 - {
52.134 - }
52.135 -};
52.136 -
52.137 -}
52.138 -
52.139 -#endif // _include_jitcraft_pool_allocator_h_
53.1 --- a/jitcraft/Reference.cpp Tue Jul 24 23:53:34 2012 -0700
53.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
53.3 @@ -1,58 +0,0 @@
53.4 -/*
53.5 - * Copyright (C) 2012 David Anderson
53.6 - *
53.7 - * This file is part of JITCraft.
53.8 - *
53.9 - * JITCraft is free software: you can redistribute it and/or modify it under
53.10 - * the terms of the GNU General Public License as published by the Free
53.11 - * Software Foundation, either version 3 of the License, or (at your option)
53.12 - * any later version.
53.13 - *
53.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
53.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
53.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
53.17 - *
53.18 - * You should have received a copy of the GNU General Public License along with
53.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
53.20 - */
53.21 -#include "Reference.h"
53.22 -#include "Zone.h"
53.23 -#include "Array.h"
53.24 -#include "Heap-inl.h"
53.25 -
53.26 -using namespace ke;
53.27 -
53.28 -Reference *
53.29 -Reference::NewStack(Zone *zone, void *location, Heap::Tenure tenure)
53.30 -{
53.31 - Local<Reference> ref(zone, Reference::cast(zone->allocate(MapKind_Reference, sizeof(Reference), tenure)));
53.32 - if (!ref)
53.33 - return NULL;
53.34 -
53.35 - ref->location_ = location;
53.36 - return ref;
53.37 -}
53.38 -
53.39 -Reference *
53.40 -Reference::NewStack(Zone *zone, const LocalSlot &slot, Heap::Tenure tenure)
53.41 -{
53.42 - Local<Reference> ref(zone, Reference::cast(zone->allocate(MapKind_Reference, sizeof(Reference), tenure)));
53.43 - if (!ref)
53.44 - return NULL;
53.45 -
53.46 - ref->location_ = &ref->slot_;
53.47 - ref->slot_ = slot;
53.48 - return ref;
53.49 -}
53.50 -
53.51 -Reference *
53.52 -Reference::NewArray(Zone *zone, Handle<Array> base, size_t index, Heap::Tenure tenure)
53.53 -{
53.54 - Local<Reference> ref(zone, Reference::cast(zone->allocate(MapKind_Reference, sizeof(Reference), tenure)));
53.55 - if (!ref)
53.56 - return NULL;
53.57 -
53.58 - ref->location_ = base->slotPtr(index);
53.59 - ref->base_ = base;
53.60 - return ref;
53.61 -}
54.1 --- a/jitcraft/Reference.h Tue Jul 24 23:53:34 2012 -0700
54.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
54.3 @@ -1,73 +0,0 @@
54.4 -/*
54.5 - * Copyright (C) 2012 David Anderson
54.6 - *
54.7 - * This file is part of JITCraft.
54.8 - *
54.9 - * JITCraft is free software: you can redistribute it and/or modify it under
54.10 - * the terms of the GNU General Public License as published by the Free
54.11 - * Software Foundation, either version 3 of the License, or (at your option)
54.12 - * any later version.
54.13 - *
54.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
54.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
54.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
54.17 - *
54.18 - * You should have received a copy of the GNU General Public License along with
54.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
54.20 - */
54.21 -#ifndef _include_jitcraft_reference_h_
54.22 -#define _include_jitcraft_reference_h_
54.23 -
54.24 -#include "Heap.h"
54.25 -#include "Barriers.h"
54.26 -#include "Stack.h"
54.27 -
54.28 -namespace ke {
54.29 -
54.30 -class Array;
54.31 -
54.32 -// A Reference is a typed pointer to another location in memory.
54.33 -class Reference : public Object
54.34 -{
54.35 - void *location_;
54.36 - LocalSlot slot_;
54.37 - Barriered<Array> base_;
54.38 -
54.39 - public:
54.40 - static Reference *NewStack(Zone *zone, void *location, Heap::Tenure tenure = Heap::Tenure_Default);
54.41 - static Reference *NewStack(Zone *zone, const LocalSlot &slot, Heap::Tenure tenure = Heap::Tenure_Default);
54.42 - static Reference *NewArray(Zone *zone, Handle<Array> base, size_t index, Heap::Tenure tenure = Heap::Tenure_Default);
54.43 -
54.44 - int getInt() {
54.45 - return *reinterpret_cast<int *>(location_);
54.46 - }
54.47 - void setInt(int i) {
54.48 - *reinterpret_cast<int *>(location_) = i;
54.49 - }
54.50 - float getFloat() {
54.51 - return *reinterpret_cast<float *>(location_);
54.52 - }
54.53 - void setFloat(float f) {
54.54 - *reinterpret_cast<float *>(location_) = f;
54.55 - }
54.56 -
54.57 - // WARNING! This should only be for Native calls.
54.58 - void *location() {
54.59 - return location_;
54.60 - }
54.61 -
54.62 - // Begin GC Descriptor.
54.63 - static inline size_t offsetOfBase() {
54.64 - return offsetof(Reference, base_);
54.65 - }
54.66 - // End GC Descriptor.
54.67 -
54.68 - static inline Reference *cast(Object *obj) {
54.69 - assert(!obj || obj->is(MapKind_Reference));
54.70 - return reinterpret_cast<Reference *>(obj);
54.71 - }
54.72 -};
54.73 -
54.74 -}
54.75 -
54.76 -#endif // _include_jitcraft_reference_h_
55.1 --- a/jitcraft/RootScopes.cpp Tue Jul 24 23:53:34 2012 -0700
55.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
55.3 @@ -1,85 +0,0 @@
55.4 -/* vim: set ts=4 sw=4 tw=99 et:
55.5 - *
55.6 - * Copyright (C) 2012 David Anderson
55.7 - *
55.8 - * This file is part of JITCraft.
55.9 - *
55.10 - * JITCraft is free software: you can redistribute it and/or modify it under
55.11 - * the terms of the GNU General Public License as published by the Free
55.12 - * Software Foundation, either version 3 of the License, or (at your option)
55.13 - * any later version.
55.14 - *
55.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
55.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
55.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
55.18 - *
55.19 - * You should have received a copy of the GNU General Public License along with
55.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
55.21 - */
55.22 -#include <stdio.h>
55.23 -#include <stdlib.h>
55.24 -#include "RootScopes.h"
55.25 -
55.26 -using namespace ke;
55.27 -
55.28 -RootScopeManager::RootScopeManager()
55.29 - : blocks_(&first_),
55.30 - first_(NULL),
55.31 - scope_(NULL)
55.32 -{
55.33 -}
55.34 -
55.35 -RootScopeManager::~RootScopeManager()
55.36 -{
55.37 - while (blocks_ != &first_) {
55.38 - Block *temp = blocks_;
55.39 - delete blocks_;
55.40 - blocks_ = temp;
55.41 - }
55.42 -}
55.43 -
55.44 -bool
55.45 -RootScopeManager::grow()
55.46 -{
55.47 - assert(blocks_->cur == blocks_->end);
55.48 -
55.49 - Block *block = new Block(blocks_);
55.50 - if (!block) {
55.51 - // We are not prepared for this. We'll start dishing out NULL-valued
55.52 - // ScopedRoots, and the engine generally assumes infallbility. Rather
55.53 - // then NULL check all sorts of nodes on parse trees, or add boolean
55.54 - // setters, for now we just abort.
55.55 - fprintf(stderr, "Unrecoverable error: could not allocate a local root scope. Aborting!\n");
55.56 - abort();
55.57 - return false;
55.58 - }
55.59 -
55.60 - blocks_ = block;
55.61 - return true;
55.62 -}
55.63 -
55.64 -void
55.65 -RootScopeManager::unwindSlow(Object **pos)
55.66 -{
55.67 - for (;;) {
55.68 - if (pos >= blocks_->objects && pos <= blocks_->end)
55.69 - break;
55.70 - assert(blocks_ != &first_);
55.71 - Block *temp = blocks_;
55.72 - delete blocks_;
55.73 - blocks_ = temp;
55.74 - }
55.75 -
55.76 - blocks_->cur = pos;
55.77 -}
55.78 -
55.79 -void
55.80 -RootScopeManager::accept(VirtualObjectVisitor *visitor)
55.81 -{
55.82 - Block *block = blocks_;
55.83 - while (block) {
55.84 - for (Object **ptr = block->objects; ptr < block->cur; ptr++)
55.85 - visitor->visit(ptr);
55.86 - block = block->prev;
55.87 - }
55.88 -}
56.1 --- a/jitcraft/RootScopes.h Tue Jul 24 23:53:34 2012 -0700
56.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
56.3 @@ -1,106 +0,0 @@
56.4 -/* vim: set ts=4 sw=4 tw=99 et:
56.5 - *
56.6 - * Copyright (C) 2012 David Anderson
56.7 - *
56.8 - * This file is part of JITCraft.
56.9 - *
56.10 - * JITCraft is free software: you can redistribute it and/or modify it under
56.11 - * the terms of the GNU General Public License as published by the Free
56.12 - * Software Foundation, either version 3 of the License, or (at your option)
56.13 - * any later version.
56.14 - *
56.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
56.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
56.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
56.18 - *
56.19 - * You should have received a copy of the GNU General Public License along with
56.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
56.21 - */
56.22 -#ifndef _include_jc_root_scopes_h_
56.23 -#define _include_jc_root_scopes_h_
56.24 -
56.25 -#include "../include/keima.h"
56.26 -#include "Objects.h"
56.27 -#include "VirtualObjectVisitor.h"
56.28 -
56.29 -namespace ke {
56.30 -
56.31 -class RootScope;
56.32 -
56.33 -// A RootScopeManager is essentially a specialized PoolAllocator that can
56.34 -// only allocate Object ** entries. It is used to allow huge, temporary
56.35 -// heap data structures like ASTs to hold safe references to objects. When
56.36 -// the data structures is no longer needed, all of the roots are removed
56.37 -// at once.
56.38 -class RootScopeManager
56.39 -{
56.40 - static const size_t kObjectsPerBlock = 4096;
56.41 -
56.42 - struct Block {
56.43 - Object *objects[kObjectsPerBlock];
56.44 - Object **cur;
56.45 - Object **end;
56.46 - Block *prev;
56.47 -
56.48 - Block(Block *prev)
56.49 - : cur(objects),
56.50 - end(objects + kObjectsPerBlock),
56.51 - prev(prev)
56.52 - {
56.53 - }
56.54 - };
56.55 -
56.56 - private:
56.57 - bool grow();
56.58 - void unwindSlow(Object **position);
56.59 -
56.60 - public:
56.61 - RootScopeManager();
56.62 - ~RootScopeManager();
56.63 -
56.64 - Object **position() const {
56.65 - return blocks_->cur;
56.66 - }
56.67 -
56.68 - void unwind(Object **position) {
56.69 - if (position >= blocks_->cur && position <= blocks_->end) {
56.70 - blocks_->cur = position;
56.71 - return;
56.72 - }
56.73 - unwindSlow(position);
56.74 - }
56.75 -
56.76 - Object **make(Object *obj) {
56.77 - assert(scope_);
56.78 - if (blocks_->cur + 1 > blocks_->end) {
56.79 - if (!grow())
56.80 - return NULL;
56.81 - }
56.82 - Object **ptr = blocks_->cur;
56.83 - blocks_->cur++;
56.84 - *ptr = obj;
56.85 - return ptr;
56.86 - }
56.87 -
56.88 - Ke::HandleScope **scope() {
56.89 - return &scope_;
56.90 - }
56.91 -
56.92 - void accept(VirtualObjectVisitor *visitor);
56.93 -
56.94 - private:
56.95 - Block *blocks_;
56.96 - Block first_;
56.97 - Ke::HandleScope *scope_;
56.98 -};
56.99 -
56.100 -class RootScope : public Ke::HandleScope
56.101 -{
56.102 - public:
56.103 - // These are implemented in Zone.h.
56.104 - inline RootScope(Zone *zone);
56.105 -};
56.106 -
56.107 -}
56.108 -
56.109 -#endif // _include_jc_root_scope_h_
57.1 --- a/jitcraft/Scanner.cpp Tue Jul 24 23:53:34 2012 -0700
57.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
57.3 @@ -1,576 +0,0 @@
57.4 -/*
57.5 - * Copyright (C) 2012 David Anderson
57.6 - *
57.7 - * This file is part of JITCraft.
57.8 - *
57.9 - * JITCraft is free software: you can redistribute it and/or modify it under
57.10 - * the terms of the GNU General Public License as published by the Free
57.11 - * Software Foundation, either version 3 of the License, or (at your option)
57.12 - * any later version.
57.13 - *
57.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
57.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
57.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
57.17 - *
57.18 - * You should have received a copy of the GNU General Public License along with
57.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
57.20 - */
57.21 -#include <assert.h>
57.22 -#include <ctype.h>
57.23 -#include <math.h>
57.24 -#include "Scanner.h"
57.25 -#include "Utility.h"
57.26 -
57.27 -using namespace ke;
57.28 -
57.29 -const char *ke::TokenNames[] =
57.30 -{
57.31 -#define _(name, str) str,
57.32 - TOKENMAP(_)
57.33 -#undef _
57.34 - NULL
57.35 -};
57.36 -
57.37 -Scanner::Scanner(CompileContext &cc, const char *stream, size_t length)
57.38 - : cc_(cc),
57.39 - stream_(stream),
57.40 - length_(length),
57.41 - pushed_(false),
57.42 - saved_('\0'),
57.43 - pos_(stream_)
57.44 -{
57.45 - cur_.line = 1;
57.46 - cur_.col = 1;
57.47 - last_ = cur_;
57.48 -}
57.49 -
57.50 -char
57.51 -Scanner::getChar()
57.52 -{
57.53 - if (saved_ != '\0') {
57.54 - char temp = saved_;
57.55 - saved_ = '\0';
57.56 - return temp;
57.57 - }
57.58 - if (pos_ >= stream_ + length_)
57.59 - return '\0';
57.60 - last_.col = cur_.col++;
57.61 - return *pos_++;
57.62 -}
57.63 -
57.64 -void
57.65 -Scanner::putChar(char c)
57.66 -{
57.67 - assert(saved_ == '\0');
57.68 - saved_ = c;
57.69 - cur_.col = last_.col;
57.70 -}
57.71 -
57.72 -void
57.73 -Scanner::calcNewLine(char c)
57.74 -{
57.75 - cur_.line++;
57.76 - cur_.col = 1;
57.77 - last_ = cur_;
57.78 -
57.79 - char o;
57.80 - if (c == '\r' && ((o = getChar()) != '\n'))
57.81 - putChar(o);
57.82 -}
57.83 -
57.84 -void
57.85 -Scanner::eatSingleLine()
57.86 -{
57.87 - char c;
57.88 - while ((c = getChar()) != '\0') {
57.89 - if (c == '\n' || c == '\r') {
57.90 - calcNewLine(c);
57.91 - break;
57.92 - }
57.93 - }
57.94 -}
57.95 -
57.96 -bool
57.97 -Scanner::eatComment()
57.98 -{
57.99 - char c;
57.100 -
57.101 - while ((c = getChar()) != '\0') {
57.102 - while (c == '*') {
57.103 - c = getChar();
57.104 - if (c == '\0')
57.105 - return false;
57.106 - if (c == '/')
57.107 - return true;
57.108 - }
57.109 - if (c == '\r' || c == '\n')
57.110 - calcNewLine(c);
57.111 - }
57.112 -
57.113 - return false;
57.114 -}
57.115 -
57.116 -static inline bool
57.117 -IsDigit(char c)
57.118 -{
57.119 - return c >= '0' && c <= '9';
57.120 -}
57.121 -
57.122 -// Based off the logic in sc2.c's ftoi()...
57.123 -double
57.124 -Scanner::ParseDouble(const char *string)
57.125 -{
57.126 - const char *ptr = string;
57.127 -
57.128 - double number = 0.0;
57.129 - while (IsDigit(*ptr)) {
57.130 - number = (number * 10) + (*ptr - '0');
57.131 - ptr++;
57.132 - }
57.133 -
57.134 - assert(*ptr == '.');
57.135 - ptr++;
57.136 -
57.137 - double fraction = 0.0;
57.138 - double multiplier = 1.0;
57.139 - while (IsDigit(*ptr)) {
57.140 - fraction = (fraction * 10) + (*ptr - '0');
57.141 - multiplier = multiplier / 10.0;
57.142 - ptr++;
57.143 - }
57.144 -
57.145 - number += fraction * multiplier;
57.146 -
57.147 - if (*ptr++ == 'e') {
57.148 - int sign = 1;
57.149 - if (*ptr == '-') {
57.150 - sign = -1;
57.151 - ptr++;
57.152 - }
57.153 -
57.154 - int exponent = 0;
57.155 - while (IsDigit(*ptr)) {
57.156 - exponent = (exponent * 10) + (*ptr - '0');
57.157 - ptr++;
57.158 - }
57.159 -
57.160 - multiplier = pow(10.0, exponent * sign);
57.161 - number *= multiplier;
57.162 - }
57.163 -
57.164 - return number;
57.165 -}
57.166 -
57.167 -static inline bool
57.168 -IsHexDigit(char c)
57.169 -{
57.170 - return IsDigit(c) ||
57.171 - (c >= 'a' && c <= 'f') ||
57.172 - (c >= 'A' && c <= 'F');
57.173 -}
57.174 -
57.175 -// Based on the logic for litchar() in sc2.c.
57.176 -int
57.177 -Scanner::readEscapeCode()
57.178 -{
57.179 - char c = getChar();
57.180 - if (c == '\\')
57.181 - return c;
57.182 -
57.183 - switch (c) {
57.184 - case 'a':
57.185 - return '\a';
57.186 - case 'b':
57.187 - return '\b';
57.188 - case 'e':
57.189 - return 27; // Apparently \e is non-standard.
57.190 - case 'f':
57.191 - return '\f';
57.192 - case 'n':
57.193 - return '\n';
57.194 - case 'r':
57.195 - return '\r';
57.196 - case 't':
57.197 - return '\t';
57.198 - case '\v':
57.199 - return '\v';
57.200 -
57.201 - case 'x':
57.202 - {
57.203 - unsigned digits = 0;
57.204 - char r = 0;
57.205 -
57.206 - c = getChar();
57.207 - while (IsHexDigit(c) && digits < 2) {
57.208 - if (IsDigit(c))
57.209 - c = (c << 4) + (c - '0');
57.210 - else
57.211 - c = (c << 4) + (tolower(c) - 'a' + 10);
57.212 - digits++;
57.213 - c = getChar();
57.214 - }
57.215 -
57.216 - // Swallow a trailing ';'
57.217 - if (c != ';')
57.218 - putChar(c);
57.219 -
57.220 - return r;
57.221 - }
57.222 -
57.223 - case '\'':
57.224 - case '\"':
57.225 - case '%':
57.226 - return c;
57.227 -
57.228 - default:
57.229 - {
57.230 - if (IsDigit(c)) {
57.231 - // \ddd
57.232 - char r = 0;
57.233 - while (IsDigit(c)) {
57.234 - r = r * 10 + (c - '0');
57.235 - c = getChar();
57.236 - }
57.237 -
57.238 - // Swallow a trailing ;
57.239 - if (c != ';')
57.240 - putChar(c);
57.241 -
57.242 - return r;
57.243 - }
57.244 - cc_.reportError(begin(), Message_UnknownEscapeCode, c);
57.245 - return INT_MAX;
57.246 - }
57.247 - }
57.248 -}
57.249 -
57.250 -TokenKind
57.251 -Scanner::stringLiteral()
57.252 -{
57.253 - literal_.clear();
57.254 -
57.255 - for (;;) {
57.256 - char c = getChar();
57.257 - if (c == '\"')
57.258 - break;
57.259 - if (c == '\r' || c == '\n' || c == '\0') {
57.260 - cc_.reportError(begin(), Message_UnterminatedString);
57.261 - return TOK_ERROR;
57.262 - }
57.263 - if (c == '\\') {
57.264 - int code = readEscapeCode();
57.265 - if (code == INT_MAX)
57.266 - return TOK_ERROR;
57.267 - c = char(code);
57.268 - }
57.269 - literal_ += c;
57.270 - }
57.271 -
57.272 - return TOK_STRING_LITERAL;
57.273 -}
57.274 -
57.275 -TokenKind
57.276 -Scanner::numberLiteral(char first)
57.277 -{
57.278 - literal_ = first;
57.279 -
57.280 - char c;
57.281 - for (;;) {
57.282 - c = getChar();
57.283 - if (!IsDigit(c))
57.284 - break;
57.285 - literal_ += c;
57.286 - }
57.287 -
57.288 - if (c != '.') {
57.289 - putChar(c);
57.290 - return TOK_INTEGER_LITERAL;
57.291 - }
57.292 - literal_ += c;
57.293 -
57.294 - c = getChar();
57.295 - if (!IsDigit(c)) {
57.296 - cc_.reportError(begin(), Message_ExpectedDigitForFloat, c);
57.297 - return TOK_ERROR;
57.298 - }
57.299 - literal_ += c;
57.300 -
57.301 - for (;;) {
57.302 - c = getChar();
57.303 - if (!IsDigit(c))
57.304 - break;
57.305 - literal_ += c;
57.306 - }
57.307 -
57.308 - if (c != 'e') {
57.309 - putChar(c);
57.310 - } else {
57.311 - literal_ += c;
57.312 - c = getChar();
57.313 - if (c == '-') {
57.314 - literal_ += c;
57.315 - c = getChar();
57.316 - }
57.317 - if (!IsDigit(c)) {
57.318 - cc_.reportError(begin(), Message_ExpectedDigitForFloat, c);
57.319 - return TOK_ERROR;
57.320 - }
57.321 - literal_ += c;
57.322 - for (;;) {
57.323 - c = getChar();
57.324 - if (!IsDigit(c)) {
57.325 - putChar(c);
57.326 - break;
57.327 - }
57.328 - literal_ += c;
57.329 - }
57.330 - }
57.331 -
57.332 - return TOK_FLOAT_LITERAL;
57.333 -}
57.334 -
57.335 -TokenKind
57.336 -Scanner::identifier(char first)
57.337 -{
57.338 - literal_ = first;
57.339 -
57.340 - char c;
57.341 - for (;;) {
57.342 - c = getChar();
57.343 - if (!isascii(c) || (!isalnum(c) && c != '_')) {
57.344 - if (c != ':')
57.345 - putChar(c);
57.346 - break;
57.347 - }
57.348 - literal_ += c;
57.349 - }
57.350 -
57.351 - if (literal_ == "new")
57.352 - return TOK_NEW;
57.353 - if (literal_ == "for")
57.354 - return TOK_FOR;
57.355 - if (literal_ == "return")
57.356 - return TOK_RETURN;
57.357 - if (literal_ == "if")
57.358 - return TOK_IF;
57.359 - if (literal_ == "else")
57.360 - return TOK_ELSE;
57.361 - if (literal_ == "enum")
57.362 - return TOK_ENUM;
57.363 - if (literal_ == "while")
57.364 - return TOK_WHILE;
57.365 - if (literal_ == "do")
57.366 - return TOK_DO;
57.367 - if (literal_ == "break")
57.368 - return TOK_BREAK;
57.369 - if (literal_ == "continue")
57.370 - return TOK_CONTINUE;
57.371 - if (literal_ == "forward")
57.372 - return TOK_FORWARD;
57.373 - if (literal_ == "public")
57.374 - return TOK_PUBLIC;
57.375 - if (literal_ == "const")
57.376 - return TOK_CONST;
57.377 - if (literal_ == "native")
57.378 - return TOK_NATIVE;
57.379 - return (c == ':') ? TOK_LABEL : TOK_NAME;
57.380 -}
57.381 -
57.382 -TokenKind
57.383 -Scanner::next()
57.384 -{
57.385 - assert(!pushed_);
57.386 -
57.387 - for (;;) {
57.388 - begin_ = cur_;
57.389 -
57.390 - char c = getChar();
57.391 - switch (c) {
57.392 - case '/':
57.393 - {
57.394 - c = getChar();
57.395 - if (c == '/') {
57.396 - eatSingleLine();
57.397 - break;
57.398 - }
57.399 - if (c == '*') {
57.400 - if (!eatComment()) {
57.401 - cc_.reportError(begin(), Message_UnterminatedComment);
57.402 - return TOK_ERROR;
57.403 - }
57.404 - break;
57.405 - }
57.406 - putChar(c);
57.407 - return TOK_SLASH;
57.408 - }
57.409 -
57.410 - case '\n':
57.411 - case '\r':
57.412 - calcNewLine(c);
57.413 - break;
57.414 -
57.415 - case ';': return TOK_SEMICOLON;
57.416 - case '{': return TOK_LBRACE;
57.417 - case '}': return TOK_RBRACE;
57.418 - case '(': return TOK_LPAREN;
57.419 - case ')': return TOK_RPAREN;
57.420 - case '[': return TOK_LBRACKET;
57.421 - case ']': return TOK_RBRACKET;
57.422 - case '~': return TOK_TILDE;
57.423 - case '?': return TOK_QMARK;
57.424 - case ':': return TOK_COLON;
57.425 -
57.426 - case '.':
57.427 - c = getChar();
57.428 - if (c == '.') {
57.429 - c = getChar();
57.430 - if (c == '.')
57.431 - return TOK_ELLIPSES;
57.432 - }
57.433 - cc_.reportError(begin_, Message_UnexpectedCharacter, c, uint8(c));
57.434 - return TOK_ERROR;
57.435 -
57.436 - case '*':
57.437 - c = getChar();
57.438 - if (c == '=')
57.439 - return TOK_ASSIGN_MUL;
57.440 - putChar(c);
57.441 - return TOK_STAR;
57.442 -
57.443 - case '+':
57.444 - c = getChar();
57.445 - if (c == '=')
57.446 - return TOK_ASSIGN_ADD;
57.447 - if (c == '+')
57.448 - return TOK_INCREMENT;
57.449 - putChar(c);
57.450 - return TOK_PLUS;
57.451 -
57.452 - case '&':
57.453 - c = getChar();
57.454 - if (c == '=')
57.455 - return TOK_ASSIGN_BITAND;
57.456 - if (c == '&')
57.457 - return TOK_AND;
57.458 - putChar(c);
57.459 - return TOK_BITAND;
57.460 -
57.461 - case '|':
57.462 - c = getChar();
57.463 - if (c == '=')
57.464 - return TOK_ASSIGN_BITOR;
57.465 - if (c == '|')
57.466 - return TOK_OR;
57.467 - putChar(c);
57.468 - return TOK_BITOR;
57.469 -
57.470 - case '^':
57.471 - c = getChar();
57.472 - if (c == '=')
57.473 - return TOK_ASSIGN_BITXOR;
57.474 - putChar(c);
57.475 - return TOK_BITXOR;
57.476 -
57.477 - case '%':
57.478 - c = getChar();
57.479 - if (c == '=')
57.480 - return TOK_ASSIGN_MOD;
57.481 - putChar(c);
57.482 - return TOK_PERCENT;
57.483 -
57.484 - case '-':
57.485 - c = getChar();
57.486 - if (c == '=')
57.487 - return TOK_ASSIGN_SUB;
57.488 - if (c == '-')
57.489 - return TOK_DECREMENT;
57.490 - putChar(c);
57.491 - return TOK_MINUS;
57.492 -
57.493 - case ',': return TOK_COMMA;
57.494 - case '\0': return TOK_EOF;
57.495 -
57.496 - case '!':
57.497 - c = getChar();
57.498 - if (c == '=')
57.499 - return TOK_NOTEQUALS;
57.500 - putChar(c);
57.501 - return TOK_NOT;
57.502 -
57.503 - case '=':
57.504 - c = getChar();
57.505 - if (c == '=')
57.506 - return TOK_EQUALS;
57.507 - putChar(c);
57.508 - return TOK_ASSIGN;
57.509 -
57.510 - case '<':
57.511 - c = getChar();
57.512 - if (c == '=')
57.513 - return TOK_LE;
57.514 - if (c == '<') {
57.515 - c = getChar();
57.516 - if (c == '=')
57.517 - return TOK_ASSIGN_SHL;
57.518 - return TOK_SHL;
57.519 - }
57.520 - putChar(c);
57.521 - return TOK_LT;
57.522 -
57.523 - case '>':
57.524 - c = getChar();
57.525 - if (c == '=')
57.526 - return TOK_GE;
57.527 - if (c == '>') {
57.528 - c = getChar();
57.529 - if (c == '>') {
57.530 - c = getChar();
57.531 - if (c == '=')
57.532 - return TOK_ASSIGN_USHR;
57.533 - putChar(c);
57.534 - return TOK_USHR;
57.535 - }
57.536 - return TOK_SHR;
57.537 - }
57.538 - putChar(c);
57.539 - return TOK_GT;
57.540 -
57.541 - case ' ':
57.542 - case '\t':
57.543 - case '\f':
57.544 - break;
57.545 -
57.546 - case '"':
57.547 - return stringLiteral();
57.548 -
57.549 - default:
57.550 - if (c >= '0' && c <= '9')
57.551 - return numberLiteral(c);
57.552 - if (c == '_' || (isascii(c) && isalpha(c)))
57.553 - return identifier(c);
57.554 - cc_.reportError(begin_, Message_UnexpectedCharacter, c, uint8(c));
57.555 - return TOK_ERROR;
57.556 - }
57.557 - }
57.558 -}
57.559 -
57.560 -TokenKind
57.561 -Scanner::scan()
57.562 -{
57.563 - if (pushed_) {
57.564 - pushed_ = false;
57.565 - return lastToken_;
57.566 - }
57.567 - lastToken_ = next();
57.568 - return lastToken_;
57.569 -}
57.570 -
57.571 -TokenKind
57.572 -Scanner::peek()
57.573 -{
57.574 - if (pushed_)
57.575 - return lastToken_;
57.576 - scan();
57.577 - pushed_ = true;
57.578 - return lastToken_;
57.579 -}
58.1 --- a/jitcraft/Scanner.h Tue Jul 24 23:53:34 2012 -0700
58.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
58.3 @@ -1,81 +0,0 @@
58.4 -/*
58.5 - * Copyright (C) 2012 David Anderson
58.6 - *
58.7 - * This file is part of JITCraft.
58.8 - *
58.9 - * JITCraft is free software: you can redistribute it and/or modify it under
58.10 - * the terms of the GNU General Public License as published by the Free
58.11 - * Software Foundation, either version 3 of the License, or (at your option)
58.12 - * any later version.
58.13 - *
58.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
58.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
58.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
58.17 - *
58.18 - * You should have received a copy of the GNU General Public License along with
58.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
58.20 - */
58.21 -#ifndef _include_jitcraft_scanner_h_
58.22 -#define _include_jitcraft_scanner_h_
58.23 -
58.24 -#include <string>
58.25 -#include "Token.h"
58.26 -#include "CompileContext.h"
58.27 -
58.28 -namespace ke {
58.29 -
58.30 -class Scanner
58.31 -{
58.32 - CompileContext &cc_;
58.33 - const char *stream_;
58.34 - size_t length_;
58.35 - bool pushed_;
58.36 - char saved_;
58.37 - const char *pos_;
58.38 - std::string literal_;
58.39 - TokenKind lastToken_;
58.40 - SourcePosition last_;
58.41 - SourcePosition cur_;
58.42 - SourcePosition begin_;
58.43 -
58.44 - private:
58.45 - char getChar();
58.46 - void putChar(char c);
58.47 - void eatSingleLine();
58.48 - bool eatComment();
58.49 - void calcNewLine(char c);
58.50 - int readEscapeCode();
58.51 - TokenKind stringLiteral();
58.52 - TokenKind numberLiteral(char first);
58.53 - TokenKind identifier(char first);
58.54 -
58.55 - TokenKind next();
58.56 -
58.57 - public:
58.58 - Scanner(CompileContext &cc, const char *stream, size_t length);
58.59 -
58.60 - static double ParseDouble(const char *string);
58.61 -
58.62 - TokenKind scan();
58.63 - TokenKind peek();
58.64 - TokenKind last() const {
58.65 - return lastToken_;
58.66 - }
58.67 -
58.68 - // Beginning source position of the last instruction.
58.69 - SourcePosition begin() const {
58.70 - return begin_;
58.71 - }
58.72 -
58.73 - // Note: the literal may have embedded NUL characters.
58.74 - const char *literal() const {
58.75 - return literal_.c_str();
58.76 - }
58.77 - size_t literal_length() const {
58.78 - return literal_.size();
58.79 - }
58.80 -};
58.81 -
58.82 -} // namespace ke
58.83 -
58.84 -#endif // _include_jitcraft_scanner_h_
59.1 --- a/jitcraft/Scopes.cpp Tue Jul 24 23:53:34 2012 -0700
59.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
59.3 @@ -1,273 +0,0 @@
59.4 -/* vim: set ts=4 sw=4 tw=99 et:
59.5 - *
59.6 - * Copyright (C) 2012 David Anderson
59.7 - *
59.8 - * This file is part of JITCraft.
59.9 - *
59.10 - * JITCraft is free software: you can redistribute it and/or modify it under
59.11 - * the terms of the GNU General Public License as published by the Free
59.12 - * Software Foundation, either version 3 of the License, or (at your option)
59.13 - * any later version.
59.14 - *
59.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
59.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
59.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
59.18 - *
59.19 - * You should have received a copy of the GNU General Public License along with
59.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
59.21 - */
59.22 -#include "Scopes.h"
59.23 -#include "Zone.h"
59.24 -#include "Types.h"
59.25 -#include "TypeManager.h"
59.26 -#include "Strings.h"
59.27 -#include "CompileContext.h"
59.28 -#include "Environments.h"
59.29 -
59.30 -using namespace ke;
59.31 -
59.32 -Scope::Scope(PoolAllocator &pool, Kind kind, Scope *enclosing)
59.33 - : pool_(pool),
59.34 - locals_(0),
59.35 - maxContainedLocals_(0),
59.36 - numFunctions_(0),
59.37 - numNatives_(0),
59.38 - lifoSlot_(NULL),
59.39 - kind_(kind),
59.40 - enclosing_(enclosing)
59.41 -{
59.42 -}
59.43 -
59.44 -bool
59.45 -Scope::initialize()
59.46 -{
59.47 - if (enclosing_ && !enclosing_->children_.append(this))
59.48 - return false;
59.49 - return true;
59.50 -}
59.51 -
59.52 -void
59.53 -Scope::unlink()
59.54 -{
59.55 - assert(empty());
59.56 -
59.57 - assert(enclosing_->children_[enclosing_->children_.length() - 1] == this);
59.58 - enclosing_->children_.pop();
59.59 -
59.60 - // OOM here is swallowed and checked after compilation.
59.61 - // :TODO: make the above true.
59.62 - for (size_t i = 0; i < children_.length(); i++)
59.63 - enclosing_->children_.append(children_[i]);
59.64 -}
59.65 -
59.66 -Scope *
59.67 -Scope::unlinkIfEmpty()
59.68 -{
59.69 - if (empty()) {
59.70 - unlink();
59.71 - return NULL;
59.72 - }
59.73 - return this;
59.74 -}
59.75 -
59.76 -BoundName *
59.77 -Scope::localLookup(Handle<String> name)
59.78 -{
59.79 - for (size_t i = 0; i < names_.length(); i++) {
59.80 - if (names_[i]->name() == name)
59.81 - return names_[i];
59.82 - }
59.83 - return NULL;
59.84 -}
59.85 -
59.86 -BoundName *
59.87 -Scope::lookup(Handle<String> name)
59.88 -{
59.89 - for (Scope *scope = this; scope; scope = scope->enclosing()) {
59.90 - if (BoundName *bound = scope->localLookup(name))
59.91 - return bound;
59.92 - }
59.93 - return NULL;
59.94 -}
59.95 -
59.96 -Variable *
59.97 -Scope::declareVariable(Handle<String> name, const SourcePosition &pos)
59.98 -{
59.99 - assert(!localLookup(name));
59.100 -
59.101 - Variable *var = new (pool_) Variable(this, name, pos);
59.102 - if (!names_.append(var))
59.103 - return NULL;
59.104 - return var;
59.105 -}
59.106 -
59.107 -Variable *
59.108 -Scope::declareArgument(Handle<String> name, const SourcePosition &pos)
59.109 -{
59.110 - assert(kind() == FUNCTION);
59.111 - Variable *var = declareVariable(name, pos);
59.112 - if (!names_.append(var))
59.113 - return NULL;
59.114 - if (!parameters_.append(var))
59.115 - return NULL;
59.116 - return var;
59.117 -}
59.118 -
59.119 -NamedFunction *
59.120 -Scope::declareFunction(Handle<String> name, const SourcePosition &pos, TokenKind token)
59.121 -{
59.122 - assert(!localLookup(name));
59.123 - assert(kind() == GLOBAL);
59.124 -
59.125 - NamedFunction *fun = new (pool_) NamedFunction(this, name, pos, token);
59.126 - if (!names_.append(fun))
59.127 - return NULL;
59.128 - return fun;
59.129 -}
59.130 -
59.131 -NamedEnum *
59.132 -Scope::declareEnum(Handle<String> name, const SourcePosition &pos)
59.133 -{
59.134 - NamedEnum *e = new (pool_) NamedEnum(this, name, pos);
59.135 - if (!names_.append(e))
59.136 - return NULL;
59.137 - return e;
59.138 -}
59.139 -
59.140 -NamedConstant *
59.141 -Scope::declareConstant(Handle<String> name, const SourcePosition &pos)
59.142 -{
59.143 - NamedConstant *constant = new (pool_) NamedConstant(this, name, pos);
59.144 - if (!names_.append(constant))
59.145 - return NULL;
59.146 - return constant;
59.147 -}
59.148 -
59.149 -void
59.150 -Scope::allocateGlobals()
59.151 -{
59.152 - assert(kind() == GLOBAL);
59.153 -
59.154 - for (size_t i = 0; i < children_.length(); i++) {
59.155 - assert(children_[i]->kind() == FUNCTION);
59.156 - children_[i]->allocate();
59.157 - }
59.158 -
59.159 - Local<Type> type(ZONE());
59.160 - for (size_t i = 0; i < names_.length(); i++) {
59.161 - BoundName *name = names_[i];
59.162 -
59.163 - if (name->kind() == BoundName::FUNCTION) {
59.164 - NamedFunction *fun = name->toNamedFunction();
59.165 - if (fun->isNative())
59.166 - fun->allocate(numNatives_++);
59.167 - else
59.168 - fun->allocate(numFunctions_++);
59.169 - } else if (name->kind() == BoundName::VARIABLE) {
59.170 - allocate(name->toVariable());
59.171 - }
59.172 - }
59.173 -}
59.174 -
59.175 -void
59.176 -Scope::allocate(Variable *var)
59.177 -{
59.178 - if (!var->unallocated())
59.179 - return;
59.180 -
59.181 - if (kind() == GLOBAL) {
59.182 - var->allocate(Variable::ENVIRONMENT, envVars_.length());
59.183 - envVars_.append(var);
59.184 - } else {
59.185 - var->allocate(Variable::STACK, maxContainedLocals_ + locals_);
59.186 - locals_++;
59.187 - }
59.188 -}
59.189 -
59.190 -void
59.191 -Scope::allocate()
59.192 -{
59.193 - maxContainedLocals_ = 0;
59.194 - for (size_t i = 0; i < children_.length(); i++) {
59.195 - Scope *scope = children_[i];
59.196 - scope->allocate();
59.197 - if (scope->maxContainedLocals() > maxContainedLocals_)
59.198 - maxContainedLocals_ = scope->maxContainedLocals();
59.199 - }
59.200 -
59.201 - for (size_t i = 0; i < parameters_.length(); i++)
59.202 - parameters_[i]->allocate(Variable::PARAMETER, i);
59.203 -
59.204 - if (lifoSlot_)
59.205 - allocate(lifoSlot_);
59.206 - for (size_t i = 0; i < names_.length(); i++) {
59.207 - if (names_[i]->kind() != BoundName::VARIABLE)
59.208 - continue;
59.209 -
59.210 - allocate(names_[i]->toVariable());
59.211 - }
59.212 -
59.213 - maxContainedLocals_ += locals_;
59.214 -}
59.215 -
59.216 -bool
59.217 -Scope::Bind(CompileContext &cc, ParseTree *tree)
59.218 -{
59.219 - Local<String> name(ZONE());
59.220 - for (size_t i = 0; i < tree->unbound()->length(); i++) {
59.221 - NameProxy *proxy = tree->unbound()->at(i);
59.222 - name = proxy->name();
59.223 - BoundName *binding = tree->scope()->lookup(name);
59.224 -
59.225 - if (!binding) {
59.226 - cc.reportError(proxy->pos(), Message_IdentifierNotFound, name->chars());
59.227 - return false;
59.228 - }
59.229 -
59.230 - // We only allow global functions to be late-bound.
59.231 - if (binding->kind() != BoundName::FUNCTION ||
59.232 - binding->scope()->kind() != Scope::GLOBAL)
59.233 - {
59.234 - cc.reportError(proxy->pos(), Message_IdentifierNotFound, name->chars());
59.235 - return false;
59.236 - }
59.237 -
59.238 - proxy->bind(binding);
59.239 - }
59.240 - return true;
59.241 -}
59.242 -
59.243 -void
59.244 -Scope::Allocate(ParseTree *tree)
59.245 -{
59.246 - tree->scope()->allocateGlobals();
59.247 -}
59.248 -
59.249 -void
59.250 -Scope::setUsesLifoHeap()
59.251 -{
59.252 - // Only one lifo slot is needed per scope.
59.253 - if (lifoSlot_)
59.254 - return;
59.255 -
59.256 - // If the parent of this scope is the function scope, then this is the
59.257 - // function's block scope, and the lifo slot is part of the Frame instead.
59.258 - // Note we can get a function scope here if we're making a temporary in a
59.259 - // function with no local variables.
59.260 - if (kind() == FUNCTION || enclosing()->kind() == FUNCTION)
59.261 - return;
59.262 -
59.263 - Local<Type> type(ZONE(), ZONE()->types()->getPrimitive(PrimitiveType_Native));
59.264 - if (!type)
59.265 - return;
59.266 -
59.267 - Local<String> name(ZONE());
59.268 - lifoSlot_ = new (pool_) Variable(this, name, SourcePosition());
59.269 - lifoSlot_->setType(type);
59.270 -}
59.271 -
59.272 -EnvironmentMap *
59.273 -Scope::createEnvironmentMap(Zone *zone)
59.274 -{
59.275 - return EnvironmentMap::New(zone, envVars_.length(), envVars_.buffer());
59.276 -}
60.1 --- a/jitcraft/Scopes.h Tue Jul 24 23:53:34 2012 -0700
60.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
60.3 @@ -1,119 +0,0 @@
60.4 -/*
60.5 - * Copyright (C) 2012 David Anderson
60.6 - *
60.7 - * This file is part of JITCraft.
60.8 - *
60.9 - * JITCraft is free software: you can redistribute it and/or modify it under
60.10 - * the terms of the GNU General Public License as published by the Free
60.11 - * Software Foundation, either version 3 of the License, or (at your option)
60.12 - * any later version.
60.13 - *
60.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
60.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
60.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
60.17 - *
60.18 - * You should have received a copy of the GNU General Public License along with
60.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
60.20 - */
60.21 -#ifndef _include_jitcraft_scopes_h_
60.22 -#define _include_jitcraft_scopes_h_
60.23 -
60.24 -#include "PoolAllocator.h"
60.25 -#include "AST.h"
60.26 -#include "NameBinding.h"
60.27 -#include "Structures.h"
60.28 -
60.29 -namespace ke {
60.30 -
60.31 -class CompileContext;
60.32 -class EnvironmentMap;
60.33 -
60.34 -class Scope : public PoolObject
60.35 -{
60.36 - PoolAllocator &pool_;
60.37 - PoolList<BoundName *> names_;
60.38 - PoolList<Scope *> children_;
60.39 - PoolList<Variable *> parameters_;
60.40 - unsigned locals_;
60.41 - unsigned maxContainedLocals_;
60.42 - unsigned numFunctions_;
60.43 - unsigned numNatives_;
60.44 - PoolList<Variable *> envVars_;
60.45 - Variable *lifoSlot_;
60.46 -
60.47 - bool empty() const {
60.48 - return names_.length() == 0;
60.49 - }
60.50 - void unlink();
60.51 -
60.52 - public:
60.53 - enum Kind {
60.54 - GLOBAL,
60.55 - FUNCTION,
60.56 - BLOCK
60.57 - };
60.58 -
60.59 - public:
60.60 - Scope(PoolAllocator &pool, Kind kind, Scope *enclosing);
60.61 - bool initialize();
60.62 -
60.63 - Kind kind() const {
60.64 - return kind_;
60.65 - }
60.66 - Scope *enclosing() const {
60.67 - return enclosing_;
60.68 - }
60.69 - unsigned locals() const {
60.70 - return locals_;
60.71 - }
60.72 - unsigned maxContainedLocals() const {
60.73 - return maxContainedLocals_;
60.74 - }
60.75 - unsigned numFunctions() const {
60.76 - return numFunctions_;
60.77 - }
60.78 - unsigned numNatives() const {
60.79 - return numNatives_;
60.80 - }
60.81 - unsigned numArguments() const {
60.82 - return parameters_.length();
60.83 - }
60.84 - unsigned numEnvironmentVars() const {
60.85 - return envVars_.length();
60.86 - }
60.87 - Variable *getArgument(size_t index) {
60.88 - return parameters_[index];
60.89 - }
60.90 - Variable *lifoSlot() {
60.91 - return lifoSlot_;
60.92 - }
60.93 - void setUsesLifoHeap();
60.94 -
60.95 - Scope *unlinkIfEmpty();
60.96 - BoundName *localLookup(Handle<String> name);
60.97 - BoundName *lookup(Handle<String> name);
60.98 -
60.99 - NamedFunction *declareFunction(Handle<String> name, const SourcePosition &pos, TokenKind token);
60.100 - Variable *declareVariable(Handle<String> name, const SourcePosition &pos);
60.101 - Variable *declareArgument(Handle<String> name, const SourcePosition &pos);
60.102 - NamedEnum *declareEnum(Handle<String> name, const SourcePosition &pos);
60.103 - NamedConstant *declareConstant(Handle<String> name, const SourcePosition &pos);
60.104 -
60.105 - EnvironmentMap *createEnvironmentMap(Zone *zone);
60.106 -
60.107 - void allocate(Variable *var);
60.108 - void allocate();
60.109 - void allocateGlobals();
60.110 -
60.111 - public:
60.112 - static bool Bind(CompileContext &cc, ParseTree *tree);
60.113 - static void Allocate(ParseTree *tree);
60.114 -
60.115 - private:
60.116 - Kind kind_;
60.117 - Scope *enclosing_;
60.118 -};
60.119 -
60.120 -}
60.121 -
60.122 -#endif // _include_jitcraft_scopes_h_
61.1 --- a/jitcraft/SemanticAnalysis.cpp Tue Jul 24 23:53:34 2012 -0700
61.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
61.3 @@ -1,1092 +0,0 @@
61.4 -/* vim: set ts=4 sw=4 tw=99 et:
61.5 - *
61.6 - * Copyright (C) 2012 David Anderson
61.7 - *
61.8 - * This file is part of JITCraft.
61.9 - *
61.10 - * JITCraft is free software: you can redistribute it and/or modify it under
61.11 - * the terms of the GNU General Public License as published by the Free
61.12 - * Software Foundation, either version 3 of the License, or (at your option)
61.13 - * any later version.
61.14 - *
61.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
61.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
61.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
61.18 - *
61.19 - * You should have received a copy of the GNU General Public License along with
61.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
61.21 - */
61.22 -#include "SemanticAnalysis.h"
61.23 -#include "Types.h"
61.24 -#include "Zone.h"
61.25 -#include "TypeManager.h"
61.26 -#include "Scopes.h"
61.27 -#include "NameBinding.h"
61.28 -#include "Heap-inl.h"
61.29 -#include "Strings.h"
61.30 -
61.31 -using namespace ke;
61.32 -
61.33 -static inline bool
61.34 -IsPrimitiveType(Type *type, PrimitiveType primitive)
61.35 -{
61.36 - if (!type)
61.37 - return false;
61.38 -
61.39 - if (!type->isPrimitive())
61.40 - return false;
61.41 -
61.42 - return primitive == type->primitive();
61.43 -}
61.44 -
61.45 -static inline bool
61.46 -EvaluateBinaryOperation(TokenKind kind, const BoxedPrimitive &left, const BoxedPrimitive &right,
61.47 - BoxedPrimitive *out)
61.48 -{
61.49 - switch (kind) {
61.50 - case TOK_PLUS:
61.51 - *out = BoxedPrimitive::Int(left.toInt() + right.toInt());
61.52 - return true;
61.53 -
61.54 - case TOK_SHL:
61.55 - *out = BoxedPrimitive::Int(left.toInt() << right.toInt());
61.56 - return true;
61.57 -
61.58 - default:
61.59 - return false;
61.60 - }
61.61 -}
61.62 -
61.63 -static bool
61.64 -EvaluateForConstant(Expression *expression, BoxedPrimitive *out)
61.65 -{
61.66 - switch (expression->kind()) {
61.67 - case AstNode::kBinaryExpression:
61.68 - {
61.69 - BoxedPrimitive left;
61.70 - BoxedPrimitive right;
61.71 - BinaryExpression *b = expression->toBinaryExpression();
61.72 - if (!EvaluateForConstant(b->left(), &left) ||
61.73 - !EvaluateForConstant(b->right(), &right))
61.74 - {
61.75 - return false;
61.76 - }
61.77 - return EvaluateBinaryOperation(b->token(), left, right, out);
61.78 - }
61.79 -
61.80 - case AstNode::kNameProxy:
61.81 - {
61.82 - NameProxy *proxy = expression->toNameProxy();
61.83 - if (proxy->binding()->kind() != BoundName::CONSTANT)
61.84 - return false;
61.85 -
61.86 - NamedConstant *c = proxy->binding()->toNamedConstant();
61.87 - if (!IsPrimitiveType(c->type(), PrimitiveType_Int32))
61.88 - return false;
61.89 -
61.90 - *out = c->value();
61.91 - return true;
61.92 - }
61.93 -
61.94 - case AstNode::kIntegerLiteral:
61.95 - *out = BoxedPrimitive::Int(expression->toIntegerLiteral()->value());
61.96 - return true;
61.97 -
61.98 - default:
61.99 - return false;
61.100 - }
61.101 -}
61.102 -
61.103 -SemanticAnalysis::SemanticAnalysis(Zone *zone, CompileContext &cc, ParseTree *tree)
61.104 - : zone_(zone),
61.105 - cc_(cc),
61.106 - tree_(tree),
61.107 - scope_(NULL),
61.108 - loop_(NULL)
61.109 -{
61.110 -}
61.111 -
61.112 -bool
61.113 -SemanticAnalysis::analyze()
61.114 -{
61.115 - if (cc_.failures())
61.116 - return false;
61.117 -
61.118 - scope_ = tree_->scope();
61.119 -
61.120 - for (size_t i = 0; i < tree_->statements()->length(); i++) {
61.121 - Statement *statement = tree_->statements()->at(i);
61.122 - if (statement->isFunctionStatement()) {
61.123 - FunctionStatement *funstmt = statement->toFunctionStatement();
61.124 - if (!preanalyze(funstmt))
61.125 - return false;
61.126 - }
61.127 - }
61.128 -
61.129 - for (size_t i = 0; i < tree_->statements()->length(); i++) {
61.130 - Statement *statement = tree_->statements()->at(i);
61.131 - statement->accept(this);
61.132 - }
61.133 -
61.134 - return !cc_.failures();
61.135 -}
61.136 -
61.137 -Type *
61.138 -SemanticAnalysis::visitAndApplyType(Expression *expression)
61.139 -{
61.140 - expression->accept(this);
61.141 - return expression->type();
61.142 -}
61.143 -
61.144 -Type *
61.145 -SemanticAnalysis::visitForLoad(Expression *expression)
61.146 -{
61.147 - Local<Type> type(zone_, visitAndApplyType(expression));
61.148 - if (!type)
61.149 - return NULL;
61.150 -
61.151 - if (type->isReference()) {
61.152 - expression->setType(type->contained());
61.153 - } else if (expression->isIndexExpression()) {
61.154 - if (type->isArray())
61.155 - expression->setType(type->contained());
61.156 - } else if (expression->isCallExpression()) {
61.157 - if (type->isVoid()) {
61.158 - CallExpression *call = expression->toCallExpression();
61.159 - cc_.reportError(call->callee()->pos(), Message_FunctionDoesNotReturnValue);
61.160 - return NULL;
61.161 - }
61.162 - }
61.163 -
61.164 - return expression->type();
61.165 -}
61.166 -
61.167 -// :TODO: this leaks an interior pointer.
61.168 -static inline const char *
61.169 -GetTypeName(Type *type)
61.170 -{
61.171 - if (type->isArray())
61.172 - return "array";
61.173 - if (type->isFunction())
61.174 - return "function";
61.175 - if (type->isReference())
61.176 - type = type->contained();
61.177 - if (type->tag())
61.178 - return type->tag()->chars();
61.179 - return "int";
61.180 -}
61.181 -
61.182 -void
61.183 -SemanticAnalysis::unaryTypeError(AstNode *node, TokenKind token, Handle<Type> type)
61.184 -{
61.185 - const char *op = TokenNames[token];
61.186 - const char *name = GetTypeName(type);
61.187 -
61.188 - cc_.reportError(node->pos(), Message_UnaryTypeError, op, name);
61.189 -}
61.190 -
61.191 -void
61.192 -SemanticAnalysis::binaryTypeError(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right)
61.193 -{
61.194 - const char *op = TokenNames[token];
61.195 - const char *leftName = GetTypeName(left);
61.196 - const char *rightName = GetTypeName(right);
61.197 -
61.198 - cc_.reportError(node->pos(), Message_BinaryTypeError, op, leftName, rightName);
61.199 -}
61.200 -
61.201 -Type *
61.202 -SemanticAnalysis::typeCheckBinary(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right)
61.203 -{
61.204 - if ((token >= TOK_PLUS && token <= TOK_SLASH) ||
61.205 - (token >= TOK_ASSIGN_ADD && token <= TOK_ASSIGN_DIV))
61.206 - {
61.207 - // If either side is a float, the other side must be a float or int.
61.208 - if (left->isFloat() || right->isFloat()) {
61.209 - Type *floatType = left->isFloat() ? left : right;
61.210 - Type *other = left->isFloat() ? right : left;
61.211 - if (other->isFloat() || (other->isInt32() && !other->tag()))
61.212 - return floatType;
61.213 - }
61.214 - }
61.215 -
61.216 - if (token == TOK_OR || token == TOK_AND) {
61.217 - if (!canTest(node, left) || !canTest(node, right))
61.218 - return NULL;
61.219 - return zone_->types()->getPrimitive(PrimitiveType_Int32);
61.220 - }
61.221 -
61.222 - if (token >= TOK_EQUALS && token <= TOK_GE) {
61.223 - if ((left->isFloat() || (left->isInt32() && !left->tag())) &&
61.224 - (right->isFloat() || (right->isInt32() && !right->tag())))
61.225 - {
61.226 - return zone_->types()->getPrimitive(PrimitiveType_Int32);
61.227 - }
61.228 - binaryTypeError(node, token, left, right);
61.229 - return NULL;
61.230 - }
61.231 -
61.232 - if ((!left->isInt32() || left->tag()) ||
61.233 - (!right->isInt32() || right->tag()))
61.234 - {
61.235 - binaryTypeError(node, token, left, right);
61.236 - return NULL;
61.237 - }
61.238 -
61.239 - return left;
61.240 -}
61.241 -
61.242 -bool
61.243 -SemanticAnalysis::canTest(AstNode *node, Handle<Type> type)
61.244 -{
61.245 - if (type->isArray() || (type->isInt32() && type->tag())) {
61.246 - cc_.reportError(node->pos(), Message_ArrayIsNotBoolean);
61.247 - return false;
61.248 - }
61.249 - return true;
61.250 -}
61.251 -
61.252 -Type *
61.253 -SemanticAnalysis::visitForLValue(Expression *expression)
61.254 -{
61.255 - if (expression->isIndexExpression()) {
61.256 - Type *type = visitAndApplyType(expression);
61.257 - if (!type)
61.258 - return NULL;
61.259 -
61.260 - if (type->isConst()) {
61.261 - cc_.reportError(expression->pos(), Message_ReferenceIsConstant);
61.262 - return NULL;
61.263 - }
61.264 -
61.265 - return type->contained();
61.266 - }
61.267 -
61.268 - if (!expression->isNameProxy()) {
61.269 - cc_.reportError(expression->pos(), Message_ExpectedLValue);
61.270 - return NULL;
61.271 - }
61.272 -
61.273 - NameProxy *proxy = expression->toNameProxy();
61.274 - if (!proxy->binding()->kind() == BoundName::VARIABLE) {
61.275 - cc_.reportError(expression->pos(), Message_ExpectedLValue);
61.276 - return NULL;
61.277 - }
61.278 -
61.279 - Variable *var = proxy->binding()->toVariable();
61.280 - if (!var->type())
61.281 - return NULL;
61.282 -
61.283 - if (var->type()->isReference()) {
61.284 - if (var->type()->isConst()) {
61.285 - cc_.reportError(expression->pos(), Message_ReferenceIsConstant);
61.286 - return NULL;
61.287 - }
61.288 - return var->type()->contained();
61.289 - }
61.290 - return var->type();
61.291 -}
61.292 -
61.293 -SemanticAnalysis::ControlStatus
61.294 -SemanticAnalysis::visitForControl(Statement *statement)
61.295 -{
61.296 - ControlScope scope(&control_);
61.297 - statement->accept(this);
61.298 - return scope.status();
61.299 -}
61.300 -
61.301 -void
61.302 -SemanticAnalysis::visit(NameProxy *name)
61.303 -{
61.304 - name->setType(name->binding()->type());
61.305 -}
61.306 -
61.307 -void
61.308 -SemanticAnalysis::visit(Assignment *node)
61.309 -{
61.310 - Local<Type> exprType(zone_, visitForLoad(node->expression()));
61.311 - if (!exprType)
61.312 - return ;
61.313 -
61.314 - Local<Type> type(zone_, visitForLValue(node->lvalue()));
61.315 - if (!type)
61.316 - return;
61.317 -
61.318 - if (node->token() != TOK_ASSIGN) {
61.319 - if (!typeCheckBinary(node, node->token(), type, exprType))
61.320 - return;
61.321 - }
61.322 -
61.323 - if (!typeCheckAssignment(node, exprType, type, true))
61.324 - return;
61.325 -
61.326 - node->setType(type);
61.327 -}
61.328 -
61.329 -void
61.330 -SemanticAnalysis::visit(IncDecExpression *node)
61.331 -{
61.332 - Local<Type> type(zone_, visitForLValue(node->expression()));
61.333 - if (!type)
61.334 - return;
61.335 -
61.336 - assert(!type->isReference());
61.337 -
61.338 - if ((!type->isInt32() || (type->isInt32() && type->tag())) && !type->isFloat()) {
61.339 - unaryTypeError(node, node->token(), type);
61.340 - return;
61.341 - }
61.342 -
61.343 - node->setType(type);
61.344 -}
61.345 -
61.346 -void
61.347 -SemanticAnalysis::visit(UnaryExpression *node)
61.348 -{
61.349 - Local<Type> type(zone_, visitForLoad(node->expression()));
61.350 - if (!type)
61.351 - return;
61.352 -
61.353 - switch (node->token())
61.354 - {
61.355 - case TOK_NOT:
61.356 - if (!canTest(node->expression(), type))
61.357 - return;
61.358 - type = zone_->types()->getPrimitive(PrimitiveType_Int32);
61.359 - if (!type)
61.360 - return;
61.361 - node->setType(type);
61.362 - break;
61.363 -
61.364 - case TOK_MINUS:
61.365 - if (!type->isFloat() && (!type->isInt32() || type->tag())) {
61.366 - unaryTypeError(node, node->token(), type);
61.367 - return;
61.368 - }
61.369 - node->setType(type);
61.370 - break;
61.371 -
61.372 - default:
61.373 - assert(node->token() == TOK_TILDE);
61.374 - if (!type->isInt32() || type->tag()) {
61.375 - unaryTypeError(node, node->token(), type);
61.376 - return;
61.377 - }
61.378 - node->setType(type);
61.379 - break;
61.380 - }
61.381 -}
61.382 -
61.383 -void
61.384 -SemanticAnalysis::visit(TernaryExpression *node)
61.385 -{
61.386 - Local<Type> type(zone_, visitForLoad(node->condition()));
61.387 - if (!type)
61.388 - return;
61.389 -
61.390 - if (!canTest(node->condition(), type))
61.391 - return;
61.392 -
61.393 - Local<Type> left(zone_, visitForLoad(node->left()));
61.394 - Local<Type> right(zone_, visitForLoad(node->right()));
61.395 - if (!left || !right)
61.396 - return;
61.397 -
61.398 - if (left != right) {
61.399 - binaryTypeError(node, TOK_QMARK, left, right);
61.400 - return;
61.401 - }
61.402 -}
61.403 -
61.404 -void
61.405 -SemanticAnalysis::visit(BinaryExpression *node)
61.406 -{
61.407 - Local<Type> left(zone_, visitForLoad(node->left()));
61.408 - Local<Type> right(zone_, visitForLoad(node->right()));
61.409 - if (!left || !right)
61.410 - return;
61.411 -
61.412 - Local<Type> result(zone_, typeCheckBinary(node, node->token(), left, right));
61.413 - if (!result)
61.414 - return;
61.415 -
61.416 - node->setType(result);
61.417 -}
61.418 -
61.419 -void
61.420 -SemanticAnalysis::visit(ReturnStatement *node)
61.421 -{
61.422 - // Set this early, so if we error we don't get more errors.
61.423 - control_->returns(Returns_Always);
61.424 -
61.425 - if (!node->expression()) {
61.426 - if (!function_->returnType()->isVoid())
61.427 - cc_.reportError(node->pos(), Message_NotAllPathsReturnValue);
61.428 - return;
61.429 - }
61.430 -
61.431 - Local<Type> type(zone_, visitForLoad(node->expression()));
61.432 - if (!type)
61.433 - return;
61.434 -
61.435 - Local<Type> returnType(zone_, function_->returnType());
61.436 - if (!typeCheckAssignment(node, type, returnType, true))
61.437 - return;
61.438 -}
61.439 -
61.440 -void
61.441 -SemanticAnalysis::visit(ForStatement *node)
61.442 -{
61.443 - LoopScope loop(&loop_);
61.444 -
61.445 - if (node->scope())
61.446 - scope_ = node->scope();
61.447 -
61.448 - if (node->initialization())
61.449 - node->initialization()->accept(this);
61.450 -
61.451 - if (node->condition()) {
61.452 - Local<Type> type(zone_, visitForLoad(node->condition()));
61.453 - if (!type || !canTest(node->condition(), type)) {
61.454 - return;
61.455 - }
61.456 - }
61.457 -
61.458 - if (node->update())
61.459 - node->update()->accept(this);
61.460 -
61.461 - ControlStatus status = visitForControl(node->body());
61.462 -
61.463 - // If there is a condition, we treat this like a while loop. Otherwise,
61.464 - // join point is only reachable if the loop contains a break. The
61.465 - // termination status doesn't tell us anything yet.
61.466 - if (node->condition() || loop.breaks())
61.467 - control_->merge(status, ControlStatus(false, Returns_Never));
61.468 - else
61.469 - control_->terminate(status.returns());
61.470 -
61.471 - if (node->scope())
61.472 - scope_ = scope_->enclosing();
61.473 -}
61.474 -
61.475 -void
61.476 -SemanticAnalysis::visit(WhileStatement *node)
61.477 -{
61.478 - LoopScope loop(&loop_);
61.479 -
61.480 - Local<Type> type(zone_, visitForLoad(node->condition()));
61.481 - if (!type || !canTest(node->condition(), type)) {
61.482 - return;
61.483 - }
61.484 -
61.485 - ControlStatus status = visitForControl(node->body());
61.486 -
61.487 - // Detect loops that will always have a fork in the control-flow graph.
61.488 - // This will be a |while| loop, or a |do-while| loop whose body does
61.489 - // not terminate.
61.490 - //
61.491 - // For now, we treat these as an |if| regardless of the direction the
61.492 - // branch can take. That means the control-flow is always conditional.
61.493 - if (node->token() == TOK_WHILE ||
61.494 - !status.terminates() ||
61.495 - loop.breaks())
61.496 - {
61.497 - control_->merge(status, ControlStatus(false, Returns_Never));
61.498 - } else {
61.499 - // At this point, we've got a do-while loop with a |return| or
61.500 - // |continue|, meaning that the rest of the block is unreachable.
61.501 - control_->terminate(status.returns());
61.502 - }
61.503 -}
61.504 -
61.505 -void
61.506 -SemanticAnalysis::visit(BlockStatement *node)
61.507 -{
61.508 - if (node->scope())
61.509 - scope_ = node->scope();
61.510 - for (size_t i = 0; i < node->statements()->length(); i++) {
61.511 - Statement *statement = node->statements()->at(i);
61.512 - statement->accept(this);
61.513 - }
61.514 - if (node->scope())
61.515 - scope_ = scope_->enclosing();
61.516 -}
61.517 -
61.518 -void
61.519 -SemanticAnalysis::visit(VariableDeclaration *node)
61.520 -{
61.521 - Local<String> tag(zone_, node->tag());
61.522 - Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
61.523 - if (!type)
61.524 - return;
61.525 -
61.526 - if (node->postDimensions()) {
61.527 - Local<Type> init(zone_);
61.528 - if (node->initialization()) {
61.529 - if ((init = visitForLoad(node->initialization())) == NULL)
61.530 - return;
61.531 - }
61.532 -
61.533 - if (node->postDimensions()->length() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
61.534 - cc_.reportError(node->pos(), Message_MaximumArrayDepth);
61.535 - return;
61.536 - }
61.537 -
61.538 - // If we have an initializer, make sure it's the same type.
61.539 - if (init && node->postDimensions()->length() != init->levels()) {
61.540 - cc_.reportError(node->pos(), Message_ArrayInitializerDepth);
61.541 - return;
61.542 - }
61.543 -
61.544 - Local<Type> check(zone_, init);
61.545 - for (size_t i = node->postDimensions()->length() - 1; i < node->postDimensions()->length(); i--) {
61.546 - Expression *expr = node->postDimensions()->at(i);
61.547 - int size = -1;
61.548 -
61.549 - if (expr) {
61.550 - Local<Type> exprType(zone_, visitForLoad(expr));
61.551 - if (!exprType)
61.552 - return;
61.553 -
61.554 - if (!IsPrimitiveType(exprType, PrimitiveType_Int32)) {
61.555 - cc_.reportError(expr->pos(), Message_ArrayDimensionNotInteger);
61.556 - return;
61.557 - }
61.558 -
61.559 - BoxedPrimitive box;
61.560 - if (EvaluateForConstant(expr, &box) && box.type() == PrimitiveType_Int32) {
61.561 - size = box.toInt();
61.562 - if (size <= 0) {
61.563 - cc_.reportError(expr->pos(), Message_BadArraySize);
61.564 - return;
61.565 - }
61.566 - if (size >= INT_MAX / sizeof(int)) {
61.567 - cc_.reportError(expr->pos(), Message_ArraySizeTooBig);
61.568 - return;
61.569 - }
61.570 -
61.571 - if (check) {
61.572 - if (check->elements() == -1) {
61.573 - cc_.reportError(expr->pos(), Message_ArraySizeCannotBeDetermined);
61.574 - return;
61.575 - }
61.576 -
61.577 - if (check->isCharArray()) {
61.578 - if (check->elements() > size) {
61.579 - cc_.reportError(node->pos(), Message_ArrayAssignmentTooBig);
61.580 - return;
61.581 - }
61.582 - } else if (check->elements() != size) {
61.583 - cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, unsigned(i));
61.584 - return;
61.585 - }
61.586 - }
61.587 - } else {
61.588 - if (init) {
61.589 - cc_.reportError(node->pos(), Message_DynamicArrayHasInitializer);
61.590 - return;
61.591 - }
61.592 -
61.593 - // here until we get dynamic array support.
61.594 - cc_.reportError(expr->pos(), Message_ArrayDimensionNotInteger);
61.595 - return;
61.596 - }
61.597 - } else {
61.598 - // Infer the size from the initializer.
61.599 - if (!init) {
61.600 - cc_.reportError(node->pos(), Message_ArraySizeNotSpecified);
61.601 - return;
61.602 - }
61.603 - if (init->elements() == -1) {
61.604 - cc_.reportError(node->pos(), Message_ArraySizeCannotBeDetermined);
61.605 - return;
61.606 - }
61.607 - size = init->elements();
61.608 - }
61.609 -
61.610 - type = zone_->types()->unsafeArray(type, size, false);
61.611 - if (!type)
61.612 - return;
61.613 -
61.614 - if (check)
61.615 - check = check->contained();
61.616 - }
61.617 -
61.618 - // If this variable is stack allocated, we could use the LIFO heap
61.619 - // to allocate it. If that's the case, make sure to reserve a slot
61.620 - // so we can unwind the LIFO heap at the end of this scope.
61.621 - if (!node->variable()->needsHeapAllocation())
61.622 - scope_->setUsesLifoHeap();
61.623 - } else {
61.624 - if (node->initialization()) {
61.625 - Local<Type> right(zone_, visitForLoad(node->initialization()));
61.626 - if (!right)
61.627 - return;
61.628 - if (!typeCheckAssignment(node, type, right, true))
61.629 - return;
61.630 - }
61.631 - if (type->primitive() == PrimitiveType_Char) {
61.632 - cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
61.633 - return;
61.634 - }
61.635 - }
61.636 -
61.637 - node->variable()->setType(type);
61.638 -}
61.639 -
61.640 -void
61.641 -SemanticAnalysis::visit(IntegerLiteral *node)
61.642 -{
61.643 - node->setType(zone_->types()->getPrimitive(PrimitiveType_Int32));
61.644 -}
61.645 -
61.646 -void
61.647 -SemanticAnalysis::visit(ExpressionStatement *node)
61.648 -{
61.649 - visitAndApplyType(node->expression());
61.650 -}
61.651 -
61.652 -bool
61.653 -SemanticAnalysis::preanalyze(FunctionStatement *node)
61.654 -{
61.655 - Local<FixedArray> args(zone_, FixedArray::New(zone_, node->parameters()->length(), Heap::Tenure_Old));
61.656 - if (!args)
61.657 - return false;
61.658 -
61.659 - // Apply types to arguments.
61.660 - for (size_t i = 0; i < node->parameters()->length(); i++) {
61.661 - Parameter *parameter = node->parameters()->at(i);
61.662 -
61.663 - Local<String> tag(zone_, parameter->tag());
61.664 - Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
61.665 - if (!type)
61.666 - return false;
61.667 -
61.668 - if (parameter->reference()) {
61.669 - if (parameter->dimensions()) {
61.670 - cc_.reportError(parameter->variable()->pos(), Message_ArrayCantBeReference);
61.671 - return NULL;
61.672 - }
61.673 -
61.674 - type = zone_->types()->getReference(type, parameter->isConst());
61.675 - if (!type)
61.676 - return false;
61.677 - } else if (parameter->dimensions()) {
61.678 - if (parameter->dimensions()->length() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
61.679 - cc_.reportError(parameter->variable()->pos(), Message_MaximumArrayDepth);
61.680 - return false;
61.681 - }
61.682 -
61.683 - if (node->fun()->isNative() && parameter->dimensions()->length() > 1) {
61.684 - cc_.reportError(parameter->variable()->pos(), Message_MultiArrayInNative);
61.685 - return false;
61.686 - }
61.687 -
61.688 - for (size_t i = parameter->dimensions()->length() - 1;
61.689 - i < parameter->dimensions()->length();
61.690 - i++)
61.691 - {
61.692 - int size = Type::UNKNOWN_SIZE;
61.693 - if (Expression *expr = parameter->dimensions()->at(i)) {
61.694 - BoxedPrimitive box;
61.695 - if (!EvaluateForConstant(expr, &box)) {
61.696 - cc_.reportError(expr->pos(), Message_ArraySizeMustBeConstant);
61.697 - return false;
61.698 - }
61.699 - size = box.toInt();
61.700 - }
61.701 -
61.702 - type = zone_->types()->unsafeArray(type, size, parameter->isConst());
61.703 - if (!type)
61.704 - return false;
61.705 - }
61.706 - }
61.707 -
61.708 - if ((type->isPrimitive() && type->primitive() == PrimitiveType_Char) ||
61.709 - (type->isReference() && type->contained()->primitive() == PrimitiveType_Char))
61.710 - {
61.711 - cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
61.712 - return false;
61.713 - }
61.714 -
61.715 - args->set(zone_, i, type);
61.716 - parameter->variable()->setType(type);
61.717 - }
61.718 -
61.719 - Local<Type> returnType(zone_);
61.720 - if (node->hasExplicitReturn() || node->fun()->isNative())
61.721 - returnType = zone_->types()->getPrimitive(PrimitiveType_Int32);
61.722 - else
61.723 - returnType = zone_->types()->getVoid();
61.724 - if (!returnType)
61.725 - return false;
61.726 -
61.727 - Local<Type> funtype(zone_);
61.728 - if (node->fun()->isNative())
61.729 - funtype = zone_->types()->newNative(returnType, args, node->fun()->isNativeVariadic());
61.730 - else
61.731 - funtype = zone_->types()->newFunction(returnType, args);
61.732 - if (!funtype)
61.733 - return false;
61.734 -
61.735 - // If the function already has a type, it was forward declared before, and
61.736 - // now this is our chance to type check the second declaration.
61.737 - if (node->fun()->type()) {
61.738 - Local<Type> forward(zone_, node->fun()->type());
61.739 - if (!Type::Compare(funtype, forward)) {
61.740 - cc_.reportError(node->pos(), Message_ForwardDeclareMismatches);
61.741 - return false;
61.742 - }
61.743 - node->fun()->setForwardType(forward);
61.744 - }
61.745 -
61.746 - node->fun()->setType(funtype);
61.747 -
61.748 - return true;
61.749 -}
61.750 -
61.751 -void
61.752 -SemanticAnalysis::visit(FunctionStatement *node)
61.753 -{
61.754 - function_ = node->fun()->type();
61.755 - scope_ = node->scope();
61.756 -
61.757 - ControlScope control(&control_);
61.758 - if (node->body()) {
61.759 - node->body()->accept(this);
61.760 -
61.761 - ControlStatus status = control.status();
61.762 - if (status.returns() == Returns_Sometimes) {
61.763 - cc_.reportError(node->pos(), Message_NotAllPathsReturnValue);
61.764 - } else if (status.returns() == Returns_Never) {
61.765 - if (!function_->returnType()->isVoid())
61.766 - cc_.reportError(node->pos(), Message_MissingReturnValue);
61.767 - }
61.768 - }
61.769 -
61.770 - scope_ = NULL;
61.771 - function_ = NULL;
61.772 -}
61.773 -
61.774 -bool
61.775 -SemanticAnalysis::typeCheckArrayAssignment(AstNode *node, Handle<Type> argGiven, Handle<Type> argActual, bool forAssign)
61.776 -{
61.777 - Local<Type> actual(zone_, argActual);
61.778 - Local<Type> given(zone_, argGiven);
61.779 -
61.780 - if (!given->isArray()) {
61.781 - cc_.reportError(node->pos(), Message_ExpectedArray);
61.782 - return false;
61.783 - }
61.784 - if (given->levels() != actual->levels()) {
61.785 - cc_.reportError(node->pos(), Message_ArrayDimensionsMismatch);
61.786 - return false;
61.787 - }
61.788 -
61.789 - unsigned level = 0;
61.790 - while (given->isArray()) {
61.791 - if (actual->elements() != -1) {
61.792 - if (forAssign) {
61.793 - if (given->elements() == -1 || actual->elements() == -1) {
61.794 - cc_.reportError(node->pos(), Message_ArraySizeNotKnown);
61.795 - return false;
61.796 - }
61.797 -
61.798 - if (actual->isCharArray()) {
61.799 - // String assignment can have a truncated |given|.
61.800 - if (given->elements() > actual->elements()) {
61.801 - cc_.reportError(node->pos(), Message_ArrayAssignmentTooBig);
61.802 - return false;
61.803 - }
61.804 - } else {
61.805 - if (given->elements() != actual->elements()) {
61.806 - cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, level);
61.807 - return false;
61.808 - }
61.809 - }
61.810 - } else {
61.811 - if (actual->elements() != -1 && given->elements() != actual->elements()) {
61.812 - cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, level);
61.813 - return false;
61.814 - }
61.815 - }
61.816 - }
61.817 - given = given->contained();
61.818 - actual = actual->contained();
61.819 - }
61.820 -
61.821 - if (given->primitive() != actual->primitive()) {
61.822 - // :TODO: leaks an interior pointer.
61.823 - const char *givenTag = given->tag() ? given->tag()->chars() : "_";
61.824 - const char *actualTag = given->tag() ? given->tag()->chars() : "_";
61.825 - cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
61.826 - return false;
61.827 - }
61.828 -
61.829 - return true;
61.830 -}
61.831 -
61.832 -bool
61.833 -SemanticAnalysis::typeCheckAssignment(AstNode *node, Handle<Type> argGiven, Handle<Type> argActual, bool forAssign)
61.834 -{
61.835 - Local<Type> actual(zone_, argActual);
61.836 - Local<Type> given(zone_, argGiven);
61.837 -
61.838 - if (actual->isArray())
61.839 - return typeCheckArrayAssignment(node, given, actual, forAssign);
61.840 -
61.841 - if (given->isArray()) {
61.842 - cc_.reportError(node->pos(), Message_CannotAssignArrayToScalar);
61.843 - return false;
61.844 - }
61.845 -
61.846 - // The given type may not have been dereferenced.
61.847 - if (given->isReference())
61.848 - given = given->contained();
61.849 - if (actual->isReference())
61.850 - actual = actual->contained();
61.851 -
61.852 - if (!given->isPrimitive() || !actual->isPrimitive()) {
61.853 - cc_.reportError(node->pos(), Message_UnsupportedType);
61.854 - return false;
61.855 - }
61.856 -
61.857 - if (given->primitive() != actual->primitive()) {
61.858 - // :TODO: leaks an interior pointer
61.859 - const char *givenTag = given->tag() ? given->tag()->chars() : "_";
61.860 - const char *actualTag = actual->tag() ? actual->tag()->chars() : "_";
61.861 - cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
61.862 - return false;
61.863 - }
61.864 -
61.865 - return true;
61.866 -}
61.867 -
61.868 -bool
61.869 -SemanticAnalysis::typeCheckParameter(AstNode *node, Handle<Type> given, Handle<Type> actual)
61.870 -{
61.871 - return typeCheckAssignment(node, given, actual, false);
61.872 -}
61.873 -
61.874 -void
61.875 -SemanticAnalysis::visit(CallExpression *node)
61.876 -{
61.877 - Local<Type> type(zone_, visitForLoad(node->callee()));
61.878 - if (!type)
61.879 - return;
61.880 -
61.881 - if (!type->isFunction()) {
61.882 - cc_.reportError(node->pos(), Message_CalleeNotFunction);
61.883 - return;
61.884 - }
61.885 - if (node->arguments()->length() != type->parameters()->length()) {
61.886 - if (!type->isNative() ||
61.887 - !type->isNativeVariadic() ||
61.888 - node->arguments()->length() < type->parameters()->length())
61.889 - {
61.890 - cc_.reportError(node->pos(), Message_ArgumentCountMismatch);
61.891 - return;
61.892 - }
61.893 - }
61.894 -
61.895 - // Currently, only calls from a NameProxy are possible.
61.896 - NamedFunction *fun = node->callee()->toNameProxy()->binding()->toNamedFunction();
61.897 - if (fun->isForward()) {
61.898 - cc_.reportError(node->pos(), Message_ForwardNotImplemented, fun->name()->chars());
61.899 - return;
61.900 - }
61.901 -
61.902 - for (unsigned i = 0; i < node->arguments()->length(); i++) {
61.903 - // Note: we don't compute references unless the callee needs a
61.904 - // reference type.
61.905 - Expression *expression = node->arguments()->at(i);
61.906 - Local<Type> given(zone_, visitAndApplyType(expression));
61.907 - if (!given)
61.908 - return;
61.909 -
61.910 - // Since we skip a load, check for a call expression that returns void.
61.911 - if (given->isVoid()) {
61.912 - assert(expression->isCallExpression());
61.913 - CallExpression *call = expression->toCallExpression();
61.914 - cc_.reportError(call->callee()->pos(), Message_FunctionDoesNotReturnValue);
61.915 - return;
61.916 - }
61.917 -
61.918 - // If it's an IndexExpression, we special case the ability to compute
61.919 - // a reference.
61.920 - if (expression->isIndexExpression())
61.921 - given = given->contained();
61.922 -
61.923 - bool mustComputeReference;
61.924 - if (i >= type->parameters()->length()) {
61.925 - // Special handling for natives. Arguments past the formal must
61.926 - // always have references computed. However, arrays are already
61.927 - // references for natives.
61.928 - assert(type->isNative() && type->isNativeVariadic());
61.929 - mustComputeReference = !given->isReference() && !given->isArray();
61.930 - } else {
61.931 - Local<Type> actual(zone_, type->parameterAt(i));
61.932 - if (!typeCheckParameter(expression, given, actual))
61.933 - return;
61.934 - mustComputeReference = actual->isReference() && !given->isReference();
61.935 - }
61.936 -
61.937 - // If the actual is a reference, and the given is not, we'll need to
61.938 - // compute a reference, which may be allocated on the stack.
61.939 - if (mustComputeReference)
61.940 - scope_->setUsesLifoHeap();
61.941 - }
61.942 -
61.943 - node->setType(fun->type()->returnType());
61.944 -}
61.945 -
61.946 -void
61.947 -SemanticAnalysis::ControlScope::merge(const ControlStatus &left, const ControlStatus &right)
61.948 -{
61.949 - // If both sides terminate in a return, we consider this a return as well.
61.950 - if (left.returns() == Returns_Always && right.returns() == Returns_Always) {
61.951 - terminate(Returns_Always);
61.952 - return;
61.953 - }
61.954 -
61.955 - ReturnStatus status = (left.returns() == Returns_Never && right.returns() == Returns_Never)
61.956 - ? Returns_Never
61.957 - : Returns_Sometimes;
61.958 -
61.959 - if (left.terminates() && right.terminates())
61.960 - terminate(status);
61.961 - else
61.962 - returns(status);
61.963 -}
61.964 -
61.965 -void
61.966 -SemanticAnalysis::visit(IfStatement *node)
61.967 -{
61.968 - Local<Type> type(zone_, visitForLoad(node->condition()));
61.969 - if (!type)
61.970 - return;
61.971 -
61.972 - if (!canTest(node, type))
61.973 - return;
61.974 -
61.975 - ControlStatus trueBranch = visitForControl(node->ifTrue());
61.976 - ControlStatus falseBranch = ControlStatus(false, Returns_Never);
61.977 -
61.978 - if (node->ifFalse())
61.979 - falseBranch = visitForControl(node->ifFalse());
61.980 -
61.981 - control_->merge(trueBranch, falseBranch);
61.982 -}
61.983 -
61.984 -void
61.985 -SemanticAnalysis::visit(IndexExpression *node)
61.986 -{
61.987 - Local<Type> left(zone_, visitForLoad(node->left()));
61.988 - Local<Type> right(zone_, visitForLoad(node->right()));
61.989 -
61.990 - if (!left || !right)
61.991 - return;
61.992 -
61.993 - if (!right->isInt32()) {
61.994 - cc_.reportError(node->right()->pos(), Message_IndexMustBeInteger);
61.995 - return;
61.996 - }
61.997 - if (!left->isArray()) {
61.998 - cc_.reportError(node->left()->pos(), Message_IndexBaseMustBeArray);
61.999 - return;
61.1000 - }
61.1001 - node->setType(left);
61.1002 -}
61.1003 -
61.1004 -void
61.1005 -SemanticAnalysis::visit(EnumStatement *node)
61.1006 -{
61.1007 - // Forbid the blessed types.
61.1008 - Local<String> tag(zone_, node->name());
61.1009 - if (!strcmp(tag->chars(), "Float") ||
61.1010 - !strcmp(tag->chars(), "String") ||
61.1011 - !strcmp(tag->chars(), "any") ||
61.1012 - !strcmp(tag->chars(), "bool"))
61.1013 - {
61.1014 - cc_.reportError(node->pos(), Message_InvalidEnumName);
61.1015 - return;
61.1016 - }
61.1017 -
61.1018 - Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
61.1019 - if (!type)
61.1020 - return;
61.1021 -
61.1022 - int value = 0;
61.1023 - for (size_t i = 0; i < node->entries()->length(); i++) {
61.1024 - EnumStatement::Entry &entry = node->entries()->at(i);
61.1025 -
61.1026 - BoxedPrimitive box = BoxedPrimitive::Int(value);
61.1027 - if (entry.expr) {
61.1028 - entry.expr->accept(this);
61.1029 - if (!EvaluateForConstant(entry.expr, &box)) {
61.1030 - cc_.reportError(entry.expr->pos(), Message_EnumFieldNotConstant);
61.1031 - return;
61.1032 - }
61.1033 -
61.1034 - assert(box.type() == PrimitiveType_Int32);
61.1035 - value = box.toInt();
61.1036 - }
61.1037 -
61.1038 - entry.name->set(type, box);
61.1039 - value++;
61.1040 - }
61.1041 -}
61.1042 -
61.1043 -void
61.1044 -SemanticAnalysis::visit(StringLiteral *node)
61.1045 -{
61.1046 - Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Char));
61.1047 - if (!type)
61.1048 - return;
61.1049 -
61.1050 - type = Type::NewArray(zone_, type, node->string()->length() + 1, true);
61.1051 - if (!type)
61.1052 - return;
61.1053 -
61.1054 - node->setType(type);
61.1055 -}
61.1056 -
61.1057 -void
61.1058 -SemanticAnalysis::visit(FloatLiteral *node)
61.1059 -{
61.1060 - Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Float));
61.1061 - if (!type)
61.1062 - return;
61.1063 -
61.1064 - node->setType(type);
61.1065 -}
61.1066 -
61.1067 -void
61.1068 -SemanticAnalysis::visit(BreakStatement *node)
61.1069 -{
61.1070 - if (!loop_) {
61.1071 - cc_.reportError(node->pos(), Message_BreakOutsideLoop);
61.1072 - return;
61.1073 - }
61.1074 -
61.1075 - // Note: ignore breaks that occur in unreachable control-flow.
61.1076 - if (!control_->status().terminates())
61.1077 - loop_->addBreak();
61.1078 -
61.1079 - control_->terminate(Returns_Never);
61.1080 -}
61.1081 -
61.1082 -void
61.1083 -SemanticAnalysis::visit(ContinueStatement *node)
61.1084 -{
61.1085 - if (!loop_) {
61.1086 - cc_.reportError(node->pos(), Message_ContinueOutsideLoop);
61.1087 - return;
61.1088 - }
61.1089 -
61.1090 - // Note: ignore continues that occur in unreachable control-flow.
61.1091 - if (!control_->status().terminates())
61.1092 - loop_->addContinue();
61.1093 -
61.1094 - control_->terminate(Returns_Never);
61.1095 -}
62.1 --- a/jitcraft/SemanticAnalysis.h Tue Jul 24 23:53:34 2012 -0700
62.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
62.3 @@ -1,204 +0,0 @@
62.4 -/* vim: set ts=4 sw=4 tw=99 et:
62.5 - *
62.6 - * Copyright (C) 2012 David Anderson
62.7 - *
62.8 - * This file is part of JITCraft.
62.9 - *
62.10 - * JITCraft is free software: you can redistribute it and/or modify it under
62.11 - * the terms of the GNU General Public License as published by the Free
62.12 - * Software Foundation, either version 3 of the License, or (at your option)
62.13 - * any later version.
62.14 - *
62.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
62.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
62.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
62.18 - *
62.19 - * You should have received a copy of the GNU General Public License along with
62.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
62.21 - */
62.22 -#ifndef _include_semantic_analysis_h_
62.23 -#define _include_semantic_analysis_h_
62.24 -
62.25 -#include <assert.h>
62.26 -#include "AST.h"
62.27 -
62.28 -namespace ke {
62.29 -
62.30 -class SemanticAnalysis : public AstVisitor
62.31 -{
62.32 - Zone *zone_;
62.33 - CompileContext &cc_;
62.34 - ParseTree *tree_;
62.35 - Scope *scope_;
62.36 - ScopedRoot<Type> function_;
62.37 -
62.38 - enum ReturnStatus
62.39 - {
62.40 - Returns_Never,
62.41 - Returns_Sometimes,
62.42 - Returns_Always
62.43 - };
62.44 -
62.45 - // Tuple that describes whether a path terminates control flow, and
62.46 - // if it is guaranteed to end in a return.
62.47 - class ControlStatus
62.48 - {
62.49 - bool terminates_;
62.50 - ReturnStatus returns_;
62.51 -
62.52 - public:
62.53 - ControlStatus(bool terminates, ReturnStatus returns)
62.54 - : terminates_(terminates),
62.55 - returns_(returns)
62.56 - {
62.57 - }
62.58 -
62.59 - bool terminates() const {
62.60 - return terminates_;
62.61 - }
62.62 - ReturnStatus returns() const {
62.63 - return returns_;
62.64 - }
62.65 - };
62.66 -
62.67 - // Used to keep track of terminating control flow and return statements
62.68 - // inside control structures.
62.69 - class ControlScope
62.70 - {
62.71 - ReturnStatus returns_;
62.72 - ControlScope **prevp_;
62.73 - ControlScope *prev_;
62.74 - bool terminates_;
62.75 -
62.76 - public:
62.77 - ControlScope(ControlScope **prev)
62.78 - : returns_(Returns_Never),
62.79 - prevp_(prev),
62.80 - prev_(*prev),
62.81 - terminates_(false)
62.82 - {
62.83 - *prevp_ = this;
62.84 - }
62.85 -
62.86 - ControlStatus status() const {
62.87 - return ControlStatus(terminates_, returns_);
62.88 - }
62.89 -
62.90 - // We allow multiple terminators, but only the first one takes effect.
62.91 - // For example, |break; continue;| is legal but the continue is
62.92 - // unreachable.
62.93 - void returns(ReturnStatus status) {
62.94 - if (terminates_)
62.95 - return;
62.96 - if (status > returns_)
62.97 - returns_ = status;
62.98 - }
62.99 - void terminate(ReturnStatus status) {
62.100 - if (terminates_)
62.101 - return;
62.102 - terminates_ = true;
62.103 - returns_ = status;
62.104 - }
62.105 - void merge(const ControlStatus &left, const ControlStatus &right);
62.106 -
62.107 - ~ControlScope()
62.108 - {
62.109 - *prevp_ = prev_;
62.110 - }
62.111 - };
62.112 -
62.113 - class LoopScope
62.114 - {
62.115 - LoopScope **prevp_;
62.116 - LoopScope *prev_;
62.117 - unsigned breaks_;
62.118 - unsigned continues_;
62.119 -
62.120 - public:
62.121 - LoopScope(LoopScope **prev)
62.122 - : prevp_(prev),
62.123 - prev_(*prev),
62.124 - breaks_(0),
62.125 - continues_(0)
62.126 - {
62.127 - *prevp_ = this;
62.128 - }
62.129 -
62.130 - ~LoopScope()
62.131 - {
62.132 - *prevp_ = prev_;
62.133 - }
62.134 -
62.135 - void addBreak() {
62.136 - breaks_++;
62.137 - }
62.138 - void addContinue() {
62.139 - continues_++;
62.140 - }
62.141 - unsigned breaks() const {
62.142 - return breaks_;
62.143 - }
62.144 - unsigned continues() const {
62.145 - return continues_;
62.146 - }
62.147 - };
62.148 -
62.149 - ControlScope *control_;
62.150 - LoopScope *loop_;
62.151 -
62.152 - private:
62.153 - bool canTest(AstNode *node, Handle<Type> type);
62.154 - void unaryTypeError(AstNode *node, TokenKind token, Handle<Type> type);
62.155 - void binaryTypeError(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right);
62.156 - Type *typeCheckBinary(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right);
62.157 -
62.158 - // These check if one type is compatible with another type, for various
62.159 - // purposes, like:
62.160 - // return (expr) matches function return type
62.161 - // call(a, b) matches expected arg type
62.162 - // a = b matches declared type
62.163 - //
62.164 - bool typeCheckArrayAssignment(AstNode *node, Handle<Type> given, Handle<Type> actual, bool forAssign);
62.165 - bool typeCheckAssignment(AstNode *node, Handle<Type> given, Handle<Type> actual, bool forAssign);
62.166 - bool typeCheckParameter(AstNode *node, Handle<Type> given, Handle<Type> actual);
62.167 -
62.168 - Type *visitForLoad(Expression *expression);
62.169 - bool preanalyze(FunctionStatement *node);
62.170 - Type *visitForLValue(Expression *expression);
62.171 - Type *visitAndApplyType(Expression *expression);
62.172 - ControlStatus visitForControl(Statement *statement);
62.173 -
62.174 - void markCallResultUsed(CallExpression *call);
62.175 -
62.176 - public:
62.177 - SemanticAnalysis(Zone *zone, CompileContext &cc, ParseTree *tree);
62.178 - bool analyze();
62.179 -
62.180 - public:
62.181 - void visit(NameProxy *name);
62.182 - void visit(Assignment *node);
62.183 - void visit(BinaryExpression *node);
62.184 - void visit(ReturnStatement *node);
62.185 - void visit(ForStatement *node);
62.186 - void visit(BlockStatement *node);
62.187 - void visit(VariableDeclaration *node);
62.188 - void visit(IntegerLiteral *node);
62.189 - void visit(ExpressionStatement *node);
62.190 - void visit(FunctionStatement *node);
62.191 - void visit(CallExpression *node);
62.192 - void visit(IfStatement *node);
62.193 - void visit(IndexExpression *node);
62.194 - void visit(EnumStatement *node);
62.195 - void visit(FloatLiteral *node);
62.196 - void visit(WhileStatement *node);
62.197 - void visit(BreakStatement *node);
62.198 - void visit(ContinueStatement *node);
62.199 - void visit(StringLiteral *node);
62.200 - void visit(IncDecExpression *node);
62.201 - void visit(UnaryExpression *node);
62.202 - void visit(TernaryExpression *node);
62.203 -};
62.204 -
62.205 -} // namespace ke
62.206 -
62.207 -#endif // _include_semantic_analysis_h_
63.1 --- a/jitcraft/Spaces-inl.h Tue Jul 24 23:53:34 2012 -0700
63.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
63.3 @@ -1,59 +0,0 @@
63.4 -/* vim: set ts=4 sw=4 tw=99 et:
63.5 - *
63.6 - * Copyright (C) 2012 David Anderson
63.7 - *
63.8 - * This file is part of JITCraft.
63.9 - *
63.10 - * JITCraft is free software: you can redistribute it and/or modify it under
63.11 - * the terms of the GNU General Public License as published by the Free
63.12 - * Software Foundation, either version 3 of the License, or (at your option)
63.13 - * any later version.
63.14 - *
63.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
63.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
63.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
63.18 - *
63.19 - * You should have received a copy of the GNU General Public License along with
63.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
63.21 - */
63.22 -#ifndef _include_jitcraft_spaces_inl_h_
63.23 -#define _include_jitcraft_spaces_inl_h_
63.24 -
63.25 -namespace ke {
63.26 -
63.27 -inline Address
63.28 -HeapStack::allocate(size_t nbytes)
63.29 -{
63.30 - nbytes = Align(nbytes, kObjectAlignment);
63.31 -
63.32 - if (cursor_ + nbytes > chunk_->end())
63.33 - return NULL;
63.34 -
63.35 - Address ptr = cursor_;
63.36 - cursor_ += nbytes;
63.37 - return ptr;
63.38 -}
63.39 -
63.40 -inline void
63.41 -HeapStack::unwind(Address to)
63.42 -{
63.43 - assert(to <= cursor_ && to >= chunk_->first());
63.44 - cursor_ = to;
63.45 -}
63.46 -
63.47 -inline Address
63.48 -OldSpace::allocate(size_t nbytes)
63.49 -{
63.50 - assert(IsAligned(nbytes, kObjectAlignment));
63.51 -
63.52 - if (cursor_ + nbytes > last_->end())
63.53 - return allocateSlow(nbytes);
63.54 -
63.55 - Address addr = cursor_;
63.56 - cursor_ += nbytes;
63.57 - return addr;
63.58 -}
63.59 -
63.60 -}
63.61 -
63.62 -#endif // _include_jitcraft_spaces_inl_h_
64.1 --- a/jitcraft/Spaces.cpp Tue Jul 24 23:53:34 2012 -0700
64.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
64.3 @@ -1,307 +0,0 @@
64.4 -/* vim: set ts=4 sw=4 tw=99 et:
64.5 - *
64.6 - * Copyright (C) 2012 David Anderson
64.7 - *
64.8 - * This file is part of JITCraft.
64.9 - *
64.10 - * JITCraft is free software: you can redistribute it and/or modify it under
64.11 - * the terms of the GNU General Public License as published by the Free
64.12 - * Software Foundation, either version 3 of the License, or (at your option)
64.13 - * any later version.
64.14 - *
64.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
64.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
64.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
64.18 - *
64.19 - * You should have received a copy of the GNU General Public License along with
64.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
64.21 - */
64.22 -#include "Zone.h"
64.23 -#include "Spaces.h"
64.24 -#include "Platform.h"
64.25 -#include "Spaces-inl.h"
64.26 -
64.27 -using namespace ke;
64.28 -
64.29 -HeapStack::HeapStack()
64.30 - : chunk_(NULL),
64.31 - cursor_(NULL)
64.32 -{
64.33 -}
64.34 -
64.35 -HeapStack::~HeapStack()
64.36 -{
64.37 - if (chunk_)
64.38 - HeapChunk::Destroy(chunk_);
64.39 -}
64.40 -
64.41 -bool
64.42 -HeapStack::initialize()
64.43 -{
64.44 - chunk_ = HeapChunk::New(NULL, kStackSize);
64.45 - cursor_ = chunk_->first();
64.46 - return true;
64.47 -}
64.48 -
64.49 -HeapChunk *
64.50 -HeapChunk::New(HeapChunk *prev, size_t size)
64.51 -{
64.52 - OS::AlignableMapping map =
64.53 - OS::MapAlignedMemory(size, HeapChunk::kAlignment, OS::Map_Commit);
64.54 -
64.55 - if (!map.base())
64.56 - return NULL;
64.57 -
64.58 - HeapChunk *chunk = reinterpret_cast<HeapChunk *>(map.aligned());
64.59 - chunk->base_ = map.base();
64.60 - chunk->end_ = map.base() + map.size();
64.61 - if (prev)
64.62 - prev->next_ = chunk;
64.63 -
64.64 - return chunk;
64.65 -}
64.66 -
64.67 -void
64.68 -HeapChunk::Destroy(HeapChunk *chunk)
64.69 -{
64.70 - OS::UnmapAlignedMemory(chunk->base(), chunk->size());
64.71 -}
64.72 -
64.73 -void
64.74 -HeapChunk::resetMarkBits()
64.75 -{
64.76 - memset(markBits(), 0, kMarkBytes);
64.77 -}
64.78 -
64.79 -FreeList::FreeList()
64.80 - : small_objects_(NULL),
64.81 - medium_objects_(NULL),
64.82 - large_objects_(NULL),
64.83 - huge_objects_(NULL)
64.84 -{
64.85 -}
64.86 -
64.87 -void
64.88 -FreeList::add(FreedObject *obj)
64.89 -{
64.90 - if (obj->size() < kMinObjectSize)
64.91 - return;
64.92 -
64.93 - FreedObject **list;
64.94 - if (obj->size() < kMaxSmallObject)
64.95 - list = &small_objects_;
64.96 - else if (obj->size() < kMaxMediumObject)
64.97 - list = &medium_objects_;
64.98 - else if (obj->size() < kMaxLargeObject)
64.99 - list = &large_objects_;
64.100 - else
64.101 - list = &huge_objects_;
64.102 -
64.103 - if (*list)
64.104 - (*list)->setNext(obj);
64.105 - *list = obj;
64.106 -}
64.107 -
64.108 -FreedObject *
64.109 -FreeList::pick(size_t size)
64.110 -{
64.111 - if (size < kMinObjectSize && small_objects_) {
64.112 - FreedObject *obj = small_objects_;
64.113 - small_objects_ = small_objects_->next();
64.114 - return obj;
64.115 - }
64.116 - if (size < kMaxSmallObject && medium_objects_) {
64.117 - FreedObject *obj = medium_objects_;
64.118 - medium_objects_ = medium_objects_->next();
64.119 - return obj;
64.120 - }
64.121 - if (size < kMaxMediumObject && large_objects_) {
64.122 - FreedObject *obj = large_objects_;
64.123 - large_objects_ = large_objects_->next();
64.124 - return obj;
64.125 - }
64.126 - if (huge_objects_) {
64.127 - FreedObject *obj = huge_objects_;
64.128 - huge_objects_ = huge_objects_->next();
64.129 - return obj;
64.130 - }
64.131 - return NULL;
64.132 -}
64.133 -
64.134 -void
64.135 -FreeList::reset()
64.136 -{
64.137 - small_objects_ = NULL;
64.138 - medium_objects_ = NULL;
64.139 - large_objects_ = NULL;
64.140 - huge_objects_ = NULL;
64.141 -}
64.142 -
64.143 -OldSpace::OldSpace(Zone *zone)
64.144 - : zone_(zone),
64.145 - first_(NULL),
64.146 - last_(NULL)
64.147 -{
64.148 -}
64.149 -
64.150 -bool
64.151 -OldSpace::initialize()
64.152 -{
64.153 - first_ = HeapChunk::New(first_, HeapChunk::kDefaultSize);
64.154 - last_ = first_;
64.155 - cursor_ = first_->first();
64.156 -
64.157 - return !!first_;
64.158 -}
64.159 -
64.160 -OldSpace::~OldSpace()
64.161 -{
64.162 - while (first_) {
64.163 - HeapChunk *temp = first_->next();
64.164 - HeapChunk::Destroy(first_);
64.165 - first_ = temp;
64.166 - }
64.167 -}
64.168 -
64.169 -Address
64.170 -OldSpace::allocateSlow(size_t nbytes)
64.171 -{
64.172 - if (FreedObject *obj = freelist_.pick(nbytes)) {
64.173 - Address address = reinterpret_cast<Address>(obj);
64.174 - size_t actual = obj->size();
64.175 - assert(actual >= nbytes);
64.176 - if (actual != nbytes)
64.177 - markRegionFree(address + nbytes, actual - nbytes);
64.178 -
64.179 - return address;
64.180 - }
64.181 -
64.182 - // Free unused stuff at the end of the current chunk.
64.183 - if (cursor_ != last_->end())
64.184 - markRegionFree(cursor_, last_->end() - cursor_);
64.185 -
64.186 - HeapChunk *chunk;
64.187 - if (last_->next()) {
64.188 - // The next chunk is guaranteed to be empty.
64.189 - chunk = last_->next();
64.190 - } else {
64.191 - chunk = HeapChunk::New(last_, HeapChunk::kDefaultSize);
64.192 - if (!chunk)
64.193 - return NULL;
64.194 - }
64.195 -
64.196 - last_ = chunk;
64.197 - cursor_ = chunk->first();
64.198 -
64.199 - assert(cursor_ + nbytes <= chunk->end());
64.200 -
64.201 - Address address = cursor_;
64.202 - cursor_ += nbytes;
64.203 - return address;
64.204 -}
64.205 -
64.206 -void
64.207 -OldSpace::markRegionFree(Address start, size_t length)
64.208 -{
64.209 - FreedObject *obj = reinterpret_cast<FreedObject *>(start);
64.210 - new (obj) FreedObject(zone_->getMap(MapKind_FreeRegion), length);
64.211 -
64.212 - if (length < sizeof(FreedObject)) {
64.213 - // Can't encode a list in this object, but it's marked free, so we're done.
64.214 - return;
64.215 - }
64.216 -
64.217 - freelist_.add(obj);
64.218 -}
64.219 -
64.220 -void
64.221 -OldSpace::freeUnusedPages()
64.222 -{
64.223 - HeapChunk **prev = &first_;
64.224 - HeapChunk *empty = NULL;
64.225 - while (*prev) {
64.226 - HeapChunk *chunk = *prev;
64.227 - if (chunk->isEmpty()) {
64.228 - *prev = chunk->next();
64.229 - if (empty) {
64.230 - // Remove this chunk.
64.231 - HeapChunk::Destroy(chunk);
64.232 - continue;
64.233 - }
64.234 - empty = chunk;
64.235 - }
64.236 - prev = chunk->nextp();
64.237 - }
64.238 -
64.239 - if (empty) {
64.240 - *empty->nextp() = NULL;
64.241 - *last_->nextp() = empty;
64.242 - }
64.243 -}
64.244 -
64.245 -void
64.246 -OldSpace::resetFreeList()
64.247 -{
64.248 - freelist_.reset();
64.249 -}
64.250 -
64.251 -LargeObjectSpace::LargeObjectSpace()
64.252 - : first_(NULL),
64.253 - last_(NULL)
64.254 -{
64.255 -}
64.256 -
64.257 -LargeObjectSpace::~LargeObjectSpace()
64.258 -{
64.259 - while (first_) {
64.260 - HeapChunk *temp = first_->next();
64.261 - HeapChunk::Destroy(first_);
64.262 - first_ = temp;
64.263 - }
64.264 -}
64.265 -
64.266 -bool
64.267 -LargeObjectSpace::initialize()
64.268 -{
64.269 - return true;
64.270 -}
64.271 -
64.272 -Address
64.273 -LargeObjectSpace::allocate(size_t nbytes)
64.274 -{
64.275 - assert(IsAligned(nbytes, kObjectAlignment));
64.276 -
64.277 - // Always allocate a new chunk for large objects.
64.278 - HeapChunk *chunk = HeapChunk::New(last_, nbytes);
64.279 - if (!chunk)
64.280 - return NULL;
64.281 -
64.282 - if (!first_)
64.283 - first_ = chunk;
64.284 - last_ = chunk;
64.285 -
64.286 - return chunk->first();
64.287 -}
64.288 -
64.289 -void
64.290 -LargeObjectSpace::sweep()
64.291 -{
64.292 - if (!first_)
64.293 - return;
64.294 -
64.295 - HeapChunk **pprev = &first_;
64.296 - do {
64.297 - HeapChunk *chunk = *pprev;
64.298 - Object *obj = reinterpret_cast<Object *>(chunk->first());
64.299 - MarkBit bit = HeapChunk::GetMarkBit(obj);
64.300 - if (HeapChunk::IsWhite(bit)) {
64.301 - *pprev = chunk->next();
64.302 - HeapChunk::Destroy(chunk);
64.303 - } else {
64.304 - assert(HeapChunk::IsBlack(bit));
64.305 - HeapChunk::Clear(bit);
64.306 - pprev = chunk->nextp();
64.307 - last_ = chunk;
64.308 - }
64.309 - } while (*pprev);
64.310 -}
65.1 --- a/jitcraft/Spaces.h Tue Jul 24 23:53:34 2012 -0700
65.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
65.3 @@ -1,434 +0,0 @@
65.4 -/* vim: set ts=4 sw=4 tw=99 et:
65.5 - *
65.6 - * Copyright (C) 2012 David Anderson
65.7 - *
65.8 - * This file is part of JITCraft.
65.9 - *
65.10 - * JITCraft is free software: you can redistribute it and/or modify it under
65.11 - * the terms of the GNU General Public License as published by the Free
65.12 - * Software Foundation, either version 3 of the License, or (at your option)
65.13 - * any later version.
65.14 - *
65.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
65.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
65.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
65.18 - *
65.19 - * You should have received a copy of the GNU General Public License along with
65.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
65.21 - */
65.22 -#ifndef _include_jitcraft_spaces_h_
65.23 -#define _include_jitcraft_spaces_h_
65.24 -
65.25 -#include <limits.h>
65.26 -#include "Utility.h"
65.27 -#include "Platform.h"
65.28 -
65.29 -namespace ke {
65.30 -
65.31 -class Zone;
65.32 -class Object;
65.33 -class Map;
65.34 -
65.35 -static const size_t kObjectAlignment = sizeof(Object *);
65.36 -
65.37 -// Every object gets two successive mark bits. These bits represent various
65.38 -// states during garbage collection:
65.39 -//
65.40 -// WHITE (00): The object is dead or unmarked.
65.41 -// GREY (11): The object is live but its children have not been marked.
65.42 -// BLACK (10): The object and all its children have been marked.
65.43 -//
65.44 -// These colors assist in maintaining the "tri-color invariant", explained
65.45 -// in Heap.h. The bits are organized such that transitioning an object from
65.46 -// White to Black requires one bit change, and Black to Grey requires another.
65.47 -class MarkBit
65.48 -{
65.49 - uint32 *word_;
65.50 - uint32 bit_;
65.51 -
65.52 - public:
65.53 - MarkBit(uint32 *word, uint32 bit)
65.54 - : word_(word),
65.55 - bit_(bit)
65.56 - {
65.57 - assert(bit_ < sizeof(*word_) * 8);
65.58 - }
65.59 -
65.60 - bool isSet() const {
65.61 - return !!(*word_ & (1 << bit_));
65.62 - }
65.63 - void set() {
65.64 - *word_ |= (1 << bit_);
65.65 - }
65.66 - void unset() {
65.67 - *word_ &= ~(1 << bit_);
65.68 - }
65.69 - uint32 *word() {
65.70 - return word_;
65.71 - }
65.72 - MarkBit next() const {
65.73 - if (bit_ == (sizeof(*word_) * 8) - 1)
65.74 - return MarkBit(word_ + 1, 0);
65.75 - return MarkBit(word_, bit_ + 1);
65.76 - }
65.77 -};
65.78 -
65.79 -class HeapChunk
65.80 -{
65.81 - HeapChunk *next_;
65.82 -
65.83 - // Base address, from OS::AlignableMapping.
65.84 - Address base_;
65.85 -
65.86 - // End of the allocated region.
65.87 - Address end_;
65.88 -
65.89 - uintptr_t flags_;
65.90 -
65.91 - public:
65.92 - enum Flag {
65.93 - HAS_OVERFLOWED_OBJECT = (1 << 0),
65.94 - EMPTY = (1 << 1)
65.95 - };
65.96 -
65.97 - public:
65.98 - static const size_t kDefaultSize = 1 * kMB;
65.99 - static const size_t kAlignment = 1 * kMB;
65.100 -
65.101 - // Maximum size of an object that will fit in a page. We limit this
65.102 - // specifically to help JITs: the computation of a[i] has a special
65.103 - // instruction form on most CPUs, but the index might not be sign-
65.104 - // extended on 64-bit architectures. We limit the size such that:
65.105 - //
65.106 - // index * sizeof(Object *)
65.107 - //
65.108 - // Is guaranteed to not overflow a signed 32-bit integer.
65.109 - static const size_t kMaxObjectSize = INT_MAX / sizeof(Object *);
65.110 -
65.111 - // Size of a HeapChunk header.
65.112 - static const size_t kHeaderSize =
65.113 - sizeof(HeapChunk *) +
65.114 - sizeof(Address) +
65.115 - sizeof(Address) +
65.116 - sizeof(Address);
65.117 -
65.118 - // All objects must be allocated in the first kAlignment bytes of the
65.119 - // chunk. We need two mark bits for every allocatable object, since there
65.120 - // are three possible states: White (00), Black (11), and Grey (10). These
65.121 - // bits are stored immediately after the HeapChunk header, and before the
65.122 - // first allocatable object.
65.123 - //
65.124 - // Although object alignment is only at word boundaries, we guarantee that
65.125 - // every object is at least two words. This means we don't need to reserve
65.126 - // two mark bits for every object, just one mark bit for every allocatable
65.127 - // address. That also means a pair of mark bits can cross a byte boundary.
65.128 - //
65.129 - // --- Math ---
65.130 - //
65.131 - // The number of mark bits needed is:
65.132 - //
65.133 - // MaxObjectsPerChunk = (kAlignment / kObjectAlignment)
65.134 - // -> 256KB (128KB on 64-bit)
65.135 - //
65.136 - // The number of bytes needed for these mark bits is:
65.137 - //
65.138 - // NumMarkBytes = MaxObjectsPerChunk / 8
65.139 - // = 32KB (16KB on 64-bit)
65.140 - //
65.141 - // The number of uint32s needed to store these bytes is:
65.142 - //
65.143 - // NumMarkWords = NumMarkBytes / sizeof(uint32)
65.144 - // = 8KB (4KB on 64-bit)
65.145 - //
65.146 - static const size_t kMaxObjectsPerChunk = kAlignment / kObjectAlignment;
65.147 - static const size_t kMarkBits = kMaxObjectsPerChunk;
65.148 - static const size_t kMarkBytes = kMarkBits / 8;
65.149 - static const size_t kMarkWords = kMarkBytes / sizeof(uint32);
65.150 - static const size_t kMarkBitsPerWord = sizeof(uint32) * 8;
65.151 -
65.152 - static const size_t kMarkBitsOffset = kHeaderSize;
65.153 - static const size_t kFirstObject = kMarkBitsOffset + kMarkBytes;
65.154 -
65.155 - // Threshold for allocating an object in the large object space.
65.156 - static const size_t kLargeObjectThreshold = kAlignment - kFirstObject;
65.157 -
65.158 - static inline void StaticAsserts() {
65.159 - STATIC_ASSERT(kHeaderSize == sizeof(HeapChunk));
65.160 - STATIC_ASSERT(IS_ALIGNED(kHeaderSize, kObjectAlignment));
65.161 - STATIC_ASSERT(IS_ALIGNED(kFirstObject, kObjectAlignment));
65.162 - }
65.163 -
65.164 - public:
65.165 - static HeapChunk *New(HeapChunk *prev, size_t size);
65.166 - static void Destroy(HeapChunk *chunk);
65.167 -
65.168 - public:
65.169 - HeapChunk *next() {
65.170 - return next_;
65.171 - }
65.172 - Address base() {
65.173 - return base_;
65.174 - }
65.175 - Address address() {
65.176 - return reinterpret_cast<Address>(this);
65.177 - }
65.178 - Address end() {
65.179 - return end_;
65.180 - }
65.181 - size_t size() {
65.182 - return end() - base();
65.183 - }
65.184 - Address first() {
65.185 - return reinterpret_cast<Address>(this) + kFirstObject;
65.186 - }
65.187 - HeapChunk **nextp() {
65.188 - return &next_;
65.189 - }
65.190 - uint32 *markBits() {
65.191 - return reinterpret_cast<uint32 *>(reinterpret_cast<Address>(this) + kMarkBitsOffset);
65.192 - }
65.193 - void resetMarkBits();
65.194 -
65.195 - // Marking functions.
65.196 - static inline MarkBit GetMarkBit(Object *obj) {
65.197 - uintptr_t address = reinterpret_cast<uintptr_t>(obj);
65.198 -
65.199 - HeapChunk *chunk = reinterpret_cast<HeapChunk *>(address & ~(kAlignment - 1));
65.200 - assert(Address(obj) >= chunk->first() && Address(obj) < chunk->end());
65.201 -
65.202 - size_t index = (address & (kAlignment - 1)) / kObjectAlignment;
65.203 - assert(index < kMaxObjectsPerChunk);
65.204 -
65.205 - uint32 *word = chunk->markBits() + (index / kMarkBitsPerWord);
65.206 - uint32 bit = index & (kMarkBitsPerWord - 1);
65.207 - return MarkBit(word, bit);
65.208 - }
65.209 - static inline Address FromMarkBit(HeapChunk *chunk, uint32 *word, uint32 bit) {
65.210 - // word = bits + (index / kMarkBitsPerWord)
65.211 - // word - bits = index / kMarkBitsPerWord
65.212 - // (word - bits) * kMarkBitsPerWord = index
65.213 - assert(word >= chunk->markBits() && word < chunk->markBits() + kMarkWords);
65.214 - uint32 index = ((word - chunk->markBits()) * kMarkBitsPerWord) + bit;
65.215 - return chunk->address() + (index * kObjectAlignment);
65.216 - }
65.217 - static inline bool IsWhite(const MarkBit &bit) {
65.218 - assert(bit.isSet() || !bit.next().isSet());
65.219 - return !bit.isSet();
65.220 - }
65.221 - static inline bool IsBlack(const MarkBit &bit) {
65.222 - return bit.isSet() && !bit.next().isSet();
65.223 - }
65.224 - static inline bool IsGrey(const MarkBit &bit) {
65.225 - return bit.isSet() && bit.next().isSet();
65.226 - }
65.227 - static inline bool IsBlackOrGrey(const MarkBit &bit) {
65.228 - return bit.isSet();
65.229 - }
65.230 - static inline void WhiteToBlack(MarkBit &bit) {
65.231 - assert(IsWhite(bit));
65.232 - bit.set();
65.233 - }
65.234 - static inline void BlackToGrey(MarkBit &bit) {
65.235 - assert(IsBlack(bit));
65.236 - bit.next().set();
65.237 - }
65.238 - static inline void GreyToBlack(MarkBit &bit) {
65.239 - assert(IsGrey(bit));
65.240 - bit.next().unset();
65.241 - }
65.242 - static inline void Clear(MarkBit &bit) {
65.243 - bit.unset();
65.244 - bit.next().unset();
65.245 - }
65.246 -
65.247 - bool hasOverflowedObject() {
65.248 - return !!(flags_ & HAS_OVERFLOWED_OBJECT);
65.249 - }
65.250 - void setHasOverflowedObject() {
65.251 - flags_ |= HAS_OVERFLOWED_OBJECT;
65.252 - }
65.253 - bool isEmpty() {
65.254 - return !!(flags_ & EMPTY);
65.255 - }
65.256 - void setEmpty() {
65.257 - flags_ |= EMPTY;
65.258 - }
65.259 -};
65.260 -
65.261 -template <typename SizeEvaluator>
65.262 -class ChunkObjectIteratorBase
65.263 -{
65.264 - HeapChunk *chunk_;
65.265 - Address top_;
65.266 - SizeEvaluator evaluator_;
65.267 - Address current_;
65.268 -
65.269 - public:
65.270 - ChunkObjectIteratorBase(HeapChunk *start, Address top, const SizeEvaluator &evaluator)
65.271 - : chunk_(start),
65.272 - top_(top),
65.273 - evaluator_(evaluator),
65.274 - current_(start ? start->first() : NULL)
65.275 - {
65.276 - }
65.277 -
65.278 - Object *next() {
65.279 - while (current_ && current_ != top_) {
65.280 - Object *obj = reinterpret_cast<Object *>(current_);
65.281 - size_t size = evaluator_(obj, obj->map());
65.282 - current_ += size;
65.283 - if (current_ == chunk_->end()) {
65.284 - chunk_ = chunk_->next();
65.285 - current_ = chunk_ ? chunk_->first() : NULL;
65.286 - }
65.287 - if (obj->is(MapKind_FreeRegion))
65.288 - continue;
65.289 - }
65.290 - return NULL;
65.291 - }
65.292 -};
65.293 -
65.294 -class FreedObject
65.295 -{
65.296 - Map *map_;
65.297 - size_t bytes_;
65.298 - FreedObject *next_;
65.299 -
65.300 - public:
65.301 - FreedObject(Map *map, size_t bytes)
65.302 - : map_(map),
65.303 - bytes_(bytes)
65.304 - {
65.305 - assert(bytes_ >= sizeof(Map *) + sizeof(size_t));
65.306 - if (bytes_ >= sizeof(FreedObject))
65.307 - next_ = NULL;
65.308 - }
65.309 -
65.310 - void setNext(FreedObject *obj) {
65.311 - assert(bytes_ >= sizeof(FreedObject));
65.312 - next_ = obj;
65.313 - }
65.314 - FreedObject *next() {
65.315 - assert(bytes_ >= sizeof(FreedObject));
65.316 - return next_;
65.317 - }
65.318 - size_t size() {
65.319 - return bytes_;
65.320 - }
65.321 -};
65.322 -
65.323 -// Free-region list used in old spaces. Based on V8's. Each object pool
65.324 -// is used to allocate objects of the previous pool's size. For example,
65.325 -// the medium object pool is used to allocate small objects.
65.326 -class FreeList
65.327 -{
65.328 - private:
65.329 - static const size_t kMinObjectSize = 32;
65.330 - static const size_t kMaxSmallObject = 255;
65.331 - static const size_t kMaxMediumObject = (2 * kKB) - 1;
65.332 - static const size_t kMaxLargeObject = (16 * kKB) - 1;
65.333 -
65.334 - public:
65.335 - FreeList();
65.336 -
65.337 - public:
65.338 - void add(FreedObject *obj);
65.339 - FreedObject *pick(size_t size);
65.340 - void reset();
65.341 -
65.342 - private:
65.343 - FreedObject *small_objects_;
65.344 - FreedObject *medium_objects_;
65.345 - FreedObject *large_objects_;
65.346 - FreedObject *huge_objects_;
65.347 -};
65.348 -
65.349 -// The heap stack is designed for structures which are known to not escape the
65.350 -// program stack, and can thus be quickly allocated in a LIFO manner.
65.351 -//
65.352 -class HeapStack
65.353 -{
65.354 - OS::AlignableMapping map_;
65.355 - HeapChunk *chunk_;
65.356 - Address cursor_;
65.357 - uintptr_t mask_;
65.358 -
65.359 - private:
65.360 - static const size_t kStackSize = 1024 * 1024;
65.361 -
65.362 - public:
65.363 - HeapStack();
65.364 - ~HeapStack();
65.365 - bool initialize();
65.366 -
65.367 - public:
65.368 - Address position() const {
65.369 - return cursor_;
65.370 - }
65.371 - inline Address allocate(size_t nbytes);
65.372 - inline void unwind(Address to);
65.373 -
65.374 - inline bool contains(Object *obj) {
65.375 - return (reinterpret_cast<uintptr_t>(obj) & mask_) == reinterpret_cast<uintptr_t>(chunk_);
65.376 - }
65.377 -
65.378 - template <typename Evaluator>
65.379 - ChunkObjectIteratorBase<Evaluator> begin(const Evaluator &evaluator) {
65.380 - return ChunkObjectIteratorBase<Evaluator>(chunk_, cursor_, evaluator);
65.381 - }
65.382 -};
65.383 -
65.384 -class OldSpace
65.385 -{
65.386 - Zone *zone_;
65.387 - HeapChunk *first_;
65.388 - HeapChunk *last_;
65.389 - Address cursor_;
65.390 - FreeList freelist_;
65.391 -
65.392 - public:
65.393 - OldSpace(Zone *zone);
65.394 - ~OldSpace();
65.395 -
65.396 - bool initialize();
65.397 -
65.398 - public:
65.399 - inline Address allocate(size_t nbytes);
65.400 - Address allocateSlow(size_t nbytes);
65.401 - void markRegionFree(Address start, size_t size);
65.402 - void freeUnusedPages();
65.403 -
65.404 - template <typename Evaluator>
65.405 - ChunkObjectIteratorBase<Evaluator> begin(const Evaluator &evaluator) {
65.406 - return ChunkObjectIteratorBase<Evaluator>(first_, cursor_, evaluator);
65.407 - }
65.408 -
65.409 - HeapChunk *first() {
65.410 - return first_;
65.411 - }
65.412 - void resetFreeList();
65.413 -};
65.414 -
65.415 -class LargeObjectSpace
65.416 -{
65.417 - HeapChunk *first_;
65.418 - HeapChunk *last_;
65.419 -
65.420 - public:
65.421 - LargeObjectSpace();
65.422 - ~LargeObjectSpace();
65.423 -
65.424 - bool initialize();
65.425 -
65.426 - public:
65.427 - Address allocate(size_t nbytes);
65.428 -
65.429 - HeapChunk *first() {
65.430 - return first_;
65.431 - }
65.432 - void sweep();
65.433 -};
65.434 -
65.435 -}
65.436 -
65.437 -#endif // _include_jitcraft_spaces_h_
66.1 --- a/jitcraft/Stack.cpp Tue Jul 24 23:53:34 2012 -0700
66.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
66.3 @@ -1,321 +0,0 @@
66.4 -/* vim: set ts=4 sw=4 tw=99 et:
66.5 - *
66.6 - * Copyright (C) 2012 David Anderson
66.7 - *
66.8 - * This file is part of JITCraft.
66.9 - *
66.10 - * JITCraft is free software: you can redistribute it and/or modify it under
66.11 - * the terms of the GNU General Public License as published by the Free
66.12 - * Software Foundation, either version 3 of the License, or (at your option)
66.13 - * any later version.
66.14 - *
66.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
66.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
66.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
66.18 - *
66.19 - * You should have received a copy of the GNU General Public License along with
66.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
66.21 - */
66.22 -#include <new>
66.23 -#include <stdlib.h>
66.24 -#include "Stack.h"
66.25 -#include "Zone.h"
66.26 -#include "Strings.h"
66.27 -#include "Modules.h"
66.28 -#include "Heap-inl.h"
66.29 -
66.30 -using namespace ke;
66.31 -
66.32 -Stack::Stack(Zone *zone)
66.33 - : zone_(zone),
66.34 - buffer_(NULL),
66.35 - end_(NULL)
66.36 -{
66.37 -}
66.38 -
66.39 -Stack::~Stack()
66.40 -{
66.41 - free(buffer_);
66.42 -}
66.43 -
66.44 -bool
66.45 -Stack::initialize()
66.46 -{
66.47 - buffer_ = (char *)malloc(STACK_SIZE);
66.48 - if (!buffer_)
66.49 - return false;
66.50 -
66.51 - top_.sp = reinterpret_cast<LocalSlot *>(buffer_);
66.52 - top_.pc = NULL;
66.53 - top_.fp = NULL;
66.54 - end_ = buffer_ + STACK_SIZE;
66.55 - return true;
66.56 -}
66.57 -
66.58 -InvokeArgs::~InvokeArgs()
66.59 -{
66.60 - stack_->popInvokeFrame(*this);
66.61 -}
66.62 -
66.63 -NativeArgs::~NativeArgs()
66.64 -{
66.65 - stack_->popNativeFrame(*this);
66.66 -}
66.67 -
66.68 -static inline size_t
66.69 -SizeForCodeFrame(Code *code)
66.70 -{
66.71 - return sizeof(Frame) + sizeof(LocalSlot) * (code->nlocals() + code->maxStackDepth());
66.72 -}
66.73 -
66.74 -bool
66.75 -Stack::pushInvokeFrame(Handle<Function> fun, InvokeArgs &args)
66.76 -{
66.77 - size_t nbytes = SizeForCodeFrame(fun->code()) +
66.78 - sizeof(LocalSlot) * fun->nargs();
66.79 - if (reinterpret_cast<char *>(top_.sp) + nbytes >= end_) {
66.80 - assert(false);
66.81 - return false;
66.82 - }
66.83 -
66.84 - memset(top_.sp, 0, sizeof(LocalSlot) * fun->nargs());
66.85 - args.args_ = top_.sp;
66.86 - args.nargs_ = fun->nargs();
66.87 - args.stack_ = this;
66.88 - top_.sp += fun->nargs();
66.89 -
66.90 - Frame *frame = reinterpret_cast<Frame *>(top_.sp);
66.91 - new (frame) Frame(top_.fp, top_.pc, fun, fun->code(), zone_->heap().lifoPosition());
66.92 -
66.93 - top_.pc = frame->code()->start();
66.94 - top_.sp = frame->stackBase();
66.95 - top_.fp = frame;
66.96 -
66.97 - return true;
66.98 -}
66.99 -
66.100 -bool
66.101 -Stack::pushModuleFrame(Handle<Module> module, InvokeArgs &args)
66.102 -{
66.103 - size_t nbytes = SizeForCodeFrame(module->code());
66.104 - if (reinterpret_cast<char *>(top_.sp) + nbytes >= end_) {
66.105 - assert(false);
66.106 - return false;
66.107 - }
66.108 -
66.109 - args.args_ = top_.sp;
66.110 - args.nargs_ = 0;
66.111 - args.stack_ = this;
66.112 -
66.113 - Frame *frame = reinterpret_cast<Frame *>(top_.sp);
66.114 - new (frame) Frame(top_.fp, top_.pc, NULL, module->code(), zone_->heap().lifoPosition());
66.115 -
66.116 - top_.pc = frame->code()->start();
66.117 - top_.sp = frame->stackBase();
66.118 - top_.fp = frame;
66.119 -
66.120 - return true;
66.121 -}
66.122 -
66.123 -bool
66.124 -Stack::pushNativeFrame(Handle<Native> native, NativeArgs &args, unsigned argc)
66.125 -{
66.126 - size_t nbytes = sizeof(intptr_t) * argc + sizeof(Frame);
66.127 - if (reinterpret_cast<char *>(top_.sp) + nbytes >= end_) {
66.128 - assert(false);
66.129 - return false;
66.130 - }
66.131 -
66.132 - memset(top_.sp, 0, sizeof(intptr_t) * argc);
66.133 - args.argsBase_ = top_.sp;
66.134 - args.stack_ = this;
66.135 - top_.sp = reinterpret_cast<LocalSlot *>(reinterpret_cast<intptr_t *>(top_.sp) + argc);
66.136 -
66.137 - Frame *frame = reinterpret_cast<Frame *>(top_.sp);
66.138 - new (frame) Frame(top_.fp, top_.pc, native, zone_->heap().lifoPosition());
66.139 -
66.140 - top_.pc = NULL;
66.141 - top_.sp = reinterpret_cast<LocalSlot *>(frame + 1);
66.142 - top_.fp = frame;
66.143 -
66.144 - return true;
66.145 -}
66.146 -
66.147 -Frame *
66.148 -Stack::pushInlineFrame(Handle<Function> fun)
66.149 -{
66.150 - Code *code = fun->code();
66.151 - size_t nbytes = SizeForCodeFrame(code);
66.152 - if (reinterpret_cast<char *>(top_.sp) + nbytes >= end_) {
66.153 - zone_->reportError(Message_TooMuchRecursion);
66.154 - return NULL;
66.155 - }
66.156 -
66.157 - Frame *frame = reinterpret_cast<Frame *>(top_.sp);
66.158 - new (frame) Frame(top_.fp, top_.pc, fun, code, zone_->heap().lifoPosition());
66.159 - memset(frame->locals(), 0, sizeof(LocalSlot) * code->nlocals());
66.160 -
66.161 - top_.pc = frame->code()->start();
66.162 - top_.sp = frame->stackBase();
66.163 - top_.fp = frame;
66.164 -
66.165 - return frame;
66.166 -}
66.167 -
66.168 -
66.169 -Frame *
66.170 -Stack::popInlineFrame()
66.171 -{
66.172 - zone_->heap().unwindLifo(top_.fp->lifoPosition());
66.173 -
66.174 - Frame *prev = top_.fp->prev();
66.175 - Function *fun = top_.fp->fun();
66.176 -
66.177 - top_.pc = top_.fp->prevpc();
66.178 - top_.sp = reinterpret_cast<LocalSlot *>(top_.fp) - fun->nargs();
66.179 - top_.fp = prev;
66.180 - return prev;
66.181 -}
66.182 -
66.183 -void
66.184 -Stack::popInvokeFrame(InvokeArgs &args)
66.185 -{
66.186 - zone_->heap().unwindLifo(top_.fp->lifoPosition());
66.187 -
66.188 - top_.pc = top_.fp->prevpc();
66.189 - top_.sp = args.args_;
66.190 - top_.fp = top_.fp->prev();
66.191 -}
66.192 -
66.193 -void
66.194 -Stack::popNativeFrame(NativeArgs &args)
66.195 -{
66.196 - zone_->heap().unwindLifo(top_.fp->lifoPosition());
66.197 -
66.198 - top_.pc = top_.fp->prevpc();
66.199 - top_.sp = args.argsBase_;
66.200 - top_.fp = top_.fp->prev();
66.201 -}
66.202 -
66.203 -void
66.204 -Frame::accept(VirtualObjectVisitor *visitor)
66.205 -{
66.206 - visitor->visit(reinterpret_cast<Object **>(&callee_));
66.207 - visitor->visit(reinterpret_cast<Object **>(&code_));
66.208 -}
66.209 -
66.210 -static void
66.211 -TraceFunctionFrame(VirtualObjectVisitor *visitor, Frame *fp, LocalSlot *sp, bytecode *pc)
66.212 -{
66.213 - Code *code = fp->code();
66.214 - LocalSlot *slots = fp->locals();
66.215 -
66.216 - // Trace local variables.
66.217 - for (unsigned i = 0; i < code->nlocals(); i++) {
66.218 - Type *type = code->localType(i);
66.219 - if (type->isTraceable())
66.220 - visitor->visit(&slots[i].obj);
66.221 - }
66.222 -
66.223 - // Trace arguments, if a function call. Note that this means we usually
66.224 - // mark arguments twice, once on the caller side and once on the callee.
66.225 - // This makes it easier to deal with invoke frames which have no caller.
66.226 - if (Function *fun = fp->maybeFun()) {
66.227 - for (unsigned i = 0; i < fun->nargs(); i++) {
66.228 - Type *type = fun->argType(i);
66.229 - if (type->isTraceable())
66.230 - visitor->visit(&fp->arg(i).obj);
66.231 - }
66.232 - }
66.233 -
66.234 - // Finally, trace stack slots. Not every gc-point in the bytecode will
66.235 - // have a safepoint; since they are actually uncommon, we don't emit
66.236 - // them unless at least one stack slot would be marked.
66.237 - if (uint8 *safepoint = code->safepointAt(code->pcToOffset(pc))) {
66.238 - LocalSlot *base = fp->stackBase();
66.239 - unsigned stackDepth = unsigned(sp - fp->stackBase());
66.240 - assert(stackDepth <= code->maxStackDepth());
66.241 -
66.242 - for (unsigned i = 0; i < stackDepth; i++) {
66.243 - if (safepoint[i / 8] & (1 << (i % 8)))
66.244 - visitor->visit(&base[i].obj);
66.245 - }
66.246 - }
66.247 -}
66.248 -
66.249 -void
66.250 -Stack::accept(VirtualObjectVisitor *visitor)
66.251 -{
66.252 - LocalSlot *sp = top_.sp;
66.253 - bytecode *pc = top_.pc;
66.254 -
66.255 - for (Frame *frame = top_.fp; frame; frame = frame->prev()) {
66.256 - if (!frame->isNative())
66.257 - TraceFunctionFrame(visitor, frame, sp, pc);
66.258 - frame->accept(visitor);
66.259 -
66.260 - sp = reinterpret_cast<LocalSlot *>(frame);
66.261 - pc = frame->prevpc();
66.262 - }
66.263 -}
66.264 -
66.265 -bool
66.266 -Stack::isInCallStack(Handle<Module> module)
66.267 -{
66.268 - for (Frame *frame = top_.fp; frame; frame = frame->prev()) {
66.269 - if (frame->code()->module() == module)
66.270 - return true;
66.271 - }
66.272 - return false;
66.273 -}
66.274 -
66.275 -StackIter::StackIter(Zone *zone)
66.276 - : pc_(zone->stack().top()->pc),
66.277 - fp_(zone->stack().top()->fp)
66.278 -{
66.279 -}
66.280 -
66.281 -bool
66.282 -StackIter::done() const
66.283 -{
66.284 - return !fp_;
66.285 -}
66.286 -
66.287 -const char *
66.288 -StackIter::function() const
66.289 -{
66.290 - if (fp_->isNative())
66.291 - return fp_->native()->name()->chars();
66.292 - if (Function *fun = fp_->maybeFun())
66.293 - return fun->name()->chars();
66.294 - return "<toplevel>";
66.295 -}
66.296 -
66.297 -unsigned
66.298 -StackIter::lineNumber() const
66.299 -{
66.300 - if (fp_->isNative())
66.301 - return 0;
66.302 - if (fp_->maybeFun()) {
66.303 - unsigned offs = fp_->code()->pcToOffset(pc_);
66.304 - return fp_->code()->pcToSource(offs).line;
66.305 - }
66.306 - return fp_->code()->lineNumber();
66.307 -}
66.308 -
66.309 -const char *
66.310 -StackIter::source() const
66.311 -{
66.312 - if (fp_->isNative())
66.313 - return "<native>";
66.314 - return fp_->code()->module()->file()
66.315 - ? fp_->code()->module()->file()->chars()
66.316 - : "(anonymous)";
66.317 -}
66.318 -
66.319 -void
66.320 -StackIter::prev()
66.321 -{
66.322 - pc_ = fp_->prevpc();
66.323 - fp_ = fp_->prev();
66.324 -}
67.1 --- a/jitcraft/Stack.h Tue Jul 24 23:53:34 2012 -0700
67.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
67.3 @@ -1,233 +0,0 @@
67.4 -/* vim: set ts=4 sw=4 tw=99 et:
67.5 - *
67.6 - * Copyright (C) 2012 David Anderson
67.7 - *
67.8 - * This file is part of JITCraft.
67.9 - *
67.10 - * JITCraft is free software: you can redistribute it and/or modify it under
67.11 - * the terms of the GNU General Public License as published by the Free
67.12 - * Software Foundation, either version 3 of the License, or (at your option)
67.13 - * any later version.
67.14 - *
67.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
67.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
67.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
67.18 - *
67.19 - * You should have received a copy of the GNU General Public License along with
67.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
67.21 - */
67.22 -#ifndef _include_jc_stack_h_
67.23 -#define _include_jc_stack_h_
67.24 -
67.25 -#include <stddef.h>
67.26 -#include "Utility.h"
67.27 -#include "Code.h"
67.28 -#include "Functions.h"
67.29 -#include "VirtualObjectVisitor.h"
67.30 -
67.31 -namespace ke {
67.32 -
67.33 -class Object;
67.34 -class Array;
67.35 -class Reference;
67.36 -class Frame;
67.37 -class Stack;
67.38 -class Zone;
67.39 -class Module;
67.40 -
67.41 -union LocalSlot
67.42 -{
67.43 - int i32;
67.44 - float f;
67.45 - Address address;
67.46 - Object *obj;
67.47 - Array *array;
67.48 - Reference *ref;
67.49 - Function *fun;
67.50 - Module *module;
67.51 -};
67.52 -
67.53 -struct Top
67.54 -{
67.55 - LocalSlot *sp;
67.56 - bytecode *pc;
67.57 - Frame *fp;
67.58 -};
67.59 -
67.60 -class Frame
67.61 -{
67.62 - friend class Stack;
67.63 -
67.64 - Frame *prev_;
67.65 - bytecode *prevpc_;
67.66 - union {
67.67 - Function *fun_;
67.68 - Native *native_;
67.69 - Object *callee_;
67.70 - };
67.71 - Code *code_;
67.72 - Address lifoPosition_;
67.73 -
67.74 - public:
67.75 - Frame(Frame *prev, bytecode *prevpc, Function *fun, Code *code, Address lifoPosition)
67.76 - : prev_(prev),
67.77 - prevpc_(prevpc),
67.78 - fun_(fun),
67.79 - code_(code),
67.80 - lifoPosition_(lifoPosition)
67.81 - {
67.82 - }
67.83 -
67.84 - Frame(Frame *prev, bytecode *prevpc, Native *native, Address lifoPosition)
67.85 - : prev_(prev),
67.86 - prevpc_(prevpc),
67.87 - native_(native),
67.88 - code_(NULL),
67.89 - lifoPosition_(lifoPosition)
67.90 - {
67.91 - }
67.92 -
67.93 - LocalSlot *locals() {
67.94 - return reinterpret_cast<LocalSlot *>(this + 1);
67.95 - }
67.96 - LocalSlot *stackBase() {
67.97 - return locals() + code_->nlocals();
67.98 - }
67.99 - Function *fun() const {
67.100 - assert(fun_ && callee_->is(MapKind_Function));
67.101 - return fun_;
67.102 - }
67.103 - Function *maybeFun() const {
67.104 - return (fun_ && callee_->is(MapKind_Function)) ? fun_ : NULL;
67.105 - }
67.106 - bool isNative() const {
67.107 - return callee_ && callee_->is(MapKind_Native);
67.108 - }
67.109 - Native *native() const {
67.110 - assert(isNative());
67.111 - return native_;
67.112 - }
67.113 - Code *code() const {
67.114 - assert(code_);
67.115 - return code_;
67.116 - }
67.117 - Frame *prev() const {
67.118 - return prev_;
67.119 - }
67.120 - bytecode *prevpc() const {
67.121 - return prevpc_;
67.122 - }
67.123 - Address lifoPosition() const {
67.124 - return lifoPosition_;
67.125 - }
67.126 - LocalSlot &arg(unsigned slot) {
67.127 - assert(slot < fun()->nargs());
67.128 - return *(reinterpret_cast<LocalSlot *>(this) - slot - 1);
67.129 - }
67.130 - void accept(VirtualObjectVisitor *visitor);
67.131 -};
67.132 -
67.133 -// RAII object for calling a function from C++.
67.134 -class InvokeArgs
67.135 -{
67.136 - friend class Stack;
67.137 -
67.138 - Stack *stack_;
67.139 - LocalSlot *args_;
67.140 - unsigned nargs_;
67.141 -
67.142 - public:
67.143 - InvokeArgs()
67.144 - : stack_(NULL),
67.145 - args_(NULL),
67.146 - nargs_(0)
67.147 - {
67.148 - }
67.149 -
67.150 - ~InvokeArgs();
67.151 -
67.152 - LocalSlot &arg(unsigned index) {
67.153 - assert(index < nargs_);
67.154 - return args_[nargs_ - index - 1];
67.155 - }
67.156 -};
67.157 -
67.158 -// RAII object for calling a native from C++.
67.159 -class NativeArgs
67.160 -{
67.161 - friend class Stack;
67.162 -
67.163 - Stack *stack_;
67.164 - LocalSlot *argsBase_;
67.165 -
67.166 - public:
67.167 - NativeArgs()
67.168 - : stack_(NULL),
67.169 - argsBase_(NULL)
67.170 - {
67.171 - }
67.172 -
67.173 - ~NativeArgs();
67.174 -
67.175 - intptr_t *args() {
67.176 - return reinterpret_cast<int *>(argsBase_);
67.177 - }
67.178 -};
67.179 -
67.180 -class Stack
67.181 -{
67.182 - friend class InvokeArgs;
67.183 - friend class NativeArgs;
67.184 -
67.185 - private:
67.186 - static const size_t STACK_SIZE = 1024 * 1024;
67.187 -
67.188 - public:
67.189 - Stack(Zone *zone);
67.190 - ~Stack();
67.191 -
67.192 - bool initialize();
67.193 -
67.194 - public:
67.195 - Frame *pushInlineFrame(Handle<Function> fun);
67.196 - Frame *popInlineFrame();
67.197 -
67.198 - bool pushInvokeFrame(Handle<Function> fun, InvokeArgs &args);
67.199 - bool pushModuleFrame(Handle<Module> module, InvokeArgs &args);
67.200 - bool pushNativeFrame(Handle<Native> native, NativeArgs &args, unsigned argc);
67.201 -
67.202 - Top *top() {
67.203 - return &top_;
67.204 - }
67.205 - bool isInCallStack(Handle<Module> module);
67.206 - void accept(VirtualObjectVisitor *visitor);
67.207 -
67.208 - private:
67.209 - void popInvokeFrame(InvokeArgs &args);
67.210 - void popNativeFrame(NativeArgs &args);
67.211 -
67.212 - private:
67.213 - Zone *zone_;
67.214 - char *buffer_;
67.215 - char *end_;
67.216 - Top top_;
67.217 -};
67.218 -
67.219 -class StackIter
67.220 -{
67.221 - bytecode *pc_;
67.222 - Frame *fp_;
67.223 -
67.224 - public:
67.225 - StackIter(Zone *zone);
67.226 -
67.227 - bool done() const;
67.228 - const char *function() const;
67.229 - unsigned lineNumber() const;
67.230 - const char *source() const;
67.231 - void prev();
67.232 -};
67.233 -
67.234 -}
67.235 -
67.236 -#endif // _include_jc_stack_h_
68.1 --- a/jitcraft/StringPool.cpp Tue Jul 24 23:53:34 2012 -0700
68.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
68.3 @@ -1,69 +0,0 @@
68.4 -/*
68.5 - * Copyright (C) 2012 David Anderson
68.6 - *
68.7 - * This file is part of JITCraft.
68.8 - *
68.9 - * JITCraft is free software: you can redistribute it and/or modify it under
68.10 - * the terms of the GNU General Public License as published by the Free
68.11 - * Software Foundation, either version 3 of the License, or (at your option)
68.12 - * any later version.
68.13 - *
68.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
68.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
68.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
68.17 - *
68.18 - * You should have received a copy of the GNU General Public License along with
68.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
68.20 - */
68.21 -#include "StringPool.h"
68.22 -#include "Strings.h"
68.23 -#include "Spaces.h"
68.24 -
68.25 -using namespace ke;
68.26 -
68.27 -StringPool::StringPool(Zone *zone)
68.28 - : zone_(zone),
68.29 - set_(ZoneAllocatorPolicy())
68.30 -{
68.31 -}
68.32 -
68.33 -StringPool::~StringPool()
68.34 -{
68.35 -}
68.36 -
68.37 -bool
68.38 -StringPool::initialize()
68.39 -{
68.40 - if (!set_.init(32))
68.41 - return false;
68.42 - return true;
68.43 -}
68.44 -
68.45 -String *
68.46 -StringPool::add(const char *str, size_t length)
68.47 -{
68.48 - StringSet::Insert i = set_.findForAdd(CharsAndLength(str, length));
68.49 - if (i.found())
68.50 - return *i;
68.51 -
68.52 - Local<String> obj(zone_, String::New(zone_, str, length, Heap::Tenure_Old));
68.53 - if (!obj)
68.54 - return NULL;
68.55 -
68.56 - set_.add(i, obj);
68.57 - return obj;
68.58 -}
68.59 -
68.60 -void
68.61 -StringPool::sweep()
68.62 -{
68.63 - for (StringSet::iterator i(&set_); !i.empty(); i.next()) {
68.64 - String *obj = *i;
68.65 - MarkBit bits = HeapChunk::GetMarkBit(obj);
68.66 - if (HeapChunk::IsWhite(bits))
68.67 - i.erase();
68.68 - else
68.69 - assert(HeapChunk::IsBlack(bits));
68.70 - }
68.71 - set_.checkDensity();
68.72 -}
69.1 --- a/jitcraft/StringPool.h Tue Jul 24 23:53:34 2012 -0700
69.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
69.3 @@ -1,85 +0,0 @@
69.4 -/*
69.5 - * Copyright (C) 2012 David Anderson
69.6 - *
69.7 - * This file is part of JITCraft.
69.8 - *
69.9 - * JITCraft is free software: you can redistribute it and/or modify it under
69.10 - * the terms of the GNU General Public License as published by the Free
69.11 - * Software Foundation, either version 3 of the License, or (at your option)
69.12 - * any later version.
69.13 - *
69.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
69.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
69.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
69.17 - *
69.18 - * You should have received a copy of the GNU General Public License along with
69.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
69.20 - */
69.21 -#ifndef _include_jitcraft_string_pool_h_
69.22 -#define _include_jitcraft_string_pool_h_
69.23 -
69.24 -#include "AllocatorPolicies.h"
69.25 -#include "HashTable.h"
69.26 -#include "Strings.h"
69.27 -
69.28 -namespace ke {
69.29 -
69.30 -class Zone;
69.31 -class String;
69.32 -
69.33 -// Guarantee that strings with the same contents will map to one pointer.
69.34 -class StringPool
69.35 -{
69.36 - class CharsAndLength {
69.37 - const char *str_;
69.38 - size_t length_;
69.39 -
69.40 - public:
69.41 - CharsAndLength(const char *str, size_t length)
69.42 - : str_(str),
69.43 - length_(length)
69.44 - {
69.45 - }
69.46 -
69.47 - const char *str() const {
69.48 - return str_;
69.49 - }
69.50 - size_t length() const {
69.51 - return length_;
69.52 - }
69.53 - };
69.54 -
69.55 - struct Policy
69.56 - {
69.57 - typedef String * Payload;
69.58 -
69.59 - static uint32 hash(const CharsAndLength &key) {
69.60 - return HashCharSequence(key.str(), key.length());
69.61 - }
69.62 -
69.63 - static bool matches(const CharsAndLength &key, String *string) {
69.64 - if (string->length() != key.length())
69.65 - return false;
69.66 - return memcmp(string->chars(), key.str(), key.length() * sizeof(char)) == 0;
69.67 - }
69.68 - };
69.69 -
69.70 - typedef HashTable<Policy, ZoneAllocatorPolicy> StringSet;
69.71 -
69.72 - public:
69.73 - StringPool(Zone *zone);
69.74 - ~StringPool();
69.75 - bool initialize();
69.76 -
69.77 - public:
69.78 - String *add(const char *str, size_t len);
69.79 - void sweep();
69.80 -
69.81 - private:
69.82 - Zone *zone_;
69.83 - StringSet set_;
69.84 -};
69.85 -
69.86 -}
69.87 -
69.88 -#endif // _include_jitcraft_string_pool_h_
70.1 --- a/jitcraft/Strings.cpp Tue Jul 24 23:53:34 2012 -0700
70.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
70.3 @@ -1,43 +0,0 @@
70.4 -/* vim: set ts=4 sw=4 tw=99 et:
70.5 - *
70.6 - * Copyright (C) 2012 David Anderson
70.7 - *
70.8 - * This file is part of JITCraft.
70.9 - *
70.10 - * JITCraft is free software: you can redistribute it and/or modify it under
70.11 - * the terms of the GNU General Public License as published by the Free
70.12 - * Software Foundation, either version 3 of the License, or (at your option)
70.13 - * any later version.
70.14 - *
70.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
70.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
70.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
70.18 - *
70.19 - * You should have received a copy of the GNU General Public License along with
70.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
70.21 - */
70.22 -#include "Strings.h"
70.23 -#include "Zone.h"
70.24 -#include "Heap-inl.h"
70.25 -
70.26 -using namespace ke;
70.27 -
70.28 -String *
70.29 -String::New(Zone *zone, const char *from, Heap::Tenure tenure)
70.30 -{
70.31 - return New(zone, from, strlen(from), tenure);
70.32 -}
70.33 -
70.34 -String *
70.35 -String::New(Zone *zone, const char *from, size_t length, Heap::Tenure tenure)
70.36 -{
70.37 - size_t bytes = SizeFor(length);
70.38 - Local<String> string(zone, String::cast(zone->allocate(MapKind_String, bytes, tenure)));
70.39 - if (!string)
70.40 - return NULL;
70.41 -
70.42 - string->length_ = length;
70.43 - memcpy(string->chars(), from, length + 1);
70.44 -
70.45 - return string;
70.46 -}
71.1 --- a/jitcraft/Strings.h Tue Jul 24 23:53:34 2012 -0700
71.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
71.3 @@ -1,54 +0,0 @@
71.4 -/* vim: set ts=4 sw=4 tw=99 et:
71.5 - *
71.6 - * Copyright (C) 2012 David Anderson
71.7 - *
71.8 - * This file is part of JITCraft.
71.9 - *
71.10 - * JITCraft is free software: you can redistribute it and/or modify it under
71.11 - * the terms of the GNU General Public License as published by the Free
71.12 - * Software Foundation, either version 3 of the License, or (at your option)
71.13 - * any later version.
71.14 - *
71.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
71.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
71.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
71.18 - *
71.19 - * You should have received a copy of the GNU General Public License along with
71.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
71.21 - */
71.22 -#ifndef _include_jitcraft_string_h_
71.23 -#define _include_jitcraft_string_h_
71.24 -
71.25 -#include "Heap.h"
71.26 -
71.27 -namespace ke {
71.28 -
71.29 -// A fixed-length string containing UTF-8 characters.
71.30 -class String : public Object
71.31 -{
71.32 - uint32 length_;
71.33 -
71.34 - public:
71.35 - static String *New(Zone *zone, const char *from, Heap::Tenure tenure = Heap::Tenure_Default);
71.36 - static String *New(Zone *zone, const char *from, size_t length, Heap::Tenure tenure = Heap::Tenure_Default);
71.37 -
71.38 - unsigned length() {
71.39 - return length_;
71.40 - }
71.41 - char *chars() {
71.42 - return reinterpret_cast<char *>(this + 1);
71.43 - }
71.44 -
71.45 - static size_t SizeFor(unsigned length) {
71.46 - return Align(sizeof(String) + sizeof(char) * (length + 1), kObjectAlignment);
71.47 - }
71.48 -
71.49 - static inline String *cast(Object *obj) {
71.50 - assert(!obj || obj->is(MapKind_String));
71.51 - return reinterpret_cast<String *>(obj);
71.52 - }
71.53 -};
71.54 -
71.55 -}
71.56 -
71.57 -#endif // _include_jitcraft_string_h_
72.1 --- a/jitcraft/Structures.cpp Tue Jul 24 23:53:34 2012 -0700
72.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
72.3 @@ -1,46 +0,0 @@
72.4 -/* vim: set ts=4 sw=4 tw=99 et
72.5 - *
72.6 - * Copyright (C) 2012 David Anderson
72.7 - *
72.8 - * This file is part of JITCraft.
72.9 - *
72.10 - * JITCraft is free software: you can redistribute it and/or modify it under
72.11 - * the terms of the GNU General Public License as published by the Free
72.12 - * Software Foundation, either version 3 of the License, or (at your option)
72.13 - * any later version.
72.14 - *
72.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
72.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
72.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
72.18 - *
72.19 - * You should have received a copy of the GNU General Public License along with
72.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
72.21 - */
72.22 -#include "Structures.h"
72.23 -#include "Types.h"
72.24 -
72.25 -using namespace ke;
72.26 -
72.27 -StructureBufferBuilder::StructureBufferBuilder()
72.28 - : size_(0)
72.29 -{
72.30 -}
72.31 -
72.32 -bool
72.33 -StructureBufferBuilder::add(Handle<Type> type, unsigned *offset)
72.34 -{
72.35 - *offset = size_;
72.36 -
72.37 - if (!type->isTraceable()) {
72.38 - // For now, assume the size of primitives is 4-byte.
72.39 - assert(type->isInt32() || type->isFloat());
72.40 - size_ += 4;
72.41 - return true;
72.42 - }
72.43 -
72.44 - if (!offsets_.append(size_))
72.45 - return false;
72.46 -
72.47 - size_ += sizeof(Object *);
72.48 - return true;
72.49 -}
73.1 --- a/jitcraft/Structures.h Tue Jul 24 23:53:34 2012 -0700
73.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
73.3 @@ -1,60 +0,0 @@
73.4 -/* vim: set ts=4 sw=4 tw=99 et
73.5 - *
73.6 - * Copyright (C) 2012 David Anderson
73.7 - *
73.8 - * This file is part of JITCraft.
73.9 - *
73.10 - * JITCraft is free software: you can redistribute it and/or modify it under
73.11 - * the terms of the GNU General Public License as published by the Free
73.12 - * Software Foundation, either version 3 of the License, or (at your option)
73.13 - * any later version.
73.14 - *
73.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
73.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
73.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
73.18 - *
73.19 - * You should have received a copy of the GNU General Public License along with
73.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
73.21 - */
73.22 -#ifndef _include_jc_structure_h_
73.23 -#define _include_jc_structure_h_
73.24 -
73.25 -#include "Objects.h"
73.26 -#include "Handles.h"
73.27 -#include "Vector.h"
73.28 -
73.29 -namespace ke {
73.30 -
73.31 -class Type;
73.32 -class String;
73.33 -class FixedArray;
73.34 -
73.35 -// When describing composite structures, the GC must be able to trace interior
73.36 -// references to Objects. To make this possible, maps that describe composite
73.37 -// structures must provide a list of offsets into their objects that are
73.38 -// traceable. StructureBufferBuilder assists with this.
73.39 -class StructureBufferBuilder
73.40 -{
73.41 - public:
73.42 - StructureBufferBuilder();
73.43 -
73.44 - bool add(Handle<Type> type, unsigned *offset);
73.45 -
73.46 - unsigned structureSize() const {
73.47 - return size_;
73.48 - }
73.49 - unsigned traceableOffsetCount() const {
73.50 - return offsets_.length();
73.51 - }
73.52 - const unsigned *offsets() {
73.53 - return offsets_.buffer();
73.54 - }
73.55 -
73.56 - private:
73.57 - Vector<unsigned> offsets_;
73.58 - unsigned size_;
73.59 -};
73.60 -
73.61 -}
73.62 -
73.63 -#endif // _include_jc_structure_h_
74.1 --- a/jitcraft/Token.h Tue Jul 24 23:53:34 2012 -0700
74.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
74.3 @@ -1,128 +0,0 @@
74.4 -/*
74.5 - * Copyright (C) 2012 David Anderson
74.6 - *
74.7 - * This file is part of JITCraft.
74.8 - *
74.9 - * JITCraft is free software: you can redistribute it and/or modify it under
74.10 - * the terms of the GNU General Public License as published by the Free
74.11 - * Software Foundation, either version 3 of the License, or (at your option)
74.12 - * any later version.
74.13 - *
74.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
74.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
74.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
74.17 - *
74.18 - * You should have received a copy of the GNU General Public License along with
74.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
74.20 - */
74.21 -#ifndef _include_jitcraft_token_h_
74.22 -#define _include_jitcraft_token_h_
74.23 -
74.24 -namespace ke {
74.25 -
74.26 -struct SourcePosition
74.27 -{
74.28 - int line;
74.29 - int col;
74.30 -
74.31 - SourcePosition()
74.32 - : line(-1),
74.33 - col(-1)
74.34 - {
74.35 - }
74.36 -
74.37 - SourcePosition(unsigned line, unsigned col)
74.38 - : line(line),
74.39 - col(col)
74.40 - {
74.41 - }
74.42 -};
74.43 -
74.44 -// List of tokens the scanner can recognize.
74.45 -//
74.46 -// Some restrictions:
74.47 -// * (ASSIGN_ADD - TOK_PLUS) must be the delta between an operator and its
74.48 -// op-and-assign equivalent.
74.49 -#define TOKENMAP(_) \
74.50 - _(ERROR, "<error>") \
74.51 - _(NEW, "'new'") \
74.52 - _(FOR, "'for'") \
74.53 - _(RETURN, "'return'") \
74.54 - _(NAME, "<name>") \
74.55 - _(INTEGER_LITERAL, "<integer>") \
74.56 - _(FLOAT_LITERAL, "<float>") \
74.57 - _(STRING_LITERAL, "<string>") \
74.58 - _(IF, "<if>") \
74.59 - _(ELSE, "<else>") \
74.60 - _(ENUM, "<enum>") \
74.61 - _(LABEL, "<label>") \
74.62 - _(WHILE, "<while>") \
74.63 - _(DO, "<do>") \
74.64 - _(BREAK, "<break>") \
74.65 - _(CONTINUE, "<continue>") \
74.66 - _(FORWARD, "<forward>") \
74.67 - _(PUBLIC, "<public>") \
74.68 - _(CONST, "<const>") \
74.69 - _(NATIVE, "<native>") \
74.70 - _(ELLIPSES, "...") \
74.71 - _(PLUS, "+") \
74.72 - _(MINUS, "-") \
74.73 - _(STAR, "*") \
74.74 - _(SLASH, "/") \
74.75 - _(PERCENT, "%") \
74.76 - _(AMPERSAND, "&") \
74.77 - _(BITOR, "|") \
74.78 - _(BITXOR, "^") \
74.79 - _(SHR, ">>") \
74.80 - _(USHR, ">>>") \
74.81 - _(SHL, "<<") \
74.82 - _(ASSIGN, "=") \
74.83 - _(SEMICOLON, ";") \
74.84 - _(LBRACE, "{") \
74.85 - _(RBRACE, "}") \
74.86 - _(LPAREN, "(") \
74.87 - _(RPAREN, ")") \
74.88 - _(LBRACKET, "[") \
74.89 - _(RBRACKET, "]") \
74.90 - _(ASSIGN_ADD, "+=") \
74.91 - _(ASSIGN_SUB, "-=") \
74.92 - _(ASSIGN_MUL, "*=") \
74.93 - _(ASSIGN_DIV, "/=") \
74.94 - _(ASSIGN_MOD, "%=") \
74.95 - _(ASSIGN_BITAND, "&=") \
74.96 - _(ASSIGN_BITOR, "|=") \
74.97 - _(ASSIGN_BITXOR, "^=") \
74.98 - _(ASSIGN_SHR, ">>=") \
74.99 - _(ASSIGN_USHR, ">>>=") \
74.100 - _(ASSIGN_SHL, "<<=") \
74.101 - _(INCREMENT, "++") \
74.102 - _(DECREMENT, "--") \
74.103 - _(EQUALS, "==") \
74.104 - _(NOTEQUALS, "!=") \
74.105 - _(LT, "<") \
74.106 - _(LE, "<=") \
74.107 - _(GT, ">") \
74.108 - _(GE, ">=") \
74.109 - _(AND, "&&") \
74.110 - _(OR, "||") \
74.111 - _(COMMA, ",") \
74.112 - _(NOT, "!") \
74.113 - _(TILDE, "~") \
74.114 - _(QMARK, "?") \
74.115 - _(COLON, ":") \
74.116 - _(EOF, "<end-of-file>")
74.117 -
74.118 -enum TokenKind
74.119 -{
74.120 -# define _(name, str) TOK_##name,
74.121 - TOKENMAP(_)
74.122 -# undef _
74.123 - TOK_BITAND = TOK_AMPERSAND,
74.124 - TOKENS_TOTAL
74.125 -};
74.126 -
74.127 -extern const char *TokenNames[];
74.128 -
74.129 -} // namespace ke
74.130 -
74.131 -#endif //_include_jitcraft_token_h_
75.1 --- a/jitcraft/TypeManager.cpp Tue Jul 24 23:53:34 2012 -0700
75.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
75.3 @@ -1,119 +0,0 @@
75.4 -/* vim: set ts=4 sw=4 tw=99 et:
75.5 - *
75.6 - * Copyright (C) 2012 David Anderson
75.7 - *
75.8 - * This file is part of JITCraft.
75.9 - *
75.10 - * JITCraft is free software: you can redistribute it and/or modify it under
75.11 - * the terms of the GNU General Public License as published by the Free
75.12 - * Software Foundation, either version 3 of the License, or (at your option)
75.13 - * any later version.
75.14 - *
75.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
75.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
75.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
75.18 - *
75.19 - * You should have received a copy of the GNU General Public License along with
75.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
75.21 - */
75.22 -#include "Types.h"
75.23 -#include "TypeManager.h"
75.24 -#include "Zone.h"
75.25 -#include "Strings.h"
75.26 -
75.27 -using namespace ke;
75.28 -
75.29 -
75.30 -TypeManager::TypeManager(Zone *zone)
75.31 - : zone_(zone)
75.32 -{
75.33 -}
75.34 -
75.35 -bool
75.36 -TypeManager::initialize()
75.37 -{
75.38 - voidType_ = Type::NewVoid(zone_);
75.39 - if (!voidType_)
75.40 - return false;
75.41 -
75.42 - Local<String> floatTag(zone_, zone_->makeSymbol("Float"));
75.43 - if (!floatTag)
75.44 - return false;
75.45 -
75.46 - Local<String> stringTag(zone_, zone_->makeSymbol("String"));
75.47 - if (!stringTag)
75.48 - return false;
75.49 -
75.50 - Local<String> nullTag(zone_);
75.51 -
75.52 - if ((primitiveTypes_[PrimitiveType_Int32] = Type::NewPrimitive(zone_, nullTag)) == NULL)
75.53 - return false;
75.54 - if ((primitiveTypes_[PrimitiveType_Float] = Type::NewPrimitive(zone_, floatTag)) == NULL)
75.55 - return false;
75.56 - if ((primitiveTypes_[PrimitiveType_Native] = Type::NewPrimitive(zone_, PrimitiveType_Native)) == NULL)
75.57 - return false;
75.58 - if ((primitiveTypes_[PrimitiveType_Char] = Type::NewPrimitive(zone_, stringTag)) == NULL)
75.59 - return false;
75.60 -
75.61 - Local<Type> type(zone_);
75.62 - for (unsigned i = 0; i < PrimitiveTypes_Total; i++) {
75.63 - type = primitiveTypes_[i];
75.64 - if ((referenceTypes_[i] = Type::NewReference(zone_, type, false)) == NULL)
75.65 - return false;
75.66 - }
75.67 -
75.68 - return true;
75.69 -}
75.70 -
75.71 -Type *
75.72 -TypeManager::getPrimitiveForTag(Handle<String> tag)
75.73 -{
75.74 - if (!tag)
75.75 - return getPrimitive(PrimitiveType_Int32);
75.76 - if (strcmp(tag->chars(), "Float") == 0)
75.77 - return getPrimitive(PrimitiveType_Float);
75.78 - if (strcmp(tag->chars(), "String") == 0)
75.79 - return getPrimitive(PrimitiveType_Char);
75.80 - return NULL;
75.81 -}
75.82 -
75.83 -Type *
75.84 -TypeManager::unsafeArray(Handle<Type> contained, int elements, bool isConst)
75.85 -{
75.86 - // :TODO: cache this.
75.87 - return Type::NewArray(zone_, contained, elements, isConst);
75.88 -}
75.89 -
75.90 -Type *
75.91 -TypeManager::getReference(Handle<Type> type, bool isConst)
75.92 -{
75.93 - if (!isConst && (type->isFloat() || (type->isInt32() && !type->tag())))
75.94 - return referenceTypes_[type->primitive()];
75.95 -
75.96 - // :TODO: cache this.
75.97 - return Type::NewReference(zone_, type, isConst);
75.98 -}
75.99 -
75.100 -Type *
75.101 -TypeManager::newFunction(Handle<Type> returnType, Handle<FixedArray> args)
75.102 -{
75.103 - // :TODO: cache this.
75.104 - return Type::NewFunction(zone_, returnType, args);
75.105 -}
75.106 -
75.107 -Type *
75.108 -TypeManager::newNative(Handle<Type> returnType, Handle<FixedArray> args, bool variadic)
75.109 -{
75.110 - // :TODO: cache this.
75.111 - return Type::NewNative(zone_, returnType, args, variadic);
75.112 -}
75.113 -
75.114 -void
75.115 -TypeManager::accept(VirtualObjectVisitor *visitor)
75.116 -{
75.117 - visitor->visit(voidType_.address());
75.118 - for (unsigned i = 0; i < PrimitiveTypes_Total; i++) {
75.119 - visitor->visit(primitiveTypes_[i].address());
75.120 - visitor->visit(referenceTypes_[i].address());
75.121 - }
75.122 -}
76.1 --- a/jitcraft/TypeManager.h Tue Jul 24 23:53:34 2012 -0700
76.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
76.3 @@ -1,61 +0,0 @@
76.4 -/*
76.5 - * Copyright (C) 2012 David Anderson
76.6 - *
76.7 - * This file is part of JITCraft.
76.8 - *
76.9 - * JITCraft is free software: you can redistribute it and/or modify it under
76.10 - * the terms of the GNU General Public License as published by the Free
76.11 - * Software Foundation, either version 3 of the License, or (at your option)
76.12 - * any later version.
76.13 - *
76.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
76.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
76.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
76.17 - *
76.18 - * You should have received a copy of the GNU General Public License along with
76.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
76.20 - */
76.21 -#ifndef _include_jitcraft_type_manager_h_
76.22 -#define _include_jitcraft_type_manager_h_
76.23 -
76.24 -#include "Barriers.h"
76.25 -#include "Types.h"
76.26 -#include "VirtualObjectVisitor.h"
76.27 -
76.28 -namespace ke {
76.29 -
76.30 -class String;
76.31 -
76.32 -class TypeManager
76.33 -{
76.34 - Zone *zone_;
76.35 -
76.36 - // Primitive type cache.
76.37 - Unbarriered<Type> voidType_;
76.38 - Unbarriered<Type> primitiveTypes_[PrimitiveTypes_Total];
76.39 - Unbarriered<Type> referenceTypes_[PrimitiveTypes_Total];
76.40 -
76.41 - public:
76.42 - TypeManager(Zone *zone);
76.43 -
76.44 - bool initialize();
76.45 -
76.46 - Type *getPrimitiveForTag(Handle<String>);
76.47 - Type *getPrimitive(PrimitiveType type) {
76.48 - return primitiveTypes_[type];
76.49 - }
76.50 -
76.51 - Type *getVoid() {
76.52 - return voidType_;
76.53 - }
76.54 - Type *getReference(Handle<Type> type, bool isConst);
76.55 - Type *unsafeArray(Handle<Type> contained, int elements, bool isConst);
76.56 - Type *newFunction(Handle<Type> returnType, Handle<FixedArray> args);
76.57 - Type *newNative(Handle<Type> returnType, Handle<FixedArray> args, bool variadic);
76.58 -
76.59 - void accept(VirtualObjectVisitor *visitor);
76.60 -};
76.61 -
76.62 -}
76.63 -
76.64 -#endif // _include_jitcraft_type_manager_h_
77.1 --- a/jitcraft/Types.cpp Tue Jul 24 23:53:34 2012 -0700
77.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
77.3 @@ -1,187 +0,0 @@
77.4 -/*
77.5 - * Copyright (C) 2012 David Anderson
77.6 - *
77.7 - * This file is part of JITCraft.
77.8 - *
77.9 - * JITCraft is free software: you can redistribute it and/or modify it under
77.10 - * the terms of the GNU General Public License as published by the Free
77.11 - * Software Foundation, either version 3 of the License, or (at your option)
77.12 - * any later version.
77.13 - *
77.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
77.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
77.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
77.17 - *
77.18 - * You should have received a copy of the GNU General Public License along with
77.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
77.20 - */
77.21 -#include "Types.h"
77.22 -#include "Zone.h"
77.23 -#include "Strings.h"
77.24 -#include "Heap-inl.h"
77.25 -
77.26 -using namespace ke;
77.27 -
77.28 -Type *
77.29 -Type::NewVoid(Zone *zone)
77.30 -{
77.31 - Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
77.32 - if (!type)
77.33 - return NULL;
77.34 -
77.35 - type->kind_ = VOID;
77.36 - type->tag_ = NULL;
77.37 - type->contained_ = NULL;
77.38 - type->returnType_ = NULL;
77.39 - type->parameters_ = NULL;
77.40 - return type;
77.41 -}
77.42 -
77.43 -Type *
77.44 -Type::NewPrimitive(Zone *zone, Handle<String> tag)
77.45 -{
77.46 - Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
77.47 - if (!type)
77.48 - return NULL;
77.49 -
77.50 - type->kind_ = PRIMITIVE;
77.51 - type->tag_ = tag;
77.52 - type->contained_ = NULL;
77.53 - type->returnType_ = NULL;
77.54 - type->parameters_ = NULL;
77.55 -
77.56 - if (tag && strcmp(tag->chars(), "Float") == 0)
77.57 - type->primitive_ = PrimitiveType_Float;
77.58 - else if (tag && strcmp(tag->chars(), "String") == 0)
77.59 - type->primitive_ = PrimitiveType_Char;
77.60 - else
77.61 - type->primitive_ = PrimitiveType_Int32;
77.62 - return type;
77.63 -}
77.64 -
77.65 -Type *
77.66 -Type::NewPrimitive(Zone *zone, PrimitiveType prim)
77.67 -{
77.68 - Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
77.69 - if (!type)
77.70 - return NULL;
77.71 -
77.72 - type->kind_ = PRIMITIVE;
77.73 - type->tag_ = NULL;
77.74 - type->contained_ = NULL;
77.75 - type->returnType_ = NULL;
77.76 - type->parameters_ = NULL;
77.77 - type->primitive_ = prim;
77.78 - return type;
77.79 -}
77.80 -
77.81 -Type *
77.82 -Type::NewArray(Zone *zone, Handle<Type> contained, int elements, bool isConst)
77.83 -{
77.84 - Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
77.85 - if (!type)
77.86 - return NULL;
77.87 -
77.88 - type->kind_ = ARRAY;
77.89 - type->tag_ = NULL;
77.90 - type->contained_ = contained;
77.91 - type->returnType_ = NULL;
77.92 - type->parameters_ = NULL;
77.93 - type->elements_ = elements;
77.94 - if (contained->isPrimitive())
77.95 - type->levels_ = 1;
77.96 - else
77.97 - type->levels_ = contained->levels() + 1;
77.98 - type->const_ = isConst;
77.99 - return type;
77.100 -}
77.101 -
77.102 -Type *
77.103 -Type::NewReference(Zone *zone, Handle<Type> contained, bool isConst)
77.104 -{
77.105 - Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
77.106 - if (!type)
77.107 - return NULL;
77.108 -
77.109 - type->kind_ = REFERENCE;
77.110 - type->tag_ = NULL;
77.111 - type->contained_ = contained;
77.112 - type->returnType_ = NULL;
77.113 - type->parameters_ = NULL;
77.114 - type->const_ = isConst;
77.115 - return type;
77.116 -}
77.117 -
77.118 -Type *
77.119 -Type::NewFunction(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters)
77.120 -{
77.121 - Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
77.122 - if (!type)
77.123 - return NULL;
77.124 -
77.125 - type->kind_ = FUNCTION;
77.126 - type->contained_ = NULL;
77.127 - type->returnType_ = returnType;
77.128 - type->parameters_ = parameters;
77.129 - return type;
77.130 -}
77.131 -
77.132 -Type *
77.133 -Type::NewNative(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters, bool variadic)
77.134 -{
77.135 - Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
77.136 - if (!type)
77.137 - return NULL;
77.138 -
77.139 - type->kind_ = NATIVE;
77.140 - type->contained_ = NULL;
77.141 - type->returnType_ = returnType;
77.142 - type->parameters_ = parameters;
77.143 - type->variadicNative_ = variadic;
77.144 - return type;
77.145 -}
77.146 -
77.147 -bool
77.148 -Type::Compare(Type *left, Type *right)
77.149 -{
77.150 - if (left->kind() != right->kind())
77.151 - return false;
77.152 -
77.153 - switch (left->kind()) {
77.154 - case Type::PRIMITIVE:
77.155 - return (left->primitive() == right->primitive() &&
77.156 - left->tag() == right->tag());
77.157 -
77.158 - case Type::ARRAY:
77.159 - {
77.160 - if (left->levels() != right->levels())
77.161 - return false;
77.162 - if (left->elements() != right->elements())
77.163 - return false;
77.164 - return Compare(left->contained(), right->contained());
77.165 - }
77.166 -
77.167 - case Type::FUNCTION:
77.168 - {
77.169 - if (!Compare(left->returnType(), right->returnType()))
77.170 - return false;
77.171 - if (left->parameters()->length() != right->parameters()->length())
77.172 - return false;
77.173 - if (left->isNative() != right->isNative())
77.174 - return false;
77.175 - if (left->isNative() && (left->isNativeVariadic() != right->isNativeVariadic()))
77.176 - return false;
77.177 - for (unsigned i = 0; i < left->parameters()->length(); i++) {
77.178 - Type *leftparam = left->parameterAt(i);
77.179 - Type *rightparam = right->parameterAt(i);
77.180 - if (!Compare(leftparam, rightparam))
77.181 - return false;
77.182 - }
77.183 - return true;
77.184 - }
77.185 -
77.186 - default:
77.187 - assert(left->kind() == Type::REFERENCE);
77.188 - return Compare(left->contained(), right->contained());
77.189 - }
77.190 -}
78.1 --- a/jitcraft/Types.h Tue Jul 24 23:53:34 2012 -0700
78.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
78.3 @@ -1,215 +0,0 @@
78.4 -/* vim: set ts=4 sw=4 tw=99 et:
78.5 - *
78.6 - * Copyright (C) 2012 David Anderson
78.7 - *
78.8 - * This file is part of JITCraft.
78.9 - *
78.10 - * JITCraft is free software: you can redistribute it and/or modify it under
78.11 - * the terms of the GNU General Public License as published by the Free
78.12 - * Software Foundation, either version 3 of the License, or (at your option)
78.13 - * any later version.
78.14 - *
78.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
78.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
78.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
78.18 - *
78.19 - * You should have received a copy of the GNU General Public License along with
78.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
78.21 - */
78.22 -#ifndef _include_jc_types_h_
78.23 -#define _include_jc_types_h_
78.24 -
78.25 -#include "Heap.h"
78.26 -#include "Barriers.h"
78.27 -#include "FixedArray.h"
78.28 -
78.29 -namespace ke {
78.30 -
78.31 -class String;
78.32 -
78.33 -enum PrimitiveType
78.34 -{
78.35 - PrimitiveType_Char, // signed, 8-bit character
78.36 - PrimitiveType_Int32, // signed, 32-bit integer
78.37 - PrimitiveType_Float, // 32-bit IEEE-754 float
78.38 - PrimitiveType_Native, // native-sized word
78.39 - PrimitiveTypes_Total
78.40 -};
78.41 -
78.42 -class Type : public Object
78.43 -{
78.44 - enum Kind {
78.45 - PRIMITIVE,
78.46 - ARRAY,
78.47 - REFERENCE,
78.48 - FUNCTION,
78.49 - NATIVE,
78.50 - VOID
78.51 - };
78.52 -
78.53 - private:
78.54 - Kind kind() {
78.55 - return kind_;
78.56 - }
78.57 -
78.58 - public:
78.59 - static const int UNKNOWN_SIZE = -1;
78.60 - static const size_t MAX_UNSAFE_ARRAY_DEPTH = 5;
78.61 -
78.62 - static Type *NewVoid(Zone *zone);
78.63 - static Type *NewPrimitive(Zone *zone, Handle<String> tag);
78.64 - static Type *NewPrimitive(Zone *zone, PrimitiveType type);
78.65 - static Type *NewArray(Zone *zone, Handle<Type> contained, int elements, bool isConst);
78.66 - static Type *NewReference(Zone *zone, Handle<Type> contained, bool isConst);
78.67 - static Type *NewFunction(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters);
78.68 - static Type *NewNative(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters, bool isVariadic);
78.69 -
78.70 - static bool Compare(Type *left, Type *right);
78.71 -
78.72 - static Type *cast(Object *obj) {
78.73 - assert(!obj || obj->is(MapKind_Type));
78.74 - return (Type *)obj;
78.75 - }
78.76 -
78.77 - bool isPrimitive() {
78.78 - return kind() == PRIMITIVE;
78.79 - }
78.80 - bool isArray() {
78.81 - return kind() == ARRAY;
78.82 - }
78.83 - bool isReference() {
78.84 - return kind() == REFERENCE;
78.85 - }
78.86 - bool isFunction() {
78.87 - return kind() == FUNCTION || kind() == NATIVE;
78.88 - }
78.89 - bool isNative() {
78.90 - return kind() == NATIVE;
78.91 - }
78.92 - bool isVoid() {
78.93 - return kind() == VOID;
78.94 - }
78.95 - bool isNativeVariadic() {
78.96 - assert(isNative());
78.97 - return variadicNative_;
78.98 - }
78.99 - PrimitiveType primitive() {
78.100 - assert(isPrimitive());
78.101 - return primitive_;
78.102 - }
78.103 - Type *contained() {
78.104 - assert(isArray() || isReference());
78.105 - return Type::cast(contained_);
78.106 - }
78.107 - int elements() {
78.108 - assert(isArray());
78.109 - return elements_;
78.110 - }
78.111 - unsigned levels() {
78.112 - assert(isArray());
78.113 - return levels_;
78.114 - }
78.115 - String *tag() {
78.116 - assert(isPrimitive());
78.117 - return tag_;
78.118 - }
78.119 - Type *innermost() {
78.120 - assert(isArray());
78.121 - Type *temp = contained();
78.122 - while (temp->isArray())
78.123 - temp = temp->contained();
78.124 - return temp;
78.125 - }
78.126 - bool isFloat() {
78.127 - return isPrimitive() && primitive() == PrimitiveType_Float;
78.128 - }
78.129 - bool isInt32() {
78.130 - return isPrimitive() && primitive() == PrimitiveType_Int32;
78.131 - }
78.132 - bool isCharArray() {
78.133 - return isArray() &&
78.134 - contained()->isPrimitive() &&
78.135 - contained()->primitive() == PrimitiveType_Char;
78.136 - }
78.137 - Type *returnType() {
78.138 - assert(isFunction());
78.139 - return returnType_;
78.140 - }
78.141 - FixedArray *parameters() {
78.142 - assert(isFunction());
78.143 - return parameters_;
78.144 - }
78.145 - Type *parameterAt(size_t i) {
78.146 - return Type::cast(parameters()->at(i));
78.147 - }
78.148 - bool isTraceable() {
78.149 - return !isPrimitive();
78.150 - }
78.151 - bool isConst() {
78.152 - assert(kind() == PRIMITIVE || kind() == ARRAY || kind() == REFERENCE);
78.153 - return const_;
78.154 - }
78.155 -
78.156 - // GC Descriptor.
78.157 - static inline size_t offsetOfContained() {
78.158 - return offsetof(Type, contained_);
78.159 - }
78.160 - static inline size_t offsetOfReturnType() {
78.161 - return offsetof(Type, returnType_);
78.162 - }
78.163 - static inline size_t offsetOfParameters() {
78.164 - return offsetof(Type, parameters_);
78.165 - }
78.166 - static inline size_t offsetOfTag() {
78.167 - return offsetof(Type, tag_);
78.168 - }
78.169 - // End GC Descriptor.
78.170 -
78.171 - private:
78.172 - Kind kind_;
78.173 - PrimitiveType primitive_;
78.174 - Barriered<String> tag_;
78.175 -
78.176 - // Primitives, arrays, and references.
78.177 - bool const_;
78.178 -
78.179 - // Arrays only.
78.180 - int32 elements_;
78.181 - unsigned levels_;
78.182 -
78.183 - // Arrays and references only.
78.184 - Barriered<Type> contained_;
78.185 -
78.186 - // Functions only.
78.187 - Barriered<Type> returnType_;
78.188 - Barriered<FixedArray> parameters_;
78.189 - bool variadicNative_;
78.190 -};
78.191 -
78.192 -class BoxedPrimitive
78.193 -{
78.194 - PrimitiveType type_;
78.195 - union {
78.196 - int i_;
78.197 - };
78.198 -
78.199 - public:
78.200 - static BoxedPrimitive Int(int i) {
78.201 - BoxedPrimitive b;
78.202 - b.type_ = PrimitiveType_Int32;
78.203 - b.i_ = i;
78.204 - return b;
78.205 - }
78.206 -
78.207 - PrimitiveType type() const {
78.208 - return type_;
78.209 - }
78.210 - int toInt() const {
78.211 - assert(type() == PrimitiveType_Int32);
78.212 - return i_;
78.213 - }
78.214 -};
78.215 -
78.216 -}
78.217 -
78.218 -#endif // _include_jc_types_h_
79.1 --- a/jitcraft/Utility.h Tue Jul 24 23:53:34 2012 -0700
79.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
79.3 @@ -1,235 +0,0 @@
79.4 -/* vim: set ts=4 sw=4 tw=99 et:
79.5 - *
79.6 - * Copyright (C) 2012 David Anderson
79.7 - *
79.8 - * This file is part of JITCraft.
79.9 - *
79.10 - * JITCraft is free software: you can redistribute it and/or modify it under
79.11 - * the terms of the GNU General Public License as published by the Free
79.12 - * Software Foundation, either version 3 of the License, or (at your option)
79.13 - * any later version.
79.14 - *
79.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
79.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
79.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
79.18 - *
79.19 - * You should have received a copy of the GNU General Public License along with
79.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
79.21 - */
79.22 -#ifndef _include_jitcraft_utility_h_
79.23 -#define _include_jitcraft_utility_h_
79.24 -
79.25 -#include <assert.h>
79.26 -#include <stdint.h>
79.27 -#ifdef _MSC_VER
79.28 -# include <intrin.h>
79.29 -#endif
79.30 -
79.31 -#ifdef _MSC_VER
79.32 -# pragma warning(disable:4355)
79.33 -#endif
79.34 -
79.35 -namespace ke {
79.36 -
79.37 -static const size_t kMallocAlignment = sizeof(void *) * 2;
79.38 -
79.39 -typedef uint8_t uint8;
79.40 -typedef int32_t int32;
79.41 -typedef uint32_t uint32;
79.42 -
79.43 -typedef uint8 * Address;
79.44 -
79.45 -static const size_t kKB = 1024;
79.46 -static const size_t kMB = 1024 * kKB;
79.47 -static const size_t kGB = 1024 * kMB;
79.48 -
79.49 -template <typename T>
79.50 -class AutoVec
79.51 -{
79.52 - T *t_;
79.53 -
79.54 - public:
79.55 - AutoVec()
79.56 - : t_(NULL)
79.57 - {
79.58 - }
79.59 - AutoVec(T *t)
79.60 - : t_(t)
79.61 - {
79.62 - }
79.63 - ~AutoVec() {
79.64 - delete [] t_;
79.65 - }
79.66 - operator T *() {
79.67 - return t_;
79.68 - }
79.69 - void operator =(T *t) {
79.70 - if (t_)
79.71 - delete [] t_;
79.72 - t_ = t;
79.73 - }
79.74 -};
79.75 -
79.76 -// Bob Jenkin's one-at-a-time hash function[1].
79.77 -//
79.78 -// [1] http://burtleburtle.net/bob/hash/doobs.html
79.79 -class CharacterStreamHasher
79.80 -{
79.81 - uint32 hash;
79.82 -
79.83 - public:
79.84 - CharacterStreamHasher()
79.85 - : hash(0)
79.86 - { }
79.87 -
79.88 - void add(char c) {
79.89 - hash += c;
79.90 - hash += (hash << 10);
79.91 - hash ^= (hash >> 6);
79.92 - }
79.93 -
79.94 - void add(const char *s, size_t length) {
79.95 - for (size_t i = 0; i < length; i++)
79.96 - add(s[i]);
79.97 - }
79.98 -
79.99 - uint32 result() {
79.100 - hash += (hash << 3);
79.101 - hash ^= (hash >> 11);
79.102 - hash += (hash << 15);
79.103 - return hash;
79.104 - }
79.105 -};
79.106 -
79.107 -static inline uint32
79.108 -HashCharSequence(const char *s, size_t length)
79.109 -{
79.110 - CharacterStreamHasher hasher;
79.111 - hasher.add(s, length);
79.112 - return hasher.result();
79.113 -}
79.114 -
79.115 -static inline size_t
79.116 -Log2(size_t number)
79.117 -{
79.118 - assert(number != 0);
79.119 -
79.120 -#ifdef _MSC_VER
79.121 - unsigned long rval;
79.122 - _BitScanReverse(&rval, number);
79.123 - return rval;
79.124 -#else
79.125 - size_t bit;
79.126 - asm("bsr %1, %0\n"
79.127 - : "=r" (bit)
79.128 - : "rm" (number));
79.129 - return bit;
79.130 -#endif
79.131 -}
79.132 -
79.133 -static inline size_t
79.134 -FindRightmostBit(size_t number)
79.135 -{
79.136 - assert(number != 0);
79.137 -
79.138 -#ifdef _MSC_VER
79.139 - unsigned long rval;
79.140 - _BitScanForward(&rval, number);
79.141 - return rval;
79.142 -#else
79.143 - size_t bit;
79.144 - asm("bsf %1, %0\n"
79.145 - : "=r" (bit)
79.146 - : "rm" (number));
79.147 - return bit;
79.148 -#endif
79.149 -}
79.150 -
79.151 -static inline bool
79.152 -IsPowerOfTwo(size_t value)
79.153 -{
79.154 - if (value == 0)
79.155 - return false;
79.156 - return !(value & (value - 1));
79.157 -}
79.158 -
79.159 -static inline size_t
79.160 -Align(size_t count, size_t alignment)
79.161 -{
79.162 - assert(IsPowerOfTwo(alignment));
79.163 - return count + (alignment - (count % alignment)) % alignment;
79.164 -}
79.165 -
79.166 -static inline bool
79.167 -IsUint32AddSafe(unsigned a, unsigned b)
79.168 -{
79.169 - if (!a || !b)
79.170 - return true;
79.171 - unsigned log2_a = Log2(a);
79.172 - unsigned log2_b = Log2(b);
79.173 - return (log2_a < sizeof(unsigned) * 8) &&
79.174 - (log2_b < sizeof(unsigned) * 8);
79.175 -}
79.176 -
79.177 -static inline bool
79.178 -IsUintPtrAddSafe(size_t a, size_t b)
79.179 -{
79.180 - if (!a || !b)
79.181 - return true;
79.182 - size_t log2_a = Log2(a);
79.183 - size_t log2_b = Log2(b);
79.184 - return (log2_a < sizeof(size_t) * 8) &&
79.185 - (log2_b < sizeof(size_t) * 8);
79.186 -}
79.187 -
79.188 -static inline bool
79.189 -IsUint32MultiplySafe(unsigned a, unsigned b)
79.190 -{
79.191 - if (a <= 1 || b <= 1)
79.192 - return true;
79.193 -
79.194 - unsigned log2_a = Log2(a);
79.195 - unsigned log2_b = Log2(b);
79.196 - return log2_a + log2_b <= sizeof(unsigned) * 8;
79.197 -}
79.198 -
79.199 -static inline bool
79.200 -IsUintPtrMultiplySafe(size_t a, size_t b)
79.201 -{
79.202 - if (a <= 1 || b <= 1)
79.203 - return true;
79.204 -
79.205 - size_t log2_a = Log2(a);
79.206 - size_t log2_b = Log2(b);
79.207 - return log2_a + log2_b <= sizeof(size_t) * 8;
79.208 -}
79.209 -
79.210 -#define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0]))
79.211 -#define STATIC_ASSERT(cond) extern int static_assert_f(int a[(cond) ? 1 : -1])
79.212 -
79.213 -#define IS_ALIGNED(addr, alignment) (!(uintptr_t(addr) & ((alignment) - 1)))
79.214 -
79.215 -template <typename T>
79.216 -static inline bool
79.217 -IsAligned(T addr, size_t alignment)
79.218 -{
79.219 - assert(IsPowerOfTwo(alignment));
79.220 - return !(uintptr_t(addr) & (alignment - 1));
79.221 -}
79.222 -
79.223 -static inline Address
79.224 -AlignedBase(Address addr, size_t alignment)
79.225 -{
79.226 - assert(IsPowerOfTwo(alignment));
79.227 - return Address(uintptr_t(addr) & ~(alignment - 1));
79.228 -}
79.229 -
79.230 -template <typename T> static inline T
79.231 -Min(const T &t1, const T &t2)
79.232 -{
79.233 - return t1 < t2 ? t1 : t2;
79.234 -}
79.235 -
79.236 -}
79.237 -
79.238 -#endif // _include_jitcraft_utility_h_
80.1 --- a/jitcraft/Vector.h Tue Jul 24 23:53:34 2012 -0700
80.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
80.3 @@ -1,119 +0,0 @@
80.4 -/* vim: set ts=4 sw=4 tw=99 et:
80.5 - *
80.6 - * Copyright (C) 2012 David Anderson
80.7 - *
80.8 - * This file is part of JITCraft.
80.9 - *
80.10 - * JITCraft is free software: you can redistribute it and/or modify it under
80.11 - * the terms of the GNU General Public License as published by the Free
80.12 - * Software Foundation, either version 3 of the License, or (at your option)
80.13 - * any later version.
80.14 - *
80.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
80.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
80.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
80.18 - *
80.19 - * You should have received a copy of the GNU General Public License along with
80.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
80.21 - */
80.22 -#ifndef _INCLUDE_KEIMA_TPL_CPP_VECTOR_H_
80.23 -#define _INCLUDE_KEIMA_TPL_CPP_VECTOR_H_
80.24 -
80.25 -#include <new>
80.26 -#include <stdlib.h>
80.27 -#include "AllocatorPolicies.h"
80.28 -#include "Utility.h"
80.29 -
80.30 -namespace ke {
80.31 -
80.32 -template <typename T, typename AllocPolicy = ZoneAllocatorPolicy>
80.33 -class Vector : public AllocPolicy
80.34 -{
80.35 - public:
80.36 - Vector(AllocPolicy = AllocPolicy())
80.37 - : data(NULL),
80.38 - nitems(0),
80.39 - maxsize(0)
80.40 - { }
80.41 - ~Vector() {
80.42 - for (size_t i = 0; i < nitems; i++)
80.43 - data[i].~T();
80.44 - this->free(data);
80.45 - }
80.46 - bool append(const T& item) {
80.47 - if (!GrowIfNeeded(1))
80.48 - return false;
80.49 - new (&data[nitems]) T(item);
80.50 - nitems++;
80.51 - return true;
80.52 - }
80.53 - void pop() {
80.54 - assert(nitems);
80.55 - data[nitems - 1].~T();
80.56 - nitems--;
80.57 - }
80.58 - size_t length() const {
80.59 - return nitems;
80.60 - }
80.61 - T& at(size_t i) {
80.62 - assert(i < length());
80.63 - return data[i];
80.64 - }
80.65 - const T& at(size_t i) const {
80.66 - assert(i < length());
80.67 - return data[i];
80.68 - }
80.69 - T& operator [](size_t i) {
80.70 - return at(i);
80.71 - }
80.72 - const T& operator [](size_t i) const {
80.73 - return at(i);
80.74 - }
80.75 - void clear() {
80.76 - nitems = 0;
80.77 - }
80.78 -
80.79 - T *buffer() const {
80.80 - return data;
80.81 - }
80.82 -
80.83 - private:
80.84 - bool GrowIfNeeded(size_t needed)
80.85 - {
80.86 - if (!IsUintPtrAddSafe(nitems, needed)) {
80.87 - this->reportAllocationOverflow();
80.88 - return false;
80.89 - }
80.90 - if (maxsize == 0)
80.91 - maxsize = 8;
80.92 - while (nitems + needed > maxsize)
80.93 - {
80.94 - if (!IsUintPtrMultiplySafe(maxsize, 2)) {
80.95 - this->reportAllocationOverflow();
80.96 - return false;
80.97 - }
80.98 - maxsize *= 2;
80.99 - }
80.100 - T* newdata = (T*)this->malloc(sizeof(T) * maxsize);
80.101 - if (newdata == NULL)
80.102 - return false;
80.103 - for (size_t i = 0; i < nitems; i++)
80.104 - {
80.105 - new (&newdata[i]) T(data[i]);
80.106 - data[i].~T();
80.107 - }
80.108 - this->free(data);
80.109 - data = newdata;
80.110 - return true;
80.111 - }
80.112 -
80.113 - private:
80.114 - T* data;
80.115 - size_t nitems;
80.116 - size_t maxsize;
80.117 -};
80.118 -
80.119 -}
80.120 -
80.121 -#endif /* _INCLUDE_KEIMA_TPL_CPP_VECTOR_H_ */
80.122 -
81.1 --- a/jitcraft/VirtualObjectVisitor.h Tue Jul 24 23:53:34 2012 -0700
81.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
81.3 @@ -1,34 +0,0 @@
81.4 -/* vim: set ts=4 sw=4 tw=99 et:
81.5 - *
81.6 - * Copyright (C) 2012 David Anderson
81.7 - *
81.8 - * This file is part of JITCraft.
81.9 - *
81.10 - * JITCraft is free software: you can redistribute it and/or modify it under
81.11 - * the terms of the GNU General Public License as published by the Free
81.12 - * Software Foundation, either version 3 of the License, or (at your option)
81.13 - * any later version.
81.14 - *
81.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
81.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
81.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
81.18 - *
81.19 - * You should have received a copy of the GNU General Public License along with
81.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
81.21 - */
81.22 -#ifndef _include_jc_virtual_object_visitor_h_
81.23 -#define _include_jc_virtual_object_visitor_h_
81.24 -
81.25 -namespace ke {
81.26 -
81.27 -class Object;
81.28 -
81.29 -class VirtualObjectVisitor
81.30 -{
81.31 - public:
81.32 - virtual void visit(Object **ptr) = 0;
81.33 -};
81.34 -
81.35 -}
81.36 -
81.37 -#endif // _include_jc_virtual_object_visitor_h_
82.1 --- a/jitcraft/Zone.cpp Tue Jul 24 23:53:34 2012 -0700
82.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
82.3 @@ -1,312 +0,0 @@
82.4 -/* vim: set ts=4 sw=4 tw=99 et:
82.5 - *
82.6 - * Copyright (C) 2012 David Anderson
82.7 - *
82.8 - * This file is part of JITCraft.
82.9 - *
82.10 - * JITCraft is free software: you can redistribute it and/or modify it under
82.11 - * the terms of the GNU General Public License as published by the Free
82.12 - * Software Foundation, either version 3 of the License, or (at your option)
82.13 - * any later version.
82.14 - *
82.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
82.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
82.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
82.18 - *
82.19 - * You should have received a copy of the GNU General Public License along with
82.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
82.21 - */
82.22 -#include <stdlib.h>
82.23 -#include "Zone.h"
82.24 -#include "StringPool.h"
82.25 -#include "TypeManager.h"
82.26 -#include "GlobalRoots.h"
82.27 -#include "AllocatorPolicies.h"
82.28 -#include "Array.h"
82.29 -
82.30 -using namespace ke;
82.31 -
82.32 -Zone *ke::SingleThreadedZone;
82.33 -
82.34 -Zone::Zone()
82.35 - : stack_(thisFromCtor()),
82.36 - heap_(thisFromCtor()),
82.37 - types_(NULL),
82.38 - symbols_(NULL),
82.39 - globalRoots_(NULL),
82.40 - lastLocalRoot_(NULL),
82.41 - hasPendingException_(false),
82.42 - reporter_(NULL)
82.43 -{
82.44 -}
82.45 -
82.46 -Zone::~Zone()
82.47 -{
82.48 - delete types_;
82.49 - delete symbols_;
82.50 - delete globalRoots_;
82.51 -}
82.52 -
82.53 -bool
82.54 -Zone::initialize()
82.55 -{
82.56 - if (!stack_.initialize())
82.57 - return false;
82.58 - if (!heap_.initialize())
82.59 - return false;
82.60 -
82.61 - symbols_ = new StringPool(this);
82.62 - if (!symbols_ || !symbols_->initialize())
82.63 - return false;
82.64 -
82.65 - globalRoots_ = new GlobalRoots(this);
82.66 - if (!globalRoots_ || !globalRoots_->initialize())
82.67 - return false;
82.68 -
82.69 - maps_[MapKind_Meta] = heap_.metaMap();
82.70 - if ((maps_[MapKind_Type] = allocateMap(MapKind_Type, sizeof(Map))) == NULL)
82.71 - return false;
82.72 - if ((maps_[MapKind_FixedArray] = allocateMap(MapKind_FixedArray, sizeof(Map))) == NULL)
82.73 - return false;
82.74 - if ((maps_[MapKind_ByteArray] = allocateMap(MapKind_ByteArray, sizeof(Map))) == NULL)
82.75 - return false;
82.76 - if ((maps_[MapKind_Code] = allocateMap(MapKind_Code, sizeof(Map))) == NULL)
82.77 - return false;
82.78 - if ((maps_[MapKind_Reference] = allocateMap(MapKind_Reference, sizeof(Map))) == NULL)
82.79 - return false;
82.80 - if ((maps_[MapKind_MetaArray] = allocateMap(MapKind_MetaArray, sizeof(Map))) == NULL)
82.81 - return false;
82.82 - if ((maps_[MapKind_MetaEnvironment] = allocateMap(MapKind_MetaEnvironment, sizeof(Map))) == NULL)
82.83 - return false;
82.84 - if ((maps_[MapKind_Module] = allocateMap(MapKind_Module, sizeof(Map))) == NULL)
82.85 - return false;
82.86 - if ((maps_[MapKind_Function] = allocateMap(MapKind_Function, sizeof(Map))) == NULL)
82.87 - return false;
82.88 - if ((maps_[MapKind_String] = allocateMap(MapKind_String, sizeof(Map))) == NULL)
82.89 - return false;
82.90 - if ((maps_[MapKind_Native] = allocateMap(MapKind_Native, sizeof(Map))) == NULL)
82.91 - return false;
82.92 - if ((maps_[MapKind_FreeRegion] = allocateMap(MapKind_FreeRegion, sizeof(Map))) == NULL)
82.93 - return false;
82.94 - if ((maps_[MapKind_EnvironmentSlotDescriptorArray] =
82.95 - allocateMap(MapKind_EnvironmentSlotDescriptorArray, sizeof(Map))) == NULL)
82.96 - {
82.97 - return false;
82.98 - }
82.99 -
82.100 - types_ = new TypeManager(this);
82.101 - if (!types_ || !types_->initialize())
82.102 - return false;
82.103 -
82.104 - // Create the cached array maps for generic arrays. This is for the API
82.105 - // version of Invoke(), which needs to make arrays very quickly from C++.
82.106 - {
82.107 - // Generic "cell" array (contents do not matter, just non-gc things).
82.108 - Local<Type> type(this, types_->getPrimitive(PrimitiveType_Int32));
82.109 - if (!type)
82.110 - return false;
82.111 -
82.112 - type = types_->unsafeArray(type, Type::UNKNOWN_SIZE, false);
82.113 - if (!type)
82.114 - return false;
82.115 -
82.116 - Local<ArrayMap> contained(this);
82.117 - genericArrayMap_ = ArrayMap::New(this, type, contained);
82.118 - if (!genericArrayMap_)
82.119 - return false;
82.120 -
82.121 - type = types_->getPrimitive(PrimitiveType_Char);
82.122 - if (!type)
82.123 - return false;
82.124 -
82.125 - type = types_->unsafeArray(type, Type::UNKNOWN_SIZE, false);
82.126 - if (!type)
82.127 - return false;
82.128 -
82.129 - charArrayMap_ = ArrayMap::New(this, type, contained);
82.130 - if (!charArrayMap_)
82.131 - return false;
82.132 - }
82.133 -
82.134 - return true;
82.135 -}
82.136 -
82.137 -Map *
82.138 -Zone::allocateMap(MapKind kind, size_t bytes, MapKind parent)
82.139 -{
82.140 - assert(maps_[parent]);
82.141 - Map *map = heap_.allocateMap(kind, bytes);
82.142 - if (!map)
82.143 - return NULL;
82.144 - map->init(maps_[parent]);
82.145 - return map;
82.146 -}
82.147 -
82.148 -void
82.149 -Zone::accept(VirtualObjectVisitor *visitor)
82.150 -{
82.151 - for (unsigned i = 0; i < MapKinds_Total; i++)
82.152 - visitor->visit(maps_[i].address());
82.153 - visitor->visit(charArrayMap_.address());
82.154 - visitor->visit(genericArrayMap_.address());
82.155 - types()->accept(visitor);
82.156 -
82.157 - Local<Object> *local = lastLocalRoot_;
82.158 - while (local) {
82.159 - visitor->visit(local->address());
82.160 - local = local->prev();
82.161 - }
82.162 -
82.163 - globalRoots_->accept(visitor);
82.164 - rootScopes_.accept(visitor);
82.165 -
82.166 - stack_.accept(visitor);
82.167 -}
82.168 -
82.169 -String *
82.170 -Zone::makeSymbol(const char *str, size_t length)
82.171 -{
82.172 - return symbols_->add(str, length);
82.173 -}
82.174 -
82.175 -String *
82.176 -Zone::makeSymbol(const char *str)
82.177 -{
82.178 - return makeSymbol(str, strlen(str));
82.179 -}
82.180 -
82.181 -bool
82.182 -Zone::hasPendingException()
82.183 -{
82.184 - return hasPendingException_;
82.185 -}
82.186 -
82.187 -void
82.188 -Zone::reportOutOfMemory()
82.189 -{
82.190 -
82.191 -}
82.192 -
82.193 -void
82.194 -Zone::reportError(Message message, ...)
82.195 -{
82.196 - va_list ap;
82.197 - va_start(ap, message);
82.198 - reportErrorVA(message, ap);
82.199 - va_end(ap);
82.200 -}
82.201 -
82.202 -#if defined(_MSC_VER)
82.203 -# define VA_COPY(to, from) to = from
82.204 -#else
82.205 -# define VA_COPY(to, from) va_copy(to, from)
82.206 -#endif
82.207 -
82.208 -static char *
82.209 -BuildErrorMessage(const char *format, va_list ap)
82.210 -{
82.211 - va_list use;
82.212 - VA_COPY(use, ap);
82.213 -
82.214 - // We over-allocate and zero terminate ahead of time, since LIBCRT's
82.215 - // version of vsnprintf is screwy.
82.216 - size_t size = 255;
82.217 - char *buffer = (char *)calloc(size + 1, 1);
82.218 - if (!buffer)
82.219 - return NULL;
82.220 -
82.221 - for (;;) {
82.222 - int r = vsnprintf(buffer, size, format, use);
82.223 -
82.224 - if (r > -1 && size_t(r) < size)
82.225 - return buffer;
82.226 -
82.227 -#if defined(_MSC_VER)
82.228 - if (r < 0)
82.229 - size *= 2;
82.230 -#else
82.231 - if (r > -1)
82.232 - size = size_t(r) + 1;
82.233 - else
82.234 - size *= 2;
82.235 -#endif
82.236 -
82.237 - free(buffer);
82.238 - if ((buffer = (char *)calloc(size + 1, 1)) == NULL)
82.239 - return NULL;
82.240 -
82.241 - VA_COPY(use, ap);
82.242 - }
82.243 -}
82.244 -
82.245 -void
82.246 -Zone::reportErrorVA(Message message, va_list ap)
82.247 -{
82.248 - char *report = BuildErrorMessage(Messages[message].format, ap);
82.249 - if (!report) {
82.250 - reportOutOfMemory();
82.251 - return;
82.252 - }
82.253 -
82.254 - if (reporter_) {
82.255 - // Reporters can re-enter. When we start having actual exception
82.256 - // objects that can be caught and inspected, this code will have to
82.257 - // save and restore the exception state.
82.258 - reporter_->onUncaughtException(report);
82.259 - }
82.260 -
82.261 - hasPendingException_ = true;
82.262 -
82.263 - free(report);
82.264 -}
82.265 -
82.266 -void
82.267 -Zone::beginCompilationErrors(const char *file)
82.268 -{
82.269 - if (reporter_)
82.270 - reporter_->beginCompilationErrors(file);
82.271 -}
82.272 -
82.273 -void
82.274 -Zone::reportCompilationError(Message message, unsigned line, unsigned col, va_list ap)
82.275 -{
82.276 - char *report = BuildErrorMessage(Messages[message].format, ap);
82.277 - if (!report) {
82.278 - reportOutOfMemory();
82.279 - return;
82.280 - }
82.281 -
82.282 - if (reporter_) {
82.283 - // Reporters can re-enter. When we start having actual exception
82.284 - // objects that can be caught and inspected, this code will have to
82.285 - // save and restore the exception state.
82.286 - reporter_->reportCompilationError(report, line, col);
82.287 - }
82.288 -
82.289 - free(report);
82.290 -}
82.291 -
82.292 -void
82.293 -Zone::endCompilationErrors()
82.294 -{
82.295 - if (reporter_)
82.296 - reporter_->endCompilationErrors();
82.297 -}
82.298 -
82.299 -void
82.300 -Zone::installErrorReporter(Ke::IMessageReporter *reporter)
82.301 -{
82.302 - reporter_ = reporter;
82.303 -}
82.304 -
82.305 -void
82.306 -ZoneAllocatorPolicy::reportOutOfMemory()
82.307 -{
82.308 - ZONE()->reportOutOfMemory();
82.309 -}
82.310 -
82.311 -void
82.312 -ZoneAllocatorPolicy::reportAllocationOverflow()
82.313 -{
82.314 - ZONE()->reportError(Message_AllocationOverflow);
82.315 -}
83.1 --- a/jitcraft/Zone.h Tue Jul 24 23:53:34 2012 -0700
83.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
83.3 @@ -1,189 +0,0 @@
83.4 -/* vim: set ts=4 sw=4 tw=99 et:
83.5 - *
83.6 - * Copyright (C) 2012 David Anderson
83.7 - *
83.8 - * This file is part of JITCraft.
83.9 - *
83.10 - * JITCraft is free software: you can redistribute it and/or modify it under
83.11 - * the terms of the GNU General Public License as published by the Free
83.12 - * Software Foundation, either version 3 of the License, or (at your option)
83.13 - * any later version.
83.14 - *
83.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
83.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
83.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
83.18 - *
83.19 - * You should have received a copy of the GNU General Public License along with
83.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
83.21 - */
83.22 -#ifndef _include_jitcraft_thread_h_
83.23 -#define _include_jitcraft_thread_h_
83.24 -
83.25 -#include <stdarg.h>
83.26 -#include "PoolAllocator.h"
83.27 -#include "Stack.h"
83.28 -#include "Heap.h"
83.29 -#include "Barriers.h"
83.30 -#include "Handles.h"
83.31 -#include "Messages.h"
83.32 -#include "RootScopes.h"
83.33 -#include "VirtualObjectVisitor.h"
83.34 -
83.35 -namespace ke {
83.36 -
83.37 -class TypeManager;
83.38 -class String;
83.39 -class StringPool;
83.40 -class GlobalRoots;
83.41 -class ArrayMap;
83.42 -class Exception;
83.43 -
83.44 -class Zone
83.45 -{
83.46 - PoolAllocator pool_;
83.47 - Stack stack_;
83.48 - Heap heap_;
83.49 -
83.50 - // Map cache.
83.51 - Unbarriered<Map> maps_[MapKinds_Total];
83.52 - Unbarriered<ArrayMap> genericArrayMap_;
83.53 - Unbarriered<ArrayMap> charArrayMap_;
83.54 -
83.55 - TypeManager *types_;
83.56 - StringPool *symbols_;
83.57 - GlobalRoots *globalRoots_;
83.58 -
83.59 - // Root list.
83.60 - Local<Object> *lastLocalRoot_;
83.61 - RootScopeManager rootScopes_;
83.62 -
83.63 - // Exception stuff.
83.64 - bool hasPendingException_;
83.65 - Ke::IMessageReporter *reporter_;
83.66 -
83.67 - private:
83.68 - Zone *thisFromCtor() {
83.69 - return this;
83.70 - }
83.71 -
83.72 - public:
83.73 - Zone();
83.74 - ~Zone();
83.75 - bool initialize();
83.76 -
83.77 - PoolAllocator &pool() {
83.78 - return pool_;
83.79 - }
83.80 - Stack &stack() {
83.81 - return stack_;
83.82 - }
83.83 - Heap &heap() {
83.84 - return heap_;
83.85 - }
83.86 - Object *allocate(MapKind kind, size_t bytes, Heap::Tenure tenure = Heap::Tenure_Default) {
83.87 - assert(maps_[kind]);
83.88 - Local<Map> map(this, maps_[kind]);
83.89 - return allocate(map, bytes, tenure);
83.90 - }
83.91 - Object *allocate(Handle<Map> map, size_t bytes, Heap::Tenure tenure = Heap::Tenure_Default) {
83.92 - return heap_.allocate(map, bytes, tenure);
83.93 - }
83.94 - Map *getMap(MapKind kind) {
83.95 - return maps_[kind];
83.96 - }
83.97 - Map *allocateMap(MapKind kind, size_t bytes, MapKind parent = MapKind_Meta);
83.98 -
83.99 - ArrayMap *genericArrayMap() {
83.100 - return genericArrayMap_;
83.101 - }
83.102 - ArrayMap *charArrayMap() {
83.103 - return charArrayMap_;
83.104 - }
83.105 -
83.106 - TypeManager *types() const {
83.107 - return types_;
83.108 - }
83.109 - Local<Object> **lastLocalRoot() {
83.110 - return &lastLocalRoot_;
83.111 - }
83.112 - Object **makeScopedRoot(Object *ptr) {
83.113 - return rootScopes_.make(ptr);
83.114 - }
83.115 - RootScopeManager &rootScopes() {
83.116 - return rootScopes_;
83.117 - }
83.118 - StringPool *symbols() {
83.119 - return symbols_;
83.120 - }
83.121 - GlobalRoots *globalRoots() {
83.122 - return globalRoots_;
83.123 - }
83.124 -
83.125 - String *makeSymbol(const char *string, size_t length);
83.126 - String *makeSymbol(const char *string);
83.127 -
83.128 - void reportOutOfMemory();
83.129 - void reportError(Message message, ...);
83.130 - void reportErrorVA(Message message, va_list ap);
83.131 - bool hasPendingException();
83.132 - void installErrorReporter(Ke::IMessageReporter *reporter);
83.133 - void beginCompilationErrors(const char *file);
83.134 - void reportCompilationError(Message message, unsigned line, unsigned col, va_list ap);
83.135 - void endCompilationErrors();
83.136 -
83.137 - void accept(VirtualObjectVisitor *visitor);
83.138 -};
83.139 -
83.140 -// In a multi-threaded system, this would be a TLS variable.
83.141 -// In the interest of simplicity, we are single-threaded for now.
83.142 -extern Zone *SingleThreadedZone;
83.143 -
83.144 -static inline Zone *ZONE()
83.145 -{
83.146 - return SingleThreadedZone;
83.147 -}
83.148 -
83.149 -template <typename T>
83.150 -Local<T>::Local(Zone *zone, T *thing)
83.151 - : zone_(zone),
83.152 - thing_(thing),
83.153 - prev_(*zone->lastLocalRoot())
83.154 -{
83.155 - *zone->lastLocalRoot() = toRaw();
83.156 -}
83.157 -
83.158 -template <typename T>
83.159 -Local<T>::~Local()
83.160 -{
83.161 - assert(*zone_->lastLocalRoot() == toRaw());
83.162 - *zone_->lastLocalRoot() = prev_;
83.163 -}
83.164 -
83.165 -template <typename T>
83.166 -ScopedRoot<T>::ScopedRoot()
83.167 - : thingp_(make(NULL))
83.168 -{
83.169 -}
83.170 -
83.171 -template <typename T>
83.172 -ScopedRoot<T>::ScopedRoot(T *thing)
83.173 - : thingp_(make(thing))
83.174 -{
83.175 - // Type check that T is an Object.
83.176 - (void)static_cast<Object *>(thing);
83.177 -}
83.178 -
83.179 -template <typename T> T **
83.180 -ScopedRoot<T>::make(T *other)
83.181 -{
83.182 - return reinterpret_cast<T **>(ZONE()->makeScopedRoot(other));
83.183 -}
83.184 -
83.185 -RootScope::RootScope(Zone *zone)
83.186 - : Ke::HandleScope(zone, zone->rootScopes().position(), *zone->rootScopes().scope())
83.187 -{
83.188 -}
83.189 -
83.190 -}
83.191 -
83.192 -#endif // _include_jitcraft_thread_h_
84.1 --- a/jitcraft/configure.in Tue Jul 24 23:53:34 2012 -0700
84.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
84.3 @@ -1,47 +0,0 @@
84.4 -# -*- Autoconf -*-
84.5 -# Process this file with autoconf to produce a configure script.
84.6 -
84.7 -AC_PREREQ([2.61])
84.8 -AC_INIT(foobar, 0.1, https://bugs.alliedmods.net/)
84.9 -AC_CONFIG_AUX_DIR(${srcdir}/build/autoconf)
84.10 -AC_CONFIG_SRCDIR([Heap.cpp])
84.11 -AC_LANG(C++)
84.12 -AC_CANONICAL_HOST
84.13 -
84.14 -# Checks for programs.
84.15 -AC_PROG_CXX
84.16 -
84.17 -# Checks for libraries.
84.18 -
84.19 -# Checks for header files.
84.20 -AC_CHECK_HEADERS([limits.h stddef.h stdint.h stdlib.h string.h sys/time.h unistd.h])
84.21 -
84.22 -# Checks for typedefs, structures, and compiler characteristics.
84.23 -AC_C_INLINE
84.24 -
84.25 -# Checks for library functions.
84.26 -AC_FUNC_MALLOC
84.27 -AC_FUNC_REALLOC
84.28 -AC_CHECK_FUNCS([gettimeofday memset strchr])
84.29 -
84.30 -mkdir -p .deps
84.31 -touch .deps/
84.32 -
84.33 -#AX_COMPILER_VENDOR
84.34 -
84.35 -CXXVENDOR=$ax_cv_cxx_compiler_vendor
84.36 -AC_SUBST(CXXVENDOR)
84.37 -
84.38 -case "$host" in
84.39 - *-linux*)
84.40 - PLATFORM="linux"
84.41 - ;;
84.42 - *-darwin*)
84.43 - PLATFORM="darwin"
84.44 - ;;
84.45 -esac
84.46 -
84.47 -AC_SUBST(PLATFORM)
84.48 -
84.49 -AC_OUTPUT(Makefile)
84.50 -
85.1 --- a/jitcraft/jitcraft.vcxproj Tue Jul 24 23:53:34 2012 -0700
85.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
85.3 @@ -1,188 +0,0 @@
85.4 -<?xml version="1.0" encoding="utf-8"?>
85.5 -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
85.6 - <ItemGroup Label="ProjectConfigurations">
85.7 - <ProjectConfiguration Include="Debug - Library|Win32">
85.8 - <Configuration>Debug - Library</Configuration>
85.9 - <Platform>Win32</Platform>
85.10 - </ProjectConfiguration>
85.11 - <ProjectConfiguration Include="Debug|Win32">
85.12 - <Configuration>Debug</Configuration>
85.13 - <Platform>Win32</Platform>
85.14 - </ProjectConfiguration>
85.15 - <ProjectConfiguration Include="Release|Win32">
85.16 - <Configuration>Release</Configuration>
85.17 - <Platform>Win32</Platform>
85.18 - </ProjectConfiguration>
85.19 - </ItemGroup>
85.20 - <PropertyGroup Label="Globals">
85.21 - <ProjectGuid>{E12034DC-E8CB-4B49-AC0A-0D27CDED9A50}</ProjectGuid>
85.22 - <Keyword>Win32Proj</Keyword>
85.23 - <RootNamespace>jitcraft</RootNamespace>
85.24 - </PropertyGroup>
85.25 - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
85.26 - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
85.27 - <ConfigurationType>Application</ConfigurationType>
85.28 - <UseDebugLibraries>true</UseDebugLibraries>
85.29 - <CharacterSet>Unicode</CharacterSet>
85.30 - </PropertyGroup>
85.31 - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
85.32 - <ConfigurationType>Application</ConfigurationType>
85.33 - <UseDebugLibraries>false</UseDebugLibraries>
85.34 - <WholeProgramOptimization>true</WholeProgramOptimization>
85.35 - <CharacterSet>Unicode</CharacterSet>
85.36 - </PropertyGroup>
85.37 - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug - Library|Win32'">
85.38 - <ConfigurationType>StaticLibrary</ConfigurationType>
85.39 - </PropertyGroup>
85.40 - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
85.41 - <ImportGroup Label="ExtensionSettings">
85.42 - </ImportGroup>
85.43 - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
85.44 - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
85.45 - </ImportGroup>
85.46 - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
85.47 - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
85.48 - </ImportGroup>
85.49 - <PropertyGroup Label="UserMacros" />
85.50 - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
85.51 - <LinkIncremental>true</LinkIncremental>
85.52 - </PropertyGroup>
85.53 - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
85.54 - <LinkIncremental>false</LinkIncremental>
85.55 - </PropertyGroup>
85.56 - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - Library|Win32'">
85.57 - <TargetExt>.lib</TargetExt>
85.58 - <TargetName>keima</TargetName>
85.59 - </PropertyGroup>
85.60 - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
85.61 - <ClCompile>
85.62 - <PrecompiledHeader>
85.63 - </PrecompiledHeader>
85.64 - <WarningLevel>Level3</WarningLevel>
85.65 - <Optimization>Disabled</Optimization>
85.66 - <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions); _CRT_SECURE_NO_WARNINGS;KE_EXPORTING</PreprocessorDefinitions>
85.67 - </ClCompile>
85.68 - <Link>
85.69 - <SubSystem>Console</SubSystem>
85.70 - <GenerateDebugInformation>true</GenerateDebugInformation>
85.71 - <RandomizedBaseAddress>false</RandomizedBaseAddress>
85.72 - </Link>
85.73 - </ItemDefinitionGroup>
85.74 - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
85.75 - <ClCompile>
85.76 - <WarningLevel>Level3</WarningLevel>
85.77 - <PrecompiledHeader>
85.78 - </PrecompiledHeader>
85.79 - <Optimization>MaxSpeed</Optimization>
85.80 - <FunctionLevelLinking>true</FunctionLevelLinking>
85.81 - <IntrinsicFunctions>true</IntrinsicFunctions>
85.82 - <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
85.83 - </ClCompile>
85.84 - <Link>
85.85 - <SubSystem>Console</SubSystem>
85.86 - <GenerateDebugInformation>true</GenerateDebugInformation>
85.87 - <EnableCOMDATFolding>true</EnableCOMDATFolding>
85.88 - <OptimizeReferences>true</OptimizeReferences>
85.89 - </Link>
85.90 - </ItemDefinitionGroup>
85.91 - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug - Library|Win32'">
85.92 - <ClCompile>
85.93 - <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
85.94 - <ExceptionHandling>false</ExceptionHandling>
85.95 - <RuntimeTypeInfo>false</RuntimeTypeInfo>
85.96 - <Optimization>Disabled</Optimization>
85.97 - </ClCompile>
85.98 - </ItemDefinitionGroup>
85.99 - <ItemGroup>
85.100 - <ClCompile Include="API.cpp" />
85.101 - <ClCompile Include="Array.cpp" />
85.102 - <ClCompile Include="BytecodeCompiler.cpp" />
85.103 - <ClCompile Include="BytecodeEmitter.cpp" />
85.104 - <ClCompile Include="CompileContext.cpp" />
85.105 - <ClCompile Include="Environments.cpp" />
85.106 - <ClCompile Include="Exception.cpp" />
85.107 - <ClCompile Include="FixedArray.cpp" />
85.108 - <ClCompile Include="Functions.cpp" />
85.109 - <ClCompile Include="GlobalRoots.cpp" />
85.110 - <ClCompile Include="Heap.cpp" />
85.111 - <ClCompile Include="Interpreter.cpp" />
85.112 - <ClCompile Include="main.cpp" />
85.113 - <ClCompile Include="Modules.cpp" />
85.114 - <ClCompile Include="NameBinding.cpp" />
85.115 - <ClCompile Include="Opcodes.cpp" />
85.116 - <ClCompile Include="Parser.cpp" />
85.117 - <ClCompile Include="Platform-Windows.cpp" />
85.118 - <ClCompile Include="PoolAllocator.cpp" />
85.119 - <ClCompile Include="Reference.cpp" />
85.120 - <ClCompile Include="RootScopes.cpp" />
85.121 - <ClCompile Include="Scanner.cpp" />
85.122 - <ClCompile Include="Scopes.cpp" />
85.123 - <ClCompile Include="SemanticAnalysis.cpp" />
85.124 - <ClCompile Include="Spaces.cpp" />
85.125 - <ClCompile Include="Stack.cpp" />
85.126 - <ClCompile Include="StringPool.cpp" />
85.127 - <ClCompile Include="Strings.cpp" />
85.128 - <ClCompile Include="Structures.cpp" />
85.129 - <ClCompile Include="TypeManager.cpp" />
85.130 - <ClCompile Include="Types.cpp" />
85.131 - <ClCompile Include="Zone.cpp" />
85.132 - </ItemGroup>
85.133 - <ItemGroup>
85.134 - <ClInclude Include="..\include\keima.h" />
85.135 - <ClInclude Include="..\include\keima_util.h" />
85.136 - <ClInclude Include="AllocatorPolicies.h" />
85.137 - <ClInclude Include="Array.h" />
85.138 - <ClInclude Include="AST.h" />
85.139 - <ClInclude Include="Barriers.h" />
85.140 - <ClInclude Include="BytecodeEmitter.h" />
85.141 - <ClInclude Include="BytecodeCompiler.h" />
85.142 - <ClInclude Include="CompactBuffer.h" />
85.143 - <ClInclude Include="CompileContext.h" />
85.144 - <ClInclude Include="Environments.h" />
85.145 - <ClInclude Include="FixedArray.h" />
85.146 - <ClInclude Include="Functions.h" />
85.147 - <ClInclude Include="GlobalRoots.h" />
85.148 - <ClInclude Include="Handles-inl.h" />
85.149 - <ClInclude Include="HashTable.h" />
85.150 - <ClInclude Include="Heap-inl.h" />
85.151 - <ClInclude Include="InlineList.h" />
85.152 - <ClInclude Include="Interpreter.h" />
85.153 - <ClInclude Include="Messages.h" />
85.154 - <ClInclude Include="Modules.h" />
85.155 - <ClInclude Include="NameBinding.h" />
85.156 - <ClInclude Include="Heap.h" />
85.157 - <ClInclude Include="Objects.h" />
85.158 - <ClInclude Include="ObjectVisitor.h" />
85.159 - <ClInclude Include="Opcodes.h" />
85.160 - <ClInclude Include="Parser.h" />
85.161 - <ClInclude Include="Platform.h" />
85.162 - <ClInclude Include="PoolAllocator.h" />
85.163 - <ClInclude Include="Handles.h" />
85.164 - <ClInclude Include="Reference.h" />
85.165 - <ClInclude Include="RootScopes.h" />
85.166 - <ClInclude Include="Scanner.h" />
85.167 - <ClInclude Include="Scopes.h" />
85.168 - <ClInclude Include="Code.h" />
85.169 - <ClInclude Include="SemanticAnalysis.h" />
85.170 - <ClInclude Include="Spaces-inl.h" />
85.171 - <ClInclude Include="Spaces.h" />
85.172 - <ClInclude Include="Stack.h" />
85.173 - <ClInclude Include="Strings.h" />
85.174 - <ClInclude Include="StringPool.h" />
85.175 - <ClInclude Include="Structures.h" />
85.176 - <ClInclude Include="TypeManager.h" />
85.177 - <ClInclude Include="Types.h" />
85.178 - <ClInclude Include="Vector.h" />
85.179 - <ClInclude Include="VirtualObjectVisitor.h" />
85.180 - <ClInclude Include="Zone.h" />
85.181 - <ClInclude Include="Token.h" />
85.182 - <ClInclude Include="Utility.h" />
85.183 - </ItemGroup>
85.184 - <ItemGroup>
85.185 - <None Include="Messages.tbl" />
85.186 - <None Include="Opcodes.tbl" />
85.187 - </ItemGroup>
85.188 - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
85.189 - <ImportGroup Label="ExtensionTargets">
85.190 - </ImportGroup>
85.191 -</Project>
85.192 \ No newline at end of file
86.1 --- a/jitcraft/main.cpp Tue Jul 24 23:53:34 2012 -0700
86.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
86.3 @@ -1,132 +0,0 @@
86.4 -/*
86.5 - * Copyright (C) 2012 David Anderson
86.6 - *
86.7 - * This file is part of JITCraft.
86.8 - *
86.9 - * JITCraft is free software: you can redistribute it and/or modify it under
86.10 - * the terms of the GNU General Public License as published by the Free
86.11 - * Software Foundation, either version 3 of the License, or (at your option)
86.12 - * any later version.
86.13 - *
86.14 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
86.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
86.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
86.17 - *
86.18 - * You should have received a copy of the GNU General Public License along with
86.19 - * JITCraft. If not, see http://www.gnu.org/licenses/.
86.20 - */
86.21 -#include <stdio.h>
86.22 -#include "Utility.h"
86.23 -#include "Scanner.h"
86.24 -#include "Parser.h"
86.25 -#include "SemanticAnalysis.h"
86.26 -#include "Zone.h"
86.27 -#include "BytecodeCompiler.h"
86.28 -#include "Code.h"
86.29 -#include "Interpreter.h"
86.30 -#include "Modules.h"
86.31 -#include "RootScopes.h"
86.32 -#include "../include/keima.h"
86.33 -
86.34 -using namespace ke;
86.35 -
86.36 -class MessageReporter : public Ke::IMessageReporter
86.37 -{
86.38 - public:
86.39 - void onOutOfMemory() {
86.40 - fprintf(stderr, "Out of memory!\n");
86.41 - }
86.42 - void onUncaughtException(const char *message) {
86.43 - fprintf(stderr, "Uncaught exception: %s\n", message);
86.44 -
86.45 - Ke::IStackFrameIterator *iter = Ke::Keima::NewStackFrameIterator();
86.46 - unsigned index = 0;
86.47 - while (!iter->done()) {
86.48 - fprintf(stderr, "[%d] %s (%s line %d)\n",
86.49 - index,
86.50 - iter->function(),
86.51 - iter->source(),
86.52 - iter->lineNumber());
86.53 - iter->prev();
86.54 - index++;
86.55 - }
86.56 - }
86.57 - virtual void beginCompilationErrors(const char *file) {
86.58 - fprintf(stderr, "\nDisplaying compilation errors for \"%s\"\n", file);
86.59 - }
86.60 - virtual void reportCompilationError(const char *message, unsigned line, unsigned col) {
86.61 - fprintf(stderr, " line %d, col %d: %s\n", line, col, message);
86.62 - }
86.63 - virtual void endCompilationErrors() {
86.64 - }
86.65 -} s_Reporter;
86.66 -
86.67 -#if 0
86.68 -static bool
86.69 -Compile(const char *stream, size_t length)
86.70 -{
86.71 -
86.72 - printf("\n ------------ \n\n");
86.73 -
86.74 - Disassemble(module->getFunction(1)->code(), stdout);
86.75 - //Disassemble(module->getFunction(1), stdout);
86.76 -
86.77 - printf("\n ------------ \n\n");
86.78 -
86.79 - Function *main = module->getFunction(1);
86.80 -
86.81 - Top top = ZONE()->stack().begin();
86.82 - LocalTop localTop(top);
86.83 -
86.84 - Frame *frame = ZONE()->stack().pushFrame(main);
86.85 - if (!frame)
86.86 - return false;
86.87 -
86.88 - LocalSlot result;
86.89 - if (!Interpret(ZONE(), frame, &result))
86.90 - return false;
86.91 -
86.92 - printf("Result: %d\n", result.i32);
86.93 -
86.94 - return true;
86.95 -}
86.96 -#endif
86.97 -
86.98 -intptr_t PrintToServer(void *blah, intptr_t *params)
86.99 -{
86.100 - assert(params[0] == 3);
86.101 - const char *fmt = reinterpret_cast<const char *>(params[1]);
86.102 - const char *str = reinterpret_cast<const char *>(params[2]);
86.103 - int *d = reinterpret_cast<int *>(params[3]);
86.104 - printf(fmt, str, *d);
86.105 - return 16;
86.106 -}
86.107 -
86.108 -int main(int argc, char **argv)
86.109 -{
86.110 - if (argc < 2) {
86.111 - fprintf(stderr, "Usage: <file>\n");
86.112 - return 1;
86.113 - }
86.114 -
86.115 - if (!Ke::Keima::Initialize())
86.116 - return 1;
86.117 - Ke::Keima::InstallMessageReporter(&s_Reporter);
86.118 - {
86.119 - Ke::HandleScope scope;
86.120 - Ke::Local<Ke::Module> module = Ke::Compile(argv[1]);
86.121 - if (!module)
86.122 - return 1;
86.123 -
86.124 - //Ke::Local<Ke::Native> native = module->getNative(0);
86.125 - //native->bind(reinterpret_cast<void *>(PrintToServer));
86.126 - //module->setNativeIdentity(reinterpret_cast<void *>(5));
86.127 -
86.128 - int result;
86.129 - Ke::Local<Ke::Function> fun = module->getPublic(0);
86.130 - if (Ke::Keima::Invoke(fun, NULL, 0, &result))
86.131 - printf("%d\n", result);
86.132 - }
86.133 -
86.134 - Ke::Keima::Shutdown();
86.135 -}
87.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
87.2 +++ b/src/AMBuild.library Tue Jul 24 23:54:14 2012 -0700
87.3 @@ -0,0 +1,49 @@
87.4 +# vim: set ts=2 sw=2 tw=99 noet ft=python:
87.5 +import os
87.6 +
87.7 +compiler = KE.DefaultCompiler()
87.8 +base = AMBuild.sourceFolder
87.9 +
87.10 +compiler['CXXINCLUDES'].append(os.path.join(base, 'include'))
87.11 +
87.12 +job = AMBuild.AddJob('libkeima')
87.13 +library = Cpp.StaticLibraryBuilder('libkeima', AMBuild, job, compiler)
87.14 +files = [
87.15 + 'API.cpp',
87.16 + 'Array.cpp',
87.17 + 'BytecodeCompiler.cpp',
87.18 + 'BytecodeEmitter.cpp',
87.19 + 'CompileContext.cpp',
87.20 + 'Environments.cpp',
87.21 + 'Exception.cpp',
87.22 + 'FixedArray.cpp',
87.23 + 'Functions.cpp',
87.24 + 'GlobalRoots.cpp',
87.25 + 'Heap.cpp',
87.26 + 'Interpreter.cpp',
87.27 + 'Modules.cpp',
87.28 + 'NameBinding.cpp',
87.29 + 'Opcodes.cpp',
87.30 + 'Parser.cpp',
87.31 + 'PoolAllocator.cpp',
87.32 + 'Reference.cpp',
87.33 + 'RootScopes.cpp',
87.34 + 'Scanner.cpp',
87.35 + 'Scopes.cpp',
87.36 + 'SemanticAnalysis.cpp',
87.37 + 'Spaces.cpp',
87.38 + 'Stack.cpp',
87.39 + 'StringPool.cpp',
87.40 + 'Strings.cpp',
87.41 + 'Structures.cpp',
87.42 + 'TypeManager.cpp',
87.43 + 'Types.cpp',
87.44 + 'Zone.cpp'
87.45 +]
87.46 +if AMBuild.target['platform'] == 'windows':
87.47 + files.append('Platform-Windows.cpp')
87.48 +else:
87.49 + files.append('Platform-Posix.cpp')
87.50 +library.AddSourceFiles('src', files)
87.51 +library.SendToJob()
87.52 +