Object* run_function(STATE) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); Thread* thread = state->vm()->thread(); NativeMethod* nm = capi::c_as<NativeMethod>( thread->variable_get(state, state->symbol("function"))); Pointer* ptr = capi::c_as<Pointer>( thread->variable_get(state, state->symbol("argument"))); NativeMethodFrame nmf(env, 0, nm); CallFrame call_frame; call_frame.previous = NULL; call_frame.lexical_scope_ = 0; call_frame.dispatch_data = (void*)&nmf; call_frame.compiled_code = 0; call_frame.flags = CallFrame::cNativeMethod; call_frame.top_scope_ = 0; call_frame.scope = 0; call_frame.arguments = 0; env->set_current_call_frame(&call_frame); env->set_current_native_frame(&nmf); state->vm()->set_call_frame(&call_frame); nmf.setup( env->get_handle(thread), env->get_handle(cNil), env->get_handle(nm), env->get_handle(nm->module())); ENTER_CAPI(state); Object* value = NULL; ExceptionPoint ep(env); PLACE_EXCEPTION_POINT(ep); if(unlikely(ep.jumped_to())) { LEAVE_CAPI(state); // Set exception in thread so it's raised when joining. state->vm()->thread()->exception(state, capi::c_as<Exception>(state->vm()->thread_state()->current_exception())); } else { value = env->get_object(nm->func()(ptr->pointer)); } LEAVE_CAPI(state); env->set_current_call_frame(NULL); env->set_current_native_frame(NULL); ep.pop(env); return value; }
NativeMethod* NativeMethod::create(State* state, String* file_name, Module* module, Symbol* method_name, void* func, Fixnum* arity) { NativeMethod* nmethod = state->new_object<NativeMethod>(G(nmethod)); nmethod->arity(state, arity); nmethod->file(state, file_name); nmethod->name(state, method_name); nmethod->module(state, module); nmethod->func_ = func; switch(arity->to_native()) { case 0: nmethod->set_executor(&NativeMethod::executor_implementation<ZeroArguments>); break; case 1: nmethod->set_executor(&NativeMethod::executor_implementation<OneArgument>); break; case 2: nmethod->set_executor(&NativeMethod::executor_implementation<TwoArguments>); break; case 3: nmethod->set_executor(&NativeMethod::executor_implementation<ThreeArguments>); break; default: nmethod->set_executor(&NativeMethod::executor_implementation<GenericArguments>); break; } nmethod->primitive(state, state->symbol("nativemethod_call")); nmethod->serial(state, Fixnum::from(0)); nmethod->inliners_ = 0; return nmethod; }
static NativeMethod* create(VM* state, String* file_name = as<String>(Qnil), Module* module = as<Module>(Qnil), Symbol* method_name = as<Symbol>(Qnil), FunctorType functor = static_cast<GenericFunctor>(NULL), Fixnum* arity = as<Fixnum>(Qnil)) { NativeMethod* nmethod = state->new_object<NativeMethod>(G(nmethod)); nmethod->arity(state, arity); nmethod->file_name(state, file_name); nmethod->method_name(state, method_name); nmethod->module(state, module); nmethod->functor(state, MemoryPointer::create(state, reinterpret_cast<void*>(functor))); nmethod->set_executor(&NativeMethod::executor_implementation); nmethod->primitive(state, state->symbol("nativemethod_call")); nmethod->serial(state, Fixnum::from(0)); return nmethod; }
Object* run_function(STATE) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); Thread* self = state->vm()->thread.get(); NativeMethod* nm = capi::c_as<NativeMethod>(self->locals_aref(state, state->symbol("function"))); Pointer* ptr = capi::c_as<Pointer>(self->locals_aref(state, state->symbol("argument"))); self->locals_remove(state, state->symbol("function")); self->locals_remove(state, state->symbol("argument")); GCTokenImpl gct; NativeMethodFrame nmf(env, 0, nm); CallFrame cf; cf.previous = 0; cf.constant_scope_ = 0; cf.dispatch_data = (void*)&nmf; cf.compiled_code = 0; cf.flags = CallFrame::cNativeMethod; cf.optional_jit_data = 0; cf.top_scope_ = 0; cf.scope = 0; cf.arguments = 0; CallFrame* saved_frame = env->current_call_frame(); env->set_current_call_frame(&cf); env->set_current_native_frame(&nmf); nmf.setup( env->get_handle(self), env->get_handle(cNil), env->get_handle(nm), env->get_handle(nm->module())); { OnStack<3> os(state, self, nm, ptr); self->hard_unlock(state, gct, &cf); } ENTER_CAPI(state); Object* ret = NULL; ExceptionPoint ep(env); PLACE_EXCEPTION_POINT(ep); if(unlikely(ep.jumped_to())) { // Setup exception in thread so it's raised when joining // Reload self because it might have been moved self = state->vm()->thread.get(); CallFrame* call_frame = env->current_call_frame(); { OnStack<1> os(state, self); self->hard_lock(state, gct, call_frame, false); Exception* exc = capi::c_as<Exception>(self->current_exception(state)); self->exception(state, exc); self->alive(state, cFalse); self->hard_unlock(state, gct, call_frame); } return NULL; } else { ret = env->get_object(nm->func()(ptr->pointer)); } LEAVE_CAPI(state); env->set_current_call_frame(saved_frame); env->set_current_native_frame(nmf.previous()); ep.pop(env); self = state->vm()->thread.get(); OnStack<1> os(state, self); self->hard_lock(state, gct, &cf, false); self->alive(state, cFalse); self->hard_unlock(state, gct, &cf); return ret; }