Tema 7 - Jamaica

Anuncio
TEMA 7: Jamaica, macroensamblador de JVM
Contenido
1.
Arquitectura de la JVM .........................................................................................................2
2.
Reglas léxico-sintácticas de Jamaica .....................................................................................2
3.
Paquetes y clases .................................................................................................................3
4.
Métodos ...............................................................................................................................3
5.
Instrucciones ........................................................................................................................4
5.1 Runtime de la JVM (Cuando un método invoca a otro) .....................................................4
6.
5.2
Notación de las instrucciones .......................................................................................4
5.3
Carga de constantes .....................................................................................................4
5.4
Acceso a variables y parámetros ..................................................................................4
5.5
Operaciones con arrays ................................................................................................5
5.6
Acceso a atributos ........................................................................................................5
5.7
Instrucciones de tipos de datos ....................................................................................6
5.8
Creación de objetos y arrays ........................................................................................6
5.9
Instrucciones aritméticas y lógicas ...............................................................................6
5.10
Manipulación de la pila ................................................................................................7
5.11
Llamadas a métodos .....................................................................................................7
5.12
Instrucciones de saltos incondicionales ........................................................................7
5.13
Instrucciones de saltos condicionales ...........................................................................8
Macros .................................................................................................................................8
1. Arquitectura de la JVM
TAREA 1
TAREA N
Frame 1.k
Frame N.k
.
.
.
.
.
.
…
Frame 1.1
Frame N.1
!!!"!#$%&'!!(
!!!"!#$%&'!!(
PC
Zona
de código y
constantes
Contador de
PROGRAMA 1
.
.
.
PC TAREA N
PC
!!!!!!"!#$%&'!!!!!!(
FRAME
PILA DE OPERANDOS
MEMORIA
DINÁMICA
INSTANCIAS
SP
VARIABLES LOCALES
PARÁMETROS
- OBJETOS
- ARRAYS
!!!!!!"!#$%&'!!!!!!(
DIREC. OBJETO PROPIO
(this)
!!!!!!!!!!!!"!#$%&'!!!!!!!!!!(
JVM está basada en pila, no en registro.
Para cada tarea hay una pila de frames y un contador de programa
Los frames almacena información de los métodos que se están ejecutando.
El frame activo es el que estará en la cima de la pila.
El main será el FRAME 1.k (es el primero que se llama).
L-0 va a trabajar con una sola pila de frames.
2. Reglas léxico-sintácticas de Jamaica
Comentarios (Línea y bloque): igual que en Java
Identificadores: igual que en Java
Palabras reservadas: igual que en Java además de las instrucciones bytecode de la JVM
Tipos de datos: igual que en Java
o Primitivos: byte(1), short(2), int(4), long(8), char(2), float(4), double(8) y
boolean (Jamaica los trata como enteros 0 ó 1) .
o Referencia: objeto y array.
Los macros comienzan por “%”.
Las instrucciones bytecode y los macros no terminan en “;”.
Ejemplo:
int i;
iconst_1
%println “hola”
//instrucción bytecode
//macro
3. Paquetes y clases
Se definen con la misma sintaxis que Java. Cada clase se coloca en un fichero “.ja”
package x;
//Nombre del módulo que contiene a la clase
(import y;)*
//Paquetes/Clases importadas
[public/private] class nombreClase {
//atributos y métodos
}
Los atributos se declaran igual que en Java, pero NO se pueden inicializar (para
inicializarlos se usa un constructor o un bloque estático). Hay tres paquetes que son
autoimportados: java.lang.*, java.io.* y java.util.*. Existe una macro a nivel de clase que invoca
al constructor de la clase padre: %default_constructor <public>
4. Métodos
Cabecera/Prototipo: igual que en Java
Cuerpo del método:
(Declaración de variables | [Etiqueta] | Instrucción)* (cláusula CATCH)*
Declaración de variables: igual que en Java
Las variables hay que declararlas antes de usarlas
Las instrucciones son bytecode o macros
Se usa la cláusula CATCH para capturar/manipular excepciones:
catch [className] (et_inicio, et_fin) et_manipulacion
- Si no especificamos el className se captura java.lang.Throwables
- et_inicio y et_fin son las etiquetas de comienzo (inclusive) y fin (exclusive)
del bloque de captura.
- et_manipulacion es la posición donde se salta si hay excepción
5. Instrucciones
5.1 Runtime de la JVM (Cuando un método invoca a otro)
Cuando se invoca a un método:
- Se apila la dirección del objeto
- Se apilan los parámetros reales
- Se reserva espacio para las variables locales
- Se posiciona la pila de operandos
- Se activa el nuevo frame
m1{
…
m2(2,5)
…
Nuevo Frame
(frame de m2)
}
“manualmente”
Llamada al método
Variables locales
Parámetros (2, 5)
Dirección del objeto (m2)
Frame ACTIVO
Frame activo hasta la
llamada al método
(frame de m1)
5.2 Notación de las instrucciones
(estado de la pila antes => estado de la pila después)
Cargar colocar un valor en la cima de la pila
Almacenar extraer un valor de la cima de la pila
5.3 Carga de constantes
aconst_null: carga de referencia nula
bipush número: carga un número de tipo byte
sipush número: carga un número de tipo short
iconst_m1: carga el valor -1
iconst_0(1…5): carga un entero de 0 a 5
lconst_0(1): carga un long 0 ó 1
fconst_0(1,2): carga un float 0,1 ó 2
dconst_0(1): carga un doublé 0 ó 1
ldc valor: carga un valor de cualquier tipo
ldc 5.1
//double
ldc (float) 5.1 //float
(… =>…, null)
(…=>…, número)
(…=>…, número)
(…=>…, -1)
(…=>…, 0(1…5))
(…=>…, 0(1))
(…=>…, 0(1,2))
(…=>…, 0(1))
(…=>…, valor)
5.4 Acceso a variables y parámetros
<tipo>load variable: carga el valor de la variable
(…=>…, variable)
<tipo>store variable: almacena el valor de la variable (…, variable=>…)
<tipo> es: b (byte), s (short), i (int), l (long), c (char), f (float), d (double), a (referencia)
aload this: carga la referencia al objeto actual.
Ejemplo: var (variable local entera), par (parámetro entero) var = par
iload par
(…=>…, par)
istore var
(…, par=>…)
5.5 Operaciones con arrays
Requieren que esté cargada la referencia al array:
<tipo>aload: carga un elemento de un array (…, ref_array, índice=>…, ref_array[índice])
<tipo>astore: almacena el valor de la cima en un array (ref_array[índice] = valor)
(…, ref_array, índice, valor=>…)
arraylength: carga el número de elementos que tiene un array (…, ref_array=>…, num_elem)
Ejemplo 1: iarr[3] = iarr[1]
aload iarr
iconst_3
aload iarr
iconst_1
iaload
iastore
(…=>…, iarr)
(…, iarr=>…, iarr, 3)
(…, iarr, 3=>…, iarr, 3, iarr)
(…, iarr, 3, iarr=>…, iarr, 3, iarr, 1)
(…, iarr, 3, iarr, 1=>…, iarr, 3, iarr[1])
(…, iarr, 3, iarr[1]=>…)
Ejemplo 2: i[2,3]
aload i
iconst_2
aaload
iconst_3
iaload
(…=>…, i)
(…, i=>…, i, 2)
(…, i, 2=>…, i[2])
(…,i[2]=>…, i[2], 3)
(…,i[2], 3=>…, i[2,3])
5.6 Acceso a atributos
Atributos no estáticos (objetos en L-0)
- Cargar el valor del atributo en la pila:
getfield nombre_atrib tipo_atrib
- Almacena el valor de la cima en el atributo:
putfield nombre_atrib tipo_atrib
(…,ref_objeto=>…,valor)
(…,ref_objeto, valor=>…)
Ejemplo:
aload this
getfield iarr int[]
Atributos estáticos (clases no instanciables en L-0)
- Cargar el valor del atributo en la pila:
getstatic [NombreClase.] nombre_atrib tipo_atrib
- Almacena el valor de la cima en el atributo:
putstatic [NombreClase.] nombre_atrib tipo_atrib
(…,=>…,valor)
(…, valor=>…)
Ejemplo: ClaseNoInst1.atr1 := objeto1.atr2;
aload objeto1
(…=>…, objeto1)
getfield atr2 int
(…, objeto1=>…,objeto1.atr2)
putstatic ClaseNoInst1.atr1 int
(…,objeto1.atr2=>…)
5.7 Instrucciones de tipos de datos
Convertir el tipo del element de la cima de la pila
i2l (int to long)
l2i (long to int)
f2i (float to int)
d2i (double to int)
i2f (int to float)
l2f (long to float)
f2l (float to long)
d2l (double to long)
i2d (int to double)
l2d (long to double)
f2d (float to double)
d2f (double to float)
i2b (int to byte)
i2s (int to short)
En todos los casos tenemos que (…, valor(tipo)=>…,valor(tipo_nuevo))
Comprobar si la referencia de la cima (objeto) es de un tipo
instanceof nombreClase
(…, ref_objeto=>…, 0 ó 1)
Devuelve 0 si el objeto es de nombreClase
Devuelve 1 si el objeto NO es de nombreClase
5.8 Creación de objetos y arrays
Crear objetos: crea una instancia nombreClase y apila la referencia. NO invoca al
constructor (habría que hacerlo explícitamente).
new nombreClase
(…=>…, ref_objeto)
Crear arrays unidimensionales:
newarray tipo_primitivo
anewarray nombreClase
(…, num_componentes=>…, ref_array)
(…, num_componentes=>…, ref_array)
Ejemplo: formación 9 entero a;
bipush 9
newarray entero
astore a
Ejemplo: formación 8 String s;
bipush 8
anewarray String
astore s
Crear arrays multidimensionales:
multianewarray tipo_dato ([])+ num_dimensiones
(…, num_componentes dim1, num_componentes dim2, …=> …, ref_array)
Ejemplo: formación 10,8 entero b;
bipush 10
bipush 8
multianewarray entero [][] 2
astore b
5.9 Instrucciones aritméticas y lógicas
Instrucciones aritméticas:
<tipo>add
(…, op1, op2=>…, op1+op2)
<tipo>sub
(…, op1, op2=>…, op1-op2)
<tipo>mul
<tipo>div
<tipo>neg
(…, op1, op2=>…, op1*op2)
(…, op1, op2=>…, op1/op2)
(…, op=>…, - op)
Instrucciones lógicas:
and
(…, op1, op2=>…, op1&&op2)
or
(…, op1, op2=>…, op1||op2)
xor
(…, op1, op2=>…, op1 xor op2)
Instrucción de incremento: (un elemento de un array no se puede incrementar
usando esta instrucción)
iinc variable (o atributo) cte_entera
a:=a+2 iinc a 2
5.10 Manipulación de la pila
pop: desapila la cima
dup: duplica la cima
swap: intercambia la cima
(…, x=>…)
(…, x=>…, x, x)
(…, x, y=>…, y, x)
5.11 Llamadas a métodos
Método no estático (pertenece a un objeto en L-0):
invokevirtual [NombreClase.]NombreMetodo Signatura
Ejemplo: invokevirtual Elemento.modificar(int) void
Frame del método llamador: (…, ref_objeto, param_real1,…, param_realN =>
Frame del método llamado: =>…, ref_objeto, param_real1,…, param_realN,
variables_locales)
Método estático (pertenece a una clase no instanciable en L-0):
invokestatic [NombreClase.]NombreMetodo Signatura
Constructores o superclase:
invokespecial [NombreClase.]NombreMetodo Signatura
Ejemplo: m(3, a+2);
aload this
bipush 3
iload a
iconst_2
iadd
invokevirtual m(int, int) void
5.12 Instrucciones de saltos incondicionales
goto etiqueta: salto incondicional
return: vuelta de un método procedural
(…, ref_objeto, par_real1,…, par_realN, var_locales =>…)
<tipo>return: vuelta de un método funcional
(…, ref_objeto, par_real1,…, par_realN, var_locales, valor =>…, valor)
jsr etiqueta: salto a una subrutina dentro de un método
ret: vuelta de una subrutina
5.13 Instrucciones de saltos condicionales
Comparaciones de entero y salto
if_icmp<comp> etiqueta
<cmp> = eq, ne, gt, lt, le, ge
(…, valor1, valor2 =>…)
Comparación de objetos y salto (también vale para arrays)
Dos objetos son iguales si apuntan al mismo sitio
if_acmp[eq|ne] etiqueta
(…,ref_objeto1, ref_objeto2=>…)
ifnull etiqueta: salta si la cima es una referencia nula (…,ref_objeto=>…)
ifnonnull etiqueta: salta si la cima no es una referencia nula
Comparación de long, float y double
lcmp: compara dos long
(…, valor1, valor2=>…,1(0,-1))
fcmpg: compara dos float
dcmpg: compara dos doublé
Los tres métodos devuelven:
1 si valor1 > valor2
0 si valor1 = valor2
-1 si valor1 < valor2
Salto condicional
if<cmp> etiqueta
(…,1|0|-1=>…)
Instrucción de selección
switch (cte_entera : etiqueta)*
default: etiqueta
Ejemplo:
(…, valor=>…)
iload a
switch
1: et_1
2: et_2
default: et_d
6. Macros
Las macros deben estar dentro de los métodos
%print [out|err] parámetro (, parámetro)*: parámetro puede ser una constante, variable,
atributo o un elemento de un array.
%println [out|err] parámetro (, parámetro)*
Ejemplo: %println a, “ “, b
%load parámetro: carga en la pila
%set par = parámetro: asignación (par no puede ser una constante evidentemente)
%object nombreClase: crea un objeto de tipo nombreClase (llama al constructor)
%array tipo ([num_elementos])+ : creación de un array.
%array_iterate nombreArray índice %end_iterate: iterador para un array
Ejemplo:
int a[];
%set a = %array int[] {9,8,7}
int i;
%array_iterate a i
%println “a[“, i, “]=”, a[i]
%end_iterate
Descargar