diff --git a/method_dispatch.m b/method_dispatch.m --- a/method_dispatch.m +++ b/method_dispatch.m @@ -1,972 +1,970 @@ /* low_make_stub() returns the address of a function in ctx that * prepends data to the list of arguments, and then calls dispatch() * with the resulting argument list. * * Arguments: * ctx Context, usually just containing space for the machine code. * data Value to prepend in the argument list. * statc dispatch is a static method. * dispatch Function to call. * args Number of integer equvivalents to pass along. * flt_args bitfield: There are float arguments at these positions. * dbl_args bitfield: There are double arguments at these positions. */ #import #import #import #include #include "piobjc.h" #include extern void low_create_pike_object(ffi_cif* cif, void* resp, void** args, void* userdata); extern void low_f_objc_dynamic_instance_method(ffi_cif* cif, void* resp, void** args, void* userdata); void low_call_class_method(ffi_cif* cif, void* resp, void** args, void* userdata); #ifndef FFI_CLOSURES #error "No closures!" #endif #include #include #define _C_CONST 'r' #define _C_IN 'n' #define _C_INOUT 'N' #define _C_OUT 'o' #define _C_BYCOPY 'O' #define _C_BYREF 'R' #define _C_ONEWAY 'V' #define _C_LNG_LNG 'q' #define _C_ULNG_LNG 'Q' #define _C_BOOL 'B' /* (Objective-)C++ 'bool' */ /* These don't actually exist in the Objective-C runtime, but are used * by the bridge to simplify code. */ #define _C_UNICHAR 'T' #define _C_CHAR_AS_TEXT 't' #define _C_CHAR_AS_INT 'z' #define _C_NSBOOL 'Z' #ifndef MAX static inline int MAX(int x, int y) { return x > y ? x : y; } #endif static inline int ROUND(int v, int a) { if (v % a == 0) { return v; } else { return v + a - (v % a); } } const char* skip_type_qualifiers (const char* type) { while ( *type == _C_CONST || *type == _C_IN || *type == _C_INOUT || *type == _C_OUT || *type == _C_BYCOPY || *type == _C_BYREF || *type == _C_ONEWAY || *type == 'O') { type++; } while (*type && isdigit(*type)) type++; return type; } const char * skip_type_spec (const char *type) { type = skip_type_qualifiers (type); switch (*type) { case '"': /* Embedded name in ivar or compound type */ type++; while (*type != '\0' && *type != '"') type++; break; /* The following are one character type codes */ case _C_UNDEF: case _C_CLASS: case _C_SEL: case _C_CHR: case _C_UCHR: case _C_CHARPTR: #ifdef _C_ATOM case _C_ATOM: #endif #ifdef _C_BOOL case _C_BOOL: #endif case _C_SHT: case _C_USHT: case _C_INT: case _C_UINT: case _C_LNG: case _C_ULNG: case _C_FLT: case _C_DBL: case _C_VOID: case _C_LNG_LNG: case _C_ULNG_LNG: case _C_UNICHAR: case _C_CHAR_AS_TEXT: case _C_CHAR_AS_INT: case _C_NSBOOL: ++type; break; case _C_BFLD: while (isdigit (*++type)); break; case _C_ID: ++type; if (*type == '?') { /* Block pointer */ type++; } break; case _C_ARY_B: /* skip digits, typespec and closing ']' */ while (isdigit (*++type)); type = skip_type_spec (type); assert (type == NULL || *type == _C_ARY_E); if (type) type++; break; case _C_STRUCT_B: /* skip name, and elements until closing '}' */ while (*type != _C_STRUCT_E && *type++ != '='); while (type && *type != _C_STRUCT_E) { if (*type == '"') { /* embedded field names */ type = strchr(type+1, '"'); if (type != NULL) { type++; } else { return NULL; } } type = skip_type_spec (type); } if (type) type++; break; case _C_UNION_B: /* skip name, and elements until closing ')' */ while (*type != _C_UNION_E && *type++ != '='); while (type && *type != _C_UNION_E) { if (*type == '"') { /* embedded field names */ type = strchr(type+1, '"'); if (type != NULL) { type++; } else { return NULL; } } type = skip_type_spec (type); } if (type) type++; break; case _C_PTR: case _C_CONST: case _C_IN: case _C_INOUT: case _C_OUT: case _C_BYCOPY: case _C_BYREF: case _C_ONEWAY: /* Just skip the following typespec */ type = skip_type_spec (type+1); break; default: printf( "PyObjCRT_SkipTypeSpec: Unhandled type '%#x' %s", *type, type); Pike_error("skip_type_spec: unhandled type.\n"); return NULL; } /* The compiler inserts a number after the actual signature, * this number may or may not be usefull depending on the compiler * version. We never use it. */ while (type && *type && isdigit(*type)) type++; return type; } static ffi_type* objc_signature_to_ffi_type(const char* argtype) { argtype = skip_type_qualifiers(argtype); switch (*argtype) { case _C_VOID: return &ffi_type_void; case _C_ID: printf("arg type is id\n"); return &ffi_type_pointer; case _C_CLASS: return &ffi_type_pointer; case _C_SEL: printf("arg type is sel\n"); return &ffi_type_pointer; case _C_CHR: return &ffi_type_schar; case _C_CHAR_AS_INT: return &ffi_type_schar; case _C_CHAR_AS_TEXT: return &ffi_type_schar; #ifdef _C_BOOL case _C_BOOL: /* sizeof(bool) == 4 on PPC32, and 1 on all others */ return &ffi_type_schar; #endif case _C_NSBOOL: return &ffi_type_schar; case _C_UCHR: return &ffi_type_uchar; case _C_SHT: return &ffi_type_sshort; case _C_UNICHAR: return &ffi_type_ushort; case _C_USHT: return &ffi_type_ushort; case _C_INT: return &ffi_type_sint; case _C_UINT: return &ffi_type_uint; /* The next to defintions are incorrect, but the correct definitions * don't work (e.g. give testsuite failures). */ #ifdef __LP64__ case _C_LNG: return &ffi_type_sint64; /* ffi_type_slong */ case _C_ULNG: return &ffi_type_uint64; /* ffi_type_ulong */ #else case _C_LNG: return &ffi_type_sint; /* ffi_type_slong */ case _C_ULNG: return &ffi_type_uint; /* ffi_type_ulong */ #endif case _C_LNG_LNG: return &ffi_type_sint64; case _C_ULNG_LNG: return &ffi_type_uint64; case _C_FLT: printf("return type is float\n"); return &ffi_type_float; case _C_DBL: printf("return type is double\n"); return &ffi_type_double; case _C_CHARPTR: return &ffi_type_pointer; case _C_PTR: return &ffi_type_pointer; /* case _C_ARY_B: return array_to_ffi_type(argtype); */ case _C_IN: case _C_OUT: case _C_INOUT: case _C_CONST: #if 0 /* 'O' is used by remote objects ??? */ case 'O': #endif return objc_signature_to_ffi_type(argtype+1); /* case _C_STRUCT_B: return struct_to_ffi_type(argtype); */ case _C_UNDEF: return &ffi_type_pointer; default: printf("Type '%#x' (%c) not supported", *argtype, *argtype); return NULL; } } ffi_type* signature_to_ffi_return_type(const char* argtype) { #ifdef __ppc__ static const char long_type[] = { _C_LNG, 0 }; static const char ulong_type[] = { _C_ULNG, 0 }; switch (*argtype) { case _C_CHR: case _C_SHT: case _C_UNICHAR: return objc_signature_to_ffi_type(long_type); case _C_UCHR: case _C_USHT: //case _C_UNICHAR: return objc_signature_to_ffi_type(ulong_type); #ifdef _C_BOOL case _C_BOOL: return objc_signature_to_ffi_type(long_type); #endif case _C_NSBOOL: return objc_signature_to_ffi_type(long_type); default: return objc_signature_to_ffi_type(argtype); } #else return objc_signature_to_ffi_type(argtype); #endif } void * make_cif_for_method(Method method) { ffi_cif* cif; ffi_type** cl_arg_types; ffi_type* cl_ret_type; const char* rettype; ffi_status rv; int i; int numargs; char * arg; numargs = method_getNumberOfArguments(method); rettype = method_copyReturnType(method); cl_ret_type = signature_to_ffi_return_type(rettype); free(rettype); if (cl_ret_type == NULL) { printf("null return type!\n"); return NULL; } /* Build FFI argumentlist description */ LOG("cif will have num args: %d\n", numargs); - cl_arg_types = malloc(sizeof(ffi_type*) * (numargs)); + cl_arg_types = calloc(sizeof(ffi_type*) * (numargs), 1); if (cl_arg_types == NULL) { free(cl_ret_type); Pike_error("make_ffi_for_method: Unable to allocate memory.\n"); } for (i = 0; i < numargs; i++) { arg = method_copyArgumentType(method, i); cl_arg_types[i] = objc_signature_to_ffi_type(arg); free(arg); if (cl_arg_types[i] == NULL) { printf("arg type %d is null\n", i); free(cl_arg_types); return NULL; } } /* Create the invocation description */ - cif = malloc(sizeof(*cif)); + cif = calloc(sizeof(*cif), 1); if (cif == NULL) { free(cl_arg_types); Pike_error("make_ffi_for_method: Unable to allocate memory.\n"); } rv = ffi_prep_cif(cif, FFI_DEFAULT_ABI, numargs, cl_ret_type, cl_arg_types); if (rv != FFI_OK) { free(cif); free(cl_arg_types); printf("Cannot create FFI CIF: err=%d", rv); Pike_error("make_ffi_for_method: Unable to create cif.\n"); } return cif; } void * make_create_stub(struct program * prog) { static ffi_cif* init_cif = NULL; void * codeloc; ffi_closure * closure = NULL; ffi_status rv; ffi_type** cl_arg_types; ffi_type* cl_ret_type; const char* rettype; void (*disp)(ffi_cif*,void*,void**,void*) = low_create_pike_object; LOG("make_create_stub(%p)\n", prog); // since Objective-C classes cannot be un-registered, we just add a reference and forget about it. // technically this is not a leak, i think. add_ref(prog); if(init_cif == NULL) { - cl_arg_types = malloc(sizeof(ffi_type *) * 2); + cl_arg_types = calloc(sizeof(ffi_type *) * 2, 1); if(cl_arg_types == NULL) { Pike_error("make_init_stub: out of memory\n"); } cl_arg_types[0] = &ffi_type_pointer; cl_arg_types[1] = &ffi_type_pointer; - init_cif = malloc(sizeof(ffi_cif)); + init_cif = calloc(1, sizeof(ffi_cif)); rv = ffi_prep_cif(init_cif, FFI_DEFAULT_ABI, 2, &ffi_type_pointer, cl_arg_types); if(rv != FFI_OK) { free(init_cif); Pike_error("Cannot create FFI interface.\n"); } } closure = ffi_closure_alloc(sizeof(ffi_closure), &codeloc); - if(closure == ((void*)-1)) + if(!closure) { Pike_error("quick_make_stub: out of memory\n"); } rv = ffi_prep_closure_loc(closure, init_cif, disp, prog, codeloc); if(rv != FFI_OK) { free(closure); Pike_error("Cannot create FFI closure.\n"); } #if 0 // Ensure that the closure will execute on all architectures. if (mprotect(closure, sizeof(closure), PROT_READ | PROT_EXEC) == -1) { Pike_error("quick_make_stub: unable to make executable\n"); } #endif /* 0 */ return (void *)closure; } void * make_class_stub(struct program * prog) { static ffi_cif* init_cif = NULL; void * codeloc; ffi_closure * closure = NULL; ffi_status rv; ffi_type** cl_arg_types; ffi_type* cl_ret_type; const char* rettype; void (*disp)(ffi_cif*,void*,void**,void*) = low_get_pike_class; // since Objective-C classes cannot be un-registered, we just add a reference and forget about it. // technically this is not a leak, i think. add_ref(prog); if(init_cif == NULL) { - cl_arg_types = malloc(sizeof(ffi_type *) * 2); + cl_arg_types = calloc(sizeof(ffi_type *) * 2, 1); if(cl_arg_types == NULL) { Pike_error("make_init_stub: out of memory\n"); } cl_arg_types[0] = &ffi_type_pointer; cl_arg_types[1] = &ffi_type_pointer; - init_cif = malloc(sizeof(ffi_cif)); + init_cif = calloc(sizeof(ffi_cif), 1); rv = ffi_prep_cif(init_cif, FFI_DEFAULT_ABI, 2, &ffi_type_pointer, cl_arg_types); if(rv != FFI_OK) { free(init_cif); Pike_error("Cannot create FFI interface.\n"); } } closure = ffi_closure_alloc(sizeof(ffi_closure), &codeloc); - if(closure == ((void*)-1)) + if(!closure) { Pike_error("quick_make_stub: out of memory\n"); } rv = ffi_prep_closure_loc(closure, init_cif, disp, prog, codeloc); if(rv != FFI_OK) { free(closure); Pike_error("Cannot create FFI closure.\n"); } #if 0 // Ensure that the closure will execute on all architectures. if (mprotect(closure, sizeof(closure), PROT_READ | PROT_EXEC) == -1) { Pike_error("quick_make_stub: unable to make executable\n"); } #endif /* 0 */ return (void *)closure; } void * make_class_func_stub(struct program * prog, struct identifier * ident, struct sval * func, char * methodTypes) { int z; static ffi_cif* init_cif = NULL; void * codeloc; ffi_closure * closure = NULL; ffi_status rv; ffi_type** cl_arg_types; ffi_type* cl_ret_type; const char* rettype; struct class_func_dta * dta; struct svalue * sv; NSMethodSignature* methodSig; void (*disp)(ffi_cif*,void*,void**,void*) = low_call_class_method; // since Objective-C classes cannot be un-registered, we just add a reference and forget about it. // technically this is not a leak, i think. add_ref(prog); dta = malloc(sizeof(struct class_func_dta)); dta->prog = prog; dta->ident = ident; dta->type = methodTypes; sv = malloc(sizeof(struct svalue)); assign_svalue_no_free(sv, func); dta->func = sv; LOG("MAKING STUB: %s %s %p\n", dta->ident->name->str, methodTypes, func); if(init_cif == NULL) { int numargs; methodSig = [NSMethodSignature signatureWithObjCTypes: methodTypes]; numargs = [methodSig numberOfArguments]; - cl_arg_types = malloc(sizeof(ffi_type *) * numargs); + cl_arg_types = calloc(sizeof(ffi_type *) * numargs, 1); if(cl_arg_types == NULL) { Pike_error("make_init_stub: out of memory\n"); } cl_arg_types[0] = &ffi_type_pointer; cl_arg_types[1] = &ffi_type_pointer; for(z = 2; z < numargs; z++) { char t = [methodSig getArgumentTypeAtIndex: z]; switch(t) { case 'c': cl_arg_types[z] = &ffi_type_schar; break; case 'i': cl_arg_types[z] = &ffi_type_sint; break; case 's': cl_arg_types[z] = &ffi_type_sshort; break; case 'l': cl_arg_types[z] = &ffi_type_slong; break; case 'q': cl_arg_types[z] = &ffi_type_sint64; break; case 'C': cl_arg_types[z] = &ffi_type_uchar; break; case 'I': cl_arg_types[z] = &ffi_type_uint; break; case 'S': cl_arg_types[z] = &ffi_type_ushort; break; case 'L': cl_arg_types[z] = &ffi_type_ulong; break; case 'Q': cl_arg_types[z] = &ffi_type_uint64; break; case 'f': cl_arg_types[z] = &ffi_type_float; break; case 'd': cl_arg_types[z] = &ffi_type_double; break; case 'B': cl_arg_types[z] = &ffi_type_uint8; break; case 'v': cl_arg_types[z] = &ffi_type_void; break; case 'b': Pike_error("unknown Objective-C type encoding 'b'.\n"); break; default: cl_arg_types[z] = &ffi_type_pointer; break; } } - init_cif = malloc(sizeof(ffi_cif)); + init_cif = calloc(sizeof(ffi_cif), 1); rv = ffi_prep_cif(init_cif, FFI_DEFAULT_ABI, 2, &ffi_type_pointer, cl_arg_types); if(rv != FFI_OK) { free(init_cif); Pike_error("Cannot create FFI interface.\n"); } } closure = ffi_closure_alloc(sizeof(ffi_closure), &codeloc); - if(closure == ((void*)-1)) + if(!closure) { Pike_error("quick_make_stub: out of memory\n"); } rv = ffi_prep_closure_loc(closure, init_cif, disp, dta, codeloc); if(rv != FFI_OK) { free(closure); Pike_error("Cannot create FFI closure.\n"); } #if 0 // Ensure that the closure will execute on all architectures. if (mprotect(closure, sizeof(closure), PROT_READ | PROT_EXEC) == -1) { Pike_error("quick_make_stub: unable to make executable\n"); } #endif /* 0 */ return (void *)closure; } void * make_dynamic_method_stub(char * function_name) { static ffi_cif* init_cif = NULL; void * codeloc; ffi_closure * closure = NULL; ffi_status rv; ffi_type** cl_arg_types; ffi_type* cl_ret_type; const char* rettype; void (*disp)(ffi_cif*,void*,void**,void*) = low_f_objc_dynamic_instance_method; //printf("make_dynamic_method_stub(%s)\n", function_name); // since Objective-C classes cannot be un-registered, we just add a reference and forget about it. // technically this is not a leak, i think. if(init_cif == NULL) { - cl_arg_types = malloc(sizeof(ffi_type *)); + cl_arg_types = calloc(sizeof(ffi_type *), 1); if(cl_arg_types == NULL) { Pike_error("make_init_stub: out of memory\n"); } cl_arg_types[0] = &ffi_type_pointer; - init_cif = malloc(sizeof(ffi_cif)); + init_cif = calloc(sizeof(ffi_cif), 1); rv = ffi_prep_cif(init_cif, FFI_DEFAULT_ABI, 1, &ffi_type_pointer, cl_arg_types); if(rv != FFI_OK) { free(init_cif); Pike_error("Cannot create FFI interface.\n"); } } closure = ffi_closure_alloc(sizeof(ffi_closure), &codeloc); - if(closure == ((void*)-1)) + if(!closure) { Pike_error("quick_make_stub: out of memory\n"); } rv = ffi_prep_closure_loc(closure, init_cif, disp, strdup(function_name), codeloc); if(rv != FFI_OK) { free(closure); Pike_error("Cannot create FFI closure.\n"); } #if 0 // Ensure that the closure will execute on all architectures. if (mprotect(closure, sizeof(closure), PROT_READ | PROT_EXEC) == -1) { Pike_error("quick_make_stub: unable to make executable\n"); } #endif /* 0 */ return (void *)closure; } void * quick_make_stub(void * dta, void * func) { static ffi_cif* init_cif = NULL; void * codeloc; ffi_closure * closure = NULL; ffi_status rv; ffi_type** cl_arg_types; ffi_type* cl_ret_type; const char* rettype; if(init_cif == NULL) { - cl_arg_types = malloc(sizeof(ffi_type *) * 2); + cl_arg_types = calloc(sizeof(ffi_type *) * 2, 1); if(cl_arg_types == NULL) { Pike_error("quick_make_stub: out of memory\n"); } cl_arg_types[0] = &ffi_type_pointer; cl_arg_types[1] = &ffi_type_uint32; - init_cif = malloc(sizeof(ffi_cif)); + init_cif = calloc(sizeof(ffi_cif), 1); rv = ffi_prep_cif(init_cif, FFI_DEFAULT_ABI, 2, &ffi_type_pointer, cl_arg_types); if(rv != FFI_OK) { free(init_cif); Pike_error("Cannot create FFI interface.\n"); } } closure = ffi_closure_alloc(sizeof(ffi_closure), &codeloc); if(closure == ((void*)-1)) { Pike_error("quick_make_stub: out of memory\n"); } rv = ffi_prep_closure_loc(closure, init_cif, func, dta, codeloc); if(rv != FFI_OK) { free(closure); Pike_error("Cannot create FFI closure.\n"); } #if 0 // Ensure that the closure will execute on all architectures. if (mprotect(closure, sizeof(closure), PROT_READ | PROT_EXEC) == -1) { Pike_error("quick_make_stub: unable to make executable\n"); } #endif /* 0 */ return (void *)closure; } #if 0 void * make_static_stub(void * dta, void * func) { static ffi_cif* init_cif = NULL; void * codeloc; ffi_closure * closure = NULL; ffi_status rv; ffi_type** cl_arg_types; ffi_type* cl_ret_type; const char* rettype; if(init_cif == NULL) { - cl_arg_types = malloc(sizeof(ffi_type *) * 2); + cl_arg_types = calloc(sizeof(ffi_type *) * 2, 1); if(cl_arg_types == NULL) { Pike_error("quick_make_stub: out of memory\n"); } cl_arg_types[0] = &ffi_type_pointer; cl_arg_types[1] = &ffi_type_uint32; - init_cif = malloc(sizeof(ffi_cif)); + init_cif = calloc(sizeof(ffi_cif), 1); rv = ffi_prep_cif(init_cif, FFI_DEFAULT_ABI, 2, &ffi_type_void, cl_arg_types); if(rv != FFI_OK) { free(init_cif); Pike_error("Cannot create FFI interface.\n"); } } closure = ffi_closure_alloc(sizeof(ffi_closure), &codeloc); - if(closure == ((void*)-1)) + if(!closure) { Pike_error("quick_make_stub: out of memory\n"); } rv = ffi_prep_closure_loc(closure, init_cif, func, dta, codeloc); #if 0 // Ensure that the closure will execute on all architectures. if (mprotect(closure, sizeof(closure), PROT_READ | PROT_EXEC) == -1) { Pike_error("quick_make_stub: unable to make executable\n"); } #endif /* 0 */ if(rv != FFI_OK) { free(closure); Pike_error("Cannot create FFI closure.\n"); } else { printf("closure: %p\n", closure); return (void *)closure; } } #endif void * make_static_stub(void * dta, void * func) { static ffi_cif* init_cif; void * codeloc; ffi_closure * closure = NULL; ffi_status rv; ffi_type** cl_arg_types; ffi_type* cl_ret_type; const char* rettype; - cl_arg_types = malloc(sizeof(ffi_type *)*2); + cl_arg_types = calloc(sizeof(ffi_type *)*2, 1); if(cl_arg_types == NULL) { Pike_error("make_static_stub: out of memory\n"); } // cl_arg_types[0] = &ffi_type_pointer; cl_arg_types[0] = &ffi_type_uint32; - init_cif = malloc(sizeof(ffi_cif)); + init_cif = calloc(sizeof(ffi_cif), 1); if(init_cif == NULL) { Pike_error("make_static_stub: out of memory\n"); } rv = ffi_prep_cif(init_cif, FFI_DEFAULT_ABI, 1, &ffi_type_void, cl_arg_types); if(rv != FFI_OK) { free(init_cif); Pike_error("Cannot create FFI interface.\n"); } // Allocate a page to hold the closure with read and write permissions. - if ((closure = ffi_closure_alloc(sizeof(ffi_closure), &codeloc)) - == (void*)-1) + if (!(closure = ffi_closure_alloc(sizeof(ffi_closure), &codeloc))) { LOG("error mmap%s\n", ""); // Check errno and handle the error. } -// closure = malloc(sizeof(ffi_closure)); if(closure == NULL) { Pike_error("quick_make_stub: out of memory\n"); } rv = ffi_prep_closure_loc(closure, init_cif, func, dta, codeloc); if(rv != FFI_OK) { free(closure); Pike_error("Cannot create FFI closure.\n"); } // Ensure that the closure will execute on all architectures. if (mprotect(closure, sizeof(closure), PROT_READ | PROT_EXEC) == -1) { LOG("error mprotect%s\n", ""); // Check errno and handle the error. } return (void *)closure; } ffi_closure * make_static_stub3(void * dta, void * func) { static ffi_cif* init_cif; void * codeloc; ffi_closure * closure = NULL; ffi_status rv; ffi_type** cl_arg_types; ffi_type* cl_ret_type; const char* rettype; - cl_arg_types = malloc(sizeof(ffi_type *)*2); + cl_arg_types = calloc(sizeof(ffi_type *)*2, 1); if(cl_arg_types == NULL) { Pike_error("quick_make_stub: out of memory\n"); } // cl_arg_types[0] = &ffi_type_pointer; cl_arg_types[0] = &ffi_type_uint32; - init_cif = malloc(sizeof(ffi_cif)); + init_cif = calloc(sizeof(ffi_cif), 1); rv = ffi_prep_cif(init_cif, FFI_DEFAULT_ABI, 1, &ffi_type_void, cl_arg_types); if(rv != FFI_OK) { free(init_cif); Pike_error("Cannot create FFI interface.\n"); } // Allocate a page to hold the closure with read and write permissions. - if ((closure = ffi_closure_alloc(sizeof(ffi_closure), &codeloc) - ) == (void*)-1) + if (!(closure = ffi_closure_alloc(sizeof(ffi_closure), &codeloc) + ) ) { LOG("error mmap%s\n", ""); // Check errno and handle the error. } // closure = malloc(sizeof(ffi_closure)); if(closure == NULL) { Pike_error("quick_make_stub: out of memory\n"); } rv = ffi_prep_closure_loc(closure, init_cif, func, dta, codeloc); if(rv != FFI_OK) { free(closure); Pike_error("Cannot create FFI closure.\n"); } - + #if 0 // Ensure that the closure will execute on all architectures. if (mprotect(closure, sizeof(closure), PROT_READ | PROT_EXEC) == -1) { LOG("error mprotect%s\n", ""); // Check errno and handle the error. } #endif /* 0 */ return closure; } ffi_closure * make_static_stub2(void * dta, void * func) { ffi_closure * closure = make_static_stub3(dta, func); return closure; } void low_call_class_method(ffi_cif* cif, void* resp, void** args, void* userdata) { NSMethodSignature * methodSig; int count; int z; struct class_func_dta * func = (struct class_func_dta *)userdata; LOG("low_call_class_method: %s %p\n", func->ident->name->str, func->func); methodSig = [NSMethodSignature signatureWithObjCTypes: func->type]; count = [methodSig numberOfArguments]; LOG("method has %d arguments.\n", count); for(z = 2; z < count; z++) { push_objc_type([methodSig getArgumentTypeAtIndex: z], *((char *)args[1])); } // pargs = *((INT32 *)args[0]); apply_svalue(func->func, count-2); }