Program optimization method, medium, electronic equipment and computer program product

By adding closure variable identification information to the bytecode debugging information and using static data flow analysis, the problem of low optimization efficiency of closure variables in existing technologies is solved, achieving more efficient bytecode optimization and program performance improvement.

CN121523682APending Publication Date: 2026-02-13HUAWEI TECH CO LTD
View PDF 0 Cites 0 Cited by

Patent Information

Application Number
CN202411095153.9
Authority / Receiving Office
CN · China
Patent Type
Applications(China)
Current Assignee / Owner
Filing Date
2024-08-09
Publication Date
2026-02-13

AI Technical Summary

Technical Problem

Existing technologies cannot effectively improve the efficiency of data flow analysis of closure variables when optimizing bytecode for applications developed in high-level languages ​​such as JavaScript and TypeScript, resulting in high resource consumption during program runtime and affecting smoothness.

Method used

By adding identification information for closure variables to the debugging information of bytecode, and performing data flow analysis in a static manner, the definition and usage relationship of closure variables can be determined, thereby optimizing bytecode and reducing redundant closure variable reading operations.

Benefits of technology

It improves bytecode optimization, enhances application execution efficiency and performance, reduces runtime resource consumption, and ensures smooth program operation.

✦ Generated by Eureka AI based on patent content.

Smart Images

  • Figure CN121523682A_ABST
    Figure CN121523682A_ABST
Patent Text Reader

Abstract

The invention relates to the technical field of computers, and discloses a program optimization method, a medium, electronic equipment and a computer program product. According to the method, when the source code of the application program is compiled, the unoptimized byte code can be generated. And before the non-optimized byte code is optimized, adding identification information of each closure variable in debugging information corresponding to the non-optimized byte code so as to uniquely indicate one closure variable through one piece of identification information. And then, in the code optimization stage, for each function in the unoptimized bytecode, the data flow relationship between bytecode instructions for operating (such as defining and using) each closure variable can be determined according to the identification information of each closure variable, and the data flow analysis process needs fewer resources and is higher in analysis efficiency. And furthermore, on the basis of the data flow relationship corresponding to each closure variable in the unoptimized bytecode, optimization processing such as redundant closure variable elimination and reading operation can be performed on the unoptimized bytecode, so that an optimized bytecode can be obtained.
Need to check novelty before this filing date? Find Prior Art

Description

Technical Field

[0001] This application relates to the field of computer technology, and in particular to a program optimization method, medium, electronic device, and computer program product. Background Technology

[0002] For applications developed using high-level languages ​​such as JavaScript (JS) and TypeScript (TS), the source code is first compiled by an encoder to obtain bytecode, which is then interpreted or compiled and executed by the runtime. For example, in some coding scenarios, the source code first undergoes syntax analysis, lexical analysis, and compilation to obtain unoptimized bytecode. This unoptimized bytecode can then be optimized through intermediate representation (IR) graphing, code optimization, and other processes to obtain optimized bytecode. These code optimizations can include eliminating redundant closure variable read operations, function inlining, and constant propagation, with the main goal of reducing runtime overhead and memory consumption to improve application execution efficiency and performance.

[0003] However, with the development of electronic technology, users have increasingly higher demands for the smoothness of application operation. To ensure the smooth operation of applications, it is necessary to improve the execution efficiency and performance of applications, which requires further optimization of the application's source code bytecode. Summary of the Invention

[0004] This application provides a program optimization method, medium, electronic device, and computer program product that can perform data flow analysis on closure variables in the bytecode of an application to improve the optimization effect of the bytecode.

[0005] In a first aspect, embodiments of this application provide a program optimization method, the method comprising: obtaining a bytecode file of an application to be optimized, wherein the bytecode file is generated from the source code of the application, the bytecode file includes at least one closure variable and debugging information corresponding to each closure variable, wherein the debugging information includes identification information of the closure variable; determining the data flow relationship corresponding to each closure variable based on the identification information in the debugging information of each closure variable; and optimizing the bytecode in the bytecode file based on the data flow relationship corresponding to each closure variable to obtain optimized bytecode.

[0006] The data flow relationship corresponding to each closure variable can be the data flow relationship between bytecode instructions that operate on (e.g., define and use) each closure variable. Specifically, when compiling the application's source code, unoptimized bytecode can be generated. Before optimizing this unoptimized bytecode, this method adds identification information for each closure variable to the debugging information corresponding to the unoptimized bytecode, so that each closure variable can be uniquely identified by its identification information. That is, the debugging information of a closure variable can identify it. Then, during the code optimization phase, for each function in the unoptimized bytecode, the data flow relationship between bytecode instructions that operate on (e.g., define and use) each closure variable can be determined based on the identification information of each closure variable. Furthermore, based on the data flow relationship corresponding to each closure variable in the unoptimized bytecode, the unoptimized bytecode can be optimized to obtain optimized bytecode. Furthermore, in this application, the encoder can perform data flow analysis on the application's bytecode based on debugging information in a static manner. In this case, the data flow analysis process does not need to run the bytecode during runtime. Compared with the dynamic analysis method, the data flow analysis process does not occupy resources during program execution, which is conducive to the smooth operation of the program.

[0007] In one possible implementation of the first aspect, the debugging information for closure variables further includes: location information for the closure variables, wherein the location information for each closure variable indicates its position in the bytecode file, such as the address of a relevant instruction, and the location information for each closure variable indicates its storage location, such as its position within the closure space. Different location information can indicate closure variables at different locations, such as closure variables with the same identifier at different locations.

[0008] In one possible implementation of the first aspect, the location information of the closure variable includes at least one of the following: the start instruction address of the function containing the closure variable, the end instruction address of the function containing the closure variable, the hierarchy information of the closure variable, and the slot information of the closure variable. In this case, to uniquely indicate the closure variable through debugging information, this application can add additional information, including identification information, to the debugging information of each closure variable, so as to indicate the corresponding closure variable through this additional information. For example, the additional information of the debugging information of a closure variable can be recorded as: [start instruction address, end instruction address, hierarchy ID, slot ID, globally unique ID].

[0009] In one possible implementation of the first aspect, determining the data flow relationship corresponding to each closure variable based on the identification information in the debugging information of each closure variable includes: generating intermediate expressions (IRs) of bytecode instructions operating on each closure variable, wherein the intermediate expressions include a first type of expression corresponding to closure variables with the same identification information in the same function and a second type of expression corresponding to closure variables with the same identification information in different functions; obtaining the identification information in the debugging information corresponding to each closure variable; connecting the first type of expressions based on the definition and usage relationship based on the identification information of each closure variable; and connecting the second type of expressions based on the definition and usage relationship based on the identification information of each closure variable. Specifically, for the unoptimized bytecode mentioned above, the IRs corresponding to bytecode instructions with the same identification information of closure variables within the same function can be connected based on the definition / usage relationship (i.e., definition and usage relationship), and the IRs corresponding to bytecode instructions with the same identification information of closure variables in different functions can be connected based on the definition / usage relationship. For example, in Figure 3 In the IR diagram shown, compared to the data flow edges L1 to L3 obtained from the data flow analysis of the prior art, the data flow analysis based on closure variables in this application adds a data flow edge L4.

