1.1 --- a/src/share/vm/c1/c1_Instruction.hpp Thu Jun 03 14:20:27 2010 -0700 1.2 +++ b/src/share/vm/c1/c1_Instruction.hpp Fri Jun 04 11:18:04 2010 -0700 1.3 @@ -116,6 +116,13 @@ 1.4 }; 1.5 1.6 1.7 +// A simple closure class for visiting the values of an Instruction 1.8 +class ValueVisitor: public StackObj { 1.9 + public: 1.10 + virtual void visit(Value* v) = 0; 1.11 +}; 1.12 + 1.13 + 1.14 // Some array and list classes 1.15 define_array(BlockBeginArray, BlockBegin*) 1.16 define_stack(_BlockList, BlockBeginArray) 1.17 @@ -129,7 +136,7 @@ 1.18 void iterate_forward(BlockClosure* closure); 1.19 void iterate_backward(BlockClosure* closure); 1.20 void blocks_do(void f(BlockBegin*)); 1.21 - void values_do(void f(Value*)); 1.22 + void values_do(ValueVisitor* f); 1.23 void print(bool cfg_only = false, bool live_only = false) PRODUCT_RETURN; 1.24 }; 1.25 1.26 @@ -264,8 +271,6 @@ 1.27 1.28 class Instruction: public CompilationResourceObj { 1.29 private: 1.30 - static int _next_id; // the node counter 1.31 - 1.32 int _id; // the unique instruction id 1.33 int _bci; // the instruction bci 1.34 int _use_count; // the number of instructions refering to this value (w/o prev/next); only roots can have use count = 0 or > 1 1.35 @@ -283,6 +288,7 @@ 1.36 #endif 1.37 1.38 friend class UseCountComputer; 1.39 + friend class BlockBegin; 1.40 1.41 protected: 1.42 void set_bci(int bci) { assert(bci == SynchronizationEntryBCI || bci >= 0, "illegal bci"); _bci = bci; } 1.43 @@ -292,6 +298,13 @@ 1.44 } 1.45 1.46 public: 1.47 + void* operator new(size_t size) { 1.48 + Compilation* c = Compilation::current(); 1.49 + void* res = c->arena()->Amalloc(size); 1.50 + ((Instruction*)res)->_id = c->get_next_id(); 1.51 + return res; 1.52 + } 1.53 + 1.54 enum InstructionFlag { 1.55 NeedsNullCheckFlag = 0, 1.56 CanTrapFlag, 1.57 @@ -338,13 +351,13 @@ 1.58 static Condition negate(Condition cond); 1.59 1.60 // initialization 1.61 - static void initialize() { _next_id = 0; } 1.62 - static int number_of_instructions() { return _next_id; } 1.63 + static int number_of_instructions() { 1.64 + return Compilation::current()->number_of_instructions(); 1.65 + } 1.66 1.67 // creation 1.68 Instruction(ValueType* type, bool type_is_constant = false, bool create_hi = true) 1.69 - : _id(_next_id++) 1.70 - , _bci(-99) 1.71 + : _bci(-99) 1.72 , _use_count(0) 1.73 , _pin_state(0) 1.74 , _type(type) 1.75 @@ -479,10 +492,10 @@ 1.76 1.77 virtual bool can_trap() const { return false; } 1.78 1.79 - virtual void input_values_do(void f(Value*)) = 0; 1.80 - virtual void state_values_do(void f(Value*)) { /* usually no state - override on demand */ } 1.81 - virtual void other_values_do(void f(Value*)) { /* usually no other - override on demand */ } 1.82 - void values_do(void f(Value*)) { input_values_do(f); state_values_do(f); other_values_do(f); } 1.83 + virtual void input_values_do(ValueVisitor* f) = 0; 1.84 + virtual void state_values_do(ValueVisitor* f) { /* usually no state - override on demand */ } 1.85 + virtual void other_values_do(ValueVisitor* f) { /* usually no other - override on demand */ } 1.86 + void values_do(ValueVisitor* f) { input_values_do(f); state_values_do(f); other_values_do(f); } 1.87 1.88 virtual ciType* exact_type() const { return NULL; } 1.89 virtual ciType* declared_type() const { return NULL; } 1.90 @@ -517,9 +530,12 @@ 1.91 1.92 // Debugging support 1.93 1.94 + 1.95 #ifdef ASSERT 1.96 - static void assert_value(Value* x) { assert((*x) != NULL, "value must exist"); } 1.97 - #define ASSERT_VALUES values_do(assert_value); 1.98 +class AssertValues: public ValueVisitor { 1.99 + void visit(Value* x) { assert((*x) != NULL, "value must exist"); } 1.100 +}; 1.101 + #define ASSERT_VALUES { AssertValues assert_value; values_do(&assert_value); } 1.102 #else 1.103 #define ASSERT_VALUES 1.104 #endif // ASSERT 1.105 @@ -555,7 +571,7 @@ 1.106 void make_illegal() { set_type(illegalType); } 1.107 1.108 // generic 1.109 - virtual void input_values_do(void f(Value*)) { ShouldNotReachHere(); } 1.110 + virtual void input_values_do(ValueVisitor* f) { ShouldNotReachHere(); } 1.111 }; 1.112 1.113 1.114 @@ -615,7 +631,7 @@ 1.115 } 1.116 1.117 // generic 1.118 - virtual void input_values_do(void f(Value*)) { 1.119 + virtual void input_values_do(ValueVisitor* f) { 1.120 } 1.121 }; 1.122 1.123 @@ -635,7 +651,7 @@ 1.124 int java_index() const { return _java_index; } 1.125 1.126 // generic 1.127 - virtual void input_values_do(void f(Value*)) { /* no values */ } 1.128 + virtual void input_values_do(ValueVisitor* f) { /* no values */ } 1.129 }; 1.130 1.131 1.132 @@ -663,8 +679,8 @@ 1.133 1.134 // generic 1.135 virtual bool can_trap() const { return state() != NULL; } 1.136 - virtual void input_values_do(void f(Value*)) { /* no values */ } 1.137 - virtual void other_values_do(void f(Value*)); 1.138 + virtual void input_values_do(ValueVisitor* f) { /* no values */ } 1.139 + virtual void other_values_do(ValueVisitor* f); 1.140 1.141 virtual intx hash() const; 1.142 virtual bool is_equal(Value v) const; 1.143 @@ -734,8 +750,8 @@ 1.144 1.145 // generic 1.146 virtual bool can_trap() const { return needs_null_check() || needs_patching(); } 1.147 - virtual void input_values_do(void f(Value*)) { f(&_obj); } 1.148 - virtual void other_values_do(void f(Value*)); 1.149 + virtual void input_values_do(ValueVisitor* f) { f->visit(&_obj); } 1.150 + virtual void other_values_do(ValueVisitor* f); 1.151 }; 1.152 1.153 1.154 @@ -776,7 +792,7 @@ 1.155 bool needs_write_barrier() const { return check_flag(NeedsWriteBarrierFlag); } 1.156 1.157 // generic 1.158 - virtual void input_values_do(void f(Value*)) { AccessField::input_values_do(f); f(&_value); } 1.159 + virtual void input_values_do(ValueVisitor* f) { AccessField::input_values_do(f); f->visit(&_value); } 1.160 }; 1.161 1.162 1.163 @@ -804,8 +820,8 @@ 1.164 1.165 // generic 1.166 virtual bool can_trap() const { return needs_null_check(); } 1.167 - virtual void input_values_do(void f(Value*)) { f(&_array); } 1.168 - virtual void other_values_do(void f(Value*)); 1.169 + virtual void input_values_do(ValueVisitor* f) { f->visit(&_array); } 1.170 + virtual void other_values_do(ValueVisitor* f); 1.171 }; 1.172 1.173 1.174 @@ -857,7 +873,7 @@ 1.175 bool compute_needs_range_check(); 1.176 1.177 // generic 1.178 - virtual void input_values_do(void f(Value*)) { AccessArray::input_values_do(f); f(&_index); if (_length != NULL) f(&_length); } 1.179 + virtual void input_values_do(ValueVisitor* f) { AccessArray::input_values_do(f); f->visit(&_index); if (_length != NULL) f->visit(&_length); } 1.180 }; 1.181 1.182 1.183 @@ -909,7 +925,7 @@ 1.184 bool needs_store_check() const { return check_flag(NeedsStoreCheckFlag); } 1.185 1.186 // generic 1.187 - virtual void input_values_do(void f(Value*)) { AccessIndexed::input_values_do(f); f(&_value); } 1.188 + virtual void input_values_do(ValueVisitor* f) { AccessIndexed::input_values_do(f); f->visit(&_value); } 1.189 }; 1.190 1.191 1.192 @@ -927,7 +943,7 @@ 1.193 Value x() const { return _x; } 1.194 1.195 // generic 1.196 - virtual void input_values_do(void f(Value*)) { f(&_x); } 1.197 + virtual void input_values_do(ValueVisitor* f) { f->visit(&_x); } 1.198 }; 1.199 1.200 1.201 @@ -956,7 +972,7 @@ 1.202 1.203 // generic 1.204 virtual bool is_commutative() const { return false; } 1.205 - virtual void input_values_do(void f(Value*)) { f(&_x); f(&_y); } 1.206 + virtual void input_values_do(ValueVisitor* f) { f->visit(&_x); f->visit(&_y); } 1.207 }; 1.208 1.209 1.210 @@ -982,7 +998,7 @@ 1.211 // generic 1.212 virtual bool is_commutative() const; 1.213 virtual bool can_trap() const; 1.214 - virtual void other_values_do(void f(Value*)); 1.215 + virtual void other_values_do(ValueVisitor* f); 1.216 HASHING3(Op2, true, op(), x()->subst(), y()->subst()) 1.217 }; 1.218 1.219 @@ -1023,7 +1039,7 @@ 1.220 1.221 // generic 1.222 HASHING3(Op2, true, op(), x()->subst(), y()->subst()) 1.223 - virtual void other_values_do(void f(Value*)); 1.224 + virtual void other_values_do(ValueVisitor* f); 1.225 }; 1.226 1.227 1.228 @@ -1051,7 +1067,7 @@ 1.229 Value fval() const { return _fval; } 1.230 1.231 // generic 1.232 - virtual void input_values_do(void f(Value*)) { Op2::input_values_do(f); f(&_tval); f(&_fval); } 1.233 + virtual void input_values_do(ValueVisitor* f) { Op2::input_values_do(f); f->visit(&_tval); f->visit(&_fval); } 1.234 }; 1.235 1.236 1.237 @@ -1071,7 +1087,7 @@ 1.238 Value value() const { return _value; } 1.239 1.240 // generic 1.241 - virtual void input_values_do(void f(Value*)) { f(&_value); } 1.242 + virtual void input_values_do(ValueVisitor* f) { f->visit(&_value); } 1.243 HASHING2(Convert, true, op(), value()->subst()) 1.244 }; 1.245 1.246 @@ -1100,8 +1116,8 @@ 1.247 1.248 // generic 1.249 virtual bool can_trap() const { return check_flag(CanTrapFlag); /* null-check elimination sets to false */ } 1.250 - virtual void input_values_do(void f(Value*)) { f(&_obj); } 1.251 - virtual void other_values_do(void f(Value*)); 1.252 + virtual void input_values_do(ValueVisitor* f) { f->visit(&_obj); } 1.253 + virtual void other_values_do(ValueVisitor* f); 1.254 HASHING1(NullCheck, true, obj()->subst()) 1.255 }; 1.256 1.257 @@ -1127,8 +1143,8 @@ 1.258 void set_state(ValueStack* state) { _state = state; } 1.259 1.260 // generic 1.261 - virtual void input_values_do(void f(Value*)) { /* no values */ } 1.262 - virtual void state_values_do(void f(Value*)); 1.263 + virtual void input_values_do(ValueVisitor* f) { /* no values */ } 1.264 + virtual void state_values_do(ValueVisitor* f); 1.265 }; 1.266 1.267 1.268 @@ -1169,12 +1185,12 @@ 1.269 1.270 // generic 1.271 virtual bool can_trap() const { return true; } 1.272 - virtual void input_values_do(void f(Value*)) { 1.273 + virtual void input_values_do(ValueVisitor* f) { 1.274 StateSplit::input_values_do(f); 1.275 - if (has_receiver()) f(&_recv); 1.276 - for (int i = 0; i < _args->length(); i++) f(_args->adr_at(i)); 1.277 + if (has_receiver()) f->visit(&_recv); 1.278 + for (int i = 0; i < _args->length(); i++) f->visit(_args->adr_at(i)); 1.279 } 1.280 - virtual void state_values_do(void f(Value*)); 1.281 + virtual void state_values_do(ValueVisitor *f); 1.282 }; 1.283 1.284 1.285 @@ -1212,8 +1228,8 @@ 1.286 1.287 // generic 1.288 virtual bool can_trap() const { return true; } 1.289 - virtual void input_values_do(void f(Value*)) { StateSplit::input_values_do(f); f(&_length); } 1.290 - virtual void other_values_do(void f(Value*)); 1.291 + virtual void input_values_do(ValueVisitor* f) { StateSplit::input_values_do(f); f->visit(&_length); } 1.292 + virtual void other_values_do(ValueVisitor* f); 1.293 }; 1.294 1.295 1.296 @@ -1262,7 +1278,7 @@ 1.297 int rank() const { return dims()->length(); } 1.298 1.299 // generic 1.300 - virtual void input_values_do(void f(Value*)) { 1.301 + virtual void input_values_do(ValueVisitor* f) { 1.302 // NOTE: we do not call NewArray::input_values_do since "length" 1.303 // is meaningless for a multi-dimensional array; passing the 1.304 // zeroth element down to NewArray as its length is a bad idea 1.305 @@ -1270,7 +1286,7 @@ 1.306 // get updated, and the value must not be traversed twice. Was bug 1.307 // - kbr 4/10/2001 1.308 StateSplit::input_values_do(f); 1.309 - for (int i = 0; i < _dims->length(); i++) f(_dims->adr_at(i)); 1.310 + for (int i = 0; i < _dims->length(); i++) f->visit(_dims->adr_at(i)); 1.311 } 1.312 }; 1.313 1.314 @@ -1300,8 +1316,8 @@ 1.315 1.316 // generic 1.317 virtual bool can_trap() const { return true; } 1.318 - virtual void input_values_do(void f(Value*)) { StateSplit::input_values_do(f); f(&_obj); } 1.319 - virtual void other_values_do(void f(Value*)); 1.320 + virtual void input_values_do(ValueVisitor* f) { StateSplit::input_values_do(f); f->visit(&_obj); } 1.321 + virtual void other_values_do(ValueVisitor* f); 1.322 }; 1.323 1.324 1.325 @@ -1366,7 +1382,7 @@ 1.326 int monitor_no() const { return _monitor_no; } 1.327 1.328 // generic 1.329 - virtual void input_values_do(void f(Value*)) { StateSplit::input_values_do(f); f(&_obj); } 1.330 + virtual void input_values_do(ValueVisitor* f) { StateSplit::input_values_do(f); f->visit(&_obj); } 1.331 }; 1.332 1.333 1.334 @@ -1385,7 +1401,7 @@ 1.335 1.336 // accessors 1.337 ValueStack* lock_stack_before() const { return _lock_stack_before; } 1.338 - virtual void state_values_do(void f(Value*)); 1.339 + virtual void state_values_do(ValueVisitor* f); 1.340 1.341 // generic 1.342 virtual bool can_trap() const { return true; } 1.343 @@ -1454,11 +1470,11 @@ 1.344 1.345 // generic 1.346 virtual bool can_trap() const { return check_flag(CanTrapFlag); } 1.347 - virtual void input_values_do(void f(Value*)) { 1.348 + virtual void input_values_do(ValueVisitor* f) { 1.349 StateSplit::input_values_do(f); 1.350 - for (int i = 0; i < _args->length(); i++) f(_args->adr_at(i)); 1.351 + for (int i = 0; i < _args->length(); i++) f->visit(_args->adr_at(i)); 1.352 } 1.353 - virtual void state_values_do(void f(Value*)); 1.354 + virtual void state_values_do(ValueVisitor* f); 1.355 1.356 }; 1.357 1.358 @@ -1467,8 +1483,6 @@ 1.359 1.360 LEAF(BlockBegin, StateSplit) 1.361 private: 1.362 - static int _next_block_id; // the block counter 1.363 - 1.364 int _block_id; // the unique block id 1.365 int _depth_first_number; // number of this block in a depth-first ordering 1.366 int _linear_scan_number; // number of this block in linear-scan ordering 1.367 @@ -1510,14 +1524,22 @@ 1.368 friend class SuxAndWeightAdjuster; 1.369 1.370 public: 1.371 + void* operator new(size_t size) { 1.372 + Compilation* c = Compilation::current(); 1.373 + void* res = c->arena()->Amalloc(size); 1.374 + ((BlockBegin*)res)->_id = c->get_next_id(); 1.375 + ((BlockBegin*)res)->_block_id = c->get_next_block_id(); 1.376 + return res; 1.377 + } 1.378 + 1.379 // initialization/counting 1.380 - static void initialize() { _next_block_id = 0; } 1.381 - static int number_of_blocks() { return _next_block_id; } 1.382 + static int number_of_blocks() { 1.383 + return Compilation::current()->number_of_blocks(); 1.384 + } 1.385 1.386 // creation 1.387 BlockBegin(int bci) 1.388 : StateSplit(illegalType) 1.389 - , _block_id(_next_block_id++) 1.390 , _depth_first_number(-1) 1.391 , _linear_scan_number(-1) 1.392 , _loop_depth(0) 1.393 @@ -1592,7 +1614,7 @@ 1.394 void init_stores_to_locals(int locals_count) { _stores_to_locals = BitMap(locals_count); _stores_to_locals.clear(); } 1.395 1.396 // generic 1.397 - virtual void state_values_do(void f(Value*)); 1.398 + virtual void state_values_do(ValueVisitor* f); 1.399 1.400 // successors and predecessors 1.401 int number_of_sux() const; 1.402 @@ -1646,7 +1668,7 @@ 1.403 void iterate_preorder (BlockClosure* closure); 1.404 void iterate_postorder (BlockClosure* closure); 1.405 1.406 - void block_values_do(void f(Value*)); 1.407 + void block_values_do(ValueVisitor* f); 1.408 1.409 // loops 1.410 void set_loop_index(int ix) { _loop_index = ix; } 1.411 @@ -1698,7 +1720,7 @@ 1.412 void set_begin(BlockBegin* begin); 1.413 1.414 // generic 1.415 - virtual void other_values_do(void f(Value*)); 1.416 + virtual void other_values_do(ValueVisitor* f); 1.417 1.418 // successors 1.419 int number_of_sux() const { return _sux != NULL ? _sux->length() : 0; } 1.420 @@ -1787,7 +1809,7 @@ 1.421 void set_profiled_bci(int bci) { _profiled_bci = bci; } 1.422 1.423 // generic 1.424 - virtual void input_values_do(void f(Value*)) { BlockEnd::input_values_do(f); f(&_x); f(&_y); } 1.425 + virtual void input_values_do(ValueVisitor* f) { BlockEnd::input_values_do(f); f->visit(&_x); f->visit(&_y); } 1.426 }; 1.427 1.428 1.429 @@ -1841,7 +1863,7 @@ 1.430 } 1.431 1.432 // generic 1.433 - virtual void input_values_do(void f(Value*)) { BlockEnd::input_values_do(f); f(&_obj); } 1.434 + virtual void input_values_do(ValueVisitor* f) { BlockEnd::input_values_do(f); f->visit(&_obj); } 1.435 }; 1.436 1.437 1.438 @@ -1863,7 +1885,7 @@ 1.439 int length() const { return number_of_sux() - 1; } 1.440 1.441 // generic 1.442 - virtual void input_values_do(void f(Value*)) { BlockEnd::input_values_do(f); f(&_tag); } 1.443 + virtual void input_values_do(ValueVisitor* f) { BlockEnd::input_values_do(f); f->visit(&_tag); } 1.444 }; 1.445 1.446 1.447 @@ -1916,9 +1938,9 @@ 1.448 bool has_result() const { return result() != NULL; } 1.449 1.450 // generic 1.451 - virtual void input_values_do(void f(Value*)) { 1.452 + virtual void input_values_do(ValueVisitor* f) { 1.453 BlockEnd::input_values_do(f); 1.454 - if (has_result()) f(&_result); 1.455 + if (has_result()) f->visit(&_result); 1.456 } 1.457 }; 1.458 1.459 @@ -1938,8 +1960,8 @@ 1.460 1.461 // generic 1.462 virtual bool can_trap() const { return true; } 1.463 - virtual void input_values_do(void f(Value*)) { BlockEnd::input_values_do(f); f(&_exception); } 1.464 - virtual void state_values_do(void f(Value*)); 1.465 + virtual void input_values_do(ValueVisitor* f) { BlockEnd::input_values_do(f); f->visit(&_exception); } 1.466 + virtual void state_values_do(ValueVisitor* f); 1.467 }; 1.468 1.469 1.470 @@ -1971,7 +1993,7 @@ 1.471 #endif 1.472 1.473 // generic 1.474 - virtual void input_values_do(void f(Value*)) { } 1.475 + virtual void input_values_do(ValueVisitor* f) { } 1.476 }; 1.477 1.478 1.479 @@ -1984,7 +2006,7 @@ 1.480 } 1.481 1.482 // generic 1.483 - virtual void input_values_do(void f(Value*)) { } 1.484 + virtual void input_values_do(ValueVisitor* f) { } 1.485 }; 1.486 1.487 1.488 @@ -2008,7 +2030,7 @@ 1.489 Value input() const { return _input; } 1.490 1.491 // generic 1.492 - virtual void input_values_do(void f(Value*)) { f(&_input); } 1.493 + virtual void input_values_do(ValueVisitor* f) { f->visit(&_input); } 1.494 }; 1.495 1.496 1.497 @@ -2033,8 +2055,8 @@ 1.498 BasicType basic_type() { return _basic_type; } 1.499 1.500 // generic 1.501 - virtual void input_values_do(void f(Value*)) { } 1.502 - virtual void other_values_do(void f(Value*)) { } 1.503 + virtual void input_values_do(ValueVisitor* f) { } 1.504 + virtual void other_values_do(ValueVisitor* f) { } 1.505 }; 1.506 1.507 1.508 @@ -2078,9 +2100,9 @@ 1.509 void set_log2_scale(int log2_scale) { _log2_scale = log2_scale; } 1.510 1.511 // generic 1.512 - virtual void input_values_do(void f(Value*)) { UnsafeOp::input_values_do(f); 1.513 - f(&_base); 1.514 - if (has_index()) f(&_index); } 1.515 + virtual void input_values_do(ValueVisitor* f) { UnsafeOp::input_values_do(f); 1.516 + f->visit(&_base); 1.517 + if (has_index()) f->visit(&_index); } 1.518 }; 1.519 1.520 1.521 @@ -2128,8 +2150,8 @@ 1.522 Value value() { return _value; } 1.523 1.524 // generic 1.525 - virtual void input_values_do(void f(Value*)) { UnsafeRawOp::input_values_do(f); 1.526 - f(&_value); } 1.527 + virtual void input_values_do(ValueVisitor* f) { UnsafeRawOp::input_values_do(f); 1.528 + f->visit(&_value); } 1.529 }; 1.530 1.531 1.532 @@ -2149,9 +2171,9 @@ 1.533 Value offset() { return _offset; } 1.534 bool is_volatile() { return _is_volatile; } 1.535 // generic 1.536 - virtual void input_values_do(void f(Value*)) { UnsafeOp::input_values_do(f); 1.537 - f(&_object); 1.538 - f(&_offset); } 1.539 + virtual void input_values_do(ValueVisitor* f) { UnsafeOp::input_values_do(f); 1.540 + f->visit(&_object); 1.541 + f->visit(&_offset); } 1.542 }; 1.543 1.544 1.545 @@ -2180,8 +2202,8 @@ 1.546 Value value() { return _value; } 1.547 1.548 // generic 1.549 - virtual void input_values_do(void f(Value*)) { UnsafeObjectOp::input_values_do(f); 1.550 - f(&_value); } 1.551 + virtual void input_values_do(ValueVisitor* f) { UnsafeObjectOp::input_values_do(f); 1.552 + f->visit(&_value); } 1.553 }; 1.554 1.555 1.556 @@ -2238,7 +2260,7 @@ 1.557 Value recv() { return _recv; } 1.558 ciKlass* known_holder() { return _known_holder; } 1.559 1.560 - virtual void input_values_do(void f(Value*)) { if (_recv != NULL) f(&_recv); } 1.561 + virtual void input_values_do(ValueVisitor* f) { if (_recv != NULL) f->visit(&_recv); } 1.562 }; 1.563 1.564 1.565 @@ -2266,7 +2288,7 @@ 1.566 int offset() { return _offset; } 1.567 int increment() { return _increment; } 1.568 1.569 - virtual void input_values_do(void f(Value*)) { f(&_mdo); } 1.570 + virtual void input_values_do(ValueVisitor* f) { f->visit(&_mdo); } 1.571 }; 1.572 1.573