示例#1
0
文件: array.cpp 项目: mutle/rubinius
  VALUE rb_iterate(VALUE(*ifunc)(VALUE), VALUE ary, VALUE(*cb)(ANYARGS), VALUE cb_data) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    // Minor optimization.
    if(ifunc == rb_each && kind_of<Array>(env->get_object(ary))) {
      for(size_t i = 0; i < rb_ary_size(ary); i++) {
        (*cb)(rb_ary_entry(ary, i), cb_data, Qnil);
      }

      return ary;
    }

    NativeMethod* nm = NativeMethod::create(env->state(),
                        (String*)Qnil, env->state()->shared.globals.rubinius.get(),
                        env->state()->symbol("call"), (void*)cb,
                        Fixnum::from(ITERATE_BLOCK));

    nm->set_ivar(env->state(), env->state()->symbol("cb_data"),
                 env->get_object(cb_data));

    Proc* prc = Proc::create(env->state(), env->state()->shared.globals.proc.get());
    prc->bound_method(env->state(), nm);

    env->set_outgoing_block(env->get_handle(prc));

    return (*ifunc)(ary);
  }
示例#2
0
  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;
  }
	/*static*/ Atom NativeMethod::verifyEnter(MethodEnv* env, int argc, uint32 *ap)
	{
		NativeMethod* f = (NativeMethod*) env->method;

		f->verify(env->vtable->toplevel);

		#ifdef AVMPLUS_VERIFYALL
		f->flags |= VERIFIED;
		f->core()->processVerifyQueue(env->toplevel());
		#endif

		env->impl32 = f->impl32;
		return f->impl32(env, argc, ap);
	}
示例#4
0
  Object* NativeMethod::executor_implementation(STATE,
      CallFrame* call_frame, Dispatch& msg, Arguments& args) {
    NativeMethod* nm = as<NativeMethod>(msg.method);

    int arity = nm->arity()->to_int();
    if(arity >= 0 && (size_t)arity != args.total()) {
      Exception* exc = Exception::make_argument_error(
          state, arity, args.total(), msg.name);
      exc->locations(state, System::vm_backtrace(state, Fixnum::from(1), call_frame));
      state->thread_state()->raise_exception(exc);

      return NULL;
    }

    NativeMethodEnvironment* env = native_method_environment.get();
    NativeMethodFrame nmf(env->current_native_frame());

    CallFrame* saved_frame = env->current_call_frame();
    Object* saved_block = env->block();
    env->set_current_call_frame(call_frame);
    env->set_current_native_frame(&nmf);
    env->set_current_block(args.block());

    Object* ret;
    ExceptionPoint ep(env);

    PLACE_EXCEPTION_POINT(ep);

    if(unlikely(ep.jumped_to())) {
      ret = NULL;
    } else {
#ifdef RBX_PROFILER
      if(unlikely(state->shared.profiling())) {
        profiler::MethodEntry method(state, msg, args);
        ret = nm->call(state, env, args);
      } else {
        ret = nm->call(state, env, args);
      }
#else
      ret = nm->call(state, env, args);
#endif
    }

    env->set_current_block(saved_block);
    env->set_current_call_frame(saved_frame);
    env->set_current_native_frame(nmf.previous());
    ep.pop(env);

    return ret;
  }
示例#5
0
    Proc* wrap_c_function(void* cb, VALUE cb_data, int arity) {
      NativeMethodEnvironment* env = NativeMethodEnvironment::get();
      NativeMethod* nm = NativeMethod::create(env->state(),
                          (String*)Qnil, env->state()->shared.globals.rubinius.get(),
                          env->state()->symbol("call"), cb,
                          Fixnum::from(arity));

      nm->set_ivar(env->state(), env->state()->symbol("cb_data"),
                   env->get_object(cb_data));

      Proc* prc = Proc::create(env->state(), env->state()->shared.globals.proc.get());
      prc->bound_method(env->state(), nm);

      return prc;
    }
