src/share/vm/asm/assembler.cpp

changeset 1057
56aae7be60d4
parent 1040
98cb887364d3
child 1077
660978a2a31a
     1.1 --- a/src/share/vm/asm/assembler.cpp	Tue Mar 03 18:25:57 2009 -0800
     1.2 +++ b/src/share/vm/asm/assembler.cpp	Wed Mar 04 09:58:39 2009 -0800
     1.3 @@ -239,6 +239,78 @@
     1.4    }
     1.5  }
     1.6  
     1.7 +struct DelayedConstant {
     1.8 +  typedef void (*value_fn_t)();
     1.9 +  BasicType type;
    1.10 +  intptr_t value;
    1.11 +  value_fn_t value_fn;
    1.12 +  // This limit of 20 is generous for initial uses.
    1.13 +  // The limit needs to be large enough to store the field offsets
    1.14 +  // into classes which do not have statically fixed layouts.
    1.15 +  // (Initial use is for method handle object offsets.)
    1.16 +  // Look for uses of "delayed_value" in the source code
    1.17 +  // and make sure this number is generous enough to handle all of them.
    1.18 +  enum { DC_LIMIT = 20 };
    1.19 +  static DelayedConstant delayed_constants[DC_LIMIT];
    1.20 +  static DelayedConstant* add(BasicType type, value_fn_t value_fn);
    1.21 +  bool match(BasicType t, value_fn_t cfn) {
    1.22 +    return type == t && value_fn == cfn;
    1.23 +  }
    1.24 +  static void update_all();
    1.25 +};
    1.26 +
    1.27 +DelayedConstant DelayedConstant::delayed_constants[DC_LIMIT];
    1.28 +// Default C structure initialization rules have the following effect here:
    1.29 +// = { { (BasicType)0, (intptr_t)NULL }, ... };
    1.30 +
    1.31 +DelayedConstant* DelayedConstant::add(BasicType type,
    1.32 +                                      DelayedConstant::value_fn_t cfn) {
    1.33 +  for (int i = 0; i < DC_LIMIT; i++) {
    1.34 +    DelayedConstant* dcon = &delayed_constants[i];
    1.35 +    if (dcon->match(type, cfn))
    1.36 +      return dcon;
    1.37 +    if (dcon->value_fn == NULL) {
    1.38 +      // (cmpxchg not because this is multi-threaded but because I'm paranoid)
    1.39 +      if (Atomic::cmpxchg_ptr(CAST_FROM_FN_PTR(void*, cfn), &dcon->value_fn, NULL) == NULL) {
    1.40 +        dcon->type = type;
    1.41 +        return dcon;
    1.42 +      }
    1.43 +    }
    1.44 +  }
    1.45 +  // If this assert is hit (in pre-integration testing!) then re-evaluate
    1.46 +  // the comment on the definition of DC_LIMIT.
    1.47 +  guarantee(false, "too many delayed constants");
    1.48 +  return NULL;
    1.49 +}
    1.50 +
    1.51 +void DelayedConstant::update_all() {
    1.52 +  for (int i = 0; i < DC_LIMIT; i++) {
    1.53 +    DelayedConstant* dcon = &delayed_constants[i];
    1.54 +    if (dcon->value_fn != NULL && dcon->value == 0) {
    1.55 +      typedef int     (*int_fn_t)();
    1.56 +      typedef address (*address_fn_t)();
    1.57 +      switch (dcon->type) {
    1.58 +      case T_INT:     dcon->value = (intptr_t) ((int_fn_t)    dcon->value_fn)(); break;
    1.59 +      case T_ADDRESS: dcon->value = (intptr_t) ((address_fn_t)dcon->value_fn)(); break;
    1.60 +      }
    1.61 +    }
    1.62 +  }
    1.63 +}
    1.64 +
    1.65 +intptr_t* AbstractAssembler::delayed_value_addr(int(*value_fn)()) {
    1.66 +  DelayedConstant* dcon = DelayedConstant::add(T_INT, (DelayedConstant::value_fn_t) value_fn);
    1.67 +  return &dcon->value;
    1.68 +}
    1.69 +intptr_t* AbstractAssembler::delayed_value_addr(address(*value_fn)()) {
    1.70 +  DelayedConstant* dcon = DelayedConstant::add(T_ADDRESS, (DelayedConstant::value_fn_t) value_fn);
    1.71 +  return &dcon->value;
    1.72 +}
    1.73 +void AbstractAssembler::update_delayed_values() {
    1.74 +  DelayedConstant::update_all();
    1.75 +}
    1.76 +
    1.77 +
    1.78 +
    1.79  
    1.80  void AbstractAssembler::block_comment(const char* comment) {
    1.81    if (sect() == CodeBuffer::SECT_INSTS) {

mercurial