Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

gh-107557: Setup abstract interpretation#107847

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

Merged
Fidget-Spinner merged 54 commits intopython:mainfromFidget-Spinner:partition_algo
Aug 15, 2023
Merged
Show file tree
Hide file tree
Changes from1 commit
Commits
Show all changes
54 commits
Select commitHold shift + click to select a range
d20fbb8
gh-107557: Tier 2 abstract interpreter barebones
Fidget-SpinnerAug 2, 2023
2aeea51
📜🤖 Added by blurb_it.
blurb-it[bot]Aug 2, 2023
1a728ab
Copy Guido's input and output code, and fix build
Fidget-SpinnerAug 2, 2023
17fccbc
fix separator
Fidget-SpinnerAug 2, 2023
a1da69d
credit Jules
Fidget-SpinnerAug 2, 2023
b458e17
add jules to co-authors
Fidget-SpinnerAug 2, 2023
f81f888
add pycore_optimizer.h to headers in makefile
Fidget-SpinnerAug 2, 2023
0020320
fix: remove whitespace
Fidget-SpinnerAug 2, 2023
1f93072
fix make smelly
Fidget-SpinnerAug 2, 2023
dac63e3
fix: build
Fidget-SpinnerAug 2, 2023
e62e015
fix wrong symbol
Fidget-SpinnerAug 2, 2023
a7f654c
ignore static globals check for abstract interpreter
Fidget-SpinnerAug 2, 2023
f4040b8
Merge remote-tracking branch 'upstream/main' into abstract_interpreter
Fidget-SpinnerAug 4, 2023
ec58145
merge Guido's changes
Fidget-SpinnerAug 4, 2023
4292767
remove unused stuff
Fidget-SpinnerAug 4, 2023
fdcca90
Turn on the abstract interpreter
Fidget-SpinnerAug 4, 2023
5110fb9
Merge remote-tracking branch 'upstream/main' into abstract_interpreter
Fidget-SpinnerAug 5, 2023
9f443a2
Merge remote-tracking branch 'origin/abstract_interpreter' into parti…
Fidget-SpinnerAug 5, 2023
7632ed1
(leaky) data structures for constant propagation
Fidget-SpinnerAug 5, 2023
0d0c4c4
(with cycles) try to fix the type prop
Fidget-SpinnerAug 6, 2023
4c8953e
fix: cycles
Fidget-SpinnerAug 6, 2023
3bd36fa
cleanup
Fidget-SpinnerAug 6, 2023
229097f
Fix+Refactor: Handling of root nodes in special-cased type prop (#40)
JuliaPooAug 7, 2023
ca0fab7
partially partially evaluate
Fidget-SpinnerAug 8, 2023
68c684f
rename vars
Fidget-SpinnerAug 8, 2023
46c5777
fixx off by one
Fidget-SpinnerAug 8, 2023
b839ee4
partial eval working for real this time
Fidget-SpinnerAug 9, 2023
6ecf3d2
Fix: Inconsistent `AbstractInterpContext` used in `PARTITIONNODE_OVER…
JuliaPooAug 9, 2023
b6eeb25
fix test, refactor, bugfix
Fidget-SpinnerAug 9, 2023
d5cceb9
re-compute jump offsets and targets
Fidget-SpinnerAug 10, 2023
8c0d65f
Fix+Refactor: Extra EXIT_TRACE emitted (#42)
JuliaPooAug 10, 2023
95db909
fix: overallocate buffer and virtual/real stack offset calculation
Fidget-SpinnerAug 10, 2023
1e05ef8
more bugfix
Fidget-SpinnerAug 10, 2023
d7d8b52
Merge remote-tracking branch 'upstream/main' into partition_algo
Fidget-SpinnerAug 10, 2023
4d7abc7
Perf+Cleanup: Removed temporary allocation in `remove_duplicate_save_…
JuliaPooAug 11, 2023
3d76f9a
clean up code
Fidget-SpinnerAug 11, 2023
e81def2
Merge branch 'partition_algo' of https://github.com/Fidget-Spinner/cp…
Fidget-SpinnerAug 11, 2023
9a5a3f7
make static
Fidget-SpinnerAug 11, 2023
df490d0
make types static
Fidget-SpinnerAug 11, 2023
1e4fc94
make const and ignore in c analyzer
Fidget-SpinnerAug 11, 2023
6de77a7
fix c-analyzer ignored list
Fidget-SpinnerAug 11, 2023
a11fc80
more cleanup
Fidget-SpinnerAug 13, 2023
c61015b
Merge remote-tracking branch 'upstream/main' into partition_algo
Fidget-SpinnerAug 13, 2023
56c62eb
regen files
Fidget-SpinnerAug 13, 2023
3c08ebe
address review
Fidget-SpinnerAug 14, 2023
d5f16be
regen
Fidget-SpinnerAug 14, 2023
1e61c49
and env var to block tests
Fidget-SpinnerAug 14, 2023
6c24b49
regen again
Fidget-SpinnerAug 14, 2023
2be404d
fix generated files
Fidget-SpinnerAug 14, 2023
29e255d
Address review
Fidget-SpinnerAug 15, 2023
3c44117
fix up INSERT
Fidget-SpinnerAug 15, 2023
b758b47
remove experimental parts
Fidget-SpinnerAug 15, 2023
80c7f18
revert more changes
Fidget-SpinnerAug 15, 2023
6a2b204
use memmove
Fidget-SpinnerAug 15, 2023
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
PrevPrevious commit
NextNext commit
Turn on the abstract interpreter
  • Loading branch information
@Fidget-Spinner
Fidget-Spinner committedAug 4, 2023
commitfdcca9036ba949185c716a3dbfcf48c9fea8e533
2 changes: 1 addition & 1 deletionInclude/cpython/optimizer.h
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,7 +22,7 @@ typedef struct _PyExecutorObject {
typedef struct _PyOptimizerObject _PyOptimizerObject;

/* Should return > 0 if a new executor is created. O if no executor is produced and < 0 if an error occurred. */
typedef int (*optimize_func)(_PyOptimizerObject* self, PyCodeObject *code, _Py_CODEUNIT *instr, _PyExecutorObject **);
typedef int (*optimize_func)(_PyOptimizerObject* self, PyCodeObject *code, _Py_CODEUNIT *instr, _PyExecutorObject **, int curr_stackentries);

typedef struct _PyOptimizerObject {
PyObject_HEAD
Expand Down
4 changes: 3 additions & 1 deletionInclude/internal/pycore_optimizer.h
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,9 @@ extern "C" {

#include "pycore_uops.h"

int _Py_uop_analyze_and_optimize(_PyUOpInstruction *trace, int trace_len);
int _Py_uop_analyze_and_optimize(PyCodeObject *code,
_PyUOpInstruction *trace, int trace_len, int curr_stackentries);


#ifdef __cplusplus
}
Expand Down
14 changes: 9 additions & 5 deletionsPython/optimizer.c
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -104,7 +104,8 @@ error_optimize(
_PyOptimizerObject* self,
PyCodeObject *code,
_Py_CODEUNIT *instr,
_PyExecutorObject **exec)
_PyExecutorObject **exec,
int Py_UNUSED(stack_entries))
{
PyErr_Format(PyExc_SystemError, "Should never call error_optimize");
return -1;
Expand DownExpand Up@@ -165,7 +166,7 @@ _PyOptimizer_BackEdge(_PyInterpreterFrame *frame, _Py_CODEUNIT *src, _Py_CODEUNI
}
_PyOptimizerObject *opt = interp->optimizer;
_PyExecutorObject *executor = NULL;
int err = opt->optimize(opt, code, dest, &executor);
int err = opt->optimize(opt, code, dest, &executor, (int)(stack_pointer - _PyFrame_Stackbase(frame)));
if (err <= 0) {
assert(executor == NULL);
if (err < 0) {
Expand DownExpand Up@@ -255,7 +256,9 @@ counter_optimize(
_PyOptimizerObject* self,
PyCodeObject *code,
_Py_CODEUNIT *instr,
_PyExecutorObject **exec_ptr)
_PyExecutorObject **exec_ptr,
int Py_UNUSED(curr_stackentries)
)
{
_PyCounterExecutorObject *executor = (_PyCounterExecutorObject *)_PyObject_New(&CounterExecutor_Type);
if (executor == NULL) {
Expand DownExpand Up@@ -691,7 +694,8 @@ uop_optimize(
_PyOptimizerObject *self,
PyCodeObject *code,
_Py_CODEUNIT *instr,
_PyExecutorObject **exec_ptr)
_PyExecutorObject **exec_ptr,
int curr_stackentries)
{
_PyUOpInstruction trace[_Py_UOP_MAX_TRACE_LENGTH];
int trace_length = translate_bytecode_to_trace(code, instr, trace, _Py_UOP_MAX_TRACE_LENGTH);
Expand All@@ -705,7 +709,7 @@ uop_optimize(
return -1;
}
executor->base.execute = _PyUopExecute;
trace_length = _Py_uop_analyze_and_optimize(trace, trace_length);
trace_length = _Py_uop_analyze_and_optimize(code,trace, trace_length, curr_stackentries);
memcpy(executor->trace, trace, trace_length * sizeof(_PyUOpInstruction));
if (trace_length < _Py_UOP_MAX_TRACE_LENGTH) {
executor->trace[trace_length].opcode = 0; // Sentinel
Expand Down
174 changes: 173 additions & 1 deletionPython/optimizer_analysis.c
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,11 +12,183 @@
#include <stddef.h>
#include "pycore_optimizer.h"

// TYPENODE is a tagged pointer that uses the last 2 LSB as the tag
#define _Py_PARTITIONNODE_t uintptr_t

// PARTITIONNODE Tags
typedef enum _Py_TypeNodeTags {
// Node is unused
TYPE_NULL = 0,
// TYPE_ROOT_POSITIVE can point to a root struct or be a NULL
TYPE_ROOT= 1,
// TYPE_REF points to a TYPE_ROOT or a TYPE_REF
TYPE_REF = 2,
} _Py_TypeNodeTags;

typedef struct _Py_PartitionRootNode {
PyObject_HEAD
// For partial evaluation
uint8_t static_or_dyanmic;
// For types (TODO)
} _Py_PartitionRootNode;

PyTypeObject _Py_PartitionRootNode_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
.tp_name = "uops abstract interpreter's root node",
.tp_basicsize = sizeof(_Py_PartitionRootNode),
.tp_dealloc = PyObject_Del,
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION
};

static inline _Py_PARTITIONNODE_t
partitionnode_get_tag(_Py_PARTITIONNODE_t node)
{
return node & 0b11;
}

static inline _Py_PARTITIONNODE_t
partitionnode_clear_tag(_Py_PARTITIONNODE_t node)
{
return node & (~(uintptr_t)(0b11));
}

static inline _Py_PARTITIONNODE_t
partitionnode_make_root(uint8_t static_or_dynamic)
{
_Py_PartitionRootNode *root = PyObject_New(_Py_PartitionRootNode, &_Py_PartitionRootNode_Type);
if (root == NULL) {
return 0;
}
root->static_or_dyanmic = static_or_dynamic;
return (_Py_PARTITIONNODE_t)root;
}

static inline _Py_PARTITIONNODE_t
partitionnode_make_ref(_Py_PARTITIONNODE_t node)
{
return partitionnode_clear_tag(node) | TYPE_REF;
}

static inline _Py_PARTITIONNODE_t
partitionnode_null()
{
return 0;
}


// Tier 2 types meta interpreter
typedef struct _Py_UOpsAbstractInterpContext {
PyObject_HEAD
// points to one element after the abstract stack
_Py_PARTITIONNODE_t *stack_pointer;
int stack_len;
_Py_PARTITIONNODE_t *stack;
int locals_len;
_Py_PARTITIONNODE_t *locals;
} _Py_UOpsAbstractInterpContext;

static void
abstractinterp_dealloc(PyObject *o)
{
_Py_UOpsAbstractInterpContext *self = (_Py_UOpsAbstractInterpContext *)o;
PyMem_Free(self->stack);
PyMem_Free(self->locals);
// TODO traverse the nodes and decref all roots too.
Py_TYPE(self)->tp_free((PyObject *)self);
}

PyTypeObject _Py_UOpsAbstractInterpContext_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
.tp_name = "uops abstract interpreter's context",
.tp_basicsize = sizeof(_Py_UOpsAbstractInterpContext),
.tp_dealloc = abstractinterp_dealloc,
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION
};

_Py_UOpsAbstractInterpContext *
_Py_UOpsAbstractInterpContext_New(int stack_len, int locals_len, int curr_stacklen)
{
_Py_UOpsAbstractInterpContext *self = (_Py_UOpsAbstractInterpContext *)PyType_GenericAlloc(
(PyTypeObject *)&_Py_UOpsAbstractInterpContext_Type, 0);
if (self == NULL) {
return NULL;
}

// Setup
self->stack_len = stack_len;
self->locals_len = locals_len;

_Py_PARTITIONNODE_t *locals_with_stack = PyMem_New(_Py_PARTITIONNODE_t, locals_len + stack_len);
if (locals_with_stack == NULL) {
Py_DECREF(self);
return NULL;
}


for (int i = 0; i < locals_len + stack_len; i++) {
locals_with_stack[i] = partitionnode_null();
}

self->locals = locals_with_stack;
self->stack = locals_with_stack + locals_len;
self->stack_pointer = self->stack + curr_stacklen;

return self;
}

int
_Py_uop_analyze_and_optimize(
PyCodeObject *co,
_PyUOpInstruction *trace,
int trace_len
int trace_len,
int curr_stacklen
)
{
#define STACK_LEVEL() ((int)(stack_pointer - ctx->stack))
#define STACK_SIZE() (co->co_stacksize)
#define BASIC_STACKADJ(n) (stack_pointer += n)

#ifdef Py_DEBUG
#define STACK_GROW(n) do { \
assert(n >= 0); \
BASIC_STACKADJ(n); \
assert(STACK_LEVEL() <= STACK_SIZE()); \
} while (0)
#define STACK_SHRINK(n) do { \
assert(n >= 0); \
assert(STACK_LEVEL() >= n); \
BASIC_STACKADJ(-(n)); \
} while (0)
#else
#define STACK_GROW(n) BASIC_STACKADJ(n)
#define STACK_SHRINK(n) BASIC_STACKADJ(-(n))
#endif
_PyUOpInstruction *temp_writebuffer = PyMem_New(_PyUOpInstruction, trace_len);
if (temp_writebuffer == NULL) {
return trace_len;
}

_Py_UOpsAbstractInterpContext *ctx = _Py_UOpsAbstractInterpContext_New(co->co_stacksize, co->co_nlocals, curr_stacklen);
if (ctx == NULL) {
PyMem_Free(temp_writebuffer);
return trace_len;
}

int oparg;
int opcode;
_Py_PARTITIONNODE_t *stack_pointer = ctx->stack_pointer;
for (int i = 0; i < trace_len; i++) {
oparg = trace[i].oparg;
opcode = trace[i].opcode;
switch (opcode) {
#include "abstract_interp_cases.c.h"
default:
fprintf(stderr, "Unknown opcode in abstract interpreter\n");
Py_UNREACHABLE();
}
ctx->stack_pointer = stack_pointer;

}
assert(STACK_SIZE() >= 0);
return trace_len;
}
14 changes: 12 additions & 2 deletionsTools/cases_generator/generate_cases.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -61,6 +61,17 @@

INSTR_FMT_PREFIX = "INSTR_FMT_"

# @TODO generate all these after updating the DSL
SPECIALLY_HANDLED_ABSTRACT_INSTR = {
# "LOAD_FAST",
# "LOAD_FAST_CHECK",
# "LOAD_FAST_AND_CLEAR",
# "LOAD_CONST",
# "STORE_FAST",
# "STORE_FAST_MAYBE_NULL",
# "COPY",
}

arg_parser = argparse.ArgumentParser(
description="Generate the code for the interpreter switch.",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
Expand DownExpand Up@@ -628,8 +639,7 @@ def write_abstract_interpreter_instructions(
self.write_overridden_instr_place_holder(thing)
case parsing.InstDef():
instr = AbstractInstruction(self.instrs[thing.name].inst)
self.out.emit("")
if instr.is_viable_uop():
if instr.is_viable_uop() and instr.name not in SPECIALLY_HANDLED_ABSTRACT_INSTR:
self.out.emit("")
with self.out.block(f"case {thing.name}:"):
instr.write(self.out, tier=TIER_TWO)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Note that ingh-107760 I'm removingInstruction.write altogether.

Expand Down
2 changes: 1 addition & 1 deletionTools/cases_generator/stacking.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -432,5 +432,5 @@ def _write_components_for_abstract_interp(
poke.effect.cond,
poke.effect.size,
),
StackEffect("NULL"),
StackEffect("partitionnode_null()"),
)

[8]ページ先頭

©2009-2025 Movatter.jp