52
V8 JavaScript Engine – 김해중(2011.10.21) V8 JavaScript Engine #Env) Linux, Windows 김해중(2011.10.21) http://haejung.egloos.com/

V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

  • Upload
    others

  • View
    4

  • Download
    0

Embed Size (px)

Citation preview

Page 1: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

V8 JavaScript Engine

#Env) Linux, Windows

김해중(2011.10.21)

http://haejung.egloos.com/

Page 2: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

목차

1. 목적 ......................................................................................................................................................................... 3

2. 소개 ......................................................................................................................................................................... 3

3. V8 Design Element .......................................................................................................................................... 4

3-1. Fast Property Access ............................................................................................................................. 4

3-2. Dynamic Machine code Generation ............................................................................................. 7

3-3. Efficient Garbage Collection ............................................................................................................. 8

4. V8 Basic Building Blocks.............................................................................................................................. 9

4-1. Handles and Garbage Collection ................................................................................................... 9

4-2. Contexts .................................................................................................................................................... 12

4-3. Templates ................................................................................................................................................ 14

4-4. Accessors .................................................................................................................................................. 15

4-5. Interceptors ............................................................................................................................................ 18

4-6. Security Model ...................................................................................................................................... 19

4-7. Exceptions ................................................................................................................................................ 20

4-8. Inheritance............................................................................................................................................... 21

5. 빌드 ...................................................................................................................................................................... 23

5-1. 환경 설정 .................................................................................................................................................. 23

5-2. 소스 받기 .................................................................................................................................................. 27

5-3. 빌드 하기 .................................................................................................................................................. 28

5-4. Hello World ............................................................................................................................................ 30

6. 예제 ...................................................................................................................................................................... 32

7. 참고문서 ............................................................................................................................................................. 52

Page 3: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

1. 목적

본 문서는 JavaScript Engine V8 의 구조 이해와 사용 방법에 대하여 기술 한다. 본 문서의

대부분 V8 구조 설명은 V8 의 문서 페이지에서 참고 하여 작성 되었다. 따라서 대부분의 내용이

V8 의 Document 페이지의 내용과 동일하다. 다만 영어 해석부분에서 오역과 다소 차이가 있을

수 있다.

2. 소개

V8 은 구글의 OpenSource 프로젝트로 소스코드 전부가 공개되어 있다. V8 은 고성능(high

performance)의 JavaScript Engine 으로 소스 대부분이 C++로 작성되어 있으며 현재 Google

Chrome 브라우저 및 Android의 기본 내장된 브라우저의 JavaScript Engine으로 사용 되고 있다.

V8 은 ECMA-262 5th Edition 의 ECMAScript 를 지원하고 이를 여러 운영체제(Windows, Mac,

Linux) 및 여러 하드웨어 플랫폼(IA-32, x64, ARM)에서 실행 할 수 있다.

V8 은 JavaScript 소스 코드를 컴파일하고 실행하며 JavaScript 객체(Object)의 메모리 할당을

제어, 그리고 Garbage Collects 에 의하여 더 이상 사용하지 않는 객체의 메모리 회수를 수행한다.

일반적으로 JavaScript 는 브라우저에서 Document Object Model(DOM)의 제어를 위한 가장

일반적인 용도의 client-side scripting 에 사용된다. 일반적으로 JavaScript Engine 이 브라우저를

대신 하여 DOM 의 제어를 지원하지만 JavaScript Engine 은 DOM 이 아니다. 정확히 말해

JavaScript Engine + Browser(V8 + Chrome)가 DOM 을 제공한다고 해야 맞다. V8 은 물론

DOM 이외의 ECMA Standard 에서 규격화된 모든 Data Type, Operator, Objects 와 Function 을

지원한다.

V8 은 모든 C++ 응용프로그램의 객체들과 함수들(Objects and Functions)을 JavaScript 코드에

노출(expose) 할 수 있다. 이후에 설명하는 부분에서 C++객체를 JavaScript 코드로 노출하여

C++객체를 JavaScript code 에서 사용하는 방법에 대하여 배워 볼 것이다. 물론 역으로도

가능하다. JavaScript 에 존재하는 객체, 함수를 C++에서 사용할 수 있다.

Page 4: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

3. V8 Design Element

V8은 Large JavaScript 응용프로그램의 빠른 실행에 특별히 초점을 두고 설계했다.

Fast Property Access

Dynamic Machine Code Generation

Efficient Garbage Collection

위 3가지 요소가 V8의 성능 설계 요소의 핵심(Key)이다.

3-1. Fast Property Access

JavaScript 는 매우 동적인 프로그래밍 언어이다. 객체에 Property(프로퍼티)를 추가 할 수

있으며 객체의 프로퍼티를 제거 할 수 있다. 이 모든 작업은 언제든 객체에 즉시 일어날 수 있다.

또한 그렇기 때문에 JavaScript 객체의 프로퍼티는 언제나 변화 가능성을 가지고 있다. V8 을

제외한 대부분의 JavaScript Engine<JavaScriptCore(구 Safari), Nitro(Safari), Spider Monkey(Fire Fox),

Carakan(Opera), Jscript(구 IE)>에서 객체의 프로퍼티 저장을 위해 사전식 데이터 구조(dictionary

data structure)를 사용한다.

이 사전식 데이터 구조는 객체 프로퍼티의 실제 메모리 위치를 찾기 위해서 동적

룩업(Dynamic lookup)을 필요로 한다. 이러한 구조는 Java 나 SmallTalk과 같은 객체화(instance)된

변수를 접근하는 방법보다 느리다. 왜냐하면 이들 언어는 변수에 접근할 때 미리 정의된 고정

오프셋(Fixed offset)에 위치한 변수에 접근하기 때문이다. 이것이 바로 가능한 이유는 컴파일러가

해당 객체의 클래스에 고정된 객체 레이아웃(fixed object layout) 크기를 미리 알 수 있기

때문이다. 따라서 변수의 접근은 메모리의 로드와 저장(Load, Store)와 같은 단일 연산을 필요로

하는 아주 간단한 문제이다. 하지만 사전식 구조는 객체의 프로퍼티 위치를 알기 위해서 동적

룩업(Dynamic lookup)을 찾아서 해석해야 하는 절차가 필요하기 때문이다.

V8 은 JavaScript 프로퍼티 접근에 대한 시간을 감소 시키기 위해 동적 룩업(Dynamic lookup)을

사용하지 않고 대신에 동적으로 hidden class 를 생성한다. 이 방법은 객체에 새로운 프로퍼티가

추가되었을 때 hidden class를 변경하는 것이다.

Page 5: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

간단한 JavaScript 함수 Point(x, y)

new Point(x, y)가 실행될 때 Point 객체가 생성 된다. V8 이 객체의 생성을 처음 시도 할 때

V8 은 Point 의 Initial hidden class 를 생성한다. 아래 그림에서 이를 C0 로 표기 한다. 객체는

아직 어떠한 프로퍼티도 가지고 있지 않는다. 즉, 정의된 초기 클래스는 비어있다. 이번

스테이지에서 Point의 hidden class는 C0이다.

첫 번째 수행 문의 Point(this.x = x;) 가 실행될 때 Point 객체에 x 라는 새로운 프로퍼티가

생성된다. 이번 스테이지에서는 V8은 다음을 수행한다.

C0 를 기반(Base)으로 하는 C1 이라는 새로운 hidden class 를 생성한다. 그런 다음에

하나의 프로퍼티 x 를 가지는 객체의 정보를 C1 에 추가 한다. 이때의 x 는 Point 객체의

0(zero)오프셋 위치에 저장되는 값이다.

Hidden class C0 에 프로퍼티 x 가 추가 되었을 경우 C0 대신에 C1 이 사용되도록 C0 의

클래스 변경 표식(a class transition indicating)을 업데이트 한다. 이번 스테이지에서

Point의 hidden class 는 C1이다.

Page 6: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

두 번째 수행 문의 Point(this.y = y;) 가 실행될 때 Point 객체에 y 라는 새로운 프로퍼티가

생성된다. 이번 스테이지에서는 V8은 다음을 수행한다.

C1 를 기반(Base)으로 하는 C2 이라는 새로운 hidden class 를 생성한다. 그런 다음에

하나의 프로퍼티 y 를 가지는 객체의 정보를 C1 에 추가 한다. 이때의 y 는 Point 객체의

1(one)오프셋 위치에 저장되는 값이다.

Hidden class C0 에 프로퍼티 y 가 추가 되었을 경우 C1 대신에 C2 이 사용되도록 C1 의

클래스 변경 표식(a class transition indicating)을 업데이트 한다. 이번 스테이지에서

Point의 hidden class 는 C2이다.

프로퍼티가 추가될 때 마다 hidden class를 생성하는 것은 어찌 보면 비효율적으로 보일 수

