There is a substantial risk there unless you can hit all the edge cases and error conditions when profiling. Even a good fuzzer can miss a very rare state. Then when you hit it in real use there's no code to handle it!
Profile-based optimization and JITting is plausible because the corner cases are still there, just not optimized.
I completely agree, that's why in that case you could download the missing code from the server and load it using dynamic linking.
The server would then mark it as reachable so it's delivered as part of the main bundle next time.
I would expect the bundle to converge quickly to the set of functions that are actually reachable.
Aditionally, it's very likely that the sets of reachable code of two versions of the same app have significant overlap, so the information collected for version N could be used as a starting point for N+1, and so on.
Profile-based optimization and JITting is plausible because the corner cases are still there, just not optimized.