Skip to content

Commit

Permalink
Feat: Merge Brandt's Copy and Patch compiler (python#52)
Browse files Browse the repository at this point in the history
Co-authored-by: Ken Jin <[email protected]>
Co-authored-by: Brandt Bucher <[email protected]>
  • Loading branch information
3 people authored Jul 11, 2023
1 parent 7210772 commit a6533c1
Show file tree
Hide file tree
Showing 32 changed files with 1,503 additions and 128 deletions.
121 changes: 121 additions & 0 deletions .github/workflows/jit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
name: JIT
on: push
jobs:
jit:
name: ${{ matrix.target }} (${{ matrix.debug && 'Debug' || 'Release' }}, LLVM ${{ matrix.llvm }})
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
target:
# - i686-pc-windows-msvc/msvc
- x86_64-pc-windows-msvc/msvc
# - x86_64-apple-darwin/clang
# - x86_64-unknown-linux-gnu/gcc
# - aarch64-apple-darwin/clang
# - aarch64-unknown-linux-gnu/gcc
# - aarch64-unknown-linux-gnu/clang
# - powerpc64le-unknown-linux-gnu/gcc
# - x86_64-unknown-linux-gnu/clang
debug:
- true
# - false
llvm:
#- 14
#- 15
- 16
include:
# - target: i686-pc-windows-msvc/msvc
# architecture: i686
# runner: windows-latest
# compiler: msvc
# tier: 1
# windows_platform: Win32
- target: x86_64-pc-windows-msvc/msvc
architecture: x86_64
runner: windows-latest
compiler: msvc
tier: 1
windows_platform: x64
# - target: x86_64-apple-darwin/clang
# architecture: x86_64
# runner: macos-latest
# compiler: clang
# tier: 1
# - target: x86_64-unknown-linux-gnu/gcc
# architecture: x86_64
# runner: ubuntu-latest
# compiler: gcc
# tier: 1
# - target: aarch64-apple-darwin/clang
# architecture: aarch64
# runner: macos-latest
# compiler: clang
# tier: 2
# - target: aarch64-unknown-linux-gnu/gcc
# architecture: aarch64
# runner: ubuntu-latest
# compiler: gcc
# tier: 2
# - target: aarch64-unknown-linux-gnu/clang
# architecture: aarch64
# runner: ubuntu-latest
# compiler: clang
# tier: 2
# - target: powerpc64le-unknown-linux-gnu/gcc
# architecture: ppc64le
# runner: ubuntu-latest
# compiler: gcc
# tier: 2
# - target: x86_64-unknown-linux-gnu/clang
# architecture: x86_64
# runner: ubuntu-latest
# compiler: clang
# tier: 2
env:
CC: ${{ matrix.compiler }}
PYTHON_LLVM_VERSION: ${{ matrix.llvm }}
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.10'
# Only support Window x64 ~ Jules
# - name: macOS
# if: runner.os == 'macOS'
# run: |
# brew install llvm@${{ matrix.llvm }}
# export SDKROOT="$(xcrun --show-sdk-path)"
# ./configure ${{ matrix.debug && '--with-pydebug' || '--enable-optimizations --with-lto' }}
# make
# ./python.exe -m test -j0 -wW
# - name: Native Linux
# if: runner.os == 'Linux' && matrix.architecture == 'x86_64'
# run: |
# sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ matrix.llvm }}
# ${{ matrix.llvm == 14 && 'sudo apt install libclang-rt-14-dev' || '' }}
# export PATH="$(llvm-config-${{ matrix.llvm }} --bindir):$PATH"
# ./configure ${{ matrix.debug && '--with-pydebug' || '--enable-optimizations --with-lto' }}
# make
# ./python -m test -j0 -wW
# - name: Emulated Linux
# if: runner.os == 'Linux' && matrix.architecture != 'x86_64'
# uses: uraimo/run-on-arch-action@v2
# with:
# arch: ${{ matrix.architecture }}
# distro: ubuntu_latest
# run: |
# sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ matrix.llvm }}
# ${{ matrix.llvm == 14 && 'sudo apt install libclang-rt-14-dev' || '' }}
# export PATH="$(llvm-config-${{ matrix.llvm }} --bindir):$PATH"
# ./configure ${{ matrix.debug && '--with-pydebug' || '--enable-optimizations --with-lto' }}
# make
# ./python -m test -j0 -wW
- name: Windows
if: runner.os == 'Windows'
run: |
choco install llvm --allow-downgrade --version ${{ matrix.llvm }}
./PCbuild/build ${{ matrix.debug && '-d' || '--pgo' }} -p ${{ matrix.windows_platform }}
# ./PCbuild/rt${{ matrix.debug && ' -d' || '' }} -p ${{ matrix.windows_platform }} -q -j0 -wW
- name: Tests
run: .\python.bat tier2_test.py
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ Tools/msi/obj
Tools/ssl/amd64
Tools/ssl/win32
Tools/freeze/test/outdir
Python/jit_stencils.h