있다. 하지만 클래스 변경(class transition)을 위해 생성된 hidden class는 재 사용될 수 있다. 즉,

다음 번 new Point(x, y)에서는 새로운 hidden class를 생성하지 않고 대신에 앞서 처음 생성된

C0, C1, C2를 공유하여 사용한다.

다음은 또 다른 Point객체가 생성될 경우의 예다.

초기화된 Point객체는 어떠한 프로퍼티도 가지고 있지 않다. 즉, 새로 생성된 객체는

클래스 C0를 의미 하게 된다.

프로퍼티 x가 추가 되었을 때, V8은 hidden class를 C0에서 C1으로 변경하고, 클래스

C1에 정의된 x의 오프셋 위치에 값을 기록(write)한다.

프로퍼티 y가 추가 되었을 때, V8은 hidden class를 C1에서 C2으로 변경하고, 클래스

C2에 정의된 y의 오프셋 위치에 값을 기록(write)한다.

즉, 이미 한번 생성된 hidden class 를 재사용하여 이후에 같은 객체를 생성할 때 객체 생성의

비용을 줄일 수 있다.

Page 7: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

JavaScript는 대부분의 객체 지향 언어보다 더 동적이다. 따라서 위와 같은 고도의 구조공유(a

high degree of structure-sharing)속에서 런타임(Runtime)은 대부분의 JavaScript 프로그램이

수행한다. hidden class 의 사용은 두 가지의 이점을 가지고 있다. 프로퍼티 접근을 위해 사전식

룩업(dictionary lookup)이 필요하지 않고, V8은 고전 방식의 클래스기반(classic class-based)의

최적화를 사용할 수 있다.

3-2. Dynamic Machine code Generation

V8 은 JavaScript 소스 코드를 컴파일 하며 이 코드가 처음 실행될 때 직접 기계코드(Machine

Code)로 변환 한다. 이 것은 중간 Byte codes 와 Interpreter 가 없다. 프로퍼티 접근은 V8

실행하는 것과 같이 다른 기계 명령어가 패치 된(patched) inline cache code 에 의해서 제어

된다.(Property access is handled by inline cache code that may be patched with other machine instructions

as V8 executes)

주어진 객체의 프로퍼티에 접근하는 초기 코드가 실행 되는 동안 V8 은 그 객체의 현재 hidden

class 를 정의한다. V8 은 코드의 같은 구역(Section)에서 이후에도 객체가 다시 사용될 것을

예상하여 프로퍼티 접근을 최적화 하며, 해당 클래스의 정보를 inline cache code 가 hidden

class 를 패치(patch)하기 위하여 사용한다. V8 이 예상한 것이 맞는다면 프로퍼티의 값은 단일

명령수행으로 할당 또는 획득하게 된다. 그렇지 않고 예상이 맞지 않는다면 해당 코드를

최적화에서 제거 한다.

Point객체의 x 프로퍼티에 접근하는 JavaScript 코드

var point = new Point(x, y);

point.x; // Point객체의 x프로퍼티에 접근

V8에 의해서 생성된 x 프로퍼티에 접근하는 기계 코드(machine code)

// ebx는 해당 객체를 가리킨다

# ebx = the point object

// 해당 객체의 hidden class offset에 있는 클래스와 cached hidden class를 비교한다

cmp [ebx,<hidden class offset>],<cached hidden class>

// 비교 결과가 같지 않다면 inline cache miss 루틴으로 점프한다

jne <inline cache miss>

// 비교 결과가 같다면 eax에 해당 객체의 cached x offset위치의 값을 저장한다

mov eax,[ebx, <cached x offset>]

Page 8: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

객체의 hidden class가 cached hidden class와 같지 않다면 V8 Runtime System 의 inline cache

misses 를 제어하는 곳으로 분기(Jump)하며 inline cache code 를 패치 하게 된다. 그렇지 않고

class 가 같다면 x 프로퍼티의 값은 쉽게 찾게 된다.

많은 객체들이 같은 hidden class 를 참조할 때 대부분의 정적 언어(Language)와 같은 이득을

얻게 된다. 프로퍼티 접근을 위해 inline caching 과 함께 hidden class 를 사용하는 것과 비슷한

방법으로 같은 타입의 객체를 자주 생성하거나 접근하는 경우가 많을수록 최적화 효율은

좋아진다. 이것은 대부분의 JavaScript 코드가 실행될 수 있는 곳에서 굉장하게 속도를

개선시킨다.

3-3. Efficient Garbage Collection

V8 은 프로세스 수행 중 더 이상 사용하지 않을 객체의 메모리를 반환하는 Garbage Collection

작업을 수행한다. 빠른 객체 할당과 짧은 Garbage Collection Pauses, 그리고 메모리

단편화(memory fragmentation)를 없도록 하기 위해 V8 은 일반적이고 정확한 Garbage

Collector를 채택했다.

V8은 Garbage Collection Cycle을 수행할 때 프로그램 실행을 멈춘다.

V8은 대부분의 Garbage Collection Cycle 동안에 객체의 heap부분만 처리한다.

이는 프로그램이 멈추는 영향을 최소화한다.

V8 은 항상 모든 객체와 포인터가 메모리상에 어디에 위치해 있는지 정확하게 알고 있다.

이는 잘못된 식별 객체를 포인터로 착각하여 발생할 수 있는 메모리 누수(memory

leak)을 피할 수 있게 한다.

V8 에서 객체의 heap 공간은 두 부분으로 구분되어있다. 객체가 생성되는 새로운 공간과

Garbage Collection 에서 살아남은 객체가 저장되는 예전(Old) 공간이다.

만약 Garbage Collection Cycle 동안에 객체가 이동되었다면 V8 은 객체를 가리키고 있는 모든

Pointer를 업데이트한다.

Page 9: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

4. V8 Basic Building Blocks

V8 JavaScript Engine을 사용하기 위해서는 필요한 몇 가지의 이론적 내용을 이해해야 한다.

4-1. Handles and Garbage Collection

Handles

핸들(Handle)은 힙(Heap)에 위치한 자바스크립트 객체의 참조(Reference)를 제공하는

것이다. V8 의 Garbage Collector 는 더 이상 사용되지 않는 객체에 대하여 메모리 회수를

수행한다. Garbage Collector 가 메모리 회수작업(Process)을 수행하는 동안 힙에 위치한

객체들은 힙의 다른 장소로 옮겨지곤 한다. 그리고 Garbage Collector 가 객체에 대한 메모리

위치 이동을 수행했을 때 Garbage Collector 는 모든 핸들에 대하여 참조하는 객체의 새로운

주소로 업데이트 하도록 한다. 참조하는 핸들이 없거나, JavaScript 에서 더 이상 접근하지

않는 객체는 Garbage 로 간주된다. Garbage Collector 는 수시로 Garbage 로 간주 되는

객체를 제거하여 메모리를 회수한다.

핸들은 두 가지 종류가 있다. Persistent 와 Local 이다. Persistent handle 은 데이터를 힙에

저장한다. 반면에 Local handle 은 스택에 저장한다. 여기서 데이터는 핸들(Handle)을 이야기

하며, 핸들의 위치가 힙과 스택이며, 모든 핸들이 가리키는 객체는 힙에 위치하게 된다.

V8 은 데이터가 영구적(Persistent)인지 아니면 로컬(Local)인지를 정하기 위해 3 가지의

템플릿(template): Handle<>과 이것의 하위 클래스인 Local<>과 Persistent<>를 제공한다. 이

템플릿은 C++의 템플릿(template)이다.

클래스의 이름에 의해서 어떤 종류의 핸들(Handle)인지 명확히 해야 한다. 여기서

Handle<>기본 클래스는 객체화(인스턴스화) 할 수 있으며 이것은 로컬 데이터로 취급 된다.

Local handles

로컬 핸들(Local Handle)은 핸들 스택(Stack)에 자리잡으며(Hold on) 소멸자(Destructor)가

호출되었을 때 제거 된다. 이 핸들들은 함수 호출 초기에 생성되는 핸들스코프(Handle

Scope)에 의해서 생명주기(Lifetime)이 결정 된다. 함수 호출에 의해서 생성된 핸들스코프가

삭제 되었을 때 Garbage Collector 는 핸들스코프 안에 존재하는 핸들(Handles)들이 이전에

참조하던(더 이상 JavaScript 에서 접근하지 않는) 객체들에 대하여 메모리 해제를 수행한다.

로컬 핸들은 Local<SomeType>클래스를 가지며 Handle<SomeType>또한 변수로 선언하여

저장할 수 있다.

Page 10: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

노트: 핸들 스택(Handle Stack)은 C++ 콜 스택(Call Stack)의 한 부분이 아니다. 하지만

