Source

hotpy_2 / Include / optimiser.h

Full commit
Mark Shannon 50a2689 

Mark Shannon c856dc4 


Mark Shannon 50a2689 



Mark Shannon bd241de 
Mark Shannon 50a2689 



Mark Shannon af124c6 
Mark Shannon 50a2689 















Mark Shannon 1e5afc1 


Mark Shannon 50a2689 








Mark Shannon 1e5afc1 
Mark Shannon 50a2689 

Mark Shannon 3583685 




Mark Shannon 50a2689 





Mark Shannon bd241de 
Mark Shannon 0e66552 

Mark Shannon 50a2689 





Mark Shannon c856dc4 

Mark Shannon 3583685 


Mark Shannon b2726bb 

Mark Shannon 6a7634a 

Mark Shannon 09b5a1e 
Mark Shannon 50a2689 


Mark Shannon c856dc4 
Mark Shannon 50a2689 







Mark Shannon 56b190a 

Mark Shannon 3b34c28 
Mark Shannon c6a1c20 
Mark Shannon 50a2689 

Mark Shannon c856dc4 






Mark Shannon 50a2689 













Mark Shannon c856dc4 













Mark Shannon 50a2689 



Mark Shannon c856dc4 
Mark Shannon 50a2689 
Mark Shannon 380da20 





Mark Shannon 50a2689 






Mark Shannon 380da20 
Mark Shannon 50a2689 
Mark Shannon c856dc4 
Mark Shannon 2a4c3ac 
Mark Shannon 6a1b383 
Mark Shannon 983fdf7 
Mark Shannon 50a2689 












Mark Shannon 06cd0c4 
Mark Shannon 50a2689 




Mark Shannon 8461893 


Mark Shannon 50a2689 
Mark Shannon 55d7b56 
Mark Shannon 50a2689 








Mark Shannon 0a47172 
Mark Shannon 50a2689 





Mark Shannon 0f7625b 
Mark Shannon 50a2689 
Mark Shannon 58a741c 
Mark Shannon 049acfc 

Mark Shannon 50a2689 


Mark Shannon 087c67d 

Mark Shannon 50a2689 


Mark Shannon c75c5f0 

Mark Shannon 50a2689 


Mark Shannon 6a1b383 

Mark Shannon 50a2689 
Mark Shannon 13984a2 
Mark Shannon 50a2689 





Mark Shannon beaa7e7 
Mark Shannon 56b190a 
Mark Shannon 50a2689 








Mark Shannon af124c6 
Mark Shannon 50a2689 














Mark Shannon c856dc4 
Mark Shannon 50a2689 







Mark Shannon c856dc4 
Mark Shannon 50a2689 
Mark Shannon 92bc785 
Mark Shannon 50a2689 








Mark Shannon c856dc4 
Mark Shannon 50a2689 




Mark Shannon 978cfe3 
Mark Shannon 50a2689 
Mark Shannon c856dc4 

Mark Shannon 92bc785 

Mark Shannon c856dc4 





Mark Shannon 335e43d 

Mark Shannon c856dc4 
Mark Shannon 2a4c3ac 


Mark Shannon 55d7b56 

Mark Shannon c856dc4 
/* Optimiser interface */

#ifndef _HOTPY_OPTIMSER_H
#define _HOTPY_OPTIMSER_H

#include "frameobject.h"
#include "trace_opcode.h"
#include "structmember.h"

#define HOTPY_CONTEXT_DEPTH 8

typedef struct _hotpy_instruction_pointer {
    PyCodeObject *code;
    unsigned int offset;
    unsigned int stack;
} HotPyIP;

/* Warning: this evaluates its parameter twice */
#define HotPyIP_ToAddr(ip) \
    ((unsigned char*)PyBytes_AS_STRING((ip).code->co_code) + (ip).offset)

#ifdef Py_DEBUG
int valid_ip_here(unsigned char *ip);
#endif

