Một số ý kiến về trình biên dịch JIT của bạn (Tôi hy vọng tôi không viết những điều "delnan" đã viết):
comments Generic
Tôi chắc chắn "thật" trình biên dịch JIT làm việc tương tự như của bạn một. Tuy nhiên bạn có thể làm một số tối ưu hóa (ví dụ: "mov eax, nnn" và "push eax" có thể được thay thế bằng "push nnn").
Bạn nên lưu trữ các biến cục bộ trên ngăn xếp; thường "ebp" được sử dụng làm con trỏ cục bộ:
push ebx
push ebp
sub esp, 8 // 2 variables with 4 bytes each
mov ebp, esp
// Now local variables are addressed using [ebp+0] and [ebp+4]
...
pop ebp
pop ebx
ret
Điều này là cần thiết vì chức năng có thể đệ quy. Việc lưu trữ một biến tại một vị trí cố định (tương đối so với EIP) sẽ làm cho các biến hoạt động giống như các biến "tĩnh". (Tôi giả sử bạn không biên dịch một hàm này nhiều lần trong trường hợp của một hàm đệ quy.)
try/catch
Thực hiện try/catch trình biên dịch JIT của bạn không chỉ phải nhìn vào Java Bytecode mà còn ở thông tin Try/Catch được lưu trữ trong một thuộc tính riêng biệt trong lớp Java. Try/catch có thể được thực hiện theo cách sau:
// push all useful registers (= the ones, that must not be destroyed)
push eax
push ebp
...
// push the "catch" pointers
push dword ptr catch_pointer
push dword ptr catch_stack
// set the "catch" pointers
mov catch_stack,esp
mov dword ptr catch_pointer, my_catch
... // some code
// Here some "throw" instruction...
push exception
jmp dword ptr catch_pointer
... //some code
// End of the "try" section: Pop all registers
pop dword_ptr catch_stack
...
pop eax
...
// The "catch" block
my_catch:
pop ecx // pop the Exception from the stack
mov esp, catch_stack // restore the stack
// Now restore all registers (same as at the end of the "try" section)
pop dword_ptr catch_stack
...
pop eax
push ecx // push the Exception to the stack
Trong một môi trường multi-thread mỗi thread đòi hỏi riêng catch_stack và catch_pointer biến của nó!
loại ngoại lệ cụ thể có thể được xử lý bằng cách sử dụng một "instanceof" theo cách sau:
try {
// some code
} catch(MyException1 ex) {
// code 1
} catch(MyException2 ex) {
// code 2
}
... thực sự là biên soạn như thế này ...:
try {
// some code
} catch(Throwable ex) {
if(ex instanceof MyException1) {
// code 1
}
else if(ex instanceof MyException2) {
// code 2
}
else throw(ex); // not handled!
}
Objects
Một trình biên dịch JIT của một máy ảo Java đơn giản không hỗ trợ các đối tượng (và mảng) sẽ là khá dễ dàng nhưng các đối tượng trong Java làm cho máy ảo rất phức tạp.
Đối tượng được lưu trữ đơn giản dưới dạng con trỏ tới đối tượng trên ngăn xếp hoặc trong các biến cục bộ. Thông thường các trình biên dịch JIT sẽ được thực hiện như thế này: Đối với mỗi lớp, một phần của bộ nhớ tồn tại chứa thông tin về lớp (ví dụ: các phương thức nào tồn tại và tại đó địa chỉ mã lắp ráp của phương thức nằm ở vị trí vv). Một đối tượng là một phần của bộ nhớ chứa tất cả các biến mẫu và một con trỏ tới bộ nhớ chứa thông tin về lớp đó.
"Instanceof" và "checkcast" có thể được triển khai bằng cách xem con trỏ tới bộ nhớ chứa thông tin về lớp. Thông tin này có thể chứa danh sách tất cả các lớp cha và các giao diện được triển khai.
Vấn đề chính của đối tượng là quản lý bộ nhớ trong Java: Không giống như C++, có một "mới" nhưng không "xóa". Bạn phải kiểm tra tần suất một đối tượng được sử dụng. Nếu một đối tượng không còn được sử dụng, nó phải được xóa khỏi bộ nhớ và hàm hủy phải được gọi. Các vấn đề ở đây là các biến cục bộ (cùng một biến cục bộ có thể chứa một đối tượng hoặc một số) và khối try/catch (khối "catch" phải quan tâm đến các biến cục bộ và ngăn xếp (!) Chứa các đối tượng trước đó khôi phục con trỏ ngăn xếp).
Điều này phải làm gì với C++? –
Vâng máy ảo và do đó việc biên dịch thực tế và các cuộc gọi của các phương thức được tạo ra được thực hiện trong C++, có thể không phải là thẻ phù hợp nhất nhưng cũng quan trọng. – maxdev
Không có mã nào được đăng là C++. Bạn đang hỏi làm thế nào để thực hiện Java bytecode trong assembly. –