summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornicola <nicola@138bc75d-0d04-0410-961f-82ee72b054a4>2010-10-12 22:00:01 +0000
committernicola <nicola@138bc75d-0d04-0410-961f-82ee72b054a4>2010-10-12 22:00:01 +0000
commit1da9f882a280710491bb5a1148b12b5da60cbe82 (patch)
treec1e1a95aab3eeed0bec8d3d90946e13dff607e7d
parent76ab33ff6aebab59cae8c47c8ce8e0099b5aa55d (diff)
downloadgcc-1da9f882a280710491bb5a1148b12b5da60cbe82.tar.gz
2010-10-12 Nicola Pero <nicola.pero@meta-innovation.com>
* Makefile.in (C_SOURCE_FILES): Added methods.c. * encoding.c (method_getNumberOfArguments): New. (method_get_number_of_arguments): Call method_getNumberOfArguments. * ivars.c (ivar_getName): Check for NULL variable argument. (ivar_getOffset): Check for NULL variable argument. (ivar_getTypeEncoding): Check for NULL variable argument. (class_copyIvarList): New. * methods.c: New. * protocols.c (class_copyProtocolList): Check for Nil class_ argument. * sendmsg.c: Use 'struct objc_method *' instead of Method_t, and 'struct objc_method_list *' instead of MethodList_t. (class_getMethodImplementation): New. (class_respondsToSelector): New. (class_getInstanceMethod): New. (class_getClassMethod): New. * objc/runtime.h: Updated comments. (class_copyIvarList): New. (class_getInstanceMethod): New. (class_getClassMethod): New. (class_getMethodImplementation): New. (class_respondsToSelector): New. (method_getName): New. (method_getImplementation): New. (method_getTypeEncoding): New. (class_copyMethodList): New. (method_getNumberOfArguments): New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@165400 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--libobjc/ChangeLog31
-rw-r--r--libobjc/Makefile.in1
-rw-r--r--libobjc/encoding.c43
-rw-r--r--libobjc/ivars.c63
-rw-r--r--libobjc/methods.c114
-rw-r--r--libobjc/objc/runtime.h95
-rw-r--r--libobjc/protocols.c7
-rw-r--r--libobjc/sendmsg.c90
8 files changed, 407 insertions, 37 deletions
diff --git a/libobjc/ChangeLog b/libobjc/ChangeLog
index ec0a98f3790..300bb3e7e20 100644
--- a/libobjc/ChangeLog
+++ b/libobjc/ChangeLog
@@ -1,5 +1,36 @@
2010-10-12 Nicola Pero <nicola.pero@meta-innovation.com>
+ * Makefile.in (C_SOURCE_FILES): Added methods.c.
+ * encoding.c (method_getNumberOfArguments): New.
+ (method_get_number_of_arguments): Call
+ method_getNumberOfArguments.
+ * ivars.c (ivar_getName): Check for NULL variable argument.
+ (ivar_getOffset): Check for NULL variable argument.
+ (ivar_getTypeEncoding): Check for NULL variable argument.
+ (class_copyIvarList): New.
+ * methods.c: New.
+ * protocols.c (class_copyProtocolList): Check for Nil class_
+ argument.
+ * sendmsg.c: Use 'struct objc_method *' instead of Method_t, and
+ 'struct objc_method_list *' instead of MethodList_t.
+ (class_getMethodImplementation): New.
+ (class_respondsToSelector): New.
+ (class_getInstanceMethod): New.
+ (class_getClassMethod): New.
+ * objc/runtime.h: Updated comments.
+ (class_copyIvarList): New.
+ (class_getInstanceMethod): New.
+ (class_getClassMethod): New.
+ (class_getMethodImplementation): New.
+ (class_respondsToSelector): New.
+ (method_getName): New.
+ (method_getImplementation): New.
+ (method_getTypeEncoding): New.
+ (class_copyMethodList): New.
+ (method_getNumberOfArguments): New.
+
+2010-10-12 Nicola Pero <nicola.pero@meta-innovation.com>
+
* class.c: Include objc/runtime.h and objc-private/module-abi-8.h
instead of objc/objc-api.h.
(objc_get_unknown_class_handler): Do not define.
diff --git a/libobjc/Makefile.in b/libobjc/Makefile.in
index 4790f952b9d..b644b3f4832 100644
--- a/libobjc/Makefile.in
+++ b/libobjc/Makefile.in
@@ -173,6 +173,7 @@ C_SOURCE_FILES = \
init.c \
ivars.c \
memory.c \
+ methods.c \
nil_method.c \
objc-foreach.c \
objc-sync.c \
diff --git a/libobjc/encoding.c b/libobjc/encoding.c
index 87517f4eaf8..b30389ee0e4 100644
--- a/libobjc/encoding.c
+++ b/libobjc/encoding.c
@@ -797,22 +797,39 @@ objc_skip_argspec (const char *type)
return type;
}
-/*
- Return the number of arguments that the method MTH expects.
- Note that all methods need two implicit arguments `self' and
- `_cmd'.
-*/
-int
-method_get_number_of_arguments (struct objc_method *mth)
+unsigned int
+method_getNumberOfArguments (struct objc_method *method)
{
- int i = 0;
- const char *type = mth->method_types;
- while (*type)
+ if (method == NULL)
+ return 0;
+ else
{
- type = objc_skip_argspec (type);
- i += 1;
+ unsigned int i = 0;
+ const char *type = method->method_types;
+ while (*type)
+ {
+ type = objc_skip_argspec (type);
+ i += 1;
+ }
+
+ if (i == 0)
+ {
+ /* This could only happen if method_types is invalid; in
+ that case, return 0. */
+ return 0;
+ }
+ else
+ {
+ /* Remove the return type. */
+ return (i - 1);
+ }
}
- return i - 1;
+}
+
+int
+method_get_number_of_arguments (struct objc_method *mth)
+{
+ return method_getNumberOfArguments (mth);
}
/*
diff --git a/libobjc/ivars.c b/libobjc/ivars.c
index 52b71af1124..0dbb45b676a 100644
--- a/libobjc/ivars.c
+++ b/libobjc/ivars.c
@@ -26,8 +26,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "objc/runtime.h"
#include "objc-private/module-abi-8.h" /* For runtime structures */
#include "objc/thr.h"
-#include "objc-private/runtime.h" /* the kitchen sink */
-#include <string.h> /* For strcmp */
+#include "objc-private/runtime.h" /* the kitchen sink */
+#include <string.h> /* For strcmp */
struct objc_ivar *
class_getInstanceVariable (Class class_, const char *name)
@@ -157,15 +157,74 @@ void object_setIvar (id object, struct objc_ivar * variable, id value)
const char * ivar_getName (struct objc_ivar * variable)
{
+ if (variable == NULL)
+ return NULL;
+
return variable->ivar_name;
}
ptrdiff_t ivar_getOffset (struct objc_ivar * variable)
{
+ if (variable == NULL)
+ return 0;
+
return (ptrdiff_t)(variable->ivar_offset);
}
const char * ivar_getTypeEncoding (struct objc_ivar * variable)
{
+ if (variable == NULL)
+ return NULL;
+
return variable->ivar_type;
}
+
+struct objc_ivar ** class_copyIvarList (Class class_, unsigned int *numberOfReturnedIvars)
+{
+ unsigned int count = 0;
+ struct objc_ivar **returnValue = NULL;
+ struct objc_ivar_list* ivar_list;
+
+ if (class_ == Nil)
+ {
+ if (numberOfReturnedIvars)
+ *numberOfReturnedIvars = 0;
+ return NULL;
+ }
+
+ /* TODO: We do not need to lock the runtime mutex if the class has
+ been registered with the runtime, since the instance variable
+ list can not change after the class is registered. The only case
+ where the lock may be useful if the class is still being created
+ using objc_allocateClassPair(), but has not been registered using
+ objc_registerClassPair() yet. I'm not even sure that is
+ allowed. */
+ objc_mutex_lock (__objc_runtime_mutex);
+
+ /* Count how many ivars we have. */
+ ivar_list = class_->ivars;
+ count = ivar_list->ivar_count;
+
+ if (count != 0)
+ {
+ unsigned int i = 0;
+
+ /* Allocate enough memory to hold them. */
+ returnValue = (struct objc_ivar **)(malloc (sizeof (struct objc_ivar *) * (count + 1)));
+
+ /* Copy the ivars. */
+ for (i = 0; i < count; i++)
+ {
+ returnValue[i] = &(ivar_list->ivar_list[i]);
+ }
+
+ returnValue[i] = NULL;
+ }
+
+ objc_mutex_unlock (__objc_runtime_mutex);
+
+ if (numberOfReturnedIvars)
+ *numberOfReturnedIvars = count;
+
+ return returnValue;
+}
diff --git a/libobjc/methods.c b/libobjc/methods.c
new file mode 100644
index 00000000000..c6236a100e7
--- /dev/null
+++ b/libobjc/methods.c
@@ -0,0 +1,114 @@
+/* GNU Objective C Runtime method related functions.
+ Copyright (C) 2010 Free Software Foundation, Inc.
+ Contributed by Nicola Pero
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 3, or (at your option) any later version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#include "objc-private/common.h"
+#include "objc/runtime.h"
+#include "objc-private/module-abi-8.h" /* For runtime structures. */
+#include "objc/thr.h"
+#include "objc-private/runtime.h" /* For __objc_runtime_mutex. */
+#include <stdlib.h> /* For malloc. */
+
+SEL method_getName (struct objc_method * method)
+{
+ if (method == NULL)
+ return NULL;
+
+ return method->method_name;
+}
+
+const char * method_getTypeEncoding (struct objc_method * method)
+{
+ if (method == NULL)
+ return NULL;
+
+ return method->method_types;
+}
+
+IMP method_getImplementation (struct objc_method * method)
+{
+ if (method == NULL)
+ return NULL;
+
+ return method->method_imp;
+}
+
+struct objc_method ** class_copyMethodList (Class class_, unsigned int *numberOfReturnedMethods)
+{
+ unsigned int count = 0;
+ struct objc_method **returnValue = NULL;
+ struct objc_method_list* method_list;
+
+ if (class_ == Nil)
+ {
+ if (numberOfReturnedMethods)
+ *numberOfReturnedMethods = 0;
+ return NULL;
+ }
+
+ /* Lock the runtime mutex because the class methods may be
+ concurrently modified. */
+ objc_mutex_lock (__objc_runtime_mutex);
+
+ /* Count how many methods we have. */
+ method_list = class_->methods;
+
+ while (method_list)
+ {
+ count = count + method_list->method_count;
+ method_list = method_list->method_next;
+ }
+
+ if (count != 0)
+ {
+ unsigned int i = 0;
+
+ /* Allocate enough memory to hold them. */
+ returnValue
+ = (struct objc_method **)(malloc (sizeof (struct objc_method *)
+ * (count + 1)));
+
+ /* Copy the methods. */
+ method_list = class_->methods;
+
+ while (method_list)
+ {
+ int j;
+ for (j = 0; j < method_list->method_count; j++)
+ {
+ returnValue[i] = &(method_list->method_list[j]);
+ i++;
+ }
+ method_list = method_list->method_next;
+ }
+
+ returnValue[i] = NULL;
+ }
+
+ objc_mutex_unlock (__objc_runtime_mutex);
+
+ if (numberOfReturnedMethods)
+ *numberOfReturnedMethods = count;
+
+ return returnValue;
+}
diff --git a/libobjc/objc/runtime.h b/libobjc/objc/runtime.h
index a52c7611857..a11d283586f 100644
--- a/libobjc/objc/runtime.h
+++ b/libobjc/objc/runtime.h
@@ -284,16 +284,27 @@ objc_EXPORT id object_getIvar (id object, Ivar variable);
object_setInstanceVariable. */
objc_EXPORT void object_setIvar (id object, Ivar variable, id value);
-/* Return the name of the instance variable. */
+/* Return the name of the instance variable. Return NULL if
+ 'variable' is NULL. */
objc_EXPORT const char * ivar_getName (Ivar variable);
/* Return the offset of the instance variable from the start of the
- object data. */
+ object data. Return 0 if 'variable' is NULL. */
objc_EXPORT ptrdiff_t ivar_getOffset (Ivar variable);
-/* Return the type encoding of the variable. */
+/* Return the type encoding of the variable. Return NULL if
+ 'variable' is NULL. */
objc_EXPORT const char * ivar_getTypeEncoding (Ivar variable);
+/* Return all the instance variables of the class. The return value
+ of the function is a pointer to an area, allocated with malloc(),
+ that contains all the instance variables of the class. It does not
+ include instance variables of superclasses. The list is terminated
+ by NULL. Optionally, if you pass a non-NULL
+ 'numberOfReturnedIvars' pointer, the unsigned int that it points to
+ will be filled with the number of instance variables returned. */
+objc_EXPORT Ivar * class_copyIvarList (Class class_, unsigned int *numberOfReturnedIvars);
+
/** Implementation: the following functions are in class.c. */
@@ -412,6 +423,84 @@ objc_EXPORT void class_setVersion (Class class_, int version);
objc_EXPORT size_t class_getInstanceSize (Class class_);
+/** Implementation: the following functions are in sendmsg.c. */
+
+/* Return the instance method with selector 'selector' of class
+ 'class_', or NULL if the class (or one of its superclasses) does
+ not implement the method. Return NULL if class_ is Nil or selector
+ is NULL. */
+objc_EXPORT Method class_getInstanceMethod (Class class_, SEL selector);
+
+/* Return the class method with selector 'selector' of class 'class_',
+ or NULL if the class (or one of its superclasses) does not
+ implement the method. Return NULL if class_ is Nil or selector is
+ NULL. */
+objc_EXPORT Method class_getClassMethod (Class class_, SEL selector);
+
+/* Return the IMP (pointer to the function implementing a method) for
+ the instance method with selector 'selector' in class 'class_'.
+ This is the same routine that is used while messaging, and should
+ be very fast. Note that you most likely would need to cast the
+ return function pointer to a function pointer with the appropriate
+ arguments and return type before calling it. To get a class
+ method, you can pass the meta-class as the class_ argument (ie, use
+ class_getMethodImplementation (object_getClass (class_),
+ selector)). Return NULL if class_ is Nil or selector is NULL. */
+objc_EXPORT IMP class_getMethodImplementation (Class class_, SEL selector);
+
+/* Compatibility Note: the Apple/NeXT runtime has the function
+ class_getMethodImplementation_stret () which currently does not
+ exist on the GNU runtime because the messaging implementation is
+ different. */
+
+/* Return YES if class 'class_' has an instance method implementing
+ selector 'selector', and NO if not. Return NO if class_ is Nil or
+ selector is NULL. If you need to check a class method, use the
+ meta-class as the class_ argument (ie, use class_respondsToSelector
+ (object_getClass (class_), selector)). */
+objc_EXPORT BOOL class_respondsToSelector (Class class_, SEL selector);
+
+
+/** Implementation: the following functions are in methods.c. */
+
+/* Return the selector for method 'method'. Return NULL if 'method'
+ is NULL.
+
+ This function is misnamed; it should be called
+ 'method_getSelector'. To get the actual name, get the selector,
+ then the name from the selector (ie, use sel_getName
+ (method_getName (method))). */
+objc_EXPORT SEL method_getName (Method method);
+
+/* Return the IMP of the method. Return NULL if 'method' is NULL. */
+objc_EXPORT IMP method_getImplementation (Method method);
+
+/* Return the type encoding of the method. Return NULL if 'method' is
+ NULL. */
+objc_EXPORT const char * method_getTypeEncoding (Method method);
+
+/* Return all the instance methods of the class. The return value of
+ the function is a pointer to an area, allocated with malloc(), that
+ contains all the instance methods of the class. It does not
+ include instance methods of superclasses. The list is terminated
+ by NULL. Optionally, if you pass a non-NULL
+ 'numberOfReturnedMethods' pointer, the unsigned int that it points
+ to will be filled with the number of instance methods returned. To
+ get the list of class methods, pass the meta-class in the 'class_'
+ argument, (ie, use class_copyMethodList (object_getClass (class_),
+ &numberOfReturnedMethods)). */
+objc_EXPORT Method * class_copyMethodList (Class class_, unsigned int *numberOfReturnedMethods);
+
+
+/** Implementation: the following functions are in encoding.c. */
+
+/* Return the number of arguments that the method 'method' expects.
+ Note that all methods need two implicit arguments ('self' for the
+ receiver, and '_cmd' for the selector). Return 0 if 'method' is
+ NULL. */
+objc_EXPORT unsigned int method_getNumberOfArguments (Method method);
+
+
/** Implementation: the following functions are in protocols.c. */
/* Return the protocol with name 'name', or nil if it the protocol is
diff --git a/libobjc/protocols.c b/libobjc/protocols.c
index 6d429803c8f..bc714ae63ae 100644
--- a/libobjc/protocols.c
+++ b/libobjc/protocols.c
@@ -211,6 +211,13 @@ class_copyProtocolList (Class class_, unsigned int *numberOfReturnedProtocols)
Protocol **returnValue = NULL;
struct objc_protocol_list* proto_list;
+ if (class_ == Nil)
+ {
+ if (numberOfReturnedProtocols)
+ *numberOfReturnedProtocols = 0;
+ return NULL;
+ }
+
/* Lock the runtime mutex because the class protocols may be
concurrently modified. */
objc_mutex_lock (__objc_runtime_mutex);
diff --git a/libobjc/sendmsg.c b/libobjc/sendmsg.c
index 02be39c5b05..d68e3040f4f 100644
--- a/libobjc/sendmsg.c
+++ b/libobjc/sendmsg.c
@@ -1,6 +1,6 @@
/* GNU Objective C Runtime message lookup
Copyright (C) 1993, 1995, 1996, 1997, 1998,
- 2001, 2002, 2004, 2009 Free Software Foundation, Inc.
+ 2001, 2002, 2004, 2009, 2010 Free Software Foundation, Inc.
Contributed by Kresten Krab Thorup
This file is part of GCC.
@@ -91,8 +91,8 @@ static __big
static id
#endif
__objc_block_forward (id, SEL, ...);
-static Method_t search_for_method_in_hierarchy (Class class, SEL sel);
-Method_t search_for_method_in_list (MethodList_t list, SEL op);
+static struct objc_method * search_for_method_in_hierarchy (Class class, SEL sel);
+struct objc_method * search_for_method_in_list (struct objc_method_list * list, SEL op);
id nil_method (id, SEL);
/* Given a selector, return the proper forwarding implementation. */
@@ -193,11 +193,22 @@ get_imp (Class class, SEL sel)
return res;
}
+/* The new name of get_imp(). */
+IMP
+class_getMethodImplementation (Class class_, SEL selector)
+{
+ if (class_ == Nil || selector == NULL)
+ return NULL;
+
+ /* get_imp is inlined, so we're good. */
+ return get_imp (class_, selector);
+}
+
/* Given a method, return its implementation. */
IMP
-method_get_imp (Method_t method)
+method_get_imp (struct objc_method * method)
{
- return (method != (Method_t)0) ? method->method_imp : (IMP)0;
+ return (method != (struct objc_method *)0) ? method->method_imp : (IMP)0;
}
/* Query if an object can respond to a selector, returns YES if the
@@ -225,6 +236,30 @@ __objc_responds_to (id object, SEL sel)
return (res != 0);
}
+BOOL
+class_respondsToSelector (Class class_, SEL selector)
+{
+ void *res;
+
+ if (class_ == Nil || selector == NULL)
+ return NO;
+
+ /* Install dispatch table if need be */
+ if (class_->dtable == __objc_uninstalled_dtable)
+ {
+ objc_mutex_lock (__objc_runtime_mutex);
+ if (class_->dtable == __objc_uninstalled_dtable)
+ {
+ __objc_install_dispatch_table_for_class (class_);
+ }
+ objc_mutex_unlock (__objc_runtime_mutex);
+ }
+
+ /* Get the method from the dispatch table */
+ res = sarray_get_safe (class_->dtable, (size_t) selector->sel_id);
+ return (res != 0);
+}
+
/* This is the lookup function. All entries in the table are either a
valid method *or* zero. If zero then either the dispatch table
needs to be installed or it doesn't exist and forwarding is attempted. */
@@ -374,11 +409,11 @@ __objc_send_initialize (Class class)
{
SEL op = sel_register_name ("initialize");
IMP imp = 0;
- MethodList_t method_list = class->class_pointer->methods;
+ struct objc_method_list * method_list = class->class_pointer->methods;
while (method_list) {
int i;
- Method_t method;
+ struct objc_method * method;
for (i = 0; i < method_list->method_count; i++) {
method = &(method_list->method_list[i]);
@@ -409,7 +444,7 @@ __objc_send_initialize (Class class)
method nothing is guaranteed about what method will be used.
Assumes that __objc_runtime_mutex is locked down. */
static void
-__objc_install_methods_in_dtable (Class class, MethodList_t method_list)
+__objc_install_methods_in_dtable (Class class, struct objc_method_list * method_list)
{
int i;
@@ -421,7 +456,7 @@ __objc_install_methods_in_dtable (Class class, MethodList_t method_list)
for (i = 0; i < method_list->method_count; i++)
{
- Method_t method = &(method_list->method_list[i]);
+ struct objc_method * method = &(method_list->method_list[i]);
sarray_at_put_safe (class->dtable,
(sidx) method->method_name->sel_id,
method->method_imp);
@@ -492,7 +527,7 @@ __objc_update_dispatch_table_for_class (Class class)
methods installed right away, and their selectors are made into
SEL's by the function __objc_register_selectors_from_class. */
void
-class_add_method_list (Class class, MethodList_t list)
+class_add_method_list (Class class, struct objc_method_list * list)
{
/* Passing of a linked list is not allowed. Do multiple calls. */
assert (! list->method_next);
@@ -507,27 +542,44 @@ class_add_method_list (Class class, MethodList_t list)
__objc_update_dispatch_table_for_class (class);
}
-Method_t
+struct objc_method *
class_get_instance_method (Class class, SEL op)
{
return search_for_method_in_hierarchy (class, op);
}
-Method_t
+struct objc_method *
class_get_class_method (MetaClass class, SEL op)
{
return search_for_method_in_hierarchy (class, op);
}
+struct objc_method *
+class_getInstanceMethod (Class class_, SEL selector)
+{
+ if (class_ == Nil || selector == NULL)
+ return NULL;
+
+ return search_for_method_in_hierarchy (class_, selector);
+}
+
+struct objc_method *
+class_getClassMethod (Class class_, SEL selector)
+{
+ if (class_ == Nil || selector == NULL)
+ return NULL;
+
+ return search_for_method_in_hierarchy (class_->class_pointer,
+ selector);
+}
/* Search for a method starting from the current class up its hierarchy.
Return a pointer to the method's method structure if found. NULL
otherwise. */
-
-static Method_t
+static struct objc_method *
search_for_method_in_hierarchy (Class cls, SEL sel)
{
- Method_t method = NULL;
+ struct objc_method * method = NULL;
Class class;
if (! sel_is_mapped (sel))
@@ -546,10 +598,10 @@ search_for_method_in_hierarchy (Class cls, SEL sel)
/* Given a linked list of method and a method's name. Search for the named
method's method structure. Return a pointer to the method's method
structure if found. NULL otherwise. */
-Method_t
-search_for_method_in_list (MethodList_t list, SEL op)
+struct objc_method *
+search_for_method_in_list (struct objc_method_list * list, SEL op)
{
- MethodList_t method_list = list;
+ struct objc_method_list * method_list = list;
if (! sel_is_mapped (op))
return NULL;
@@ -562,7 +614,7 @@ search_for_method_in_list (MethodList_t list, SEL op)
/* Search the method list. */
for (i = 0; i < method_list->method_count; ++i)
{
- Method_t method = &method_list->method_list[i];
+ struct objc_method * method = &method_list->method_list[i];
if (method->method_name)
if (method->method_name->sel_id == op->sel_id)