• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <gtest/gtest.h>
17 
18 #include "assembler/assembly-parser.h"
19 
20 #include "bytecode_optimizer/optimize_bytecode.h"
21 
22 namespace panda::bytecodeopt {
23 using LiteralArray = pandasm::LiteralArray;
24 using Literal = LiteralArray::Literal;
25 using LiteralTag = panda_file::LiteralTag;
26 
27 class ExcludedKeysTest : public testing::Test {
28 public:
SetUpTestCase(void)29     static void SetUpTestCase(void) {};
TearDownTestCase(void)30     static void TearDownTestCase(void) {};
SetUp()31     void SetUp() {};
TearDown()32     void TearDown() {};
33 
EmitAndOptimize(const std::string & abc_file_name,panda::pandasm::Program & program) const34     void EmitAndOptimize(const std::string &abc_file_name, panda::pandasm::Program &program) const
35     {
36         panda::pandasm::AsmEmitter::PandaFileToPandaAsmMaps panda_file_to_asm_maps {};
37         EXPECT_TRUE(panda::pandasm::AsmEmitter::Emit(abc_file_name, program, nullptr, &panda_file_to_asm_maps, false));
38         EXPECT_TRUE(panda::bytecodeopt::OptimizeBytecode(&program, &panda_file_to_asm_maps, abc_file_name, true));
39     }
40 };
41 
42 HWTEST_F(ExcludedKeysTest, excluded_keys_001, testing::ext::TestSize.Level1)
43 {
44     /* js source code
45     function foo()
46     {
47         let {a, b, c, ...d} = {a:'a', b:'b', c:'c', f:'f', e:'e'}
48     }
49     */
50     const auto source = R"(
51         .language ECMAScript
52         .function any foo(any a0, any a1, any a2) {
53             mov v0, a0
54             mov v1, a1
55             mov v2, a2
56             ldundefined
57             sta v3
58             lda v3
59             sta v3
60             sta v4
61             lda v4
62             ldobjbyname 0x1, "a"
63             sttoglobalrecord 0x3, "a"
64             lda v4
65             ldobjbyname 0x4, "b"
66             sttoglobalrecord 0x6, "b"
67             lda v4
68             ldobjbyname 0x7, "c"
69             sttoglobalrecord 0x9, "c"
70             lda.str "a"
71             sta v9
72             lda.str "b"
73             sta v10
74             lda.str "c"
75             sta v11
76             createobjectwithexcludedkeys 0x2, v4, v9
77             sttoglobalrecord 0xa, "d"
78             lda v3
79             returnundefined
80         }
81     )";
82     panda::pandasm::Parser parser;
83     auto res = parser.Parse(source);
84     auto &program = res.Value();
85     const std::string fun_name = "foo:(any,any,any)";
86     auto it = program.function_table.find(fun_name);
87     EXPECT_NE(it, program.function_table.end());
88     auto &func = it->second;
89 
90     EmitAndOptimize("ExcludedKeysTest1.abc", program);
91 
92     // Collect valid instructions
93     std::vector<panda::pandasm::Ins> insns;
94     for (const auto &in : func.ins) {
95         if (in.opcode != panda::pandasm::Opcode::INVALID) {
96             insns.emplace_back(in);
97         }
98     }
99 
100     // Expected instructions after optimization in binary file
101     const auto expected = R"(
102         .language ECMAScript
103         .function any foo(any a0, any a1, any a2) {
104             ldundefined
105             sta v0
106             ldobjbyname 0x1, "a"
107             sttoglobalrecord 0x3, "a"
108             lda v0
109             ldobjbyname 0x4, "b"
110             sttoglobalrecord 0x6, "b"
111             lda v0
112             ldobjbyname 0x7, "c"
113             sttoglobalrecord 0x9, "c"
114             lda.str "a"
115             sta v1
116             lda.str "b"
117             sta v2
118             lda.str "c"
119             sta v3
120             mov v4, v0
121             mov v5, v1
122             mov v6, v2
123             mov v7, v3
124             createobjectwithexcludedkeys 0x2, v4, v5
125             sttoglobalrecord 0xa, "d"
126             returnundefined
127         }
128     )";
129     panda::pandasm::Parser parser1;
130     auto res1 = parser1.Parse(expected);
131     auto &program1 = res1.Value();
132     auto it1 = program1.function_table.find(fun_name);
133     EXPECT_NE(it1, program1.function_table.end());
134     auto &expected_func = it1->second;
135 
136     // Compare
137     for (size_t i = 0; i < insns.size(); i++) {
138         const auto &opt_ins = insns[i];
139         const auto &expected_ins = expected_func.ins[i];
140         EXPECT_EQ(opt_ins.opcode, expected_ins.opcode);
141 
142         EXPECT_EQ(opt_ins.imms.size(), expected_ins.imms.size());
143         for (size_t k = 0; k < opt_ins.imms.size(); k++) {
144             EXPECT_EQ(opt_ins.imms[k], expected_ins.imms[k]);
145         }
146 
147         EXPECT_EQ(opt_ins.ids.size(), expected_ins.ids.size());
148         for (size_t k = 0; k < opt_ins.ids.size(); k++) {
149             EXPECT_EQ(opt_ins.ids[k], expected_ins.ids[k]);
150         }
151     }
152 }
153 }  // namespace panda::bytecodeopt
154