| 1269 | } |
| 1270 | |
| 1271 | func (r *Runtime) registerClassObjectIdentity(contextID uint64, handleID int32) int32 { |
| 1272 | if r == nil || contextID == 0 || handleID <= 0 { |
| 1273 | return 0 |
| 1274 | } |
| 1275 | |
| 1276 | objectID := r.nextClassObjectID() |
| 1277 | if objectID == 0 { |
| 1278 | return 0 |
| 1279 | } |
| 1280 | identity := classObjectIdentity{contextID: contextID, handleID: handleID} |
| 1281 | r.classObjectRegistry.Store(objectID, identity) |
| 1282 | |
| 1283 | bucketValue, _ := r.classObjectIDsByCtx.LoadOrStore(contextID, &sync.Map{}) |
| 1284 | bucket, ok := bucketValue.(*sync.Map) |
| 1285 | if !ok { |
| 1286 | // Corruption path: serialize replacement to avoid concurrent overwrite. |
| 1287 | r.mu.Lock() |
| 1288 | currentBucket, loaded := r.classObjectIDsByCtx.Load(contextID) |
| 1289 | if loaded { |
| 1290 | if existing, typed := currentBucket.(*sync.Map); typed { |
| 1291 | bucket = existing |
| 1292 | ok = true |
| 1293 | } |
| 1294 | } |
| 1295 | if !ok { |
| 1296 | replacement := &sync.Map{} |
| 1297 | r.classObjectIDsByCtx.Store(contextID, replacement) |
| 1298 | bucket = replacement |
| 1299 | } |
| 1300 | r.mu.Unlock() |
| 1301 | } |
| 1302 | bucket.Store(objectID, struct{}{}) |
| 1303 | |
| 1304 | return objectID |
| 1305 | } |
| 1306 | |
| 1307 | func (r *Runtime) getClassObjectIdentity(objectID int32) (classObjectIdentity, bool) { |
| 1308 | if r == nil || objectID == 0 { |