zeroc-ice 3.8.2 → 3.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. checksums.yaml +4 -4
  2. data/dist/IceRuby/Communicator.cpp +26 -9
  3. data/dist/IceRuby/Config.h +0 -12
  4. data/dist/IceRuby/Connection.cpp +18 -9
  5. data/dist/IceRuby/DefaultSliceLoader.h +1 -1
  6. data/dist/IceRuby/Endpoint.cpp +21 -8
  7. data/dist/IceRuby/Operation.cpp +7 -5
  8. data/dist/IceRuby/Properties.cpp +3 -4
  9. data/dist/IceRuby/Proxy.cpp +11 -19
  10. data/dist/IceRuby/RubySliceLoader.cpp +1 -1
  11. data/dist/IceRuby/RubySliceLoader.h +6 -0
  12. data/dist/IceRuby/Types.cpp +162 -138
  13. data/dist/IceRuby/Types.h +68 -28
  14. data/dist/IceRuby/Util.cpp +14 -78
  15. data/dist/IceRuby/Util.h +7 -17
  16. data/dist/ice/cpp/include/Ice/Communicator.h +31 -8
  17. data/dist/ice/cpp/include/Ice/Config.h +2 -2
  18. data/dist/ice/cpp/include/Ice/Connection.h +24 -8
  19. data/dist/ice/cpp/include/Ice/CtrlCHandler.h +1 -1
  20. data/dist/ice/cpp/include/Ice/Demangle.h +1 -1
  21. data/dist/ice/cpp/include/Ice/Endpoint.h +4 -4
  22. data/dist/ice/cpp/include/Ice/Initialize.h +4 -4
  23. data/dist/ice/cpp/include/Ice/InputStream.h +5 -5
  24. data/dist/ice/cpp/include/Ice/Instrumentation.h +13 -7
  25. data/dist/ice/cpp/include/Ice/LocalExceptions.h +5 -5
  26. data/dist/ice/cpp/include/Ice/Logger.h +7 -0
  27. data/dist/ice/cpp/include/Ice/LoggerUtil.h +1 -1
  28. data/dist/ice/cpp/include/Ice/Object.h +10 -8
  29. data/dist/ice/cpp/include/Ice/ObjectAdapter.h +1 -1
  30. data/dist/ice/cpp/include/Ice/OutgoingAsync.h +5 -2
  31. data/dist/ice/cpp/include/Ice/OutgoingResponse.h +2 -1
  32. data/dist/ice/cpp/include/Ice/OutputStream.h +7 -6
  33. data/dist/ice/cpp/include/Ice/PluginFactory.h +1 -1
  34. data/dist/ice/cpp/include/Ice/Properties.h +3 -3
  35. data/dist/ice/cpp/include/Ice/Proxy.h +192 -50
  36. data/dist/ice/cpp/include/Ice/SSL/ClientAuthenticationOptions.h +3 -3
  37. data/dist/ice/cpp/include/Ice/SSL/EndpointInfo.h +1 -1
  38. data/dist/ice/cpp/include/Ice/SSL/ServerAuthenticationOptions.h +5 -5
  39. data/dist/ice/cpp/include/Ice/ServantLocator.h +1 -1
  40. data/dist/ice/cpp/include/Ice/Service.h +2 -5
  41. data/dist/ice/cpp/include/Ice/SliceLoader.h +1 -1
  42. data/dist/ice/cpp/include/Ice/SlicedData.h +5 -3
  43. data/dist/ice/cpp/include/Ice/StreamHelpers.h +1 -1
  44. data/dist/ice/cpp/include/Ice/StreamableTraits.h +2 -2
  45. data/dist/ice/cpp/include/Ice/StringConverter.h +2 -3
  46. data/dist/ice/cpp/include/Ice/StringUtil.h +2 -7
  47. data/dist/ice/cpp/include/Ice/UUID.h +1 -0
  48. data/dist/ice/cpp/include/Ice/Value.h +2 -2
  49. data/dist/ice/cpp/include/generated/Ice/BuiltinSequences.h +2 -2
  50. data/dist/ice/cpp/include/generated/Ice/Context.h +2 -2
  51. data/dist/ice/cpp/include/generated/Ice/EndpointTypes.h +2 -2
  52. data/dist/ice/cpp/include/generated/Ice/Identity.h +2 -2
  53. data/dist/ice/cpp/include/generated/Ice/Locator.h +50 -14
  54. data/dist/ice/cpp/include/generated/Ice/LocatorRegistry.h +38 -11
  55. data/dist/ice/cpp/include/generated/Ice/Metrics.h +94 -39
  56. data/dist/ice/cpp/include/generated/Ice/OperationMode.h +2 -2
  57. data/dist/ice/cpp/include/generated/Ice/Process.h +34 -8
  58. data/dist/ice/cpp/include/generated/Ice/PropertiesAdmin.h +42 -11
  59. data/dist/ice/cpp/include/generated/Ice/PropertyDict.h +2 -2
  60. data/dist/ice/cpp/include/generated/Ice/RemoteLogger.h +93 -40
  61. data/dist/ice/cpp/include/generated/Ice/ReplyStatus.h +2 -2
  62. data/dist/ice/cpp/include/generated/Ice/Router.h +50 -14
  63. data/dist/ice/cpp/include/generated/Ice/SliceChecksumDict.h +2 -2
  64. data/dist/ice/cpp/include/generated/Ice/Version.h +2 -2
  65. data/dist/ice/cpp/include/generated/IceDiscovery/Lookup.h +66 -14
  66. data/dist/ice/cpp/include/generated/IceLocatorDiscovery/Lookup.h +34 -8
  67. data/dist/ice/cpp/src/Ice/AddDefaultPluginFactories_all.cpp +1 -1
  68. data/dist/ice/cpp/src/Ice/Base64.cpp +47 -137
  69. data/dist/ice/cpp/src/Ice/Base64.h +2 -2
  70. data/dist/ice/cpp/src/Ice/BatchRequestQueue.cpp +28 -13
  71. data/dist/ice/cpp/src/Ice/BatchRequestQueue.h +5 -1
  72. data/dist/ice/cpp/src/Ice/Buffer.cpp +1 -1
  73. data/dist/ice/cpp/src/Ice/CollocatedRequestHandler.cpp +1 -1
  74. data/dist/ice/cpp/src/Ice/CollocatedRequestHandler.h +1 -1
  75. data/dist/ice/cpp/src/Ice/Communicator.cpp +4 -3
  76. data/dist/ice/cpp/src/Ice/CommunicatorFlushBatchAsync.cpp +8 -0
  77. data/dist/ice/cpp/src/Ice/ConnectRequestHandler.cpp +5 -15
  78. data/dist/ice/cpp/src/Ice/ConnectRequestHandler.h +1 -1
  79. data/dist/ice/cpp/src/Ice/ConnectionFactory.cpp +6 -8
  80. data/dist/ice/cpp/src/Ice/ConnectionFactory.h +0 -3
  81. data/dist/ice/cpp/src/Ice/ConnectionI.cpp +94 -99
  82. data/dist/ice/cpp/src/Ice/ConnectionI.h +11 -8
  83. data/dist/ice/cpp/src/Ice/ConsoleUtil.cpp +1 -1
  84. data/dist/ice/cpp/src/Ice/DefaultsAndOverrides.cpp +10 -14
  85. data/dist/ice/cpp/src/Ice/EndpointI.h +1 -1
  86. data/dist/ice/cpp/src/Ice/FileUtil.cpp +12 -12
  87. data/dist/ice/cpp/src/Ice/FixedRequestHandler.cpp +1 -1
  88. data/dist/ice/cpp/src/Ice/FixedRequestHandler.h +1 -1
  89. data/dist/ice/cpp/src/Ice/HttpParser.h +0 -2
  90. data/dist/ice/cpp/src/Ice/IdleTimeoutTransceiverDecorator.cpp +6 -3
  91. data/dist/ice/cpp/src/Ice/IncomingRequest.cpp +1 -3
  92. data/dist/ice/cpp/src/Ice/InputStream.cpp +23 -19
  93. data/dist/ice/cpp/src/Ice/Instance.cpp +73 -50
  94. data/dist/ice/cpp/src/Ice/Instance.h +1 -6
  95. data/dist/ice/cpp/src/Ice/LocalExceptions.cpp +1 -1
  96. data/dist/ice/cpp/src/Ice/LocatorInfo.cpp +2 -2
  97. data/dist/ice/cpp/src/Ice/LoggerAdminI.cpp +13 -18
  98. data/dist/ice/cpp/src/Ice/LoggerI.cpp +1 -1
  99. data/dist/ice/cpp/src/Ice/LoggerI.h +2 -2
  100. data/dist/ice/cpp/src/Ice/MetricsAdminI.h +6 -1
  101. data/dist/ice/cpp/src/Ice/MetricsObserverI.h +22 -18
  102. data/dist/ice/cpp/src/Ice/NativePropertiesAdmin.cpp +5 -2
  103. data/dist/ice/cpp/src/Ice/Network.cpp +168 -103
  104. data/dist/ice/cpp/src/Ice/Network.h +12 -7
  105. data/dist/ice/cpp/src/Ice/NetworkProxy.cpp +17 -6
  106. data/dist/ice/cpp/src/Ice/NetworkProxy.h +2 -1
  107. data/dist/ice/cpp/src/Ice/Object.cpp +1 -1
  108. data/dist/ice/cpp/src/Ice/ObjectAdapterI.cpp +56 -19
  109. data/dist/ice/cpp/src/Ice/OpaqueEndpointI.cpp +10 -10
  110. data/dist/ice/cpp/src/Ice/Options.cpp +7 -2
  111. data/dist/ice/cpp/src/Ice/OutgoingAsync.cpp +1 -1
  112. data/dist/ice/cpp/src/Ice/OutputStream.cpp +4 -4
  113. data/dist/ice/cpp/src/Ice/PluginManagerI.cpp +7 -1
  114. data/dist/ice/cpp/src/Ice/Properties.cpp +26 -16
  115. data/dist/ice/cpp/src/Ice/PropertyUtil.cpp +1 -1
  116. data/dist/ice/cpp/src/Ice/ProtocolInstance.cpp +0 -11
  117. data/dist/ice/cpp/src/Ice/ProtocolInstance.h +1 -2
  118. data/dist/ice/cpp/src/Ice/Proxy.cpp +9 -1
  119. data/dist/ice/cpp/src/Ice/ProxyAsync.cpp +110 -13
  120. data/dist/ice/cpp/src/Ice/Random.cpp +68 -7
  121. data/dist/ice/cpp/src/Ice/Random.h +6 -2
  122. data/dist/ice/cpp/src/Ice/Reference.cpp +22 -11
  123. data/dist/ice/cpp/src/Ice/Reference.h +3 -0
  124. data/dist/ice/cpp/src/Ice/ReferenceFactory.cpp +10 -0
  125. data/dist/ice/cpp/src/Ice/RequestHandler.h +3 -1
  126. data/dist/ice/cpp/src/Ice/RequestHandlerCache.cpp +1 -1
  127. data/dist/ice/cpp/src/Ice/RequestHandlerCache.h +1 -1
  128. data/dist/ice/cpp/src/Ice/ResourceConfig.h +3 -3
  129. data/dist/ice/cpp/src/Ice/RetryQueue.cpp +8 -12
  130. data/dist/ice/cpp/src/Ice/SHA1.cpp +11 -11
  131. data/dist/ice/cpp/src/Ice/SSL/DistinguishedName.cpp +0 -6
  132. data/dist/ice/cpp/src/Ice/SSL/DistinguishedName.h +0 -6
  133. data/dist/ice/cpp/src/Ice/SSL/OpenSSLEngine.cpp +15 -1
  134. data/dist/ice/cpp/src/Ice/SSL/OpenSSLTransceiverI.cpp +77 -27
  135. data/dist/ice/cpp/src/Ice/SSL/OpenSSLTransceiverI.h +2 -1
  136. data/dist/ice/cpp/src/Ice/SSL/RFC2253.cpp +2 -2
  137. data/dist/ice/cpp/src/Ice/SSL/SSLUtil.cpp +39 -34
  138. data/dist/ice/cpp/src/Ice/SSL/SchannelEngine.cpp +130 -52
  139. data/dist/ice/cpp/src/Ice/SSL/SchannelTransceiverI.cpp +64 -33
  140. data/dist/ice/cpp/src/Ice/SSL/SchannelTransceiverI.h +0 -1
  141. data/dist/ice/cpp/src/Ice/SSL/SecureTransportEngine.cpp +3 -3
  142. data/dist/ice/cpp/src/Ice/SSL/SecureTransportTransceiverI.cpp +9 -3
  143. data/dist/ice/cpp/src/Ice/SSL/SecureTransportUtil.cpp +73 -51
  144. data/dist/ice/cpp/src/Ice/SSL/SecureTransportUtil.h +0 -8
  145. data/dist/ice/cpp/src/Ice/Selector.cpp +13 -11
  146. data/dist/ice/cpp/src/Ice/ServantManager.cpp +3 -3
  147. data/dist/ice/cpp/src/Ice/Service.cpp +33 -115
  148. data/dist/ice/cpp/src/Ice/StreamSocket.cpp +33 -40
  149. data/dist/ice/cpp/src/Ice/StreamSocket.h +4 -4
  150. data/dist/ice/cpp/src/Ice/StringConverter.cpp +1 -1
  151. data/dist/ice/cpp/src/Ice/StringUtil.cpp +12 -21
  152. data/dist/ice/cpp/src/Ice/SysLoggerI.cpp +136 -100
  153. data/dist/ice/cpp/src/Ice/SysLoggerI.h +7 -3
  154. data/dist/ice/cpp/src/Ice/SystemdJournalI.cpp +1 -1
  155. data/dist/ice/cpp/src/Ice/TcpAcceptor.cpp +7 -7
  156. data/dist/ice/cpp/src/Ice/TcpAcceptor.h +2 -1
  157. data/dist/ice/cpp/src/Ice/TcpBufSize.h +40 -0
  158. data/dist/ice/cpp/src/Ice/TcpConnector.cpp +5 -2
  159. data/dist/ice/cpp/src/Ice/TcpConnector.h +2 -0
  160. data/dist/ice/cpp/src/Ice/TcpTransceiver.cpp +6 -2
  161. data/dist/ice/cpp/src/Ice/ThreadPool.cpp +2 -8
  162. data/dist/ice/cpp/src/Ice/ThreadPool.h +0 -2
  163. data/dist/ice/cpp/src/Ice/Timer.cpp +7 -3
  164. data/dist/ice/cpp/src/Ice/UUID.cpp +1 -2
  165. data/dist/ice/cpp/src/Ice/UdpEndpointI.cpp +4 -1
  166. data/dist/ice/cpp/src/Ice/UdpTransceiver.cpp +136 -123
  167. data/dist/ice/cpp/src/Ice/UdpTransceiver.h +3 -4
  168. data/dist/ice/cpp/src/Ice/WSTransceiver.cpp +96 -27
  169. data/dist/ice/cpp/src/Ice/WSTransceiver.h +1 -1
  170. data/dist/ice/cpp/src/Ice/generated/BuiltinSequences.cpp +2 -2
  171. data/dist/ice/cpp/src/Ice/generated/Context.cpp +2 -2
  172. data/dist/ice/cpp/src/Ice/generated/EndpointTypes.cpp +2 -2
  173. data/dist/ice/cpp/src/Ice/generated/Identity.cpp +2 -2
  174. data/dist/ice/cpp/src/Ice/generated/Locator.cpp +2 -2
  175. data/dist/ice/cpp/src/Ice/generated/LocatorRegistry.cpp +2 -2
  176. data/dist/ice/cpp/src/Ice/generated/Metrics.cpp +2 -2
  177. data/dist/ice/cpp/src/Ice/generated/OperationMode.cpp +2 -2
  178. data/dist/ice/cpp/src/Ice/generated/Process.cpp +2 -2
  179. data/dist/ice/cpp/src/Ice/generated/PropertiesAdmin.cpp +2 -2
  180. data/dist/ice/cpp/src/Ice/generated/PropertyDict.cpp +2 -2
  181. data/dist/ice/cpp/src/Ice/generated/RemoteLogger.cpp +2 -2
  182. data/dist/ice/cpp/src/Ice/generated/ReplyStatus.cpp +2 -2
  183. data/dist/ice/cpp/src/Ice/generated/Router.cpp +2 -2
  184. data/dist/ice/cpp/src/Ice/generated/SliceChecksumDict.cpp +2 -2
  185. data/dist/ice/cpp/src/Ice/generated/Version.cpp +2 -2
  186. data/dist/ice/cpp/src/IceDiscovery/LookupI.cpp +47 -9
  187. data/dist/ice/cpp/src/IceDiscovery/LookupI.h +8 -3
  188. data/dist/ice/cpp/src/IceDiscovery/generated/Lookup.cpp +2 -2
  189. data/dist/ice/cpp/src/IceLocatorDiscovery/PluginI.cpp +43 -14
  190. data/dist/ice/cpp/src/IceLocatorDiscovery/generated/Lookup.cpp +2 -2
  191. data/dist/ice/cpp/src/Slice/DocCommentParser.cpp +26 -20
  192. data/dist/ice/cpp/src/Slice/DocCommentParser.h +2 -2
  193. data/dist/ice/cpp/src/Slice/FileTracker.cpp +3 -11
  194. data/dist/ice/cpp/src/Slice/FileTracker.h +0 -2
  195. data/dist/ice/cpp/src/Slice/Grammar.cpp +211 -210
  196. data/dist/ice/cpp/src/Slice/MetadataValidation.cpp +10 -9
  197. data/dist/ice/cpp/src/Slice/Parser.cpp +28 -20
  198. data/dist/ice/cpp/src/Slice/Parser.h +3 -4
  199. data/dist/ice/cpp/src/Slice/Preprocessor.cpp +3 -11
  200. data/dist/ice/cpp/src/Slice/Preprocessor.h +0 -2
  201. data/dist/ice/cpp/src/Slice/Scanner.cpp +3 -3
  202. data/dist/ice/cpp/src/Slice/SliceUtil.cpp +197 -114
  203. data/dist/ice/cpp/src/Slice/StringLiteralUtil.cpp +0 -2
  204. data/dist/ice/cpp/src/Slice/Util.h +21 -9
  205. data/dist/ice/cpp/src/slice2rb/Ruby.cpp +7 -3
  206. data/dist/ice/cpp/src/slice2rb/RubyUtil.cpp +16 -12
  207. data/dist/ice/cpp/src/slice2rb/RubyUtil.h +3 -3
  208. data/dist/ice/slice/Glacier2/Router.ice +3 -3
  209. data/dist/ice/slice/Ice/Metrics.ice +6 -5
  210. data/dist/ice/slice/Ice/RemoteLogger.ice +5 -5
  211. data/dist/ice/slice/IceGrid/Admin.ice +9 -9
  212. data/dist/ice/slice/IceGrid/Descriptor.ice +5 -5
  213. data/dist/ice/slice/IceStorm/Metrics.ice +1 -1
  214. data/dist/lib/Glacier2/Metrics.rb +1 -1
  215. data/dist/lib/Glacier2/PermissionsVerifier.rb +1 -1
  216. data/dist/lib/Glacier2/Router.rb +2 -2
  217. data/dist/lib/Glacier2/SSLInfo.rb +1 -1
  218. data/dist/lib/Glacier2/Session.rb +1 -1
  219. data/dist/lib/Ice/BuiltinSequences.rb +1 -1
  220. data/dist/lib/Ice/CompressBatch.rb +1 -2
  221. data/dist/lib/Ice/Context.rb +1 -1
  222. data/dist/lib/Ice/EndpointSelectionType.rb +1 -2
  223. data/dist/lib/Ice/EndpointTypes.rb +1 -1
  224. data/dist/lib/Ice/Identity.rb +1 -1
  225. data/dist/lib/Ice/IdentitySpaceship.rb +1 -0
  226. data/dist/lib/Ice/Locator.rb +1 -1
  227. data/dist/lib/Ice/LocatorRegistry.rb +1 -1
  228. data/dist/lib/Ice/Metrics.rb +1 -1
  229. data/dist/lib/Ice/OperationMode.rb +2 -3
  230. data/dist/lib/Ice/Process.rb +1 -1
  231. data/dist/lib/Ice/PropertiesAdmin.rb +1 -1
  232. data/dist/lib/Ice/PropertyDict.rb +1 -1
  233. data/dist/lib/Ice/RemoteLogger.rb +2 -3
  234. data/dist/lib/Ice/ReplyStatus.rb +2 -3
  235. data/dist/lib/Ice/Router.rb +1 -1
  236. data/dist/lib/Ice/SliceChecksumDict.rb +1 -1
  237. data/dist/lib/Ice/SliceUtil.rb +2 -2
  238. data/dist/lib/Ice/Struct.rb +1 -0
  239. data/dist/lib/Ice/ToStringMode.rb +1 -2
  240. data/dist/lib/Ice/Value.rb +2 -2
  241. data/dist/lib/Ice/Version.rb +1 -1
  242. data/dist/lib/IceBox/ServiceManager.rb +1 -1
  243. data/dist/lib/IceGrid/Admin.rb +3 -4
  244. data/dist/lib/IceGrid/Descriptor.rb +1 -1
  245. data/dist/lib/IceGrid/Exception.rb +1 -1
  246. data/dist/lib/IceGrid/FileParser.rb +1 -1
  247. data/dist/lib/IceGrid/Registry.rb +2 -3
  248. data/dist/lib/IceGrid/Session.rb +2 -2
  249. data/dist/lib/IceGrid/UserAccountMapper.rb +1 -1
  250. data/dist/lib/IceStorm/IceStorm.rb +1 -1
  251. data/dist/lib/IceStorm/Metrics.rb +1 -1
  252. data/extconf.rb +1 -1
  253. data/ice.gemspec +3 -3
  254. metadata +4 -5
  255. data/dist/ice/cpp/src/Ice/DLLMain.cpp +0 -40
  256. data/dist/ice/cpp/src/Ice/UndefSysMacros.h +0 -37
