Skip to content

Instantly share code, notes, and snippets.

@bjouhier
Last active December 17, 2015 05:08
Show Gist options
  • Save bjouhier/5555142 to your computer and use it in GitHub Desktop.
Save bjouhier/5555142 to your computer and use it in GitHub Desktop.
Demonstrates crash with V8 generators
function isGenerator(val) {
return Object.prototype.toString.call(val) === "[object Generator]";
}
var PENDING = {};
function run(fn, args, idx) {
var cb = args[idx],
g;
function resume(err, val) {
while (g) {
try {
val = err ? g.
throw (err) : g.send(val);
val = val.done ? undefined : val.value;
err = null;
// if we get PENDING, the current call completed with a pending I/O
// resume will be called again when the I/O completes. So just save the context and return here.
if (val === PENDING) {
return;
}
// if we get [PENDING, e, r], the current call invoked its callback synchronously
// we just loop to send/throw what the callback gave us.
if (val && val[0] === PENDING) {
err = val[1];
val = val[2];
}
// else, if g yielded a value which is not a generator, g is done.
// so we unwind it we send val to the parent generator (or through cb if we are at the top)
else if (!isGenerator(val)) {
//g.close();
g = g.prev;
}
// else, we got a new generator which means that g called another generator function
// the new generator become current and we loop with g.send(undefined) (equiv to g.next())
else {
val.prev = g;
g = val;
val = undefined;
}
} catch (ex) {
// the send/throw call failed.
// we unwind the current generator and we rethrow into the parent generator (or through cb if at the top)
//g.close();
g = g.prev;
err = makeError(ex);
val = undefined;
}
}
// we have exhausted the stack of generators.
// return the result or error through the callback.
try {
cb(err, val);
} catch (ex) {
trap(ex);
}
}
// set resume as the new callback
args[idx] = resume;
// call fn to get the initial generator
g = fn.apply(this, args);
// start the resume loop
resume();
}
function create(fn, idx) {
function F() {
//if (arguments[idx] == null) return future.call(this, F, arguments, idx);
return run.call(this, fn, arguments, idx);
};
// Memoize the original function for fast passing later
F.gstreamlineFunction = fn;
return F;
}
function invoke(that, fn, args, idx) {
// Resolve the function to be called
if (typeof fn !== 'function') {
if (typeof that === 'function' && that.gstreamlineFunction && fn === 'call') {
return that.gstreamlineFunction.apply(args[0], args.slice(1));
}
fn = that[fn];
}
// If we're waiting on a fstreamline.create function we can just call it directly instead
if (fn.gstreamlineFunction) return fn.gstreamlineFunction.apply(that, args);
// Set things up so that call returns:
// * PENDING if it completes with a pending I/O (and cb will be called later)
// * [PENDING, e, r] if the callback is called synchronously.
var result = PENDING,
sync = true;
var cb = args[idx];
args[idx] = function(e, r) {
if (sync) {
result = [PENDING, e, r];
} else {
cb(e, r);
}
}
fn.apply(that, args);
sync = false;
return result;
}
function fib(n) {
return n <= 1 ? 1 : fib(n - 1) + fib(n - 2);
}
var bench = create(function *bench(prefix, n, loop, modulo, asyncFn, _) {
var fibo_ = create(fibo, 0);
var count = 0;
function *fibo(_, nn) {
if (modulo && count++ % modulo === 0)(yield invoke(null, asyncFn, [_], 0));
if (nn <= 1) yield(1);
yield((yield fibo(_, nn - 1)) + (yield fibo(_, nn - 2)));
}
var expected = fib(n);
var t0 = Date.now();
for (var i = 0; i < loop; i++) {
var got = (yield fibo(_, n));
if (got !== expected) throw new Error("bench failed: got " + got + ', expected ' + expected);
}
var tabs = (prefix.length < 7) ? '\t\t' : '\t';
console.log(prefix + ':' + tabs + (Date.now() - t0) + "ms");
yield(count);
}, 5);
bench("generators", 25, 1, 3, setImmediate, function(err) {
if (err) throw err;
console.log("BENCH DONE");
})
@bjouhier
Copy link
Author

This example works ok on my macboook but if I change the 4th parameter from 3 to 1 or 2 in the bench call, I get a segmentation fault.

@bjouhier
Copy link
Author

Here is what I get with gdb:

(gdb) run --harmony junk/fiboCrash
Starting program: /usr/local/bin/node --harmony junk/fiboCrash
Reading symbols for shared libraries +++++++...................................................................................................................................... done

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x00000000000004a1
v8::internal::LinearSearch<(v8::internal::SearchMode)1, v8::internal::DescriptorArray> (array=0x18dc937517e1, name=0x49a, len=1178, valid_entries=7) at objects-inl.h:2154
2154    objects-inl.h: No such file or directory.
    in objects-inl.h
