Modularità e
Compilazione Separata
Mauro Franceschi, Giacomo Zanghi
Concetti Generali
La compilazione separata permette un
completo controllo della coerenza tra le entità
condivisi tra i moduli (come già visto a
lezione).
La coerenza non può essere garantita
solamente dal compilatore ma necessita
anche di adeguati concetti e costrutti nel
linguaggio (es.: moduli).
Concetti Generali
Come può il compilatore garantire che gli oggetti visibili al di
fuori dei confini del modulo siano usati in modo conforme con le
regole di compatibilità?
O meglio
come possono essere visibili le dichiarazioni di un modulo
durante la compilazione di un altro modulo?
Soluzione: una symbol table per le entità esterne,
memorizzabile in modo che sia disponibile per diverse
compilazioni;
Il compilatore ripristina la “symbol table” dal “symbol file” ogni
qualvolta l’interfaccia compare nella “import list” del modulo che
si sta compilando.
Moduli
Abbiamo già visto nella nostra carriera a cosa
servono i moduli;
Abbiamo visto a lezione i moduli in Modula-2:
i concetti di “definition module” (module
interface) ed “import list”;
Ora vediamo come sono implementati i
moduli in Oberon.
Oberon
Le parti di “definition” ed “implementation”
sono fuse in una sola;
Le entità che devono essere esportate per
creare l’interfaccia sono segnati con un
asterisco nella loro dichiarazione;
Vantaggi:
- in Oberon basta una sola compilazione;
- non bisogna gestire due file separati.
Moduli in Oberon
IL Problema della
Consistenza
Concetti Generali
I client di un’entità esportata hanno bisogno di
informazioni per utilizzarla (memorizzate nel
symbol file). Questi client devono essere
invalidati quando queste informazioni
vengono modificate!
Per ripristinare l’integrità bisogna ricompilare.
Cosa succede?
Nei moderni linguaggi di alto livello le
compilazioni ridondanti sono un pericolo
serio. Il costo del processo di aggiunta di
poche dichiarazioni o modifiche minori può
essere così grave da ritardare la crescita e
l’evoluzione del sistema stesso.
Quindi
L’estensione di un’interfaccia con nuovi
oggetti deve lasciare le informazioni delle
entità già esistenti che non sono cambiate, in
modo che i client di queste vecchie entità non
necessitino di essere ricompilati;
Ma più che altro …
Oggigiorno i sistemi sono composti di librerie di
moduli che, in futuro, verranno utilizzati per lo
sviluppo di nuove applicazioni.
Inoltre non dovrebbe mai essere necessaria la
ricompilazione di un sistema solo perché viene
utilizzata una nuova versione di una libreria.
Obiettivo
Permettere l’estensione dei moduli evitando
inutili ricompilazioni e continuando a
garantire la consistenza tra i moduli.
O meglio: eliminare il problema alla radice
evitando l’invalidazione dei client.
La Consistenza in Oberon
In Oberon il modello originale prevede una key
nel symbol file che viene rigenerata ad ogni
compilazione.
Ora vedremo altri due modelli migliorati:
Layer Model;
Object Model.
IL Layer Model di OP2
Lo Stack degli Extension Layers
La parte dei symbol file esistenti, deve rimanere immutata da
un’estensione dell’interfaccia. Ogni volta che un’interfaccia viene
estesa , un nuovo livello di estensione appare al top dell’interfaccia
esistente.
Estensioni portano a Interfaccia Multilivello --> Stack di livelli ordinati.
Non è possibile determinare il livello a cui un oggetto appartiene, ma
solo guardare se la dichiarazione e ‘ nel testo sorgente(tramite il
vecchio symbol file).
Tabella in memoria che associa un numero di livello per ogni nome
presente nel symbol file.
Il Numero di Livello di ogni oggetto  Posizione dell’oggetto nel symbol
file.
IL Layer Model di OP2
Routine di compilazione
IL Layer Model di OP2
Controllo sulla Consistenza
Client di un modulo vede stack di livelli che descrivono
l’interfaccia importata.
Se l’interfaccia venisse estesa nello stesso tempo, la
consistenza sarebbe garantita, perché lo stack di livelli, richiesto
dal client, è presente come un prefisso dello stack
effettivamente fornito.
Il Client per ogni modulo importato specifica nel suo object file il
numero di livelli che necessita così come il fingerprint.
Il modulo che esporta elenca un fingerprint per ogni livello di
strato, allora un client può importare un certo numero di livelli.
IL Layer Model di OP2
Controllo sulla Consistenza
Fingerprint: è una funzione di hash sul contenuto
dei livelli.
Per trovare il Fingerprint di un livello ci si basa
anche sul Fingerprint del livello precedente.
Vantaggi: i livelli hanno sempre un solo id
indipendente dal lavoro a compilation time.
La funzione di Fingerprinting garantisce che I
cambiamenti su un certo livello si ripercuotono sul
suo fingerprint.
IL Layer Model di OP2
Esempio controllo della consistenza
Object Model: premesse
Evitare di mantenere la cronologia dello sviluppo;
Prevenire disastrose conseguenze dovute alla
perdita di symbol file;
Consistency checking con una granularità più fine.
Object Model: l’ idea
Il problema è distinguere I nuovi oggetti introdotti con
l’espansione del modulo;
Considera l’altro estremo rispetto al modello classico e al
Layer Model: un layer ed un identificativo individuale
(fingerprint) per ogni oggetto;
Cambia l’aspetto della lista degli oggetti importati, serve la
coppia (objname, fingerprint).
Esempio della lista di esportazione
Passo 2
Passo 1
Object Model: Fingerprinting
Nel layer model la funzione di fingerprinting
era una funzione di hashing; qui non si può;
Che cosa possiamo usare e cosa no ?
Per capirlo ricordiamoci che il fingerprint
serve a controllare la consistenza delle entità
esportati al di fuori dei confini di un modulo.
Object Model: Fingerprinting
Cosa non possiamo
usare:
Attributi non esportati;
Cosa possiamo
usare:
Il suo tipo (non basta il
nome);
Indirizzi delle variabili;
I suoi attributi;
Indirizzi dei descrittori di
tipo;
Il nome dell’oggetto
(dipende);
Object Model: Fingerprinting
Il fingerprint di un oggetto è generato dai fingerprint
del suo tipo e delle sue sottoparti considerate;
Inoltre per le structure viene inserito anche il nome
del modulo e il nome canonico;
I fingerprint dei tipi predefiniti sono costanti e
predefiniti.
Esempio di fingerprint associati
Considerazioni
Ora facciamo una breve comparazione tra i tre modelli in termini di
efficienza.
Per il benchmarks verrà usato l’editor grafico Draw che è
un’applicazione Oberon composta di 5 moduli per un totale di
46200 bytes.
Dimensione dell’ object file
Dimensione del symbol file
Tempo di compilazione
Uso della memoria
Conclusioni
Entrambi i modelli visti hanno raggiunto lo scopo
di poter estendere i moduli limitando le
invalidazioni.
Il miglior modello è risultato essere l’ object model.
Risolve il problema dell’invalidazione dei client nel
caso in cui symbol file vada perduto.
Inoltre permette l’eliminazione di oggetti obsoleti
senza invalidare i client che non usano tali oggetti.
Bibliografia
Separate compilation and Module Extension,
autore:Regis Bernard Joseph Crelier.
Scarica

Modularita` e Compilazione Separata