示例#6
0
  Location* Location::create(STATE, NativeMethodFrame* nmf) {
    NativeMethod* nm = try_as<NativeMethod>(nmf->get_object(nmf->method()));
    if(!nm) return 0;

    Location* loc = state->new_object<Location>(G(location));
    if(Module* mod = try_as<Module>(nmf->get_object(nmf->module()))) {
      loc->method_module(state, mod);
    }

    loc->receiver(state, nmf->get_object(nmf->receiver()));

    loc->method(state, nm);
    loc->ip(state, Fixnum::from(-1));
    loc->flags(state, Fixnum::from(2));

    loc->name(state, nm->name());
    return loc;
  }
示例#7
0
文件: capi.cpp 项目: cutorad/rubinius
    Proc* wrap_c_function(void* cb, VALUE cb_data, int arity) {
      NativeMethodEnvironment* env = NativeMethodEnvironment::get();
      NativeMethod* nm = NativeMethod::create(env->state(),
                          nil<String>(), env->state()->vm()->shared.globals.rubinius.get(),
                          env->state()->symbol("call"), cb,
                          Fixnum::from(arity), 0);

      nm->set_ivar(env->state(), env->state()->symbol("cb_data"),
                   env->get_object(cb_data));

      Object* current_block = env->block();
      if(!current_block->nil_p()) {
        nm->set_ivar(env->state(), env->state()->symbol("original_block"),
                     current_block);
      }

      Proc* prc = Proc::create(env->state(), env->state()->vm()->shared.globals.proc.get());
      prc->bound_method(env->state(), nm);

      return prc;
    }
示例#8
0
      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;
      }
示例#9
0
  NativeMethod* NativeMethod::create(VM* 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));

    return nmethod;
  }
示例#10
0
  Object* NativeMethod::executor_implementation(STATE,
      CallFrame* call_frame, Dispatch& msg, Arguments& args) {
    NativeMethod* nm = as<NativeMethod>(msg.method);

    int arity = nm->arity()->to_int();

    if(arity >= 0 && (size_t)arity != args.total()) {
      Exception* exc = Exception::make_argument_error(
          state, arity, args.total(), msg.name);
      exc->locations(state, Location::from_call_stack(state, call_frame));
      state->thread_state()->raise_exception(exc);

      return NULL;
    }

    NativeMethodEnvironment* env = native_method_environment.get();

    // Optionally get the handles back to the proper state.
    if(state->shared.config.capi_global_flush) {
      capi::Handles* handles = state->shared.cached_handles();

      if(handles->size() > 0) {
        for(capi::Handles::Iterator i(*handles); i.more(); i.advance()) {
          i->update(env);
        }
      }
    }

    // Register the CallFrame, because we might GC below this.
    state->set_call_frame(call_frame);

    NativeMethodFrame nmf(env->current_native_frame());

    CallFrame* saved_frame = env->current_call_frame();
    env->set_current_call_frame(call_frame);
    env->set_current_native_frame(&nmf);

    // Be sure to do this after installing nmf as the current
    // native frame.
    nmf.setup(
        env->get_handle(args.recv()),
        env->get_handle(args.block()),
        env->get_handle(msg.method),
        env->get_handle(msg.module));

    Object* ret;
    ExceptionPoint ep(env);

    PLACE_EXCEPTION_POINT(ep);

    if(unlikely(ep.jumped_to())) {
      ret = NULL;
    } else {
#ifdef RBX_PROFILER
      if(unlikely(state->tooling())) {
        tooling::MethodEntry method(state, msg, args);
        ret = ArgumentHandler::invoke(state, nm, env, args);
      } else {
        ret = ArgumentHandler::invoke(state, nm, env, args);
      }
#else
      ret = ArgumentHandler::invoke(state, nm, env, args);
#endif
    }

    env->set_current_call_frame(saved_frame);
    env->set_current_native_frame(nmf.previous());
    ep.pop(env);

    // Handle any signals that occurred while the native method
    // was running.
    if(!state->check_async(call_frame)) return NULL;

    return ret;
  }