[0010] In one possible implementation of the first aspect, obtaining the identification information in the debugging information corresponding to each closure variable includes: obtaining the bytecode instructions that operate on the closure variables; determining the start and end instruction addresses of the function where the closure variables are located based on the instruction addresses of the bytecode instructions; and determining the hierarchy and slot information of the closure variables in the bytecode instructions; and accessing the debugging information containing the start and end instruction addresses, hierarchy information, and slot information in the function to obtain the identification information of the closure variables from the debugging information.

[0011] Specifically, for an operation instruction on a closure variable, the actual location information of the closure variable can be determined. Specifically, the actual start and end instruction addresses of the closure variable within the current function are determined based on the instruction address of the operation instruction, and the actual location information of the closure variable within the operation instruction, such as its actual hierarchy and actual slot information, is also determined. This actual location information includes the actual start instruction address, actual end instruction address, actual hierarchy information, and actual slot information. Furthermore, the actual location information of the closure variable can be compared with various debugging information within the current function to identify debugging information with the same location information, and the identification information of the closure variable can be obtained from this debugging information.

[0012] In one possible implementation of the first aspect, the type of bytecode instructions for manipulating closure variables includes: bytecode instructions for defining closure variables, or bytecode instructions for using closure variables. For example, instructions for manipulating closure variables refer to bytecode instructions for manipulating the closure variable, including but not limited to: instructions for storing closure variables such as the `stlevar` instruction (i.e., bytecode instructions for defining closure variables), and instructions for loading closure variables such as the `ldlexvar` instruction (i.e., bytecode instructions for using closure variables).

[0013] In one possible implementation of the first aspect, obtaining the bytecode file to be optimized for the application includes: obtaining the source code; compiling the source code into bytecode; generating identification information corresponding to each closure variable in the source code; generating debugging information containing the corresponding identification information and the corresponding location information for each closure variable in each function; and generating a bytecode file by combining the bytecode and the debugging information corresponding to each closure variable. For example, the compiler can use an existing encoding method such as line numbering to store the unoptimized bytecode and the debugging information corresponding to each closure variable in the unoptimized bytecode file (i.e., the bytecode file to be optimized).

[0014] In one possible implementation of the first aspect, the source code language includes at least one of the following: JavaScript or TypeScript.

[0015] In one possible implementation of the first aspect, the optimization method includes at least one of the following: optimization method based on constant propagation; optimization method based on function inlining; optimization method to eliminate redundant closure variable reading operations.

[0016] Secondly, embodiments of this application provide a readable medium storing instructions that, when executed on an electronic device, cause the electronic device to perform the program optimization method of the first aspect and any possible implementation thereof.

[0017] Thirdly, embodiments of this application provide an electronic device, including: a memory for storing instructions executed by one or more processors of the electronic device, and a processor, one of the processors of the electronic device, for executing the program optimization method in the first aspect and any possible implementation thereof.

[0018] Fourthly, embodiments of this application provide a computer program product that, when run on an electronic device, enables the electronic device to implement the program optimization method in the first aspect and any possible implementation thereof.

[0019] The beneficial effects of the second, third, and fourth aspects can be referred to the relevant descriptions in the first aspect, and will not be repeated here. Attached Figure Description

[0020] Figure 1A A schematic diagram of an application development framework provided in an embodiment of this application;

[0021] Figure 1B A schematic diagram illustrating an application analysis scenario provided in an embodiment of this application;

[0022] Figure 1C A schematic diagram of an encoder data flow analysis process provided in an embodiment of this application;

[0023] Figure 1D A schematic diagram of a compiler's data flow analysis process based on debugging information, provided for an embodiment of this application;

[0024] Figure 2 A schematic diagram of a process optimization method provided in an embodiment of this application;

[0025] Figure 3 A schematic diagram of an intermediate expression structure for static single assignment of bytecode provided in an embodiment of this application;

[0026] Figure 4 This is a schematic diagram of the hardware structure of an electronic device provided in an embodiment of this application. Detailed Implementation

[0027] The illustrative embodiments of this application include, but are not limited to, program optimization methods, media, and electronic devices.

[0028] First, some terms in the application embodiments will be explained.

[0029] 1. Compiler: A compiler is a computer program that converts source code written in a high-level programming language into machine code or intermediate code that a computer can directly execute. As an example, the compiler in this application can be a compiler that supports multiple programming languages, such as TS / JS. For instance, the compiler mentioned above could be the ArkCompiler, in which case the supported language could also be ArkTS (i.e., the Ark Compiler language).

[0030] 2. Runtime: This refers to the environment in which an application executes. It is responsible for managing the program's execution process, including memory management, thread scheduling, and exception handling. For example, the runtime mentioned above could include the Ark JSRuntime.

[0031] 3. Bytecode: Bytecode is an intermediate code layer between the high-level language source code written by the developer and machine code. For example, the bytecode in this application may include Ark bytecode. Specifically, applications developed by developers using high-level languages ​​are first compiled into bytecode by a compiler, and then interpreted or compiled and executed by the runtime. It can be understood that using bytecode as a bridge between the compiler and the runtime avoids the additional overhead of analyzing and parsing the semantics of the source code during runtime, and also hides the commonality issues arising from the differences in the underlying central processing unit (CPU) architecture of the electronic device where the runtime resides.

[0032] 4. Closure: refers to "a combination of a function and a reference to its bound environment state". For example, in TS / JS, the closure feature allows a function to access variables defined outside the function.

[0033] 5. Closure variables: also known as captured variables, in this application, variables defined outside of functions but accessed by function code through closure characteristics are called closure variables.

[0034] 6. Non-closure variables: Non-closure variables are those variables that are defined or used within a function body but are not captured by the closure. Non-closure variables are typically only valid within the scope of the function in which they are defined.

[0035] 7. Function Inlining: This is an optimization technique that replaces a function call with a copy of the called function's body. This eliminates the overhead of function calls (such as saving and restoring register states, stack operations, etc.), allowing the program to directly execute the inlined function's code at runtime, thus improving execution speed. While inlining itself may increase the initial code size (because the function body is copied multiple times), it can also indirectly reduce the final bytecode size by improving execution efficiency and reducing other types of overhead (such as stack operations during function calls). For example, more efficient execution may allow for the removal of code segments or data structures that are no longer needed.

[0036] 8. Constant Propagation: Constant propagation is an optimization technique used to identify and replace values ​​(i.e., constants) that remain unchanged throughout the application's execution. This optimization can reduce computation and potentially reduce the application's memory footprint. Specifically, in constant propagation optimization, the compiler analyzes expressions in the application and determines which expressions have constant results during program execution. Once such expressions are identified, the compiler replaces references to them with their values.

[0037] 9. Data Flow Analysis: This is a program analysis technique used to analyze the definition-use relationships between data in an application, thereby supporting functions such as program compilation optimization and security analysis. For example, the statement "a = 1" defines variable 'a', and the statement "b = a + 1" uses variable 'a'. Data flow analysis of these two statements can determine that "a = 1" has a definition relationship with variable 'a', and "b = a + 1" has a use relationship with variable 'a', that is, it analyzes the definition-use relationship of variable 'a' in the application between the statements "a = 1" and "b = a + 1". Therefore, for optimizations such as function inlining, data flow analysis is used to identify the relationship between function definitions (i.e., function bodies) and function uses (i.e., function call points). In other words, data flow analysis can help determine which variables are modified or read before and after function calls, which is crucial for determining the safety and effectiveness of function inlining.

