Skip to content

Missed juicy code size optimization with -sEXIT_RUNTIME=0 #17872

@juj

Description

@juj

Example code:
a.cpp

#include <vector>
#include <emscripten.h>

std::vector<double> d;

int main()
{
	// just some random stuff to prevent dead code elimination
	for(int i = (int)emscripten_get_now(); i >= 0; --i)
		d.push_back(i);
	return d[d.size()/2];
}

Build with em++ a.cpp -o a.js -Oz -g3 -sEXIT_RUNTIME=0.

The generated code will emit the following global initializer for the std::vector instance in wasm:

 (func $__cxx_global_var_init
  (drop
   (call $std::__2::vector<double\2c\20std::__2::allocator<double>>::vector\28\29
    (i32.const 1684)
   )
  )
  (drop
   (call $__cxa_atexit
    (i32.const 1)
    (i32.const 0)
    (i32.const 1024)
   )
  )
 )

Note the __cxa_atexit call. This should not be present in the generated code, since the code is being built with -sEXIT_RUNTIME=0. This atexit directive is registering a destructor function pointer, which is present in the function pointer table as:

(elem (i32.const 1) $__cxx_global_array_dtor

which is

 (func $__cxx_global_array_dtor (param $0 i32)
  (drop
   (call $std::__2::vector<double\2c\20std::__2::allocator<double>>::~vector\28\29
    (i32.const 1684)
   )
  )
 )

This dtor is likewise never called, since EXIT_RUNTIME=0.

I see that in Unity codebase and other codebases, there are quite a lot of these global dtors and __cxa_atexit directives piling up even when the codebase is built with -sEXIT_RUNTIME=0.

Would there be a good way to get rid of those when the runtime will never exit?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions