Skip to content

Commit

Permalink
Pull request cython#21: Fannkuch test fixes
Browse files Browse the repository at this point in the history
Merge in ~FLORIAN.ANGERER_ORACLE.COM/cython from fannkuch_test_fixes to hpy_backend

* commit 'c94941b747bef7d028d0bd19753d51b1d4b554bd': (31 commits)
  Use HPyIter_Next
  Fixed float issues on GraalPy
  Fixed issues reintroduced on fannkuch
  Made float test work for HPy
  Make coverage work, start work on float
  Fixed most errors for fannkuch benchmark
  Fix: use API_CALL_TUPLE_DICT for __Pyx_PyObject_Call
  Remove helper funcs HPySlice_New and HPy_GetSlice
  Use HPyList_Insert for LIST_INSERT
  Introduce SEQUENCE_(GET/SET)_SLICE
  Use HPy_GetItem_i for LIST_GET_ITEM
  Merge decl of __Pyx__PyObject_PopNewIndex
  Use HPy_GetItem_i for TUPLE_GET_ITEM(_SAFE)
  Prefer SEQUENCE_SET_SLICE over __Pyx_PyObject_SetSlice if possible
  Fixed segfaults on CPython ABI
  Fix: wrong usage of HPy_Call
  Fix compilation warnings
  Also define __pyx_vectorcallfunc if CYTHON_METH_FASTCALL
  Fix operator precedence issues with expanded macros
  Add missing return stmt
  ...
  • Loading branch information
Du Toit Spies committed Jan 25, 2024
2 parents f007944 + c94941b commit f7a04ee
Show file tree
Hide file tree
Showing 21 changed files with 890 additions and 405 deletions.
4 changes: 2 additions & 2 deletions Cython/Compiler/Builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ def declare_in_type(self, self_type):
# resulting in unintuitive runtime behavior and segfaults.
# ("bool", "&PyBool_Type", []),

("int", "&PyLong_Type", []),
("int", "API_LONG_TYPE_DEREF", []),
("float", "&PyFloat_Type", []),

("complex", "&PyComplex_Type", [BuiltinAttribute('cval', field_type_name = 'Py_complex'),
Expand Down Expand Up @@ -318,7 +318,7 @@ def declare_in_type(self, self_type):
utility_code=UtilityCode.load("PySequenceMultiply", "ObjectHandling.c")),
]),