# The frozen modules are always generated by the build so we don't
# keep them in the repo. Also see Tools/build/freeze_modules.py.
Expand Down
4 changes: 2 additions & 2 deletions Include/internal/pycore_abstract.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ _PyIndex_Check(PyObject *obj)
return (tp_as_number != NULL && tp_as_number->nb_index != NULL);
}

PyObject *_PyNumber_PowerNoMod(PyObject *lhs, PyObject *rhs);
PyObject *_PyNumber_InPlacePowerNoMod(PyObject *lhs, PyObject *rhs);
PyAPI_FUNC(PyObject *)_PyNumber_PowerNoMod(PyObject *lhs, PyObject *rhs);
PyAPI_FUNC(PyObject *)_PyNumber_InPlacePowerNoMod(PyObject *lhs, PyObject *rhs);

#ifdef __cplusplus
}
Expand Down
20 changes: 17 additions & 3 deletions Include/internal/pycore_ceval.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ struct _ceval_runtime_state;

#include "pycore_interp.h" // PyInterpreterState.eval_frame
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "pycore_frame.h"


extern void _Py_FinishPendingCalls(PyThreadState *tstate);
Expand Down Expand Up @@ -124,9 +125,18 @@ PyAPI_FUNC(int) _Py_CheckRecursiveCall(
PyThreadState *tstate,
const char *where);

