• 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     for (auto &ins : func.ins) {
90         std::cerr << ins->ToString() << std::endl;
91     }
92 
93     EmitAndOptimize("ExcludedKeysTest1.abc", program);
94 
95     // Collect valid instructions
96     std::vector<const panda::pandasm::Ins *> insns;
97     for (const auto &in : func.ins) {
98         if (in->opcode != panda::pandasm::Opcode::INVALID) {
99             insns.emplace_back(in.get());
100         }
101     }
102 
103     // Expected instructions after optimization in binary file
104     const auto expected = R"(
105         .language ECMAScript
106         .function any foo(any a0, any a1, any a2) {
107             ldundefined
108             sta v0
109             ldobjbyname 0x1, "a"
110             sttoglobalrecord 0x3, "a"
111             lda v0
112             ldobjbyname 0x4, "b"
113             sttoglobalrecord 0x6, "b"
114             lda v0
115             ldobjbyname 0x7, "c"
116             sttoglobalrecord 0x9, "c"
117             lda.str "a"
118             sta v1
119             lda.str "b"
120             sta v2
121             lda.str "c"
122             sta v3
123             mov v4, v0
124             mov v5, v1
125             mov v6, v2
126             mov v7, v3
127             createobjectwithexcludedkeys 0x2, v4, v5
128             sttoglobalrecord 0xa, "d"
129             returnundefined
130         }
131     )";
132     panda::pandasm::Parser parser1;
133     auto res1 = parser1.Parse(expected);
134     auto &program1 = res1.Value();
135     auto it1 = program1.function_table.find(fun_name);
136     EXPECT_NE(it1, program1.function_table.end());
137     auto &expected_func = it1->second;
138 
139     // Compare
140     for (size_t i = 0; i < insns.size(); i++) {
141         const auto &opt_ins = insns[i];
142         const auto &expected_ins = expected_func.ins[i];
143         EXPECT_EQ(opt_ins->opcode, expected_ins->opcode);
144 
145         EXPECT_EQ(opt_ins->Imms().size(), expected_ins->Imms().size());
146         for (size_t k = 0; k < opt_ins->Imms().size(); k++) {
147             EXPECT_EQ(opt_ins->Imms()[k], expected_ins->Imms()[k]);
148         }
149 
150         EXPECT_EQ(opt_ins->Ids().size(), expected_ins->Ids().size());
151         for (size_t k = 0; k < opt_ins->Ids().size(); k++) {
152             EXPECT_EQ(opt_ins->Ids()[k], expected_ins->Ids()[k]);
153         }
154     }
155 }
156 }  // namespace panda::bytecodeopt
157