@@ -12,18 +12,6 @@
12
12
  #include <list>
13
13
  #include <math.h>
14
14
 
15
- //
16
- // Required for RHASH_SIZE to work properly with Ruby 1.8.x.
17
- // T_ZOMBIE is only defined in Ruby 1.9.
18
- //
19
- #ifndef T_ZOMBIE
20
- # include "st.h"
21
- #endif
22
-
23
- #ifndef RHASH_SIZE
24
- # define RHASH_SIZE(v) RHASH(v)->tbl->num_entries
25
- #endif
26
-
27
15
  using namespace std;
28
16
  using namespace IceRuby;
29
17
  using namespace Ice;
@@ -40,6 +28,11 @@ static ProxyInfoMap _proxyInfoMap;
40
28
  typedef map<string, ExceptionInfoPtr, std::less<>> ExceptionInfoMap;
41
29
  static ExceptionInfoMap _exceptionInfoMap;
42
30
 
31
+ namespace
32
+ {
33
+ StreamUtil* streamUtil(Ice::InputStream* is) { return reinterpret_cast<StreamUtil*>(is->getClosure()); }
34
+ }
35
+
43
36
  namespace IceRuby
44
37
  {
45
38
  class InfoMapDestroyer
@@ -151,16 +144,26 @@ addExceptionInfo(const string& id, const ExceptionInfoPtr& info)
151
144
  _exceptionInfoMap.insert(ExceptionInfoMap::value_type(id, info));
152
145
  }
