public
Rubygem
Description: Johnson wraps JavaScript in a loving Ruby embrace.
Homepage: http://github.com/jbarnette/johnson/wikis
Clone URL: git://github.com/jbarnette/johnson.git
Don't call Ruby from gc_callback when Ruby's GCing.
matthewd (author)
Mon Sep 15 19:28:29 -0700 2008
commit  1dee0d1756ad0fc61792b96712b3fcf9f0b9ce32
tree    66af7688c3b5b20dae6baa2e4b17e56ce14209a6
parent  0e7dc2b6ba187a55e5da58787ae173075b4f14cb
...
5
6
7
 
 
8
9
10
...
90
91
92
 
93
94
95
96
97
 
98
99
100
...
5
6
7
8
9
10
11
12
...
92
93
94
95
96
97
98
99
100
101
102
103
104
0
@@ -5,6 +5,8 @@
0
 #include "idhash.h"
0
 #include "jsdbgapi.h"
0
 
0
+extern int gc_phase;
0
+
0
 // callback for JS_SetErrorReporter
0
 static void report_js_error(JSContext* js, const char* message, JSErrorReport* UNUSED(report))
0
 {
0
@@ -90,11 +92,13 @@ initialize_native(VALUE self, VALUE rb_runtime, VALUE UNUSED(options))
0
 ///////////////////////////////////////////////////////////////////////////
0
 
0
 static void deallocate(JohnsonContext *context) {
0
+ ENTER_GC_PHASE;
0
   JS_SetContextPrivate(context->js, 0);
0
   /*
0
   JS_DestroyContext(context->js);
0
   free(context);
0
   */
0
+ LEAVE_GC_PHASE;
0
 }
0
 
0
 static VALUE allocate(VALUE klass)
...
1
2
3
 
 
4
5
6
...
447
448
449
 
 
450
451
452
...
463
464
465
 
 
466
467
468
...
1
2
3
4
5
6
7
8
...
449
450
451
452
453
454
455
456
...
467
468
469
470
471
472
473
474
0
@@ -1,6 +1,8 @@
0
 #include "ruby_land_proxy.h"
0
 #include "conversions.h"
0
 
0
+extern int gc_phase;
0
+
0
 DECLARE_RUBY_WRAPPER(rb_call_super, int argc; const VALUE* argv)
0
 DEFINE_RUBY_WRAPPER(rb_call_super, rb_call_super, ARGLIST2(argc, argv))
0
 
0
@@ -447,6 +449,8 @@ static VALUE to_s(VALUE self)
0
 
0
 static void finalize(RubyLandProxy* proxy)
0
 {
0
+ ENTER_GC_PHASE;
0
+
0
   // could get finalized after the context has been freed
0
   if (proxy->runtime && proxy->runtime->jsids)
0
   {
0
@@ -463,6 +467,8 @@ static void finalize(RubyLandProxy* proxy)
0
   }
0
 
0
   free(proxy);
0
+
0
+ LEAVE_GC_PHASE;
0
 }
0
 
0
 bool ruby_value_is_proxy(VALUE maybe_proxy)
...
6
7
8
 
 
9
10
11
...
217
218
219
 
 
220
221
222
...
240
241
242
243
 
244
245
246
...
270
271
272
273
274
 
 
275
276
277
278
 
 
 
 
 
279
280
281
282
283
284
 
 
285
286
287
...
6
7
8
9
10
11
12
13
...
219
220
221
222
223
224
225
226
...
244
245
246
 
247
248
249
250
...
274
275
276
 
 
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
0
@@ -6,6 +6,8 @@
0
 #include "jroot.h"
0
 #include "ruby_land_proxy.h"
0
 
0
+extern int gc_phase;
0
+
0
 /*
0
  * call-seq:
0
  * global
0
@@ -217,6 +219,8 @@ JSBool gc_callback(JSContext *context, JSGCStatus status)
0
 {
0
   if(status == JSGC_BEGIN) {
0
     VALUE ruby_runtime = (VALUE)JS_GetRuntimePrivate(JS_GetRuntime(context));
0
+ if(gc_phase > 0)
0
+ return JS_FALSE;
0
     if(rb_funcall(ruby_runtime, rb_intern("should_sm_gc?"), 0) == Qtrue)
0
       return JS_TRUE;
0
   }
0
@@ -240,7 +244,7 @@ initialize_native(VALUE self, VALUE UNUSED(options))
0
     JSContext* context = johnson_get_current_context(runtime);
0
     if(
0
         (runtime->global = JS_GetGlobalObject(context))
0
- && (JS_AddNamedRoot(context, &(runtime->global), "runtime->global"))
0
+ && (JS_AddNamedRootRT(runtime->js, &(runtime->global), "runtime->global"))
0
     ) {
0
       return self;
0
     }
0
@@ -270,18 +274,25 @@ JSContext* johnson_get_current_context(JohnsonRuntime * runtime)
0
 
0
 static void deallocate(JohnsonRuntime* runtime)
0
 {
0
- JS_RemoveRoot(johnson_get_current_context(runtime), &(runtime->global));
0
-
0
+ ENTER_GC_PHASE;
0
+
0
   JSContext *context = NULL;
0
   JSContext *iterator = NULL;
0
 
0
   while ((context = JS_ContextIterator(runtime->js, &iterator)) != NULL) {
0
+ if (runtime->global) {
0
+ JS_RemoveRootRT(runtime->js, &(runtime->global));
0
+ runtime->global = NULL;
0
+ }
0
+
0
     JS_DestroyContext(iterator);
0
     iterator = NULL;
0
   }
0
   
0
   JS_DestroyRuntime(runtime->js);
0
   free(runtime);
0
+
0
+ LEAVE_GC_PHASE;
0
 }
0
 
0
 static VALUE allocate(VALUE klass)
...
4
5
6
 
 
7
8
9
...
4
5
6
7
8
9
10
11
0
@@ -4,6 +4,8 @@
0
 #include "debugger.h"
0
 #include "immutable_node.h"
0
 
0
+int gc_phase = 0;
0
+
0
 void Init_spidermonkey()
0
 {
0
   VALUE johnson = rb_define_module("Johnson"); // FIXME: this belongs outside the extension
...
26
27
28
 
 
 
29
...
26
27
28
29
30
31
32
0
@@ -26,4 +26,7 @@
0
 # endif
0
 #endif
0
 
0
+#define ENTER_GC_PHASE do { gc_phase++; } while(0)
0
+#define LEAVE_GC_PHASE do { gc_phase--; } while(0)
0
+
0
 #endif

Comments

    No one has commented yet.