コード例 #1
0
ファイル: kernel.cpp プロジェクト: Azzurrio/rubinius
  VALUE rb_ensure(VALUE (*func)(ANYARGS), VALUE arg1,
                  VALUE (*ensure_func)(ANYARGS), VALUE arg2)
  {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();
    VALUE ret = Qnil;
    bool exc_raised = false;

    ExceptionPoint ep(env);
    PLACE_EXCEPTION_POINT(ep);

    if(unlikely(ep.jumped_to())) {
      exc_raised = true;
    } else {
      ret = (*func)(arg1);
    }

    ep.pop(env);
    (*ensure_func)(arg2);

    if(exc_raised) {
      env->current_ep()->return_to(env);
    }

    return ret;
  }
コード例 #2
0
ファイル: kernel.cpp プロジェクト: Azzurrio/rubinius
  VALUE rb_exec_recursive(VALUE (*func)(VALUE, VALUE, int),
                          VALUE obj, VALUE arg)
  {
    VALUE hash = rb_thread_local_aref(rb_thread_current(),
                                      rb_intern("__recursive_key"));
    VALUE objid = rb_obj_id(obj);

    if(recursive_check(hash, objid)) {
      return (*func)(obj, arg, 1);
    } else {
      NativeMethodEnvironment* env = NativeMethodEnvironment::get();
      VALUE ret = Qnil;

      ExceptionPoint ep(env);
      PLACE_EXCEPTION_POINT(ep);

      bool unwinding = false;
      hash = recursive_push(hash, objid);

      if(unlikely(ep.jumped_to())) {
        unwinding = true;
      } else {
        ret = (*func)(obj, arg, 0);
      }

      ep.pop(env);

      recursive_pop(hash, objid);
      if(unwinding) env->current_ep()->return_to(env);
      return ret;
    }
  }
コード例 #3
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);
    }
コード例 #4
0
ファイル: module.cpp プロジェクト: JesseChavez/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 = NULL;

    // Create a scope so we know that the OnStack variables are popped off
    // before we possibly make a longjmp. Making a longjmp doesn't give
    // any guarantees about destructors being run
    {
      OnStack<2> os(env->state(), parent, constant);

      module = rubinius::Helpers::open_module(env->state(), 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;
  }
コード例 #5
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;
  }
コード例 #6
0
ファイル: kernel.cpp プロジェクト: Azzurrio/rubinius
  void rb_jump_tag(int status) {
    if(!status) return;

    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    // TODO should check if there is an ep?
    env->current_ep()->return_to(env);
  }
コード例 #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
ファイル: kernel.cpp プロジェクト: Red54/rubinius
  VALUE rb_rescue2(VALUE (*func)(ANYARGS), VALUE arg1,
                   VALUE (*raise_func)(ANYARGS), VALUE arg2, ...)
  {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();
    VALUE ret = Qnil;
    ExceptionPoint ep(env);
    va_list exc_classes;

    PLACE_EXCEPTION_POINT(ep);
    if(unlikely(ep.jumped_to())) {
      ep.pop(env);

      if(env->state()->thread_state()->raise_reason() != cException) {
        env->current_ep()->return_to(env);
      }

      VALUE exc_handle = env->get_handle(env->state()->thread_state()->current_exception());
      bool handle_exc = false;

      va_start(exc_classes, arg2);
      while(VALUE eclass = va_arg(exc_classes, VALUE)) {
        if(RTEST(rb_obj_is_kind_of(exc_handle, eclass))) {
          handle_exc = true;
          break;
        }
      }
      va_end(exc_classes);

      if(handle_exc) {
        ret = (*raise_func)(arg2, exc_handle);
        env->state()->thread_state()->clear_raise();
      } else {
        env->current_ep()->return_to(env);
      }

    } else {
      ret = (*func)(arg1);
      ep.pop(env);
    }

    return ret;
  }
コード例 #9
0
  void rb_raise(VALUE error_handle, const char* format_string, ...) {
    va_list args;
    char reason[RB_RAISE_BUFSIZE];

    va_start(args, format_string);
    vsnprintf(reason, RB_RAISE_BUFSIZE, format_string, args);
    va_end(args);

    NativeMethodEnvironment* env = NativeMethodEnvironment::get();
    Exception* exc = Exception::make_exception(
          env->state(), as<Class>(env->get_object(error_handle)), reason);
    env->state()->thread_state()->raise_exception(exc);

    env->current_ep()->return_to(env);
  }
コード例 #10
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);
  }
コード例 #11
0
ファイル: array.cpp プロジェクト: Locke23rus/rubinius
  VALUE rb_protect_inspect(VALUE (*func)(VALUE a, VALUE b), VALUE h_obj, VALUE h_arg) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();
    STATE = env->state();

    Thread* thr = Thread::current(state);
    LookupTable* rectbl = thr->recursive_objects();

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

    Object* id = obj->id(state);

    bool found = false;
    rectbl->fetch(state, id, &found);

    if(found) {
      return (*func)(h_obj, h_arg);
    }

    rectbl->store(state, id, cTrue);

    VALUE ret = Qnil;

    ExceptionPoint ep(env);
    PLACE_EXCEPTION_POINT(ep);

    bool unwinding = false;

    if(unlikely(ep.jumped_to())) {
      unwinding = true;
    } else {
      ret = (*func)(h_obj, h_arg);
    }

    ep.pop(env);

    // Get the thread and table again, the GC might have fun.
    thr = Thread::current(state);
    rectbl = thr->recursive_objects();
    obj = env->get_object(h_obj);
    id = obj->id(state);

    rectbl->remove(state, id);

    if(unwinding) env->current_ep()->return_to(env);

    return ret;
  }
コード例 #12
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;
    }
コード例 #13
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;
    }
コード例 #14
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;
  }
コード例 #15
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;
  }
コード例 #16
0
ファイル: capi.cpp プロジェクト: cutorad/rubinius
 void capi_raise_break(VALUE obj) {
   NativeMethodEnvironment* env = NativeMethodEnvironment::get();
   env->state()->vm()->thread_state()->raise_break(env->get_object(obj), env->scope()->parent());
   env->current_ep()->return_to(env);
 }