[0038] In addition, some compilers, such as the Ark Compiler, perform data flow analysis at the bytecode level, specifically analyzing the relationships between the data operated on by different bytecode instructions, such as determining the definition-usage relationship of variable 'a' among various bytecode instructions.

[0039] refer to Figure 1A In the application development scenario shown, the compiler compiles the application's JS / TS source code into bytecode, and then sends this bytecode to the runtime for interpretation or compilation. Specifically, after directly compiling the source code into bytecode, the compiler can optimize this bytecode before sending the optimized bytecode to the runtime. During code optimization, it's typically necessary to perform data flow analysis on the application's unoptimized bytecode to analyze the data flow relationships between different data points in the application, i.e., to analyze the definition-usage relationships of variables across functions. Furthermore, applications contain not only non-closure variables but also closure variables.

[0040] As mentioned earlier, to improve the smooth operation of the application, it is necessary to enhance the optimization effect of the application's bytecode. To improve the optimization effect, in addition to optimizing the application's bytecode for non-closure variables, optimization based on closure variables can be added. In other words, to improve the optimization effect, data flow analysis of closure variables in the application's bytecode is also required.

[0041] However, some compilers currently employ a dynamic approach to perform data flow analysis on bytecode. For example, the V8 engine uses a just-in-time (JIT) compiler, which dynamically analyzes closure variables during application runtime. However, this dynamic analysis method requires running the application's bytecode in real time, resulting in significant resource consumption for closure variable data flow analysis during program execution, potentially impacting program smoothness.

[0042] To perform efficient data flow analysis on application closure variables, this application provides a program optimization method. This method adds identification information of closure variables to the debugging information corresponding to the bytecode, and then performs data flow analysis on each closure variable based on this identification information.

[0043] Specifically, during the compilation of the application's source code, unoptimized bytecode can be generated. Before optimizing this unoptimized bytecode, this method adds identification information for each closure variable to the corresponding debugging information, allowing each closure variable to be uniquely identified by a single identifier. That is, the debugging information of a closure variable can identify it. Then, during the code optimization phase, for each function in the unoptimized bytecode, the data flow relationship between bytecode instructions that operate on (e.g., define and use) each closure variable can be determined based on the identification information of each closure variable. For example, based on the identification information corresponding to a closure variable, the bytecode instructions that define a closure variable and the bytecode instructions that use that closure variable in a function can be identified, thus determining the definition-use relationship related to that closure variable. Furthermore, based on the data flow relationship corresponding to each closure variable in the unoptimized bytecode, optimization processes such as eliminating redundant closure variable read operations can be performed on the unoptimized bytecode to obtain optimized bytecode, improving the optimization effect and thus enhancing the execution efficiency and performance of the optimized bytecode at runtime. Furthermore, in this application, the encoder can perform data flow analysis on the application's bytecode based on debugging information in a static manner. In this case, the data flow analysis process does not need to run the bytecode during runtime. Compared with the dynamic analysis method, the data flow analysis process does not occupy resources during program execution, which is conducive to the smooth operation of the program.

[0044] Next, referring to the contents of source code A shown in Table 1, we will explain closures and closure variables.

[0045] Table 1:

[0046]

[0047] In the source code A shown in Table 1 above, the function `bar` is defined inside the function `foo`, and it can access the scope of function `foo`, including the variable `a`. It can be understood that because the JavaScript language uses lexical scoping (also known as static scoping), the function `bar`, defined inside function `foo`, can access the entire scope of function `foo`, including the variable `a`. In this case, variable `a` is a closure variable.

[0048] Continuing with the example source code A above, let's illustrate the definition-use relationship of closure variables. For example, regarding the definition of the closure variable `a`, `a` is defined inside the function `foo` using the `let` keyword, that is, `let` defines `a` as 1. This means its scope is limited to the function `foo`. Furthermore, regarding the use of the closure variable `a`, when the function `bar` is executed, the instruction `console(a)` in the function `bar` will attempt to print the value of variable `a`. Since the function `bar` is part of a closure, it can access and use the variable `a` defined in its outer function `foo`. Therefore, if variable `a` has already been assigned the value 1 before calling function `bar`, then the instruction `console(a)` will output 1. In this case, the instruction `let a = 1` can be used to define variable `a`, and the instruction `console(a)` is used to use variable `a`. Of course, in practical applications, the code for the `foo` function and the code for the `bar` function in the above source code A are not limited to the code in the example above; other code can also be used, and this application does not limit this.

[0049] In the example above, the function 'bar' only shows one closure variable. In real-world applications, a function may contain multiple closure variables.

[0050] Debugging information is understood to be additional information stored in a released executable application to help developers debug their code. Specifically, during the compilation of an application's source code, unoptimized bytecode and corresponding debugging information are generated simultaneously. These unoptimized bytecode and debugging information are then combined into a bytecode file. Subsequently, after the unoptimized bytecode is optimized and optimized bytecode is generated, the bytecode in the bytecode file is updated to the optimized bytecode, and the corresponding debugging information is deleted, resulting in an optimized bytecode file. Currently, debugging information includes the correspondence between each instruction and the line number of the source code, as well as the specific location (e.g., registers, memory addresses, etc.) where variables in the source code are stored. Specifically, some application bytecode files contain debugging information, and this debugging information stores at least one of the following: the source code line and column number corresponding to each bytecode instruction; and the variable in the source code corresponding to the data accessed by each bytecode instruction (located in a virtual register).

[0051] Typically, for debug applications, the debug information in the bytecode file includes the source code variables corresponding to the data accessed by each bytecode instruction. For release applications, however, the debug information in the bytecode file includes the source code line and column number corresponding to each bytecode instruction. In this case, the debug information in the bytecode file does not contain information related to closure variables; therefore, this debug information cannot indicate closure variables in the bytecode, nor can it distinguish between different closure variables in the bytecode. Consequently, the aforementioned debug information cannot be used for data flow analysis of closure variables.

[0052] Therefore, in order to uniquely indicate closure variables through debugging information, this application can add additional information, including identification information, to the debugging information of each closure variable, so as to indicate the corresponding closure variable through this additional information.

[0053] In some embodiments, the identification information of a closure variable can be a globally unique identifier (ID) used to identify the closure variable itself. For example, the globally unique ID of variable a is 1, and the globally unique ID of variable b is 2.

[0054] In other embodiments, additional information about a closure variable may include not only identification information but also location information indicating the closure variable's position within the function and its storage location. For example, the location information of a closure variable may include at least one of the following parameters:

[0055] 1) Starting instruction address: The address of the starting instruction in the function containing the closure variable, i.e., the offset address of that starting instruction. For example, the starting instruction address is 0x00.

[0056] 2) End instruction address: The address of the end instruction in the function containing the closure variable, that is, the offset address of the end instruction compared to the start instruction in the function. For example, the start instruction address is 0x10.

