Improve some Pathname instance variable handling

Will fix or at least partly address:
```
/home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/os/linux/elf.rb:225: warning: The class Pathname reached 8 shape variations, instance variables accesses will be slower and memory usage increased.
35
It is recommended to define instance variables in a consistent order, for instance by eagerly defining them all in the #initialize method.
```
This commit is contained in:
Mike McQuaid 2025-07-11 08:02:27 +00:00 committed by GitHub
parent 5692ea6c17
commit d57efd9ea2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 48 additions and 16 deletions

View File

@ -449,7 +449,7 @@ class Pathname
# This is why monkeypatching is non-ideal (but right solution to get
# Ruby 3.3 over the line).
odisabled "rmtree", "FileUtils#rm_r"
FileUtils.rm_r(@path, noop:, verbose:, secure:)
FileUtils.rm_r(T.must(@path), noop:, verbose:, secure:)
nil
end
end

View File

@ -44,6 +44,19 @@ module ELFShim
requires_ancestor { Pathname }
def initialize(*args)
@elf = T.let(nil, T.nilable(T::Boolean))
@arch = T.let(nil, T.nilable(Symbol))
@elf_type = T.let(nil, T.nilable(Symbol))
@rpath = T.let(nil, T.nilable(String))
@interpreter = T.let(nil, T.nilable(String))
@dynamic_elf = T.let(nil, T.nilable(T::Boolean))
@metadata = T.let(nil, T.nilable(Metadata))
@patchelf_patcher = nil
super
end
def read_uint8(offset)
read(1, offset).unpack1("C")
end
@ -52,8 +65,10 @@ module ELFShim
read(2, offset).unpack1("v")
end
sig { returns(T::Boolean) }
def elf?
return @elf if defined? @elf
return @elf unless @elf.nil?
return @elf = false if read(MAGIC_NUMBER_ASCII.size, MAGIC_NUMBER_OFFSET) != MAGIC_NUMBER_ASCII
# Check that this ELF file is for Linux or System V.
@ -61,6 +76,7 @@ module ELFShim
@elf = [OS_ABI_LINUX, OS_ABI_SYSTEM_V].include? read_uint8(OS_ABI_OFFSET)
end
sig { returns(Symbol) }
def arch
return :dunno unless elf?
@ -84,6 +100,7 @@ module ELFShim
wanted_arch == arch
end
sig { returns(Symbol) }
def elf_type
return :dunno unless elf?
@ -104,10 +121,9 @@ module ELFShim
# The runtime search path, such as:
# "/lib:/usr/lib:/usr/local/lib"
sig { returns(T.nilable(String)) }
def rpath
return @rpath if defined? @rpath
@rpath = rpath_using_patchelf_rb
@rpath ||= rpath_using_patchelf_rb
end
# An array of runtime search path entries, such as:
@ -116,10 +132,9 @@ module ELFShim
Array(rpath&.split(":"))
end
sig { returns(T.nilable(String)) }
def interpreter
return @interpreter if defined? @interpreter
@interpreter = patchelf_patcher.interpreter
@interpreter ||= patchelf_patcher.interpreter
end
def patch!(interpreter: nil, rpath: nil)
@ -128,23 +143,31 @@ module ELFShim
save_using_patchelf_rb interpreter, rpath
end
sig { returns(T::Boolean) }
def dynamic_elf?
return @dynamic_elf if defined? @dynamic_elf
@dynamic_elf = patchelf_patcher.elf.segment_by_type(:DYNAMIC).present?
@dynamic_elf ||= patchelf_patcher.elf.segment_by_type(:DYNAMIC).present?
end
# Helper class for reading metadata from an ELF file.
class Metadata
attr_reader :path, :dylib_id, :dylibs
sig { returns(ELFShim) }
attr_reader :path
sig { returns(T.nilable(String)) }
attr_reader :dylib_id
sig { returns(T::Array[String]) }
attr_reader :dylibs
sig { params(path: ELFShim).void }
def initialize(path)
@path = path
@dylibs = []
@path = T.let(path, ELFShim)
@dylibs = T.let([], T::Array[String])
@dylib_id = T.let(nil, T.nilable(String))
@dylib_id, needed = needed_libraries path
return if needed.empty?
@dylibs = needed.map { |lib| find_full_lib_path(lib).to_s } if needed.present?
@dylibs = needed.map { |lib| find_full_lib_path(lib).to_s }
@metadata = T.let(nil, T.nilable(T::Hash[String, T.untyped]))
end
private
@ -225,6 +248,7 @@ module ELFShim
@patchelf_patcher ||= ::PatchELF::Patcher.new to_s, on_error: :silent
end
sig { returns(Metadata) }
def metadata
@metadata ||= Metadata.new(self)
end

View File

@ -12,11 +12,19 @@ module MachOShim
delegate [:dylib_id] => :macho
def initialize(*args)
@macho = T.let(nil, T.nilable(MachO::MachOFile))
@mach_data = T.let(nil, T.nilable(T::Array[T::Hash[Symbol, T.untyped]]))
super
end
def macho
@macho ||= MachO.open(to_s)
end
private :macho
sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
def mach_data
@mach_data ||= begin
machos = []