153
146
 
147
+ //
148
+ // PrintObjectHistory implementation
149
+ //
150
+ IceRuby::PrintObjectHistory::PrintObjectHistory() : objects(callRuby(rb_hash_new))
151
+ {
152
+ callRuby(rb_funcall, objects, rb_intern("compare_by_identity"), 0);
153
+ }
154
+
154
155
  //
155
156
  // StreamUtil implementation
156
157
  //
157
158
  VALUE IceRuby::StreamUtil::_slicedDataType = Qnil;
158
159
  VALUE IceRuby::StreamUtil::_sliceInfoType = Qnil;
159
160
 
160
- IceRuby::StreamUtil::StreamUtil() = default;
161
+ IceRuby::StreamUtil::StreamUtil() : _held(Qnil) { rb_gc_register_address(&_held); }
161
162
 
162
163
  IceRuby::StreamUtil::~StreamUtil()
163
164
  {
165
+ rb_gc_unregister_address(&_held);
166
+
164
167
  //
165
168
  // Make sure we break any cycles among the ValueReaders in preserved slices.
166
169
  //
@@ -194,6 +197,24 @@ IceRuby::StreamUtil::add(const shared_ptr<ValueReader>& reader)
194
197
  _readers.insert(reader);
195
198
  }
196
199
 