핸들스코프(Handle Scope)는 C++의 스택(Stack)에 내장(Embedded)된다. 즉, 핸들 스코프는

오직 스택(Stack)위에서만 할당 된다. 따라서 new를 사용하여 힙(Heap)에 할당 할 수 없다.

Persistent handles

영구 핸들(Persistent Handle)은 핸들 스택(Stack)에 자리잡지 않으며(Not hold on), 오직

특수한 방법으로 제거 할 수 있다. 일반적인 로컬 핸들(Local Handle)처럼 영구

핸들(Persistent Handle)은 힙에 할당 된 객체를 참조 제공한다.

보통 영구 핸들(Persistent Handle)은 일회성 함수 호출 이상의 객체 참조가 요구될 때,

즉 다시 사용 할 가능 성이 있는 객체를 계속 유지해야 할 때 또는 핸들(Handle)의

생명주기(Lifetime)가 C++의 Scope 에 의해 제어되지 않기를 원할 때(함수 호출이 종료되면

로컬 변수가 제거 되는 경우처럼) 사용한다.

영구 핸들(Persistent Handle)을 Persistent::New()를 사용하여 생성하며, Persistent::

Dispose를 사용하여 제거(해제) 할 수 있다.

영구 핸들(Persistent Handle)은 Persistent::MakeWeak 를 사용하여 약한 영구 핸들(Weak

Persistent Handle)로 만들 수 있다. 약한 영구 핸들(Weak Persistent Handle)은 객체에 대한

유일한 참조가 약한 영구 핸들(Weak Persistent Handle)을 참조 할 때 Garbage Collector 에

의해 미리 등록된 콜백(Callback) 메소드를 호출(Trigger)하게 된다.

영구 핸들(Persistent Handle)은 Persistent<SomeType>클래스를 가지며 Handle<Some

Type>또한 변수로 선언하여 저장할 수 있다.

Handle Scope

프로그램은 객체의 생성과 마찬가지로 매번 핸들(Handle)을 만들게 된다. 이것은 결국

수많은 핸들을 만들게 된다. 여기서 핸들스코프(Handle Scope)는 매우 유용하다.

핸들스코프(Handle Scope)가 소멸자에 의해서 소멸 될 때 이전에 생성된 모든 해들은

핸들스택(Handle Stack)에서 제거 하기 때문이다. 즉, 핸들스코프가 모든 핸들의

컨테이너(Container)처럼 동작 하기 때문이다.

이것은 핸들(Handle)이 가리키는 객체가 Garbage Collector 에 의해서 삭제 대상이

된다는 것이다. (this results in the objects to which the handles point being eligible for deletion

from the heap by the garbage collector.)

Page 11: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

아래 그림은 핸들스코프의 간단한 예로, 다이어그램에서 보듯이 handle-stack 과 heap-allocated

objects의 관계를 볼 수 있다.

Context::New()로 생성된 핸들은 영구 핸들(Persistent Handle)을 반한 하여 핸들 스택(Handle

Stack)에 위치 하지 않는다.

[핸들스코프 예제]

핸들스코프의 소멸자 HandleScope::~HandleScope 가 호출 될 때 핸들스코프는 삭제된다. 더

이상 객체에 대한 참조가 없을 경우 제거된 핸들스코프에 의해서 객체를 참조하는 핸들은 다음

Garbage Collection 에서 삭제 대상이 된다. 그림 [핸들스코프 예제]에서 객체 source_obj,

script_obj 는 더 이상 참조 되지 않거나, JavaScript code 에서 접근 하지 않는 경우 Garbage

Collector에 의해서 제거 될 수 있다.

여기서 context 핸들의 경우 영구 핸들(Persistent Handle)이기 때문에 핸들스코프(Handle

Scope)가 종료(exited)되어도 제거 되지 않는다. context 핸들과 같이 영구 핸들(Persistent

Handle)을 삭제하는 방법은 명시적으로 context 핸들의 Dispose 메소드를 호출 하는 방법뿐이다.

이 핸들스코프(Handle Scope) 모델의 일반적인 함정을 알아 차리는 것은 매우 중요하다. 즉,

핸들스코프(Handle Scope)에 정의된 함수에서 지역(Local) 핸들을 직접 반환(Return)하는 것은 불가능 하다.

만약 함수 끝 부분에서 지역 핸들(Local Handle)을 반환(Return)하려고 할 때, 함수 반한 직전에

핸들스코프(Handle Scope)의 소멸자(Destructor)가 바로 호출되어 반환 하려고 했던 지역

핸들(Local Handle)은 삭제 될 것이다. 따라서 핸들스코프(Handle Scope)는 지역 핸들(Local

Handle)을 반환 하기 위한 적절한 방법을 제공하는데 핸들스코프(Handle Scope)의 Close

메소드를 호출 하면 된다. Close 메소드를 호출 함으로서 반환 하기 위한 새로운 핸들(new

handle)을 되돌려 받을 수 있다.

Page 12: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

HandleScope::Close() 예제

// This function returns a new array with three elements, x, y, and z. Handle<Array> NewPointArray(int x, int y, int z) { // We will be creating temporary handles so we use a handle scope. HandleScope handle_scope; // Create a new empty array. Handle<Array> array = Array::New(3); // Return an empty result if there was an error creating the array. if (array.IsEmpty()) return Handle<Array>(); // Fill out the values array->Set(0, Integer::New(x)); array->Set(1, Integer::New(y)); array->Set(2, Integer::New(z)); // Return the value through Close.

return handle_scope.Close(array); }

Close 메소드는 인자(Argument)로 받은 값을 복사하고, 나머지 모든 지역 핸들(Local Handle)을

삭제하고 그리고 안전하게 반환(Return)할 수 있는 새로운 핸들을 되돌려 준다.

즉, 핸들스코프(Handle Scope)에 의해서 삭제되지 않고 안전하게 지역 핸들(Local Handle)을

반환 할 수 있다.

4-2. Contexts

V8 에서 Context 는 분리되고(Separate), 연관성이 없는(Unrelated) 그리고 JavaScript

Application이 단일 V8 인스턴스에서 실행(Run)할 수 있는 실행 환경(Execution Environment)이다.

개발자는 반듯이 JavaScript Code가 어떤 Context에서 실행 될지 명시 해야 한다.

이것이 왜 필요할까? 이유는 내장된(Built-in) Utility Function 과 JavaScript Code 에서 변경할 수

있는 객체를 제공해야 하기 때문이다. 예를 들어, 전혀 연관성이 없는 두 개의 JavaScript Code 가

각각 Global Object 를 변경하게 되면 의도 하지 않은 결과를 만들기 때문이다(여기서 Global

Object란, 공통으로 내장된 Utility Function 과 Objects를 의미한다).

시간, 자원 측면에서 각각의 새로운 실행환경을 만들기 위해 내장된 Utility Function 과

Objects 를 만드는 것은 비효율적으로 보일 수 있다. 그러나 V8 은 어느 정도의 캐싱(Caching)을

보장한다. 처음 Context 를 생성하는 동안 어느 정도의 비용(Expensive)이 발생하지만, 두 번째

Context 를 생성할 때는 처음보다는 좀더 적은 비용이 발생한다. 좀더 자세히 설명하면, 처음

Context 는 내장된(Built-in) 객체들의 생성과 내장된(Build-in) JavaScript Code 를 해석(Parse) 및

처리해야 하기 때문이다. 하지만 두 번째 Context 는 단지 자기만을 위한 내장된(Built-in)

Page 13: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

객체들만 생성하면 되기 때문이다. 추가로 V8 은 Snapshot 기능을 지원한다. Snapshot 은 처음

Context 가 생성될 때 내장된(Built-in) JavaScript Code 를 해석(Parse)하는 비용을 줄이기

위해(Highly optimized) 미리 Built-in JavaScript Code 를 컴파일 하고 힙(Heap)에 바로 적재할 수

있는 직렬화된 형태로 snapshot 을 포함하고 있다.

생성된 Context 에 대하여 얼마든지(any number of times) 진입(Enter)과 탈출(Exit) 할 수 있다.

예를 들어 Context A 에 진입해 있는 동안 다른 Context B 에 진입 할 수 있다. 좀더 설명하면

Context A 에서 Context B 로 진입했다는 것은 현재 적용되는 Context 가 A 에서 B 로 변경

되었다는 뜻이다. 그리고 Context B 에서 탈출하게 되면 현재 적용되는 Context 가 B 에서 A 로

변경되는 것이다. 아래 그림을 보자.

[Context의 진입(Enter)과 탈출(Exit)]

여기서 내장된(Built-in) Utility Function 과 Objects 는 각각의 Context 마다 분리되어 있다.

그리고 Context가 생성 될 때 Security Token 을 사용할 수 있다. [Security Model 참조]