typedef struct _hotpy_context {
    PyObject_HEAD
    HotPyIP cf_instrs[HOTPY_CONTEXT_DEPTH]; /* 0 is the current frame, 1 its caller, etc. */
    PyObject *cf_deferred_state;
    PyObject *cf_type_info;
    PyObject *cf_constants;
#ifdef Py_DEBUG
    char *cf_name;
#endif
} HotPyContext;

/* why                  value
   WHY_RETURN           (PyObject *)return value
   WHY_EXCEPTION        NULL
   WHY_NOT              (unsigned char*) next instruction */
typedef struct _hotpy_return_value
{
    void *value;
    enum why_code why; /* Can be RETURN, EXCEPTION or NOT */
} HotPyReturnValue;

struct instruction_count {
    char *name;
    unsigned long count;
};

typedef struct _hotpy_stats {
    unsigned long recording;
    unsigned long on_trace;
    unsigned long off_trace;
    unsigned long trace_entries;
    unsigned long trace_transfers;
    unsigned long mono_to_poly_exit;
    unsigned long polymorphic_cold_exits;
    unsigned long polymorphic_overflow_exits;
    unsigned long not_bool_exits;
    unsigned long cold_exits;
    unsigned long exceptions_in_trace;
    unsigned long materialisations;
    unsigned long invalid_exits;
    unsigned long exception_exits;
    unsigned long decays;
    unsigned long trace_cache_size;
#ifdef Py_DEBUG
    struct instruction_count trace_instructions[256];
#endif
    unsigned long failed_trace_recordings;
    unsigned long tracing_frame_stack_overflows;
    unsigned long return_exits;
    unsigned long rare_exits;
    unsigned long materialisation_exits;
} HotPyStatistics;

typedef struct _hotpy_options {
    int decay_interval;
    char show_stats;
    char tracing;
    char log_trace;
    char log_specialiser;
    char log_DOC;
    char specialise;
    char DOC;
    char lltrace;
    char register_vm;
    char coalesce;
    char tailcall;
    char compact;
} HotPyOptions;

typedef struct _hotpy_thresholds {
    int cold;
    int warm;
    int hot;
} HotPyThresholds;

extern HotPyThresholds _HotPy_Thresholds;
extern HotPyStatistics _HotPy_Stats;
extern HotPyOptions _HotPy_Options;

extern void _HotPy_ShowStats(void);

typedef struct _hotpy_trace_object HotPyTraceObject;

typedef struct _hotpy_exit_object {
    PyObject_HEAD
    HotPyContext *exit_context;
    HotPyTraceObject *exit_trace;
    unsigned int execution_count;
} HotPyExitObject;

typedef struct _exit_entry {
    PyObject *value; /* Exit if var (or type(var) is eq/ne to this value */
    HotPyTraceObject *trace;
    unsigned int execution_count;
} HotPyExitEntry;

#define HOTPY_POLYMORPHIC_LIMIT 6

typedef struct _hotpy_poly_exit_object {
    PyObject_HEAD
    HotPyContext *exit_context;
    HotPyExitEntry entries[HOTPY_POLYMORPHIC_LIMIT];
} HotPyPolyExitObject;

void HotPyContext_Dump(char *buf, HotPyContext *ctx);

HotPyContext *HotPyContext_New(void);

PyObject *HotPyExitObject_New(HotPyContext *);

enum trace_status {
    TRACE_INVALID = -1,
    TRACE_NOT_READY = 0,
    TRACE_VALID
};

struct _hotpy_trace_object {
    PyObject_HEAD
    Py_ssize_t execution_count;
    PyBytesObject *trace_code;
    PyObject *trace_exits;
    PyObject *trace_constants;
    HotPyContext *trace_context;
    enum trace_status status;
    PyObject *trace_names;
    PyObject *trace_guarded_by;
    PyObject *trace_weakrefs; /* List of weak references */
    PyDictKeysObject **trace_keys;
    PyObject *poly_value;
};