200
+ long
201
+ IceRuby::StreamUtil::hold(VALUE value)
202
+ {
203
+ if (NIL_P(_held))
204
+ {
205
+ _held = callRuby(rb_ary_new);
206
+ }
207
+ callRuby(rb_ary_push, _held, value);
208
+ return RARRAY_LEN(_held) - 1;
209
+ }
210
+
211
+ VALUE
212
+ IceRuby::StreamUtil::getHeldValue(long index) const
213
+ {
214
+ assert(!NIL_P(_held) && index >= 0 && index < RARRAY_LEN(_held));
215
+ return RARRAY_AREF(_held, index);
216
+ }
217
+
197
218
  void
198
219
  IceRuby::StreamUtil::updateSlicedData()
199
220
  {
@@ -216,11 +237,13 @@ IceRuby::StreamUtil::setSlicedDataMember(VALUE obj, const Ice::SlicedDataPtr& sl
216
237
  {
217
238
  _slicedDataType = callRuby(rb_path2class, "Ice::SlicedData");
218
239
  assert(!NIL_P(_slicedDataType));
240
+ rb_gc_register_mark_object(_slicedDataType);
219
241
  }
220
242
  if (_sliceInfoType == Qnil)
221
243
  {
222
244
  _sliceInfoType = callRuby(rb_path2class, "Ice::SliceInfo");
223
245
  assert(!NIL_P(_sliceInfoType));
246
+ rb_gc_register_mark_object(_sliceInfoType);
224
247
  }
225
248
 
226
249
  volatile VALUE sd = callRuby(rb_class_new_instance, 0, static_cast<VALUE*>(0), _slicedDataType);
@@ -337,7 +360,7 @@ IceRuby::StreamUtil::getSlicedDataMember(VALUE obj, ValueMap* valueMap)
337
360
 
338
361
  auto info = std::make_shared<Ice::SliceInfo>(
339
362
  getString(typeId),
340
- static_cast<int32_t>(getInteger(compactId)),
363
+ getInteger(compactId),
341
364
  std::move(vtmp),
342
365
  hasOptionalMembers == Qtrue,
343
366
  isLastSlice == Qtrue);
@@ -392,7 +415,7 @@ IceRuby::TypeInfo::usesClasses() const
392
415
  }
393
416
 
394
417
  void
395
- IceRuby::TypeInfo::unmarshaled(VALUE, VALUE, void*)
418
+ IceRuby::TypeInfo::unmarshaled(VALUE, VALUE, void*, StreamUtil*)
396
419
  {
397
420
  assert(false);
398
421
  }
@@ -405,8 +428,6 @@ IceRuby::TypeInfo::destroy()
405
428
  //
406
429
  // PrimitiveInfo implementation.
407
430
  //
408
- IceRuby::PrimitiveInfo::PrimitiveInfo() = default;
409
-
410
431
  IceRuby::PrimitiveInfo::PrimitiveInfo(Kind k) : kind(k) {}
411
432
 
412
433
  string
@@ -516,33 +537,28 @@ IceRuby::PrimitiveInfo::marshal(VALUE p, Ice::OutputStream* os, ValueMap*, bool)
516
537
  }
517
538
  case PrimitiveInfo::KindByte:
518
539
  {
519
- long i = getInteger(p);
540
+ int32_t i = getInteger(p);
520
541
  if (i >= 0 && i <= 255)
521
542
  {
522
543
  os->write(static_cast<uint8_t>(i));
523
544
  break;
524
545
  }
525
- throw RubyException(rb_eTypeError, "value is out of range for a byte");
546
+ throw RubyException(rb_eRangeError, "value is out of range for a byte");
526
547
  }
527
548
  case PrimitiveInfo::KindShort:
528
549
  {
529
- long i = getInteger(p);
550
+ int32_t i = getInteger(p);
530
551
  if (i >= SHRT_MIN && i <= SHRT_MAX)
531
552
  {
532
553
  os->write(static_cast<int16_t>(i));
533
554
  break;
534
555
  }
535
- throw RubyException(rb_eTypeError, "value is out of range for a short");
556
+ throw RubyException(rb_eRangeError, "value is out of range for a short");
536
557
  }
537
558
  case PrimitiveInfo::KindInt:
538
559
  {
539
- long i = getInteger(p);
540
- if (i >= INT_MIN && i <= INT_MAX)
541
- {
542
- os->write(static_cast<int32_t>(i));
543
- break;
544
- }
545
- throw RubyException(rb_eTypeError, "value is out of range for an int");
560
+ os->write(getInteger(p));
561
+ break;
546
562
  }
547
563
  case PrimitiveInfo::KindLong:
548
564
  {
@@ -558,7 +574,7 @@ IceRuby::PrimitiveInfo::marshal(VALUE p, Ice::OutputStream* os, ValueMap*, bool)
558
574
  }
559
575
  assert(TYPE(val) == T_FLOAT);
560
576
  double d = static_cast<double>(RFLOAT_VALUE(val));
