Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions Doc/library/importlib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -210,12 +210,6 @@ Functions
:exc:`ModuleNotFoundError` is raised when the module being reloaded lacks
a :class:`~importlib.machinery.ModuleSpec`.

.. versionchanged:: 3.15
If *module* is a lazy module that has not yet been materialized (i.e.,
loaded via :class:`importlib.util.LazyLoader` and not yet accessed),
calling :func:`reload` is a no-op and returns the module unchanged.
This prevents the reload from unintentionally triggering the lazy load.

.. warning::
This function is not thread-safe. Calling it from multiple threads can result
in unexpected behavior. It's recommended to use the :class:`threading.Lock`
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 @@ -22,7 +22,7 @@ PyGenObject *_PyGen_GetGeneratorFromFrame(_PyInterpreterFrame *frame)
}

PyAPI_FUNC(PyObject *)_PyGen_yf(PyGenObject *);
extern void _PyGen_Finalize(PyObject *self);
extern int _PyGen_ClearFrame(PyGenObject *self);

// Export for '_asyncio' shared extension
PyAPI_FUNC(int) _PyGen_SetStopIterationValue(PyObject *);
Expand Down
125 changes: 2 additions & 123 deletions Include/internal/pycore_optimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ extern "C" {
#include "pycore_uop.h" // _PyUOpInstruction
#include "pycore_uop_ids.h"
#include "pycore_stackref.h" // _PyStackRef
#include "pycore_optimizer_types.h"
#include <stdbool.h>


Expand Down Expand Up @@ -84,7 +85,7 @@ PyAPI_FUNC(void) _Py_Executors_InvalidateCold(PyInterpreterState *interp);
#define JIT_CLEANUP_THRESHOLD 1000

int _Py_uop_analyze_and_optimize(
PyFunctionObject *func,
_PyThreadStateImpl *tstate,
_PyUOpInstruction *trace, int trace_len, int curr_stackentries,
_PyBloomFilter *dependencies);

Expand Down Expand Up @@ -112,86 +113,6 @@ static inline uint16_t uop_get_error_target(const _PyUOpInstruction *inst)
return inst->error_target;
}

// Holds locals, stack, locals, stack ... co_consts (in that order)
#define MAX_ABSTRACT_INTERP_SIZE 4096

#define TY_ARENA_SIZE (UOP_MAX_TRACE_LENGTH * 5)

// Need extras for root frame and for overflow frame (see TRACE_STACK_PUSH())
#define MAX_ABSTRACT_FRAME_DEPTH (16)

// The maximum number of side exits that we can take before requiring forward
// progress (and inserting a new ENTER_EXECUTOR instruction). In practice, this
// is the "maximum amount of polymorphism" that an isolated trace tree can
// handle before rejoining the rest of the program.
#define MAX_CHAIN_DEPTH 4

/* Symbols */
/* See explanation in optimizer_symbols.c */


typedef enum _JitSymType {
JIT_SYM_UNKNOWN_TAG = 1,
JIT_SYM_NULL_TAG = 2,
JIT_SYM_NON_NULL_TAG = 3,
JIT_SYM_BOTTOM_TAG = 4,
JIT_SYM_TYPE_VERSION_TAG = 5,
JIT_SYM_KNOWN_CLASS_TAG = 6,
JIT_SYM_KNOWN_VALUE_TAG = 7,
JIT_SYM_TUPLE_TAG = 8,
JIT_SYM_TRUTHINESS_TAG = 9,
JIT_SYM_COMPACT_INT = 10,
} JitSymType;

typedef struct _jit_opt_known_class {
uint8_t tag;
uint32_t version;
PyTypeObject *type;
} JitOptKnownClass;

typedef struct _jit_opt_known_version {
uint8_t tag;
uint32_t version;
} JitOptKnownVersion;

typedef struct _jit_opt_known_value {
uint8_t tag;
PyObject *value;
} JitOptKnownValue;

#define MAX_SYMBOLIC_TUPLE_SIZE 7

typedef struct _jit_opt_tuple {
uint8_t tag;
uint8_t length;
uint16_t items[MAX_SYMBOLIC_TUPLE_SIZE];
} JitOptTuple;

typedef struct {
uint8_t tag;
bool invert;
uint16_t value;
} JitOptTruthiness;

typedef struct {
uint8_t tag;
} JitOptCompactInt;

