Skip to content
Permalink
Browse files Browse the repository at this point in the history
Fix backward branching in SwitchImm.
Summary:
`SwitchImm` can subtract from `ip`, but it was reading the offset
from a `uint32_t *` instead of `int32_t *`.
Change the type to the correct one.

Reviewed By: dulinriley

Differential Revision: D23114516

fbshipit-source-id: d4ddab94eb16dc1ce479590851eeb1ab428bd5d6
  • Loading branch information
avp authored and facebook-github-bot committed Aug 14, 2020
1 parent 5e557a4 commit 2c7af7e
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 2 deletions.
5 changes: 3 additions & 2 deletions lib/VM/Interpreter.cpp
Expand Up @@ -3387,8 +3387,9 @@ CallResult<HermesValue> Interpreter::interpretFunction(
(const uint8_t *)ip + ip->iSwitchImm.op2, sizeof(uint32_t));

// Read the offset from the table.
const uint32_t *loc =
(const uint32_t *)tablestart + uintVal - ip->iSwitchImm.op4;
// Must be signed to account for backwards branching.
const int32_t *loc =
(const int32_t *)tablestart + uintVal - ip->iSwitchImm.op4;

ip = IPADD(*loc);
DISPATCH;
Expand Down
36 changes: 36 additions & 0 deletions test/Optimizer/switch_stmt.js
@@ -0,0 +1,36 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

// RUN: %hermes -O -dump-ir %s | %FileCheck %s

function backwards_branch() {
for (var i = 0; i < 4; i++) {
switch (i) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
break;
}
i = 2;
}
}

// CHECK-LABEL: function backwards_branch() : undefined
// CHECK-NEXT: frame = []
// CHECK-NEXT: %BB0:
// CHECK-NEXT: %0 = BranchInst %BB1
// CHECK-NEXT: %BB1:
// CHECK-NEXT: %1 = PhiInst 0 : number, %BB0, 3 : number, %BB1
// CHECK-NEXT: %2 = SwitchInst %1 : number, %BB1, 0 : number, %BB1, 1 : number, %BB1, 2 : number, %BB1, 3 : number, %BB1, 4 : number, %BB1, 5 : number, %BB1, 6 : number, %BB1, 7 : number, %BB1, 8 : number, %BB1, 9 : number, %BB1
// CHECK-NEXT: function_end
43 changes: 43 additions & 0 deletions test/hermes/switch-regress1.js
@@ -0,0 +1,43 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

// RUN: %hermes -O0 %s | %FileCheck --match-full-lines %s
// RUN: %hermes -O %s | %FileCheck --match-full-lines %s
// RUN: %hermes -O -emit-binary -out %t.hbc %s && %hermes %t.hbc | %FileCheck --match-full-lines %s

// Ensure that switch statements that are backwards branches work properly.

(function() {
var j = 0;
for (var i = 0; i < 4; i++) {
++j;
if (j > 5) {
return;
}
print(i);
switch (i) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
break;
}
i = 2;
}
})();

// CHECK: 0
// CHECK: 3
// CHECK: 3
// CHECK: 3
// CHECK: 3

0 comments on commit 2c7af7e

Please sign in to comment.