V8 에서 Context 를 사용하게 된 동기는 Browser 에서 각 window 와 iframe(Inline Frame)에서

전혀 수정되지 않은(Fresh) JavaScript 환경을 각각 가져야 하기 때문이다.

Page 14: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

4-3. Templates

템플릿(Template)은 V8 Context 속의 JavaScript Function 과 객체들의 청사진(Blueprint)같은

것이다. (여기서의 템플릿은 C++의 템플릿이 아니다). 템플릿은 C++ 함수와 데이터 구조들을

JavaScript 의 스크립트(Script)가 사용할 수 있는 자바스크립트 객체로 변환(Wrap)할 수 있다.

개발자는 템플릿을 생성할 수 있고 모든 새 Context 에서 하나의 템플릿을 사용한다. 템플릿은

필요로 하다면 얼마든지 만들 수 있다. 하지만 어떤 주어진 Context 안에서 오직 하나만의 템플릿

인스턴스(Instance)만을 가질 수 있다(However you can only have one instance of any template in any

given context)

JavaScript 안에서 Function 과 Object 는 강한 이중성(duality)을 가지고 있다. 일반적인 Java 나

C++에서 새로운 타입의 객체를 생성하는 방법은 새로운 클래스를 정의 하면 된다. JavaScript 는

이를 Function 이 대신하고 있으며, Function 을 생성자(Constructor)처럼 사용하여 새로운

인스턴스를 생성한다. JavaScript 의 레이아웃(Layout)과 기능(Functionality)은 매우 밀접하게

Function의 생성자(Construct)와 묶여 있다.

함수 템플릿(FunctionTemplate)

함수 템플릿(Function Template)은 단일 함수(Function)의 청사진(Blueprint)이다. 해당

Context 에 템플릿의 GetFunction 메소드를 호출하여 템플릿의 JavaScript 인스턴스를

생성할 수 있다. 또한 C++ 콜백(Callbacks)들과 함수 템플릿(Function Template)을 결합하여

JavaScript Function Instance 를 실행(Invoke)할 때 해당 콜백(Callback)을 호출 하게 할 수

있다.

객체 템플릿(ObjectTemplate)

각 함수 템플릿(Function Template)은 객체 템플릿(Object Template)과 결합 되어있다.

이것은 객체의 생성자(Constructor)와 같이 생성될 객체를 설정하는데 사용한다. 두 가지

종류의 C++ 콜백(Callback)와 객체 템플릿(Object Template)을 결합 할 수 있다.

Accessor

Accessor 콜백(Callbacks)들은 JavaScript 의 Script 에서 특정한 객체 프로퍼티를 접근

할 때 실행(Invoke)된다.

Interceptor

Interceptor 콜백(Callbacks)들은 JavaScript 의 Script 에서 어느 객체의 프로퍼티를

접근 할 때 실행(Invoke)된다.

Page 15: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

템플릿(Template) 예제

// Create a template for the global object and set the // built-in global functions. Handle<ObjectTemplate> global = ObjectTemplate::New();

// 함수 LogCallback을 함수 템플릿과 결합하고 global객체에 log 함수로 등록한다.

global->Set(String::New("log"), FunctionTemplate::New(LogCallback)); // Each processor gets its own context so different processors // do not affect each other.

Persistent<Context> context = Context::New(NULL, global);

[이 예제는 process.cc의 JsHttpProcessor::Initializer 부분이다]

4-4. Accessors

Accessor 는 JavaScript 의 Script 가 객체의 프로퍼티에 접근했을 때 계산을 하거나 값을

반환하는 콜백(Callback)이다. Accessor 는 객체 템플릿(Object Template)의 SetAccessor 메소드를

통하여 설정된다. Accessor 는 Script 가 프로퍼티에 읽기, 쓰기를 시도할 때 실행하는 두 개의

콜백(Callback) 메소드를 해당 프로퍼티 이름과 결합한다.

Accessor의 복잡성은 다루고자 하는 데이터 타입에 따라 다르다.

Accessing Static Global Variables

Accessing Dynamic Variables

Accessor는 위와 같이 두 가지 타입이 있다. 각각은 아래에서 설명한다.

Accessing Static Global Variables

예를 들어 설명한다. 두 개의 C++ 정수타입 변수 x, y 가 있다. 이것을 JavaScript 의 Global

변수로 사용할 수 있다. 이것을 수행 하려면, Script 에서 변수를 읽기, 쓰기 위한 C++ Accessor

함수들을 호출하는 것이 필요하다. 이들 Accessor 함수들은 C++ 정수를 v8::Integer::New 를

사용하여 JavaScript 정수로 변환 하며, v8::Integer::Int32Value 를 사용하여 JavaScript 정수를 C++

정수로 변환 할 수 있다. 아래 예제를 보자.

Accessing Static Global Variable 예제

// C++ 정수 x를 반환하는 함수

Handle<Value> XGetter(Local<String> property, const AccessorInfo& info) { return Integer::New(x); }

// C++ 정수 x를 설정하는 함수

void XSetter(Local<String> property, Local<Value> value, const AccessorInfo& info) { x = value->Int32Value(); }

Page 16: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

// YGetter/YSetter are so similar they are omitted for brevity Handle<ObjectTemplate> global_templ = ObjectTemplate::New();

// 앞서 정의한 변수 x의 Getter/Setter를 프로퍼티 x의 이름으로 Global 변수로 등록한다.

global_templ->SetAccessor(String::New("x"), XGetter, XSetter); global_templ->SetAccessor(String::New("y"), YGetter, YSetter); Persistent<Context> context = Context::New(NULL, global_templ);

위 예제의 객체 템플릿(Object Template)은 Context 의 생성과 동일하게 생성된다. 이 템플릿은

미리 만들 수 있으며 어떠한 수의 Context에서 사용할 수 있다.

Accessing Dynamic Variables

앞의 예제에서 다루어야 하는 변수는 정적(Static)이고 전역(Global)이었다. 하지만 만약

다루어야 하는 변수가 동적(Dynamic)이면 어떻게 해야 할까? 아래 예제를 보자.

Accessing Dynamic Variables - 1

// 정수 x, y를 가지는 Point 클래스

class Point { public: Point(int x, int y) : x_(x), y_(y) { } int x_, y_; }

여러 개의 C++ Point 인스턴스를 JavaScript 에서 사용 가능하게 만드는 것은 각 C++ Point 를

위한 JavaScript 객체를 생성하는 것이 필요하고 JavaScript 객체와 C++ 인스턴스간에 연결을

만들어야 한다. 이것은 외부 값(External Value)와 내부 객체 필드(Internal object field)로 수행 할

수 있다.

처음 Point를 wrapping 하고있는 객체를 위한 객체 템플릿(Object Template)을 만든다.

Accessing Dynamic Variables – 2

// 객체 템플릿 생성

Handle<ObjectTemplate> point_templ = ObjectTemplate::New();

각각의 JavaScript Point객체는 내부 필드(Internal Field)에 의해 wrapping된 C++객체의 참조를

유지한다. 이 필드는 JavaScript 에서 접근 할 수 없고, 오직 내부(C++코드)에서만 접근 할 수

있기 때문에 내부 필드(Internal Field)라고 불려지게 되었다. 객체는 여러 개의 내부 필드(Internal

Field)를 가질 수 있는데, 설정 가능한 내부 필드의 수는 아래와 같이 지정할 수 있다.

Page 17: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

Accessing Dynamic Variables – 3

// 생성된 객체 템플릿의 최대 저장할 수 있는 내부 필드 개수 지정(최대 1개)

point_templ->SetInternalFieldCount(1);

설정된 내부 필드(Internal Field)의 최대 지정 가능한 수는 1 이다. 그리고 C++객체의 인덱싱

가능한 번호는 0이 된다.

템플릿에 x, y 의 Accessor 를 추가한다.

Accessing Dynamic Variables – 4

// 객체 템플릿에 x, y객체의 Accessor를 설정한다.

// 즉, x는 Getter -> GetPointX, Setter -> SetPointX와 같이

point_templ.SetAccessor(String::New("x"), GetPointX, SetPointX); point_templ.SetAccessor(String::New("y"), GetPointY, SetPointY);

다음, 위에서 Accessor 와 내부 필드 수(Internal Field Count)를 설정한 객체 템플릿(Object

Template)의 인스턴스를 생성하고, 생성된 인스턴스에 Point 객체의 포인터를 v8::External 로

wrapping하여 내부 필드(Internal Field)의 인덱스 0 번에 설정 한다.

Accessing Dynamic Variables – 5

Point* p = ...; Local<Object> obj = point_templ->NewInstance();

// 객체 템플릿의 인스턴스에 내부 필드 0번 위치에 객체 p를 설정한다.

obj->SetInternalField(0, External::New(p));