[0057] 3) Hierarchical information: such as the hierarchy ID. In bytecode, hierarchy usually refers to the level of code abstraction, specifically used to identify the nesting level of closures. For example, the hierarchy ID of a closure variable is 0, 1, or 2, etc.

[0058] 4) Slot information: Slot ID, for example, refers to the storage location allocated to variables or temporary values ​​in the bytecode, specifically identifying the position of a closure variable within its scope. For example, a slot ID might be 0, 1, or 2. It can be understood that during compilation, the compiler allocates slots to variables based on their access scope and lifetime, so that these values ​​can be stored and retrieved at runtime. For example, the access scope can be the number of functions the variable accesses across.

[0059] As an example, for each function in the bytecode file, the additional debugging information of a closure variable can be recorded as: [starting instruction address, ending instruction address, level ID, slot ID, globally unique ID]. For ease of description, the debugging information described in some places in the following embodiments mainly refers to the additional information of a closure variable.

[0060] In some embodiments, the bytecode file in this application may include the following: bytecode instructions defining the environment of the closure variable; bytecode instructions corresponding to the source code; debugging information, etc. The debugging information includes not only additional information about the closure variable, but also the line number of the source code corresponding to the bytecode instructions, etc., which is not specifically limited in this application.

[0061] Referring to the contents of bytecode file B shown in Table 2, the relevant content of the closure variables in the bytecode is explained. Note that bytecode file B can be the unoptimized bytecode file corresponding to source code A mentioned above.

[0062] Table 2:

[0063]

[0064]

[0065] Specifically, in the instructions of the `foo` function in Table 2 above, `newlexenv` is used to create a closure environment, i.e., a closure space. `ldai 0x1` is used to assign the value 0x1 (i.e., 1) to the variable. `stlexvar 0x0`, 0x0, is used to indicate that the value of the closure variable is stored in the closure space with a level of 0 and a slot of 0 relative to the current instruction context, where the `stlexvar` instruction is used to store the closure variable. `returnundefined` indicates the end of the function. Furthermore, the closure variable information in the debugging information of the bytecode file of the `foo` function can be: "1, 0x0, 0x10, 0, 0", i.e., [Globally Unique ID: 1, Start Instruction Address: 0x0, End Instruction Address: 0x10, Level ID: 0, Slot ID: 0]. For example, the start instruction address is the address of the `newlexenv` instruction in the `foo` function, such as 0x0. The end instruction address is the address of the `returnundefined` instruction in the `foo` function, such as 0x10.

[0066] Furthermore, information about non-closure variables in the debugging information can be recorded as [Start instruction address: 0x0, End instruction address: 0x10, Line number: 10]. The start instruction address and end instruction address are the start and end instruction addresses of the function containing the bytecode instruction. The line number can be the value of the line number in the source code corresponding to the bytecode instruction.

[0067] In the instructions of the `bar` function above, `ldlexvar 0x1` loads the value 0x1 (i.e., 1) into a variable. `tryldglobalbyname 0x0,console.log` attempts to load the `console.log` function (i.e., the `console` function) from the global environment and stores its address in a temporary location (represented by 0x0, but it could actually be a register or a location on the stack). `sta v0` stores the address of the `console.log` function into a temporary variable named `v0`. `ldlexvar 0x0,0x0` loads the value (i.e., 1) from the 0th level, 0th closure variable in the current closure space (e.g., sharing the same closure space as the `foo` function or the closure of the `foo` function being captured by the `bar` function). `sta v1` stores the loaded value (i.e., 1) into a temporary variable named `v1`. `call v0,v1` calls the `console.log` stored in `v0`, passing the value 1 stored in `v1` as an argument. `return undefined` indicates the end of the `bar` function. Furthermore, the debugging information for the closure variable in the `bar` function can be recorded as "1, 0x0, 0x10, 0, 0", which is [Globally Unique ID: 1, Start Instruction Address: 0x0, End Instruction Address: 0x10, Level ID: 0, Slot ID: 0]. Of course, in practical applications, the `foo` and `bar` functions are not limited to the above bytecode instructions and may include other bytecode instructions; this application does not impose any limitations on this.

[0068] In some embodiments, when the compiler compiles the application's source code into bytecode, it can add additional information about each closure variable to the debugging information of the bytecode to obtain a bytecode file containing this debugging information and unoptimized bytecode. Subsequently, before optimizing the unoptimized bytecode in this bytecode file, the compiler can perform data flow analysis on the closure variables based on the additional information. Specifically, the compiler can locate the corresponding closure variable based on the position information in the additional information of the debugging information and obtain the identification information of that closure variable. Then, based on the identification information of each closure variable, the compiler determines the definition-usage relationship of each closure variable in the unoptimized bytecode to achieve data flow analysis of each closure variable.

[0069] In some embodiments, the program optimization method provided in this application is applied to the bytecode compilation stage of an application, specifically in the data flow analysis process of the bytecode optimization stage. Specifically, this program optimization method can be executed by a compiler. For example, the method can be applied to... Figure 1A The application development framework shown.

[0070] The compiler in this application can be implemented by the developer's electronic device, which includes, but is not limited to, servers, personal computers (PCs), laptops, ultra-mobile personal computers (UMPCs), netbooks, and personal digital assistants (PDAs). Therefore, the data flow analysis in the program optimization method provided in this application embodiment can be performed by the electronic device where the encoder is located.

[0071] Furthermore, the runtime in this application can be implemented by a user-side electronic device, including but not limited to: mobile phones, tablets, wearable devices, in-vehicle devices, PCs, augmented reality (AR) devices, virtual reality (VR) devices, laptops, UMPCs, netbooks, PDAs, or smart screens.

[0072] In some embodiments, Figure 1B This diagram illustrates a scenario for application analytics. It is understood that... Figure 1B This example uses mobile phones and computers to illustrate the scenario of analyzing the bytecode of compiled applications on a computer.

[0073] For details, please refer to the following: Figure 1B As shown, the scenario includes a mobile phone 10 and a computer 20. One or more applications to be analyzed can be installed on the mobile phone 10, such as... Figure 1B The examples shown are APP01, APP02, APP03, APP04, etc. The computer 20 can, for example, run an integrated development environment (IDE) and display the debugging interface 210. In some embodiments, the above applications can also run on a virtual machine, and analysis tools such as the aforementioned IDE can also run on a server or other electronic devices with a processor; there are no limitations on this.

[0074] The computer 20 can run an IDE to obtain the source code written by the developer and compile it into bytecode using a compiler. During the bytecode optimization process, program analysis is performed to achieve bytecode optimization. For example, when a developer enters the source code of APP01 in the IDE and displays its contents on the debugging interface 210, clicking button 211 on the debugging interface 210 will compile the source code to obtain and display the bytecode of APP01. Subsequently, the developer clicks button 212 on the debugging interface 210 for reference... Figure 1BThe "Operation ①" shown allows for data flow analysis and optimization of the bytecode of the source code to obtain an intermediate expression diagram, which is then used to update the already displayed APP01 bytecode. Furthermore, after the computer 20 optimizes the application's bytecode, the optimized APP01 bytecode can be sent to the mobile phone 10 for interpretation or execution by the runtime environment of the mobile phone 10, thereby improving the execution efficiency and performance of the APP01 containing this bytecode.

