1/* 2 * Copyright (c) 2022 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 "patchFix.h" 17#include <binder/binder.h> 18#include <binder/scope.h> 19#include <binder/variable.h> 20#include <compiler/core/pandagen.h> 21#include <ir/expressions/literal.h> 22 23#include <fstream> 24#include <iostream> 25#include <string> 26#include <unistd.h> 27 28namespace panda::es2panda::util { 29 30const std::string EXTERNAL_ATTRIBUTE = "external"; 31const panda::panda_file::SourceLang SRC_LANG = panda::panda_file::SourceLang::ECMASCRIPT; 32 33void PatchFix::ProcessFunction(const compiler::PandaGen *pg, panda::pandasm::Function *func, 34 LiteralBuffers &literalBuffers) 35{ 36 if (generateSymbolFile_) { 37 DumpFunctionInfo(pg, func, literalBuffers); 38 return; 39 } 40 41 if (generatePatch_ || IsHotReload()) { 42 HandleFunction(pg, func, literalBuffers); 43 return; 44 } 45} 46 47void PatchFix::ProcessModule(const std::string &recordName, 48 std::vector<panda::pandasm::LiteralArray::Literal> &moduleBuffer) 49{ 50 if (generateSymbolFile_) { 51 DumpModuleInfo(recordName, moduleBuffer); 52 return; 53 } 54 55 if (generatePatch_ || IsHotReload()) { 56 ValidateModuleInfo(recordName, moduleBuffer); 57 return; 58 } 59} 60 61void PatchFix::ProcessJsonContentRecord(const std::string &recordName, const std::string &jsonFileContent) 62{ 63 if (generateSymbolFile_) { 64 DumpJsonContentRecInfo(recordName, jsonFileContent); 65 return; 66 } 67 68 if (generatePatch_ || IsHotReload()) { 69 ValidateJsonContentRecInfo(recordName, jsonFileContent); 70 return; 71 } 72} 73 74void PatchFix::DumpModuleInfo(const std::string &recordName, 75 std::vector<panda::pandasm::LiteralArray::Literal> &moduleBuffer) 76{ 77 std::stringstream ss; 78 ss << recordName << SymbolTable::SECOND_LEVEL_SEPERATOR; 79 ss << Helpers::GetHashString(ConvertLiteralToString(moduleBuffer)) << std::endl; 80 symbolTable_->FillSymbolTable(ss); 81} 82 83void PatchFix::ValidateModuleInfo(const std::string &recordName, 84 std::vector<panda::pandasm::LiteralArray::Literal> &moduleBuffer) 85{ 86 auto it = originModuleInfo_->find(recordName); 87 if (!IsHotReload() && it == originModuleInfo_->end()) { 88 std::cerr << "[Patch] Found new import/export expression in " << recordName << ", not supported!" << std::endl; 89 patchError_ = true; 90 return; 91 } 92 93 if (!IsHotReload() && Helpers::GetHashString(ConvertLiteralToString(moduleBuffer)) != it->second) { 94 std::cerr << "[Patch] Found import/export expression changed in " << recordName << ", not supported!" << 95 std::endl; 96 patchError_ = true; 97 return; 98 } 99} 100 101void PatchFix::DumpJsonContentRecInfo(const std::string &recordName, const std::string &jsonFileContent) 102{ 103 std::stringstream ss; 104 ss << recordName << SymbolTable::SECOND_LEVEL_SEPERATOR; 105 ss << Helpers::GetHashString(jsonFileContent) << std::endl; 106 symbolTable_->FillSymbolTable(ss); 107} 108 109void PatchFix::ValidateJsonContentRecInfo(const std::string &recordName, const std::string &jsonFileContent) 110{ 111 auto it = originModuleInfo_->find(recordName); 112 if (!IsHotReload() && it == originModuleInfo_->end()) { 113 std::cerr << "[Patch] Found new import/require json file expression in " << recordName << 114 ", not supported!" << std::endl; 115 patchError_ = true; 116 return; 117 } 118 119 if (!IsHotReload() && Helpers::GetHashString(jsonFileContent) != it->second) { 120 std::cerr << "[Patch] Found imported/required json file content changed in " << recordName << 121 ", not supported!" << std::endl; 122 patchError_ = true; 123 return; 124 } 125} 126 127bool PatchFix::IsAnonymousOrSpecialOrDuplicateFunction(const std::string &funcName) 128{ 129 if (util::Helpers::IsDefaultApiVersion(targetApiVersion_, targetApiSubVersion_)) { 130 return funcName.find(binder::Binder::ANONYMOUS_SPECIAL_DUPLICATE_FUNCTION_SPECIFIER) != std::string::npos; 131 } 132 // Function name is like: #scopes^1#functionname^1 133 // Special function name is which includes "\\" or ".", the name should be transformed into "". 134 // Anonymous function name is "", it's the same with special function name here. 135 // Duplicate function name includes "^" after the last "#". 136 auto pos = funcName.find_last_of(Helpers::FUNC_NAME_SEPARATOR); 137 if (pos == std::string::npos) { 138 return false; 139 } 140 141 if (pos == funcName.size() - 1) { 142 return true; 143 } 144 145 auto posOfDuplicateSep = funcName.find_last_of(Helpers::DUPLICATED_SEPERATOR); 146 if (posOfDuplicateSep != std::string::npos && posOfDuplicateSep > pos) { 147 return true; 148 } 149 150 return false; 151} 152 153int64_t PatchFix::GetLiteralIdxFromStringId(const std::string &stringId) 154{ 155 auto recordPrefix = recordName_ + "_"; 156 auto idxStr = stringId.substr(recordPrefix.size()); 157 return std::atoi(idxStr.c_str()); 158} 159 160void PatchFix::CollectFunctionsWithDefinedClasses(std::string funcName, std::string className) 161{ 162 auto funcInfo = funcDefinedClasses_.find(funcName); 163 if (funcInfo != funcDefinedClasses_.end()) { 164 funcInfo->second.push_back(className); 165 return; 166 } 167 std::vector<std::string> funcDefinedClasses = {className}; 168 funcDefinedClasses_.insert({funcName, funcDefinedClasses}); 169} 170 171std::vector<std::pair<std::string, std::string>> PatchFix::GenerateFunctionAndClassHash(panda::pandasm::Function *func, 172 LiteralBuffers &literalBuffers) 173{ 174 std::stringstream ss; 175 std::vector<std::pair<std::string, std::string>> hashList; 176 177 ss << ".function any " << func->name << '('; 178 179 for (uint32_t i = 0; i < func->GetParamsNum(); i++) { 180 ss << "any a" << std::to_string(i); 181 if (i != func->GetParamsNum() - 1) { 182 ss << ", "; 183 } 184 } 185 ss << ") {" << std::endl; 186 187 for (const auto &ins : func->ins) { 188 ss << (ins.set_label ? "" : "\t") << ins.ToString("", true, func->GetTotalRegs()) << " "; 189 if (ins.opcode == panda::pandasm::Opcode::CREATEARRAYWITHBUFFER || 190 ins.opcode == panda::pandasm::Opcode::CREATEOBJECTWITHBUFFER) { 191 int64_t bufferIdx = GetLiteralIdxFromStringId(ins.ids[0]); 192 ss << ExpandLiteral(bufferIdx, literalBuffers) << " "; 193 } else if (ins.opcode == panda::pandasm::Opcode::DEFINECLASSWITHBUFFER) { 194 CollectFunctionsWithDefinedClasses(func->name, ins.ids[0]); 195 int64_t bufferIdx = GetLiteralIdxFromStringId(ins.ids[1]); 196 std::string literalStr = ExpandLiteral(bufferIdx, literalBuffers); 197 auto classHash = Helpers::GetHashString(literalStr); 198 hashList.push_back(std::pair<std::string, std::string>(ins.ids[0], classHash)); 199 CollectClassMemberFunctions(ins.ids[0], bufferIdx, literalBuffers); 200 } 201 ss << " "; 202 } 203 204 ss << "}" << std::endl; 205 206 for (const auto &ct : func->catch_blocks) { 207 ss << ".catchall " << ct.try_begin_label << ", " << ct.try_end_label << ", " << ct.catch_begin_label 208 << std::endl; 209 } 210 211 auto funcHash = Helpers::GetHashString(ss.str()); 212 hashList.push_back(std::pair<std::string, std::string>(func->name, funcHash)); 213 return hashList; 214} 215 216std::string PatchFix::ConvertLiteralToString(std::vector<panda::pandasm::LiteralArray::Literal> &literalBuffer) 217{ 218 std::stringstream ss; 219 int count = 0; 220 for (auto &literal : literalBuffer) { 221 ss << "{" << "index: " << count++ << " "; 222 ss << "tag: " << static_cast<std::underlying_type<panda::es2panda::ir::LiteralTag>::type>(literal.tag_); 223 ss << " "; 224 std::string val; 225 std::visit([&val](auto&& element) { 226 val += "val: "; 227 val += element; 228 val += " "; 229 }, literal.value_); 230 ss << val; 231 ss << "},"; 232 } 233 234 return ss.str(); 235} 236 237std::string PatchFix::ExpandLiteral(int64_t bufferIdx, PatchFix::LiteralBuffers &literalBuffers) 238{ 239 for (auto &litPair : literalBuffers) { 240 if (litPair.first == bufferIdx) { 241 return ConvertLiteralToString(litPair.second); 242 } 243 } 244 245 return ""; 246} 247 248std::vector<std::string> PatchFix::GetLiteralMethods(int64_t bufferIdx, PatchFix::LiteralBuffers &literalBuffers) 249{ 250 std::vector<std::string> methods; 251 for (auto &litPair : literalBuffers) { 252 if (litPair.first != bufferIdx) { 253 continue; 254 } 255 for (auto &literal : litPair.second) { 256 switch (literal.tag_) { 257 case panda::panda_file::LiteralTag::METHOD: 258 case panda::panda_file::LiteralTag::GENERATORMETHOD: 259 case panda::panda_file::LiteralTag::ASYNCGENERATORMETHOD: { 260 methods.push_back(std::get<std::string>(literal.value_)); 261 break; 262 } 263 default: 264 break; 265 } 266 } 267 } 268 269 return methods; 270} 271 272void PatchFix::CollectClassMemberFunctions(const std::string &className, int64_t bufferIdx, 273 PatchFix::LiteralBuffers &literalBuffers) 274{ 275 std::vector<std::string> classMemberFunctions = GetLiteralMethods(bufferIdx, literalBuffers); 276 classMemberFunctions.push_back(className); 277 classMemberFunctions_.insert({className, classMemberFunctions}); 278} 279 280bool PatchFix::IsScopeValidToPatchLexical(binder::VariableScope *scope) const 281{ 282 if (IsDumpSymbolTable()) { 283 return false; 284 } 285 286 CHECK_NOT_NULL(scope); 287 if (!scope->IsFunctionVariableScope()) { 288 return false; 289 } 290 291 auto funcName = scope->AsFunctionVariableScope()->InternalName(); 292 if (std::string(funcName) != funcMain0_) { 293 return false; 294 } 295 return true; 296} 297 298void PatchFix::AllocSlotfromPatchEnv(const std::string &variableName) 299{ 300 if (!topScopeLexEnvs_.count(variableName)) { 301 topScopeLexEnvs_[variableName] = topScopeIdx_++; 302 } 303} 304 305uint32_t PatchFix::GetSlotIdFromSymbolTable(const std::string &variableName) 306{ 307 auto functionIter = originFunctionInfo_->find(funcMain0_); 308 if (functionIter != originFunctionInfo_->end()) { 309 for (const auto &lexenv : functionIter->second.lexenv) { 310 if (lexenv.second.first == variableName) { 311 return lexenv.first; 312 } 313 } 314 } 315 return UINT32_MAX; 316} 317 318uint32_t PatchFix::GetEnvSizeOfFuncMain0() 319{ 320 auto functionIter = originFunctionInfo_->find(funcMain0_); 321 ASSERT(functionIter != originFunctionInfo_->end()); 322 return functionIter->second.lexenv.size(); 323} 324 325uint32_t PatchFix::GetPatchLexicalIdx(const std::string &variableName) 326{ 327 ASSERT(topScopeLexEnvs_.count(variableName)); 328 return topScopeLexEnvs_[variableName]; 329} 330 331bool IsFunctionOrClassDefineIns(panda::pandasm::Ins &ins) 332{ 333 if (ins.opcode == panda::pandasm::Opcode::DEFINEMETHOD || 334 ins.opcode == panda::pandasm::Opcode::DEFINEFUNC || 335 ins.opcode == panda::pandasm::Opcode::DEFINECLASSWITHBUFFER) { 336 return true; 337 } 338 return false; 339} 340 341bool IsStPatchVarIns(panda::pandasm::Ins &ins) 342{ 343 return ins.opcode == panda::pandasm::Opcode::WIDE_STPATCHVAR; 344} 345 346void PatchFix::CollectFuncDefineIns(panda::pandasm::Function *func) 347{ 348 for (size_t i = 0; i < func->ins.size(); ++i) { 349 if (IsFunctionOrClassDefineIns(func->ins[i])) { 350 funcDefineIns_.push_back(func->ins[i]); // push define ins 351 funcDefineIns_.push_back(func->ins[i + 1]); // push store ins 352 } 353 } 354} 355 356void PatchFix::HandleModifiedClasses(panda::pandasm::Program *prog) 357{ 358 for (auto &cls: classMemberFunctions_) { 359 for (auto &func: cls.second) { 360 if (!prog->function_table.at(func).metadata->IsForeign()) { 361 modifiedClassNames_.insert(cls.first); 362 break; 363 } 364 } 365 } 366 367 for (auto &cls: modifiedClassNames_) { 368 auto &memberFunctions = classMemberFunctions_[cls]; 369 for (auto &func: memberFunctions) { 370 if (prog->function_table.at(func).metadata->IsForeign()) { 371 prog->function_table.at(func).metadata->RemoveAttribute(EXTERNAL_ATTRIBUTE); 372 } 373 } 374 } 375} 376 377void PatchFix::HandleModifiedDefinedClassFunc(panda::pandasm::Program *prog) 378{ 379 for (auto &funcInfo: funcDefinedClasses_) { 380 for (auto &definedClass: funcInfo.second) { 381 if (modifiedClassNames_.count(definedClass) && 382 prog->function_table.at(funcInfo.first).metadata->IsForeign()) { 383 prog->function_table.at(funcInfo.first).metadata->RemoveAttribute(EXTERNAL_ATTRIBUTE); 384 } 385 } 386 } 387} 388 389void PatchFix::AddHeadAndTailInsForPatchFuncMain0(std::vector<panda::pandasm::Ins> &ins) 390{ 391 panda::pandasm::Ins returnUndefine; 392 returnUndefine.opcode = pandasm::Opcode::RETURNUNDEFINED; 393 394 if (ins.size() == 0) { 395 ins.push_back(returnUndefine); 396 return; 397 } 398 399 panda::pandasm::Ins newLexenv; 400 newLexenv.opcode = pandasm::Opcode::NEWLEXENV; 401 newLexenv.imms.reserve(1); 402 auto newFuncNum = long(ins.size() / 2); // each new function has 2 ins: define and store 403 newLexenv.imms.emplace_back(newFuncNum); 404 405 ins.insert(ins.begin(), newLexenv); 406 ins.push_back(returnUndefine); 407} 408 409void PatchFix::AddTailInsForPatchFuncMain1(std::vector<panda::pandasm::Ins> &ins) 410{ 411 panda::pandasm::Ins returnUndefined; 412 returnUndefined.opcode = pandasm::Opcode::RETURNUNDEFINED; 413 ins.push_back(returnUndefined); 414} 415 416void PatchFix::CreateFunctionPatchMain0AndMain1(panda::pandasm::Function &patchFuncMain0, 417 panda::pandasm::Function &patchFuncMain1) 418{ 419 const size_t defaultParamCount = 3; 420 patchFuncMain0.params.reserve(defaultParamCount); 421 patchFuncMain1.params.reserve(defaultParamCount); 422 for (uint32_t i = 0; i < defaultParamCount; ++i) { 423 patchFuncMain0.params.emplace_back(panda::pandasm::Type("any", 0), SRC_LANG); 424 patchFuncMain1.params.emplace_back(panda::pandasm::Type("any", 0), SRC_LANG); 425 } 426 427 std::vector<panda::pandasm::Ins> patchMain0DefineIns; 428 std::vector<panda::pandasm::Ins> patchMain1DefineIns; 429 430 for (size_t i = 0; i < funcDefineIns_.size(); ++i) { 431 if (IsFunctionOrClassDefineIns(funcDefineIns_[i])) { 432 auto &name = funcDefineIns_[i].ids[0]; 433 if (newFuncNames_.count(name) && IsStPatchVarIns(funcDefineIns_[i + 1])) { 434 patchMain0DefineIns.push_back(funcDefineIns_[i]); 435 patchMain0DefineIns.push_back(funcDefineIns_[i + 1]); 436 continue; 437 } 438 if (patchFuncNames_.count(name) || modifiedClassNames_.count(name)) { 439 patchMain1DefineIns.push_back(funcDefineIns_[i]); 440 continue; 441 } 442 } 443 } 444 445 AddHeadAndTailInsForPatchFuncMain0(patchMain0DefineIns); 446 AddTailInsForPatchFuncMain1(patchMain1DefineIns); 447 448 patchFuncMain0.ins = patchMain0DefineIns; 449 patchFuncMain1.ins = patchMain1DefineIns; 450 451 patchFuncMain0.return_type = panda::pandasm::Type("any", 0); 452 patchFuncMain1.return_type = panda::pandasm::Type("any", 0); 453} 454 455void PatchFix::Finalize(panda::pandasm::Program **prog) 456{ 457 if (IsDumpSymbolTable() || IsColdReload()) { 458 return; 459 } 460 461 HandleModifiedClasses(*prog); 462 463 HandleModifiedDefinedClassFunc(*prog); 464 465 if (patchError_) { 466 *prog = nullptr; 467 std::cerr << "[Patch] Found unsupported change in file, will not generate patch!" << std::endl; 468 return; 469 } 470 471 if (IsHotReload() || IsColdFix()) { 472 return; 473 } 474 475 panda::pandasm::Function patchFuncMain0(patchMain0_, SRC_LANG); 476 panda::pandasm::Function patchFuncMain1(patchMain1_, SRC_LANG); 477 CreateFunctionPatchMain0AndMain1(patchFuncMain0, patchFuncMain1); 478 479 (*prog)->function_table.emplace(patchFuncMain0.name, std::move(patchFuncMain0)); 480 (*prog)->function_table.emplace(patchFuncMain1.name, std::move(patchFuncMain1)); 481} 482 483bool PatchFix::CompareLexenv(const std::string &funcName, const compiler::PandaGen *pg, 484 SymbolTable::OriginFunctionInfo &bytecodeInfo) 485{ 486 auto &lexicalVarNameAndTypes = pg->TopScope()->GetLexicalVarNameAndTypes(); 487 auto &lexenv = bytecodeInfo.lexenv; 488 if (funcName != funcMain0_) { 489 if (lexenv.size() != lexicalVarNameAndTypes.size()) { 490 std::cerr << "[Patch] Found lexical variable added or removed in " << funcName << ", not supported!" 491 << std::endl; 492 patchError_ = true; 493 return false; 494 } 495 for (auto &variable: lexicalVarNameAndTypes) { 496 auto varSlot = variable.first; 497 auto lexenvIter = lexenv.find(varSlot); 498 if (lexenvIter == lexenv.end()) { 499 std::cerr << "[Patch] Found new lexical variable added in function " << funcName << ", not supported!" 500 << std::endl; 501 patchError_ = true; 502 return false; 503 } 504 505 auto &lexInfo = lexenvIter->second; 506 if (!IsColdFix() && (std::string(variable.second.first) != lexInfo.first || 507 variable.second.second != lexInfo.second)) { 508 std::cerr << "[Patch] Found lexical variable changed in function " << funcName << ", not supported!" 509 << std::endl; 510 patchError_ = true; 511 return false; 512 } 513 } 514 } 515 return true; 516} 517 518bool PatchFix::CompareClassHash(std::vector<std::pair<std::string, std::string>> &hashList, 519 SymbolTable::OriginFunctionInfo &bytecodeInfo) 520{ 521 auto &classInfo = bytecodeInfo.classHash; 522 for (size_t i = 0; i < hashList.size() - 1; ++i) { 523 auto &className = hashList[i].first; 524 auto classIter = classInfo.find(className); 525 if (!IsHotReload() && classIter != classInfo.end() && classIter->second != hashList[i].second) { 526 if (IsColdFix()) { 527 modifiedClassNames_.insert(className); 528 continue; 529 } else { 530 ASSERT(IsHotFix()); 531 std::cerr << "[Patch] Found class " << hashList[i].first << " changed, not supported!" << std::endl; 532 } 533 patchError_ = true; 534 return false; 535 } 536 } 537 return true; 538} 539 540void PatchFix::CheckAndRestoreSpecialFunctionName(uint32_t globalIndexForSpecialFunc, std::string &funcInternalName, 541 std::string recordName) 542{ 543 auto it = originRecordHashFunctionNames_->find(recordName); 544 if (it != originRecordHashFunctionNames_->end()) { 545 if (it->second.size() == 0 || globalIndexForSpecialFunc > it->second.size()) { 546 // anonymous, special or duplicate function added 547 std::cerr << "[Patch] Found new anonymous, special(containing '.' or '\\') or duplicate name function " 548 << funcInternalName << " not supported!" << std::endl; 549 patchError_ = true; 550 return; 551 } 552 std::string originalName = it->second.at(std::to_string(globalIndexForSpecialFunc)); 553 // special name function in the same position must have the same real function name as original 554 if (originalName.substr(originalName.find_last_of("#")) != 555 funcInternalName.substr(funcInternalName.find_last_of("#"))) { 556 std::cerr << "[Patch] Found new anonymous, special(containing '.' or '\\') or duplicate name function " 557 << funcInternalName << " not supported!" << std::endl; 558 patchError_ = true; 559 return; 560 } 561 funcInternalName = originalName; 562 } 563} 564 565void PatchFix::HandleFunction(const compiler::PandaGen *pg, panda::pandasm::Function *func, 566 LiteralBuffers &literalBuffers) 567{ 568 std::string funcName = func->name; 569 auto originFunction = originFunctionInfo_->find(funcName); 570 if (originFunction == originFunctionInfo_->end()) { 571 if ((!util::Helpers::IsDefaultApiVersion(targetApiVersion_, targetApiSubVersion_)) && 572 IsHotFix() && 573 IsAnonymousOrSpecialOrDuplicateFunction(funcName)) { 574 std::cerr << "[Patch] Found new anonymous, special(containing '.' or '\\') or duplicate name function " 575 << funcName << " not supported!" << std::endl; 576 patchError_ = true; 577 return; 578 } 579 newFuncNames_.insert(funcName); 580 CollectFuncDefineIns(func); 581 return; 582 } 583 584 auto &bytecodeInfo = originFunction->second; 585 if (!CompareLexenv(funcName, pg, bytecodeInfo)) { 586 return; 587 } 588 589 auto hashList = GenerateFunctionAndClassHash(func, literalBuffers); 590 if (!CompareClassHash(hashList, bytecodeInfo)) { 591 return; 592 } 593 594 if (IsHotReload()) { 595 return; 596 } 597 598 auto funcHash = hashList.back().second; 599 600 if (funcName == funcMain0_) { 601 if (IsHotFix()) { 602 func->metadata->SetAttribute(EXTERNAL_ATTRIBUTE); 603 } else { 604 patchFuncNames_.insert(funcName); 605 } 606 } else { 607 if (funcHash == bytecodeInfo.funcHash) { 608 func->metadata->SetAttribute(EXTERNAL_ATTRIBUTE); 609 } else { 610 patchFuncNames_.insert(funcName); 611 } 612 } 613 614 CollectFuncDefineIns(func); 615} 616 617void PatchFix::DumpFunctionInfo(const compiler::PandaGen *pg, panda::pandasm::Function *func, 618 PatchFix::LiteralBuffers &literalBuffers) 619{ 620 std::stringstream ss; 621 622 ss << pg->InternalName(); 623 ss << SymbolTable::SECOND_LEVEL_SEPERATOR << pg->InternalName() << SymbolTable::SECOND_LEVEL_SEPERATOR; 624 625 std::vector<std::pair<std::string, std::string>> hashList = GenerateFunctionAndClassHash(func, literalBuffers); 626 ss << hashList.back().second << SymbolTable::SECOND_LEVEL_SEPERATOR; 627 628 if (util::Helpers::IsDefaultApiVersion(targetApiVersion_, targetApiSubVersion_)) { 629 auto internalNameStr = pg->InternalName().Mutf8(); 630 if (internalNameStr.find("#") != std::string::npos) { 631 ss << (pg->Binder()->SpecialFuncNameIndexMap()).at(internalNameStr) << SymbolTable::SECOND_LEVEL_SEPERATOR; 632 } else { 633 // index 0 for all the normal name functions 634 ss << "0" << SymbolTable::SECOND_LEVEL_SEPERATOR; 635 } 636 } 637 638 ss << SymbolTable::FIRST_LEVEL_SEPERATOR; 639 for (size_t i = 0; i < hashList.size() - 1; ++i) { 640 ss << hashList[i].first << SymbolTable::SECOND_LEVEL_SEPERATOR << hashList[i].second << 641 SymbolTable::SECOND_LEVEL_SEPERATOR; 642 } 643 ss << SymbolTable::SECOND_LEVEL_SEPERATOR << SymbolTable::FIRST_LEVEL_SEPERATOR; 644 645 for (auto &variable: pg->TopScope()->GetLexicalVarNameAndTypes()) { 646 ss << variable.second.first << SymbolTable::SECOND_LEVEL_SEPERATOR 647 << variable.first << SymbolTable::SECOND_LEVEL_SEPERATOR 648 << variable.second.second << SymbolTable::SECOND_LEVEL_SEPERATOR; 649 } 650 ss << SymbolTable::SECOND_LEVEL_SEPERATOR << std::endl; 651 652 symbolTable_->FillSymbolTable(ss); 653} 654 655bool PatchFix::IsAdditionalVarInPatch(uint32_t slot) 656{ 657 return slot == UINT32_MAX; 658} 659 660bool PatchFix::IsDumpSymbolTable() const 661{ 662 return patchFixKind_ == PatchFixKind::DUMPSYMBOLTABLE; 663} 664 665bool PatchFix::IsHotFix() const 666{ 667 return patchFixKind_ == PatchFixKind::HOTFIX; 668} 669 670bool PatchFix::IsColdFix() const 671{ 672 return patchFixKind_ == PatchFixKind::COLDFIX; 673} 674 675bool PatchFix::IsHotReload() const 676{ 677 return patchFixKind_ == PatchFixKind::HOTRELOAD; 678} 679 680bool PatchFix::IsColdReload() const 681{ 682 return patchFixKind_ == PatchFixKind::COLDRELOAD; 683} 684 685} // namespace panda::es2panda::util 686