[자바 가상 머신의 JIT 컴파일러에 대한 심층적 이해] 1151 Graal 컴파일러에 대한 심층적 이해

1. 역사적 배경

1. Graal 가상 머신과 Graal 컴파일러는 실험실에서 아직 상용화되어 있지 않지만 향후 차세대 HotSpot 기술을 대체하거나 기반이 될 것으로 예상됩니다. Graal 컴파일러는 원래 Maxine 가상 머신 [그림]에서 C1X 컴파일러 [그림]의 차세대 컴파일러로 설계되었으므로 물론 Java 언어로 작성되었습니다.

2. 2012 년 Graal 컴파일러는 Maxine 가상 머신 프로젝트에서 분리되어 독립적으로 개발 된 Java 컴파일러 프로젝트가되었습니다.

3. Graal 컴파일러는 JDK 9의 Jaotc 사전 컴파일 도구의 형태로 공식 JDK에 처음 추가되었습니다. JDK 10부터 Graal 컴파일러는 서버 측 컴파일러를 대체하고 HotSpot의 계층화 된 컴파일에서 최상위 수준의 Just-In-Time 컴파일이 될 수 있습니다. 장치. 이 대체 Just-In-Time 컴파일러 아키텍처의 실현은 HotSpot 컴파일러 인터페이스의 출현으로 혜택을받습니다.

4. C1 및 C2와 같이 Graal의 초기에는 HotSpot과의 협업이 긴밀하게 결합되어 Graal을 컴파일 할 때마다 전체 HotSpot을 다시 컴파일해야했습니다. JEP 243 : JDK 9에서 릴리스 된 Java-Level JVM 컴파일러 인터페이스 (JVMCI)를 사용하면 Graal을 HotSpot의 코드에서 분리 할 수 ​​있습니다.

5. JVMCI의 세 가지 기능

A : HotSpot의 컴파일 요청에 응답하고 요청을 Java로 구현 된 Just-In-Time 컴파일러에 배포합니다.

B : 컴파일러가 클래스, 필드, 메소드 및 성능 모니터링 데이터 등을 포함하여 HotSpot의 JIT 컴파일과 관련된 데이터 구조에 액세스 할 수 있도록 허용하고 Java 언어 수준에서 이러한 데이터 구조의 추상 표현 세트를 제공합니다.

C : 컴파일러가 컴파일 된 이진 기계 코드를 배포 할 수 있도록 핫스팟 코드 캐시의 Java 측 추상 표현을 제공합니다.

세 가지 기능을 사용하면 HotSpot 가상 머신 외부에서 Java 언어로 구현 된 Just-In-Time 컴파일러 (Gral에 국한되지 않음)를 HotSpot에 통합하여 HotSpot에서 발행 한 최상위 컴파일 요청에 응답하고 컴파일 된 바이너리 코드를 변환 할 수 있습니다. HotSpot의 코드 캐시에 배포합니다.

6. Graal과 JVMCI의 등장은 Java 가상 머신과 컴파일러의 개발에 직접 관여하지는 않지만 Java 가상 머신 기술에 대해 궁금한 독자를 위해 컴파일러 기술을 스누핑하고 사용해 볼 수있는 좋은 방법을 제공합니다. Graal은 HotSpot 가상 머신의 실시간 컴파일 및 코드 최적화 프로세스와 싸우기 위해 여기에 있습니다.

둘째, 컴파일 및 디버깅 환경 구축

1. 코드 관리, 종속성 관리, 컴파일 및 테스트의 복잡성을 줄이기 위해 Graal 팀은 Python 2에서 mx라는 작은 도구를 작성하여 이러한 작업을 자동화했습니다.

2. 먼저 mx 설치

# git clone https://github.com/graalvm/mx.git
# 倒入环境变量
export PATH = 'pwd'/mx:$PATH

기술

컴파일하기에 적합한 JDK를 찾으십시오. Graal VM 프로젝트는 OpenJDK 8을 기반으로 개발되고 JVMCI 인터페이스는 JDK 9 이후에 제공된다는 점을 고려하면 Graal 팀은 JVMCI 기능이있는 OpenJDK 8 버전을 제공 했으므로이 버전의 JDK 8을 컴파일 할 수 있습니다. . 독자가 HotSpot에서 Graal 컴파일러의 응용 프로그램에만주의를 기울이고 Graal VM의 다른 측면을 포함하지 않으려는 경우 JDK 9 이상 표준 Open / OracleJDK를 직접 사용할 수 있습니다.

