New issue
Advanced search Search tips

Issue 782027 link

Starred by 1 user

Issue metadata

Status: Available
Owner:
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: ----
Pri: 3
Type: Bug

Blocking:
issue 82385



Sign in to add a comment

clang generates at least eleven static initializers that VC++ did not

Project Member Reported by brucedaw...@chromium.org, Nov 7 2017

Issue description

Running 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;
    };

 
Cc: r...@chromium.org
Components: Build
There may be more of these - it's impossible to tell because the clang dynamic initializer reports merge together multiple initializers from one translation unit.

Comment 2 by r...@chromium.org, 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.

Comment 3 by r...@chromium.org, Nov 16 2017

Cc: inglorion@chromium.org h...@chromium.org
Owner: r...@chromium.org
Status: Assigned (was: Untriaged)
> 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.

Comment 4 by h...@chromium.org, Nov 16 2017

Blocking: 82385

Comment 5 by r...@chromium.org, Nov 17 2017

Owner: ----
Status: Available (was: Assigned)
Project Member

Comment 6 by sheriffbot@chromium.org, Nov 19

Labels: Hotlist-Recharge-Cold
Status: Untriaged (was: Available)
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
Status: Available (was: Untriaged)
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''

Owner: r...@chromium.org
I was able to improve globalopt to handle these cases:
https://reviews.llvm.org/D54774

Sign in to add a comment