561
- if (isfinite(d) && (d > numeric_limits<float>::max() || d < -numeric_limits<float>::max()))
577
+ if (isfinite(d) && (d > numeric_limits<float>::max() || d < numeric_limits<float>::lowest()))
562
578
  {
563
579
  throw RubyException(rb_eTypeError, "value is out of range for a float");
564
580
  }
@@ -653,7 +669,7 @@ IceRuby::PrimitiveInfo::unmarshal(
653
669
  break;
654
670
  }
655
671
  }
656
- cb->unmarshaled(val, target, closure);
672
+ cb->unmarshaled(val, target, closure, streamUtil(is));
657
673
  }
658
674
 
659
675
  void
@@ -718,7 +734,7 @@ namespace
718
734
 
719
735
  virtual void element(VALUE key, VALUE value)
720
736
  {
721
- const int32_t v = static_cast<int32_t>(getInteger(key));
737
+ const int32_t v = getInteger(key);
722
738
  assert(enumerators.find(v) == enumerators.end());
723
739
  enumerators[v] = value;
724
740
 
@@ -742,6 +758,13 @@ IceRuby::EnumInfo::EnumInfo(VALUE ident, VALUE t, VALUE e) : rubyClass(t), maxVa
742
758
 
743
759
  const_cast<int32_t&>(maxValue) = iter.maxValue;
744
760
  const_cast<EnumeratorMap&>(enumerators) = iter.enumerators;
761
+
762
+ // Pin these objects: the GC cannot see the VALUEs stored in this object, so they must never move.
763
+ rb_gc_register_mark_object(rubyClass);
764
+ for (const auto& p : enumerators)
765
+ {
766
+ rb_gc_register_mark_object(p.second);
767
+ }
745
768
  }
746
769
 
747
770
  string
@@ -783,10 +806,10 @@ IceRuby::EnumInfo::marshal(VALUE p, Ice::OutputStream* os, ValueMap*, bool)
783
806
  // Validate value.
784
807
  //
785
808
  volatile VALUE val = callRuby(rb_iv_get, p, "@value");
786
- const int32_t ival = static_cast<int32_t>(getInteger(val));
809
+ const int32_t ival = getInteger(val);
787
810
  if (enumerators.find(ival) == enumerators.end())
788
811
  {
789
- throw RubyException(rb_eRangeError, "invalid enumerator %ld for enum %s", ival, id.c_str());
812
+ throw RubyException(rb_eRangeError, "invalid enumerator %d for enum %s", ival, id.c_str());
790
813
  }
791
814
 
792
815
  os->writeEnum(ival, maxValue);
@@ -805,7 +828,7 @@ IceRuby::EnumInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr& c
805
828
  throw Ice::MarshalException(__FILE__, __LINE__, ostr.str());
806
829
  }
807
830
 
808
- cb->unmarshaled(p->second, target, closure);
831
+ cb->unmarshaled(p->second, target, closure, streamUtil(is));
809
832
  }
810
833
 
811
834
  void
@@ -824,7 +847,7 @@ IceRuby::EnumInfo::print(VALUE value, IceInternal::Output& out, PrintObjectHisto
824
847
  // DataMember implementation.
825
848
  //
826
849
  void
827
- IceRuby::DataMember::unmarshaled(VALUE val, VALUE target, void*)
850
+ IceRuby::DataMember::unmarshaled(VALUE val, VALUE target, void*, StreamUtil*)
828
851
  {
829
852
  callRuby(rb_ivar_set, target, rubyID, val);
830
853
  }
@@ -852,7 +875,7 @@ convertDataMembers(VALUE members, DataMemberList& reqMembers, DataMemberList& op
852
875
  if (allowOptional)
853
876
  {
854
877
  member->optional = RTEST(RARRAY_AREF(m, 2));
855
- member->tag = static_cast<int>(getInteger(RARRAY_AREF(m, 3)));
878
+ member->tag = getInteger(RARRAY_AREF(m, 3));
856
879
  }
857
880
  else
858
881
  {
@@ -888,6 +911,9 @@ convertDataMembers(VALUE members, DataMemberList& reqMembers, DataMemberList& op
888
911
  //
889
912
  IceRuby::StructInfo::StructInfo(VALUE ident, VALUE t, VALUE m) : rubyClass(t)
890
913
  {
914
+ // Pin the class: the GC cannot see the VALUE stored in this object, so it must never move.
915
+ rb_gc_register_mark_object(rubyClass);
916
+
891
917
  const_cast<string&>(id) = getString(ident);
892
918
 
893
919
  DataMemberList opt;
@@ -1017,7 +1043,7 @@ IceRuby::StructInfo::unmarshal(
1017
1043
  member->type->unmarshal(is, member, obj, 0, false);
1018
1044
  }
1019
1045
 
1020
- cb->unmarshaled(obj, target, closure);
1046
+ cb->unmarshaled(obj, target, closure, streamUtil(is));
1021
1047
  }
1022
1048
 
1023
1049
  void
@@ -1225,7 +1251,7 @@ IceRuby::SequenceInfo::unmarshal(
1225
1251
  return;
1226
1252
  }
1227
1253
 
1228
- int32_t sz = is->readSize();
1254
+ int32_t sz = is->readAndCheckSeqSize(elementType->wireSize());
1229
1255
  volatile VALUE arr = createArray(sz);
1230
1256
 
1231
1257
  for (int32_t i = 0; i < sz; ++i)
@@ -1234,11 +1260,11 @@ IceRuby::SequenceInfo::unmarshal(
1234
1260
  elementType->unmarshal(is, shared_from_this(), arr, cl, false);
1235
1261
  }
1236
1262
 
1237
- cb->unmarshaled(arr, target, closure);
1263
+ cb->unmarshaled(arr, target, closure, streamUtil(is));
1238
1264
  }
1239
1265
 
1240
1266
  void
1241
- IceRuby::SequenceInfo::unmarshaled(VALUE val, VALUE target, void* closure)
1267
+ IceRuby::SequenceInfo::unmarshaled(VALUE val, VALUE target, void* closure, StreamUtil*)
1242
1268
  {
1243
1269
  static_assert(sizeof(long) == sizeof(void*), "long and void* must have the same size");
1244
1270
  long i = reinterpret_cast<long>(closure);
@@ -1352,7 +1378,7 @@ IceRuby::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, VALU
1352
1378
  const long len = RSTRING_LEN(str);
1353
1379
  if (s == 0 || len == 0)
1354
1380
  {
1355
- os->write(int32_t(0));
1381
+ os->writeSize(0);
1356
1382
  }
1357
1383
  else
1358
1384
  {
@@ -1365,10 +1391,10 @@ IceRuby::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, VALU
1365
1391
  Ice::ByteSeq seq(static_cast<size_t>(sz));
1366
1392
  for (long i = 0; i < sz; ++i)
1367
1393
  {
1368
- long val = getInteger(RARRAY_AREF(arr, i));
1394
+ int32_t val = getInteger(RARRAY_AREF(arr, i));
1369
1395
  if (val < 0 || val > 255)
1370
1396
  {
1371
- throw RubyException(rb_eTypeError, "invalid value for element %ld of sequence<byte>", i);
1397
+ throw RubyException(rb_eRangeError, "invalid value for element %ld of sequence<byte>", i);
1372
1398
  }
1373
1399
  seq[static_cast<size_t>(i)] = static_cast<byte>(val);
1374
1400
  }
@@ -1382,10 +1408,10 @@ IceRuby::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, VALU
1382
1408
  Ice::ShortSeq seq(static_cast<size_t>(sz));
1383
1409
  for (long i = 0; i < sz; ++i)
1384
1410
  {
1385
- long val = getInteger(RARRAY_AREF(arr, i));
1411
+ int32_t val = getInteger(RARRAY_AREF(arr, i));
1386
1412
  if (val < SHRT_MIN || val > SHRT_MAX)
1387
1413
  {
1388
- throw RubyException(rb_eTypeError, "invalid value for element %ld of sequence<short>", i);
1414
+ throw RubyException(rb_eRangeError, "invalid value for element %ld of sequence<short>", i);
1389
1415
  }
1390
1416
  seq[static_cast<size_t>(i)] = static_cast<int16_t>(val);
1391
1417
  }
@@ -1398,12 +1424,7 @@ IceRuby::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, VALU
1398
1424
  Ice::IntSeq seq(static_cast<size_t>(sz));
1399
1425
  for (long i = 0; i < sz; ++i)
1400
1426
  {
1401
- long val = getInteger(RARRAY_AREF(arr, i));
1402
- if (val < INT_MIN || val > INT_MAX)
1403
- {
1404
- throw RubyException(rb_eTypeError, "invalid value for element %ld of sequence<int>", i);
1405
- }
1406
- seq[static_cast<size_t>(i)] = static_cast<int32_t>(val);
1427
+ seq[static_cast<size_t>(i)] = getInteger(RARRAY_AREF(arr, i));
1407
1428
  }
1408
1429
  os->write(seq);
1409
1430
  break;
@@ -1431,7 +1452,12 @@ IceRuby::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, VALU
1431
1452
  throw RubyException(rb_eTypeError, "unable to convert array element %ld to a float", i);
1432
1453
  }
1433
1454
  assert(TYPE(v) == T_FLOAT);
1434
- seq[static_cast<size_t>(i)] = static_cast<float>(RFLOAT_VALUE(v));
1455
+ double d = static_cast<double>(RFLOAT_VALUE(v));
1456
+ if (isfinite(d) && (d > numeric_limits<float>::max() || d < numeric_limits<float>::lowest()))
1457
+ {
1458
+ throw RubyException(rb_eTypeError, "array element %ld is out of range for a float", i);
1459
+ }
1460
+ seq[static_cast<size_t>(i)] = static_cast<float>(d);
1435
1461
  }
1436
1462
  os->write(seq);
1437
1463
  break;
@@ -1467,7 +1493,7 @@ IceRuby::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, VALU
1467
1493
  }
1468
1494
  else
1469
1495
  {
1470
- os->write(&seq[0], &seq[0] + seq.size(), false); // Bypass string conversion.
1496
+ os->write(seq.data(), seq.data() + seq.size(), false); // Bypass string conversion.
1471
1497
  }
1472
1498
  break;
1473
1499
  }
@@ -1604,7 +1630,7 @@ IceRuby::SequenceInfo::unmarshalPrimitiveSequence(
1604
1630
  break;
1605
1631
  }
1606
1632
  }
