12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555 |
- diff --git a/ChangeLog b/ChangeLog
- index e66e305..e4c539a 100644
- --- a/ChangeLog
- +++ b/ChangeLog
- @@ -1,3 +1,20 @@
- +Wed Feb 27 12:01:19 2009 Brent Roman <brent@mbari.org>
- +
- + * rubysig.c: added support for __anyPowerPC__
- +
- + * version.h: bumped date
- +
- +Mon Feb 25 10:53:52 2008 Brent Roman <brent@mbari.org>
- +
- + * backported MBARI 8A patches still
- + fails YAML test_object_id_collision
- +
- +Mon Feb 16 10:53:52 2008 Brent Roman <brent@mbari.org>
- +
- + * backport from 1.8.7p72-mbari of MBARI patches described at
- + http://sites.google.com/site/brentsrubypatches
- + fails YAML test_object_id_collision
- +
- Fri Aug 8 10:53:52 2008 Tanaka Akira <akr@fsij.org>
-
- * lib/resolv.rb: randomize source port and transaction id.
- diff --git a/common.mk b/common.mk
- index 6d5b35d..3e43e41 100644
- --- a/common.mk
- +++ b/common.mk
- @@ -441,7 +441,7 @@ variable.$(OBJEXT): {$(VPATH)}variable.c {$(VPATH)}ruby.h config.h \
- {$(VPATH)}env.h {$(VPATH)}node.h {$(VPATH)}st.h {$(VPATH)}util.h
- version.$(OBJEXT): {$(VPATH)}version.c {$(VPATH)}ruby.h config.h \
- {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
- - {$(VPATH)}version.h
- + {$(VPATH)}rubysig.h {$(VPATH)}version.h
-
- dist: $(PROGRAM)
- $(RUNRUBY) $(srcdir)/distruby.rb
- diff --git a/configure.in b/configure.in
- index c775862..aafeb30 100644
- --- a/configure.in
- +++ b/configure.in
- @@ -139,6 +139,24 @@ AC_ARG_ENABLE(frame-address,
- if test $frame_address = yes; then
- AC_DEFINE(USE_BUILTIN_FRAME_ADDRESS)
- fi
- +AC_ARG_ENABLE(mbari-api,
- + [ --enable-mbari-api enable API changes from the MBARI patches. ],
- + [mbari_api=$enableval])
- +if test "$mbari_api" = yes; then
- + AC_DEFINE(MBARI_API)
- +fi
- +AC_ARG_WITH(wipe-sites,
- +[ --with-wipe-sites=MASK override default STACK_WIPES_SITES mask in rubysig.h],
- +[wipe_sites=$withval])
- +if test "$wipe_sites" != ""; then
- + case $wipe_sites in
- + none|no) wipe_sites=0x0;;
- + yes) wipe_sites=;;
- + esac
- + if test -n "$wipe_sites"; then
- + AC_DEFINE_UNQUOTED(STACK_WIPE_SITES,$wipe_sites)
- + fi
- +fi
-
- AC_ARG_PROGRAM
-
- diff --git a/eval.c b/eval.c
- index 54a0fee..8002203 100644
- --- a/eval.c
- +++ b/eval.c
- @@ -222,9 +222,9 @@ VALUE rb_cProc;
- VALUE rb_cBinding;
- static VALUE proc_invoke _((VALUE,VALUE,VALUE,VALUE));
- static VALUE rb_f_binding _((VALUE));
- -static void rb_f_END _((void));
- +NOINLINE(static void rb_f_END _((void)));
- static VALUE rb_f_block_given_p _((void));
- -static VALUE block_pass _((VALUE,NODE*));
- +static VALUE block_pass _((volatile VALUE, NODE *volatile));
-
- VALUE rb_cMethod;
- static VALUE method_call _((int, VALUE*, VALUE));
- @@ -246,6 +246,30 @@ static int scope_vmode;
- VALUE (*ruby_sandbox_save)_((rb_thread_t));
- VALUE (*ruby_sandbox_restore)_((rb_thread_t));
- NODE* ruby_current_node;
- +
- +#if 0
- +#define SET_CURRENT_SOURCE() (ruby_sourcefile = ruby_current_node->nd_file, \
- + ruby_sourceline = nd_line(ruby_current_node))
- +#else
- +#define SET_CURRENT_SOURCE() ((void)0)
- +#endif
- +
- +void
- +ruby_set_current_source()
- +{
- + if (ruby_current_node) {
- + ruby_sourcefile = ruby_current_node->nd_file;
- + ruby_sourceline = nd_line(ruby_current_node);
- + }
- +}
- +
- +#ifdef MBARI_API
- +#define SET_METHOD_SOURCE() ruby_set_current_source()
- +#else
- +#define SET_METHOD_SOURCE() (void)0
- +#endif
- +
- +
- int ruby_safe_level = 0;
- /* safe-level:
- 0 - strings from streams/environment/ARGV are tainted (default)
- @@ -490,7 +514,7 @@ rb_get_method_body(klassp, idp, noexp)
- {
- ID id = *idp;
- VALUE klass = *klassp;
- - VALUE origin;
- + VALUE origin = 0;
- NODE * volatile body;
- struct cache_entry *ent;
-
- @@ -729,6 +753,7 @@ rb_attr(klass, id, read, write, ex)
- if (!name) {
- rb_raise(rb_eArgError, "argument needs to be symbol or string");
- }
- + SET_METHOD_SOURCE();
- len = strlen(name)+2;
- buf = ALLOCA_N(char,len);
- snprintf(buf, len, "@%s", name);
- @@ -769,11 +794,11 @@ static unsigned long frame_unique = 0;
- _frame.argc = 0; \
- _frame.flags = 0; \
- _frame.uniq = frame_unique++; \
- - ruby_frame = &_frame
- + ruby_frame = (struct FRAME *)&_frame
-
- #define POP_FRAME() \
- ruby_current_node = _frame.node; \
- - ruby_frame = _frame.prev; \
- + ruby_frame = _frame.prev; \
- } while (0)
-
- struct BLOCK {
- @@ -967,7 +992,7 @@ rb_svar(cnt)
- ID id;
-
- if (!ruby_scope->local_tbl) return NULL;
- - if (cnt >= ruby_scope->local_tbl[0]) return NULL;
- + if ((ID)cnt >= ruby_scope->local_tbl[0]) return NULL;
- id = ruby_scope->local_tbl[cnt+1];
- while (vars) {
- if (vars->id == id) return &vars->val;
- @@ -1030,7 +1055,26 @@ static struct tag *prot_tag;
- #define PROT_LAMBDA INT2FIX(2) /* 5 */
- #define PROT_YIELD INT2FIX(3) /* 7 */
-
- -#define EXEC_TAG() (FLUSH_REGISTER_WINDOWS, ruby_setjmp(((void)0), prot_tag->buf))
- +#if STACK_WIPE_SITES & 0x42
- +#ifdef __GNUC__
- +static inline int wipeAfter(int) __attribute__((always_inline));
- +#endif
- +static inline int wipeAfter(int status)
- +{
- + rb_gc_wipe_stack();
- + return status;
- +}
- +#else
- +#define wipeAfter(status) status
- +#endif
- +#if STACK_WIPE_SITES & 2
- +#define wipeAfterTag(status) wipeAfter(status)
- +#else
- +#define wipeAfterTag(status) status
- +#endif
- +
- +#define EXEC_TAG_0() ruby_setjmp(((void)0), prot_tag->buf)
- +#define EXEC_TAG() wipeAfterTag(EXEC_TAG_0())
-
- #define JUMP_TAG(st) do { \
- ruby_frame = prot_tag->frame; \
- @@ -1106,10 +1150,17 @@ static void scope_dup _((struct SCOPE *));
- } while (0)
-
- static VALUE rb_eval _((VALUE,NODE*));
- -static VALUE eval _((VALUE,VALUE,VALUE,char*,int));
- -static NODE *compile _((VALUE, char*, int));
- +static VALUE eval _((VALUE,VALUE,volatile VALUE,const char* volatile,int));
- +static NODE *compile _((VALUE, const char*, int));
-
- -static VALUE rb_yield_0 _((VALUE, VALUE, VALUE, int, int));
- +static VALUE rb_yield_0
- + _((volatile VALUE, volatile VALUE, VALUE, int, volatile int));
- +
- +#if STACK_WIPE_SITES & 0x20
- +#define wipeBeforeYield() rb_gc_wipe_stack()
- +#else
- +#define wipeBeforeYield() (void)0
- +#endif
-
- #define YIELD_LAMBDA_CALL 1
- #define YIELD_PROC_CALL 2
- @@ -1118,7 +1169,7 @@ static VALUE rb_yield_0 _((VALUE, VALUE, VALUE, int, int));
- #define YIELD_FUNC_SVALUE 2
-
- static VALUE rb_call _((VALUE,VALUE,ID,int,const VALUE*,int,VALUE));
- -static VALUE module_setup _((VALUE,NODE*));
- +static VALUE module_setup _((VALUE,NODE *volatile));
-
- static VALUE massign _((VALUE,NODE*,VALUE,int));
- static void assign _((VALUE,NODE*,VALUE,int));
- @@ -1150,22 +1201,6 @@ static VALUE trace_func = 0;
- static int tracing = 0;
- static void call_trace_func _((rb_event_t,NODE*,VALUE,ID,VALUE));
-
- -#if 0
- -#define SET_CURRENT_SOURCE() (ruby_sourcefile = ruby_current_node->nd_file, \
- - ruby_sourceline = nd_line(ruby_current_node))
- -#else
- -#define SET_CURRENT_SOURCE() ((void)0)
- -#endif
- -
- -void
- -ruby_set_current_source()
- -{
- - if (ruby_current_node) {
- - ruby_sourcefile = ruby_current_node->nd_file;
- - ruby_sourceline = nd_line(ruby_current_node);
- - }
- -}
- -
- static void
- #ifdef HAVE_STDARG_PROTOTYPES
- warn_printf(const char *fmt, ...)
- @@ -1227,20 +1262,15 @@ set_backtrace(info, bt)
- static void
- error_print()
- {
- - VALUE errat = Qnil; /* OK */
- + VALUE errat;
- volatile VALUE eclass, e;
- - char *einfo;
- + const char * einfo;
- long elen;
-
- if (NIL_P(ruby_errinfo)) return;
-
- PUSH_TAG(PROT_NONE);
- - if (EXEC_TAG() == 0) {
- - errat = get_backtrace(ruby_errinfo);
- - }
- - else {
- - errat = Qnil;
- - }
- + errat = EXEC_TAG() ? Qnil : get_backtrace(ruby_errinfo);
- if (EXEC_TAG()) goto error;
- if (NIL_P(errat)){
- ruby_set_current_source();
- @@ -1422,7 +1452,7 @@ ruby_init()
- }
-
- static VALUE
- -eval_node(self, node)
- +eval_tree(self, node)
- VALUE self;
- NODE *node;
- {
- @@ -1571,12 +1601,13 @@ ruby_finalize()
- }
-
- int
- -ruby_cleanup(ex)
- - int ex;
- +ruby_cleanup(exArg)
- + int exArg;
- {
- int state;
- volatile VALUE errs[2];
- - int nerr;
- + unsigned nerr;
- + volatile int ex = exArg;
-
- errs[1] = ruby_errinfo;
- ruby_safe_level = 0;
- @@ -1639,7 +1670,7 @@ ruby_exec_internal()
- /* default visibility is private at toplevel */
- SCOPE_SET(SCOPE_PRIVATE);
- if ((state = EXEC_TAG()) == 0) {
- - eval_node(ruby_top_self, ruby_eval_tree);
- + eval_tree(ruby_top_self, ruby_eval_tree);
- }
- POP_ITER();
- POP_TAG();
- @@ -1847,8 +1878,8 @@ rb_eval_cmd(cmd, arg, level)
- int level;
- {
- int state;
- - VALUE val = Qnil; /* OK */
- - struct SCOPE *saved_scope;
- + VALUE val;
- + struct SCOPE * volatile saved_scope;
- volatile int safe = ruby_safe_level;
-
- if (OBJ_TAINTED(cmd)) {
- @@ -1879,9 +1910,7 @@ rb_eval_cmd(cmd, arg, level)
- ruby_safe_level = level;
-
- PUSH_TAG(PROT_NONE);
- - if ((state = EXEC_TAG()) == 0) {
- - val = eval(ruby_top_self, cmd, Qnil, 0, 0);
- - }
- + val = (state = EXEC_TAG()) ? Qnil : eval(ruby_top_self, cmd, Qnil, 0, 0);
- if (ruby_scope->flags & SCOPE_DONT_RECYCLE)
- scope_dup(saved_scope);
- ruby_scope = saved_scope;
- @@ -1920,6 +1949,10 @@ ev_const_defined(cref, id, self)
- return rb_const_defined(cref->nd_clss, id);
- }
-
- +NOINLINE(static VALUE ev_const_get _((NODE *cref, ID id, VALUE self)));
- +NOINLINE(static void eval_cvar_set _((NODE *node, VALUE result, int warn)));
- +NOINLINE(static void eval_cdecl _((VALUE self, NODE *node, VALUE value)));
- +
- static VALUE
- ev_const_get(cref, id, self)
- NODE *cref;
- @@ -2032,7 +2065,7 @@ void
- rb_frozen_class_p(klass)
- VALUE klass;
- {
- - char *desc = "something(?!)";
- + const char *desc = "something(?!)";
-
- if (OBJ_FROZEN(klass)) {
- if (FL_TEST(klass, FL_SINGLETON))
- @@ -2070,7 +2103,7 @@ rb_undef(klass, id)
- }
- body = search_method(klass, id, &origin);
- if (!body || !body->nd_body) {
- - char *s0 = " class";
- + const char *s0 = " class";
- VALUE c = klass;
-
- if (FL_TEST(c, FL_SINGLETON)) {
- @@ -2161,7 +2194,7 @@ rb_alias(klass, name, def)
- VALUE klass;
- ID name, def;
- {
- - VALUE origin;
- + VALUE origin = 0;
- NODE *orig, *body, *node;
- VALUE singleton = 0;
- st_data_t data;
- @@ -2247,7 +2280,10 @@ rb_copy_node_scope(node, rval)
- NODE *node;
- NODE *rval;
- {
- - NODE *copy = NEW_NODE(NODE_SCOPE,0,rval,node->nd_next);
- + NODE *copy;
- +
- + SET_METHOD_SOURCE();
- + copy=NEW_NODE(NODE_SCOPE,0,rval,node->nd_next);
-
- if (node->nd_tbl) {
- copy->nd_tbl = ALLOC_N(ID, node->nd_tbl[0]+1);
- @@ -2322,9 +2358,9 @@ rb_copy_node_scope(node, rval)
-
- #define MATCH_DATA *rb_svar(node->nd_cnt)
-
- -static char* is_defined _((VALUE, NODE*, char*));
- +static const char* is_defined _((VALUE, NODE*, char*));
-
- -static char*
- +static const char*
- arg_defined(self, node, buf, type)
- VALUE self;
- NODE *node;
- @@ -2351,13 +2387,13 @@ arg_defined(self, node, buf, type)
- return type;
- }
-
- -static char*
- +static const char*
- is_defined(self, node, buf)
- VALUE self;
- - NODE *node; /* OK */
- + NODE *node;
- char *buf;
- {
- - VALUE val; /* OK */
- + VALUE val;
- int state;
-
- again:
- @@ -2671,27 +2707,27 @@ set_trace_func(obj, trace)
- return trace;
- }
-
- -static char *
- +static const char *
- get_event_name(rb_event_t event)
- {
- switch (event) {
- - case RUBY_EVENT_LINE:
- + case RUBY_EVENT_LINE:
- return "line";
- - case RUBY_EVENT_CLASS:
- + case RUBY_EVENT_CLASS:
- return "class";
- - case RUBY_EVENT_END:
- + case RUBY_EVENT_END:
- return "end";
- - case RUBY_EVENT_CALL:
- + case RUBY_EVENT_CALL:
- return "call";
- - case RUBY_EVENT_RETURN:
- + case RUBY_EVENT_RETURN:
- return "return";
- - case RUBY_EVENT_C_CALL:
- + case RUBY_EVENT_C_CALL:
- return "c-call";
- - case RUBY_EVENT_C_RETURN:
- + case RUBY_EVENT_C_RETURN:
- return "c-return";
- - case RUBY_EVENT_RAISE:
- + case RUBY_EVENT_RAISE:
- return "raise";
- - default:
- + default:
- return "unknown";
- }
- }
- @@ -2702,14 +2738,15 @@ call_trace_func(event, node, self, id, klass)
- NODE *node;
- VALUE self;
- ID id;
- - VALUE klass; /* OK */
- + VALUE klass;
- {
- - int state, raised;
- + int state;
- + volatile int raised;
- struct FRAME *prev;
- - NODE *node_save;
- + NODE * volatile node_save;
- VALUE srcfile;
- - char *event_name;
- - rb_thread_t th = curr_thread;
- + const char *event_name;
- + volatile rb_thread_t th = curr_thread;
-
- if (!trace_func) return;
- if (tracing) return;
- @@ -2918,11 +2955,11 @@ class_prefix(self, cpath)
- NORETURN(static void return_jump _((VALUE)));
- NORETURN(static void break_jump _((VALUE)));
- NORETURN(static void next_jump _((VALUE)));
- -NORETURN(static void unknown_node _((NODE * volatile)));
- +NORETURN(static void unknown_node _((NODE *)));
-
- static void
- unknown_node(node)
- - NODE *volatile node;
- + NODE *node;
- {
- ruby_current_node = 0;
- if (node->flags == 0) {
- @@ -2936,40 +2973,886 @@ unknown_node(node)
- }
- }
-
- -static VALUE
- -rb_eval(self, n)
- - VALUE self;
- - NODE *n;
- +/*
- + * functions factored out of rb_eval() to reduce its stack frame size
- + */
- +#define eval_node_0(n,retType, self, node) \
- +NOINLINE(static retType TOKEN_PASTE(eval_,n) _((self, node)));\
- +static retType TOKEN_PASTE(eval_,n)(self, node)
- +
- +#define eval_node(n,retType) \
- + eval_node_0(n,retType, VALUE self, NODE *node)
- +#define eval_node_volatile(n,retType) \
- + eval_node_0(n,retType, volatile VALUE self, NODE * volatile node)
- +
- +eval_node(match2, VALUE)
- +{
- + VALUE l = rb_eval(self,node->nd_recv);
- + VALUE r = rb_eval(self,node->nd_value);
- + return rb_reg_match(l, r);
- +}
- +
- +eval_node(match3, VALUE)
- {
- - NODE * volatile contnode = 0;
- - NODE * volatile node = n;
- + VALUE r = rb_eval(self,node->nd_recv);
- + VALUE l = rb_eval(self,node->nd_value);
- + return TYPE(l) == T_STRING ? rb_reg_match(r, l) : rb_funcall(l, match, 1, r);
- +}
- +
- +
- +eval_node_volatile(opt_n, void)
- +{
- + int state;
- + PUSH_TAG(PROT_LOOP);
- + switch (state = EXEC_TAG()) {
- + case TAG_NEXT:
- + state = 0;
- + case 0:
- + while (!NIL_P(rb_gets())) {
- + opt_n_redo:
- + rb_eval(self, node->nd_body);
- + }
- + break;
- +
- + case TAG_REDO:
- + state = 0;
- + goto opt_n_redo;
- +
- + case TAG_BREAK:
- + state = 0;
- + default:
- + break;
- + }
- + POP_TAG();
- + if (state) JUMP_TAG(state);
- +}
- +
- +
- +eval_node(when, NODE*)
- +{
- + do {
- + NODE *tag = node->nd_head;
- + while (tag) {
- + EXEC_EVENT_HOOK(RUBY_EVENT_LINE, tag, self,
- + ruby_frame->last_func,
- + ruby_frame->last_class);
- + if (tag->nd_head && nd_type(tag->nd_head) == NODE_WHEN) {
- + VALUE v = rb_eval(self, tag->nd_head->nd_head);
- + long i;
- +
- + if (TYPE(v) != T_ARRAY) v = rb_ary_to_ary(v);
- + for (i=0; i<RARRAY(v)->len; i++) {
- + if (RTEST(RARRAY(v)->ptr[i])) return node->nd_body;
- + }
- + tag = tag->nd_next;
- + continue;
- + }
- + if (RTEST(rb_eval(self, tag->nd_head))) return node->nd_body;
- + tag = tag->nd_next;
- + }
- + } while ((node = node->nd_next) && nd_type(node) == NODE_WHEN);
- + return node;
- +}
- +
- +
- +eval_node(case, NODE*)
- +{
- + VALUE val = rb_eval(self, node->nd_head);
- + node = node->nd_body;
- + while (node) {
- + NODE *tag;
- +
- + if (nd_type(node) != NODE_WHEN) break;
- + tag = node->nd_head;
- + while (tag) {
- + EXEC_EVENT_HOOK(RUBY_EVENT_LINE, tag, self,
- + ruby_frame->last_func,
- + ruby_frame->last_class);
- + if (tag->nd_head && nd_type(tag->nd_head) == NODE_WHEN) {
- + VALUE v = rb_eval(self, tag->nd_head->nd_head);
- + long i;
- +
- + if (TYPE(v) != T_ARRAY) v = rb_ary_to_ary(v);
- + for (i=0; i<RARRAY(v)->len; i++) {
- + if (RTEST(rb_funcall2(RARRAY(v)->ptr[i], eqq, 1, &val)))
- + return node->nd_body;
- + }
- + tag = tag->nd_next;
- + continue;
- + }
- + if (RTEST(rb_funcall2(rb_eval(self, tag->nd_head), eqq, 1, &val)))
- + return node->nd_body;
- + tag = tag->nd_next;
- + }
- + node = node->nd_next;
- + }
- + return node;
- +}
- +
- +
- +eval_node_volatile(while, VALUE)
- +{
- + int state;
- + VALUE result;
- + PUSH_TAG(PROT_LOOP);
- + switch (state = EXEC_TAG()) {
- + case 0:
- + if (!(node->nd_state) || RTEST(rb_eval(self, node->nd_cond))) {
- + do {
- + while_redo:
- +#if STACK_WIPE_SITES & 0x10
- + rb_gc_wipe_stack();
- +#endif
- + rb_eval(self, node->nd_body);
- + while_next:
- + ;
- + } while (RTEST(rb_eval(self, node->nd_cond)));
- + } /* fall thru */
- + default:
- + result=Qnil;
- + break;
- +
- + case TAG_REDO:
- + state = 0;
- + goto while_redo;
- + case TAG_NEXT:
- + state = 0;
- + goto while_next;
- + case TAG_BREAK:
- + if (TAG_DST()) {
- + state = 0;
- + result = prot_tag->retval;
- + }
- + }
- + POP_TAG();
- + if (state) JUMP_TAG(state);
- + return result;
- +}
- +
- +
- +eval_node_volatile(until, VALUE)
- +{
- + int state;
- + VALUE result;
- + PUSH_TAG(PROT_LOOP);
- + switch (state = EXEC_TAG()) {
- + case 0:
- + if (!(node->nd_state) || !RTEST(rb_eval(self, node->nd_cond))) {
- + do {
- + until_redo:
- + #if STACK_WIPE_SITES & 0x10
- + rb_gc_wipe_stack();
- + #endif
- + rb_eval(self, node->nd_body);
- + until_next:
- + ;
- + } while (!RTEST(rb_eval(self, node->nd_cond)));
- + } /* fall thru */
- + default:
- + result=Qnil;
- + break;
- +
- + case TAG_REDO:
- + state = 0;
- + goto until_redo;
- + case TAG_NEXT:
- + state = 0;
- + goto until_next;
- + case TAG_BREAK:
- + if (TAG_DST()) {
- + state = 0;
- + result = prot_tag->retval;
- + }
- + }
- + POP_TAG();
- + if (state) JUMP_TAG(state);
- + return result;
- +}
- +
- +
- +eval_node_volatile(iter, VALUE)
- +{
- + int state;
- + VALUE result;
- +
- + PUSH_TAG(PROT_LOOP);
- + PUSH_BLOCK(node->nd_var, node->nd_body);
- +
- + state = EXEC_TAG();
- + switch (state) {
- + case TAG_RETRY:
- + state = 0; /* fall thru to case 0 */
- + case 0:
- + PUSH_ITER(ITER_PRE);
- + if (nd_type(node) == NODE_ITER) {
- + result = rb_eval(self, node->nd_iter);
- + }
- + else {
- + _block.flags &= ~BLOCK_D_SCOPE;
- + BEGIN_CALLARGS;
- + result = rb_eval(self, node->nd_iter);
- + END_CALLARGS;
- + ruby_current_node = (NODE *)node;
- + SET_CURRENT_SOURCE();
- + result = rb_call(CLASS_OF(result),result,each,0,0,0,self);
- + }
- + POP_ITER();
- + break;
- +
- + case TAG_BREAK:
- + if (TAG_DST()) {
- + result = prot_tag->retval;
- + state = 0;
- + }
- + }
- + POP_BLOCK();
- + POP_TAG();
- + if (state) JUMP_TAG(state);
- + return result;
- +}
- +
- +
- +eval_node_volatile(rescue, VALUE)
- +{
- + volatile VALUE e_info = ruby_errinfo;
- + volatile int rescuing = 0;
- int state;
- - volatile VALUE result = Qnil;
- - st_data_t data;
- + VALUE result;
-
- -#define RETURN(v) do { \
- - result = (v); \
- - goto finish; \
- -} while (0)
- + PUSH_TAG(PROT_NONE);
- + if ((state = EXEC_TAG()) == 0) {
- + retry_entry:
- + result = rb_eval(self, node->nd_head);
- + }
- + else if (rescuing) {
- + if (rescuing < 0) {
- + /* in rescue argument, just reraise */
- + result = Qnil;
- + }
- + else if (state == TAG_RETRY) {
- + rescuing = state = 0;
- + ruby_errinfo = e_info;
- + goto retry_entry;
- + }
- + else if (state != TAG_RAISE) {
- + result = prot_tag->retval;
- + }
- + }
- + else if (state == TAG_RAISE) {
- + NODE *resq = node->nd_resq;
- +
- + rescuing = -1;
- + while (resq) {
- + ruby_current_node = resq;
- + if (handle_rescue(self, resq)) {
- + state = 0;
- + rescuing = 1;
- + result = rb_eval(self, resq->nd_body);
- + break;
- + }
- + resq = resq->nd_head; /* next rescue */
- + }
- + }
- + else {
- + result = prot_tag->retval;
- + }
- + POP_TAG();
- + if (state != TAG_RAISE) ruby_errinfo = e_info;
- + if (state) {
- + JUMP_TAG(state);
- + }
- + /* no exception raised */
- + if (!rescuing && node->nd_else) { /* else clause given */
- + result = Qundef; /* caller must eval this! */
- + }
- + return result;
- +}
- +
- +
- +eval_node_volatile(ensure, VALUE)
- +{
- + int state;
- + VALUE result;
- +
- + PUSH_TAG(PROT_NONE);
- + if ((state = EXEC_TAG()) == 0) {
- + result = rb_eval(self, node->nd_head);
- + }
- + POP_TAG();
- + if (node->nd_ensr && !thread_no_ensure()) {
- + VALUE retval = prot_tag->retval; /* save retval */
- + VALUE errinfo = ruby_errinfo;
- +
- + rb_eval(self, node->nd_ensr);
- + return_value(retval);
- + ruby_errinfo = errinfo;
- + }
- + if (state) JUMP_TAG(state);
- + return result;
- +}
- +
- +
- +eval_node(dot, VALUE)
- +{
- + VALUE beg = rb_eval(self, node->nd_beg);
- + VALUE end = rb_eval(self, node->nd_end);
- + return rb_range_new(beg, end, nd_type(node) == NODE_DOT3);
- +}
- +
- +
- +eval_node(flip2, VALUE)
- +{
- + VALUE *flip = rb_svar(node->nd_cnt);
- + if (!flip) rb_bug("unexpected local variable");
- + if (!RTEST(*flip)) {
- + if (!RTEST(rb_eval(self, node->nd_beg)))
- + return Qfalse;
- + *flip = RTEST(rb_eval(self, node->nd_end))?Qfalse:Qtrue;
- + }
- + else if (RTEST(rb_eval(self, node->nd_end)))
- + *flip = Qfalse;
- + return Qtrue;
- +}
- +
- +
- +eval_node(flip3, VALUE)
- +{
- + VALUE *flip = rb_svar(node->nd_cnt);
- + if (!flip) rb_bug("unexpected local variable");
- + if (!RTEST(*flip))
- + return *flip = (RTEST(rb_eval(self, node->nd_beg)) ? Qtrue : Qfalse);
- + if (RTEST(rb_eval(self, node->nd_end)))
- + *flip = Qfalse;
- + return Qtrue;
- +}
- +
- +
- +eval_node(attrasgn, VALUE)
- +{
- + VALUE recv;
- + int argc; VALUE *argv; /* used in SETUP_ARGS */
- + int scope;
- + TMP_PROTECT;
- +
- + BEGIN_CALLARGS;
- + if (node->nd_recv == (NODE *)1) {
- + recv = self;
- + scope = 1;
- + }
- + else {
- + recv = rb_eval(self, node->nd_recv);
- + scope = 0;
- + }
- + SETUP_ARGS(node->nd_args);
- + END_CALLARGS;
- +
- + ruby_current_node = node;
- + SET_CURRENT_SOURCE();
- + rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,scope,self);
- + return argv[argc-1];
- +}
- +
- +
- +eval_node(call, VALUE)
- +{
- + VALUE recv;
- + int argc; VALUE *argv; /* used in SETUP_ARGS */
- + TMP_PROTECT;
- +
- + BEGIN_CALLARGS;
- + recv = rb_eval(self, node->nd_recv);
- + SETUP_ARGS(node->nd_args);
- + END_CALLARGS;
- +
- + ruby_current_node = node;
- + SET_CURRENT_SOURCE();
- + return rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,0,self);
- +}
- +
- +
- +eval_node(fcall, VALUE)
- +{
- + int argc; VALUE *argv; /* used in SETUP_ARGS */
- + TMP_PROTECT;
- +
- + BEGIN_CALLARGS;
- + SETUP_ARGS(node->nd_args);
- + END_CALLARGS;
- +
- + ruby_current_node = node;
- + SET_CURRENT_SOURCE();
- + return rb_call(CLASS_OF(self),self,node->nd_mid,argc,argv,1,self);
- +}
- +
- +
- +eval_node(super, VALUE)
- +{
- + int argc; VALUE *argv; /* used in SETUP_ARGS */
- + TMP_PROTECT;
- +
- + if (ruby_frame->last_class == 0) {
- + if (ruby_frame->last_func) {
- + rb_name_error(ruby_frame->last_func,
- + "superclass method `%s' disabled",
- + rb_id2name(ruby_frame->orig_func));
- + }
- + else {
- + rb_raise(rb_eNoMethodError, "super called outside of method");
- + }
- + }
- + if (nd_type(node) == NODE_ZSUPER) {
- + argc = ruby_frame->argc;
- + if (argc && DMETHOD_P()) {
- + if (TYPE(RBASIC(ruby_scope)->klass) != T_ARRAY ||
- + RARRAY(RBASIC(ruby_scope)->klass)->len != argc) {
- + rb_raise(rb_eRuntimeError,
- + "super: specify arguments explicitly");
- + }
- + argv = RARRAY(RBASIC(ruby_scope)->klass)->ptr;
- + }
- + else if (!ruby_scope->local_vars) {
- + argc = 0;
- + argv = 0;
- + }
- + else {
- + argv = ruby_scope->local_vars + 2;
- + }
- + }
- + else {
- + BEGIN_CALLARGS;
- + SETUP_ARGS(node->nd_args);
- + END_CALLARGS;
- + ruby_current_node = node;
- + }
- +
- + SET_CURRENT_SOURCE();
- + return rb_call_super(argc, argv);
- +}
- +
- +
- +eval_node_volatile(scope, VALUE)
- +{
- + int state;
- + VALUE result;
- + struct FRAME frame;
- + NODE * volatile saved_cref = 0;
- +
- + frame = *ruby_frame;
- + frame.tmp = ruby_frame;
- + ruby_frame = &frame;
- +
- + PUSH_SCOPE();
- + PUSH_TAG(PROT_NONE);
- + if (node->nd_rval) {
- + saved_cref = ruby_cref;
- + ruby_cref = (NODE*)node->nd_rval;
- + }
- + if (node->nd_tbl) {
- + VALUE *vars = ALLOCA_N(VALUE, node->nd_tbl[0]+1);
- + *vars++ = (VALUE)node;
- + ruby_scope->local_vars = vars;
- + rb_mem_clear(ruby_scope->local_vars, node->nd_tbl[0]);
- + ruby_scope->local_tbl = node->nd_tbl;
- + }
- + else {
- + ruby_scope->local_vars = 0;
- + ruby_scope->local_tbl = 0;
- + }
- + if ((state = EXEC_TAG()) == 0) {
- + result = rb_eval(self, node->nd_next);
- + }
- + POP_TAG();
- + POP_SCOPE();
- + ruby_frame = frame.tmp;
- + if (saved_cref)
- + ruby_cref = saved_cref;
- + if (state) JUMP_TAG(state);
- + return result;
- +}
- +
- +eval_node(op_asgn1, VALUE)
- +{
- + int argc; VALUE *argv; /* used in SETUP_ARGS */
- + VALUE recv, val, tmp;
- + NODE *rval;
- + TMP_PROTECT;
- +
- + recv = rb_eval(self, node->nd_recv);
- + rval = node->nd_args->nd_head;
- + SETUP_ARGS0(node->nd_args->nd_body, 1);
- + val = rb_funcall3(recv, aref, argc, argv);
- + switch (node->nd_mid) {
- + case 0: /* OR */
- + if (RTEST(val)) return val;
- + val = rb_eval(self, rval);
- + break;
- + case 1: /* AND */
- + if (!RTEST(val)) return val;
- + val = rb_eval(self, rval);
- + break;
- + default:
- + tmp = rb_eval(self, rval);
- + val = rb_funcall3(val, node->nd_mid, 1, &tmp);
- + }
- + argv[argc] = val;
- + rb_funcall2(recv, aset, argc+1, argv);
- + return val;
- +}
- +
- +
- +eval_node(op_asgn2, VALUE)
- +{
- + ID id = node->nd_next->nd_vid;
- + VALUE recv, val, tmp;
- +
- + recv = rb_eval(self, node->nd_recv);
- + val = rb_funcall3(recv, id, 0, 0);
- + switch (node->nd_next->nd_mid) {
- + case 0: /* OR */
- + if (RTEST(val)) return val;
- + val = rb_eval(self, node->nd_value);
- + break;
- + case 1: /* AND */
- + if (!RTEST(val)) return val;
- + val = rb_eval(self, node->nd_value);
- + break;
- + default:
- + tmp = rb_eval(self, node->nd_value);
- + val = rb_funcall3(val, node->nd_next->nd_mid, 1, &tmp);
- + }
- +
- + rb_funcall2(recv, node->nd_next->nd_aid, 1, &val);
- + return val;
- +}
- +
- +
- +eval_node(hash, VALUE)
- +{
- + NODE *list;
- + VALUE hash = rb_hash_new();
- + VALUE key, val;
- +
- + list = node->nd_head;
- + while (list) {
- + key = rb_eval(self, list->nd_head);
- + list = list->nd_next;
- + if (list == 0)
- + rb_bug("odd number list for Hash");
- + val = rb_eval(self, list->nd_head);
- + list = list->nd_next;
- + rb_hash_aset(hash, key, val);
- + }
- + return hash;
- +}
- +
- +
- +eval_node(array, VALUE)
- +{
- + VALUE ary;
- + long i;
- +
- + i = node->nd_alen;
- + ary = rb_ary_new2(i);
- + for (i=0;node;node=node->nd_next) {
- + RARRAY(ary)->ptr[i++] = rb_eval(self, node->nd_head);
- + RARRAY(ary)->len = i;
- + }
- + return ary;
- +}
- +
- +
- +eval_node(slit, VALUE)
- +{
- + VALUE str, str2;
- + NODE *list = node->nd_next;
- +
- + str = rb_str_new3(node->nd_lit);
- + while (list) {
- + if (list->nd_head) {
- + switch (nd_type(list->nd_head)) {
- + case NODE_STR:
- + str2 = list->nd_head->nd_lit;
- + break;
- + default:
- + str2 = rb_eval(self, list->nd_head);
- + break;
- + }
- + rb_str_append(str, str2);
- + OBJ_INFECT(str, str2);
- + }
- + list = list->nd_next;
- + }
- + switch (nd_type(node)) {
- + case NODE_DREGX:
- + str2 = rb_reg_new(RSTRING(str)->ptr, RSTRING(str)->len,
- + node->nd_cflag);
- + RB_GC_GUARD(str); /* prevent tail call optimization here */
- + return str2;
- + case NODE_DREGX_ONCE: /* regexp expand once */
- + str2 = rb_reg_new(RSTRING(str)->ptr, RSTRING(str)->len,
- + node->nd_cflag);
- + nd_set_type(node, NODE_LIT);
- + RB_GC_GUARD(str); /* ensure str is not GC'd in rb_reg_new */
- + return node->nd_lit = str2;
- + case NODE_LIT:
- + /* other thread may replace NODE_DREGX_ONCE to NODE_LIT */
- + return Qundef;
- + case NODE_DXSTR:
- + return rb_funcall(self, '`', 1, str);
- + case NODE_DSYM:
- + return rb_str_intern(str);
- + }
- + return str;
- +}
- +
- +
- +eval_node(defn, void)
- +{
- + NODE *body, *defn;
- + VALUE origin = 0;
- + int noex;
- +
- + if (NIL_P(ruby_class)) {
- + rb_raise(rb_eTypeError, "no class/module to add method");
- + }
- + if (ruby_class == rb_cObject && node->nd_mid == init) {
- + rb_warn("redefining Object#initialize may cause infinite loop");
- + }
- + if (node->nd_mid == __id__ || node->nd_mid == __send__) {
- + rb_warn("redefining `%s' may cause serious problem",
- + rb_id2name(node->nd_mid));
- + }
- + rb_frozen_class_p(ruby_class);
- + body = search_method(ruby_class, node->nd_mid, &origin);
- + if (body){
- + if (RTEST(ruby_verbose) && ruby_class == origin && body->nd_cnt == 0 && body->nd_body) {
- + rb_warning("method redefined; discarding old %s", rb_id2name(node->nd_mid));
- + }
- + }
- +
- + if (SCOPE_TEST(SCOPE_PRIVATE) || node->nd_mid == init) {
- + noex = NOEX_PRIVATE;
- + }
- + else if (SCOPE_TEST(SCOPE_PROTECTED)) {
- + noex = NOEX_PROTECTED;
- + }
- + else {
- + noex = NOEX_PUBLIC;
- + }
- + if (body && origin == ruby_class && body->nd_body == 0) {
- + noex |= NOEX_NOSUPER;
- + }
- +
- + defn = rb_copy_node_scope(node->nd_defn, ruby_cref);
- + rb_add_method(ruby_class, node->nd_mid, defn, noex);
- + if (scope_vmode == SCOPE_MODFUNC) {
- + rb_add_method(rb_singleton_class(ruby_class),
- + node->nd_mid, defn, NOEX_PUBLIC);
- + }
- +}
- +
- +
- +eval_node(defs, void)
- +{
- + VALUE recv = rb_eval(self, node->nd_recv);
- + VALUE klass;
- + NODE *body = 0, *defn;
- + st_data_t data;
- +
- + if (ruby_safe_level >= 4 && !OBJ_TAINTED(recv)) {
- + rb_raise(rb_eSecurityError, "Insecure: can't define singleton method");
- + }
- + if (FIXNUM_P(recv) || SYMBOL_P(recv)) {
- + rb_raise(rb_eTypeError,
- + "can't define singleton method \"%s\" for %s",
- + rb_id2name(node->nd_mid),
- + rb_obj_classname(recv));
- + }
- +
- + if (OBJ_FROZEN(recv)) rb_error_frozen("object");
- + klass = rb_singleton_class(recv);
- + if (st_lookup(RCLASS(klass)->m_tbl, node->nd_mid, &data)) {
- + body = (NODE *)data;
- + if (ruby_safe_level >= 4) {
- + rb_raise(rb_eSecurityError, "redefining method prohibited");
- + }
- + if (RTEST(ruby_verbose)) {
- + rb_warning("redefine %s", rb_id2name(node->nd_mid));
- + }
- + }
- + defn = rb_copy_node_scope(node->nd_defn, ruby_cref);
- + rb_add_method(klass, node->nd_mid, defn,
- + NOEX_PUBLIC|(body?body->nd_noex&NOEX_UNDEF:0));
- +}
- +
- +
- +eval_node(class, VALUE)
- +{
- + VALUE super, klass, tmp, cbase;
- + ID cname;
- + int gen = Qfalse;
- +
- + cbase = class_prefix(self, node->nd_cpath);
- + cname = node->nd_cpath->nd_mid;
- +
- + if (NIL_P(ruby_cbase)) {
- + rb_raise(rb_eTypeError, "no outer class/module");
- + }
- + if (node->nd_super) {
- + super = rb_eval(self, node->nd_super);
- + rb_check_inheritable(super);
- + }
- + else {
- + super = 0;
- + }
- +
- + if (rb_const_defined_at(cbase, cname)) {
- + klass = rb_const_get_at(cbase, cname);
- + if (TYPE(klass) != T_CLASS) {
- + rb_raise(rb_eTypeError, "%s is not a class",
- + rb_id2name(cname));
- + }
- + if (super) {
- + tmp = rb_class_real(RCLASS(klass)->super);
- + if (tmp != super) {
- + rb_raise(rb_eTypeError, "superclass mismatch for class %s",
- + rb_id2name(cname));
- + }
- + super = 0;
- + }
- + if (ruby_safe_level >= 4) {
- + rb_raise(rb_eSecurityError, "extending class prohibited");
- + }
- + }
- + else {
- + if (!super) super = rb_cObject;
- + klass = rb_define_class_id(cname, super);
- + rb_set_class_path(klass, cbase, rb_id2name(cname));
- + rb_const_set(cbase, cname, klass);
- + gen = Qtrue;
- + }
- + if (ruby_wrapper) {
- + rb_extend_object(klass, ruby_wrapper);
- + rb_include_module(klass, ruby_wrapper);
- + }
- + if (super && gen) {
- + rb_class_inherited(super, klass);
- + }
- + return module_setup(klass, node);
- +}
- +
- +
- +eval_node(module, VALUE)
- +{
- + VALUE module, cbase;
- + ID cname;
- +
- + if (NIL_P(ruby_cbase)) {
- + rb_raise(rb_eTypeError, "no outer class/module");
- + }
- + cbase = class_prefix(self, node->nd_cpath);
- + cname = node->nd_cpath->nd_mid;
- + if (rb_const_defined_at(cbase, cname)) {
- + module = rb_const_get_at(cbase, cname);
- + if (TYPE(module) != T_MODULE) {
- + rb_raise(rb_eTypeError, "%s is not a module",
- + rb_id2name(cname));
- + }
- + if (ruby_safe_level >= 4) {
- + rb_raise(rb_eSecurityError, "extending module prohibited");
- + }
- + }
- + else {
- + module = rb_define_module_id(cname);
- + rb_set_class_path(module, cbase, rb_id2name(cname));
- + rb_const_set(cbase, cname, module);
- + }
- + if (ruby_wrapper) {
- + rb_extend_object(module, ruby_wrapper);
- + rb_include_module(module, ruby_wrapper);
- + }
- +
- + return module_setup(module, node);
- +}
- +
- +
- +eval_node(sclass, VALUE)
- +{
- + VALUE klass, result;
- +
- + result = rb_eval(self, node->nd_recv);
- + if (FIXNUM_P(result) || SYMBOL_P(result)) {
- + rb_raise(rb_eTypeError, "no virtual class for %s",
- + rb_obj_classname(result));
- + }
- + if (ruby_safe_level >= 4 && !OBJ_TAINTED(result))
- + rb_raise(rb_eSecurityError, "Insecure: can't extend object");
- + klass = rb_singleton_class(result);
- +
- + if (ruby_wrapper) {
- + rb_extend_object(klass, ruby_wrapper);
- + rb_include_module(klass, ruby_wrapper);
- + }
- +
- + return module_setup(klass, node);
- +}
- +
- +
- +eval_node(defined, VALUE)
- +{
- + char buf[20];
- + const char *desc = is_defined(self, node->nd_head, buf);
- + return desc ? rb_str_new2(desc) : Qnil;
- +}
- +
- +
- +static void
- +eval_cvar_set(node, result, warn)
- + NODE *node;
- + VALUE result;
- + int warn;
- +{
- + rb_cvar_set(cvar_cbase(), node->nd_vid, result, warn);
- +}
- +
- +
- +static void
- +eval_cdecl(self, node, result)
- + VALUE self, result;
- + NODE *node;
- +{
- + if (node->nd_vid == 0)
- + rb_const_set(class_prefix(self, node->nd_else),
- + node->nd_else->nd_mid, result);
- + else
- + rb_const_set(ruby_cbase, node->nd_vid, result);
- +}
-
- - again:
- - if (!node) RETURN(Qnil);
-
- +static VALUE
- +rb_eval(self, node)
- + VALUE self;
- + NODE * node;
- +{
- + VALUE result;
- +
- +again:
- + CHECK_INTS;
- + result = Qnil;
- + if (node) {
- ruby_current_node = node;
- switch (nd_type(node)) {
- case NODE_BLOCK:
- - if (contnode) {
- - result = rb_eval(self, node);
- - break;
- + while (node->nd_next) {
- + rb_eval(self, node->nd_head);
- + node = node->nd_next;
- }
- - contnode = node->nd_next;
- node = node->nd_head;
- goto again;
-
- case NODE_POSTEXE:
- rb_f_END();
- nd_set_type(node, NODE_NIL); /* exec just once */
- - result = Qnil;
- break;
-
- /* begin .. end without clauses */
- @@ -2984,223 +3867,57 @@ rb_eval(self, n)
-
- /* nodes for speed-up(literal match) */
- case NODE_MATCH2:
- - {
- - VALUE l = rb_eval(self,node->nd_recv);
- - VALUE r = rb_eval(self,node->nd_value);
- - result = rb_reg_match(l, r);
- - }
- + result = eval_match2(self, node);
- break;
-
- /* nodes for speed-up(literal match) */
- case NODE_MATCH3:
- - {
- - VALUE r = rb_eval(self,node->nd_recv);
- - VALUE l = rb_eval(self,node->nd_value);
- - if (TYPE(l) == T_STRING) {
- - result = rb_reg_match(r, l);
- - }
- - else {
- - result = rb_funcall(l, match, 1, r);
- - }
- - }
- + result = eval_match3(self,node);
- break;
-
- /* node for speed-up(top-level loop for -n/-p) */
- case NODE_OPT_N:
- - PUSH_TAG(PROT_LOOP);
- - switch (state = EXEC_TAG()) {
- - case 0:
- - opt_n_next:
- - while (!NIL_P(rb_gets())) {
- - opt_n_redo:
- - rb_eval(self, node->nd_body);
- - }
- - break;
- -
- - case TAG_REDO:
- - state = 0;
- - goto opt_n_redo;
- - case TAG_NEXT:
- - state = 0;
- - goto opt_n_next;
- - case TAG_BREAK:
- - state = 0;
- - default:
- - break;
- - }
- - POP_TAG();
- - if (state) JUMP_TAG(state);
- - RETURN(Qnil);
- + eval_opt_n(self, node);
- + break;
-
- case NODE_SELF:
- - RETURN(self);
- + result = self;
- + break;
-
- case NODE_NIL:
- - RETURN(Qnil);
- + break;
-
- case NODE_TRUE:
- - RETURN(Qtrue);
- + result = Qtrue;
- + break;
-
- case NODE_FALSE:
- - RETURN(Qfalse);
- + result = Qfalse;
- + break;
-
- case NODE_IF:
- EXEC_EVENT_HOOK(RUBY_EVENT_LINE, node, self,
- ruby_frame->last_func,
- ruby_frame->last_class);
- - if (RTEST(rb_eval(self, node->nd_cond))) {
- - node = node->nd_body;
- - }
- - else {
- - node = node->nd_else;
- - }
- + node = RTEST(rb_eval(self, node->nd_cond)) ?
- + node->nd_body : node->nd_else;
- goto again;
-
- case NODE_WHEN:
- - while (node) {
- - NODE *tag;
- -
- - if (nd_type(node) != NODE_WHEN) goto again;
- - tag = node->nd_head;
- - while (tag) {
- - EXEC_EVENT_HOOK(RUBY_EVENT_LINE, tag, self,
- - ruby_frame->last_func,
- - ruby_frame->last_class);
- - if (tag->nd_head && nd_type(tag->nd_head) == NODE_WHEN) {
- - VALUE v = rb_eval(self, tag->nd_head->nd_head);
- - long i;
- -
- - if (TYPE(v) != T_ARRAY) v = rb_ary_to_ary(v);
- - for (i=0; i<RARRAY(v)->len; i++) {
- - if (RTEST(RARRAY(v)->ptr[i])) {
- - node = node->nd_body;
- - goto again;
- - }
- - }
- - tag = tag->nd_next;
- - continue;
- - }
- - if (RTEST(rb_eval(self, tag->nd_head))) {
- - node = node->nd_body;
- - goto again;
- - }
- - tag = tag->nd_next;
- - }
- - node = node->nd_next;
- - }
- - RETURN(Qnil);
- + if (node = eval_when(self, node)) goto again;
- + break;
-
- case NODE_CASE:
- - {
- - VALUE val;
- -
- - val = rb_eval(self, node->nd_head);
- - node = node->nd_body;
- - while (node) {
- - NODE *tag;
- -
- - if (nd_type(node) != NODE_WHEN) {
- - goto again;
- - }
- - tag = node->nd_head;
- - while (tag) {
- - EXEC_EVENT_HOOK(RUBY_EVENT_LINE, tag, self,
- - ruby_frame->last_func,
- - ruby_frame->last_class);
- - if (tag->nd_head && nd_type(tag->nd_head) == NODE_WHEN) {
- - VALUE v = rb_eval(self, tag->nd_head->nd_head);
- - long i;
- -
- - if (TYPE(v) != T_ARRAY) v = rb_ary_to_ary(v);
- - for (i=0; i<RARRAY(v)->len; i++) {
- - if (RTEST(rb_funcall2(RARRAY(v)->ptr[i], eqq, 1, &val))){
- - node = node->nd_body;
- - goto again;
- - }
- - }
- - tag = tag->nd_next;
- - continue;
- - }
- - if (RTEST(rb_funcall2(rb_eval(self, tag->nd_head), eqq, 1, &val))) {
- - node = node->nd_body;
- - goto again;
- - }
- - tag = tag->nd_next;
- - }
- - node = node->nd_next;
- - }
- - }
- - RETURN(Qnil);
- + if (node = eval_case(self, node)) goto again;
- + break;
-
- case NODE_WHILE:
- - PUSH_TAG(PROT_LOOP);
- - result = Qnil;
- - switch (state = EXEC_TAG()) {
- - case 0:
- - if (node->nd_state && !RTEST(rb_eval(self, node->nd_cond)))
- - goto while_out;
- - do {
- - while_redo:
- - rb_eval(self, node->nd_body);
- - while_next:
- - ;
- - } while (RTEST(rb_eval(self, node->nd_cond)));
- - break;
- -
- - case TAG_REDO:
- - state = 0;
- - goto while_redo;
- - case TAG_NEXT:
- - state = 0;
- - goto while_next;
- - case TAG_BREAK:
- - if (TAG_DST()) {
- - state = 0;
- - result = prot_tag->retval;
- - }
- - /* fall through */
- - default:
- - break;
- - }
- - while_out:
- - POP_TAG();
- - if (state) JUMP_TAG(state);
- - RETURN(result);
- + result = eval_while(self,node);
- + break;
-
- case NODE_UNTIL:
- - PUSH_TAG(PROT_LOOP);
- - result = Qnil;
- - switch (state = EXEC_TAG()) {
- - case 0:
- - if (node->nd_state && RTEST(rb_eval(self, node->nd_cond)))
- - goto until_out;
- - do {
- - until_redo:
- - rb_eval(self, node->nd_body);
- - until_next:
- - ;
- - } while (!RTEST(rb_eval(self, node->nd_cond)));
- - break;
- -
- - case TAG_REDO:
- - state = 0;
- - goto until_redo;
- - case TAG_NEXT:
- - state = 0;
- - goto until_next;
- - case TAG_BREAK:
- - if (TAG_DST()) {
- - state = 0;
- - result = prot_tag->retval;
- - }
- - /* fall through */
- - default:
- - break;
- - }
- - until_out:
- - POP_TAG();
- - if (state) JUMP_TAG(state);
- - RETURN(result);
- + result = eval_until(self,node);
- + break;
-
- case NODE_BLOCK_PASS:
- result = block_pass(self, node);
- @@ -3208,47 +3925,7 @@ rb_eval(self, n)
-
- case NODE_ITER:
- case NODE_FOR:
- - {
- - PUSH_TAG(PROT_LOOP);
- - PUSH_BLOCK(node->nd_var, node->nd_body);
- -
- - state = EXEC_TAG();
- - if (state == 0) {
- - iter_retry:
- - PUSH_ITER(ITER_PRE);
- - if (nd_type(node) == NODE_ITER) {
- - result = rb_eval(self, node->nd_iter);
- - }
- - else {
- - VALUE recv;
- -
- - _block.flags &= ~BLOCK_D_SCOPE;
- - BEGIN_CALLARGS;
- - recv = rb_eval(self, node->nd_iter);
- - END_CALLARGS;
- - ruby_current_node = node;
- - SET_CURRENT_SOURCE();
- - result = rb_call(CLASS_OF(recv),recv,each,0,0,0,self);
- - }
- - POP_ITER();
- - }
- - else if (state == TAG_BREAK && TAG_DST()) {
- - result = prot_tag->retval;
- - state = 0;
- - }
- - else if (state == TAG_RETRY) {
- - state = 0;
- - goto iter_retry;
- - }
- - POP_BLOCK();
- - POP_TAG();
- - switch (state) {
- - case 0:
- - break;
- - default:
- - JUMP_TAG(state);
- - }
- - }
- + result = eval_iter(self, node);
- break;
-
- case NODE_BREAK:
- @@ -3256,17 +3933,14 @@ rb_eval(self, n)
- break;
-
- case NODE_NEXT:
- - CHECK_INTS;
- next_jump(rb_eval(self, node->nd_stts));
- break;
-
- case NODE_REDO:
- - CHECK_INTS;
- JUMP_TAG(TAG_REDO);
- break;
-
- case NODE_RETRY:
- - CHECK_INTS;
- JUMP_TAG(TAG_RETRY);
- break;
-
- @@ -3296,73 +3970,15 @@ rb_eval(self, n)
- break;
-
- case NODE_RESCUE:
- - {
- - volatile VALUE e_info = ruby_errinfo;
- - volatile int rescuing = 0;
- -
- - PUSH_TAG(PROT_NONE);
- - if ((state = EXEC_TAG()) == 0) {
- - retry_entry:
- - result = rb_eval(self, node->nd_head);
- - }
- - else if (rescuing) {
- - if (rescuing < 0) {
- - /* in rescue argument, just reraise */
- - }
- - else if (state == TAG_RETRY) {
- - rescuing = state = 0;
- - ruby_errinfo = e_info;
- - goto retry_entry;
- - }
- - else if (state != TAG_RAISE) {
- - result = prot_tag->retval;
- - }
- - }
- - else if (state == TAG_RAISE) {
- - NODE *resq = node->nd_resq;
- -
- - rescuing = -1;
- - while (resq) {
- - ruby_current_node = resq;
- - if (handle_rescue(self, resq)) {
- - state = 0;
- - rescuing = 1;
- - result = rb_eval(self, resq->nd_body);
- - break;
- - }
- - resq = resq->nd_head; /* next rescue */
- - }
- - }
- - else {
- - result = prot_tag->retval;
- - }
- - POP_TAG();
- - if (state != TAG_RAISE) ruby_errinfo = e_info;
- - if (state) {
- - JUMP_TAG(state);
- - }
- - /* no exception raised */
- - if (!rescuing && (node = node->nd_else)) { /* else clause given */
- - goto again;
- - }
- - }
- + result = eval_rescue(self,node);
- + if (result == Qundef) { /* handle else clause w/o recursion */
- + node = node->nd_else;
- + goto again;
- + }
- break;
-
- case NODE_ENSURE:
- - PUSH_TAG(PROT_NONE);
- - if ((state = EXEC_TAG()) == 0) {
- - result = rb_eval(self, node->nd_head);
- - }
- - POP_TAG();
- - if (node->nd_ensr && !thread_no_ensure()) {
- - VALUE retval = prot_tag->retval; /* save retval */
- - VALUE errinfo = ruby_errinfo;
- -
- - rb_eval(self, node->nd_ensr);
- - return_value(retval);
- - ruby_errinfo = errinfo;
- - }
- - if (state) JUMP_TAG(state);
- + result = eval_ensure(self,node);
- break;
-
- case NODE_AND:
- @@ -3378,56 +3994,20 @@ rb_eval(self, n)
- goto again;
-
- case NODE_NOT:
- - if (RTEST(rb_eval(self, node->nd_body))) result = Qfalse;
- - else result = Qtrue;
- + result = RTEST(rb_eval(self, node->nd_body)) ? Qfalse : Qtrue;
- break;
-
- case NODE_DOT2:
- case NODE_DOT3:
- - {
- - VALUE beg = rb_eval(self, node->nd_beg);
- - VALUE end = rb_eval(self, node->nd_end);
- - result = rb_range_new(beg, end, nd_type(node) == NODE_DOT3);
- - }
- - break;
- + result = eval_dot(self,node);
- + break;
-
- case NODE_FLIP2: /* like AWK */
- - {
- - VALUE *flip = rb_svar(node->nd_cnt);
- - if (!flip) rb_bug("unexpected local variable");
- - if (!RTEST(*flip)) {
- - if (RTEST(rb_eval(self, node->nd_beg))) {
- - *flip = RTEST(rb_eval(self, node->nd_end))?Qfalse:Qtrue;
- - result = Qtrue;
- - }
- - else {
- - result = Qfalse;
- - }
- - }
- - else {
- - if (RTEST(rb_eval(self, node->nd_end))) {
- - *flip = Qfalse;
- - }
- - result = Qtrue;
- - }
- - }
- + result = eval_flip2(self,node);
- break;
-
- case NODE_FLIP3: /* like SED */
- - {
- - VALUE *flip = rb_svar(node->nd_cnt);
- - if (!flip) rb_bug("unexpected local variable");
- - if (!RTEST(*flip)) {
- - result = RTEST(rb_eval(self, node->nd_beg)) ? Qtrue : Qfalse;
- - *flip = result;
- - }
- - else {
- - if (RTEST(rb_eval(self, node->nd_end))) {
- - *flip = Qfalse;
- - }
- - result = Qtrue;
- - }
- - }
- + result = eval_flip3(self,node);
- break;
-
- case NODE_RETURN:
- @@ -3435,75 +4015,25 @@ rb_eval(self, n)
- break;
-
- case NODE_ARGSCAT:
- - {
- - VALUE args = rb_eval(self, node->nd_head);
- - result = rb_ary_concat(args, splat_value(rb_eval(self, node->nd_body)));
- - }
- + result = rb_eval(self, node->nd_head);
- + result = rb_ary_concat(result, splat_value(rb_eval(self, node->nd_body)));
- break;
-
- case NODE_ARGSPUSH:
- - {
- - VALUE args = rb_ary_dup(rb_eval(self, node->nd_head));
- - result = rb_ary_push(args, rb_eval(self, node->nd_body));
- - }
- + result = rb_ary_dup(rb_eval(self, node->nd_head));
- + result = rb_ary_push(result, rb_eval(self, node->nd_body));
- break;
-
- case NODE_ATTRASGN:
- - {
- - VALUE recv;
- - int argc; VALUE *argv; /* used in SETUP_ARGS */
- - int scope;
- - TMP_PROTECT;
- -
- - BEGIN_CALLARGS;
- - if (node->nd_recv == (NODE *)1) {
- - recv = self;
- - scope = 1;
- - }
- - else {
- - recv = rb_eval(self, node->nd_recv);
- - scope = 0;
- - }
- - SETUP_ARGS(node->nd_args);
- - END_CALLARGS;
- -
- - ruby_current_node = node;
- - SET_CURRENT_SOURCE();
- - rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,scope,self);
- - result = argv[argc-1];
- - }
- - break;
- + result = eval_attrasgn(self,node);
- + break;
-
- case NODE_CALL:
- - {
- - VALUE recv;
- - int argc; VALUE *argv; /* used in SETUP_ARGS */
- - TMP_PROTECT;
- -
- - BEGIN_CALLARGS;
- - recv = rb_eval(self, node->nd_recv);
- - SETUP_ARGS(node->nd_args);
- - END_CALLARGS;
- -
- - ruby_current_node = node;
- - SET_CURRENT_SOURCE();
- - result = rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,0,self);
- - }
- + result = eval_call(self,node);
- break;
-
- case NODE_FCALL:
- - {
- - int argc; VALUE *argv; /* used in SETUP_ARGS */
- - TMP_PROTECT;
- -
- - BEGIN_CALLARGS;
- - SETUP_ARGS(node->nd_args);
- - END_CALLARGS;
- -
- - ruby_current_node = node;
- - SET_CURRENT_SOURCE();
- - result = rb_call(CLASS_OF(self),self,node->nd_mid,argc,argv,1,self);
- - }
- + result = eval_fcall(self,node);
- break;
-
- case NODE_VCALL:
- @@ -3513,142 +4043,19 @@ rb_eval(self, n)
-
- case NODE_SUPER:
- case NODE_ZSUPER:
- - {
- - int argc; VALUE *argv; /* used in SETUP_ARGS */
- - TMP_PROTECT;
- -
- - if (ruby_frame->last_class == 0) {
- - if (ruby_frame->last_func) {
- - rb_name_error(ruby_frame->last_func,
- - "superclass method `%s' disabled",
- - rb_id2name(ruby_frame->orig_func));
- - }
- - else {
- - rb_raise(rb_eNoMethodError, "super called outside of method");
- - }
- - }
- - if (nd_type(node) == NODE_ZSUPER) {
- - argc = ruby_frame->argc;
- - if (argc && DMETHOD_P()) {
- - if (TYPE(RBASIC(ruby_scope)->klass) != T_ARRAY ||
- - RARRAY(RBASIC(ruby_scope)->klass)->len != argc) {
- - rb_raise(rb_eRuntimeError,
- - "super: specify arguments explicitly");
- - }
- - argv = RARRAY(RBASIC(ruby_scope)->klass)->ptr;
- - }
- - else if (!ruby_scope->local_vars) {
- - argc = 0;
- - argv = 0;
- - }
- - else {
- - argv = ruby_scope->local_vars + 2;
- - }
- - }
- - else {
- - BEGIN_CALLARGS;
- - SETUP_ARGS(node->nd_args);
- - END_CALLARGS;
- - ruby_current_node = node;
- - }
- -
- - SET_CURRENT_SOURCE();
- - result = rb_call_super(argc, argv);
- - }
- + result = eval_super(self,node);
- break;
-
- case NODE_SCOPE:
- - {
- - struct FRAME frame;
- - NODE *saved_cref = 0;
- -
- - frame = *ruby_frame;
- - frame.tmp = ruby_frame;
- - ruby_frame = &frame;
- -
- - PUSH_SCOPE();
- - PUSH_TAG(PROT_NONE);
- - if (node->nd_rval) {
- - saved_cref = ruby_cref;
- - ruby_cref = (NODE*)node->nd_rval;
- - }
- - if (node->nd_tbl) {
- - VALUE *vars = ALLOCA_N(VALUE, node->nd_tbl[0]+1);
- - *vars++ = (VALUE)node;
- - ruby_scope->local_vars = vars;
- - rb_mem_clear(ruby_scope->local_vars, node->nd_tbl[0]);
- - ruby_scope->local_tbl = node->nd_tbl;
- - }
- - else {
- - ruby_scope->local_vars = 0;
- - ruby_scope->local_tbl = 0;
- - }
- - if ((state = EXEC_TAG()) == 0) {
- - result = rb_eval(self, node->nd_next);
- - }
- - POP_TAG();
- - POP_SCOPE();
- - ruby_frame = frame.tmp;
- - if (saved_cref)
- - ruby_cref = saved_cref;
- - if (state) JUMP_TAG(state);
- - }
- - break;
- + result = eval_scope(self,node);
- + break;
-
- case NODE_OP_ASGN1:
- - {
- - int argc; VALUE *argv; /* used in SETUP_ARGS */
- - VALUE recv, val, tmp;
- - NODE *rval;
- - TMP_PROTECT;
- -
- - recv = rb_eval(self, node->nd_recv);
- - rval = node->nd_args->nd_head;
- - SETUP_ARGS0(node->nd_args->nd_body, 1);
- - val = rb_funcall3(recv, aref, argc, argv);
- - switch (node->nd_mid) {
- - case 0: /* OR */
- - if (RTEST(val)) RETURN(val);
- - val = rb_eval(self, rval);
- - break;
- - case 1: /* AND */
- - if (!RTEST(val)) RETURN(val);
- - val = rb_eval(self, rval);
- - break;
- - default:
- - tmp = rb_eval(self, rval);
- - val = rb_funcall3(val, node->nd_mid, 1, &tmp);
- - }
- - argv[argc] = val;
- - rb_funcall2(recv, aset, argc+1, argv);
- - result = val;
- - }
- + result = eval_op_asgn1(self,node);
- break;
-
- case NODE_OP_ASGN2:
- - {
- - ID id = node->nd_next->nd_vid;
- - VALUE recv, val, tmp;
- -
- - recv = rb_eval(self, node->nd_recv);
- - val = rb_funcall3(recv, id, 0, 0);
- - switch (node->nd_next->nd_mid) {
- - case 0: /* OR */
- - if (RTEST(val)) RETURN(val);
- - val = rb_eval(self, node->nd_value);
- - break;
- - case 1: /* AND */
- - if (!RTEST(val)) RETURN(val);
- - val = rb_eval(self, node->nd_value);
- - break;
- - default:
- - tmp = rb_eval(self, node->nd_value);
- - val = rb_funcall3(val, node->nd_next->nd_mid, 1, &tmp);
- - }
- -
- - rb_funcall2(recv, node->nd_next->nd_aid, 1, &val);
- - result = val;
- - }
- + result = eval_op_asgn2(self,node);
- break;
-
- case NODE_OP_ASGN_AND:
- @@ -3697,26 +4104,21 @@ rb_eval(self, n)
- break;
-
- case NODE_CDECL:
- - result = rb_eval(self, node->nd_value);
- - if (node->nd_vid == 0) {
- - rb_const_set(class_prefix(self, node->nd_else), node->nd_else->nd_mid, result);
- - }
- - else {
- - rb_const_set(ruby_cbase, node->nd_vid, result);
- - }
- + result = rb_eval(self, node->nd_value);
- + eval_cdecl(self, node, result);
- break;
-
- case NODE_CVDECL:
- if (NIL_P(ruby_cbase)) {
- rb_raise(rb_eTypeError, "no class/module to define class variable");
- }
- - result = rb_eval(self, node->nd_value);
- - rb_cvar_set(cvar_cbase(), node->nd_vid, result, Qtrue);
- + result = rb_eval(self, node->nd_value);
- + eval_cvar_set(node, result, Qtrue);
- break;
-
- case NODE_CVASGN:
- - result = rb_eval(self, node->nd_value);
- - rb_cvar_set(cvar_cbase(), node->nd_vid, result, Qfalse);
- + result = rb_eval(self, node->nd_value);
- + eval_cvar_set(node, result, Qfalse);
- break;
-
- case NODE_LVAR:
- @@ -3759,26 +4161,21 @@ rb_eval(self, n)
- break;
-
- case NODE_COLON2:
- - {
- - VALUE klass;
- -
- - klass = rb_eval(self, node->nd_head);
- - if (rb_is_const_id(node->nd_mid)) {
- - switch (TYPE(klass)) {
- - case T_CLASS:
- - case T_MODULE:
- - result = rb_const_get_from(klass, node->nd_mid);
- - break;
- - default:
- - rb_raise(rb_eTypeError, "%s is not a class/module",
- - RSTRING(rb_obj_as_string(klass))->ptr);
- - break;
- - }
- - }
- - else {
- - result = rb_funcall(klass, node->nd_mid, 0, 0);
- + result = rb_eval(self, node->nd_head);
- + if (rb_is_const_id(node->nd_mid)) {
- + switch (TYPE(result)) {
- + case T_CLASS:
- + case T_MODULE:
- + result = rb_const_get_from(result, node->nd_mid);
- + break;
- + default:
- + rb_raise(rb_eTypeError, "%s is not a class/module",
- + RSTRING(rb_obj_as_string(result))->ptr);
- + break;
- }
- }
- + else
- + result = rb_funcall(result, node->nd_mid, 0, 0);
- break;
-
- case NODE_COLON3:
- @@ -3809,23 +4206,7 @@ rb_eval(self, n)
- break;
-
- case NODE_HASH:
- - {
- - NODE *list;
- - VALUE hash = rb_hash_new();
- - VALUE key, val;
- -
- - list = node->nd_head;
- - while (list) {
- - key = rb_eval(self, list->nd_head);
- - list = list->nd_next;
- - if (list == 0)
- - rb_bug("odd number list for Hash");
- - val = rb_eval(self, list->nd_head);
- - list = list->nd_next;
- - rb_hash_aset(hash, key, val);
- - }
- - result = hash;
- - }
- + result = eval_hash(self,node);
- break;
-
- case NODE_ZARRAY: /* zero length list */
- @@ -3833,19 +4214,7 @@ rb_eval(self, n)
- break;
-
- case NODE_ARRAY:
- - {
- - VALUE ary;
- - long i;
- -
- - i = node->nd_alen;
- - ary = rb_ary_new2(i);
- - for (i=0;node;node=node->nd_next) {
- - RARRAY(ary)->ptr[i++] = rb_eval(self, node->nd_head);
- - RARRAY(ary)->len = i;
- - }
- -
- - result = ary;
- - }
- + result = eval_array(self,node);
- break;
-
- case NODE_STR:
- @@ -3861,51 +4230,8 @@ rb_eval(self, n)
- case NODE_DREGX:
- case NODE_DREGX_ONCE:
- case NODE_DSYM:
- - {
- - VALUE str, str2;
- - NODE *list = node->nd_next;
- -
- - str = rb_str_new3(node->nd_lit);
- - while (list) {
- - if (list->nd_head) {
- - switch (nd_type(list->nd_head)) {
- - case NODE_STR:
- - str2 = list->nd_head->nd_lit;
- - break;
- - default:
- - str2 = rb_eval(self, list->nd_head);
- - break;
- - }
- - rb_str_append(str, str2);
- - OBJ_INFECT(str, str2);
- - }
- - list = list->nd_next;
- - }
- - switch (nd_type(node)) {
- - case NODE_DREGX:
- - result = rb_reg_new(RSTRING(str)->ptr, RSTRING(str)->len,
- - node->nd_cflag);
- - break;
- - case NODE_DREGX_ONCE: /* regexp expand once */
- - result = rb_reg_new(RSTRING(str)->ptr, RSTRING(str)->len,
- - node->nd_cflag);
- - nd_set_type(node, NODE_LIT);
- - node->nd_lit = result;
- - break;
- - case NODE_LIT:
- - /* other thread may replace NODE_DREGX_ONCE to NODE_LIT */
- - goto again;
- - case NODE_DXSTR:
- - result = rb_funcall(self, '`', 1, str);
- - break;
- - case NODE_DSYM:
- - result = rb_str_intern(str);
- - break;
- - default:
- - result = str;
- - break;
- - }
- - }
- + result = eval_slit(self, node);
- + if (result == Qundef) goto again;
- break;
-
- case NODE_XSTR:
- @@ -3917,84 +4243,13 @@ rb_eval(self, n)
- break;
-
- case NODE_DEFN:
- - if (node->nd_defn) {
- - NODE *body, *defn;
- - VALUE origin;
- - int noex;
- -
- - if (NIL_P(ruby_class)) {
- - rb_raise(rb_eTypeError, "no class/module to add method");
- - }
- - if (ruby_class == rb_cObject && node->nd_mid == init) {
- - rb_warn("redefining Object#initialize may cause infinite loop");
- - }
- - if (node->nd_mid == __id__ || node->nd_mid == __send__) {
- - rb_warn("redefining `%s' may cause serious problem",
- - rb_id2name(node->nd_mid));
- - }
- - rb_frozen_class_p(ruby_class);
- - body = search_method(ruby_class, node->nd_mid, &origin);
- - if (body){
- - if (RTEST(ruby_verbose) && ruby_class == origin && body->nd_cnt == 0 && body->nd_body) {
- - rb_warning("method redefined; discarding old %s", rb_id2name(node->nd_mid));
- - }
- - }
- -
- - if (SCOPE_TEST(SCOPE_PRIVATE) || node->nd_mid == init) {
- - noex = NOEX_PRIVATE;
- - }
- - else if (SCOPE_TEST(SCOPE_PROTECTED)) {
- - noex = NOEX_PROTECTED;
- - }
- - else {
- - noex = NOEX_PUBLIC;
- - }
- - if (body && origin == ruby_class && body->nd_body == 0) {
- - noex |= NOEX_NOSUPER;
- - }
- -
- - defn = rb_copy_node_scope(node->nd_defn, ruby_cref);
- - rb_add_method(ruby_class, node->nd_mid, defn, noex);
- - if (scope_vmode == SCOPE_MODFUNC) {
- - rb_add_method(rb_singleton_class(ruby_class),
- - node->nd_mid, defn, NOEX_PUBLIC);
- - }
- - result = Qnil;
- - }
- + if (node->nd_defn)
- + eval_defn(self,node);
- break;
-
- case NODE_DEFS:
- - if (node->nd_defn) {
- - VALUE recv = rb_eval(self, node->nd_recv);
- - VALUE klass;
- - NODE *body = 0, *defn;
- -
- - if (ruby_safe_level >= 4 && !OBJ_TAINTED(recv)) {
- - rb_raise(rb_eSecurityError, "Insecure: can't define singleton method");
- - }
- - if (FIXNUM_P(recv) || SYMBOL_P(recv)) {
- - rb_raise(rb_eTypeError,
- - "can't define singleton method \"%s\" for %s",
- - rb_id2name(node->nd_mid),
- - rb_obj_classname(recv));
- - }
- -
- - if (OBJ_FROZEN(recv)) rb_error_frozen("object");
- - klass = rb_singleton_class(recv);
- - if (st_lookup(RCLASS(klass)->m_tbl, node->nd_mid, &data)) {
- - body = (NODE *)data;
- - if (ruby_safe_level >= 4) {
- - rb_raise(rb_eSecurityError, "redefining method prohibited");
- - }
- - if (RTEST(ruby_verbose)) {
- - rb_warning("redefine %s", rb_id2name(node->nd_mid));
- - }
- - }
- - defn = rb_copy_node_scope(node->nd_defn, ruby_cref);
- - rb_add_method(klass, node->nd_mid, defn,
- - NOEX_PUBLIC|(body?body->nd_noex&NOEX_UNDEF:0));
- - result = Qnil;
- - }
- + if (node->nd_defn)
- + eval_defs(self,node);
- break;
-
- case NODE_UNDEF:
- @@ -4002,7 +4257,6 @@ rb_eval(self, n)
- rb_raise(rb_eTypeError, "no class to undef method");
- }
- rb_undef(ruby_class, rb_to_id(rb_eval(self, node->u2.node)));
- - result = Qnil;
- break;
-
- case NODE_ALIAS:
- @@ -4011,134 +4265,26 @@ rb_eval(self, n)
- }
- rb_alias(ruby_class, rb_to_id(rb_eval(self, node->u1.node)),
- rb_to_id(rb_eval(self, node->u2.node)));
- - result = Qnil;
- break;
-
- case NODE_VALIAS:
- rb_alias_variable(node->u1.id, node->u2.id);
- - result = Qnil;
- break;
-
- case NODE_CLASS:
- - {
- - VALUE super, klass, tmp, cbase;
- - ID cname;
- - int gen = Qfalse;
- -
- - cbase = class_prefix(self, node->nd_cpath);
- - cname = node->nd_cpath->nd_mid;
- -
- - if (NIL_P(ruby_cbase)) {
- - rb_raise(rb_eTypeError, "no outer class/module");
- - }
- - if (node->nd_super) {
- - super = rb_eval(self, node->nd_super);
- - rb_check_inheritable(super);
- - }
- - else {
- - super = 0;
- - }
- -
- - if (rb_const_defined_at(cbase, cname)) {
- - klass = rb_const_get_at(cbase, cname);
- - if (TYPE(klass) != T_CLASS) {
- - rb_raise(rb_eTypeError, "%s is not a class",
- - rb_id2name(cname));
- - }
- - if (super) {
- - tmp = rb_class_real(RCLASS(klass)->super);
- - if (tmp != super) {
- - rb_raise(rb_eTypeError, "superclass mismatch for class %s",
- - rb_id2name(cname));
- - }
- - super = 0;
- - }
- - if (ruby_safe_level >= 4) {
- - rb_raise(rb_eSecurityError, "extending class prohibited");
- - }
- - }
- - else {
- - if (!super) super = rb_cObject;
- - klass = rb_define_class_id(cname, super);
- - rb_set_class_path(klass, cbase, rb_id2name(cname));
- - rb_const_set(cbase, cname, klass);
- - gen = Qtrue;
- - }
- - if (ruby_wrapper) {
- - rb_extend_object(klass, ruby_wrapper);
- - rb_include_module(klass, ruby_wrapper);
- - }
- - if (super && gen) {
- - rb_class_inherited(super, klass);
- - }
- - result = module_setup(klass, node);
- - }
- + result = eval_class(self,node);
- break;
-
- case NODE_MODULE:
- - {
- - VALUE module, cbase;
- - ID cname;
- -
- - if (NIL_P(ruby_cbase)) {
- - rb_raise(rb_eTypeError, "no outer class/module");
- - }
- - cbase = class_prefix(self, node->nd_cpath);
- - cname = node->nd_cpath->nd_mid;
- - if (rb_const_defined_at(cbase, cname)) {
- - module = rb_const_get_at(cbase, cname);
- - if (TYPE(module) != T_MODULE) {
- - rb_raise(rb_eTypeError, "%s is not a module",
- - rb_id2name(cname));
- - }
- - if (ruby_safe_level >= 4) {
- - rb_raise(rb_eSecurityError, "extending module prohibited");
- - }
- - }
- - else {
- - module = rb_define_module_id(cname);
- - rb_set_class_path(module, cbase, rb_id2name(cname));
- - rb_const_set(cbase, cname, module);
- - }
- - if (ruby_wrapper) {
- - rb_extend_object(module, ruby_wrapper);
- - rb_include_module(module, ruby_wrapper);
- - }
- -
- - result = module_setup(module, node);
- - }
- + result = eval_module(self,node);
- break;
-
- case NODE_SCLASS:
- - {
- - VALUE klass;
- -
- - result = rb_eval(self, node->nd_recv);
- - if (FIXNUM_P(result) || SYMBOL_P(result)) {
- - rb_raise(rb_eTypeError, "no virtual class for %s",
- - rb_obj_classname(result));
- - }
- - if (ruby_safe_level >= 4 && !OBJ_TAINTED(result))
- - rb_raise(rb_eSecurityError, "Insecure: can't extend object");
- - klass = rb_singleton_class(result);
- -
- - if (ruby_wrapper) {
- - rb_extend_object(klass, ruby_wrapper);
- - rb_include_module(klass, ruby_wrapper);
- - }
- -
- - result = module_setup(klass, node);
- - }
- + result = eval_sclass(self,node);
- break;
-
- case NODE_DEFINED:
- - {
- - char buf[20];
- - char *desc = is_defined(self, node->nd_head, buf);
- -
- - if (desc) result = rb_str_new2(desc);
- - else result = Qnil;
- - }
- + result = eval_defined(self,node);
- break;
-
- case NODE_NEWLINE:
- @@ -4151,25 +4297,19 @@ rb_eval(self, n)
- default:
- unknown_node(node);
- }
- - finish:
- - CHECK_INTS;
- - if (contnode) {
- - node = contnode;
- - contnode = 0;
- - goto again;
- - }
- - return result;
- + }
- + return result;
- }
-
- static VALUE
- module_setup(module, n)
- VALUE module;
- - NODE *n;
- + NODE * volatile n;
- {
- - NODE * volatile node = n->nd_body;
- + NODE *node = n->nd_body;
- int state;
- struct FRAME frame;
- - VALUE result = Qnil; /* OK */
- + VALUE result;
- TMP_PROTECT;
-
- frame = *ruby_frame;
- @@ -4560,16 +4700,16 @@ rb_iter_break()
- break_jump(Qnil);
- }
-
- -NORETURN(static void rb_longjmp _((int, VALUE)));
- +NORETURN(static void rb_longjmp _((volatile int, volatile VALUE)));
- static VALUE make_backtrace _((void));
-
- static void
- rb_longjmp(tag, mesg)
- - int tag;
- - VALUE mesg;
- + volatile int tag;
- + volatile VALUE mesg;
- {
- VALUE at;
- - rb_thread_t th = curr_thread;
- + volatile rb_thread_t th = curr_thread;
-
- if (rb_thread_set_raised(th)) {
- ruby_errinfo = exception_error;
- @@ -4658,7 +4798,8 @@ rb_exc_fatal(mesg)
- void
- rb_interrupt()
- {
- - rb_raise(rb_eInterrupt, "");
- + static const char fmt[1] = {'\0'};
- + rb_raise(rb_eInterrupt, fmt);
- }
-
- /*
- @@ -4814,7 +4955,7 @@ proc_jump_error(state, result)
- VALUE result;
- {
- char mesg[32];
- - char *statement;
- + const char *statement;
-
- switch (state) {
- case TAG_BREAK:
- @@ -4925,19 +5066,21 @@ rb_need_block()
-
- static VALUE
- rb_yield_0(val, self, klass, flags, avalue)
- - VALUE val, self, klass; /* OK */
- - int flags, avalue;
- + volatile VALUE val, self;
- + VALUE klass;
- + int flags;
- + volatile int avalue;
- {
- - NODE *node;
- + NODE *volatile node;
- volatile VALUE result = Qnil;
- volatile VALUE old_cref;
- volatile VALUE old_wrapper;
- struct BLOCK * volatile block;
- struct SCOPE * volatile old_scope;
- - int old_vmode;
- + volatile int old_vmode;
- struct FRAME frame;
- NODE *cnode = ruby_current_node;
- - int lambda = flags & YIELD_LAMBDA_CALL;
- + volatile int lambda = flags & YIELD_LAMBDA_CALL;
- int state;
-
- rb_need_block();
- @@ -5116,6 +5259,7 @@ rb_yield_0(val, self, klass, flags, avalue)
- tt->retval = result;
- JUMP_TAG(TAG_BREAK);
- }
- + if (tt->tag == PROT_THREAD) break;
- tt = tt->prev;
- }
- proc_jump_error(TAG_BREAK, result);
- @@ -5133,6 +5277,7 @@ VALUE
- rb_yield(val)
- VALUE val;
- {
- + wipeBeforeYield();
- return rb_yield_0(val, 0, 0, 0, Qfalse);
- }
-
- @@ -5195,6 +5340,7 @@ static VALUE
- rb_f_loop()
- {
- for (;;) {
- + wipeBeforeYield();
- rb_yield_0(Qundef, 0, 0, 0, Qfalse);
- CHECK_INTS;
- }
- @@ -5348,11 +5494,12 @@ assign(self, lhs, val, pcall)
-
- VALUE
- rb_iterate(it_proc, data1, bl_proc, data2)
- - VALUE (*it_proc) _((VALUE)), (*bl_proc)(ANYARGS);
- - VALUE data1, data2;
- + VALUE (* volatile it_proc) _((VALUE)), (*bl_proc)(ANYARGS);
- + volatile VALUE data1;
- + VALUE data2;
- {
- int state;
- - volatile VALUE retval = Qnil;
- + VALUE retval = Qnil;
- NODE *node = NEW_IFUNC(bl_proc, data2);
- VALUE self = ruby_top_self;
-
- @@ -5376,12 +5523,7 @@ rb_iterate(it_proc, data1, bl_proc, data2)
- POP_BLOCK();
- POP_TAG();
-
- - switch (state) {
- - case 0:
- - break;
- - default:
- - JUMP_TAG(state);
- - }
- + if (state) JUMP_TAG(state);
- return retval;
- }
-
- @@ -5413,16 +5555,17 @@ handle_rescue(self, node)
-
- VALUE
- #ifdef HAVE_STDARG_PROTOTYPES
- -rb_rescue2(VALUE (*b_proc)(ANYARGS), VALUE data1, VALUE (*r_proc)(ANYARGS), VALUE data2, ...)
- +rb_rescue2(VALUE (* volatile b_proc)(ANYARGS), volatile VALUE data1,
- + VALUE (* volatile r_proc)(ANYARGS), volatile VALUE data2, ...)
- #else
- rb_rescue2(b_proc, data1, r_proc, data2, va_alist)
- - VALUE (*b_proc)(ANYARGS), (*r_proc)(ANYARGS);
- - VALUE data1, data2;
- + VALUE (* volatile b_proc)(ANYARGS), (* volatile r_proc)(ANYARGS);
- + volatile VALUE data1, data2;
- va_dcl
- #endif
- {
- int state;
- - volatile VALUE result;
- + VALUE result;
- volatile VALUE e_info = ruby_errinfo;
- volatile int handle = Qfalse;
- VALUE eclass;
- @@ -5481,9 +5624,9 @@ VALUE
- rb_protect(proc, data, state)
- VALUE (*proc) _((VALUE));
- VALUE data;
- - int *state;
- + int * volatile state;
- {
- - VALUE result = Qnil; /* OK */
- + VALUE result;
- int status;
-
- PUSH_TAG(PROT_NONE);
- @@ -5496,22 +5639,18 @@ rb_protect(proc, data, state)
- if (state) {
- *state = status;
- }
- - if (status != 0) {
- - return Qnil;
- - }
- -
- - return result;
- + return status ? Qnil : result;
- }
-
- VALUE
- rb_ensure(b_proc, data1, e_proc, data2)
- VALUE (*b_proc)();
- VALUE data1;
- - VALUE (*e_proc)();
- - VALUE data2;
- + VALUE (* volatile e_proc)();
- + volatile VALUE data2;
- {
- int state;
- - volatile VALUE result = Qnil;
- + VALUE result;
- VALUE retval;
-
- PUSH_TAG(PROT_NONE);
- @@ -5519,7 +5658,7 @@ rb_ensure(b_proc, data1, e_proc, data2)
- result = (*b_proc)(data1);
- }
- POP_TAG();
- - retval = prot_tag ? prot_tag->retval : Qnil; /* save retval */
- + if (prot_tag) retval = prot_tag->retval; /* save retval */
- if (!thread_no_ensure()) {
- (*e_proc)(data2);
- }
- @@ -5533,7 +5672,7 @@ rb_with_disable_interrupt(proc, data)
- VALUE (*proc)();
- VALUE data;
- {
- - VALUE result = Qnil; /* OK */
- + VALUE result;
- int status;
-
- DEFER_INTS;
- @@ -5610,7 +5749,7 @@ rb_method_missing(argc, argv, obj)
- {
- ID id;
- VALUE exc = rb_eNoMethodError;
- - char *format = 0;
- + const char *format = 0;
- NODE *cnode = ruby_current_node;
-
- if (argc == 0 || !SYMBOL_P(argv[0])) {
- @@ -5785,16 +5924,16 @@ call_cfunc(func, recv, len, argc, argv)
-
- static VALUE
- rb_call0(klass, recv, id, oid, argc, argv, body, flags)
- - VALUE klass, recv;
- - ID id;
- + volatile VALUE klass, recv;
- + volatile ID id;
- ID oid;
- - int argc; /* OK */
- - VALUE *argv; /* OK */
- - NODE * volatile body;
- + int argc;
- + VALUE *argv;
- + NODE *volatile body;
- int flags;
- {
- NODE *b2; /* OK */
- - volatile VALUE result = Qnil;
- + VALUE result;
- int itr;
- static int tick;
- TMP_PROTECT;
- @@ -5911,7 +6050,7 @@ rb_call0(klass, recv, id, oid, argc, argv, body, flags)
- {
- int state;
- VALUE *local_vars; /* OK */
- - NODE *saved_cref = 0;
- + NODE * volatile saved_cref = 0;
-
- PUSH_SCOPE();
- if (body->nd_rval) {
- @@ -6054,7 +6193,6 @@ rb_call0(klass, recv, id, oid, argc, argv, body, flags)
-
- default:
- unknown_node(body);
- - break;
- }
- POP_FRAME();
- POP_ITER();
- @@ -6222,7 +6360,7 @@ rb_funcall_rescue(recv, mid, n, va_alist)
- va_dcl
- #endif
- {
- - VALUE result = Qnil; /* OK */
- + VALUE result;
- int status;
- va_list ar;
-
- @@ -6413,7 +6551,7 @@ rb_frame_last_func()
- static NODE*
- compile(src, file, line)
- VALUE src;
- - char *file;
- + const char *file;
- int line;
- {
- NODE *node;
- @@ -6432,12 +6570,13 @@ compile(src, file, line)
-
- static VALUE
- eval(self, src, scope, file, line)
- - VALUE self, src, scope;
- - char *file;
- + VALUE self, src;
- + volatile VALUE scope;
- + const char * volatile file;
- int line;
- {
- struct BLOCK *data = NULL;
- - volatile VALUE result = Qnil;
- + VALUE result;
- struct SCOPE * volatile old_scope;
- struct BLOCK * volatile old_block;
- struct RVarmap * volatile old_dyna_vars;
- @@ -6445,7 +6584,7 @@ eval(self, src, scope, file, line)
- int volatile old_vmode;
- volatile VALUE old_wrapper;
- struct FRAME frame;
- - NODE *nodesave = ruby_current_node;
- + NODE * volatile nodesave = ruby_current_node;
- volatile int iter = ruby_frame->iter;
- volatile int safe = ruby_safe_level;
- int state;
- @@ -6510,7 +6649,7 @@ eval(self, src, scope, file, line)
- compile_error(0);
- }
- if (!NIL_P(result)) ruby_errinfo = result;
- - result = eval_node(self, node);
- + result = eval_tree(self, node);
- }
- POP_TAG();
- POP_CLASS();
- @@ -6532,6 +6671,7 @@ eval(self, src, scope, file, line)
-
- scope_dup(ruby_scope);
- for (tag=prot_tag; tag; tag=tag->prev) {
- + if (tag->tag == PROT_THREAD) break;
- scope_dup(tag->scope);
- }
- for (vars = ruby_dyna_vars; vars; vars = vars->next) {
- @@ -6594,7 +6734,7 @@ rb_f_eval(argc, argv, self)
- VALUE self;
- {
- VALUE src, scope, vfile, vline;
- - char *file = "(eval)";
- + const char *file = "(eval)";
- int line = 1;
-
- rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
- @@ -6635,12 +6775,13 @@ rb_f_eval(argc, argv, self)
- static VALUE
- exec_under(func, under, cbase, args)
- VALUE (*func)();
- - VALUE under, cbase;
- + VALUE under;
- + volatile VALUE cbase;
- void *args;
- {
- - VALUE val = Qnil; /* OK */
- + VALUE val;
- int state;
- - int mode;
- + volatile int mode;
- struct FRAME *f = ruby_frame;
-
- PUSH_CLASS(under);
- @@ -6732,7 +6873,7 @@ specific_eval(argc, argv, klass, self)
- return yield_under(klass, self);
- }
- else {
- - char *file = "(eval)";
- + const char *file = "(eval)";
- int line = 1;
-
- if (argc == 0) {
- @@ -6846,9 +6987,9 @@ rb_load(fname, wrap)
- volatile int prohibit_int = rb_prohibit_interrupt;
- volatile ID last_func;
- volatile VALUE wrapper = ruby_wrapper;
- - volatile VALUE self = ruby_top_self;
- + VALUE self = ruby_top_self;
- NODE *volatile last_node;
- - NODE *saved_cref = ruby_cref;
- + NODE *volatile saved_cref = ruby_cref;
-
- if (wrap && ruby_safe_level >= 4) {
- StringValue(fname);
- @@ -6897,7 +7038,7 @@ rb_load(fname, wrap)
- ruby_current_node = 0;
- if (state == 0) {
- NODE *node;
- - volatile int critical;
- + int critical;
-
- DEFER_INTS;
- ruby_in_eval++;
- @@ -6909,7 +7050,7 @@ rb_load(fname, wrap)
- rb_thread_critical = critical;
- ALLOW_INTS;
- if (ruby_nerrs == 0) {
- - eval_node(self, node);
- + eval_tree(self, node);
- }
- }
- ruby_frame->last_func = last_func;
- @@ -6942,7 +7083,7 @@ void
- rb_load_protect(fname, wrap, state)
- VALUE fname;
- int wrap;
- - int *state;
- + int * volatile state;
- {
- int status;
-
- @@ -7231,7 +7372,7 @@ rb_require_safe(fname, safe)
- VALUE fname;
- int safe;
- {
- - VALUE result = Qnil;
- + VALUE result;
- volatile VALUE errinfo = ruby_errinfo;
- int state;
- struct {
- @@ -7282,7 +7423,8 @@ rb_require_safe(fname, safe)
- rb_provide_feature(feature);
- result = Qtrue;
- }
- - }
- + }else
- + result = Qnil;
- }
- POP_TAG();
- ruby_current_node = saved.node;
- @@ -7950,7 +8092,7 @@ rb_f_at_exit()
- void
- rb_exec_end_proc()
- {
- - struct end_proc_data *link, *tmp;
- + struct end_proc_data *tmp, *volatile link;
- int status;
- volatile int safe = ruby_safe_level;
-
- @@ -8595,8 +8737,9 @@ proc_invoke(proc, args, self, klass)
- int state;
- volatile int safe = ruby_safe_level;
- volatile VALUE old_wrapper = ruby_wrapper;
- - volatile int pcall, avalue = Qtrue;
- - volatile VALUE tmp = args;
- + volatile int pcall;
- + int avalue = Qtrue;
- + VALUE tmp = args;
-
- if (rb_block_given_p() && ruby_frame->last_func) {
- if (klass != ruby_frame->last_class)
- @@ -8814,7 +8957,7 @@ proc_to_s(self)
- {
- struct BLOCK *data;
- NODE *node;
- - char *cname = rb_obj_classname(self);
- + const char *cname = rb_obj_classname(self);
- const int w = (sizeof(VALUE) * CHAR_BIT) / 4;
- long len = strlen(cname)+6+w; /* 6:tags 16:addr */
- VALUE str;
- @@ -8895,15 +9038,15 @@ proc_binding(proc)
-
- static VALUE
- block_pass(self, node)
- - VALUE self;
- - NODE *node;
- + volatile VALUE self;
- + NODE *volatile node;
- {
- - VALUE proc = rb_eval(self, node->nd_body); /* OK */
- + volatile VALUE proc = rb_eval(self, node->nd_body);
- VALUE b;
- struct BLOCK * volatile old_block;
- struct BLOCK _block;
- struct BLOCK *data;
- - volatile VALUE result = Qnil;
- + VALUE result;
- int state;
- volatile int orphan;
- volatile int safe = ruby_safe_level;
- @@ -8950,20 +9093,24 @@ block_pass(self, node)
-
- PUSH_TAG(PROT_LOOP);
- state = EXEC_TAG();
- - if (state == 0) {
- - retry:
- + switch (state) {
- + case TAG_RETRY:
- + state = 0;
- + case 0:
- proc_set_safe_level(proc);
- if (safe > ruby_safe_level)
- ruby_safe_level = safe;
- result = rb_eval(self, node->nd_iter);
- - }
- - else if (state == TAG_BREAK && TAG_DST()) {
- - result = prot_tag->retval;
- - state = 0;
- - }
- - else if (state == TAG_RETRY) {
- - state = 0;
- - goto retry;
- + break;
- + case TAG_BREAK:
- + result = Qnil;
- + if (TAG_DST()) {
- + result = prot_tag->retval;
- + state = 0;
- + }
- + break;
- + default:
- + result = Qnil;
- }
- POP_TAG();
- POP_ITER();
- @@ -8980,7 +9127,6 @@ block_pass(self, node)
- default:
- JUMP_TAG(state);
- }
- -
- return result;
- }
-
- @@ -9239,7 +9385,7 @@ method_call(argc, argv, method)
- VALUE *argv;
- VALUE method;
- {
- - VALUE result = Qnil; /* OK */
- + VALUE result;
- struct METHOD *data;
- int safe;
-
- @@ -9473,7 +9619,7 @@ method_inspect(method)
- struct METHOD *data;
- VALUE str;
- const char *s;
- - char *sharp = "#";
- + const char *sharp = "#";
-
- Data_Get_Struct(method, struct METHOD, data);
- str = rb_str_buf_new2("#<");
- @@ -9538,12 +9684,9 @@ static VALUE
- bmcall(args, method)
- VALUE args, method;
- {
- - volatile VALUE a;
- - VALUE ret;
- -
- - a = svalue_to_avalue(args);
- - ret = method_call(RARRAY(a)->len, RARRAY(a)->ptr, method);
- - a = Qnil; /* prevent tail call */
- + VALUE a = svalue_to_avalue(args);
- + VALUE ret = method_call(RARRAY(a)->len, RARRAY(a)->ptr, method);
- + RB_GC_GUARD(a); /* ensure a is not GC'd during method_call */
- return ret;
- }
-
- @@ -9658,6 +9801,7 @@ rb_mod_define_method(argc, argv, mod)
- else {
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
- }
- + SET_METHOD_SOURCE();
- if (RDATA(body)->dmark == (RUBY_DATA_FUNC)bm_mark) {
- node = NEW_DMETHOD(method_unbind(body));
- }
- @@ -9689,6 +9833,112 @@ rb_mod_define_method(argc, argv, mod)
- return body;
- }
-
- +
- +#ifdef MBARI_API
- +/*
- + * call-seq:
- + * meth.__file__ => String
- + *
- + * returns the filename containing this method's definition
- + *
- + * raises ArgumentError if method has no associated ruby source code
- + *
- + * <i>Only available when MBARI_API extentions are enabled at build time</i>
- + */
- +
- +static VALUE
- +method_source_file_name(VALUE method)
- +{
- + struct METHOD *data;
- + NODE *node;
- +
- + Data_Get_Struct(method, struct METHOD, data);
- + if (node = data->body) {
- + const char *filename = node->nd_file;
- + if (filename)
- + return rb_str_new2(filename);
- + }
- + rb_raise(rb_eArgError, "native Method");
- +}
- +
- +/*
- + * call-seq:
- + * meth.__line__ => Fixnum
- + *
- + * returns the starting line number of this method
- + *
- + * raises ArgumentError if method has no associated ruby source code
- + *
- + * <i>Only available when MBARI_API extentions are enabled at build time</i>
- + */
- +
- +static VALUE
- +method_source_line(VALUE method)
- +{
- + struct METHOD *data;
- + NODE *node;
- +
- + Data_Get_Struct(method, struct METHOD, data);
- + if (node = data->body) {
- + int lineno = nd_line(node);
- + if (lineno)
- + return INT2FIX(nd_line(node));
- + }
- + rb_raise(rb_eArgError, "native Method");
- +}
- +
- +
- +/*
- + * call-seq:
- + * prc.__file__ => String
- + *
- + * returns the filename where this proc is defined
- + *
- + * raises ArgumentError if proc has no associated ruby source
- + *
- + * <i>Only available when MBARI_API extentions are enabled at build time</i>
- + */
- +
- +static VALUE
- +proc_source_file_name(VALUE block)
- +{
- + struct BLOCK *data;
- + const char *filename;
- + NODE *node;
- +
- + Data_Get_Struct(block, struct BLOCK, data);
- + if ((node = data->frame.node) || (node = data->body))
- + return rb_str_new2(node->nd_file);
- + rb_raise(rb_eArgError, "native Proc");
- +}
- +
- +
- +/*
- + * call-seq:
- + * prc.__line__ => Fixnum
- + *
- + * returns the starting line number of this proc
- + *
- + * raises ArgumentError if proc has no associated ruby source code
- + *
- + * <i>Only available when MBARI_API extentions are enabled at build time</i>
- + */
- +
- +static VALUE
- +proc_source_line(VALUE block)
- +{
- + struct BLOCK *data;
- + NODE *node;
- +
- + Data_Get_Struct(block, struct BLOCK, data);
- + if ((node = data->frame.node) || (node = data->body))
- + return INT2FIX( nd_line(node) );
- + rb_raise(rb_eArgError, "native Proc");
- +}
- +
- +#endif /* MBARI_API */
- +
- +
- /*
- * <code>Proc</code> objects are blocks of code that have been bound to
- * a set of local variables. Once bound, the code may be called in
- @@ -9768,6 +10018,15 @@ Init_Proc()
- rb_define_method(rb_cUnboundMethod, "to_s", method_inspect, 0);
- rb_define_method(rb_cUnboundMethod, "bind", umethod_bind, 1);
- rb_define_method(rb_cModule, "instance_method", rb_mod_method, 1);
- +
- +#ifdef MBARI_API
- + rb_define_method(rb_cUnboundMethod, "__file__", method_source_file_name, 0);
- + rb_define_method(rb_cUnboundMethod, "__line__", method_source_line, 0);
- + rb_define_method(rb_cProc, "__file__", proc_source_file_name, 0);
- + rb_define_method(rb_cProc, "__line__", proc_source_line, 0);
- + rb_define_method(rb_cMethod, "__file__", method_source_file_name, 0);
- + rb_define_method(rb_cMethod, "__line__", method_source_line, 0);
- +#endif
- }
-
- /*
- @@ -10084,14 +10343,19 @@ timeofday()
- return (double)tv.tv_sec + (double)tv.tv_usec * 1e-6;
- }
-
- -#define STACK(addr) (th->stk_pos<(VALUE*)(addr) && (VALUE*)(addr)<th->stk_pos+th->stk_len)
- -#define ADJ(addr) (void*)(STACK(addr)?(((VALUE*)(addr)-th->stk_pos)+th->stk_ptr):(VALUE*)(addr))
- +
- +#define ADJ(addr) \
- + if ((size_t)((void *)addr - stkBase) < stkSize) addr=(void *)addr + stkShift
- +
- static void
- thread_mark(th)
- rb_thread_t th;
- {
- struct FRAME *frame;
- struct BLOCK *block;
- + void *stkBase;
- + ptrdiff_t stkShift;
- + size_t stkSize;
-
- rb_gc_mark(th->result);
- rb_gc_mark(th->thread);
- @@ -10126,15 +10390,26 @@ thread_mark(th)
- }
- #endif
- }
- +
- + stkBase = (void *)th->stk_start;
- + stkSize = th->stk_len * sizeof(VALUE);
- +#if STACK_GROW_DIRECTION == 0
- + if (rb_gc_stack_grow_direction < 0)
- +#endif
- +#if STACK_GROW_DIRECTION <= 0
- + stkBase -= stkSize;
- +#endif
- + stkShift = (void *)th->stk_ptr - stkBase;
- +
- frame = th->frame;
- while (frame && frame != top_frame) {
- - frame = ADJ(frame);
- + ADJ(frame);
- rb_gc_mark_frame(frame);
- if (frame->tmp) {
- struct FRAME *tmp = frame->tmp;
-
- while (tmp && tmp != top_frame) {
- - tmp = ADJ(tmp);
- + ADJ(tmp);
- rb_gc_mark_frame(tmp);
- tmp = tmp->prev;
- }
- @@ -10143,7 +10418,7 @@ thread_mark(th)
- }
- block = th->block;
- while (block) {
- - block = ADJ(block);
- + ADJ(block);
- rb_gc_mark_frame(&block->frame);
- block = block->prev;
- }
- @@ -10202,16 +10477,57 @@ rb_gc_abort_threads()
- } END_FOREACH_FROM(main_thread, th);
- }
-
- -static void
- -thread_free(th)
- +
- +static inline void
- +stack_free(th)
- rb_thread_t th;
- {
- - if (th->stk_ptr) free(th->stk_ptr);
- - th->stk_ptr = 0;
- + if (th->stk_ptr) {
- + free(th->stk_ptr);
- + th->stk_ptr = 0;
- + }
- #ifdef __ia64
- - if (th->bstr_ptr) free(th->bstr_ptr);
- - th->bstr_ptr = 0;
- + if (th->bstr_ptr) {
- + free(th->bstr_ptr);
- + th->bstr_ptr = 0;
- + }
- #endif
- +}
- +
- +static void
- +rb_thread_die(th)
- + rb_thread_t th;
- +{
- + th->thgroup = 0;
- + th->status = THREAD_KILLED;
- + stack_free(th);
- +}
- +
- +#define THREAD_DATA(threadObject) ((rb_thread_t)RDATA(threadObject)->data)
- +
- +static inline void
- +cc_purge(cc)
- + rb_thread_t cc;
- +{ /* free continuation's stack if it has just died */
- + if (cc->thread != Qnil && THREAD_DATA(cc->thread)->status == THREAD_KILLED) {
- + cc->thread = Qnil;
- + rb_thread_die(cc); /* can't possibly activate this stack */
- + }
- +}
- +
- +static void
- +cc_mark(cc)
- + rb_thread_t cc;
- +{ /* mark this continuation's stack only if its parent thread is still alive */
- + cc_purge(cc);
- + thread_mark(cc);
- +}
- +
- +static void
- +thread_free(th)
- + rb_thread_t th;
- +{
- + stack_free(th);
- if (th->locals) st_free_table(th->locals);
- if (th->status != THREAD_KILLED) {
- if (th->prev) th->prev->next = th->next;
- @@ -10228,7 +10544,7 @@ rb_thread_check(data)
- rb_raise(rb_eTypeError, "wrong argument type %s (expected Thread)",
- rb_obj_classname(data));
- }
- - return (rb_thread_t)RDATA(data)->data;
- + return THREAD_DATA(data);
- }
-
- static VALUE rb_thread_raise _((int, VALUE*, rb_thread_t));
- @@ -10255,13 +10571,10 @@ static void
- rb_thread_save_context(th)
- rb_thread_t th;
- {
- - VALUE *pos;
- - int len;
- + size_t len;
- static VALUE tval;
-
- - len = ruby_stack_length(&pos);
- - th->stk_len = 0;
- - th->stk_pos = pos;
- + len = ruby_stack_length(th->stk_start,&th->stk_pos);
- if (len > th->stk_max) {
- VALUE *ptr = realloc(th->stk_ptr, sizeof(VALUE) * len);
- if (!ptr) rb_memerror();
- @@ -10323,6 +10636,9 @@ static int
- rb_thread_switch(n)
- int n;
- {
- +#if STACK_WIPE_SITES & 1
- + rb_gc_wipe_stack();
- +#endif
- rb_trap_immediate = (curr_thread->flags&0x100)?1:0;
- switch (n) {
- case 0:
- @@ -10359,15 +10675,14 @@ rb_thread_switch(n)
- return 1;
- }
-
- -#define THREAD_SAVE_CONTEXT(th) \
- - (rb_thread_switch((FLUSH_REGISTER_WINDOWS, ruby_setjmp(rb_thread_save_context(th), (th)->context))))
- +#define THREAD_SAVE_CONTEXT(th) (rb_thread_switch( wipeAfter(\
- + ruby_setjmp(rb_thread_save_context(th), (th)->context))))
-
- NORETURN(static void rb_thread_restore_context _((rb_thread_t,int)));
- -NORETURN(NOINLINE(static void rb_thread_restore_context_0(rb_thread_t,int,void*)));
- -NORETURN(NOINLINE(static void stack_extend(rb_thread_t, int, VALUE *)));
- +NORETURN(NOINLINE(static void rb_thread_restore_context_0(rb_thread_t,int)));
-
- static void
- -rb_thread_restore_context_0(rb_thread_t th, int exit, void *vp)
- +rb_thread_restore_context_0(rb_thread_t th, int exit)
- {
- static rb_thread_t tmp;
- static int ex;
- @@ -10424,9 +10739,9 @@ static volatile int C(f), C(g), C(h), C(i), C(j);
- static volatile int C(k), C(l), C(m), C(n), C(o);
- static volatile int C(p), C(q), C(r), C(s), C(t);
- int rb_dummy_false = 0;
- -NORETURN(NOINLINE(static void register_stack_extend(rb_thread_t, int, void *, VALUE *)));
- +NORETURN(NOINLINE(static void register_stack_extend(rb_thread_t, int, VALUE *)));
- static void
- -register_stack_extend(rb_thread_t th, int exit, void *vp, VALUE *curr_bsp)
- +register_stack_extend(rb_thread_t th, int exit, VALUE *curr_bsp)
- {
- if (rb_dummy_false) {
- /* use registers as much as possible */
- @@ -10440,52 +10755,69 @@ register_stack_extend(rb_thread_t th, int exit, void *vp, VALUE *curr_bsp)
- E(p) = E(q) = E(r) = E(s) = E(t) = 0;
- }
- if (curr_bsp < th->bstr_pos+th->bstr_len) {
- - register_stack_extend(th, exit, &exit, (VALUE*)rb_ia64_bsp());
- + register_stack_extend(th, exit, (VALUE*)rb_ia64_bsp());
- }
- - rb_thread_restore_context_0(th, exit, &exit);
- + rb_thread_restore_context_0(th, exit);
- }
- #undef C
- #undef E
- #endif
-
- -# if defined(_MSC_VER) && _MSC_VER >= 1300
- -__declspec(noinline) static void stack_extend(rb_thread_t, int, VALUE*);
- -# endif
- -static void
- -stack_extend(rb_thread_t th, int exit, VALUE *addr_in_prev_frame)
- -{
- -#define STACK_PAD_SIZE 1024
- - VALUE space[STACK_PAD_SIZE];
- -
- -#if STACK_GROW_DIRECTION < 0
- - if (addr_in_prev_frame > th->stk_pos) stack_extend(th, exit, &space[0]);
- -#elif STACK_GROW_DIRECTION > 0
- - if (addr_in_prev_frame < th->stk_pos + th->stk_len) stack_extend(th, exit, &space[STACK_PAD_SIZE-1]);
- -#else
- - if (addr_in_prev_frame < rb_gc_stack_start) {
- - /* Stack grows downward */
- - if (addr_in_prev_frame > th->stk_pos) stack_extend(th, exit, &space[0]);
- - }
- - else {
- - /* Stack grows upward */
- - if (addr_in_prev_frame < th->stk_pos + th->stk_len) stack_extend(th, exit, &space[STACK_PAD_SIZE-1]);
- - }
- -#endif
- -#ifdef __ia64
- - register_stack_extend(th, exit, space, (VALUE*)rb_ia64_bsp());
- -#else
- - rb_thread_restore_context_0(th, exit, space);
- -#endif
- -}
-
- static void
- rb_thread_restore_context(th, exit)
- rb_thread_t th;
- int exit;
- {
- + VALUE *pos = th->stk_start;
- +
- +#if HAVE_ALLOCA /* use alloca to grow stack in O(1) time */
- VALUE v;
- +
- + if (!th->stk_ptr) rb_bug("unsaved context");
- +# if !STACK_GROW_DIRECTION /* unknown at compile time */
- + if (rb_gc_stack_grow_direction < 0) {
- +# endif
- +# if STACK_GROW_DIRECTION <= 0
- + pos -= th->stk_len;
- + if (&v > pos)
- + (volatile void *)ALLOCA_N(VALUE, &v-pos);
- +# endif
- +# if !STACK_GROW_DIRECTION
- + }else
- +# endif
- +#if STACK_GROW_DIRECTION >= 0 /* stack grows upward */
- + if (&v < pos + th->stk_len)
- + (volatile void *)ALLOCA_N(VALUE, pos+th->stk_len - &v);
- +# endif
- +
- +#else /* recursive O(n/1024) if extending stack > 1024 VALUEs */
- +
- + volatile VALUE v[1023];
- +
- +# if !STACK_GROW_DIRECTION /* unknown at compile time */
- + if (rb_gc_stack_grow_direction < 0) {
- +# endif
- +# if STACK_GROW_DIRECTION <= 0
- + pos -= th->stk_len;
- + if (v > pos) rb_thread_restore_context(th, exit);
- +# endif
- +# if !STACK_GROW_DIRECTION
- + }else
- +# endif
- +# if STACK_GROW_DIRECTION >= 0 /* stack grows upward */
- + if (v < pos + th->stk_len) rb_thread_restore_context(th, exit);
- +# endif
- if (!th->stk_ptr) rb_bug("unsaved context");
- - stack_extend(th, exit, &v);
- +
- +#endif /* stack now extended */
- +
- +
- +#ifdef __ia64
- + register_stack_extend(th, exit, (VALUE*)rb_ia64_bsp());
- +#else
- + rb_thread_restore_context_0(th, exit);
- +#endif
- }
-
- static void
- @@ -10499,16 +10831,6 @@ rb_thread_ready(th)
- }
-
- static void
- -rb_thread_die(th)
- - rb_thread_t th;
- -{
- - th->thgroup = 0;
- - th->status = THREAD_KILLED;
- - if (th->stk_ptr) free(th->stk_ptr);
- - th->stk_ptr = 0;
- -}
- -
- -static void
- rb_thread_remove(th)
- rb_thread_t th;
- {
- @@ -11077,8 +11399,6 @@ rb_thread_select(max, read, write, except, timeout)
- return curr_thread->select_value;
- }
-
- -static int rb_thread_join _((rb_thread_t, double));
- -
- static int
- rb_thread_join(th, limit)
- rb_thread_t th;
- @@ -11171,7 +11491,7 @@ rb_thread_join_m(argc, argv, thread)
- {
- VALUE limit;
- double delay = DELAY_INFTY;
- - rb_thread_t th = rb_thread_check(thread);
- + rb_thread_t th = THREAD_DATA(thread);
-
- rb_scan_args(argc, argv, "01", &limit);
- if (!NIL_P(limit)) delay = rb_num2dbl(limit);
- @@ -11283,7 +11603,7 @@ VALUE
- rb_thread_wakeup_alive(thread)
- VALUE thread;
- {
- - rb_thread_t th = rb_thread_check(thread);
- + rb_thread_t th = THREAD_DATA(thread);
-
- if (th->status == THREAD_KILLED)
- return Qnil;
- @@ -11358,7 +11678,7 @@ VALUE
- rb_thread_kill(thread)
- VALUE thread;
- {
- - rb_thread_t th = rb_thread_check(thread);
- + rb_thread_t th = THREAD_DATA(thread);
-
- rb_kill_thread(th, 0);
- return thread;
- @@ -11382,7 +11702,7 @@ static VALUE
- rb_thread_kill_bang(thread)
- VALUE thread;
- {
- - rb_thread_t th = rb_thread_check(thread);
- + rb_thread_t th = THREAD_DATA(thread);
- rb_kill_thread(th, THREAD_NO_ENSURE);
- return thread;
- }
- @@ -11554,7 +11874,7 @@ static VALUE
- rb_thread_priority(thread)
- VALUE thread;
- {
- - return INT2NUM(rb_thread_check(thread)->priority);
- + return INT2NUM(THREAD_DATA(thread)->priority);
- }
-
-
- @@ -11588,7 +11908,7 @@ rb_thread_priority_set(thread, prio)
- rb_thread_t th;
-
- rb_secure(4);
- - th = rb_thread_check(thread);
- + th = THREAD_DATA(thread);
-
- th->priority = NUM2INT(prio);
- rb_thread_schedule();
- @@ -11614,7 +11934,7 @@ rb_thread_safe_level(thread)
- {
- rb_thread_t th;
-
- - th = rb_thread_check(thread);
- + th = THREAD_DATA(thread);
- if (th == curr_thread) {
- return INT2NUM(ruby_safe_level);
- }
- @@ -11691,7 +12011,7 @@ static VALUE
- rb_thread_abort_exc(thread)
- VALUE thread;
- {
- - return rb_thread_check(thread)->abort?Qtrue:Qfalse;
- + return THREAD_DATA(thread)->abort?Qtrue:Qfalse;
- }
-
-
- @@ -11709,7 +12029,7 @@ rb_thread_abort_exc_set(thread, val)
- VALUE thread, val;
- {
- rb_secure(4);
- - rb_thread_check(thread)->abort = RTEST(val);
- + THREAD_DATA(thread)->abort = RTEST(val);
- return val;
- }
-
- @@ -11718,7 +12038,7 @@ enum rb_thread_status
- rb_thread_status(thread)
- VALUE thread;
- {
- - rb_thread_t th = rb_thread_check(thread);
- + rb_thread_t th = THREAD_DATA(thread);
- return th->status;
- }
-
- @@ -11737,7 +12057,7 @@ VALUE
- rb_thread_group(thread)
- VALUE thread;
- {
- - VALUE group = rb_thread_check(thread)->thgroup;
- + VALUE group = THREAD_DATA(thread)->thgroup;
- if (!group) {
- group = Qnil;
- }
- @@ -11760,6 +12080,7 @@ rb_thread_group(thread)
- th->result = 0;\
- th->flags = 0;\
- \
- + th->stk_start = rb_gc_stack_start;\
- th->stk_ptr = 0;\
- th->stk_len = 0;\
- th->stk_max = 0;\
- @@ -11971,6 +12292,16 @@ rb_thread_start_0(fn, arg, th)
- "can't start a new thread (frozen ThreadGroup)");
- }
-
- +
- + th->stk_start = /* establish start of new thread's stack */
- +#if STACK_GROW_DIRECTION > 0
- + (VALUE *)ruby_frame;
- +#elif STACK_GROW_DIRECTION < 0
- + (VALUE *)(ruby_frame+1);
- +#else
- + (VALUE *)(ruby_frame+((VALUE *)(&arg)<rb_gc_stack_start))
- +#endif
- +
- if (!thread_init) {
- thread_init = 1;
- #if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE)
- @@ -12016,6 +12347,8 @@ rb_thread_start_0(fn, arg, th)
- PUSH_TAG(PROT_THREAD);
- if ((state = EXEC_TAG()) == 0) {
- if (THREAD_SAVE_CONTEXT(th) == 0) {
- + ruby_frame->prev = top_frame; /* hide parent thread's frames */
- + ruby_frame->tmp = 0;
- curr_thread = th;
- th->result = (*fn)(arg, th);
- }
- @@ -12127,9 +12460,6 @@ rb_thread_s_new(argc, argv, klass)
- VALUE klass;
- {
- rb_thread_t th = rb_thread_alloc(klass);
- - volatile VALUE *pos;
- -
- - pos = th->stk_pos;
- rb_obj_call_init(th->thread, argc, argv);
- if (th->stk_pos == 0) {
- rb_raise(rb_eThreadError, "uninitialized thread - check `%s#initialize'",
- @@ -12167,7 +12497,7 @@ rb_thread_initialize(thread, args)
- if (!rb_block_given_p()) {
- rb_raise(rb_eThreadError, "must be called with a block");
- }
- - th = rb_thread_check(thread);
- + th = THREAD_DATA(thread);
- if (th->stk_max) {
- NODE *node = th->node;
- if (!node) {
- @@ -12216,7 +12546,7 @@ static VALUE
- rb_thread_value(thread)
- VALUE thread;
- {
- - rb_thread_t th = rb_thread_check(thread);
- + rb_thread_t th = THREAD_DATA(thread);
-
- while (!rb_thread_join(th, DELAY_INFTY));
-
- @@ -12251,7 +12581,7 @@ static VALUE
- rb_thread_status_name(thread)
- VALUE thread;
- {
- - rb_thread_t th = rb_thread_check(thread);
- + rb_thread_t th = THREAD_DATA(thread);
-
- if (rb_thread_dead(th)) {
- if (!NIL_P(th->errinfo) && (th->flags & RAISED_EXCEPTION))
- @@ -12279,7 +12609,7 @@ VALUE
- rb_thread_alive_p(thread)
- VALUE thread;
- {
- - rb_thread_t th = rb_thread_check(thread);
- + rb_thread_t th = THREAD_DATA(thread);
-
- if (rb_thread_dead(th)) return Qfalse;
- return Qtrue;
- @@ -12302,7 +12632,7 @@ static VALUE
- rb_thread_stop_p(thread)
- VALUE thread;
- {
- - rb_thread_t th = rb_thread_check(thread);
- + rb_thread_t th = THREAD_DATA(thread);
-
- if (rb_thread_dead(th)) return Qtrue;
- if (th->status == THREAD_STOPPED) return Qtrue;
- @@ -12536,7 +12866,7 @@ rb_thread_raise_m(argc, argv, thread)
- VALUE *argv;
- VALUE thread;
- {
- - rb_thread_t th = rb_thread_check(thread);
- + rb_thread_t th = THREAD_DATA(thread);
-
- if (ruby_safe_level > th->safe) {
- rb_secure(4);
- @@ -12553,7 +12883,7 @@ rb_thread_local_aref(thread, id)
- rb_thread_t th;
- VALUE val;
-
- - th = rb_thread_check(thread);
- + th = THREAD_DATA(thread);
- if (ruby_safe_level >= 4 && th != curr_thread) {
- rb_raise(rb_eSecurityError, "Insecure: thread locals");
- }
- @@ -12599,7 +12929,7 @@ rb_thread_local_aset(thread, id, val)
- ID id;
- VALUE val;
- {
- - rb_thread_t th = rb_thread_check(thread);
- + rb_thread_t th = THREAD_DATA(thread);
-
- if (ruby_safe_level >= 4 && th != curr_thread) {
- rb_raise(rb_eSecurityError, "Insecure: can't modify thread locals");
- @@ -12652,7 +12982,7 @@ static VALUE
- rb_thread_key_p(thread, id)
- VALUE thread, id;
- {
- - rb_thread_t th = rb_thread_check(thread);
- + rb_thread_t th = THREAD_DATA(thread);
-
- if (!th->locals) return Qfalse;
- if (st_lookup(th->locals, rb_to_id(id), 0))
- @@ -12688,7 +13018,7 @@ static VALUE
- rb_thread_keys(thread)
- VALUE thread;
- {
- - rb_thread_t th = rb_thread_check(thread);
- + rb_thread_t th = THREAD_DATA(thread);
- VALUE ary = rb_ary_new();
-
- if (th->locals) {
- @@ -12709,7 +13039,7 @@ rb_thread_inspect(thread)
- VALUE thread;
- {
- char *cname = rb_obj_classname(thread);
- - rb_thread_t th = rb_thread_check(thread);
- + rb_thread_t th = THREAD_DATA(thread);
- const char *status = thread_status_name(th->status);
- VALUE str;
- size_t len = strlen(cname)+7+16+9+1;
- @@ -12789,6 +13119,32 @@ rb_thread_atfork()
-
- VALUE rb_cCont;
-
- +
- +static rb_thread_t prep4callcc(void)
- +{
- + rb_thread_t th;
- + struct tag *tag;
- + struct RVarmap *vars;
- +
- + THREAD_ALLOC(th);
- + /* must finish th initialization before any possible gc */
- + th->thread = curr_thread->thread; /* brent@mbari.org */
- + th->thgroup = cont_protect;
- +
- + scope_dup(ruby_scope);
- + for (tag=prot_tag; tag; tag=tag->prev) {
- + if (tag->tag == PROT_THREAD) break;
- + scope_dup(tag->scope);
- + }
- +
- + for (vars = ruby_dyna_vars; vars; vars = vars->next) {
- + if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
- + FL_SET(vars, DVAR_DONT_RECYCLE);
- + }
- + return th;
- +}
- +
- +
- /*
- * call-seq:
- * callcc {|cont| block } => obj
- @@ -12807,35 +13163,14 @@ static VALUE
- rb_callcc(self)
- VALUE self;
- {
- - volatile VALUE cont;
- - rb_thread_t th;
- - volatile rb_thread_t th_save;
- - struct tag *tag;
- - struct RVarmap *vars;
- -
- - THREAD_ALLOC(th);
- - cont = Data_Wrap_Struct(rb_cCont, thread_mark, thread_free, th);
- -
- - scope_dup(ruby_scope);
- - for (tag=prot_tag; tag; tag=tag->prev) {
- - scope_dup(tag->scope);
- - }
- - th->thread = curr_thread->thread;
- - th->thgroup = cont_protect;
- -
- - for (vars = ruby_dyna_vars; vars; vars = vars->next) {
- - if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
- - FL_SET(vars, DVAR_DONT_RECYCLE);
- - }
- - th_save = th;
- - if (THREAD_SAVE_CONTEXT(th)) {
- - return th_save->result;
- - }
- - else {
- - return rb_yield(cont);
- - }
- + volatile rb_thread_t th = prep4callcc();
- + return THREAD_SAVE_CONTEXT(th) ?
- + th->result
- + :
- + rb_yield(Data_Wrap_Struct(rb_cCont, cc_mark, thread_free, th));
- }
-
- +
- /*
- * call-seq:
- * cont.call(args, ...)
- @@ -12858,7 +13193,7 @@ rb_cont_call(argc, argv, cont)
- VALUE *argv;
- VALUE cont;
- {
- - rb_thread_t th = rb_thread_check(cont);
- + rb_thread_t th = THREAD_DATA(cont);
-
- if (th->thread != curr_thread->thread) {
- rb_raise(rb_eRuntimeError, "continuation called across threads");
- @@ -12882,6 +13217,34 @@ rb_cont_call(argc, argv, cont)
- return Qnil;
- }
-
- +
- +#ifdef MBARI_API
- +/*
- + * call-seq:
- + * cont.thread
- + *
- + * Returns the thread on which this continuation can be called
- + * or nil if that thread has died
- + *
- + * t = Thread.new {callcc{|c| $x=c}; sleep 5}
- + * sleep 1
- + * $x.thread #=> t
- + * sleep 10
- + * $x.thread #=> nil
- + *
- + * <i>Only available when MBARI_API extentions are enabled at build time</i>
- + */
- +static VALUE
- +rb_cont_thread(cont)
- + VALUE cont;
- +{
- + rb_thread_t th = THREAD_DATA(cont);
- + cc_purge(th);
- + return th->thread;
- +}
- +#endif
- +
- +
- struct thgroup {
- int enclosed;
- VALUE group;
- @@ -13034,10 +13397,6 @@ thgroup_add(group, thread)
-
- rb_secure(4);
- th = rb_thread_check(thread);
- - if (!th->next || !th->prev) {
- - rb_raise(rb_eTypeError, "wrong argument type %s (expected Thread)",
- - rb_obj_classname(thread));
- - }
-
- if (OBJ_FROZEN(group)) {
- rb_raise(rb_eThreadError, "can't move to the frozen thread group");
- @@ -13135,6 +13494,9 @@ Init_Thread()
- rb_undef_method(CLASS_OF(rb_cCont), "new");
- rb_define_method(rb_cCont, "call", rb_cont_call, -1);
- rb_define_method(rb_cCont, "[]", rb_cont_call, -1);
- +#ifdef MBARI_API
- + rb_define_method(rb_cCont, "thread", rb_cont_thread, 0);
- +#endif
- rb_define_global_function("callcc", rb_callcc, 0);
- rb_global_variable(&cont_protect);
-
- @@ -13186,14 +13548,15 @@ Init_Thread()
-
- static VALUE
- rb_f_catch(dmy, tag)
- - VALUE dmy, tag;
- + VALUE dmy;
- + volatile VALUE tag;
- {
- int state;
- - VALUE val = Qnil; /* OK */
- + VALUE val;
-
- tag = ID2SYM(rb_to_id(tag));
- PUSH_TAG(tag);
- - if ((state = EXEC_TAG()) == 0) {
- + if ((state = wipeAfter(EXEC_TAG_0())) == 0) {
- val = rb_yield_0(tag, 0, 0, 0, Qfalse);
- }
- else if (state == TAG_THROW && tag == prot_tag->dst) {
- @@ -13261,6 +13624,9 @@ rb_f_throw(argc, argv)
- if (!tt) {
- rb_name_error(SYM2ID(tag), "uncaught throw `%s'", rb_id2name(SYM2ID(tag)));
- }
- +#if STACK_WIPE_SITES & 0x800
- + rb_gc_update_stack_extent();
- +#endif
- rb_trap_restore_mask();
- JUMP_TAG(TAG_THROW);
- #ifndef __GNUC__
- diff --git a/gc.c b/gc.c
- index 33f035e..d89ee09 100644
- --- a/gc.c
- +++ b/gc.c
- @@ -22,10 +22,6 @@
- #include <setjmp.h>
- #include <sys/types.h>
-
- -#ifdef HAVE_SYS_TIME_H
- -#include <sys/time.h>
- -#endif
- -
- #ifdef HAVE_SYS_RESOURCE_H
- #include <sys/resource.h>
- #endif
- @@ -41,39 +37,150 @@ void rb_io_fptr_finalize _((struct OpenFile*));
- #define setjmp(env) _setjmp(env)
- #endif
-
- -/* Make alloca work the best possible way. */
- -#ifdef __GNUC__
- -# ifndef atarist
- -# ifndef alloca
- -# define alloca __builtin_alloca
- -# endif
- -# endif /* atarist */
- -#else
- -# ifdef HAVE_ALLOCA_H
- -# include <alloca.h>
- -# else
- -# ifndef _AIX
- -# ifndef alloca /* predefined by HP cc +Olibcalls */
- -void *alloca ();
- -# endif
- -# endif /* AIX */
- -# endif /* HAVE_ALLOCA_H */
- -#endif /* __GNUC__ */
- -
- #ifndef GC_MALLOC_LIMIT
- #if defined(MSDOS) || defined(__human68k__)
- #define GC_MALLOC_LIMIT 200000
- #else
- -#define GC_MALLOC_LIMIT 8000000
- +#define GC_MALLOC_LIMIT (2000000*sizeof(VALUE))
- #endif
- #endif
-
- -static unsigned long malloc_increase = 0;
- -static unsigned long malloc_limit = GC_MALLOC_LIMIT;
- +#ifndef GC_LEVEL_MAX /*maximum # of VALUEs on 'C' stack during GC*/
- +#define GC_LEVEL_MAX 8000
- +#endif
- +#ifndef GC_STACK_PAD
- +#define GC_STACK_PAD 200 /* extra padding VALUEs for GC stack */
- +#endif
- +#define GC_STACK_MAX (GC_LEVEL_MAX+GC_STACK_PAD)
- +
- +static VALUE *stack_limit, *gc_stack_limit;
- +
- +static size_t malloc_increase = 0;
- +static size_t malloc_limit = GC_MALLOC_LIMIT;
- +
- +#ifdef MBARI_API
- +/*
- + * call-seq:
- + * GC.limit => increase limit in bytes
- + *
- + * Get the # of bytes that may be allocated before triggering
- + * a mark and sweep by the garbarge collector to reclaim unused storage.
- + *
- + * <i>Only available when MBARI_API extentions are enabled at build time</i>
- + */
- +static VALUE gc_getlimit(VALUE mod)
- +{
- + return ULONG2NUM(malloc_limit);
- +}
- +
- +/*
- + * call-seq:
- + * GC.limit= => updated increase limit in bytes
- + *
- + * Set the # of bytes that may be allocated before triggering
- + * a mark and sweep by the garbarge collector to reclaim unused storage.
- + * Attempts to set the GC.limit= less than 0 will be ignored.
- + *
- + * GC.limit=5000000 #=> 5000000
- + * GC.limit #=> 5000000
- + * GC.limit=-50 #=> 5000000
- + * GC.limit=0 #=> 0 #functionally equivalent to GC.stress=true
- + *
- + * <i>Only available when MBARI_API extentions are enabled at build time</i>
- + */
- +static VALUE gc_setlimit(VALUE mod, VALUE newLimit)
- +{
- + long limit = NUM2LONG(newLimit);
- + rb_secure(2);
- + if (limit < 0) return gc_getlimit(mod);
- + malloc_limit = limit;
- + return newLimit;
- +}
- +
- +
- +/*
- + * call-seq:
- + * GC.growth
- + *
- + * Get # of bytes that have been allocated since the last mark & sweep
- + *
- + * <i>Only available when MBARI_API extentions are enabled at build time</i>
- + */
- +static VALUE gc_growth(VALUE mod)
- +{
- + return ULONG2NUM(malloc_increase);
- +}
- +
- +
- +/*
- + * call-seq:
- + * GC.exorcise
- + *
- + * Purge ghost references from recently freed stack space
- + *
- + * <i>Only available when MBARI_API extentions are enabled at build time</i>
- + */
- +static VALUE gc_exorcise(VALUE mod)
- +{
- + rb_gc_wipe_stack();
- + return Qnil;
- +}
- +
- +#else /* no api changes */
- +
- +static size_t unstressed_malloc_limit = GC_MALLOC_LIMIT;
- +
- +/*
- + * call-seq:
- + * GC.stress => true or false
- + *
- + * returns current status of GC stress mode.
- + *
- + * <i>Only available when MBARI_API extentions are disabled at build time</i>
- + */
- +
- +static VALUE
- +gc_stress_get(self)
- + VALUE self;
- +{
- + return malloc_limit ? Qfalse : Qtrue;
- +}
- +
- +/*
- + * call-seq:
- + * GC.stress = bool => bool
- + *
- + * updates GC stress mode.
- + *
- + * When GC.stress = true, GC is invoked for all GC opportunity:
- + * all memory and object allocation.
- + *
- + * Since it makes Ruby very slow, it is only for debugging.
- + *
- + * <i>Only available when MBARI_API extentions are enabled at build time</i>
- + */
- +
- +static VALUE
- +gc_stress_set(self, bool)
- + VALUE self, bool;
- +{
- + rb_secure(2);
- + if (!RTEST(bool))
- + malloc_limit = unstressed_malloc_limit;
- + else if (malloc_limit > 0) {
- + unstressed_malloc_limit = malloc_limit;
- + malloc_limit = 0;
- + }
- + return bool;
- +}
- +
- +#endif /* MBARI_API */
- +
- static void run_final();
- static VALUE nomem_error;
- static void garbage_collect();
-
- +
- NORETURN(void rb_exc_jump _((VALUE)));
-
- void
- @@ -93,6 +200,7 @@ rb_memerror()
- rb_exc_raise(nomem_error);
- }
-
- +
- void *
- ruby_xmalloc(size)
- long size;
- @@ -104,8 +212,9 @@ ruby_xmalloc(size)
- }
- if (size == 0) size = 1;
-
- - if ((malloc_increase+size) > malloc_limit) {
- + if ((malloc_increase+=size) > malloc_limit) {
- garbage_collect();
- + malloc_increase = size;
- }
- RUBY_CRITICAL(mem = malloc(size));
- if (!mem) {
- @@ -115,8 +224,9 @@ ruby_xmalloc(size)
- rb_memerror();
- }
- }
- - malloc_increase += size;
- -
- +#if STACK_WIPE_SITES & 0x100
- + rb_gc_update_stack_extent();
- +#endif
- return mem;
- }
-
- @@ -144,6 +254,10 @@ ruby_xrealloc(ptr, size)
- }
- if (!ptr) return xmalloc(size);
- if (size == 0) size = 1;
- + if ((malloc_increase+=size) > malloc_limit) {
- + garbage_collect();
- + malloc_increase = size;
- + }
- RUBY_CRITICAL(mem = realloc(ptr, size));
- if (!mem) {
- garbage_collect();
- @@ -152,8 +266,9 @@ ruby_xrealloc(ptr, size)
- rb_memerror();
- }
- }
- - malloc_increase += size;
- -
- +#if STACK_WIPE_SITES & 0x200
- + rb_gc_update_stack_extent();
- +#endif
- return mem;
- }
-
- @@ -393,7 +508,7 @@ rb_newobj()
- if (during_gc)
- rb_bug("object allocation during garbage collection phase");
-
- - if (!freelist) garbage_collect();
- + if (!malloc_limit || !freelist) garbage_collect();
-
- obj = (VALUE)freelist;
- freelist = freelist->as.free.next;
- @@ -428,6 +543,9 @@ VALUE *rb_gc_stack_start = 0;
- VALUE *rb_gc_register_stack_start = 0;
- #endif
-
- +VALUE *rb_gc_stack_end = (VALUE *)STACK_GROW_DIRECTION;
- +
- +
- #ifdef DJGPP
- /* set stack size (http://www.delorie.com/djgpp/v2faq/faq15_9.html) */
- unsigned int _stklen = 0x180000; /* 1.5 kB */
- @@ -445,77 +563,90 @@ static unsigned int STACK_LEVEL_MAX = 655300;
- # define STACK_LEVEL_MAX 655300
- #endif
-
- -#ifdef C_ALLOCA
- -# define SET_STACK_END VALUE stack_end; alloca(0);
- +#ifndef nativeAllocA
- + /* portable way to return an approximate stack pointer */
- +NOINLINE(VALUE *__sp(void));
- +VALUE *__sp(void) {
- + VALUE tos;
- + return &tos;
- +}
- +# define SET_STACK_END VALUE stack_end
- # define STACK_END (&stack_end)
- #else
- -# if defined(__GNUC__) && defined(USE_BUILTIN_FRAME_ADDRESS) && !defined(__ia64)
- -# if ( __GNUC__ == 3 && __GNUC_MINOR__ > 0 ) || __GNUC__ > 3
- -__attribute__ ((noinline))
- -# endif
- -static void
- -stack_end_address(VALUE **stack_end_p)
- -{
- - VALUE stack_end;
- - *stack_end_p = &stack_end;
- -}
- -# define SET_STACK_END VALUE *stack_end; stack_end_address(&stack_end)
- -# else
- -# define SET_STACK_END VALUE *stack_end = alloca(1)
- -# endif
- -# define STACK_END (stack_end)
- +# define SET_STACK_END ((void)0)
- +# define STACK_END __sp()
- #endif
- +
- #if STACK_GROW_DIRECTION < 0
- -# define STACK_LENGTH (rb_gc_stack_start - STACK_END)
- +# define STACK_LENGTH(start) ((start) - STACK_END)
- #elif STACK_GROW_DIRECTION > 0
- -# define STACK_LENGTH (STACK_END - rb_gc_stack_start + 1)
- +# define STACK_LENGTH(start) (STACK_END - (start) + 1)
- #else
- -# define STACK_LENGTH ((STACK_END < rb_gc_stack_start) ? rb_gc_stack_start - STACK_END\
- - : STACK_END - rb_gc_stack_start + 1)
- +# define STACK_LENGTH(start) ((STACK_END < (start)) ? \
- + (start) - STACK_END : STACK_END - (start) + 1)
- #endif
- +
- #if STACK_GROW_DIRECTION > 0
- -# define STACK_UPPER(x, a, b) a
- +# define STACK_UPPER(a, b) a
- #elif STACK_GROW_DIRECTION < 0
- -# define STACK_UPPER(x, a, b) b
- +# define STACK_UPPER(a, b) b
- #else
- -static int grow_direction;
- +int rb_gc_stack_grow_direction;
- static int
- stack_grow_direction(addr)
- VALUE *addr;
- {
- SET_STACK_END;
- -
- - if (STACK_END > addr) return grow_direction = 1;
- - return grow_direction = -1;
- + return rb_gc_stack_grow_direction = STACK_END > addr ? 1 : -1;
- }
- -# define stack_growup_p(x) ((grow_direction ? grow_direction : stack_grow_direction(x)) > 0)
- -# define STACK_UPPER(x, a, b) (stack_growup_p(x) ? a : b)
- +# define STACK_UPPER(a, b) (rb_gc_stack_grow_direction > 0 ? a : b)
- #endif
-
- -#define GC_WATER_MARK 512
- -
- -#define CHECK_STACK(ret) do {\
- - SET_STACK_END;\
- - (ret) = (STACK_LENGTH > STACK_LEVEL_MAX + GC_WATER_MARK);\
- -} while (0)
- -
- -int
- -ruby_stack_length(p)
- - VALUE **p;
- +size_t
- +ruby_stack_length(start, base)
- + VALUE *start, **base;
- {
- SET_STACK_END;
- - if (p) *p = STACK_UPPER(STACK_END, rb_gc_stack_start, STACK_END);
- - return STACK_LENGTH;
- + if (base) *base = STACK_UPPER(start, STACK_END);
- + return STACK_LENGTH(start);
- }
-
- int
- ruby_stack_check()
- {
- - int ret;
- + SET_STACK_END;
- + return __stack_past(stack_limit, STACK_END);
- +}
-
- - CHECK_STACK(ret);
- - return ret;
- +/*
- + Zero memory that was (recently) part of the stack, but is no longer.
- + Invoke when stack is deep to mark its extent and when it's shallow to wipe it.
- +*/
- +#if STACK_WIPE_METHOD != 4
- +#if STACK_WIPE_METHOD
- +void rb_gc_wipe_stack(void)
- +{
- + VALUE *stack_end = rb_gc_stack_end;
- + VALUE *sp = __sp();
- + rb_gc_stack_end = sp;
- +#if STACK_WIPE_METHOD == 1
- +#warning clearing of "ghost references" from the call stack has been disabled
- +#elif STACK_WIPE_METHOD == 2 /* alloca ghost stack before clearing it */
- + if (__stack_past(sp, stack_end)) {
- + size_t bytes = __stack_depth((char *)stack_end, (char *)sp);
- + STACK_UPPER(sp = nativeAllocA(bytes), stack_end = nativeAllocA(bytes));
- + __stack_zero(stack_end, sp);
- + }
- +#elif STACK_WIPE_METHOD == 3 /* clear unallocated area past stack pointer */
- + __stack_zero(stack_end, sp); /* will crash if compiler pushes a temp. here */
- +#else
- +#error unsupported method of clearing ghost references from the stack
- +#endif
- }
- +#else
- +#warning clearing of "ghost references" from the call stack completely disabled
- +#endif
- +#endif
-
- #define MARK_STACK_MAX 1024
- static VALUE mark_stack[MARK_STACK_MAX];
- @@ -530,7 +661,18 @@ init_mark_stack()
- }
-
- #define MARK_STACK_EMPTY (mark_stack_ptr == mark_stack)
- -
- +
- +static inline void
- +push_mark_stack(VALUE ptr)
- +{
- + if (!mark_stack_overflow) {
- + if (mark_stack_ptr - mark_stack < MARK_STACK_MAX)
- + *mark_stack_ptr++ = ptr;
- + else
- + mark_stack_overflow = 1;
- + }
- +}
- +
- static st_table *source_filenames;
-
- char *
- @@ -574,22 +716,22 @@ sweep_source_filename(key, value)
- }
- }
-
- -static void gc_mark _((VALUE ptr, int lev));
- -static void gc_mark_children _((VALUE ptr, int lev));
- +#define gc_mark(ptr) rb_gc_mark(ptr)
- +static void gc_mark_children _((VALUE ptr));
-
- static void
- gc_mark_all()
- {
- RVALUE *p, *pend;
- - int i;
- + struct heaps_slot *heap = heaps+heaps_used;
-
- init_mark_stack();
- - for (i = 0; i < heaps_used; i++) {
- - p = heaps[i].slot; pend = p + heaps[i].limit;
- + while (--heap >= heaps) {
- + p = heap->slot; pend = p + heap->limit;
- while (p < pend) {
- if ((p->as.basic.flags & FL_MARK) &&
- (p->as.basic.flags != FL_MARK)) {
- - gc_mark_children((VALUE)p, 0);
- + gc_mark_children((VALUE)p);
- }
- p++;
- }
- @@ -599,169 +741,129 @@ gc_mark_all()
- static void
- gc_mark_rest()
- {
- + size_t stackLen = mark_stack_ptr - mark_stack;
- +#ifdef nativeAllocA
- + VALUE *tmp_arry = nativeAllocA(stackLen*sizeof(VALUE));
- +#else
- VALUE tmp_arry[MARK_STACK_MAX];
- - VALUE *p;
- -
- - p = (mark_stack_ptr - mark_stack) + tmp_arry;
- - MEMCPY(tmp_arry, mark_stack, VALUE, MARK_STACK_MAX);
- +#endif
- + VALUE *p = tmp_arry + stackLen;
- +
- + MEMCPY(tmp_arry, mark_stack, VALUE, stackLen);
-
- init_mark_stack();
- - while(p != tmp_arry){
- - p--;
- - gc_mark_children(*p, 0);
- - }
- + while(--p >= tmp_arry) gc_mark_children(*p);
- }
-
- static inline int
- is_pointer_to_heap(ptr)
- void *ptr;
- {
- - register RVALUE *p = RANY(ptr);
- - register RVALUE *heap_org;
- - register long i;
- + RVALUE *p = RANY(ptr);
- + struct heaps_slot *heap;
-
- - if (p < lomem || p > himem) return Qfalse;
- - if ((VALUE)p % sizeof(RVALUE) != 0) return Qfalse;
- + if (p < lomem || p > himem || (VALUE)p % sizeof(RVALUE)) return Qfalse;
-
- /* check if p looks like a pointer */
- - for (i=0; i < heaps_used; i++) {
- - heap_org = heaps[i].slot;
- - if (heap_org <= p && p < heap_org + heaps[i].limit)
- - return Qtrue;
- - }
- + heap = heaps+heaps_used;
- + while (--heap >= heaps)
- + if (p >= heap->slot && p < heap->slot + heap->limit)
- + return Qtrue;
- return Qfalse;
- }
-
- static void
- mark_locations_array(x, n)
- - register VALUE *x;
- - register long n;
- + VALUE *x;
- + size_t n;
- {
- VALUE v;
- while (n--) {
- v = *x;
- if (is_pointer_to_heap((void *)v)) {
- - gc_mark(v, 0);
- + gc_mark(v);
- }
- x++;
- }
- }
-
- -void
- +inline void
- rb_gc_mark_locations(start, end)
- VALUE *start, *end;
- {
- - long n;
- -
- - n = end - start;
- - mark_locations_array(start,n);
- + mark_locations_array(start,end - start);
- }
-
- static int
- -mark_entry(key, value, lev)
- +mark_entry(key, value)
- ID key;
- VALUE value;
- - int lev;
- {
- - gc_mark(value, lev);
- + gc_mark(value);
- return ST_CONTINUE;
- }
-
- -static void
- -mark_tbl(tbl, lev)
- - st_table *tbl;
- - int lev;
- -{
- - if (!tbl) return;
- - st_foreach(tbl, mark_entry, lev);
- -}
- -
- void
- rb_mark_tbl(tbl)
- st_table *tbl;
- {
- - mark_tbl(tbl, 0);
- + if (!tbl) return;
- + st_foreach(tbl, mark_entry, 0);
- }
- +#define mark_tbl(tbl) rb_mark_tbl(tbl)
-
- static int
- -mark_keyvalue(key, value, lev)
- +mark_keyvalue(key, value)
- VALUE key;
- VALUE value;
- - int lev;
- {
- - gc_mark(key, lev);
- - gc_mark(value, lev);
- + gc_mark(key);
- + gc_mark(value);
- return ST_CONTINUE;
- }
-
- -static void
- -mark_hash(tbl, lev)
- - st_table *tbl;
- - int lev;
- -{
- - if (!tbl) return;
- - st_foreach(tbl, mark_keyvalue, lev);
- -}
- -
- void
- rb_mark_hash(tbl)
- st_table *tbl;
- {
- - mark_hash(tbl, 0);
- + if (!tbl) return;
- + st_foreach(tbl, mark_keyvalue, 0);
- }
- +#define mark_hash(tbl) rb_mark_hash(tbl)
-
- void
- rb_gc_mark_maybe(obj)
- VALUE obj;
- {
- if (is_pointer_to_heap((void *)obj)) {
- - gc_mark(obj, 0);
- + gc_mark(obj);
- }
- }
-
- -#define GC_LEVEL_MAX 250
- -
- -static void
- -gc_mark(ptr, lev)
- +void
- +rb_gc_mark(ptr)
- VALUE ptr;
- - int lev;
- {
- - register RVALUE *obj;
- -
- - obj = RANY(ptr);
- + RVALUE *obj = RANY(ptr);
- + SET_STACK_END;
- +
- if (rb_special_const_p(ptr)) return; /* special const not marked */
- if (obj->as.basic.flags == 0) return; /* free cell */
- if (obj->as.basic.flags & FL_MARK) return; /* already marked */
- obj->as.basic.flags |= FL_MARK;
-
- - if (lev > GC_LEVEL_MAX || (lev == 0 && ruby_stack_check())) {
- - if (!mark_stack_overflow) {
- - if (mark_stack_ptr - mark_stack < MARK_STACK_MAX) {
- - *mark_stack_ptr = ptr;
- - mark_stack_ptr++;
- - }
- - else {
- - mark_stack_overflow = 1;
- - }
- - }
- - return;
- + if (__stack_past(gc_stack_limit, STACK_END))
- + push_mark_stack(ptr);
- + else{
- + gc_mark_children(ptr);
- }
- - gc_mark_children(ptr, lev+1);
- -}
- -
- -void
- -rb_gc_mark(ptr)
- - VALUE ptr;
- -{
- - gc_mark(ptr, 0);
- }
-
- static void
- -gc_mark_children(ptr, lev)
- +gc_mark_children(ptr)
- VALUE ptr;
- - int lev;
- {
- - register RVALUE *obj = RANY(ptr);
- + RVALUE *obj = RANY(ptr);
-
- goto marking; /* skip */
-
- @@ -795,7 +897,7 @@ gc_mark_children(ptr, lev)
- case NODE_RESCUE:
- case NODE_RESBODY:
- case NODE_CLASS:
- - gc_mark((VALUE)obj->as.node.u2.node, lev);
- + gc_mark((VALUE)obj->as.node.u2.node);
- /* fall through */
- case NODE_BLOCK: /* 1,3 */
- case NODE_ARRAY:
- @@ -808,7 +910,7 @@ gc_mark_children(ptr, lev)
- case NODE_CALL:
- case NODE_DEFS:
- case NODE_OP_ASGN1:
- - gc_mark((VALUE)obj->as.node.u1.node, lev);
- + gc_mark((VALUE)obj->as.node.u1.node);
- /* fall through */
- case NODE_SUPER: /* 3 */
- case NODE_FCALL:
- @@ -835,7 +937,7 @@ gc_mark_children(ptr, lev)
- case NODE_ALIAS:
- case NODE_VALIAS:
- case NODE_ARGS:
- - gc_mark((VALUE)obj->as.node.u1.node, lev);
- + gc_mark((VALUE)obj->as.node.u1.node);
- /* fall through */
- case NODE_METHOD: /* 2 */
- case NODE_NOT:
- @@ -873,7 +975,7 @@ gc_mark_children(ptr, lev)
- case NODE_SCOPE: /* 2,3 */
- case NODE_BLOCK_PASS:
- case NODE_CDECL:
- - gc_mark((VALUE)obj->as.node.u3.node, lev);
- + gc_mark((VALUE)obj->as.node.u3.node);
- ptr = (VALUE)obj->as.node.u2.node;
- goto again;
-
- @@ -906,25 +1008,26 @@ gc_mark_children(ptr, lev)
-
- default: /* unlisted NODE */
- if (is_pointer_to_heap(obj->as.node.u1.node)) {
- - gc_mark((VALUE)obj->as.node.u1.node, lev);
- + gc_mark((VALUE)obj->as.node.u1.node);
- }
- if (is_pointer_to_heap(obj->as.node.u2.node)) {
- - gc_mark((VALUE)obj->as.node.u2.node, lev);
- + gc_mark((VALUE)obj->as.node.u2.node);
- }
- if (is_pointer_to_heap(obj->as.node.u3.node)) {
- - gc_mark((VALUE)obj->as.node.u3.node, lev);
- + ptr = (VALUE)obj->as.node.u3.node;
- + goto again;
- }
- }
- - return; /* no need to mark class. */
- + return; /* no need to mark class. */
- }
-
- - gc_mark(obj->as.basic.klass, lev);
- + gc_mark(obj->as.basic.klass);
- switch (obj->as.basic.flags & T_MASK) {
- case T_ICLASS:
- case T_CLASS:
- case T_MODULE:
- - mark_tbl(obj->as.klass.m_tbl, lev);
- - mark_tbl(obj->as.klass.iv_tbl, lev);
- + mark_tbl(obj->as.klass.m_tbl);
- + mark_tbl(obj->as.klass.iv_tbl);
- ptr = obj->as.klass.super;
- goto again;
-
- @@ -934,17 +1037,16 @@ gc_mark_children(ptr, lev)
- goto again;
- }
- else {
- - long i, len = obj->as.array.len;
- VALUE *ptr = obj->as.array.ptr;
- -
- - for (i=0; i < len; i++) {
- - gc_mark(*ptr++, lev);
- + VALUE *pend = ptr + obj->as.array.len;
- + while (ptr < pend) {
- + gc_mark(*ptr++);
- }
- }
- break;
-
- case T_HASH:
- - mark_hash(obj->as.hash.tbl, lev);
- + mark_hash(obj->as.hash.tbl);
- ptr = obj->as.hash.ifnone;
- goto again;
-
- @@ -961,7 +1063,7 @@ gc_mark_children(ptr, lev)
- break;
-
- case T_OBJECT:
- - mark_tbl(obj->as.object.iv_tbl, lev);
- + mark_tbl(obj->as.object.iv_tbl);
- break;
-
- case T_FILE:
- @@ -979,7 +1081,7 @@ gc_mark_children(ptr, lev)
- break;
-
- case T_VARMAP:
- - gc_mark(obj->as.varmap.val, lev);
- + gc_mark(obj->as.varmap.val);
- ptr = (VALUE)obj->as.varmap.next;
- goto again;
-
- @@ -989,19 +1091,17 @@ gc_mark_children(ptr, lev)
- VALUE *vars = &obj->as.scope.local_vars[-1];
-
- while (n--) {
- - gc_mark(*vars++, lev);
- + gc_mark(*vars++);
- }
- }
- break;
-
- case T_STRUCT:
- {
- - long len = obj->as.rstruct.len;
- VALUE *ptr = obj->as.rstruct.ptr;
- -
- - while (len--) {
- - gc_mark(*ptr++, lev);
- - }
- + VALUE *pend = ptr + obj->as.rstruct.len;
- + while (ptr < pend)
- + gc_mark(*ptr++);
- }
- break;
-
- @@ -1057,13 +1157,12 @@ gc_sweep()
- RVALUE *p, *pend, *final_list;
- int freed = 0;
- int i;
- - unsigned long live = 0;
- - unsigned long free_min = 0;
- + long free_min = 0;
-
- for (i = 0; i < heaps_used; i++) {
- free_min += heaps[i].limit;
- }
- - free_min = free_min * 0.2;
- + free_min /= 5;
- if (free_min < FREE_MIN)
- free_min = FREE_MIN;
-
- @@ -1074,7 +1173,7 @@ gc_sweep()
- p = heaps[i].slot; pend = p + heaps[i].limit;
- while (p < pend) {
- if (!(p->as.basic.flags&FL_MARK) && BUILTIN_TYPE(p) == T_NODE)
- - gc_mark((VALUE)p, 0);
- + gc_mark((VALUE)p);
- p++;
- }
- }
- @@ -1117,7 +1216,6 @@ gc_sweep()
- }
- else {
- RBASIC(p)->flags &= ~FL_MARK;
- - live++;
- }
- p++;
- }
- @@ -1134,10 +1232,6 @@ gc_sweep()
- freed += n;
- }
- }
- - if (malloc_increase > malloc_limit) {
- - malloc_limit += (malloc_increase - malloc_limit) * (double)live / (live + freed);
- - if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT;
- - }
- malloc_increase = 0;
- if (freed < free_min) {
- add_heap();
- @@ -1291,7 +1385,7 @@ void
- rb_gc_mark_frame(frame)
- struct FRAME *frame;
- {
- - gc_mark((VALUE)frame->node, 0);
- + gc_mark((VALUE)frame->node);
- }
-
- #ifdef __GNUC__
- @@ -1332,12 +1426,13 @@ int rb_setjmp (rb_jmp_buf);
- #endif /* __human68k__ or DJGPP */
- #endif /* __GNUC__ */
-
- +
- +
- static void
- -garbage_collect()
- +garbage_collect_0(VALUE *top_frame)
- {
- struct gc_list *list;
- - struct FRAME * volatile frame; /* gcc 2.7.2.3 -O2 bug?? */
- - jmp_buf save_regs_gc_mark;
- + struct FRAME * frame;
- SET_STACK_END;
-
- #ifdef HAVE_NATIVETHREAD
- @@ -1354,9 +1449,10 @@ garbage_collect()
- if (during_gc) return;
- during_gc++;
-
- + gc_stack_limit = __stack_grow(STACK_END, GC_LEVEL_MAX);
- init_mark_stack();
-
- - gc_mark((VALUE)ruby_current_node, 0);
- + gc_mark((VALUE)ruby_current_node);
-
- /* mark frame stack */
- for (frame = ruby_frame; frame; frame = frame->prev) {
- @@ -1369,25 +1465,21 @@ garbage_collect()
- }
- }
- }
- - gc_mark((VALUE)ruby_scope, 0);
- - gc_mark((VALUE)ruby_dyna_vars, 0);
- + gc_mark((VALUE)ruby_scope);
- + gc_mark((VALUE)ruby_dyna_vars);
- if (finalizer_table) {
- - mark_tbl(finalizer_table, 0);
- + mark_tbl(finalizer_table);
- }
-
- - FLUSH_REGISTER_WINDOWS;
- - /* This assumes that all registers are saved into the jmp_buf (and stack) */
- - setjmp(save_regs_gc_mark);
- - mark_locations_array((VALUE*)save_regs_gc_mark, sizeof(save_regs_gc_mark) / sizeof(VALUE *));
- #if STACK_GROW_DIRECTION < 0
- - rb_gc_mark_locations((VALUE*)STACK_END, rb_gc_stack_start);
- + rb_gc_mark_locations(top_frame, rb_curr_thread->stk_start);
- #elif STACK_GROW_DIRECTION > 0
- - rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1);
- + rb_gc_mark_locations(rb_curr_thread->stk_start, top_frame + 1);
- #else
- - if ((VALUE*)STACK_END < rb_gc_stack_start)
- - rb_gc_mark_locations((VALUE*)STACK_END, rb_gc_stack_start);
- + if (rb_gc_stack_grow_direction < 0)
- + rb_gc_mark_locations(top_frame, rb_curr_thread->stk_start);
- else
- - rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1);
- + rb_gc_mark_locations(rb_curr_thread->stk_start, top_frame + 1);
- #endif
- #ifdef __ia64
- /* mark backing store (flushed register window on the stack) */
- @@ -1396,7 +1488,7 @@ garbage_collect()
- #endif
- #if defined(__human68k__) || defined(__mc68000__)
- rb_gc_mark_locations((VALUE*)((char*)STACK_END + 2),
- - (VALUE*)((char*)rb_gc_stack_start + 2));
- + (VALUE*)((char*)rb_curr_thread->stk_start + 2));
- #endif
- rb_gc_mark_threads();
-
- @@ -1427,10 +1519,39 @@ garbage_collect()
- }
- rb_gc_abort_threads();
- } while (!MARK_STACK_EMPTY);
- -
- gc_sweep();
- }
-
- +static void
- +garbage_collect()
- +{
- + jmp_buf save_regs_gc_mark;
- + VALUE *top = __sp();
- + FLUSH_REGISTER_WINDOWS;
- + /* This assumes that all registers are saved into the jmp_buf (and stack) */
- + setjmp(save_regs_gc_mark);
- +
- +#if STACK_WIPE_SITES & 0x400
- +# ifdef nativeAllocA
- + if (__stack_past (top, stack_limit)) {
- + /* allocate a large frame to ensure app stack cannot grow into GC stack */
- + (volatile void*) nativeAllocA(__stack_depth((void*)stack_limit,(void*)top));
- + }
- + garbage_collect_0(top);
- +# else /* no native alloca() available */
- + garbage_collect_0(top);
- + {
- + VALUE *paddedLimit = __stack_grow(gc_stack_limit, GC_STACK_PAD);
- + if (__stack_past(rb_gc_stack_end, paddedLimit))
- + rb_gc_stack_end = paddedLimit;
- + }
- + rb_gc_wipe_stack(); /* wipe the whole stack area reserved for this gc */
- +# endif
- +#else
- + garbage_collect_0(top);
- +#endif
- +}
- +
- void
- rb_gc()
- {
- @@ -1455,6 +1576,7 @@ rb_gc_start()
- return Qnil;
- }
-
- +
- void
- ruby_set_stack_size(size)
- size_t size;
- @@ -1462,6 +1584,29 @@ ruby_set_stack_size(size)
- #ifndef STACK_LEVEL_MAX
- STACK_LEVEL_MAX = size / sizeof(VALUE);
- #endif
- + stack_limit = __stack_grow(rb_gc_stack_start, STACK_LEVEL_MAX-GC_STACK_MAX);
- +}
- +
- +static void
- +set_stack_size(void)
- +{
- +#ifdef HAVE_GETRLIMIT
- + struct rlimit rlim;
- + if (getrlimit(RLIMIT_STACK, &rlim) == 0) {
- + if (rlim.rlim_cur > 0 && rlim.rlim_cur != RLIM_INFINITY) {
- + size_t maxStackBytes = rlim.rlim_cur;
- + if (rlim.rlim_cur != maxStackBytes)
- + maxStackBytes = -1;
- + {
- + size_t space = maxStackBytes/5;
- + if (space > 1024*1024) space = 1024*1024;
- + ruby_set_stack_size(maxStackBytes - space);
- + return;
- + }
- + }
- + }
- +#endif
- + ruby_set_stack_size(STACK_LEVEL_MAX*sizeof(VALUE));
- }
-
- void
- @@ -1495,7 +1640,7 @@ Init_stack(addr)
- memset(&m, 0, sizeof(m));
- VirtualQuery(&m, &m, sizeof(m));
- rb_gc_stack_start =
- - STACK_UPPER((VALUE *)&m, (VALUE *)m.BaseAddress,
- + STACK_UPPER((VALUE *)m.BaseAddress,
- (VALUE *)((char *)m.BaseAddress + m.RegionSize) - 1);
- #elif defined(STACK_END_ADDRESS)
- {
- @@ -1504,28 +1649,16 @@ Init_stack(addr)
- }
- #else
- if (!addr) addr = (void *)&addr;
- - STACK_UPPER(&addr, addr, ++addr);
- + STACK_UPPER(addr, ++addr);
- if (rb_gc_stack_start) {
- - if (STACK_UPPER(&addr,
- - rb_gc_stack_start > addr,
- + if (STACK_UPPER(rb_gc_stack_start > addr,
- rb_gc_stack_start < addr))
- rb_gc_stack_start = addr;
- return;
- }
- rb_gc_stack_start = addr;
- #endif
- -#ifdef HAVE_GETRLIMIT
- - {
- - struct rlimit rlim;
- -
- - if (getrlimit(RLIMIT_STACK, &rlim) == 0) {
- - unsigned int space = rlim.rlim_cur/5;
- -
- - if (space > 1024*1024) space = 1024*1024;
- - STACK_LEVEL_MAX = (rlim.rlim_cur - space) / sizeof(VALUE);
- - }
- - }
- -#endif
- + set_stack_size();
- }
-
- void ruby_init_stack(VALUE *addr
- @@ -1535,8 +1668,7 @@ void ruby_init_stack(VALUE *addr
- )
- {
- if (!rb_gc_stack_start ||
- - STACK_UPPER(&addr,
- - rb_gc_stack_start > addr,
- + STACK_UPPER(rb_gc_stack_start > addr,
- rb_gc_stack_start < addr)) {
- rb_gc_stack_start = addr;
- }
- @@ -1547,16 +1679,7 @@ void ruby_init_stack(VALUE *addr
- }
- #endif
- #ifdef HAVE_GETRLIMIT
- - {
- - struct rlimit rlim;
- -
- - if (getrlimit(RLIMIT_STACK, &rlim) == 0) {
- - unsigned int space = rlim.rlim_cur/5;
- -
- - if (space > 1024*1024) space = 1024*1024;
- - STACK_LEVEL_MAX = (rlim.rlim_cur - space) / sizeof(VALUE);
- - }
- - }
- + set_stack_size();
- #elif defined _WIN32
- {
- MEMORY_BASIC_INFORMATION mi;
- @@ -1567,7 +1690,7 @@ void ruby_init_stack(VALUE *addr
- size = (char *)mi.BaseAddress - (char *)mi.AllocationBase;
- space = size / 5;
- if (space > 1024*1024) space = 1024*1024;
- - STACK_LEVEL_MAX = (size - space) / sizeof(VALUE);
- + ruby_set_stack_size(size - space);
- }
- }
- #endif
- @@ -2042,10 +2165,22 @@ Init_GC()
- {
- VALUE rb_mObSpace;
-
- +#if !STACK_GROW_DIRECTION
- + rb_gc_stack_end = stack_grow_direction(&rb_mObSpace);
- +#endif
- rb_mGC = rb_define_module("GC");
- rb_define_singleton_method(rb_mGC, "start", rb_gc_start, 0);
- rb_define_singleton_method(rb_mGC, "enable", rb_gc_enable, 0);
- rb_define_singleton_method(rb_mGC, "disable", rb_gc_disable, 0);
- +#ifdef MBARI_API
- + rb_define_singleton_method(rb_mGC, "limit", gc_getlimit, 0);
- + rb_define_singleton_method(rb_mGC, "limit=", gc_setlimit, 1);
- + rb_define_singleton_method(rb_mGC, "growth", gc_growth, 0);
- + rb_define_singleton_method(rb_mGC, "exorcise", gc_exorcise, 0);
- +#else
- + rb_define_singleton_method(rb_mGC, "stress", gc_stress_get, 0);
- + rb_define_singleton_method(rb_mGC, "stress=", gc_stress_set, 1);
- +#endif
- rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0);
-
- rb_mObSpace = rb_define_module("ObjectSpace");
- diff --git a/intern.h b/intern.h
- index b251a83..70a7656 100644
- --- a/intern.h
- +++ b/intern.h
- @@ -238,7 +238,7 @@ VALUE rb_file_directory_p _((VALUE,VALUE));
- /* gc.c */
- NORETURN(void rb_memerror __((void)));
- int ruby_stack_check _((void));
- -int ruby_stack_length _((VALUE**));
- +size_t ruby_stack_length _((VALUE *,VALUE**));
- int rb_during_gc _((void));
- char *rb_source_filename _((const char*));
- void rb_gc_mark_locations _((VALUE*, VALUE*));
- diff --git a/missing/alloca.c b/missing/alloca.c
- index 39697f1..3facdfe 100644
- --- a/missing/alloca.c
- +++ b/missing/alloca.c
- @@ -29,6 +29,7 @@
- static char SCCSid[] = "@(#)alloca.c 1.1"; /* for the "what" utility */
- #endif
-
- +#include <sys/types.h>
- #include "config.h"
- #ifdef emacs
- #ifdef static
- @@ -44,11 +45,7 @@ lose
- #endif /* static */
- #endif /* emacs */
-
- -#ifdef X3J11
- typedef void *pointer; /* generic pointer type */
- -#else
- -typedef char *pointer; /* generic pointer type */
- -#endif /* X3J11 */
-
- #define NULL 0 /* null pointer constant */
-
- @@ -140,8 +137,7 @@ typedef union hdr
- static header *last_alloca_header = NULL; /* -> last alloca header */
-
- pointer
- -alloca (size) /* returns pointer to storage */
- - unsigned size; /* # bytes to allocate */
- +alloca (size_t size) /* returns pointer to storage */
- {
- auto char probe; /* probes stack depth: */
- register char *depth = &probe;
- diff --git a/node.h b/node.h
- index 7d3f756..4a1db92 100644
- --- a/node.h
- +++ b/node.h
- @@ -409,15 +409,11 @@ struct rb_thread {
-
- VALUE result;
-
- - long stk_len;
- - long stk_max;
- - VALUE *stk_ptr;
- - VALUE *stk_pos;
- + size_t stk_len, stk_max;
- + VALUE *stk_ptr, *stk_pos, *stk_start;
- #ifdef __ia64
- - long bstr_len;
- - long bstr_max;
- - VALUE *bstr_ptr;
- - VALUE *bstr_pos;
- + size_t bstr_len, bstr_max;
- + VALUE *bstr_ptr, *bstr_pos;
- #endif
-
- struct FRAME *frame;
- diff --git a/re.c b/re.c
- index 5553d28..129b621 100644
- --- a/re.c
- +++ b/re.c
- @@ -1419,7 +1419,7 @@ VALUE
- rb_reg_regcomp(str)
- VALUE str;
- {
- - volatile VALUE save_str = str;
- + VALUE save_str = str;
- if (reg_cache && RREGEXP(reg_cache)->len == RSTRING(str)->len
- && case_cache == ruby_ignorecase
- && kcode_cache == reg_kcode
- @@ -1428,8 +1428,9 @@ rb_reg_regcomp(str)
-
- case_cache = ruby_ignorecase;
- kcode_cache = reg_kcode;
- - return reg_cache = rb_reg_new(RSTRING(str)->ptr, RSTRING(str)->len,
- - ruby_ignorecase);
- + reg_cache = rb_reg_new(RSTRING(str)->ptr, RSTRING(str)->len, ruby_ignorecase);
- + RB_GC_GUARD(save_str);
- + return reg_cache;
- }
-
- static int
- diff --git a/ruby.h b/ruby.h
- index 2701f0d..3cf4e19 100644
- --- a/ruby.h
- +++ b/ruby.h
- @@ -224,6 +224,8 @@ VALUE rb_ull2inum _((unsigned LONG_LONG));
-
- #define TYPE(x) rb_type((VALUE)(x))
-
- +#define RB_GC_GUARD(v) (*(volatile VALUE *)&(v))
- +
- void rb_check_type _((VALUE,int));
- #define Check_Type(v,t) rb_check_type((VALUE)(v),t)
-
- diff --git a/rubysig.h b/rubysig.h
- index f716824..fae0869 100644
- --- a/rubysig.h
- +++ b/rubysig.h
- @@ -12,8 +12,80 @@
-
- #ifndef SIG_H
- #define SIG_H
- +
- #include <errno.h>
-
- +#if defined __ppc__ || defined __powerpc__ || \
- + defined __ppc64__ || defined __powerpc64__
- +#define __anyPowerPC__ 1 /* for compatibility with older gcc versions */
- +#endif
- +
- +/* STACK_WIPE_SITES determines where attempts are made to exorcise
- + "ghost object refereces" from the stack and how the stack is cleared:
- +
- + 0x*001 --> wipe stack just after every thread_switch
- + 0x*002 --> wipe stack just after every EXEC_TAG()
- + 0x*004 --> wipe stack in CHECK_INTS
- + 0x*010 --> wipe stack in while & until loops
- + 0x*020 --> wipe stack before yield() in iterators and outside eval.c
- + 0x*040 --> wipe stack on catch and thread save context
- + 0x*100 --> update stack extent on each object allocation
- + 0x*200 --> update stack extent on each object reallocation
- + 0x*400 --> update stack extent during GC marking passes
- + 0x*800 --> update stack extent on each throw (use with 0x040)
- + 0x1000 --> use inline assembly code for x86, PowerPC, or ARM CPUs
- +
- + 0x0*** --> do not even call rb_wipe_stack()
- + 0x2*** --> call dummy rb_wipe_stack() (for debugging and profiling)
- + 0x4*** --> safe, portable stack clearing in memory allocated with alloca
- + 0x6*** --> use faster, but less safe stack clearing in unallocated stack
- + 0x8*** --> use faster, but less safe stack clearing (with inline code)
- +
- + for most effective gc use 0x*707
- + for fastest micro-benchmarking use 0x0000
- + 0x*770 prevents almost all memory leaks caused by ghost references
- + without adding much overhead for stack clearing.
- + Other good trade offs are 0x*270, 0x*703, 0x*303 or even 0x*03
- +
- + In general, you may lessen the default -mpreferred-stack-boundary
- + only if using less safe stack clearing (0x6***). Lessening the
- + stack alignment with portable stack clearing (0x4***) may fail to clear
- + all ghost references off the stack.
- +
- + When using 0x6*** or 0x8***, the compiler could insert
- + stack push(s) between reading the stack pointer and clearing
- + the ghost references. The register(s) pushed will be
- + cleared by the rb_gc_stack_wipe(), typically resulting in a segfault
- + or an interpreter hang.
- +
- + STACK_WIPE_SITES of 0x8770 works well compiled with gcc on most machines
- + using the recommended CFLAGS="-O2 -fno-stack-protector". However...
- + If it hangs or crashes for you, try changing STACK_WIPE_SITES to 0x4770
- + and please report your details. i.e. CFLAGS, compiler, version, CPU
- +
- + Note that it is redundant to wipe_stack in looping constructs if
- + also doing so in CHECK_INTS. It is also redundant to wipe_stack on
- + each thread_switch if wiping after every thread save context.
- +*/
- +#ifndef STACK_WIPE_SITES
- +# ifdef __x86_64__ /* deal with "red zone" by not inlining stack clearing */
- +# define STACK_WIPE_SITES 0x6770
- +# elif defined __anyPowerPC__ /* On any PowerPC, deal with... */
- +# define STACK_WIPE_SITES 0x7764 /* red zone & alloc(0) doesn't return sp */
- +# else
- +# define STACK_WIPE_SITES 0x8770 /*normal case, use 0x4770 if problems arise*/
- +# endif
- +#endif
- +
- +#if (STACK_WIPE_SITES & 0x14) == 0x14
- +#warning wiping stack in CHECK_INTS makes wiping in loops redundant
- +#endif
- +#if (STACK_WIPE_SITES & 0x41) == 0x41
- +#warning wiping stack after thread save makes wiping on thread_switch redundant
- +#endif
- +
- +#define STACK_WIPE_METHOD (STACK_WIPE_SITES>>13)
- +
- #ifdef _WIN32
- typedef LONG rb_atomic_t;
-
- @@ -79,9 +151,152 @@ void rb_trap_restore_mask _((void));
-
- RUBY_EXTERN int rb_thread_critical;
- void rb_thread_schedule _((void));
- +
- +RUBY_EXTERN VALUE *rb_gc_stack_end;
- +RUBY_EXTERN int rb_gc_stack_grow_direction; /* -1 for down or 1 for up */
- +
- +#if STACK_GROW_DIRECTION > 0
- +
- +/* clear stack space between end and sp (not including *sp) */
- +#define __stack_zero(end,sp) __stack_zero_up(end,sp)
- +
- +/* true if top has grown past limit, i.e. top deeper than limit */
- +#define __stack_past(limit,top) __stack_past_up(limit,top)
- +
- +/* depth of mid below stack top */
- +#define __stack_depth(top,mid) __stack_depth_up(top,mid)
- +
- +/* stack pointer top adjusted to include depth more items */
- +#define __stack_grow(top,depth) __stack_grow_up(top,depth)
- +
- +
- +#elif STACK_GROW_DIRECTION < 0
- +#define __stack_zero(end,sp) __stack_zero_down(end,sp)
- +#define __stack_past(limit,top) __stack_past_down(limit,top)
- +#define __stack_depth(top,mid) __stack_depth_down(top,mid)
- +#define __stack_grow(top,depth) __stack_grow_down(top,depth)
- +
- +#else /* limp along if stack direction can't be determined at compile time */
- +#define __stack_zero(end,sp) if (rb_gc_stack_grow_direction<0) \
- + __stack_zero_down(end,sp); else __stack_zero_up(end,sp);
- +#define __stack_past(limit,top) (rb_gc_stack_grow_direction<0 ? \
- + __stack_past_down(limit,top) : __stack_past_up(limit,top))
- +#define __stack_depth(top,mid) (rb_gc_stack_grow_direction<0 ? \
- + __stack_depth_down(top,mid) : __stack_depth_up(top,mid))
- +#define __stack_grow(top,depth) (rb_gc_stack_grow_direction<0 ? \
- + __stack_grow_down(top,depth) : __stack_grow_up(top,depth))
- +#endif
- +
- +#define __stack_zero_up(end,sp) while (end >= ++sp) *sp=0
- +#define __stack_past_up(limit,top) ((limit) < (top))
- +#define __stack_depth_up(top,mid) ((top) - (mid))
- +#define __stack_grow_up(top,depth) ((top)+(depth))
- +
- +#define __stack_zero_down(end,sp) while (end <= --sp) *sp=0
- +#define __stack_past_down(limit,top) ((limit) > (top))
- +#define __stack_depth_down(top,mid) ((mid) - (top))
- +#define __stack_grow_down(top,depth) ((top)-(depth))
- +
- +/* Make alloca work the best possible way. */
- +#ifdef __GNUC__
- +# ifndef atarist
- +# ifndef alloca
- +# define alloca __builtin_alloca
- +# endif
- +# endif /* atarist */
- +
- +# define nativeAllocA __builtin_alloca
- +
- +/* use assembly to get stack pointer quickly */
- +# if STACK_WIPE_SITES & 0x1000
- +# define __defspfn(asmb) \
- +static inline VALUE *__sp(void) __attribute__((always_inline)); \
- +static inline VALUE *__sp(void) \
- +{ \
- + VALUE *sp; asm(asmb); \
- + return sp; \
- +}
- +# ifdef __anyPowerPC__
- +__defspfn("addi %0, r1, 0": "=r"(sp))
- +# elif defined __i386__
- +__defspfn("movl %%esp, %0": "=r"(sp))
- +# elif defined __x86_64__
- +#warn ===> x86_64 inline assembler is known to crash -- change STACK_WIPE_SITES
- +__defspfn("movq %%rsp, %0": "=r"(sp))
- +# elif __arm__
- +__defspfn("mov %0, sp": "=r"(sp))
- +# else
- +# define __sp() ((VALUE *)__builtin_alloca(0))
- +# warning No assembly version of __sp() defined for this CPU.
- +# endif
- +# else
- +# define __sp() ((VALUE *)__builtin_alloca(0))
- +# endif
- +
- +#else // not GNUC
- +
- +# ifdef HAVE_ALLOCA_H
- +# include <alloca.h>
- +# else
- +# ifndef _AIX
- +# ifndef alloca /* predefined by HP cc +Olibcalls */
- +void *alloca ();
- +# endif
- +# endif /* AIX */
- +# endif /* HAVE_ALLOCA_H */
- +
- +# if STACK_WIPE_SITES & 0x1000
- +# warning No assembly versions of __sp() defined for this compiler.
- +# endif
- +# if HAVE_ALLOCA
- +# define __sp() ((VALUE *)alloca(0))
- +# define nativeAllocA alloca
- +# else
- +RUBY_EXTERN VALUE *__sp(void);
- +# if STACK_WIPE_SITES
- +# define STACK_WIPE_SITES 0
- +# warning Disabled Stack Wiping because there is no native alloca()
- +# endif
- +# endif
- +#endif /* __GNUC__ */
- +
- +
- +/*
- + Zero memory that was (recently) part of the stack, but is no longer.
- + Invoke when stack is deep to mark its extent and when it's shallow to wipe it.
- +*/
- +#if STACK_WIPE_METHOD == 0
- +#define rb_gc_wipe_stack() ((void)0)
- +#elif STACK_WIPE_METHOD == 4
- +#define rb_gc_wipe_stack() { \
- + VALUE *end = rb_gc_stack_end; \
- + VALUE *sp = __sp(); \
- + rb_gc_stack_end = sp; \
- + __stack_zero(end, sp); \
- +}
- +#else
- +RUBY_EXTERN void rb_gc_wipe_stack(void);
- +#endif
- +
- +/*
- + Update our record of maximum stack extent without zeroing unused stack
- +*/
- +#define rb_gc_update_stack_extent() do { \
- + VALUE *sp = __sp(); \
- + if __stack_past(rb_gc_stack_end, sp) rb_gc_stack_end = sp; \
- +} while(0)
- +
- +
- +#if STACK_WIPE_SITES & 4
- +# define CHECK_INTS_wipe_stack() rb_gc_wipe_stack()
- +#else
- +# define CHECK_INTS_wipe_stack() (void)0
- +#endif
- +
- #if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE)
- RUBY_EXTERN int rb_thread_pending;
- # define CHECK_INTS do {\
- + CHECK_INTS_wipe_stack(); \
- if (!(rb_prohibit_interrupt || rb_thread_critical)) {\
- if (rb_thread_pending) rb_thread_schedule();\
- if (rb_trap_pending) rb_trap_exec();\
- @@ -92,13 +307,14 @@ RUBY_EXTERN int rb_thread_pending;
- RUBY_EXTERN int rb_thread_tick;
- #define THREAD_TICK 500
- #define CHECK_INTS do {\
- + CHECK_INTS_wipe_stack(); \
- if (!(rb_prohibit_interrupt || rb_thread_critical)) {\
- if (rb_thread_tick-- <= 0) {\
- rb_thread_tick = THREAD_TICK;\
- rb_thread_schedule();\
- }\
- + if (rb_trap_pending) rb_trap_exec();\
- }\
- - if (rb_trap_pending) rb_trap_exec();\
- } while (0)
- #endif
-
- diff --git a/signal.c b/signal.c
- index b6cad9d..bc9deae 100644
- --- a/signal.c
- +++ b/signal.c
- @@ -389,6 +389,7 @@ rb_f_kill(argc, argv)
- rb_sys_fail(0);
- }
- }
- + CHECK_INTS; /* in case we killed ourselves */
- return INT2FIX(i-1);
- }
-
- diff --git a/test/ruby/suicide.rb b/test/ruby/suicide.rb
- index 2687ed0..c7a0a67 100644
- --- a/test/ruby/suicide.rb
- +++ b/test/ruby/suicide.rb
- @@ -1,2 +1,4 @@
- STDERR.reopen(STDOUT)
- -at_exit{Process.kill(:INT, $$)}
- +at_exit{Process.kill(:INT, $$); sleep 0}
- +# brent@mbari.org says
- +# sleep 0 avoids race between process termination and signal reception
- diff --git a/version.c b/version.c
- index b235673..dbc65b0 100644
- --- a/version.c
- +++ b/version.c
- @@ -14,23 +14,44 @@
- #include "version.h"
- #include <stdio.h>
-
- +#define PRINT(type) puts(ruby_##type)
- +#define MKSTR(type) rb_obj_freeze(rb_str_new(ruby_##type, sizeof(ruby_##type)-1))
- +
- const char ruby_version[] = RUBY_VERSION;
- const char ruby_release_date[] = RUBY_RELEASE_DATE;
- const char ruby_platform[] = RUBY_PLATFORM;
- const int ruby_patchlevel = RUBY_PATCHLEVEL;
- +const char *ruby_description;
- +const char *ruby_copyright;
-
- void
- Init_version()
- {
- - VALUE v = rb_obj_freeze(rb_str_new2(ruby_version));
- - VALUE d = rb_obj_freeze(rb_str_new2(ruby_release_date));
- - VALUE p = rb_obj_freeze(rb_str_new2(ruby_platform));
- + static char description[128];
- + static char copyright[128];
- + VALUE v = MKSTR(version);
- + VALUE d = MKSTR(release_date);
- + VALUE p = MKSTR(platform);
- + VALUE tmp;
-
- rb_define_global_const("RUBY_VERSION", v);
- rb_define_global_const("RUBY_RELEASE_DATE", d);
- rb_define_global_const("RUBY_PLATFORM", p);
- rb_define_global_const("RUBY_PATCHLEVEL", INT2FIX(RUBY_PATCHLEVEL));
-
- + snprintf(description, sizeof(description), "ruby %s (%s %s %d) [%s]",
- + RUBY_VERSION, RUBY_RELEASE_DATE, RUBY_RELEASE_STR,
- + RUBY_RELEASE_NUM, RUBY_PLATFORM);
- + ruby_description = description;
- + tmp = rb_obj_freeze(rb_str_new2(description));
- + rb_define_global_const("RUBY_DESCRIPTION", tmp);
- +
- + snprintf(copyright, sizeof(copyright), "ruby - Copyright (C) %d-%d %s",
- + RUBY_BIRTH_YEAR, RUBY_RELEASE_YEAR, RUBY_AUTHOR);
- + ruby_copyright = copyright;
- + tmp = rb_obj_freeze(rb_str_new2(copyright));
- + rb_define_global_const("RUBY_COPYRIGHT", tmp);
- +
- /* obsolete constants */
- rb_define_global_const("VERSION", v);
- rb_define_global_const("RELEASE_DATE", d);
- @@ -40,13 +61,13 @@ Init_version()
- void
- ruby_show_version()
- {
- - printf("ruby %s (%s patchlevel %d) [%s]\n", RUBY_VERSION, RUBY_RELEASE_DATE, RUBY_PATCHLEVEL, RUBY_PLATFORM);
- + PRINT(description);
- fflush(stdout);
- }
-
- void
- ruby_show_copyright()
- {
- - printf("ruby - Copyright (C) 1993-%d Yukihiro Matsumoto\n", RUBY_RELEASE_YEAR);
- + PRINT(copyright);
- exit(0);
- }
- diff --git a/version.h b/version.h
- index 88ddd67..fa36fa5 100644
- --- a/version.h
- +++ b/version.h
- @@ -1,21 +1,43 @@
- #define RUBY_VERSION "1.8.6"
- -#define RUBY_RELEASE_DATE "2008-08-11"
- +#define RUBY_RELEASE_DATE "2009-3-1"
- #define RUBY_VERSION_CODE 186
- -#define RUBY_RELEASE_CODE 20080811
- +#define RUBY_RELEASE_CODE 20090301
- #define RUBY_PATCHLEVEL 287
-
- #define RUBY_VERSION_MAJOR 1
- #define RUBY_VERSION_MINOR 8
- #define RUBY_VERSION_TEENY 6
- -#define RUBY_RELEASE_YEAR 2008
- -#define RUBY_RELEASE_MONTH 8
- -#define RUBY_RELEASE_DAY 11
- +#define RUBY_RELEASE_YEAR 2009
- +#define RUBY_RELEASE_MONTH 3
- +#define RUBY_RELEASE_DAY 1
-
- #ifdef RUBY_EXTERN
- RUBY_EXTERN const char ruby_version[];
- RUBY_EXTERN const char ruby_release_date[];
- RUBY_EXTERN const char ruby_platform[];
- RUBY_EXTERN const int ruby_patchlevel;
- +RUBY_EXTERN const char *ruby_description;
- +RUBY_EXTERN const char *ruby_copyright;
- #endif
-
- +#define RUBY_AUTHOR "Yukihiro Matsumoto"
- +#define RUBY_BIRTH_YEAR 1993
- +#define RUBY_BIRTH_MONTH 2
- +#define RUBY_BIRTH_DAY 24
- +
- +#include "rubysig.h"
- +
- +#define string_arg(s) #s
- +
- +#ifdef MBARI_API
- +#define _mbari_rev_ "MBARI"
- +#else
- +#define _mbari_rev_ "mbari"
- +#endif
- +
- +#define MBARI_RELEASE(wipe_sites) _mbari_rev_ " 8B/" string_arg(wipe_sites)
- +
- +#define RUBY_RELEASE_STR MBARI_RELEASE(STACK_WIPE_SITES) " on patchlevel"
- +#define RUBY_RELEASE_NUM RUBY_PATCHLEVEL
- +
-
- --- ruby-1.8.6-p287/configure 2008-08-10 17:38:35.000000000 -0700
- +++ ruby-1.8.6-mbari/configure 2009-02-26 22:43:03.000000000 -0800
- @@ -1352,6 +1352,7 @@
- is disabled or omitted entirely, then the package
- will be built only for the target platform
- --enable-frame-address use GCC __builtin_frame_address().
- + --enable-mbari-api enable API changes from the MBARI patches.
- --disable-largefile omit support for large files
- --enable-pthread use pthread library.
- --disable-fastthread do not use the fastthread mutex
- @@ -1364,6 +1365,7 @@
- --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
- --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
- --without-gcc never use gcc
- + --with-wipe-sites=MASK override default STACK_WIPES_SITES mask in rubysig.h
- --with-winsock2 link winsock2 (MinGW only)
- --with-libc_r link libc_r if possible (FreeBSD only)
- --with-default-kcode=CODE specify default value for \$KCODE (utf8|euc|sjis|none)
- @@ -2080,6 +2082,35 @@
- _ACEOF
-
- fi
- +# Check whether --enable-mbari-api was given.
- +if test "${enable_mbari_api+set}" = set; then
- + enableval=$enable_mbari_api; mbari_api=$enableval
- +fi
- +
- +if test "$mbari_api" = yes; then
- + cat >>confdefs.h <<\_ACEOF
- +#define MBARI_API 1
- +_ACEOF
- +
- +fi
- +
- +# Check whether --with-wipe-sites was given.
- +if test "${with_wipe_sites+set}" = set; then
- + withval=$with_wipe_sites; wipe_sites=$withval
- +fi
- +
- +if test "$wipe_sites" != ""; then
- + case $wipe_sites in
- + none|no) wipe_sites=0x0;;
- + yes) wipe_sites=;;
- + esac
- + if test -n "$wipe_sites"; then
- + cat >>confdefs.h <<_ACEOF
- +#define STACK_WIPE_SITES $wipe_sites
- +_ACEOF
- +
- + fi
- +fi
-
- test "$program_prefix" != NONE &&
- program_transform_name="s&^&$program_prefix&;$program_transform_name"
|