@@ -4681,11 +4681,26 @@ private static boolean profileCondition(byte[] data, final int profileOffset, bo
4681
4681
}
4682
4682
4683
4683
private static void updateBranchTableProfile (byte [] data , final int counterOffset , final int profileOffset ) {
4684
- assert CompilerDirectives . inInterpreter ();
4684
+ CompilerAsserts . neverPartOfCompilation ();
4685
4685
int counter = rawPeekU16 (data , counterOffset );
4686
+ int profile = rawPeekU16 (data , profileOffset );
4687
+ /*
4688
+ * Even if the total hit counter has already reached the limit, we need to increment the
4689
+ * branch profile counter from 0 to 1 iff it's still 0 to mark the branch as having been
4690
+ * taken at least once, to prevent recurrent deoptimizations due to profileBranchTable
4691
+ * assuming that a value of 0 means the branch has never been reached.
4692
+ *
4693
+ * Similarly, we need to make sure we never increase any branch counter to the max value,
4694
+ * otherwise we can get into a situation where both the branch and the total counter values
4695
+ * are at the max value that we cannot recover from since we never decrease counter values;
4696
+ * profileBranchTable would then deoptimize every time that branch is not taken (see below).
4697
+ */
4698
+ assert profile != MAX_TABLE_PROFILE_VALUE ;
4686
4699
if (counter < MAX_TABLE_PROFILE_VALUE ) {
4687
4700
BinaryStreamParser .writeU16 (data , counterOffset , counter + 1 );
4688
- BinaryStreamParser .writeU16 (data , profileOffset , rawPeekU16 (data , profileOffset ) + 1 );
4701
+ }
4702
+ if ((counter < MAX_TABLE_PROFILE_VALUE || profile == 0 ) && (profile < MAX_TABLE_PROFILE_VALUE - 1 )) {
4703
+ BinaryStreamParser .writeU16 (data , profileOffset , profile + 1 );
4689
4704
}
4690
4705
}
4691
4706
0 commit comments