MJIT: Convert compact_p flag to an enum
I'm gonna add another type of unit shortly.
This commit is contained in:
parent
bfc225764e
commit
0dc5c117a5
48
mjit.c
48
mjit.c
@ -1104,6 +1104,24 @@ free_list(struct rb_mjit_unit_list *list, bool close_handle_p)
|
|||||||
list->length = 0;
|
list->length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct rb_mjit_unit*
|
||||||
|
create_unit(enum rb_mjit_unit_type type)
|
||||||
|
{
|
||||||
|
struct rb_mjit_unit *unit = ZALLOC_N(struct rb_mjit_unit, 1);
|
||||||
|
unit->id = current_unit_num++;
|
||||||
|
unit->type = type;
|
||||||
|
return unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct rb_mjit_unit*
|
||||||
|
create_iseq_unit(const rb_iseq_t *iseq)
|
||||||
|
{
|
||||||
|
struct rb_mjit_unit *unit = create_unit(MJIT_UNIT_ISEQ);
|
||||||
|
unit->iseq = (rb_iseq_t *)iseq;
|
||||||
|
ISEQ_BODY(iseq)->jit_unit = unit;
|
||||||
|
return unit;
|
||||||
|
}
|
||||||
|
|
||||||
static void mjit_wait(struct rb_mjit_unit *unit);
|
static void mjit_wait(struct rb_mjit_unit *unit);
|
||||||
|
|
||||||
// Check the unit queue and start mjit_compile if nothing is in progress.
|
// Check the unit queue and start mjit_compile if nothing is in progress.
|
||||||
@ -1130,7 +1148,7 @@ check_unit_queue(void)
|
|||||||
// Dequeue a unit
|
// Dequeue a unit
|
||||||
struct rb_mjit_unit *unit = get_from_list(&unit_queue);
|
struct rb_mjit_unit *unit = get_from_list(&unit_queue);
|
||||||
if (unit == NULL) return;
|
if (unit == NULL) return;
|
||||||
VM_ASSERT(!unit->compact_p);
|
VM_ASSERT(unit->type == MJIT_UNIT_ISEQ);
|
||||||
|
|
||||||
// Run the MJIT compiler synchronously
|
// Run the MJIT compiler synchronously
|
||||||
current_cc_ms = real_ms_time();
|
current_cc_ms = real_ms_time();
|
||||||
@ -1156,22 +1174,6 @@ check_unit_queue(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create unit for `iseq`. This function may be called from an MJIT worker.
|
|
||||||
static struct rb_mjit_unit*
|
|
||||||
create_unit(const rb_iseq_t *iseq)
|
|
||||||
{
|
|
||||||
struct rb_mjit_unit *unit = ZALLOC_N(struct rb_mjit_unit, 1);
|
|
||||||
unit->id = current_unit_num++;
|
|
||||||
if (iseq == NULL) { // Compact unit
|
|
||||||
unit->compact_p = true;
|
|
||||||
}
|
|
||||||
else { // Normal unit
|
|
||||||
unit->iseq = (rb_iseq_t *)iseq;
|
|
||||||
ISEQ_BODY(iseq)->jit_unit = unit;
|
|
||||||
}
|
|
||||||
return unit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if it should compact all JIT code and start it as needed
|
// Check if it should compact all JIT code and start it as needed
|
||||||
static void
|
static void
|
||||||
check_compaction(void)
|
check_compaction(void)
|
||||||
@ -1188,7 +1190,7 @@ check_compaction(void)
|
|||||||
if (compact_units.length < max_compact_size
|
if (compact_units.length < max_compact_size
|
||||||
&& ((!mjit_opts.wait && unit_queue.length == 0 && active_units.length > 1)
|
&& ((!mjit_opts.wait && unit_queue.length == 0 && active_units.length > 1)
|
||||||
|| (active_units.length == mjit_opts.max_cache_size && compact_units.length * throttle_threshold <= total_unloads))) { // throttle compaction by total_unloads
|
|| (active_units.length == mjit_opts.max_cache_size && compact_units.length * throttle_threshold <= total_unloads))) { // throttle compaction by total_unloads
|
||||||
struct rb_mjit_unit *unit = create_unit(NULL);
|
struct rb_mjit_unit *unit = create_unit(MJIT_UNIT_COMPACT);
|
||||||
|
|
||||||
// Run the MJIT compiler synchronously
|
// Run the MJIT compiler synchronously
|
||||||
current_cc_ms = real_ms_time();
|
current_cc_ms = real_ms_time();
|
||||||
@ -1225,7 +1227,7 @@ mjit_notify_waitpid(int exit_code)
|
|||||||
// Check the result
|
// Check the result
|
||||||
if (exit_code != 0) {
|
if (exit_code != 0) {
|
||||||
verbose(2, "Failed to generate so");
|
verbose(2, "Failed to generate so");
|
||||||
if (!current_cc_unit->compact_p) {
|
if (current_cc_unit->type == MJIT_UNIT_ISEQ) {
|
||||||
current_cc_unit->iseq->body->jit_func = (jit_func_t)MJIT_FUNC_FAILED;
|
current_cc_unit->iseq->body->jit_func = (jit_func_t)MJIT_FUNC_FAILED;
|
||||||
}
|
}
|
||||||
free_unit(current_cc_unit);
|
free_unit(current_cc_unit);
|
||||||
@ -1236,11 +1238,11 @@ mjit_notify_waitpid(int exit_code)
|
|||||||
// Load .so file
|
// Load .so file
|
||||||
char so_file[MAXPATHLEN];
|
char so_file[MAXPATHLEN];
|
||||||
sprint_uniq_filename(so_file, (int)sizeof(so_file), current_cc_unit->id, MJIT_TMP_PREFIX, DLEXT);
|
sprint_uniq_filename(so_file, (int)sizeof(so_file), current_cc_unit->id, MJIT_TMP_PREFIX, DLEXT);
|
||||||
if (current_cc_unit->compact_p) { // Compact unit
|
if (current_cc_unit->type == MJIT_UNIT_COMPACT) {
|
||||||
load_compact_funcs_from_so(current_cc_unit, c_file, so_file);
|
load_compact_funcs_from_so(current_cc_unit, c_file, so_file);
|
||||||
current_cc_unit = NULL;
|
current_cc_unit = NULL;
|
||||||
}
|
}
|
||||||
else { // Normal unit
|
else { // MJIT_UNIT_ISEQ
|
||||||
// Load the function from so
|
// Load the function from so
|
||||||
char funcname[MAXPATHLEN];
|
char funcname[MAXPATHLEN];
|
||||||
sprint_funcname(funcname, sizeof(funcname), current_cc_unit);
|
sprint_funcname(funcname, sizeof(funcname), current_cc_unit);
|
||||||
@ -1327,7 +1329,7 @@ mjit_add_iseq_to_process(const rb_iseq_t *iseq, const struct rb_mjit_compile_inf
|
|||||||
}
|
}
|
||||||
|
|
||||||
ISEQ_BODY(iseq)->jit_func = (jit_func_t)MJIT_FUNC_COMPILING;
|
ISEQ_BODY(iseq)->jit_func = (jit_func_t)MJIT_FUNC_COMPILING;
|
||||||
create_unit(iseq);
|
create_iseq_unit(iseq);
|
||||||
if (compile_info != NULL)
|
if (compile_info != NULL)
|
||||||
ISEQ_BODY(iseq)->jit_unit->compile_info = *compile_info;
|
ISEQ_BODY(iseq)->jit_unit->compile_info = *compile_info;
|
||||||
add_to_list(ISEQ_BODY(iseq)->jit_unit, &unit_queue);
|
add_to_list(ISEQ_BODY(iseq)->jit_unit, &unit_queue);
|
||||||
@ -1363,7 +1365,7 @@ mjit_wait(struct rb_mjit_unit *unit)
|
|||||||
while (current_cc_pid == initial_pid) {
|
while (current_cc_pid == initial_pid) {
|
||||||
tries++;
|
tries++;
|
||||||
if (tries / 1000 > MJIT_WAIT_TIMEOUT_SECONDS) {
|
if (tries / 1000 > MJIT_WAIT_TIMEOUT_SECONDS) {
|
||||||
if (!unit->compact_p) {
|
if (unit->type == MJIT_UNIT_ISEQ) {
|
||||||
unit->iseq->body->jit_func = (jit_func_t)MJIT_FUNC_FAILED; // C compiler was too slow. Give up.
|
unit->iseq->body->jit_func = (jit_func_t)MJIT_FUNC_FAILED; // C compiler was too slow. Give up.
|
||||||
}
|
}
|
||||||
mjit_warning("timed out to wait for JIT finish");
|
mjit_warning("timed out to wait for JIT finish");
|
||||||
|
18
mjit_c.h
18
mjit_c.h
@ -14,23 +14,35 @@
|
|||||||
#define NOT_COMPILED_STACK_SIZE -1
|
#define NOT_COMPILED_STACK_SIZE -1
|
||||||
#define ALREADY_COMPILED_P(status, pos) (status->stack_size_for_pos[pos] != NOT_COMPILED_STACK_SIZE)
|
#define ALREADY_COMPILED_P(status, pos) (status->stack_size_for_pos[pos] != NOT_COMPILED_STACK_SIZE)
|
||||||
|
|
||||||
|
// Type of rb_mjit_unit
|
||||||
|
enum rb_mjit_unit_type {
|
||||||
|
// Single-ISEQ unit for mjit_compile
|
||||||
|
MJIT_UNIT_ISEQ = 0,
|
||||||
|
// All-ISEQ unit for mjit_compact
|
||||||
|
MJIT_UNIT_COMPACT = 1,
|
||||||
|
};
|
||||||
|
|
||||||
// The unit structure that holds metadata of ISeq for MJIT.
|
// The unit structure that holds metadata of ISeq for MJIT.
|
||||||
|
// TODO: Use different structs for ISEQ and COMPACT
|
||||||
struct rb_mjit_unit {
|
struct rb_mjit_unit {
|
||||||
struct ccan_list_node unode;
|
struct ccan_list_node unode;
|
||||||
// Unique order number of unit.
|
// Unique order number of unit.
|
||||||
int id;
|
int id;
|
||||||
// Dlopen handle of the loaded object file.
|
// Dlopen handle of the loaded object file.
|
||||||
void *handle;
|
void *handle;
|
||||||
|
// Type of this unit
|
||||||
|
enum rb_mjit_unit_type type;
|
||||||
|
|
||||||
|
// ISEQ for a non-batch unit
|
||||||
rb_iseq_t *iseq;
|
rb_iseq_t *iseq;
|
||||||
// Only used by unload_units. Flag to check this unit is currently on stack or not.
|
// Only used by unload_units. Flag to check this unit is currently on stack or not.
|
||||||
bool used_code_p;
|
bool used_code_p;
|
||||||
// True if it's a unit for JIT compaction
|
|
||||||
bool compact_p;
|
|
||||||
// mjit_compile's optimization switches
|
// mjit_compile's optimization switches
|
||||||
struct rb_mjit_compile_info compile_info;
|
struct rb_mjit_compile_info compile_info;
|
||||||
// captured CC values, they should be marked with iseq.
|
// captured CC values, they should be marked with iseq.
|
||||||
const struct rb_callcache **cc_entries;
|
const struct rb_callcache **cc_entries;
|
||||||
unsigned int cc_entries_size; // ISEQ_BODY(iseq)->ci_size + ones of inlined iseqs
|
// ISEQ_BODY(iseq)->ci_size + ones of inlined iseqs
|
||||||
|
unsigned int cc_entries_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Storage to keep data which is consistent in each conditional branch.
|
// Storage to keep data which is consistent in each conditional branch.
|
||||||
|
@ -621,9 +621,9 @@ module RubyVM::MJIT
|
|||||||
unode: [self.ccan_list_node, Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_unit *)NULL)), unode)")],
|
unode: [self.ccan_list_node, Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_unit *)NULL)), unode)")],
|
||||||
id: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_unit *)NULL)), id)")],
|
id: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_unit *)NULL)), id)")],
|
||||||
handle: [CType::Pointer.new { CType::Immediate.parse("void") }, Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_unit *)NULL)), handle)")],
|
handle: [CType::Pointer.new { CType::Immediate.parse("void") }, Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_unit *)NULL)), handle)")],
|
||||||
|
type: [self.rb_mjit_unit_type, Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_unit *)NULL)), type)")],
|
||||||
iseq: [CType::Pointer.new { self.rb_iseq_t }, Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_unit *)NULL)), iseq)")],
|
iseq: [CType::Pointer.new { self.rb_iseq_t }, Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_unit *)NULL)), iseq)")],
|
||||||
used_code_p: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_unit *)NULL)), used_code_p)")],
|
used_code_p: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_unit *)NULL)), used_code_p)")],
|
||||||
compact_p: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_unit *)NULL)), compact_p)")],
|
|
||||||
compile_info: [self.rb_mjit_compile_info, Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_unit *)NULL)), compile_info)")],
|
compile_info: [self.rb_mjit_compile_info, Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_unit *)NULL)), compile_info)")],
|
||||||
cc_entries: [CType::Pointer.new { CType::Pointer.new { self.rb_callcache } }, Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_unit *)NULL)), cc_entries)")],
|
cc_entries: [CType::Pointer.new { CType::Pointer.new { self.rb_callcache } }, Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_unit *)NULL)), cc_entries)")],
|
||||||
cc_entries_size: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_unit *)NULL)), cc_entries_size)")],
|
cc_entries_size: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_unit *)NULL)), cc_entries_size)")],
|
||||||
@ -783,5 +783,9 @@ module RubyVM::MJIT
|
|||||||
CType::Stub.new(:ccan_list_node)
|
CType::Stub.new(:ccan_list_node)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def C.rb_mjit_unit_type
|
||||||
|
CType::Stub.new(:rb_mjit_unit_type)
|
||||||
|
end
|
||||||
|
|
||||||
### MJIT bindgen end ###
|
### MJIT bindgen end ###
|
||||||
end if RubyVM::MJIT.enabled? && RubyVM::MJIT.const_defined?(:C) # not defined for miniruby
|
end if RubyVM::MJIT.enabled? && RubyVM::MJIT.const_defined?(:C) # not defined for miniruby
|
||||||
|
Loading…
x
Reference in New Issue
Block a user