1607
- cb->unmarshaled(result, target, closure);
1633
+ cb->unmarshaled(result, target, closure, streamUtil(is));
1608
1634
  }
1609
1635
 
1610
1636
  //
@@ -1787,6 +1813,15 @@ IceRuby::DictionaryInfo::unmarshal(
1787
1813
  //
1788
1814
  keyType->unmarshal(is, keyCB, Qnil, 0, false);
1789
1815
  assert(!NIL_P(keyCB->key));
1816
+
1817
+ //
1818
+ // The callback will set the dictionary entry with the unmarshaled value, so we
1819
+ // pass it the key through the closure. When the value type uses classes, the
1820
+ // callback can run after this frame is gone and a raw VALUE copy of the key
1821
+ // would go stale if GC compaction moves the key, so we pass the key's index in
1822
+ // the stream's holding array instead.
1823
+ //
1824
+ void* cl;
1790
1825
  if (valueType->usesClasses())
1791
1826
  {
1792
1827
  // Temporarily set the entry with a Qnil value to ensure the key is not GC
@@ -1795,25 +1830,38 @@ IceRuby::DictionaryInfo::unmarshal(
1795
1830
  {
1796
1831
  // For string keys create a frozen string to ensure that the key used
1797
1832
  // in the map matches the one keep in the closure
1798
- keyCB->key = rb_str_new_frozen(keyCB->key);
1833
+ keyCB->key = callRuby(rb_str_new_frozen, keyCB->key);
1799
1834
  }
1800
1835
  callRuby(rb_hash_aset, hash, keyCB->key, Qnil);
1836
+
1837
+ StreamUtil* util = streamUtil(is);
1838
+ assert(util);
1839
+ cl = reinterpret_cast<void*>(util->hold(keyCB->key));
1840
+ }
1841
+ else
1842
+ {
1843
+ cl = reinterpret_cast<void*>(keyCB->key);
1801
1844
  }
1802
- //
1803
- // The callback will set the dictionary entry with the unmarshaled value,
1804
- // so we pass it the key.
1805
- //
1806
- void* cl = reinterpret_cast<void*>(keyCB->key);
1807
1845
  valueType->unmarshal(is, shared_from_this(), hash, cl, false);
1808
1846
  }
1809
1847
 
1810
- cb->unmarshaled(hash, target, closure);
1848
+ cb->unmarshaled(hash, target, closure, streamUtil(is));
1811
1849
  }
1812
1850
 
1813
1851
  void
1814
- IceRuby::DictionaryInfo::unmarshaled(VALUE val, VALUE target, void* closure)
1852
+ IceRuby::DictionaryInfo::unmarshaled(VALUE val, VALUE target, void* closure, StreamUtil* util)
1815
1853
  {
1816
- volatile VALUE key = reinterpret_cast<VALUE>(closure);
1854
+ volatile VALUE key;
1855
+ if (valueType->usesClasses())
1856
+ {
1857
+ assert(util);
1858
+ static_assert(sizeof(long) == sizeof(void*), "long and void* must have the same size");
1859
+ key = util->getHeldValue(reinterpret_cast<long>(closure));
1860
+ }
1861
+ else
1862
+ {
1863
+ key = reinterpret_cast<VALUE>(closure);
1864
+ }
1817
1865
  callRuby(rb_hash_aset, target, key, val);
1818
1866
  }
1819
1867
 
@@ -1880,7 +1928,7 @@ IceRuby::DictionaryInfo::printElement(VALUE key, VALUE value, IceInternal::Outpu
1880
1928
  }
1881
1929
 
1882
1930
  void
1883
- IceRuby::DictionaryInfo::KeyCallback::unmarshaled(VALUE val, VALUE, void*)
1931
+ IceRuby::DictionaryInfo::KeyCallback::unmarshaled(VALUE val, VALUE, void*, StreamUtil*)
1884
1932
  {
1885
1933
  key = val;
1886
1934
  }
@@ -1909,6 +1957,8 @@ IceRuby::ClassInfo::create(VALUE ident)
1909
1957
  {
1910
1958
  shared_ptr<ClassInfo> classInfo{new ClassInfo{ident}};
1911
1959
  const_cast<VALUE&>(classInfo->typeObj) = createType(classInfo);
1960
+ // Pin the type object: the GC cannot see the VALUE stored in this object, so it must never move.
1961
+ rb_gc_register_mark_object(classInfo->typeObj);
1912
1962
  return classInfo;
1913
1963
  }
1914
1964
 
