@@ -506,7 +506,7 @@ var immediateQueue = L.create();
506
506
507
507
508
508
function processImmediate ( ) {
509
- var queue = immediateQueue ;
509
+ const queue = immediateQueue ;
510
510
var domain , immediate ;
511
511
512
512
immediateQueue = L . create ( ) ;
@@ -515,9 +515,13 @@ function processImmediate() {
515
515
immediate = L . shift ( queue ) ;
516
516
domain = immediate . domain ;
517
517
518
+ if ( ! immediate . _onImmediate )
519
+ continue ;
520
+
518
521
if ( domain )
519
522
domain . enter ( ) ;
520
523
524
+ immediate . _callback = immediate . _onImmediate ;
521
525
tryOnImmediate ( immediate , queue ) ;
522
526
523
527
if ( domain )
@@ -538,7 +542,8 @@ function processImmediate() {
538
542
function tryOnImmediate ( immediate , queue ) {
539
543
var threw = true ;
540
544
try {
541
- immediate . _onImmediate ( ) ;
545
+ // make the actual call outside the try/catch to allow it to be optimized
546
+ runCallback ( immediate ) ;
542
547
threw = false ;
543
548
} finally {
544
549
if ( threw && ! L . isEmpty ( queue ) ) {
@@ -552,67 +557,77 @@ function tryOnImmediate(immediate, queue) {
552
557
}
553
558
}
554
559
560
+ function runCallback ( timer ) {
561
+ const argv = timer . _argv ;
562
+ const argc = argv ? argv . length : 0 ;
563
+ switch ( argc ) {
564
+ // fast-path callbacks with 0-3 arguments
565
+ case 0 :
566
+ return timer . _callback ( ) ;
567
+ case 1 :
568
+ return timer . _callback ( argv [ 0 ] ) ;
569
+ case 2 :
570
+ return timer . _callback ( argv [ 0 ] , argv [ 1 ] ) ;
571
+ case 3 :
572
+ return timer . _callback ( argv [ 0 ] , argv [ 1 ] , argv [ 2 ] ) ;
573
+ // more than 3 arguments run slower with .apply
574
+ default :
575
+ return timer . _callback . apply ( timer , argv ) ;
576
+ }
577
+ }
555
578
556
- function Immediate ( ) { }
557
-
558
- Immediate . prototype . domain = undefined ;
559
- Immediate . prototype . _onImmediate = undefined ;
560
- Immediate . prototype . _idleNext = undefined ;
561
- Immediate . prototype . _idlePrev = undefined ;
562
579
580
+ function Immediate ( ) {
581
+ // assigning the callback here can cause optimize/deoptimize thrashing
582
+ // so have caller annotate the object (node v6.0.0, v8 5.0.71.35)
583
+ this . _idleNext = null ;
584
+ this . _idlePrev = null ;
585
+ this . _callback = null ;
586
+ this . _argv = null ;
587
+ this . _onImmediate = null ;
588
+ this . domain = process . domain ;
589
+ }
563
590
564
591
exports . setImmediate = function ( callback , arg1 , arg2 , arg3 ) {
565
592
if ( typeof callback !== 'function' ) {
566
593
throw new TypeError ( '"callback" argument must be a function' ) ;
567
594
}
568
595
569
596
var i , args ;
570
- var len = arguments . length ;
571
- var immediate = new Immediate ( ) ;
572
-
573
- L . init ( immediate ) ;
574
597
575
- switch ( len ) {
598
+ switch ( arguments . length ) {
576
599
// fast cases
577
600
case 0 :
578
601
case 1 :
579
- immediate . _onImmediate = callback ;
580
602
break ;
581
603
case 2 :
582
- immediate . _onImmediate = function ( ) {
583
- callback . call ( immediate , arg1 ) ;
584
- } ;
604
+ args = [ arg1 ] ;
585
605
break ;
586
606
case 3 :
587
- immediate . _onImmediate = function ( ) {
588
- callback . call ( immediate , arg1 , arg2 ) ;
589
- } ;
607
+ args = [ arg1 , arg2 ] ;
590
608
break ;
591
609
case 4 :
592
- immediate . _onImmediate = function ( ) {
593
- callback . call ( immediate , arg1 , arg2 , arg3 ) ;
594
- } ;
610
+ args = [ arg1 , arg2 , arg3 ] ;
595
611
break ;
596
612
// slow case
597
613
default :
598
- args = new Array ( len - 1 ) ;
599
- for ( i = 1 ; i < len ; i ++ )
614
+ args = [ arg1 , arg2 , arg3 ] ;
615
+ for ( i = 4 ; i < arguments . length ; i ++ )
616
+ // extend array dynamically, makes .apply run much faster in v6.0.0
600
617
args [ i - 1 ] = arguments [ i ] ;
601
-
602
- immediate . _onImmediate = function ( ) {
603
- callback . apply ( immediate , args ) ;
604
- } ;
605
618
break ;
606
619
}
620
+ // declaring it `const immediate` causes v6.0.0 to deoptimize this function
621
+ var immediate = new Immediate ( ) ;
622
+ immediate . _callback = callback ;
623
+ immediate . _argv = args ;
624
+ immediate . _onImmediate = callback ;
607
625
608
626
if ( ! process . _needImmediateCallback ) {
609
627
process . _needImmediateCallback = true ;
610
628
process . _immediateCallback = processImmediate ;
611
629
}
612
630
613
- if ( process . domain )
614
- immediate . domain = process . domain ;
615
-
616
631
L . append ( immediateQueue , immediate ) ;
617
632
618
633
return immediate ;
0 commit comments