コード例 #1
0
ファイル: thread.cpp プロジェクト: Locke23rus/rubinius
  VALUE capi_thread_create(VALUE (*func)(ANYARGS), void* arg, const char* name, const char* file) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();
    State* state = env->state();

    NativeMethod* nm = NativeMethod::create(state,
                        String::create(state, file), G(thread),
                        state->symbol(name), (void*)func,
                        Fixnum::from(1), 0);

    Pointer* ptr = Pointer::create(state, arg);

    Thread* thr = Thread::create(env->state(), G(thread), run_function);

    thr->locals_store(state, state->symbol("function"), nm);
    thr->locals_store(state, state->symbol("argument"), ptr);

    VALUE thr_handle = env->get_handle(thr);
    thr->fork(state);
    GCTokenImpl gct;
    // We do a lock and unlock here so we wait until the started
    // thread is actually ready. This is to prevent we GC stuff on
    // the stack in the C-API caller that might be stuffed in the void* argument
    thr->hard_lock(state, gct, env->current_call_frame());
    thr->hard_unlock(state, gct, env->current_call_frame());

    return thr_handle;
  }
コード例 #2
0
ファイル: thread.cpp プロジェクト: atoulme/rubinius
  int rb_thread_select(int max, fd_set* read, fd_set* write, fd_set* except,
                       struct timeval *timeval) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();
    int ret = 0;

    {
      GlobalLock::UnlockGuard guard(env);
      ret = select(max, read, write, except, timeval);
    }

    // Ok, now check if there were async events that happened while
    // we were waiting on select...

    if(!env->state()->check_async(env->current_call_frame())) {
      // Ok, there was an exception raised by an async event. We need
      // to unwind through the caller back the entrance to the native
      // method.

      // Only handle true exceptions being raised, eat all other requests
      // for now.

      if(env->state()->thread_state()->raise_reason() == cException) {
        capi::capi_raise_backend(env->state()->thread_state()->current_exception());
      } else {
        env->state()->thread_state()->clear();
      }
    }

    return ret;
  }
コード例 #3
0
ファイル: capi.cpp プロジェクト: cutorad/rubinius
  VALUE rb_apply(VALUE recv, ID mid, VALUE args) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();
    env->flush_cached_data();

    Array* ary = capi::c_as<Array>(env->get_object(args));

    Object* obj = env->get_object(recv);

    // Unlock, we're leaving extension code.
    LEAVE_CAPI(env->state());

    Object* ret = obj->send(env->state(), env->current_call_frame(),
        reinterpret_cast<Symbol*>(mid), ary, cNil);

    // We need to get the handle for the return value before getting
    // the GEL so that ret isn't accidentally GCd while we wait.
    VALUE ret_handle = 0;
    if(ret) ret_handle = env->get_handle(ret);

    // Re-entering extension code
    ENTER_CAPI(env->state());

    env->update_cached_data();

    // An exception occurred
    if(!ret) env->current_ep()->return_to(env);

    return ret_handle;
  }
コード例 #4
0
ファイル: module.cpp プロジェクト: BRIMIL01/rubinius
  ID rb_frame_last_func() {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    CallFrame* rcf = env->current_call_frame()->previous->top_ruby_frame();

    return env->get_handle(rcf->name());
  }
コード例 #5
0
ファイル: capi.cpp プロジェクト: MarkusQ/rubinius
    /**
     *  Common implementation for rb_funcall*
     */
    VALUE capi_funcall_backend(const char* file, int line,
                               VALUE receiver, ID method_name,
                               size_t arg_count, VALUE* arg_array)
    {
      NativeMethodEnvironment* env = NativeMethodEnvironment::get();
      env->flush_cached_data();

      Array* args = Array::create(env->state(), arg_count);
      for(size_t i = 0; i < arg_count; i++) {
        args->set(env->state(), i, env->get_object(arg_array[i]));
      }

      Object* blk = RBX_Qnil;

      if(VALUE blk_handle = env->outgoing_block()) {
        blk = env->get_object(blk_handle);
        env->set_outgoing_block(0);
      }

      Object* recv = env->get_object(receiver);
      Object* ret = recv->send(env->state(), env->current_call_frame(),
          reinterpret_cast<Symbol*>(method_name), args, blk);
      env->update_cached_data();

      // An exception occurred
      if(!ret) env->current_ep()->return_to(env);

      return env->get_handle(ret);
    }