IDE에서 Graal의 컴파일 및 구성이 원활하게 진행될 수 있도록 IDE 구성에 사용되는 Java 힙을 2GB 이상으로 수정해야합니다.

3. Java 버전에 해당하는 환경 변수 구성

export JAVA_HOME=/usr/lib/jvm/oraclejdk1.8.0...

4, Graal 컴파일러 코드를 얻는 것입니다.

# git clone https://github.com/graalvm/graal.git
# cd /graal/comiler
# mx build

세, JVMCI 컴파일러 인터페이스

1. JVMCI 인터페이스의 핵심 내용은 실제로

바이트 코드, 변수 테이블의 변수 슬롯 수, 피연산자 스택의 최대 깊이 및 계층화 된 컴파일의 맨 아래에서 수집 된 통계 정보.

2. 인터페이스

interface JVMCICompiler {
    
}

interface CompliationRequest {
    
}

interface JavaMethod {
    
}

넷째, 코드 중간 표현

1. 코드는 컴파일러 내부에 있습니다.

바이트 코드 → 이상적인 그래프 → 최적화 → 머신 코드 (Mach Node Graph로 표시)의 변환 과정.

2. 이상적인 그래프는 방향성 그래프로, 노드는 변수, 연산자, 방법, 필드 등과 같은 프로그램의 요소를 나타내는 데 사용되며 에지는 데이터 또는 제어 흐름을 나타내는 데 사용됩니다.

A : 작성자는 데이터 흐름에 파란색 선 (점선으로 표시)을 사용하고 제어 흐름에 빨간색 선 (실선으로 표시)을 사용합니다.

B : 이상적인 그래프는 본질적으로 데이터 흐름 그래프와 제어 흐름 그래프를 특정 방식으로 결합하는 그래픽 표현입니다. 한 종류의 에지를 사용하여 데이터 흐름을 나타내고 다른 종류의 에지를 사용하여 제어 흐름을 나타냅니다.

여기에 사진 설명 삽입

매개 변수 0 (P (0)으로 표시됨) 및 매개 변수 1 (P (1)로 표시됨)이 덧셈 연산에 전송되는 방법 및 결과가 상수 2 (C (2)로 표시됨)와 함께 나누기 연산으로 전송되는 방법 .

3. 일반적인 단어 표현 제거
여기에 사진 설명 삽입

여기에 사진 설명 삽입

여기에 사진 설명 삽입

다섯, 코드 최적화 및 생성

1. 이상적인 그래프의 각 노드에는 공통된 두 가지 주요 작업이 있습니다. 하나는 정규화이고 다른 하나는 세대입니다.

2. 표준화는 이상적인 그래프의 스케일을 줄이는 방법, 즉 이상적인 그래프를 기반으로 코드를 최적화하기 위해 취해야 할 조치를 말합니다.

3. 제거 할 수있는 산술 하위 표현식이 그래프에서 발견되면 중복 노드를 찾은 다음 교체하고 삭제합니다.

예:

두 개의 정수를 추가하는 간단한 작업은 상수 폴딩 (두 피연산자가 상수이면 상수 노드가 직접 반환 됨), 산술 집계 (집계 트리의 상수 자식 노드 (예 : (a + 1) +2는 a + 3으로 집계), 부호 병합 (집계 트리의 반대 부호 하위 노드, 예를 들어 (ab) + b 또는 b + (ab)를 a로 직접 병합) 및 기타 여러 최적화.

4. Graal은 이상적인 그래프에서 기계어 코드로 직접 변환되지 않지만 다른 컴파일러와 마찬가지로 먼저 저수준 중간 표현 (LIR, 특정 기계 명령어 세트와 관련된 중간 표현)을 생성 한 다음 HotSpot 통합 백엔드를 생성합니다. 기계어 코드를 생성합니다.

산술 덧셈과 관련된 연산의 경우 ArithmeticLIRGeneratorTool 인터페이스의 emitAdd () 메서드에서 수행됩니다.

5. Graal 컴파일러에서 지원하는 대상 플랫폼

현재 세 가지 대상 플랫폼 (SPARC, x86-AMD64, ARMv8-AArch64)의 명령어 세트에 대한 저수준 중간 표현 만 제공합니다.

6. 정규화는 단일 opcode의 로컬 범위에 국한되지 않고 전체 상황에 따라 많은 최적화가 이루어지며 이러한 유형의 작업은 CanonicalizerPhase 클래스에서 완료됩니다.

추천

출처blog.csdn.net/qq_40996741/article/details/109173594