void HotPyTraceObject_Init(HotPyTraceObject*, PyObject*, PyObject*, PyObject*, PyObject*);

typedef struct _optimiserobject HotPyOptimiser;

struct _optimiserobject {
    const char *opt_name;
    HotPyOptimiser *next;
    void (*push_constant)(HotPyOptimiser*, PyObject*);
    HotPyContext*(*require_type)(HotPyOptimiser*, PyTypeObject*);
    HotPyContext*(*require_lasti)(HotPyOptimiser*, int lasti);
    HotPyContext*(*require_value)(HotPyOptimiser*, PyObject*);
    HotPyContext*(*require_code)(HotPyOptimiser*, PyObject*);
    HotPyContext*(*require_boolean_or_int)(HotPyOptimiser*);
    HotPyContext*(*opcode_with_exit)(HotPyOptimiser*, int);
    HotPyContext*(*prepare_call1)(HotPyOptimiser*);
    HotPyContext*(*prepare_call2)(HotPyOptimiser*);
    HotPyContext*(*call_object)(HotPyOptimiser*);
    HotPyContext*(*call_cmethod)(HotPyOptimiser*, PyObject *, int);
    HotPyContext*(*call_cfunction)(HotPyOptimiser*, PyObject *, int);
    HotPyContext*(*call_wrapper)(HotPyOptimiser*, int, PyObject *);
    void (*clear)(HotPyOptimiser*);
    int (*start)(HotPyOptimiser*, HotPyTraceObject*, PyFrameObject*, HotPyContext*, char *reason);
    void (*finish)(HotPyOptimiser*);
    void (*fail)(HotPyOptimiser*, int, char*);
    void (*unrolling)(HotPyOptimiser*);
    void (*comment)(HotPyOptimiser*, const char*txt);
    void (*load_fast)(HotPyOptimiser*, int);
    void (*store_fast)(HotPyOptimiser*, int);
    void (*delete_fast)(HotPyOptimiser*, int);
    void (*get_globals)(HotPyOptimiser*);
    void (*load_from_globals)(HotPyOptimiser*, PyObject*);
    void (*fast_load_from_globals)(HotPyOptimiser*, PyObject*, PyObject*);
    void (*store_to_globals)(HotPyOptimiser*, PyObject*);
    void (*has_special)(HotPyOptimiser*, PyObject*);
    void (*load_register)(HotPyOptimiser*, int);
    void (*load_clear_register)(HotPyOptimiser*, int);
    void (*store_register)(HotPyOptimiser*, int);
    void (*set_lasti)(HotPyOptimiser*, int);
    void (*fast_frame)(HotPyOptimiser*, int, PyCodeObject*);
    HotPyContext*(*make_frame)(HotPyOptimiser*, PyObject *func);
    HotPyContext*(*make_frame_const)(HotPyOptimiser*, PyObject *func);
    void (*enter_frame)(HotPyOptimiser*, PyCodeObject*);
    void (*gen_enter)(HotPyOptimiser*, PyCodeObject*);
    void (*leave_frame)(HotPyOptimiser*);
    void (*leave_gen_frame)(HotPyOptimiser*);
    void (*binary_op)(HotPyOptimiser*, int, PyObject*);
    void (*binary_op_kv)(HotPyOptimiser*, int, PyObject*, PyObject*);
    void (*binary_op_vk)(HotPyOptimiser*, int, PyObject*, PyObject*);
    void (*tuple_concat)(HotPyOptimiser*);
    void (*pick)(HotPyOptimiser*, int);
    void (*bind_callable)(HotPyOptimiser*, PyTypeObject*);
    HotPyContext* (*load_member)(HotPyOptimiser*, PyMemberDescrObject *desc);
    HotPyContext* (*store_member)(HotPyOptimiser*, PyMemberDef*);
    void (*opcode)(HotPyOptimiser*, int);
    void (*opcode_with_arg)(HotPyOptimiser*, int, int);
    void (*setup_block)(HotPyOptimiser*, int, int, int);
    HotPyContext*(*from_object_dict_fast)(HotPyOptimiser*, int, PyDictKeysObject*, PyObject*);
    void (*set_in_object_dict_fast)(HotPyOptimiser*, int, PyDictKeysObject*, PyObject*);
    HotPyContext*(*current_context)(HotPyOptimiser*);
    void (*dead_locals)(HotPyOptimiser*);
    int instruction_count;
    HotPyContext *start_context;
};