示例#11
0
  void SignalThread::print_backtraces() {
    STATE = shared_.env()->state;
    ThreadList* threads = shared_.thread_nexus()->threads();

    for(ThreadList::iterator i = threads->begin(); i != threads->end(); ++i) {
      VM* vm = (*i)->as_vm();
      if(!vm) continue;

      bool first = true;
      CallFrame* frame = vm->call_frame();

      while(frame) {
        if(first) {
          logger::fatal("--- %s %d backtrace ---", vm->kind_name(), vm->thread_id());
          first = false;
        }

        std::ostringstream stream;

        if(NativeMethodFrame* nmf = frame->native_method_frame()) {
          stream << static_cast<void*>(frame) << ": ";
          NativeMethod* nm = try_as<NativeMethod>(nmf->get_object(nmf->method()));
          if(nm && nm->name()->symbol_p()) {
            stream << "capi:" << nm->name()->debug_str(state) << " at ";
            stream << nm->file()->c_str(state);
          } else {
            stream << "unknown capi";
          }
        } else if(frame->compiled_code) {
          if(frame->is_block_p(state)) {
            stream << "__block__";
          } else {
            if(SingletonClass* sc = try_as<SingletonClass>(frame->module())) {
              Object* obj = sc->singleton();

              if(Module* mod = try_as<Module>(obj)) {
                stream << mod->debug_str(state) << ".";
              } else {
                if(obj == G(main)) {
                  stream << "MAIN.";
                } else {
                  stream << "#<" << obj->class_object(state)->debug_str(state) <<
                            ":" << (void*)obj->id(state)->to_native() << ">.";
                }
              }
            } else if(IncludedModule* im = try_as<IncludedModule>(frame->module())) {
              stream <<  im->module()->debug_str(state) << "#";
            } else {
              Symbol* name;
              std::string mod_name;

              if(frame->module()->nil_p()) {
                mod_name = frame->lexical_scope()->module()->debug_str(state);
              } else {
                if((name = try_as<Symbol>(frame->module()->module_name()))) {
                  mod_name = name->debug_str(state);
                } else if((name = try_as<Symbol>(
                          frame->lexical_scope()->module()->module_name()))) {
                  mod_name = name->debug_str(state);
                } else {
                  mod_name = "<anonymous module>";
                }
              }
              stream << mod_name << "#";
            }

            Symbol* name = try_as<Symbol>(frame->name());
            if(name) {
              stream << name->debug_str(state);
            } else {
              stream << frame->compiled_code->name()->debug_str(state);
            }
          }

          stream << " in ";
          if(Symbol* file_sym = try_as<Symbol>(frame->compiled_code->file())) {
            stream << file_sym->debug_str(state) << ":" << frame->line(state);
          } else {
            stream << "<unknown>";
          }

          stream << " (+" << frame->ip();
          if(frame->is_inline_frame()) {
            stream << " inline";
          } else if(frame->jitted_p()) {
            stream << " jit";
          }
          stream << ")";
        }

        logger::fatal(stream.str().c_str());

        frame = frame->previous;
      }
    }
  }
示例#12
0
  void CallFrame::print_backtrace(STATE, std::ostream& stream, int total, bool filter) {
    CallFrame* cf = this;

    int i = -1;

    while(cf) {
      i++;

      if(total > 0 && i == total) return;

      if(NativeMethodFrame* nmf = cf->native_method_frame()) {
        stream << static_cast<void*>(cf) << ": ";
        NativeMethod* nm = try_as<NativeMethod>(nmf->get_object(nmf->method()));
        if(nm && nm->name()->symbol_p()) {
          stream << "capi:" << nm->name()->debug_str(state) << " at ";
          stream << nm->file()->c_str(state);
        } else {
          stream << "unknown capi";
        }

        stream << std::endl;
        cf = cf->previous;
        continue;
      }

      if(!cf->compiled_code) {
        cf = cf->previous;
        continue;
      }

      if(filter && cf->compiled_code->kernel_method(state)) {
        cf = cf->previous;
        continue;
      }

      stream << static_cast<void*>(cf) << ": ";

      if(cf->is_block_p(state)) {
        stream << "__block__";
      } else {
        if(SingletonClass* sc = try_as<SingletonClass>(cf->module())) {
          Object* obj = sc->attached_instance();

          if(Module* mod = try_as<Module>(obj)) {
            stream << mod->debug_str(state) << ".";
          } else {
            if(obj == G(main)) {
              stream << "MAIN.";
            } else {
              stream << "#<" << obj->class_object(state)->debug_str(state) <<
                        ":" << (void*)obj->id(state)->to_native() << ">.";
            }
          }
        } else if(IncludedModule* im = try_as<IncludedModule>(cf->module())) {
          stream <<  im->module()->debug_str(state) << "#";
        } else {
          Symbol* name;
          std::string mod_name;

          if(cf->module()->nil_p()) {
            mod_name = cf->constant_scope()->module()->debug_str(state);
          } else {
            if((name = try_as<Symbol>(cf->module()->module_name()))) {
              mod_name = name->debug_str(state);
            } else if((name = try_as<Symbol>(
                      cf->constant_scope()->module()->module_name()))) {
              mod_name = name->debug_str(state);
            } else {
              mod_name = "<anonymous module>";
            }
          }
          stream << mod_name << "#";
        }

        Symbol* name = try_as<Symbol>(cf->name());
        if(name) {
          stream << name->debug_str(state);
        } else {
          stream << cf->compiled_code->name()->debug_str(state);
        }
      }

      stream << " in ";
      if(Symbol* file_sym = try_as<Symbol>(cf->compiled_code->file())) {
        stream << file_sym->debug_str(state) << ":" << cf->line(state);
      } else {
        stream << "<unknown>";
      }

      stream << " (+" << cf->ip();
      if(cf->is_inline_frame()) {
        stream << " inline";
      } else if(cf->jitted_p()) {
        stream << " jit";
      }
      stream << ")";

      stream << std::endl;
      cf = cf->previous;
    }

  }
