Xây Dựng Máy Ảo Độc Lập Với Ngăn Xếp Hệ Thống
Khi thiết kế máy ảo ban đầu, việc gọi hàm trong bytecode ban đầu được chuyển đổi trực tiếp thành các lời gọi hàm native code. Mặc dù cách tiếp cận này có vẻ đơn giản hơn, nhưng nó tạo ra một vấn đề nghiêm trọng: không thể thực hiện chạy từng bước (single-step) trên bytecode được. Để giải quyết điều này, tôi đã quyết định tách biệt hoàn toàn ngăn xếp hệ thống bằng cách tạo một luồng giám sát riêng biệt. Luồng này sẽ kiểm soát luồng chạy của máy ảo, cho phép tạm dừng sau mỗi bước thực thi mà không làm hỏng trạng thái ngăn xếp.
Ý tưởng chính là xây dựng một máy ảo hoàn toàn độc lập với ngăn xếp hệ thống. Việc chỉnh sửa lại kiến trúc máy ảo thực ra khá đơn giản. Thay vì dựa vào ngăn xếp vật lý của hệ thống, tôi thiết kế một bảng mô phỏng ngăn xếp riêng. Trong bảng này, mỗi lần gọi hàm sẽ lưu trữ bốn thông tin quan trọng: điểm gọi hàm, vị trí đỉnh ngăn xếp, số lượng tham số đầu vào và số lượng giá trị trả về cần thiết.
Đặc biệt, tôi phải giữ lại đối tượng thân hàm (function body) trong quá trình thực thi. Lý do là vì toàn bộ hệ thống quản lý bộ nhớ của máy ảo đều dựa trên cơ chế thu gom rác (GC), bao gồm cả bytecode. Nếu không lưu trữ rõ ràng các đối tượng hàm, chúng có thể bị xóa mất trong quá trình GC hoạt động.
Điểm thú vị nằm ở chỗ, bảng ngăn xếp này thực ra đã tồn tại từ trước - ban đầu chỉ dùng để lưu trữ các đối tượng hàm. Nay chỉ cần mở rộng thêm ba trường dữ liệu nữa là có thể đáp ứng yêu cầu mới. Việc chỉnh sửa này không chỉ giải quyết bài toán đơn bước mà còn tạo nền tảng cho các tính năng nâng cao sau này.
Khi thiết kế chế độ chạy mới này, tôi đối mặt với một bài toán quan trọng: nếu kích hoạt chế độ single-step, hiệu suất thực thi bytecode sẽ bị ảnh hưởng. Giải pháp tôi chọn là giữ nguyên chế độ chạy gốc, đồng thời sử dụng kỹ thuật kế thừa để thêm chế độ mới. Điều này đòi hỏi hai chế độ phải có bố cục ngăn xếp tương thích. Trong chế độ chạy liên tục sử dụng ngăn xếp hệ thống, hầu hết các thông tin ngăn xếp ảo có thể được điền giá trị mặc định (nil).
Ưu điểm vượt trội của kiến trúc mới thể hiện rõ khi triển khai coroutine. Nhờ độc lập với ngăn xếp hệ thống, việc thêm hỗ trợ coroutine trở nên cực kỳ đơn giản. Điều mà tôi tưởng sẽ mất cả tuần để hoàn thành, hóa ra chỉ cần 2 giờ đồng hồ thực hiện vào đêm hôm nay :)
Hiện tại, toàn bộ hệ thống đã hoàn thiện: từ trình biên dịch đến máy ảo. Đặc biệt, ngôn ngữ script này đã hỗ trợ các tính năng hướng đối tượng giới hạn. Về mặt hiệu suất, tôi tự tin rằng nó có thể sánh ngang hoặc thậm chí vượt qua Lua trong các bài test thực tế.
Một điểm mạnh vượt trội so với Lua là hệ thống thu gom rác của tôi sử dụng thuật toán phân vùng bộ nhớ thực sự, rất phù hợp cho các ứng dụng server cần vận hành liên tục trong thời gian dài. Việc lưu trữ trạng thái dữ liệu (persistence) cũng trở nên dễ dàng hơn nhiều nhờ cơ chế quản lý bộ nhớ hiệu quả này.
Nếu có thời gian, tôi dự định sẽ phát triển một môi trường IDE bằng .NET để thử nghiệm thêm các tính năng nâng cao. Nhưng cho đến hôm nay, toàn bộ hệ thống đã hoạt động ổn định và sẵn sàng cho các giai đoạn phát triển tiếp theo.