#define MAXIMUM_TRACE_LENGTH 10000

HotPyOptimiser *HotPyTraceRecorderRegister_New(void);
HotPyOptimiser *HotPyTraceRecorder_New(void);

HotPyOptimiser *HotPySpecialiser_New(HotPyOptimiser *);

HotPyOptimiser *HotPyDOC_New(HotPyOptimiser *);

void HotPyDOC_RestoreThreadState(PyThreadState *, HotPyContext *);

HotPyOptimiser *HotPyTraceLogger_New(HotPyOptimiser *, FILE* out);

HotPyTraceObject *HotPyTraceManager_FindTrace(PyThreadState *, unsigned char *, int);

HotPyTraceObject *HotPyTraceManager_TraceForContext(PyThreadState *, HotPyContext *);

void HotPyTraceManager_InvalidateAllTraces(PyThreadState *);

void HotPyTrace_RecordingEval(PyThreadState *, HotPyTraceObject *, HotPyOptimiser *, PyObject *);

void HotPyTrace_Invalidate(PyObject *);

void HotPyTraceManager_CoolTraces(PyThreadState *);

/* Steals a reference to the trace */
HotPyReturnValue HotPyTrace_Execute(PyThreadState *, HotPyTraceObject *);

HotPyReturnValue
PyEval_RecordingEval(PyThreadState *, HotPyContext *, HotPyOptimiser *);

PyFrameObject *_PyEval_FastFrame(PyObject *, PyObject **, int);
PyFrameObject *_PyEval_MakeFrame(PyObject *, PyObject *, PyObject *);

void HotPy_RestoreThreadState(PyThreadState *, HotPyContext *context);

HotPyTraceObject *HotPyTraceObject_FromExit(PyThreadState *, HotPyExitObject *);

HotPyTraceObject *HotPyTraceObject_FromContextAndValue(PyThreadState *, HotPyContext *, PyObject *);

HotPyReturnValue HotPyTraceObject_RaiseAtExit(PyThreadState*, HotPyExitObject *);

HotPyOptimiser *HotPy_GetOptimiser(void);

HotPyReturnValue
_HotPy_RecordUnwinding(PyThreadState *, HotPyOptimiser *, HotPyContext *);

PyObject *_HotPy_PolyExit(HotPyExitObject *);

int PyType_GuardAttribute(PyTypeObject *, PyObject *, PyObject *);
void PyType_Unguard(PyTypeObject *, PyObject *);

void PyType_RemoveAllGuardsForTrace(PyTypeObject *, PyObject *);

unsigned char *_HotPy_NextInstruction(PyFrameObject *);

int HotPyDOC_IsSelfConsistent(void);

void HotPyTraceManager_Decay(void);

void HotPy_MaterialiseFrame(PyThreadState *, PyObject *, PyObject *, int);

#define HOTPY_TICK() do { \
    if (--tstate->trace_ticks <= 0) { \
        HotPyTraceManager_Decay(); \
    } \
} while (0)

#define HOTPY_MINIMUM_DECAY 2500
#define HOTPY_DEFAULT_DECAY 25000

int HotPyGuard_AddTraceToSet(PyObject *, PyObject *);
void HotPyGuard_InvalidateSet(PyObject *);

HotPyReturnValue _HotPy_TraceExcecuteCold(PyThreadState *, HotPyTraceObject *, char *);

#endif /* _HOTPY_OPTIMSER_H */