Tracing object properties from HiddenClass

33 views
Skip to first unread message

Filip Petronijevic

unread,
Nov 9, 2022, 9:19:19 AM11/9/22
to v8-users
Ok, I'll explain what problem I have and if there is any way of solving it.

Imagine I have following Javascript code:

var obj1=  {}
obj1["mainkey"] = {canvasComputed: "oewrewqioewrerqewjoijiqerw", todata: "somerandomdata"}

var obj2=  {}
obj2["mainkey"] = "some big string"

var obj3 = {}
obj3['mainkey'] = {test: {test1:"somestring"}, test2: 3432}


I have 3 objects, they all share same Map. My question is if I know what memory space this Map has, If I can use that to recursively find all property values of all objects that share that same Map? In this case to list obj1's property values (canvasComputed, toData), obj2 property values (1 string) and obj3  property   values(test object along with string test2) ?

Or the only way I can list own properties of these objects is if I know exact memory location of each of them? Is there any way I could traverse from their Map or something they share in common (only mainkey key) and use this fact to find all property values that hold mainkey as a key?


When I do %DebugPrint(obj1) I can see its property values and that this object shares same map as other objects, but I'm trying to find a way to generalize this by starting from some common memory slot they all share and traverse up recursively or whatever to get all property values?

Best regards



Jakob Kummerow

unread,
Nov 11, 2022, 5:47:33 AM11/11/22
to v8-u...@googlegroups.com
Maps don't keep lists of the objects that use them. To find all objects that use a given map, you'd have to walk the entire heap to find all objects, and filter them by map.

Considering your previous question, I'm not sure finding all objects that use a given map will actually be helpful. A possible way to intercept creation of properties with a given name (e.g. "mainkey") would be to run with `--nouse-ic` and put a breakpoint on StoreIC::Store(). This is (obviously?) not an officially supported feature, and I haven't tried it, so you may encounter obstacles or limitations of the approach, but it might at least get you a little further.

I guess you'd need this in Chrome, not just d8, so the full workflow is:
- build a Debug build of Chrome. Be sure to set v8_optimized_debug = false in args.gn beforehand.
- run with each renderer in a debugger: out/debug/chrome --no-sandbox --disable-hang-monitor --disable-extensions --js-flags="--nouse-ic" --renderer-cmd-prefix="xterm -e gdb -args"
- bring a large amount of patience to both of these steps, and have enough RAM in your machine (64GB is good, dunno if 32GB is enough)

Good luck!

Filip Petronijevic

unread,
Nov 11, 2022, 5:56:07 AM11/11/22
to v8-users

Thanks! I found this StoreIC::Store() function just yesterday while debugging in D8 and it works even without (--nouse-ic flag), even though I have no clue what this flag does as I can't find it in docs. But this tracks all of the keys and objects created.


When I cast this object (value) into JSObject and do shortPrint or PrintProperties() it doesn't take in account all properties if for example its recursive object like this test: {test1: { test2: "testhelloworld" } } but rather it prints just test and gives memory lolcation to test1. I can obviously recursively do this, but is there any prittier way of doing this like via some JSON stringify function? 

I found such JSON stringify function here https://source.chromium.org/chromium/chromium/src/+/main:v8/src/json/json-stringifier.h;bpv=1;bpt=0 but I have very hard trouble in passing arguments to this function and printing String out of it as it return MaybeHandle object. Any help here would be appreciated.

Jakob Kummerow

unread,
Nov 11, 2022, 6:26:52 AM11/11/22
to v8-u...@googlegroups.com
Thanks! I found this StoreIC::Store() function just yesterday while debugging in D8 and it works even without (--nouse-ic flag), even though I have no clue what this flag does as I can't find it in docs. But this tracks all of the keys and objects created.

No, it won't catch all of them without the flag, but if it catches the ones you care about, that's good enough.
 

When I cast this object (value) into JSObject and do shortPrint or PrintProperties() it doesn't take in account all properties if for example its recursive object like this test: {test1: { test2: "testhelloworld" } } but rather it prints just test and gives memory lolcation to test1. I can obviously recursively do this, but is there any prittier way of doing this like via some JSON stringify function? 

I'd just inspect objects manually, using the `job` macro from tools/gdbinit.
 
I found such JSON stringify function here https://source.chromium.org/chromium/chromium/src/+/main:v8/src/json/json-stringifier.h;bpv=1;bpt=0 but I have very hard trouble in passing arguments to this function and printing String out of it as it return MaybeHandle object. Any help here would be appreciated.

