Skip to content

Commit

Permalink
Merge pull request #2564 from natalie-lang/test-runner-no-hydrate
Browse files Browse the repository at this point in the history
Fewer integer hydrations
  • Loading branch information
seven1m authored Feb 2, 2025
2 parents 9d81f44 + d0eedb5 commit b9935cf
Show file tree
Hide file tree
Showing 21 changed files with 232 additions and 172 deletions.
2 changes: 1 addition & 1 deletion include/natalie/env.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class Env : public Cell {
[[noreturn]] void raise_errno();
[[noreturn]] void raise_errno(StringObject *);
[[noreturn]] void raise_invalid_byte_sequence_error(const EncodingObject *);
[[noreturn]] void raise_no_method_error(Object *, SymbolObject *, MethodMissingReason);
[[noreturn]] void raise_no_method_error(Value, SymbolObject *, MethodMissingReason);
[[noreturn]] void raise_name_error(SymbolObject *name, String);
[[noreturn]] void raise_name_error(StringObject *name, String);
[[noreturn]] void raise_not_comparable_error(Value lhs, Value rhs);
Expand Down
4 changes: 4 additions & 0 deletions include/natalie/kernel_module.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class KernelModule {
static Value define_singleton_method(Env *env, Value self, Value name, Block *block);
static Value dup(Env *env, Value self);
static Value dup_better(Env *env, Value self); // This will eventually replace `dup`.
static Value extend(Env *, Value, Args &&);
static Value hash(Env *env, Value self);
static Value initialize_copy(Env *env, Value self, Value object);
static Value inspect(Env *env, Value self);
Expand All @@ -87,6 +88,9 @@ class KernelModule {
static Value protected_methods(Env *env, Value self, Value recur = nullptr);
static Value public_methods(Env *env, Value self, Value recur = nullptr);
static Value remove_instance_variable(Env *env, Value self, Value name_val);
static bool respond_to_missing(Env *, Value, Value, Value) { return false; }
static bool respond_to_method(Env *, Value, Value, Value);
static bool respond_to_method(Env *, Value, Value, bool);
static Value tap(Env *env, Value self, Block *block);
static bool is_a(Env *env, Value self, Value module);
};
Expand Down
7 changes: 5 additions & 2 deletions include/natalie/module_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,13 @@ class ModuleObject : public Object {
Value prepend(Env *, Args &&args);
void prepend_once(Env *, ModuleObject *);

Value extend_object(Env *, Value);

Value is_autoload(Env *, Value) const;

virtual Value const_find(Env *, SymbolObject *, ConstLookupSearchMode = ConstLookupSearchMode::Strict, ConstLookupFailureMode = ConstLookupFailureMode::ConstMissing) override;
virtual Value const_find_with_autoload(Env *, Value, SymbolObject *, ConstLookupSearchMode = ConstLookupSearchMode::Strict, ConstLookupFailureMode = ConstLookupFailureMode::ConstMissing) override;
Value const_find_with_autoload(Env *, Value, SymbolObject *, ConstLookupSearchMode = ConstLookupSearchMode::Strict, ConstLookupFailureMode = ConstLookupFailureMode::ConstMissing);
Value const_find(Env *, SymbolObject *, ConstLookupSearchMode = ConstLookupSearchMode::Strict, ConstLookupFailureMode = ConstLookupFailureMode::ConstMissing);

virtual Value const_get(SymbolObject *) const override;
virtual Value const_fetch(SymbolObject *) override;
virtual Value const_set(SymbolObject *, Value) override;
Expand Down
31 changes: 16 additions & 15 deletions include/natalie/object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ class Object : public Cell {
Type type() const { return m_type; }
ClassObject *klass() const { return m_klass; }

Value initialize(Env *);
static Value initialize(Env *, Value);

Enumerator::ArithmeticSequenceObject *as_enumerator_arithmetic_sequence();
ArrayObject *as_array();
Expand Down Expand Up @@ -162,6 +162,7 @@ class Object : public Cell {
FloatObject *as_float_or_raise(Env *);
HashObject *as_hash_or_raise(Env *);
MatchDataObject *as_match_data_or_raise(Env *);
ModuleObject *as_module_or_raise(Env *);
RangeObject *as_range_or_raise(Env *);
StringObject *as_string_or_raise(Env *);

Expand All @@ -175,11 +176,10 @@ class Object : public Cell {

void set_singleton_class(ClassObject *);

Value extend(Env *, Args &&);
void extend_once(Env *, ModuleObject *);

virtual Value const_find(Env *, SymbolObject *, ConstLookupSearchMode = ConstLookupSearchMode::Strict, ConstLookupFailureMode = ConstLookupFailureMode::ConstMissing);
virtual Value const_find_with_autoload(Env *, Value, SymbolObject *, ConstLookupSearchMode = ConstLookupSearchMode::Strict, ConstLookupFailureMode = ConstLookupFailureMode::ConstMissing);
static Value const_find_with_autoload(Env *, Value, Value, SymbolObject *, ConstLookupSearchMode = ConstLookupSearchMode::Strict, ConstLookupFailureMode = ConstLookupFailureMode::ConstMissing);

virtual Value const_get(SymbolObject *) const;
virtual Value const_fetch(SymbolObject *);
virtual Value const_set(SymbolObject *, Value);
Expand Down Expand Up @@ -243,20 +243,18 @@ class Object : public Cell {

Value send(Env *, SymbolObject *, Args &&, Block *, MethodVisibility, Value = nullptr);
Value method_missing_send(Env *, SymbolObject *, Args &&, Block *);
Value method_missing(Env *, Args &&, Block *);
static Value method_missing(Env *, Value, Args &&, Block *);

Method *find_method(Env *, SymbolObject *, MethodVisibility, Value) const;

Value duplicate(Env *) const;
Value clone(Env *env, Value freeze = nullptr);
static Value clone_obj(Env *env, Value self, Value freeze = nullptr);

void copy_instance_variables(Value);

bool is_a(Env *, Value) const;
bool respond_to(Env *, Value, bool = true);
bool respond_to_method(Env *, Value, Value);
bool respond_to_method(Env *, Value, bool);
bool respond_to_missing(Env *, Value, Value);
bool respond_to(Env *env, SymbolObject *name) { return Value(this).respond_to(env, name); }

const char *defined(Env *, SymbolObject *, bool);
Value defined_obj(Env *, SymbolObject *, bool = false);
Expand All @@ -268,15 +266,18 @@ class Object : public Cell {
void freeze();
bool is_frozen() const { return m_type == Type::Integer || m_type == Type::Float || m_frozen; }

bool not_truthy() const { return m_type == Type::Nil || m_type == Type::False; }
static bool not_truthy(Value self) {
if (self.is_integer())
return false;
return self.is_falsey();
}

bool eq(Env *, Value other) { return other == this; }
static bool eq(Env *, Value self, Value other) { return other == self; }
static bool equal(Value, Value);
static bool neq(Env *env, Value self, Value other);

bool neq(Env *env, Value other);

Value instance_eval(Env *, Args &&, Block *);
Value instance_exec(Env *, Args &&, Block *);
static Value instance_eval(Env *, Value, Args &&, Block *);
static Value instance_exec(Env *, Value, Args &&, Block *);

void assert_not_frozen(Env *);
void assert_not_frozen(Env *, Value);
Expand Down
7 changes: 7 additions & 0 deletions include/natalie/value.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ class Value {

Value integer_send(Env *env, SymbolObject *name, Args &&args, Block *block, Value sent_from, MethodVisibility visibility);

ClassObject *klass() const;
ClassObject *singleton_class() const;
ClassObject *singleton_class(Env *);

bool is_fast_integer() const {
return m_type == Type::Integer;
}
Expand All @@ -120,6 +124,9 @@ class Value {
nat_int_t object_id() const;

void assert_type(Env *, ObjectType, const char *) const;
void assert_not_frozen(Env *) const;

bool respond_to(Env *, SymbolObject *, bool include_all = true);

bool is_nil() const;
bool is_true() const;
Expand Down
6 changes: 3 additions & 3 deletions lib/fiddle.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class Handle
path.assert_type(env, Object::Type::String, "String");
auto handle = dlopen(path->as_string()->c_str(), RTLD_LAZY);
if (!handle) {
auto dl_error = self->const_find(env, "DLError"_s, Object::ConstLookupSearchMode::NotStrict)->as_class();
auto dl_error = self->klass()->const_find(env, "DLError"_s, Object::ConstLookupSearchMode::NotStrict)->as_class();
env->raise(dl_error, "{}", dlerror());
}
auto handle_ptr = new VoidPObject { handle };
Expand Down Expand Up @@ -90,7 +90,7 @@ def call(*args)
auto symbol = self->ivar_get(env, "@symbol"_s).integer().to_nat_int_t();
auto fn = (void* (*)())symbol;
auto result = fn();
auto pointer_class = self->const_find(env, "Pointer"_s, Object::ConstLookupSearchMode::NotStrict)->as_class();
auto pointer_class = self->klass()->const_find(env, "Pointer"_s, Object::ConstLookupSearchMode::NotStrict)->as_class();
auto pointer_obj = new Object { Object::Type::Object, pointer_class };
auto pointer_ptr = new VoidPObject { result };
pointer_obj->ivar_set(env, "@ptr"_s, pointer_ptr);
Expand All @@ -101,7 +101,7 @@ def call(*args)
auto symbol = self->ivar_get(env, "@symbol"_s).integer().to_nat_int_t();
auto fn = (void* (*)(void*))symbol;
void *p1_ptr;
auto pointer_class = self->const_find(env, "Pointer"_s, Object::ConstLookupSearchMode::NotStrict)->as_class();
auto pointer_class = self->klass()->const_find(env, "Pointer"_s, Object::ConstLookupSearchMode::NotStrict)->as_class();
if (p1->is_a(env, pointer_class))
p1_ptr = p1->ivar_get(env, "@ptr"_s)->as_void_p()->void_ptr();
else if (p1.is_void_p())
Expand Down
26 changes: 13 additions & 13 deletions lib/natalie/compiler/binding_gen.rb
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ def get_object
if GLOBAL_ENV_ACCESSORS.include?(rb_class)
"Value #{rb_class} = GlobalEnv::the()->#{rb_class}();"
else
"Value #{rb_class_as_c_variable} = GlobalEnv::the()->Object()->#{rb_class.split('::').map { |c| "const_find(env, #{c.inspect}_s)" }.join('->')};"
"Value #{rb_class_as_c_variable} = fetch_nested_const({ #{rb_class.split('::').map { |c| "#{c.inspect}_s" }.join(',')} });"
end
end

Expand Down Expand Up @@ -459,13 +459,13 @@ def generate_name
gen.static_binding_as_instance_method('BasicObject', '__id__', 'Object', 'object_id', argc: 0, pass_env: false, pass_block: false, return_type: :int)
gen.static_binding_as_instance_method('BasicObject', 'equal?', 'Object', 'equal', argc: 1, pass_env: false, pass_block: false, return_type: :bool)
gen.static_binding_as_instance_method('BasicObject', '__send__', 'Object', 'send', argc: 1.., pass_env: true, pass_block: true, return_type: :Object)
gen.binding('BasicObject', '!', 'Object', 'not_truthy', argc: 0, pass_env: false, pass_block: false, return_type: :bool)
gen.binding('BasicObject', '==', 'Object', 'eq', argc: 1, pass_env: true, pass_block: false, return_type: :bool)
gen.binding('BasicObject', '!=', 'Object', 'neq', argc: 1, pass_env: true, pass_block: false, return_type: :bool)
gen.binding('BasicObject', 'initialize', 'Object', 'initialize', argc: 0, pass_env: true, pass_block: false, return_type: :Object, visibility: :private)
gen.binding('BasicObject', 'instance_eval', 'Object', 'instance_eval', argc: :any, pass_env: true, pass_block: true, return_type: :Object)
gen.binding('BasicObject', 'instance_exec', 'Object', 'instance_exec', argc: :any, pass_env: true, pass_block: true, return_type: :Object)
gen.binding('BasicObject', 'method_missing', 'Object', 'method_missing', argc: :any, pass_env: true, pass_block: true, return_type: :Object, visibility: :private)
gen.static_binding_as_instance_method('BasicObject', '!', 'Object', 'not_truthy', argc: 0, pass_env: false, pass_block: false, return_type: :bool)
gen.static_binding_as_instance_method('BasicObject', '==', 'Object', 'eq', argc: 1, pass_env: true, pass_block: false, return_type: :bool)
gen.static_binding_as_instance_method('BasicObject', '!=', 'Object', 'neq', argc: 1, pass_env: true, pass_block: false, return_type: :bool)
gen.static_binding_as_instance_method('BasicObject', 'initialize', 'Object', 'initialize', argc: 0, pass_env: true, pass_block: false, return_type: :Object, visibility: :private)
gen.static_binding_as_instance_method('BasicObject', 'instance_eval', 'Object', 'instance_eval', argc: :any, pass_env: true, pass_block: true, return_type: :Object)
gen.static_binding_as_instance_method('BasicObject', 'instance_exec', 'Object', 'instance_exec', argc: :any, pass_env: true, pass_block: true, return_type: :Object)
gen.static_binding_as_instance_method('BasicObject', 'method_missing', 'Object', 'method_missing', argc: :any, pass_env: true, pass_block: true, return_type: :Object, visibility: :private)

gen.binding('Binding', 'source_location', 'BindingObject', 'source_location', argc: 0, pass_env: false, pass_block: false, return_type: :Object)

Expand Down Expand Up @@ -1012,11 +1012,11 @@ def generate_name
gen.static_binding_as_instance_method('Kernel', 'to_s', 'KernelModule', 'inspect', argc: 0, pass_env: true, pass_block: false, return_type: :Object)
gen.static_binding_as_instance_method('Kernel', 'send', 'Object', 'send', argc: 1.., pass_env: true, pass_block: true, return_type: :Object)
gen.static_binding_as_instance_method('Kernel', 'public_send', 'Object', 'public_send', argc: 1.., pass_env: true, pass_block: true, return_type: :Object)
gen.binding('Kernel', 'clone', 'Object', 'clone', argc: 0, kwargs: [:freeze], pass_env: true, pass_block: false, return_type: :Object)
gen.binding('Kernel', 'extend', 'Object', 'extend', argc: 1.., pass_env: true, pass_block: false, return_type: :Object)
gen.static_binding_as_instance_method('Kernel', 'clone', 'Object', 'clone_obj', argc: 0, kwargs: [:freeze], pass_env: true, pass_block: false, return_type: :Object)
gen.static_binding_as_instance_method('Kernel', 'extend', 'KernelModule', 'extend', argc: 1.., pass_env: true, pass_block: false, return_type: :Object)
gen.binding('Kernel', 'frozen?', 'Object', 'is_frozen', argc: 0, pass_env: false, pass_block: false, return_type: :bool)
gen.binding('Kernel', 'respond_to?', 'Object', 'respond_to_method', argc: 1..2, pass_env: true, pass_block: false, return_type: :bool)
gen.binding('Kernel', 'respond_to_missing?', 'Object', 'respond_to_missing', argc: 2, pass_env: true, pass_block: false, return_type: :bool, visibility: :private)
gen.static_binding_as_instance_method('Kernel', 'respond_to?', 'KernelModule', 'respond_to_method', argc: 1..2, pass_env: true, pass_block: false, return_type: :bool)
gen.static_binding_as_instance_method('Kernel', 'respond_to_missing?', 'KernelModule', 'respond_to_missing', argc: 2, pass_env: true, pass_block: false, return_type: :bool, visibility: :private)

gen.undefine_singleton_method('MatchData', 'new')
gen.undefine_singleton_method('MatchData', 'allocate')
Expand Down Expand Up @@ -1075,7 +1075,7 @@ def generate_name
gen.binding('Module', 'constants', 'ModuleObject', 'constants', argc: 0..1, pass_env: true, pass_block: false, return_type: :Object)
gen.binding('Module', 'define_method', 'ModuleObject', 'define_method', argc: 1..2, pass_env: true, pass_block: true, return_type: :Object)
gen.binding('Module', 'deprecate_constant', 'ModuleObject', 'deprecate_constant', argc: :any, pass_env: true, pass_block: false, return_type: :Object)
gen.binding('Module', 'extend', 'Object', 'extend', argc: 1.., pass_env: true, pass_block: false, return_type: :Object)
gen.binding('Module', 'extend_object', 'ModuleObject', 'extend_object', argc: 1, pass_env: true, pass_block: false, return_type: :Object, visibility: :private)
gen.binding('Module', 'include', 'ModuleObject', 'include', argc: 1.., pass_env: true, pass_block: false, return_type: :Object)
gen.binding('Module', 'include?', 'ModuleObject', 'does_include_module', argc: 1, pass_env: true, pass_block: false, return_type: :bool)
gen.binding('Module', 'included_modules', 'ModuleObject', 'included_modules', argc: 0, pass_env: true, pass_block: false, return_type: :Object)
Expand Down
16 changes: 9 additions & 7 deletions lib/natalie/compiler/instructions/const_find_instruction.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,17 @@ def generate(transform)

namespace = transform.pop
search_mode = @strict ? 'Strict' : 'NotStrict'
args = [
'env',
namespace,
'self',
transform.intern(name),
"Object::ConstLookupSearchMode::#{search_mode}",
"Object::ConstLookupFailureMode::#{@failure_mode}",
]
transform.exec_and_push(
:const,
"#{namespace}->const_find_with_autoload(" \
'env, ' \
'self, ' \
"#{transform.intern(name)}, " \
"Object::ConstLookupSearchMode::#{search_mode}, " \
"Object::ConstLookupFailureMode::#{@failure_mode}" \
')'
"Object::const_find_with_autoload(#{args.join(', ')})"
)
end

Expand Down
4 changes: 2 additions & 2 deletions lib/natalie/compiler/instructions/define_class_instruction.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ def generate(transform)
search_mode = private? ? 'StrictPrivate' : 'Strict'

code = []
code << "auto #{klass} = #{namespace}->const_find_with_autoload(env, self, " \
code << "auto #{klass} = Object::const_find_with_autoload(env, #{namespace}, self, " \
"#{transform.intern(@name)}, Object::ConstLookupSearchMode::#{search_mode}, " \
'Object::ConstLookupFailureMode::Null)'
code << "if (#{klass}) {"
code << " if (!#{klass}.is_class()) {"
code << " env->raise(\"TypeError\", \"#{@name} is not a class\");"
code << ' }'
code << "} else {"
code << '} else {'
code << " #{klass} = #{superclass}->subclass(env, #{@name.to_s.inspect})"
code << " #{namespace}->const_set(#{transform.intern(@name)}, #{klass})"
code << '}'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,16 @@ def generate(transform)
search_mode = private? ? 'StrictPrivate' : 'Strict'

code = []
code << "auto #{mod} = #{namespace}->const_find_with_autoload(env, self, " \
code << "auto #{mod} = Object::const_find_with_autoload(env, #{namespace}, self, " \
"#{transform.intern(@name)}, Object::ConstLookupSearchMode::#{search_mode}, " \
'Object::ConstLookupFailureMode::Null)'
code << "if (!#{mod}) {"
code << " #{mod} = new ModuleObject(#{@name.to_s.inspect})"
code << " #{namespace}->const_set(#{transform.intern(@name)}, #{mod})"
code << "}"
code << '}'
code << "if (!#{mod}.is_module() || #{mod}.is_class()) {"
code << " env->raise(\"TypeError\", \"#{@name} is not a module\");"
code << "}"
code << '}'
code << "#{mod}->as_module()->eval_body(env, #{fn})"

transform.exec_and_push(:result_of_define_module, code)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def generate(transform)
# we have to include all methods in this case
include_all = receiver == 'self'
transform.exec(
"if (!#{receiver}->respond_to(env, #{transform.intern(@message)}, #{include_all})) throw new ExceptionObject"
"if (!#{receiver}.respond_to(env, #{transform.intern(@message)}, #{include_all})) throw new ExceptionObject"
)
transform.push_nil
end
Expand Down
Loading

0 comments on commit b9935cf

Please sign in to comment.