-
Notifications
You must be signed in to change notification settings - Fork 1
Domains
We use the several data structures for the analysis. Since the data structures reflect the design of the analysis domain, it is crucial to understand the analysis.
Type is the super-class of all types. It has several sub-classes.
-
ObjTypeextendsType:ObjTypeis the class for abstract objects. EachFnTypehas oneObjTypeinstance which represents all of its concrete objects.ObjTypehas instance variablepropswhich is a mapping from string properties toAVals. We usenullvalue to represent the unknown properties. -
PrimTypeextendsType:PrimTypehas 3 instances -PrimNumber,PrimStringandPrimBoolean. We abstract each primitive value into one of the 3 instances. -
FnTypeextendsObjType: Since functions are also objects,FnTypeinheritsObjType.FnTypehas additional information specific for functions like list of parameters, abstract scope, lexical this and so on. -
ArrTypeextendsObjType:ArrTypeis the class for arrays.
Calcium basically collects possible types of expressions and variables into corresponding sets.
AVals basically constitute not only type sets but also propagation graph.
-
AVal's instance variabletypescollects its types. -
AVal's instance variableforwardscollects its propagation targets. Here, a propagation target can be eitherAValorCSTR.
Therefore, we know the propagation status from types and propagation graphs from forwards.
AVal's two most important methods are :
-
addType(type): add a single type tothisand also addtypeto each target inforwards. -
propagate(target): add all the types it has to thetargetand addstargetto itsforwards.
VarBlock represents a syntactic block where we can declare variables. We collect basic information about block scopes into VarBlocks use it to construct Scope.
- Its instance variable
parenis pointing to the parentvarBlock. - Its instance variable
blockTypedenotes its type of block. Possible types of a block areglobalBlock,oldFunctionBlock,arrowFunctionBlock,parameterBlock,catchBlockandnormalBlock. - Its instance variable
paramVarNameshas the array of its parameter variables, andlocalVarNameshas the array of its local variables. These variables are used to create avarMapinstance.varMapis a mapping from its variable names to theirAVals. - Its instance variable
instancesis a mapping fromContexttovarMap. Note that onevarMapcan be included by multipleScopeinstances. - The most important method is
getScopeInstance(paren, delta)which returns aScopeinstance whose parentScopeisparenand whosevarMapis an instance fordeltacontext.
Scope is the class for abstract scopes which we carry during constraint generation to obtain AVals for variables.
- Its instance variable
parenhas the parentScopeinstance. We visit a finite list ofScopes to look up variables. Note that the graph ofShapeinduced byparendoes not have any cycles. - Its instance variable
varMaphas the mapping from variables to theirAVals. - The most important method is
getAValOf(varName)that returns theAValfor variable namedvarNamefromvarMap. It recursively visits parentScopeif the variable is not found in itsvarMap.
Calcium supports context sensitivity by distinguishing various AVals according to the context. The context information is a list of call-sites. CallSiteContext generates and manipulates the context information. To analyze functions that have never been called, we introduced nullContext and we insert fake calls from nullContext encountering functions' declarations. At nullContext, we do not propagate any types to arguments. Note that appending a call-site to nullContext gives again nullContext. You may regard nullContext as the bottom of all contexts.
Status is the class for environmental information that we carry during the constraint generation.
Each status instance has
-
self:AValfor the currentthis -
ret:AValfor collecting return values -
exc:AValfor collecting exception values -
delta:CallSiteContextinstance for current context -
sc:Scopeinstance for current scope We should change theStatuswhen we visit functions, block, try block and so on. We provide deep equality forStatusnot to visit 'same' code with 'same' status.
For each analysis, we use only one instance AbsCache which is Ĉ.
Ĉ is basically a mapping from program location and context to its corresponding AVal.
It is useful when querying the analysis result since Ĉ has most of the data.
CSTR is the super class of special constraints.
A CSTR instance can be a target for type propagation since it has addType function.
However, the behavior of addType is quite different from that of AVal. The following items are the subclasses of CSTR. Note that the parameters are the constructor's parameters.
-
ReadProp(prop, to): When anAValfor a receiver gets a new type, theAValfor the member access can get new types from the property of the new type. For such case, we generate a constraint from theAValof the receiver tonew ReadProp(prop, to)wherepropis a string or null representing the property andtois theAValfor member access. When a type is added to the receiverAVal,addType(obj)is executed whereobjbeing the new type. Due to JavaScript's prototype inheritance, in principle we should recursively generate similar constraints for all prototype types. However, we made an unsound choice : we stop visiting prototypes as soon as we find the property. The intention is to read out the property from the most closest types in the prototype chain. For assisting property names, often this unsound approach is faster and what users expect. -
WriteProp(prop, from): Assume we have a property write statement. When theAValfor the receiver gets a new type, its property should contain the types of RHS. For such case, we generate a constraint from theAValof the receiver toWriteProp(prop, from)whereproprepresents the property andfromis theAValof RHS. -
IsAdded(other, to): For a binary addition, we generate a constraint from one operand toIsAdded(other, to)whereotheris theAValof the other operand, andtois theAValof the result of the addition. Basically, when a type is added to the operand, we look into theAValof the other operand and conditionally addPrimStringorPrimNumbertotoAVal. -
IsCallee(self, args, ret, exc, delta): For a method or a function call-site, we generate a constraint from the calleeAValtoIsCallee(self, args, ret, exc, delta). Let us explain the meaning of each argument. -
self:selfis theAValof the receiver. When the call is not a method invocation, it will be anAValcontaining the type for global object. -
args:argsis an array ofAValwhere the i-th element is theAValof the i-th argument of the call. -
ret:retis theAValfor the call expression. Inside the function, we shall propagate the arguments of return statements to theAValofret. -
exc:excis theAValfor collecting escaping exceptions. Those exceptions that can escape the callee should be collected inexc. -
delta:deltadenotes the call-site context of the call. Whenever an instance ofFnTypeis propagated to the calleeAVal, the corresponding function gets analyzed usingself,args,ret,excanddelta. -
IsCtor(args, ret, exc, delta): We use this constraint fornewexpression. This constraint is quite similar toIsCalleeexcept a few things. - we do not need
selfsincethiswill refer to the newly created instance. - By default,
retwill get propagated fromthisin the constructor. -
IfObjType(aval):IfObjType(aval)is a wrapper ofAValaval. If anAValis wrapped byIfObjType, onlyObjTypecan be propagated to theAVal.