예제 #1
0
jobject JNIHandleBlock::allocate_handle(oop obj) {
  assert(Universe::heap()->is_in_reserved(obj), "sanity check");
  if (_top == 0) {
    // This is the first allocation or the initial block got zapped when
    // entering a native function. If we have any following blocks they are
    // not valid anymore.
    for (JNIHandleBlock* current = _next; current != NULL;
         current = current->_next) {
      assert(current->_last == NULL, "only first block should have _last set");
      assert(current->_free_list == NULL,
             "only first block should have _free_list set");
      current->_top = 0;
      if (ZapJNIHandleArea) current->zap();
    }

    // Clear initial block
    _free_list = NULL;
    _allocate_before_rebuild = 0;
    _last = this;
    if (ZapJNIHandleArea) zap();
  }

  // Try last block
  if (_last->_top < block_size_in_oops) {
    oop* handle = &(_last->_handles)[_last->_top++];
    *handle = obj;
    return (jobject) handle;
  }

  // Try free list
  if (_free_list != NULL) {
    oop* handle = _free_list;
    _free_list = (oop*) *_free_list;
    *handle = obj;
    return (jobject) handle;
  }
  // Check if unused block follow last
  if (_last->_next != NULL) {
    // update last and retry
    _last = _last->_next;
    return allocate_handle(obj);
  }

  // No space available, we have to rebuild free list or expand
  if (_allocate_before_rebuild == 0) {
      rebuild_free_list();        // updates _allocate_before_rebuild counter
  } else {
    // Append new block
    Thread* thread = Thread::current();
    Handle obj_handle(thread, obj);
    // This can block, so we need to preserve obj accross call.
    _last->_next = JNIHandleBlock::allocate_block(thread);
    _last = _last->_next;
    _allocate_before_rebuild--;
    obj = obj_handle();
  }
  return allocate_handle(obj);  // retry
}
예제 #2
0
    static void construct(::PyObject *obj_ptr, bp::converter::rvalue_from_python_stage1_data *data)
    {
        // NOTE: here we cannot construct directly from string, as we need to query the precision.
        piranha_assert(obj_ptr);
        // NOTE: here the handle is from borrowed because we are not responsible for the generation of obj_ptr:
        // borrowed will increase the refcount of obj_ptr, so that, when obj is destroyed, the refcount
        // for obj_ptr goes back to the original value instead of decreasing by 1.
        bp::handle<> obj_handle(bp::borrowed(obj_ptr));
        bp::object obj(obj_handle);
        const ::mpfr_prec_t prec
            = piranha::safe_cast<::mpfr_prec_t>(static_cast<long>(bp::extract<long>(obj.attr("context").attr("prec"))));
        // NOTE: here we use repr instead of str because the repr seems to give the most accurate representation
        // in base 10 for the object.
        ::PyObject *str_obj = ::PyObject_Repr(obj.ptr());
        if (!str_obj) {
            ::PyErr_SetString(PyExc_RuntimeError, "unable to extract string representation of real");
            bp::throw_error_already_set();
        }
        bp::handle<> str_rep(str_obj);
#if PY_MAJOR_VERSION < 3
        const char *s = ::PyString_AsString(str_rep.get());
#else
        ::PyObject *unicode_str_obj = ::PyUnicode_AsEncodedString(str_rep.get(), "ascii", "strict");
        if (!unicode_str_obj) {
            ::PyErr_SetString(PyExc_RuntimeError, "unable to extract string representation of real");
            bp::throw_error_already_set();
        }
        bp::handle<> unicode_str(unicode_str_obj);
        const char *s = ::PyBytes_AsString(unicode_str.get());
        if (!s) {
            ::PyErr_SetString(PyExc_RuntimeError, "unable to extract string representation of real");
            bp::throw_error_already_set();
        }
#endif
        // NOTE: the search for "'" is due to the string format of mpmath.mpf objects.
        while (*s != '\0' && *s != '\'') {
            ++s;
        }
        if (*s == '\0') {
            ::PyErr_SetString(PyExc_RuntimeError, "invalid string input converting to real");
            bp::throw_error_already_set();
        }
        ++s;
        auto start = s;
        while (*s != '\0' && *s != '\'') {
            ++s;
        }
        if (*s == '\0') {
            ::PyErr_SetString(PyExc_RuntimeError, "invalid string input converting to real");
            bp::throw_error_already_set();
        }
        void *storage
            = reinterpret_cast<bp::converter::rvalue_from_python_storage<piranha::real> *>(data)->storage.bytes;
        ::new (storage) piranha::real(std::string(start, s), prec);
        data->convertible = storage;
    }