1
+ /*
2
+ * QuickJS Javascript Engine
3
+ *
4
+ * Copyright (c) 2017-2021 Fabrice Bellard
5
+ * Copyright (c) 2017-2021 Charlie Gordon
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ * of this software and associated documentation files (the "Software"), to deal
9
+ * in the Software without restriction, including without limitation the rights
10
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the Software is
12
+ * furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included in
15
+ * all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ * THE SOFTWARE.
24
+ */
25
+
26
+ #include "ic.h"
27
+
28
+ uint32_t get_index_hash (JSAtom atom , int hash_bits ) {
29
+ return (atom * 0x9e370001 ) >> (32 - hash_bits );
30
+ }
31
+
32
+ InlineCache * init_ic (JSRuntime * rt ) {
33
+ InlineCache * ic ;
34
+ ic = js_malloc_rt (rt , sizeof (InlineCache ));
35
+ if (unlikely (!ic ))
36
+ goto fail ;
37
+ ic -> count = 0 ;
38
+ ic -> hash_bits = 4 ;
39
+ ic -> capacity = 1 << ic -> hash_bits ;
40
+ ic -> rt = rt ;
41
+ ic -> hash = js_malloc_rt (rt , sizeof (ic -> hash [0 ]) * ic -> capacity );
42
+ if (unlikely (!ic -> hash ))
43
+ goto fail ;
44
+ memset (ic -> hash , 0 , sizeof (ic -> hash [0 ]) * ic -> capacity );
45
+ ic -> cache = NULL ;
46
+ ic -> updated = FALSE;
47
+ ic -> updated_offset = 0 ;
48
+ return ic ;
49
+ fail :
50
+ return NULL ;
51
+ }
52
+
53
+ int rebuild_ic (InlineCache * ic ) {
54
+ uint32_t i , count ;
55
+ InlineCacheHashSlot * ch ;
56
+ if (ic -> count == 0 )
57
+ goto end ;
58
+ count = 0 ;
59
+ ic -> cache = js_malloc_rt (ic -> rt , sizeof (InlineCacheRingSlot ) * ic -> count );
60
+ if (unlikely (!ic -> cache ))
61
+ goto fail ;
62
+ memset (ic -> cache , 0 , sizeof (InlineCacheRingSlot ) * ic -> count );
63
+ for (i = 0 ; i < ic -> capacity ; i ++ ) {
64
+ for (ch = ic -> hash [i ]; ch != NULL ; ch = ch -> next ) {
65
+ ch -> index = count ++ ;
66
+ ic -> cache [ch -> index ].atom = ch -> atom ;
67
+ ic -> cache [ch -> index ].index = 0 ;
68
+ }
69
+ }
70
+ end :
71
+ return 0 ;
72
+ fail :
73
+ return -1 ;
74
+ }
75
+
76
+ int resize_ic_hash (InlineCache * ic ) {
77
+ uint32_t new_capacity , i , h ;
78
+ InlineCacheHashSlot * ch , * ch_next ;
79
+ InlineCacheHashSlot * * new_hash ;
80
+ ic -> hash_bits += 1 ;
81
+ new_capacity = 1 << ic -> hash_bits ;
82
+ new_hash = js_malloc_rt (ic -> rt , sizeof (ic -> hash [0 ]) * new_capacity );
83
+ if (unlikely (!new_hash ))
84
+ goto fail ;
85
+ memset (new_hash , 0 , sizeof (ic -> hash [0 ]) * new_capacity );
86
+ for (i = 0 ; i < ic -> capacity ; i ++ ) {
87
+ for (ch = ic -> hash [i ]; ch != NULL ; ch = ch_next ) {
88
+ h = get_index_hash (ch -> atom , ic -> hash_bits );
89
+ ch_next = ch -> next ;
90
+ ch -> next = new_hash [h ];
91
+ new_hash [h ] = ch ;
92
+ }
93
+ }
94
+ js_free_rt (ic -> rt , ic -> hash );
95
+ ic -> hash = new_hash ;
96
+ ic -> capacity = new_capacity ;
97
+ return 0 ;
98
+ fail :
99
+ return -1 ;
100
+ }
101
+
102
+ int free_ic (InlineCache * ic ) {
103
+ uint32_t i , j ;
104
+ InlineCacheHashSlot * ch , * ch_next ;
105
+ InlineCacheRingItem * buffer ;
106
+ for (i = 0 ; i < ic -> count ; i ++ ) {
107
+ buffer = ic -> cache [i ].buffer ;
108
+ for (j = 0 ; j < IC_CACHE_ITEM_CAPACITY ; j ++ ) {
109
+ js_free_shape_null (ic -> rt , buffer [j ].shape );
110
+ }
111
+ }
112
+ for (i = 0 ; i < ic -> capacity ; i ++ ) {
113
+ for (ch = ic -> hash [i ]; ch != NULL ; ch = ch_next ) {
114
+ ch_next = ch -> next ;
115
+ js_free_rt (ic -> rt , ch );
116
+ }
117
+ }
118
+ if (ic -> count > 0 )
119
+ js_free_rt (ic -> rt , ic -> cache );
120
+ js_free_rt (ic -> rt , ic -> hash );
121
+ js_free_rt (ic -> rt , ic );
122
+ return 0 ;
123
+ }
124
+
125
+ uint32_t add_ic_slot (InlineCache * ic , JSAtom atom , JSObject * object ,
126
+ uint32_t prop_offset ) {
127
+ int32_t i ;
128
+ uint32_t h ;
129
+ InlineCacheHashSlot * ch ;
130
+ InlineCacheRingSlot * cr ;
131
+ JSShape * sh ;
132
+ cr = NULL ;
133
+ h = get_index_hash (atom , ic -> hash_bits );
134
+ for (ch = ic -> hash [h ]; ch != NULL ; ch = ch -> next )
135
+ if (ch -> atom == atom ) {
136
+ cr = ic -> cache + ch -> index ;
137
+ break ;
138
+ }
139
+
140
+ assert (cr != NULL );
141
+ i = cr -> index ;
142
+ for (;;) {
143
+ if (object -> shape == cr -> buffer [i ].shape ) {
144
+ cr -> buffer [i ].prop_offset = prop_offset ;
145
+ goto end ;
146
+ }
147
+
148
+ i = (i + 1 ) % IC_CACHE_ITEM_CAPACITY ;
149
+ if (i == cr -> index )
150
+ break ;
151
+ }
152
+
153
+ sh = cr -> buffer [i ].shape ;
154
+ cr -> buffer [i ].shape = js_dup_shape (object -> shape );
155
+ js_free_shape_null (ic -> rt , sh );
156
+ cr -> buffer [i ].prop_offset = prop_offset ;
157
+ end :
158
+ return ch -> index ;
159
+ }
160
+
161
+ uint32_t add_ic_slot1 (InlineCache * ic , JSAtom atom ) {
162
+ uint32_t h ;
163
+ InlineCacheHashSlot * ch ;
164
+ if (ic -> count + 1 >= ic -> capacity && resize_ic_hash (ic ))
165
+ goto end ;
166
+ h = get_index_hash (atom , ic -> hash_bits );
167
+ for (ch = ic -> hash [h ]; ch != NULL ; ch = ch -> next )
168
+ if (ch -> atom == atom )
169
+ goto end ;
170
+ ch = js_malloc_rt (ic -> rt , sizeof (InlineCacheHashSlot ));
171
+ if (unlikely (!ch ))
172
+ goto end ;
173
+ ch -> atom = atom ;
174
+ ch -> index = 0 ;
175
+ ch -> next = ic -> hash [h ];
176
+ ic -> hash [h ] = ch ;
177
+ ic -> count += 1 ;
178
+ end :
179
+ return 0 ;
180
+ }
0 commit comments