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