Added global variable support.
1 /* vim: set ts=4 sw=4 tw=99 et:
3 * Copyright (C) 2012 David Anderson
5 * This file is part of JITCraft.
7 * JITCraft is free software: you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License as published by the Free
9 * Software Foundation, either version 3 of the License, or (at your option)
12 * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
13 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with
17 * JITCraft. If not, see http://www.gnu.org/licenses/.
19 #include "../include/keima.h"
21 #include "RootScopes.h"
22 #include "CompileContext.h"
25 #include "SemanticAnalysis.h"
26 #include "BytecodeCompiler.h"
28 #include "GlobalRoots.h"
29 #include "Reference.h"
31 #include "Interpreter.h"
38 Ke::Keima::Initialize()
40 SingleThreadedZone = new Zone();
41 if (!SingleThreadedZone || !SingleThreadedZone->initialize())
49 delete SingleThreadedZone;
50 SingleThreadedZone = NULL;
53 Ke::HandleScope::HandleScope()
55 position_(zone_->rootScopes().position()),
56 prev_(*zone_->rootScopes().scope())
58 *zone_->rootScopes().scope() = this;
61 Ke::HandleScope::~HandleScope()
63 zone_->rootScopes().unwind(position_);
64 *zone_->rootScopes().scope() = prev_;
68 Ke::HandleScope::CreateHandle(ke::Object *obj)
73 return ZONE()->rootScopes().make(obj);
76 template <typename From, typename To> static inline To *
77 Open(Ke::Handle<From> from)
79 return *reinterpret_cast<To **>(*from);
82 template <typename From, typename To> static inline To *
85 return *reinterpret_cast<To **>(from);
88 template <typename From, typename To> static inline Ke::Local<To>
91 return Ke::Local<To>(reinterpret_cast<To *>(Ke::HandleScope::CreateHandle(from)));
95 CompileFromSource(CompileContext &cc, const char *path, const char *stream, size_t length)
97 Parser parser(ZONE(), cc, stream, length);
98 ParseTree *tree = parser.parse();
103 if (!Scope::Bind(cc, tree))
106 SemanticAnalysis semantics(ZONE(), cc, tree);
107 if (!semantics.analyze())
110 Scope::Allocate(tree);
112 BytecodeCompiler compiler(ZONE(), tree, NULL);
113 ke::Local<Module> module(ke::ZONE(), compiler.compile());
118 if (!ke::ZONE()->stack().pushModuleFrame(module, args))
120 if (!ke::Interpret(ke::ZONE(), NULL, NULL))
126 Ke::Local<Ke::Module>
127 Ke::Compile(const char *path)
129 RootScope roots(ZONE());
130 CompileContext cc(ZONE(), path);
135 FILE *fp = fopen(path, "rb");
137 cc.reportError(SourcePosition(), Message_CantOpenFile);
138 return Ke::Local<Ke::Module>();
141 if (fseek(fp, 0, SEEK_END)) {
142 cc.reportError(SourcePosition(), Message_ErrorSeekingFile);
144 return Ke::Local<Ke::Module>();;
146 long size = ftell(fp);
148 cc.reportError(SourcePosition(), Message_ErrorSeekingFile);
150 return Ke::Local<Ke::Module>();;
153 length = size_t(size);
154 bytes = new char[length + 1];
155 if (fread(bytes, 1, length, fp) != length) {
156 cc.reportError(SourcePosition(), Message_ErrorReadingFile);
159 return Ke::Local<Ke::Module>();;
164 ke::Local<ke::Module> module(ZONE(), CompileFromSource(cc, path, bytes, length));
167 return Ke::Local<Ke::Module>();
169 ke::Local<ke::String> pathstr(ZONE(), ke::String::New(ZONE(), path, Heap::Tenure_Old));
171 return Ke::Local<Ke::Module>();
173 module->setPath(pathstr);
174 return ToLocal<ke::Module, Ke::Module>(module);
178 Ke::Keima::InstallMessageReporter(Ke::IMessageReporter *reporter)
180 ZONE()->installErrorReporter(reporter);
183 class StackFrameIterator : public Ke::IStackFrameIterator
193 virtual bool done() {
197 const char *function() {
198 return iter_.function();
201 const char *source() {
202 return iter_.source();
205 unsigned lineNumber() {
206 return iter_.lineNumber();
214 Ke::IStackFrameIterator *
215 Ke::Keima::NewStackFrameIterator()
217 return new StackFrameIterator();
220 static inline ke::HeapRoot *
221 FromAPI(ke::HeapRoot *from)
223 ke::Address address = reinterpret_cast<ke::Address>(from);
224 address -= offsetof(ke::HeapRoot, obj);
225 return reinterpret_cast<ke::HeapRoot *>(address);
229 Ke::Internals::NewHeapRoot(ke::Object **ptr)
231 ke::Local<ke::Object> obj(ZONE(), *ptr);
232 ke::HeapRoot *root = ke::ZONE()->globalRoots()->create(obj);
236 // Compute an interior pointer, so it looks like a Handle to an object.
237 return reinterpret_cast<ke::HeapRoot *>(&root->obj);
241 Ke::Internals::IncRef(ke::HeapRoot *root)
243 ZONE()->globalRoots()->incref(FromAPI(root));
247 Ke::Internals::DecRef(ke::HeapRoot *root)
249 ZONE()->globalRoots()->decref(FromAPI(root));
253 Ke::Keima::IsInCallStack(Handle<Module> argModule)
255 ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(argModule));
256 return ZONE()->stack().isInCallStack(module);
260 Ke::Keima::CollectGarbage()
262 ke::ZONE()->heap().reclaim();
266 Ke::Module::numPublics()
268 ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(this));
269 if (!module->publics())
271 return module->publics()->length();
274 Ke::Local<Ke::Function>
275 Ke::Module::getPublic(unsigned index)
277 ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(this));
278 ke::Local<ke::Function> fun(ke::ZONE(), ke::Function::cast(module->publics()->at(index)));
279 return ToLocal<ke::Function, Ke::Function>(fun);
283 Ke::Module::numNatives()
285 ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(this));
286 if (!module->natives())
288 return module->natives()->length();
291 Ke::Local<Ke::Native>
292 Ke::Module::getNative(unsigned index)
294 ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(this));
295 ke::Local<ke::Native> fun(ke::ZONE(), ke::Native::cast(module->natives()->at(index)));
296 return ToLocal<ke::Native, Ke::Native>(fun);
300 Ke::Module::setNativeIdentity(void *identity)
302 ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(this));
303 module->setNativeIdentity(identity);
309 ke::Local<ke::String> obj(ke::ZONE(), Open<Ke::String, ke::String>(this));
310 return obj->length();
316 ke::Local<ke::String> obj(ke::ZONE(), Open<Ke::String, ke::String>(this));
320 Ke::Local<Ke::String>
323 ke::Local<ke::Function> fun(ke::ZONE(), Open<Ke::Function, ke::Function>(this));
324 return ToLocal<ke::String, Ke::String>(fun->name());
327 Ke::Local<Ke::String>
330 ke::Local<ke::Native> native(ke::ZONE(), Open<Ke::Native, ke::Native>(this));
331 return ToLocal<ke::String, Ke::String>(native->name());
335 Ke::Native::bind(void *function)
337 ke::Local<ke::Native> native(ke::ZONE(), Open<Ke::Native, ke::Native>(this));
338 native->bind(function);
342 CheckInvokeType(const Ke::Parameter ¶m, Type *type)
344 switch (param.type()) {
345 case Ke::Parameter::Array:
346 return type->isArray() &&
347 type->levels() == 1 &&
348 type->contained()->isPrimitive() &&
349 (type->contained()->primitive() != PrimitiveType_Char);
350 case Ke::Parameter::CharArray:
351 return type->isCharArray();
352 case Ke::Parameter::Float:
353 return type->isFloat();
354 case Ke::Parameter::FloatRef:
355 return type->isReference() && type->contained()->isFloat();
356 case Ke::Parameter::Int:
357 return type->isInt32();
358 case Ke::Parameter::IntRef:
359 return type->isReference() && type->contained()->isInt32();
366 Ke::Keima::CheckInvokeTypes(Ke::Handle<Ke::Function> argFun, const Ke::Parameter *params, unsigned nparams)
368 ke::Local<ke::Function> fun(ke::ZONE(), Open<Ke::Function, ke::Function>(argFun));
370 if (fun->nargs() != nparams)
373 for (unsigned i = 0; i < nparams; i++) {
374 if (!CheckInvokeType(params[i], fun->argType(i)))
378 // Functions can only return tagged cells, for ISPE1-compatible Invoke().
379 ke::Local<ke::Type> returnType(ke::ZONE(), fun->type()->returnType());
380 if ((!returnType->isPrimitive() && !returnType->isVoid()) || returnType->isTraceable())
387 Ke::Keima::Invoke(Handle<Function> argFun, const Parameter *params, unsigned nparams, int *retval)
389 assert(CheckInvokeTypes(argFun, params, nparams));
391 ke::Local<ke::Function> fun(ke::ZONE(), Open<Ke::Function, ke::Function>(argFun));
393 if (fun->nargs() != nparams) {
394 // :TODO: report error
400 if (!ke::ZONE()->stack().pushInvokeFrame(fun, args))
403 for (unsigned i = 0; i < nparams; i++) {
404 ke::LocalSlot &slot = args.arg(i);
405 switch (params[i].type()) {
406 case Ke::Parameter::Int:
407 slot.i32 = params[i].i32();
410 case Ke::Parameter::Float:
411 slot.f = params[i].f();
414 case Ke::Parameter::IntRef:
415 if (params[i].writeback()) {
416 slot.ref = Reference::NewStack(ke::ZONE(), params[i].i32p(), Heap::Tenure_Stack);
419 other.i32 = *params[i].i32p();
420 slot.ref = Reference::NewStack(ke::ZONE(), other, Heap::Tenure_Stack);
426 case Ke::Parameter::FloatRef:
427 if (params[i].writeback()) {
428 slot.ref = Reference::NewStack(ke::ZONE(), params[i].fp(), Heap::Tenure_Stack);
431 other.f = *params[i].fp();
432 slot.ref = Reference::NewStack(ke::ZONE(), other, Heap::Tenure_Stack);
438 case Ke::Parameter::Array:
440 ke::Local<ke::ArrayMap> map(ke::ZONE(), ke::ZONE()->genericArrayMap());
441 if (params[i].writeback()) {
442 slot.obj = Array::NewExternal(ke::ZONE(), map, params[i].length(),
443 params[i].buffer(), Heap::Tenure_Stack);
447 Array *array = Array::New(ke::ZONE(), map, params[i].length(), Heap::Tenure_Stack);
450 memcpy(array->vec(), params[i].buffer(), params[i].length() * sizeof(int));
455 case Ke::Parameter::CharArray:
457 ke::Local<ke::ArrayMap> map(ke::ZONE(), ke::ZONE()->charArrayMap());
458 if (params[i].writeback()) {
459 slot.obj = Array::NewExternal(ke::ZONE(), map, params[i].length(),
460 params[i].buffer(), Heap::Tenure_Stack);
464 Array *array = Array::New(ke::ZONE(), map, params[i].length(), Heap::Tenure_Stack);
467 memcpy(array->vec(), params[i].buffer(), params[i].length() * sizeof(char));
475 if (!Interpret(ke::ZONE(), NULL, &result))
478 if (fun->type()->returnType()->isVoid())
481 *retval = result.i32;