(gdb) where
#0  v8::internal::LinearSearch<(v8::internal::SearchMode)1, v8::internal::DescriptorArray> (array=0x18dc937517e1, name=0x49a, len=1178, valid_entries=7) at objects-inl.h:2154
#1  0x00000001002f6993 in v8::internal::Search<(v8::internal::SearchMode)1, v8::internal::DescriptorArray> () at objects-inl.h:2192
#2  0x00000001002f6993 in v8::internal::DescriptorArray::Search () at :2201
#3  0x00000001002f6993 in v8::internal::Map::LookupDescriptor (this=0x3bede4105f19, holder=0x18dc937517c1, name=0x49a, result=0x7fff5fbff430) at objects-inl.h:2154
#4  0x00000001002c3dc1 in v8::internal::PropertyDetails::type () at ../deps/v8/src/objects.cc:3100
#5  v8::internal::LookupResult::IsField () at :299
#6  0x00000001002c3dc1 in v8::internal::JSObject::LocalLookupRealNamedProperty (this=0x18dc937517c1, name=0xffffffff) at ../deps/v8/src/objects.cc:2154
#7  0x00000001002ccaf2 in v8::internal::LookupResult::IsFound () at :5506
#8  0x00000001002ccaf2 in v8::internal::JSReceiver::LocalLookup (this=0x18dc937517c1, name=0x49a) at ../deps/v8/src/objects.cc:2154
#9  0x00000001002c1a50 in v8::internal::LookupResult::IsFound () at :5524
#10 v8::internal::JSReceiver::Lookup () at :5525
#11 0x00000001002c1a50 in v8::internal::Object::Lookup (this=<value temporarily unavailable, due to optimizations>, name=0x49a, result=0x7fff5fbff430) at ../deps/v8/src/objects.cc:2154
#12 0x000000010025de1e in v8::internal::LookupResult::IsInterceptor () at :451
#13 0x000000010025de1e in LookupForRead (lookup=0x7fff5fbff430) at ../deps/v8/src/ic.cc:2154
#14 0x000000010025eefe in v8::internal::LookupResult::IsFound () at :928
#15 0x000000010025eefe in v8::internal::LoadIC::Load (this=0x7fff5fbff518, state=v8::internal::UNINITIALIZED) at ../deps/v8/src/ic.cc:2154
#16 0x0000000100263507 in __RT_impl_LoadIC_Miss [inlined] () at :2169
#17 0x0000000100263507 in v8::internal::LoadIC_Miss () at ../deps/v8/src/ic.cc:2154
#18 0x00003fe0b0f0616e in ?? ()
#19 0x00003fe0b0f16a9f in ?? ()
#20 0x00003fe0b0f71343 in ?? ()
#21 0x00003fe0b0f70dc2 in ?? ()
#22 0x00003fe0b0f77591 in ?? ()
#23 0x00003fe0b0f0c374 in ?? ()
#24 0x00003fe0b0f83588 in ?? ()
#25 0x00003fe0b0f26604 in ?? ()
#26 0x00003fe0b0f077f7 in ?? ()
#27 0x00000001001adffa in Invoke (is_construct=<value temporarily unavailable, due to optimizations>, argc=0, args=0x0, has_pending_exception=0x7fff5fbff8a7) at ../deps/v8/src/execution.cc:119
#28 0x000000010014dc12 in v8::Function::Call (this=0x10204b290, argc=0, argv=0x0) at ../deps/v8/src/api.cc:4044
#29 0x0000000100007309 in node::MakeCallback (argc=0, argv=0x0) at ../src/node.cc:1021
#30 0x0000000100007420 in node::MakeCallback (argc=<value temporarily unavailable, due to optimizations>, argv=<value temporarily unavailable, due to optimizations>) at ../src/node.cc:1057
#31 0x000000010000c1fa in CheckImmediate (handle=<value temporarily unavailable, due to optimizations>, status=<value temporarily unavailable, due to optimizations>) at ../src/node.cc:228
#32 0x000000010012f6e1 in uv__run_check (loop=<value temporarily unavailable, due to optimizations>) at ../deps/uv/src/unix/loop-watcher.c:63
#33 0x000000010012bf03 in uv__run_closing_handles [inlined] () at :315
#34 0x000000010012bf03 in uv_run (loop=0x100737930, mode=<value temporarily unavailable, due to optimizations>) at ../deps/uv/src/unix/core.c:2154
#35 0x000000010000bec1 in node::Start (argc=3, argv=0x100c0ec00) at ../src/node.cc:3167
#36 0x0000000100001574 in start ()

@wingo
Copy link

wingo commented May 13, 2013

I've filed down the test case: http://code.google.com/p/v8/issues/detail?id=2681

@wingo
Copy link

wingo commented May 13, 2013

Fixed, and updated my node mirror. Thanks for the report. If you find something else, please use v8's issue tracker; thanks :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment