Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork33.7k
GH-113464: A copy-and-patch JIT compiler#113465
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes from1 commit
8f6c5fee0888de365f7a27fb79b866a5659f90bd1ea98d4fedc308baf2b18d7e2ae7bcbe8896556976b3e33b4ab3ac194650731b5e559898317ba7907e03a1e64905911c7f444981573168883029936e6ed75bd68488def28351a0cc5db79f2817bbfb9663877e14875e9259dff1d6a7af9f114c8b507357a801968a87a1f44767b60d6295d634cd3ca4956f092c79515ba80df2927ae26abedf1cb4a1fb2e47f91799b79aef1e427b33e2132b270894448edd08d53c502ab9cf87aab283492ddc4b166f0c4e1470f23be38c626633497f8c0be489a73eb3cee5298091a71c1ab13056f898dcc2720878f07fb485aa9d3b38db6838e0a69d1d33cc952c78f70a62e82d878dc80c440e55169acb3d6fa4ad4ffe087ff195e27de56641963c663b54bb6fb3afb5d934ddf21a9efd7eaec09cdf8b1d5f4e950c4bf874eda424d3c816f8824cb777aa253c4f60977d65308afb676a60e8a50ac997b66c26012b82579d2393017071dd8bed2687e45774f6dcd05c17241ce0f5137145ffac31b888d9ca46112654d3a08196c3499cc201a90446e986f86a0f7a7e995c4904e48021c98f17495bc2b5b57d39d915249e12af142c2f6490a7127a50cf89996d958bd20c7bb54b57a592f01a8a63b40614ee5bbda588342f07925f1404ae9371e2954073b641244cb7a875bf5187dfface9a9637a80466d7a00abf88a9c613e094581abc5ba1242d96de1fa6d7b01ffefced95f11772d8687809ccedcb290a86ed6a18349218e8176b8c3e2aab3af4a4ba4a2862780b6789901843ab556e7c458df49c1867b882263c522adc586d4fd794f0877bfa6533c5c44c856fbb07a8931fe1fcdc9464f903c4e67db478f01ae73ed82b53c35f3dc55796770a48089989523d0434646063fb8addbbe6b19d7cb63610e44a024aaf7606df23805750b0df80d358ef323a9d6d36c9de7026d0c412c68db1f1c9fe9faa27422932726434393342775c1b700720ad5f5c518c095e229edd01a2c74266f5a6ebd0852d17e22afbc1f55315b1d6b84187675dd0cbc6763efb62bc8344683f2636eceefbe31a23fad9844b194feb5f21d0dca530a2491701a956bde78341d0bba20fb4474d041162cadebb24d4f656e00c9c80679b1bbf6643773663ba3121ac0f2b352c6b763f527b15529c1cee73981d0fb6437bc5326e248af3984e6113a1f16648d8446bee49c33c78f4d3e207581036eb00e021File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
- Loading branch information
Uh oh!
There was an error while loading.Please reload this page.
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -23,116 +23,94 @@ | ||
| #include <sys/mman.h> | ||
| #endif | ||
| #define FITS_IN_BITS(U, B) \ | ||
| (((int64_t)(U) >= -(1LL << ((B) - 1))) && ((int64_t)(U) < (1LL << ((B) - 1)))) | ||
| staticuint64_t | ||
| get_page_size(void) | ||
| { | ||
| #ifdef MS_WINDOWS | ||
| SYSTEM_INFO si; | ||
| GetSystemInfo(&si); | ||
| return si.dwPageSize; | ||
| #else | ||
| return sysconf(_SC_PAGESIZE); | ||
| #endif | ||
| } | ||
| static void | ||
| warn(const char *message) | ||
| { | ||
| #ifdef MS_WINDOWS | ||
| int errno = GetLastError(); | ||
| #endif | ||
| PyErr_WarnFormat(PyExc_RuntimeWarning, 0, "JIT %s (%d)", message, errno); | ||
| } | ||
| static char * | ||
| alloc(uint64_tsize) | ||
| { | ||
| assert(size); | ||
| assert(size % get_page_size() == 0); | ||
| #ifdef MS_WINDOWS | ||
brandtbucher marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
| char *memory = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); | ||
| int failed = memory == NULL; | ||
| #else | ||
| char *memory = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); | ||
| int failed = memory == MAP_FAILED; | ||
| #endif | ||
| if (failed) { | ||
| warn("unable to allocate memory"); | ||
| return NULL; | ||
| } | ||
| return memory; | ||
| } | ||
| static int | ||
| mark_executable(char *memory, uint64_tsize) | ||
| { | ||
| if (size == 0) { | ||
| return 0; | ||
| } | ||
| assert(size% get_page_size() == 0); | ||
| #ifdef MS_WINDOWS | ||
| if (!FlushInstructionCache(GetCurrentProcess(), memory, size)) { | ||
| warn("unable to flush instruction cache"); | ||
| return -1; | ||
| } | ||
| DWORD old; | ||
| int failed = !VirtualProtect(memory, size, PAGE_EXECUTE, &old); | ||
| #else | ||
| __builtin___clear_cache((char *)memory, (char *)memory + size); | ||
| int failed = mprotect(memory, size, PROT_EXEC); | ||
| #endif | ||
| if (failed) { | ||
| warn("unable to protect executable memory"); | ||
| return -1; | ||
| } | ||
| return 0; | ||
| } | ||
| static int | ||
| mark_readable(char *memory, uint64_tsize) | ||
| { | ||
| 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) { | ||
| warn("unable to protect readable memory"); | ||
| return -1; | ||
| } | ||
| return 0; | ||
| } | ||
| static void | ||
| patch(char *base, const Hole *hole, uint64_t *patches) | ||
brandtbucher marked this conversation as resolved. OutdatedShow resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
| { | ||
| @@ -145,16 +123,11 @@ patch(char *base, const Hole *hole, uint64_t *patches) | ||
| return; | ||
| case HoleKind_IMAGE_REL_AMD64_REL32: | ||
| case HoleKind_IMAGE_REL_I386_REL32: | ||
| case HoleKind_X86_64_RELOC_BRANCH: | ||
| case HoleKind_X86_64_RELOC_GOT: | ||
| case HoleKind_X86_64_RELOC_GOT_LOAD: | ||
| value -= (uint64_t)location; | ||
| assert(FITS_IN_BITS(value, 32)); | ||
| *addr = (uint32_t)value; | ||
| return; | ||
| case HoleKind_ARM64_RELOC_UNSIGNED: | ||
| @@ -174,14 +147,11 @@ patch(char *base, const Hole *hole, uint64_t *patches) | ||
| return; | ||
| case HoleKind_R_AARCH64_CALL26: | ||
| case HoleKind_R_AARCH64_JUMP26: | ||
| value -= (uint64_t)location; | ||
| assert(((*addr & 0xFC000000) == 0x14000000) || | ||
| ((*addr & 0xFC000000) == 0x94000000)); | ||
| assert((value & 0x3) == 0); | ||
| assert(FITS_IN_BITS(value, 28)); | ||
| *addr = (*addr & 0xFC000000) | ((uint32_t)(value >> 2) & 0x03FFFFFF); | ||
| return; | ||
| case HoleKind_ARM64_RELOC_GOT_LOAD_PAGEOFF12: | ||
| @@ -236,101 +206,59 @@ emit(const StencilGroup *stencil_group, uint64_t patches[]) | ||
| copy_and_patch(text, &stencil_group->text, patches); | ||
| } | ||
| _PyJITFunction | ||
| _PyJIT_CompileTrace(_PyUOpExecutorObject *executor, _PyUOpInstruction *trace, int size) | ||
| { | ||
| uint64_t text_size = wrapper_stencil_group.text.body_size; | ||
| uint64_t data_size = wrapper_stencil_group.data.body_size; | ||
| for (int i = 0; i < size; i++) { | ||
| _PyUOpInstruction *instruction = &trace[i]; | ||
| const StencilGroup *stencil_group = &stencil_groups[instruction->opcode]; | ||
| text_size += stencil_group->text.body_size; | ||
| data_size += stencil_group->data.body_size; | ||
| } | ||
| uint64_t page_size = get_page_size(); | ||
| assert((page_size & (page_size - 1)) == 0); | ||
| text_size += page_size - (text_size & (page_size - 1)); | ||
| data_size += page_size - (data_size & (page_size - 1)); | ||
| char *memory = alloc(text_size + data_size); | ||
| if (memory == NULL) { | ||
| return NULL; | ||
| } | ||
| char *text = memory; | ||
| char *data = memory + text_size; | ||
| const StencilGroup *stencil_group = &wrapper_stencil_group; | ||
| uint64_t patches[] = GET_PATCHES(); | ||
| patches[HoleValue_CONTINUE] = (uint64_t)text + stencil_group->text.body_size; | ||
| patches[HoleValue_DATA] = (uint64_t)data; | ||
| patches[HoleValue_TEXT] = (uint64_t)text; | ||
| patches[HoleValue_ZERO] = 0; | ||
| emit(stencil_group, patches); | ||
| text += stencil_group->text.body_size; | ||
| data += stencil_group->data.body_size; | ||
| for (int i = 0; i < size; i++) { | ||
| _PyUOpInstruction *instruction = &trace[i]; | ||
| const StencilGroup *stencil_group = &stencil_groups[instruction->opcode]; | ||
| uint64_t patches[] = GET_PATCHES(); | ||
| patches[HoleValue_CONTINUE] = (uint64_t)text + stencil_group->text.body_size; | ||
| patches[HoleValue_CURRENT_EXECUTOR] = (uint64_t)executor; | ||
| patches[HoleValue_OPARG] = instruction->oparg; | ||
| patches[HoleValue_OPERAND] = instruction->operand; | ||
| patches[HoleValue_TARGET] = instruction->target; | ||
| patches[HoleValue_DATA] = (uint64_t)data; | ||
| patches[HoleValue_TEXT] = (uint64_t)text; | ||
| patches[HoleValue_TOP] = (uint64_t)memory + wrapper_stencil_group.text.body_size; | ||
| patches[HoleValue_ZERO] = 0; | ||
| emit(stencil_group, patches); | ||
| text += stencil_group->text.body_size; | ||
| data += stencil_group->data.body_size; | ||
| } | ||
| if (mark_executable(memory, text_size) || | ||
| mark_readable(memory + text_size, data_size)) | ||
| { | ||
| return NULL; | ||
| } | ||
| return (_PyJITFunction)memory; | ||
| } | ||
| #endif | ||
Uh oh!
There was an error while loading.Please reload this page.