コード例 #6
0
ファイル: thread.cpp プロジェクト: monkeylibre/rubinius
  int rb_thread_select(int max, fd_set* read, fd_set* write, fd_set* except,
                       struct timeval *input_tv)
  {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();
    int ret = 0;

    struct timeval tv;
    struct timeval absolute_tv;
    struct timeval* tvp = NULL;

    if(input_tv) {
      // We make a new timeval rather than using input_tv because we modify it.
      tv = *input_tv;
      tvp = &tv;

      gettimeofday(&absolute_tv, NULL);

      timeradd(&absolute_tv, &tv, &absolute_tv);
    }

    for(;;) {
      env->state()->shared().leave_capi(env->state());
      {
        GCIndependent guard(env);
        ret = select(max, read, write, except, tvp);
      }

      bool ok = env->state()->check_async(env->current_call_frame());

      env->state()->shared().enter_capi(env->state());

      if(!ok) {
        // Ok, there was an exception raised by an async event. We need
        // to unwind through the caller back the entrance to the native
        // method.

        // Only handle true exceptions being raised, eat all other requests
        // for now.

        if(env->state()->thread_state()->raise_reason() == cException) {
          capi::capi_raise_backend(env->state()->thread_state()->current_exception());
        } else {
          env->state()->thread_state()->clear();
        }
      }

      if(ret < 0 && errno == EINTR) {
        if(input_tv) {
          struct timeval cur_tv;
          gettimeofday(&cur_tv, NULL);
          timersub(&absolute_tv, &cur_tv, &tv);
        }
      } else {
        break;
      }
    }

    return ret;
  }
コード例 #7
0
ファイル: capi.cpp プロジェクト: cutorad/rubinius
    void capi_raise_backend(Exception* exception) {
      NativeMethodEnvironment* env = NativeMethodEnvironment::get();
      exception->locations(env->state(), Location::from_call_stack(env->state(),
                           env->current_call_frame()));
      env->state()->raise_exception(exception);

      env->current_ep()->return_to(env);
    }
コード例 #8
0
ファイル: module.cpp プロジェクト: JesseChavez/rubinius
  ID rb_frame_this_func() {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    CallFrame* rcf = env->current_call_frame();
    Symbol* name = rcf->name();

    if(name->nil_p()) return rb_intern("<nil>");

    return env->get_handle(name);
  }
コード例 #9
0
ファイル: module.cpp プロジェクト: BRIMIL01/rubinius
  /** @note   Shares code with rb_define_class_under, change there too. --rue */
  VALUE rb_define_module_under(VALUE parent_handle, const char* name) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    Module* parent = c_as<Module>(env->get_object(parent_handle));
    Symbol* constant = env->state()->symbol(name);

    Module* module = rubinius::Helpers::open_module(env->state(),
        env->current_call_frame(), parent, constant);

    return env->get_handle(module);
  }
コード例 #10
0
  /** @note   Shares code with rb_define_module_under, change there too. --rue */
  VALUE rb_define_class_under(VALUE parent_handle, const char* name, VALUE superclass_handle) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    Module* parent = c_as<Module>(env->get_object(parent_handle));
    Class* superclass = c_as<Class>(env->get_object(superclass_handle));
    Symbol* constant = env->state()->symbol(name);

    bool created = false;
    Class* cls = rubinius::Helpers::open_class(env->state(),
        env->current_call_frame(), parent, superclass, constant, &created);

    return env->get_handle_global(cls);
  }
コード例 #11
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;
  }
コード例 #12
0
ファイル: thread.cpp プロジェクト: Locke23rus/rubinius
  void* rb_thread_call_with_gvl(void* (*func)(void*), void* data) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    GCTokenImpl gct;
    State* state = env->state();
    ENTER_CAPI(state);
    state->gc_dependent(gct, state->vm()->saved_call_frame());

    void* ret = (*func)(data);

    env->state()->gc_independent(gct, env->current_call_frame());
    LEAVE_CAPI(env->state());

    return ret;
  }
コード例 #13
0
ファイル: capi.cpp プロジェクト: MarkusQ/rubinius
  VALUE rb_apply(VALUE recv, ID mid, VALUE args) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();
    env->flush_cached_data();

    Array* ary = capi::c_as<Array>(env->get_object(args));

    Object* obj = env->get_object(recv);
    Object* ret = obj->send(env->state(), env->current_call_frame(),
        reinterpret_cast<Symbol*>(mid), ary, RBX_Qnil);
    env->update_cached_data();

    // An exception occurred
    if(!ret) env->current_ep()->return_to(env);

    return env->get_handle(ret);
  }
