12
12
/*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. */
13
13
14
14
// -- 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*/
16
16
/*global emval_addMethodCaller, emval_methodCallers, addToLibrary, global, emval_lookupTypes, makeLegalFunctionName*/
17
17
/*global emval_get_global*/
18
18
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
+ } } }
19
25
var 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 : [ ] ,
22
30
$emval_symbols : { } , // address -> string
23
31
24
32
$init_emval__deps : [ '$count_emval_handles' , '$emval_handles' ] ,
25
33
$init_emval__postset : 'init_emval();' ,
26
34
$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 ,
34
42
) ;
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
36
46
Module [ 'count_emval_handles' ] = count_emval_handles;
37
47
} ,
38
48
39
- $count_emval_handles__deps : [ '$emval_handles' ] ,
49
+ $count_emval_handles__deps : [ '$emval_freelist' , '$ emval_handles'] ,
40
50
$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 ;
48
52
} ,
49
53
50
54
_emval_register_symbol__deps : [ '$emval_symbols' , '$readLatin1String' ] ,
@@ -61,39 +65,50 @@ var LibraryEmVal = {
61
65
return symbol ;
62
66
} ,
63
67
64
- $Emval__deps : [ '$emval_handles' , '$throwBindingError' , '$init_emval' ] ,
68
+ $Emval__deps : [ '$emval_freelist' , '$ emval_handles', '$throwBindingError' , '$init_emval' ] ,
65
69
$Emval : {
66
70
toValue : ( handle ) => {
67
71
if ( ! handle ) {
68
72
throwBindingError ( 'Cannot use deleted val. handle = ' + handle ) ;
69
73
}
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 ] ;
71
79
} ,
72
80
73
81
toHandle : ( value ) => {
74
82
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 ;
79
87
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 ;
81
92
}
82
93
}
83
94
}
84
95
} ,
85
96
86
97
_emval_incref__deps : [ '$emval_handles' ] ,
87
98
_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 ;
90
101
}
91
102
} ,
92
103
93
- _emval_decref__deps : [ '$emval_handles' ] ,
104
+ _emval_decref__deps : [ '$emval_freelist' , '$ emval_handles'] ,
94
105
_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 ) ;
97
112
}
98
113
} ,
99
114
0 commit comments