ebook img

The VM Already Knew That PDF

27 Pages·2017·0.47 MB·English
by  
Save to my drive
Quick download
Download
Most books are stored in the elastic cloud where traffic is expensive. For this reason, we have a limit on daily download.

Preview The VM Already Knew That

The VM Already Knew That LeveragingCompile-TimeKnowledgetoOptimizeGradualTyping GREGORRICHARDS,UniversityofWaterloo,Canada,Canada ELLENARTECA,UniversityofWaterloo,Canada,Canada ALEXITURCOTTE,UniversityofWaterloo,Canada,Canada Programmersindynamiclanguageswishingtoconstrainandunderstandthebehavioroftheirprograms mayturntogradually-typedlanguages,whichallowtypestobespecifiedoptionallyandcheckvaluesatthe boundarybetweendynamicandstaticcode.Unfortunately,theperformancecostoftheserun-timecheckscan besevere,slowingdownexecutionbyatleast10xwhenchecksarepresent.Modernvirtualmachines(VMs) fordynamiclanguagesusespeculativetechniquestoimproveperformance:Ifaparticularvaluewasseenonce, itislikelythatsimilarvalueswillbeseeninthefuture.Theycombineoptimization-relevantpropertiesof valuesintocacheablełshapesž,thenuseasingleshapechecktosubsumechecksforeachproperty.Valueswith thesamememorylayoutorthesamefieldtypeshavethesameshape.Thisgreatlyreducestheamountoftype checkingthatneedstobeperformedatrun-timetoexecutedynamiccode.WhileveryvaluabletotheVM’s optimization,thesechecksdolittletobenefittheprogrammerasidefromimprovingperformance.Wepresent inthispaperadesignforintrinsicobjectcontracts,whichmakestheobligationsofgradually-typedlanguages’ typechecksanintrinsicpartofobjectshapes,andthuscansubsumerun-timetypechecksintoexistingshape checks,eliminatingredundantchecksentirely.WithanimplementationonaVMforJavaScriptusedasa targetforSafeTypeScript’ssoundnessguarantees,wedemonstrateslowdownaveraging7%infully-typed coderelativetouncheckedcode,andnomorethan45%inpessimalconfigurations. CCSConcepts:•Softwareanditsengineering→Just-in-timecompilers;Runtimeenvironments; AdditionalKeyWordsandPhrases:Gradualtyping,run-timetypechecking ACMReferenceFormat: GregorRichards,EllenArteca,andAlexiTurcotte.2017.TheVMAlreadyKnewThat:LeveragingCompile- TimeKnowledgetoOptimizeGradualTyping.Proc.ACMProgram.Lang.1,OOPSLA,Article55(October2017), 27pages.https://doi.org/10.1145/3133879 1 INTRODUCTION Dynamiclanguagesprovideflexibility,andmodernimplementationsofdynamiclanguagesare quiteefficient.However,thedynamicnatureoftheselanguagesmakesitdifficultforaprogrammer tostaticallyconstraintheirbehavior.Forexample,afunctionmaybewritteninanticipationofa numberasanargument,butcanbecalledwithanobject,whichwillresultinaruntimetypeerror. Programmers wishing to understand or constrain run-time behavior in dynamic languages havetheoptiontousegradually-typedprogramminglanguages.Gradually-typedlanguagesare Authors’addresses:GregorRichards,SchoolofComputerScience,UniversityofWaterloo,Canada,200UniversityAvenue West,Waterloo,Ontario,N2L3G1,Canada,[email protected];EllenArteca,SchoolofComputerScience, UniversityofWaterloo,Canada,200UniversityAvenueWest,Waterloo,Ontario,N2L3G1,Canada,[email protected]; AlexiTurcotte,SchoolofComputerScience,UniversityofWaterloo,Canada,200UniversityAvenueWest,Waterloo,Ontario, N2L3G1,Canada,[email protected]. 55 Permissiontomakedigitalorhardcopiesofpartorallofthisworkforpersonalorclassroomuseisgrantedwithoutfee providedthatcopiesarenotmadeordistributedforprofitorcommercialadvantageandthatcopiesbearthisnoticeand thefullcitationonthefirstpage.Copyrightsforthird-partycomponentsofthisworkmustbehonored.Forallotheruses, Tcohnistawctorthkeisolwicneenrs/eaduuthnodre(rs)a.CreativeCommonsAttribution4.0InternationalLicense. ©2017Copyrightheldbytheowner/author(s). 2475-1421/2017/10-ART55 https://doi.org/10.1145/3133879 ProceedingsoftheACMonProgrammingLanguages,Vol.1,No.OOPSLA,Article55.Publicationdate:October2017. 55:2 GregorRichards,EllenArteca,andAlexiTurcotte typicallycompatibleextensionsofexistingdynamically-typedlanguages,whichallowtypedand untypedcodetointeractwhilestillprovidingsometypesoundnessguarantees.Typically,run-time checksareusedtoverifytypeswhenvaluescomefromdynamicsources,andsocan’tbetrusted. Implementingthesechecksfacesasemanticmismatch,however:Typesmaybearbitrarilycomplex, andindeedrecursive,andthuscannotbecheckedquickly.Somegradually-typedlanguagesresolve this by restricting the type system in such a way that checks are always fast [Richards et al. 2015][Bloometal.2009],butthisnaturallyrestrictstheexpressibilityoftypes.Othersworkby delayingchecksuntilafirst-order,easilycheckablevalueisobtained. Inatypicalimplementation,first-ordertypecheckingisimposedonhigher-ordervaluesthrough run-timecontracts.Run-timecontractsinterposeonvaluestocheckallaccesses,guaranteeingthat theconstraintsofthespecifiedtypesarenotviolated.Checkinghasprovedtobeamajoroverhead ingraduallytypedlanguages[Takikawaetal.2016];dependingonwherecheckingisnecessary,the additionofcontractscanslowdowntheexecutionofsoftwareby100times.Otherimplementation techniqueshavebeenused,whichcanmovethecostofchecking,butslowdownsof10x[Vitousek etal.2014]to22x[Rastogietal.2015]arestillreportedwhenstaticanddynamiccodeinteracts. TheseslowdownshaveledTakikawaetal.[2016]toask,łissoundgradualtypingdead?žThegoal ofthisworkistodemonstratethatwithsomehelpfromthevirtualmachine,soundgradualtyping withusableperformanceisstillpractical. Modern virtual machines (VMs) for dynamic languages optimize based on speculation: If a particularvaluewasseenonce,itislikelythatsimilarvalueswillbeseeninthefuture.Thisis possible because of just-in-time (JIT) compilation, which blurs the line between compile-time andrun-time,andallowsthecompilertoutilizerun-timeinformation.Codemaybecompiledor recompiledoncecrucialinformationisknown.ThecodegeneratedbyJITschecksthatcertain propertiesofvaluesaresimilartopreviously-seenvalues,andiftheyare,runsbranchesoptimized tothoseassumptions. Inparticular,dynamiclanguageVMsoptimizeaccesstoobjectfieldsbygivingeveryobjecta łshapež,andassuringthatsimilarobjectshavesimilarshapes.Allobjectswiththesameshapehave thesamefields,andarelaidoutidenticallyinmemory,sooptimizingbasedontheshapeallows suchobjectstobeaccessedefficiently. SpeculativeJIToptimizationsandgradualtypechecksareoftencheckingsimilarproperties,but theyareeffectivelyunawareofeachother.Inthebestcase,theVMmaybeabletospeculatebased oncontractsuccess,butnothingmore.Thegoalofthisworkistoimprovetheperformanceofrun- timecontractsforgradually-typedprogramminglanguagesbyleveragingtheexistingspeculative optimizationframeworkinJITs,andtakingadvantageoftheredundanciesbetweenthesesystems. Thispaperillustratesthedesignofacontractsystemsufficientforthesoundnesschecksrequired bySafeTypeScript,agradually-typedlanguagebasedonJavaScript,andaVMwhichimplements thesecontractswithoptimizationstosubstantiallyreducethecostofrun-timetypechecking.We callthisstyleofcontractsintrinsicobjectcontracts,andimplementitintheHiggs[Chevalier-Boisvert and Feeley 2016] [Chevalier-Boisvert and Feeley 2015] JavaScript research virtual machine, as HiggsCheck.WedemonstratetheefficacyofthissystembyreimplementingSafeTypeScript[Rastogi etal.2015]toprovideitsguaranteeswithourcontractsystem,andshowusingSafeTypeScript’s benchmarks that we achieve slowdown of 7% in the common case, and no worse than 45% in intentionallypessimalconfigurations,ascomparedto22xslowdownsintheoriginalimplementation ofSafeTypeScript.ThepresentedimplementationisonaJavaScript-basedlanguageonaJavaScript virtualmachine,butthetechniquedoesnotdependdeeplyonJavaScript’ssemantics. Thecontributionsofthispaperare • thedesignofanintrinsiccontractsystemattheVMlevel, ProceedingsoftheACMonProgrammingLanguages,Vol.1,No.OOPSLA,Article55.Publicationdate:October2017. TheVMAlreadyKnewThat 55:3 • atechniqueforreducingtheoverheadofcheckingofsuchcontracts, • theimplementationofthatsystemontheHiggsvirtualmachine, • theimplementationofSafeTypeScript’ssoundnessguaranteesonthesecontracts, • anevaluation,demonstratingthattheoverheadofthiscontractsystemispractical. Thecompletesourcecodeofthissystemisavailableathttp://plg.uwaterloo.ca/~dynjs/higgscheck/. 2 BACKGROUNDANDGOALS Wewilldemonstratethegoalsofthissystemthroughasimplerunningexample.Considerthe followingJavaScriptcode,whichsumsthevaluesinalistofnumbers: function sum(node) { if (node.next) return sum(node.next) + node.item; else return node.item; } Itisevidentfromthiscodethatnodeisexpectedtobeanobject,withfieldsnextasareferenceto asimilarobjectornull,andfielditemasanumber.Calledwiththeobject{next: {next: null, item: 40}, item: 2}, sum will return 42. However, due to the dynamic nature and peculiar semanticsofJavaScript,inpracticethisfunctionwilldosomethingÐalbeitperhapssomething unpredictableÐwithmanyinputobjects.Forinstance,calledwith{next: 42},whichisobviously notanodeinalist,sumwillreturnNaN(NotaNumber),aconsequenceoftheoddbehaviorof accessingandperformingarithmeticwithnonexistentfields. 2.1 OptionalandGradualTyping AprogrammerwishingtomaketheirintentsclearermayinsteaduseTypeScript[Biermanetal. 2014],alanguagewhichextends,andcompilesinto,JavaScript,addingtypeannotations.InType- Script,thisfunctionanditsexpectedtypecanbeexpressedas: interface Node { function sum(node: Node) { next: Node; if (node.next) item: number; return sum(node.next) + node.item; } else return node.item; } Now,thecallsum({next: 42})willfailtocompile,withanappropriatetypeerror:Argument oftype'{ next: number; }'isnotassignabletoparameteroftype'Node'.However,TypeScript isastrictlycompile-timetypechecker,andisdesignedtointeractwithuntypedcode,soit’strivial toworkaroundthistyperestrictionbyeithercallingsumfromuntypedcode,orusingthespecial łanyžtypetobypasschecking.Indeed,theJavaScriptcodeaboveisthecompiledoutputofthis TypeScriptsnippet.Thisstyleoftypingisoftencalledoptionaltyping,whichimpliesthatthetypes are,ofcourse,optional,butalsothattherearenorun-timeguaranteesthattheexpressedtypes arecorrect.TypeScriptisintentionallyunsound,allowinguncheckeddowncastsandcovariant functionoverloading,butithasasoundcore,andfully-typedprogramswritteninthatsoundcore aretypesound[Biermanetal.2014]. Graduallytypedlanguagesregainsomeoftheassuranceofstaticallytypedlanguages,while maintainingtheflexibilityofinteractingwithdynamiccode.Theydefineadistinctconsistency relation,bywhichatypemaybeconsistentevenifitisnotasubtype,andtheconsistencyrelation isusedtoallowdynamicandstaticcodetointeract.Typically,asingledynamictype(inTypeScript, ProceedingsoftheACMonProgrammingLanguages,Vol.1,No.OOPSLA,Article55.Publicationdate:October2017. 55:4 GregorRichards,EllenArteca,andAlexiTurcotte any)isconsistentwithalltypes,andstructuralorhigher-ordertypesmustbeconsistentintheir typemembers.Intermsofdynamicsemantics,thetypecorrectnessofthisrelationshipisenforced byinjectingunsoundcasts,andimplementingthosecastsasrun-timechecks.Thestandardcriteria bywhichtheircorrectnessismeasuredisthataddingtypesdoesnotaffectbehaviorintheabsence ofunsoundcasts,andinthepresenceofunsoundcasts,errorsarealwaysthefaultofdynamic code[Sieketal.2015a][WadlerandFindler2009]. Thecaveatishowoneperformsrun-timecheckswithhigher-ordertypes.Languagessuchas StrongScript[Richardsetal.2015]andThorn[Bloometal.2009]accomplishthisbyrestricting thetypesystemtonominal,Java-likeclasses,suchthatalltypecheckscanbeperformedeagerly, orbyallowingtheprogrammertoexplicitlyspecifywhethercheckingisdesired[Wrigstadetal. 2010],avoidingbehavioralchangeswhencheckingisnotperformed.Moregeneralapproaches, suchasTypedRacket[Tobin-HochstadtandFelleisen2008],ReticulatedPython[Vitouseketal. 2014]and,relevanttothiswork,SafeTypeScript[Rastogietal.2015],performtheircheckslazily: Whenafirst-order,primitivevalueisexpected,itischeckedimmediately,butotherchecksare delayed.Thisapproachallowsforhigher-ordertypes,suchasstructuralobjecttypesandfirst-class functions,inawaythatnominaltypescannot,anddoesnottypicallyinterferewiththebehavior oftheunderlyingdynamiclanguageexcepttointroducechecks. Threeprincipletechniqueshaveemergedfordelayedrun-timechecksingradually-typedlan- guages, each with their own benefits and disadvantages. In each case, if a value undergoes an unsoundcasttoafirst-order,primitivetype,itissimplycheckedeagerly,butcastingtoahigher- ordertypeinvokessomeformofrun-timeprotection. TypedRacketandReticulatedPython(inoneconfiguration)usewrappers,orproxies.These wrappersimplementageneralcontract,whichcouldnotionallyverifyanypropertyexpressiblein thehostlanguage,butaretypicallyusedfortypes.Therelationshipbetweencontractsandtypes hasbeenexploredforbothobjects[FindlerandFelleisen2001]andfunctions[FindlerandFelleisen 2002].Inawrapper-basedgradually-typedsystem,everytimeavalueisobtainedwhichmaynot havethecorrecttype,itiswrappedinafunctionorobjectwhichprotectsitandchecksaccesses. Thiswrapperimplementsarun-timecontract,guaranteeingthatthevalue’sbehaviormatchesthe specifiedtype.Forobjects,forinstance,eachfieldisimplementedasanaccessorfunction.Ifthe field’stypeisitselfhigher-order,thisaccessorwrapsit;ifitisfirst-order,theaccessorchecksit. Further,thesewrapperscontainblameinformation,i.e.,alabelofwherethewrapperitselfwas applied.Becausechecksaredelayed,ifacheckfails,theblameinformationstoredinthewrapper willultimatelytelltheprogrammerwheretheincorrectcastwasperformed,ratherthanthepoint wheretheerroroccurred. Usingthewrappingtechniqueputsthecostofbothallocationofwrappersandcheckingon bothstatically-typedanddynamically-typedcode,foranyvaluewhichhasbeendowncast.Thus, fully-typedcodeincursnocost,andfully-untypedcodealsoincursnocost,butmixedcodecan havesevereslowdown:Whenstaticanddynamiccodeismixed,TypedRacketreportsslowdowns upto100x[Takikawaetal.2016]. ReticulatedPythonintroducedtwoothersemantics:transientchecksandmonotonicobjects.The techniqueoftransientcheckssimplyexplicitlychecksprimitivetypeswhenthey’reexpected.That is,nocheckwouldbeperformedtoverifythatanobjectisaNode(exceptperhapsthatitisan object),butiftheitemmemberofaNode-typedvariableisaccessed,itstypeischecked.Transient checkingcannotpreserveblameinformation,ashigher-orderdowncastshavenorun-timebehavior. It’slikelythattransientcheckscouldbemadetoworkwellwiththeVM,butifthey’repurely superficial,theyalsocausesignificantslowdowns.ReticulatedPythonreportsslowdownsof10xin thisconfiguration[Vitouseketal.2014]. ProceedingsoftheACMonProgrammingLanguages,Vol.1,No.OOPSLA,Article55.Publicationdate:October2017. TheVMAlreadyKnewThat 55:5 Reticulated Python’s third mode, monotonic objects, assures that values in the heap which undergounsoundcastsmayonlymonotonicallybecomemorepreciselytypedandtheirbehavior moreconstrained.Solongasobjectsmonotonicallybecomemorepreciselytyped,staticcodecan befreefromperformingchecks:Staticcodeaccessesmembersdirectly,assuredthattheywillbe correctlytyped,whiledynamiccodeisredirectedtoperformchecks,thusnotsullyingtheobjects thatstaticcodeexpects.Thus,adirectimplementationofmonotonicobjectsmakesstaticcodevery efficient,butataseverecosttodynamiccode.Themonotonicsemanticshasbeenshowntobe soundandcorrectwithrespecttoblame[Sieketal.2015b].ReticulatedPythonreportsslowdowns of3.4xofmonotonicobjectsovertransientchecks,soapproximately34xofmonotonicobjectsover uncheckedcode. SafeTypeScript’stechnique,thoughitcarriesthetypesinaseparatełtagheapž,hasthesame semantics:Whenobjectspassthroughanunsoundcast,itisshallowlycheckedandtaggedinthe heap,andallunsound(i.e.,dynamic)updateshavetheirvaluescheckedagainstthetag.Thetag maybemademoreprecise,butneverlessprecise.Thetagcorrespondstoaresolvedstructural objecttype,whichinTypeScriptisalistoftypedfields,andalistofacallsignatures,andwethus designoursystemofcontractstobesufficientforthesetypes. SafeTypeScriptreportssmallslowdowns,onaverage6.5%,infully-typedcode,butinmixedcode, thecostofmaintainingtypesoundnessisonaverage22xforonesuiteofbenchmarks. OurworkimplementsthesyntaxofSafeTypeScript(andthusTypeScript)andthesemantics requiredbySafeTypeScript’stagheap,butdoesnotavoidchecksinfully-staticcode,forreasonsof polymorphismwhichwillbediscussedinlatersections.Wehighlyoptimizedynamicsoundness checksbytakingadvantageofexistingchecksintheinfrastructureofthelanguageimplementation, substantiallyreducingthecostondynamiccode.OurimplementationreportsinSection6similar slowdownstotheoriginalimplementationofSafeTypeScript’stagheapforfullytypedcode,6.61% intheaveragecase,butouroptimizationbringstheperformancetoaslowdownofatworstjust 44.8%inintentionallypessimalmixesoftypedanduntypedcode. 2.2 Just-in-TimeCompilation Modernvirtualmachines(VMs)fordynamiclanguagesuseJust-in-Time(JIT)compilation.This allowsforspeculativeoptimizations,whichoptimizecodebasedonvaluesseenatrun-time:The programisallowedtorununtilaparticularfunctionorblockmustbecompiled,andthenitis compiledundertheassumptionthatthevaluesitinteractswithwillbesimilartotheonespreviously seen.Checksareinsertedtovalidatetheseassumptions,andcodeisrecompiledifthosechecksare violated. Inparticular,derivingfromworkinSelf[Chambersetal.1989],modernimplementationsof JavaScriptandsimilardynamiclanguagesrepresentobjectsasashapeandastore.Thestoreis asimplearraycontainingthevaluesofeveryfieldintheobject,butnottheirnames.Theshape (inothercontextscalledłmapžorłhiddenclassž)isatablemappingfieldnamestotheirposition inthestore.Everyobjectwiththesamefieldsandsamelayoutofthosefieldsinthestorerefers tothesameshape.Thisfactisusedtoavoiddynamicallylookingupfieldsinatechniquewhich inJavaScriptiscalledinlinecaching:Theshapeofaseenobjectiscached,andthesurrounding functionorblockiscompiledwithknowledgeofthatseenshape,andthusthelookupconsistsonly ofaccessingaknownoffsetinanarray. Toassurethateveryobjectwiththesamelayouthasthesameshape,shapesarestoredina globaltree.Emptyobjectsallsharethesameemptyshape,andtoaddafieldtoanobject,one followsthetransitioninthattreefromtheobject’scurrentshapelabeledwiththefieldbeingadded. Forinstance,inFigure1,iffielditemisaddedtoanemptyobject(i.e.,anobjectwithshape0), theobject’sshapeisupdatedtoshape1andthevalueisstoredatoffset0ofthestore.Ifnextis ProceedingsoftheACMonProgrammingLanguages,Vol.1,No.OOPSLA,Article55.Publicationdate:October2017. 55:6 GregorRichards,EllenArteca,andAlexiTurcotte shape 0 {} {} shape 0 {} item:numberitem:string toString:function item toString shape 1a shape 1b shape 3 shape 1 shape 3 {item→0} {item→0} {toString→0} {item→0} {toString→0} {item→number} {item→string} {toString→function} next next next:object next:object next:object {item→sh0a,p ne e2xt→1} {toStrinsgh→ap0e, 4next→1} {items→ha0p, en 2exat→1} {items→ha0p, en 2exbt→1} {toStrinsgh→ap0e, 4next→1} {item→number, {item→string, {toString→function, next→object} next→object} next→object} Fig.1. Basicshapetree. Fig.2. Higgsshapetree. thenaddedtotheobject,itsshapewillbeupdatedtoshape2.Ifnotransitionexistsforanecessary additiontoanobject,anewshapeiscreatedandaddedtotheshapetreetosatisfytherequest. Thus,inourpreviousexample,Nodeswillhave1shape2. ThisworkbuildsontheHiggsvirtualmachine[Chevalier-BoisvertandFeeley2016][Chevalier- BoisvertandFeeley2015],aresearchJavaScriptvirtualmachinewithcompetitiveperformance. HiggsimplementsmanymodernJavaScriptoptimizations,aswellasafewuniqueoneswhichwe utilize. Higgsimplementsspeculativeoptimizationsthroughlazybasicblockversioning.Inlazybasic blockversioning,eachbasicblockiscompiledspeculativelywithassumptionsaboutthetypesof datathatitaccesses,andthoseassumptionsarecheckedbeforeexecutionisallowedtoproceed intosuchaspeculativelycompiledblock.Singlebasicblocksmayhavemultiplecompiledversions, correspondingtodifferentsetsofassumptions,andexecutionwillchoosewhichblocktoproceed intothroughrun-timechecks.Whenchecksofthoseassumptionsfail,anewversionofthebasic blockandallfollowingbasicblocksisbuilttofitthenewassumptions.Theseassumptionspropagate intofurtherblocks,sorechecksareelided.Thus,thecompiledcodeforafunctionbecomesagraph ofbasicblockversions,eachrepresentingthecompilationofabasicblockunderaparticularsetof assumptions.Toavoidcodeblowup,limitsareplacedonhowlargethisgraphcanget,buttheyare rarelyreachedinpractice. Forinstance,consideroursumfunction.Adirectcompilationofthisfunctiontobasicblocks, withcontrolflowreplacedbygotos,is: (1) if (!node.next) goto 4 (2) tmp1 = sum(node.next); tmp2 = node.item; (3) return tmp1 + tmp2; (4) return node.item; Blocks2and3mustbesplit,becausethecompilationofthe+operatordependsonthetypesof itsoperands,creatingimplicitcontrolflowforthosetypestobechecked. Uponthefirstcompilationofthisfunction,asblock1requirestheshapeofnode,theshapeseen willbecached,resultinginacompiledprocedureasinFigure3.Assumingthefunctioniscalled withanon-nullnode.next,itwillproceedthroughblock2,andthenbecompiledagain,intoa procedureasinFigure4. Higgs, building on work in TruffleJS [Würthinger et al. 2013], extends shapes by encoding membertypesintothemaswell.Objectsbuiltofthesamefieldsbutdistinctprimitivetypesof 1Thisassumesthattheyarebuiltinaparticularorder,asinJavaScriptVMsthestoreisneverrearranged. ProceedingsoftheACMonProgrammingLanguages,Vol.1,No.OOPSLA,Article55.Publicationdate:October2017. TheVMAlreadyKnewThat 55:7 node: shape 2? node: shape 2a? yes node: shape 2? yes yes 1 (node:2) node.next==null? 1 (node:2a) node.next==null? 1 (node:2) node.next==null? no yes no yes 2 (node:2) 4 no no yes no 2 (node:2a) 4 no 2 (node:2) 4 tmp1:number&& tmp1:number? tmp2:number? recompile yes no yes no 3 (node:2a, Fig.3. Firstcompilationof tm3p (1n:onduem:2b,er, recompile ttmmpp21::nnuummbbeerr), recompile sum. tmp2:number) Fig.5. Withtypedshapes. Fig.4. Secondcompilation. theirmemberswillhavedistinctshapes,andobjectswithidenticallayoutsandtypeshavethe sameshape.Thisisaccomplishedbyextendingshapeswithamapofnamestoprimitivetypes. Thetransitionsinthisextendedshapetreearelabeledwithbothanameandaprimitivetype.For instance,inFigure2,iffielditemisaddedtoanemptyobjectwithtypenumber,theobject’sshape isupdatedtoshape1a.Ifit’saddedwithtypestring,theobject’sshapeisupdatedtoshape1b. Becausefieldsaretypicallymutable,thismeanstheshapecanalsochangewhenafieldismodified: Ifanobjectwithshape2a’sitemfieldisupdatedtoastring,theobject’sshapemustbeupdatedto 2b.Thatis,theshapeisonlyasnapshotofthecurrentstateoftheobject,notaguaranteeoffuture state. Thebenefitofaddingtypestoshapeistwofold:First,asprimitivetypesareavailableinthe shape,it’sunnecessarytotagorboxvaluesintheheap[Wößetal.2014].Objectscanthusbe laidoutmoreefficiently,avoidingwastingbitsontypeinformationthat’sidenticalbetweenmany objects.Second,speculatingonashapeallowsthecompilernotonlytooptimizefieldaccess,butto eliminatetypechecksovertheaccessedfieldvalues:Thecheckofthecontainingobject’sshape subsumesthecheckoftheaccessedvalue’stype.Forinstance,sumcanbecompiledtotheprocedure inFigure5withtypedshapes,avoidingacheckforthetypeoftmp2,whichisimpliedbytheshape ofnode.Thisoptimizationisimportanttoourgoal:IfataginSafeTypeScript’stagheapobligesthe itemfieldofanobjecttobeanumber,andthatobject’sshapeisshape2a,thatobligationcannot fail,andsodoesnotneedtobechecked. Lazybasicblockversioningisinmanywayssimilartotracing[Galetal.2009]andevenmeta- tracing [Bolz et al. 2009], and all of the optimizations of contracts discussed herein could be appliedequallytothosecontexts.Thatis,ourperformanceimprovementcomesfromcarefuluseof speculation,notfromtheparticularimplementationofspeculationinHiggs. 2.3 EfficientContracts Thecheckspresentindynamicallytypedprogramminglanguages,andthustheguardsandchecks presentinspeculatively-compileddynamiccode,arefundamentallysimilartotherun-timecontracts generatedbygradually-typedlanguages.Theprincipledifferenceissimplythatthepropertiesa JITischeckingarenotrequestedbytheuser,butbyspeculativecompilation,andthusviolating suchaguardisnotanerror,merelyacauseforrecompilation.WeimplementinHiggsCheck,an extensionofHiggs,asystemofintrinsicobjectcontracts,whichintegrateswiththeshapetreeto maketypecontractsasintrinsicapartofanobject’srun-timeimplementationasitsmemorylayout. ShapesinHiggsCheckencodethelayout,types,andcontractualobligationsofobjectmembers, ProceedingsoftheACMonProgrammingLanguages,Vol.1,No.OOPSLA,Article55.Publicationdate:October2017. 55:8 GregorRichards,EllenArteca,andAlexiTurcotte andthecompilerisawareoftheseobligations.Thecontractsthemselves,whilenotasgeneralas truepre-andpost-conditioncontracts,correspondtostructuralobjecttypes,anddelaytypechecks offieldsandfunctionreturnsuntiltherelevantfieldaccessorfunctioncallisperformed,similarly towrappers.Wheneverafieldofanobjectwithcontractsisread,acheckisincurred,andifthe contractstipulatesthatthevalueitselfhaveahigher-ordertype,thenacontractisappliedtothe value.Contractsmaybeaddedbutneverremoved,andsovaluesaremonotonic,andmayonly becomemorerestrictiveÐmorepreciselytypedÐduringtheexecutionofaprogramastheyare usedwithcontracts. Intheremainderofthispaperwediscusstheimplementationofcontractsandhowtheybridge thegapbetweentheVMandgradually-typedlanguages.InSection3wediscussthedesignof intrinsicobjectcontractsinisolation.Section4discusseshowthesecontractscanbeimplemented efficiently,andSection5howtheyareusedinthereimplementationofSafeTypeScript. 3 CONTRACTS In this section we discuss the features and basic implementation of the contracts provided by HiggsCheck,independentoftheiroptimizationsandthedirectuseofthesecontractsbygradually- typedlanguages.Wecallthisstyleofcontractsintrinsicobjectcontracts,asthecontractsareintrinsic totheprotectedobjects.Inparticular,wefocusonhowitsdesigndiffersfromotherunderlying systemsofhigher-orderchecks. 3.1 Design ThebehaviorofintrinsicobjectcontractsinHiggsCheckissemanticallysimple:Valuesmaybe testedagainstcontracts,andthosecontractsdescribeanumberofobligationsthevaluesmust adhereto.Theseobligationsareintendedtosupportgradualtyping,andsoaretotype-related propertiesthatareusefulforlanguagesandsupportedbytheVM.Thatis,acontractisasetof typing obligations over a value, and a value may be tested against a contract to assure that it conformstothoseobligations. Wedividethesupportedobligationsintobasicobligations,whichcanbecheckedquicklyandin constanttimeforanyvalue,andhigher-orderobligations,whichcannot.Higher-orderobligations correspondapproximatelytohigher-ordertypes,whilebasicobligationscorrespondtofirst-order, orprimitive,types.Wecallacontractwithonlybasicobligationsabasiccontract,andacontract with at least one higher-order obligation a higher-order contract. The empty contract, i.e. the contractwithnoobligationsatall,isalsoabasiccontract.Whenavalueistestedagainstacontract, conceptuallyitistestedagainstallofthatcontract’sobligations. Thebasicobligationsaretotheprimitiverun-timetypesandnullness.Forinstance,theobliga- tionłnumberžcorrespondsnaturallytotheJavaScripttypenumber.Thesebasicobligationsare trivialtocheckwithnocontractsystematall,asJavaScript’sbuilt-intypeofoperatorissufficient. Higher-orderobligationsarerequirementsoverobjectfieldsandfunctionreturnvalues.We focusfirstonobjectfields.Theseobligationsrequirethatthevaluesyieldedbyaccessingafield compliestoagivencontract,andthusincurtestingofthevalueagainstthecontractwheneveritis accessed.Ahigher-ordercontractwithseveralfieldobligationsisequivalenttoastructuralobject type,witheachobligationreferringtothetypeofaparticularfield.Forinstance,acontractcanbe builtfortheNodetypeasfollows:Contractα’ssoleobligationisłnumberž.Contractβ,thecontract forNode,hasthreeobligations:Thebasicobligationłobjectž,thehigher-orderobligationthatfield itembetestedagainstcontractα,andtheobligationthatfieldnextbetestedagainstcontractβ. Tosupportarrayindices,whichinJavaScriptaresimplyfieldswithnumericnames,acontract mayhaveanobligationoverallnumericfields.So,tosupportarraysofNodes,wemaycreatea ProceedingsoftheACMonProgrammingLanguages,Vol.1,No.OOPSLA,Article55.Publicationdate:October2017. TheVMAlreadyKnewThat 55:9 contractγ withtwoobligations:Thebasicobligationłobjectž,andthehigher-orderobligationthat allfieldswithnumericnamebetestedagainstcontractβ. Because these obligations allow the recursive testing of contracts, they cannot be checked eagerly.Eveninthecasethatthey’renotrecursive,theycannotbecheckedquickly,andbecause objectsinJavaScriptaretypicallymutable,acheckofsuchahigher-ordercontractwouldonly beamomentaryguarantee.Assuch,testingavalueagainstsuchacontractchecksonlythebasic obligationsimmediately,anddelaystestingofhigher-orderobligationsuntiltherelevantfieldis accessed.Testinganobjectxagainstcontractβ,ourcontractforNode,forinstance,willimmediately verifythatxisanobject,butwillonlytestthatx.itemisanumberwhen,andif,x.itemisaccessed. Higher-order obligations may additionally restrict function returns. For instance, a contract δ mayhavetheobligationthatreturnvaluescomplytocontractα above.Ifafunctionistested againstδ,itcannotbecheckedeagerly,andsoinsteadthesystemassertsthatthefunction’sreturn willbetestedinallfuturecalls.Thisisasimpleobligationnotsufficientformoresophisticated functionalprogramming,andthereasonsforthislimitationandpossibleenhancementstosupport functionalprogrammingarediscussedinSection4.3. Whenanobjectorfunction(inJavaScript,functionsareobjects)istestedagainstahigher-order contract,assumingallbasicobligationssucceed,thehigher-orderobligationsareimposedonthe objectthroughdelayedchecks.Toassurethatthesedelayedcheckshappen,thecontractisapplied totheobject.Objectsinthissystemmayhaveanynumberofcontractsappliedtothem,andeach objectretainsalistofappliedcontractsforitslifetime.Thiscontractapplicationiswhatassures thatfutureaccesseswillbetestedagainstthehigher-orderobligations:Whenafieldisreadfroman objectwithappliedcontracts,ifanyofitscontractshaveobligationsoverthatfield,thatobligation’s contractistestedagainstthevalueseenatrun-time.Ashigher-orderobligationseachtestavalue against a contract, this contract application may occur recursively. For instance, if an object x hasthecontractforNodeapplied,anaccesstox.nextwillbetestedagainsttheNodecontract, applyingitifapplicable.Ifanobjectistestedagainstacontractwhichhasalreadybeenapplied,it isn’tappliedasecondtime. Contractsaremonotonic:Whileanobjectmayalwayshavemorecontractsapplied,andthus gainmorespecifictypeinformationandamorerestrictiveAPI,itmayneverlosecontracts.Itis possibletoaddincompatiblecontracts,forinstanceNodealongwithacontractthatdemandsthat itembeastring,inwhichcaseaccessingsuchcontradictingfieldswillinevitablycauseacontract violation.TheyareindependentofJavaScript’sparticularsystemofinheritance,andtreatobjects asblackboxes.Thus,ifithappensthatthevalueofafieldisfulfilledbyaccessingaprototype,or byusinganaccessorfunction,itischeckedthesameasasimple,localfield. Built-infunctions,intendedtobeusedbytheimplementationofagradually-typedlanguage, areprovidedtobuildcontracts.Basiccontractsfortheprimitivetypes(objects,functions,strings, numbers and booleans) and the empty contract are built in, and other contracts are built by extending them through further built-in functions which add field, index and function return obligations. 3.2 Blame Whenacontractisappliedtoanobject,anactualviolationassociatedwiththatcontractmayoccur laterintheexecutionoftheprogram,whenaprimitivevalueisobtained.Withwrapper-based systems,thewrapperobjectcarrieswithitblameinformation,suchasthecodelocationofthe castwhichcausedacontracttobeadded,andwithmonotonicobjects,theblameisstoredinthe objectitself.IntrinsiccontractsinHiggsCheckcontainsimilarblameinformation:Acontracttest mayprovideanadditionalargumentwhichrepresentstherelevantblamelabel,typicallyacode location,andthatblamewillbereportedifthecontract’sobligationsareviolatedontheobject. ProceedingsoftheACMonProgrammingLanguages,Vol.1,No.OOPSLA,Article55.Publicationdate:October2017. 55:10 GregorRichards,EllenArteca,andAlexiTurcotte Whentestingtheobligationsofacontractrequirestestinganothervalueagainstanothercontract, theblameinformationfromtheparentcontractispassedontothechild. ThisgivesintrinsicobjectcontractssupportforblameasinFindlerandFelleisen[2002].As contractsareonlyappliedonce,anobjectcannotaccruemultipleblamelabelsforasinglecontract, andso-calledłthreesomesž[SiekandWadler2010]naturallycollapse:Wedonotre-applyacontract ifonlyitsblamehaschanged.Givenafixednumberofhigher-ordertypesinaprogram,thereare thusafixednumberofcontractsthatanobjectmayeveracquire.However,onlythefirstblame labelappliediskept. Thecreationofusefulblameinformationitselfislefttothecontract-utilizingcode.Itisassumed thatcontractswillusuallybeusedbycodegeneratedfromcompilationofgradually-typedpro- gramming languages, and so it is the role of that compiler to provide useful information. The compilerdescribedinSection5simplyusescodelinesasblamelabels,butusinge.g.stacktracesis analternativeÐalbeitslowerÐoption. 3.3 Discussion Thedesignofourcontractsystemwasintendedtosatisfytworequirements:Thatitbeusablefor thecontractsusuallyneededbygradually-typedobject-orientedprogramminglanguages,andthat itbeimplementableinanoptimalway.Relativetowrapper-basedcontracts,ourcontractsareless easilygeneralizabletootherkindsofchecks,butareimplementablewithasignificantlyreduced performancepenalty,asdemonstratedinSection6. Ourcontractsimplementthesemanticsofmonotonicobjects,andsoallreferencestoanobject have the same contractual obligations. In wrapper-based systems, references derived from the onetowhichthewrapperwasappliedwillconform,andotherswillnot.Bothsemanticshave advantages,andbothhavebeendemonstratedtobecorrect,butmonotonicsemanticsdomeanthat objectscannotbełchameleonsž:Theycannotchangetheirbehaviorinnon-backwards-compatible waysoncecontractshavebeenapplied. Unlikewrapper-basedimplementations,thereisnoquestionofobjectidentity,andnopossibility ofdistinctidentitiesforthesameobject,asnostand-inisevercreatedforanobject.Theapplication ofcontractsdoesnotaffectanobject’sidentityor,equivalently,itaffectstheidentityofallreferences totheobjectinthesameway. As intrinsic object contracts are a new language-level feature, backwards compatibility is a problem.ReticulatedPythondemonstrates[Vitouseketal.2014]thatmonotonicobjectsareimple- mentablethroughaccessorfunctions,andthesewouldbesufficienttoimplementintrinsicobject contractsaswellwithnochangestotheVM,butsuchimplementationsareslow.Ascontractsdonot changethebehaviorofprogramsexcepttoraisecontractviolationerrors,thebehaviorofacorrect programisnotalteredbyremovingitscontracts.Thus,asimpleshimlibrarywhichimplements thecontractbuilt-infunctionswithnobehaviorcanbeusedtosupportstandardimplementations (withnochecking),whilestillusingcontractsonsupportingimplementations. 4 IMPLEMENTATION UsingasimilartechniquetoReticulatedPython’smonotonicobjects,itwouldbepossibletocreatea correctimplementationofthecontractspresentedinSection3withpureJavaScript2.Therequisite checkingofallvalues,however,wouldbeuntenablyslow.HiggsCheckimplementscontractsat theVMlevel,andusescompile-timeknowledgetooptimizethem.Inthissectionwedescribethe 2IfimplementedattheVMlevel,contractswillbenaturallyresistanttomalicioustampering,whichmaybeimpossiblein animplementationinpureJavaScript. ProceedingsoftheACMonProgrammingLanguages,Vol.1,No.OOPSLA,Article55.Publicationdate:October2017.

Description:
Authors' addresses: Gregor Richards, School of Computer Science, University of Waterloo, Canada, 200 University Avenue. West, Waterloo, Ontario, N2L 3G1, value is used later in the function, later checks are elided, and so the cost of run-time checking is similarly made redundant with existing
See more

The list of books you might like

Most books are stored in the elastic cloud where traffic is expensive. For this reason, we have a limit on daily download.