コード例 #14
0
ファイル: globals.cpp プロジェクト: Azzurrio/rubinius
  VALUE rb_gv_get(const char* name) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();
    long len;

    len = strlen(name);
    if((len == 1 && name[0] == '~') ||
       (len == 2 && name[0] == '$' && name[1] == '~')) {
      return env->get_handle(Regexp::last_match_result(env->state(),
        Fixnum::from(0), Fixnum::from(0), env->current_call_frame()));
    }
    VALUE Globals = rb_const_get(rb_mRubinius, rb_intern("Globals"));

    return rb_funcall(Globals,
                      rb_intern("[]"),
                      1,
                      env->get_handle(prefixed_by(env->state(), '$', rb_intern(name))));
  }
コード例 #15
0
ファイル: capi.cpp プロジェクト: cutorad/rubinius
    VALUE capi_fast_call(VALUE receiver, ID method_name, int arg_count, ...) {
      NativeMethodEnvironment* env = NativeMethodEnvironment::get();

      va_list varargs;
      va_start(varargs, arg_count);

      Object* args[arg_count];

      for(int i = 0; i < arg_count; i++) {
        args[i] = env->get_object(va_arg(varargs, VALUE));
      }

      va_end(varargs);

      // Unlock, we're leaving extension code.
      LEAVE_CAPI(env->state());

      Object* recv = env->get_object(receiver);
      Symbol* method = (Symbol*)method_name;

      Object* ret = cNil;
      // Run in block so we properly deconstruct objects allocated
      // on the stack if we do a longjmp because of an exception.
      {
        LookupData lookup(recv, recv->lookup_begin(env->state()), env->state()->globals().sym_private.get());
        Arguments args_o(method, recv, cNil, arg_count, args);
        Dispatch dis(method);

        ret = dis.send(env->state(), env->current_call_frame(),
                       lookup, args_o);
      }

      // We need to get the handle for the return value before getting
      // the GEL so that ret isn't accidentally GCd while we wait.
      VALUE ret_handle = 0;
      if(ret) ret_handle = env->get_handle(ret);

      // Re-entering extension code
      ENTER_CAPI(env->state());

      // An exception occurred
      if(!ret) env->current_ep()->return_to(env);

      return ret_handle;
    }
コード例 #16
0
ファイル: capi.cpp プロジェクト: cutorad/rubinius
  void capi_define_method(const char* file, VALUE target,
                          const char* name, CApiGenericFunction fptr,
                          int arity, CApiMethodKind kind)
  {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    State* state = env->state();
    Symbol* method_name = state->symbol(name);

    Module* module = NULL;

    if(kind == cCApiSingletonMethod) {
      module = c_as<Module>(env->get_object(target)->singleton_class(env->state()));
    } else {
      module = c_as<Module>(env->get_object(target));
    }

    NativeMethod* method = NULL;
    method = NativeMethod::create(state, String::create(state, file),
                                  module, method_name,
                                  (void*)fptr, Fixnum::from(arity),
                                  env->current_native_frame()->capi_lock_index());

    Symbol* visibility;

    switch(kind) {
    case cCApiPrivateMethod:
      visibility = G(sym_private);
      break;

    case cCApiProtectedMethod:
      visibility = G(sym_protected);
      break;

    default:  /* Also catches singletons for now. @todo Verify OK. --rue */
      visibility = G(sym_public);
      break;
    }

    module->add_method(state, method_name, method, visibility);
    System::vm_reset_method_cache(env->state(), module, method_name, env->current_call_frame());
  }
コード例 #17
0
ファイル: capi.cpp プロジェクト: cutorad/rubinius
    /**
     *  Common implementation for rb_funcall*
     */
    VALUE capi_funcall_backend(const char* file, int line,
                               VALUE receiver, ID method_name,
                               size_t arg_count, VALUE* arg_array)
    {
      NativeMethodEnvironment* env = NativeMethodEnvironment::get();
      env->flush_cached_data();

      Array* args = Array::create(env->state(), arg_count);
      for(size_t i = 0; i < arg_count; i++) {
        args->set(env->state(), i, env->get_object(arg_array[i]));
      }

      Object* blk = cNil;

      if(VALUE blk_handle = env->outgoing_block()) {
        blk = env->get_object(blk_handle);
        env->set_outgoing_block(0);
      }

      Object* recv = env->get_object(receiver);

      // Unlock, we're leaving extension code.
      LEAVE_CAPI(env->state());

      Object* ret = recv->send(env->state(), env->current_call_frame(),
          reinterpret_cast<Symbol*>(method_name), args, blk);

      // We need to get the handle for the return value before getting
      // the GEL so that ret isn't accidentally GCd while we wait.
      VALUE ret_handle = 0;
      if(ret) ret_handle = env->get_handle(ret);

      // Re-entering extension code
      ENTER_CAPI(env->state());

      env->update_cached_data();

      // An exception occurred
      if(!ret) env->current_ep()->return_to(env);

      return ret_handle;
    }
