Thanks Toon, will do.

On Wednesday, April 9, 2025 at 7:52:48 AM UTC-4 Toon Verwaest wrote:

> Thanks for this report! That sounds like a ScopeInfo deserialization bug. 
> Presumably we rehash when we deserialize the NameToIndexHashTable but 
> forget that we directly point to an entry from the ScopeInfo. Care to file 
> a bug?
>
> On Wed, Apr 9, 2025 at 1:32 PM alex...@gmail.com <alex...@gmail.com> 
> wrote:
>
>> FWIW, one "thought" I had on this was that if saved_class_variable_info 
>> were an Smi if the local names are inlined and a String reference, if not, 
>> then there would never be a need to fix anything up during deserialization 
>> as the String reference could be used to do a lookup in the local names 
>> hash table. But this is just kibitzing.
>>
>> On Wednesday, April 9, 2025 at 12:14:53 AM UTC-4 alex...@gmail.com wrote:
>>
>>> Hey folks,
>>>
>>> I have a class with many private functions/properties (77 in the most 
>>> recent incarnation). When I get a stack trace (say to create an Error 
>>> object) when I'm inside a function in this class, we end up in 
>>> ClassScope::ClassScope in scopes.cc:
>>> ```
>>>   if (scope_info->HasSavedClassVariable()) {
>>>     Tagged<String> name;
>>>     int index;
>>>     std::tie(name, index) = scope_info->SavedClassVariable();
>>> ```
>>>
>>> This ends up loading an index tacked on to the end of the context slots 
>>> in the ScopeInfo heap object which looks like:
>>>
>>> ```
>>> 0x25eabdda3541: [ScopeInfo]
>>> - map: 0x2ad145840d71 <Map(SCOPE_INFO_TYPE)>
>>> - parameters: 0
>>> - context locals : 79
>>> - local names in a hashtable: 0x25eabdda2d19 <Other heap object 
>>> (NAME_TO_INDEX_HASH_TABLE_TYPE)>
>>> - scope type: CLASS_SCOPE
>>> - language mode: strict
>>> - class scope has private brand
>>> - has saved class variable
>>> - function kind: NormalFunction
>>> - outer scope info: 0x25eabdda2801 <ScopeInfo MODULE_SCOPE>
>>> - start position: 22541
>>> - end position: 282321
>>> - length: 87
>>> - context slots {
>>> - 51: 0x1a45b21b8311 <String[17]: ##getTransactionId>
>>> - 72: 0x1a45b21b7fc9 <String[13]: ##valueMatches>
>>> - 0: 0x1a45b21b6d21 <String[17]: ##allowRunJsScript>
>>> - 32: 0x1a45b21b71d1 <String[5]: ##call>
>>> - 75: 0x1a45b21b9e59 <String[17]: ##writeNumericParm>
>>> - 77: 0x2ad145846ae1 <String[6]: #.brand>
>>> - 59: 0x1070007a8419 <String[13]: ##sendResponse>
>>> - 29: 0x1a45b21b70a1 <String[9]: ##timeZone>
>>> - 37: 0x1a45b21b84a9 <String[11]: ##createFind>
>>> - 71: 0x1a45b21bcc91 <String[14]: ##updateRecords>
>>> - 17: 0x1a45b21b6f69 <String[19]: ##pendingImageFields>
>>> - 28: 0x1a45b21b7081 <String[14]: ##syncSemaphore>
>>> - 27: 0x1a45b21b7061 <String[14]: ##syncQueueLock>
>>> - 39: 0x1a45b21b8a31 <String[5]: ##find>
>>> - 45: 0x1a45b21b91c1 <String[25]: ##getFindRecordTypeInfoSet>
>>> - 8: 0x1a45b21b6df9 <String[9]: ##inBuffer>
>>> - 44: 0x1a45b21b9d91 <String[12]: ##getFileInfo>
>>> - 66: 0x1a45b21bd609 <String[16]: ##syncBuildRecord> 
>>> - 78: 0x208cca45af99 <String[10]: #Connection>
>>> ```
>>> A lot more slots follow, but after them is the class variable info 
>>> retrieved by the TorqueGeneratedScopeInfo::saved_class_variable_info 
>>> function. FWIW, job in lldb does not show the value (23 in my example).
>>>
>>> That saved_class_variable_info is then used to index a name and value in 
>>> the local names hash table referenced by the ScopeInfo heap object. And 
>>> this table is used in ScopeInfo::SavedClassVariable to get the class name 
>>> and index:
>>> ```
>>>   if (HasInlinedLocalNames()) {
>>>     ...
>>>   } else {
>>>     // The saved class variable info corresponds to the offset in the 
>>> hash
>>>     // table storage.
>>>     InternalIndex entry(saved_class_variable_info());
>>>     Tagged<NameToIndexHashTable> table = context_local_names_hashtable();
>>>     Tagged<Object> name = table->KeyAt(entry);
>>>     DCHECK(IsString(name));
>>>     return std::make_pair(Cast<String>(name), table->IndexAt(entry));
>>>   } 
>>> ```
>>> The table is a hash table because it's gotten beyond a certain size. In 
>>> my example it looks like:
>>> ```
>>> 0x25eabdda2d19: [NameToIndexHashTable]
>>> - FixedArray length: 259
>>>   - elements: 79
>>>   - deleted: 0
>>>   - capacity: 12
>>>   - elements: {
>>>               0: #getTransactionId -> 51
>>>               1: #valueMatches -> 72
>>>               4: #allowRunJsScript -> 0
>>>               5: #call -> 32
>>>               6: #writeNumericParm -> 75
>>>               7: .brand -> 77
>>>               9: #sendResponse -> 59
>>>              10: #timeZone -> 29
>>>              11: #createFind -> 37
>>>              12: #updateRecords -> 71
>>>              13: #pendingImageFields -> 17
>>>              14: #syncSemaphore -> 28
>>>              15: #syncQueueLock -> 27
>>>              16: #find -> 39
>>>              17: #getFindRecordTypeInfoSet -> 45
>>>              18: #inBuffer -> 8
>>>              20: #getFileInfo -> 44
>>>              21: #syncBuildRecord -> 66
>>>              23: Connection -> 78
>>> ```
>>> As noted before, the saved_class_variable_info has value 23 which does, 
>>> indeed, reference Connection, my class name. 
>>>
>>> The problem occurs when I use the codeCache from the compilation on the 
>>> Isolate shown above on a different Isolate. The ScopeInfo heap object looks 
>>> largely identical to the first Isolate, but the local names hash table 
>>> looks like it's been rehashed (unsurprisingly):
>>> ```
>>> 0x27b95eb86f19: [NameToIndexHashTable]
>>>  - FixedArray length: 259
>>>  - elements: 79
>>>  - deleted: 0
>>>  - capacity: 128
>>>  - elements: {
>>>               0: #getTransactionId -> 51
>>>               1: #valueMatches -> 72
>>>               4: #allowRunJsScript -> 0
>>>               5: #call -> 32
>>>               6: #writeNumericParm -> 75
>>>               7: .brand -> 77
>>>               9: #sendResponse -> 59
>>>              10: #timeZone -> 29
>>>              11: #createFind -> 37
>>>              12: #updateRecords -> 71
>>>              13: #pendingImageFields -> 17
>>>              14: #syncSemaphore -> 28
>>>              15: #syncQueueLock -> 27
>>>              16: #find -> 39
>>>              17: Connection -> 78
>>>              18: #inBuffer -> 8
>>>              19: #getFindRecordTypeInfoSet -> 45
>>>              20: #getUpdateValue -> 49
>>>              21: #syncBuildRecord -> 66
>>>              24: #syncImagineFileObj -> 24
>>> ```
>>> Note that the class name Connection is now in slot 17 and slot 23 is 
>>> unused. So now, when we try to create the class ScopeInfo for a stack 
>>> trace, the 23 in saved_class_variable_info references an unused slot and I 
>>> get a seg fault or a failed DCHECK(isString(name)), depending on the type 
>>> of build.
>>>
>>> Unfortunately, the fix seems beyond my meager skills. It seems that in 
>>> deserialization for ScopeInfo, we would have to detect that we have a 
>>> saved_class_variable_info and so need to recalculate 
>>> saved_class_variable_info from the old value and the new hash table. But 
>>> I'm not sure we can control the order in which the local names hash table 
>>> and the ScopeInfo are deserialized and I'm not sure where in 
>>> deserialization one would check for the ScopeInfo. 
>>>
>>> Maybe someone more knowledgeable in the snapshot code could fix this 
>>> relatively easily, suggest a work-around, or tell me what I'm doing wrong?
>>>
>>> FWIW, this problem occurs for me on V8 13.1.139 and 13.6.233.2.
>>>
>>> Thanks in advance!
>>>
>> -- 
>> -- 
>> v8-users mailing list
>> v8-u...@googlegroups.com
>> http://groups.google.com/group/v8-users
>> --- 
>> You received this message because you are subscribed to the Google Groups 
>> "v8-users" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to v8-users+u...@googlegroups.com.
>> To view this discussion visit 
>> https://groups.google.com/d/msgid/v8-users/afbfdb4c-81ea-4ce1-b3fc-db5aaea8d6b2n%40googlegroups.com
>>  
>> <https://groups.google.com/d/msgid/v8-users/afbfdb4c-81ea-4ce1-b3fc-db5aaea8d6b2n%40googlegroups.com?utm_medium=email&utm_source=footer>
>> .
>>
>

-- 
-- 
v8-users mailing list
v8-users@googlegroups.com
http://groups.google.com/group/v8-users
--- 
You received this message because you are subscribed to the Google Groups 
"v8-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to v8-users+unsubscr...@googlegroups.com.
To view this discussion visit 
https://groups.google.com/d/msgid/v8-users/1254ba45-a2c8-4172-8b39-47a4aaa8ef56n%40googlegroups.com.

Reply via email to