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