1212/*jslint sub:true*/ /* The symbols 'fromWireType' and 'toWireType' must be accessed via array notation to be closure-safe since craftInvokerFunction crafts functions as strings that can't be closured. */
1313
1414// -- jshint doesn't understand library syntax, so we need to mark the symbols exposed here
15- /*global getStringOrSymbol, emval_handles, Emval, __emval_unregister, count_emval_handles, emval_symbols, __emval_decref*/
15+ /*global getStringOrSymbol, emval_freelist, emval_handles, Emval, __emval_unregister, count_emval_handles, emval_symbols, __emval_decref*/
1616/*global emval_addMethodCaller, emval_methodCallers, addToLibrary, global, emval_lookupTypes, makeLegalFunctionName*/
1717/*global emval_get_global*/
1818
19+ // Number of handles reserved for non-use (0) or common values w/o refcount.
20+ { { {
21+ globalThis . EMVAL_RESERVED_HANDLES = 5 ;
22+ globalThis . EMVAL_LAST_RESERVED_HANDLE = globalThis . EMVAL_RESERVED_HANDLES * 2 - 1 ;
23+ null ;
24+ } } }
1925var LibraryEmVal = {
20- $emval_handles__deps : [ '$HandleAllocator' ] ,
21- $emval_handles : "new HandleAllocator();" ,
26+ // Stack of handles available for reuse.
27+ $emval_freelist : [ ] ,
28+ // Array of alternating pairs (value, refcount).
29+ $emval_handles : [ ] ,
2230 $emval_symbols : { } , // address -> string
2331
2432 $init_emval__deps : [ '$count_emval_handles' , '$emval_handles' ] ,
2533 $init_emval__postset : 'init_emval();' ,
2634 $init_emval : ( ) => {
27- // reserve some special values. These never get de-allocated.
28- // The HandleAllocator takes care of reserving zero.
29- emval_handles . allocated . push (
30- { value : undefined } ,
31- { value : null } ,
32- { value : true } ,
33- { value : false } ,
35+ // reserve 0 and some special values. These never get de-allocated.
36+ emval_handles . push (
37+ 0 , 1 ,
38+ undefined , 1 ,
39+ null , 1 ,
40+ true , 1 ,
41+ false , 1 ,
3442 ) ;
35- Object . assign ( emval_handles , /** @lends {emval_handles} */ { reserved : emval_handles . allocated . length } ) ,
43+ #if ASSERTIONS
44+ assert ( emval_handles . length === { { { EMVAL_RESERVED_HANDLES } } } * 2 ) ;
45+ #endif
3646 Module [ 'count_emval_handles' ] = count_emval_handles;
3747 } ,
3848
39- $count_emval_handles__deps : [ '$emval_handles' ] ,
49+ $count_emval_handles__deps : [ '$emval_freelist' , '$ emval_handles'] ,
4050 $count_emval_handles : ( ) => {
41- var count = 0 ;
42- for ( var i = emval_handles . reserved ; i < emval_handles . allocated . length ; ++ i ) {
43- if ( emval_handles . allocated [ i ] !== undefined ) {
44- ++ count ;
45- }
46- }
47- return count ;
51+ return emval_handles . length / 2 - { { { EMVAL_RESERVED_HANDLES } } } - emval_freelist . length ;
4852 } ,
4953
5054 _emval_register_symbol__deps : [ '$emval_symbols' , '$readLatin1String' ] ,
@@ -61,39 +65,50 @@ var LibraryEmVal = {
6165 return symbol ;
6266 } ,
6367
64- $Emval__deps : [ '$emval_handles' , '$throwBindingError' , '$init_emval' ] ,
68+ $Emval__deps : [ '$emval_freelist' , '$ emval_handles', '$throwBindingError' , '$init_emval' ] ,
6569 $Emval : {
6670 toValue : ( handle ) => {
6771 if ( ! handle ) {
6872 throwBindingError ( 'Cannot use deleted val. handle = ' + handle ) ;
6973 }
70- return emval_handles . get ( handle ) . value ;
74+ #if ASSERTIONS
75+ // handle 2 is supposed to be `undefined`.
76+ assert ( handle === 2 || emval_handles [ handle ] !== undefined && handle % 2 === 0 , `invalid handle: ${ handle } ` ) ;
77+ #endif
78+ return emval_handles [ handle ] ;
7179 } ,
7280
7381 toHandle : ( value ) => {
7482 switch ( value ) {
75- case undefined : return 1 ;
76- case null : return 2 ;
77- case true : return 3 ;
78- case false : return 4 ;
83+ case undefined : return 2 ;
84+ case null : return 4 ;
85+ case true : return 6 ;
86+ case false : return 8 ;
7987 default :{
80- return emval_handles . allocate ( { refcount : 1 , value : value } ) ;
88+ const handle = emval_freelist . pop ( ) || emval_handles . length ;
89+ emval_handles [ handle ] = value ;
90+ emval_handles [ handle + 1 ] = 1 ;
91+ return handle ;
8192 }
8293 }
8394 }
8495 } ,
8596
8697 _emval_incref__deps : [ '$emval_handles' ] ,
8798 _emval_incref : ( handle ) => {
88- if ( handle > 4 ) {
89- emval_handles . get ( handle ) . refcount += 1 ;
99+ if ( handle > { { { EMVAL_LAST_RESERVED_HANDLE } } } ) {
100+ emval_handles [ handle + 1 ] += 1 ;
90101 }
91102 } ,
92103
93- _emval_decref__deps : [ '$emval_handles' ] ,
104+ _emval_decref__deps : [ '$emval_freelist' , '$ emval_handles'] ,
94105 _emval_decref : ( handle ) => {
95- if ( handle >= emval_handles . reserved && 0 === -- emval_handles . get ( handle ) . refcount ) {
96- emval_handles . free ( handle ) ;
106+ if ( handle > { { { EMVAL_LAST_RESERVED_HANDLE } } } && 0 === -- emval_handles [ handle + 1 ] ) {
107+ #if ASSERTIONS
108+ assert ( emval_handles [ handle ] !== undefined , `Decref for unallocated handle.` ) ;
109+ #endif
110+ emval_handles [ handle ] = undefined ;
111+ emval_freelist . push ( handle ) ;
97112 }
98113 } ,
99114
0 commit comments