Esempio n. 1
0
  Object* run_instance(STATE) {
    /* These are all referenced, so OnStack is not necessary. Additionally,
     * thread is pinned, so we do not need to worry about it moving.
     */
    Thread* thread = state->vm()->thread.get();
    Array* args = thread->args();
    Object* block = thread->block();

    if(thread->initialized()->false_p() || args->nil_p() || block->nil_p()) {
      return cNil;
    }

    Object* value = block->send(state, G(sym_call), args, block);

    /* We explicitly set the current CallFrame reference to NULL because we
     * are at the top of the stack in terms of managed code.
     */
    state->vm()->set_call_frame(NULL);

    thread->exception(state, state->vm()->thread_state()->current_exception());

    if(state->vm()->thread_state()->raise_reason() == cThreadKill) {
      thread->value(state, cNil);
    } else if(value) {
      thread->value(state, value);
    }

    Object* mirror = G(mirror)->send(state, state->symbol("reflect"),
        Array::from_tuple(state, Tuple::from(state, 1, thread)));
    mirror->send(state, state->symbol("finish"));

    return value;
  }
Esempio n. 2
0
 Object* rbx_cast_for_splat_block_arg(STATE, CallFrame* call_frame, Arguments& args) {
   if(args.total() == 1) {
     Object* obj = args.get_argument(0);
     if(!kind_of<Array>(obj)) {
       /* Yes, you are reading this code correctly: In Ruby 1.8, calling a
        * block with these forms { |*| } and { |*a| } with a single argument
        * that is not an Array and which responds to #to_ary will cause #to_ary
        * to be called and its return value ignored. Ultimately, the original
        * object itself is wrapped in an Array and passed to the block.
        */
       if(CBOOL(obj->respond_to(state, state->symbol("to_ary"), cFalse))) {
         OnStack<1> os(state, obj);
         Object* ignored = obj->send(state, call_frame, state->symbol("to_ary"));
         if(!ignored->nil_p() && !kind_of<Array>(ignored)) {
           Exception::type_error(state, "to_ary must return an Array", call_frame);
           return 0;
         }
       }
     }
     Array* ary = Array::create(state, 1);
     ary->set(state, 0, obj);
     return ary;
   } else {
     Array* ary = Array::create(state, args.total());
     for(size_t i = 0; i < args.total(); i++) {
       ary->set(state, i, args.get_argument(i));
     }
     return ary;
   }
 }
Esempio n. 3
0
  unsigned long rb_big2ulong(VALUE obj) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

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

    if(object->nil_p()) {
      rb_raise(rb_eTypeError, "no implicit conversion from nil to unsigned long");
    } else if(Bignum* big = try_as<Bignum>(object)) {
      size_t bits = (size_t)mp_count_bits(big->mp_val());
      size_t bound = sizeof(long) * CHAR_BIT;
      unsigned long val = big->to_ulong();

      if(big->mp_val()->sign == MP_NEG) {
        if(bits < bound) {
          return -val;
        } else if (bits == bound && val == 1+(unsigned long)(-(LONG_MIN+1))) {
          return LONG_MIN;
        }
      } else if(bits <= bound) {
        return val;
      }

      rb_raise(rb_eRangeError, "bignum out of range of unsigned long");
    }

    rb_raise(rb_eArgError, "parameter is not a Bignum");

    return 0;
  }
Esempio n. 4
0
    Class* open_class(STATE, GCToken gct, CallFrame* call_frame, Module* under, Object* super, Symbol* name, bool* created) {
      bool found;

      *created = false;

      Object* obj = under->get_const(state, name, &found);

      OnStack<4> os(state, under, super, name, obj);

      if(found) {
        TypedRoot<Object*> sup(state, super);

        if(Autoload* autoload = try_as<Autoload>(obj)) {
          obj = autoload->resolve(state, gct, call_frame, true);

          // Check if an exception occurred
          if(!obj) return NULL;
        }

        // Autoload::resolve will return nil if code loading failed, in which
        // case we ignore the autoload.
        if(!obj->nil_p()) {
          return check_superclass(state, call_frame, as<Class>(obj), sup.get());
        }
      }

      *created = true;
      return add_class(state, under, super, name);
    }
