Implement |const| keyword.
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 "compiler/CompileContext.h"
25 #include "GlobalRoots.h"
26 #include "Reference.h"
28 #include "Interpreter.h"
31 #include "NativeTable.h"
32 #include "Spaces-inl.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 InternalCompile(const char *path)
97 PoolScope poolScope(ZONE()->pool());
98 RootScope roots(ZONE());
99 CompileContext cc(ZONE(), path);
101 TranslationUnit *unit = new (ZONE()->pool()) TranslationUnit();
104 if (!cc.addTranslationUnit(unit))
113 // This is split out from InternalCompile so the RootScope doesn't conflict
114 // with making a return handle.
116 Ke::Compile(const char *path)
118 return InternalCompile(path);
122 Ke::Keima::InstallMessageReporter(Ke::IMessageReporter *reporter)
124 ZONE()->installErrorReporter(reporter);
127 class StackFrameIterator : public Ke::IStackFrameIterator
137 virtual bool done() {
141 const char *function() {
142 return iter_.function();
145 const char *source() {
146 return iter_.source();
149 unsigned lineNumber() {
150 return iter_.lineNumber();
158 Ke::IStackFrameIterator *
159 Ke::Keima::NewStackFrameIterator()
161 return new StackFrameIterator();
164 static inline ke::HeapRoot *
165 FromAPI(ke::HeapRoot *from)
167 ke::Address address = reinterpret_cast<ke::Address>(from);
168 address -= offsetof(ke::HeapRoot, obj);
169 return reinterpret_cast<ke::HeapRoot *>(address);
173 Ke::Internals::NewHeapRoot()
175 ke::HeapRoot *root = ke::ZONE()->globalRoots()->create();
179 // Compute an interior pointer, so it looks like a Handle to an object.
180 return reinterpret_cast<ke::HeapRoot *>(&root->obj);
184 Ke::Internals::Destroy(ke::HeapRoot *root)
186 ZONE()->globalRoots()->destroy(FromAPI(root));
190 Ke::Keima::IsInCallStack(Handle<Module> argModule)
192 ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(argModule));
193 return ZONE()->stack().isInCallStack(module);
197 Ke::Keima::CollectGarbage()
199 ke::ZONE()->heap().reclaim();
203 Ke::Keima::ClearPendingException()
205 ke::ZONE()->clearPendingException();
209 Ke::Module::setNativeIdentity(void *identity)
211 ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(this));
212 module->setNativeIdentity(identity);
218 ke::Local<ke::String> obj(ke::ZONE(), Open<Ke::String, ke::String>(this));
219 return obj->length();
225 ke::Local<ke::String> obj(ke::ZONE(), Open<Ke::String, ke::String>(this));
229 Ke::Local<Ke::String>
232 ke::Local<ke::Function> fun(ke::ZONE(), Open<Ke::Function, ke::Function>(this));
233 return ToLocal<ke::String, Ke::String>(fun->name());
236 static inline const char *
237 GetInvokeTypeName(Ke::Parameter::Type type)
240 case Ke::Parameter::Array:
242 case Ke::Parameter::CharArray:
244 case Ke::Parameter::Float:
246 case Ke::Parameter::FloatRef:
248 case Ke::Parameter::Int:
250 case Ke::Parameter::IntRef:
258 CheckInvokeType(const Ke::Parameter ¶m, Type *type)
260 switch (param.type()) {
261 case Ke::Parameter::Array:
263 if (!type->isArray())
266 ArrayType *atype = ArrayType::cast(type);
267 return atype->levels() == 1 &&
268 (atype->contained()->isPrimitive() || atype->contained()->isEnum()) &&
269 (atype->contained()->primitive() != PrimitiveType_Char);
271 case Ke::Parameter::CharArray:
272 return type->isArray() && ArrayType::cast(type)->isCharArray();
273 case Ke::Parameter::Float:
274 return type->isFloat();
275 case Ke::Parameter::FloatRef:
276 return type->isReference() && ReferenceType::cast(type)->contained()->isFloat();
277 case Ke::Parameter::Int:
278 return type->isInt32() || type->isEnum();
279 case Ke::Parameter::IntRef:
280 return type->isReference() &&
281 (ReferenceType::cast(type)->contained()->isInt32() ||
282 ReferenceType::cast(type)->contained()->isEnum());
289 CheckInvokeTypes(Ke::Handle<Ke::Function> argFun, const Ke::Parameter *params, unsigned nparams)
291 ke::Local<ke::Function> fun(ke::ZONE(), Open<Ke::Function, ke::Function>(argFun));
293 if (fun->nargs() != nparams)
296 for (unsigned i = 0; i < nparams; i++) {
297 if (!CheckInvokeType(params[i], fun->argType(i))) {
299 ke::ZONE()->reportError(Message_TypeMismatchDuringInvoke,
300 GetInvokeTypeName(params[i].type()),
301 GetTypeName(fun->argType(i), name, sizeof(name)));
306 // Functions can only return tagged cells, for ISPE1-compatible Invoke().
307 ke::Local<ke::Type> returnType(ke::ZONE(), fun->type()->returnType());
308 if (!returnType->isPrimitive() &&
309 !returnType->isEnum() &&
310 !returnType->isVoid())
313 ke::ZONE()->reportError(Message_CannotInvokeReturnType,
314 GetTypeName(returnType, name, sizeof(name)));
322 Ke::Keima::Invoke(Handle<Function> argFun, const Parameter *params, unsigned nparams,
323 bool checkTypes, int *retval)
325 assert(CheckInvokeTypes(argFun, params, nparams));
327 ke::Local<ke::Function> fun(ke::ZONE(), Open<Ke::Function, ke::Function>(argFun));
329 if (fun->nargs() != nparams) {
330 // :TODO: report error
336 if (!ke::ZONE()->stack().pushInvokeFrame(fun, args))
339 if (checkTypes && !CheckInvokeTypes(argFun, params, nparams))
342 for (unsigned i = 0; i < nparams; i++) {
343 ke::LocalSlot &slot = args.arg(i);
344 switch (params[i].type()) {
345 case Ke::Parameter::Int:
346 slot.i32 = params[i].i32();
349 case Ke::Parameter::Float:
350 slot.f = params[i].f();
353 case Ke::Parameter::IntRef:
354 if (params[i].writeback()) {
355 slot.ref = Reference::NewStack(ke::ZONE(), params[i].i32p(), Heap::Tenure_Stack);
358 other.i32 = *params[i].i32p();
359 slot.ref = Reference::NewStack(ke::ZONE(), other, Heap::Tenure_Stack);
365 case Ke::Parameter::FloatRef:
366 if (params[i].writeback()) {
367 slot.ref = Reference::NewStack(ke::ZONE(), params[i].fp(), Heap::Tenure_Stack);
370 other.f = *params[i].fp();
371 slot.ref = Reference::NewStack(ke::ZONE(), other, Heap::Tenure_Stack);
377 case Ke::Parameter::Array:
379 ke::Local<ke::ArrayMap> map(ke::ZONE(), ke::ZONE()->externalGenericArrayMap());
380 if (params[i].writeback()) {
381 slot.obj = Array::NewExternal(ke::ZONE(), map, params[i].buffer(),
382 params[i].length(), Heap::Tenure_Stack);
386 Array *array = Array::New1D(ke::ZONE(), map, params[i].length(), Heap::Tenure_Stack);
389 if (params[i].length())
390 memcpy(array->bytes(), params[i].buffer(), params[i].length() * sizeof(int));
395 case Ke::Parameter::CharArray:
397 ke::Local<ke::ArrayMap> map(ke::ZONE(), ke::ZONE()->externalCharArrayMap());
398 if (params[i].writeback()) {
399 slot.obj = Array::NewExternal(ke::ZONE(), map, params[i].buffer(),
400 params[i].length(), Heap::Tenure_Stack);
404 Array *array = Array::New1D(ke::ZONE(), map, params[i].length(), Heap::Tenure_Stack);
407 if (params[i].length())
408 memcpy(array->bytes(), params[i].buffer(), params[i].length() * sizeof(char));
416 if (!Interpret(ke::ZONE(), NULL, &result))
419 if (fun->type()->returnType()->isVoid())
422 *retval = result.i32;
427 Ke::Keima::BindNative(const char *name, void *address)
429 return ke::ZONE()->nativeTable()->bind(name, address);
433 Ke::Keima::SetPublicFunctionListener(IPublicFunctionListener *listener)
435 ke::ZONE()->setPublicFunctionListener(listener);
439 Zone::registerPublic(ke::Handle<Function> fun)
441 if (!publicFunctionListener_)
444 Ke::Local<Ke::Function> local = ToLocal<ke::Function, Ke::Function>(fun);
445 publicFunctionListener_->registerPublic(local);