clang generates at least eleven static initializers that VC++ did not |
|||||||
Issue descriptionRunning a patched version of tools\win\static_initializers\static_initializers.exe (see crrev.com/c/752187 and crbug.com/777943#c6 ) on chrome.exe, chrome.dll, and chrome_child.dll shows eleven constructors for 'id' objects. These constructors are not present in VC++ builds. The reports look like this: C:\b\c\b\win64_clang\src\out\Release_x64\obj\chrome\main_dll\chrome_main.obj: std::num_put<char,std::ostreambuf_iterator<char,std::char_traits<char> > >::`dynamic initializer for 'id'' C:\b\c\b\win64_clang\src\out\Release_x64\obj\chrome\main_dll\chrome_main.obj: std::numpunct<char>::`dynamic initializer for 'id'' C:\b\c\b\win64_clang\src\out\Release_x64\obj\media\base\base\audio_hash.obj: std::num_get<char,std::istreambuf_iterator<char,std::char_traits<char> > >::`dynamic initializer for 'id'' C:\b\c\b\win64_clang\src\out\Release_x64\obj\tools\battor_agent\battor_agent_lib\battor_connection_impl.obj: std::codecvt<char,char,_Mbstatet>::`dynamic initializer for 'id'' C:\b\c\b\win64_clang\src\out\Release_x64\obj\chrome\chrome_child\chrome_main.obj: std::num_put<char,std::ostreambuf_iterator<char,std::char_traits<char> > >::`dynamic initializer for 'id'' C:\b\c\b\win64_clang\src\out\Release_x64\obj\chrome\chrome_child\chrome_main.obj: std::numpunct<char>::`dynamic initializer for 'id'' C:\b\c\b\win64_clang\src\out\Release_x64\obj\media\base\base\audio_hash.obj: std::num_get<char,std::istreambuf_iterator<char,std::char_traits<char> > >::`dynamic initializer for 'id'' C:\b\c\b\win64_clang\src\out\Release_x64\obj\tools\battor_agent\battor_agent_lib\battor_connection_impl.obj: std::codecvt<char,char,_Mbstatet>::`dynamic initializer for 'id'' C:\b\c\b\win64_clang\src\out\Release_x64\obj\chrome\chrome_initial\chrome_exe_main_win.obj: std::num_put<char,std::ostreambuf_iterator<char,std::char_traits<char> > >::`dynamic initializer for 'id'' C:\b\c\b\win64_clang\src\out\Release_x64\obj\chrome\chrome_initial\chrome_exe_main_win.obj: std::numpunct<char>::`dynamic initializer for 'id'' C:\b\c\b\win64_clang\src\out\Release_x64\obj\third_party\breakpad\breakpad_sender\http_upload.obj: std::codecvt<char,char,_Mbstatet>::`dynamic initializer for 'id'' A typical variable declaration looks like this: __PURE_APPDOMAIN_GLOBAL static locale::id id; The __PURE_APPDOMAIN_GLOBAL define appears to map to nothing so the problem is purely with the class constructor, which looks pretty simple: class _CRTIMP2_PURE_IMPORT id { // identifier stamp, unique for each distinct kind of facet public: __CLR_OR_THIS_CALL id(size_t _Val = 0) : _Id(_Val) { // construct with specified stamp value } __CLR_OR_THIS_CALL operator size_t() { // get stamp, with lazy allocation if (_Id == 0) { // still zero, allocate stamp _BEGIN_LOCK(_LOCK_LOCALE) if (_Id == 0) _Id = ++_Id_cnt; _END_LOCK() } return (_Id); } private: size_t _Id; // the identifier stamp __PURE_APPDOMAIN_GLOBAL static int _Id_cnt; public: __CLR_OR_THIS_CALL id(const id&) = delete; id& __CLR_OR_THIS_CALL operator=(const id&) = delete; };
,
Nov 16 2017
Here's a possible reduction:
#include <iostream>
int main() {
double d = 42.3;
std::cout << d << '\n';
}
$ cl -O2 -Z7 t.cpp -nologo -D_HAS_EXCEPTIONS=0
t.cpp
$ /c/src/chromium/src/tools/win/static_initializers/static_initializers.exe t.exe | grep num_put
$ clang-cl -O2 -Z7 t.cpp -nologo -D_HAS_EXCEPTIONS=0
$ /c/src/chromium/src/tools/win/static_initializers/static_initializers.exe t.exe | grep num_put
C:\Users\rnk\AppData\Local\Temp\t-39a1a9.obj: std::num_put<char,std::ostreambuf_iterator<char,std::char_traits<char> > >::`dynamic initializer for 'id''
The optimization level doesn't matter. I guess clang thinks it needs this 'id' global but MSVC doesn't.
,
Nov 16 2017
> The optimization level doesn't matter. I guess clang thinks it needs this 'id' global but MSVC doesn't.
I was wrong, it does matter. Here's a nicer reduction:
struct my_id {
my_id() : v_(0) {}
int v_;
};
template <typename T> struct Foo {
static my_id id;
};
template <typename T> my_id Foo<T>::id;
int main() { Foo<char>::id.v_++; }
So, this is a missing optimization in LLVM. LLVM's globalopt pass is supposed to handle this, but it gives up too easily. The COMDAT scheme that Microsoft uses is clever and allows the compiler to optimize this to static initialization without changing the ABI.
,
Nov 16 2017
,
Nov 17 2017
,
Nov 19
This issue has been Available for over a year. If it's no longer important or seems unlikely to be fixed, please consider closing it out. If it is important, please re-triage the issue. Sorry for the inconvenience if the bug really should have been left as Available. For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
,
Nov 19
This issue is still relevant. It's not critical, but we would like to reduce our number of dynamic initializers. As before we have eleven coming from the 'id' pattern discussed above. I filed a clang-cl bug for this possible optimization: https://bugs.llvm.org/show_bug.cgi?id=39712 The remaining static initializers are mostly coming from Microsoft's libraries so there is nothing we can do about them except. Here are the results of running the static_initializers tool on the three main Chrome binaries. First I ran these three commands to get the symbols: set _NT_SYMBOL_PATH=SRV*C:\symbols*https://msdl.microsoft.com/download/symbols;SRV*C:\symbols*https://chromium-browser-symsrv.commondatastorage.googleapis.com "c:\Program Files (x86)\Windows Kits\10\Debuggers\x64\symchk.exe" /os /ob /op /r "C:\Users\brucedawson\AppData\Local\Google\Chrome SxS\Application\*.dll" "c:\Program Files (x86)\Windows Kits\10\Debuggers\x64\symchk.exe" /os /ob /op /r "C:\Users\brucedawson\AppData\Local\Google\Chrome SxS\Application\*.exe" Here are the initializer results: c:\src\chromium4\src>tools\win\static_initializers\static_initializers.exe "C:\Users\brucedawson\AppData\Local\Google\Chrome SxS\Application\chrome.exe" | find "dynamic initializer" C:\b\c\b\win64_clang\src\out\Release_x64\obj\chrome\chrome_initial\chrome_exe_main_win.obj: `dynamic initializer for 'std::num_put<char,std::ostreambuf_iterator<char,std::char_traits<char> > >::id'' C:\b\c\b\win64_clang\src\out\Release_x64\obj\chrome\chrome_initial\chrome_exe_main_win.obj: `dynamic initializer for 'std::numpunct<char>::id'' C:\b\c\b\win64_clang\src\out\Release_x64\obj\third_party\breakpad\breakpad_sender\http_upload.obj: `dynamic initializer for 'std::codecvt<char,char,_Mbstatet>::id'' f:\binaries\Intermediate\vctools\libcpmt.nativeproj_366855620\objr\amd64\xlock.obj: std::`dynamic initializer for 'initlocks'' f:\binaries\Intermediate\vctools\libcpmt.nativeproj_366855620\objr\amd64\locale0.obj: std::`dynamic initializer for '_Fac_tidy_reg'' f:\binaries\Intermediate\vctools\libcpmt.nativeproj_366855620\objr\amd64\locale0.obj: std::`dynamic initializer for 'classic_locale'' f:\binaries\Intermediate\vctools\libcpmt.nativeproj_366855620\objr\amd64\iosptrs.obj: `dynamic initializer for 'init_atexit'' f:\binaries\Intermediate\vctools\libcpmt.nativeproj_366855620\objr\amd64\iosptrs.obj: std::`dynamic initializer for 'initlocks'' f:\binaries\Intermediate\vctools\libcpmt.nativeproj_366855620\objr\amd64\cerr.obj: std::`dynamic initializer for 'cerr'' f:\binaries\Intermediate\vctools\libcpmt.nativeproj_366855620\objr\amd64\cerr.obj: std::`dynamic initializer for 'ferr'' f:\binaries\Intermediate\vctools\libcpmt.nativeproj_366855620\objr\amd64\cerr.obj: std::`dynamic initializer for 'init_cerr'' f:\binaries\Intermediate\vctools\libcpmt.nativeproj_366855620\objr\amd64\cerr.obj: `dynamic initializer for 'initlocks'' f:\binaries\Intermediate\vctools\atls.nativeproj_950353558\objr\amd64\atlbase.obj: ATL::`dynamic initializer for '_AtlBaseModule'' f:\binaries\Intermediate\vctools\libconcrt.nativeproj__2086454777\objr\amd64\Platform.obj: Concurrency::details::platform::`dynamic initializer for 's_defaultWaiterPool'' f:\binaries\Intermediate\vctools\libconcrt.nativeproj__2086454777\objr\amd64\utils.obj: Concurrency::details::`dynamic initializer for 'g_DebugOutFilePtr'' f:\binaries\Intermediate\vctools\libconcrt.nativeproj__2086454777\objr\amd64\staticinits.obj: `dynamic initializer for 'Concurrency::details::Security::s_cookie'' f:\binaries\Intermediate\vctools\libconcrt.nativeproj__2086454777\objr\amd64\staticinits.obj: `dynamic initializer for 'Concurrency::details::SchedulerBase::s_subAllocatorFreePool'' c:\src\chromium4\src>tools\win\static_initializers\static_initializers.exe "C:\Users\brucedawson\AppData\Local\Google\Chrome SxS\Application\72.0.3615.0\chrome.dll" | find "dynamic initializer" C:\b\c\b\win64_clang\src\out\Release_x64\obj\chrome\main_dll\chrome_main.obj: `dynamic initializer for 'std::num_put<char,std::ostreambuf_iterator<char,std::char_traits<char> > >::id'' C:\b\c\b\win64_clang\src\out\Release_x64\obj\chrome\main_dll\chrome_main.obj: `dynamic initializer for 'std::numpunct<char>::id'' C:\b\c\b\win64_clang\src\out\Release_x64\obj\chrome\main_dll\chrome_main_delegate.obj: ATL::`dynamic initializer for '_AtlWinModule'' C:\b\c\b\win64_clang\src\out\Release_x64\obj\third_party\openh264\common\WelsThreadPool.obj: _GLOBAL__sub_I_WelsThreadPool.cpp (dynamic initializer) C:\b\c\b\win64_clang\src\out\Release_x64\obj\skia\skia_core_and_effects\SkExecutor.obj: _GLOBAL__sub_I_SkExecutor.cpp (dynamic initializer) C:\b\c\b\win64_clang\src\out\Release_x64\obj\media\base\base\audio_hash.obj: `dynamic initializer for 'std::num_get<char,std::istreambuf_iterator<char,std::char_traits<char> > >::id'' C:\b\c\b\win64_clang\src\out\Release_x64\obj\media\device_monitors\device_monitors\system_message_window_win.obj: _GLOBAL__sub_I_system_message_window_win.cc (dynamic initializer) C:\b\c\b\win64_clang\src\out\Release_x64\obj\chrome\browser\web_applications\extensions\extensions\web_app_extension_shortcut.obj: _GLOBAL__sub_I_web_app_extension_shortcut.cc (dynamic initializer) obj/base\base/file_util.obj: `dynamic initializer for 'std::codecvt<char,char,_Mbstatet>::id'' f:\binaries\Intermediate\vctools\libcpmt.nativeproj_366855620\objr\amd64\xlock.obj: std::`dynamic initializer for 'initlocks'' f:\binaries\Intermediate\vctools\libcpmt.nativeproj_366855620\objr\amd64\locale0.obj: std::`dynamic initializer for '_Fac_tidy_reg'' f:\binaries\Intermediate\vctools\libcpmt.nativeproj_366855620\objr\amd64\locale0.obj: std::`dynamic initializer for 'classic_locale'' f:\binaries\Intermediate\vctools\atls.nativeproj_950353558\objr\amd64\atlbase.obj: ATL::`dynamic initializer for '_AtlBaseModule'' obj/media/capture\capture_lib/video_capture_device_factory_win.obj: _GLOBAL__sub_I_video_capture_device_factory_win.cc (dynamic initializer) obj/third_party/unrar\unrar/unicode.obj: _GLOBAL__sub_I_unicode.cpp (dynamic initializer) obj/third_party/unrar\unrar/secpassword.obj: _GLOBAL__sub_I_secpassword.cpp (dynamic initializer) f:\binaries\Intermediate\vctools\libcpmt.nativeproj_366855620\objr\amd64\iosptrs.obj: `dynamic initializer for 'init_atexit'' f:\binaries\Intermediate\vctools\libcpmt.nativeproj_366855620\objr\amd64\iosptrs.obj: std::`dynamic initializer for 'initlocks'' obj/chrome/browser\browser/browser_switcher_service.obj: _GLOBAL__sub_I_browser_switcher_service.cc (dynamic initializer) obj/chrome/browser\browser/sw_reporter_installer_win.obj: _GLOBAL__sub_I_sw_reporter_installer_win.cc (dynamic initializer) f:\binaries\Intermediate\vctools\libcpmt.nativeproj_366855620\objr\amd64\cerr.obj: std::`dynamic initializer for 'cerr'' f:\binaries\Intermediate\vctools\libcpmt.nativeproj_366855620\objr\amd64\cerr.obj: std::`dynamic initializer for 'ferr'' f:\binaries\Intermediate\vctools\libcpmt.nativeproj_366855620\objr\amd64\cerr.obj: std::`dynamic initializer for 'init_cerr'' f:\binaries\Intermediate\vctools\libcpmt.nativeproj_366855620\objr\amd64\cerr.obj: `dynamic initializer for 'initlocks'' obj/device/bluetooth\bluetooth/bluetooth_task_manager_win.obj: _GLOBAL__sub_I_bluetooth_task_manager_win.cc (dynamic initializer) obj/ui/shell_dialogs\shell_dialogs/base_shell_dialog_win.obj: _GLOBAL__sub_I_base_shell_dialog_win.cc (dynamic initializer) obj/skia\skia/SkScalerContext_win_dw.obj: _GLOBAL__sub_I_SkScalerContext_win_dw.cpp (dynamic initializer) f:\binaries\Intermediate\vctools\libconcrt.nativeproj__2086454777\objr\amd64\Platform.obj: Concurrency::details::platform::`dynamic initializer for 's_defaultWaiterPool'' f:\binaries\Intermediate\vctools\libconcrt.nativeproj__2086454777\objr\amd64\utils.obj: Concurrency::details::`dynamic initializer for 'g_DebugOutFilePtr'' f:\binaries\Intermediate\vctools\comsuppw.nativeproj__261200648\objr\amd64\comutil.obj: `dynamic initializer for 'vtMissing'' f:\binaries\Intermediate\vctools\libconcrt.nativeproj__2086454777\objr\amd64\staticinits.obj: `dynamic initializer for 'Concurrency::details::Security::s_cookie'' f:\binaries\Intermediate\vctools\libconcrt.nativeproj__2086454777\objr\amd64\staticinits.obj: `dynamic initializer for 'Concurrency::details::SchedulerBase::s_subAllocatorFreePool'' obj/chrome/browser/ui\ui/taskbar_decorator_win.obj: _GLOBAL__sub_I_taskbar_decorator_win.cc (dynamic initializer) c:\src\chromium4\src>tools\win\static_initializers\static_initializers.exe "C:\Users\brucedawson\AppData\Local\Google\Chrome SxS\Application\72.0.3615.0\chrome_child.dll" | find "dynamic initializer" C:\b\c\b\win64_clang\src\out\Release_x64\obj\chrome\chrome_child\chrome_main.obj: `dynamic initializer for 'std::num_put<char,std::ostreambuf_iterator<char,std::char_traits<char> > >::id'' C:\b\c\b\win64_clang\src\out\Release_x64\obj\chrome\chrome_child\chrome_main.obj: `dynamic initializer for 'std::numpunct<char>::id'' C:\b\c\b\win64_clang\src\out\Release_x64\obj\chrome\chrome_child\chrome_main_delegate.obj: ATL::`dynamic initializer for '_AtlWinModule'' C:\b\c\b\win64_clang\src\out\Release_x64\obj\third_party\openh264\common\WelsThreadPool.obj: _GLOBAL__sub_I_WelsThreadPool.cpp (dynamic initializer) C:\b\c\b\win64_clang\src\out\Release_x64\obj\skia\skia_core_and_effects\SkExecutor.obj: _GLOBAL__sub_I_SkExecutor.cpp (dynamic initializer) C:\b\c\b\win64_clang\src\out\Release_x64\obj\media\base\base\audio_hash.obj: `dynamic initializer for 'std::num_get<char,std::istreambuf_iterator<char,std::char_traits<char> > >::id'' C:\b\c\b\win64_clang\src\out\Release_x64\obj\media\device_monitors\device_monitors\system_message_window_win.obj: _GLOBAL__sub_I_system_message_window_win.cc (dynamic initializer) C:\b\c\b\win64_clang\src\out\Release_x64\obj\v8\v8_base\graph-visualizer.obj: `dynamic initializer for 'std::codecvt<char,char,_Mbstatet>::id'' f:\binaries\Intermediate\vctools\libcpmt.nativeproj_366855620\objr\amd64\xlock.obj: std::`dynamic initializer for 'initlocks'' f:\binaries\Intermediate\vctools\libcpmt.nativeproj_366855620\objr\amd64\locale0.obj: std::`dynamic initializer for '_Fac_tidy_reg'' f:\binaries\Intermediate\vctools\libcpmt.nativeproj_366855620\objr\amd64\locale0.obj: std::`dynamic initializer for 'classic_locale'' f:\binaries\Intermediate\vctools\atls.nativeproj_950353558\objr\amd64\atlbase.obj: ATL::`dynamic initializer for '_AtlBaseModule'' obj/media/capture\capture_lib/video_capture_device_factory_win.obj: _GLOBAL__sub_I_video_capture_device_factory_win.cc (dynamic initializer) obj/ui/shell_dialogs\shell_dialogs/base_shell_dialog_win.obj: _GLOBAL__sub_I_base_shell_dialog_win.cc (dynamic initializer) obj/third_party/unrar\unrar/unicode.obj: _GLOBAL__sub_I_unicode.cpp (dynamic initializer) obj/third_party/unrar\unrar/secpassword.obj: _GLOBAL__sub_I_secpassword.cpp (dynamic initializer) f:\binaries\Intermediate\vctools\libcpmt.nativeproj_366855620\objr\amd64\iosptrs.obj: `dynamic initializer for 'init_atexit'' f:\binaries\Intermediate\vctools\libcpmt.nativeproj_366855620\objr\amd64\iosptrs.obj: std::`dynamic initializer for 'initlocks'' f:\binaries\Intermediate\vctools\libcpmt.nativeproj_366855620\objr\amd64\cerr.obj: std::`dynamic initializer for 'cerr'' f:\binaries\Intermediate\vctools\libcpmt.nativeproj_366855620\objr\amd64\cerr.obj: std::`dynamic initializer for 'ferr'' f:\binaries\Intermediate\vctools\libcpmt.nativeproj_366855620\objr\amd64\cerr.obj: std::`dynamic initializer for 'init_cerr'' f:\binaries\Intermediate\vctools\libcpmt.nativeproj_366855620\objr\amd64\cerr.obj: `dynamic initializer for 'initlocks'' obj/device/bluetooth\bluetooth/bluetooth_task_manager_win.obj: _GLOBAL__sub_I_bluetooth_task_manager_win.cc (dynamic initializer) obj/skia\skia/SkScalerContext_win_dw.obj: _GLOBAL__sub_I_SkScalerContext_win_dw.cpp (dynamic initializer) f:\binaries\Intermediate\vctools\libconcrt.nativeproj__2086454777\objr\amd64\Platform.obj: Concurrency::details::platform::`dynamic initializer for 's_defaultWaiterPool'' f:\binaries\Intermediate\vctools\libconcrt.nativeproj__2086454777\objr\amd64\utils.obj: Concurrency::details::`dynamic initializer for 'g_DebugOutFilePtr'' f:\binaries\Intermediate\vctools\libconcrt.nativeproj__2086454777\objr\amd64\staticinits.obj: `dynamic initializer for 'Concurrency::details::Security::s_cookie'' f:\binaries\Intermediate\vctools\libconcrt.nativeproj__2086454777\objr\amd64\staticinits.obj: `dynamic initializer for 'Concurrency::details::SchedulerBase::s_subAllocatorFreePool''
,
Nov 20
I was able to improve globalopt to handle these cases: https://reviews.llvm.org/D54774 |
|||||||
►
Sign in to add a comment |
|||||||
Comment 1 by brucedaw...@chromium.org
, Nov 7 2017Components: Build