Maison >développement back-end >tutoriel php >Explication détaillée du principe OpCode en PHP

Explication détaillée du principe OpCode en PHP

墨辰丷
墨辰丷original
2018-06-02 09:29:061990parcourir

Cet article présente principalement le principe OpCode de PHP et analyse plus en détail le mécanisme de compilation pertinent et le principe de fonctionnement du programme PHP. Les amis dans le besoin peuvent s'y référer

OpCode est un script PHP compilé intermédiaire. langage, comme le ByteCode de Java ou le MSL de .NET. Cet article est principalement basé sur « Comprendre l'OPcode » et Internet. Il est enregistré sur la base d'une compréhension et d'une modification personnelles :

Code PHP :

<?php
  echo "Hello World";
  $a = 1 + 1;
  echo $a;
?>

PHP passera par les 4 étapes suivantes lors de l'exécution de ce code :

1. Scanning (Lexing), convertir le code PHP en fragments de langage (Tokens)

2. Jetons en expressions simples et significatives
3. Compilation, compilez l'expression en Opocdes
4, exécutez les Opcodes séquentiellement, un à la fois, réalisant ainsi la fonction de script PHP.

Remarque : certains caches actuels, comme APC, peuvent permettre à PHP de mettre en cache les Opcodes. De cette façon, chaque fois qu'une requête arrive, il n'est pas nécessaire de répéter les trois premières étapes, ce qui peut grandement améliorer l'exécution. vitesse de PHP.

Tout d'abord, Zend/zend_lingual_scanner.c effectuera une analyse lexicale sur le code PHP d'entrée basé sur Zend/zend_lingual_scanner.l (fichier Lex) pour obtenir les "mots" un par un. PHP4.2+ commence à fournir A. une fonction appelée token_get_all est créée. Cette fonction peut scanner un morceau de code PHP en jetons

obtiendra les résultats suivants :

Array
(
  [0] => Array
    (
      [0] => 367
      [1] => <?php
      [2] => 1
    )
  [1] => Array
    (
      [0] => 370
      [1] =>
      [2] => 2
    )
  [2] => Array
    (
      [0] => 316
      [1] => echo
      [2] => 2
    )
  [3] => Array
    (
      [0] => 370
      [1] =>
      [2] => 2
    )
  [4] => Array
    (
      [0] => 315
      [1] => "Hello World"
      [2] => 2
    )
  [5] => ;
  [6] => Array
    (
      [0] => 370
      [1] =>
      [2] => 2
    )
  [7] => Array
    (
      [0] => 309
      [1] => $a
      [2] => 3
    )
  [8] => Array
    (
      [0] => 370
      [1] =>
      [2] => 3
    )
  [9] => =
  [10] => Array
    (
      [0] => 370
      [1] =>
      [2] => 3
    )
  [11] => Array
    (
      [0] => 305
      [1] => 1
      [2] => 3
    )
  [12] => Array
    (
      [0] => 370
      [1] =>
      [2] => 3
    )
  [13] => +
  [14] => Array
    (
      [0] => 370
      [1] =>
      [2] => 3
    )
  [15] => Array
    (
      [0] => 305
      [1] => 1
      [2] => 3
    )
  [16] => ;
  [17] => Array
    (
      [0] => 370
      [1] =>
      [2] => 3
    )
  [18] => Array
    (
      [0] => 316
      [1] => echo
      [2] => 4
    )
  [19] => Array
    (
      [0] => 370
      [1] =>
      [2] => 4
    )
  [20] => Array
    (
      [0] => 309
      [1] => $a
      [2] => 4
    )
  [21] => ;
  [22] => Array
    (
      [0] => 370
      [1] =>
      [2] => 4
    )
  [23] => Array
    (
      [0] => 369
      [1] => ?>
      [2] => 5
    )
)

Le résultat renvoyé, les chaînes, les caractères et les espaces dans le code source seront renvoyés inchangés. Les caractères de chaque code source apparaîtront dans l'ordre correspondant. Cependant, d'autres éléments tels que les balises, les opérateurs et les instructions seront convertis en un tableau contenant deux parties : l'ID du jeton (c'est-à-dire le code correspondant pour changer le jeton dans Zend, tel que T_ECHO, T_STRING) et le code original dans Zend. le contenu du code source.

L'étape suivante est l'étape d'analyse. L'analyse supprimera d'abord les espaces excédentaires dans le tableau de jetons, puis convertira les jetons restants en expressions simples un par un

1.

2. ajoutez deux nombres ensemble
3. stockez le résultat de l'expression précédente dans une variable
4. faites écho à une variable

Ensuite, changez l'étape de compilation, les jetons seront compilés. dans les op_arrays un par un. Chaque op_arrayd contient les 5 parties suivantes :

1 L'identification du numéro d'Opcode indique le type d'opération de chaque op_array, tel que add, echo

2. result
3. L'opérande 1 est l'opérande de l'Opcode
4. Opérande 2
5. La valeur étendue est un entier utilisé pour distinguer l'opérateur surchargé

Par exemple, le code PHP le fera. être analysé en :

[root@localhost html]# /usr/local/php/bin/php -dvld.active=1 hello.php
Branch analysis from position: 0
Return found
filename:    /var/www/html/hello.php
function name: (null)
number of ops: 6
compiled vars: !0 = $a
line   # op              fetch     ext return operands
-------------------------------------------------------------------------------
  2   0 ECHO                           &#39;Hello+world&#39;
  3   1 ADD                       ~0   1, 1
     2 ASSIGN                          !0, ~0
  4   3 ECHO                           !0
  6   4 RETURN                          1
     5* ZEND_HANDLE_EXCEPTION
Hello world2

Chaque opérande est composé des deux parties suivantes :

a) op_type : IS_CONST, IS_TMP_VAR, IS_VAR , IS_UNUSED, ou IS_CV

b) u, une union, qui stocke la valeur (const) ou la lvalue de l'opérande dans différents types en fonction de l'op_type (var)

Pour var, chaque variable est différente. IS_TMP_VAR, comme son nom l'indique, il s'agit d'une variable temporaire qui enregistre certains résultats de op_array pour une utilisation dans le prochain op_array. Le u de ce type d'opérande stocke un handle (entier) pointant vers la table de variables. utilisé~ Le début, tel que ~0, représente la variable temporaire inconnue IS_VAR au numéro 0 dans la table des variables. Il s'agit de notre variable générale. Ils commencent par $ pour représenter IS_CV, qui représente le type utilisé par les compilateurs après ZE2.1/. Mécanisme de cache PHP5.1, cette variable stocke l'adresse de la variable référencée par elle lorsqu'une variable est référencée pour la première fois, les références ultérieures à cette variable n'ont pas besoin de rechercher à nouveau la table des symboles active. . Les variables CV sont représentées en commençant par !.

La variable $a est optimisée à !0.

Résumé : Ce qui précède représente l'intégralité du contenu de cet article, j'espère qu'il sera utile à l'étude de chacun.

Recommandations associées :

Méthode d'utilisation du verrouillage pour implémenter la fonction de capture de code sous concurrence basée sur PHP

Chargement automatique PHP Méthode d'implémentation simple

Comparaison du temps d'exécution de quatre algorithmes de tri de base implémentés en PHP (à lire absolument)

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn