506
507 *vp = *lvp;
508 return (0);
509 }
510
511 extern "C" void
512 v8plus_jsfunc_hold(v8plus_jsfunc_t f)
513 {
514 v8::Persistent<v8::Function> pfh;
515 std::unordered_map<uint64_t, cb_hdl_t>::iterator it;
516
517 if ((it = cbhash.find(f)) == cbhash.end())
518 v8plus_panic("callback hash tag %llu not found", f);
519
520 if (!it->second.ch_persist) {
521 pfh = v8::Persistent<v8::Function>::New(it->second.ch_hdl);
522 it->second.ch_hdl = pfh;
523 it->second.ch_persist = _B_TRUE;
524 }
525 ++it->second.ch_refs;
526 }
527
528 extern "C" void
529 v8plus_jsfunc_rele_direct(v8plus_jsfunc_t f)
530 {
531 v8::Local<v8::Function> lfh;
532 std::unordered_map<uint64_t, cb_hdl_t>::iterator it;
533
534 if ((it = cbhash.find(f)) == cbhash.end())
535 v8plus_panic("callback hash tag %llu not found", f);
536
537 if (it->second.ch_refs == 0)
538 v8plus_panic("releasing unheld callback hash tag %llu", f);
539
540 if (--it->second.ch_refs == 0) {
541 if (it->second.ch_persist) {
542 v8::Persistent<v8::Function> pfh(it->second.ch_hdl);
543 pfh.Dispose();
544 }
545 cbhash.erase(it);
546 }
547 }
548
549 static size_t
550 library_name(const char *base, const char *version, char *buf, size_t len)
551 {
552 #ifdef __MACH__
553 return (snprintf(buf, len, "lib%s.%s%sdylib", base,
554 version ? version : "", version ? "." : ""));
555 #else
556 return (snprintf(buf, len, "lib%s.so%s%s", base,
557 version ? "." : "", version ? version : ""));
558 #endif
559 }
560
561 /*
562 * This is really gross: we need to free up JS function slots when then list
563 * is freed, but there's no way for us to know that's happening. So we
564 * interpose on nvlist_free() here, checking for function slots to free iff
565 * this is a list that has a V8 JS function handle in it. Lists created by
566 * someone else, even if they have uint64 arrays in them, are passed through.
620 extern "C" int
621 nvpair_value_v8plus_jsfunc(const nvpair_t *pp, v8plus_jsfunc_t *vp)
622 {
623 uint64_t *lvp;
624 uint_t nv;
625 int err;
626
627 if ((err = nvpair_value_uint64_array((nvpair_t *)pp, &lvp, &nv)) != 0)
628 return (err);
629
630 *vp = *lvp;
631
632 return (0);
633 }
634
635 extern "C" void
636 v8plus_obj_hold(const void *cop)
637 {
638 v8plus::ObjectWrap *op = v8plus::ObjectWrap::objlookup(cop);
639 op->public_Ref();
640 }
641
642 extern "C" void
643 v8plus_obj_rele_direct(const void *cop)
644 {
645 v8plus::ObjectWrap *op = v8plus::ObjectWrap::objlookup(cop);
646 op->public_Unref();
647 }
|
506
507 *vp = *lvp;
508 return (0);
509 }
510
511 extern "C" void
512 v8plus_jsfunc_hold(v8plus_jsfunc_t f)
513 {
514 v8::Persistent<v8::Function> pfh;
515 std::unordered_map<uint64_t, cb_hdl_t>::iterator it;
516
517 if ((it = cbhash.find(f)) == cbhash.end())
518 v8plus_panic("callback hash tag %llu not found", f);
519
520 if (!it->second.ch_persist) {
521 pfh = v8::Persistent<v8::Function>::New(it->second.ch_hdl);
522 it->second.ch_hdl = pfh;
523 it->second.ch_persist = _B_TRUE;
524 }
525 ++it->second.ch_refs;
526
527 /*
528 * If the consumer puts a hold on a callback, we should also put a hold
529 * on the V8 event loop to prevent it dematerialising beneath us.
530 */
531 v8plus_eventloop_hold();
532 }
533
534 extern "C" void
535 v8plus_jsfunc_rele_direct(v8plus_jsfunc_t f)
536 {
537 v8::Local<v8::Function> lfh;
538 std::unordered_map<uint64_t, cb_hdl_t>::iterator it;
539
540 if ((it = cbhash.find(f)) == cbhash.end())
541 v8plus_panic("callback hash tag %llu not found", f);
542
543 if (it->second.ch_refs == 0)
544 v8plus_panic("releasing unheld callback hash tag %llu", f);
545
546 if (--it->second.ch_refs == 0) {
547 if (it->second.ch_persist) {
548 v8::Persistent<v8::Function> pfh(it->second.ch_hdl);
549 pfh.Dispose();
550 }
551 cbhash.erase(it);
552 }
553
554 /*
555 * Release the event loop hold we took in v8plus_jsfunc_hold():
556 */
557 v8plus_eventloop_rele_direct();
558 }
559
560 static size_t
561 library_name(const char *base, const char *version, char *buf, size_t len)
562 {
563 #ifdef __MACH__
564 return (snprintf(buf, len, "lib%s.%s%sdylib", base,
565 version ? version : "", version ? "." : ""));
566 #else
567 return (snprintf(buf, len, "lib%s.so%s%s", base,
568 version ? "." : "", version ? version : ""));
569 #endif
570 }
571
572 /*
573 * This is really gross: we need to free up JS function slots when then list
574 * is freed, but there's no way for us to know that's happening. So we
575 * interpose on nvlist_free() here, checking for function slots to free iff
576 * this is a list that has a V8 JS function handle in it. Lists created by
577 * someone else, even if they have uint64 arrays in them, are passed through.
631 extern "C" int
632 nvpair_value_v8plus_jsfunc(const nvpair_t *pp, v8plus_jsfunc_t *vp)
633 {
634 uint64_t *lvp;
635 uint_t nv;
636 int err;
637
638 if ((err = nvpair_value_uint64_array((nvpair_t *)pp, &lvp, &nv)) != 0)
639 return (err);
640
641 *vp = *lvp;
642
643 return (0);
644 }
645
646 extern "C" void
647 v8plus_obj_hold(const void *cop)
648 {
649 v8plus::ObjectWrap *op = v8plus::ObjectWrap::objlookup(cop);
650 op->public_Ref();
651
652 /*
653 * If the consumer puts a hold on an object, we should also put a hold
654 * on the V8 event loop to prevent it dematerialising beneath us.
655 */
656 v8plus_eventloop_hold();
657 }
658
659 extern "C" void
660 v8plus_obj_rele_direct(const void *cop)
661 {
662 v8plus::ObjectWrap *op = v8plus::ObjectWrap::objlookup(cop);
663 op->public_Unref();
664
665 /*
666 * Release the event loop hold we took in v8plus_obj_hold():
667 */
668 v8plus_eventloop_rele_direct();
669 }
|