int _Py_CheckRecursiveCallPy(
PyAPI_FUNC(int) _Py_CheckRecursiveCallPy(
PyThreadState *tstate);

static inline int _Py_EnterRecursivePy(PyThreadState *tstate) {
return (tstate->py_recursion_remaining-- <= 0) &&
_Py_CheckRecursiveCallPy(tstate);
}

static inline void _Py_LeaveRecursiveCallPy(PyThreadState *tstate) {
tstate->py_recursion_remaining++;
}

static inline int _Py_EnterRecursiveCallTstate(PyThreadState *tstate,
const char *where) {
return (_Py_MakeRecCheck(tstate) && _Py_CheckRecursiveCall(tstate, where));
Expand All @@ -148,10 +158,14 @@ static inline void _Py_LeaveRecursiveCall(void) {

extern struct _PyInterpreterFrame* _PyEval_GetFrame(void);

extern PyObject* _Py_MakeCoro(PyFunctionObject *func);
PyAPI_FUNC(PyObject *)_Py_MakeCoro(PyFunctionObject *func);

PyAPI_FUNC(int) _Py_HandlePending(PyThreadState *tstate);

extern int _Py_HandlePending(PyThreadState *tstate);
PyAPI_FUNC(void) _PyEvalFrameClearAndPop(PyThreadState *tstate, _PyInterpreterFrame *frame);
PyAPI_FUNC(_PyInterpreterFrame *)_PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func, PyObject *locals, PyObject* const* args, size_t argcount, PyObject *kwnames);

PyAPI_FUNC(PyObject *)trace_call_function(PyThreadState *tstate, PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwnames);


#ifdef __cplusplus
Expand Down
22 changes: 11 additions & 11 deletions Include/internal/pycore_code.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,26 +238,26 @@ extern int _PyLineTable_PreviousAddressRange(PyCodeAddressRange *range);

/* Specialization functions */

extern void _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr,
PyAPI_FUNC(void) _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr,
PyObject *name);
extern void _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr,
PyAPI_FUNC(void) _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr,
PyObject *name);
extern void _Py_Specialize_LoadGlobal(PyObject *globals, PyObject *builtins,
PyAPI_FUNC(void) _Py_Specialize_LoadGlobal(PyObject *globals, PyObject *builtins,
_Py_CODEUNIT *instr, PyObject *name);
extern void _Py_Specialize_BinarySubscr(PyObject *sub, PyObject *container,
PyAPI_FUNC(void) _Py_Specialize_BinarySubscr(PyObject *sub, PyObject *container,
_Py_CODEUNIT *instr);
extern void _Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub,
PyAPI_FUNC(void) _Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub,
_Py_CODEUNIT *instr);
extern void _Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr,
PyAPI_FUNC(void) _Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr,
int nargs, PyObject *kwnames);
extern void _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
PyAPI_FUNC(void) _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
int oparg, PyObject **locals);
extern void _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs,
PyAPI_FUNC(void) _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs,
_Py_CODEUNIT *instr, int oparg);
extern void _Py_Specialize_UnpackSequence(PyObject *seq, _Py_CODEUNIT *instr,
PyAPI_FUNC(void) _Py_Specialize_UnpackSequence(PyObject *seq, _Py_CODEUNIT *instr,
int oparg);
extern void _Py_Specialize_ForIter(PyObject *iter, _Py_CODEUNIT *instr, int oparg, char is_bb);
extern void _Py_Specialize_Send(PyObject *receiver, _Py_CODEUNIT *instr);
PyAPI_FUNC(void) _Py_Specialize_ForIter(PyObject *iter, _Py_CODEUNIT *instr, int oparg, char is_bb);
PyAPI_FUNC(void) _Py_Specialize_Send(PyObject *receiver, _Py_CODEUNIT *instr);

/* Finalizer function for static codeobjects used in deepfreeze.py */
extern void _PyStaticCode_Fini(PyCodeObject *co);
Expand Down
4 changes: 2 additions & 2 deletions Include/internal/pycore_dict.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ extern Py_ssize_t _PyDictKeys_StringLookup(PyDictKeysObject* dictkeys, PyObject
extern PyObject *_PyDict_LoadGlobal(PyDictObject *, PyDictObject *, PyObject *);

/* Consumes references to key and value */
extern int _PyDict_SetItem_Take2(PyDictObject *op, PyObject *key, PyObject *value);
PyAPI_FUNC(int) _PyDict_SetItem_Take2(PyDictObject *op, PyObject *key, PyObject *value);
extern int _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr, PyObject *name, PyObject *value);

extern PyObject *_PyDict_Pop_KnownHash(PyObject *, PyObject *, Py_hash_t, PyObject *);
Expand Down Expand Up @@ -176,7 +176,7 @@ _PyDict_NotifyEvent(PyInterpreterState *interp,
}

extern PyObject *_PyObject_MakeDictFromInstanceAttributes(PyObject *obj, PyDictValues *values);
extern PyObject *_PyDict_FromItems(
PyAPI_FUNC(PyObject *)_PyDict_FromItems(
PyObject *const *keys, Py_ssize_t keys_offset,
PyObject *const *values, Py_ssize_t values_offset,
Py_ssize_t length);
Expand Down
2 changes: 1 addition & 1 deletion Include/internal/pycore_floatobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ struct _Py_float_state {
#endif
};

void _PyFloat_ExactDealloc(PyObject *op);
PyAPI_FUNC(void) _PyFloat_ExactDealloc(PyObject *op);


PyAPI_FUNC(void) _PyFloat_DebugMallocStats(FILE* out);
Expand Down
4 changes: 2 additions & 2 deletions Include/internal/pycore_frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ _PyFrame_NumSlotsForCodeObject(PyCodeObject *code)
return res;
}

void _PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *dest);
PyAPI_FUNC(void) _PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *dest);

