Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion class.c
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@ rb_module_add_to_subclasses_list(VALUE module, VALUE iclass)
}

void
rb_class_remove_subclass_head(VALUE klass) // TODO: check this is still used and required
rb_class_remove_subclass_head(VALUE klass)
{
rb_classext_t *ext = RCLASS_EXT_WRITABLE(klass);
rb_class_classext_free_subclasses(ext, klass);
Expand Down
1 change: 1 addition & 0 deletions lib/erb/erb.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Gem::Specification.new do |spec|

spec.metadata['homepage_uri'] = spec.homepage
spec.metadata['source_code_uri'] = spec.homepage
spec.metadata['changelog_uri'] = "https://github.com/ruby/erb/blob/v#{spec.version}/NEWS.md"

spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
Expand Down
26 changes: 8 additions & 18 deletions namespace.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,12 @@ namespace_generate_id(void)
return id;
}

static VALUE
namespace_main_to_s(VALUE obj)
{
return rb_str_new2("main");
}

static void
namespace_entry_initialize(rb_namespace_t *ns)
{
Expand All @@ -128,9 +134,8 @@ namespace_entry_initialize(rb_namespace_t *ns)
ns->ns_id = 0;

ns->top_self = rb_obj_alloc(rb_cObject);
// TODO:
// rb_define_singleton_method(rb_vm_top_self(), "to_s", main_to_s, 0);
// rb_define_alias(rb_singleton_class(rb_vm_top_self()), "inspect", "to_s");
rb_define_singleton_method(ns->top_self, "to_s", namespace_main_to_s, 0);
rb_define_alias(rb_singleton_class(ns->top_self), "inspect", "to_s");
ns->load_path = rb_ary_dup(root->load_path);
ns->expanded_load_path = rb_ary_dup(root->expanded_load_path);
ns->load_path_snapshot = rb_ary_new();
Expand Down Expand Up @@ -349,20 +354,6 @@ rb_namespace_s_current(VALUE recv)
return ns->ns_object;
}

/*
* call-seq:
* Namespace.is_builtin?(klass) -> true or false
*
* Returns +true+ if +klass+ is only in a user namespace.
*/
static VALUE
rb_namespace_s_is_builtin_p(VALUE recv, VALUE klass)
{
if (RCLASS_PRIME_CLASSEXT_READABLE_P(klass) && !RCLASS_PRIME_CLASSEXT_WRITABLE_P(klass))
return Qtrue;
return Qfalse;
}

/*
* call-seq:
* load_path -> array
Expand Down Expand Up @@ -1056,7 +1047,6 @@ Init_Namespace(void)

rb_define_singleton_method(rb_cNamespace, "enabled?", rb_namespace_s_getenabled, 0);
rb_define_singleton_method(rb_cNamespace, "current", rb_namespace_s_current, 0);
rb_define_singleton_method(rb_cNamespace, "is_builtin?", rb_namespace_s_is_builtin_p, 1);

rb_define_method(rb_cNamespace, "load_path", rb_namespace_load_path, 0);
rb_define_method(rb_cNamespace, "load", rb_namespace_load, -1);
Expand Down
3 changes: 1 addition & 2 deletions variable.c
Original file line number Diff line number Diff line change
Expand Up @@ -999,7 +999,7 @@ rb_gvar_set_entry(struct rb_global_entry *entry, VALUE val)
}

#define USE_NAMESPACE_GVAR_TBL(ns,entry) \
(NAMESPACE_OPTIONAL_P(ns) && \
(NAMESPACE_USER_P(ns) && \
(!entry || !entry->var->namespace_ready || entry->var->setter != rb_gvar_readonly_setter))

VALUE
Expand All @@ -1012,7 +1012,6 @@ rb_gvar_set(ID id, VALUE val)
RB_VM_LOCKING() {
entry = rb_global_entry(id);

// TODO: consider root/main namespaces
if (USE_NAMESPACE_GVAR_TBL(ns, entry)) {
rb_hash_aset(ns->gvar_tbl, rb_id2sym(entry->id), val);
retval = val;
Expand Down
3 changes: 0 additions & 3 deletions vm_eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -2000,7 +2000,6 @@ eval_string_with_cref(VALUE self, VALUE src, rb_cref_t *cref, VALUE file, int li
cref = vm_cref_dup(orig_cref);
}
vm_set_eval_stack(ec, iseq, cref, &block);
// TODO: set the namespace frame

/* kick */
return vm_exec(ec);
Expand All @@ -2023,8 +2022,6 @@ eval_string_with_scope(VALUE scope, VALUE src, VALUE file, int line)
vm_bind_update_env(scope, bind, vm_make_env_object(ec, ec->cfp));
}

// TODO: set the namespace frame

/* kick */
return vm_exec(ec);
}
Expand Down
50 changes: 47 additions & 3 deletions zjit/src/cruby_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::cruby::*;
use std::collections::HashMap;
use std::ffi::c_void;
use crate::hir_type::{types, Type};
use crate::hir;