Esempio n. 5
0
  Object* rbx_check_keyword(STATE, CallFrame* call_frame, Object* obj) {
    Object* cls = G(object)->get_const(state, "Hash");

    if(!cls->nil_p()) {
      if(obj->kind_of_p(state, cls)) {
        return obj;
      } else {
        OnStack<1> os(state, cls);

        Symbol* name = state->symbol("to_hash");
        Arguments args(name, obj, 0, 0);
        Dispatch dis(name);

        obj = dis.send(state, call_frame, args);
        if(obj) {
          if(obj->kind_of_p(state, cls)) {
            return obj;
          } else if(!obj->nil_p()) {
            Exception::type_error(state, "to_hash must return a Hash", call_frame);
            return NULL;
          }
        } else {
          state->vm()->thread_state()->clear_raise();
        }
      }
    }

    return NULL;
  }
Esempio n. 6
0
    Class* open_class(STATE, GCToken gct, CallFrame* call_frame, Module* under, Object* super, Symbol* name, bool* created) {
      ConstantMissingReason reason;

      *created = false;

      Object* obj = under->get_const(state, name, G(sym_public), &reason);

      if(reason == vFound) {
        OnStack<4> os(state, under, super, name, obj);

        if(Autoload* autoload = try_as<Autoload>(obj)) {
          obj = autoload->resolve(state, gct, call_frame, under, true);

          // Check if an exception occurred
          if(!obj) return NULL;
        }

        // Autoload::resolve will return nil if code loading failed, in which
        // case we ignore the autoload.
        if(!obj->nil_p()) {
          return check_superclass(state, call_frame, as<Class>(obj), super);
        }
      }

      *created = true;
      return add_class(state, under, super, name);
    }
Esempio n. 7
0
    Module* open_module(STATE, GCToken gct, CallFrame* call_frame, Module* under, Symbol* name) {
      Module* module;
      bool found;

      Object* obj = under->get_const(state, name, &found);

      OnStack<3> os(state, under, name, obj);

      if(found) {
        if(Autoload* autoload = try_as<Autoload>(obj)) {
          obj = autoload->resolve(state, gct, call_frame, true);
        }

        // Check if an exception occurred
        if(!obj) return NULL;

        // Autoload::resolve will return nil if code loading failed, in which
        // case we ignore the autoload.
        if(!obj->nil_p()) {
          return as<Module>(obj);
        }
      }

      module = Module::create(state);

      module->set_name(state, name, under);
      under->set_const(state, name, module);

      return module;
    }
Esempio n. 8
0
    Module* open_module(STATE, Module* under, Symbol* name) {
      Module* module;
      ConstantMissingReason reason;

      Object* obj = under->get_const(state, name, G(sym_public), &reason);

      if(reason == vFound) {
        OnStack<3> os(state, under, name, obj);

        if(Autoload* autoload = try_as<Autoload>(obj)) {
          obj = autoload->resolve(state, under, true);
        }

        // Check if an exception occurred
        if(!obj) return NULL;

        // Autoload::resolve will return nil if code loading failed, in which
        // case we ignore the autoload.
        if(!obj->nil_p()) {
          return as<Module>(obj);
        }
      }

      module = Module::create(state);

      module->set_name(state, name, under);
      under->set_const(state, name, module);

      return module;
    }
Esempio n. 9
0
  Array* Array::to_ary(STATE, Object* value, CallFrame* call_frame) {
    if(Tuple* tup = try_as<Tuple>(value)) {
      return Array::from_tuple(state, tup);
    }

    if(CBOOL(value->respond_to(state, G(sym_to_ary), cTrue))) {
      Object* res = value->send(state, call_frame, G(sym_to_ary));
      if(!res) return 0;

      if(Array* ary = try_as<Array>(res)) {
        return ary;
      }

      if(LANGUAGE_18_ENABLED || !res->nil_p()) {
        Exception::type_error(state, "to_ary should return an Array", call_frame);
        return 0;
      }

      // NOTE: On >= 1.9, if res is nil just fall through and return [value]
    }

    Array* ary = Array::create(state, 1);
    ary->set(state, 0, value);
    return ary;
  }