[0075] Next, the application scenarios of the data flow analysis provided in the embodiments of this application will be described.

[0076] Reference Figure 1C The data flow analysis process for an encoder is described. For example... Figure 1C As shown, the TS / JS source code undergoes compilation steps such as lexical analysis, syntax analysis, and semantic analysis, generating unoptimized bytecode and corresponding debugging information, resulting in a bytecode file containing the unoptimized bytecode and its debugging information. Then, some techniques construct intermediate expressions from the unoptimized bytecode, generating intermediate expressions for the unoptimized code. These intermediate expressions can then undergo optimization processes such as eliminating redundant closure variable reads, variable propagation, and function inlining, resulting in optimized intermediate expressions. Finally, the optimized intermediate expressions are used to generate bytecode, yielding the optimized bytecode.

[0077] Understandable. Figure 1C Although the illustrated process generates bytecode files containing debugging information through compilation steps such as lexical analysis, this debugging information does not include additional information about closure variables, nor is it used for subsequent data flow analysis or other processing of closure variables. In other words, Figure 1C The illustrated process does not involve static data flow analysis of closure variables based on debugging information with added extra details. In this case, the compiler can perform data flow analysis on non-closure variables in the bytecode file using existing techniques. Based on the definition-use relationships of these non-closure variables, it can optimize the unoptimized bytecode by eliminating redundant closure variable reads, variable propagation, and function inlining, which can reduce the memory footprint of the optimized bytecode to some extent. However, since existing techniques may not be able to analyze closure variables, they cannot optimize the unoptimized bytecode based on the definition-use relationships of closure variables. This can result in the final optimized bytecode potentially having a larger memory footprint or lower execution efficiency and performance.

[0078] It's understandable that the application package size in a user's electronic device depends on the memory required by the corresponding bytecode. This application package size refers to the total data volume of the application and all its resource files. Obviously, the larger the application package size, the longer the application download time and the larger the storage space required. In some embodiments, developers can often optimize the bytecode to reduce the application package size, thereby improving the application's execution performance and efficiency, and ultimately enhancing the user experience.

[0079] Reference Figure 1D This application describes the data flow analysis process of the compiler based on debugging information. Figure 1D The data flow analysis process shown is similar to Figure 1C The difference lies in: on the one hand, Figure 1D The debugging information corresponding to the unoptimized bytecode contains additional information about each closure variable, such as identification and location information; on the other hand, Figure 1D In the intermediate expressions of unoptimized bytecode, data flow relationships of closure variables generated based on debugging information can be added. Furthermore, this application... Figure 1D The process shown is the same as Figure 1C The similarities between the illustrated processes will not be elaborated upon.

[0080] in this way, Figure 1D The illustrated data analysis flow allows for static data flow analysis of closure variables based on debugging information with added details. In this case, the compiler can perform data flow analysis on not only non-closure variables in the bytecode file to obtain their definition-usage relationships, but also on closure variables in the bytecode file to obtain their definition-usage relationships. Thus, during the code optimization phase, optimizations such as variable propagation and function inlining can be performed on the unoptimized bytecode based on the definition-usage relationships of both non-closure and closure variables. This results in optimized bytecode that reduces runtime overhead and memory consumption, improving application efficiency and performance, and facilitating smooth operation on user-side electronic devices.

[0081] Next, refer to Figure 2 The flowchart of the program optimization method provided in this application embodiment is described below. This method can be applied to an electronic device on the compilation side, specifically to the compiler of that electronic device. Specifically, the method includes the following steps:

[0082] S201: Obtain source code.

[0083] The source code mentioned above contains closure variables. For example, this source code can be JS / TS code, but it is not limited to this.

[0084] S202: Compile the source code to generate unoptimized bytecode.

[0085] Specifically, the source code can undergo lexical analysis, syntax analysis, and compilation to generate unoptimized bytecode. Furthermore, the aforementioned unoptimized bytecode can also be referred to as bytecode to be optimized, first bytecode, or other names, referring to bytecode that requires optimization; this application does not specifically limit its usage.

[0086] S203: Generate identification information for each closure variable in the source code.

[0087] One of the identifiers for a closure variable can be a globally unique ID.

[0088] S204: For each closure variable in the unoptimized bytecode, determine the corresponding location information in each function based on the identification information of the closure variable, and generate corresponding debugging information based on the identification information and location information of each closure variable.

[0089] Specifically, debugging information can include additional information about non-closure variables, specifically location and identification information. The location information of a closure variable within a function can include: start instruction address, end instruction address, hierarchy identifier, and slot identifier. This can be understood as follows: the start instruction address is the address of the first instruction in the function; the end address can be the address of the end instruction in the function; the hierarchy identifier indicates the hierarchy of the closure space where the closure variable resides; and the slot is the slot within that hierarchy.

[0090] In some embodiments, the additional information entries for a closure variable in a function include: start instruction address, end instruction address, hierarchy identifier (i.e., hierarchy ID), slot identifier (i.e., slot ID), and globally unique identifier (i.e., globally unique ID). For example, the information for a non-closure variable is [type: line number, start instruction address: 0x0, end instruction address: 0x10, line number: 10].

[0091] S205: Store the unoptimized bytecode and the debugging information corresponding to each closure variable into the unoptimized bytecode file.

[0092] In some embodiments, the compiler can use existing encoding methods such as line numbering to store the unoptimized bytecode and debugging information corresponding to each closure variable into an unoptimized bytecode file. For example, the unoptimized bytecode file can be an abc format file, i.e., an abc file. Of course, the above encoding method is not limited to the line numbering method, and can be any other implementable encoding method; this application does not specifically limit this. In addition, the above unoptimized bytecode file can also be called the bytecode file to be optimized or the first bytecode file, etc., and this application does not specifically limit this.

[0093] S206: Construct intermediate expression graphs for each bytecode instruction in the unoptimized bytecode and generate unoptimized static single assignment (SSA) intermediate expressions (i.e., IR).

[0094] In some embodiments, the above intermediate expression mainly consists of the following four categories:

[0095] 1) Basic Block: A linear block of program instructions that can only be entered at the beginning (first instruction) and exited at the end (last instruction). For example, the instructions of the foo function in bytecode file B above constitute a basic block.

[0096] 2) Instructions: These are bytecode instructions, representing the smallest unit of executable semantics. Each instruction represents a piece of executable semantics. For example, in the foo function of bytecode file B above, one instruction could be the instruction newlexnv.

[0097] 3) Control flow: This refers to the jump relationship between basic blocks. If, based on certain conditions, execution can proceed from one basic block to the first line of code in another basic block, then there is a control flow connection between the two basic blocks.

[0098] 4) Data Flow: The definition-use relationship between instructions, where the output of one instruction is the input of a subsequent instruction. In data flow, this is represented by a data flow edge connecting two instructions. The data flow relationship can be a definition-use relationship.

[0099] It is understandable that intermediate expressions are often represented using graph structures, where nodes are connected to each other by edges to represent data flow and control flow.

[0100] In some embodiments, the intermediate expression (IR) consists of a series of nodes, each representing a specific operation, data, or control flow element. These IR nodes reflect different operations that may be encountered during compilation, including scope management, variable assignment, data storage, and function return.

