1.1 --- a/jitcraft/API.cpp Sun Jul 08 17:57:44 2012 -0700
1.2 +++ b/jitcraft/API.cpp Mon Jul 09 01:22:03 2012 -0700
1.3 @@ -26,6 +26,9 @@
1.4 #include "BytecodeCompiler.h"
1.5 #include "Modules.h"
1.6 #include "GlobalRoots.h"
1.7 +#include "Reference.h"
1.8 +#include "Array.h"
1.9 +#include "Interpreter.h"
1.10
1.11 using namespace ke;
1.12
1.13 @@ -203,6 +206,8 @@
1.14 Ke::Module::numPublics()
1.15 {
1.16 ke::Local<ke::Module> module(ke::ZONE(), Open<Ke::Module, ke::Module>(this));
1.17 + if (!module->publics())
1.18 + return 0;
1.19 return module->publics()->length();
1.20 }
1.21
1.22 @@ -234,3 +239,143 @@
1.23 ke::Local<ke::Function> fun(ke::ZONE(), Open<Ke::Function, ke::Function>(this));
1.24 return ToLocal<ke::String, Ke::String>(fun->name());
1.25 }
1.26 +
1.27 +static inline bool
1.28 +CheckInvokeType(const Ke::Parameter ¶m, Type *type)
1.29 +{
1.30 + switch (param.type()) {
1.31 + case Ke::Parameter::Array:
1.32 + return type->isArray() &&
1.33 + type->levels() == 1 &&
1.34 + type->contained()->isPrimitive() &&
1.35 + (type->contained()->primitive() != PrimitiveType_Char);
1.36 + case Ke::Parameter::CharArray:
1.37 + return type->isCharArray();
1.38 + case Ke::Parameter::Float:
1.39 + return type->isFloat();
1.40 + case Ke::Parameter::FloatRef:
1.41 + return type->isReference() && type->contained()->isFloat();
1.42 + case Ke::Parameter::Int:
1.43 + return type->isInt32();
1.44 + case Ke::Parameter::IntRef:
1.45 + return type->isReference() && type->contained()->isInt32();
1.46 + default:
1.47 + return false;
1.48 + }
1.49 +}
1.50 +
1.51 +bool
1.52 +Ke::Keima::CheckInvokeTypes(Ke::Handle<Ke::Function> argFun, const Ke::Parameter *params, unsigned nparams)
1.53 +{
1.54 + ke::Local<ke::Function> fun(ke::ZONE(), Open<Ke::Function, ke::Function>(argFun));
1.55 +
1.56 + if (fun->nargs() != nparams)
1.57 + return false;
1.58 +
1.59 + for (unsigned i = 0; i < nparams; i++) {
1.60 + if (!CheckInvokeType(params[i], fun->argType(i)))
1.61 + return false;
1.62 + }
1.63 +
1.64 + // Functions can only return tagged cells, for ISPE1-compatible Invoke().
1.65 + if (!fun->type()->returnType()->isPrimitive() || fun->type()->returnType()->isTraceable())
1.66 + return false;
1.67 +
1.68 + return true;
1.69 +}
1.70 +
1.71 +bool
1.72 +Ke::Keima::Invoke(Handle<Function> argFun, const Parameter *params, unsigned nparams, int *retval)
1.73 +{
1.74 + assert(CheckInvokeTypes(argFun, params, nparams));
1.75 +
1.76 + ke::Local<ke::Function> fun(ke::ZONE(), Open<Ke::Function, ke::Function>(argFun));
1.77 +
1.78 + if (fun->nargs() != nparams) {
1.79 + // :TODO: report error
1.80 + assert(false);
1.81 + return false;
1.82 + }
1.83 +
1.84 + ke::InvokeArgs args;
1.85 + if (!ke::ZONE()->stack().pushInvokeFrame(fun, args))
1.86 + return false;
1.87 +
1.88 + for (unsigned i = 0; i < nparams; i++) {
1.89 + ke::LocalSlot &slot = args.arg(i);
1.90 + switch (params[i].type()) {
1.91 + case Ke::Parameter::Int:
1.92 + slot.i32 = params[i].i32();
1.93 + break;
1.94 +
1.95 + case Ke::Parameter::Float:
1.96 + slot.f = params[i].f();
1.97 + break;
1.98 +
1.99 + case Ke::Parameter::IntRef:
1.100 + if (params[i].writeback()) {
1.101 + slot.ref = Reference::NewStack(ke::ZONE(), params[i].i32p(), Heap::Tenure_Stack);
1.102 + } else {
1.103 + LocalSlot other;
1.104 + other.i32 = *params[i].i32p();
1.105 + slot.ref = Reference::NewStack(ke::ZONE(), other, Heap::Tenure_Stack);
1.106 + }
1.107 + if (!slot.ref)
1.108 + return false;
1.109 + break;
1.110 +
1.111 + case Ke::Parameter::FloatRef:
1.112 + if (params[i].writeback()) {
1.113 + slot.ref = Reference::NewStack(ke::ZONE(), params[i].fp(), Heap::Tenure_Stack);
1.114 + } else {
1.115 + LocalSlot other;
1.116 + other.f = *params[i].fp();
1.117 + slot.ref = Reference::NewStack(ke::ZONE(), other, Heap::Tenure_Stack);
1.118 + }
1.119 + if (!slot.ref)
1.120 + return false;
1.121 + break;
1.122 +
1.123 + case Ke::Parameter::Array:
1.124 + {
1.125 + ke::Local<ke::ArrayMap> map(ke::ZONE(), ke::ZONE()->genericArrayMap());
1.126 + if (params[i].writeback()) {
1.127 + slot.obj = Array::NewExternal(ke::ZONE(), map, params[i].length(),
1.128 + params[i].buffer(), Heap::Tenure_Stack);
1.129 + if (!slot.obj)
1.130 + return false;
1.131 + } else {
1.132 + Array *array = Array::New(ke::ZONE(), map, params[i].length(), Heap::Tenure_Stack);
1.133 + if (!slot.obj)
1.134 + return false;
1.135 + memcpy(array->vec(), params[i].buffer(), params[i].length() * sizeof(int));
1.136 + }
1.137 + break;
1.138 + }
1.139 +
1.140 + case Ke::Parameter::CharArray:
1.141 + {
1.142 + ke::Local<ke::ArrayMap> map(ke::ZONE(), ke::ZONE()->charArrayMap());
1.143 + if (params[i].writeback()) {
1.144 + slot.obj = Array::NewExternal(ke::ZONE(), map, params[i].length(),
1.145 + params[i].buffer(), Heap::Tenure_Stack);
1.146 + if (!slot.obj)
1.147 + return false;
1.148 + } else {
1.149 + Array *array = Array::New(ke::ZONE(), map, params[i].length(), Heap::Tenure_Stack);
1.150 + if (!slot.obj)
1.151 + return false;
1.152 + memcpy(array->vec(), params[i].buffer(), params[i].length() * sizeof(char));
1.153 + }
1.154 + break;
1.155 + }
1.156 + }
1.157 + }
1.158 +
1.159 + LocalSlot result;
1.160 + if (!Interpret(ke::ZONE(), NULL, &result))
1.161 + return false;
1.162 +
1.163 + *retval = result.i32;
1.164 + return true;
1.165 +}