Mercurial > hg > graal-jvmci-8
comparison src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp @ 22962:2ac41ee91b06
8062591: SPARC PICL causes significantly longer startup times
Summary: Optimize traversals of the PICL tree
Reviewed-by: kvn
author | iveresov |
---|---|
date | Fri, 10 Apr 2015 15:24:50 -0700 |
parents | c49cd31b6da6 |
children | f79d8e8caecb |
comparison
equal
deleted
inserted
replaced
22959:421863f11ad7 | 22962:2ac41ee91b06 |
---|---|
32 #include <kstat.h> | 32 #include <kstat.h> |
33 #include <picl.h> | 33 #include <picl.h> |
34 #include <dlfcn.h> | 34 #include <dlfcn.h> |
35 #include <link.h> | 35 #include <link.h> |
36 | 36 |
37 extern "C" static int PICL_get_l1_data_cache_line_size_helper(picl_nodehdl_t nodeh, void *result); | 37 extern "C" static int PICL_visit_cpu_helper(picl_nodehdl_t nodeh, void *result); |
38 extern "C" static int PICL_get_l2_cache_line_size_helper(picl_nodehdl_t nodeh, void *result); | |
39 | 38 |
40 // Functions from the library we need (signatures should match those in picl.h) | 39 // Functions from the library we need (signatures should match those in picl.h) |
41 extern "C" { | 40 extern "C" { |
42 typedef int (*picl_initialize_func_t)(void); | 41 typedef int (*picl_initialize_func_t)(void); |
43 typedef int (*picl_shutdown_func_t)(void); | 42 typedef int (*picl_shutdown_func_t)(void); |
126 bool is_initial() { return _state == INITIAL; } | 125 bool is_initial() { return _state == INITIAL; } |
127 bool is_assigned() { return _state == ASSIGNED; } | 126 bool is_assigned() { return _state == ASSIGNED; } |
128 bool is_inconsistent() { return _state == INCONSISTENT; } | 127 bool is_inconsistent() { return _state == INCONSISTENT; } |
129 void set_inconsistent() { _state = INCONSISTENT; } | 128 void set_inconsistent() { _state = INCONSISTENT; } |
130 | 129 |
131 static int visit(picl_nodehdl_t nodeh, const char* name, void *arg) { | 130 void visit(picl_nodehdl_t nodeh, const char* name) { |
132 UniqueValueVisitor *state = static_cast<UniqueValueVisitor*>(arg); | 131 assert(!is_inconsistent(), "Precondition"); |
133 PICL* picl = state->_picl; | |
134 assert(!state->is_inconsistent(), "Precondition"); | |
135 int curr; | 132 int curr; |
136 if (picl->get_int_property(nodeh, name, &curr) == PICL_SUCCESS) { | 133 if (_picl->get_int_property(nodeh, name, &curr) == PICL_SUCCESS) { |
137 if (!state->is_assigned()) { // first iteration | 134 if (!is_assigned()) { // first iteration |
138 state->set_value(curr); | 135 set_value(curr); |
139 } else if (curr != state->value()) { // following iterations | 136 } else if (curr != value()) { // following iterations |
140 state->set_inconsistent(); | 137 set_inconsistent(); |
141 } | 138 } |
142 } | 139 } |
143 if (state->is_inconsistent()) { | 140 } |
141 }; | |
142 | |
143 class CPUVisitor { | |
144 UniqueValueVisitor _l1_visitor; | |
145 UniqueValueVisitor _l2_visitor; | |
146 int _limit; // number of times visit() can be run | |
147 public: | |
148 CPUVisitor(PICL *picl, int limit) : _l1_visitor(picl), _l2_visitor(picl), _limit(limit) {} | |
149 static int visit(picl_nodehdl_t nodeh, void *arg) { | |
150 CPUVisitor *cpu_visitor = static_cast<CPUVisitor*>(arg); | |
151 UniqueValueVisitor* l1_visitor = cpu_visitor->l1_visitor(); | |
152 UniqueValueVisitor* l2_visitor = cpu_visitor->l2_visitor(); | |
153 if (!l1_visitor->is_inconsistent()) { | |
154 l1_visitor->visit(nodeh, "l1-dcache-line-size"); | |
155 } | |
156 if (!l2_visitor->is_inconsistent()) { | |
157 l2_visitor->visit(nodeh, "l2-cache-line-size"); | |
158 } | |
159 | |
160 if (l1_visitor->is_inconsistent() && l2_visitor->is_inconsistent()) { | |
144 return PICL_WALK_TERMINATE; | 161 return PICL_WALK_TERMINATE; |
145 } | 162 } |
163 cpu_visitor->_limit--; | |
164 if (cpu_visitor->_limit <= 0) { | |
165 return PICL_WALK_TERMINATE; | |
166 } | |
146 return PICL_WALK_CONTINUE; | 167 return PICL_WALK_CONTINUE; |
147 } | 168 } |
169 UniqueValueVisitor* l1_visitor() { return &_l1_visitor; } | |
170 UniqueValueVisitor* l2_visitor() { return &_l2_visitor; } | |
148 }; | 171 }; |
149 | |
150 int _L1_data_cache_line_size; | 172 int _L1_data_cache_line_size; |
151 int _L2_cache_line_size; | 173 int _L2_cache_line_size; |
152 public: | 174 public: |
153 static int get_l1_data_cache_line_size(picl_nodehdl_t nodeh, void *state) { | 175 static int visit_cpu(picl_nodehdl_t nodeh, void *state) { |
154 return UniqueValueVisitor::visit(nodeh, "l1-dcache-line-size", state); | 176 return CPUVisitor::visit(nodeh, state); |
155 } | 177 } |
156 static int get_l2_cache_line_size(picl_nodehdl_t nodeh, void *state) { | 178 |
157 return UniqueValueVisitor::visit(nodeh, "l2-cache-line-size", state); | 179 PICL(bool is_fujitsu) : _L1_data_cache_line_size(0), _L2_cache_line_size(0), _dl_handle(NULL) { |
158 } | |
159 | |
160 PICL() : _L1_data_cache_line_size(0), _L2_cache_line_size(0), _dl_handle(NULL) { | |
161 if (!open_library()) { | 180 if (!open_library()) { |
162 return; | 181 return; |
163 } | 182 } |
164 if (_picl_initialize() == PICL_SUCCESS) { | 183 if (_picl_initialize() == PICL_SUCCESS) { |
165 picl_nodehdl_t rooth; | 184 picl_nodehdl_t rooth; |
166 if (_picl_get_root(&rooth) == PICL_SUCCESS) { | 185 if (_picl_get_root(&rooth) == PICL_SUCCESS) { |
167 UniqueValueVisitor L1_state(this); | 186 const char* cpu_class = "cpu"; |
168 // Visit all "cpu" class instances | 187 // If it's a Fujitsu machine, it's a "core" |
169 _picl_walk_tree_by_class(rooth, "cpu", &L1_state, PICL_get_l1_data_cache_line_size_helper); | 188 if (is_fujitsu) { |
170 if (L1_state.is_initial()) { // Still initial, iteration found no values | 189 cpu_class = "core"; |
171 // Try walk all "core" class instances, it might be a Fujitsu machine | 190 } |
172 _picl_walk_tree_by_class(rooth, "core", &L1_state, PICL_get_l1_data_cache_line_size_helper); | 191 CPUVisitor cpu_visitor(this, os::processor_count()); |
173 } | 192 _picl_walk_tree_by_class(rooth, cpu_class, &cpu_visitor, PICL_visit_cpu_helper); |
174 if (L1_state.is_assigned()) { // Is there a value? | 193 if (cpu_visitor.l1_visitor()->is_assigned()) { // Is there a value? |
175 _L1_data_cache_line_size = L1_state.value(); | 194 _L1_data_cache_line_size = cpu_visitor.l1_visitor()->value(); |
176 } | 195 } |
177 | 196 if (cpu_visitor.l2_visitor()->is_assigned()) { |
178 UniqueValueVisitor L2_state(this); | 197 _L2_cache_line_size = cpu_visitor.l2_visitor()->value(); |
179 _picl_walk_tree_by_class(rooth, "cpu", &L2_state, PICL_get_l2_cache_line_size_helper); | |
180 if (L2_state.is_initial()) { | |
181 _picl_walk_tree_by_class(rooth, "core", &L2_state, PICL_get_l2_cache_line_size_helper); | |
182 } | |
183 if (L2_state.is_assigned()) { | |
184 _L2_cache_line_size = L2_state.value(); | |
185 } | 198 } |
186 } | 199 } |
187 _picl_shutdown(); | 200 _picl_shutdown(); |
188 } | 201 } |
189 close_library(); | 202 close_library(); |
191 | 204 |
192 unsigned int L1_data_cache_line_size() const { return _L1_data_cache_line_size; } | 205 unsigned int L1_data_cache_line_size() const { return _L1_data_cache_line_size; } |
193 unsigned int L2_cache_line_size() const { return _L2_cache_line_size; } | 206 unsigned int L2_cache_line_size() const { return _L2_cache_line_size; } |
194 }; | 207 }; |
195 | 208 |
196 extern "C" static int PICL_get_l1_data_cache_line_size_helper(picl_nodehdl_t nodeh, void *result) { | 209 |
197 return PICL::get_l1_data_cache_line_size(nodeh, result); | 210 extern "C" static int PICL_visit_cpu_helper(picl_nodehdl_t nodeh, void *result) { |
198 } | 211 return PICL::visit_cpu(nodeh, result); |
199 extern "C" static int PICL_get_l2_cache_line_size_helper(picl_nodehdl_t nodeh, void *result) { | |
200 return PICL::get_l2_cache_line_size(nodeh, result); | |
201 } | 212 } |
202 | 213 |
203 template<typename FuncType> | 214 template<typename FuncType> |
204 bool PICL::bind(FuncType& func, const char* name) { | 215 bool PICL::bind(FuncType& func, const char* name) { |
205 func = reinterpret_cast<FuncType>(dlsym(_dl_handle, name)); | 216 func = reinterpret_cast<FuncType>(dlsym(_dl_handle, name)); |
468 "unknown cpu info (changed kstat interface?)"); | 479 "unknown cpu info (changed kstat interface?)"); |
469 kstat_close(kc); | 480 kstat_close(kc); |
470 } | 481 } |
471 | 482 |
472 // Figure out cache line sizes using PICL | 483 // Figure out cache line sizes using PICL |
473 PICL picl; | 484 PICL picl((features & sparc64_family_m) != 0); |
474 _L2_cache_line_size = picl.L2_cache_line_size(); | 485 _L2_cache_line_size = picl.L2_cache_line_size(); |
475 | 486 |
476 return features; | 487 return features; |
477 } | 488 } |