[0101] Static Single Assignment (SSA) is a form of Instructional Reference (IR) used in the compiler's optimization and code generation phases. The main characteristic of SSA is that each variable is assigned a value only once throughout the entire program. This means that in SSA, if a variable is reassigned in different parts of the program, these different assignments are treated as different variables (i.e., distinguished by introducing a new variable name or version number).

[0102] In particular, because the SSA form simplifies the analysis of variable assignment and value propagation, the compiler can more accurately identify which variables are redundant, which calculations can be performed in advance, and how to map variables to registers to improve program execution efficiency. Thus, during the compiler's optimization phase, the intermediate expression in the SSA form allows the compiler to perform more complex optimizations, such as constant propagation, dead code elimination, loop optimization, and register allocation.

[0103] In other embodiments, different compilers may choose different IR forms to suit their specific optimization goals and architectures. Specifically, the IR form in this application is not limited to the SSA form described above, but may also be other forms such as Abstract Syntax Tree (AST), three-address code, etc., which are not specifically limited in this application.

[0104] Reference Figure 3 This diagram illustrates the construction of an intermediate expression for a static single assignment of bytecode. Figure 3 The intermediate expression for static single assignment shown (i.e., SSAIR) can be the IR generated from the bytecode file B mentioned above. Figure 3 In the diagram, large squares (thick-lined squares) represent basic blocks, small squares (thin-lined squares) represent SSA IRs, and solid black arrows represent data flow edges. Figure 3 No control flow edges are involved, i.e. Figure 3 Control flow is not shown.

[0105] Understandable. Figure 3 The solid black arrow in the middle indicates that the data flow edge can be the data flow edge analyzed in the existing technology. This data flow edge is obtained by performing data flow analysis on non-closure variables.

[0106] Specifically, Figure 3 It includes the base block 01 of the function foo and the base block 02 of the function bar.

[0107] Basic block 01 includes IR 011 to IR014, which are newlexenv, val2 = constant(1), stlevarval2->0x0,0x0, and returnundefined, respectively. In addition, basic block 01 also includes data flow edges L1 from IR012 to IR013.

[0108] Basic block 02 includes IR021 to IR024, which are val1 = tryldglobalbyname(console.log), val2 = ldlexvar 0x0, 0x0, val3 = call(val1, val2), and return undefined, respectively. Furthermore, basic block 02 also includes data flow edge L2 from IR021 to IR023, and data flow edge L3 from IR022 to IR023.

[0109] As examples, common IR node types in IR expressions include: assignment nodes, constant nodes, variable nodes, function call nodes, return nodes, operation nodes, block nodes, and lexical environment nodes. An assignment node represents assigning a value to a variable or storage location. A constant node represents a specific, immutable value. A variable node represents a variable in the program; in IR, variable nodes are typically used to reference a value stored in a specific location. A function call node represents a call to a function; this node usually contains the function name, parameter list, and a possible return value reference. A condition node represents the control flow that executes different paths based on a condition. A loop node represents a control flow structure that repeatedly executes a block of code, such as a loop initialization, condition checking, and iterative update section. A return node represents the function's return operation; this node may contain a return value expression or indicate that the function has no return value (e.g., `return undefined`). Operation nodes represent operations performed on values, such as arithmetic operations (addition, subtraction, multiplication, division), logical operations (AND, OR, NOT), bitwise operations, etc. Block nodes represent a group of statements executed sequentially; block nodes typically contain a series of child nodes that are executed in order. Lexical environment nodes can be operations or functions, such as the operation that creates a lexical environment.

[0110] Next, we will consider the IR node type. Figure 3 Each IR shown is explained.

[0111] As an example, in the base block 01 of the foo function, IR 011, or newlexenv, can be a lexical environment node, which corresponds to "newlexenv 0x1" in bytecode file B.

[0112] IR 012, i.e., val2 = constant(1), can be an assignment node, where val2 is the target variable and constant(1) is the source value (a constant). In this case, the IR node corresponds to the instruction "ldai 0x1" in bytecode file B, which is used to load 1.

[0113] IR 013, or `stlevar val2->0x0`, can be a variable node, where `val2` is the target variable, and `stlevar` represents referencing the value stored at position 0x0,0x0 (i.e., the 0th slot of level 0) through `val2`. In this case, this IR node corresponds to the instruction "stlexvar 0x0,0x0" in bytecode file B, used to store 1 into the 0th closure variable of level 0 to achieve `a = 1`. Here, the 1 output by IR 012 is the value input by IR 013. IR 012 defines the variable with a value of 1 (i.e., `a`), and IR 013 uses this variable; therefore, there is a data flow edge L1 between IR 012 and IR 013.

[0114] IR 014, or returnundefined, is the return node. This IR corresponds to the instruction "returnundefined" in the foo function in bytecode file B, which indicates the end of the foo function.

[0115] Furthermore, in the base block 02 of the bar function, IR 021, i.e., val1 = tryldglobalbyname(console.log), is a variable node, val1 is the target variable, and tryldglobalbyname(console.log) loads the function named console.log into val1. At this time, IR021 corresponds to the instructions "tryldglobalbyname 0x0,console.log" and "sta v0" in bytecode file B.

[0116] IR 022, where val2 = ldlexvar 0x0,0x0, is a variable node, val2 is the target variable, and ldlexvar indicates that the value (i.e., 1) at position 0x0,0x0 (i.e., the position of the 0th slot in the 0th layer) is loaded through val2. In this case, IR022 corresponds to the instructions "ldlexvar 0x0,0x0" and "sta v1" in bytecode file B.

[0117] IR 023, i.e., val3 = call(val1, val2), is a function call node, where val3 is the target variable, and call(val1, val2) calls the console.log function in val1, passing the parameter 1 from val2. In this case, this IR corresponds to the instruction "call v0, v1" in bytecode file B. Furthermore, the console.log function output by IR 021 is the value input by IR 023, therefore, there is a data flow edge L2 between IR 021 and IR 023. The 1 output by IR 022 is the value input by IR 023, therefore, there is a data flow edge L3 between IR 022 and IR 023.

[0118] IR 024, or returnundefined, is the return node. In this case, this IR corresponds to the instruction "returnundefined" in the bar function in bytecode file B, indicating that the bar function has ended.

[0119] Understandable. Figure 3 The data flow edges shown are the data flow edges inside the foo function and the data flow edges inside the bar function, that is, the data flow edges of non-closure variables. In other words, the above data flow edges L1, L2 and L3 are all data flow edges of non-closure variables.

[0120] S207: For operation instructions on closure variables in unoptimized bytecode, access the debugging information of the closure variable and obtain the identification information of the closure variable.

[0121] The operation instructions for closure variables refer to the bytecode instructions that operate on the closure variable, including but not limited to: instructions for storing closure variables such as the stlevar instruction, and instructions for loading closure variables such as the ldlexvar instruction.

[0122] In some embodiments, this application can traverse each bytecode instruction in the unoptimized bytecode. When traversing an operation instruction of a closure variable, the debugging information of the closure variable can be accessed, the identification information of the closure variable can be obtained, and the identification information of each closure variable can be collected.

