Grundlagen der JavaScript-Engine: Allgemeine Formulare und Inline-Caching. Teil 2

Hallo allerseits! Der Kurs "Sicherheit von Informationssystemen" beginnt in zwei Wochen. Daher möchten wir heute den zweiten Teil des Artikels veröffentlichen, dessen Veröffentlichung zeitlich auf den Start abgestimmt ist. Den ersten Teil können Sie hier lesen. Also fangen wir an.

Inline-Caches (ICs)

Die Hauptidee hinter den Formularen ist das Konzept von Inline-Caches oder ICs. Sie sind eine Schlüsselkomponente von schnellem JavaScript! JavaScript-Engines verwenden ICs, um Informationen darüber zu speichern, wo die Eigenschaften von Objekten zu finden sind, um die Anzahl kostspieliger Suchvorgänge zu verringern.



Wir haben eine getX Funktion, die ein Objekt als Eingabe verwendet und die x Eigenschaft daraus lädt:

 function getX(o) { return ox; } 

Wenn wir diese Funktion in JSC ausführen, erhalten wir den folgenden Bytecode:



Die erste get_by_id lädt die Eigenschaft 'x' aus dem ersten Argument (arg1) und speichert das Ergebnis in loc0 . Die folgende Anweisung gibt zurück, was wir in loc0 gespeichert loc0 .
JSC bettet auch den Inline-Cache in die get_by_id , die aus zwei nicht initialisierten Slots besteht.



getX wir getX an, wir rufen getX zusammen mit dem Objekt { x: 'a' } . Wir wissen bereits, dass dieses Objekt die Eigenschaft 'x' hat und seine Form den Versatz und die Attribute der Eigenschaft speichert. Wenn Sie die Funktion zum ersten Mal get_by_id , get_by_id die Anweisung get_by_id der Eigenschaft 'x' und stellt fest, dass ihr Wert bei Offset 0 gespeichert ist.



Der in die Anweisung integrierte get_by_id IC merkt sich die Form und den Versatz, in dem die Eigenschaft gefunden wurde.



Für nachfolgende IC-Starts müssen Sie nur das Formular vergleichen. Wenn es das gleiche wie zuvor ist, laden Sie einfach den Wert aus dem gespeicherten Offset. Insbesondere wenn die JavaScript-Engine Objekte mit einem Formular sieht, das er zuvor geschrieben hat, muss er im Allgemeinen nicht mehr nach Informationen zu diesen Eigenschaften fragen. Stattdessen kann eine teure Suche nach Informationen zu Eigenschaften vollständig übersprungen werden. Dies ist erheblich schneller, als jedes Mal nach Immobilien zu suchen.

Effiziente Speicherung von Arrays

Bei Arrays ist es üblich, Array-Indizes zu speichern. Die Werte solcher Eigenschaften werden als Array-Elemente bezeichnet. Es wäre verschwenderisch, Eigenschaftsattribute für jedes Element des Arrays in einem separaten Array zu speichern. Stattdessen stützen sich JavaScript-Engines auf die Tatsache, dass in einem Array indizierte Eigenschaften standardmäßig beschreibbar, aufzählbar und konfigurierbar sind. Außerdem speichern sie Array-Elemente getrennt von anderen benannten Eigenschaften.

Betrachten Sie das folgende Array:

 const array = [ '#jsconfeu', ]; 

Die Engine speichert ein Array von Einheitslängen und zeigt auf eine Form, die den Versatz und die Attribute für die Eigenschaft 'length' .



Dies ähnelt dem, was wir zuvor gesehen haben ... Aber wo werden die Werte der Array-Elemente gespeichert?



Jedes Array verfügt über einen separaten Element-Sicherungsspeicher, der alle vom Array indizierten Eigenschaftswerte enthält. Die JavaScript-Engine muss keine Eigenschaftsattribute für die Elemente des Arrays speichern, da diese normalerweise beschreibbar, aufzählbar und konfigurierbar sind.

Aber was passiert, wenn sie plötzlich nicht mehr für die Konfiguration verfügbar sind? Was ist, wenn Sie die Attribute einer Eigenschaft eines Array-Elements ändern?

 // Please don't ever do this! const array = Object.defineProperty( [], '0', { value: 'Oh noes!!1', writable: false, enumerable: false, configurable: false, } ); 

Das obige Code-Snippet definiert eine Eigenschaft namens '0' (in diesem Fall stellt sich heraus, dass es sich um einen Array-Index handelt). Es ändert die Attributwerte in nicht standardmäßige Werte.

In solchen extremen Fällen präsentiert die JavaScript-Engine den gesamten Sicherungsspeicher von Elementen als Wörterbuch, das Array-Indizes Eigenschaftsattributen zuordnet.



Selbst wenn nur ein Element des Arrays nicht standardmäßige Attribute aufweist, wird die gesamte Speicherung von Sicherungskopien von Elementen langsam und ineffizient ausgeführt. Vermeiden Sie Object.defineProperty in Array-Indizes! (Ich weiß nicht einmal, warum Sie es im Prinzip verwenden sollten. Es scheint seltsam und irrational.)

Schlussfolgerungen

Wir haben gelernt, wie JavaScript-Engines Objekte und Arrays speichern, wie Formulare und Inline-Caches zur Optimierung verschiedener Vorgänge beitragen. In diesem Artikel möchten wir Ihnen einige praktische Tipps für JavaScript geben, mit denen Sie die Leistung Ihres Codes steigern können:

  • Initialisieren Sie Ihre Objekte immer auf die gleiche Weise, damit sie keine unterschiedlichen Formen haben.
  • Spielen Sie nicht mit den Attributen der Eigenschaften der Elemente des Arrays, sondern geben Sie ihnen die Möglichkeit, sicher gespeichert zu werden und effizient zu arbeiten.

Jetzt kann der Artikel als vollständig betrachtet werden. Gemäß der etablierten Tradition warten wir auf Ihre Kommentare und laden Sie ein, sich für ein offenes Webinar zum Kurs "Sicherheit von Informationssystemen" anzumelden, das heute von einem bekannten Virenanalytiker und Teilzeitlehrer - Alexander Kolesnikov - abgehalten wird.

Lesen Sie den ersten Teil.

Source: https://habr.com/ru/post/de447220/


All Articles