@@ -1933,10 +1983,12 @@ IceRuby::ClassInfo::define(VALUE t, VALUE compact, VALUE intf, VALUE b, VALUE m)
1933
1983
  assert(base);
1934
1984
  }
1935
1985
 
1936
- const_cast<int32_t&>(compactId) = static_cast<int32_t>(getInteger(compact));
1986
+ const_cast<int32_t&>(compactId) = getInteger(compact);
1937
1987
  const_cast<bool&>(interface) = RTEST(intf);
1938
1988
  convertDataMembers(m, const_cast<DataMemberList&>(members), const_cast<DataMemberList&>(optionalMembers), true);
1939
1989
  const_cast<VALUE&>(rubyClass) = t;
1990
+ // Pin the class: the GC cannot see the VALUE stored in this object, so it must never move.
1991
+ rb_gc_register_mark_object(rubyClass);
1940
1992
  const_cast<bool&>(defined) = true;
1941
1993
  }
1942
1994
 
@@ -2054,9 +2106,9 @@ IceRuby::ClassInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallbackPtr&
2054
2106
  // attached to the stream keeps a reference to the callback object to ensure it lives
2055
2107
  // long enough.
2056
2108
  //
2057
- ReadValueCallbackPtr rocb = make_shared<ReadValueCallback>(shared_from_this(), cb, target, closure);
2058
- StreamUtil* util = reinterpret_cast<StreamUtil*>(is->getClosure());
2109
+ StreamUtil* util = streamUtil(is);
2059
2110
  assert(util);
2111
+ ReadValueCallbackPtr rocb = make_shared<ReadValueCallback>(shared_from_this(), cb, target, closure, util);
2060
2112
  util->add(rocb);
2061
2113
  is->read(patchObject, rocb.get());
2062
2114
  }
@@ -2076,10 +2128,10 @@ IceRuby::ClassInfo::print(VALUE value, IceInternal::Output& out, PrintObjectHist
2076
2128
  }
2077
2129
  else
2078
2130
  {
2079
- map<VALUE, int>::iterator q = history->objects.find(value);
2080
- if (q != history->objects.end())
2131
+ volatile VALUE printedIndex = callRuby(rb_hash_lookup, history->objects, value);
2132
+ if (!NIL_P(printedIndex))
2081
2133
  {
2082
- out << "<object #" << q->second << ">";
2134
+ out << "<object #" << FIX2INT(printedIndex) << ">";
2083
2135
  }
2084
2136
  else
2085
2137
  {
@@ -2090,7 +2142,7 @@ IceRuby::ClassInfo::print(VALUE value, IceInternal::Output& out, PrintObjectHist
2090
2142
  info = dynamic_pointer_cast<ClassInfo>(getType(type));
2091
2143
  assert(info);
2092
2144
  out << "object #" << history->index << " (" << info->id << ')';
2093
- history->objects.insert(map<VALUE, int>::value_type(value, history->index));
2145
+ callRuby(rb_hash_aset, history->objects, value, INT2FIX(history->index));
2094
2146
  ++history->index;
2095
2147
  out.sb();
2096
2148
  info->printMembers(value, out, history);
@@ -2185,13 +2237,14 @@ IceRuby::ProxyInfo::create(VALUE ident)
2185
2237
  {
2186
2238
  shared_ptr<ProxyInfo> proxyInfo{new ProxyInfo{ident}};
2187
2239
  const_cast<VALUE&>(proxyInfo->typeObj) = createType(proxyInfo);
2240
+ // Pin the type object: the GC cannot see the VALUE stored in this object, so it must never move.
2241
+ rb_gc_register_mark_object(proxyInfo->typeObj);
2188
2242
  return proxyInfo;
2189
2243
  }
2190
2244
 
2191
- IceRuby::ProxyInfo::ProxyInfo(VALUE ident) : isBase(false), rubyClass(Qnil), typeObj(Qnil)
2245
+ IceRuby::ProxyInfo::ProxyInfo(VALUE ident) : rubyClass(Qnil), typeObj(Qnil)
2192
2246
  {
2193
2247
  const_cast<string&>(id) = getString(ident);
2194
- const_cast<bool&>(isBase) = id == Ice::Object::ice_staticId();
2195
2248
  }
2196
2249
 
2197
2250
  void
@@ -2199,20 +2252,19 @@ IceRuby::ProxyInfo::define(VALUE t, VALUE b, VALUE i)
2199
2252
  {
2200
2253
  if (!NIL_P(b))
2201
2254
  {
2202
- const_cast<ProxyInfoPtr&>(base) = dynamic_pointer_cast<ProxyInfo>(getType(b));
2203
- assert(base);
2255
+ assert(dynamic_pointer_cast<ProxyInfo>(getType(b)));
2204
2256
  }
2205
2257
 
2206
2258
  volatile VALUE arr = callRuby(rb_check_array_type, i);
2207
2259
  assert(!NIL_P(arr));
2208
2260
  for (int n = 0; n < RARRAY_LEN(arr); ++n)
2209
2261
  {
2210
- ProxyInfoPtr iface = dynamic_pointer_cast<ProxyInfo>(getType(RARRAY_AREF(arr, n)));
2211
- assert(iface);
2212
- const_cast<ProxyInfoList&>(interfaces).push_back(iface);
2262
+ assert(dynamic_pointer_cast<ProxyInfo>(getType(RARRAY_AREF(arr, n))));
2213
2263
  }
2214
2264
 
2215
2265
  const_cast<VALUE&>(rubyClass) = t;
2266
+ // Pin the class: the GC cannot see the VALUE stored in this object, so it must never move.
2267
+ rb_gc_register_mark_object(rubyClass);
2216
2268
  }
2217
2269
 
2218
2270
  string
@@ -2236,7 +2288,7 @@ IceRuby::ProxyInfo::variableLength() const
2236
2288
  int
2237
2289
  IceRuby::ProxyInfo::wireSize() const
2238
2290
  {
2239
- return 1;
2291
+ return 2;
2240
2292
  }
2241
2293
 
2242
2294
  Ice::OptionalFormat
@@ -2287,7 +2339,7 @@ IceRuby::ProxyInfo::unmarshal(
2287
2339
 
2288
2340
  if (!proxy)
2289
2341
  {
2290
- cb->unmarshaled(Qnil, target, closure);
2342
+ cb->unmarshaled(Qnil, target, closure, streamUtil(is));
2291
2343
  return;
2292
2344
  }
2293
2345
 
@@ -2297,7 +2349,7 @@ IceRuby::ProxyInfo::unmarshal(
2297
2349
  }
2298
2350
 
2299
2351
  volatile VALUE p = createProxy(proxy.value(), rubyClass);
2300
- cb->unmarshaled(p, target, closure);
2352
+ cb->unmarshaled(p, target, closure, streamUtil(is));
2301
2353
  }
2302
2354
 
2303
2355
  void
@@ -2315,47 +2367,8 @@ IceRuby::ProxyInfo::print(VALUE value, IceInternal::Output& out, PrintObjectHist
2315
2367
  }
2316
2368
  else
2317
2369
  {
2318
- out << getString(value);
2319
- }
2320
- }
2321
-
2322
- bool
2323
- IceRuby::ProxyInfo::isA(const ProxyInfoPtr& info)
2324
- {
2325
- //
2326
- // Return true if this class has an is-a relationship with info.
2327
- //
2328
- if (info->isBase)
2329
- {
2330
- return true;
2331
- }
2332
- else if (this == info.get())
2333
- {
2334
- return true;
2335
- }
2336
- else if (base && base->isA(info))
2337
- {
2338
- return true;
2339
- }
2340
- else if (!interfaces.empty())
2341
- {
2342
- for (ProxyInfoList::const_iterator p = interfaces.begin(); p != interfaces.end(); ++p)
2343
- {
2344
- if ((*p)->isA(info))
2345
- {
2346
- return true;
2347
- }
2348
- }
2370
+ out << getProxy(value)->ice_toString();
2349
2371
  }
2350
-
2351
- return false;
2352
- }
2353
-
2354
- void
2355
- IceRuby::ProxyInfo::destroy()
2356
- {
2357
- const_cast<ProxyInfoPtr&>(base) = 0;
2358
- const_cast<ProxyInfoList&>(interfaces).clear();
2359
2372
  }
2360
2373
 
2361
2374
  //
@@ -2366,10 +2379,6 @@ IceRuby::ValueWriter::ValueWriter(VALUE object, ValueMap* valueMap, const ClassI
2366
2379
  _map(valueMap),
2367
2380
  _formal(formal)
2368
2381
  {
2369
- //
2370
- // Mark the object as in use for the lifetime of this wrapper.
2371
- //
2372
- rb_gc_register_address(&_object);
2373
2382
  if (!_formal || !_formal->interface)
2374
2383
  {
2375
2384
  volatile VALUE cls = CLASS_OF(object);
@@ -2378,6 +2387,9 @@ IceRuby::ValueWriter::ValueWriter(VALUE object, ValueMap* valueMap, const ClassI
2378
2387
  _info = dynamic_pointer_cast<ClassInfo>(getType(type));
2379
2388
  assert(_info);
2380
2389
  }
2390
+
2391
+ // Mark the object as in use for the lifetime of this wrapper. We register last, in case the code above throws.
2392
+ rb_gc_register_address(&_object);
2381
2393
  }
2382
2394
 
2383
2395
  IceRuby::ValueWriter::~ValueWriter() { rb_gc_unregister_address(&_object); }
@@ -2553,7 +2565,9 @@ IceRuby::ValueReader::_iceRead(Ice::InputStream* is)
2553
2565
  {
2554
2566
  assert(!_slicedData->slices.empty());
2555
2567
 
2556
- volatile VALUE typeId = createString(_slicedData->slices[0]->typeId);
2568
+ const Ice::SliceInfoPtr& sliceInfo = _slicedData->slices[0];
2569
+ volatile VALUE typeId =
2570
+ createString(sliceInfo->typeId.empty() ? std::to_string(sliceInfo->compactId) : sliceInfo->typeId);
2557
2571
  callRuby(rb_iv_set, _object, "@unknownTypeId", typeId);
2558
2572
  }
2559
2573
  }
@@ -2601,10 +2615,14 @@ IceRuby::ReadValueCallback::ReadValueCallback(
2601
2615
  const ClassInfoPtr& info,
2602
2616
  const UnmarshalCallbackPtr& cb,
2603
2617
  VALUE target,
2604
- void* closure)
2618
+ void* closure,
2619
+ StreamUtil* util)
2605
2620
  : _info(info),
2606
2621
  _cb(cb),
2607
- _target(target),
2622
+ _util(util),
2623
+ // invoke() can run after the unmarshal frame that created target has returned, and GC compaction
2624
+ // can move target in the meantime; hold it in the stream's holding array and recover it by index.
2625
+ _targetIndex(util->hold(target)),
2608
2626
  _closure(closure)
2609
2627
  {
2610
2628
  }
@@ -2633,11 +2651,11 @@ IceRuby::ReadValueCallback::invoke(const shared_ptr<Ice::Value>& p)
2633
2651
  // With debug builds we force a GC to ensure that all data members are correctly keep alive.
2634
2652
  rb_gc();
2635
2653
  #endif
2636
- _cb->unmarshaled(obj, _target, _closure);
2654
+ _cb->unmarshaled(obj, _util->getHeldValue(_targetIndex), _closure, _util);
2637
2655
  }
2638
2656
  else
2639
2657
  {
2640
- _cb->unmarshaled(Qnil, _target, _closure);
2658
+ _cb->unmarshaled(Qnil, _util->getHeldValue(_targetIndex), _closure, _util);
2641
2659
  }
2642
2660
  }
