Skip to content

Commit

Permalink
Merge pull request #486 from tenderlove/better-iv
Browse files Browse the repository at this point in the history
Improve cache hits and JIT friendliness
  • Loading branch information
dentarg committed Dec 15, 2022
2 parents 8657465 + 8eb40a7 commit d6f6288
Showing 1 changed file with 94 additions and 79 deletions.
173 changes: 94 additions & 79 deletions lib/addressable/uri.rb
Original file line number Diff line number Diff line change
Expand Up @@ -836,6 +836,8 @@ def initialize(options={})
end
end

reset_ivs

self.defer_validation do
# Bunch of crazy logic required because of the composite components
# like userinfo and authority.
Expand Down Expand Up @@ -878,18 +880,16 @@ def freeze
# The scheme component for this URI.
#
# @return [String] The scheme component.
def scheme
return defined?(@scheme) ? @scheme : nil
end
attr_reader :scheme

##
# The scheme component for this URI, normalized.
#
# @return [String] The scheme component, normalized.
def normalized_scheme
return nil unless self.scheme
@normalized_scheme ||= begin
if self.scheme =~ /^\s*ssh\+svn\s*$/i
if @normalized_scheme == NONE
@normalized_scheme = if self.scheme =~ /^\s*ssh\+svn\s*$/i
"svn+ssh".dup
else
Addressable::URI.normalize_component(
Expand Down Expand Up @@ -920,7 +920,7 @@ def scheme=(new_scheme)
@scheme = nil if @scheme.to_s.strip.empty?

# Reset dependent values
remove_instance_variable(:@normalized_scheme) if defined?(@normalized_scheme)
@normalized_scheme = NONE
remove_composite_values

# Ensure we haven't created an invalid URI
Expand All @@ -931,18 +931,16 @@ def scheme=(new_scheme)
# The user component for this URI.
#
# @return [String] The user component.
def user
return defined?(@user) ? @user : nil
end
attr_reader :user

##
# The user component for this URI, normalized.
#
# @return [String] The user component, normalized.
def normalized_user
return nil unless self.user
return @normalized_user if defined?(@normalized_user)
@normalized_user ||= begin
return @normalized_user unless @normalized_user == NONE
@normalized_user = begin
if normalized_scheme =~ /https?/ && self.user.strip.empty? &&
(!self.password || self.password.strip.empty?)
nil
Expand Down Expand Up @@ -970,14 +968,14 @@ def user=(new_user)

# You can't have a nil user with a non-nil password
if password != nil
@user = EMPTY_STR if @user.nil?
@user = EMPTY_STR unless user
end

# Reset dependent values
remove_instance_variable(:@userinfo) if defined?(@userinfo)
remove_instance_variable(:@normalized_userinfo) if defined?(@normalized_userinfo)
remove_instance_variable(:@authority) if defined?(@authority)
remove_instance_variable(:@normalized_user) if defined?(@normalized_user)
@userinfo = nil
@normalized_userinfo = NONE
@authority = nil
@normalized_user = NONE
remove_composite_values

# Ensure we haven't created an invalid URI
Expand All @@ -988,18 +986,16 @@ def user=(new_user)
# The password component for this URI.
#
# @return [String] The password component.
def password
return defined?(@password) ? @password : nil
end
attr_reader :password

##
# The password component for this URI, normalized.
#
# @return [String] The password component, normalized.
def normalized_password
return nil unless self.password
return @normalized_password if defined?(@normalized_password)
@normalized_password ||= begin
return @normalized_password unless @normalized_password == NONE
@normalized_password = begin
if self.normalized_scheme =~ /https?/ && self.password.strip.empty? &&
(!self.user || self.user.strip.empty?)
nil
Expand All @@ -1026,17 +1022,15 @@ def password=(new_password)
@password = new_password ? new_password.to_str : nil

# You can't have a nil user with a non-nil password
@password ||= nil
@user ||= nil
if @password != nil
@user = EMPTY_STR if @user.nil?
self.user = EMPTY_STR if user.nil?
end

# Reset dependent values
remove_instance_variable(:@userinfo) if defined?(@userinfo)
remove_instance_variable(:@normalized_userinfo) if defined?(@normalized_userinfo)
remove_instance_variable(:@authority) if defined?(@authority)
remove_instance_variable(:@normalized_password) if defined?(@normalized_password)
@userinfo = nil
@normalized_userinfo = NONE
@authority = nil
@normalized_password = NONE
remove_composite_values

# Ensure we haven't created an invalid URI
Expand Down Expand Up @@ -1066,8 +1060,8 @@ def userinfo
# @return [String] The userinfo component, normalized.
def normalized_userinfo
return nil unless self.userinfo
return @normalized_userinfo if defined?(@normalized_userinfo)
@normalized_userinfo ||= begin
return @normalized_userinfo unless @normalized_userinfo == NONE
@normalized_userinfo = begin
current_user = self.normalized_user
current_password = self.normalized_password
if !current_user && !current_password
Expand Down Expand Up @@ -1105,7 +1099,7 @@ def userinfo=(new_userinfo)
self.user = new_user

# Reset dependent values
remove_instance_variable(:@authority) if defined?(@authority)
@authority = nil
remove_composite_values

# Ensure we haven't created an invalid URI
Expand All @@ -1116,9 +1110,7 @@ def userinfo=(new_userinfo)
# The host component for this URI.
#
# @return [String] The host component.
def host
return defined?(@host) ? @host : nil
end
attr_reader :host

##
# The host component for this URI, normalized.
Expand Down Expand Up @@ -1161,8 +1153,8 @@ def host=(new_host)
@host = new_host ? new_host.to_str : nil

# Reset dependent values
remove_instance_variable(:@authority) if defined?(@authority)
remove_instance_variable(:@normalized_host) if defined?(@normalized_host)
@authority = nil
@normalized_host = nil
remove_composite_values

# Ensure we haven't created an invalid URI
Expand Down Expand Up @@ -1293,14 +1285,14 @@ def authority=(new_authority)
end

# Password assigned first to ensure validity in case of nil
self.password = defined?(new_password) ? new_password : nil
self.user = defined?(new_user) ? new_user : nil
self.host = defined?(new_host) ? new_host : nil
self.port = defined?(new_port) ? new_port : nil
self.password = new_password
self.user = new_user
self.host = new_host
self.port = new_port

# Reset dependent values
remove_instance_variable(:@userinfo) if defined?(@userinfo)
remove_instance_variable(:@normalized_userinfo) if defined?(@normalized_userinfo)
@userinfo = nil
@normalized_userinfo = NONE
remove_composite_values

# Ensure we haven't created an invalid URI
Expand Down Expand Up @@ -1348,16 +1340,16 @@ def origin=(new_origin)
new_port = new_origin[/:([^:@\[\]\/]*?)$/, 1]
end

self.scheme = defined?(new_scheme) ? new_scheme : nil
self.host = defined?(new_host) ? new_host : nil
self.port = defined?(new_port) ? new_port : nil
self.scheme = new_scheme
self.host = new_host
self.port = new_port
self.userinfo = nil

# Reset dependent values
remove_instance_variable(:@userinfo) if defined?(@userinfo)
remove_instance_variable(:@normalized_userinfo) if defined?(@normalized_userinfo)
remove_instance_variable(:@authority) if defined?(@authority)
remove_instance_variable(:@normalized_authority) if defined?(@normalized_authority)
@userinfo = nil
@normalized_userinfo = NONE
@authority = nil
@normalized_authority = nil
remove_composite_values

# Ensure we haven't created an invalid URI
Expand All @@ -1384,18 +1376,16 @@ def self.port_mapping
# infer port numbers from default values.
#
# @return [Integer] The port component.
def port
return defined?(@port) ? @port : nil
end
attr_reader :port

##
# The port component for this URI, normalized.
#
# @return [Integer] The port component, normalized.
def normalized_port
return nil unless self.port
return @normalized_port if defined?(@normalized_port)
@normalized_port ||= begin
return @normalized_port unless @normalized_port == NONE
@normalized_port = begin
if URI.port_mapping[self.normalized_scheme] == self.port
nil
else
Expand Down Expand Up @@ -1426,8 +1416,8 @@ def port=(new_port)
@port = nil if @port == 0

# Reset dependent values
remove_instance_variable(:@authority) if defined?(@authority)
remove_instance_variable(:@normalized_port) if defined?(@normalized_port)
@authority = nil
@normalized_port = NONE
remove_composite_values

# Ensure we haven't created an invalid URI
Expand Down Expand Up @@ -1528,9 +1518,7 @@ def site=(new_site)
# The path component for this URI.
#
# @return [String] The path component.
def path
return defined?(@path) ? @path : EMPTY_STR
end
attr_reader :path

NORMPATH = /^(?!\/)[^\/:]*:.*$/
##
Expand Down Expand Up @@ -1579,7 +1567,7 @@ def path=(new_path)
end

# Reset dependent values
remove_instance_variable(:@normalized_path) if defined?(@normalized_path)
@normalized_path = nil
remove_composite_values

# Ensure we haven't created an invalid URI
Expand Down Expand Up @@ -1609,18 +1597,16 @@ def extname
# The query component for this URI.
#
# @return [String] The query component.
def query
return defined?(@query) ? @query : nil
end
attr_reader :query

##
# The query component for this URI, normalized.
#
# @return [String] The query component, normalized.
def normalized_query(*flags)
return nil unless self.query
return @normalized_query if defined?(@normalized_query)
@normalized_query ||= begin
return @normalized_query unless @normalized_query == NONE
@normalized_query = begin
modified_query_class = Addressable::URI::CharacterClasses::QUERY.dup
# Make sure possible key-value pair delimiters are escaped.
modified_query_class.sub!("\\&", "").sub!("\\;", "")
Expand Down Expand Up @@ -1652,7 +1638,7 @@ def query=(new_query)
@query = new_query ? new_query.to_str : nil

# Reset dependent values
remove_instance_variable(:@normalized_query) if defined?(@normalized_query)
@normalized_query = NONE
remove_composite_values
end

Expand Down Expand Up @@ -1814,18 +1800,16 @@ def request_uri=(new_request_uri)
# The fragment component for this URI.
#
# @return [String] The fragment component.
def fragment
return defined?(@fragment) ? @fragment : nil
end
attr_reader :fragment

##
# The fragment component for this URI, normalized.
#
# @return [String] The fragment component, normalized.
def normalized_fragment
return nil unless self.fragment
return @normalized_fragment if defined?(@normalized_fragment)
@normalized_fragment ||= begin
return @normalized_fragment unless @normalized_fragment == NONE
@normalized_fragment = begin
component = Addressable::URI.normalize_component(
self.fragment,
Addressable::URI::NormalizeCharacterClasses::FRAGMENT
Expand All @@ -1848,7 +1832,7 @@ def fragment=(new_fragment)
@fragment = new_fragment ? new_fragment.to_str : nil

# Reset dependent values
remove_instance_variable(:@normalized_fragment) if defined?(@normalized_fragment)
@normalized_fragment = NONE
remove_composite_values

# Ensure we haven't created an invalid URI
Expand Down Expand Up @@ -2507,11 +2491,7 @@ def validate
# @return [Addressable::URI] <code>self</code>.
def replace_self(uri)
# Reset dependent values
instance_variables.each do |var|
if instance_variable_defined?(var) && var != :@validation_deferred
remove_instance_variable(var)
end
end
reset_ivs

@scheme = uri.scheme
@user = uri.user
Expand Down Expand Up @@ -2543,8 +2523,8 @@ def split_path(path)
#
# @api private
def remove_composite_values
remove_instance_variable(:@uri_string) if defined?(@uri_string)
remove_instance_variable(:@hash) if defined?(@hash)
@uri_string = nil
@hash = nil
end

##
Expand All @@ -2556,5 +2536,40 @@ def force_utf8_encoding_if_needed(str)
str.force_encoding(Encoding::UTF_8)
end
end

private

##
# Resets instance variables
#
# @api private
def reset_ivs
@scheme = nil
@user = nil
@normalized_scheme = NONE
@normalized_user = NONE
@uri_string = nil
@hash = nil
@userinfo = nil
@normalized_userinfo = NONE
@authority = nil
@password = nil
@normalized_authority = nil
@port = nil
@normalized_password = NONE
@host = nil
@normalized_host = nil
@normalized_port = NONE
@path = EMPTY_STR
@normalized_path = nil
@normalized_query = NONE
@fragment = nil
@normalized_fragment = NONE
@query = nil
end

NONE = Object.new.freeze

private_constant :NONE
end
end

0 comments on commit d6f6288

Please sign in to comment.