Objc Runtime Datenstruktur "objc_class" - das "cache" Element

  • Objc Runtime Datenstruktur "objc_class" - das "cache" Element

    Hallo,
    ich mache dieses Semester eine Seminarabeit über Objective-C und deren Runtime (die von Apple).

    Beim Durchkauen der objc_class Struktur, die die Daten einer Klasse hält habe ich mir u.a. den Methodencache angeschaut. Die Literatur sagt, dass beim Suchen nach einer Methode zuerst im Cache geschaut wird ob sich das Selektor/IMP-Paar (objc_method Struktur) der aufgerufene Methode bereits darin befindet. Falls nicht werden die Methodenlisten linear durchsucht. Wurde die Methode dann gefunden, wird das Selektor/IMP Paar im Cache gespeichert für zukünftige Aufrufe.

    Außerdem gilt: Caches grow dynamically to accommodate new messages as the program runs. und Once a program has been running long enough to “warm up” its caches, almost all the messages it sends find a cached method.

    Das wollte ich mir mittels Debugger mal anschauen. Dazu habe ich eine schwachsinnige Klasse mit ganzen drei Methoden (plus die von NSObject) erzeugt. In einer noch schwachsinnigeren main-Methode habe ich dann wahllos Methoden einer Instanz dieser Klasse (und von NSObject) aufgerufen.
    Dabei habe ich mir das cache Element von der zugehörigen objc_class Struktur angeschaut.
    Das komische ist, dass Xcode beim debuggen behauptet, dass immer nur eine Selekor/IMP-Paar im Cache ist. Nämlich immer die als letztes aufgerufene Methode. - Da frage ich mich jetzt: Soll ich Xcode glauben (es wäre nicht das erste mal, dass der Debugger absoluten Bockmist behauptet)?
    Und falls es tatsächlich stimmen sollte was angezeigt wird: Lügt sämtliche Literatur?
    Wie wird die Maximalgröße des Caches bestimmt? Vielleicht anhand der Anzahl eigener Methoden einer Klasse?

    Vielleicht hat sich hier ja jemand ebenfalls Gedanken darüber gemacht und kann mir weiterhelfen.
  • RE: Objc Runtime Datenstruktur "objc_class" - das "cache" Element

    Ich würde mal sagen: Gefährliche Falle.

    Wie schaust du die Größe des Arrays nach? Öffnest du es einfach in Xcode? Da hat jedes C-Array 1 Element. Das liegt einfach daran, dass Xcode nicht wissen kann, wie groß ein C-Array ist. Wie sollte das gehen?

    BTW: Da du etwas Interessantes zu machen scheinst, verweise ich mal hierhin:
    cocoading.de/OSXTreffen2007/Treffen.html

    Beachte auch den Punkt: "Erscheinungsbild". ;) Du erfüllst 2 von 2 Kriterien.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • ähm scheiße ja, genauso hab ich das gemacht mit Xcode. Das würde auch erklären warum mask und occupied vom struct objc_cache sich geändert haben und das angezeigte 1-Element-Array nicht... :)

    Das mit Treffen klingt gut, leider ists kurz vor meinen letzten Klausuren des Studiums - und die will ich noch mal voll auskosten :)

    Das von Nat! kenne ich noch nicht, werde es mir morgen aber mal anschauen. Jetzt habe ich keine Zeit, muss morgen früh raus.

    Danke soweit.
  • Nach längerer Beratung hat der einköpfige Treffensvorstand beschlossen, pr0n-Brillen und F*tzenbesen zuzulassen.


    ROFL Das nenn ich mal nen Spruch fürs Poesiealbum … oder so :D
    "Wales is the land of my fathers. And my fathers can have it." - Dylan Thomas
  • noch eine Frage zum "methodLists" bzw. "isa" Element von objc_class

    Hi,

    ich bin gerade auf folgende Ungereimtheit in verschiedener Literatur gestoßen, bzgl. des Speicherorts der Klassenmethoden einer Klasse.

    "Cocoa Programming" (Sams) sagt folgendes zum methodLists Element der objc_class Datenstruktur:
    The methodLists element is declared as objc_method_list **methodLists. The double pointer is used because multiple arrays of methods are stored. At a minimum, instance methods and class methods are stored in separate arrays.


    D.h. doch die Klassenmethoden sind im Klassenobjekt (isa Element in der objc_object Struktur) gespeichert. Zusammen mit allen Instanzmethoden. Klingt für mich plausibel - und ich wüsste nicht was dagegen sprechen sollte dies so zu tun.

    ABER: in "Objective-C Pocket Reference (O'Reilly) steht auch folgendes:
    If instance methods are stored in class objects, then were are the class methods stored? Class objects themselves have other objects to store the methods they responds to: these are called "metaclass objects".

    Laut diesem Buch ist die jeweilige Metaclass einer Klasse der Pointer auf die objc_class Struktur (isa Element), das in objc_class ebenfalls existiert.
    Im Buch von Sams steht zum isa Element in objc_class lediglich:
    The key to the definition of the Class structure is that it contains an isa element just like the objc_object structure. The first bytes of an objc_class structure have the same meaning as an objc_object structure. As a result, Objective-C classes are objects that can receive messages and can be used in any situation that any other object can be used.

    Auf jeden Fall behaupten die Buecher (nach meiner Interpretation) einen unterschiedlichen Speicherort für die Klassenmethoden einer Klasse. Ok, in Wirklichkeit sind das ja alles Pointer. Ist der Speicherort dann vielleicht doch gleich und die Pointer auf den selben Speicher exisitieren mehrmals?

    Weis zufällig jemand die ganze Wahrheit?




    Zur Übersicht nochmals die zwei Strukturen um die es geht:

    typedef struct objc_object {
    Class isa;
    } *id;

    typedef struct objc_class {
    struct objc_class *isa;
    struct objc_class *super_class;
    const char *name;
    long version;
    long info;
    long instance_size;
    struct objc_ivar_list *ivars;
    struct objc_method_list **methodLists;
    struct objc_cache *cache;
    struct objc_protocol_list *protocols;
    } *Class;
  • RE: noch eine Frage zum "methodLists" bzw. "isa" Element von objc_class

    Original von Graboid
    ABER: in "Objective-C Pocket Reference (O'Reilly) steht auch folgendes:
    If instance methods are stored in class objects, then were are the class methods stored? Class objects themselves have other objects to store the methods they responds to: these are called "metaclass objects".

    Kannst Du die Seitenzahl referenzieren?
    W.
    I would be embarrassed if they did not spy on me.
  • Ja, ich habe es gefunden, und die Darstellung stimmt: Klassen haben ihre eigenen Objekte, die Klassenobjekte, und eigene Methoden, die Klassenmethoden.
    Schau auch in Anguish/Buck/Yacktman: Cocoa Programing, Appendix A, Unleashing the Objective-C Runtime.
    I would be embarrassed if they did not spy on me.
  • Irgendwie kann ich mit deiner Antwort nichts anfagen. Die Zitate aus dem Sams Buch hatte ich aus dem Unleashing-Kapitel.

    Dass Klassen ihre eigene Klassenobjekte haben ist mir klar. Und das Klassen auch Klassenmethoden besitzten ist mir ebenfalls klar (die mit dem "+" davor im Header).

    Aber mein Problem ist, WO diese Klassenmethoden gespeichert werden.
    Das O'Reilly Pocket Reference Buch sagt in dem objc_method_list struct der Metaclass-Objekten. Das Sams Buch sagt, in dem objc_method_list struct des Klassenobjekt (zusammen mit den Instanzmethoden).
    Und es gilt ja Metaclass-Objekt != Klassenobjekt.

    instance->isa = Klassenobjekt
    instance->isa->isa = Metaclass Objekt
    Wobei beide der Datenstruktur objc_class entsprechen. Auf Seite 68 Figure 2 ist das im O'Reilly Buch ganz gut illustriert.
  • Ich habe da nicht genau genug gelesen, sonst ich die Gleichheit der Zitate von Dir und im Buch bemerkt. Aber SAMS ist ein großer Verlag, und das nicht das einzige Buch über Cocoa.
    Wie dem auch sei, die Passage in der 'pocket-reference' ab S. 66 verstehe ich auch nicht. Der Abschnitt davor deckt sich mit anderen Quellen: Klassenobjekte speichen alle Methoden in einem Feld von Feldern, wie auf S. 1070 Anguish et al. beschrieben.
    Das Feld wird dynamisch verwaltet, Methoden können hinzu gefügt werden etc., z.B. Protokolle, aber das Klassenobjekt verwaltet die Felder.
    Was das ganze mit "Metaklassen" soll, weiss ich so nicht. Für mich sind die ersten beide Sätze dort nicht richtig:
    If instance methods are stored in class objects, then were are the class methods stored? Class objects themselves have other objects to store the methods they responds to: these are called "metaclass objects".
    I would be embarrassed if they did not spy on me.
  • Ohne es nachgeprüft zu haben, scheint es mir auch logisch Unsinn zu sein.

    Instanzen einer Klasse haben alle denselbem Methodensatz. (Einer Instanz kann keine Methode hinzugefügt werden.) Deshalb kann man den Instanzmethodensatz (der eigentlich zur Instanz gehört) in der Klasse speichern. Klar.

    Das Klassenobjekt hat für die Klasse einen Methodensatz. Deshalb kann der Klassenmethodensatz in der Klasse gespeichert werden. (Erwartungsgemäß).

    Hieraus ergibt sich strukturell der gleiche Speicherort.

    "Meta"-Klassen sind nichts anderes als Die Klasse enes Klassenobjektes. Diese hat den Typen class. Dort, also in den Metaklassen, befänden sich dann die Methoden dieser Metaklasse. Nur hat class keine Methoden. Da gibt es nicht zu speichern. Insbesondere sind Methoden, die man dort erwarten könnte, wie etwa stringFromClass oder ähnliches, gerade keine (Instanz-)Methoden von class, sondern Funktionen.

    Kurz gesagt: Der von der Implementierung her gedachte notwendige Speicherort für alle Methoden ist das Klassenobjekt. Daher würde ich auch erwarten, dass sie in der Hierarchie an der gleichen Stelle gespeichert sind. Die abweichende Meinung scheint mir ein "Lost in hierarchy" zu sein.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Wenn man die Bibel nicht auslegen kann, muss man den Papst fragen. Zu Objective-C ist das Apple:
    Runtime Reference
    z.B.
    void class_removeMethods(Class aClass, struct objc_method_list* methodList)
    Parameters
    aClass
    A pointer to an objc_class data structure. To remove instance methods, pass the class definition from which you wish to remove the methods. To remove class methods, pass the metaclass definition (aClass->isa instead of aClass).
    etc.

    Ähnliches findet sich überall dort. Das ist eigentlich eindeutig.
    I would be embarrassed if they did not spy on me.
  • Das ist nicht das, was ich in der Klammer mente. Ich wollte sagen: Du kannst nicht die Methodenliste einer Instanz verändern. Du hast also zwei INstanzen von NSString und willst bei einer Instanz eine Methode entfernen. Das geht nicht. Du kannst die Instanzmethoden nur pro Klasse (also NSString) verändern. Das gilt dann für alle Instanzen der Klasse.

    Aber wieso nicht einfach ausprobieren?

    +++

    Aaaaaaaaaber, die Klassenmethoden in einem Metaobjekt zu speichern könnte doch Sinn haben. Zum Zeitpunkt der Laufzeit haben Methodennamen kein - und + mehr. Sie wären daher nicht mehr unterscheidbar. Irgendwie muss dsa aufgelöst werden.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Ich werde jetzt einfach das mir am logischsten vorkommende als "die Wahrheit" annehmen. Nämlich das Instanz- und Klassenmethoden im Klassenobjekt gespeichert sind. Also die SAMS-Version quasi.

    Wobei ich hier noch anmerken möchte, dass im SAMS Buch zum Teil auch grober Unfug steht:

    zum "super_class" Element in der Struktur "objc_class" steht dort folgender Satz:
    The super_class element points to the class that is used by the runtime to find a method to invoke if the receiver of a message does not provide such a method itself or when a message is sent to super.
    Außerdem steht dort ebenfalls: objc_msgSendSuper(...) begins the search for a method with the receiver's superclass [...]

    Den fett geschriebenen Teil meine ich. Die Klasse, die hinter dem super Schlüsselwort steckt, wird nämlich zur Kompilezeit festgelegt (nicht zur Laufzeit), da sonst unter bestimmten Umständen eine Endlosschleife entstehen könnte. (Beispiel Obj-C Pocket Reference O'REILLY Seite 24 "Special receivers").

    Bei einem normalen Methodenaufruf wie die Runtimefunktion "objc_msgSend(...)" verwendet, die als Parameter u.a. den Empfänger der Nachricht und den Selektor der Nachricht erhält. Für Aufrufe an "super" existiert extra die Runtimefunktion "objc_msgSendSuper(...)" die als Parameter neben dem Selektor eine Struktur "objc_super" entgegennimmt, die erzeugt wird sobald der Kompiler auf "super" stößt. Diese Struktur speichert zu einer Instanz (!) einer Klasse die entsprechende Elternklasse: "super" ist nicht die Elternklasse des Empfängers der Nachricht, sondern die Elternklasse der Klasse in der die Nachricht an "super" gesendet wird!

    Dies deckt sich auch mit Erläuterung der Objc Runtime Funktionen von Apple.


    Edit: Ich möchte das Buch hier keinesfalls schlecht reden! Es ist ein gutes Buch und es steht sehr viel Interessantes drin (zumindest fuer die Teile, die ich gelesen habe, kann ich das behaupten). Mir ist natürlich klar, dass nicht jedes Buch fehlerfrei sein kann. Ich wollte den Fehler hier nur mal anmerken. Der Fehler ist auch nicht so tragisch, da man intuitiv eigentlich vom richtigen Verhalten ausgeht und somit die Relevanz als Programmierer nicht so hoch ist.
  • Das von dir beschriebene Problem scheint mir absolut nachvollziehbar. Habe ich nämlich eine Instanz einer Subklasse instantiert und darin aber eine Methode -init nicht überschrieben, so lande ich in -init (Basiskasse). würde dort erneut [super init] aufgerufen (was naheliegend ist), so würde bei einer *Laufzeitsuche* die Basisklasse der tatsächlich instantierten Klasse durchsucht werden. Da befinde ich mich jedoch gerade, so dass exakt dieselbe Methode erneut aufgerufen würde -- bis in alle Ewigkeiten.

    Das muss zur Compilezeit aufgelöst werden.

    Zu deinem Ursprungsproblem scheint es dennoch so zu sein, dass aus welchen Gründen auch immer, die Klassenmethoden in einem gsonderten Objekt gespeichrt werden. Ich müsste mir das auch mal anschauen.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Nochmal nachgeschaut:
    Der Verwalter der Methoden ist die Klasse, und jedes Objekt kennt seine Klasse. nur wenn man die Klassenmethoden selbst ansprechen will, muss man das Klassenobjekt selbst aufrufen. Die Funktion heisst ja auch class_removeMethod.
    Was ich meinte ist das
    Und es gilt ja Metaclass-Objekt != Klassenobjekt.
    falsch ist.
    Es muss lauten:
    Metaclass-Objekt == Klassenobjekt

    Das Klassenobjekt hat 2 Funktionen, einmal ist es Vorlage für alle Instanzen, und dann Objekt für sich selbst als Instanz.
    I would be embarrassed if they did not spy on me.
  • id objc_msgSendSuper(struct objc_super* superContext, SEL theSelector, ...)
    ...
    Discussion
    When it encounters a method call, the compiler generates a call to one of the functions objc_msgSend, objc_msgSend_stret, objc_msgSendSuper, or objc_msgSendSuper_stret. Messages sent to an object’s superclass (using the super keyword) are sent using objc_msgSendSuper; other messages are sent using objc_msgSend. Methods that have data structures as return values are sent using objc_msgSendSuper_stret and objc_msgSend_stret.

    Ganz sehe ich den Fehler nicht, nur unscharfe Formulierungen. "super" wird vom pre-compiler in andere Funktionsaufrufe übersetzt.
    I would be embarrassed if they did not spy on me.
  • @longW

    ich denke wir haben, dass selbe gemeint mit

    Metaclass-Objekt != Klassenobjekt bzw. Metaclass-Objekt == Klassenobjekt.

    Beides ist ist eine objc_class Struktur. Die zu zwei verschiedene Zwecke genutzt werden kann. (Wie von dir erläutert). Laut der ObjC Runtime Reference von Apple existieren hierzu zwei Flags um dies anzuzeigen: CLS_CLASS(0x1L) und CLS_META(0x2L)

    Ist es vom Typ CLS_CLASS beinhaltet methodLists "all the instance methods that can be sent to objects that are instances of this class", ist es CLS_META gilt: "If this class is a metaclass definition, this field specifies the class methods of the class"