Re: [v8-users] Variable in global JS scope being garbage collected?

45 views
Skip to first unread message

Jochen Eisinger

unread,
Mar 24, 2016, 2:51:30 AM3/24/16
to v8-users

It looks like mesh is collected, not root. How does root keep mesh alive?


On Wed, Mar 23, 2016, 9:20 PM Scott Duensing <scott.d...@gmail.com> wrote:
I've been working on a game engine and using V8 as the embedded language.  Everything has been going fairly well, using SWIG to wrap native C++ classes for use in JS.

Until today.

My test code creates a triangle in JavaScript and sends it to the engine to be rendered.  It works.  For about 5 seconds.  Then the 'root' object of my scene gets garbage collected by V8 and I'm not sure why.  I set a breakpoint when the object is destroyed and captured a stack trace:

0    ComponentMesh::~ComponentMesh    componentMesh.cpp    18    0x4cd39e
1    ComponentMesh::~ComponentMesh    componentMesh.cpp    19    0x4cd472
2    _wrap_delete_ComponentMesh    componentMesh_wrap.cpp    1788    0x435c46
3    v8::internal::GlobalHandles::Node::PostGarbageCollectionProcessing(v8::internal::Isolate *)            0x6a7fee
4    v8::internal::GlobalHandles::PostScavengeProcessing(int)            0x6a7e75
5    v8::internal::GlobalHandles::PostGarbageCollectionProcessing(v8::internal::GarbageCollector, v8::GCCallbackFlags)            0x6a86ba
6    v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags)            0x6afa77
7    v8::internal::Heap::CollectGarbage(v8::internal::GarbageCollector, const char *, const char *, v8::GCCallbackFlags)            0x6af054
8    v8::internal::Factory::NewRawOneByteString(int, v8::internal::PretenureFlag)            0x68677d
9    v8::internal::Factory::NewStringFromUtf8(v8::internal::Vector<char const>, v8::internal::PretenureFlag)            0x686bb0
10    v8::String::NewFromUtf8(v8::Isolate *, const char *, v8::NewStringType, int)            0x4d00ea
11    ScriptInstance::update    scriptInstance.cpp    179    0x41d744
12    Scripting::update    scripting.cpp    219    0x41609c
13    main    main.cpp    70    0x4b2331



As you can see, my scripting system calls update() in the JS code which should call render() back in the engine.  Except the mesh is being GCed before that happens.  The JS is:

"use strict";

var root;

function startup(scriptId) {
   
var mesh = new ComponentMesh("triangle");
    mesh
.addVertex(new Vertex(-1.0, -1.0, 0.0));
    mesh
.addVertex(new Vertex( 1.0, -1.0, 0.0));
    mesh
.addVertex(new Vertex( 0.0,  1.0, 0.0));
    mesh
.addIndex(0);
    mesh
.addIndex(1);
    mesh
.addIndex(2);

    root
= new Entity("root");
    root
.addComponent(mesh);
}

function update(delta, event) {
   
Engine.render(root);
}

function shutdown() {
}


Why is 'root' being GCed?  The context for this script is Persistent<> and I don't call Destroy()/Reset().

The entire codebase is available to browse at http://skunkworks.kangaroopunch.com/projects/magrathea/repository

Help?  Please?  Thanks!


Scott


--
--
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.
For more options, visit https://groups.google.com/d/optout.

Louis Santillan

unread,
Mar 24, 2016, 4:48:09 AM3/24/16
to v8-u...@googlegroups.com
I agree with Jochen. Looks like ~ComponentMesh is being called by gc.

Scott Duensing

unread,
Mar 28, 2016, 11:09:34 AM3/28/16
to v8-users
You're right, of course.  I figured this out as soon as I posted.  Doh! 

Which brings up the next question...

What's the *proper* way to keep 'mesh' alive?  I hate to keep a global JS variable for everything I create from the C++ side.  I also hate to pass copies of objects when a pointer is really what I want.


Scott

Jochen Eisinger

unread,
Mar 29, 2016, 5:27:13 AM3/29/16
to v8-users
The C++ class corresponding to Engine should have a v8::Global that references the JS representation of the ComponentMesh. That way, the Engine will keep the ComponentMesh alive as long as the C++ side is alive.

Note that this will potentially create a cycle through C++ which V8's GC cannot detect: C++ Engine - (via v8::Global) -> mesh -> creation context -> root - (via another global handle) -> C++ Engine, and you will have to manually break this cycle for garbage collection to collect it.

Scott Duensing

unread,
Mar 29, 2016, 4:12:47 PM3/29/16
to v8-u...@googlegroups.com

Thank you!  I'll give it a go!

You received this message because you are subscribed to a topic in the Google Groups "v8-users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/v8-users/PYxVvgjAi24/unsubscribe.
To unsubscribe from this group and all its topics, send an email to v8-users+u...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages