Un grand quotidien du soir s'alarmait dans ses colonnes, pourtant rarement ouvertes à la technique, du blocage des cookies tiers par défaut de la nouvelle version du navigateur Web de Mozilla, Firefox 22. Les zélateurs de la publicité ciblée font assaut de promptitude pour faire entendre leur voix. Après Google, fossoyeur de la presse écrite, Apple pourfendeur de la gratuité peccamineuse offerte par nos startups nationales dans le mobile, Mozilla, éradicateur de nos publicitaires culturellement exceptionnels ? Faut-il donc laisser le Web aux mains de quelques architectes programmeurs dont le radicalisme se fait entendre avec une certaine insistance ces derniers temps ?
Pour cantonner la réflexion au plan technique, quelques initiatives notables visent aujourd'hui à une redéfinition, à vrai dire plutôt une définition, de l'API du Web. Qu'est-ce à dire ?
Il est utile de rappeler que le Web n'a pas été initialement créé par des programmeurs pour des programmeurs. Aussi surprenant que cela puisse paraître aux yeux de la Génération Y, la « récupération » du Web par les entreprises comme territoire d'expansion est une opération de grande ampleur mais somme toute récente. Cette guerre de prédation primitive qui ne dit pas son nom est à l'origine de certaines des tensions aujourd'hui sensibles dans l'analyse du développement du Net : neutralité, sécurité, accès et contrôle sociétal, données et statistiques, propriété et Open Source, sont tous des sujets qui ont largement débordé des marches de l'empire des directions informatiques d'entreprise pour envahir la discussion globale du Web.
Dans un billet récent (#), John Resig, le démiurge du toolkit Javascript JQuery, succès fulgurant chez les développeurs d'applications Web, tresse des louanges que cette auréole JQuery revêt d'une qualité semi-divine à asm.js (#). C'est un projet de la fondation Mozilla visant à une spécification d'un langage assembleur pour les applications Web à partir du langage script Javascript, la lingua franca actuelle des programmeurs Web.
Faut-il rappeler à nos jeunes lecteurs que l'assembleur est un séducteur faustien qui apparaît dans la splendeur de la beauté du Diable. Il compense l'expression aride de ses phonèmes gutturaux par une performance d'exécution inégalée : sa proximité concupiscente des instructions machines du hardware emporte ainsi toutes les préventions linguistiques. Prenons, par exemple, ce court fragment de code source assembleur :
020252,000178: 35,2000 SETLOC CSI/CDH 020253,000179: 35,2000 BANK 020254,000180: 35,2000 E4,1770 EBANK= SUBEXIT 020255,000181: 35,2000 COUNT 35/P3474 020256,000182: 020257,000183: 35,2000 04627 P34 TC AVFLAGA 020258,000184: 35,2001 02003 TC P34/P74A 020259,000185: 35,2002 04642 P74 TC AVFLAGP 020260,000186: 35,2003 04647 P34/P74A TC P20FLGON # SET UPDATFLG, TRACKFLG
Même aux âmes les plus rébarbatives cet extrait insufflera une poésie musicale ineffable, et c'est miraculeusement ce même code qui mit en 1969 deux hommes sur la lune (#). Que l'invention géniale du stored program de Von Neumann retrouve à l'ère du Web toute sa portée conceptuelle est une joie toute pascalienne !
Car, comme l'indique Resig, un nouveau clan — un Clang pourrait-on dire — d'applications Javascript s'apprête à déferler sur le Web, signant le grand retour du Compilateur. On connaissait le retour en grâce, modeste néanmoins jusqu'à présent, du compilateur dans les navigateurs Web. Ces compilateurs Just In Time (JIT), comme IonMonkey (#) de Mozilla, utilisent les techniques éprouvées de l'indien Sioux en flairant des traces d'exécution des langages dynamiques laissées dans leurs interpréteurs (#) pour optimiser l'exécution ultérieure. Cette compilation JIT n'est pas propre au Web ; elle s'applique tout autant à Javascript qu'à d'autres langages populaires comme Python et qu'à des langages intermédiaires pour machines virtuelles comme CIL chez Microsoft ou le bytecode Java lui-même. Mais dans le cas présent, nous parlons bien du retour de Compilateur Khan, de l'idée pure et essentielle de recompiler des applications classiques et historiques, laborieusement écrites en C et C++ par les vétérans aux catogans grisonnants, vers Javascript, ramenant de facto le navigateur au rang d'environnement runtime.
Pour réussir ce retour en force, ces applications C/C++ traversent une nouvelle chaîne de compilation et de génération de code dont les développements, ces dernièes années, ont réussi à laisser quelque peu dans l'ombre le précurseur irrédentiste GNU. Les compilateurs paramétrables LLVM (#), habillés de frontaux comme CLang (#), qui nous avaient déjà esbaudis dans cette chronique (#), produisent un bytecode générique ouvert, que l'extraordinaire Emscripten (#) peut à son tour compiler en Javascript — et faire tourner ainsi sur le client dans le navigateur Web comme sur le serveur avec, par exemple, node.js (#), lui aussi initiateur d'un véritable écosystème Javascript pour le cloud. Dans le cas d'émerveillement évangélisé par Resig, la compilation produit un sous-ensemble de Javascript, appelé asm.js et présenté comme « l'assembleur » des applications Web.
Par conception, asm.js est de fonctionnalité limitée, un compromis accepté en échange d'une exécution ultra-rapide. La proximité d'asm.js avec les instructions machines permet en effet — et c'est l'idée directrice de Mozilla — au compilateur JIT Javascript embarqué dans le navigateur de reconnaître du code asm.js et de le passer, pratiquement sans transformation supplémentaire, à l'assembleur machine correspondant.
Bien sûr, les poètes d'entre nous ne trouveront peut-être pas dans asm.js :
function Vb(d) { d = d | 0; var e = 0, f = 0, h = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0; e = i; i = i + 12 | 0; f = e | 0; h = d + 12 | 0; j = c[h >> 2] | 0; if ((j | 0) > 0) { c[h >> 2] = 0; k = 0 } else { k = j } j = d + 24 | 0; if ((c[j >> 2] | 0) > 0) { c[j >> 2] = 0 } l = d + 28 | 0; c[l >> 2] = 0; c[l + 4 >> 2] = 0; l = (c[1384465] | 0) + 3 | 0; do { if (l >>> 0 < 26) { if ((4980736 >>> (l >>> 0) & 1 | 0) == 0) { break }
le même impair si soluble dans l'air qu'exhale un authentique assembleur S/370 transpirant le cambouis et l'huile de vidange :
//IEFBR14 JOB CLASS=A,MSGCLASS=A,RESTART=ASMF //*-------------------------------------------------------------------- //IEHPROGM EXEC PGM=IEHPROGM //SYSPRINT DD SYSOUT=* //MVS3380 DD UNIT=3380,VOL=SER=MVS809,DISP=SHR //SYSIN DD * SCRATCH DSNAME=JMM.S370ASM.LOAD,VOL=3380=MVS809 UNCATLG DSNAME=JMM.S370ASM.LOAD //*-------------------------------------------------------------------- //ALLOC EXEC PGM=IEFBR14 //LOAD DD DSN=JMM.S370ASM.LOAD, // UNIT=3380,VOL=SER=MVS809, // SPACE=(CYL,(20,0,15)), // DCB=(RECFM=U,BLKSIZE=32760), // DISP=(,CATLG) //*-------------------------------------------------------------------- //ASMF EXEC PGM=IFOX00,REGION=2048K //SYSLIB DD DSN=SYS1.AMODGEN,DISP=SHR // DD DSN=SYS1.AMACLIB,DISP=SHR //SYSUT1 DD DISP=(NEW,DELETE),SPACE=(1700,(900,100)),UNIT=SYSDA //SYSUT2 DD DISP=(NEW,DELETE),SPACE=(1700,(600,100)),UNIT=SYSDA //SYSUT3 DD DISP=(NEW,DELETE),SPACE=(1700,(600,100)),UNIT=SYSDA //SYSPRINT DD SYSOUT=* //SYSPUNCH DD DSN=&&OBJ,UNIT=SYSDA,SPACE=(CYL,1),DISP=(,PASS) //SYSIN DD * IEFBR14 CSECT , SLR 15,15 BR 14 END , //*------------------------------------------------------------------- //LKED EXEC PGM=IEWL, // COND=(5,LT,ASMF), // PARM='LIST,MAP,XREF,LET,NCAL,RENT' //SYSPRINT DD SYSOUT=* //SYSLMOD DD DSN=JMM.S370ASM.LOAD,DISP=SHR //* SLIB DD DSN=SYS1.LINKLIB,DISP=SHR //SYSUT1 DD UNIT=SYSDA,SPACE=(TRK,(5,5)) //SYSLIN DD DSN=&&OBJ,DISP=(OLD,DELETE) // DD * NAME IEFBR14(R) //*------------------------------------------------------------------- //IEFBR14 EXEC PGM=IEFBR14 //STEPLIB DD DSN=JMM.S370ASM.LOAD,DISP=SHR
mais impossible de mettre en doute l'efficacité du code engendré. Au point que l'éditeur de jeux Epic a réussi le tour de force de porter son moteur de jeux Unreal Engine 3 vers asm.js (#) et à faire tourner les jeux les plus consommateurs de ressources dans le navigateur Firefox et sous WebGL, un rendering pas particulièrement connu pour sa vélocité !
Tout ceci ne va pourtant pas sans chagriner quelques gardiens du temple de la Compilation éclairée (#). Pointant en particulier le fait que les compilateurs Javascript modernes sont déjà des fusées à plusieurs étages d'optimisation, comme Crankshaft dans V8 (#) chez Google, l'idée de réduire Javascript à un sous-ensemble n'est-elle pas contradictoire avec celle, devenue presque courante aujourd'hui, de créer plutôt des surensembles de Javascript, bénéficiant de l'empilement d'optimisations de ces compilateurs JIT. (Que l'on pense par exemple à TypeScript (#), CoffeeScript (#), voire à Dart (#), Script# (#) et autre espèces du bestiaire (#) scriptural.)
Mais bien plus, arguent ces Quirites contemporains, asm.js ne fait que porter le masque de Javascript. Il ne serait qu'un bytecode vulgum pecus paradant sur les voies impériales et menant ultimement à la confusion des genres. À cacher un bytecode dans un langage de haut niveau, ne court-on pas à la « pollution » du langage de haut niveau de features pertinents pour le seul bytecode de plus bas niveau ? Ce mariage morganatique est-il donc si fâcheux ?
Le débat sur l'approche radicaliste de l'architecture Web ne fait que s'ouvrir.