Appending `.ToHandleChecked()` may be of use here (if the stringification doesn't throw), but yeah, invoking such functions in GDB tends to not work.
 
On Friday, November 11, 2022 at 11:47:33 AM UTC+1 Jakob Kummerow wrote:
Maps don't keep lists of the objects that use them. To find all objects that use a given map, you'd have to walk the entire heap to find all objects, and filter them by map.

Considering your previous question, I'm not sure finding all objects that use a given map will actually be helpful. A possible way to intercept creation of properties with a given name (e.g. "mainkey") would be to run with `--nouse-ic` and put a breakpoint on StoreIC::Store(). This is (obviously?) not an officially supported feature, and I haven't tried it, so you may encounter obstacles or limitations of the approach, but it might at least get you a little further.

I guess you'd need this in Chrome, not just d8, so the full workflow is:
- build a Debug build of Chrome. Be sure to set v8_optimized_debug = false in args.gn beforehand.
- run with each renderer in a debugger: out/debug/chrome --no-sandbox --disable-hang-monitor --disable-extensions --js-flags="--nouse-ic" --renderer-cmd-prefix="xterm -e gdb -args"
- bring a large amount of patience to both of these steps, and have enough RAM in your machine (64GB is good, dunno if 32GB is enough)

Good luck!


On Wed, Nov 9, 2022 at 3:19 PM Filip Petronijevic <fpetronij...@raf.rs> wrote:
Ok, I'll explain what problem I have and if there is any way of solving it.

Imagine I have following Javascript code:

var obj1=  {}
obj1["mainkey"] = {canvasComputed: "oewrewqioewrerqewjoijiqerw", todata: "somerandomdata"}

var obj2=  {}
obj2["mainkey"] = "some big string"

var obj3 = {}
obj3['mainkey'] = {test: {test1:"somestring"}, test2: 3432}


I have 3 objects, they all share same Map. My question is if I know what memory space this Map has, If I can use that to recursively find all property values of all objects that share that same Map? In this case to list obj1's property values (canvasComputed, toData), obj2 property values (1 string) and obj3  property   values(test object along with string test2) ?

Or the only way I can list own properties of these objects is if I know exact memory location of each of them? Is there any way I could traverse from their Map or something they share in common (only mainkey key) and use this fact to find all property values that hold mainkey as a key?


When I do %DebugPrint(obj1) I can see its property values and that this object shares same map as other objects, but I'm trying to find a way to generalize this by starting from some common memory slot they all share and traverse up recursively or whatever to get all property values?

Best regards

--
--
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 on the web visit https://groups.google.com/d/msgid/v8-users/e46c2e2e-f6ab-43d2-8682-7c7759f3fb04n%40googlegroups.com.

Filip Petronijevic

unread,
Nov 11, 2022, 7:15:54 AM11/11/22
to v8-u...@googlegroups.com
I treced down 'job' macro from tools/gdbinit and I found out it calls in the end https://source.chromium.org/chromium/chromium/src/+/main:v8/src/objects/objects.h;drc=a0dedabb214a245c792009e64baf333c7e8d7357;l=679

which is shortPrint. This still doesn't show me all level depths of an object but rather first levels of representation and their corresponding addresses. Do I have to manually go in these recursive depths or is there any better way like to Stringify it? I'm trying to Stringify this value object located in https://source.chromium.org/chromium/chromium/src/+/main:v8/src/ic/ic.cc;l=1847;bpv=1;bpt=0?q=ic.cc&ss=chromium%2Fchromium%2Fsrc:v8%2F
but I have hard times converting it to a String

Jakob Kummerow

unread,
Nov 11, 2022, 8:49:09 AM11/11/22
to v8-u...@googlegroups.com
On Fri, Nov 11, 2022 at 1:15 PM Filip Petronijevic <fpetronij...@raf.rs> wrote:
I treced down 'job' macro from tools/gdbinit and I found out it calls in the end https://source.chromium.org/chromium/chromium/src/+/main:v8/src/objects/objects.h;drc=a0dedabb214a245c792009e64baf333c7e8d7357;l=679

which is shortPrint. This still doesn't show me all level depths of an object but rather first levels of representation and their corresponding addresses.

Yes.
 
Do I have to manually go in these recursive depths or is there any better way like to Stringify it? I'm trying to Stringify this value object located in https://source.chromium.org/chromium/chromium/src/+/main:v8/src/ic/ic.cc;l=1847;bpv=1;bpt=0?q=ic.cc&ss=chromium%2Fchromium%2Fsrc:v8%2F
but I have hard times converting it to a String

I don't know of a JSON.stringify equivalent for use in GDB. As I said, I'd inspect objects manually, level by level. If you find that you're spending too much time doing that, you could build your own tooling, e.g. a function that has a similar entry point as _v8_internal_Print_Object and internally wraps JsonStringify() and printf()s the result to stdout.

Filip Petronijevic

unread,
Nov 11, 2022, 3:02:17 PM11/11/22
to v8-users
Thank you for the reply. I have one very weird problem (not sure if its a bug).
I ran Chromium with arguments you told me and args.gn setup and when I run this code 

var obj143 = {};
obj143["test"] = {test: 1, test2: 2, test3: 3};

var obj221 = {};
obj221["test"] = {test3: 14, test5: 23, test6: 322222};

var obj343 = {};
obj343["test"] = "test13"

For some weird reason the third "test" never gets printed and it never enters  StoreIC::Store() function nor Object::SetProperty. What is the reason for this? I print all keys that ever come in but third one never enters for some reason. I also hooked into SetProperty hoping it will go in there but it never does. Is there any other function I can hook where I can have a guarantee all property sets will go through?

Jakob Kummerow

unread,
Nov 14, 2022, 5:00:43 AM11/14/22
to v8-u...@googlegroups.com
Ah, looks like we can follow existing map transitions without entering ic.cc code.
Adding --nolazy-feedback-allocation should disable that.


--
--
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.
Reply all
Reply to author
Forward
0 new messages