typedef union _jit_opt_symbol {
uint8_t tag;
JitOptKnownClass cls;
JitOptKnownValue value;
JitOptKnownVersion version;
JitOptTuple tuple;
JitOptTruthiness truthiness;
JitOptCompactInt compact;
} JitOptSymbol;


// This mimics the _PyStackRef API
typedef union {
uintptr_t bits;
} JitOptRef;

#define REF_IS_BORROWED 1

Expand Down Expand Up @@ -238,48 +159,6 @@ PyJitRef_IsBorrowed(JitOptRef ref)
return (ref.bits & REF_IS_BORROWED) == REF_IS_BORROWED;
}

struct _Py_UOpsAbstractFrame {
bool globals_watched;
// The version number of the globals dicts, once checked. 0 if unchecked.
uint32_t globals_checked_version;
// Max stacklen
int stack_len;
int locals_len;
PyFunctionObject *func;
PyCodeObject *code;

JitOptRef *stack_pointer;
JitOptRef *stack;
JitOptRef *locals;
};

typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame;

typedef struct ty_arena {
int ty_curr_number;
int ty_max_number;
JitOptSymbol arena[TY_ARENA_SIZE];
} ty_arena;

typedef struct _JitOptContext {
char done;
char out_of_space;
bool contradiction;
// Has the builtins dict been watched?
bool builtins_watched;
// The current "executing" frame.
_Py_UOpsAbstractFrame *frame;
_Py_UOpsAbstractFrame frames[MAX_ABSTRACT_FRAME_DEPTH];
int curr_frame_depth;

// Arena for the symbolic types.
ty_arena t_arena;

JitOptRef *n_consumed;
JitOptRef *limit;
JitOptRef locals_and_stack[MAX_ABSTRACT_INTERP_SIZE];
} JitOptContext;

