/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 |