Skip to content

Remove unnecessary control flow#10363

Open
niloc132 wants to merge 45 commits into
gwtproject:mainfrom
niloc132:10248-remove-pointless-returns
Open

Remove unnecessary control flow#10363
niloc132 wants to merge 45 commits into
gwtproject:mainfrom
niloc132:10248-remove-pointless-returns

Conversation

@niloc132

@niloc132 niloc132 commented Jul 9, 2026

Copy link
Copy Markdown
Member

Removes trailing returns in methods and non-loop blocks, breaks in switches, and continues in loops. Returns at the end of loops can be replaced by breaks if the loop is the last statement of the method. By itself, will make no difference in runtime performance, but by removing these can reduce simple byte count and and avoid the appearance of control flow that could prevent pruning or inlining.

Generally speaking, this seems like a silly optimization to make - developers won't end void methods with return or loop blocks with continue, but as other code gets optimized away, these end up being left and can't be removed any other way.

There is a risk here for size regressions through making a method easier to inline, though adding explicit return isn't intended as a way to preventing inlining.

This is a necessary prerequisite for #10240 to avoid risking avoidable size regressions.

Fixes #10248

@niloc132 niloc132 added this to the 2.14 milestone Jul 9, 2026
@niloc132

niloc132 commented Jul 9, 2026

Copy link
Copy Markdown
Member Author

Here are some simple changes in the Hello sample that are caused by this patch:

 function dispatchCapturedMouseEvent(evt){
   $clinit_DOM();
-  return;
 }

The first shows the main point of the change, that return should have been optimized out when the rest of the method was removed. Original Java for reference:

private static void dispatchCapturedMouseEvent(Event evt) {
boolean cancelled = !DOM.previewEvent(evt);
if (cancelled || captureElem == null) {
return;
}
if (DOM.dispatchEvent(evt, captureElem)) {
evt.stopPropagation();
}
}

I didn't chase the rest of the optimization, but likely the sCaptureElem field is always null for this project, so the first if is always true, and the rest of the method goes away.

Compiling the Showcase shows that Tree has another such example

case KeyCodes.KEY_RIGHT: {
maybeExpandTreeItem();
break;
}
default: {
return;
}

IntelliJ calls out this pointless return at least, and the optimized output also loses the default and preceding `break.

     case 39:
       {
         topClosedParent = $getTopClosedParent(this$static, this$static.curSelection);
         topClosedParent?$setSelectedItem(this$static, topClosedParent):this$static.curSelection.open?$getChildCount(this$static.curSelection) > 0 && $setSelectedItem(this$static, $getChild(this$static.curSelection, 0)):$setState(this$static.curSelection, true, true);
-        break;
-      }
-
-    default:{
-        return;
       }
 
   }
 }

This is one of a handful of "okay, maybe developers do leave in useless keywords" that we can benefit from (see also PopupPanel, AbstractHasData, SplitPanel, SplitLayoutPanel, CellBrowser, CellTree, CellGridImpl, ...).


With that said, the largest Showcase permutation only loses about 100 bytes from just this patch, about 0.05%, while Hello loses about 7 bytes.

EDIT Updated to reflect comparing compiled output with that of #10270, which should merge first.

@niloc132

niloc132 commented Jul 9, 2026

Copy link
Copy Markdown
Member Author

These long running branches got me a little backwards - most of this could/should be moved over to #10270 to make this patch a little simpler, and that PR should land first. I'll make that change so this PR is a little more focused.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remove unnecessary returns in compiled output

1 participant