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 }
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; }