Mercurial > hg > truffle
comparison src/share/vm/asm/assembler.cpp @ 622:56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
Summary: minor assembler enhancements preparing for method handles
Reviewed-by: kvn
author | jrose |
---|---|
date | Wed, 04 Mar 2009 09:58:39 -0800 |
parents | 98cb887364d3 |
children | 660978a2a31a |
comparison
equal
deleted
inserted
replaced
621:19f25e603e7b | 622:56aae7be60d4 |
---|---|
237 // Push the target offset into the branch instruction. | 237 // Push the target offset into the branch instruction. |
238 masm->pd_patch_instruction(branch, target); | 238 masm->pd_patch_instruction(branch, target); |
239 } | 239 } |
240 } | 240 } |
241 | 241 |
242 struct DelayedConstant { | |
243 typedef void (*value_fn_t)(); | |
244 BasicType type; | |
245 intptr_t value; | |
246 value_fn_t value_fn; | |
247 // This limit of 20 is generous for initial uses. | |
248 // The limit needs to be large enough to store the field offsets | |
249 // into classes which do not have statically fixed layouts. | |
250 // (Initial use is for method handle object offsets.) | |
251 // Look for uses of "delayed_value" in the source code | |
252 // and make sure this number is generous enough to handle all of them. | |
253 enum { DC_LIMIT = 20 }; | |
254 static DelayedConstant delayed_constants[DC_LIMIT]; | |
255 static DelayedConstant* add(BasicType type, value_fn_t value_fn); | |
256 bool match(BasicType t, value_fn_t cfn) { | |
257 return type == t && value_fn == cfn; | |
258 } | |
259 static void update_all(); | |
260 }; | |
261 | |
262 DelayedConstant DelayedConstant::delayed_constants[DC_LIMIT]; | |
263 // Default C structure initialization rules have the following effect here: | |
264 // = { { (BasicType)0, (intptr_t)NULL }, ... }; | |
265 | |
266 DelayedConstant* DelayedConstant::add(BasicType type, | |
267 DelayedConstant::value_fn_t cfn) { | |
268 for (int i = 0; i < DC_LIMIT; i++) { | |
269 DelayedConstant* dcon = &delayed_constants[i]; | |
270 if (dcon->match(type, cfn)) | |
271 return dcon; | |
272 if (dcon->value_fn == NULL) { | |
273 // (cmpxchg not because this is multi-threaded but because I'm paranoid) | |
274 if (Atomic::cmpxchg_ptr(CAST_FROM_FN_PTR(void*, cfn), &dcon->value_fn, NULL) == NULL) { | |
275 dcon->type = type; | |
276 return dcon; | |
277 } | |
278 } | |
279 } | |
280 // If this assert is hit (in pre-integration testing!) then re-evaluate | |
281 // the comment on the definition of DC_LIMIT. | |
282 guarantee(false, "too many delayed constants"); | |
283 return NULL; | |
284 } | |
285 | |
286 void DelayedConstant::update_all() { | |
287 for (int i = 0; i < DC_LIMIT; i++) { | |
288 DelayedConstant* dcon = &delayed_constants[i]; | |
289 if (dcon->value_fn != NULL && dcon->value == 0) { | |
290 typedef int (*int_fn_t)(); | |
291 typedef address (*address_fn_t)(); | |
292 switch (dcon->type) { | |
293 case T_INT: dcon->value = (intptr_t) ((int_fn_t) dcon->value_fn)(); break; | |
294 case T_ADDRESS: dcon->value = (intptr_t) ((address_fn_t)dcon->value_fn)(); break; | |
295 } | |
296 } | |
297 } | |
298 } | |
299 | |
300 intptr_t* AbstractAssembler::delayed_value_addr(int(*value_fn)()) { | |
301 DelayedConstant* dcon = DelayedConstant::add(T_INT, (DelayedConstant::value_fn_t) value_fn); | |
302 return &dcon->value; | |
303 } | |
304 intptr_t* AbstractAssembler::delayed_value_addr(address(*value_fn)()) { | |
305 DelayedConstant* dcon = DelayedConstant::add(T_ADDRESS, (DelayedConstant::value_fn_t) value_fn); | |
306 return &dcon->value; | |
307 } | |
308 void AbstractAssembler::update_delayed_values() { | |
309 DelayedConstant::update_all(); | |
310 } | |
311 | |
312 | |
313 | |
242 | 314 |
243 void AbstractAssembler::block_comment(const char* comment) { | 315 void AbstractAssembler::block_comment(const char* comment) { |
244 if (sect() == CodeBuffer::SECT_INSTS) { | 316 if (sect() == CodeBuffer::SECT_INSTS) { |
245 code_section()->outer()->block_comment(offset(), comment); | 317 code_section()->outer()->block_comment(offset(), comment); |
246 } | 318 } |