Authors Barbara G. Ryder Shiyi Wei
License CC-BY-3.0
Adaptive Context-sensitive Analysis for JavaScript Shiyi Wei and Barbara G. Ryder Department of Computer Science Virginia Tech Blacksburg, VA, USA {wei, ryder}@cs.vt.edu Abstract Context sensitivity is a technique to improve program analysis precision by distinguishing between function calls. A specific context-sensitive analysis is usually designed to accommodate the pro- gramming paradigm of a particular programming language. JavaScript features both the object- oriented and functional programming paradigms. Our empirical study suggests that there is no single context-sensitive analysis that always produces precise results for JavaScript applications. This observation motivated us to design an adaptive analysis, selecting a context-sensitive ana- lysis from multiple choices for each function. Our two-staged adaptive context-sensitive analysis first extracts function characteristics from an inexpensive points-to analysis and then chooses a specialized context-sensitive analysis per function based on the heuristics. The experimental results show that our adaptive analysis achieved more precise results than any single context- sensitive analysis for several JavaScript programs in the benchmarks. 1998 ACM Subject Classification D.3.4 Processors, F.3.2 Semantics of Programming Languages, D.2.5 Testing and Debugging Keywords and phrases Context Sensitivity, JavaScript, Static Program Analysis Digital Object Identifier 10.4230/LIPIcs.ECOOP.2015.712 1 Introduction JavaScript is the lingua franca of client-side web applications and is becoming the most popular programming language choice for open source projects [13]. Its flexible programming paradigm is one of the reasons behind its popularity. JavaScript is known as a dynamic object-oriented language, supporting prototype-based programming [9, 20], a different model from class-based languages. However, it also supports features of functional programming (e.g., first class functions). This flexibility helps in programming JavaScript applications for different requirements and goals, but it also renders program analysis techniques more complicated and often ineffective. Context sensitivity is a general technique to achieve more precise program analysis by distinguishing between calls to a specific function. Historically, call-strings and functional are the two approaches to enable context sensitivity in an analysis [14]. The call-strings approach, using the information on the call stack as a context element1 , originally was explored by Shivers (i.e., known as call-site sensitivity or k-CFA) for functional programming languages [15] and was later adapted to object-oriented languages such as Java [2]. The functional approach, using information about the computation state as a context element, was investigated in several variations for object-oriented languages (e.g., [1, 10]). Several 1 A context element refers to the label that is used to distinguish between different function calling contexts. © Shiyi Wei and Barbara G. Ryder; licensed under Creative Commons License CC-BY 29th European Conference on Object-Oriented Programming (ECOOP’15). Editor: John Tang Boyland; pp. 712–734 Leibniz International Proceedings in Informatics Schloss Dagstuhl – Leibniz-Zentrum für Informatik, Dagstuhl Publishing, Germany S. Wei and B. G. Ryder 713 studies were performed to compare the precision of different context-sensitive analyses for Java [7, 16]. These studies revealed that object sensitivity [10], an functional approach that uses the receiver object represented by its allocation site as a context element, often produced more precise results than call-site sensitivity in Java applications. Despite the challenges of effective analysis for JavaScript programs, different context- sensitive analyses have been developed to improve precision. Jensen et al. implemented object sensitivity in the TAJS analysis framework [4]. Several other context-sensitive analyses were designed for specific features in JavaScript programs (e.g., dynamic property accesses [19] and object property changes [22]). These approaches have been demonstrated effective when certain program features are present. Recently, Kashyap et al. conducted a study to compare the performance and precision of different context-sensitive analyses for JavaScript [5]. Unlike the results for Java analyses [7, 16], the authors concluded that there was no clear winner context-sensitive analysis for JavaScript across all benchmarks [5]. Because JavaScript features flexible programming paradigms and no single context- sensitive analysis seems best for analyzing JavaScript programs, there are opportunities for an adaptive (i.e., multi-choice) analysis to improve precision. In this work, we first performed a fine-grained study that compares the precision of four different JavaScript analyses on the function level (Section 2.2) on the same benchmarks used by Kashyap et al. [5]. We observed that JavaScript functions in the same program may benefit from use of different context-sensitive analyses depending on specific characteristics of the functions. The results of our empirical study guided us to design a novel adaptive context-sensitive analysis for JavaScript that selectively applies a specialized context-sensitive analysis per function chosen from call-site, object and parameter sensitivity. This two-staged analysis first applied an inexpensive points-to analysis (i.e., mostly context-insensitive, Section 2.2) to a JavaScript program to extract function characteristics. Each function characteristic is relevant to the precision of a context-sensitive analysis of the function (e.g., the call sites that invoke function foo determine the context elements to be generated if call-site sensitivity is applied to foo). We designed heuristics according to our observations on the relationship between function characteristics and the precision of a specific analysis using the empirical results on the benchmark programs. Finally, an adaptive analysis based on the heuristics-based selection of a context-sensitive analysis per function was performed. We have evaluated our new approach on two sets of benchmarks. The experimental results show that our adaptive context-sensitive analysis produces more precise results than any single context-sensitive analysis we evaluated for several JavaScript programs and that the heuristics for selecting a context-sensitive analysis per function are fairly accurate. The major contributions of this work are: A new empirical study on JavaScript benchmarks to compare the precision of different context-sensitive analyses (i.e., 1-call-site, 1-object and 1st-parameter as defined in Section 2.1). We measure the precision per function on two simple clients of points-to analysis (i.e., Pts-Size and REF ). We have made several observations: (i) any specific context-sensitive analysis is precise only for a subset of programs in the benchmarks. More interestingly, any specific context-sensitive analysis is often effective only on a portion of a program. (ii) The precision of a context-sensitive analysis also is dependent on the analysis client. These findings motivated and guided us to design a novel JavaScript analysis. An adaptive context-sensitive analysis for JavaScript. The heuristics to select from various context-sensitive analyses (i.e., 1-call-site, 1-object and ith-parameter) for a function are based on the function characteristics computed from an inexpensive points-to solution. This adaptive analysis is the first analysis for JavaScript that automatically and selectively ECOOP’15 714 Adaptive Context-sensitive Analysis for JavaScript applies a context-sensitive analysis depending on the programming paradigms (i.e., coding styles) of a function. An empirical evaluation of the adaptive context-sensitive analysis on two sets of benchmark programs. The experimental results show that our adaptive analysis was more precise than any single context-sensitive analysis for several applications in the benchmarks, especially for those using multiple programming paradigms. Our results also show that the heuristics were accurate for selecting appropriate context-sensitive analysis on the function level. Overview. Section 2 introduces various context-sensitive analyses and then presents our motivating empirical study. Section 3 discusses heuristics that represent the relationship between function characteristics and analysis precision. Section 4 describes the design of our new analysis. Section 5 presents experimental results. Section 6 further discusses related work. Section 7 offers conclusions. 2 Background and Empirical Study In this section, we first introduce the context-sensitive analyses used in our study. We then present the new comparisons among different context-sensitive analyses with empirical results and observations. 2.1 Context Sensitivity As discussed in Section 1, various context-sensitive analyses have been designed for different programming languages. In this section, we only discuss the approaches that are most relevant to our empirical study of context-sensitive analysis for JavaScript. We provide more discussions on related context-sensitive analyses in Section 6. Call-strings approach. A call-strings approach distinguishes function calls using information on the call stack. The most widely known call-strings approach is call-site-sensitive (k-CFA) analysis [15]. A k-call-site sensitive analysis uses a sequence of the top k call sites on the call stack as the context element. k is a parameter that determines the maximum length of the call string maintained to adjust the precision and performance of call-site-sensitive analysis. We used 1-call-site sensitivity for comparison. 1-call-site-sensitive analysis separately analyzes each different call site of a function. Intuitively in the code example below, 1-call-site-sensitive analysis will analyze function foo in two calling contexts L1 and L2, such that local variables (including parameters) of foo will be analyzed independently for each context element. L1 : x . foo ( p1 , p3 ); L2 : y . foo ( p2 , p4 ); Functional approach. A functional approach distinguishes function calls using information about the computation state at the call. Object sensitivity analyzes a function separately for each of the abstract object names on which this function may be invoked [10]. Milanova et al. presented object sensitivity as a parameterized k-object-sensitive analysis, where k denotes the maximum sequence of allocation sites to represent an object name. We used 1-object sensitivity for comparison. 1-object-sensitive analysis separately analyzes a function for each of its receiver objects with a different allocation site. Intuitively in the code example above, 1-object-sensitive analysis will analyze function foo separately if x and/or y may point to S. Wei and B. G. Ryder 715 different abstract objects. If x points to objects O1 and O2 , while y points to object O3 , 1-object-sensitive analysis will analyze function foo for three context elements differentiated as O1 , O2 and O3 . Other functional approaches presented use the computation state of the parameter instead of the receiver object as a context element [1, 19]. The Cartesian Product Algorithm (CPA) uses tuples of parameter types as a context element for Self [1]. The context-sensitive analysis presented by Sridharan et al., designed specifically for JavaScript programs, analyzes a function separately using the values of a parameter p if p is used as the property name in a dynamic property access (e.g., v[p]) [19]. To capture these approaches, we define a simplified, parameterized ith-parameter-sensitive analysis, where i means we use the abstract objects corresponding to the ith parameter as a context element. We used 1st-parameter sensitivity for comparisons. Intuitively in the code example above, 1st-parameter-sensitive analysis will analyze function foo separately if p1 and/or p2 may point to different abstract objects. If p1 points to object O4 , while p2 points to object O4 and O5 , 1st-parameter-sensitive analysis will analyze function foo for two context elements distinguished as O4 and O5 . 2.2 Empirical Study There is no theoretical comparison between the functional and call-strings approaches to context sensitivity that proves one better than the other. Therefore, we study the precision of different context-sensitive analyses in practice based on experimental observations. Such comparisons have been conducted for call-site and object sensitivity on Java [7, 16] as well as JavaScript [5] applications. Object sensitivity produced more precise results for Java benchmarks [7, 16], while there was no clear winner across all benchmarks for JavaScript [5]. The latter observation motivated us to perform an in-depth, fine-grained, function-level study which led to our design of a new context-sensitive analysis for JavaScript. Hypothesis. Our hypothesis is that a specific context-sensitive analysis may be more effective on a portion of a JavaScript program (i.e., some functions), while another kind of context sensitivity may produce better results for other portions of the same program. To test this hypothesis, we compared the precision of different context-sensitive analyses at the function level (i.e., we collect the results of different analyses for a specific function and compare their precision). In contrast, all previous work [7, 16, 5] reported overall precision results per benchmark program. The results of our empirical study were obtained on a 2.4 GHz Intel Core i5 MacBook Pro with 8GB memory running the Mac OS X 10.10 operating system. Analyses for comparisons. We compared across four different flow-insensitive analyses to study their precision. The baseline analysis is an analysis that applies the default context- sensitive analysis for JavaScript in WALA2 (i.e., only uses 1-call-site-sensitive analysis for the constructors to name abstract objects by their allocation sites and for nested functions to properly access variables accessible through lexical scoping [19]). In the implementation, the other three analyses (i.e., 1-call-site, 1-object and 1st-parameter) all apply this default analysis. In principle, these analyses should be at least as precise as the baseline analysis for all functions. 2 Our implementation is based on the IBM T.J. Watson Libraries for Analysis (WALA). http://wala. sourceforge.net/ ECOOP’15 716 Adaptive Context-sensitive Analysis for JavaScript Analysis clients and precision metrics. We compare precision results on two simple clients of points-to analysis. Points-to analysis calculates the set of values a reference property or variable may have during execution, an important enabling analysis for many clients. The first client, Pts-Size, is a points-to query returning the cardinality of the set of all values of all local variables in a function (i.e., the total number of abstract objects pointed to by local variables). The second client, REF [22], is a points-to query returning the cardinality of the set of all property values in all the property read (e.g., x=y.p) or call statements (e.g., x = y.p(...)) in a function (i.e., the total number of abstract objects returned by all the property lookups). Because both clients count the number of abstract objects returned and object-naming scheme is unified across different analyses, if an analysis A1 produces a smaller result than another analysis A2 for a function foo, we say that A1 is more precise than A2 for foo. Benchmarks. We conduct our comparisons on the same set of benchmarks used for the study performed by Kashyap et al. [5]. There are in total 28 JavaScript programs divided into four categories: standard (i.e., from SunSpider3 and V84 ), addon (i.e., Firefox browser plugins), generated (i.e., from the Emscripten LLVM test suite5 ) and opensrc (i.e., open source JavaScript frameworks). There are seven programs in each benchmark category.6 In our study, all benchmark programs are transformed with function extraction for correlated property accesses [19] before running any analysis. This program transformation preserves the semantics of the original programs and may help handle dynamic property accesses more accurately [19]. Results. We ran each analysis of a benchmark program under a time limit of 10 minutes. The baseline and 1-call-site-sensitive analyses finished analyzing all 28 programs under the time limit. 1-object-sensitive analysis timed out on 4 programs (i.e., linq_aggregate, linq_enumerable and linq_functional in the opensrc benchmarks and fourinarow in the generated benchmarks), while 1st-parameter-sensitive analysis timed out on 2 programs (i.e., fasta and fourinarow in the generated benchmarks). Figures 1a and 1b show the relative precision results for Pts-Size and REF, respectively. In both figures, the horizontal axis represents the results from four benchmark categories (i.e., standard, addon, generated and opensrc) and the vertical axis represents the percentages of functions in each benchmark category on which an analysis produces the best results (i.e., more precise results than those from all other three analyses) or equally precise results. We consider the results of an analysis as equally precise as follows. (i) Baseline analysis is equally precise on a function if its results are as precise as each of the other three context-sensitive analyses. (ii) 1-call-site-sensitive, 1-object-sensitive or 1st-parameter-sensitive analysis is equally precise on a function if the results are more precise results than baseline analysis, and if the analysis does not produce the best results but the results are at least as precise as the other two context-sensitive analyses. This definition indicates that multiple context-sensitive analyses (e.g., 1-call-site-sensitive and 1-object-sensitive analyses) may produce equally precise results on a function. For example, the left four bars in Figure 1a present the precision results for the addon 3 https://www.webkit.org/perf/sunspider/sunspider.html 4 http://v8.googlecode.com/svn/data/benchmarks/v7/run.html 5 http://kripken.github.io/emscripten-site/ 6 Details of the benchmark programs were provided in Kashyap et al. [5]. S. Wei and B. G. Ryder 717 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 70% 60% Percentage of functions 50% 1st-parameter_equal 1st-parameter_best 40% 1-object_equal 30% 1-object_best 1-call-site_equal 20% 1-call-site_best 10% baseline_equal 0% addon opensrc standard generated Benchmark category (a) Relative precision results for the Pts-Size client. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 100% 90% 80% Percentage of functions 70% 1st-parameter_equal 60% 1st-parameter_best 50% 1-object_equal 40% 1-object_best 30% 1-call-site_equal 20% 1-call-site_best 10% baseline_equal 0% addon opensrc standard generated Benchmark category (b) Relative precision results for the REF client. Figure 1 Comparison results between baseline, 1-call-site-sensitive, 1-object-sensitive and 1st- parameter-sensitive analyses. Bars show the percentage of functions on which an analysis is best or equally precise. benchmarks for the Pts-Size client. The baseline_equal bar (i.e., the left most) shows that baseline analysis achieved as precise results as those from all three other analyses for 64% of the functions in the addon benchmarks, indicating context sensitivity does not make much difference for more than two thirds of the functions in these programs for the Pts-Size client. The 1-call-site_best and 1st-parameter_best bars (i.e., the parts of the second and fourth bars from left filled with patterns) show that 1-call-site-sensitive and 1st-parameter-sensitive analyses produced more precise results than all other analyses for 9% and 1.5% of the functions in the addon benchmarks, respectively. The 1-object_best result missing from the third bar from left indicates that 1-object-sensitive analysis failed to produce the most precise results for any function in addon benchmarks. Nevertheless, the 1-object_equal bar shows 1-object-sensitive analysis achieved equally precise results with 1-call-site-sensitive and/or 1st-parameter-sensitive analyses for 25% of the functions in the addon benchmarks. ECOOP’15 718 Adaptive Context-sensitive Analysis for JavaScript Comparing with the 1-call-site_equal (26%) and 1st-parameter_equal (1%) bars, we can predict that 1-call-site-sensitive and 1-object-sensitive analyses had similar precision on a quarter of the functions in the addon benchmarks. The baseline_equal bars in Figure 1a show that analysis of a large percentage of functions in the benchmarks does not benefit from context sensitivity in terms of the Pts-Size results (i.e., from 32% for the generated benchmarks to 64% for the addon benchmarks). Also, 1-call- site-sensitive analysis had relatively consistent impact in the benchmarks, achieving best or equally precise results for around 30% functions across all benchmark categories. In contrast, the precision of 1-object-sensitive analysis results seems dependent on the benchmark. Having little impact on the precision of the opensrc benchmarks, 1-object-sensitive analysis produced best results for 29% of the functions in the generated benchmarks with an additional 11% of the functions achieving equally best results. 1st-parameter-sensitive analysis, less studied in previous work, produced best results for about 10% functions in the opensrc, standard and generated benchmarks, a reasonable technique to improve precision for these programs. It is also interesting to learn from Figure 1a that different context-sensitive analyses may produce equally precise results on many functions in some benchmark categories. 1-call-site-sensitive and 1-object-sensitive analyses produced equally best results for 25% functions in the addon benchmarks. 1-call-site-sensitive, 1-object-sensitive and 1st-parameter-sensitive analyses produced equally best results for 3% functions in the generated benchmarks. Recall that the REF client uses data from different parts of the points-to results than the Pts-Size client; in addition, the REF client may query the points-to results (i.e., all the property lookup statements in a function) less frequently than the Pts-Size client (i.e., all local variables in a function). Overall in Figure 1b, context sensitivity improves precision less over baseline analysis for the REF than for the Pts-Size client. Baseline analysis produced as precise results as all other three analysis for more than 50% of the functions in all benchmark categories. About 96% of the functions in the addon benchmarks did not benefit from any context-sensitive analysis over the baseline analysis. 1-call-site-sensitive analysis achieved dramatically better results for the Pts-Size client than REF client in addon, opensrc and standard benchmarks. 1-object-sensitive analysis also achieved much better results for the Pts-Size client than the REF client in the generated benchmarks. On the other hand, 1st-parameter-sensitive analysis still remains effective in the opensrc, standard and generated benchmarks. Summary. First, the effectiveness of specific context-sensitive analysis for JavaScript func- tions is sensitive to the coding style. For example, 1-call-site-sensitive, 1-object-sensitive and 1st-parameter-senstive analyses each produced best results on a large percentage of functions in the programs from the generated benchmarks. Second, the precision of context-sensitive analysis also depends on the analysis client. Based on these observations, we believe JavaScript programs can benefit from an adaptive context-sensitive analysis that chooses an appropriate context-sensitive analysis for a specific function. We used these observations as guidance to design our new analysis. 3 Function Characteristics and Heuristics A context-sensitive analysis is designed to be useful for a specific programming paradigm. For example, object-sensitive analysis targets the class-based model of object-oriented languages. The results from Section 2 indicate that JavaScript functions in one program may benefit from different context-sensitive analyses depending on the coding style of the functions. In S. Wei and B. G. Ryder 719 Table 1 Function characteristics. 1-call-site 1-object 1st-parameter FC1: CSNum FC6: 1ParNum context element FC4: RCNum approximations FC2: EquivCSNum FC7: 1ParName client-related FC3: AllUse FC5: ThisUse metrics FC8: 1ParOther this section, we present the function characteristics we extracted from the baseline analysis results and then investigate heuristics that represent the relations between these function characteristics and the precision of context-sensitive analyses. Finally, we use these heuristics to select the appropriate context-sensitive analysis per function in our adaptive algorithm (Section 4). 3.1 Function Characteristics For a JavaScript function, we extracted characteristics from the baseline analysis results that are relevant to the precision of context-sensitive analyses for a specific client. The goal is to extract function characteristics that (i) intuitively are relevant to the precision of a specific analysis for a particular client, and (ii) do not require more costly analysis than a baseline points-to analysis. Table 1 shows that for a JavaScript function foo, we extract eight function characteristics (i.e., FC1, FC2, ..., FC8 ). Each function characteristic is related to the precision of a specific context-sensitive analysis (i.e., FC1-FC3, FC4-FC5, and FC6-FC8 are related to the precision of 1-call-site, 1-object and 1st-parameter, respectively). For a specific context-sensitive analysis, we extracted two kinds of function characteristics: context element approximations and client-related metrics. A context element approximation predicts the number of distinct context elements generated for a function by a context-sensitive analysis, which determines its ability to distinguish between function calls. A client-related metric predicts the effectiveness of a context-sensitive analysis on a JavaScript function for a particular client. FC1 -FC2, FC4 and FC6 in Table 1 are the context element approximations we designed for 1-call-site-sensitive, 1-object-sensitive and 1st-parameter-sensitive analyses, respectively. For example, FC4-RCNum presents an approximation of the number of receiver objects on which a function is called, computed from the baseline points-to results. FC3, FC5 and FC7 -FC8 are the client-related metrics we designed for the Pts-Size client7 for 1-call-site, 1-object and 1st-parameter sensitivity, respectively. For example, FC5-ThisUse measures the usage frequency of the this object in the function body, because frequent use of the this object indicates that the precision of the Pts-Size client on the function depends on how accurately the this object is analyzed. Because 1-object-sensitive analysis potentially analyzes the this object more precisely, we use FC5-ThisUse to predict the effectiveness of 1-object-sensitive analysis on a function for the Pts-Size client. We now will define each function characteristic. 7 In this work, we use the Pts-Size client to demonstrate the effectiveness of our approach because the empirical results in Section 2.2 suggest that the Pts-Size client is relatively more sensitive to the choice of context-sensitive analyses. ECOOP’15 720 Adaptive Context-sensitive Analysis for JavaScript Function characteristics for 1-call-site-sensitive analysis. Recall that a 1-call-site-sensitive analysis uses the immediate call site of a function as the context element. We define FC1, the CSNum metric, as follows: FC1-CSNum: for function foo, the number of call sites that invoke foo in the baseline call graph G. Although FC1 approximates the number of context elements that a 1-call-site-sensitive analysis would generate for foo, this metric may not be directly relevant to the precision of 1-call-site-sensitive analysis. Intuitively, if function foo is invoked from two call sites CS1 and CS2, the analysis precision on foo is not likely to benefit from distinguishing between these two call sites if the parameters of CS1 and CS2 have the same values because these parameters are used in foo as local variables. More precisely, we define two call sites, CS1: p0.foo(p1, p2, ... , pn) and CS2: p0’.foo(p1’, p2’, ..., pn’), to be equivalent if for each pair of receiver objects and parameters (i.e., pi and pi’) in CS1 and CS2, the points-to sets of pi and pi’ are the same. We then define FC2, the EquivCSNum metric using this definition of equivalent call sites, as follows: FC2-EquivCSNum: for function foo, the number of equivalence classes of call sites that invoke foo in the baseline call graph G. Recall that the Pts-Size client calculates the cardinality of the set of abstract objects to which a local variable of foo may point. Intuitively, the precision of the Pts-Size client depends on the receiver object or parameters that are frequently used as local variables in the function body. For example, if a parameter p is never used in foo, even if 1-call-site-sensitive analysis distinguishes call sites that pass different values of p, the results of the Pts-Size client may not be different because p is never used locally. Theoretically, 1-call-site sensitivity may distinguish objects passed through any parameter as well as receiver objects via call sites. We define FC3, the AllUse metric, as follows: FC3-AllUse: for function foo, the total number of uses of the this object and all parameters. Function characteristics for 1-object-sensitive analysis. Recall that 1-object-sensitive ana- lysis distinguishes calls to a function if they correspond to different receiver objects. To approximate the number of context elements generated by 1-object-sensitive analysis for function foo, we define FC4, the RCNum metric, as follows: FC4-RCNum: for function foo, the total number of abstract receiver objects from all call sites that invoke foo in the baseline call graph G. Naturally, 1-object-sensitive analysis would be effective on functions implemented with the object-oriented programming paradigm. The behavior of these functions is dependent on the objects on which they are called. Uses of the this object in a function is common in the object-oriented programming paradigm and 1-object-sensitive analysis should produce relatively precise results. We define FC5, the ThisUse metric, as follows: FC5-ThisUse: for function foo, the total number of uses of the this object. Function characteristics for 1st-parameter-sensitive analysis. The ith-parameter sensit- ivity is designed to be effective when a specific parameter (e.g., the first parameter for 1st-parameter-sensitive analysis) has large impact on analysis precision. 1st-parameter- sensitive analysis uses the objects that the 1st parameter points to as context elements. We define FC6, the 1ParNum metric, as follows: FC6-1ParNum: for function foo, the total number of abstract objects to which the 1st parameter may point from all call sites that invoke foo in the baseline call graph G. S. Wei and B. G. Ryder 721 If a parameter p is frequently used in a function, it may be more important to apply context-sensitive analysis on p than on the receiver object. Also, if p is used as a property name in dynamic property accesses, using context sensitivity to distinguish the values of p significantly improves analysis precision [19]. We define FC7, the 1ParName metric, and FC8, the 1ParOther metric, as follows: FC7-1ParName: for function foo, the total number of uses of the 1st parameter as a property name in dynamic property accesses. FC8-1ParOther. for function foo, the total number of uses of the 1st parameter not as a property name. 3.2 Heuristics The function characteristics defined in Section 3.1 are intuitive and easy to calculate from the baseline points-to graph and call graph. Nevertheless, it is still not clear how these function characteristics are related to the precision of a context-sensitive analysis. In this section, we use empirical data to design the heuristics that define the relations between function characteristics and analysis precision. Our goal is to select an appropriate analysis for a function given the set of its function characteristics. The heuristics are not obvious given that there are multiple context-sensitive analysis choices. To design useful heuristics, we first compared the precision of a pair of analyses on the function level and observed the impact of a subset of function characteristics on these two analyses. We then applied these heuristics to adaptively choose an appropriate context-sensitive analysis using the function characteristics (Section 4). More specifically, for the Pts-Size results from the benchmarks (Section 2.2), we compared the precision between all 2-combinations of baseline, 1-call-site-sensitive, 1-object-sensitive and 1st-parameter-sensitive analyses and derived the heuristics to select an analysis from each of the combinations. For example, to choose between the baseline analysis and 1-call-site-sensitive analysis, we obtained the relevant subset of function characteristics (i.e., FC1-FC3 ) and the Pts-Size results of baseline and 1-call-site-sensitive analyses for each function foo in the benchmarks. If the Pts-Size result from 1-call-site-sensitive analysis is more precise than baseline analysis, 1-call-site sensitivity should be chosen when analyzing foo; otherwise, baseline analysis should be chosen. Given the list of function characteristics and corresponding analysis choices on the benchmark functions, we first used a machine learning algorithm8 to get the relationship (i.e., presented as a decision tree) between the function characteristics and analysis choice. We then manually adjusted the initial decision tree based on domain knowledge to decide on the heuristic, in order to ensure that the heuristic is intuitive and easy to interpret while the classifications still maintain good accuracy. We report the accuracy of an analysis choice (e.g., 1-call-site-sensitive analysis) using the standard information retrieval metrics of precision and recall. Assuming S1 is the set of all functions in the benchmarks where 1-call-site-sensitive analysis produces more precise results than baseline analysis and S2 is the set of functions where 1-call-site-sensitive analysis is chosen by the heuristic. T The precision of 1-call-site sensitivity classification isTcomputed |S1 S2| |S1 S2| as P1−call−site = |S2| and the recall is computed as R1−call−site = |S1| . The balanced F-score, the harmonic mean of the precision and recall, is computed as F1−call−site 8 We used the C4.5 classifier [12] implemented in Weka data mining software (http://www.cs.waikato. ac.nz/ml/weka/) to derive the initial decision tree. ECOOP’15 722 Adaptive Context-sensitive Analysis for JavaScript 1−call−site ×R1−call−site = 2× P P1−call−site +R1−call−site , where F1−call−site has its best value at 1 and worst score at 0 for choosing 1-call-site-sensitive analysis by this heuristic. Figure 2 shows the heuristics to make a choice between each pair of the analyses using function characteristic values. We discuss each pair of the analyses in turn: Baseline vs. 1-call-site. Three function characteristics (i.e., FC1-FC3 ) are relevant to the precision of 1-call-site-sensitive analysis for the Pts-Size client. For 1-call-site-sensitive analysis to produce more precise results than baseline analysis, the prerequisite is that there is more than one distinct 1-call-site-sensitive context element (i.e., FC1 > 1 ). Figure 2a shows the heuristic to choose between baseline and 1-call-site-sensitive analyses. 1-call-site- sensitive analysis is chosen over baseline analysis for a function foo if there is more than one equivalence class of call sites that invoke foo (i.e., FC2 > 1 ). This result indicates that the effectiveness of 1-call-site sensitivity depends on its ability to distinguish call sites with different receiver objects or different corresponding parameters. The balanced F-scores for baseline and 1-call-site-sensitive analyses in this heuristic are 0.46 and 0.8, respectively. Baseline vs. 1-object. FC4 and FC5 are relevant to the precision of 1-object-sensitive analysis for the Pts-Size client. For 1-object-sensitive analysis to produce more precise results than baseline analysis, the prerequisite is that there is more than one 1-object-sensitive context element (i.e., FC4 > 1 ). Figure 2b shows the heuristic to choose between baseline and 1-object-sensitive analyses. 1-object-sensitive analysis is chosen over baseline analysis for a function foo if the this object is used at least once in the function body of foo (i.e., FC5 > 0 ). This result suggests that 1-object-sensitive analysis is useful in terms of Pts-Size client for a function foo whose behavior relies on the values of the this object, even for a small number of 1-object-sensitive context elements for foo. The balanced F-scores for baseline and 1-object-sensitive analyses in this heuristic are 0.65 and 0.79, respectively. Baseline vs. 1st-parameter. Three function characteristics (i.e., FC6-FC8 ) are relevant to the precision of 1st-parameter-sensitive analysis for the Pts-Size client. For 1st-parameter- sensitive analysis to produce more precise results than baseline analysis, the prerequisite is that there is more than one 1st-parameter-sensitive context element (i.e., FC6 > 1 ). Figure 2c shows the heuristic to choose between baseline and 1st-parameter-sensitive analyses. 1st-parameter-sensitive analysis is chosen over baseline analysis for a function foo if the first parameter of foo is used (i.e., as the property name in dynamic property accesses or otherwise) at least once in the function body of foo (i.e., FC7 > 0 OR FC8 > 0 ). Similar to 1-object sensitivity, 1st-parameter sensitivity is another functional approach that distinguishes calls based on the computation states of a parameter. It is expected for 1-object-sensitive or 1st-parameter-sensitive analysis to be effective on the function foo if the values of the this object or the first parameter affect the behavior of foo. The balanced F-scores for baseline and 1st-parameter-sensitive analyses in this heuristic are 0.49 and 0.83, respectively. 1-call-site vs. 1-object. To select between 1-call-site-sensitive and 1-object-sensitive ana- lyses, function characteristics related to both are considered (i.e., FC1-FC5 ). In our adaptive analysis, two context-sensitive analyses are compared for a function when both of them would be chosen over baseline analysis (see Section 4). As a consequence, the prerequisite for the heuristic in this case is the number of equivalence classes of call sites is larger than 1 (i.e., FC2 > 1 ) and the this object is used at least once (i.e., FC5 > 0 ). Figure 2d shows the heuristic to choose between 1-call-site-sensitive and 1-object-sensitive analyses. The heuristic S. Wei and B. G. Ryder 723 FC2 - EquivCSNum = 1: baseline FC2 - EquivCSNum > 1: 1 - call - site (a) Baseline vs. 1-call-site. FC5 - ThisUse = 0: baseline FC5 - ThisUse > 0: 1 - object (b) Baseline vs. 1-object. FC7 -1 ParName = 0 AND FC8 -1 ParOther = 0: baseline FC7 -1 ParName > 0 OR FC8 -1 ParOther > 0: 1 st - parameter (c) Baseline vs. 1st-parameter. FC4 - RCNum / FC2 - EquivCSNum <= 0.8: 1 - call - site FC4 - RCNum / FC2 - EquivCSNum > 0.8 | FC5 - ThisUse / FC3 - AllUse <= 0.375: 1 - call - site | FC5 - ThisUse / FC3 - AllUse > 0.375: 1 - object (d) 1-call-site vs. 1-object. FC7 -1 ParName = 0 | FC8 -1 ParOther / FC3 - AllUse <= 0.19: 1 - call - site | FC8 -1 ParOther / FC3 - AllUse > 0.19 | | FC6 -1 ParNum / FC2 - EquivCSNum <= 3.8 | | | FC8 -1 ParOther / FC3 - AllUse <= 0.35: 1 - call - site | | | FC8 -1 ParOther / FC3 - AllUse > 0.35: 1 st - parameter | | FC6 -1 ParNum / FC2 - EquivCSNum > 3.8: 1 st - parameter FC7 -1 ParName > 0: 1 st - parameter (e) 1-call-site vs. 1st-parameter. FC7 -1 ParName = 0 | FC5 - ThisUse / FC8 -1 ParOther <= 0.8: 1 st - parameter | FC5 - ThisUse / FC8 -1 ParOther > 0.8 | | FC5 - ThisUse / FC8 -1 ParOther <= 1.34 | | | FC4 - RCNum / FC6 -1 ParNum < 0.5: 1 st - parameter | | | FC4 - RCNum / FC6 -1 ParNum >= 0.5 | | | | FC4 - RCNum / FC6 -1 ParNum <= 1: unknown | | | | FC4 - RCNum / FC6 -1 ParNum > 1: 1 - object | | FC5 - ThisUse / FC8 -1 ParOther > 1.34: 1 - object FC7 -1 ParName > 0: 1 st - parameter (f) 1-object vs. 1st-parameter. Figure 2 Heuristics to select between a pair of analyses. consists of the relationship between the metrics of both analyses. 1-call-site-sensitive analysis is selected if it generates a greater number of context elements than 1-object-sensitive analysis (i.e., FC4 / FC2 <= 0.8 ) for a function. This result suggests that 1-call-site-sensitive and 1-object-sensitive analyses in this case are empirically comparable in terms of precision. The relationship between the numbers of context elements generated by each analysis on foo indicates which context-sensitive analysis may be more precise for that function. When the ECOOP’15 724 Adaptive Context-sensitive Analysis for JavaScript number of receiver objects that invoke foo is close to or larger than the number of equivalence classes of call sites (i.e., FC4 /FC2 > 0.8 ), if the this object is used quite frequently (i.e., FC5 / FC3 > 0.375 ) in foo, 1-object-sensitive analysis is more precise for foo; otherwise (i.e., FC5 / FC3 <= 0.375 ), 1-call-site-sensitive analysis is selected. This result is intuitive in that 1-object-sensitive analysis produces more precise results than 1-call-site-sensitive analysis for the Pts-Size client when (i) 1-object-sensitive analysis generates a number of context elements and (ii) the behavior of a function is heavily dependent on the values of the receiver object. The balanced F-scores for 1-call-site-sensitive and 1-object-sensitive analyses in this heuristic are 0.67 and 0.8, respectively. 1-call-site vs. 1st-parameter. Function characteristics FC1-FC3 and FC6-FC8 are con- sidered to select between 1-call-site-sensitive and 1-object-sensitive analyses. The prerequisite for this comparison is FC2 > 1 and the first parameter of the function is used at least once (i.e., FC7 > 0 OR FC8 > 0 ). Figure 2e shows the heuristic to choose between 1-call-site- sensitive and 1-object-sensitive analyses. 1st-parameter-sensitive analysis is always selected if the first parameter is ever used as a property name in dynamic property accesses because the dynamic property accesses in JavaScript make analysis results very imprecise [19] and 1st-parameter sensitivity is a technique that significantly improves the analysis precision in this situation. In other cases, 1-call-site sensitive analysis is preferred if uses of the first parameter are not important to the function behavior (i.e., FC8 / FC3 <= 0.19 ). Also, similar to the heuristic that selects between 1-call-site-sensitive and 1-object-sensitive analyses (Figure 2d), the heuristic between 1-call-site-sensitive and 1st-parameter-sensitive analyses is dependent on the relationship between the context elements generated by both analyses. If 1st-parameter-sensitive analysis potentially generates many more context elements than 1-call-site sensitive analysis (i.e., FC6 / FC2 > 3.8 ), we expect the 1st-parameter-sensitive analysis to be more precise. Otherwise (i.e., FC6 / FC2 <= 3.8 ), depending on the import- ance of the first parameter to the function behavior, 1-call-site-sensitive analysis (when 0.19 < FC8 / FC3 <= 0.35 ) or 1st-parameter-sensitive analysis (when FC8 / FC3 > 0.35 ) is selected. The balanced F-scores for 1-call-site-sensitive and 1st-parameter-sensitive analyses in this heuristic are 0.73 and 0.66, respectively. 1-object vs. 1st-parameter. Finally, Figure 2f presents the heuristic that selects between 1-object-sensitive and 1st-parameter-sensitive analyses. Function characteristics FC4-FC8 are considered and the prerequisite is FC5 > 0 and FC7 > 0 OR FC8 > 0. It is not surprising that 1-object-sensitive analysis is selected by the heuristic when the this object is more frequently used (i.e., FC5 /FC8 > 1.34 ) and 1st-parameter-sensitive analysis is selected when the condition is opposite (i.e., FC5 /FC8 <= 0.8 ). When uses of the this object and the first parameter are similar (i.e., 0.8 < FC5 /FC8 < 1.34 ), the number of context elements generated by these two analyses decides the selection: (i) if 1-object- sensitive analysis potentially generates more context elements than 1st-parameter-sensitive analysis (i.e., FC5 /FC 8 > 1 ), we expect 1-object sensitive analysis to be more precise; (ii) if 1st-parameter-sensitive analysis generates more than twice the number of context elements than 1-object-sensitive analysis (i.e., FC5 /FC 8 < 0.5 ), 1st-parameter-sensitive analysis is selected; (iii) otherwise (i.e., 0.5 <= FC5 /FC 8 <= 1 ), it is not clear from the data in the benchmarks which analysis produces more precise results because the function characteristics indicate that they have similar capability to analyze the function. In this case, we randomly select between 1-object-sensitive and 1st-parameter-sensitive analyses for the function whose characteristics fall in this region. The balanced F-scores for 1-object-sensitive and 1st-parameter-sensitive analyses in this heuristic are 0.79 and 0.86, respectively. S. Wei and B. G. Ryder 725 iParName < jParName : jth - parameter iParName = jParName | iParOther < jParOther : jth - parameter | iParOther = jParOther | | iParNum < jParNum : jth - parameter | | iParNum >= jParNum : ith - parameter | iParOther > jParOther : ith - parameter iParName > jParName : ith - parameter Figure 3 Heuristic for ith-parameter vs. jth-parameter. Summary. The heuristics presented in Figure 2 are intuitive for making a choice between each pair of analyses. More importantly, the heuristics for the call-strings approach and the functional approaches (i.e., Figures 2d and 2e) allow us to make a decision between two incomparable analyses. Finally, these heuristics are accurate (i.e., good balanced F-scores) in terms of their effectiveness on the benchmark programs. 4 Adaptive Context-sensitive Analysis In this section, we present our adaptive context-sensitive analysis algorithm. This staged analysis (i) uses baseline analysis to obtain a call graph and points-to solution to extract function characteristics and (ii) performs an adaptive context-sensitive analysis based on heuristics that select an appropriate context-sensitive analysis for each function. 4.1 Function Characteristics Extraction In Section 3, we discussed the function characteristics used in the heuristics to select from baseline, 1-call-site-sensitive, 1-object-sensitive and 1st-parameter-sensitive analyses. Various other context-sensitive analyses exist for improving analysis precision. For example, ith- parameter-sensitive analysis (Section 2.1) provides variations to distinguish function calls based on the computation states of parameters, decided by the parameter i. In our adaptive context-sensitive analysis, we actually apply ith-parameter-sensitive analysis for a function whose precision relies on how accurately the ith parameter is ana- lyzed. Therefore, for each parameter of a function, we extract three function characteristics: iParNum, iParName and iParOther. We apply the heuristics of 1st-parameter-sensitive analysis to select between ith-parameter-sensitive analysis and baseline(Figure 2c), 1-call- site-sensitive (Figure 2e) or 1-object-sensitive (Figure 2f) analysis. To select between ith- parameter-sensitive and jth-parameter-sensitive analyses, we apply the heuristic shown in Figure 3. We designed this heuristic based on the observation that for parameter sensitivity, a functional approach, the uses of the parameter whose computation states are used to distinguish function calls usually are more closely related to the analysis precision. In Figure 3, because the uses of a parameter as a property name in the dynamic property accesses is the most important characteristic, if one parameter is used as a property name more often than the other, distinguishing function calls based on its values may produce more precise results. If the ParName characteristics are the same for parameters i and j, the uses of the parameters in other situations are compared to decide if ith-parameter-sensitive analysis is more/less precise than jth-parameter-sensitive analysis. Finally, if both client-related metrics (i.e., ParName and ParOther) cannot distinguish the parameters, the heuristic selects the parameter that points to more objects. ECOOP’15 726 Adaptive Context-sensitive Analysis for JavaScript ith-par =1 analysis Proc >1 2 par-sens > 1 analyses Function Proc Characteristics >1 analyses <=1 par-sens 3 Proc baseline 1 1-call-site 1-call-site 1-object ith-par =1 analysis 1-object ith-par Figure 4 Workflow to select a context-sensitive analysis for a JavaScript function. For a function foo with n parameters, we extract three characteristics for 1-call-site sensitivity (i.e., CSNum, EquivCSNum and AllUse), two characteristics for 1-object sensitivity (i.e., RCNum and ThisUse), and three characteristics for ith-parameter sensitivity (i.e., iParNum, iParName and iParOther). In total, there are 6+3n function characteristics for foo. 4.2 Algorithm Our adaptive context-sensitive analysis automatically selects a specific context-sensitive analysis for each function based on the function characteristics derived from the baseline analysis. Figures 2a-2f and 3 present the heuristics used to choose between pairs of analyses. The overall algorithm to select the context-sensitive analysis for a function is described in Figure 4. Given the function characteristics of function foo, Procedure 1 performs all pairwise comparisons between baseline analysis and 1-call-site-sensitive, 1-object-sensitive and ith-parameter-sensitive analyses for all the parameters of foo. If Procedure 1 returns a single analysis, this analysis is selected for foo. Returning baseline analysis means none of the context-sensitive analyses makes much difference to improve precision for foo. In case more than one choice is returned by Procedure 1, further comparisons are conducted to decide the specific context-sensitive analysis to use for foo. If the analysis precision of foo may benefit from applying parameter-sensitive analyses on multiple parameter choices returned by Procedure 1, Procedure 2 selects from among them to find the parameter i that may produce the most precise results when ith-parameter-sensitive analysis is applied. If the choices from Procedure 1 are now narrowed down to only the ith-parameter-sensitive analysis, this analysis is selected by our algorithm to analyze foo. When necessary, Procedure 3 chooses from the remaining context-sensitive analyses that are returned by Procedures 1 and 2. If there are two remaining context-sensitive analyses to choose from, Procedure 3 applies the heuristic in Figure 2d, 2e or 2f to decide on the context- sensitive analysis for analyzing foo. Otherwise (i.e., to choose from all three context-sensitive analyses), Procedure 3 compares each pair of 1-call-site-sensitive, 1-object-sensitive and ith- parameter-sensitive analyses and tries to find a best context-sensitive analysis for a majority of the pairs using heuristics in Figures 2d, 2e and 2f. For example, the adaptive analysis selects 1-call-site-sensitive analysis to analyze foo if it is chosen by both heuristics comparisons with 1-object-sensitive and ith-parameter-sensitive analyses. Finally, if Procedure 3 cannot S. Wei and B. G. Ryder 727 decide on a specific accurate context-sensitive analysis (i.e, when each of the three heuristics returns a different analysis choice), the adaptive analysis randomly chooses an analysis for foo. 5 Evaluation In this section, we first present the details of our experimental setup. We then evaluate our adaptive context-sensitive analysis using two sets of benchmarks. We compared the precision of adaptive analysis to other context-sensitive analyses applied to the entire program. 5.1 Experiment Setup Our implementation of adaptive context-sensitive analysis was based on the WALA static analysis infrastructure that supports JavaScript analysis. The baseline points-to analysis, ZERO_ONE_CFA analysis in WALA that uses the default context sensitivity for JavaScript analysis (Section 2.2), produced a call graph and a points-to solution from which we extracted the function characteristics. For the adaptive context-sensitive analysis, we implemented a new context selector9 that applies the context-sensitive analysis chosen by the heuristics for each function. Note that the default context-sensitive analysis is always used as well to ensure that the results of adaptive analysis are comparable to the baseline analysis. The goals of the experiments include: (i) comparing the precision of adaptive context- sensitive analysis with each of the other context-sensitive analyses to learn if the adaptive analysis improves JavaScript analysis precision and (ii) studying the accuracy of selecting a specific context-sensitive analysis for each function to validate the quality of the heuristics presented in Section 3. To achieve these goals, we evaluated our analysis on two sets of benchmarks: (i) the same benchmark programs on which we performed the empirical study in Section 2.2 (i.e., Benchmarks I including the 28 JavaScript programs collected by Kashyap et al. [5], divided into four categories) and (ii) four open-source JavaScript applications or libraries (i.e., Benchmarks II). The programs in Benchmarks II are (i) Box2DWeb, collected in the Octane benchmarks10 , (ii) minified.js library11 version 1.0, (iii) mootools library12 version 1.5.1, and benchmark.js library13 version 1.0.0. Because the heuristics were designed based on machine learning results using Benchmarks I, Benchmarks II serve to test if these heuristics can be applied by the adaptive context-sensitive analysis to arbitrary JavaScript programs and produce fairly accurate analysis results for the Pts-Size client. 5.2 Experimental Results Results for Benchmarks I. Figure 5 shows the analysis precision results for Benchmarks I. We compared the results of our adaptive analysis with the context-sensitive analysis (i.e., 1-call-site-sensitive, 1-object-sensitive or 1st-parameter-sensitive analysis) that produced most accurate results for each program for these benchmarks. We define a context-sensitive analysis to be the winner analysis for a program if it was at least as precise as the other 9 In WALA, the context element at a call site is decided by a context selector. 10 https://developers.google.com/octane/ 11 http://minifiedjs.com 12 http://mootools.net 13 http://benchmarkjs.com ECOOP’15 728 Adaptive Context-sensitive Analysis for JavaScript winner analysis adaptive analysis 1 1 2 2 3 3 4 4 100% Percentage of functions 95% 90% 85% 80% 75% 70% 65% 60% addon opensrc standard generated Benchmark I category Figure 5 Analysis precision on Benchmarks I. two context-sensitive analyses on the largest number of functions. For all 14 programs in the addon and opensrc benchmarks, 1-call-site-sensitive analysis was the winner among the 1-call-site-sensitive, 1-object-sensitive and 1st-parameter-sensitive analyses. For the standard benchmarks, 1st-parameter-sensitive analysis was winner on three programs and 1-call-site-sensitive analysis was winner on the other four programs. For all but one program in the generated benchmarks, 1-object-sensitive analysis was the winner analysis and 1- call-site-sensitive analysis was winner for fourinarow. In Figure 5, the winner analysis bar shows the percentage of the total number of functions in each benchmark category on which the winner analysis produced most accurate results. For example, the leftmost winner analysis bar represents that 1-call-site analysis (i.e., the winner analysis for all the programs in the addon benchmarks) produced at least as precise results as 1-object-sensitive and 1st-parameter-sensitive analyses for 98.8% of the functions in the addon benchmarks. The adaptive analysis bar shows the percentage of functions in each benchmark category for which our adaptive analysis produced at least as precise results as 1-call-site-sensitive, 1-object-sensitive and 1st-parameter-sensitive analyses. In Figure 5, our adaptive analysis produced at least as precise results for most functions in the addon and opensrc benchmarks (i.e., 98% and 90%, respectively). In these two benchmark categories, 1-call-site-sensitive analysis was the winner analysis for all programs, producing at least as precise results for 98.8% and 89.8% of the functions, respectively. These results indicate our adaptive analysis is capable of producing similar precision for a set of programs that shares the same winner analysis. For the standard benchmarks, the winner analyses (i.e., 1-call-site-sensitive analysis for four programs and 1st-parameter-sensitive analysis for three programs) were more precise than the adaptive analysis in terms of the percentage of functions for which an analysis produced at least as precise results (i.e., 81.9% of the functions for the winner analyses comparing to 77.1% of the functions for adaptive analysis). Nevertheless, the adaptive analysis still achieved good precision for most of these relatively small programs in the standard benchmarks. Even though there were different winner context-sensitive analyses on the programs from the standard benchmarks, the use of the adaptive analysis avoided having to manually pick a specific context-sensitive analysis for an individual program. Finally, for the programs in the generated benchmarks, our adaptive analysis significantly improved precision over the winner context-sensitive analyses (i.e., 1-object-sensitive analysis for 6 programs and 1-call-site-sensitive analysis for the other one), S. Wei and B. G. Ryder 729 Table 2 Selection precision for Benchmarks I. # of selected best / equally precise # of observed true positive functions (true analysis functions rate positives) 1-call-site 351 258 73.5% 1-object 241 164 68.0% 1st-parameter 162 79 48.8% 1-call-site: 39 1-call-site = 1-object 153 94.1% 1-object: 105 1-call-site 1-call-site: 23 39 74.4% = 1st-parameter 1st-parameter: 6 1-object 1-object: 4 6 83.3% = 1st-parameter 1st-parameter: 1 1-call-site 1-call-site: 2 = 1-object 25 1-object: 13 100% = 1st-pararameter 1st-parameter: 10 total 977 704 72.1% from 71.7% to 86.7% functions. According to the results in Figure 1a, the programs in the generated benchmarks require context sensitivity for precision and moreover, these programs often benefited from different context-sensitive analyses. The results for the generated benchmarks show that we achieved our goal to analyze a multi-paradigm JavaScript program more accurately using a different context-sensitive analysis for each function. The most important aspect of adaptive analysis is its ability to select an appropriate context-sensitive analysis for a specific function. Table 2 shows the accuracy of the analysis selection process for a function using the heuristics presented in Section 3 with the Pts-Size client. The first column in Table 2 lists the (set of) analyses that are best or equally precise (i.e., rows 4-7 in the first column) for a function (see Section 2.2). The second column shows the total number of functions in all programs from Benchmarks I on which the corresponding analyses were observed to produced the best or equally precise results. There were in total 1817 functions analyzed in Benchmarks I and the precision results of 977 functions were improved over baseline analysis by at least one context-sensitive analysis for the Pts-Size client. The last column presents the the number of functions on which the adaptive analysis matched the observed results (i.e., true positives for our heuristics). For those functions on which 1-call-site-sensitive and 1-object-sensitive analyses produced the best results, the selection heuristics resulted in good precision (i.e., 73.5% and 68%, respectively). However, the selection on 1st-parameter-sensitive analysis only achieved 48.8% precision. This is because our adaptive analysis chooses the appropriate ith-parameter-sensitive analysis to analyze a function using the parameter sensitivity. Here we are only checking the selection precision with respect to 1st-parameter-sensitive analysis; whereas ith-parameter-sensitive analysis (i>1) was applied to analyze 51 functions in the programs of Benchmarks I. 1-call-site-sensitive and 1-object-sensitive analyses produced equally precise results in terms on Pts-Size client on 153 functions. The adaptive analysis correctly selected 1- call-site-sensitive or 1-object-sensitive analysis to analyze 144 of those 153 functions, and interestingly, the choice was leaning towards 1-object-sensitive analysis (i.e., 1-object-sensitive analysis for 105 functions comparing to 1-call-site-sensitive analysis for 39 functions). For the functions on which equally precise results were produced by 1-call-site-sensitive and ECOOP’15 730 Adaptive Context-sensitive Analysis for JavaScript 1-call-site 1-object 1st-parameter adaptive 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100% Percentage of functions 90% 80% 70% 60% 50% 40% box2d minified.js mootools benchmark.js Benchmarks II Figure 6 Analysis precision on Benchmarks II. 1st-parameter-sensitive analyses, adaptive analysis selects more functions to be analyzed by 1-call-site-sensitive analysis. The overall precision of selecting a context-sensitive analysis by our heuristics is very good (i.e., 72.1%); this is a measure of when adaptive analysis made the best choice possible. The above observations may help us to improve the heuristics in the future. The time cost of our adaptive analysis is the sum of its two stages (i.e., the baseline points-to analysis to gather function characteristics and the subsequent adaptive context- sensitive analysis). We compare the performance of our adaptive analysis with the winner analysis for each program in Benchmarks I. On average over all the programs in Benchmarks I, our two-staged analysis introduced a 67% overhead. Nevertheless, the second stage (i.e., the adaptive context-sensitive analysis) is on average 19% faster than the winner analysis over the Benchmarks I programs. This result suggests that an appropriate choice of context sensitivity per function yields better performance and precision. Results for Benchmarks II. Figure 6 shows initial analysis precision results using four programs from Benchmarks II. The sizes of these programs, in terms of the number of functions analyzed, are 126, 119, 80 and 64, respectively. The 1-call-site, 1-object and 1st-parameter bars represent the percentage of functions on which each context-sensitive analysis produced at least as precise results as the other two. The adaptive bar (rightmost) represents the percentage of functions on which the adaptive analysis produced at least as precise results as 1-call-site-sensitive, 1-object-sensitive and 1st-parameter-sensitive analyses. We picked these four programs in Benchmarks II because their analysis results for different context-sensitive analyses were varied. For example, 1-object-sensitive analysis was more precise than 1-call-site-sensitive and 1st-parameter sensitive analyses for box2d, while 1st- parameter-sensitive analysis was the most precise for mootools. The results in Figure 6 show that our adaptive analysis achieved better results than any single context-sensitive analysis for box-2d and minified.js. For example, 1-object-sensitive analysis was at least as precise for 92.8% of the functions in box-2d; adaptive analysis improved these results to 98.4% of the functions. 1-call-site-sensitive analysis produced at least precise results for 88.2% of the functions in minified.js; adaptive analysis improved the results by 5.9% more functions. 1st-parameter-sensitive and 1-call-site-sensitive analyses were the most precise context-sensitive analyses for mootools and benchmark.js, respectively. While adaptive analysis produced results lower than these analyses, the results of adaptive analysis S. Wei and B. G. Ryder 731 were close, only different for 6.2% and 4.7% of the functions in mootools and benchmark.js, respectively. Overall, our adaptive context-sensitive analysis was fairly accurate for analyzing these programs from Benchmarks II. This promising result indicates that the heuristics presented in Section 3 may be applicable in general to JavaScript programs. 5.3 Discussion In this work, we have demonstrated the ability of our adaptive analysis that chooses a specific context-sensitive analysis for each function in order to significantly improve analysis precision. Nevertheless, this initial work has inspired us with more research ideas for further improvements of context-sensitive analyses for JavaScript. First, since we evaluated the adaptive analysis on a simple client of points-to analysis (i.e., Pts-Size), it would be interesting to know if adaptive analysis is effective to improve precision for other clients (e.g., security analysis). Second, context-sensitive analysis for JavaScript are not limited to 1-call-site, 1-object and ith-parameter. A deeper object-sensitive analysis (i.e., k-object) or another context-sensitive analysis (e.g., using the length of the parameter list at a call site as context element to distinguish JavaScript variadic functions [21]) could be used by adaptive analysis. New heuristics need to be designed for selecting these analyses. Third, we would like to explore if analysis precision may benefit from applying multiple-sensitive analyses on a specific JavaScript function. The idea of hybrid context-sensitive analysis has been tried for analyzing Java programs [6]. Fourth, scalability is an important issue for JavaScript analyses, especially for analyzing JavaScript websites that use libraries heavily (e.g., jQuery). In this work, we do not address this problem, that is, when a baseline points-to analysis is not scalable for a large JavaScript application, typically a website. In the future, we plan to focus on improving the performance of analysis of JavaScript websites using an adaptive approach. Although we used benchmarks collected by Kashyap et al. [5] as well as other JavaScript programs to evaluate adaptive context-sensitive analysis, these programs may not be rep- resentative of non-website JavaScript applications, which might threaten the validity of our conclusions as applicable to all JavaScript programs. 6 Related Work To the best of our knowledge, we have proposed the first analysis for JavaScript that adaptively uses multiple context-sensitive analyses to analyze a program when context sensitivity may help improve precision. Nevertheless, our work is related to approaches that apply context-sensitive analysis selectively (e.g., refinement-based analysis [3, 18, 17] and hybrid context-sensitive analysis [6]) for other programming languages. We already have discussed several context-sensitive analyses in Sections 1 and 2. In this section, we focus on related “selective” context-sensitive analyses. Context-sensitive analysis has been deeply investigated for other object-oriented languages such as Java. However, these object-oriented languages do not seem as amenable to our approach of using different context-sensitive analyses on different functions. Castries and Smaragdakis presented hybrid context-sensitive points-to analysis for Java [6]. Several combinations of call-site and object-sensitive analyses were explored and evaluated for precision. Their results showed that selectively adding call-site-sensitive analysis to specific places in the program (e.g., static calls) significantly improved the precision of object-sensitive points-to analysis for Java. Our adaptive analysis automatically chooses an appropriate context-sensitive analysis for each function in JavaScript program. ECOOP’15 732 Adaptive Context-sensitive Analysis for JavaScript Several works were proposed to tune the context sensitivity of an analysis based on pre-analysis results. Smaragdakis et al. presented introspective analysis that aims to improve the performance of a context-sensitive analysis for Java [17]. Introspective analysis selectively refines allocation sites or call sites based on the heuristics consisting of metrics computed from context-insensitive points-to results. The heuristics are tunable via constant parameters. In our adaptive analysis, the heuristics are computed from baseline analysis and syntactic analysis. The heuristics in our analysis focus on “which” context-sensitive analysis may improve precision instead of “if” context sensitivity would be of benefit. Sridharan and Bodík presented a refinement-based points-to analysis for Java [18] that refines sensitivity for heap accesses and method calls. It also is demand-driven in that it skips irrelevant code in the analysis. Our adaptive context-sensitive analysis aims to improve precision for the whole program. Guyer and Lin presented a client-driven analysis for C that automatically adjusts its precision in response to the needs of client analyses [3]. This client-driven analysis monitors polluting assignments (i.e., the program points that result inaccuracy in the analysis) and tunes context as well as flow sensitivity to improve precision. Liang and Naik presented another client-driven algorithm for Java that prunes away analysis results irrelevant to refinement for more precision [8]. For these techniques, a pre-analysis is used to determine the program points for refinement. Baseline points-to analysis is used to derive the function characteristics for our heuristics. Furthermore, our adaptive analysis involves more than one context-sensitive analysis. Oh et al. presented a selective context-sensitive analysis for C guided by an impact pre- analysis [11]. The impact pre-analysis applies full context sensitivity (i.e., ∞-CFA) but with simplified abstract domain and transfer functions to infer the impacts of context sensitivity in the main analysis. The heuristics in our adaptive analysis focus on the characteristics of a function to indicate whether analysis precision for a function would benefit from a specific context-sensitive analysis. Our pre-analysis, the baseline analysis, is comparable with the adaptive analysis in terms of abstract domain and transfer functions. 7 Conclusions The effectiveness of a context-sensitive analysis on a JavaScript program depends on its coding style because JavaScript features both object-oriented and functional programming paradigms. The fact that there is no winner context-sensitive analysis for the JavaScript benchmarks we examined motivated us to design an adaptive analysis. Our analysis applies a specialized context-sensitive analysis per function, using heuristics based on function characteristics derived from an inexpensive points-to analysis. Our experimental results show that adaptive analysis is more precise than any single context-sensitive analysis for several programs in the benchmarks, especially for those multi-paradigm programs whose analysis precision can benefit from multiple context-sensitive analyses. This work also has inspired opportunities to solve fundamental problems in analyzing JavaScript programs including analysis scalability for websites. References 1 Ole Agesen. The cartesian product algorithm: Simple and precise type inference of para- metric polymorphism. In Proceedings of the 9th European Conference on Object-Oriented Programming, ECOOP’95, pages 2–26, 1995. S. Wei and B. G. Ryder 733 2 David Grove, Greg DeFouw, Jeffrey Dean, and Craig Chambers. Call graph construction in object-oriented languages. In Proceedings of the 12th ACM SIGPLAN Conference on Object-oriented Programming, Systems, Languages, and Applications, OOPSLA’97, pages 108–124, 1997. 3 Samuel Z. Guyer and Calvin Lin. Client-driven pointer analysis. In Proceedings of the 10th International Conference on Static Analysis, SAS’03, pages 214–236, 2003. 4 Simon Holm Jensen, Anders Møller, and Peter Thiemann. Type analysis for JavaScript. In Proceedings of the 16th International Symposium on Static Analysis, SAS’09, pages 238–255, 2009. 5 Vineeth Kashyap, Kyle Dewey, Ethan A. Kuefner, John Wagner, Kevin Gibbons, John Sar- racino, Ben Wiedermann, and Ben Hardekopf. Jsai: A static analysis platform for JavaS- cript. In Proceedings of the 22Nd ACM SIGSOFT International Symposium on Foundations of Software Engineering, FSE 2014, pages 121–132, 2014. 6 George Kastrinis and Yannis Smaragdakis. Hybrid context-sensitivity for points-to analysis. In Proceedings of the 34th ACM SIGPLAN Conference on Programming Language Design and Implementation, PLDI’13, pages 423–434, 2013. 7 Ondřej Lhoták and Laurie Hendren. Evaluating the benefits of context-sensitive points-to analysis using a bdd-based implementation. ACM Trans. Softw. Eng. Methodol., 18(1):3:1– 3:53, October 2008. 8 Percy Liang and Mayur Naik. Scaling abstraction refinement via pruning. In Proceedings of the 32Nd ACM SIGPLAN Conference on Programming Language Design and Implementa- tion, PLDI’11, pages 590–601, 2011. 9 Henry Lieberman. Using prototypical objects to implement shared behavior in object- oriented systems. In Conference proceedings on Object-oriented programming systems, lan- guages and applications, OOPLSA’86, pages 214–223, 1986. 10 Ana Milanova, Atanas Rountev, and Barbara G. Ryder. Parameterized object sensitivity for points-to analysis for Java. ACM Trans. Softw. Eng. Methodol., 14(1):1–41, January 2005. 11 Hakjoo Oh, Wonchan Lee, Kihong Heo, Hongseok Yang, and Kwangkeun Yi. Selective context-sensitivity guided by impact pre-analysis. In Proceedings of the 35th ACM SIG- PLAN Conference on Programming Language Design and Implementation, PLDI’14, pages 475–484, 2014. 12 J. Ross Quinlan. C4.5: Programs for Machine Learning. Morgan Kaufmann Publishers Inc., San Francisco, CA, USA, 1993. 13 RedMonk. The RedMonk programming language rankings. http://redmonk.com/ sogrady/2014/06/13/language-rankings-6-14/, 2014. 14 Micha Sharir and Amir Pnueli. Two approaches to interprocedural data flow analysis. Program Flow Analysis: Theory and Applications, pages 189–234, 1981. 15 Olin Grigsby Shivers. Control-flow Analysis of Higher-order Languages of Taming Lambda. PhD thesis, Carnegie Mellon University, 1991. 16 Yannis Smaragdakis, Martin Bravenboer, and Ondrej Lhoták. Pick your contexts well: un- derstanding object-sensitivity. In Proceedings of the 38th annual ACM SIGPLAN-SIGACT symposium on Principles of programming languages, POPL’11, pages 17–30, 2011. 17 Yannis Smaragdakis, George Kastrinis, and George Balatsouras. Introspective analysis: Context-sensitivity, across the board. In Proceedings of the 35th ACM SIGPLAN Con- ference on Programming Language Design and Implementation, PLDI’14, pages 485–495, 2014. 18 Manu Sridharan and Rastislav Bodík. Refinement-based context-sensitive points-to analysis for Java. In Proceedings of the 2006 ACM SIGPLAN Conference on Programming Language Design and Implementation, PLDI’06, pages 387–400, 2006. ECOOP’15 734 Adaptive Context-sensitive Analysis for JavaScript 19 Manu Sridharan, Julian Dolby, Satish Chandra, Max Schäfer, and Frank Tip. Correlation tracking for points-to analysis of JavaScript. In Proceedings of the 26th European Conference on Object-Oriented Programming, ECOOP’12, pages 435–458, 2012. 20 Peter Wegner. Dimensions of object-based language design. In Conference proceedings on Object-oriented programming systems, languages and applications, OOPSLA’87, pages 168–182, 1987. 21 Shiyi Wei and Barbara G. Ryder. Practical blended taint analysis for JavaScript. In Proceedings of the 2013 International Symposium on Software Testing and Analysis, ISSTA 2013, pages 336–346, 2013. 22 Shiyi Wei and Barbara G. Ryder. State-sensitive points-to analysis for the dynamic behavior of JavaScript objects. In Proceedings of the 28th European Conference on Object-oriented Programming, ECOOP’14, pages 1–26, 2014.