示例#13
0
  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;
  }
示例#14
0
  Object* NativeMethod::executor_implementation(STATE,
      CallFrame* call_frame, Executable* exec, Module* mod, Arguments& args) {
    NativeMethod* nm = as<NativeMethod>(exec);

    int arity = nm->arity()->to_int();

    if(arity >= 0 && (size_t)arity != args.total()) {
      Exception* exc = Exception::make_argument_error(
          state, arity, args.total(), args.name());
      exc->locations(state, Location::from_call_stack(state, call_frame));
      state->raise_exception(exc);

      return NULL;
    }

    NativeMethodEnvironment* env = native_method_environment.get();

    // Optionally get the handles back to the proper state.
    if(state->shared().config.capi_global_flush) {
      capi::Handles* handles = state->shared().cached_handles();

      if(handles->size() > 0) {
        for(capi::Handles::Iterator i(*handles); i.more(); i.advance()) {
          i->update(env);
        }
      }
    }

    // Register the CallFrame, because we might GC below this.
    state->set_call_frame(call_frame);

    NativeMethodFrame nmf(env->current_native_frame());
    CallFrame cf;
    cf.previous = call_frame;
    cf.cm = 0;
    cf.scope = 0;
    cf.dispatch_data = (void*)&nmf;
    cf.flags = CallFrame::cNativeMethod;

    CallFrame* saved_frame = env->current_call_frame();
    env->set_current_call_frame(&cf);
    env->set_current_native_frame(&nmf);

    // Be sure to do this after installing nmf as the current
    // native frame.
    nmf.setup(
        env->get_handle(args.recv()),
        env->get_handle(args.block()),
        env->get_handle(exec),
        env->get_handle(mod));

    // We've got things setup (they can be GC'd properly), so we need to
    // wait before entering the extension code.
    ENTER_CAPI(state);

    Object* ret;
    ExceptionPoint ep(env);

    PLACE_EXCEPTION_POINT(ep);

    if(unlikely(ep.jumped_to())) {
      ret = NULL;
    } else {
#ifdef RBX_PROFILER
      if(unlikely(state->vm()->tooling())) {
        tooling::MethodEntry method(state, exec, mod, args);
        ret = ArgumentHandler::invoke(state, nm, env, args);
      } else {
        ret = ArgumentHandler::invoke(state, nm, env, args);
      }
#else
      ret = ArgumentHandler::invoke(state, nm, env, args);
#endif
    }

    env->set_current_call_frame(saved_frame);
    env->set_current_native_frame(nmf.previous());
    ep.pop(env);

    LEAVE_CAPI(state);

    // Handle any signals that occurred while the native method
    // was running.
    if(!state->check_async(call_frame)) return NULL;

    return ret;
  }
