2020-12-08 16:54:41 -05:00
|
|
|
#ifndef UJIT_CORE_H
|
|
|
|
#define UJIT_CORE_H 1
|
|
|
|
|
|
|
|
#include "stddef.h"
|
|
|
|
#include "ujit_asm.h"
|
|
|
|
|
|
|
|
// Register uJIT receives the CFP and EC into
|
|
|
|
#define REG_CFP RDI
|
|
|
|
#define REG_EC RSI
|
|
|
|
|
|
|
|
// Register uJIT loads the SP into
|
|
|
|
#define REG_SP RDX
|
|
|
|
|
|
|
|
// Scratch registers used by uJIT
|
|
|
|
#define REG0 RAX
|
|
|
|
#define REG1 RCX
|
|
|
|
#define REG0_32 EAX
|
|
|
|
#define REG1_32 ECX
|
|
|
|
|
2021-01-20 12:44:24 -05:00
|
|
|
// Maximum number of temp value types we keep track of
|
|
|
|
#define MAX_TEMP_TYPES 8
|
|
|
|
|
2021-01-22 12:22:34 -05:00
|
|
|
/**
|
|
|
|
Code generation context
|
|
|
|
Contains information we can use to optimize code
|
|
|
|
*/
|
2020-12-18 13:49:53 -05:00
|
|
|
typedef struct CtxStruct
|
2020-12-08 16:54:41 -05:00
|
|
|
{
|
2021-01-20 12:44:24 -05:00
|
|
|
// Temporary variable types we keep track of
|
|
|
|
// Values are `ruby_value_type`
|
|
|
|
// T_NONE==0 is the unknown type
|
|
|
|
uint8_t temp_types[MAX_TEMP_TYPES];
|
|
|
|
|
2021-02-09 16:24:06 -05:00
|
|
|
// Number of values currently on the temporary stack
|
2021-01-26 16:51:44 -05:00
|
|
|
uint16_t stack_size;
|
2020-12-10 00:06:10 -05:00
|
|
|
|
2021-02-09 16:24:06 -05:00
|
|
|
// Offset of the JIT SP relative to the interpreter SP
|
|
|
|
int16_t sp_offset;
|
|
|
|
|
2020-12-08 16:54:41 -05:00
|
|
|
// Whether we know self is a heap object
|
2021-01-26 16:51:44 -05:00
|
|
|
bool self_is_object : 1;
|
2020-12-08 16:54:41 -05:00
|
|
|
|
|
|
|
} ctx_t;
|
|
|
|
|
2020-12-16 17:07:18 -05:00
|
|
|
// Tuple of (iseq, idx) used to idenfity basic blocks
|
|
|
|
typedef struct BlockId
|
|
|
|
{
|
|
|
|
// Instruction sequence
|
|
|
|
const rb_iseq_t *iseq;
|
|
|
|
|
2021-01-18 17:03:04 -05:00
|
|
|
// Index in the iseq where the block starts
|
|
|
|
uint32_t idx;
|
2020-12-16 17:07:18 -05:00
|
|
|
|
|
|
|
} blockid_t;
|
|
|
|
|
2021-01-08 15:18:03 -05:00
|
|
|
// Null block id constant
|
|
|
|
static const blockid_t BLOCKID_NULL = { 0, 0 };
|
|
|
|
|
2020-12-16 17:07:18 -05:00
|
|
|
/// Branch code shape enumeration
|
|
|
|
enum uint8_t
|
|
|
|
{
|
2020-12-16 21:45:51 -05:00
|
|
|
SHAPE_NEXT0, // Target 0 is next
|
|
|
|
SHAPE_NEXT1, // Target 1 is next
|
|
|
|
SHAPE_DEFAULT // Neither target is next
|
2020-12-16 17:07:18 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
// Branch code generation function signature
|
|
|
|
typedef void (*branchgen_fn)(codeblock_t* cb, uint8_t* target0, uint8_t* target1, uint8_t shape);
|
|
|
|
|
2021-01-22 12:22:34 -05:00
|
|
|
/**
|
|
|
|
Store info about an outgoing branch in a code segment
|
|
|
|
Note: care must be taken to minimize the size of branch_t objects
|
|
|
|
*/
|
2020-12-16 17:07:18 -05:00
|
|
|
typedef struct BranchEntry
|
|
|
|
{
|
|
|
|
// Positions where the generated code starts and ends
|
|
|
|
uint32_t start_pos;
|
|
|
|
uint32_t end_pos;
|
|
|
|
|
2021-01-08 15:18:03 -05:00
|
|
|
// Context right after the branch instruction
|
|
|
|
ctx_t src_ctx;
|
|
|
|
|
|
|
|
// Branch target blocks and their contexts
|
2020-12-16 17:07:18 -05:00
|
|
|
blockid_t targets[2];
|
2021-01-08 15:18:03 -05:00
|
|
|
ctx_t target_ctxs[2];
|
2020-12-16 17:07:18 -05:00
|
|
|
|
2020-12-16 21:45:51 -05:00
|
|
|
// Jump target addresses
|
|
|
|
uint8_t* dst_addrs[2];
|
|
|
|
|
2020-12-16 17:07:18 -05:00
|
|
|
// Branch code generation function
|
|
|
|
branchgen_fn gen_fn;
|
|
|
|
|
2020-12-16 21:45:51 -05:00
|
|
|
// Shape of the branch
|
|
|
|
uint8_t shape;
|
|
|
|
|
2020-12-16 17:07:18 -05:00
|
|
|
} branch_t;
|
2020-12-14 15:57:55 -05:00
|
|
|
|
2021-02-19 15:03:12 -05:00
|
|
|
|
|
|
|
typedef rb_darray(uint32_t) offset_array_t;
|
|
|
|
|
2021-01-22 12:22:34 -05:00
|
|
|
/**
|
|
|
|
Basic block version
|
|
|
|
Represents a portion of an iseq compiled with a given context
|
|
|
|
Note: care must be taken to minimize the size of block_t objects
|
|
|
|
*/
|
2021-02-12 17:12:18 -05:00
|
|
|
typedef struct ujit_block_version
|
2021-01-13 15:18:35 -05:00
|
|
|
{
|
2021-01-14 13:33:19 -05:00
|
|
|
// Bytecode sequence (iseq, idx) this is a version of
|
2021-01-13 15:18:35 -05:00
|
|
|
blockid_t blockid;
|
|
|
|
|
2021-01-18 17:03:04 -05:00
|
|
|
// Index one past the last instruction in the iseq
|
2021-01-14 19:36:07 -05:00
|
|
|
uint32_t end_idx;
|
|
|
|
|
2021-01-13 15:18:35 -05:00
|
|
|
// Context at the start of the block
|
|
|
|
ctx_t ctx;
|
|
|
|
|
|
|
|
// Positions where the generated code starts and ends
|
|
|
|
uint32_t start_pos;
|
|
|
|
uint32_t end_pos;
|
|
|
|
|
|
|
|
// List of incoming branches indices
|
2021-02-12 17:12:18 -05:00
|
|
|
uint32_t *incoming;
|
2021-01-13 15:18:35 -05:00
|
|
|
uint32_t num_incoming;
|
|
|
|
|
2021-01-22 13:29:09 -05:00
|
|
|
// Next block version for this blockid (singly-linked list)
|
2021-02-12 17:12:18 -05:00
|
|
|
struct ujit_block_version *next;
|
2021-01-22 13:29:09 -05:00
|
|
|
|
2021-02-19 15:03:12 -05:00
|
|
|
// Offsets for GC managed objects in the mainline code block
|
|
|
|
offset_array_t gc_object_offsets;
|
2021-02-12 17:12:18 -05:00
|
|
|
|
|
|
|
// GC managed objects that this block depend on
|
|
|
|
struct {
|
|
|
|
VALUE cc;
|
|
|
|
VALUE cme;
|
|
|
|
VALUE iseq;
|
|
|
|
} dependencies;
|
2021-01-14 13:33:19 -05:00
|
|
|
} block_t;
|
2021-01-13 15:18:35 -05:00
|
|
|
|
2020-12-10 16:59:13 -05:00
|
|
|
// Context object methods
|
2020-12-08 16:54:41 -05:00
|
|
|
x86opnd_t ctx_sp_opnd(ctx_t* ctx, int32_t offset_bytes);
|
2021-01-20 16:58:09 -05:00
|
|
|
x86opnd_t ctx_stack_push(ctx_t* ctx, int type);
|
2020-12-08 16:54:41 -05:00
|
|
|
x86opnd_t ctx_stack_pop(ctx_t* ctx, size_t n);
|
|
|
|
x86opnd_t ctx_stack_opnd(ctx_t* ctx, int32_t idx);
|
2021-01-20 16:58:09 -05:00
|
|
|
int ctx_get_top_type(ctx_t* ctx);
|
2021-01-22 14:57:44 -05:00
|
|
|
int ctx_diff(const ctx_t* src, const ctx_t* dst);
|
2020-12-08 16:54:41 -05:00
|
|
|
|
2021-01-14 13:33:19 -05:00
|
|
|
block_t* find_block_version(blockid_t blockid, const ctx_t* ctx);
|
|
|
|
block_t* gen_block_version(blockid_t blockid, const ctx_t* ctx);
|
2021-01-13 14:14:16 -05:00
|
|
|
uint8_t* gen_entry_point(const rb_iseq_t *iseq, uint32_t insn_idx);
|
2021-02-12 17:12:18 -05:00
|
|
|
void ujit_free_block(block_t *block);
|
2021-02-18 11:54:37 -05:00
|
|
|
void ujit_branches_update_references(void);
|
2021-01-08 15:18:03 -05:00
|
|
|
|
|
|
|
void gen_branch(
|
|
|
|
const ctx_t* src_ctx,
|
|
|
|
blockid_t target0,
|
|
|
|
const ctx_t* ctx0,
|
|
|
|
blockid_t target1,
|
|
|
|
const ctx_t* ctx1,
|
|
|
|
branchgen_fn gen_fn
|
|
|
|
);
|
2020-12-16 17:07:18 -05:00
|
|
|
|
2021-01-19 11:11:11 -05:00
|
|
|
void gen_direct_jump(
|
|
|
|
const ctx_t* ctx,
|
|
|
|
blockid_t target0
|
|
|
|
);
|
|
|
|
|
2021-01-29 12:07:18 -05:00
|
|
|
void invalidate_block_version(block_t* block);
|
2021-01-12 17:03:54 -05:00
|
|
|
|
2020-12-10 16:59:13 -05:00
|
|
|
void ujit_init_core(void);
|
|
|
|
|
2020-12-08 16:54:41 -05:00
|
|
|
#endif // #ifndef UJIT_CORE_H
|