216 // Push the target offset into the branch instruction. |
216 // Push the target offset into the branch instruction. |
217 masm->pd_patch_instruction(branch, target, file, line); |
217 masm->pd_patch_instruction(branch, target, file, line); |
218 } |
218 } |
219 } |
219 } |
220 |
220 |
221 struct DelayedConstant { |
|
222 typedef void (*value_fn_t)(); |
|
223 BasicType type; |
|
224 intptr_t value; |
|
225 value_fn_t value_fn; |
|
226 // This limit of 20 is generous for initial uses. |
|
227 // The limit needs to be large enough to store the field offsets |
|
228 // into classes which do not have statically fixed layouts. |
|
229 // (Initial use is for method handle object offsets.) |
|
230 // Look for uses of "delayed_value" in the source code |
|
231 // and make sure this number is generous enough to handle all of them. |
|
232 enum { DC_LIMIT = 20 }; |
|
233 static DelayedConstant delayed_constants[DC_LIMIT]; |
|
234 static DelayedConstant* add(BasicType type, value_fn_t value_fn); |
|
235 bool match(BasicType t, value_fn_t cfn) { |
|
236 return type == t && value_fn == cfn; |
|
237 } |
|
238 static void update_all(); |
|
239 }; |
|
240 |
|
241 DelayedConstant DelayedConstant::delayed_constants[DC_LIMIT]; |
|
242 // Default C structure initialization rules have the following effect here: |
|
243 // = { { (BasicType)0, (intptr_t)NULL }, ... }; |
|
244 |
|
245 DelayedConstant* DelayedConstant::add(BasicType type, |
|
246 DelayedConstant::value_fn_t cfn) { |
|
247 for (int i = 0; i < DC_LIMIT; i++) { |
|
248 DelayedConstant* dcon = &delayed_constants[i]; |
|
249 if (dcon->match(type, cfn)) |
|
250 return dcon; |
|
251 if (dcon->value_fn == NULL) { |
|
252 dcon->value_fn = cfn; |
|
253 dcon->type = type; |
|
254 return dcon; |
|
255 } |
|
256 } |
|
257 // If this assert is hit (in pre-integration testing!) then re-evaluate |
|
258 // the comment on the definition of DC_LIMIT. |
|
259 guarantee(false, "too many delayed constants"); |
|
260 return NULL; |
|
261 } |
|
262 |
|
263 void DelayedConstant::update_all() { |
|
264 for (int i = 0; i < DC_LIMIT; i++) { |
|
265 DelayedConstant* dcon = &delayed_constants[i]; |
|
266 if (dcon->value_fn != NULL && dcon->value == 0) { |
|
267 typedef int (*int_fn_t)(); |
|
268 typedef address (*address_fn_t)(); |
|
269 switch (dcon->type) { |
|
270 case T_INT: dcon->value = (intptr_t) ((int_fn_t) dcon->value_fn)(); break; |
|
271 case T_ADDRESS: dcon->value = (intptr_t) ((address_fn_t)dcon->value_fn)(); break; |
|
272 default: break; |
|
273 } |
|
274 } |
|
275 } |
|
276 } |
|
277 |
|
278 RegisterOrConstant AbstractAssembler::delayed_value(int(*value_fn)(), Register tmp, int offset) { |
|
279 intptr_t val = (intptr_t) (*value_fn)(); |
|
280 if (val != 0) return val + offset; |
|
281 return delayed_value_impl(delayed_value_addr(value_fn), tmp, offset); |
|
282 } |
|
283 RegisterOrConstant AbstractAssembler::delayed_value(address(*value_fn)(), Register tmp, int offset) { |
|
284 intptr_t val = (intptr_t) (*value_fn)(); |
|
285 if (val != 0) return val + offset; |
|
286 return delayed_value_impl(delayed_value_addr(value_fn), tmp, offset); |
|
287 } |
|
288 intptr_t* AbstractAssembler::delayed_value_addr(int(*value_fn)()) { |
|
289 DelayedConstant* dcon = DelayedConstant::add(T_INT, (DelayedConstant::value_fn_t) value_fn); |
|
290 return &dcon->value; |
|
291 } |
|
292 intptr_t* AbstractAssembler::delayed_value_addr(address(*value_fn)()) { |
|
293 DelayedConstant* dcon = DelayedConstant::add(T_ADDRESS, (DelayedConstant::value_fn_t) value_fn); |
|
294 return &dcon->value; |
|
295 } |
|
296 void AbstractAssembler::update_delayed_values() { |
|
297 DelayedConstant::update_all(); |
|
298 } |
|
299 |
|
300 void AbstractAssembler::block_comment(const char* comment) { |
221 void AbstractAssembler::block_comment(const char* comment) { |
301 if (sect() == CodeBuffer::SECT_INSTS) { |
222 if (sect() == CodeBuffer::SECT_INSTS) { |
302 code_section()->outer()->block_comment(offset(), comment); |
223 code_section()->outer()->block_comment(offset(), comment); |
303 } |
224 } |
304 } |
225 } |