int main(int argc, char* argv[]) {
v8::V8::InitializeICUDefaultLocation(argv[0]);
v8::V8::InitializeExternalStartupData(argv[0]);
std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(platform.get());
v8::V8::Initialize();
v8::Isolate::CreateParams create_params;
create_params.array_buffer_allocator =
v8::ArrayBuffer::Allocator::NewDefaultAllocator();
v8::Isolate* isolate = v8::Isolate::New(create_params);
{
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Context> context = v8::Context::New(isolate);
v8::Context::Scope context_scope(context);
{
v8::Local<v8::String> source =
v8::String::NewFromUtf8Literal(isolate, "'Hello' + ', World!'");
v8::Local<v8::Script> script =
v8::Script::Compile(context, source).ToLocalChecked();
v8::Local<v8::Value> result = script->Run(context).ToLocalChecked();
v8::String::Utf8Value utf8(isolate, result);
printf("%s\n", *utf8);
}
{
const char csource[] = R"(
let bytes = new Uint8Array([
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0x01,
0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07,
0x07, 0x01, 0x03, 0x61, 0x64, 0x64, 0x00, 0x00, 0x0a, 0x09, 0x01,
0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b
]);
let module = new WebAssembly.Module(bytes);
let instance = new WebAssembly.Instance(module);
instance.exports.add(3, 4);
)";
v8::Local<v8::String> source =
v8::String::NewFromUtf8Literal(isolate, csource);
v8::Local<v8::Script> script =
v8::Script::Compile(context, source).ToLocalChecked();
v8::Local<v8::Value> result = script->Run(context).ToLocalChecked();
uint32_t number = result->Uint32Value(context).ToChecked();
printf("3 + 4 = %u\n", number);
}
}
isolate->Dispose();
v8::V8::Dispose();
v8::V8::DisposePlatform();
delete create_params.array_buffer_allocator;
return 0;
}
Initialize V8.
v8::V8::InitializeICUDefaultLocation(argv[0]);
v8::V8::InitializeExternalStartupData(argv[0]);
std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(platform.get());
v8::V8::Initialize();
- V8 플렛폼 객체?
- V8 엔진은 자바스크립트 코드를 실행하는데 집중하고 V8 플랫폼 객체는 플랫폼(OS) 의존적인 작업을 처리한다. (엔진의 동작과 운영 체제 간의 연결 고리 역할)
- 플랫폼 의존적인 작업
- 비동기 작업 스케줄링
setTimeout , promise 등과 같이 백그라운드에서 비동기 작업을 하고 완료했을 때 자바스크립트 엔진에 알린다.
- 스레드 관리
- 자바스크립트는 싱글스레드로 실행되지만 가비지 컬렉션, JIT 컴파일 작업은 별도의 스레드에서 진행한다. = V8 엔진은 여러 스레드가 필요하다
- 플랫폼 객체는 여러 스레드를 효율적으로 관리한다.
- 운영체제와 상호작용
- 파일, 네트워크, 시스템 시간 등 운영체제 리소스에 접근할 수 있도록 한다.
- V8 엔진 자체는 자바스크립트 실행을 담당하고, 운영체제 리소스에 직접 접근하지 않는다.
Create a new Isolate and make it the current one.
v8::Isolate::CreateParams create_params;
create_params.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
v8::Isolate* isolate = v8::Isolate::New(create_params);
{
v8::Isolate::Scope isolate_scope(isolate);
- Isolate 역할은?
- V8 엔진에서 “독립된” 자바스크립트 실행 환경을 제공한다.
- 자바스크립트 실행 시 컨텍스트와 데이터는 모두 특정 Isolate 안에서만 존재함.
- “독립된” : Isolate 들 끼리 서로 데이터를 주고 받는 일은 없다.
- ⇒ 독립적이고 안전한 자바스크립트 실행 환경. (스레드 안정성)
- 가비지 컬렉션 및 메모리 관리
- 각 Isolate는 자신만의 heap 영역을 가지고 있고 이 힙 영역에서 자바스크립트 객체를 관리함.
- 여러 Isolate를 만들어서 병렬 실행을 할 수 있다.
Create a stack-allocated handle scope.
v8::HandleScope handle_scope(isolate);
- HandleScope? : 자바스크립트에서 생성된 객체는 자주 생성되고 파괴되는데 이 객체들을 메모리 방면에서 효율적으로 관리하기 위해 사용된다.
- 임시 객체 메모리 관리
- 특정 스코프 안에서 임시로 생성된 V8 객체들의 수명을 관리함. 즉 로컬 핸들(V8 객체에 대한 참조)를 관리한다.
- 스코프가 끝나면 이 스코프 안 모든 객체의 핸들이 자동으로 해체되고 메모리가 회수됨 (가비지 컬랙션)
- 또한 이 핸들이 필요 없어졌을 때 메모리를 자동으로 해체한다. (가비지 컬랙션)
Create a new context. & Enter the context for compiling and running the hello world script.
v8::Local<v8::Context> context = v8::Context::New(isolate);
v8::Context::Scope context_scope(context);
- Context는 자바스크립트 실행환경을 의미하는데 Isolate와 어떤 차이점이?
- → 서로 다른 수준의 자바스크립트 실행환경을 나타낸다.
| 개념 | Isolate | Context |
|---|
| 역할 | 독립적인 V8 자바스크립트 실행 환경 전체를 제공하며, 각 Isolate는 자신의 메모리 힙을 가짐 | 자바스크립트 코드의 변수, 객체, 함수 등의 스코프를 관리하는 실행 환경 |
| 메모리 관리 | 각 Isolate는 자체적인 메모리 힙과 가비지 컬렉션을 가짐 | Isolate 내에서 Context는 스코프 기반으로 관리되며, 여러 개의 Context가 같은 메모리 공간을 공유 가능 |
| 독립성 | 각 Isolate는 서로 완전히 독립적이며 메모리와 객체를 공유하지 않음 | 같은 Isolate 내에서 여러 Context는 서로 독립된 스코프를 가지지만, 동일한 메모리 공간에서 실행될 수 있음 |
| 생성 용도 | 자바스크립트 엔진의 전체적인 실행 환경을 격리하기 위해 사용됨 (예: 멀티 스레드 환경에서 서로 다른 자바스크립트 실행) | 특정 자바스크립트 코드가 실행될 때 사용할 스코프를 정의하기 위해 사용됨 (예: 특정 웹 페이지의 자바스크립트 코드 실행 환경 정의) |
| 유사 개념 | 운영체제의 프로세스에 비유할 수 있음 | 프로세스 내에서의 스레드나 스코프에 비유 가능 |
드디어 코드를 실행
{
v8::Local<v8::String> source =
v8::String::NewFromUtf8Literal(isolate, "'Hello' + ', World!'");
v8::Local<v8::Script> script =
v8::Script::Compile(context, source).ToLocalChecked();
v8::Local<v8::Value> result = script->Run(context).ToLocalChecked();
v8::String::Utf8Value utf8(isolate, result);
printf("%s\n", *utf8);
}
{
const char csource[] = R"(
let bytes = new Uint8Array([
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0x01,
0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07,
0x07, 0x01, 0x03, 0x61, 0x64, 0x64, 0x00, 0x00, 0x0a, 0x09, 0x01,
0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b
]);
let module = new WebAssembly.Module(bytes);
let instance = new WebAssembly.Instance(module);
instance.exports.add(3, 4);
)";
v8::Local<v8::String> source =
v8::String::NewFromUtf8Literal(isolate, csource);
v8::Local<v8::Script> script =
v8::Script::Compile(context, source).ToLocalChecked();
v8::Local<v8::Value> result = script->Run(context).ToLocalChecked();
uint32_t number = result->Uint32Value(context).ToChecked();
printf("3 + 4 = %u\n", number);
}
- 순서
- 자바스크립트 코드를 V8의 문자열로 변환
- 자바스크립트 코드를 컴파일
- 컴파일된 코드를 실행
Dispose the isolate and tear down V8.
isolate->Dispose();
v8::V8::Dispose();
v8::V8::DisposePlatform();
delete create_params.array_buffer_allocator;
return 0;
- Isolate를 해제하고 V8 엔진을 종료
- 할당된 메모리를 해제