/* Consumes reference to func and locals.
Does not initialize frame->previous, which happens
Expand Down Expand Up @@ -265,7 +265,7 @@ _PyThreadState_HasStackSpace(PyThreadState *tstate, int size)
extern _PyInterpreterFrame *
_PyThreadState_PushFrame(PyThreadState *tstate, size_t size);

void _PyThreadState_PopFrame(PyThreadState *tstate, _PyInterpreterFrame *frame);
PyAPI_FUNC(void) _PyThreadState_PopFrame(PyThreadState *tstate, _PyInterpreterFrame *frame);

/* Pushes a frame without checking for space.
* Must be guarded by _PyThreadState_HasStackSpace()
Expand Down
2 changes: 1 addition & 1 deletion Include/internal/pycore_genobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ extern "C" {
#endif

extern PyObject *_PyGen_yf(PyGenObject *);
extern PyObject *_PyCoro_GetAwaitableIter(PyObject *o);
PyAPI_FUNC(PyObject *)_PyCoro_GetAwaitableIter(PyObject *o);
extern PyObject *_PyAsyncGenValueWrapperNew(PyThreadState *state, PyObject *);

/* runtime lifecycle */
Expand Down
4 changes: 2 additions & 2 deletions Include/internal/pycore_intrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@
typedef PyObject *(*instrinsic_func1)(PyThreadState* tstate, PyObject *value);
typedef PyObject *(*instrinsic_func2)(PyThreadState* tstate, PyObject *value1, PyObject *value2);

extern const instrinsic_func1 _PyIntrinsics_UnaryFunctions[];
extern const instrinsic_func2 _PyIntrinsics_BinaryFunctions[];
PyAPI_DATA(const instrinsic_func1) _PyIntrinsics_UnaryFunctions[];
PyAPI_DATA(const instrinsic_func2) _PyIntrinsics_BinaryFunctions[];

10 changes: 10 additions & 0 deletions Include/internal/pycore_jit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
typedef enum {
_JUSTIN_RETURN_DEOPT = -1,
_JUSTIN_RETURN_OK = 0,
_JUSTIN_RETURN_GOTO_ERROR = 1,
} _PyJITReturnCode;

typedef _PyJITReturnCode (*_PyJITFunction)(PyThreadState *tstate, _PyInterpreterFrame *frame, PyObject **stack_pointer, _Py_CODEUNIT *next_instr);

PyAPI_FUNC(_PyJITFunction)_PyJIT_CompileTrace(int size, _Py_CODEUNIT **trace);
PyAPI_FUNC(void)_PyJIT_Free(_PyJITFunction trace);
4 changes: 2 additions & 2 deletions Include/internal/pycore_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ struct _Py_list_state {

#define _PyList_ITEMS(op) _Py_RVALUE(_PyList_CAST(op)->ob_item)

extern int
PyAPI_FUNC(int)
_PyList_AppendTakeRefListResize(PyListObject *self, PyObject *newitem);

static inline int
Expand Down Expand Up @@ -75,7 +75,7 @@ typedef struct {
PyListObject *it_seq; /* Set to NULL when iterator is exhausted */
} _PyListIterObject;

extern PyObject *_PyList_FromArraySteal(PyObject *const *src, Py_ssize_t n);
PyAPI_FUNC(PyObject *)_PyList_FromArraySteal(PyObject *const *src, Py_ssize_t n);

#ifdef __cplusplus
}
Expand Down
6 changes: 3 additions & 3 deletions Include/internal/pycore_long.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ static inline PyObject* _PyLong_FromUnsignedChar(unsigned char i)
return Py_NewRef((PyObject *)&_PyLong_SMALL_INTS[_PY_NSMALLNEGINTS+i]);
}

PyObject *_PyLong_Add(PyLongObject *left, PyLongObject *right);
PyObject *_PyLong_Multiply(PyLongObject *left, PyLongObject *right);
PyObject *_PyLong_Subtract(PyLongObject *left, PyLongObject *right);
PyAPI_FUNC(PyObject *)_PyLong_Add(PyLongObject *left, PyLongObject *right);
PyAPI_FUNC(PyObject *)_PyLong_Multiply(PyLongObject *left, PyLongObject *right);
PyAPI_FUNC(PyObject *)_PyLong_Subtract(PyLongObject *left, PyLongObject *right);

