Stop using ccache on OS X.
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/.
20 #include "../include/keima.h"
22 #include "RootScopes.h"
23 #include "CompileContext.h"
26 #include "SemanticAnalysis.h"
27 #include "BytecodeCompiler.h"
29 #include "GlobalRoots.h"
30 #include "Reference.h"
32 #include "Interpreter.h"
35 #include "Spaces-inl.h"
41 Ke::Keima::Initialize()
43 SingleThreadedZone = new Zone();
44 if (!SingleThreadedZone || !SingleThreadedZone->initialize())
52 delete SingleThreadedZone;
53 SingleThreadedZone = NULL;
56 Ke::HandleScope::HandleScope()
58 position_(zone_->rootScopes().position()),
59 prev_(*zone_->rootScopes().scope())
61 *zone_->rootScopes().scope() = this;
64 Ke::HandleScope::~HandleScope()
66 zone_->rootScopes().unwind(position_);
67 *zone_->rootScopes().scope() = prev_;
71 Ke::HandleScope::CreateHandle(ke::Object *obj)
76 return ZONE()->rootScopes().make(obj);
79 template <typename From, typename To> static inline To *
80 Open(Ke::Handle<From> from)
82 return *reinterpret_cast<To **>(*from);
85 template <typename From, typename To> static inline To *
88 return *reinterpret_cast<To **>(from);
91 template <typename From, typename To> static inline Ke::Local<To>
94 return Ke::Local<To>(reinterpret_cast<To *>(Ke::HandleScope::CreateHandle(from)));
98 CompileFromSource(CompileContext &cc, const char *path, const char *stream, size_t length)
100 Parser parser(ZONE(), cc, stream, length);
101 ParseTree *tree = parser.parse();
106 if (!Scope::Bind(cc, tree))
109 SemanticAnalysis semantics(ZONE(), cc, tree);
110 if (!semantics.analyze())
113 Scope::Allocate(tree);
115 BytecodeCompiler compiler(ZONE(), tree, NULL);
116 ke::Local<Module> module(ke::ZONE(), compiler.compile());
121 if (!ke::ZONE()->stack().pushModuleFrame(module, args))
123 if (!ke::Interpret(ke::ZONE(), NULL, NULL))
129 Ke::Local<Ke::Module>
130 Ke::Compile(const char *path)
132 RootScope roots(ZONE());
133 CompileContext cc(ZONE(), path);
138 FILE *fp = fopen(path, "rb");
140 cc.reportError(SourcePosition(), Message_CantOpenFile);
141 return Ke::Local<Ke::Module>();
144 if (fseek(fp, 0, SEEK_END)) {
145 cc.reportError(SourcePosition(), Message_ErrorSeekingFile);
147 return Ke::Local<Ke::Module>();;
149 long size = ftell(fp);
151 cc.reportError(SourcePosition(), Message_ErrorSeekingFile);
153 return Ke::Local<Ke::Module>();;
156 length = size_t(size);
157 bytes = new char[length + 1];
158 if (fread(bytes, 1, length, fp) != length) {
159 cc.reportError(SourcePosition(), Message_ErrorReadingFile);
162 return Ke::Local<Ke::Module>();;
167 ke::Local<ke::Module> module(ZONE(), CompileFromSource(cc, path, bytes, length));
170 return Ke::Local<Ke::Module>();
172 ke::Local<ke::String> pathstr(ZONE(), ke::String::New(ZONE(), path, Heap::Tenure_Old));
174 return Ke::Local<Ke::Module>();
176 module->setPath(pathstr);
177 return ToLocal<ke::Module, Ke::Module>(module);
181 Ke::Keima::InstallMessageReporter(Ke::IMessageReporter *reporter)
183 ZONE()->installErrorReporter(reporter);
186 class StackFrameIterator : public Ke::IStackFrameIterator
196 virtual bool done() {
200 const char *function() {
201 return iter_.function();
204 const char *source() {
205 return iter_.source();
208 unsigned lineNumber() {
209 return iter_.lineNumber();
217 Ke::IStackFrameIterator *
218 Ke::Keima::NewStackFrameIterator()
220 return new StackFrameIterator();
223 static inline ke::HeapRoot *
224 FromAPI(ke::HeapRoot *from)
226 ke::Address address = reinterpret_cast<ke::Address>(from);
227 address -= offsetof(ke::HeapRoot, obj);
228 return reinterpret_cast<ke::HeapRoot *>(address);
232 Ke::Internals::NewHeapRoot(ke::Object **ptr)
234 ke::Local<ke::Object> obj(ZONE(), *ptr);
235 ke::HeapRoot *root = ke::ZONE()->globalRoots()->create(obj);
239 // Compute an interior pointer, so it looks like a Handle to an object.
240 return reinterpret_cast<ke::HeapRoot *>(&root->obj);
244 Ke::Internals::IncRef(ke::HeapRoot *root)
246 ZONE()->globalRoots()->incref(FromAPI(root));
250 Ke::Internals::DecRef(ke::HeapRoot *root)
252 ZONE()->globalRoots()->decref(FromAPI(root));
256 Ke::Keima::IsInCallStack(Handle<Module> argModule)
258 ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(argModule));
259 return ZONE()->stack().isInCallStack(module);
263 Ke::Keima::CollectGarbage()
265 ke::ZONE()->heap().reclaim();
269 Ke::Module::numPublics()
271 ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(this));
272 if (!module->publics())
274 return module->publics()->length();
277 Ke::Local<Ke::Function>
278 Ke::Module::getPublic(unsigned index)
280 ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(this));
281 ke::Local<ke::Function> fun(ke::ZONE(), ke::Function::cast(module->publics()->at(index)));
282 return ToLocal<ke::Function, Ke::Function>(fun);
286 Ke::Module::numNatives()
288 ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(this));
289 if (!module->natives())
291 return module->natives()->length();
294 Ke::Local<Ke::Native>
295 Ke::Module::getNative(unsigned index)
297 ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(this));
298 ke::Local<ke::Native> fun(ke::ZONE(), ke::Native::cast(module->natives()->at(index)));
299 return ToLocal<ke::Native, Ke::Native>(fun);
303 Ke::Module::setNativeIdentity(void *identity)
305 ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(this));
306 module->setNativeIdentity(identity);
312 ke::Local<ke::String> obj(ke::ZONE(), Open<Ke::String, ke::String>(this));
313 return obj->length();
319 ke::Local<ke::String> obj(ke::ZONE(), Open<Ke::String, ke::String>(this));
323 Ke::Local<Ke::String>
326 ke::Local<ke::Function> fun(ke::ZONE(), Open<Ke::Function, ke::Function>(this));
327 return ToLocal<ke::String, Ke::String>(fun->name());
330 Ke::Local<Ke::String>
333 ke::Local<ke::Native> native(ke::ZONE(), Open<Ke::Native, ke::Native>(this));
334 return ToLocal<ke::String, Ke::String>(native->name());
338 Ke::Native::bind(void *function)
340 ke::Local<ke::Native> native(ke::ZONE(), Open<Ke::Native, ke::Native>(this));
341 native->bind(function);
345 CheckInvokeType(const Ke::Parameter ¶m, Type *type)
347 switch (param.type()) {
348 case Ke::Parameter::Array:
349 return type->isArray() &&
350 type->levels() == 1 &&
351 type->contained()->isPrimitive() &&
352 (type->contained()->primitive() != PrimitiveType_Char);
353 case Ke::Parameter::CharArray:
354 return type->isCharArray();
355 case Ke::Parameter::Float:
356 return type->isFloat();
357 case Ke::Parameter::FloatRef:
358 return type->isReference() && type->contained()->isFloat();
359 case Ke::Parameter::Int:
360 return type->isInt32();
361 case Ke::Parameter::IntRef:
362 return type->isReference() && type->contained()->isInt32();
369 Ke::Keima::CheckInvokeTypes(Ke::Handle<Ke::Function> argFun, const Ke::Parameter *params, unsigned nparams)
371 ke::Local<ke::Function> fun(ke::ZONE(), Open<Ke::Function, ke::Function>(argFun));
373 if (fun->nargs() != nparams)
376 for (unsigned i = 0; i < nparams; i++) {
377 if (!CheckInvokeType(params[i], fun->argType(i)))
381 // Functions can only return tagged cells, for ISPE1-compatible Invoke().
382 ke::Local<ke::Type> returnType(ke::ZONE(), fun->type()->returnType());
383 if ((!returnType->isPrimitive() && !returnType->isVoid()) || returnType->isTraceable())
390 Ke::Keima::Invoke(Handle<Function> argFun, const Parameter *params, unsigned nparams, int *retval)
392 assert(CheckInvokeTypes(argFun, params, nparams));
394 ke::Local<ke::Function> fun(ke::ZONE(), Open<Ke::Function, ke::Function>(argFun));
396 if (fun->nargs() != nparams) {
397 // :TODO: report error
403 if (!ke::ZONE()->stack().pushInvokeFrame(fun, args))
406 for (unsigned i = 0; i < nparams; i++) {
407 ke::LocalSlot &slot = args.arg(i);
408 switch (params[i].type()) {
409 case Ke::Parameter::Int:
410 slot.i32 = params[i].i32();
413 case Ke::Parameter::Float:
414 slot.f = params[i].f();
417 case Ke::Parameter::IntRef:
418 if (params[i].writeback()) {
419 slot.ref = Reference::NewStack(ke::ZONE(), params[i].i32p(), Heap::Tenure_Stack);
422 other.i32 = *params[i].i32p();
423 slot.ref = Reference::NewStack(ke::ZONE(), other, Heap::Tenure_Stack);
429 case Ke::Parameter::FloatRef:
430 if (params[i].writeback()) {
431 slot.ref = Reference::NewStack(ke::ZONE(), params[i].fp(), Heap::Tenure_Stack);
434 other.f = *params[i].fp();
435 slot.ref = Reference::NewStack(ke::ZONE(), other, Heap::Tenure_Stack);
441 case Ke::Parameter::Array:
443 ke::Local<ke::ArrayMap> map(ke::ZONE(), ke::ZONE()->genericArrayMap());
444 if (params[i].writeback()) {
445 slot.obj = Array::NewExternal(ke::ZONE(), map, params[i].length(),
446 params[i].buffer(), Heap::Tenure_Stack);
450 Array *array = Array::New(ke::ZONE(), map, params[i].length(), Heap::Tenure_Stack);
453 memcpy(array->vec(), params[i].buffer(), params[i].length() * sizeof(int));
458 case Ke::Parameter::CharArray:
460 ke::Local<ke::ArrayMap> map(ke::ZONE(), ke::ZONE()->charArrayMap());
461 if (params[i].writeback()) {
462 slot.obj = Array::NewExternal(ke::ZONE(), map, params[i].length(),
463 params[i].buffer(), Heap::Tenure_Stack);
467 Array *array = Array::New(ke::ZONE(), map, params[i].length(), Heap::Tenure_Stack);
470 memcpy(array->vec(), params[i].buffer(), params[i].length() * sizeof(char));
478 if (!Interpret(ke::ZONE(), NULL, &result))
481 if (fun->type()->returnType()->isVoid())
484 *retval = result.i32;