[0123] In some embodiments, for an operation instruction that operates on a closure variable, the actual location information of the closure variable is determined, and the debugging information to which the same location information belongs is queried based on the actual location information, thereby accessing the debugging information to obtain the identification information of the closure variable.

[0124] Specifically, for an operation instruction on a closure variable, the actual location information of the closure variable can be determined. Specifically, the actual start and end instruction addresses of the closure variable within the current function are determined based on the instruction address of the operation instruction, and the actual location information of the closure variable within the operation instruction, such as actual hierarchy and actual slot information, is also determined. This actual location information includes the actual start instruction address, actual end instruction address, actual hierarchy information, and actual slot information. Furthermore, the actual location information of the closure variable can be compared with various debugging information within the current function to identify debugging information whose location information matches the actual location information. The identifier information of the closure variable is then obtained from this debugging information. It can be understood that "the location information in the debugging information is the same as the actual location information" means that the start instruction address, end instruction address, hierarchy information, and slot information in the debugging information are all identical to the actual start instruction address, actual end instruction address, actual hierarchy information, and actual slot information in the actual location information, respectively.

[0125] For example, regarding the instruction "stlexvar 0x0,0x0" that operates on the closure variable a in the function foo of bytecode file B, we can determine that the actual hierarchical information of the closure variable a is 0x0 (i.e., 0) and the actual slot information is 0x0 (i.e., 0). Based on the instruction address, such as 0x2, we can determine the actual start instruction, such as 0x0, and the actual end instruction address, such as 0x10, of the instruction within the current foo function. Furthermore, based on the actual start instruction 0x0, the actual end instruction address 0x10, the actual hierarchical information 0, and the actual slot information 0, we can determine the debugging information of the closure variable as "closure variable, 1, 0x0, 0x10, 0, 0", thus determining that the identifier information of the closure variable is 1.

[0126] S208: For unoptimized bytecode, determine the definition / usage relationship of bytecode instructions with the same identification information for closure variables. That is, determine the data flow relationship of bytecode instructions that operate on each closure variable in the unoptimized bytecode.

[0127] For example, for the aforementioned bytecode file B, this application can determine that the identifier information of the closure variable in the debugging information corresponding to the instruction "stlexvar 0x0,0x0" in the foo function is 1, and also determine that the identifier information of the closure variable in the debugging information corresponding to the instruction "ldlexvar 0x0,0x0" in the bar function is 1. That is, it determines that the identifier information of the closure variable in the instructions "stlexvar 0x0,0x0" and "ldlexvar 0x0,0x0" is the same. Furthermore, the instruction "stlexvar 0x0,0x0" is used to define the closure variable (i.e., a), and the instruction "ldlexvar 0x0,0x0" is used to access the closure variable (i.e., a).

[0128] S209: For unoptimized static single-assignment intermediate expressions, connect the intermediate expressions corresponding to bytecode instructions with the same closure variable identification information based on definition / usage relationships. This allows adding data flow relationships of closure variables to unoptimized static single-assignment intermediate expressions.

[0129] Specifically, for the aforementioned unoptimized bytecode, the IRs corresponding to bytecode instructions with the same identification information of closure variables within the same function can be connected based on definition / use relationship, and the IRs corresponding to bytecode instructions with the same identification information of closure variables in different functions can be connected based on definition / use relationship.

[0130] As an example, refer to Figure 3 As shown, IR 013 in the `foo` function, i.e., `stlevar val2->0x0,0x0`, defines the closure variable (i.e., `a`), while IR 022 in the `bar` function, i.e., `val2 = ldlexvar 0x0,0x0`, uses this closure variable `a`. At this point, the output of IR 013 is the input of IR 022, therefore there exists a data flow edge L4 between IR 012 and IR 022. Thus, in... Figure 3 In the IR diagram shown, compared to the data flow edges L1 to L3 obtained from the data flow analysis of the prior art, the data flow analysis based on closure variables in this application adds a data flow edge L4.

[0131] S210: Optimize the unoptimized intermediate expression of static single assignment to obtain the optimized intermediate expression of static single assignment.

[0132] For example, unoptimized static single-assignment intermediate expressions can be optimized by eliminating redundant closure variable reads, constant propagation, and function inlining. For instance, based on data flow edge L4, ... Figure 3 The foo function shown is a sub-block of IR 022 in the bar function, so that IR 022 can call the output of IR 013.

[0133] S211: Convert the optimized static single assignment intermediate expression into bytecode to obtain optimized bytecode.

[0134] For example, based on L4 optimization, redundant closure variable read operations are eliminated between the foo and bar functions in the optimized bytecode, which helps improve the efficiency of subsequent function execution. In other words, it improves the bytecode optimization effect and enhances the execution efficiency and performance of the bytecode runtime.

[0135] In some embodiments, after the compiler-side electronic device (such as computer 20) sends the optimized bytecode to the user-side electronic device (such as mobile phone 10), the user-side electronic device can load the application package corresponding to the optimized bytecode, that is, install the application containing the optimized bytecode, and then run the application. For example, the memory occupied by the application package containing the optimized bytecode may be less than the memory occupied by the application package corresponding to the unoptimized bytecode of that application, thereby improving the execution efficiency of the application.

[0136] Thus, this application provides a function to analyze the data flow relationships between closure variables. When analyzing bytecode instructions that operate on closure variables in bytecode files, debugging information can be used as input for data flow analysis to construct definition / usage relationships. Specifically, regarding "bytecode optimization," this function can provide the data flow relationships between multiple closure variable access bytecode instructions within and across functions. This provides the necessary input for optimizations such as constant propagation and redundant code elimination. Furthermore, optimization can reduce application package size and improve application execution performance, thereby enhancing the end-user experience and helping user-side electronic devices achieve smooth application operation.

[0137] The hardware structure of the electronic device that implements the program optimization method in this application will be described next.

[0138] like Figure 4 The diagram shown is a hardware structure schematic of an electronic device according to an embodiment of this application. The electronic device 110 is a block diagram of a general-purpose computer. Specifically, the electronic device 110 includes: a memory 11, an arithmetic logic unit (ALU) 12, a controller 13, an input device 14, and an output device 15. The controller 13 reads code instructions from the memory 11 and controls the execution of the ALU 12 according to the instructions, such as executing... Figure 2 The method described in the text. During operation, the arithmetic logic unit 12 needs to read and store data from the memory 44, such as storing log files. In addition to the arithmetic logic unit 12 and the memory, the controller 13 also controls the input device 14 and the output device 15 to realize the system's data input and output. For example, the input device 14 can be implemented using a screen, keyboard, or mouse to receive user-triggered application installation operations. Similarly, the input device 15 can be implemented using a screen, sound output device, etc., to output the application's running interface to the user. Specifically, the program optimization method in this application is also implemented within the program code stored in the memory 11, following the above processing flow. Furthermore, Figure 4 The solid arrows shown represent data flow, the dashed arrows represent control flow, and the circular dashed arrows represent instruction flow.

[0139] This application also provides a computer-readable storage medium storing instructions that, when executed on a processor. Figure 2 The method and flow shown are thus implemented.

[0140] This application also provides a computer program product that, when run on a processor, provides a solution for... Figure 2 The method and flow shown are thus implemented.

