Skip to content

Commit 9bd52da

Browse files
committed
[GR-18163] Avoid creating autorelease pointers when spawning subprocesses (#2264)
PullRequest: truffleruby/2436
2 parents 3414643 + 8ca9852 commit 9bd52da

File tree

4 files changed

+36
-39
lines changed

4 files changed

+36
-39
lines changed

lib/truffle/socket/truffle/foreign.rb

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# truffleruby_primitives: true
2+
13
# Copyright (c) 2013, Brian Shirai
24
# All rights reserved.
35
#
@@ -95,31 +97,30 @@ module Foreign
9597
attach_function :freeifaddrs, [:pointer], :void
9698

9799
def self.bind(descriptor, sockaddr)
98-
sockaddr_p = Truffle::FFI::Pool.stack_alloc(:char, sockaddr.bytesize)
100+
sockaddr_p = Primitive.io_thread_buffer_allocate(sockaddr.bytesize)
99101
begin
100102
sockaddr_p.write_bytes(sockaddr)
101103
_bind(descriptor, sockaddr_p, sockaddr.bytesize)
102104
ensure
103-
Truffle::FFI::Pool.stack_free(sockaddr_p)
105+
Primitive.io_thread_buffer_free(sockaddr_p)
104106
end
105107
end
106108

107109
def self.connect(descriptor, sockaddr)
108110
sockaddr = Socket.coerce_to_string(sockaddr)
109111

110-
sockaddr_p = Truffle::FFI::Pool.stack_alloc(:char, sockaddr.bytesize)
111-
112+
sockaddr_p = Primitive.io_thread_buffer_allocate(sockaddr.bytesize)
112113
begin
113114
sockaddr_p.write_bytes(sockaddr)
114115

115116
_connect(descriptor, sockaddr_p, sockaddr.bytesize)
116117
ensure
117-
Truffle::FFI::Pool.stack_free(sockaddr_p)
118+
Primitive.io_thread_buffer_free(sockaddr_p)
118119
end
119120
end
120121

121122
def self.getsockopt(descriptor, level, optname)
122-
val, length = Truffle::FFI::Pool.stack_alloc(:char, 256, :socklen_t, 1)
123+
val, length = Truffle::FFI::Pool.stack_alloc(256, Primitive.pointer_find_type_size(:socklen_t))
123124

124125
begin
125126
length.write_int(256)
@@ -143,10 +144,10 @@ def self.getaddrinfo(host, service = nil, family = nil, socktype = nil,
143144
hints[:ai_protocol] = protocol || 0
144145
hints[:ai_flags] = flags || 0
145146

146-
res_p = Truffle::FFI::Pool.stack_alloc(:pointer, 1)
147+
res_p = Primitive.io_thread_buffer_allocate(Primitive.pointer_find_type_size(:pointer))
147148

148149
res_p.clear
149-
err = _getaddrinfo(host, service, hints.pointer, res_p)
150+
err = _getaddrinfo(host, service, hints.pointer, res_p)
150151

151152
raise SocketError, gai_strerror(err) unless err == 0
152153

@@ -183,7 +184,7 @@ def self.getaddrinfo(host, service = nil, family = nil, socktype = nil,
183184

184185
# Be sure to feed a legit pointer to freeaddrinfo
185186
freeaddrinfo(ptr) unless ptr.null?
186-
Truffle::FFI::Pool.stack_free(res_p)
187+
Primitive.io_thread_buffer_free(res_p)
187188
end
188189
end
189190

@@ -198,7 +199,7 @@ def self.getnameinfo(sockaddr, flags = ::Socket::NI_NUMERICHOST | ::Socket::NI_N
198199
name_info = []
199200

200201
sockaddr_p, node, service = Truffle::FFI::Pool.stack_alloc(
201-
:char, sockaddr.bytesize, :char, ::Socket::NI_MAXHOST, :char, ::Socket::NI_MAXSERV)
202+
sockaddr.bytesize, ::Socket::NI_MAXHOST, ::Socket::NI_MAXSERV)
202203

203204
begin
204205
sockaddr_p.write_bytes(sockaddr)
@@ -231,7 +232,7 @@ def self.getnameinfo(sockaddr, flags = ::Socket::NI_NUMERICHOST | ::Socket::NI_N
231232
end
232233

233234
def self.getpeername(descriptor)
234-
sockaddr_storage_p, len_p = Truffle::FFI::Pool.stack_alloc(:char, 128, :socklen_t, 1)
235+
sockaddr_storage_p, len_p = Truffle::FFI::Pool.stack_alloc(128, Primitive.pointer_find_type_size(:socklen_t))
235236
begin
236237
len_p.write_int(128)
237238

@@ -246,7 +247,7 @@ def self.getpeername(descriptor)
246247
end
247248

248249
def self.getsockname(descriptor)
249-
sockaddr_storage_p, len_p = Truffle::FFI::Pool.stack_alloc(:char, 128, :socklen_t, 1)
250+
sockaddr_storage_p, len_p = Truffle::FFI::Pool.stack_alloc(128, Primitive.pointer_find_type_size(:socklen_t))
250251

251252
begin
252253
len_p.write_int(128)
@@ -283,7 +284,7 @@ def self.pack_sockaddr_in(host, port, family = ::Socket::AF_UNSPEC,
283284
host = '0.0.0.0'
284285
end
285286

286-
res_p = Truffle::FFI::Pool.stack_alloc(:pointer, 1)
287+
res_p = Primitive.io_thread_buffer_allocate(Primitive.pointer_find_type_size(:pointer))
287288
res_p.clear
288289

289290
err = _getaddrinfo(host, port.to_s, hints.pointer, res_p)
@@ -302,7 +303,7 @@ def self.pack_sockaddr_in(host, port, family = ::Socket::AF_UNSPEC,
302303
ptr = res_p.read_pointer
303304

304305
freeaddrinfo(ptr) unless ptr.null?
305-
Truffle::FFI::Pool.stack_free(res_p)
306+
Primitive.io_thread_buffer_free(res_p)
306307
end
307308
end
308309

@@ -328,7 +329,7 @@ def self.getpeereid(*)
328329
end
329330

330331
def self.socketpair(family, type, protocol)
331-
pointer = Truffle::FFI::Pool.stack_alloc(:int, 2)
332+
pointer = Primitive.io_thread_buffer_allocate(Primitive.pointer_find_type_size(:int) * 2)
332333
begin
333334
pointer.clear
334335
status = _socketpair(family, type, protocol, pointer)
@@ -337,7 +338,7 @@ def self.socketpair(family, type, protocol)
337338

338339
pointer.read_array_of_int(2)
339340
ensure
340-
Truffle::FFI::Pool.stack_free(pointer)
341+
Primitive.io_thread_buffer_free(pointer)
341342
end
342343
end
343344

@@ -373,7 +374,7 @@ def self.ip_to_bytes(family, address)
373374
address = address[0...i]
374375
end
375376

376-
pointer = Truffle::FFI::Pool.stack_alloc(:pointer, size)
377+
pointer = Primitive.io_thread_buffer_allocate(Primitive.pointer_find_type_size(:pointer) * size)
377378

378379
begin
379380
status = inet_pton(family, address, pointer)
@@ -382,7 +383,7 @@ def self.ip_to_bytes(family, address)
382383

383384
pointer.get_array_of_uchar(0, size)
384385
ensure
385-
Truffle::FFI::Pool.stack_free(pointer)
386+
Primitive.io_thread_buffer_free(pointer)
386387
end
387388
end
388389
end

src/main/ruby/truffleruby/core/posix.rb

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -326,12 +326,15 @@ def self.with_array_of_ints(ints)
326326

327327
def self.with_array_of_strings_pointer(strings)
328328
Truffle::FFI::MemoryPointer.new(:pointer, strings.size + 1) do |ptr|
329-
pointers = strings.map do |str|
330-
Truffle::FFI::MemoryPointer.from_string(str)
329+
pointers = Truffle::FFI::Pool.stack_alloc(*strings.map { |s| s.bytesize + 1 })
330+
begin
331+
pointers.zip(strings) { |sp, s| sp.put_string(0, s) }
332+
pointers << Truffle::FFI::Pointer::NULL
333+
ptr.write_array_of_pointer pointers
334+
yield(ptr)
335+
ensure
336+
Truffle::FFI::Pool.stack_free(pointers[0])
331337
end
332-
pointers << Truffle::FFI::Pointer::NULL
333-
ptr.write_array_of_pointer pointers
334-
yield(ptr)
335338
end
336339
end
337340

src/main/ruby/truffleruby/core/truffle/ffi/pointer.rb

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -266,30 +266,23 @@ def self.from_string(str)
266266
end
267267

268268
class Pool
269-
269+
# Use Primitive.io_thread_buffer_allocate(Primitive.pointer_find_type_size(:type) * n)
270+
# instead for a single pointer. This method always returns an Array of FFI::Pointer.
270271
def self.stack_alloc(*args)
271272
total_length = 0
272273
offsets = []
273-
args.each_slice(2) do |type, count|
274-
type_size = case type
275-
when nil
276-
1
277-
when Integer
278-
type
279-
when Symbol
280-
Pointer.find_type_size(type)
281-
else
282-
type.size
283-
end
284-
length = (type_size * count)
274+
args.each do |length|
275+
unless Primitive.object_kind_of?(length, Integer)
276+
raise ArgumentError, "incorrect pointer type: #{length.inspect}"
277+
end
285278
offsets << [total_length, length]
286279
total_length += length
287280
end
288281
buffer = Primitive.io_thread_buffer_allocate(total_length)
289-
pointers = offsets.map { |offset, length| buffer.slice(offset, length) }
290-
pointers.size == 1 ? pointers[0] : pointers
282+
offsets.map { |offset, length| buffer.slice(offset, length) }
291283
end
292284

285+
# The argument is the first pointer returned by #stack_alloc
293286
def self.stack_free(pointer)
294287
Primitive.io_thread_buffer_free(pointer)
295288
end

src/main/ruby/truffleruby/core/truffle/io_operations.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ def self.select(readables, readable_ios, writables, writable_ios, errorables, er
137137
end
138138

139139
readables_pointer, writables_pointer, errorables_pointer =
140-
Truffle::FFI::Pool.stack_alloc(:int, readables.size, :int, writables.size, :int, errorables.size)
140+
Truffle::FFI::Pool.stack_alloc(readables.size * SIZEOF_INT, writables.size * SIZEOF_INT, errorables.size * SIZEOF_INT)
141141

142142
begin
143143
to_fds(readable_ios, readables_pointer)

0 commit comments

Comments
 (0)