Skip to content

Commit f836954

Browse files
authored
Merge pull request #90 from bulasevich/GR-60616
2 parents b84bb16 + c174dbd commit f836954

File tree

1 file changed

+37
-20
lines changed

1 file changed

+37
-20
lines changed

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/nodes/WasmFunctionNode.java

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -435,15 +435,17 @@ public Object executeBodyFromOffset(WasmContext context, WasmInstance instance,
435435
stackPointer--;
436436
int index = popInt(frame, stackPointer);
437437
final int size = rawPeekU8(bytecode, offset);
438-
if (index < 0 || index >= size) {
439-
// If unsigned index is larger or equal to the table size use the
440-
// default (last) index.
441-
index = size - 1;
442-
}
438+
final int counterOffset = offset + 1;
443439

444440
if (CompilerDirectives.inInterpreter()) {
441+
if (index < 0 || index >= size) {
442+
// If unsigned index is larger or equal to the table size use the
443+
// default (last) index.
444+
index = size - 1;
445+
}
446+
445447
final int indexOffset = offset + 3 + index * 6;
446-
updateBranchTableProfile(bytecode, offset + 1, indexOffset + 4);
448+
updateBranchTableProfile(bytecode, counterOffset, indexOffset + 4);
447449
final int offsetDelta = rawPeekI32(bytecode, indexOffset);
448450
offset = indexOffset + offsetDelta;
449451
break;
@@ -453,29 +455,30 @@ public Object executeBodyFromOffset(WasmContext context, WasmInstance instance,
453455
// time constants, since the loop is unrolled.
454456
for (int i = 0; i < size; i++) {
455457
final int indexOffset = offset + 3 + i * 6;
456-
if (profileBranchTable(bytecode, offset + 1, indexOffset + 4, i == index)) {
458+
if (profileBranchTable(bytecode, counterOffset, indexOffset + 4, i == index || i == size - 1)) {
457459
final int offsetDelta = rawPeekI32(bytecode, indexOffset);
458460
offset = indexOffset + offsetDelta;
459461
continue loop;
460462
}
461463
}
464+
throw CompilerDirectives.shouldNotReachHere("br_table");
462465
}
463-
enterErrorBranch();
464-
throw WasmException.create(Failure.UNSPECIFIED_INTERNAL, this, "Should not reach here");
465466
}
466467
case Bytecode.BR_TABLE_I32: {
467468
stackPointer--;
468469
int index = popInt(frame, stackPointer);
469470
final int size = rawPeekI32(bytecode, offset);
470-
if (index < 0 || index >= size) {
471-
// If unsigned index is larger or equal to the table size use the
472-
// default (last) index.
473-
index = size - 1;
474-
}
471+
final int counterOffset = offset + 4;
475472

476473
if (CompilerDirectives.inInterpreter()) {
474+
if (index < 0 || index >= size) {
475+
// If unsigned index is larger or equal to the table size use the
476+
// default (last) index.
477+
index = size - 1;
478+
}
479+
477480
final int indexOffset = offset + 6 + index * 6;
478-
updateBranchTableProfile(bytecode, offset + 4, indexOffset + 4);
481+
updateBranchTableProfile(bytecode, counterOffset, indexOffset + 4);
479482
final int offsetDelta = rawPeekI32(bytecode, indexOffset);
480483
offset = indexOffset + offsetDelta;
481484
break;
@@ -485,15 +488,14 @@ public Object executeBodyFromOffset(WasmContext context, WasmInstance instance,
485488
// time constants, since the loop is unrolled.
486489
for (int i = 0; i < size; i++) {
487490
final int indexOffset = offset + 6 + i * 6;
488-
if (profileBranchTable(bytecode, offset + 1, indexOffset + 4, i == index)) {
491+
if (profileBranchTable(bytecode, counterOffset, indexOffset + 4, i == index || i == size - 1)) {
489492
final int offsetDelta = rawPeekI32(bytecode, indexOffset);
490493
offset = indexOffset + offsetDelta;
491494
continue loop;
492495
}
493496
}
497+
throw CompilerDirectives.shouldNotReachHere("br_table");
494498
}
495-
enterErrorBranch();
496-
throw WasmException.create(Failure.UNSPECIFIED_INTERNAL, this, "Should not reach here");
497499
}
498500
case Bytecode.CALL_U8:
499501
case Bytecode.CALL_I32: {
@@ -4679,11 +4681,26 @@ private static boolean profileCondition(byte[] data, final int profileOffset, bo
46794681
}
46804682

46814683
private static void updateBranchTableProfile(byte[] data, final int counterOffset, final int profileOffset) {
4682-
assert CompilerDirectives.inInterpreter();
4684+
CompilerAsserts.neverPartOfCompilation();
46834685
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;
46844699
if (counter < MAX_TABLE_PROFILE_VALUE) {
46854700
BinaryStreamParser.writeU16(data, counterOffset, counter + 1);
4686-
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);
46874704
}
46884705
}
46894706

0 commit comments

Comments
 (0)