4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
26 * iexpr.c -- instanced expression cache module
28 * this module provides a cache of fully instantized expressions.
31 #pragma ident "%Z%%M% %I% %E% SMI"
47 #define IEXPRSZ 1024 /* hash table size */
49 static struct stats
*Niexpr
;
51 /* the cache is a hash table of these structs */
54 struct iexpr
*next
; /* next entry in hash bucket */
59 * iexpr_init -- initialize the iexpr module
64 Niexpr
= stats_new_counter("iexpr.niexpr", "iexpr cache entries", 1);
68 * iexpr_hash -- produce a simple hash from an instanced expression tree
71 iexpr_hash(struct node
*np
)
78 return ((uintptr_t)np
->u
.globid
.s
);
105 (iexpr_hash(np
->u
.expr
.left
) +
106 iexpr_hash(np
->u
.expr
.right
)));
109 return ((uintptr_t)np
->u
.name
.s
);
112 return (iexpr_hash(np
->u
.event
.ename
) +
113 iexpr_hash(np
->u
.event
.epname
));
116 return ((uintptr_t)np
->u
.func
.s
+
117 iexpr_hash(np
->u
.func
.arglist
));
120 return ((uintptr_t)np
->u
.quote
.s
);
124 return ((int)np
->u
.ull
);
127 outfl(O_DIE
, np
->file
, np
->line
,
128 "iexpr_hash: unexpected node type: %s",
129 ptree_nodetype2str(np
->t
));
136 * iexpr_cmp -- compare two instanced expression trees
139 iexpr_cmp(struct node
*np1
, struct node
*np2
)
152 if (np1
->t
!= np2
->t
)
153 return (np2
->t
- np1
->t
);
155 /* types match, need to see additional info matches */
158 return (np2
->u
.globid
.s
- np1
->u
.globid
.s
);
184 diff
= iexpr_cmp(np1
->u
.expr
.left
, np2
->u
.expr
.left
);
187 return (iexpr_cmp(np1
->u
.expr
.right
, np2
->u
.expr
.right
));
190 if (np2
->u
.name
.s
!= np1
->u
.name
.s
)
191 return (np2
->u
.name
.s
- np1
->u
.name
.s
);
192 diff
= iexpr_cmp(np1
->u
.name
.child
, np2
->u
.name
.child
);
195 return (iexpr_cmp(np1
->u
.name
.next
, np2
->u
.name
.next
));
198 diff
= iexpr_cmp(np1
->u
.event
.ename
, np2
->u
.event
.ename
);
201 return (iexpr_cmp(np1
->u
.event
.epname
, np2
->u
.event
.epname
));
204 if (np1
->u
.func
.s
!= np2
->u
.func
.s
)
205 return (np2
->u
.func
.s
- np1
->u
.func
.s
);
206 return (iexpr_cmp(np1
->u
.func
.arglist
, np2
->u
.func
.arglist
));
209 return (np2
->u
.quote
.s
- np1
->u
.quote
.s
);
213 if (np2
->u
.ull
> np1
->u
.ull
)
215 else if (np1
->u
.ull
> np2
->u
.ull
)
221 outfl(O_DIE
, np1
->file
, np1
->line
,
222 "iexpr_cmp: unexpected node type: %s",
223 ptree_nodetype2str(np1
->t
));
230 * iexpr -- find instanced expr in cache, or add it if necessary
233 iexpr(struct node
*np
)
235 unsigned idx
= iexpr_hash(np
) % IEXPRSZ
;
236 struct iexpr
*bucketp
= Cache
[idx
];
240 for (cp
= bucketp
; cp
!= NULL
; cp
= cp
->next
)
241 if (iexpr_cmp(cp
->np
, np
) == 0) {
248 /* allocate new cache entry */
249 cp
= MALLOC(sizeof (*cp
));
255 stats_counter_bump(Niexpr
);
261 iexpr_free(struct node
*np
)
263 unsigned idx
= iexpr_hash(np
) % IEXPRSZ
;
265 struct iexpr
*prevcp
= NULL
;
268 for (cp
= Cache
[idx
]; cp
!= NULL
; cp
= cp
->next
) {
269 if (iexpr_cmp(cp
->np
, np
) == 0) {
272 if (cp
->count
== 0) {
275 Cache
[idx
] = cp
->next
;
277 prevcp
->next
= cp
->next
;
287 * iexpr_cached -- return true if np is in the iexpr cache
290 iexpr_cached(struct node
*np
)
292 struct iexpr
*cp
= Cache
[iexpr_hash(np
) % IEXPRSZ
];
295 for (; cp
!= NULL
; cp
= cp
->next
)
296 if (iexpr_cmp(cp
->np
, np
) == 0) {
305 * iexpr_fini -- free the iexpr cache
312 for (i
= 0; i
< IEXPRSZ
; i
++) {
316 for (cp
= Cache
[i
]; cp
!= NULL
; cp
= ncp
) {