The big advantage in optimizing a trace at a time is that you don't have inbound control flow. In fact, the first transform that a tracing JIT does to the code (trace extraction) can be seen as removing every inbound CF edge except the loop head (leaving them in the deoptimized version of the trace).
One reason for that is that it makes optimization of the trace a lot easier since every forward dataflow problem (e.g. constant propagation or type inference) becomes more precise :
if a is a string && b is a string
x = concat(a,b)
else if a is a int && b is a int
x = add_int(a,b)
else ...
if you have knowledge (thanks to runtime instrumentation) that most of the time the second branch is taken, you can transform it to :
bail if a is a string && b is a string
bail if !(a is a int && b is a int)
x = add_int(a,b)
...
(where bail goes to the full code at the right place)
This version is a lot easier to analyze because you don't have to worry about what might be true in alternate branches : for example, since we can assume we didn't bail out, at the end of this snippet x is always an integer.
There is no reason to my knowledge why they couldn't support unbiased branches by including them in a trace, but it would complicate the implementation of various (forward) optimizing passes which don't have to worry about control flow in a single-trace model.
One reason for that is that it makes optimization of the trace a lot easier since every forward dataflow problem (e.g. constant propagation or type inference) becomes more precise :
if you have knowledge (thanks to runtime instrumentation) that most of the time the second branch is taken, you can transform it to : (where bail goes to the full code at the right place)This version is a lot easier to analyze because you don't have to worry about what might be true in alternate branches : for example, since we can assume we didn't bail out, at the end of this snippet x is always an integer.
There is no reason to my knowledge why they couldn't support unbiased branches by including them in a trace, but it would complicate the implementation of various (forward) optimizing passes which don't have to worry about control flow in a single-trace model.