Esempio n. 10
0
    inline bool yield_splat(STATE, CallFrame* call_frame, intptr_t count) {
      Object* ary = stack_pop();
      Object* t1 = call_frame->scope->block();

      Arguments args(G(sym_call), t1, count, stack_back_position(count));

      if(!ary->nil_p()) {
        args.append(state, as<Array>(ary));
      }

      if(BlockEnvironment *env = try_as<BlockEnvironment>(t1)) {
        call_frame->return_value = env->call(state, args);
      } else if(Proc* proc = try_as<Proc>(t1)) {
        call_frame->return_value = proc->yield(state, args);
      } else if(t1->nil_p()) {
        state->raise_exception(Exception::make_lje(state));
        call_frame->return_value = NULL;
      } else {
        Dispatch dispatch(G(sym_call));
        call_frame->return_value = dispatch.send(state, args);
      }

      stack_clear(count);

      state->vm()->checkpoint(state);

      CHECK_AND_PUSH(call_frame->return_value);
    }
Esempio n. 11
0
    void Console::process_requests(STATE) {
      GCTokenImpl gct;
      RBX_DTRACE_CONST char* thread_name =
        const_cast<RBX_DTRACE_CONST char*>("rbx.console.request");
      request_vm_->set_name(thread_name);

      RUBINIUS_THREAD_START(const_cast<RBX_DTRACE_CONST char*>(thread_name),
                            state->vm()->thread_id(), 1);

      state->vm()->thread->hard_unlock(state, gct, 0);
      state->gc_independent(gct, 0);

      while(!request_exit_) {
        Object* status = fsevent_.get()->wait_for_event(state);

        if(request_exit_) break;
        if(status->nil_p()) continue;

        char* request = read_request(state);

        if(request) {
          utilities::thread::Mutex::LockGuard lg(list_lock_);

          request_list_->push_back(request);
          response_cond_.signal();
        }
      }

      state->gc_dependent(gct, 0);

      RUBINIUS_THREAD_STOP(const_cast<RBX_DTRACE_CONST char*>(thread_name),
                           state->vm()->thread_id(), 1);
    }
Esempio n. 12
0
  long rb_num2long(VALUE obj) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

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

    if(object->nil_p()) {
      rb_raise(rb_eTypeError, "no implicit conversion from nil to Integer");
    } else if(Fixnum* fix = try_as<Fixnum>(object)) {
      return fix->to_long();
    } else if(try_as<Bignum>(object)) {
      return rb_big2long(obj);
    } else if(try_as<Float>(object)) {
      return (long)capi_get_float(env, obj)->val;
    } else if(object->true_p()) {
      rb_raise(rb_eTypeError, "can't convert true to Integer");
    } else if(object->false_p()) {
      rb_raise(rb_eTypeError, "can't convert false to Integer");
    }

    ID to_int_id = rb_intern("to_int");

    if(!rb_respond_to(obj, to_int_id)) {
	    rb_raise(rb_eTypeError, "can't convert %s into Integer",
		     rb_obj_classname(obj));
    }

    obj = rb_funcall(obj, to_int_id, 0);

    return rb_num2long(obj);
  }
Esempio n. 13
0
  void MachineCode::fill_opcodes(STATE, CompiledCode* original) {
    Tuple* ops = original->iseq()->opcodes();

    int sends = 0;
    int constants = 0;

    for(size_t index = 0; index < total;) {
      Object* val = ops->at(state, index);
      if(val->nil_p()) {
        opcodes[index++] = 0;
      } else {
        opcodes[index] = as<Fixnum>(val)->to_native();

        size_t width = InstructionSequence::instruction_width(opcodes[index]);

        switch(width) {
        case 2:
          opcodes[index + 1] = as<Fixnum>(ops->at(state, index + 1))->to_native();
          break;
        case 3:
          opcodes[index + 1] = as<Fixnum>(ops->at(state, index + 1))->to_native();
          opcodes[index + 2] = as<Fixnum>(ops->at(state, index + 2))->to_native();
          break;
        }

        switch(opcodes[index]) {
        case InstructionSequence::insn_send_method:
        case InstructionSequence::insn_send_stack:
        case InstructionSequence::insn_send_stack_with_block:
        case InstructionSequence::insn_send_stack_with_splat:
        case InstructionSequence::insn_send_super_stack_with_block:
        case InstructionSequence::insn_send_super_stack_with_splat:
        case InstructionSequence::insn_zsuper:
        case InstructionSequence::insn_meta_send_call:
        case InstructionSequence::insn_meta_send_op_plus:
        case InstructionSequence::insn_meta_send_op_minus:
        case InstructionSequence::insn_meta_send_op_equal:
        case InstructionSequence::insn_meta_send_op_tequal:
        case InstructionSequence::insn_meta_send_op_lt:
        case InstructionSequence::insn_meta_send_op_gt:
        case InstructionSequence::insn_meta_to_s:
        case InstructionSequence::insn_check_serial:
        case InstructionSequence::insn_check_serial_private:
        case InstructionSequence::insn_call_custom:
          sends++;
          break;
        case InstructionSequence::insn_push_const_fast:
        case InstructionSequence::insn_find_const_fast:
          constants++;
          break;
        }

        index += width;
      }
    }

    initialize_call_sites(state, original, sends);
    initialize_constant_caches(state, original, constants);
  }
 inline void restore_exception_state(STATE, CallFrame* call_frame) {
   Object* top = stack_pop();
   if(top->nil_p()) {
     state->vm()->thread_state()->clear();
   } else {
     state->vm()->thread_state()->set_state(state, as<ThreadState>(top));
   }
 }