コード例 #18
0
ファイル: module.cpp プロジェクト: shaliko/rubinius
  /** @note   Shares code with rb_define_class_under, change there too. --rue */
  VALUE rb_define_module_under(VALUE parent_handle, const char* name) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    Module* parent = c_as<Module>(env->get_object(parent_handle));
    Symbol* constant = env->state()->symbol(name);

    LEAVE_CAPI(env->state());
    Module* module = rubinius::Helpers::open_module(env->state(),
        env->current_call_frame(), parent, constant);

    // The call above could have triggered an Autoload resolve, which may
    // raise an exception, so we have to check the value returned.
    if(!module) env->current_ep()->return_to(env);

    // Grab the module handle before grabbing the lock
    // so the Module isn't accidentally GC'ed.
    VALUE module_handle = env->get_handle(module);
    ENTER_CAPI(env->state());

    return module_handle;
  }
コード例 #19
0
  /** @note   Shares code with rb_define_module_under, change there too. --rue */
  VALUE rb_define_class_under(VALUE outer, const char* name, VALUE super) {


    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    Module* module = c_as<Module>(env->get_object(outer));
    Class* superclass = c_as<Class>(env->get_object(super ? super : rb_cObject));
    Symbol* constant = env->state()->symbol(name);

    bool created = false;

    LEAVE_CAPI(env->state());
    Class* opened_class = NULL;

    // Run in a block so OnStack is properly deallocated before we
    // might do a longjmp because of an exception.
    {
      GCTokenImpl gct;
      OnStack<3> os(env->state(), module, superclass, constant);

      opened_class = rubinius::Helpers::open_class(env->state(), gct,
          env->current_call_frame(), module, superclass, constant, &created);
    }

    // The call above could have triggered an Autoload resolve, which may
    // raise an exception, so we have to check the value returned.
    if(!opened_class) env->current_ep()->return_to(env);

    // We need to grab the handle before entering back into C-API
    // code. The problem otherwise can be that the GC runs and
    // the opened_class is GC'ed.

    VALUE klass = env->get_handle(opened_class);
    ENTER_CAPI(env->state());

    if(super) rb_funcall(super, rb_intern("inherited"), 1, klass);

    return klass;
  }
コード例 #20
0
ファイル: thread.cpp プロジェクト: Locke23rus/rubinius
  // THAR BE EVEN MORE DRAGONS.
  //
  // When venturing through the valleys of the unmanaged, our hero must
  // remain vigilant and disciplined! If she should ever find a VALUE for
  // a reference in her travels: Look away! For these VALUEs are pure
  // death! Our hero must steel herself and continue on her quest, returning
  // as soon as possible to the castle of the managed.
  void* rb_thread_call_without_gvl2(void *(*func)(void *data), void* data1,
                                   rb_unblock_function_t ubf, void* ubf_data) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();
    State* state = env->state();
    void* ret = NULL;

    if(!state->check_async(env->current_call_frame())) {
      return ret;
    }
    if(ubf == RUBY_UBF_IO || ubf == RUBY_UBF_PROCESS) {
      state->vm()->interrupt_with_signal();
    } else {
      state->vm()->wait_on_custom_function(ubf, ubf_data);
    }
    LEAVE_CAPI(env->state());
    {
      GCIndependent guard(env);
      ret = (*func)(data1);
    }
    ENTER_CAPI(env->state());
    state->vm()->clear_waiter();

    return ret;
  }
コード例 #21
0
ファイル: nativemethod.cpp プロジェクト: AndreMeira/rubinius
  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;
  }
コード例 #22
0
ファイル: nativemethod.cpp プロジェクト: dziulius/rubinius
  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;
  }
コード例 #23
0
ファイル: module.cpp プロジェクト: atoulme/rubinius
  ID rb_frame_last_func() {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    return reinterpret_cast<ID>(env->current_call_frame()->name());
  }
コード例 #24
0
ファイル: module.cpp プロジェクト: FunkyFortune/rubinius
  ID rb_frame_last_func() {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    return env->get_handle(env->current_call_frame()->name());
  }
コード例 #25
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;
  }
コード例 #26
0
ファイル: thread.cpp プロジェクト: Locke23rus/rubinius
  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;
  }