V8 Hello World

송민준·2024년 10월 9일

hello-world.cc

int main(int argc, char* argv[]) {
  // 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();

  // 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);

    // Create a stack-allocated handle scope.
    v8::HandleScope handle_scope(isolate);

    // Create a new context.
    v8::Local<v8::Context> context = v8::Context::New(isolate);

    // Enter the context for compiling and running the hello world script.
    v8::Context::Scope context_scope(context);

    {
      // Create a string containing the JavaScript source code.
      v8::Local<v8::String> source =
          v8::String::NewFromUtf8Literal(isolate, "'Hello' + ', World!'");

      // Compile the source code.
      v8::Local<v8::Script> script =
          v8::Script::Compile(context, source).ToLocalChecked();

      // Run the script to get the result.
      v8::Local<v8::Value> result = script->Run(context).ToLocalChecked();

      // Convert the result to an UTF8 string and print it.
      v8::String::Utf8Value utf8(isolate, result);
      printf("%s\n", *utf8);
    }

    {
      // Use the JavaScript API to generate a WebAssembly module.
      //
      // |bytes| contains the binary format for the following module:
      //
      //     (func (export "add") (param i32 i32) (result i32)
      //       get_local 0
      //       get_local 1
      //       i32.add)
      //
      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);
      )";

      // Create a string containing the JavaScript source code.
      v8::Local<v8::String> source =
          v8::String::NewFromUtf8Literal(isolate, csource);

      // Compile the source code.
      v8::Local<v8::Script> script =
          v8::Script::Compile(context, source).ToLocalChecked();

      // Run the script to get the result.
      v8::Local<v8::Value> result = script->Run(context).ToLocalChecked();

      // Convert the result to a uint32 and print it.
      uint32_t number = result->Uint32Value(context).ToChecked();
      printf("3 + 4 = %u\n", number);
    }
  }

  // Dispose the isolate and tear down V8.
  isolate->Dispose();
  v8::V8::Dispose();
  v8::V8::DisposePlatform();
  delete create_params.array_buffer_allocator;
  return 0;
}

Initialize V8.

  // V8 Engine 초기화
  v8::V8::InitializeICUDefaultLocation(argv[0]);
  v8::V8::InitializeExternalStartupData(argv[0]);
  
  // V8 Platform Object 생성 및 초기화
  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.

// 새로운 Isolate 생성 
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를 스코프 내에서 활성화
  • 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.

// Create a new context.
v8::Local<v8::Context> context = v8::Context::New(isolate);

// Enter the context for compiling and running the hello world script.
v8::Context::Scope context_scope(context);
  • Context는 자바스크립트 실행환경을 의미하는데 Isolate와 어떤 차이점이?
  • → 서로 다른 수준의 자바스크립트 실행환경을 나타낸다.
개념IsolateContext
역할독립적인 V8 자바스크립트 실행 환경 전체를 제공하며, 각 Isolate는 자신의 메모리 힙을 가짐자바스크립트 코드의 변수, 객체, 함수 등의 스코프를 관리하는 실행 환경
메모리 관리각 Isolate는 자체적인 메모리 힙과 가비지 컬렉션을 가짐Isolate 내에서 Context는 스코프 기반으로 관리되며, 여러 개의 Context가 같은 메모리 공간을 공유 가능
독립성각 Isolate는 서로 완전히 독립적이며 메모리와 객체를 공유하지 않음같은 Isolate 내에서 여러 Context는 서로 독립된 스코프를 가지지만, 동일한 메모리 공간에서 실행될 수 있음
생성 용도자바스크립트 엔진의 전체적인 실행 환경을 격리하기 위해 사용됨 (예: 멀티 스레드 환경에서 서로 다른 자바스크립트 실행)특정 자바스크립트 코드가 실행될 때 사용할 스코프를 정의하기 위해 사용됨 (예: 특정 웹 페이지의 자바스크립트 코드 실행 환경 정의)
유사 개념운영체제의 프로세스에 비유할 수 있음프로세스 내에서의 스레드나 스코프에 비유 가능

드디어 코드를 실행

{
  // Create a string containing the JavaScript source code.
  v8::Local<v8::String> source =
      v8::String::NewFromUtf8Literal(isolate, "'Hello' + ', World!'");

  // Compile the source code.
  v8::Local<v8::Script> script =
      v8::Script::Compile(context, source).ToLocalChecked();

  // Run the script to get the result.
  v8::Local<v8::Value> result = script->Run(context).ToLocalChecked();

  // Convert the result to an UTF8 string and print it.
  v8::String::Utf8Value utf8(isolate, result);
  printf("%s\n", *utf8);
}
{
  // Use the JavaScript API to generate a WebAssembly module.
  //
  // |bytes| contains the binary format for the following module:
  //
  //     (func (export "add") (param i32 i32) (result i32)
  //       get_local 0
  //       get_local 1
  //       i32.add)
  //
  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);
  )";

  // Create a string containing the JavaScript source code.
  v8::Local<v8::String> source =
      v8::String::NewFromUtf8Literal(isolate, csource);

  // Compile the source code.
  v8::Local<v8::Script> script =
      v8::Script::Compile(context, source).ToLocalChecked();

  // Run the script to get the result.
  v8::Local<v8::Value> result = script->Run(context).ToLocalChecked();

  // Convert the result to a uint32 and print it.
  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 엔진을 종료
  • 할당된 메모리를 해제
profile
개발자

0개의 댓글