pub struct Annotations {
cfuncs: HashMap<*mut c_void, FnProperties>,
Expand All @@ -29,6 +30,7 @@ pub struct FnProperties {
pub return_type: Type,
/// Whether it's legal to remove the call if the result is unused
pub elidable: bool,
pub inline: fn(&mut hir::Function, hir::BlockId, hir::InsnId, &[hir::InsnId], hir::InsnId) -> Option<hir::InsnId>,
}

/// A safe default for un-annotated Ruby methods: we can't optimize them or their returned values.
Expand All @@ -39,6 +41,7 @@ impl Default for FnProperties {
leaf: false,
return_type: types::BasicObject,
elidable: false,
inline: no_inline,
}
}
}
Expand Down Expand Up @@ -152,12 +155,17 @@ pub fn init() -> Annotations {
let builtin_funcs = &mut HashMap::new();

macro_rules! annotate {
($module:ident, $method_name:literal, $inline:ident) => {
let props = FnProperties { no_gc: false, leaf: false, elidable: false, return_type: types::BasicObject, inline: $inline };
annotate_c_method(cfuncs, unsafe { $module }, $method_name, props);
};
($module:ident, $method_name:literal, $return_type:expr $(, $properties:ident)*) => {
#[allow(unused_mut)]
let mut props = FnProperties { no_gc: false, leaf: false, elidable: false, return_type: $return_type };
let mut props = FnProperties { no_gc: false, leaf: false, elidable: false, return_type: $return_type, inline: no_inline };
$(
props.$properties = true;
)*
#[allow(unused_unsafe)]
annotate_c_method(cfuncs, unsafe { $module }, $method_name, props);
}
}
Expand All @@ -171,14 +179,15 @@ pub fn init() -> Annotations {
no_gc: false,
leaf: false,
elidable: false,
return_type: $return_type
return_type: $return_type,
inline: no_inline,
};
$(props.$properties = true;)+
annotate_builtin_method(builtin_funcs, unsafe { $module }, $method_name, props);
}
}

annotate!(rb_mKernel, "itself", types::BasicObject, no_gc, leaf, elidable);
annotate!(rb_mKernel, "itself", inline_kernel_itself);
annotate!(rb_cString, "bytesize", types::Fixnum, no_gc, leaf);
annotate!(rb_cString, "to_s", types::StringExact);
annotate!(rb_cModule, "name", types::StringExact.union(types::NilClass), no_gc, leaf, elidable);
Expand All @@ -188,12 +197,16 @@ pub fn init() -> Annotations {
annotate!(rb_cArray, "empty?", types::BoolExact, no_gc, leaf, elidable);
annotate!(rb_cArray, "reverse", types::ArrayExact, leaf, elidable);
annotate!(rb_cArray, "join", types::StringExact);
annotate!(rb_cArray, "[]", inline_array_aref);
annotate!(rb_cHash, "empty?", types::BoolExact, no_gc, leaf, elidable);
annotate!(rb_cNilClass, "nil?", types::TrueClass, no_gc, leaf, elidable);
annotate!(rb_mKernel, "nil?", types::FalseClass, no_gc, leaf, elidable);
annotate!(rb_cBasicObject, "==", types::BoolExact, no_gc, leaf, elidable);
annotate!(rb_cBasicObject, "!", types::BoolExact, no_gc, leaf, elidable);
annotate!(rb_cBasicObject, "initialize", types::NilClass, no_gc, leaf, elidable);
annotate!(rb_cString, "to_s", inline_string_to_s);
let thread_singleton = unsafe { rb_singleton_class(rb_cThread) };
annotate!(thread_singleton, "current", types::BasicObject, no_gc, leaf);

annotate_builtin!(rb_mKernel, "Float", types::Float);
annotate_builtin!(rb_mKernel, "Integer", types::Integer);
Expand All @@ -204,3 +217,34 @@ pub fn init() -> Annotations {
builtin_funcs: std::mem::take(builtin_funcs),
}
}

fn no_inline(_fun: &mut hir::Function, _block: hir::BlockId, _recv: hir::InsnId, _args: &[hir::InsnId], _state: hir::InsnId) -> Option<hir::InsnId> {
None
}

fn inline_string_to_s(fun: &mut hir::Function, block: hir::BlockId, recv: hir::InsnId, args: &[hir::InsnId], state: hir::InsnId) -> Option<hir::InsnId> {
if args.len() == 0 && fun.likely_a(recv, types::StringExact, state) {
let recv = fun.coerce_to(block, recv, types::StringExact, state);
return Some(recv);
}
None
}

fn inline_kernel_itself(_fun: &mut hir::Function, _block: hir::BlockId, recv: hir::InsnId, args: &[hir::InsnId], _state: hir::InsnId) -> Option<hir::InsnId> {
if args.len() == 0 {
// No need to coerce the receiver; that is done by the SendWithoutBlock rewriting.
return Some(recv);
}
None
}

fn inline_array_aref(fun: &mut hir::Function, block: hir::BlockId, recv: hir::InsnId, args: &[hir::InsnId], state: hir::InsnId) -> Option<hir::InsnId> {
if let &[index] = args {
if fun.likely_a(index, types::Fixnum, state) {
let index = fun.coerce_to(block, index, types::Fixnum, state);
let result = fun.push_insn(block, hir::Insn::ArrayArefFixnum { array: recv, index });
return Some(result);
}
}
None
}
Loading