зеркало из https://github.com/github/ruby.git
Родитель
daf7c48d88
Коммит
69f377a3d6
5
iseq.c
5
iseq.c
|
@ -359,10 +359,9 @@ rb_iseq_mark(const rb_iseq_t *iseq)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if USE_MJIT
|
#if USE_MJIT
|
||||||
if (body->jit_unit && body->jit_unit->cc_entries != NULL) {
|
if (body->jit_unit && mjit_iseq_cc_entries(body) != NULL) {
|
||||||
// TODO: move to mjit.c?
|
|
||||||
for (unsigned int i=0; i<body->ci_size; i++) {
|
for (unsigned int i=0; i<body->ci_size; i++) {
|
||||||
const struct rb_callcache *cc = body->jit_unit->cc_entries[i];
|
const struct rb_callcache *cc = mjit_iseq_cc_entries(body)[i];
|
||||||
if (cc != NULL) {
|
if (cc != NULL) {
|
||||||
rb_gc_mark((VALUE)cc); // pindown
|
rb_gc_mark((VALUE)cc); // pindown
|
||||||
}
|
}
|
||||||
|
|
8
mjit.c
8
mjit.c
|
@ -45,7 +45,7 @@ mjit_copy_job_handler(void *data)
|
||||||
CRITICAL_SECTION_FINISH(3, "in mjit_copy_job_handler");
|
CRITICAL_SECTION_FINISH(3, "in mjit_copy_job_handler");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (job->iseq == NULL) { // ISeq GC notified in mjit_mark_iseq
|
else if (job->iseq == NULL) { // ISeq GC notified in mjit_free_iseq
|
||||||
job->finish_p = true;
|
job->finish_p = true;
|
||||||
CRITICAL_SECTION_FINISH(3, "in mjit_copy_job_handler");
|
CRITICAL_SECTION_FINISH(3, "in mjit_copy_job_handler");
|
||||||
return;
|
return;
|
||||||
|
@ -1019,6 +1019,12 @@ mjit_mark(void)
|
||||||
RUBY_MARK_LEAVE("mjit");
|
RUBY_MARK_LEAVE("mjit");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const struct rb_callcache **
|
||||||
|
mjit_iseq_cc_entries(const struct rb_iseq_constant_body *const body)
|
||||||
|
{
|
||||||
|
return body->jit_unit->cc_entries;
|
||||||
|
}
|
||||||
|
|
||||||
// A hook to update valid_class_serials.
|
// A hook to update valid_class_serials.
|
||||||
void
|
void
|
||||||
mjit_add_class_serial(rb_serial_t class_serial)
|
mjit_add_class_serial(rb_serial_t class_serial)
|
||||||
|
|
30
mjit.h
30
mjit.h
|
@ -70,35 +70,6 @@ struct rb_mjit_compile_info {
|
||||||
bool disable_inlining;
|
bool disable_inlining;
|
||||||
};
|
};
|
||||||
|
|
||||||
// The unit structure that holds metadata of ISeq for MJIT.
|
|
||||||
struct rb_mjit_unit {
|
|
||||||
// Unique order number of unit.
|
|
||||||
int id;
|
|
||||||
// Dlopen handle of the loaded object file.
|
|
||||||
void *handle;
|
|
||||||
rb_iseq_t *iseq;
|
|
||||||
#ifndef _MSC_VER
|
|
||||||
// This value is always set for `compact_all_jit_code`. Also used for lazy deletion.
|
|
||||||
char *o_file;
|
|
||||||
// true if it's inherited from parent Ruby process and lazy deletion should be skipped.
|
|
||||||
// `o_file = NULL` can't be used to skip lazy deletion because `o_file` could be used
|
|
||||||
// by child for `compact_all_jit_code`.
|
|
||||||
bool o_file_inherited_p;
|
|
||||||
#endif
|
|
||||||
#if defined(_WIN32)
|
|
||||||
// DLL cannot be removed while loaded on Windows. If this is set, it'll be lazily deleted.
|
|
||||||
char *so_file;
|
|
||||||
#endif
|
|
||||||
// Only used by unload_units. Flag to check this unit is currently on stack or not.
|
|
||||||
char used_code_p;
|
|
||||||
struct list_node unode;
|
|
||||||
// mjit_compile's optimization switches
|
|
||||||
struct rb_mjit_compile_info compile_info;
|
|
||||||
|
|
||||||
// captured CC values, they should be marked with iseq.
|
|
||||||
const struct rb_callcache **cc_entries; // size: iseq->body->ci_size
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef VALUE (*mjit_func_t)(rb_execution_context_t *, rb_control_frame_t *);
|
typedef VALUE (*mjit_func_t)(rb_execution_context_t *, rb_control_frame_t *);
|
||||||
|
|
||||||
RUBY_SYMBOL_EXPORT_BEGIN
|
RUBY_SYMBOL_EXPORT_BEGIN
|
||||||
|
@ -122,6 +93,7 @@ extern struct mjit_cont *mjit_cont_new(rb_execution_context_t *ec);
|
||||||
extern void mjit_cont_free(struct mjit_cont *cont);
|
extern void mjit_cont_free(struct mjit_cont *cont);
|
||||||
extern void mjit_add_class_serial(rb_serial_t class_serial);
|
extern void mjit_add_class_serial(rb_serial_t class_serial);
|
||||||
extern void mjit_remove_class_serial(rb_serial_t class_serial);
|
extern void mjit_remove_class_serial(rb_serial_t class_serial);
|
||||||
|
const struct rb_callcache ** mjit_iseq_cc_entries(const struct rb_iseq_constant_body *const body);
|
||||||
|
|
||||||
// A threshold used to reject long iseqs from JITting as such iseqs
|
// A threshold used to reject long iseqs from JITting as such iseqs
|
||||||
// takes too much time to be compiled.
|
// takes too much time to be compiled.
|
||||||
|
|
|
@ -393,7 +393,7 @@ precompile_inlinable_iseqs(FILE *f, const rb_iseq_t *iseq, struct compile_status
|
||||||
if (insn == BIN(opt_send_without_block)) { // `compile_inlined_cancel_handler` supports only `opt_send_without_block`
|
if (insn == BIN(opt_send_without_block)) { // `compile_inlined_cancel_handler` supports only `opt_send_without_block`
|
||||||
CALL_DATA cd = (CALL_DATA)body->iseq_encoded[pos + 1];
|
CALL_DATA cd = (CALL_DATA)body->iseq_encoded[pos + 1];
|
||||||
const struct rb_callinfo *ci = cd->ci;
|
const struct rb_callinfo *ci = cd->ci;
|
||||||
const struct rb_callcache *cc = iseq->body->jit_unit->cc_entries[call_data_index(cd, body)]; // use copy to avoid race condition
|
const struct rb_callcache *cc = mjit_iseq_cc_entries(iseq->body)[call_data_index(cd, body)]; // use copy to avoid race condition
|
||||||
|
|
||||||
const rb_iseq_t *child_iseq;
|
const rb_iseq_t *child_iseq;
|
||||||
if (has_valid_method_type(cc) &&
|
if (has_valid_method_type(cc) &&
|
||||||
|
|
|
@ -135,6 +135,34 @@ typedef intptr_t pid_t;
|
||||||
|
|
||||||
#define MJIT_TMP_PREFIX "_ruby_mjit_"
|
#define MJIT_TMP_PREFIX "_ruby_mjit_"
|
||||||
|
|
||||||
|
// The unit structure that holds metadata of ISeq for MJIT.
|
||||||
|
struct rb_mjit_unit {
|
||||||
|
// Unique order number of unit.
|
||||||
|
int id;
|
||||||
|
// Dlopen handle of the loaded object file.
|
||||||
|
void *handle;
|
||||||
|
rb_iseq_t *iseq;
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
// This value is always set for `compact_all_jit_code`. Also used for lazy deletion.
|
||||||
|
char *o_file;
|
||||||
|
// true if it's inherited from parent Ruby process and lazy deletion should be skipped.
|
||||||
|
// `o_file = NULL` can't be used to skip lazy deletion because `o_file` could be used
|
||||||
|
// by child for `compact_all_jit_code`.
|
||||||
|
bool o_file_inherited_p;
|
||||||
|
#endif
|
||||||
|
#if defined(_WIN32)
|
||||||
|
// DLL cannot be removed while loaded on Windows. If this is set, it'll be lazily deleted.
|
||||||
|
char *so_file;
|
||||||
|
#endif
|
||||||
|
// Only used by unload_units. Flag to check this unit is currently on stack or not.
|
||||||
|
char used_code_p;
|
||||||
|
struct list_node unode;
|
||||||
|
// mjit_compile's optimization switches
|
||||||
|
struct rb_mjit_compile_info compile_info;
|
||||||
|
// captured CC values, they should be marked with iseq.
|
||||||
|
const struct rb_callcache **cc_entries; // size: iseq->body->ci_size
|
||||||
|
};
|
||||||
|
|
||||||
// Linked list of struct rb_mjit_unit.
|
// Linked list of struct rb_mjit_unit.
|
||||||
struct rb_mjit_unit_list {
|
struct rb_mjit_unit_list {
|
||||||
struct list_head head;
|
struct list_head head;
|
||||||
|
@ -1184,7 +1212,7 @@ mjit_copy_cache_from_main_thread(const rb_iseq_t *iseq, union iseq_inline_storag
|
||||||
job->finish_p = true;
|
job->finish_p = true;
|
||||||
|
|
||||||
in_jit = true; // Prohibit GC during JIT compilation
|
in_jit = true; // Prohibit GC during JIT compilation
|
||||||
if (job->iseq == NULL) // ISeq GC is notified in mjit_mark_iseq
|
if (job->iseq == NULL) // ISeq GC is notified in mjit_free_iseq
|
||||||
success_p = false;
|
success_p = false;
|
||||||
job->iseq = NULL; // Allow future GC of this ISeq from here
|
job->iseq = NULL; // Allow future GC of this ISeq from here
|
||||||
CRITICAL_SECTION_FINISH(3, "in mjit_copy_cache_from_main_thread");
|
CRITICAL_SECTION_FINISH(3, "in mjit_copy_cache_from_main_thread");
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
MAYBE_UNUSED(<%= ope.fetch(:decl) %>) = (<%= ope.fetch(:type) %>)operands[<%= i %>];
|
MAYBE_UNUSED(<%= ope.fetch(:decl) %>) = (<%= ope.fetch(:type) %>)operands[<%= i %>];
|
||||||
% end
|
% end
|
||||||
% # compiler: Use copied cc to avoid race condition
|
% # compiler: Use copied cc to avoid race condition
|
||||||
const struct rb_callcache *captured_cc = body->jit_unit->cc_entries[call_data_index(cd, body)];
|
const struct rb_callcache *captured_cc = mjit_iseq_cc_entries(body)[call_data_index(cd, body)];
|
||||||
%
|
%
|
||||||
if (!status->compile_info->disable_send_cache && has_valid_method_type(captured_cc)) {
|
if (!status->compile_info->disable_send_cache && has_valid_method_type(captured_cc)) {
|
||||||
const rb_iseq_t *iseq;
|
const rb_iseq_t *iseq;
|
||||||
|
|
|
@ -57,7 +57,7 @@ switch (insn) {
|
||||||
% when *send_compatible_opt_insns
|
% when *send_compatible_opt_insns
|
||||||
% # To avoid cancel, just emit `opt_send_without_block` instead of `opt_*` insn if call cache is populated.
|
% # To avoid cancel, just emit `opt_send_without_block` instead of `opt_*` insn if call cache is populated.
|
||||||
% cd_index = insn.opes.index { |o| o.fetch(:type) == 'CALL_DATA' }
|
% cd_index = insn.opes.index { |o| o.fetch(:type) == 'CALL_DATA' }
|
||||||
if (has_valid_method_type(body->jit_unit->cc_entries[call_data_index((CALL_DATA)operands[<%= cd_index %>], body)])) {
|
if (has_valid_method_type(mjit_iseq_cc_entries(body)[call_data_index((CALL_DATA)operands[<%= cd_index %>], body)])) {
|
||||||
<%= render 'mjit_compile_send', locals: { insn: opt_send_without_block } -%>
|
<%= render 'mjit_compile_send', locals: { insn: opt_send_without_block } -%>
|
||||||
<%= render 'mjit_compile_insn', locals: { insn: opt_send_without_block } -%>
|
<%= render 'mjit_compile_insn', locals: { insn: opt_send_without_block } -%>
|
||||||
break;
|
break;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче