Así que, ahora que hemos echado un vistazo rápido a la historia, veamos cómo son estos archivos de clase en realidad. Así que, si volvemos al ejemplo de compilación simple, ¿qué contiene este archivo hello.class? Un lío binario. Podemos ver los nombres de algunas otras clases, pero, sí, eso no es muy útil. Así que, los archivos de clase en sí están empaquetados en archivos jar, y cada archivo de clase se ve algo así como esto, donde tienes este pool de constantes, tienes algunos metadatos, tienes algunos campos, y tienes el código real en sí.
Los métodos cada uno tiene una especie de descriptor de método que describe los tipos de las entradas y las salidas. Así que, tenemos este tipo de parámetros entre paréntesis y luego el tipo de retorno después. Y los tipos primitivos de Java se mapean a estas pequeñas letras, así que, como, byte es B, char es C, long es J, por supuesto, y así sucesivamente.
Así que, ahora que podemos analizar estos archivos de clase, hablemos sobre la compilación y la llamada a funciones con ellos. Así que, tenemos los descriptores de métodos, tenemos el bytecode. Así que, podemos comenzar a transformarlo a WebAssembly. Para hacer esto, podemos simplemente hacer un patrón de coincidencia en los descriptores que hemos analizado anteriormente y convertirlos a tipos de WebAssembly, y de manera similar para las instrucciones, podemos simplemente tomar las instrucciones de la JVM y convertirlas a WebAssembly. Esto va a ser realmente fácil. Y eso es más o menos todo lo que necesitamos para la compilación básica. Cuando tienes esto, para ejecutarlo, puedes simplemente envolverlo con un módulo de WebAssembly, y luego puedes exportarlo, y luego tenemos este formato de texto que en realidad no podemos ejecutar, así que lo convertimos al formato binario, y obtenemos este código de Node.js, que es súper agradable, porque solo tenemos que leer el archivo, podemos compilar eso en un módulo de WebAssembly, instanciarlo y llamar a sus exportaciones.
Genial, esto es tan fácil. Hemos terminado. Oh, espera, un momento, no, no hemos terminado. Así que, también podemos llamar a la función desde dentro de WebAssembly, lo cual es agradable, pero espera un momento, tenemos un primer problema. Java te permite hacer sobrecargas de métodos, donde puedes tener el mismo método, el mismo nombre, pero solo, como, diferentes parámetros en su lugar. Y podemos implementar esto en WebAssembly. Podemos simplemente poner los descriptores de métodos en los nombres de las funciones y tratarlos como funciones separadas. Eso funciona, está bien. Pero hay una pequeña sutileza aquí. En, a pesar de que estamos añadiendo dos de las mismas cosas, en el ejemplo de enteros, el segundo entero se carga desde el índice uno, y en el ejemplo de dobles, el segundo doble se carga desde el índice dos. Esta es una especie de peculiaridad de cómo Java almacena estos locales. Así que, Java trata los locales como slots de cuatro bytes, y los ints son una palabra cada uno, los dobles son dos palabras, y el problema es que WebAssembly espera valores tipados únicos para locales. Así que, cuando creas un local en WebAssembly, tienes que definir su tipo de antemano, y solo puede ser ese tipo.
Comments