("list", "&PyList_Type", [BuiltinMethod("insert", "TzO", "r", "PyList_Insert"),
("list", "&PyList_Type", [BuiltinMethod("insert", "TzO", "r", "LIST_INSERT"),
BuiltinMethod("reverse", "T", "r", "PyList_Reverse"),
BuiltinMethod("append", "TO", "r", "__Pyx_PyList_Append",
utility_code=UtilityCode.load("ListAppend", "Optimize.c")),
Expand Down
1 change: 1 addition & 0 deletions Cython/Compiler/Code.py
Original file line number Diff line number Diff line change
Expand Up @@ -1476,6 +1476,7 @@ def new_const_cname(self, prefix='', value=''):
prefix = Naming.interned_prefixes[prefix]
else:
prefix = Naming.const_prefix
self.const_cname_array.append("%s%s" % (prefix, name_suffix))
return "%s%s" % (prefix, name_suffix)

def get_cached_unbound_method(self, type_cname, method_name):
Expand Down
320 changes: 225 additions & 95 deletions Cython/Compiler/ExprNodes.py

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions Cython/Compiler/ModuleNode.py
Original file line number Diff line number Diff line change
Expand Up @@ -2236,7 +2236,7 @@ def generate_richcmp_function(self, scope, code):
code.putln("PyObject *ret;")
code.putln("ret = %s(o1, o2);" % comp_entry[ordering_source].func_cname)
code.putln("if (likely(ret && ret != Py_NotImplemented)) {")
code.putln("int order_res = __Pyx_PyObject_IsTrue(ret);")
code.putln("int order_res = __Pyx_PyObject_IsTrue(HPY_CONTEXT_FIRST_ARG_CALL ret);")
code.putln("Py_DECREF(ret);")
code.putln("if (unlikely(order_res < 0)) return NULL;")
# We may need to check equality too. For some combos it's never required.
Expand All @@ -2261,7 +2261,7 @@ def generate_richcmp_function(self, scope, code):

code.putln("ret = %s(o1, o2);" % comp_entry[eq_func].func_cname)
code.putln("if (likely(ret && ret != Py_NotImplemented)) {")
code.putln("int eq_res = __Pyx_PyObject_IsTrue(ret);")
code.putln("int eq_res = __Pyx_PyObject_IsTrue(HPY_CONTEXT_FIRST_ARG_CALL ret);")
code.putln("Py_DECREF(ret);")
code.putln("if (unlikely(eq_res < 0)) return NULL;")
if invert_equals:
Expand Down Expand Up @@ -2291,7 +2291,7 @@ def generate_richcmp_function(self, scope, code):
#code.putln("if (o1 == o2) return __Pyx_NewRef(Py_False);")
code.putln("ret = %s(o1, o2);" % comp_entry['__eq__'].func_cname)
code.putln("if (likely(ret && ret != Py_NotImplemented)) {")
code.putln("int b = __Pyx_PyObject_IsTrue(ret);")
code.putln("int b = __Pyx_PyObject_IsTrue(HPY_CONTEXT_FIRST_ARG_CALL ret);")
code.putln("Py_DECREF(ret);")
code.putln("if (unlikely(b < 0)) return NULL;")
code.putln("ret = (b) ? API_FALSE : API_TRUE;")
Expand Down Expand Up @@ -3152,8 +3152,8 @@ def generate_module_init_func(self, imported_modules, env, code):
Naming.empty_tuple, code.error_goto_if_null_object("TUPLE_CREATE_EMPTY()", self.pos)))
code.putln("PYOBJECT_GLOBAL_STORE(%s, BYTES_FROM_STR_AND_SIZE(\"\", 0)); %s" % (
Naming.empty_bytes, code.error_goto_if_null_object("BYTES_FROM_STR_AND_SIZE(\"\", 0)", self.pos)))
code.putln("PYOBJECT_GLOBAL_STORE(%s, HPY_LEGACY_OBJECT_FROM(PyUnicode_FromStringAndSize(\"\", 0))); %s" % (
Naming.empty_unicode, code.error_goto_if_null_object("HPY_LEGACY_OBJECT_FROM(PyUnicode_FromStringAndSize(\"\", 0))", self.pos)))
code.putln("PYOBJECT_GLOBAL_STORE(%s, PYOBJECT_UNICODE_FROM_STRING(\"\")); %s" % (
Naming.empty_unicode, code.error_goto_if_null_object("PYOBJECT_UNICODE_FROM_STRING(\"\")", self.pos)))

for ext_type in ('CyFunction', 'FusedFunction', 'Coroutine', 'Generator', 'AsyncGen', 'StopAsyncIteration'):
code.putln("#ifdef __Pyx_%s_USED" % ext_type)
Expand Down
32 changes: 24 additions & 8 deletions Cython/Compiler/Nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2445,9 +2445,9 @@ def generate_arg_type_test(self, arg, code):
code.globalstate.use_utility_code(
UtilityCode.load_cached("ArgTypeTest", "FunctionArguments.c"))
typeptr_cname = arg.type.typeptr_cname
arg_code = "((PyObject *)%s)" % arg.entry.cname
arg_code = "(CAST_IF_CAPI(PyObject *)%s)" % arg.entry.cname
code.putln(
'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, %s, %s))) %s' % (
'if (unlikely(!(__Pyx_ArgTypeTest(%s, %s, %d, %s, %s)))) %s' % (
arg_code,
typeptr_cname,
arg.accept_none,
Expand Down Expand Up @@ -5224,12 +5224,19 @@ def generate_execution_code(self, code):
self.dict.generate_evaluation_code(code)
if self.orig_bases:
# update __orig_bases__ if needed
code.putln("if (API_IS_NOT_EQUAL(%s, %s)) {" % (self.bases.result(), self.orig_bases.result()))
from .ExprNodes import LoadGlobalNode
load_bases = LoadGlobalNode(self.pos, self.bases.result())
load_orig_bases = LoadGlobalNode(self.pos, self.orig_bases.result())
load_bases.allocate(code)
load_orig_bases.allocate(code)
code.putln("if (API_IS_NOT_EQUAL(%s, %s)) {" % (load_bases.temp_cname, load_orig_bases.temp_cname))
code.putln(
code.error_goto_if_neg('DICT_SET_ITEM_STR(%s, "__orig_bases__", %s)' % (
self.dict.result(), self.orig_bases.result()),
self.dict.result(), load_orig_bases.temp_cname),
self.pos
))
load_bases.release(code)
load_orig_bases.release(code)
code.putln("}")
self.orig_bases.generate_disposal_code(code)
self.orig_bases.free_temps(code)
Expand Down Expand Up @@ -9064,13 +9071,22 @@ def generate_execution_code(self, code):
if self.interned_items:
code.globalstate.use_utility_code(
UtilityCode.load_cached("ImportFrom", "ImportExport.c"))

from . import ExprNodes

for name, target, coerced_item in self.interned_items:
load_module_result = ExprNodes.LoadGlobalNode(self.pos, self.module.py_result())
load_intern_id = ExprNodes.LoadGlobalNode(self.pos, code.intern_identifier(name))
load_module_result.allocate(code)
load_intern_id.allocate(code)
code.putln(
'%s = __Pyx_ImportFrom(%s, %s); %s' % (
'%s = __Pyx_ImportFrom(HPY_CONTEXT_FIRST_ARG_CALL %s, %s); %s' % (
item_temp,
self.module.py_result(),
code.intern_identifier(name),
code.error_goto_if_null(item_temp, self.pos)))
load_module_result.temp_cname,
load_intern_id.temp_cname,
code.error_goto_if_null_object(item_temp, self.pos)))
load_module_result.release(code)
load_intern_id.release(code)
code.put_gotref(item_temp, py_object_type)
if coerced_item is None:
target.generate_assignment_code(self.item, code)
Expand Down
6 changes: 3 additions & 3 deletions Cython/Compiler/PyrexTypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1568,7 +1568,7 @@ def type_check_function(self, exact=True):
elif type_name == 'frozenset':
type_check = 'PyFrozenSet_Check'
elif type_name == 'int':
type_check = 'PyLong_Check'
type_check = 'LONG_CHECK'
elif type_name == "memoryview":
# captialize doesn't catch the 'V'
type_check = "PyMemoryView_Check"
Expand All @@ -1585,12 +1585,12 @@ def type_test_code(self, arg, notnone=False, exact=True):
type_check = self.type_check_function(exact=exact)
check = 'likely(%s(%s))' % (type_check, arg)
if not notnone:
check += '||((%s) == Py_None)' % arg
check += '|| API_IS_EQUAL(%s, API_NONE_VALUE)' % arg
if self.name == 'basestring':
name = '(PY_MAJOR_VERSION < 3 ? "basestring" : "str")'
else:
name = '"%s"' % self.name
return check + ' || __Pyx_RaiseUnexpectedTypeError(%s, %s)' % (name, arg)
return check + ' || __Pyx_RaiseUnexpectedTypeError(HPY_CONTEXT_FIRST_ARG_CALL %s, %s)' % (name, arg)

def declaration_code(self, entity_code,
for_display = 0, dll_linkage = None, pyrex = 0):
Expand Down
4 changes: 4 additions & 0 deletions Cython/Compiler/UtilNodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,11 @@ def setup_temp_expr(self, code):
self.temp_expression.make_owned_reference(code)
self.temp = code.funcstate.allocate_temp(
self.temp_type, manage_ref=True)
code.putln("#if CYTHON_USING_HPY")
code.putln("%s = PYOBJECT_NEWREF(%s);" % (self.temp, self.temp_expression.result()))
code.putln("#else")
code.putln("%s = %s;" % (self.temp, self.temp_expression.result()))
code.putln("#endif")
self.temp_expression.generate_disposal_code(code)
self.temp_expression.free_temps(code)
self.lazy_temp.result_code = self.temp
Expand Down
2 changes: 1 addition & 1 deletion Cython/Utility/CommonStructures.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ static PYTYPEOBJECT_TYPE __Pyx_FetchCommonTypeFromSpec(HPY_CONTEXT_FIRST_ARG_DEF
PYOBJECT_TYPE py_basicsize;
py_basicsize = PYOBJECT_GET_ATTR_STR(cached_type, "__basicsize__");
if (unlikely(API_IS_NULL(py_basicsize))) goto bad;
basicsize = PYOBJECT_LONG_AS_SSIZE(py_basicsize);
basicsize = PYOBJECT_LONG_AS_SSIZE_T(py_basicsize);
PYOBJECT_CLOSEREF(py_basicsize);
py_basicsize = API_DEFAULT_VALUE;
if (unlikely(basicsize == (API_SSIZE_T)-1) && PYERR_OCCURRED()) goto bad;
Expand Down
15 changes: 8 additions & 7 deletions Cython/Utility/CythonFunction.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,11 @@ HPyType_HELPERS(__pyx_CyFunctionObject)

#undef __Pyx_CyOrPyCFunction_Check
#define __Pyx_CyFunction_Check(obj) __Pyx_TypeCheck(obj, PYOBJECT_GLOBAL_LOAD(__pyx_CyFunctionType))
#define __Pyx_CyOrPyCFunction_Check(obj) __Pyx_TypeCheck2(obj, __pyx_CyFunctionType, &PyCFunction_Type)
#if !CYTHON_USING_HPY
#define __Pyx_CyOrPyCFunction_Check(obj) __Pyx_TypeCheck2(obj, __pyx_CyFunctionType, &PyCFunction_Type)
#define __Pyx_CyFunction_CheckExact(obj) __Pyx_IS_TYPE(obj, __pyx_CyFunctionType)
#else
#define __Pyx_CyOrPyCFunction_Check(obj) __Pyx_TypeCheck(obj, PYOBJECT_GLOBAL_LOAD(__pyx_CyFunctionType)) //TODO(HPy): Loading here is a memory leak
#define __Pyx_CyFunction_CheckExact(obj) __Pyx_TypeCheck(obj, __pyx_CyFunctionType)
#endif
static CYTHON_INLINE int __Pyx__IsSameCyOrCFunction(HPY_CONTEXT_FIRST_ARG_DEF PYOBJECT_TYPE func, void *cfunc);/*proto*/
Expand Down Expand Up @@ -649,7 +650,7 @@ __Pyx_CyFunction_get_is_coroutine(HPY_CONTEXT_FIRST_ARG_DEF __pyx_CyFunctionObje
#if CYTHON_USING_HPY
return load_is_coroutine_temp;
#else
__Pyx_NewRef(load_is_coroutine_temp);
return __Pyx_NewRef(load_is_coroutine_temp);
#endif
}
ignore:
Expand All @@ -660,7 +661,7 @@ __Pyx_CyFunction_get_is_coroutine(HPY_CONTEXT_FIRST_ARG_DEF __pyx_CyFunctionObje
#if CYTHON_USING_HPY
return PYOBJECT_FIELD_LOAD(op, struct_op->func_is_coroutine);
#else
__Pyx_NewRef(struct_op->func_is_coroutine);
return __Pyx_NewRef(struct_op->func_is_coroutine);
#endif
}

Expand Down Expand Up @@ -688,7 +689,7 @@ __Pyx_CyFunction_get_is_coroutine(HPY_CONTEXT_FIRST_ARG_DEF __pyx_CyFunctionObje
// return NULL;
//}

#if CYTHON_COMPILING_IN_LIMITED_API
#if CYTHON_COMPILING_IN_LIMITED_API && !CYTHON_USING_HPY
static PyObject *
__Pyx_CyFunction_get_module(__pyx_CyFunctionObject *op, void *context) {
CYTHON_UNUSED_VAR(context);
Expand Down Expand Up @@ -722,7 +723,7 @@ static PyGetSetDef __pyx_CyFunction_getsets[] = {
{"__annotations__", (getter)__Pyx_CyFunction_get_annotations, (setter)__Pyx_CyFunction_set_annotations, 0, 0},
{"_is_coroutine", (getter)__Pyx_CyFunction_get_is_coroutine, 0, 0, 0},
// {"__signature__", (getter)__Pyx_CyFunction_get_signature, 0, 0, 0},
#if CYTHON_COMPILING_IN_LIMITED_API
#if CYTHON_COMPILING_IN_LIMITED_API && !CYTHON_USING_HPY
{"__module__", (getter)__Pyx_CyFunction_get_module, (setter)__Pyx_CyFunction_set_module, 0, 0},
#endif
{0, 0, 0, 0, 0}
Expand Down Expand Up @@ -1292,7 +1293,7 @@ static HPy __Pyx_CyFunction_hpycall_NOARGS_impl(HPyContext *HPY_CONTEXT_CNAME, H
def->meth.name, nargs);
return HPy_NULL;
}
HPyFunc_noargs func_noargs = def->meth.impl;
HPyFunc_noargs func_noargs = (HPyFunc_noargs) def->meth.impl;
result = func_noargs(HPY_CONTEXT_CNAME, self);
if (self_needs_close) {
HPy_Close(HPY_CONTEXT_CNAME, self);
Expand Down Expand Up @@ -1322,7 +1323,7 @@ static HPy __Pyx_CyFunction_hpycall_KEYWORDS_impl(HPyContext *HPY_CONTEXT_CNAME,
return HPy_NULL;
}

HPyFunc_keywords func_keywords = def->meth.impl;
HPyFunc_keywords func_keywords = (HPyFunc_keywords) def->meth.impl;
result = func_keywords(HPY_CONTEXT_CNAME, self, args, nargs, kwnames);
if (self_needs_close) {
HPy_Close(HPY_CONTEXT_CNAME, self);
Expand Down
4 changes: 4 additions & 0 deletions Cython/Utility/Exceptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -852,7 +852,11 @@ static PYOBJECT_TYPE __Pyx_PyCode_Replace_For_AddTraceback(HPY_CONTEXT_FIRST_ARG
if (likely(API_IS_NOT_NULL(replace))) {
PYOBJECT_TYPE result;
PYOBJECT_TYPE temp_empty_tuple = PYOBJECT_GLOBAL_LOAD($empty_tuple);
#if CYTHON_USING_HPY
result = HPy_CallTupleDict(HPY_CONTEXT_CNAME, replace, temp_empty_tuple, scratch_dict);
#else
result = API_CALL_FUNC(replace, &temp_empty_tuple, 0, scratch_dict);
#endif
PYOBJECT_CLOSEREF(replace);
PYOBJECT_CLOSEREF(temp_empty_tuple);
return result;
Expand Down
2 changes: 1 addition & 1 deletion Cython/Utility/FunctionArguments.c
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@ static CYTHON_INLINE PYOBJECT_TYPE __Pyx_GetKwValue_FASTCALL(HPY_CONTEXT_FIRST_A
}
for (i = 0; i < n; i++)
{
int eq = __Pyx_PyUnicode_Equals(HPY_LEGACY_OBJECT_AS(s), HPY_LEGACY_OBJECT_AS(TUPLE_GET_ITEM(kwnames, i)), Py_EQ);
int eq = __Pyx_PyUnicode_Equals(HPY_CONTEXT_FIRST_ARG_CALL s, TUPLE_GET_ITEM(kwnames, i), Py_EQ);
if (unlikely(eq != 0)) {
if (unlikely(eq < 0)) return API_NULL_VALUE; // error
return kwvalues[i];
Expand Down
Loading

0 comments on commit f7a04ee

Please sign in to comment.