v8::external 객체는 단순히 void* 로 wrapping 하는 것이다. External 객체는 오직 내부

필드(Internal Field)에 참조 값(Reference Value)를 저장하기 위해 사용한다. JavaScript 객체는

C++객체를 직접(Directly) 참조 할 수 없다. 그래서 v8::external 은 JavaScript 와 C++의

다리(Bridge)역할을 하는 것이다. 그런 의미에서 v8::external 은 C++객체를 JavaScript 에서 참조할

수 있게 하는 핸들(Handle)과는 정 반대(Opposite)의 의미를 가진다.

Page 18: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

여기에 x 의 Get / Set 의 Accessor 가 정의 되어있다. y 에 대한 Get / Set 은 x 와 동일하며

단순히 x를 y로 변경하면 된다.

Accessing Dynamic Variables – 6

// x의 Getter

Handle<Value> GetPointX(Local<String> property, const AccessorInfo &info) {

// AccessorInfo로부터 Accessor의 객체를 얻는다.

Local<Object> self = info.Holder();

// 객체의 내부 필드 0번위치에서 v8::External로 캐스팅하여 내부 필드에 저장된

// Point객체를 추출 한다.

Local<External> wrap = Local<External>::Cast(self->GetInternalField(0)); void* ptr = wrap->Value();

// 추출한 Point 객체의 값 x를 획득하여 이를 v8::Integer로 변환하여 반환한다.

int value = static_cast<Point*>(ptr)->x_; return Integer::New(value); }

// x의 Setter

void SetPointX(Local<String> property, Local<Value> value, const AccessorInfo& info) { Local<Object> self = info.Holder(); Local<External> wrap = Local<External>::Cast(self->GetInternalField(0)); void* ptr = wrap->Value(); static_cast<Point*>(ptr)->x_ = value->Int32Value(); }

Accessor 는 내부 필드(Internal Field)에 wrapping 되어 있던 Point 객체의 참조를

추출(Extract)한다. 그리고 연관된 필드와 읽기, 쓰기 작업을 수행한다.

4-5. Interceptors

JavaScript 의 Script 에서 모든 객체 프로퍼티에 접근할 때 특정 콜백(Callback)이 호출 되도록

할 수 있습니다. 이것을 인터셉터(Interceptor)라 부릅니다. 효율성을 위해 인터셉터(Interceptor)는

두 가지 종류가 있다.

Named Property Interceptors – 문자열 이름에 프로퍼티에 접근할 때 콜백을 호출한다.

예를 들어 document.theFormName.elementName 와 같은 경우

Indexed Property Interceptors – 인덱스에 의해서 프로퍼티에 접근할 때 콜백을 호출한다.

예를 들어 document.forms.elements[0] 와 같은 경우

Page 19: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

객체 템플릿(Object Template)의 SetNamedPropertyHandler 를 사용하여 Get / Set 인터셉터를

설정 할 수 있다.

Interceptors 예제 - 1

Handle<ObjectTemplate> result = ObjectTemplate::New(); result->SetNamedPropertyHandler(MapGet, MapSet);

Getter인 MapGet은 아래와 같다.

Interceptors 예제 - 2

