1. nov-2011 1
Escape Analysis for Java
Jong-Deok Choi Manish Gupta Mauricio Serrano Vugranam C. Sreedhar Sam Midkiff
IBM T.J. Watson Research Center
{jdchoi, mgupta, mserrano, vugranam, smidkiff} @ us.ibm.com
Resumo realizado por Marcio Machado Pereira – RA 780681
A idéia básica do Escape Analysis consiste no seguinte:
Define-se três estados de escape para os objetos – NoEscape,
I. INTRODUÇÃO quando o objeto é local ao método (e, consequentemente, à
N
thread); ArgEscape, quando o objeto escapa o método via
o artigo [1], Choi et al. introduziram um novo
argumentos, mas não escapa a thread que o criou e
framework para realizar a analise de fluxo de dados
GlobalEscape quando o objeto escapa globalmente (i.e., todos
(DFA) no contexto de Java denominada Escape analysis.
os métodos e threads).
Este framework está baseado em uma abstração do programa
chamada de Connection Graph (CG). Em Java, os objetos
Os nós que representam campos estáticos (variáveis globais)
normalmente são alocados no heap e só podem ser dealocados
são inicializados no estado GlobalEscape. Os demais nós são
pelo Garbage Collector (GC). Escape Analysis determina se
inicializados como NoEscape. Se um objeto pode ser
um objeto pode escapar o método que o criou (i.e., não é local
alcançado no Connection Graph por algum nó cujo estado é
ao método) e se o mesmo pode escapar a thread que o criou
diferente de NoEscape então o objeto escapa o Método. Após
(i.e., outras threads podem acessar o objeto). Se o objeto não
a DFA, todos os objetos marcados como NoEscape são
escapa o método ou a thread, duas otimizações podem ser
alocáveis na pilha (stack-allocatable) e todos os objetos
feitas: (1) O objeto pode ser alocado na pilha (stack frame) do
marcados como NoEscape ou ArgEscape são locais à thread
método que o criou. Esta alocação normalmente é mais barata
e, portanto, as operações de sincronização podem ser
do que a alocação no heap, reduzindo o overhead do GC; (2)
eliminadas sem violar a semântica do programa.
pode-se eliminar os mecanismos de sincronização associados
ao objeto, uma vez que o objeto é acessado por uma única
Dois tipos de analise são realizadas para se construir o CG e
thread. Além disso, o objeto pode ser alocado na memória do
identificar os objetos que não escapam seu método ou thread
processador onde a thread foi agendada (scheduled)
de criação: Intraprocedural e Interprocedural. Dada a
melhorando a localidade do dado. Connection Graph captura
representação de um método Java em CFG (Control Flow
a relação de conectividade entre os objetos alocados no heap e
Graph) usa-se um esquema iterativo, descrito na seção III
as referencias a estes objetos. A DFA simplesmente realiza
para a construção do CG intraprocedural. Este CG pode ser
uma analise de alcance (reachability analysis) no CG para
sumarizado para cada método de forma que a mesma
determinar se um objeto é local a um método ou local a uma
informação pode ser usada eficientemente em diferentes
thread.
contextos de chamada (calling contexts). Choi et al.
II. ESCAPE ANALYSIS
apresentaram um algorítmo interprocedural, descrito na seção
IV, que usa a propriedade de sumarização para computar de
No Connection Graph, os objetos, as variáveis de referencia forma eficiente o CG e identificar objetos que não escapam
locais e formais, e os campos (fields) estáticos e não estáticos métodos ou threads.
são representados pelos vértices (ou nós) enquanto as arestas
representam os diversos tipos de referencias entre variáveis, III.ANALISE INTRAPROCEDURAL
objetos e campos (fields) estáticos ou não. A figura abaixo
A analise intraprocedural faz uso de uma DFA forward,
ilustra os tipos de nós e arestas:
disjuntiva, onde o CG na saída de um statement é dada pela
função de transferencia aplicada ao CG na entrada do mesmo
que, por sua vez, é o resultado da união dos CGs na saída dos
predecessores do referido statement.
Para a descrição desta análise, algumas definições fazem-se
necessárias:
CG = ( No U Nr U Nf U Ng, Er U Ed U Ef ) onde,
No – representa o conjunto de objetos
Nr – variáveis de referência (locais e formais)
O trabalho em referência foi apresentado na conferência OOPSLA'99
realizado em novembro de 1999 na cidade de Denver, Colorado, EUA. O Nf – fields não estáticos
resumo é parte do trabalho de pesquisa de doutorado do Instituto de Computação Ng – fields estáticos (variáveis globais)
da UNICAMP (IC-Unicamp) e foi elaborado por Pereira, M. M. (e-mail:
mpereira@ic.unicamp.br ). Er – arestas “point-to”
2. nov-2011 2
x → y ∈ Er ⇒ x ∈ Nr U Nf U Ng & y ∈ No Conservativamente, cria-se um objeto fantasma Oph
(phantom object node) e insere-se a aresta p Oph
Ed – arestas deferred (diferidas) • Faça V = { v | u v, u,v ∈ U & fid(v) = f }
x → y ∈ Ed ⇒ x, y ∈ Nr U Nf U Ng • Se V = Ø cria-se um nó field e adiciona-se a V
Ef – arestas field
• Finalmente, adiciona-se arestas { v q|v∈ V}
x → y ∈ Ef ⇒ x ∈ No & y ∈ Nf U Ng
(4) p = q.f;
representa uma aresta point-to do nó x para o nó y
• Faça U = { u | q u },
representa uma aresta diferida no nó x para o nó y
V={v|u v, u ∈ U & fid (v) = fid (f) }
representa uma aresta field do nó x para o nó y
• Se U = Ø então cria-se um nó phantom object e adiciona-se
a U. Se V = Ø então cria-se um nó field reference e
Associa-se ainda a cada field f de um objeto um identificador adiciona-se a V.
único fid(f) que corresponde ao offset de f na classe que
define o objeto. Isto posto, se O1 e O2, são 2 objetos da • (Flow-Sensitive) → aplica ByPass (p)
• (Both) → adiciona-se arestas { p v|v∈V}
mesma classe C, então fid(O1.f) = fid (O2.f). Dado um nó
de referencia m ∈ Nr U Nf U Ng, o conjunto de nós objetos Segue um exemplo ilustrando a computação do CG:
O ⊆ Νο que m aponta para (point-to) é determinado
percorrendo as arestas diferidas a partir de m até visitarmos a
primeira aresta point-to no caminho. Formalmente:
onde é uma sequencia de arestas
que termina exatamente em uma aresta point-to.
Para uma analise sensível ao fluxo (flow-sensitive) faz-se
necessário também definir uma função ByPass que, quando
aplicada ao nó p ∈ Nr U Nf redireciona as arestas diferidas
incidentes em p aos nós sucessores de p. Exemplo:
IV. ANALISE INTERPROCEDURAL
Vamos assumir que um método A chama um outro método B.
Temos então quatro pontos que são relevantes na análise
interprocedural:
• Na entrada do método B;
Quatro statements básicos afetam o Escape Analysis. A
• Na saída do método B;
seguir são apresentadas as funções de transferência para cada
um destes statements: • Em A, imediatamente antes da invocação do método B
• Em A, imediatamente após a invocação do método B.
(1) p = new r();
Se método B já foi analisado pelo Escape Analysis então,
• Cria o nó objeto O (se não existir) quando for feito a análise intraprocedural de A, este
• (Flow-Sensitive) → aplica ByPass (p) simplesmente usa a informação sumarizada de B.
• (Both) → adiciona aresta point-to de p para O
Nos exemplos abaixo o método L() (Caller) constrói uma
(2) p = q; lista ligada e invoca o método T() (Callee) para construir
uma estrutura em árvore.
• (Flow-Sensitive) → aplica ByPass (p)
• (Both) → adiciona a aresta (1) Connection Graph na entrada do método:
Para cada parâmetro formal fi, existe um parâmetro real ai no
(3) p.f = q; Caller, que produz o valor para fi. No ponto de entrada do
• Faça U = PointsTo (p) Callee cria-se então uma atribuição da forma fi = ai. O
• Se U = Ø então ou p = null (null pointer exception) ou o argumento fi é tratado como uma variável local dentro do
objeto para o qual p aponta foi criado fora do método (p é um
parâmetro formal ou alcançável por um parâmetro formal). método. Como ela pode ser morta (killed) por outras
3. nov-2011 3
atribuições a fi, cria-se então um nó de referência phantom (3) CG imediatamente antes da invocação do método B:
para ai e insere uma aresta diferida de fi para ai. Exemplo: No local (A) de invocação do método, cada passagem de
parâmetros é tratada como uma atribuição a um parâmetro
real no chamador. Considere a chamada u1.foo(u2, …, un)
onde u2, …, un são os parametros reais. Modela-se a chamada
com as atribuições:
â1 = u1; â2 = u2; …; foo (â1, â2, …, ân)
Cada parâmetro no local da chamada será comparado com o
nó de referência phantom do método chamado. No exemplo
abaixo, dois nós â1 e â2 são criados como arestas diferidas
apontando para o primeiro e segundo parâmetros reais da
(2) Connection Graph na saída do método: chamada, u e v, respectivamente.
Modela-se a ação return que retorna uma referência a um
objeto como uma atribuição a uma variável especial phantom
chamada return. Multiplas ações de retorno são resolvidas no
CG executando o “merge” dos respectivos valores return.
Após completar o Escape Analysis intraprocedural para um
método usa-se a função ByPass para eliminar todas as arestas
diferidas no CG, criando nós phantom onde forem
necessários. É o caso do nó R no exemplo abaixo:
Ao final, faz-se a análise de alcançe (reachability analysis) (4) CG imediatamente após a invocação do método B:
no CG para atualizar os estados de Escape dos objetos. Esta Neste momento, essencialmente faz-se o mapeamento das
análise particiona o grafo em três subgrafos: informações contidas no CG sumarizado do método chamado
de volta para o CG do chamador. Três tipos de nós
• Subgrafo induzido Sg do conjunto de nós que são desempenham um papel importante na atualização do CG,
“alcançaveis” a partir de um nó GlobalEscape (inicialmente, logo após a invocação do método: âi's do caller's CG, ai's do
static fields e objetos runnable). callee's CG e o nó return. A atualização do CG é feito
atualizando-se o conjunto de nós do CG do chamador usando
• Subgrafo induzido Sa do conjunto de nós “alcançaveis” a âi's e ai's e o respectivo conjunto de arestas. A atualização do
partir de um nó ArgEscape (inicialmente, nós de referência nó return é feito tratando o return como um ai e o nó alvo
phantom que representam os parâmetros reais criados na na invocação do método da mesma forma como âi.
entrada do método, como a1 e a2 no exemplo.
As equações abaixo definem, recursivamente, as relações de
• Subgrafo induzido Sn do conjunto de nós que não são mapeamento MapsToObj ( ↦ ) para atualização dos nós:
alcançaveis por nenhum nó GlobalEscape ou ArgEscape.
Então: Sg U Sa ≅ NonLocalGraph (representa o CG
sumarizado do método); Sn ≅ LocalGraph (todos os objetos
são marcados stack-allocatable).
A atualização das arestas é feita da seguinte maneira:
Sejam p e q nós objetos do Callee' CG tal que:
Então, para cada ∈ MapsToObj(p) e ∈ MapsToObj(q)
estabelece-se
inserindo arestas point-to para cada nó field
4. nov-2011 4
tal que:
V. HISTÓRICO E TRABALHOS RELACIONADOS
Analises do tempo de vida de objetos alocados dinâmicamente
tem sido tradicionalmente usadas para gerenciar o espaço de
armazenamento em tempo de compilação. Park &
Goldeberg[2] introduziram o termo Escape Analysis em
linguagens funcionais para determinar estaticamente quais
partes de uma lista passada para uma função não escapa a
chamada da função (e, portanto, podem ser alocadas na
pilha). Outros melhoraram e extenderam o trabalho de Park
& Goldeberg. Birkedal et al. Propuseram um modelo de
alocação baseado em regiões que são gerenciadas durante a
compilação. Tem havido uma série de esforços paralelos em
Escape Analysis para Java. Bogda & Holzle [3] usam um
conjunto de restrições para computar objetos locais às threads.
Blanchet [4] atribui “pesos” a tipos para codificar como um
objeto de um tipo pode ter referências a outros objetos ou é
um subtipo de outro objeto. Ele propõe uma analise flow-
insensitive em duas fases (backward e forward) para
computar as informações de Escape.
VI. CONCLUSÃO
Choi et al. apresentaram uma nova abordagem para a Escape
Analysis que simplifica a analise de fluxo de dados para um
problema de alcance (reachability analysis) sob um grafo de
conexão (CG). Os resultados experimentais em um protótipo
do “IBM High Performance Compiler for Java” para uma
máquina alvo “PowerPC 333Mhz, 128MB” mostraram que:
• Ο no de objetos que puderam ser alocados na pilha excedeu
70% dos objetos criados dinamicamente em 3 de 10
benchmarks (com a mediana em 19%);
• 11% a 92% de todas as operações de lock foram eliminadas
nos 10 programas (com a mediana em 51%);
• A redução no tempo de execução foi de 2% a 23% (com a
mediana em 7%).
VII. REFERENCIAS
[1] Jong-Deok Choi, M. Gupta, M. Serrano, V.C. Sreedhar and S. Midkiff.
Escape Analysis for Java. In Proceedings of ACM SIGPLAN Conference on
Object-Oriented Programming Systems, Languages and Applications, Denver,
Colorado, November 1999.
[2] Y.G. Park and B. Goldberg. Escape analysis on lists. In Proceedings of.
ACM SIGPLAN Conference Programming Language Design and
Implementation, pages 117-127, July 1992.
[3] Jeff Bodga and Urs Holzle. Removing unnecessary synchronization in java.
In Proceedings of ACM SIGPLAN Conference on Object-Oriented
Programming Systems, Languages and Applications, Denver, Colorado,
November 1999.
[4] Bruno Blanchet. Escape Analysis for object-oriented languages:
Applications to Java. In Proceedings of ACM SIGPLAN Conference on Object-
Oriented Programming Systems, Languages and Applications, Denver,
Colorado, November 1999.