/* Used by Python/mystrtoul.c, _PyBytes_FromHex(),
_PyBytes_DecodeEscape(), etc. */
Expand Down
2 changes: 1 addition & 1 deletion Include/internal/pycore_sliceobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ extern "C" {

extern void _PySlice_Fini(PyInterpreterState *);

extern PyObject *
PyAPI_FUNC(PyObject *)
_PyBuildSlice_ConsumeRefs(PyObject *start, PyObject *stop);

#ifdef __cplusplus
Expand Down
2 changes: 1 addition & 1 deletion Include/internal/pycore_tuple.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ struct _Py_tuple_state {
#define _PyTuple_ITEMS(op) _Py_RVALUE(_PyTuple_CAST(op)->ob_item)

extern PyObject *_PyTuple_FromArray(PyObject *const *, Py_ssize_t);
extern PyObject *_PyTuple_FromArraySteal(PyObject *const *, Py_ssize_t);
PyAPI_FUNC(PyObject *)_PyTuple_FromArraySteal(PyObject *const *, Py_ssize_t);


typedef struct {
Expand Down
2 changes: 1 addition & 1 deletion Include/internal/pycore_unicodeobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ extern "C" {
#include "pycore_fileutils.h" // _Py_error_handler
#include "pycore_ucnhash.h" // _PyUnicode_Name_CAPI

void _PyUnicode_ExactDealloc(PyObject *op);
PyAPI_FUNC(void) _PyUnicode_ExactDealloc(PyObject *op);

/* runtime lifecycle */

Expand Down
14 changes: 13 additions & 1 deletion Makefile.pre.in
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,7 @@ PYTHON_OBJS= \
Python/importdl.o \
Python/initconfig.o \
Python/intrinsics.o \
Python/jit.o \
Python/marshal.o \
Python/modsupport.o \
Python/mysnprintf.o \
Expand Down Expand Up @@ -1260,7 +1261,7 @@ regen-limited-abi: all
regen-all: regen-cases regen-opcode regen-opcode-targets regen-typeslots \
regen-token regen-ast regen-keyword regen-sre regen-frozen clinic \
regen-pegen-metaparser regen-pegen regen-test-frozenmain \
regen-test-levenshtein regen-global-objects
regen-test-levenshtein regen-global-objects regen-jit-stencils
@echo
@echo "Note: make regen-stdlib-module-names and make regen-configure should be run manually"

Expand Down Expand Up @@ -1695,6 +1696,7 @@ PYTHON_HEADERS= \
$(srcdir)/Include/internal/pycore_interp.h \
$(srcdir)/Include/internal/pycore_interpreteridobject.h \
$(srcdir)/Include/internal/pycore_intrinsics.h \
$(srcdir)/Include/internal/pycore_jit.h \
$(srcdir)/Include/internal/pycore_list.h \
$(srcdir)/Include/internal/pycore_long.h \
$(srcdir)/Include/internal/pycore_moduleobject.h \
Expand Down Expand Up @@ -2423,6 +2425,16 @@ config.status: $(srcdir)/configure
Python/asm_trampoline.o: $(srcdir)/Python/asm_trampoline.S
$(CC) -c $(PY_CORE_CFLAGS) -o $@ $<

Python/jit.o: $(srcdir)/Python/jit_stencils.h

Python/jit_stencils.h: regen-jit-stencils

.PHONY: regen-jit-stencils
regen-jit-stencils: regen-cases
$(PYTHON_FOR_REGEN) $(srcdir)/Tools/justin/build.py \
$(srcdir)/Python/generated_cases.c.h $(srcdir)/Python/jit_stencils.h


# Some make's put the object file in the current directory
.c.o:
$(CC) -c $(PY_CORE_CFLAGS) -o $@ $<
Expand Down
Loading

0 comments on commit a6533c1

Please sign in to comment.