[0141] The various embodiments of the mechanisms disclosed in this application can be implemented in hardware, software, firmware, or a combination of these implementation methods. Embodiments of this application can be implemented as computer programs or program code executable on a programmable system, the programmable system including at least one processor, a storage system (including volatile and non-volatile memory and / or storage elements), at least one input device, and at least one output device.

[0142] Program code can be applied to input instructions to execute the functions described in this application and generate output information. The output information can be applied to one or more output devices in a known manner. For the purposes of this application, the processing system includes any system having a processor such as, for example, a digital signal processor (DSP), a microcontroller, an application-specific integrated circuit (ASIC), or a microprocessor.

[0143] The program code can be implemented using a high-level procedural language or an object-oriented programming language to communicate with the processing system. Assembly language or machine language can also be used when needed. In fact, the mechanisms described in this application are not limited to any particular programming language. In either case, the language can be a compiled language or an interpreted language.

[0144] In some cases, the disclosed embodiments may be implemented in hardware, firmware, software, or any combination thereof. The disclosed embodiments may also be implemented as instructions carried on or stored thereon on one or more transient or non-transitory machine-readable (e.g., computer-readable) storage media, which may be read and executed by one or more processors. For example, the instructions may be distributed via a network or through other computer-readable media. Therefore, machine-readable media can include any mechanism for storing or transmitting information in a machine-readable (e.g., computer-readable) form, including but not limited to floppy disks, optical disks, CD-ROMs, compact disc read-only memory (CD-ROMs), magneto-optical disks, read-only memory (ROM), random access memory (RAM), erasable programmable read-only memory (EPROM), electrically erasable programmable read-only memory (EEPROM), magnetic cards or optical cards, flash memory, or tangible machine-readable storage for transmitting information (e.g., carrier waves, infrared signals, digital signals, etc.) using the Internet in the form of electrical, optical, acoustic, or other forms of propagation signals. Therefore, machine-readable media includes any type of machine-readable medium suitable for storing or transmitting electronic instructions or information in a machine-readable (e.g., computer-readable) form.

[0145] In the accompanying drawings, some structural or methodological features may be shown in a specific arrangement and / or order. However, it should be understood that such a specific arrangement and / or order may not be necessary. Rather, in some embodiments, these features may be arranged in a manner and / or order different from that shown in the illustrative drawings. Furthermore, the inclusion of structural or methodological features in a particular figure does not imply that such features are required in all embodiments, and in some embodiments, these features may be omitted or may be combined with other features.

[0146] It should be noted that all units / modules mentioned in the device embodiments of this application are logical units / modules. Physically, a logical unit / module can be a physical unit / module, a part of a physical unit / module, or a combination of multiple physical units / modules. The physical implementation of these logical units / modules themselves is not the most important factor; the combination of functions implemented by these logical units / modules is the key to solving the technical problems proposed in this application. Furthermore, to highlight the innovative aspects of this application, the above-described device embodiments of this application have not introduced units / modules that are not closely related to solving the technical problems proposed in this application. This does not mean that the above-described device embodiments do not contain other units / modules.

[0147] It should be noted that in the examples and description of this patent, relational terms such as "first" and "second" are used merely to distinguish one entity or operation from another, and do not necessarily require or imply any such actual relationship or order between these entities or operations. Furthermore, the terms "comprising," "including," or any other variations thereof are intended to cover non-exclusive inclusion, such that a process, method, article, or apparatus that comprises a list of elements includes not only those elements but also other elements not expressly listed, or elements inherent to such a process, method, article, or apparatus. Without further limitations, an element defined by the phrase "comprising one" does not exclude the presence of other identical elements in the process, method, article, or apparatus that includes said element.

[0148] Although this application has been illustrated and described with reference to certain preferred embodiments thereof, those skilled in the art should understand that various changes in form and detail may be made thereto without departing from the spirit and scope of this application.

Claims

1. A method of program optimization, characterized by, The method comprises: acquiring a bytecode file to be optimized by an application, wherein the bytecode file is generated according to source code of the application, the bytecode file comprises at least one closure variable and debugging information corresponding to each closure variable, and the debugging information comprises identification information of the closure variable; determining a data flow relationship corresponding to each closure variable according to the identification information in the debugging information of each closure variable; optimizing bytecode in the bytecode file according to the data flow relationship corresponding to each closure variable to obtain optimized bytecode.

2. The method of claim 1, wherein, The debugging information of the closure variable further comprises position information of the closure variable, wherein the position information of each closure variable is used to indicate a position of the closure variable in the bytecode file, and the position information of each closure variable is used to indicate a storage position of the closure variable.

3. The method of claim 2, wherein, The position information of the closure variable comprises at least one of the following: a starting instruction address of a function where the closure variable is located, an ending instruction address of the function where the closure variable is located, level information of the closure variable, and slot information of the closure variable.

4. The method of claim 3, wherein, The determining of the data flow relationship corresponding to each closure variable according to the identification information in the debugging information of each closure variable comprises: generating an intermediate expression of bytecode instructions for operating each closure variable, wherein the intermediate expression comprises a first type of expression corresponding to closure variables with the same identification information in the same function, and a second type of expression corresponding to closure variables with the same identification information in different functions; acquiring the identification information in the debugging information corresponding to each closure variable; connecting the first type of expression based on a definition and use relationship according to the identification information of each closure variable; connecting the second type of expression based on the definition and use relationship according to the identification information of each closure variable.

5. The method of claim 4, wherein, The acquiring of the identification information in the debugging information corresponding to each closure variable comprises: acquiring bytecode instructions for operating the closure variable, determining a starting instruction address and an ending instruction address of a function where the closure variable is located according to an instruction address of the bytecode instructions, and determining level information and slot information of the closure variable in the bytecode instructions; accessing debugging information containing the starting instruction address, the ending instruction address, the level information and the slot information in the function to acquire the identification information of the closure variable from the debugging information.

6. The method of claim 5, wherein, The type of the bytecode instructions for operating the closure variable comprises: a bytecode instruction for defining the closure variable, or a bytecode instruction for using the closure variable.

7. The method of claim 2, wherein, The acquiring of the bytecode file to be optimized by the application comprises: acquiring the source code; compiling the source code into bytecode; generating identification information corresponding to each closure variable in the source code; generating, in each function, debugging information containing corresponding identification information and corresponding position information for each closure variable; generating the bytecode file by using the bytecode and the debugging information corresponding to each closure variable.

8. The method of claim 1, wherein, The language of the source code comprises at least one of the following: JavaScript language, a TypeScript language.

9. The method of claim 1, wherein, The optimization processing mode comprises at least one of the following: an optimization mode based on constant propagation; an optimization mode based on function inlining; an optimization mode based on eliminating redundant closure variable reading operations.

10. A readable medium characterized by The readable medium stores instructions, which, when executed on an electronic device, cause the electronic device to perform the program optimization method of any one of claims 1 to 9.

11. An electronic device, comprising: Comprise: a memory for storing instructions executed by one or more processors of an electronic device, and a processor, which is one of the processors of the electronic device, for executing the program optimization method of any one of claims 1 to 9.

12. A computer program product, characterised in that, The computer program product, when running on an electronic device, causes the electronic device to implement the program optimization method of any one of claims 1 to 9.