Coverage Report

Created: 2025-12-12 07:27

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hermes/lib/BCGen/HBC/TraverseLiteralStrings.cpp
Line
Count
Source
1
/*
2
 * Copyright (c) Meta Platforms, Inc. and affiliates.
3
 *
4
 * This source code is licensed under the MIT license found in the
5
 * LICENSE file in the root directory of this source tree.
6
 */
7
8
#include "hermes/BCGen/HBC/TraverseLiteralStrings.h"
9
#include "hermes/IR/Instrs.h"
10
11
#include <functional>
12
13
namespace {
14
15
using namespace hermes;
16
17
/// \return true if and only if a literal string operand at index \p idx of
18
/// instruction \p I is to be treated as an Identifier during Hermes Bytecode
19
/// generation.
20
485k
bool isIdOperand(Instruction *I, unsigned idx) {
21
485k
#define CASE_WITH_PROP_IDX(INSN) \
22
485k
  case ValueKind::INSN##Kind:    \
23
332k
    return idx == INSN::PropertyIdx
24
25
485k
  switch (I->getKind()) {
26
18.6k
    CASE_WITH_PROP_IDX(DeletePropertyInst);
27
13.8k
    CASE_WITH_PROP_IDX(LoadPropertyInst);
28
0
    CASE_WITH_PROP_IDX(StoreNewOwnPropertyInst);
29
4.09k
    CASE_WITH_PROP_IDX(StorePropertyInst);
30
295k
    CASE_WITH_PROP_IDX(TryLoadGlobalPropertyInst);
31
0
    CASE_WITH_PROP_IDX(TryStoreGlobalPropertyInst);
32
0
    CASE_WITH_PROP_IDX(ThrowIfHasRestrictedGlobalPropertyInst);
33
34
0
    case ValueKind::HBCAllocObjectFromBufferInstKind:
35
      // AllocObjectFromBuffer stores the keys and values as alternating
36
      // operands starting from FirstKeyIdx.
37
0
      return (idx - HBCAllocObjectFromBufferInst::FirstKeyIdx) % 2 == 0;
38
39
153k
    default:
40
153k
      return false;
41
485k
  }
42
485k
#undef CASE
43
485k
}
44
45
} // namespace
46
47
namespace hermes {
48
namespace hbc {
49
50
void traverseFunctions(
51
    Module *M,
52
    std::function<bool(Function *)> shouldVisitFunction,
53
    std::function<void(llvh::StringRef)> traversal,
54
    std::function<void(llvh::StringRef)> functionSourceTraversal,
55
147
    bool stripFunctionNames) {
56
23.2k
  for (auto &F : *M) {
57
23.2k
    if (!shouldVisitFunction(&F)) {
58
0
      continue;
59
0
    }
60
23.2k
    if (!stripFunctionNames) {
61
23.2k
      traversal(F.getOriginalOrInferredName().str());
62
23.2k
    }
63
    // The source visibility of the global function indicate the presence of
64
    // top-level source visibility directives, but we should not preserve the
65
    // source code of the global function.
66
23.2k
    if (!F.isGlobalScope()) {
67
      // Only add non-default source representation to the string table.
68
23.1k
      if (auto source = F.getSourceRepresentationStr()) {
69
0
        functionSourceTraversal(*source);
70
0
      }
71
23.1k
    }
72
23.2k
  }
73
147
}
74
75
void traverseCJSModuleNames(
76
    Module *M,
77
    std::function<bool(Function *)> shouldVisitFunction,
78
147
    std::function<void(llvh::StringRef)> traversal) {
79
23.2k
  for (auto &F : *M) {
80
23.2k
    if (!shouldVisitFunction(&F)) {
81
0
      continue;
82
0
    }
83
84
23.2k
    if (auto *cjsModule = M->findCJSModule(&F)) {
85
0
      traversal(cjsModule->filename.str());
86
0
    }
87
23.2k
  }
88
147
}
89
90
void traverseLiteralStrings(
91
    Module *M,
92
    std::function<bool(Function *)> shouldVisitFunction,
93
147
    std::function<void(llvh::StringRef, bool)> traversal) {
94
  // Walk declared global properties.
95
9.88k
  for (auto *prop : M->getGlobalProperties()) {
96
9.88k
    if (prop->isDeclared()) {
97
0
      traversal(prop->getName()->getValue().str(), /* isIdentifier */ true);
98
0
    }
99
9.88k
  }
100
101
  // Walk functions.
102
23.2k
  for (auto &F : *M) {
103
23.2k
    if (!shouldVisitFunction(&F)) {
104
0
      continue;
105
0
    }
106
107
119k
    for (auto &BB : F) {
108
      // Walk instruction operands.
109
2.21M
      for (auto &I : BB) {
110
6.06M
        for (int i = 0, e = I.getNumOperands(); i < e; i++) {
111
3.84M
          auto *op = I.getOperand(i);
112
3.84M
          if (auto *str = llvh::dyn_cast<LiteralString>(op)) {
113
485k
            traversal(str->getValue().str(), isIdOperand(&I, i));
114
485k
          }
115
3.84M
        }
116
2.21M
      }
117
119k
    }
118
23.2k
  }
119
147
}
120
121
} // namespace hbc
122
} // namespace hermes