extern bool _Py_uop_sym_is_null(JitOptRef sym);
extern bool _Py_uop_sym_is_not_null(JitOptRef sym);
extern bool _Py_uop_sym_is_const(JitOptContext *ctx, JitOptRef sym);
Expand Down
137 changes: 137 additions & 0 deletions Include/internal/pycore_optimizer_types.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
#ifndef Py_INTERNAL_OPTIMIZER_TYPES_H
#define Py_INTERNAL_OPTIMIZER_TYPES_H
#ifdef __cplusplus
extern "C" {
#endif

#ifndef Py_BUILD_CORE
# error "this header requires Py_BUILD_CORE define"
#endif

#include "pycore_uop.h" // UOP_MAX_TRACE_LENGTH

// Holds locals, stack, locals, stack ... co_consts (in that order)
#define MAX_ABSTRACT_INTERP_SIZE 4096

#define TY_ARENA_SIZE (UOP_MAX_TRACE_LENGTH * 5)

// Need extras for root frame and for overflow frame (see TRACE_STACK_PUSH())
#define MAX_ABSTRACT_FRAME_DEPTH (16)

// The maximum number of side exits that we can take before requiring forward
// progress (and inserting a new ENTER_EXECUTOR instruction). In practice, this
// is the "maximum amount of polymorphism" that an isolated trace tree can
// handle before rejoining the rest of the program.
#define MAX_CHAIN_DEPTH 4

/* Symbols */
/* See explanation in optimizer_symbols.c */


typedef enum _JitSymType {
JIT_SYM_UNKNOWN_TAG = 1,
JIT_SYM_NULL_TAG = 2,
JIT_SYM_NON_NULL_TAG = 3,
JIT_SYM_BOTTOM_TAG = 4,
JIT_SYM_TYPE_VERSION_TAG = 5,
JIT_SYM_KNOWN_CLASS_TAG = 6,
JIT_SYM_KNOWN_VALUE_TAG = 7,
JIT_SYM_TUPLE_TAG = 8,
JIT_SYM_TRUTHINESS_TAG = 9,
JIT_SYM_COMPACT_INT = 10,
} JitSymType;

typedef struct _jit_opt_known_class {
uint8_t tag;
uint32_t version;
PyTypeObject *type;
} JitOptKnownClass;

typedef struct _jit_opt_known_version {
uint8_t tag;
uint32_t version;
} JitOptKnownVersion;

typedef struct _jit_opt_known_value {
uint8_t tag;
PyObject *value;
} JitOptKnownValue;

#define MAX_SYMBOLIC_TUPLE_SIZE 7

typedef struct _jit_opt_tuple {
uint8_t tag;
uint8_t length;
uint16_t items[MAX_SYMBOLIC_TUPLE_SIZE];
} JitOptTuple;

typedef struct {
uint8_t tag;
bool invert;
uint16_t value;
} JitOptTruthiness;

typedef struct {
uint8_t tag;
} JitOptCompactInt;

typedef union _jit_opt_symbol {
uint8_t tag;
JitOptKnownClass cls;
JitOptKnownValue value;
JitOptKnownVersion version;
JitOptTuple tuple;
JitOptTruthiness truthiness;
JitOptCompactInt compact;
} JitOptSymbol;

// This mimics the _PyStackRef API
typedef union {
uintptr_t bits;
} JitOptRef;

typedef struct _Py_UOpsAbstractFrame {
bool globals_watched;
// The version number of the globals dicts, once checked. 0 if unchecked.
uint32_t globals_checked_version;
// Max stacklen
int stack_len;
int locals_len;
PyFunctionObject *func;
PyCodeObject *code;

JitOptRef *stack_pointer;
JitOptRef *stack;
JitOptRef *locals;
} _Py_UOpsAbstractFrame;

typedef struct ty_arena {
int ty_curr_number;
int ty_max_number;
JitOptSymbol arena[TY_ARENA_SIZE];
} ty_arena;

typedef struct _JitOptContext {
char done;
char out_of_space;
bool contradiction;
// Has the builtins dict been watched?
bool builtins_watched;
// The current "executing" frame.
_Py_UOpsAbstractFrame *frame;
_Py_UOpsAbstractFrame frames[MAX_ABSTRACT_FRAME_DEPTH];
int curr_frame_depth;

// Arena for the symbolic types.
ty_arena t_arena;

JitOptRef *n_consumed;
JitOptRef *limit;
JitOptRef locals_and_stack[MAX_ABSTRACT_INTERP_SIZE];
} JitOptContext;


#ifdef __cplusplus
}
#endif
#endif /* !Py_INTERNAL_OPTIMIZER_TYPES_H */
4 changes: 3 additions & 1 deletion Include/internal/pycore_tstate.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ extern "C" {
#include "pycore_freelist_state.h" // struct _Py_freelists
#include "pycore_interpframe_structs.h" // _PyInterpreterFrame
#include "pycore_mimalloc.h" // struct _mimalloc_thread_state
#include "pycore_optimizer_types.h" // JitOptContext
#include "pycore_qsbr.h" // struct qsbr
#include "pycore_uop.h" // struct _PyUOpInstruction
#include "pycore_structs.h"
Expand Down Expand Up @@ -52,10 +53,11 @@ typedef struct _PyJitTracerTranslatorState {
} _PyJitTracerTranslatorState;

typedef struct _PyJitTracerState {
_PyUOpInstruction *code_buffer;
_PyJitTracerInitialState initial_state;
_PyJitTracerPreviousState prev_state;
_PyJitTracerTranslatorState translator_state;
JitOptContext opt_context;
_PyUOpInstruction code_buffer[UOP_MAX_TRACE_LENGTH];
} _PyJitTracerState;

#endif
Expand Down
5 changes: 0 additions & 5 deletions Lib/importlib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,6 @@ def reload(module):
The module must have been successfully imported before.
"""
# If a LazyModule has not yet been materialized, reload is a no-op.
if importlib_util := sys.modules.get('importlib.util'):
if lazy_module_type := getattr(importlib_util, '_LazyModule', None):
if isinstance(module, lazy_module_type):
return module
try:
name = module.__spec__.name
except AttributeError:
Expand Down
9 changes: 7 additions & 2 deletions Lib/test/test_grammar.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# Python test set -- part 1, grammar.
# This just tests whether the parser accepts them all.

from test.support import check_syntax_error, skip_wasi_stack_overflow
from test.support import import_helper
import annotationlib
import inspect
import unittest
Expand All @@ -18,6 +16,12 @@
import typing
from test.typinganndata import ann_module2
import test
from test.support import (
check_syntax_error,
import_helper,
skip_emscripten_stack_overflow,
skip_wasi_stack_overflow,
)
from test.support.numbers import (
VALID_UNDERSCORE_LITERALS,
INVALID_UNDERSCORE_LITERALS,
Expand Down Expand Up @@ -250,6 +254,7 @@ def test_eof_error(self):
self.assertIn("was never closed", str(cm.exception))

@skip_wasi_stack_overflow()
@skip_emscripten_stack_overflow()
def test_max_level(self):
# Macro defined in Parser/lexer/state.h
MAXLEVEL = 200
Expand Down
Loading
Loading