Esempio n. 15
0
Array* CompactLookupTable::filtered_keys(STATE, ObjectMatcher& match) {
    Array* ary = Array::create(state, COMPACTLOOKUPTABLE_SIZE / 2);

    for(unsigned int i = 0; i < COMPACTLOOKUPTABLE_SIZE; i += 2) {
        Object* key = at(state, i);
        if(!key->nil_p() && match.match_p(state, key)) ary->append(state, key);
    }

    return ary;
}
Esempio n. 16
0
LookupTable* CompactLookupTable::to_lookuptable(STATE) {
    LookupTable* tbl = (LookupTable*)LookupTable::create(state);

    for(unsigned int i = 0; i < COMPACTLOOKUPTABLE_SIZE; i += 2) {
        Object* key = at(state, i);
        if(!key->nil_p()) tbl->store(state, key, at(state, i + 1));
    }

    return tbl;
}
Esempio n. 17
0
Array* CompactLookupTable::values(STATE) {
    Array* ary = Array::create(state, COMPACTLOOKUPTABLE_SIZE / 2);

    for(unsigned int i = 0; i < COMPACTLOOKUPTABLE_SIZE; i += 2) {
        Object* key = at(state, i);
        if(!key->nil_p()) ary->append(state, at(state, i + 1));
    }

    return ary;
}
Esempio n. 18
0
 Object* MatchData::last_capture(STATE) {
   if(region_->num_fields() == 0) return cNil;
   native_int captures = region_->num_fields();
   while(captures--) {
     Object* capture = nth_capture(state, captures);
     if(!capture->nil_p()) {
       return capture;
     }
   }
   return cNil;
 }
Esempio n. 19
0
 Integer* ObjectMemory::assign_object_id_ivar(STATE, Object* obj) {
   SYNC(state);
   Object* id = obj->get_ivar(state, G(sym_object_id));
   if(id->nil_p()) {
     /* All references have an even object_id. last_object_id starts out at 0
      * but we don't want to use 0 as an object_id, so we just add before using */
     id = Integer::from(state, ++state->memory()->last_object_id << TAG_REF_WIDTH);
     obj->set_ivar(state, G(sym_object_id), id);
   }
   return as<Integer>(id);
 }
Esempio n. 20
0
  /**
   * Runs rbx from the filesystem. Searches for the Rubinius runtime files
   * according to the algorithm in find_runtime().
   */
  void Environment::run_from_filesystem() {
    int i = 0;
    state->vm()->set_root_stack(reinterpret_cast<uintptr_t>(&i),
                                VM::cStackDepthMax);

    std::string runtime = system_prefix() + RBX_RUNTIME_PATH;

    load_platform_conf(runtime);
    boot_vm();
    start_finalizer();

    load_argv(argc_, argv_);

    start_signals();
    state->vm()->initialize_config();

    load_tool();

    G(rubinius)->set_const(state, "Signature", Integer::from(state, signature_));

    if(LANGUAGE_20_ENABLED(state)) {
      runtime += "/20";
    } else if(LANGUAGE_19_ENABLED(state)) {
      runtime += "/19";
    } else {
      runtime += "/18";
    }
    G(rubinius)->set_const(state, "RUNTIME_PATH", String::create(state,
                           runtime.c_str(), runtime.size()));

    load_kernel(runtime);
    shared->finalizer_handler()->start_thread(state);

    run_file(runtime + "/loader.rbc");

    state->vm()->thread_state()->clear();

    Object* loader = G(rubinius)->get_const(state, state->symbol("Loader"));
    if(loader->nil_p()) {
      rubinius::bug("Unable to find loader");
    }

    OnStack<1> os(state, loader);

    Object* inst = loader->send(state, 0, state->symbol("new"));
    if(inst) {
      OnStack<1> os2(state, inst);

      inst->send(state, 0, state->symbol("main"));
    } else {
      rubinius::bug("Unable to instantiate loader");
    }
  }