示例#15
0
  Object* NativeMethod::executor_implementation(STATE,
      CallFrame* previous, Executable* exec, Module* mod, Arguments& args) {
    NativeMethod* nm = as<NativeMethod>(exec);

    int arity = nm->arity()->to_int();

    if(arity >= 0 && (size_t)arity != args.total()) {
      Exception* exc = Exception::make_argument_error(
          state, arity, args.total(), args.name());
      exc->locations(state, Location::from_call_stack(state, previous));
      state->raise_exception(exc);

      return NULL;
    }

    NativeMethodEnvironment* env = native_method_environment.get();

    // Optionally get the handles back to the proper state.
    if(state->shared().config.capi_global_flush) {
      std::list<capi::Handle*>* handles = env->state()->memory()->cached_capi_handles();

      for(std::list<capi::Handle*>::iterator i = handles->begin();
          i != handles->end();
          ++i) {
        (*i)->update(env);
      }
    }


    NativeMethodFrame nmf(env->current_native_frame());
    CallFrame* call_frame = ALLOCA_CALLFRAME(0);
    call_frame->previous = previous;
    call_frame->constant_scope_ = 0;
    call_frame->dispatch_data = (void*)&nmf;
    call_frame->compiled_code = 0;
    call_frame->flags = CallFrame::cNativeMethod;
    call_frame->optional_jit_data = 0;
    call_frame->top_scope_ = 0;
    call_frame->scope = 0;
    call_frame->arguments = &args;

    CallFrame* saved_frame = env->current_call_frame();
    env->set_current_call_frame(call_frame);
    env->set_current_native_frame(&nmf);

    // Register the CallFrame, because we might GC below this.
    state->set_call_frame(call_frame);

    // Be sure to do this after installing nmf as the current
    // native frame.
    nmf.setup(
        env->get_handle(args.recv()),
        env->get_handle(args.block()),
        env->get_handle(exec),
        env->get_handle(mod));

    // We've got things setup (they can be GC'd properly), so we need to
    // wait before entering the extension code.
    ENTER_CAPI(state);

    Object* ret;
    ExceptionPoint ep(env);

#ifdef RBX_PROFILER
    // This is organized like this so that we don't jump past the destructor of
    // MethodEntry. It's duplicated, but it's much easier to understand than
    // trying to de-dup it.

    OnStack<2> os(state, exec, mod);
    if(unlikely(state->vm()->tooling())) {
      tooling::MethodEntry method(state, exec, mod, args);
      RUBINIUS_METHOD_NATIVE_ENTRY_HOOK(state, mod, args.name(), call_frame);

      PLACE_EXCEPTION_POINT(ep);

      if(unlikely(ep.jumped_to())) {
        ret = NULL;
      } else {
        ret = ArgumentHandler::invoke(state, nm, env, args);
      }
      RUBINIUS_METHOD_NATIVE_RETURN_HOOK(state, mod, args.name(), call_frame);
    } else {
      RUBINIUS_METHOD_NATIVE_ENTRY_HOOK(state, mod, args.name(), call_frame);

      PLACE_EXCEPTION_POINT(ep);

      if(unlikely(ep.jumped_to())) {
        ret = NULL;
      } else {
        ret = ArgumentHandler::invoke(state, nm, env, args);
      }
      RUBINIUS_METHOD_NATIVE_RETURN_HOOK(state, mod, args.name(), call_frame);
    }
#else
    RUBINIUS_METHOD_NATIVE_ENTRY_HOOK(state, mod, args.name(), call_frame);

    PLACE_EXCEPTION_POINT(ep);

    if(unlikely(ep.jumped_to())) {
      ret = NULL;
    } else {
      ret = ArgumentHandler::invoke(state, nm, env, args);
    }
    RUBINIUS_METHOD_NATIVE_RETURN_HOOK(state, mod, args.name(), call_frame);
#endif

    env->set_current_call_frame(saved_frame);
    env->set_current_native_frame(nmf.previous());
    ep.pop(env);

    LEAVE_CAPI(state);
    OnStack<1> os_ret(state, ret);

    // Handle any signals that occurred while the native method
    // was running.
    if(!state->check_async(call_frame)) return NULL;

    return ret;
  }