@@ -60,7 +60,7 @@ function setupNextTick() {
6060 // Grab the constants necessary for working with internal arrays.
6161 const { kInit, kDestroy, kAsyncIdCounter } = async_wrap . constants ;
6262 const { async_id_symbol, trigger_async_id_symbol } = async_wrap ;
63- var nextTickQueue = new NextTickQueue ( ) ;
63+ const nextTickQueue = new NextTickQueue ( ) ;
6464 var microtasksScheduled = false ;
6565
6666 // Used to run V8's micro task queue.
@@ -99,7 +99,6 @@ function setupNextTick() {
9999 const microTasksTickObject = {
100100 callback : runMicrotasksCallback ,
101101 args : undefined ,
102- domain : null ,
103102 [ async_id_symbol ] : 0 ,
104103 [ trigger_async_id_symbol ] : 0
105104 } ;
@@ -125,35 +124,13 @@ function setupNextTick() {
125124 }
126125 }
127126
128- function _combinedTickCallback ( args , callback ) {
129- if ( args === undefined ) {
130- callback ( ) ;
131- } else {
132- switch ( args . length ) {
133- case 1 :
134- callback ( args [ 0 ] ) ;
135- break ;
136- case 2 :
137- callback ( args [ 0 ] , args [ 1 ] ) ;
138- break ;
139- case 3 :
140- callback ( args [ 0 ] , args [ 1 ] , args [ 2 ] ) ;
141- break ;
142- default :
143- callback ( ...args ) ;
144- }
145- }
146- }
147-
148127 // Run callbacks that have no domain.
149128 // Using domains will cause this to be overridden.
150129 function _tickCallback ( ) {
151130 do {
152131 while ( tickInfo [ kIndex ] < tickInfo [ kLength ] ) {
153132 ++ tickInfo [ kIndex ] ;
154133 const tock = nextTickQueue . shift ( ) ;
155- const callback = tock . callback ;
156- const args = tock . args ;
157134
158135 // CHECK(Number.isSafeInteger(tock[async_id_symbol]))
159136 // CHECK(tock[async_id_symbol] > 0)
@@ -173,10 +150,11 @@ function setupNextTick() {
173150 if ( async_hook_fields [ kDestroy ] > 0 )
174151 emitDestroy ( tock [ async_id_symbol ] ) ;
175152
176- // Using separate callback execution functions allows direct
177- // callback invocation with small numbers of arguments to avoid the
178- // performance hit associated with using `fn.apply()`
179- _combinedTickCallback ( args , callback ) ;
153+ const callback = tock . callback ;
154+ if ( tock . args === undefined )
155+ callback ( ) ;
156+ else
157+ Reflect . apply ( callback , undefined , tock . args ) ;
180158
181159 emitAfter ( tock [ async_id_symbol ] ) ;
182160
@@ -191,11 +169,21 @@ function setupNextTick() {
191169
192170 class TickObject {
193171 constructor ( callback , args , asyncId , triggerAsyncId ) {
172+ // this must be set to null first to avoid function tracking
173+ // on the hidden class, revisit in V8 versions after 6.2
174+ this . callback = null ;
194175 this . callback = callback ;
195176 this . args = args ;
196- this . domain = process . domain || null ;
177+
197178 this [ async_id_symbol ] = asyncId ;
198179 this [ trigger_async_id_symbol ] = triggerAsyncId ;
180+
181+ if ( async_hook_fields [ kInit ] > 0 ) {
182+ emitInit ( asyncId ,
183+ 'TickObject' ,
184+ triggerAsyncId ,
185+ this ) ;
186+ }
199187 }
200188 }
201189
@@ -220,13 +208,14 @@ function setupNextTick() {
220208 args [ i - 1 ] = arguments [ i ] ;
221209 }
222210
223- const asyncId = ++ async_id_fields [ kAsyncIdCounter ] ;
224- const triggerAsyncId = initTriggerId ( ) ;
225- const obj = new TickObject ( callback , args , asyncId , triggerAsyncId ) ;
226- nextTickQueue . push ( obj ) ;
211+ // In V8 6.2, moving tickInfo & async_id_fields[kAsyncIdCounter] into the
212+ // TickObject incurs a significant performance penalty in the
213+ // next-tick-breadth-args benchmark (revisit later)
227214 ++ tickInfo [ kLength ] ;
228- if ( async_hook_fields [ kInit ] > 0 )
229- emitInit ( asyncId , 'TickObject' , triggerAsyncId , obj ) ;
215+ nextTickQueue . push ( new TickObject ( callback ,
216+ args ,
217+ ++ async_id_fields [ kAsyncIdCounter ] ,
218+ initTriggerId ( ) ) ) ;
230219 }
231220
232221 // `internalNextTick()` will not enqueue any callback when the process is
@@ -240,10 +229,6 @@ function setupNextTick() {
240229 if ( process . _exiting )
241230 return ;
242231
243- if ( triggerAsyncId === null ) {
244- triggerAsyncId = async_hooks . initTriggerId ( ) ;
245- }
246-
247232 var args ;
248233 switch ( arguments . length ) {
249234 case 2 : break ;
@@ -256,11 +241,15 @@ function setupNextTick() {
256241 args [ i - 2 ] = arguments [ i ] ;
257242 }
258243
259- const asyncId = ++ async_id_fields [ kAsyncIdCounter ] ;
260- const obj = new TickObject ( callback , args , asyncId , triggerAsyncId ) ;
261- nextTickQueue . push ( obj ) ;
244+ if ( triggerAsyncId === null )
245+ triggerAsyncId = initTriggerId ( ) ;
246+ // In V8 6.2, moving tickInfo & async_id_fields[kAsyncIdCounter] into the
247+ // TickObject incurs a significant performance penalty in the
248+ // next-tick-breadth-args benchmark (revisit later)
262249 ++ tickInfo [ kLength ] ;
263- if ( async_hook_fields [ kInit ] > 0 )
264- emitInit ( asyncId , 'TickObject' , triggerAsyncId , obj ) ;
250+ nextTickQueue . push ( new TickObject ( callback ,
251+ args ,
252+ ++ async_id_fields [ kAsyncIdCounter ] ,
253+ triggerAsyncId ) ) ;
265254 }
266255}
0 commit comments