Esempio n. 21
0
Object* CompactLookupTable::store(STATE, Object* key, Object* val) {
    for(unsigned int i = 0; i < COMPACTLOOKUPTABLE_SIZE; i += 2) {
        Object* tmp = at(state, i);
        if(tmp == key || tmp->nil_p()) {
            put(state, i, key);
            put(state, i + 1, val);
            return Qtrue;
        }
    }

    return Qfalse;
}
Esempio n. 22
0
  void Transcoding::declare(STATE, const char* from, const char* to, const char* lib) {
    LookupTable* map = Encoding::transcoding_map(state);
    Object* obj = map->fetch(state, encoding_symbol(state, from));
    LookupTable* table;

    if(obj->nil_p()) {
      table = LookupTable::create(state);
      map->store(state, encoding_symbol(state, from), table);
    } else {
      table = as<LookupTable>(obj);
    }

    table->store(state, encoding_symbol(state, to), String::create(state, lib));
  }
Esempio n. 23
0
  double rb_num2dbl(VALUE val) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    Object* object = env->get_object(val);

    if(object->nil_p()) {
      rb_raise(rb_eTypeError, "no implicit conversion from nil to Float");
    } else if(try_as<String>(object)) {
      rb_raise(rb_eTypeError, "no implicit conversion from String to Float");
    } else if(!try_as<Float>(object)) {
      val = rb_Float(val);
    }

    return capi_get_float(env, val)->val;
  }
Esempio n. 24
0
  void Transcoding::define(STATE, OnigTranscodingType* tr) {
    LookupTable* map = Encoding::transcoding_map(state);
    Object* obj = map->fetch(state, encoding_symbol(state, tr->src_encoding));
    LookupTable* table;

    if(obj->nil_p()) {
      table = LookupTable::create(state);
      map->store(state, encoding_symbol(state, tr->src_encoding), table);
    } else {
      table = as<LookupTable>(obj);
    }

    Transcoding* t = Transcoding::create(state, tr);
    table->store(state, encoding_symbol(state, tr->dst_encoding), t);
  }
Esempio n. 25
0
  Object* Thread::main_thread(STATE) {
    GCTokenImpl gct;

    state->vm()->thread->hard_unlock(state, gct, 0);

    std::string& runtime = state->shared().env()->runtime_path();

    G(rubinius)->set_const(state, "Signature",
        Integer::from(state, state->shared().env()->signature()));

    G(rubinius)->set_const(state, "RUNTIME_PATH", String::create(state,
                           runtime.c_str(), runtime.size()));

    state->vm()->thread->pid(state, Fixnum::from(gettid()));

    state->shared().env()->load_core(state, runtime);

    state->vm()->thread->alive(state, cTrue);
    state->vm()->thread_state()->clear();

    state->shared().start_console(state);
    state->shared().start_metrics(state);

    Object* klass = G(rubinius)->get_const(state, state->symbol("Loader"));
    if(klass->nil_p()) {
      rubinius::bug("unable to find class Rubinius::Loader");
    }

    Object* instance = 0;
    OnStack<1> os(state, instance);

    instance = klass->send(state, 0, state->symbol("new"));
    if(instance) {
      state->shared().env()->set_loader(instance);
    } else {
      rubinius::bug("unable to instantiate Rubinius::Loader");
    }

    // Enable the JIT after the core library has loaded
    G(jit)->enable(state);

    Object* exit = instance->send(state, 0, state->symbol("main"));

    state->shared().signals()->system_exit(state->vm()->thread_state()->raise_value());

    return exit;
  }
