-
MicroQuickJS(MQuickJS) 는 임베디드 시스템용으로 설계된 초경량 JavaScript 엔진으로, 약 10kB RAM과 100kB ROM만으로 실행 가능
-
QuickJS와 유사한 속도를 유지하면서도 메모리 사용량을 줄이기 위해 트레이싱 가비지 컬렉터와 UTF-8 문자열 저장 방식을 채택
- 지원 언어는 ES5에 가까운 제한된 JavaScript 부분집합이며, 오류 가능성이 높은 구문을 금지하는 엄격 모드(strict mode) 만 허용
-
REPL 도구 mqjs 를 통해 스크립트 실행, 바이트코드 저장 및 메모리 제한 설정이 가능하며, 생성된 바이트코드는 ROM에서 직접 실행 가능
- 전체 엔진과 표준 라이브러리가 ROM에 상주해 빠른 초기화와 낮은 메모리 소비를 실현, 임베디드 환경에서의 JavaScript 실행 효율성을 높임
소개
-
MicroQuickJS(MQuickJS) 는 임베디드 시스템을 대상으로 하는 JavaScript 엔진으로, 10kB RAM과 100kB ROM(ARM Thumb-2 코드 포함)에서 동작
-
ES5에 가까운 부분집합만 지원하며, 비효율적이거나 오류 가능성이 높은 구문을 금지하는 엄격 모드(strict mode) 로만 작동
- QuickJS와 코드 일부를 공유하지만, 내부 구조는 메모리 절약을 위해 완전히 다르게 설계됨
-
트레이싱 가비지 컬렉터, CPU 스택 미사용, UTF-8 문자열 저장 방식 사용
REPL
- REPL 명령은 mqjs이며, 스크립트 실행, 평가, 인터랙티브 모드, 메모리 제한 설정, 바이트코드 저장 등을 지원
- 예: ./mqjs --memory-limit 10k tests/mandelbrot.js
-
-o 옵션으로 컴파일된 바이트코드를 파일로 저장 가능
- 저장된 바이트코드는 ./mqjs mandelbrot.bin으로 실행 가능
- 바이트코드는 CPU의 엔디언 및 워드 길이(32/64비트) 에 따라 다르며, -m32 옵션으로 32비트용 바이트코드 생성 가능
-
--no-column 옵션으로 디버그 정보의 열 번호 제거 가능
엄격 모드
-
strict mode만 허용하며, with 키워드 사용 불가, 전역 변수는 반드시 var로 선언해야 함
-
배열의 구멍(hole) 허용 안 함
- 예: a[10] = 2는 TypeError 발생
- 구멍이 있는 배열이 필요하면 일반 객체 사용
-
전역 eval만 지원, 지역 변수 접근 불가
-
값 박싱(value boxing) 비지원 (new Number(1) 등)
JavaScript 부분집합
-
strict mode 기반, ES5 호환성 중심
-
Array 객체는 구멍이 없으며, 범위를 벗어난 인덱스 접근은 오류
-
for in은 객체의 자체 속성만 순회, for of는 배열만 지원
-
글로벌 객체는 존재하지만 getter/setter 불가, 직접 생성한 속성은 전역 변수로 노출되지 않음
-
정규식(Regexp) 은 ASCII만 대소문자 구분 처리, /./은 UTF-16 대신 유니코드 코드포인트 단위로 매칭
-
문자열 함수는 ASCII만 처리 (toLowerCase, toUpperCase)
-
Date는 Date.now()만 지원
- 추가 지원 기능:
-
for of, Typed arrays, \u{hex} 문자열 리터럴
-
Math 함수: imul, clz32, fround, trunc, log2, log10
-
지수 연산자, 정규식 플래그(s, y, u) , 문자열 함수(replaceAll, trimStart, trimEnd), globalThis
C API
-
C 라이브러리 의존성 최소화, malloc, free, printf 미사용
-
메모리 버퍼를 직접 제공해야 하며, 엔진은 해당 버퍼 내에서만 메모리 할당
- 예: ctx = JS_NewContext(mem_buf, sizeof(mem_buf), &js_stdlib)
-
가비지 컬렉션 방식으로 인해 JS_FreeValue() 호출 불필요
- 객체 주소는 할당 시마다 이동 가능하므로, JSValue 포인터 사용 권장
-
JS_PushGCRef() / JS_PopGCRef()로 안전한 참조 관리
-
표준 라이브러리는 ROM에 저장 가능한 C 구조체로 컴파일되어, 빠른 초기화와 낮은 RAM 사용량 달성
-
바이트코드 실행은 ROM에서 가능하며, JS_RelocateBytecode()로 재배치 후 JS_LoadBytecode()와 JS_Run()으로 실행
-
수학 라이브러리(libm.c) 와 부동소수점 에뮬레이터 내장
내부 구조 및 QuickJS 비교
-
가비지 컬렉션: 참조 카운팅 대신 트레이싱·압축형 GC 사용
-
값 표현: CPU 워드 크기(32/64비트)에 맞춰 설계
- 31비트 정수, 유니코드 코드포인트, 부동소수점, 메모리 블록 포인터 저장 가능
-
문자열은 UTF-8로 저장, QuickJS의 8/16비트 배열 방식보다 효율적
-
C 함수는 단일 값으로 저장 가능, 속성 추가 불가
-
표준 라이브러리는 ROM에 상주하며, RAM 객체 최소화로 빠른 엔진 초기화 가능
-
바이트코드는 스택 기반이며, 간접 참조 테이블을 통해 읽기 전용 처리
-
컴파일러는 QuickJS와 유사하지만 비재귀적 파서를 사용해 C 스택 사용량 제한
테스트 및 벤치마크
- 기본 테스트: make test
- QuickJS 마이크로 벤치마크: make microbench
-
Octane 벤치마크(엄격 모드용 수정 버전)는 별도 다운로드 가능
라이선스
-
MIT 라이선스로 배포
- 소스코드 저작권은 Fabrice Bellard와 Charlie Gordon 소유