The JIT engine plays a vital role in the optimization. It will do assumptions and estimations in parts of our code, then decide what code can be sent directly to execution and which one should be hold to optimize.
The JIT holds some assumptions for our code when it's doing the optimization. With some code is run frequently, the engine will capture the code, make assumption and optimized version for each of its assumption. If the assumption is correct, the optimized code will be pushed to the compiled code and ready for execution, if it's not, the wrongly-optimized code will be trashed out - this is called deoptimization.
Elaborate more on how JIT works - A crash course in just-in-time (JIT) compilers.
The process of op-deop may cause the engine to slow down the run time of the code due to making to many assumptions by the JIT. The browsers solve this problem by limiting how many time the op-deop should occur, if it reaches the limit, the op-deop should be stopped trying and use the baseline code.