From 6b6fbe791fb2a8ba20e806a36e86c0c9e2d663ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Pag=C3=A8s?= Date: Fri, 11 Jan 2019 18:18:17 -0500 Subject: [PATCH 1/7] Beginning massive changes in function stubs --- jit/compiler.py | 46 ++++++++++++++++++++++++++++++++++------- jit/ffi_definitions.py | 21 +++++++++++++++++-- jit/stub_handler.py | 47 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 104 insertions(+), 10 deletions(-) diff --git a/jit/compiler.py b/jit/compiler.py index 9c239b5..b9ff156 100644 --- a/jit/compiler.py +++ b/jit/compiler.py @@ -260,9 +260,9 @@ def compile_instructions(self, mfunction, block, index=0): # Offset of the first instruction compiled in the block return_offset = 0 - # print("Compiling the block " + str(id(block)) + " in function " + str(mfunction)) - # for ins in block.instructions: - # print("\t" + str(ins)) + print("Compiling the block " + str(id(block)) + " in function " + str(mfunction)) + for ins in block.instructions: + print("\t" + str(ins)) # If we are compiling the first block of the function, compile the prolog if block == mfunction.start_basic_block and index == 0: @@ -1032,12 +1032,18 @@ def compile_instructions(self, mfunction, block, index=0): # TODO : temporary, the return address will be after the call to the stub address = stub_handler.lib.get_address(stub_handler.ffi.from_buffer(self.global_allocator.code_section), self.global_allocator.code_offset + 13) - stub_address = self.stub_handler.compile_function_stub(mfunction, nbargs, address) + stub_function = self.stub_handler.compile_function_stub(mfunction, nbargs, address) - allocator.encode(asm.MOV(asm.r10, stub_address)) - allocator.encode(asm.CALL(asm.r10)) + self.compile_make_function(block, i, stub_function) - context.decrease_stack_size() + # Clean the stack of the two TOS + # allocator.encode(asm.ADD(asm.registers.rsp, 16)) + # context.decrease_stack_size() + # context.decrease_stack_size() + + # Push the address of the stub on the stack + allocator.encode(asm.MOV(asm.r10, stub_function.first_address)) + allocator.encode(asm.CALL(asm.r10)) elif isinstance(instruction, model.BUILD_SLICE): self.nyi() @@ -1176,6 +1182,32 @@ def compile_load_class(self, allocator, block, i, instruction): compare_operators = ('<', '<=', '==', '!=', '>', '>=', 'in', 'not in', 'is', 'is not', 'exception match', 'BAD') + # Compile the MAKE_FUNCTION instruction at given index in the block + # block : currently compiled basic block + # index : index on this instruction in the block + # stub_function : StubFunction instance of this stub + def compile_make_function(self, block, index, stub_function): + # This function try to analyze the IR + # In the normal case (no closure or default arguments) a Make_function has the following structure on the stack: + # | name of function | + # | code of function | + # + # The MAKE_FUNCTION is supposed to be after two LOAD_CONSTS with the code and the name of the function + if block.instructions[index].argument == 0 and index >= 2: + tos = block.instructions[index-1] + tos1 = block.instructions[index-2] + + if isinstance(tos, model.LOAD_CONST) and isinstance(tos1, model.LOAD_CONST): + function_name = block.function.consts[tos.argument] + function_code = block.function.consts[tos1.argument] + + stub_function.function_name = function_name + stub_function.code = function_code + return + + # We should always be in the previous case for now + self.nyi() + # Functions used to compile a comparison then a jump after (a if) # mfunction : Current compiled function # instruction : Current python Bytecode instruction diff --git a/jit/ffi_definitions.py b/jit/ffi_definitions.py index 838b0d0..39d2111 100644 --- a/jit/ffi_definitions.py +++ b/jit/ffi_definitions.py @@ -34,6 +34,9 @@ // Callback to trigger the compilation of a function extern "Python+C" void python_callback_function_stub(uint64_t, uint64_t, uint64_t, uint64_t); + + // Callback to trigger the compilation of a function with some information in the stub + extern "Python+C" void python_callback_function_stub_simplified(uint64_t); // Callback for type tests extern "Python+C" void python_callback_type_stub(uint64_t, int, int); @@ -81,6 +84,8 @@ static void python_callback_bb_stub(uint64_t rsp); static void python_callback_function_stub(uint64_t, uint64_t, uint64_t, uint64_t); + + static void python_callback_function_stub_simplified(uint64_t); static void python_callback_type_stub(uint64_t, int, int); @@ -107,9 +112,21 @@ { python_callback_bb_stub(rsp[-2]); } - + // Handle the compilation of a function's stub + // Case where the Stub is already filled with some information void function_stub(uint64_t* rsp) + { + printf("ON est en C dans function_stub\\n"); + + uint64_t return_address = rsp[0]; + + // Callback to python to trigger the compilation of the function + python_callback_function_stub_simplified(return_address); + } + + // Handle the compilation of a function's stub + /*void function_stub_old(uint64_t* rsp) { uint64_t* code_address = (uint64_t*)rsp[-2]; @@ -128,7 +145,7 @@ // Callback to python to trigger the compilation of the function python_callback_function_stub(name_id, code_id, return_address, rsp[3]); - } + }*/ // Handle compilation of a type-test stub void type_test_stub(uint64_t* rsp) diff --git a/jit/stub_handler.py b/jit/stub_handler.py index 3af3888..e1e1477 100644 --- a/jit/stub_handler.py +++ b/jit/stub_handler.py @@ -173,6 +173,7 @@ def compile_function_stub(self, mfunction, nbargs, address_after): nbargs_bytes = encode_bytes(nbargs) stub_function = StubFunction() + stub_function.first_address = address self.stub_dictionary[address_after] = stub_function self.data_addresses[address_after] = jitcompiler_instance.global_allocator.stub_offset @@ -186,7 +187,7 @@ def compile_function_stub(self, mfunction, nbargs, address_after): for i in range(5): mfunction.allocator.encode_stub(asm.NOP()) - return address + return stub_function # Compile a jump to an error # error_code The code of the error sent to C @@ -298,6 +299,8 @@ def python_callback_function_stub(name_id, code_id, return_address, canary_value name = jitcompiler_instance.consts[name_id] code = jitcompiler_instance.consts[code_id] + #TODO: find a way to get this name and code from elsewhere + # we could put them into the stub function = jitcompiler_instance.interpreter.generate_function(code, name, jitcompiler_instance.interpreter.mainmodule, False) # We may need to generate a class @@ -319,6 +322,39 @@ def python_callback_function_stub(name_id, code_id, return_address, canary_value stub.clean(return_address, function.allocator.code_address, canary_value) + # This function is called when a stub is executed, need to compile a function + @ffi.def_extern() + def python_callback_function_stub_simplified(return_address): + + # Get the stub and its information + stub = stubhandler_instance.stub_dictionary[return_address] + stub.data_address = stubhandler_instance.data_addresses[return_address] + + # Generate the Function object in the model + name = stub.function_name + code = stub.code + + function = jitcompiler_instance.interpreter.generate_function(code, name, + jitcompiler_instance.interpreter.mainmodule, + False) + + # TODO: handle the case where we are compiling a class + # We may need to generate a class + # if canary_value in stubhandler_instance.class_stub_addresses: + # function.is_class = True + # function.mclass = objects.JITClass(function, name) + # + # # Add this class-function to the global collection + # jitcompiler_instance.class_functions.append(function) + + # Trigger the compilation of the given function + jitcompiler_instance.compile_function(function) + + if jitcompiler_instance.interpreter.args.asm: + jitcompiler_instance.global_allocator.disassemble_asm() + + stub.clean(return_address, function.allocator.code_address) + @ffi.def_extern() def python_callback_type_stub(return_address, id_variable, type_value): stub = stubhandler_instance.stub_dictionary[return_address] @@ -622,6 +658,15 @@ class StubFunction(Stub): def __init__(self): super().__init__() + # The address of the first encoded instruction in stub section for this stub + self.first_address = None + + # The name of the function + self.function_name = None + + # The CodeObject of this function + self.code = None + # Write instructions to restore the context before returning to asm # return_address : where to jump after this stub # function_address : address of the newly compiled function, to put on TOS after returning From 9f597202e786134d80a35e6508928b7ebf0acc96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Pag=C3=A8s?= Date: Sat, 12 Jan 2019 11:39:02 -0500 Subject: [PATCH 2/7] SAVE --- jit/compiler.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/jit/compiler.py b/jit/compiler.py index b9ff156..bf27343 100644 --- a/jit/compiler.py +++ b/jit/compiler.py @@ -273,6 +273,9 @@ def compile_instructions(self, mfunction, block, index=0): # Store its name self.class_names.append(mfunction.name) + if mfunction.name == "main": + allocator.encode(asm.INT(3)) + for i in range(index, len(block.instructions)): # If its the first instruction of the block, save its offset if i == 0: @@ -1036,14 +1039,16 @@ def compile_instructions(self, mfunction, block, index=0): self.compile_make_function(block, i, stub_function) + allocator.encode(asm.INT(3)) + allocator.encode(asm.INT(3)) # Clean the stack of the two TOS - # allocator.encode(asm.ADD(asm.registers.rsp, 16)) - # context.decrease_stack_size() - # context.decrease_stack_size() + allocator.encode(asm.ADD(asm.registers.rsp, 16)) + context.decrease_stack_size() + context.decrease_stack_size() # Push the address of the stub on the stack allocator.encode(asm.MOV(asm.r10, stub_function.first_address)) - allocator.encode(asm.CALL(asm.r10)) + allocator.encode(asm.PUSH(asm.r10)) elif isinstance(instruction, model.BUILD_SLICE): self.nyi() From 38fc485fd1faa099197ceb65a78f35046c71a4df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Pag=C3=A8s?= Date: Sat, 12 Jan 2019 11:43:55 -0500 Subject: [PATCH 3/7] Typo --- jit/stub_handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jit/stub_handler.py b/jit/stub_handler.py index 3af3888..7aa4e98 100644 --- a/jit/stub_handler.py +++ b/jit/stub_handler.py @@ -168,7 +168,7 @@ def compile_function_stub(self, mfunction, nbargs, address_after): mfunction.allocator.encode_stub(asm.MOV(asm.r10, function_address)) mfunction.allocator.encode_stub(asm.CALL(asm.r10)) - # Now put additional informations for the stub + # Now put additional information for the stub # Force min 8 bits encoding for this value nbargs_bytes = encode_bytes(nbargs) From 50fd8c40267f8aff891e9c342b22a12e3367f7cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Pag=C3=A8s?= Date: Mon, 14 Jan 2019 09:50:10 -0500 Subject: [PATCH 4/7] Save --- jit/compiler.py | 14 ++++++++++---- jit/ffi_definitions.py | 5 ++--- jit/stub_handler.py | 10 ++++++++-- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/jit/compiler.py b/jit/compiler.py index bf27343..6516722 100644 --- a/jit/compiler.py +++ b/jit/compiler.py @@ -793,6 +793,7 @@ def compile_instructions(self, mfunction, block, index=0): context.push_value(name, objects.Types.Unknown) + print(name in stub_handler.primitive_addresses) if name == "__name__": self.compile_load_special(mfunction, name) elif name in self.class_names: @@ -1032,10 +1033,7 @@ def compile_instructions(self, mfunction, block, index=0): # default arguments pass - # TODO : temporary, the return address will be after the call to the stub - address = stub_handler.lib.get_address(stub_handler.ffi.from_buffer(self.global_allocator.code_section), self.global_allocator.code_offset + 13) - - stub_function = self.stub_handler.compile_function_stub(mfunction, nbargs, address) + stub_function = self.stub_handler.compile_function_stub(mfunction, nbargs) self.compile_make_function(block, i, stub_function) @@ -1208,6 +1206,14 @@ def compile_make_function(self, block, index, stub_function): stub_function.function_name = function_name stub_function.code = function_code + + # Special case for primitive functions and addresses + if "standard_library.py" in block.function.filename: + print("Compiling standard function") + short_name = function_name.replace("twopy_", "") + stub_handler.primitive_addresses[short_name] = stub_function.first_address + + return # We should always be in the previous case for now diff --git a/jit/ffi_definitions.py b/jit/ffi_definitions.py index 39d2111..1d87ab8 100644 --- a/jit/ffi_definitions.py +++ b/jit/ffi_definitions.py @@ -118,8 +118,7 @@ void function_stub(uint64_t* rsp) { printf("ON est en C dans function_stub\\n"); - - uint64_t return_address = rsp[0]; + uint64_t return_address = rsp[-2]; // Callback to python to trigger the compilation of the function python_callback_function_stub_simplified(return_address); @@ -171,7 +170,7 @@ void print_stack(uint64_t* rsp) { printf("Print the stack\\n"); - for(int i=-1; i!=7; i++) + for(int i=-2; i!=7; i++) printf("\\t 0x%lx stack[%d] = 0x%lx\\n", (long int)&rsp[i], i, rsp[i]); } diff --git a/jit/stub_handler.py b/jit/stub_handler.py index f84cb83..08ccb05 100644 --- a/jit/stub_handler.py +++ b/jit/stub_handler.py @@ -143,8 +143,7 @@ def compile_stub(self, mfunction, stub): # Compile a stub to a function # mfunction: The simple_interpreter.Function # nbargs : number of arguments in the registers, used by C function later - # address_after : where to jump after the stub - def compile_function_stub(self, mfunction, nbargs, address_after): + def compile_function_stub(self, mfunction, nbargs): # Now encode the stub stub_label = asm.Label("Stub_label_" + str(mfunction.name)) @@ -174,6 +173,10 @@ def compile_function_stub(self, mfunction, nbargs, address_after): stub_function = StubFunction() stub_function.first_address = address + + address_after = lib.get_address(ffi.from_buffer(jitcompiler_instance.global_allocator.code_section), + jitcompiler_instance.global_allocator.stub_offset) + self.stub_dictionary[address_after] = stub_function self.data_addresses[address_after] = jitcompiler_instance.global_allocator.stub_offset @@ -326,6 +329,8 @@ def python_callback_function_stub(name_id, code_id, return_address, canary_value @ffi.def_extern() def python_callback_function_stub_simplified(return_address): + print("Stub dictionary ") + print(stubhandler_instance.stub_dictionary) # Get the stub and its information stub = stubhandler_instance.stub_dictionary[return_address] stub.data_address = stubhandler_instance.data_addresses[return_address] @@ -675,6 +680,7 @@ def clean(self, return_address, function_address, canary_value=None): instructions = [] # restore rsp + instructions.append(asm.INT(3).encode()) instructions.append(asm.POP(asm.registers.rsp).encode()) if canary_value in stubhandler_instance.class_stub_addresses: From 899e28ac3a13a5a96cb6d691296ad94cb4ac5cca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Pag=C3=A8s?= Date: Mon, 14 Jan 2019 18:05:40 -0500 Subject: [PATCH 5/7] WIP --- jit/compiler.py | 14 +++----------- jit/ffi_definitions.py | 12 +++++++----- jit/stub_handler.py | 26 +++++++++++--------------- 3 files changed, 21 insertions(+), 31 deletions(-) diff --git a/jit/compiler.py b/jit/compiler.py index 6516722..3fc5b77 100644 --- a/jit/compiler.py +++ b/jit/compiler.py @@ -260,9 +260,9 @@ def compile_instructions(self, mfunction, block, index=0): # Offset of the first instruction compiled in the block return_offset = 0 - print("Compiling the block " + str(id(block)) + " in function " + str(mfunction)) - for ins in block.instructions: - print("\t" + str(ins)) + # print("Compiling the block " + str(id(block)) + " in function " + str(mfunction)) + # for ins in block.instructions: + # print("\t" + str(ins)) # If we are compiling the first block of the function, compile the prolog if block == mfunction.start_basic_block and index == 0: @@ -273,9 +273,6 @@ def compile_instructions(self, mfunction, block, index=0): # Store its name self.class_names.append(mfunction.name) - if mfunction.name == "main": - allocator.encode(asm.INT(3)) - for i in range(index, len(block.instructions)): # If its the first instruction of the block, save its offset if i == 0: @@ -793,7 +790,6 @@ def compile_instructions(self, mfunction, block, index=0): context.push_value(name, objects.Types.Unknown) - print(name in stub_handler.primitive_addresses) if name == "__name__": self.compile_load_special(mfunction, name) elif name in self.class_names: @@ -1037,8 +1033,6 @@ def compile_instructions(self, mfunction, block, index=0): self.compile_make_function(block, i, stub_function) - allocator.encode(asm.INT(3)) - allocator.encode(asm.INT(3)) # Clean the stack of the two TOS allocator.encode(asm.ADD(asm.registers.rsp, 16)) context.decrease_stack_size() @@ -1209,11 +1203,9 @@ def compile_make_function(self, block, index, stub_function): # Special case for primitive functions and addresses if "standard_library.py" in block.function.filename: - print("Compiling standard function") short_name = function_name.replace("twopy_", "") stub_handler.primitive_addresses[short_name] = stub_function.first_address - return # We should always be in the previous case for now diff --git a/jit/ffi_definitions.py b/jit/ffi_definitions.py index 1d87ab8..06a1696 100644 --- a/jit/ffi_definitions.py +++ b/jit/ffi_definitions.py @@ -36,7 +36,7 @@ extern "Python+C" void python_callback_function_stub(uint64_t, uint64_t, uint64_t, uint64_t); // Callback to trigger the compilation of a function with some information in the stub - extern "Python+C" void python_callback_function_stub_simplified(uint64_t); + extern "Python+C" void python_callback_function_stub_simplified(uint64_t, uint64_t); // Callback for type tests extern "Python+C" void python_callback_type_stub(uint64_t, int, int); @@ -85,7 +85,7 @@ static void python_callback_function_stub(uint64_t, uint64_t, uint64_t, uint64_t); - static void python_callback_function_stub_simplified(uint64_t); + static void python_callback_function_stub_simplified(uint64_t, uint64_t); static void python_callback_type_stub(uint64_t, int, int); @@ -117,11 +117,13 @@ // Case where the Stub is already filled with some information void function_stub(uint64_t* rsp) { - printf("ON est en C dans function_stub\\n"); uint64_t return_address = rsp[-2]; + + // Where to jump after the call to this stub + uint64_t address_after = rsp[0]; // Callback to python to trigger the compilation of the function - python_callback_function_stub_simplified(return_address); + python_callback_function_stub_simplified(return_address, address_after); } // Handle the compilation of a function's stub @@ -161,7 +163,7 @@ python_callback_type_stub(return_address_aligned, id_variable, type_value); } - + void class_stub(uint64_t* rsp) { python_callback_class_stub(rsp[-1], rsp[0]); diff --git a/jit/stub_handler.py b/jit/stub_handler.py index 08ccb05..30487d7 100644 --- a/jit/stub_handler.py +++ b/jit/stub_handler.py @@ -161,8 +161,8 @@ def compile_function_stub(self, mfunction, nbargs): # Align the stack on 16 bits mfunction.allocator.encode_stub(asm.MOV(asm.rax, asm.registers.rsp)) - mfunction.allocator.encode_stub(asm.AND(asm.registers.rsp, -16)) - mfunction.allocator.encode_stub(asm.PUSH(asm.registers.rsp)) + mfunction.allocator.encode_stub(asm.AND(asm.registers.rax, -16)) + mfunction.allocator.encode_stub(asm.PUSH(asm.registers.rax)) mfunction.allocator.encode_stub(asm.MOV(asm.r10, function_address)) mfunction.allocator.encode_stub(asm.CALL(asm.r10)) @@ -327,10 +327,7 @@ def python_callback_function_stub(name_id, code_id, return_address, canary_value # This function is called when a stub is executed, need to compile a function @ffi.def_extern() - def python_callback_function_stub_simplified(return_address): - - print("Stub dictionary ") - print(stubhandler_instance.stub_dictionary) + def python_callback_function_stub_simplified(return_address, address_after): # Get the stub and its information stub = stubhandler_instance.stub_dictionary[return_address] stub.data_address = stubhandler_instance.data_addresses[return_address] @@ -358,7 +355,7 @@ def python_callback_function_stub_simplified(return_address): if jitcompiler_instance.interpreter.args.asm: jitcompiler_instance.global_allocator.disassemble_asm() - stub.clean(return_address, function.allocator.code_address) + stub.clean(address_after, function.allocator.code_address) @ffi.def_extern() def python_callback_type_stub(return_address, id_variable, type_value): @@ -680,22 +677,21 @@ def clean(self, return_address, function_address, canary_value=None): instructions = [] # restore rsp - instructions.append(asm.INT(3).encode()) instructions.append(asm.POP(asm.registers.rsp).encode()) if canary_value in stubhandler_instance.class_stub_addresses: instructions.append(asm.ADD(asm.registers.rsp, 32).encode()) else: - # Discard the three top values on the stack - instructions.append(asm.ADD(asm.registers.rsp, 24).encode()) + # Discard the return value on the stack + instructions.append(asm.ADD(asm.registers.rsp, 8).encode()) - # Now push the function address + # Now call the newly compiled function instructions.append(asm.MOV(asm.rax, function_address).encode()) - instructions.append(asm.PUSH(asm.rax).encode()) + instructions.append(asm.CALL(asm.rax).encode()) - # Finally, jump to the correct destination - instructions.append(asm.MOV(asm.rax, return_address).encode()) - instructions.append(asm.JMP(asm.rax).encode()) + # After the call, jump to the code section with the return_address + instructions.append(asm.MOV(asm.r10, return_address).encode()) + instructions.append(asm.JMP(asm.r10).encode()) offset = self.data_address for i in instructions: From e41fc4e331ec2cbb93247edbd42cc03e79bcf26f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Pag=C3=A8s?= Date: Tue, 29 Jan 2019 15:23:38 -0500 Subject: [PATCH 6/7] Fixing a bug in StubFunction cleaning before returning to asm code --- jit/compiler.py | 18 +++++++++++++++--- jit/stub_handler.py | 5 +---- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/jit/compiler.py b/jit/compiler.py index 3fc5b77..8492862 100644 --- a/jit/compiler.py +++ b/jit/compiler.py @@ -1035,8 +1035,10 @@ def compile_instructions(self, mfunction, block, index=0): # Clean the stack of the two TOS allocator.encode(asm.ADD(asm.registers.rsp, 16)) - context.decrease_stack_size() - context.decrease_stack_size() + context.pop_value() + context.pop_value() + # context.decrease_stack_size() + # context.decrease_stack_size() # Push the address of the stub on the stack allocator.encode(asm.MOV(asm.r10, stub_function.first_address)) @@ -1575,8 +1577,13 @@ def __call__(self, *args): def compile_prolog(self): offset_before = self.jitcompiler.global_allocator.code_offset - # Save rbp + # Save rbp and other registers self.encode(asm.PUSH(asm.rbp)) + self.encode(asm.PUSH(asm.rbx)) + self.encode(asm.PUSH(asm.r12)) + self.encode(asm.PUSH(asm.r13)) + self.encode(asm.PUSH(asm.r14)) + self.encode(asm.PUSH(asm.r15)) self.encode(asm.MOV(asm.rbp, asm.registers.rsp)) # Call the function just after this prolog @@ -1586,6 +1593,11 @@ def compile_prolog(self): # Restore the stack instructions.append(asm.MOV(asm.registers.rsp, asm.rbp)) + instructions.append(asm.POP(asm.r15)) + instructions.append(asm.POP(asm.r14)) + instructions.append(asm.POP(asm.r13)) + instructions.append(asm.POP(asm.r12)) + instructions.append(asm.POP(asm.rbx)) instructions.append(asm.POP(asm.rbp)) instructions.append(asm.RET()) diff --git a/jit/stub_handler.py b/jit/stub_handler.py index 30487d7..93e642e 100644 --- a/jit/stub_handler.py +++ b/jit/stub_handler.py @@ -676,14 +676,11 @@ def __init__(self): def clean(self, return_address, function_address, canary_value=None): instructions = [] - # restore rsp - instructions.append(asm.POP(asm.registers.rsp).encode()) - if canary_value in stubhandler_instance.class_stub_addresses: instructions.append(asm.ADD(asm.registers.rsp, 32).encode()) else: # Discard the return value on the stack - instructions.append(asm.ADD(asm.registers.rsp, 8).encode()) + instructions.append(asm.ADD(asm.registers.rsp, 16).encode()) # Now call the newly compiled function instructions.append(asm.MOV(asm.rax, function_address).encode()) From 051569806f32f12ea98d3bdd2f801069c633557d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Pag=C3=A8s?= Date: Mon, 18 Feb 2019 17:42:54 -0500 Subject: [PATCH 7/7] WIP --- jit/compiler.py | 6 +++-- jit/stub_handler.py | 65 +++++++++++++++++++++++---------------------- 2 files changed, 37 insertions(+), 34 deletions(-) diff --git a/jit/compiler.py b/jit/compiler.py index 8492862..02a90bd 100644 --- a/jit/compiler.py +++ b/jit/compiler.py @@ -588,6 +588,8 @@ def compile_instructions(self, mfunction, block, index=0): elif isinstance(instruction, model.LOAD_BUILD_CLASS): self.stub_handler.compile_class_stub(mfunction) + context.push_value("class_stub_address") + # Get the following class name which should be a LOAD_CONST instruction const_number = block.instructions[i + 2].argument name = block.function.consts[const_number] @@ -1037,13 +1039,13 @@ def compile_instructions(self, mfunction, block, index=0): allocator.encode(asm.ADD(asm.registers.rsp, 16)) context.pop_value() context.pop_value() - # context.decrease_stack_size() - # context.decrease_stack_size() # Push the address of the stub on the stack allocator.encode(asm.MOV(asm.r10, stub_function.first_address)) allocator.encode(asm.PUSH(asm.r10)) + # context.push_value("stub_address") + elif isinstance(instruction, model.BUILD_SLICE): self.nyi() elif isinstance(instruction, model.LOAD_CLOSURE): diff --git a/jit/stub_handler.py b/jit/stub_handler.py index 93e642e..5eeb36f 100644 --- a/jit/stub_handler.py +++ b/jit/stub_handler.py @@ -220,9 +220,6 @@ def compile_class_stub(self, mfunction): c_buffer = ffi.from_buffer(jitcompiler_instance.global_allocator.code_section) address_code = lib.get_address(c_buffer, jitcompiler_instance.global_allocator.code_offset) - # Be able to find them in the collection during the later callback - self.class_stub_addresses.append(address_stub) - # Call the stub function mfunction.allocator.encode_stub(asm.MOV(asm.rdi, asm.registers.rsp)) @@ -239,6 +236,9 @@ def compile_class_stub(self, mfunction): stub.data_address = offset stub.return_address = address_code + # Be able to find them in the collection during the later callback + self.class_stub_addresses.append(address_code) + # Indicate this offset correspond to the "return address" on the stub after the call to C returned self.data_addresses[return_address] = offset self.stub_dictionary[return_address] = stub @@ -296,34 +296,34 @@ def python_callback_bb_stub(rsp): del stubhandler_instance.stub_dictionary[rsp] # This function is called when a stub is executed, need to compile a function - @ffi.def_extern() - def python_callback_function_stub(name_id, code_id, return_address, canary_value): - # Generate the Function object in the model - name = jitcompiler_instance.consts[name_id] - code = jitcompiler_instance.consts[code_id] - - #TODO: find a way to get this name and code from elsewhere - # we could put them into the stub - function = jitcompiler_instance.interpreter.generate_function(code, name, jitcompiler_instance.interpreter.mainmodule, False) - - # We may need to generate a class - if canary_value in stubhandler_instance.class_stub_addresses: - function.is_class = True - function.mclass = objects.JITClass(function, name) - - # Add this class-function to the global collection - jitcompiler_instance.class_functions.append(function) - - # Trigger the compilation of the given function - jitcompiler_instance.compile_function(function) - - if jitcompiler_instance.interpreter.args.asm: - jitcompiler_instance.global_allocator.disassemble_asm() - - stub = stubhandler_instance.stub_dictionary[return_address] - stub.data_address = stubhandler_instance.data_addresses[return_address] - - stub.clean(return_address, function.allocator.code_address, canary_value) + # @ffi.def_extern() + # def python_callback_function_stub(name_id, code_id, return_address, canary_value): + # # Generate the Function object in the model + # name = jitcompiler_instance.consts[name_id] + # code = jitcompiler_instance.consts[code_id] + # + # #TODO: find a way to get this name and code from elsewhere + # # we could put them into the stub + # function = jitcompiler_instance.interpreter.generate_function(code, name, jitcompiler_instance.interpreter.mainmodule, False) + # + # # We may need to generate a class + # if canary_value in stubhandler_instance.class_stub_addresses: + # function.is_class = True + # function.mclass = objects.JITClass(function, name) + # + # # Add this class-function to the global collection + # jitcompiler_instance.class_functions.append(function) + # + # # Trigger the compilation of the given function + # jitcompiler_instance.compile_function(function) + # + # if jitcompiler_instance.interpreter.args.asm: + # jitcompiler_instance.global_allocator.disassemble_asm() + # + # stub = stubhandler_instance.stub_dictionary[return_address] + # stub.data_address = stubhandler_instance.data_addresses[return_address] + # + # stub.clean(return_address, function.allocator.code_address, canary_value) # This function is called when a stub is executed, need to compile a function @ffi.def_extern() @@ -342,7 +342,8 @@ def python_callback_function_stub_simplified(return_address, address_after): # TODO: handle the case where we are compiling a class # We may need to generate a class - # if canary_value in stubhandler_instance.class_stub_addresses: + # if address_after in stubhandler_instance.class_stub_addresses: + # print("Compiling a class") # function.is_class = True # function.mclass = objects.JITClass(function, name) #