Esempio n. 26
0
    long rb_num2long(VALUE obj) {
        NativeMethodEnvironment* env = NativeMethodEnvironment::get();

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

        if(object->nil_p()) {
            rb_raise(rb_eTypeError, "no implicit conversion from nil to Integer");
        } else if(Fixnum* fix = try_as<Fixnum>(object)) {
            return fix->to_long();
        } else if(Bignum* big = try_as<Bignum>(object)) {
            return big->to_long();
        } else if(try_as<Float>(object)) {
            return (long)capi_get_float(env, obj)->val;
        }

        obj = rb_funcall(obj, rb_intern("to_int"), 0);
        return rb_num2long(obj);
    }
Esempio n. 27
0
  VALUE rb_Integer(VALUE object_handle) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    Object* object = env->get_object(object_handle);

    if(kind_of<Fixnum>(object) || kind_of<Bignum>(object)) {
      return object_handle;
    } else if(String* str = try_as<String>(object)) {
      Object* ret = str->to_i(env->state(), Fixnum::from(0), cTrue);
      if(ret->nil_p()) {
        rb_raise(rb_eArgError, "invalid value for Integer");
      }

      return env->get_handle(ret);
    }

    return rb_convert_type(object_handle, 0, "Integer", "to_i");
  }
Esempio n. 28
0
  bool VM::wakeup(STATE, GCToken gct, CallFrame* call_frame) {
    SYNC(state);

    set_check_local_interrupts();
    Object* wait = waiting_object_.get();

    if(park_->parked_p()) {
      park_->unpark();
      return true;
    } else if(vm_jit_.interrupt_with_signal_) {
#ifdef RBX_WINDOWS
      // TODO: wake up the thread
#else
      pthread_kill(os_thread_, SIGVTALRM);
#endif
      UNSYNC;
      // Wakeup any locks hanging around with contention
      om->release_contention(state, gct, call_frame);
      return true;
    } else if(!wait->nil_p()) {
      // We shouldn't hold the VM lock and the IH lock at the same time,
      // other threads can grab them and deadlock.
      InflatedHeader* ih = wait->inflated_header(state);
      UNSYNC;
      ih->wakeup(state, gct, call_frame, wait);
      return true;
    } else {
      Channel* chan = waiting_channel_.get();

      if(!chan->nil_p()) {
        UNSYNC;
        om->release_contention(state, gct, call_frame);
        chan->send(state, gct, cNil, call_frame);
        return true;
      } else if(custom_wakeup_) {
        UNSYNC;
        om->release_contention(state, gct, call_frame);
        (*custom_wakeup_)(custom_wakeup_data_);
        return true;
      }

      return false;
    }
  }
Esempio n. 29
0
  bool VM::wakeup(STATE) {
    utilities::thread::SpinLock::LockGuard guard(interrupt_lock_);

    set_check_local_interrupts();
    Object* wait = waiting_object_.get();

    if(park_->parked_p()) {
      park_->unpark();
      return true;
    } else if(interrupt_with_signal_) {
#ifdef RBX_WINDOWS
      // TODO: wake up the thread
#else
      pthread_kill(os_thread_, SIGVTALRM);
#endif
      interrupt_lock_.unlock();
      // Wakeup any locks hanging around with contention
      memory()->release_contention(state);
      return true;
    } else if(!wait->nil_p()) {
      // We shouldn't hold the VM lock and the IH lock at the same time,
      // other threads can grab them and deadlock.
      InflatedHeader* ih = wait->inflated_header(state);
      interrupt_lock_.unlock();
      ih->wakeup(state, wait);
      return true;
    } else {
      Channel* chan = waiting_channel_.get();

      if(!chan->nil_p()) {
        interrupt_lock_.unlock();
        memory()->release_contention(state);
        chan->send(state, cNil);
        return true;
      } else if(custom_wakeup_) {
        interrupt_lock_.unlock();
        memory()->release_contention(state);
        (*custom_wakeup_)(custom_wakeup_data_);
        return true;
      }

      return false;
    }
  }
Esempio n. 30
0
  long long rb_big2ll(VALUE obj) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

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

    if(object->nil_p()) {
      rb_raise(rb_eTypeError, "no implicit conversion from nil to unsigned long");
    } else if(Bignum* big = try_as<Bignum>(object)) {
      if((size_t)mp_count_bits(big->mp_val()) > sizeof(long long) * CHAR_BIT)
        rb_raise(rb_eRangeError, "bignum too big to convert into long long");

      long long val = big->to_ulong_long();
      if(big->mp_val()->sign == MP_NEG) return -val;
      return val;
    }
    rb_raise(rb_eArgError, "parameter is not a Bignum");

    return 0;
  }