Skip to content

Commit

Permalink
pythonGH-116017: Put JIT code and data on the same page (pythonGH-116845
Browse files Browse the repository at this point in the history
)
  • Loading branch information
brandtbucher authored and adorilson committed Mar 25, 2024
1 parent a493183 commit 62ef665
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 34 deletions.
52 changes: 23 additions & 29 deletions Python/jit.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,26 +112,6 @@ mark_executable(unsigned char *memory, size_t size)
return 0;
}

static int
mark_readable(unsigned char *memory, size_t size)
{
if (size == 0) {
return 0;
}
assert(size % get_page_size() == 0);
#ifdef MS_WINDOWS
DWORD old;
int failed = !VirtualProtect(memory, size, PAGE_READONLY, &old);
#else
int failed = mprotect(memory, size, PROT_READ);
#endif
if (failed) {
jit_error("unable to protect readable memory");
return -1;
}
return 0;
}

// JIT compiler stuff: /////////////////////////////////////////////////////////

// Warning! AArch64 requires you to get your hands dirty. These are your gloves:
Expand Down Expand Up @@ -409,12 +389,14 @@ _PyJIT_Compile(_PyExecutorObject *executor, const _PyUOpInstruction *trace, size
code_size += group->code.body_size;
data_size += group->data.body_size;
}
// Round up to the nearest page (code and data need separate pages):
code_size += stencil_groups[_FATAL_ERROR].code.body_size;
data_size += stencil_groups[_FATAL_ERROR].data.body_size;
// Round up to the nearest page:
size_t page_size = get_page_size();
assert((page_size & (page_size - 1)) == 0);
code_size += page_size - (code_size & (page_size - 1));
data_size += page_size - (data_size & (page_size - 1));
unsigned char *memory = jit_alloc(code_size + data_size);
size_t padding = page_size - ((code_size + data_size) & (page_size - 1));
size_t total_size = code_size + data_size + padding;
unsigned char *memory = jit_alloc(total_size);
if (memory == NULL) {
return -1;
}
Expand Down Expand Up @@ -444,14 +426,26 @@ _PyJIT_Compile(_PyExecutorObject *executor, const _PyUOpInstruction *trace, size
code += group->code.body_size;
data += group->data.body_size;
}
if (mark_executable(memory, code_size) ||
mark_readable(memory + code_size, data_size))
{
jit_free(memory, code_size + data_size);
// Protect against accidental buffer overrun into data:
const StencilGroup *group = &stencil_groups[_FATAL_ERROR];
uint64_t patches[] = GET_PATCHES();
patches[HoleValue_CODE] = (uint64_t)code;
patches[HoleValue_CONTINUE] = (uint64_t)code;
patches[HoleValue_DATA] = (uint64_t)data;
patches[HoleValue_EXECUTOR] = (uint64_t)executor;
patches[HoleValue_TOP] = (uint64_t)code;
patches[HoleValue_ZERO] = 0;
emit(group, patches);
code += group->code.body_size;
data += group->data.body_size;
assert(code == memory + code_size);
assert(data == memory + code_size + data_size);
if (mark_executable(memory, total_size)) {
jit_free(memory, total_size);
return -1;
}
executor->jit_code = memory;
executor->jit_size = code_size + data_size;
executor->jit_size = total_size;
return 0;
}

Expand Down
7 changes: 3 additions & 4 deletions Tools/jit/_stencils.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ def emit_aarch64_trampoline(self, hole: Hole) -> None:
):
self.holes.append(hole.replace(offset=base + 4 * i, kind=kind))

def remove_jump(self) -> None:
def remove_jump(self, *, alignment: int = 1) -> None:
"""Remove a zero-length continuation jump, if it exists."""
hole = max(self.holes, key=lambda hole: hole.offset)
match hole:
Expand Down Expand Up @@ -170,7 +170,7 @@ def remove_jump(self) -> None:
offset -= 2
case _:
return
if self.body[offset:] == jump:
if self.body[offset:] == jump and offset % alignment == 0:
self.body = self.body[:offset]
self.holes.remove(hole)

Expand Down Expand Up @@ -199,9 +199,8 @@ def process_relocations(self, *, alignment: int = 1) -> None:
):
self.code.pad(alignment)
self.code.emit_aarch64_trampoline(hole)
self.code.pad(alignment)
self.code.holes.remove(hole)
self.code.remove_jump()
self.code.remove_jump(alignment=alignment)
self.code.pad(alignment)
self.data.pad(8)
for stencil in [self.code, self.data]:
Expand Down
2 changes: 1 addition & 1 deletion Tools/jit/_targets.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ async def _parse(self, path: pathlib.Path) -> _stencils.StencilGroup:
if group.data.body:
line = f"0: {str(bytes(group.data.body)).removeprefix('b')}"
group.data.disassembly.append(line)
group.process_relocations()
group.process_relocations(alignment=self.alignment)
return group

def _handle_section(self, section: _S, group: _stencils.StencilGroup) -> None:
Expand Down

0 comments on commit 62ef665

Please sign in to comment.