2643
2661
 
@@ -2696,7 +2714,6 @@ IceRuby::ExceptionInfo::print(VALUE value, IceInternal::Output& out)
2696
2714
  }
2697
2715
 
2698
2716
  PrintObjectHistory history;
2699
- history.index = 0;
2700
2717
 
2701
2718
  out << "exception " << id;
2702
2719
  out.sb();
@@ -2751,7 +2768,10 @@ IceRuby::ExceptionInfo::printMembers(VALUE value, IceInternal::Output& out, Prin
2751
2768
  //
2752
2769
  // ExceptionReader implementation.
2753
2770
  //
2754
- IceRuby::ExceptionReader::ExceptionReader(const ExceptionInfoPtr& info) : _info(info) {}
2771
+ IceRuby::ExceptionReader::ExceptionReader(const ExceptionInfoPtr& info) : _info(info), _ex(Qnil)
2772
+ {
2773
+ rb_gc_register_address(&_ex);
2774
+ }
2755
2775
 
2756
2776
  IceRuby::ExceptionReader::ExceptionReader(const ExceptionReader& reader) : _info(reader._info), _ex(reader._ex)
2757
2777
  {
@@ -2782,9 +2802,8 @@ void
2782
2802
  IceRuby::ExceptionReader::_read(Ice::InputStream* is)
2783
2803
  {
2784
2804
  is->startException();
2785
-
2786
- const_cast<VALUE&>(_ex) = _info->unmarshal(is);
2787
- rb_gc_register_address(&_ex);
2805
+ _ex = _info->unmarshal(is);
2806
+ is->endException();
2788
2807
  }
2789
2808
 
2790
2809
  bool
@@ -2814,7 +2833,9 @@ IceRuby_defineStruct(VALUE /*self*/, VALUE id, VALUE type, VALUE members)
2814
2833
  ICE_RUBY_TRY
2815
2834
  {
2816
2835
  StructInfoPtr info = make_shared<StructInfo>(id, type, members);
2817
- return createType(info);
2836
+ VALUE result = createType(info);
2837
+ rb_define_const(type, "ICE_TYPE", result);
2838
+ return result;
2818
2839
  }
2819
2840
  ICE_RUBY_CATCH
2820
2841
  return Qnil;
@@ -2914,10 +2935,14 @@ IceRuby_defineException(VALUE /*self*/, VALUE id, VALUE type, VALUE base, VALUE
2914
2935
  }
2915
2936
 
2916
2937
  info->rubyClass = type;
2938
+ // Pin the class: the GC cannot see the VALUE stored in this object, so it must never move.
2939
+ rb_gc_register_mark_object(type);
2917
2940
 
2918
2941
  addExceptionInfo(info->id, info);
2919
2942
 
2920
- return createException(info);
2943
+ VALUE result = createException(info);
2944
+ rb_define_const(type, "ICE_TYPE", result);
2945
+ return result;
2921
2946
  }
2922
2947
  ICE_RUBY_CATCH
2923
2948
  return Qnil;
@@ -2974,7 +2999,6 @@ IceRuby_stringify(VALUE /*self*/, VALUE obj, VALUE type)
2974
2999
  ostringstream ostr;
2975
3000
  IceInternal::Output out(ostr);
2976
3001
  PrintObjectHistory history;
2977
- history.index = 0;
2978
3002
  info->print(obj, out, &history);
2979
3003
 
2980
3004
  string str = ostr.str();