Handle<Value> JsHttpRequestProcessor::MapGet(Local<String> name, const AccessorInfo &info) { // Fetch the map wrapped by this object. map<string, string> *obj = UnwrapMap(info.Holder()); // Convert the JavaScript string to a std::string. string key = ObjectToString(name); // Look up the value if it exists using the standard STL idiom. map<string, string>::iterator iter = obj->find(key); // If the key is not present return an empty handle as signal. if (iter == obj->end()) return Handle<Value>(); // Otherwise fetch the value and wrap it in a JavaScript string. const string &value = (*iter).second; return String::New(value.c_str(), value.length()); }

Accessor 처럼 JavaScript 의 프로퍼티에 접근했을 때 특정 콜백(Callback)을 실행(Invoke)한다.

다만 Accessor 와 인터셉터(Interceptor)와의 차이점은 인터셉터(Interceptor)는 모든 프로퍼티를

다루(Handle)는데 반면에 Accessor는 특정한 하나의 프로퍼티와 결합되어있다.

예제의 자세한 코드 내용은 V8의 소스코드내부의 process.cc 샘플을 참조하면 된다.

4-6. Security Model

Same Origin Policy

동일 출처[영역] 정책(Same Origin Policy)는 어떤 하나의 출처(Origin)의 문서 또는 로드 된

Script 가 다른 출처(Origin)에 정의된 프로퍼티를 획득 및 설정(Getting / Setting)하는 것을 방지

하는 것이다. 여기서 출처(Origin)이란 도메인 이름(www.haejung.com), 프로토콜(http, https)

그리고 포트(www.haejung.com:80)의 조합으로 이루어진다. 두 개의 웹 페이지(Webpages)가 앞의

3 개의 조합이 모두 같다면 동일한 출처(Same Origin)에 있다고 볼 수 있다. 이러한 보호 정책이

Page 20: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

없다면 악의적인 웹 페이지(Web page)가 다른 웹 페이지(Web page)의 무결성을 손상 시킬 수

있다.

V8 에서 출처(Origin)이란 Context 으로 정의 되어 있다. 기본(Default)값으로 하나 이외의 다른

어떤 Context 에서 접근하는 호출은 허용되지 않는다. 하지만 보안 토큰(Security Token)을

사용하면 다른 Context 에서 접근하는 것이 가능하다. 보안 토큰은 일반적으로 특정한 값이다.

상징적인 의미(Symbol), 특징적인 문자열로 어디에도 존재하지 않는 유일한 것으로 한다. 보안

토큰은 부가 선택사항(Option)이며 Context 를 초기 설정할 때 SetSecurityToken 메소드를

사용하여 설정 한다. 만약 Context 가 생성될 때 특정한 보안 토큰(Security Token)이 설정 되니

않으면 자동으로 생성되어 설정된다.

Global 변수에 접근을 시도 할 때 V8 보안 시스템은 처음 접근 하려는 Global 변수의 보안

토큰(Security Token)과 접근을 시도 하는 코드의 보안 토큰(Security Token)을 대조(Against)하여

검사한다. 토큰이 일치 하다면 접근을 허용한다. 만약 보안 토큰(Security Token)이 일치 하지

않는다면 접근이 허용되는지 여부를 확인하기 위해 추가로 콜백(Callback)을 수행한다. 객체에

대한 접근 권한을 객체 템플릿(Object Template)의 SetAccessCheckCallbacks 메소드를 통해 보안

콜백(Security Callback)을 설정하여 객체에 대한 허용(Allow) 여부를 지정할 수 있다. V8 의 보안

시스템은 엑세스 되는 객체의 보안 콜백을 가져(Fetch)올 수 있으며, 다른 Context 가 접근을

시도할 때 접근 허용 여부(Allow)를 묻기(To ask) 위해 보안 콜백(Security Callback)을 호출 한다.

보안 콜백은 접근을 시도하는 객체에 대한 다음 정보를 제공한다. 접근하려는 프로퍼티의 이름,

접근 가능한 타입(읽기, 쓰기, 삭제가능 여부 등) 그리고 접근 가능한지 아닌지에 대하여 접근

가능 여부를 반환(Return) 한다.

4-7. Exceptions

V8 은 에러가 발생하면 예외(Exception)을 발생(Throw)한다. 예를 들어, Script 또는

함수(Function)이 존재 하지 않는 프로퍼티에 대하여 읽기(Read)를 수행할 때, 또는

함수(Function)를 호출 하지만 호출 당하는 것이 함수(Function) 타입이 아닐 때와 같은 경우

예외를 발생한다.

V8 은 작업이 성공적으로 종료되지 않으면 빈 핸들(Empty Handle)을 반환(Return) 한다.

그러므로 프로그램 수행 중, 반환된(Returned) 핸들이 빈 핸들(Empty Handle)인지 아닌지

확인(Check)하는 것은 중요하다. 핸들이 비어 있는지 확인 하는 방법은 Handle 의 IsEmpty()

메소드를 통하여 확인 할 수 있다.

Page 21: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

TryCatch를 사용하여 발생한 예외를 확인(Catch)할 수 있다.

Exception 예제

TryCatch trycatch; Handle<Value> v = script->Run();

// 정상적으로 Script가 수행되지 못하면 빈 핸들을 반환 한다.

if (v.IsEmpty()) { Handle<Value> exception = trycatch.Exception(); String::AsciiValue exception_str(exception); printf("Exception: %s\n", *exception_str); // ... }

만약 반환된 핸들이 빈 핸들이고, 여기에 TryCatch 가 없다면, 분명 코드는 잘못될 것이다.

하지만 TryCatch를 두어 발생한 예외(Exception)을 처리하게 되면 프로그램은 계속 수행 가능하다.

4-8. Inheritance

JavaScript 는 객체 지향 언어이며 class-free 이고 고전적인 클래스 상속 대신에 프로토타입

(Prototypal)적인 상속을 사용한다. 이는 C++이나 Java 와 같은 전통적인 객체 지향 언어에

익숙해져 있는 프로그래머에게 혼란을 느끼게 한다.

C++, Java 와 같은 클래스 기반(Class-based)의 객체 지향 언어가 클래스와 인스턴스라는 두

가지 별개 엔티티(Entities)의 개념에 근거하고 있기 때문이다. JavaScript 는 프로토타입 기반의

언어이다. 따라서 단순한 객체만 가지고 있을 뿐 따로 구별을 만들지는 않는다. JavaScript 는

기본적으로 클래스 계층의 선원을 지원하지 않는다. 그러나 JavaScript 의 프로토타입 메커니즘

(Mechanism)은 객체의 모든 인스턴스에게 임의(Custom)의 프로퍼티와 메소드(Method)를

추가하는 작업을 단순화 했다.

다음 JavaScript예제를 통해 임의(Custom)의 프로퍼티를 추가한다.

Inheritance 예제 – 1

// Create an object "bicycle" function bicycle(){ } // Create an instance of bicycle called roadbike

var roadbike = new bicycle() // Define a custom property, wheels, on roadbike

roadbike.wheels = 2

위 예제에서 임의의(Custom) 프로퍼티를 추가하는 방법은 오직 이미 생성된 객체의

인스턴스에게 추가할 수 있다. 만약 또 다른 bicycle()의 인스턴스 mountainbike 를 생성하고 나서

Page 22: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

mountainbike.wheels 는 wheels 프로퍼티에 명시적으로 값을 추가하지 않으면 undefined 를

반환(Return)한다.

객체의 모든 인스턴스가 임의의(Custom) 프로퍼티가 추가되어 있는 것은 많은 도움을 줄 수

있다. 즉, 모든 bicycle 가 wheel 프로퍼티를 가지게 되는 하는 것이다. 여기서 JavaScript 의

프로토타입 객체가 매우 유용하다. 프로토타입 객체를 사용하는 것은 임의의(Custom) 프로퍼티를

추가하기 전에 객체에 키워드 prototype 사용한다. 아래 예제를 보자.

Inheritance 예제 – 2

// First, create the "bicycle" object function bicycle(){ } // Assign the wheels property to the object's prototype

bicycle.prototype.wheels = 2

이제 bicycle()의 모든 인스턴스는 미리 만들어진 wheels 프로퍼티를 가지게 된다.

같은 맥락에서 V8 의 템플릿(Template)에서는 다음과 같이 할 수 있다. 각 FunctionTemplate 는

Function 의 Prototype 을 제공할 수 있는 PrototypeTemplate 메소드를 가지고 있다. 예제와 같이

FunctionTemplate 의 모든 인스턴스에 wheels 프로퍼티가 존재하도록 PrototypeTemplate 을

이용하여 C++함수(Function)와 결합된 프로퍼티를 설정 할 수 있습니다.

Inheritance 예제 – 3

Handle<FunctionTemplate> biketemplate = FunctionTemplate::New();

// PrototypeTemplate() 메소드에 wheels 프로퍼티를 C++의 MyWheelsMethodCallback으로 등록

biketemplate->PrototypeTemplate().Set( String::New("wheels"), FunctionTemplate::New(MyWheelsMethodCallback)->GetFunction(); )

모든 biketemplate 의 인스턴스가 프로토타입 체인(Prototype chain)에 wheels 메소드를 가지고

있기 때문에 wheels 프로퍼티를 호출할 때, C++의 MyWheelsMethodCallback을 호출 하게 된다.

V8 의 FunctionTemplate 클래스는 공용 멤버 함수인 Inherit()을 제공한다. 이 메소드는 다른

FunctionTemplate으로부터 상속받고자 원할 때 호출 한다.

Inheritance 예제 – 4

void Inherit(Handle<FunctionTemplate> parent);

Page 23: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

5. 빌드

V8 소스 코드를 받고 빌드를 수행해 본다. 환경은 리눅스, 윈도우에서 진행한다.

리눅스(Ubuntu 10 or later)

참조: http://code.google.com/intl/ko-KR/apis/v8/build.html

설치 목록: GNU GCC, Scons

윈도우(Windows 7)

참조: http://code.google.com/p/v8/wiki/BuildingOnWindows

설치 목록: Microsoft Visual Studio 2010(2005, 2008), SVN, Python, Scons

각 환경은 위와 같이 2 가지 운영체제에서 진행하며 환경 설정 부분만 다르며, 빌드 수행

내용은 대부분 동일하다.

5-1. 환경 설정

리눅스(Ubuntu)

1. Ubuntu에서 기본 빌드 환경과 Subversion, Scons 설치 하기

윈도우(Windows 7)

1. Microsoft Visual Studio 2010 설치

Page 24: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

2. SVN (Cygwin)

위치: http://cygwin.com/setup.exe

[설치를 진행한다]

[설치할 패키지에서 subversion을 클릭하여 skip 에서 bin설치가 되도록 한다]

[Cygwin을 실행하여 SVN이 설치 되었는지 확인한다]

Page 25: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

Cygwin 은 SVN 을 사용하기 위해 설치하는 것이다. 따라서 사용자 기호에 맞게 다른

SVN클라이언트 프로그램을 사용해도 상관없다. (Totories SVN 등)

3. Python 설치하기 (2.7.2 버전 기준)

[1] 다운로드 위치: http://www.python.org/download/releases/2.7.2/

[2] 위 주소에서 Windows x86 MSI Installer (2.7.2)를 다운로드 받는다.

[3] python-2.7.2.msi 를 실행한다.

[4] 설치 완료

4. Scons 설치 (A Software Construction Tool)

[1] 다운로드 위치: http://sourceforge.net/projects/scons/files/scons/2.1.0/

[2] 파일 리스트에서 scons-2.1.0.win32.exe를 다운로드 받는다.

[3] 앞서 설치한 Python 설치 위치 선택

Page 26: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

[4] 설치 완료

설치 완료 후 C:\Python27\Scripts 위치에 정상 설치 되었는지 확인한다.

5. 환경 변수 설정

제어판 – 시스템 - 고급 시스템 설정 - 환경 변수

환경변수에서 Path항목에 위 Scons의 설치 위치(C:\Python27\Scripts)를 설정한다.

위와 같이 추가한다.

Page 27: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

5-2. 소스 받기

#) svn checkout http://v8.googlecode.com/svn/trunk src

위 명령어를 사용하여 src위치에 v8 소스코드를 다운 받는다(위치는 편의대로 변경 가능하다)

리눅스(Ubuntu)

리눅스 Shell에서 V8 소스코드 받기

윈도우(Windows 7)

Cygwin을 실행하여 SVN으로 V8 소스코드를 받는다.

Page 28: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

소스 코드를 모드 다운 받은 후 받을 파일을 확인해 본다.

리눅스(Ubuntu)

윈도우(Windows 7)

5-3. 빌드 하기

V8 은 Scons 라는 빌드 유틸리티를 사용하며 각 운영체제에 맞게 알아서 빌드 해준다. Scons 의

빌드 옵션을 확인 하려면, 타겟 소스가 있는 곳에서 #) scons --help 수행하면 된다. Scons 는

Scons 을 실행한 디렉터리 위치에서 SConstruct 파일에 작성되어 있는 스크립트를 읽어 빌드 시

사용 가능한 옵션을 출력해준다.

리눅스(Ubuntu)

[1] V8 소스코드 있는 곳으로 이동한다

[2] #) scons mode=debug library=shared 실행

기본 빌드 옵션은 release 에 static 으로 빌드를 수행하므로 디버그 모드에 shared

library로 빌드 한다(사용자 편의에 따라 옵션은 수정한다)

[3] 빌드 완료

[4] libv8_g.so, libv8preparser_g.so 라이브러리 파일 확인

Page 29: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

윈도우(Windows 7)

[1] 시작 – 모든프로그램 – Microsoft Visual Studio 2010 – Visual Studio Tool -

Visual Studio 명령 프롬프트(2010) 실행

[2] V8 소스코드 있는 곳으로 이동한다

[3] #> scons env="PATH:%PATH%,INCLUDE:%INCLUDE%,LIB:%LIB%"

mode=debug library=shared msvcrt=shared 실행

[4] 빌드 완료

[5] v8_g.dll, v8_g.lib, v8preparser_g.dll, v8preparser_g.lib 라이브러리 파일 확인

Page 30: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

5-4. Hello World

참조: http://code.google.com/intl/ko-KR/apis/v8/get_started.html

Hello World 예제 코드

#include <v8.h> using namespace v8; int main(int argc, char* argv[]) { // Create a stack-allocated handle scope. HandleScope handle_scope; // Create a new context. Persistent<Context> context = Context::New(); // Enter the created context for compiling and // running the hello world script. Context::Scope context_scope(context); // Create a string containing the JavaScript source code. Handle<String> source = String::New("'Hello' + ', World!'"); // Compile the source code. Handle<Script> script = Script::Compile(source); // Run the script to get the result. Handle<Value> result = script->Run(); // Dispose the persistent context. context.Dispose(); // Convert the result to an ASCII string and print it. String::AsciiValue ascii(result); printf("%s\n", *ascii); return 0; }

위 Hello World 예제 코드를 파일로 작성하여 V8 소스 코드 및 빌드 된 라이브러리가 있는

위치에 hello_world.cpp로 만든다(사용자 편의대로 하면 된다).

리눅스(Ubuntu)

[1] V8소스 코드 위치로 이동한다.

[2] 위 예제 코드를 복사하여 파일을 hello_world.cpp 파일을 만든다.

[3] #) g++ -o hello_world hello_world.cpp -m32 -Iinclude -lv8_g –lpthread 실행

[4] ./hello_world 실행

[5] Hello, World! 메시지가 출력되는지 확인

Page 31: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

윈도우(Windows 7)

[1] V8소스 코드 위치로 이동한다.

[2] 위 예제 코드를 복사하여 파일을 hello_world.cpp 파일을 만든다.

[3] #> cl /Iinclude /DUSING_V8_SHARED hello_world.cpp v8_g.lib 실행

[4] hello_world.exe 실행

[5] Hello, World! 메시지가 출력되는지 확인

Page 32: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

6. 예제

앞에서 각 항목에 관하여 대략적인 설명을 했다. 이제 간단한 예제를 통하여 V8 의 각 항목을

이해해 본다.

6-1. Function Template

v8_example_01.cpp 예제

설명: Log출력용 Callback 함수 선언

Page 33: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

설명: [2]은 JavaScript 를 바로 실행하기 위해 v8::String 으로 선언하고, [3].[4]은 JavaScript World 가 실행

하는 환경인 Context 를 선언 및 진입(Enter)하는 부분이다. [5]는 앞서 선언한 LogCallback 을

FunctionTemplate 으로 Wrapping 하여 인스턴스 func 을 생성한다. [6]는 함수 템플릿을 Context 의 Global

객체에 등록하여, JavaScript World 에서 “log” 함수로 동작하게 설정한다. [8],[9]에서 실행할 script 를

컴파일하여 바로 기계코드(Machine Code)로 생성한다. [10],[11]에서 앞서 컴파일한 script 를 실행한다. 이때

실행 결과 result 는 실행 결과에 따라서 정상적인 실행이 불가능할 경우 빈 Value 를 반환하는데 [11]에서 그

예외 처리를 수행한다.

[12]은 Persistent Handle 선언한 context 를 Dispose 하여 명시적으로 메모리 해제 시킨다. 이유는

Persistent핸들은 HandleScope의 영향을 받지 않기 때문이다.

[2]의 script 에서 log(“Call LogCallback”)은 JavaScript World 에서 실행하며, script 실행 전에 Context 의

Global 에 등록된 log 함수를 호출하게 되어 메시지 “Call LogCallback”을 C++의 Handle<Value>

LogCAllback(const Arguments& args)에서 args로 전달 받아서 Console에 출력하게 된다.

출력 화면

Page 34: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

6-2. Object Template

v8_example_02.cpp 예제

설명: 임의의 객체 템플릿을 생성한다. 이 객체 템플릿은 v8::String 타입의 프로퍼티 tp 를 가지고 있다.

따라서 object.tp로 반환되는 값은 string타입의 “Temporary Property” 문자열이 된다.

Page 35: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

설명: [2]은 JavaScript 를 바로 실행하기 위해 v8::String 으로 선언한다. [7]에서 임의의 객체 템플릿을

생성하고 생성된 객체 템플릿의 인스턴스 MDObject 를 Context 의 Global 객체에 “MicroData” 객체로

설정한다.

출력 화면

Page 36: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

6-3. Accessors

Accessing Static Global Variables

v8_example_03.cpp 예제

설명: Log 출력 용 C++ Callback 함수 정의

설명: 정적 전역 변수를 Accessor 를 사용하여 설정한다. 전역 변수 string tp는 GetTemporaryProperty,

SetTemporaryProperty 에 의해서 Get/Set 된다. 이들 Getter/Setter 함수를 tp 의 Accessor 로 설정 하며

MakeMicroDataObjectTemplate 에서 [1]항목에 SetAccessor 메소드를 사용하여 객체 템플릿에 설정하게

된다. 즉, tp 라는 프로퍼티를 설정하게 되며 이 프로퍼티의 Get/Set 을 담당하는 Accessor 를 함께 설정하게

되는 것이다. StringToV8String, V8StringToString은 단순히 타입 변환을 수행한다.

Page 37: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

설명: [2]은 JavaScript 를 바로 실행하기 위해 v8::String 으로 선언한다. [7]에서 임의의 객체 템플릿을

생성하고 생성된 객체 템플릿의 인스턴스 MDObject 를 Context 의 Global 객체에 “MicroData” 객체로

설정한다.

출력 화면

Page 38: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

Accessing Dynamic Variables

v8_example_04.cpp 예제

설명: Log 출력 용 C++ Callback 및 문자열 타입 변환 함수 정의한다.

설명: 이름, 나이를 저장하는 클래스 Person 정의한다.

설명: C++ 클래스 Person을 JavaScript에 노출(Expose) 하기 위한 PersonWrapper 정의한다.

Page 39: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

설명: PersonWrapper 의 소멸자, 영구 핸들(Persistent Handle)의 Dispose()를 호출하여 명시적으로 메모리

해제 한다.

설명: JavaScript World 에 Person 클래스를 제공하기 위한 Context 에 설정 한다. [1] JavaScript 가 실행

환경인 Context 를 생성하고, [2]에서 이후 진행되는 모든 연산이 Context 위에서 실행되도록 Context 에

진입한다. [3],[4] Log 출력 용 함수 템플릿을 생성하고 등록한다. [5] Person 객체를 제공하기 위한 객체

템플릿을 생성하고, 그 템플릿의 인스턴스를 생성한다. [6] 앞서 생성한 person_obj 의 내부 필드(Internal

Field 에 저장하기 위한 Person 객체를 생성하고, 그 포인터를 [7]에서 v8::External 클래스로 Wrapping 하여

SetInternalField()를 사용하여 person_obj 의 내부필드 0 번위치에 등록한다. [8] person_obj 객체를 JavaScript

World에서 “person”이라는 객체로 제공하기 위해 Set() 메소드를 사용하여 설정한다.

이번 예제에서의 핵심은 동적 객체에 접근하기 위하여 객체 Wrapping하고 내부 필드에 등록하는 부분이다. [6], [7]

Page 40: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

설명: 인자로 전달 받은 script를 실행한다. [2]에서 앞에 Initialize()에서 선언한 m_Context를 가지고 이 후에

실행되는 script 의 실행 환경을 위해 다시 Context 에 진입(Enter)한다. [3],[4]은 script 를 가지고 컴파일을

수행하며(Machine Code 생성), 결과를 확인한다. [5],[6] 앞서 컴파일한 script 를 실행하며 그 결과를

확인한다.

Page 41: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

설명: 앞서 Initialize() 함수의 [6],[7]번 항목에서 Person 객체의 포인터를 v8::External 로 Wrapping 하여 내부

필드에 설정했다. 여기서는 반대로 내부 필드에 설정 되어있는 객체를 획득하여, 그 객체가 가지고 있는

정보를 제공한다. Person* UnwrapPerson(Handle<Object>)는 전달 받은 인자의 내부 필드 0 번에 위치한

객체를 Person*로 캐스팅 해준다. GetPersonName(), SetPersonName(), GetPersonAge(), SetPersonAge()

함수들은 UnwrapPerson()함수로부터 전달 받은 Person 객체를 가지고 이름, 나이 정보를 반환, 설정하는

것이다.

이 부분 또한 이번 예제의 핵심이며 내부 필드로부터 객체를 Unwrapping하는 중요 내용이다.

설명: Person 객체를 JavaScript World 에 제공하기 위한 Person 객체 템플릿을 생성한다. 이 템플릿은

이름(name), 나이(age)의 프로퍼티를 가지며, 각 프로퍼티는 Accessor로 Getter / Setter 를 설정한다.

설명: [2] 실행할 script 를 정의한다. [3] PersonWrapper 객체를 선언한다. [4] pw 객체의 Initailize()를 호출,

인자로 “Haejung Kim”과 29 를 전달하며 Initailize는 전달 받은 인자로 미리 name, age의 값을 설정한다.

[4] 앞의 [2]에서 선언한 script를 실행한다.

script 를 실행하면 Initialize()에 전달된 “Haejung Kim”, 29 의 결과가 출력되며, 그런 후에 “Incross”, 12 값을

Accessor의 Setter를 통하여 내부 필드에 값을 저장하고, 그 결과를 다시 출력하게 된다.

Page 42: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

출력 화면

Page 43: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

6-4. Interceptor

v8_example_05.cpp 예제

설명: Log 출력용 C++ Callback 함수 정의 및 Named, Indexed 의 Getter/Setter 에서 사용할 map, vector 의

자료형 재정의 한다. StringToV8String, V8StringToString은 string의 타입 변환 함수 이다.

설명: Named, Indexed 프로퍼티를 JavaScript World에 노출(Expose)하기 위한 JSPropertyWrapper 클래스

Page 44: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

설명: [1]에서 JavaScript 실행 환경인 Context 를 생성한다. [2]는 앞서 생성한 Context 에 진입하여 이후에

실행되는 모든 연산이 Context 에서 이루어지도록 한다. [3],[4] Log 출력용 Callback 함수를 함수 템플릿 및

인스턴스를 생성 및 설정한다. [5] Interceptor 를 설정하기위한 객체 템플릿을 생성한다. [6],[7] Named

프로퍼티에서 사용할 Map 객체의 포인터를 내부 필드 0 번에 v8::External 로 wrapping 하여 등록한다. [8],

[9]는 앞의 Map 과 마찬가지로 Indexed 프로퍼티에서 사용할 Vector 객체의 포인터를 내부 필드 1 번에에

등록한다. 각각 Map과 Vector 는 임의(“Haejung Kim”, “Incross!”)의 값으로 미리 초기화 한다. [10] JavaScript

World에서 “interceptor”의 객체로 사용가능하게 Context의 Global객체에 inter_obj 를 설정한다.

Page 45: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

설명: 인자로 전달 받은 script를 실행한다. [2]에서 앞에 Initialize()에서 선언한 m_Context를 가지고 이 후에

실행되는 script 의 실행 환경을 위해 다시 Context 에 진입(Enter)한다. [3],[4]은 script 를 가지고 컴파일을

수행하며(Machine Code 생성), 결과를 확인한다. [5],[6] 앞서 컴파일한 script 를 실행하며 그 결과를

확인한다.

설명: pMapString UnwrapJSNamedProperty(Handle<Object>)는 내부 필드 0번에 설정되어 있는 Map객체를

unwrapping하여 Naemd Property의 Getter/Setter에서 Map객체를 사용할 수 있도록 한다.

pVecString UnwrapJSIndexedProperty(Handle<Object>)는 내부 필드 1 번에 설정되어 있는 Vector 객체를

unwrapping하여 Indexed Property의 Getter/Setter에서 Vector객체를 사용할 수 있도록 한다.

Page 46: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

설명: 내부 필드 0 번에 설정되어 있는 Map 객체를 사용하여 Named Property 로 접근하는 객체에 대하여

처리한다. 각 Getter/Setter 의 인자 name 은 접근하는 프로퍼티의 이름을 나타내고, Setter 의 경우는

value를 포함하여 설정하게 된다.

Named Property는 객체 또는 프로퍼티에 object.name or object[name]으로 접근하는 것을 말한다.

Page 47: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

설명: 내부 필드 1 번에 설정되어 있는 Vector 객체를 사용하여 Indexed Property 로 접근하는 객체에 대하여

처리한다. 각 Getter/Setter 의 인자 index 는 접근하는 프로퍼티의 Index 를 타내고, Setter 의 경우는 value 를

포함하여 설정하게 된다.

Indexed Property는 객체 또는 프로퍼티에 object[0] or object[1] 처럼 번호를 Index하여 접근하는 것을 말한다.

설명: 인터셉터가 설정 되어있는 객체 템플릿을 생성한다. [1]에서 생성된 객체 템플릿에 [2]에서 각각

Named, Indexed Property를 설정, 지정된 Getter/Setter 메소드를 프로퍼티에 Named, Indexed로 접근할 때

호출 하게 된다. [3]에서 내부 필드의 최대 허용 개수를 2 개로 설정한다.

Page 48: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

설명: [2]은 실행할 script를 정의 하며, [3]에서 JSPropertyWrapper 클래스의 객체 pw를 생성한다. [4],[5]에서

초기화 및 script를 실행한다.

[2] script 는 Named 와 Indexed 의 프로퍼티에 대한 접근을 시도한다. Initialize()에서 초기화 진행중 각 Map,

Vector 에 임의의 객체를 설정하여, interceptor.Kim 에서 미리설정된 임의의 값을 보여준다. John, Emi 의

프로퍼티를 설정하고 이를 바로 출력한다. interceptor[Neil]은 존재하지 않는 프로퍼티로 출력 화면과 같이

Invalid Key Value 를 반환한다. 그리고 Indexed 프로퍼티도 interceptor[0], interceptor[1]과 같이 Indexing 에

의한 프로퍼티 접근을 수행하며, inteceptor[2]와 같이 존재하지 않는 프로퍼티에 접근하는 경우 Invalid Index

Value를 반환한다.

출력 화면

Page 49: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

6-5. Constructor

v8_example_06.cpp 예제

설명: Log 출력용 C++ Callback 함수 정의 및 JavaScript 에서 new 로 생성되는 객체의 생성자를 정의한다.

이 생성자 함수 Callback 은 메시지 객체를 생성한다. [2]에서 만약 인자가 있고 또 인자가 문자열인경우

인자로 받은 문자열을 프로퍼티 msg에 설정한다. 없을 경우 임의로 “Hello World!”를 msg에 설정한다.

Page 50: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

설명: [2]는 실행할 script 를 선언한다. [3],[4]는 JavaScript 실행환경인 Context 를 생성하고 진입(Enter)한다.

[5],[6]은 Log 출력 용 함수를 등록한다. [7]에서 생성자로 사용할 FunctionTemplate 를 생성한다.

JavaScript 에서 “JMessage”라는 함수로 사용하며 “new “ 키워드와 함께 호출될 때 Constructor 로

동작하도록 MessageConstructor 함수 내부에서 확인하고 처리한다. 즉, JMessage()과 같은 함수 호출은

않되며, new JMessage()처럼 new 키워드를 포함하여 생성자로 호출 할 때만 객체를 생성하도록 한다.

[8],[9],[10],[11],[12]는 script 의 실행 및 결과를 확인한다. [13]은 영구 핸들(Persistent Handle)로 생성한

context를 메모리 해제한다.

출력 화면

Page 51: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

6-6. Call JavaScript Function

JavaScript World에 정의된 함수나 객체를 반대로 Native(C++)에서 호출한다.

v8_example_07.cpp 예제

설명: [1]에서 JavaScript 의 실행환경인 Context 를 생성하고 진입(Enter)한다. [2]에서 실행할 script 를

선언한다. script 에는 함수 sum 이 정의 되어 있다. [3]에서 [2]의 script 를 컴파일 하고 실행한다. 즉,

Context 에 sum 객체가 존재하게 된다. [4]에서 [3]에서 실행 후 생성되는 sum 객체를 가져온다. [5]는 sum 을

함수 객체로 캐스팅한다. [6]은 가져온 함수에 전달할 인자 v8_a, v8_b 를 생성하고 임의 값 101, 303 를

설정한다. [7]에서 앞서 [6]에서 설정한 v8_a, v8_b 를 Value 배열에 설정하여 함수 객체의 Call() 메소드

호출하여 전달한다. [8]에서 [7]의 호출 결과인 404를 출력한다. [9] 은 영구 핸들(Persistent Handle)로 생성한

context를 메모리 해제한다.

출력 화면

Page 52: V8 JavaScript Engine – 김해중(2011.10.21)pds24.egloos.com/pds/201203/07/22/V8_JS_Engine_posted.pdf · V8 JavaScript Engine – 김중 (2011.10.21) 3. V8 Design Element V8은

V8 JavaScript Engine – 김해중(2011.10.21)

7. 참고문서

V8 Project page

http://code.google.com/p/v8/

V8 Document page

http://code.google.com/intl/ko-KR/apis/v8/intro.html

V8 API page

http://izs.me/v8-docs/main.html

V8 Reference blog - 1

http://create.tpsitulsa.com/blog/2009/01/29/v8-objects/

V8 Reference blog – 2

http://www.homepluspower.info/2010/06/v8-javascript-engine-tutorial-part-1.html

V8 Reference blog – 3

http://blog.owned.co.za/?p=205

V8 Reference blog – 4

http://www.codeproject.com/KB/library/Using_V8_Javascript_VM.aspx

Reference Project : V8 node

https://github.com/joyent/node