Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

BcelClassWeaver.java 132KB

pirms 21 gadiem
pirms 21 gadiem
pirms 21 gadiem
pirms 21 gadiem
pirms 21 gadiem
pirms 18 gadiem
pirms 21 gadiem
pirms 18 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 11 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 21 gadiem
pirms 21 gadiem
pirms 14 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 13 gadiem
pirms 14 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 12 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 18 gadiem
pirms 15 gadiem
pirms 18 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 18 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 18 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 18 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 13 gadiem
pirms 13 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 21 gadiem
pirms 13 gadiem
pirms 21 gadiem
pirms 13 gadiem
pirms 21 gadiem
pirms 14 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 21 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 21 gadiem
pirms 14 gadiem
pirms 21 gadiem
pirms 21 gadiem
pirms 14 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 21 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 21 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 21 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 21 gadiem
pirms 14 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 21 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 21 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 21 gadiem
pirms 21 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 21 gadiem
pirms 21 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 21 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 21 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 13 gadiem
pirms 13 gadiem
pirms 13 gadiem
pirms 13 gadiem
pirms 13 gadiem
pirms 13 gadiem
pirms 13 gadiem
pirms 13 gadiem
pirms 13 gadiem
pirms 13 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 11 gadiem
pirms 15 gadiem
pirms 11 gadiem
pirms 15 gadiem
pirms 11 gadiem
pirms 15 gadiem
pirms 11 gadiem
pirms 15 gadiem
pirms 11 gadiem
pirms 15 gadiem
pirms 11 gadiem
pirms 15 gadiem
pirms 11 gadiem
pirms 11 gadiem
pirms 11 gadiem
pirms 14 gadiem
pirms 11 gadiem
pirms 11 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 21 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 21 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 15 gadiem
pirms 14 gadiem
pirms 15 gadiem
pirms 21 gadiem
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://www.eclipse.org/legal/epl-v10.html
  8. *
  9. * Contributors:
  10. * PARC initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.weaver.bcel;
  13. import java.lang.reflect.Modifier;
  14. import java.util.ArrayList;
  15. import java.util.Collections;
  16. import java.util.Comparator;
  17. import java.util.HashMap;
  18. import java.util.HashSet;
  19. import java.util.Iterator;
  20. import java.util.LinkedHashSet;
  21. import java.util.List;
  22. import java.util.Map;
  23. import java.util.Objects;
  24. import java.util.Properties;
  25. import java.util.Set;
  26. import org.aspectj.apache.bcel.Constants;
  27. import org.aspectj.apache.bcel.classfile.BootstrapMethods;
  28. import org.aspectj.apache.bcel.classfile.ConstantPool;
  29. import org.aspectj.apache.bcel.classfile.Method;
  30. import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
  31. import org.aspectj.apache.bcel.generic.FieldGen;
  32. import org.aspectj.apache.bcel.generic.FieldInstruction;
  33. import org.aspectj.apache.bcel.generic.Instruction;
  34. import org.aspectj.apache.bcel.generic.InstructionBranch;
  35. import org.aspectj.apache.bcel.generic.InstructionCP;
  36. import org.aspectj.apache.bcel.generic.InstructionConstants;
  37. import org.aspectj.apache.bcel.generic.InstructionFactory;
  38. import org.aspectj.apache.bcel.generic.InstructionHandle;
  39. import org.aspectj.apache.bcel.generic.InstructionLV;
  40. import org.aspectj.apache.bcel.generic.InstructionList;
  41. import org.aspectj.apache.bcel.generic.InstructionSelect;
  42. import org.aspectj.apache.bcel.generic.InstructionTargeter;
  43. import org.aspectj.apache.bcel.generic.InvokeInstruction;
  44. import org.aspectj.apache.bcel.generic.LineNumberTag;
  45. import org.aspectj.apache.bcel.generic.LocalVariableTag;
  46. import org.aspectj.apache.bcel.generic.MULTIANEWARRAY;
  47. import org.aspectj.apache.bcel.generic.MethodGen;
  48. import org.aspectj.apache.bcel.generic.ObjectType;
  49. import org.aspectj.apache.bcel.generic.RET;
  50. import org.aspectj.apache.bcel.generic.Tag;
  51. import org.aspectj.apache.bcel.generic.Type;
  52. import org.aspectj.asm.AsmManager;
  53. import org.aspectj.bridge.IMessage;
  54. import org.aspectj.bridge.ISourceLocation;
  55. import org.aspectj.bridge.Message;
  56. import org.aspectj.bridge.MessageUtil;
  57. import org.aspectj.bridge.WeaveMessage;
  58. import org.aspectj.bridge.context.CompilationAndWeavingContext;
  59. import org.aspectj.bridge.context.ContextToken;
  60. import org.aspectj.util.PartialOrder;
  61. import org.aspectj.weaver.AjAttribute;
  62. import org.aspectj.weaver.AjcMemberMaker;
  63. import org.aspectj.weaver.AnnotationAJ;
  64. import org.aspectj.weaver.BCException;
  65. import org.aspectj.weaver.ConcreteTypeMunger;
  66. import org.aspectj.weaver.IClassWeaver;
  67. import org.aspectj.weaver.IntMap;
  68. import org.aspectj.weaver.Member;
  69. import org.aspectj.weaver.MissingResolvedTypeWithKnownSignature;
  70. import org.aspectj.weaver.NameMangler;
  71. import org.aspectj.weaver.NewConstructorTypeMunger;
  72. import org.aspectj.weaver.NewFieldTypeMunger;
  73. import org.aspectj.weaver.NewMethodTypeMunger;
  74. import org.aspectj.weaver.ResolvedMember;
  75. import org.aspectj.weaver.ResolvedMemberImpl;
  76. import org.aspectj.weaver.ResolvedType;
  77. import org.aspectj.weaver.ResolvedTypeMunger;
  78. import org.aspectj.weaver.Shadow;
  79. import org.aspectj.weaver.ShadowMunger;
  80. import org.aspectj.weaver.UnresolvedType;
  81. import org.aspectj.weaver.UnresolvedTypeVariableReferenceType;
  82. import org.aspectj.weaver.WeaverStateInfo;
  83. import org.aspectj.weaver.World;
  84. import org.aspectj.weaver.model.AsmRelationshipProvider;
  85. import org.aspectj.weaver.patterns.DeclareAnnotation;
  86. import org.aspectj.weaver.patterns.ExactTypePattern;
  87. import org.aspectj.weaver.tools.Trace;
  88. import org.aspectj.weaver.tools.TraceFactory;
  89. class BcelClassWeaver implements IClassWeaver {
  90. private static Trace trace = TraceFactory.getTraceFactory().getTrace(BcelClassWeaver.class);
  91. // Name of helper method generated by JDT compiler. Javac uses a separate inner class.
  92. private static final String SWITCH_TABLE_SYNTHETIC_METHOD_PREFIX = "$SWITCH_TABLE$";
  93. public static boolean weave(BcelWorld world, LazyClassGen clazz, List<ShadowMunger> shadowMungers,
  94. List<ConcreteTypeMunger> typeMungers, List<ConcreteTypeMunger> lateTypeMungers, boolean inReweavableMode) {
  95. BcelClassWeaver classWeaver = new BcelClassWeaver(world, clazz, shadowMungers, typeMungers, lateTypeMungers);
  96. classWeaver.setReweavableMode(inReweavableMode);
  97. boolean b = classWeaver.weave();
  98. return b;
  99. }
  100. // --------------------------------------------
  101. private final LazyClassGen clazz;
  102. private final List<ShadowMunger> shadowMungers;
  103. private final List<ConcreteTypeMunger> typeMungers;
  104. private final List<ConcreteTypeMunger> lateTypeMungers;
  105. private List<ShadowMunger>[] indexedShadowMungers;
  106. private boolean canMatchBodyShadows = false;
  107. private final BcelObjectType ty; // alias of clazz.getType()
  108. private final BcelWorld world; // alias of ty.getWorld()
  109. private final ConstantPool cpg; // alias of clazz.getConstantPoolGen()
  110. private final InstructionFactory fact; // alias of clazz.getFactory();
  111. private final List<LazyMethodGen> addedLazyMethodGens = new ArrayList<LazyMethodGen>();
  112. private final Set<ResolvedMember> addedDispatchTargets = new HashSet<ResolvedMember>();
  113. private boolean inReweavableMode = false;
  114. private List<IfaceInitList> addedSuperInitializersAsList = null;
  115. private final Map<ResolvedType, IfaceInitList> addedSuperInitializers = new HashMap<ResolvedType, IfaceInitList>();
  116. private final List<ConcreteTypeMunger> addedThisInitializers = new ArrayList<ConcreteTypeMunger>();
  117. private final List<ConcreteTypeMunger> addedClassInitializers = new ArrayList<ConcreteTypeMunger>();
  118. private final Map<ResolvedMember, ResolvedMember> mapToAnnotationHolder = new HashMap<ResolvedMember, ResolvedMember>();
  119. // private BcelShadow clinitShadow = null;
  120. /**
  121. * This holds the initialization and pre-initialization shadows for this class that were actually matched by mungers (if no
  122. * match, then we don't even create the shadows really).
  123. */
  124. private final List<BcelShadow> initializationShadows = new ArrayList<BcelShadow>();
  125. private BcelClassWeaver(BcelWorld world, LazyClassGen clazz, List<ShadowMunger> shadowMungers,
  126. List<ConcreteTypeMunger> typeMungers, List<ConcreteTypeMunger> lateTypeMungers) {
  127. super();
  128. this.world = world;
  129. this.clazz = clazz;
  130. this.shadowMungers = shadowMungers;
  131. this.typeMungers = typeMungers;
  132. this.lateTypeMungers = lateTypeMungers;
  133. this.ty = clazz.getBcelObjectType();
  134. this.cpg = clazz.getConstantPool();
  135. this.fact = clazz.getFactory();
  136. indexShadowMungers();
  137. initializeSuperInitializerMap(ty.getResolvedTypeX());
  138. if (!checkedXsetForLowLevelContextCapturing) {
  139. Properties p = world.getExtraConfiguration();
  140. if (p != null) {
  141. String s = p.getProperty(World.xsetCAPTURE_ALL_CONTEXT, "false");
  142. captureLowLevelContext = s.equalsIgnoreCase("true");
  143. if (captureLowLevelContext) {
  144. world.getMessageHandler().handleMessage(
  145. MessageUtil.info("[" + World.xsetCAPTURE_ALL_CONTEXT
  146. + "=true] Enabling collection of low level context for debug/crash messages"));
  147. }
  148. }
  149. checkedXsetForLowLevelContextCapturing = true;
  150. }
  151. }
  152. private boolean canMatch(Shadow.Kind kind) {
  153. return indexedShadowMungers[kind.getKey()] != null;
  154. }
  155. // private void fastMatchShadowMungers(List shadowMungers, ArrayList
  156. // mungers, Kind kind) {
  157. // FastMatchInfo info = new FastMatchInfo(clazz.getType(), kind);
  158. // for (Iterator i = shadowMungers.iterator(); i.hasNext();) {
  159. // ShadowMunger munger = (ShadowMunger) i.next();
  160. // FuzzyBoolean fb = munger.getPointcut().fastMatch(info);
  161. // WeaverMetrics.recordFastMatchResult(fb);// Could pass:
  162. // munger.getPointcut().toString()
  163. // if (fb.maybeTrue()) mungers.add(munger);
  164. // }
  165. // }
  166. private void initializeSuperInitializerMap(ResolvedType child) {
  167. ResolvedType[] superInterfaces = child.getDeclaredInterfaces();
  168. for (int i = 0, len = superInterfaces.length; i < len; i++) {
  169. if (ty.getResolvedTypeX().isTopmostImplementor(superInterfaces[i])) {
  170. if (addSuperInitializer(superInterfaces[i])) {
  171. initializeSuperInitializerMap(superInterfaces[i]);
  172. }
  173. }
  174. }
  175. }
  176. /**
  177. * Process the shadow mungers into array 'buckets', each bucket represents a shadow kind and contains a list of shadowmungers
  178. * that could potentially apply at that shadow kind.
  179. */
  180. private void indexShadowMungers() {
  181. // beware the annoying property that SHADOW_KINDS[i].getKey == (i+1) !
  182. indexedShadowMungers = new List[Shadow.MAX_SHADOW_KIND + 1];
  183. for (ShadowMunger shadowMunger : shadowMungers) {
  184. int couldMatchKinds = shadowMunger.getPointcut().couldMatchKinds();
  185. for (Shadow.Kind kind : Shadow.SHADOW_KINDS) {
  186. if (kind.isSet(couldMatchKinds)) {
  187. byte k = kind.getKey();
  188. if (indexedShadowMungers[k] == null) {
  189. indexedShadowMungers[k] = new ArrayList<ShadowMunger>();
  190. if (!kind.isEnclosingKind()) {
  191. canMatchBodyShadows = true;
  192. }
  193. }
  194. indexedShadowMungers[k].add(shadowMunger);
  195. }
  196. }
  197. }
  198. }
  199. private boolean addSuperInitializer(ResolvedType onType) {
  200. if (onType.isRawType() || onType.isParameterizedType()) {
  201. onType = onType.getGenericType();
  202. }
  203. IfaceInitList l = addedSuperInitializers.get(onType);
  204. if (l != null) {
  205. return false;
  206. }
  207. l = new IfaceInitList(onType);
  208. addedSuperInitializers.put(onType, l);
  209. return true;
  210. }
  211. public void addInitializer(ConcreteTypeMunger cm) {
  212. NewFieldTypeMunger m = (NewFieldTypeMunger) cm.getMunger();
  213. ResolvedType onType = m.getSignature().getDeclaringType().resolve(world);
  214. if (onType.isRawType()) {
  215. onType = onType.getGenericType();
  216. }
  217. if (Modifier.isStatic(m.getSignature().getModifiers())) {
  218. addedClassInitializers.add(cm);
  219. } else {
  220. if (onType == ty.getResolvedTypeX()) {
  221. addedThisInitializers.add(cm);
  222. } else {
  223. IfaceInitList l = addedSuperInitializers.get(onType);
  224. l.list.add(cm);
  225. }
  226. }
  227. }
  228. private static class IfaceInitList implements PartialOrder.PartialComparable {
  229. final ResolvedType onType;
  230. List<ConcreteTypeMunger> list = new ArrayList<ConcreteTypeMunger>();
  231. IfaceInitList(ResolvedType onType) {
  232. this.onType = onType;
  233. }
  234. public int compareTo(Object other) {
  235. IfaceInitList o = (IfaceInitList) other;
  236. if (onType.isAssignableFrom(o.onType)) {
  237. return +1;
  238. } else if (o.onType.isAssignableFrom(onType)) {
  239. return -1;
  240. } else {
  241. return 0;
  242. }
  243. }
  244. public int fallbackCompareTo(Object other) {
  245. return 0;
  246. }
  247. }
  248. // XXX this is being called, but the result doesn't seem to be being used
  249. public boolean addDispatchTarget(ResolvedMember m) {
  250. return addedDispatchTargets.add(m);
  251. }
  252. public void addLazyMethodGen(LazyMethodGen gen) {
  253. addedLazyMethodGens.add(gen);
  254. }
  255. public void addOrReplaceLazyMethodGen(LazyMethodGen mg) {
  256. if (alreadyDefined(clazz, mg)) {
  257. return;
  258. }
  259. for (Iterator<LazyMethodGen> i = addedLazyMethodGens.iterator(); i.hasNext();) {
  260. LazyMethodGen existing = i.next();
  261. if (signaturesMatch(mg, existing)) {
  262. if (existing.definingType == null) {
  263. // this means existing was introduced on the class itself
  264. return;
  265. } else if (mg.definingType.isAssignableFrom(existing.definingType)) {
  266. // existing is mg's subtype and dominates mg
  267. return;
  268. } else if (existing.definingType.isAssignableFrom(mg.definingType)) {
  269. // mg is existing's subtype and dominates existing
  270. i.remove();
  271. addedLazyMethodGens.add(mg);
  272. return;
  273. } else {
  274. throw new BCException("conflict between: " + mg + " and " + existing);
  275. }
  276. }
  277. }
  278. addedLazyMethodGens.add(mg);
  279. }
  280. private boolean alreadyDefined(LazyClassGen clazz, LazyMethodGen mg) {
  281. for (Iterator<LazyMethodGen> i = clazz.getMethodGens().iterator(); i.hasNext();) {
  282. LazyMethodGen existing = i.next();
  283. if (signaturesMatch(mg, existing)) {
  284. if (!mg.isAbstract() && existing.isAbstract()) {
  285. i.remove();
  286. return false;
  287. }
  288. return true;
  289. }
  290. }
  291. return false;
  292. }
  293. private boolean signaturesMatch(LazyMethodGen mg, LazyMethodGen existing) {
  294. return mg.getName().equals(existing.getName()) && mg.getSignature().equals(existing.getSignature());
  295. }
  296. protected static LazyMethodGen makeBridgeMethod(LazyClassGen gen, ResolvedMember member) {
  297. // remove abstract modifier
  298. int mods = member.getModifiers();
  299. if (Modifier.isAbstract(mods)) {
  300. mods = mods - Modifier.ABSTRACT;
  301. }
  302. LazyMethodGen ret = new LazyMethodGen(mods, BcelWorld.makeBcelType(member.getReturnType()), member.getName(),
  303. BcelWorld.makeBcelTypes(member.getParameterTypes()), UnresolvedType.getNames(member.getExceptions()), gen);
  304. // 43972 : Static crosscutting makes interfaces unusable for javac
  305. // ret.makeSynthetic();
  306. return ret;
  307. }
  308. /**
  309. * Create a single bridge method called 'theBridgeMethod' that bridges to 'whatToBridgeTo'
  310. */
  311. private static void createBridgeMethod(BcelWorld world, LazyMethodGen whatToBridgeToMethodGen, LazyClassGen clazz, ResolvedMember theBridgeMethod) {
  312. InstructionList body;
  313. InstructionFactory fact;
  314. int pos = 0;
  315. ResolvedMember whatToBridgeTo = whatToBridgeToMethodGen.getMemberView();
  316. if (whatToBridgeTo == null) {
  317. whatToBridgeTo = new ResolvedMemberImpl(Member.METHOD, whatToBridgeToMethodGen.getEnclosingClass().getType(),
  318. whatToBridgeToMethodGen.getAccessFlags(), whatToBridgeToMethodGen.getName(),
  319. whatToBridgeToMethodGen.getSignature());
  320. }
  321. // The bridge method in this type will have the same signature as the one in the supertype
  322. LazyMethodGen bridgeMethod = makeBridgeMethod(clazz, theBridgeMethod);
  323. int newflags = bridgeMethod.getAccessFlags() | Constants.ACC_BRIDGE | Constants.ACC_SYNTHETIC ;// BRIDGE = 0x00000040
  324. if ((newflags & 0x00000100) != 0) {
  325. newflags = newflags - 0x100;// NATIVE = 0x00000100 - need to clear it
  326. }
  327. bridgeMethod.setAccessFlags(newflags);
  328. Type returnType = BcelWorld.makeBcelType(theBridgeMethod.getReturnType());
  329. Type[] paramTypes = BcelWorld.makeBcelTypes(theBridgeMethod.getParameterTypes());
  330. Type[] newParamTypes = whatToBridgeToMethodGen.getArgumentTypes();
  331. body = bridgeMethod.getBody();
  332. fact = clazz.getFactory();
  333. if (!whatToBridgeToMethodGen.isStatic()) {
  334. body.append(InstructionFactory.createThis());
  335. pos++;
  336. }
  337. for (int i = 0, len = paramTypes.length; i < len; i++) {
  338. Type paramType = paramTypes[i];
  339. body.append(InstructionFactory.createLoad(paramType, pos));
  340. if (!newParamTypes[i].equals(paramTypes[i])) {
  341. if (world.forDEBUG_bridgingCode) {
  342. System.err.println("Bridging: Cast " + newParamTypes[i] + " from " + paramTypes[i]);
  343. }
  344. body.append(fact.createCast(paramTypes[i], newParamTypes[i]));
  345. }
  346. pos += paramType.getSize();
  347. }
  348. body.append(Utility.createInvoke(fact, world, whatToBridgeTo));
  349. body.append(InstructionFactory.createReturn(returnType));
  350. clazz.addMethodGen(bridgeMethod);
  351. }
  352. /**
  353. * Weave a class and indicate through the return value whether the class was modified.
  354. *
  355. * @return true if the class was modified
  356. */
  357. public boolean weave() {
  358. if (clazz.isWoven() && !clazz.isReweavable()) {
  359. if (world.getLint().nonReweavableTypeEncountered.isEnabled()) {
  360. world.getLint().nonReweavableTypeEncountered.signal(clazz.getType().getName(), ty.getSourceLocation());
  361. }
  362. // Integer uniqueID = new Integer(rm.hashCode() * deca.hashCode());
  363. // if (!reportedProblems.contains(uniqueID)) {
  364. // reportedProblems.add(uniqueID);
  365. // world.getLint().elementAlreadyAnnotated.signal(new String[] { rm.toString(),
  366. // world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.ALREADY_WOVEN, clazz.getType().getName()),
  367. // ty.getSourceLocation(), null);
  368. return false;
  369. }
  370. Set<String> aspectsAffectingType = null;
  371. if (inReweavableMode || clazz.getType().isAspect()) {
  372. aspectsAffectingType = new HashSet<String>();
  373. }
  374. boolean isChanged = false;
  375. // we want to "touch" all aspects
  376. if (clazz.getType().isAspect()) {
  377. isChanged = true;
  378. }
  379. WeaverStateInfo typeWeaverState = (world.isOverWeaving() ? getLazyClassGen().getType().getWeaverState() : null);
  380. // start by munging all typeMungers
  381. for (ConcreteTypeMunger o : typeMungers) {
  382. if (!(o instanceof BcelTypeMunger)) {
  383. // ???System.err.println("surprising: " + o);
  384. continue;
  385. }
  386. BcelTypeMunger munger = (BcelTypeMunger) o;
  387. if (typeWeaverState != null && typeWeaverState.isAspectAlreadyApplied(munger.getAspectType())) {
  388. continue;
  389. }
  390. boolean typeMungerAffectedType = munger.munge(this);
  391. if (typeMungerAffectedType) {
  392. isChanged = true;
  393. if (inReweavableMode || clazz.getType().isAspect()) {
  394. aspectsAffectingType.add(munger.getAspectType().getSignature());
  395. }
  396. }
  397. }
  398. // Weave special half type/half shadow mungers...
  399. isChanged = weaveDeclareAtMethodCtor(clazz) || isChanged;
  400. isChanged = weaveDeclareAtField(clazz) || isChanged;
  401. // XXX do major sort of stuff
  402. // sort according to: Major: type hierarchy
  403. // within each list: dominates
  404. // don't forget to sort addedThisInitialiers according to dominates
  405. addedSuperInitializersAsList = new ArrayList<IfaceInitList>(addedSuperInitializers.values());
  406. addedSuperInitializersAsList = PartialOrder.sort(addedSuperInitializersAsList);
  407. if (addedSuperInitializersAsList == null) {
  408. throw new BCException("circularity in inter-types");
  409. }
  410. // this will create a static initializer if there isn't one
  411. // this is in just as bad taste as NOPs
  412. LazyMethodGen staticInit = clazz.getStaticInitializer();
  413. staticInit.getBody().insert(genInitInstructions(addedClassInitializers, true));
  414. // now go through each method, and match against each method. This
  415. // sets up each method's {@link LazyMethodGen#matchedShadows} field,
  416. // and it also possibly adds to {@link #initializationShadows}.
  417. List<LazyMethodGen> methodGens = new ArrayList<LazyMethodGen>(clazz.getMethodGens());
  418. for (LazyMethodGen member : methodGens) {
  419. if (!member.hasBody()) {
  420. continue;
  421. }
  422. if (world.isJoinpointSynchronizationEnabled() && world.areSynchronizationPointcutsInUse()
  423. && member.getMethod().isSynchronized()) {
  424. transformSynchronizedMethod(member);
  425. }
  426. boolean shadowMungerMatched = match(member);
  427. if (shadowMungerMatched) {
  428. // For matching mungers, add their declaring aspects to the list
  429. // that affected this type
  430. if (inReweavableMode || clazz.getType().isAspect()) {
  431. aspectsAffectingType.addAll(findAspectsForMungers(member));
  432. }
  433. isChanged = true;
  434. }
  435. }
  436. // now we weave all but the initialization shadows
  437. for (LazyMethodGen methodGen : methodGens) {
  438. if (!methodGen.hasBody()) {
  439. continue;
  440. }
  441. implement(methodGen);
  442. }
  443. // if we matched any initialization shadows, we inline and weave
  444. if (!initializationShadows.isEmpty()) {
  445. // Repeat next step until nothing left to inline...cant go on
  446. // infinetly as compiler will have detected and reported
  447. // "Recursive constructor invocation"
  448. List<LazyMethodGen> recursiveCtors = new ArrayList<LazyMethodGen>();
  449. while (inlineSelfConstructors(methodGens, recursiveCtors)) {
  450. }
  451. positionAndImplement(initializationShadows);
  452. }
  453. // now proceed with late type mungers
  454. if (lateTypeMungers != null) {
  455. for (Iterator<ConcreteTypeMunger> i = lateTypeMungers.iterator(); i.hasNext();) {
  456. BcelTypeMunger munger = (BcelTypeMunger) i.next();
  457. if (munger.matches(clazz.getType())) {
  458. boolean typeMungerAffectedType = munger.munge(this);
  459. if (typeMungerAffectedType) {
  460. isChanged = true;
  461. if (inReweavableMode || clazz.getType().isAspect()) {
  462. aspectsAffectingType.add(munger.getAspectType().getSignature());
  463. }
  464. }
  465. }
  466. }
  467. }
  468. // FIXME AV - see #75442, for now this is not enough to fix the bug,
  469. // comment that out until we really fix it
  470. // // flush to save some memory
  471. // PerObjectInterfaceTypeMunger.unregisterFromAsAdvisedBy(clazz.getType()
  472. // );
  473. // finally, if we changed, we add in the introduced methods.
  474. if (isChanged) {
  475. clazz.getOrCreateWeaverStateInfo(inReweavableMode);
  476. weaveInAddedMethods();
  477. }
  478. if (inReweavableMode) {
  479. WeaverStateInfo wsi = clazz.getOrCreateWeaverStateInfo(true);
  480. wsi.addAspectsAffectingType(aspectsAffectingType);
  481. if (!world.isOverWeaving()) {
  482. wsi.setUnwovenClassFileData(ty.getJavaClass().getBytes());
  483. wsi.setReweavable(true);
  484. } else {
  485. wsi.markOverweavingInUse();
  486. }
  487. } else {
  488. clazz.getOrCreateWeaverStateInfo(false).setReweavable(false);
  489. }
  490. // tidyup, reduce ongoing memory usage of BcelMethods that hang around
  491. for (LazyMethodGen mg : methodGens) {
  492. BcelMethod method = mg.getMemberView();
  493. if (method != null) {
  494. method.wipeJoinpointSignatures();
  495. }
  496. }
  497. return isChanged;
  498. }
  499. // **************************** start of bridge method creation code
  500. // *****************
  501. // FIXASC tidy this lot up !!
  502. // FIXASC refactor into ResolvedType or even ResolvedMember?
  503. /**
  504. * Check if a particular method is overriding another - refactored into this helper so it can be used from multiple places.
  505. * @return method that is overriding if it
  506. */
  507. private static ResolvedMember isOverriding(ResolvedType typeToCheck, ResolvedMember methodThatMightBeGettingOverridden,
  508. String mname, String mrettype, int mmods, boolean inSamePackage, UnresolvedType[] methodParamsArray) {
  509. // Check if we can be an override...
  510. if (Modifier.isStatic(methodThatMightBeGettingOverridden.getModifiers())) {
  511. // we can't be overriding a static method
  512. return null;
  513. }
  514. if (Modifier.isPrivate(methodThatMightBeGettingOverridden.getModifiers())) {
  515. // we can't be overriding a private method
  516. return null;
  517. }
  518. if (!methodThatMightBeGettingOverridden.getName().equals(mname)) {
  519. // names do not match (this will also skip <init> and <clinit>)
  520. return null;
  521. }
  522. if (methodThatMightBeGettingOverridden.getParameterTypes().length != methodParamsArray.length) {
  523. // not the same number of parameters
  524. return null;
  525. }
  526. if (!isVisibilityOverride(mmods, methodThatMightBeGettingOverridden, inSamePackage)) {
  527. // not override from visibility point of view
  528. return null;
  529. }
  530. if (typeToCheck.getWorld().forDEBUG_bridgingCode) {
  531. System.err.println(" Bridging:seriously considering this might be getting overridden '"
  532. + methodThatMightBeGettingOverridden + "'");
  533. }
  534. World w = typeToCheck.getWorld();
  535. // Look at erasures of parameters (List<String> erased is List)
  536. boolean sameParams = true;
  537. for (int p = 0, max = methodThatMightBeGettingOverridden.getParameterTypes().length; p < max; p++) {
  538. UnresolvedType mtmbgoParameter = methodThatMightBeGettingOverridden.getParameterTypes()[p];
  539. UnresolvedType ptype = methodParamsArray[p];
  540. if (mtmbgoParameter.isTypeVariableReference()) {
  541. if (!mtmbgoParameter.resolve(w).isAssignableFrom(ptype.resolve(w))) {
  542. sameParams = false;
  543. }
  544. } else {
  545. // old condition:
  546. boolean b = !methodThatMightBeGettingOverridden.getParameterTypes()[p].getErasureSignature().equals(
  547. methodParamsArray[p].getErasureSignature());
  548. UnresolvedType parameterType = methodThatMightBeGettingOverridden.getParameterTypes()[p];
  549. // Collapse to first bound (isn't that the same as erasure!
  550. if (parameterType instanceof UnresolvedTypeVariableReferenceType) {
  551. parameterType = ((UnresolvedTypeVariableReferenceType) parameterType).getTypeVariable().getFirstBound();
  552. }
  553. if (b) { // !parameterType.resolve(w).equals(parameterType2.resolve(w))) {
  554. sameParams = false;
  555. }
  556. }
  557. //
  558. // if (!ut.getErasureSignature().equals(ut2.getErasureSignature()))
  559. // sameParams = false;
  560. }
  561. // If the 'typeToCheck' represents a parameterized type then the method
  562. // will be the parameterized form of the
  563. // generic method in the generic type. So if the method was 'void
  564. // m(List<T> lt, T t)' and the parameterized type here
  565. // is I<String> then the method we are looking at will be 'void
  566. // m(List<String> lt, String t)' which when erased
  567. // is 'void m(List lt,String t)' - so if the parameters *do* match then
  568. // there is a generic method we are
  569. // overriding
  570. // FIXASC Why bother with the return type? If it is incompatible then the code has other problems!
  571. if (sameParams) {
  572. if (typeToCheck.isParameterizedType()) {
  573. return methodThatMightBeGettingOverridden.getBackingGenericMember();
  574. } else if (!methodThatMightBeGettingOverridden.getReturnType().getErasureSignature().equals(mrettype)) {
  575. // addressing the wierd situation from bug 147801
  576. // just check whether these things are in the right relationship
  577. // for covariance...
  578. ResolvedType superReturn = typeToCheck.getWorld().resolve(
  579. UnresolvedType.forSignature(methodThatMightBeGettingOverridden.getReturnType().getErasureSignature()));
  580. ResolvedType subReturn = typeToCheck.getWorld().resolve(UnresolvedType.forSignature(mrettype));
  581. if (superReturn.isAssignableFrom(subReturn)) {
  582. return methodThatMightBeGettingOverridden;
  583. }
  584. // } else if (typeToCheck.isParameterizedType()) {
  585. // return methodThatMightBeGettingOverridden.getBackingGenericMember();
  586. } else {
  587. return methodThatMightBeGettingOverridden;
  588. }
  589. }
  590. return null;
  591. }
  592. /**
  593. * Looks at the visibility modifiers between two methods, and knows whether they are from classes in the same package, and
  594. * decides whether one overrides the other.
  595. *
  596. * @return true if there is an overrides rather than a 'hides' relationship
  597. */
  598. static boolean isVisibilityOverride(int methodMods, ResolvedMember inheritedMethod, boolean inSamePackage) {
  599. int inheritedModifiers = inheritedMethod.getModifiers();
  600. if (Modifier.isStatic(inheritedModifiers)) {
  601. return false;
  602. }
  603. if (methodMods == inheritedModifiers) {
  604. return true;
  605. }
  606. if (Modifier.isPrivate(inheritedModifiers)) {
  607. return false;
  608. }
  609. boolean isPackageVisible = !Modifier.isPrivate(inheritedModifiers) && !Modifier.isProtected(inheritedModifiers)
  610. && !Modifier.isPublic(inheritedModifiers);
  611. if (isPackageVisible && !inSamePackage) {
  612. return false;
  613. }
  614. return true;
  615. }
  616. /**
  617. * This method recurses up a specified type looking for a method that overrides the one passed in.
  618. *
  619. * @return the method being overridden or null if none is found
  620. */
  621. public static void checkForOverride(ResolvedType typeToCheck, String mname, String mparams, String mrettype,
  622. int mmods, String mpkg, UnresolvedType[] methodParamsArray, List<ResolvedMember> overriddenMethodsCollector) {
  623. if (typeToCheck == null) {
  624. return;
  625. }
  626. if (typeToCheck instanceof MissingResolvedTypeWithKnownSignature) {
  627. return; // we just can't tell !
  628. }
  629. if (typeToCheck.getWorld().forDEBUG_bridgingCode) {
  630. System.err.println(" Bridging:checking for override of " + mname + " in " + typeToCheck);
  631. }
  632. String packageName = typeToCheck.getPackageName();
  633. if (packageName == null) {
  634. packageName = "";
  635. }
  636. // used when looking at visibility rules
  637. boolean inSamePackage = packageName.equals(mpkg);
  638. ResolvedMember[] methods = typeToCheck.getDeclaredMethods();
  639. for (int ii = 0; ii < methods.length; ii++) {
  640. // the method we are going to check
  641. ResolvedMember methodThatMightBeGettingOverridden = methods[ii];
  642. ResolvedMember isOverriding = isOverriding(typeToCheck, methodThatMightBeGettingOverridden, mname, mrettype, mmods,
  643. inSamePackage, methodParamsArray);
  644. if (isOverriding != null) {
  645. overriddenMethodsCollector.add(isOverriding);
  646. }
  647. }
  648. // was: List l = typeToCheck.getInterTypeMungers();
  649. List<ConcreteTypeMunger> l = (typeToCheck.isRawType() ? typeToCheck.getGenericType().getInterTypeMungers() : typeToCheck
  650. .getInterTypeMungers());
  651. for (Iterator<ConcreteTypeMunger> iterator = l.iterator(); iterator.hasNext();) {
  652. ConcreteTypeMunger o = iterator.next();
  653. // FIXME asc if its not a BcelTypeMunger then its an
  654. // EclipseTypeMunger ... do I need to worry about that?
  655. if (o instanceof BcelTypeMunger) {
  656. BcelTypeMunger element = (BcelTypeMunger) o;
  657. if (element.getMunger() instanceof NewMethodTypeMunger) {
  658. if (typeToCheck.getWorld().forDEBUG_bridgingCode) {
  659. System.err.println("Possible ITD candidate " + element);
  660. }
  661. ResolvedMember aMethod = element.getSignature();
  662. ResolvedMember isOverriding = isOverriding(typeToCheck, aMethod, mname, mrettype, mmods, inSamePackage,
  663. methodParamsArray);
  664. if (isOverriding != null) {
  665. overriddenMethodsCollector.add(isOverriding);
  666. }
  667. }
  668. }
  669. }
  670. if (typeToCheck.equals(UnresolvedType.OBJECT)) {
  671. return;
  672. }
  673. ResolvedType superclass = typeToCheck.getSuperclass();
  674. checkForOverride(superclass, mname, mparams, mrettype, mmods, mpkg, methodParamsArray,overriddenMethodsCollector);
  675. ResolvedType[] interfaces = typeToCheck.getDeclaredInterfaces();
  676. for (int i = 0; i < interfaces.length; i++) {
  677. ResolvedType anInterface = interfaces[i];
  678. checkForOverride(anInterface, mname, mparams, mrettype, mmods, mpkg, methodParamsArray,overriddenMethodsCollector);
  679. }
  680. }
  681. /**
  682. * We need to determine if any methods in this type require bridge methods - this method should only be called if necessary to
  683. * do this calculation, i.e. we are on a 1.5 VM (where covariance/generics exist) and the type hierarchy for the specified class
  684. * has changed (via decp/itd).
  685. *
  686. * See pr108101
  687. */
  688. public static boolean calculateAnyRequiredBridgeMethods(BcelWorld world, LazyClassGen clazz) {
  689. world.ensureAdvancedConfigurationProcessed();
  690. if (!world.isInJava5Mode()) {
  691. return false; // just double check... the caller should have already
  692. }
  693. if (clazz.isInterface()) {
  694. return false; // dont bother if we are an interface
  695. }
  696. boolean didSomething = false; // set if we build any bridge methods
  697. // So what methods do we have right now in this class?
  698. List<LazyMethodGen> methods = clazz.getMethodGens();
  699. // Keep a set of all methods from this type - it'll help us to check if bridge methods
  700. // have already been created, we don't want to do it twice!
  701. Set<String> methodsSet = new HashSet<String>();
  702. for (int i = 0; i < methods.size(); i++) {
  703. LazyMethodGen aMethod = methods.get(i);
  704. StringBuilder sb = new StringBuilder(aMethod.getName());
  705. sb.append(aMethod.getSignature());
  706. methodsSet.add(sb.toString()); // e.g. "foo(Ljava/lang/String;)V"
  707. }
  708. // Now go through all the methods in this type
  709. for (int i = 0; i < methods.size(); i++) {
  710. // This is the local method that we *might* have to bridge to
  711. LazyMethodGen bridgeToCandidate = methods.get(i);
  712. if (bridgeToCandidate.isBridgeMethod()) {
  713. continue; // Doh!
  714. }
  715. String name = bridgeToCandidate.getName();
  716. String psig = bridgeToCandidate.getParameterSignature();
  717. String rsig = bridgeToCandidate.getReturnType().getSignature();
  718. // if (bridgeToCandidate.isAbstract()) continue;
  719. if (bridgeToCandidate.isStatic()) {
  720. continue; // ignore static methods
  721. }
  722. if (name.endsWith("init>")) {
  723. continue; // Skip constructors and static initializers
  724. }
  725. if (world.forDEBUG_bridgingCode) {
  726. System.err.println("Bridging: Determining if we have to bridge to " + clazz.getName() + "." + name + "" + bridgeToCandidate.getSignature());
  727. }
  728. // Let's take a look at the superclass
  729. ResolvedType theSuperclass = clazz.getSuperClass();
  730. if (world.forDEBUG_bridgingCode) {
  731. System.err.println("Bridging: Checking supertype " + theSuperclass);
  732. }
  733. String pkgName = clazz.getPackageName();
  734. UnresolvedType[] bm = BcelWorld.fromBcel(bridgeToCandidate.getArgumentTypes());
  735. List<ResolvedMember> overriddenMethodsCollector = new ArrayList<ResolvedMember>();
  736. checkForOverride(theSuperclass, name, psig, rsig, bridgeToCandidate.getAccessFlags(), pkgName, bm, overriddenMethodsCollector);
  737. if (overriddenMethodsCollector.size() != 0) {
  738. for (ResolvedMember overriddenMethod: overriddenMethodsCollector) {
  739. String key = new StringBuilder(overriddenMethod.getName()).append(overriddenMethod.getSignatureErased()).toString(); // pr237419
  740. boolean alreadyHaveABridgeMethod = methodsSet.contains(key);
  741. if (!alreadyHaveABridgeMethod) {
  742. if (world.forDEBUG_bridgingCode) {
  743. System.err.println("Bridging:bridging to '" + overriddenMethod + "'");
  744. }
  745. createBridgeMethod(world, bridgeToCandidate, clazz, overriddenMethod);
  746. methodsSet.add(key);
  747. didSomething = true;
  748. }
  749. }
  750. }
  751. // Check superinterfaces
  752. String[] interfaces = clazz.getInterfaceNames();
  753. for (int j = 0; j < interfaces.length; j++) {
  754. if (world.forDEBUG_bridgingCode) {
  755. System.err.println("Bridging:checking superinterface " + interfaces[j]);
  756. }
  757. ResolvedType interfaceType = world.resolve(interfaces[j]);
  758. overriddenMethodsCollector.clear();
  759. checkForOverride(interfaceType, name, psig, rsig, bridgeToCandidate.getAccessFlags(),
  760. clazz.getPackageName(), bm, overriddenMethodsCollector);
  761. for (ResolvedMember overriddenMethod: overriddenMethodsCollector) {
  762. String key = new StringBuffer().append(overriddenMethod.getName()).append(overriddenMethod.getSignatureErased()).toString(); // pr237419
  763. boolean alreadyHaveABridgeMethod = methodsSet.contains(key);
  764. if (!alreadyHaveABridgeMethod) {
  765. createBridgeMethod(world, bridgeToCandidate, clazz, overriddenMethod);
  766. methodsSet.add(key);
  767. didSomething = true;
  768. if (world.forDEBUG_bridgingCode) {
  769. System.err.println("Bridging:bridging to " + overriddenMethod);
  770. }
  771. }
  772. }
  773. }
  774. }
  775. return didSomething;
  776. }
  777. // **************************** end of bridge method creation code *****************
  778. /**
  779. * Weave any declare @method/@ctor statements into the members of the supplied class
  780. */
  781. private boolean weaveDeclareAtMethodCtor(LazyClassGen clazz) {
  782. List<Integer> reportedProblems = new ArrayList<Integer>();
  783. List<DeclareAnnotation> allDecams = world.getDeclareAnnotationOnMethods();
  784. if (allDecams.isEmpty()) {
  785. return false;
  786. }
  787. boolean isChanged = false;
  788. // deal with ITDs
  789. List<ConcreteTypeMunger> itdMethodsCtors = getITDSubset(clazz, ResolvedTypeMunger.Method);
  790. itdMethodsCtors.addAll(getITDSubset(clazz, ResolvedTypeMunger.Constructor));
  791. if (!itdMethodsCtors.isEmpty()) {
  792. // Can't use the subset called 'decaMs' as it won't be right for
  793. // ITDs...
  794. isChanged = weaveAtMethodOnITDSRepeatedly(allDecams, itdMethodsCtors, reportedProblems);
  795. }
  796. List<DeclareAnnotation> decaMs = getMatchingSubset(allDecams, clazz.getType());
  797. if (decaMs.isEmpty()) {
  798. return false; // nothing to do
  799. }
  800. Set<DeclareAnnotation> unusedDecams = new HashSet<DeclareAnnotation>();
  801. unusedDecams.addAll(decaMs);
  802. // These methods may have been targeted with declare annotation. Example: ITD on an interface
  803. // where the top most implementor gets a real method. The top most implementor method
  804. // is an 'addedLazyMethodGen'
  805. if (addedLazyMethodGens!=null) {
  806. for (LazyMethodGen method: addedLazyMethodGens) {
  807. // They have no resolvedmember of their own, conjure one up for matching purposes
  808. ResolvedMember resolvedmember =
  809. new ResolvedMemberImpl(ResolvedMember.METHOD,method.getEnclosingClass().getType(),method.getAccessFlags(),
  810. BcelWorld.fromBcel(method.getReturnType()),method.getName(),
  811. BcelWorld.fromBcel(method.getArgumentTypes()),UnresolvedType.forNames(method.getDeclaredExceptions()));
  812. resolvedmember.setAnnotationTypes(method.getAnnotationTypes());
  813. resolvedmember.setAnnotations(method.getAnnotations());
  814. List<DeclareAnnotation> worthRetrying = new ArrayList<DeclareAnnotation>();
  815. boolean modificationOccured = false;
  816. for (DeclareAnnotation decam: decaMs) {
  817. if (decam.matches(resolvedmember, world)) {
  818. if (doesAlreadyHaveAnnotation(resolvedmember, decam, reportedProblems,false)) {
  819. // remove the declare @method since don't want an error when the annotation is already there
  820. unusedDecams.remove(decam);
  821. continue;
  822. }
  823. AnnotationGen a = ((BcelAnnotation) decam.getAnnotation()).getBcelAnnotation();
  824. // create copy to get the annotation type into the right constant pool
  825. AnnotationAJ aj = new BcelAnnotation(new AnnotationGen(a, clazz.getConstantPool(), true),world);
  826. method.addAnnotation(aj);
  827. resolvedmember.addAnnotation(decam.getAnnotation());
  828. AsmRelationshipProvider.addDeclareAnnotationMethodRelationship(decam.getSourceLocation(),
  829. clazz.getName(), resolvedmember, world.getModelAsAsmManager());
  830. reportMethodCtorWeavingMessage(clazz, resolvedmember, decam, method.getDeclarationLineNumber());
  831. isChanged = true;
  832. modificationOccured = true;
  833. unusedDecams.remove(decam);
  834. } else if (!decam.isStarredAnnotationPattern()) {
  835. // an annotation is specified that might be put on by a subsequent decaf
  836. worthRetrying.add(decam);
  837. }
  838. }
  839. // Multiple secondary passes
  840. while (!worthRetrying.isEmpty() && modificationOccured) {
  841. modificationOccured = false;
  842. // lets have another go
  843. List<DeclareAnnotation> forRemoval = new ArrayList<DeclareAnnotation>();
  844. for (DeclareAnnotation decam : worthRetrying) {
  845. if (decam.matches(resolvedmember, world)) {
  846. if (doesAlreadyHaveAnnotation(resolvedmember, decam, reportedProblems,false)) {
  847. // remove the declare @method since don't
  848. // want an error when
  849. // the annotation is already there
  850. unusedDecams.remove(decam);
  851. continue; // skip this one...
  852. }
  853. AnnotationGen a = ((BcelAnnotation) decam.getAnnotation()).getBcelAnnotation();
  854. // create copy to get the annotation type into the right constant pool
  855. AnnotationAJ aj = new BcelAnnotation(new AnnotationGen(a, clazz.getConstantPool(), true),world);
  856. method.addAnnotation(aj);
  857. resolvedmember.addAnnotation(decam.getAnnotation());
  858. AsmRelationshipProvider.addDeclareAnnotationMethodRelationship(decam.getSourceLocation(),
  859. clazz.getName(), resolvedmember, world.getModelAsAsmManager());// getMethod());
  860. isChanged = true;
  861. modificationOccured = true;
  862. forRemoval.add(decam);
  863. unusedDecams.remove(decam);
  864. }
  865. }
  866. worthRetrying.removeAll(forRemoval);
  867. }
  868. }
  869. }
  870. // deal with all the other methods...
  871. List<LazyMethodGen> members = clazz.getMethodGens();
  872. if (!members.isEmpty()) {
  873. for (int memberCounter = 0; memberCounter < members.size(); memberCounter++) {
  874. LazyMethodGen mg = members.get(memberCounter);
  875. if (!mg.getName().startsWith(NameMangler.PREFIX)) {
  876. // Single first pass
  877. List<DeclareAnnotation> worthRetrying = new ArrayList<DeclareAnnotation>();
  878. boolean modificationOccured = false;
  879. List<AnnotationGen> annotationsToAdd = null;
  880. for (DeclareAnnotation decaM : decaMs) {
  881. if (decaM.matches(mg.getMemberView(), world)) {
  882. if (doesAlreadyHaveAnnotation(mg.getMemberView(), decaM, reportedProblems,true)) {
  883. // remove the declare @method since don't want
  884. // an error when the annotation is already there
  885. unusedDecams.remove(decaM);
  886. continue; // skip this one...
  887. }
  888. if (annotationsToAdd == null) {
  889. annotationsToAdd = new ArrayList<AnnotationGen>();
  890. }
  891. AnnotationGen a = ((BcelAnnotation) decaM.getAnnotation()).getBcelAnnotation();
  892. AnnotationGen ag = new AnnotationGen(a, clazz.getConstantPool(), true);
  893. annotationsToAdd.add(ag);
  894. mg.addAnnotation(decaM.getAnnotation());
  895. AsmRelationshipProvider.addDeclareAnnotationMethodRelationship(decaM.getSourceLocation(),
  896. clazz.getName(), mg.getMemberView(), world.getModelAsAsmManager());// getMethod());
  897. reportMethodCtorWeavingMessage(clazz, mg.getMemberView(), decaM, mg.getDeclarationLineNumber());
  898. isChanged = true;
  899. modificationOccured = true;
  900. // remove the declare @method since have matched
  901. // against it
  902. unusedDecams.remove(decaM);
  903. } else {
  904. if (!decaM.isStarredAnnotationPattern()) {
  905. worthRetrying.add(decaM); // an annotation is
  906. // specified that
  907. // might be put on
  908. // by a subsequent
  909. // decaf
  910. }
  911. }
  912. }
  913. // Multiple secondary passes
  914. while (!worthRetrying.isEmpty() && modificationOccured) {
  915. modificationOccured = false;
  916. // lets have another go
  917. List<DeclareAnnotation> forRemoval = new ArrayList<DeclareAnnotation>();
  918. for (DeclareAnnotation decaM : worthRetrying) {
  919. if (decaM.matches(mg.getMemberView(), world)) {
  920. if (doesAlreadyHaveAnnotation(mg.getMemberView(), decaM, reportedProblems,true)) {
  921. // remove the declare @method since don't
  922. // want an error when
  923. // the annotation is already there
  924. unusedDecams.remove(decaM);
  925. continue; // skip this one...
  926. }
  927. if (annotationsToAdd == null) {
  928. annotationsToAdd = new ArrayList<AnnotationGen>();
  929. }
  930. AnnotationGen a = ((BcelAnnotation) decaM.getAnnotation()).getBcelAnnotation();
  931. // create copy to get the annotation type into the right constant pool
  932. AnnotationGen ag = new AnnotationGen(a, clazz.getConstantPool(), true);
  933. annotationsToAdd.add(ag);
  934. mg.addAnnotation(decaM.getAnnotation());
  935. AsmRelationshipProvider.addDeclareAnnotationMethodRelationship(decaM.getSourceLocation(),
  936. clazz.getName(), mg.getMemberView(), world.getModelAsAsmManager());// getMethod());
  937. isChanged = true;
  938. modificationOccured = true;
  939. forRemoval.add(decaM);
  940. // remove the declare @method since have matched
  941. // against it
  942. unusedDecams.remove(decaM);
  943. }
  944. }
  945. worthRetrying.removeAll(forRemoval);
  946. }
  947. if (annotationsToAdd != null) {
  948. Method oldMethod = mg.getMethod();
  949. MethodGen myGen = new MethodGen(oldMethod, clazz.getClassName(), clazz.getConstantPool(), false);
  950. for (AnnotationGen a : annotationsToAdd) {
  951. myGen.addAnnotation(a);
  952. }
  953. Method newMethod = myGen.getMethod();
  954. members.set(memberCounter, new LazyMethodGen(newMethod, clazz));
  955. }
  956. }
  957. }
  958. checkUnusedDeclareAts(unusedDecams, false);
  959. }
  960. return isChanged;
  961. }
  962. // TAG: WeavingMessage
  963. private void reportMethodCtorWeavingMessage(LazyClassGen clazz, ResolvedMember member, DeclareAnnotation decaM,
  964. int memberLineNumber) {
  965. if (!getWorld().getMessageHandler().isIgnoring(IMessage.WEAVEINFO)) {
  966. StringBuffer parmString = new StringBuffer("(");
  967. UnresolvedType[] paramTypes = member.getParameterTypes();
  968. for (int i = 0; i < paramTypes.length; i++) {
  969. UnresolvedType type = paramTypes[i];
  970. String s = org.aspectj.apache.bcel.classfile.Utility.signatureToString(type.getSignature());
  971. if (s.lastIndexOf('.') != -1) {
  972. s = s.substring(s.lastIndexOf('.') + 1);
  973. }
  974. parmString.append(s);
  975. if ((i + 1) < paramTypes.length) {
  976. parmString.append(",");
  977. }
  978. }
  979. parmString.append(")");
  980. String methodName = member.getName();
  981. StringBuffer sig = new StringBuffer();
  982. sig.append(org.aspectj.apache.bcel.classfile.Utility.accessToString(member.getModifiers()));
  983. sig.append(" ");
  984. sig.append(member.getReturnType().toString());
  985. sig.append(" ");
  986. sig.append(member.getDeclaringType().toString());
  987. sig.append(".");
  988. sig.append(methodName.equals("<init>") ? "new" : methodName);
  989. sig.append(parmString);
  990. StringBuffer loc = new StringBuffer();
  991. if (clazz.getFileName() == null) {
  992. loc.append("no debug info available");
  993. } else {
  994. loc.append(clazz.getFileName());
  995. if (memberLineNumber != -1) {
  996. loc.append(":" + memberLineNumber);
  997. }
  998. }
  999. getWorld().getMessageHandler().handleMessage(
  1000. WeaveMessage.constructWeavingMessage(
  1001. WeaveMessage.WEAVEMESSAGE_ANNOTATES,
  1002. new String[] { sig.toString(), loc.toString(), decaM.getAnnotationString(),
  1003. methodName.startsWith("<init>") ? "constructor" : "method", decaM.getAspect().toString(),
  1004. Utility.beautifyLocation(decaM.getSourceLocation()) }));
  1005. }
  1006. }
  1007. /**
  1008. * Looks through a list of declare annotation statements and only returns those that could possibly match on a field/method/ctor
  1009. * in type.
  1010. */
  1011. private List<DeclareAnnotation> getMatchingSubset(List<DeclareAnnotation> declareAnnotations, ResolvedType type) {
  1012. List<DeclareAnnotation> subset = new ArrayList<DeclareAnnotation>();
  1013. for (DeclareAnnotation da : declareAnnotations) {
  1014. if (da.couldEverMatch(type)) {
  1015. subset.add(da);
  1016. }
  1017. }
  1018. return subset;
  1019. }
  1020. /**
  1021. * Get a subset of all the type mungers defined on this aspect
  1022. */
  1023. private List<ConcreteTypeMunger> getITDSubset(LazyClassGen clazz, ResolvedTypeMunger.Kind wantedKind) {
  1024. List<ConcreteTypeMunger> subset = new ArrayList<ConcreteTypeMunger>();
  1025. for (ConcreteTypeMunger typeMunger : clazz.getBcelObjectType().getTypeMungers()) {
  1026. if (typeMunger.getMunger().getKind() == wantedKind) {
  1027. subset.add(typeMunger);
  1028. }
  1029. }
  1030. return subset;
  1031. }
  1032. public LazyMethodGen locateAnnotationHolderForFieldMunger(LazyClassGen clazz, ConcreteTypeMunger fieldMunger) {
  1033. NewFieldTypeMunger newFieldMunger = (NewFieldTypeMunger) fieldMunger.getMunger();
  1034. ResolvedMember lookingFor = AjcMemberMaker.interFieldInitializer(newFieldMunger.getSignature(), clazz.getType());
  1035. for (LazyMethodGen method : clazz.getMethodGens()) {
  1036. if (method.getName().equals(lookingFor.getName())) {
  1037. return method;
  1038. }
  1039. }
  1040. return null;
  1041. }
  1042. // FIXME asc refactor this to neaten it up
  1043. public LazyMethodGen locateAnnotationHolderForMethodCtorMunger(LazyClassGen clazz, ConcreteTypeMunger methodCtorMunger) {
  1044. ResolvedTypeMunger rtMunger = methodCtorMunger.getMunger();
  1045. ResolvedMember lookingFor = null;
  1046. if (rtMunger instanceof NewMethodTypeMunger) {
  1047. NewMethodTypeMunger nftm = (NewMethodTypeMunger) rtMunger;
  1048. lookingFor = AjcMemberMaker.interMethodDispatcher(nftm.getSignature(), methodCtorMunger.getAspectType());
  1049. } else if (rtMunger instanceof NewConstructorTypeMunger) {
  1050. NewConstructorTypeMunger nftm = (NewConstructorTypeMunger) rtMunger;
  1051. lookingFor = AjcMemberMaker.postIntroducedConstructor(methodCtorMunger.getAspectType(), nftm.getSignature()
  1052. .getDeclaringType(), nftm.getSignature().getParameterTypes());
  1053. } else {
  1054. throw new BCException("Not sure what this is: " + methodCtorMunger);
  1055. }
  1056. String name = lookingFor.getName();
  1057. String paramSignature = lookingFor.getParameterSignature();
  1058. for (LazyMethodGen member : clazz.getMethodGens()) {
  1059. if (member.getName().equals(name) && member.getParameterSignature().equals(paramSignature)) {
  1060. return member;
  1061. }
  1062. }
  1063. return null;
  1064. }
  1065. /**
  1066. * Applies some set of declare @field constructs (List<DeclareAnnotation>) to some bunch of ITDfields (List<BcelTypeMunger>. It
  1067. * will iterate over the fields repeatedly until everything has been applied.
  1068. *
  1069. */
  1070. private boolean weaveAtFieldRepeatedly(List<DeclareAnnotation> decaFs, List<ConcreteTypeMunger> itdFields,
  1071. List<Integer> reportedErrors) {
  1072. boolean isChanged = false;
  1073. for (Iterator<ConcreteTypeMunger> iter = itdFields.iterator(); iter.hasNext();) {
  1074. BcelTypeMunger fieldMunger = (BcelTypeMunger) iter.next();
  1075. ResolvedMember itdIsActually = fieldMunger.getSignature();
  1076. Set<DeclareAnnotation> worthRetrying = new LinkedHashSet<DeclareAnnotation>();
  1077. boolean modificationOccured = false;
  1078. for (Iterator<DeclareAnnotation> iter2 = decaFs.iterator(); iter2.hasNext();) {
  1079. DeclareAnnotation decaF = iter2.next();
  1080. if (decaF.matches(itdIsActually, world)) {
  1081. if (decaF.isRemover()) {
  1082. LazyMethodGen annotationHolder = locateAnnotationHolderForFieldMunger(clazz, fieldMunger);
  1083. if (annotationHolder.hasAnnotation(decaF.getAnnotationType())) {
  1084. isChanged = true;
  1085. // something to remove
  1086. annotationHolder.removeAnnotation(decaF.getAnnotationType());
  1087. AsmRelationshipProvider.addDeclareAnnotationRelationship(world.getModelAsAsmManager(),
  1088. decaF.getSourceLocation(), itdIsActually.getSourceLocation(), true);
  1089. } else {
  1090. worthRetrying.add(decaF);
  1091. }
  1092. } else {
  1093. LazyMethodGen annotationHolder = locateAnnotationHolderForFieldMunger(clazz, fieldMunger);
  1094. if (doesAlreadyHaveAnnotation(annotationHolder, itdIsActually, decaF, reportedErrors)) {
  1095. continue; // skip this one...
  1096. }
  1097. annotationHolder.addAnnotation(decaF.getAnnotation());
  1098. AsmRelationshipProvider.addDeclareAnnotationRelationship(world.getModelAsAsmManager(),
  1099. decaF.getSourceLocation(), itdIsActually.getSourceLocation(), false);
  1100. isChanged = true;
  1101. modificationOccured = true;
  1102. }
  1103. } else {
  1104. if (!decaF.isStarredAnnotationPattern()) {
  1105. worthRetrying.add(decaF); // an annotation is specified
  1106. // that might be put on by a
  1107. // subsequent decaf
  1108. }
  1109. }
  1110. }
  1111. while (!worthRetrying.isEmpty() && modificationOccured) {
  1112. modificationOccured = false;
  1113. List<DeclareAnnotation> forRemoval = new ArrayList<DeclareAnnotation>();
  1114. for (Iterator<DeclareAnnotation> iter2 = worthRetrying.iterator(); iter2.hasNext();) {
  1115. DeclareAnnotation decaF = iter2.next();
  1116. if (decaF.matches(itdIsActually, world)) {
  1117. if (decaF.isRemover()) {
  1118. LazyMethodGen annotationHolder = locateAnnotationHolderForFieldMunger(clazz, fieldMunger);
  1119. if (annotationHolder.hasAnnotation(decaF.getAnnotationType())) {
  1120. isChanged = true;
  1121. // something to remove
  1122. annotationHolder.removeAnnotation(decaF.getAnnotationType());
  1123. AsmRelationshipProvider.addDeclareAnnotationRelationship(world.getModelAsAsmManager(),
  1124. decaF.getSourceLocation(), itdIsActually.getSourceLocation(), true);
  1125. forRemoval.add(decaF);
  1126. }
  1127. } else {
  1128. LazyMethodGen annotationHolder = locateAnnotationHolderForFieldMunger(clazz, fieldMunger);
  1129. if (doesAlreadyHaveAnnotation(annotationHolder, itdIsActually, decaF, reportedErrors)) {
  1130. continue; // skip this one...
  1131. }
  1132. annotationHolder.addAnnotation(decaF.getAnnotation());
  1133. AsmRelationshipProvider.addDeclareAnnotationRelationship(world.getModelAsAsmManager(),
  1134. decaF.getSourceLocation(), itdIsActually.getSourceLocation(), false);
  1135. isChanged = true;
  1136. modificationOccured = true;
  1137. forRemoval.add(decaF);
  1138. }
  1139. }
  1140. }
  1141. worthRetrying.removeAll(forRemoval);
  1142. }
  1143. }
  1144. return isChanged;
  1145. }
  1146. /**
  1147. * Applies some set of declare @method/@ctor constructs (List<DeclareAnnotation>) to some bunch of ITDmembers
  1148. * (List<BcelTypeMunger>. It will iterate over the fields repeatedly until everything has been applied.
  1149. */
  1150. private boolean weaveAtMethodOnITDSRepeatedly(List<DeclareAnnotation> decaMCs,
  1151. List<ConcreteTypeMunger> itdsForMethodAndConstructor, List<Integer> reportedErrors) {
  1152. boolean isChanged = false;
  1153. AsmManager asmManager = world.getModelAsAsmManager();
  1154. for (ConcreteTypeMunger methodctorMunger : itdsForMethodAndConstructor) {
  1155. // for (Iterator iter = itdsForMethodAndConstructor.iterator(); iter.hasNext();) {
  1156. // BcelTypeMunger methodctorMunger = (BcelTypeMunger) iter.next();
  1157. ResolvedMember unMangledInterMethod = methodctorMunger.getSignature();
  1158. List<DeclareAnnotation> worthRetrying = new ArrayList<DeclareAnnotation>();
  1159. boolean modificationOccured = false;
  1160. for (Iterator<DeclareAnnotation> iter2 = decaMCs.iterator(); iter2.hasNext();) {
  1161. DeclareAnnotation decaMC = iter2.next();
  1162. if (decaMC.matches(unMangledInterMethod, world)) {
  1163. LazyMethodGen annotationHolder = locateAnnotationHolderForMethodCtorMunger(clazz, methodctorMunger);
  1164. if (annotationHolder == null
  1165. || doesAlreadyHaveAnnotation(annotationHolder, unMangledInterMethod, decaMC, reportedErrors)) {
  1166. continue; // skip this one...
  1167. }
  1168. annotationHolder.addAnnotation(decaMC.getAnnotation());
  1169. isChanged = true;
  1170. AsmRelationshipProvider.addDeclareAnnotationRelationship(asmManager, decaMC.getSourceLocation(),
  1171. unMangledInterMethod.getSourceLocation(), false);
  1172. reportMethodCtorWeavingMessage(clazz, unMangledInterMethod, decaMC, -1);
  1173. modificationOccured = true;
  1174. } else {
  1175. // If an annotation is specified, it might be added by one of the other declare annotation statements
  1176. if (!decaMC.isStarredAnnotationPattern()) {
  1177. worthRetrying.add(decaMC);
  1178. }
  1179. }
  1180. }
  1181. while (!worthRetrying.isEmpty() && modificationOccured) {
  1182. modificationOccured = false;
  1183. List<DeclareAnnotation> forRemoval = new ArrayList<DeclareAnnotation>();
  1184. for (Iterator<DeclareAnnotation> iter2 = worthRetrying.iterator(); iter2.hasNext();) {
  1185. DeclareAnnotation decaMC = iter2.next();
  1186. if (decaMC.matches(unMangledInterMethod, world)) {
  1187. LazyMethodGen annotationHolder = locateAnnotationHolderForFieldMunger(clazz, methodctorMunger);
  1188. if (doesAlreadyHaveAnnotation(annotationHolder, unMangledInterMethod, decaMC, reportedErrors)) {
  1189. continue; // skip this one...
  1190. }
  1191. annotationHolder.addAnnotation(decaMC.getAnnotation());
  1192. unMangledInterMethod.addAnnotation(decaMC.getAnnotation());
  1193. AsmRelationshipProvider.addDeclareAnnotationRelationship(asmManager, decaMC.getSourceLocation(),
  1194. unMangledInterMethod.getSourceLocation(), false);
  1195. isChanged = true;
  1196. modificationOccured = true;
  1197. forRemoval.add(decaMC);
  1198. }
  1199. worthRetrying.removeAll(forRemoval);
  1200. }
  1201. }
  1202. }
  1203. return isChanged;
  1204. }
  1205. private boolean dontAddTwice(DeclareAnnotation decaF, AnnotationAJ[] dontAddMeTwice) {
  1206. for (AnnotationAJ ann : dontAddMeTwice) {
  1207. if (ann != null && decaF.getAnnotation().getTypeName().equals(ann.getTypeName())) {
  1208. return true;
  1209. }
  1210. }
  1211. return false;
  1212. }
  1213. /**
  1214. * Remove an annotation from the supplied array, if it is in there.
  1215. */
  1216. private AnnotationAJ[] removeFromAnnotationsArray(AnnotationAJ[] annotations,AnnotationAJ annotation) {
  1217. for (int i=0;i<annotations.length;i++) {
  1218. if (annotations[i] != null && annotation.getTypeName().equals(annotations[i].getTypeName())) {
  1219. // Remove it!
  1220. AnnotationAJ[] newArray = new AnnotationAJ[annotations.length-1];
  1221. int index=0;
  1222. for (int j=0;j<annotations.length;j++) {
  1223. if (j!=i) {
  1224. newArray[index++]=annotations[j];
  1225. }
  1226. }
  1227. return newArray;
  1228. }
  1229. }
  1230. return annotations;
  1231. }
  1232. // BUGWARNING not getting enough warnings out on declare @field ? There is a potential problem here with warnings not
  1233. // coming out - this will occur if they are created on the second iteration round this loop.
  1234. // We currently deactivate error reporting for the second time round. A possible solution is to record what annotations
  1235. // were added by what decafs and check that to see if an error needs to be reported - this would be expensive so lets
  1236. // skip it for now
  1237. /**
  1238. * Weave any declare @field statements into the fields of the supplied class. This will attempt to apply them to the ITDs too.
  1239. *
  1240. * Interesting case relating to public ITDd fields. The annotations are really stored against the interfieldinit method in the
  1241. * aspect, but the public field is placed in the target type and then is processed in the 2nd pass over fields that occurs. I
  1242. * think it would be more expensive to avoid putting the annotation on that inserted public field than just to have it put there
  1243. * as well as on the interfieldinit method.
  1244. */
  1245. private boolean weaveDeclareAtField(LazyClassGen clazz) {
  1246. List<Integer> reportedProblems = new ArrayList<Integer>();
  1247. List<DeclareAnnotation> allDecafs = world.getDeclareAnnotationOnFields();
  1248. if (allDecafs.isEmpty()) {
  1249. return false;
  1250. }
  1251. boolean typeIsChanged = false;
  1252. List<ConcreteTypeMunger> relevantItdFields = getITDSubset(clazz, ResolvedTypeMunger.Field);
  1253. if (relevantItdFields != null) {
  1254. typeIsChanged = weaveAtFieldRepeatedly(allDecafs, relevantItdFields, reportedProblems);
  1255. }
  1256. List<DeclareAnnotation> decafs = getMatchingSubset(allDecafs, clazz.getType());
  1257. if (decafs.isEmpty()) {
  1258. return typeIsChanged;
  1259. }
  1260. List<BcelField> fields = clazz.getFieldGens();
  1261. if (fields != null) {
  1262. Set<DeclareAnnotation> unusedDecafs = new HashSet<DeclareAnnotation>();
  1263. unusedDecafs.addAll(decafs);
  1264. for (BcelField field : fields) {
  1265. if (!field.getName().startsWith(NameMangler.PREFIX)) {
  1266. // Single first pass
  1267. Set<DeclareAnnotation> worthRetrying = new LinkedHashSet<DeclareAnnotation>();
  1268. boolean modificationOccured = false;
  1269. AnnotationAJ[] dontAddMeTwice = field.getAnnotations();
  1270. // go through all the declare @field statements
  1271. for (DeclareAnnotation decaf : decafs) {
  1272. if (decaf.getAnnotation() == null) {
  1273. return false;
  1274. }
  1275. if (decaf.matches(field, world)) {
  1276. if (decaf.isRemover()) {
  1277. AnnotationAJ annotation = decaf.getAnnotation();
  1278. if (field.hasAnnotation(annotation.getType())) {
  1279. // something to remove
  1280. typeIsChanged = true;
  1281. field.removeAnnotation(annotation);
  1282. AsmRelationshipProvider.addDeclareAnnotationFieldRelationship(world.getModelAsAsmManager(),
  1283. decaf.getSourceLocation(), clazz.getName(), field, true);
  1284. reportFieldAnnotationWeavingMessage(clazz, field, decaf, true);
  1285. dontAddMeTwice = removeFromAnnotationsArray(dontAddMeTwice, annotation);
  1286. } else {
  1287. worthRetrying.add(decaf);
  1288. }
  1289. unusedDecafs.remove(decaf);
  1290. } else {
  1291. if (!dontAddTwice(decaf, dontAddMeTwice)) {
  1292. if (doesAlreadyHaveAnnotation(field, decaf, reportedProblems,true )) {
  1293. // remove the declare @field since don't want an error when the annotation is already there
  1294. unusedDecafs.remove(decaf);
  1295. continue;
  1296. }
  1297. field.addAnnotation(decaf.getAnnotation());
  1298. }
  1299. AsmRelationshipProvider.addDeclareAnnotationFieldRelationship(world.getModelAsAsmManager(),
  1300. decaf.getSourceLocation(), clazz.getName(), field, false);
  1301. reportFieldAnnotationWeavingMessage(clazz, field, decaf, false);
  1302. typeIsChanged = true;
  1303. modificationOccured = true;
  1304. unusedDecafs.remove(decaf);
  1305. }
  1306. } else if (!decaf.isStarredAnnotationPattern() || decaf.isRemover()) {
  1307. worthRetrying.add(decaf); // an annotation is specified that might be put on by a subsequent decaf
  1308. }
  1309. }
  1310. // Multiple secondary passes
  1311. while (!worthRetrying.isEmpty() && modificationOccured) {
  1312. modificationOccured = false;
  1313. // lets have another go with any remaining ones
  1314. List<DeclareAnnotation> forRemoval = new ArrayList<DeclareAnnotation>();
  1315. for (Iterator<DeclareAnnotation> iter = worthRetrying.iterator(); iter.hasNext();) {
  1316. DeclareAnnotation decaF = iter.next();
  1317. if (decaF.matches(field, world)) {
  1318. if (decaF.isRemover()) {
  1319. AnnotationAJ annotation = decaF.getAnnotation();
  1320. if (field.hasAnnotation(annotation.getType())) {
  1321. // something to remove
  1322. typeIsChanged = modificationOccured = true;
  1323. forRemoval.add(decaF);
  1324. field.removeAnnotation(annotation);
  1325. AsmRelationshipProvider.addDeclareAnnotationFieldRelationship(world.getModelAsAsmManager(),
  1326. decaF.getSourceLocation(), clazz.getName(), field, true);
  1327. reportFieldAnnotationWeavingMessage(clazz, field, decaF, true);
  1328. }
  1329. } else {
  1330. // below code is for recursive things
  1331. unusedDecafs.remove(decaF);
  1332. if (doesAlreadyHaveAnnotation(field, decaF, reportedProblems,true)) {
  1333. continue;
  1334. }
  1335. field.addAnnotation(decaF.getAnnotation());
  1336. AsmRelationshipProvider.addDeclareAnnotationFieldRelationship(world.getModelAsAsmManager(),
  1337. decaF.getSourceLocation(), clazz.getName(), field, false);
  1338. typeIsChanged = modificationOccured = true;
  1339. forRemoval.add(decaF);
  1340. }
  1341. }
  1342. }
  1343. worthRetrying.removeAll(forRemoval);
  1344. }
  1345. }
  1346. }
  1347. checkUnusedDeclareAts(unusedDecafs, true);
  1348. }
  1349. return typeIsChanged;
  1350. }
  1351. // bug 99191 - put out an error message if the type doesn't exist
  1352. /**
  1353. * Report an error if the reason a "declare @method/ctor/field" was not used was because the member specified does not exist.
  1354. * This method is passed some set of declare statements that didn't match and a flag indicating whether the set contains declare @field
  1355. * or declare @method/ctor entries.
  1356. */
  1357. private void checkUnusedDeclareAts(Set<DeclareAnnotation> unusedDecaTs, boolean isDeclareAtField) {
  1358. for (DeclareAnnotation declA : unusedDecaTs) {
  1359. // Error if an exact type pattern was specified
  1360. boolean shouldCheck = declA.isExactPattern() || declA.getSignaturePattern().getExactDeclaringTypes().size() != 0;
  1361. if (shouldCheck && declA.getKind() != DeclareAnnotation.AT_CONSTRUCTOR) {
  1362. if (declA.getSignaturePattern().isMatchOnAnyName()) {
  1363. shouldCheck = false;
  1364. } else {
  1365. List<ExactTypePattern> declaringTypePatterns = declA.getSignaturePattern().getExactDeclaringTypes();
  1366. if (declaringTypePatterns.size() == 0) {
  1367. shouldCheck = false;
  1368. } else {
  1369. for (ExactTypePattern exactTypePattern : declaringTypePatterns) {
  1370. if (exactTypePattern.isIncludeSubtypes()) {
  1371. shouldCheck = false;
  1372. break;
  1373. }
  1374. }
  1375. }
  1376. }
  1377. }
  1378. if (shouldCheck) {
  1379. // Quickly check if an ITD supplies the 'missing' member
  1380. boolean itdMatch = false;
  1381. List<ConcreteTypeMunger> lst = clazz.getType().getInterTypeMungers();
  1382. for (Iterator<ConcreteTypeMunger> iterator = lst.iterator(); iterator.hasNext() && !itdMatch;) {
  1383. ConcreteTypeMunger element = iterator.next();
  1384. if (element.getMunger() instanceof NewFieldTypeMunger) {
  1385. NewFieldTypeMunger nftm = (NewFieldTypeMunger) element.getMunger();
  1386. itdMatch = declA.matches(nftm.getSignature(), world);
  1387. } else if (element.getMunger() instanceof NewMethodTypeMunger) {
  1388. NewMethodTypeMunger nmtm = (NewMethodTypeMunger) element.getMunger();
  1389. itdMatch = declA.matches(nmtm.getSignature(), world);
  1390. } else if (element.getMunger() instanceof NewConstructorTypeMunger) {
  1391. NewConstructorTypeMunger nctm = (NewConstructorTypeMunger) element.getMunger();
  1392. itdMatch = declA.matches(nctm.getSignature(), world);
  1393. }
  1394. }
  1395. if (!itdMatch) {
  1396. IMessage message = null;
  1397. if (isDeclareAtField) {
  1398. message = new Message("The field '" + declA.getSignaturePattern().toString() + "' does not exist",
  1399. declA.getSourceLocation(), true);
  1400. } else {
  1401. message = new Message("The method '" + declA.getSignaturePattern().toString() + "' does not exist",
  1402. declA.getSourceLocation(), true);
  1403. }
  1404. world.getMessageHandler().handleMessage(message);
  1405. }
  1406. }
  1407. }
  1408. }
  1409. // TAG: WeavingMessage
  1410. private void reportFieldAnnotationWeavingMessage(LazyClassGen clazz, BcelField theField, DeclareAnnotation decaf,
  1411. boolean isRemove) {
  1412. if (!getWorld().getMessageHandler().isIgnoring(IMessage.WEAVEINFO)) {
  1413. world.getMessageHandler().handleMessage(
  1414. WeaveMessage.constructWeavingMessage(
  1415. isRemove ? WeaveMessage.WEAVEMESSAGE_REMOVES_ANNOTATION : WeaveMessage.WEAVEMESSAGE_ANNOTATES,
  1416. new String[] { theField.getFieldAsIs().toString() + "' of type '" + clazz.getName(),
  1417. clazz.getFileName(), decaf.getAnnotationString(), "field", decaf.getAspect().toString(),
  1418. Utility.beautifyLocation(decaf.getSourceLocation()) }));
  1419. }
  1420. }
  1421. /**
  1422. * Check if a resolved member (field/method/ctor) already has an annotation, if it does then put out a warning and return true
  1423. */
  1424. private boolean doesAlreadyHaveAnnotation(ResolvedMember rm, DeclareAnnotation deca, List<Integer> reportedProblems, boolean reportError) {
  1425. if (rm.hasAnnotation(deca.getAnnotationType())) {
  1426. if (reportError && world.getLint().elementAlreadyAnnotated.isEnabled()) {
  1427. Integer uniqueID = new Integer(rm.hashCode() * deca.hashCode());
  1428. if (!reportedProblems.contains(uniqueID)) {
  1429. reportedProblems.add(uniqueID);
  1430. world.getLint().elementAlreadyAnnotated.signal(new String[] { rm.toString(),
  1431. deca.getAnnotationType().toString() }, rm.getSourceLocation(),
  1432. new ISourceLocation[] { deca.getSourceLocation() });
  1433. }
  1434. }
  1435. return true;
  1436. }
  1437. return false;
  1438. }
  1439. private boolean doesAlreadyHaveAnnotation(LazyMethodGen rm, ResolvedMember itdfieldsig, DeclareAnnotation deca,
  1440. List<Integer> reportedProblems) {
  1441. if (rm != null && rm.hasAnnotation(deca.getAnnotationType())) {
  1442. if (world.getLint().elementAlreadyAnnotated.isEnabled()) {
  1443. Integer uniqueID = new Integer(rm.hashCode() * deca.hashCode());
  1444. if (!reportedProblems.contains(uniqueID)) {
  1445. reportedProblems.add(uniqueID);
  1446. reportedProblems.add(new Integer(itdfieldsig.hashCode() * deca.hashCode()));
  1447. world.getLint().elementAlreadyAnnotated.signal(new String[] { itdfieldsig.toString(),
  1448. deca.getAnnotationType().toString() }, rm.getSourceLocation(),
  1449. new ISourceLocation[] { deca.getSourceLocation() });
  1450. }
  1451. }
  1452. return true;
  1453. }
  1454. return false;
  1455. }
  1456. private Set<String> findAspectsForMungers(LazyMethodGen mg) {
  1457. Set<String> aspectsAffectingType = new HashSet<String>();
  1458. for (BcelShadow shadow : mg.matchedShadows) {
  1459. for (ShadowMunger munger : shadow.getMungers()) {
  1460. if (munger instanceof BcelAdvice) {
  1461. BcelAdvice bcelAdvice = (BcelAdvice) munger;
  1462. if (bcelAdvice.getConcreteAspect() != null) {
  1463. aspectsAffectingType.add(bcelAdvice.getConcreteAspect().getSignature());
  1464. }
  1465. } else {
  1466. // It is a 'Checker' - we don't need to remember aspects
  1467. // that only contributed Checkers...
  1468. }
  1469. }
  1470. }
  1471. return aspectsAffectingType;
  1472. }
  1473. private boolean inlineSelfConstructors(List<LazyMethodGen> methodGens, List<LazyMethodGen> recursiveCtors) {
  1474. boolean inlinedSomething = false;
  1475. List<LazyMethodGen> newRecursiveCtors = new ArrayList<LazyMethodGen>();
  1476. for (LazyMethodGen methodGen : methodGens) {
  1477. if (!methodGen.getName().equals("<init>")) {
  1478. continue;
  1479. }
  1480. InstructionHandle ih = findSuperOrThisCall(methodGen);
  1481. if (ih != null && isThisCall(ih)) {
  1482. LazyMethodGen donor = getCalledMethod(ih);
  1483. if (donor.equals(methodGen)) {
  1484. newRecursiveCtors.add(donor);
  1485. } else {
  1486. if (!recursiveCtors.contains(donor)) {
  1487. inlineMethod(donor, methodGen, ih);
  1488. inlinedSomething = true;
  1489. }
  1490. }
  1491. }
  1492. }
  1493. recursiveCtors.addAll(newRecursiveCtors);
  1494. return inlinedSomething;
  1495. }
  1496. private void positionAndImplement(List<BcelShadow> initializationShadows) {
  1497. for (BcelShadow s : initializationShadows) {
  1498. positionInitializationShadow(s);
  1499. // s.getEnclosingMethod().print();
  1500. s.implement();
  1501. }
  1502. }
  1503. private void positionInitializationShadow(BcelShadow s) {
  1504. LazyMethodGen mg = s.getEnclosingMethod();
  1505. InstructionHandle call = findSuperOrThisCall(mg);
  1506. InstructionList body = mg.getBody();
  1507. ShadowRange r = new ShadowRange(body);
  1508. r.associateWithShadow(s);
  1509. if (s.getKind() == Shadow.PreInitialization) {
  1510. // XXX assert first instruction is an ALOAD_0.
  1511. // a pre shadow goes from AFTER the first instruction (which we
  1512. // believe to
  1513. // be an ALOAD_0) to just before the call to super
  1514. r.associateWithTargets(Range.genStart(body, body.getStart().getNext()), Range.genEnd(body, call.getPrev()));
  1515. } else {
  1516. // assert s.getKind() == Shadow.Initialization
  1517. r.associateWithTargets(Range.genStart(body, call.getNext()), Range.genEnd(body));
  1518. }
  1519. }
  1520. private boolean isThisCall(InstructionHandle ih) {
  1521. InvokeInstruction inst = (InvokeInstruction) ih.getInstruction();
  1522. return inst.getClassName(cpg).equals(clazz.getName());
  1523. }
  1524. /**
  1525. * inline a particular call in bytecode.
  1526. *
  1527. * @param donor the method we want to inline
  1528. * @param recipient the method containing the call we want to inline
  1529. * @param call the instructionHandle in recipient's body holding the call we want to inline.
  1530. */
  1531. public static void inlineMethod(LazyMethodGen donor, LazyMethodGen recipient, InstructionHandle call) {
  1532. // assert recipient.contains(call)
  1533. /*
  1534. * Implementation notes:
  1535. *
  1536. * We allocate two slots for every tempvar so we don't screw up longs and doubles which may share space. This could be
  1537. * conservatively avoided (no reference to a long/double instruction, don't do it) or packed later. Right now we don't
  1538. * bother to pack.
  1539. *
  1540. * Allocate a new var for each formal param of the inlined. Fill with stack contents. Then copy the inlined instructions in
  1541. * with the appropriate remap table. Any framelocs used by locals in inlined are reallocated to top of frame,
  1542. */
  1543. final InstructionFactory fact = recipient.getEnclosingClass().getFactory();
  1544. IntMap frameEnv = new IntMap();
  1545. // this also sets up the initial environment
  1546. InstructionList argumentStores = genArgumentStores(donor, recipient, frameEnv, fact);
  1547. InstructionList inlineInstructions = genInlineInstructions(donor, recipient, frameEnv, fact, false);
  1548. inlineInstructions.insert(argumentStores);
  1549. recipient.getBody().append(call, inlineInstructions);
  1550. Utility.deleteInstruction(call, recipient);
  1551. }
  1552. // public BcelVar genTempVar(UnresolvedType typeX) {
  1553. // return new BcelVar(typeX.resolve(world),
  1554. // genTempVarIndex(typeX.getSize()));
  1555. // }
  1556. //
  1557. // private int genTempVarIndex(int size) {
  1558. // return enclosingMethod.allocateLocal(size);
  1559. // }
  1560. /**
  1561. * Input method is a synchronized method, we remove the bit flag for synchronized and then insert a try..finally block
  1562. *
  1563. * Some jumping through firey hoops required - depending on the input code level (1.5 or not) we may or may not be able to use
  1564. * the LDC instruction that takes a class literal (doesnt on <1.5).
  1565. *
  1566. * FIXME asc Before promoting -Xjoinpoints:synchronization to be a standard option, this needs a bunch of tidying up - there is
  1567. * some duplication that can be removed.
  1568. */
  1569. public static void transformSynchronizedMethod(LazyMethodGen synchronizedMethod) {
  1570. if (trace.isTraceEnabled()) {
  1571. trace.enter("transformSynchronizedMethod", synchronizedMethod);
  1572. }
  1573. // System.err.println("DEBUG: Transforming synchronized method: "+
  1574. // synchronizedMethod.getName());
  1575. final InstructionFactory fact = synchronizedMethod.getEnclosingClass().getFactory();
  1576. InstructionList body = synchronizedMethod.getBody();
  1577. InstructionList prepend = new InstructionList();
  1578. Type enclosingClassType = BcelWorld.makeBcelType(synchronizedMethod.getEnclosingClass().getType());
  1579. // STATIC METHOD TRANSFORMATION
  1580. if (synchronizedMethod.isStatic()) {
  1581. // What to do here depends on the level of the class file!
  1582. // LDC can handle class literals in Java5 and above *sigh*
  1583. if (synchronizedMethod.getEnclosingClass().isAtLeastJava5()) {
  1584. // MONITORENTER logic:
  1585. // 0: ldc #2; //class C
  1586. // 2: dup
  1587. // 3: astore_0
  1588. // 4: monitorenter
  1589. int slotForLockObject = synchronizedMethod.allocateLocal(enclosingClassType);
  1590. prepend.append(fact.createConstant(enclosingClassType));
  1591. prepend.append(InstructionFactory.createDup(1));
  1592. prepend.append(InstructionFactory.createStore(enclosingClassType, slotForLockObject));
  1593. prepend.append(InstructionFactory.MONITORENTER);
  1594. // MONITOREXIT logic:
  1595. // We basically need to wrap the code from the method in a
  1596. // finally block that
  1597. // will ensure monitorexit is called. Content on the finally
  1598. // block seems to
  1599. // be always:
  1600. //
  1601. // E1: ALOAD_1
  1602. // MONITOREXIT
  1603. // ATHROW
  1604. //
  1605. // so lets build that:
  1606. InstructionList finallyBlock = new InstructionList();
  1607. finallyBlock.append(InstructionFactory.createLoad(Type.getType(java.lang.Class.class), slotForLockObject));
  1608. finallyBlock.append(InstructionConstants.MONITOREXIT);
  1609. finallyBlock.append(InstructionConstants.ATHROW);
  1610. // finally -> E1
  1611. // | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line
  1612. // 21)
  1613. // | LDC "hello"
  1614. // | INVOKEVIRTUAL java.io.PrintStream.println
  1615. // (Ljava/lang/String;)V
  1616. // | ALOAD_1 (line 20)
  1617. // | MONITOREXIT
  1618. // finally -> E1
  1619. // GOTO L0
  1620. // finally -> E1
  1621. // | E1: ALOAD_1
  1622. // | MONITOREXIT
  1623. // finally -> E1
  1624. // ATHROW
  1625. // L0: RETURN (line 23)
  1626. // search for 'returns' and make them jump to the
  1627. // aload_<n>,monitorexit
  1628. InstructionHandle walker = body.getStart();
  1629. List<InstructionHandle> rets = new ArrayList<InstructionHandle>();
  1630. while (walker != null) {
  1631. if (walker.getInstruction().isReturnInstruction()) {
  1632. rets.add(walker);
  1633. }
  1634. walker = walker.getNext();
  1635. }
  1636. if (!rets.isEmpty()) {
  1637. // need to ensure targeters for 'return' now instead target
  1638. // the load instruction
  1639. // (so we never jump over the monitorexit logic)
  1640. for (Iterator<InstructionHandle> iter = rets.iterator(); iter.hasNext();) {
  1641. InstructionHandle element = iter.next();
  1642. InstructionList monitorExitBlock = new InstructionList();
  1643. monitorExitBlock.append(InstructionFactory.createLoad(enclosingClassType, slotForLockObject));
  1644. monitorExitBlock.append(InstructionConstants.MONITOREXIT);
  1645. // monitorExitBlock.append(Utility.copyInstruction(element
  1646. // .getInstruction()));
  1647. // element.setInstruction(InstructionFactory.createLoad(
  1648. // classType,slotForThis));
  1649. InstructionHandle monitorExitBlockStart = body.insert(element, monitorExitBlock);
  1650. // now move the targeters from the RET to the start of
  1651. // the monitorexit block
  1652. for (InstructionTargeter targeter : element.getTargetersCopy()) {
  1653. // what kinds are there?
  1654. if (targeter instanceof LocalVariableTag) {
  1655. // ignore
  1656. } else if (targeter instanceof LineNumberTag) {
  1657. // ignore
  1658. // } else if (targeter instanceof
  1659. // InstructionBranch &&
  1660. // ((InstructionBranch)targeter).isGoto()) {
  1661. // // move it...
  1662. // targeter.updateTarget(element,
  1663. // monitorExitBlockStart);
  1664. } else if (targeter instanceof InstructionBranch) {
  1665. // move it
  1666. targeter.updateTarget(element, monitorExitBlockStart);
  1667. } else {
  1668. throw new BCException("Unexpected targeter encountered during transform: " + targeter);
  1669. }
  1670. }
  1671. }
  1672. }
  1673. // now the magic, putting the finally block around the code
  1674. InstructionHandle finallyStart = finallyBlock.getStart();
  1675. InstructionHandle tryPosition = body.getStart();
  1676. InstructionHandle catchPosition = body.getEnd();
  1677. body.insert(body.getStart(), prepend); // now we can put the
  1678. // monitorenter stuff on
  1679. synchronizedMethod.getBody().append(finallyBlock);
  1680. synchronizedMethod.addExceptionHandler(tryPosition, catchPosition, finallyStart, null/* ==finally */, false);
  1681. synchronizedMethod.addExceptionHandler(finallyStart, finallyStart.getNext(), finallyStart, null, false);
  1682. } else {
  1683. // TRANSFORMING STATIC METHOD ON PRE JAVA5
  1684. // Hideous nightmare, class literal references prior to Java5
  1685. // YIKES! this is just the code for MONITORENTER !
  1686. // 0: getstatic #59; //Field class$1:Ljava/lang/Class;
  1687. // 3: dup
  1688. // 4: ifnonnull 32
  1689. // 7: pop
  1690. // try
  1691. // 8: ldc #61; //String java.lang.String
  1692. // 10: invokestatic #44; //Method
  1693. // java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
  1694. // 13: dup
  1695. // catch
  1696. // 14: putstatic #59; //Field class$1:Ljava/lang/Class;
  1697. // 17: goto 32
  1698. // 20: new #46; //class java/lang/NoClassDefFoundError
  1699. // 23: dup_x1
  1700. // 24: swap
  1701. // 25: invokevirtual #52; //Method
  1702. // java/lang/Throwable.getMessage:()Ljava/lang/String;
  1703. // 28: invokespecial #54; //Method
  1704. // java/lang/NoClassDefFoundError."<init>":(Ljava/lang/String;)V
  1705. // 31: athrow
  1706. // 32: dup <-- partTwo (branch target)
  1707. // 33: astore_0
  1708. // 34: monitorenter
  1709. //
  1710. // plus exceptiontable entry!
  1711. // 8 13 20 Class java/lang/ClassNotFoundException
  1712. Type classType = BcelWorld.makeBcelType(synchronizedMethod.getEnclosingClass().getType());
  1713. Type clazzType = Type.getType(Class.class);
  1714. InstructionList parttwo = new InstructionList();
  1715. parttwo.append(InstructionFactory.createDup(1));
  1716. int slotForThis = synchronizedMethod.allocateLocal(classType);
  1717. parttwo.append(InstructionFactory.createStore(clazzType, slotForThis)); // ? should be the real type ? String or
  1718. // something?
  1719. parttwo.append(InstructionFactory.MONITORENTER);
  1720. String fieldname = synchronizedMethod.getEnclosingClass().allocateField("class$");
  1721. FieldGen f = new FieldGen(Modifier.STATIC | Modifier.PRIVATE, Type.getType(Class.class), fieldname,
  1722. synchronizedMethod.getEnclosingClass().getConstantPool());
  1723. synchronizedMethod.getEnclosingClass().addField(f, null);
  1724. // 10: invokestatic #44; //Method
  1725. // java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
  1726. // 13: dup
  1727. // 14: putstatic #59; //Field class$1:Ljava/lang/Class;
  1728. // 17: goto 32
  1729. // 20: new #46; //class java/lang/NoClassDefFoundError
  1730. // 23: dup_x1
  1731. // 24: swap
  1732. // 25: invokevirtual #52; //Method
  1733. // java/lang/Throwable.getMessage:()Ljava/lang/String;
  1734. // 28: invokespecial #54; //Method
  1735. // java/lang/NoClassDefFoundError."<init>":(Ljava/lang/String;)V
  1736. // 31: athrow
  1737. String name = synchronizedMethod.getEnclosingClass().getName();
  1738. prepend.append(fact.createGetStatic(name, fieldname, Type.getType(Class.class)));
  1739. prepend.append(InstructionFactory.createDup(1));
  1740. prepend.append(InstructionFactory.createBranchInstruction(Constants.IFNONNULL, parttwo.getStart()));
  1741. prepend.append(InstructionFactory.POP);
  1742. prepend.append(fact.createConstant(name));
  1743. InstructionHandle tryInstruction = prepend.getEnd();
  1744. prepend.append(fact.createInvoke("java.lang.Class", "forName", clazzType,
  1745. new Type[] { Type.getType(String.class) }, Constants.INVOKESTATIC));
  1746. InstructionHandle catchInstruction = prepend.getEnd();
  1747. prepend.append(InstructionFactory.createDup(1));
  1748. prepend.append(fact.createPutStatic(synchronizedMethod.getEnclosingClass().getType().getName(), fieldname,
  1749. Type.getType(Class.class)));
  1750. prepend.append(InstructionFactory.createBranchInstruction(Constants.GOTO, parttwo.getStart()));
  1751. // start of catch block
  1752. InstructionList catchBlockForLiteralLoadingFail = new InstructionList();
  1753. catchBlockForLiteralLoadingFail.append(fact.createNew((ObjectType) Type.getType(NoClassDefFoundError.class)));
  1754. catchBlockForLiteralLoadingFail.append(InstructionFactory.createDup_1(1));
  1755. catchBlockForLiteralLoadingFail.append(InstructionFactory.SWAP);
  1756. catchBlockForLiteralLoadingFail.append(fact.createInvoke("java.lang.Throwable", "getMessage",
  1757. Type.getType(String.class), new Type[] {}, Constants.INVOKEVIRTUAL));
  1758. catchBlockForLiteralLoadingFail.append(fact.createInvoke("java.lang.NoClassDefFoundError", "<init>", Type.VOID,
  1759. new Type[] { Type.getType(String.class) }, Constants.INVOKESPECIAL));
  1760. catchBlockForLiteralLoadingFail.append(InstructionFactory.ATHROW);
  1761. InstructionHandle catchBlockStart = catchBlockForLiteralLoadingFail.getStart();
  1762. prepend.append(catchBlockForLiteralLoadingFail);
  1763. prepend.append(parttwo);
  1764. // MONITORENTER
  1765. // pseudocode: load up 'this' (var0), dup it, store it in a new
  1766. // local var (for use with monitorexit) and call
  1767. // monitorenter:
  1768. // ALOAD_0, DUP, ASTORE_<n>, MONITORENTER
  1769. // prepend.append(InstructionFactory.createLoad(classType,0));
  1770. // prepend.append(InstructionFactory.createDup(1));
  1771. // int slotForThis =
  1772. // synchronizedMethod.allocateLocal(classType);
  1773. // prepend.append(InstructionFactory.createStore(classType,
  1774. // slotForThis));
  1775. // prepend.append(InstructionFactory.MONITORENTER);
  1776. // MONITOREXIT
  1777. // here be dragons
  1778. // We basically need to wrap the code from the method in a
  1779. // finally block that
  1780. // will ensure monitorexit is called. Content on the finally
  1781. // block seems to
  1782. // be always:
  1783. //
  1784. // E1: ALOAD_1
  1785. // MONITOREXIT
  1786. // ATHROW
  1787. //
  1788. // so lets build that:
  1789. InstructionList finallyBlock = new InstructionList();
  1790. finallyBlock.append(InstructionFactory.createLoad(Type.getType(java.lang.Class.class), slotForThis));
  1791. finallyBlock.append(InstructionConstants.MONITOREXIT);
  1792. finallyBlock.append(InstructionConstants.ATHROW);
  1793. // finally -> E1
  1794. // | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line
  1795. // 21)
  1796. // | LDC "hello"
  1797. // | INVOKEVIRTUAL java.io.PrintStream.println
  1798. // (Ljava/lang/String;)V
  1799. // | ALOAD_1 (line 20)
  1800. // | MONITOREXIT
  1801. // finally -> E1
  1802. // GOTO L0
  1803. // finally -> E1
  1804. // | E1: ALOAD_1
  1805. // | MONITOREXIT
  1806. // finally -> E1
  1807. // ATHROW
  1808. // L0: RETURN (line 23)
  1809. // frameEnv.put(donorFramePos, thisSlot);
  1810. // search for 'returns' and make them to the
  1811. // aload_<n>,monitorexit
  1812. InstructionHandle walker = body.getStart();
  1813. List<InstructionHandle> rets = new ArrayList<InstructionHandle>();
  1814. while (walker != null) { // !walker.equals(body.getEnd())) {
  1815. if (walker.getInstruction().isReturnInstruction()) {
  1816. rets.add(walker);
  1817. }
  1818. walker = walker.getNext();
  1819. }
  1820. if (rets.size() > 0) {
  1821. // need to ensure targeters for 'return' now instead target
  1822. // the load instruction
  1823. // (so we never jump over the monitorexit logic)
  1824. for (InstructionHandle ret : rets) {
  1825. // System.err.println("Adding monitor exit block at "+
  1826. // element);
  1827. InstructionList monitorExitBlock = new InstructionList();
  1828. monitorExitBlock.append(InstructionFactory.createLoad(classType, slotForThis));
  1829. monitorExitBlock.append(InstructionConstants.MONITOREXIT);
  1830. // monitorExitBlock.append(Utility.copyInstruction(element
  1831. // .getInstruction()));
  1832. // element.setInstruction(InstructionFactory.createLoad(
  1833. // classType,slotForThis));
  1834. InstructionHandle monitorExitBlockStart = body.insert(ret, monitorExitBlock);
  1835. // now move the targeters from the RET to the start of
  1836. // the monitorexit block
  1837. for (InstructionTargeter targeter : ret.getTargetersCopy()) {
  1838. // what kinds are there?
  1839. if (targeter instanceof LocalVariableTag) {
  1840. // ignore
  1841. } else if (targeter instanceof LineNumberTag) {
  1842. // ignore
  1843. // } else if (targeter instanceof GOTO ||
  1844. // targeter instanceof GOTO_W) {
  1845. // // move it...
  1846. // targeter.updateTarget(element,
  1847. // monitorExitBlockStart);
  1848. } else if (targeter instanceof InstructionBranch) {
  1849. // move it
  1850. targeter.updateTarget(ret, monitorExitBlockStart);
  1851. } else {
  1852. throw new BCException("Unexpected targeter encountered during transform: " + targeter);
  1853. }
  1854. }
  1855. }
  1856. }
  1857. // body =
  1858. // rewriteWithMonitorExitCalls(body,fact,true,slotForThis,
  1859. // classType);
  1860. // synchronizedMethod.setBody(body);
  1861. // now the magic, putting the finally block around the code
  1862. InstructionHandle finallyStart = finallyBlock.getStart();
  1863. InstructionHandle tryPosition = body.getStart();
  1864. InstructionHandle catchPosition = body.getEnd();
  1865. body.insert(body.getStart(), prepend); // now we can put the
  1866. // monitorenter stuff on
  1867. synchronizedMethod.getBody().append(finallyBlock);
  1868. synchronizedMethod.addExceptionHandler(tryPosition, catchPosition, finallyStart, null/* ==finally */, false);
  1869. synchronizedMethod.addExceptionHandler(tryInstruction, catchInstruction, catchBlockStart,
  1870. (ObjectType) Type.getType(ClassNotFoundException.class), true);
  1871. synchronizedMethod.addExceptionHandler(finallyStart, finallyStart.getNext(), finallyStart, null, false);
  1872. }
  1873. } else {
  1874. // TRANSFORMING NON STATIC METHOD
  1875. Type classType = BcelWorld.makeBcelType(synchronizedMethod.getEnclosingClass().getType());
  1876. // MONITORENTER
  1877. // pseudocode: load up 'this' (var0), dup it, store it in a new
  1878. // local var (for use with monitorexit) and call
  1879. // monitorenter:
  1880. // ALOAD_0, DUP, ASTORE_<n>, MONITORENTER
  1881. prepend.append(InstructionFactory.createLoad(classType, 0));
  1882. prepend.append(InstructionFactory.createDup(1));
  1883. int slotForThis = synchronizedMethod.allocateLocal(classType);
  1884. prepend.append(InstructionFactory.createStore(classType, slotForThis));
  1885. prepend.append(InstructionFactory.MONITORENTER);
  1886. // body.insert(body.getStart(),prepend);
  1887. // MONITOREXIT
  1888. // We basically need to wrap the code from the method in a finally
  1889. // block that
  1890. // will ensure monitorexit is called. Content on the finally block
  1891. // seems to
  1892. // be always:
  1893. //
  1894. // E1: ALOAD_1
  1895. // MONITOREXIT
  1896. // ATHROW
  1897. //
  1898. // so lets build that:
  1899. InstructionList finallyBlock = new InstructionList();
  1900. finallyBlock.append(InstructionFactory.createLoad(classType, slotForThis));
  1901. finallyBlock.append(InstructionConstants.MONITOREXIT);
  1902. finallyBlock.append(InstructionConstants.ATHROW);
  1903. // finally -> E1
  1904. // | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 21)
  1905. // | LDC "hello"
  1906. // | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
  1907. // | ALOAD_1 (line 20)
  1908. // | MONITOREXIT
  1909. // finally -> E1
  1910. // GOTO L0
  1911. // finally -> E1
  1912. // | E1: ALOAD_1
  1913. // | MONITOREXIT
  1914. // finally -> E1
  1915. // ATHROW
  1916. // L0: RETURN (line 23)
  1917. // frameEnv.put(donorFramePos, thisSlot);
  1918. // search for 'returns' and make them to the aload_<n>,monitorexit
  1919. InstructionHandle walker = body.getStart();
  1920. List<InstructionHandle> rets = new ArrayList<InstructionHandle>();
  1921. while (walker != null) { // !walker.equals(body.getEnd())) {
  1922. if (walker.getInstruction().isReturnInstruction()) {
  1923. rets.add(walker);
  1924. }
  1925. walker = walker.getNext();
  1926. }
  1927. if (!rets.isEmpty()) {
  1928. // need to ensure targeters for 'return' now instead target the
  1929. // load instruction
  1930. // (so we never jump over the monitorexit logic)
  1931. for (Iterator<InstructionHandle> iter = rets.iterator(); iter.hasNext();) {
  1932. InstructionHandle element = iter.next();
  1933. // System.err.println("Adding monitor exit block at "+element
  1934. // );
  1935. InstructionList monitorExitBlock = new InstructionList();
  1936. monitorExitBlock.append(InstructionFactory.createLoad(classType, slotForThis));
  1937. monitorExitBlock.append(InstructionConstants.MONITOREXIT);
  1938. // monitorExitBlock.append(Utility.copyInstruction(element.
  1939. // getInstruction()));
  1940. // element.setInstruction(InstructionFactory.createLoad(
  1941. // classType,slotForThis));
  1942. InstructionHandle monitorExitBlockStart = body.insert(element, monitorExitBlock);
  1943. // now move the targeters from the RET to the start of the
  1944. // monitorexit block
  1945. for (InstructionTargeter targeter : element.getTargetersCopy()) {
  1946. // what kinds are there?
  1947. if (targeter instanceof LocalVariableTag) {
  1948. // ignore
  1949. } else if (targeter instanceof LineNumberTag) {
  1950. // ignore
  1951. // } else if (targeter instanceof GOTO ||
  1952. // targeter instanceof GOTO_W) {
  1953. // // move it...
  1954. // targeter.updateTarget(element,
  1955. // monitorExitBlockStart);
  1956. } else if (targeter instanceof InstructionBranch) {
  1957. // move it
  1958. targeter.updateTarget(element, monitorExitBlockStart);
  1959. } else {
  1960. throw new BCException("Unexpected targeter encountered during transform: " + targeter);
  1961. }
  1962. }
  1963. }
  1964. }
  1965. // now the magic, putting the finally block around the code
  1966. InstructionHandle finallyStart = finallyBlock.getStart();
  1967. InstructionHandle tryPosition = body.getStart();
  1968. InstructionHandle catchPosition = body.getEnd();
  1969. body.insert(body.getStart(), prepend); // now we can put the
  1970. // monitorenter stuff on
  1971. synchronizedMethod.getBody().append(finallyBlock);
  1972. synchronizedMethod.addExceptionHandler(tryPosition, catchPosition, finallyStart, null/* ==finally */, false);
  1973. synchronizedMethod.addExceptionHandler(finallyStart, finallyStart.getNext(), finallyStart, null, false);
  1974. // also the exception handling for the finally block jumps to itself
  1975. // max locals will already have been modified in the allocateLocal()
  1976. // call
  1977. // synchronized bit is removed on LazyMethodGen.pack()
  1978. }
  1979. // gonna have to go through and change all aload_0s to load the var from
  1980. // a variable,
  1981. // going to add a new variable for the this var
  1982. if (trace.isTraceEnabled()) {
  1983. trace.exit("transformSynchronizedMethod");
  1984. }
  1985. }
  1986. /**
  1987. * generate the instructions to be inlined.
  1988. *
  1989. * @param donor the method from which we will copy (and adjust frame and jumps) instructions.
  1990. * @param recipient the method the instructions will go into. Used to get the frame size so we can allocate new frame locations
  1991. * for locals in donor.
  1992. * @param frameEnv an environment to map from donor frame to recipient frame, initially populated with argument locations.
  1993. * @param fact an instruction factory for recipient
  1994. */
  1995. static InstructionList genInlineInstructions(LazyMethodGen donor, LazyMethodGen recipient, IntMap frameEnv,
  1996. InstructionFactory fact, boolean keepReturns) {
  1997. InstructionList footer = new InstructionList();
  1998. InstructionHandle end = footer.append(InstructionConstants.NOP);
  1999. InstructionList ret = new InstructionList();
  2000. InstructionList sourceList = donor.getBody();
  2001. Map<InstructionHandle, InstructionHandle> srcToDest = new HashMap<InstructionHandle, InstructionHandle>();
  2002. ConstantPool donorCpg = donor.getEnclosingClass().getConstantPool();
  2003. ConstantPool recipientCpg = recipient.getEnclosingClass().getConstantPool();
  2004. boolean isAcrossClass = donorCpg != recipientCpg;
  2005. BootstrapMethods bootstrapMethods = null;
  2006. // first pass: copy the instructions directly, populate the srcToDest
  2007. // map,
  2008. // fix frame instructions
  2009. for (InstructionHandle src = sourceList.getStart(); src != null; src = src.getNext()) {
  2010. Instruction fresh = Utility.copyInstruction(src.getInstruction());
  2011. InstructionHandle dest;
  2012. // OPTIMIZE optimize this stuff?
  2013. if (fresh.isConstantPoolInstruction()) {
  2014. // need to reset index to go to new constant pool. This is totally
  2015. // a computation leak... we're testing this LOTS of times. Sigh.
  2016. if (isAcrossClass) {
  2017. InstructionCP cpi = (InstructionCP) fresh;
  2018. cpi.setIndex(recipientCpg.addConstant(donorCpg.getConstant(cpi.getIndex()), donorCpg));
  2019. }
  2020. // May need to copy bootstrapmethods across too.
  2021. // if (fresh instanceof InvokeDynamic) {
  2022. // InvokeDynamic id = (InvokeDynamic)fresh;
  2023. // ConstantInvokeDynamic cid = (ConstantInvokeDynamic)donorCpg.getConstant(src.getInstruction().getIndex());
  2024. // int bmaIndex = cid.getBootstrapMethodAttrIndex();
  2025. // if (bootstrapMethods == null) {
  2026. // Collection<Attribute> attributes = donor.getEnclosingClass().getAttributes();
  2027. // if (attributes != null) {
  2028. // for (Attribute attribute: attributes) {
  2029. // if (attribute instanceof BootstrapMethods) {
  2030. // bootstrapMethods = (BootstrapMethods)attribute;
  2031. // }
  2032. // }
  2033. // }
  2034. // BootstrapMethods.BootstrapMethod bootstrapMethod =
  2035. // bootstrapMethods.getBootstrapMethods()[bmaIndex];
  2036. // ConstantMethodHandle methodhandle = (ConstantMethodHandle)donorCpg.getConstant(bootstrapMethod.getBootstrapMethodRef());
  2037. // int bootstrapMethodArguments[] = bootstrapMethod.getBootstrapArguments();
  2038. //
  2039. // // Finally have all we need to build the new one...
  2040. //
  2041. // int newMethodHandleIndex = recipientCpg.addConstant(methodhandle, donorCpg);
  2042. // int[] newMethodArguments = new int[bootstrapMethodArguments.length];
  2043. // for (int a=0; a<bootstrapMethodArguments.length; a++) {
  2044. // newMethodArguments[a] = recipientCpg.addConstant(donorCpg.getConstant(bootstrapMethodArguments[a]),donorCpg);
  2045. // }
  2046. // BootstrapMethods.BootstrapMethod newBootstrapMethod =
  2047. // new BootstrapMethods.BootstrapMethod(newMethodHandleIndex,newMethodArguments);
  2048. //
  2049. // Collection<Attribute> newAttributes = recipient.getEnclosingClass().getAttributes();
  2050. // BootstrapMethods newBootstrapMethods = null;
  2051. // for (Attribute attr: newAttributes) {
  2052. // if (attr instanceof BootstrapMethods) {
  2053. // newBootstrapMethods = (BootstrapMethods)newBootstrapMethods;
  2054. // }
  2055. // }
  2056. // if (newBootstrapMethods == null) {
  2057. // newBootstrapMethods =
  2058. // new BootstrapMethods(recipientCpg.addUtf8("BootstrapMethods"),
  2059. // 2+newBootstrapMethod.getLength(),
  2060. // new BootstrapMethods.BootstrapMethod[] {newBootstrapMethod},
  2061. // recipientCpg);
  2062. // recipient.getEnclosingClass().addAttribute(newBootstrapMethods);
  2063. // }
  2064. // TODO need to copy over lambda$0 support methods too...
  2065. // }
  2066. //
  2067. // }
  2068. }
  2069. if (src.getInstruction() == Range.RANGEINSTRUCTION) {
  2070. dest = ret.append(Range.RANGEINSTRUCTION);
  2071. } else if (fresh.isReturnInstruction()) {
  2072. if (keepReturns) {
  2073. dest = ret.append(fresh);
  2074. } else {
  2075. dest = ret.append(InstructionFactory.createBranchInstruction(Constants.GOTO, end));
  2076. }
  2077. } else if (fresh instanceof InstructionBranch) {
  2078. dest = ret.append((InstructionBranch) fresh);
  2079. } else if (fresh.isLocalVariableInstruction() || fresh instanceof RET) {
  2080. // IndexedInstruction indexed = (IndexedInstruction) fresh;
  2081. int oldIndex = fresh.getIndex();
  2082. int freshIndex;
  2083. if (!frameEnv.hasKey(oldIndex)) {
  2084. freshIndex = recipient.allocateLocal(2);
  2085. frameEnv.put(oldIndex, freshIndex);
  2086. } else {
  2087. freshIndex = frameEnv.get(oldIndex);
  2088. }
  2089. if (fresh instanceof RET) {
  2090. fresh.setIndex(freshIndex);
  2091. } else {
  2092. fresh = ((InstructionLV) fresh).setIndexAndCopyIfNecessary(freshIndex);
  2093. }
  2094. dest = ret.append(fresh);
  2095. } else {
  2096. dest = ret.append(fresh);
  2097. }
  2098. srcToDest.put(src, dest);
  2099. }
  2100. // second pass: retarget branch instructions, copy ranges and tags
  2101. Map<Tag, Tag> tagMap = new HashMap<Tag, Tag>();
  2102. Map<BcelShadow, BcelShadow> shadowMap = new HashMap<BcelShadow, BcelShadow>();
  2103. for (InstructionHandle dest = ret.getStart(), src = sourceList.getStart(); dest != null; dest = dest.getNext(), src = src
  2104. .getNext()) {
  2105. Instruction inst = dest.getInstruction();
  2106. // retarget branches
  2107. if (inst instanceof InstructionBranch) {
  2108. InstructionBranch branch = (InstructionBranch) inst;
  2109. InstructionHandle oldTarget = branch.getTarget();
  2110. InstructionHandle newTarget = srcToDest.get(oldTarget);
  2111. if (newTarget == null) {
  2112. // assert this is a GOTO
  2113. // this was a return instruction we previously replaced
  2114. } else {
  2115. branch.setTarget(newTarget);
  2116. if (branch instanceof InstructionSelect) {
  2117. InstructionSelect select = (InstructionSelect) branch;
  2118. InstructionHandle[] oldTargets = select.getTargets();
  2119. for (int k = oldTargets.length - 1; k >= 0; k--) {
  2120. select.setTarget(k, srcToDest.get(oldTargets[k]));
  2121. }
  2122. }
  2123. }
  2124. }
  2125. // copy over tags and range attributes
  2126. Iterator<InstructionTargeter> tIter = src.getTargeters().iterator();
  2127. while (tIter.hasNext()) {
  2128. InstructionTargeter old = tIter.next();
  2129. if (old instanceof Tag) {
  2130. Tag oldTag = (Tag) old;
  2131. Tag fresh = tagMap.get(oldTag);
  2132. if (fresh == null) {
  2133. fresh = oldTag.copy();
  2134. if (old instanceof LocalVariableTag) {
  2135. // LocalVariable
  2136. LocalVariableTag lvTag = (LocalVariableTag) old;
  2137. LocalVariableTag lvTagFresh = (LocalVariableTag) fresh;
  2138. if (lvTag.getSlot() == 0) {
  2139. fresh = new LocalVariableTag(lvTag.getRealType().getSignature(), "ajc$aspectInstance",
  2140. frameEnv.get(lvTag.getSlot()), 0);
  2141. } else {
  2142. // // Do not move it - when copying the code from the aspect to the affected target, 'this' is
  2143. // // going to change from aspect to affected type. So just fix the type
  2144. // System.out.println("For local variable tag at instruction " + src + " changing slot from "
  2145. // + lvTag.getSlot() + " > " + frameEnv.get(lvTag.getSlot()));
  2146. lvTagFresh.updateSlot(frameEnv.get(lvTag.getSlot()));
  2147. }
  2148. }
  2149. tagMap.put(oldTag, fresh);
  2150. }
  2151. dest.addTargeter(fresh);
  2152. } else if (old instanceof ExceptionRange) {
  2153. ExceptionRange er = (ExceptionRange) old;
  2154. if (er.getStart() == src) {
  2155. ExceptionRange freshEr = new ExceptionRange(recipient.getBody(), er.getCatchType(), er.getPriority());
  2156. freshEr.associateWithTargets(dest, srcToDest.get(er.getEnd()), srcToDest.get(er.getHandler()));
  2157. }
  2158. } else if (old instanceof ShadowRange) {
  2159. ShadowRange oldRange = (ShadowRange) old;
  2160. if (oldRange.getStart() == src) {
  2161. BcelShadow oldShadow = oldRange.getShadow();
  2162. BcelShadow freshEnclosing = oldShadow.getEnclosingShadow() == null ? null : (BcelShadow) shadowMap
  2163. .get(oldShadow.getEnclosingShadow());
  2164. BcelShadow freshShadow = oldShadow.copyInto(recipient, freshEnclosing);
  2165. ShadowRange freshRange = new ShadowRange(recipient.getBody());
  2166. freshRange.associateWithShadow(freshShadow);
  2167. freshRange.associateWithTargets(dest, srcToDest.get(oldRange.getEnd()));
  2168. shadowMap.put(oldShadow, freshShadow); // oldRange, freshRange
  2169. // recipient.matchedShadows.add(freshShadow);
  2170. // XXX should go through the NEW copied shadow and
  2171. // update
  2172. // the thisVar, targetVar, and argsVar
  2173. // ??? Might want to also go through at this time and
  2174. // add
  2175. // "extra" vars to the shadow.
  2176. }
  2177. }
  2178. }
  2179. }
  2180. if (!keepReturns) {
  2181. ret.append(footer);
  2182. }
  2183. return ret;
  2184. }
  2185. // static InstructionList rewriteWithMonitorExitCalls(InstructionList
  2186. // sourceList,InstructionFactory fact,boolean keepReturns,int
  2187. // monitorVarSlot,Type monitorVarType)
  2188. // {
  2189. // InstructionList footer = new InstructionList();
  2190. // InstructionHandle end = footer.append(InstructionConstants.NOP);
  2191. //
  2192. // InstructionList newList = new InstructionList();
  2193. //
  2194. // Map srcToDest = new HashMap();
  2195. //
  2196. // // first pass: copy the instructions directly, populate the srcToDest
  2197. // map,
  2198. // // fix frame instructions
  2199. // for (InstructionHandle src = sourceList.getStart(); src != null; src =
  2200. // src.getNext()) {
  2201. // Instruction fresh = Utility.copyInstruction(src.getInstruction());
  2202. // InstructionHandle dest;
  2203. // if (src.getInstruction() == Range.RANGEINSTRUCTION) {
  2204. // dest = newList.append(Range.RANGEINSTRUCTION);
  2205. // } else if (fresh.isReturnInstruction()) {
  2206. // if (keepReturns) {
  2207. // newList.append(InstructionFactory.createLoad(monitorVarType,monitorVarSlot
  2208. // ));
  2209. // newList.append(InstructionConstants.MONITOREXIT);
  2210. // dest = newList.append(fresh);
  2211. // } else {
  2212. // dest =
  2213. // newList.append(InstructionFactory.createBranchInstruction(Constants.GOTO,
  2214. // end));
  2215. // }
  2216. // } else if (fresh instanceof InstructionBranch) {
  2217. // dest = newList.append((InstructionBranch) fresh);
  2218. // } else if (
  2219. // fresh.isLocalVariableInstruction() || fresh instanceof RET) {
  2220. // //IndexedInstruction indexed = (IndexedInstruction) fresh;
  2221. // int oldIndex = fresh.getIndex();
  2222. // int freshIndex;
  2223. // // if (!frameEnv.hasKey(oldIndex)) {
  2224. // // freshIndex = recipient.allocateLocal(2);
  2225. // // frameEnv.put(oldIndex, freshIndex);
  2226. // // } else {
  2227. // freshIndex = oldIndex;//frameEnv.get(oldIndex);
  2228. // // }
  2229. // if (fresh instanceof RET) {
  2230. // fresh.setIndex(freshIndex);
  2231. // } else {
  2232. // fresh = ((InstructionLV)fresh).setIndexAndCopyIfNecessary(freshIndex);
  2233. // }
  2234. // dest = newList.append(fresh);
  2235. // } else {
  2236. // dest = newList.append(fresh);
  2237. // }
  2238. // srcToDest.put(src, dest);
  2239. // }
  2240. //
  2241. // // second pass: retarget branch instructions, copy ranges and tags
  2242. // Map tagMap = new HashMap();
  2243. // for (InstructionHandle dest = newList.getStart(), src =
  2244. // sourceList.getStart();
  2245. // dest != null;
  2246. // dest = dest.getNext(), src = src.getNext()) {
  2247. // Instruction inst = dest.getInstruction();
  2248. //
  2249. // // retarget branches
  2250. // if (inst instanceof InstructionBranch) {
  2251. // InstructionBranch branch = (InstructionBranch) inst;
  2252. // InstructionHandle oldTarget = branch.getTarget();
  2253. // InstructionHandle newTarget =
  2254. // (InstructionHandle) srcToDest.get(oldTarget);
  2255. // if (newTarget == null) {
  2256. // // assert this is a GOTO
  2257. // // this was a return instruction we previously replaced
  2258. // } else {
  2259. // branch.setTarget(newTarget);
  2260. // if (branch instanceof InstructionSelect) {
  2261. // InstructionSelect select = (InstructionSelect) branch;
  2262. // InstructionHandle[] oldTargets = select.getTargets();
  2263. // for (int k = oldTargets.length - 1; k >= 0; k--) {
  2264. // select.setTarget(
  2265. // k,
  2266. // (InstructionHandle) srcToDest.get(oldTargets[k]));
  2267. // }
  2268. // }
  2269. // }
  2270. // }
  2271. //
  2272. // //copy over tags and range attributes
  2273. // Iterator tIter = src.getTargeters().iterator();
  2274. //
  2275. // while (tIter.hasNext()) {
  2276. // InstructionTargeter old = (InstructionTargeter)tIter.next();
  2277. // if (old instanceof Tag) {
  2278. // Tag oldTag = (Tag) old;
  2279. // Tag fresh = (Tag) tagMap.get(oldTag);
  2280. // if (fresh == null) {
  2281. // fresh = oldTag.copy();
  2282. // tagMap.put(oldTag, fresh);
  2283. // }
  2284. // dest.addTargeter(fresh);
  2285. // } else if (old instanceof ExceptionRange) {
  2286. // ExceptionRange er = (ExceptionRange) old;
  2287. // if (er.getStart() == src) {
  2288. // ExceptionRange freshEr =
  2289. // new ExceptionRange(newList/*recipient.getBody()*/,er.getCatchType(),er.
  2290. // getPriority());
  2291. // freshEr.associateWithTargets(
  2292. // dest,
  2293. // (InstructionHandle)srcToDest.get(er.getEnd()),
  2294. // (InstructionHandle)srcToDest.get(er.getHandler()));
  2295. // }
  2296. // }
  2297. // /*else if (old instanceof ShadowRange) {
  2298. // ShadowRange oldRange = (ShadowRange) old;
  2299. // if (oldRange.getStart() == src) {
  2300. // BcelShadow oldShadow = oldRange.getShadow();
  2301. // BcelShadow freshEnclosing =
  2302. // oldShadow.getEnclosingShadow() == null
  2303. // ? null
  2304. // : (BcelShadow) shadowMap.get(oldShadow.getEnclosingShadow());
  2305. // BcelShadow freshShadow =
  2306. // oldShadow.copyInto(recipient, freshEnclosing);
  2307. // ShadowRange freshRange = new ShadowRange(recipient.getBody());
  2308. // freshRange.associateWithShadow(freshShadow);
  2309. // freshRange.associateWithTargets(
  2310. // dest,
  2311. // (InstructionHandle) srcToDest.get(oldRange.getEnd()));
  2312. // shadowMap.put(oldRange, freshRange);
  2313. // //recipient.matchedShadows.add(freshShadow);
  2314. // // XXX should go through the NEW copied shadow and update
  2315. // // the thisVar, targetVar, and argsVar
  2316. // // ??? Might want to also go through at this time and add
  2317. // // "extra" vars to the shadow.
  2318. // }
  2319. // }*/
  2320. // }
  2321. // }
  2322. // if (!keepReturns) newList.append(footer);
  2323. // return newList;
  2324. // }
  2325. /**
  2326. * generate the argument stores in preparation for inlining.
  2327. *
  2328. * @param donor the method we will inline from. Used to get the signature.
  2329. * @param recipient the method we will inline into. Used to get the frame size so we can allocate fresh locations.
  2330. * @param frameEnv an empty environment we populate with a map from donor frame to recipient frame.
  2331. * @param fact an instruction factory for recipient
  2332. */
  2333. private static InstructionList genArgumentStores(LazyMethodGen donor, LazyMethodGen recipient, IntMap frameEnv,
  2334. InstructionFactory fact) {
  2335. InstructionList ret = new InstructionList();
  2336. int donorFramePos = 0;
  2337. // writing ret back to front because we're popping.
  2338. if (!donor.isStatic()) {
  2339. int targetSlot = recipient.allocateLocal(Type.OBJECT);
  2340. ret.insert(InstructionFactory.createStore(Type.OBJECT, targetSlot));
  2341. frameEnv.put(donorFramePos, targetSlot);
  2342. donorFramePos += 1;
  2343. }
  2344. Type[] argTypes = donor.getArgumentTypes();
  2345. for (int i = 0, len = argTypes.length; i < len; i++) {
  2346. Type argType = argTypes[i];
  2347. int argSlot = recipient.allocateLocal(argType);
  2348. ret.insert(InstructionFactory.createStore(argType, argSlot));
  2349. frameEnv.put(donorFramePos, argSlot);
  2350. donorFramePos += argType.getSize();
  2351. }
  2352. return ret;
  2353. }
  2354. /**
  2355. * get a called method: Assumes the called method is in this class, and the reference to it is exact (a la INVOKESPECIAL).
  2356. *
  2357. * @param ih The InvokeInstruction instructionHandle pointing to the called method.
  2358. */
  2359. private LazyMethodGen getCalledMethod(InstructionHandle ih) {
  2360. InvokeInstruction inst = (InvokeInstruction) ih.getInstruction();
  2361. String methodName = inst.getName(cpg);
  2362. String signature = inst.getSignature(cpg);
  2363. return clazz.getLazyMethodGen(methodName, signature);
  2364. }
  2365. private void weaveInAddedMethods() {
  2366. Collections.sort(addedLazyMethodGens, new Comparator<LazyMethodGen>() {
  2367. public int compare(LazyMethodGen aa, LazyMethodGen bb) {
  2368. int i = aa.getName().compareTo(bb.getName());
  2369. if (i != 0) {
  2370. return i;
  2371. }
  2372. return aa.getSignature().compareTo(bb.getSignature());
  2373. }
  2374. });
  2375. for (LazyMethodGen addedMember : addedLazyMethodGens) {
  2376. clazz.addMethodGen(addedMember);
  2377. }
  2378. }
  2379. // void addPerSingletonField(Member field) {
  2380. // ObjectType aspectType = (ObjectType)
  2381. // BcelWorld.makeBcelType(field.getReturnType());
  2382. // String aspectName = field.getReturnType().getName();
  2383. //
  2384. // LazyMethodGen clinit = clazz.getStaticInitializer();
  2385. // InstructionList setup = new InstructionList();
  2386. // InstructionFactory fact = clazz.getFactory();
  2387. //
  2388. // setup.append(fact.createNew(aspectType));
  2389. // setup.append(InstructionFactory.createDup(1));
  2390. // setup.append(fact.createInvoke(aspectName, "<init>", Type.VOID, new
  2391. // Type[0], Constants.INVOKESPECIAL));
  2392. // setup.append(fact.createFieldAccess(aspectName, field.getName(),
  2393. // aspectType, Constants.PUTSTATIC));
  2394. // clinit.getBody().insert(setup);
  2395. // }
  2396. /**
  2397. * Returns null if this is not a Java constructor, and then we won't weave into it at all
  2398. */
  2399. private InstructionHandle findSuperOrThisCall(LazyMethodGen mg) {
  2400. int depth = 1;
  2401. InstructionHandle start = mg.getBody().getStart();
  2402. while (true) {
  2403. if (start == null) {
  2404. return null;
  2405. }
  2406. Instruction inst = start.getInstruction();
  2407. if (inst.opcode == Constants.INVOKESPECIAL && ((InvokeInstruction) inst).getName(cpg).equals("<init>")) {
  2408. depth--;
  2409. if (depth == 0) {
  2410. return start;
  2411. }
  2412. } else if (inst.opcode == Constants.NEW) {
  2413. depth++;
  2414. }
  2415. start = start.getNext();
  2416. }
  2417. }
  2418. // ----
  2419. private boolean match(LazyMethodGen mg) {
  2420. BcelShadow enclosingShadow;
  2421. List<BcelShadow> shadowAccumulator = new ArrayList<BcelShadow>();
  2422. boolean isOverweaving = world.isOverWeaving();
  2423. boolean startsAngly = mg.getName().charAt(0) == '<';
  2424. // we want to match ajsynthetic constructors...
  2425. if (startsAngly && mg.getName().equals("<init>")) {
  2426. return matchInit(mg, shadowAccumulator);
  2427. } else if (!shouldWeaveBody(mg)) {
  2428. return false;
  2429. } else {
  2430. if (startsAngly && mg.getName().equals("<clinit>")) {
  2431. // clinitShadow =
  2432. enclosingShadow = BcelShadow.makeStaticInitialization(world, mg);
  2433. // System.err.println(enclosingShadow);
  2434. } else if (mg.isAdviceMethod()) {
  2435. enclosingShadow = BcelShadow.makeAdviceExecution(world, mg);
  2436. } else {
  2437. AjAttribute.EffectiveSignatureAttribute effective = mg.getEffectiveSignature();
  2438. if (effective == null) {
  2439. // Don't want ajc$preClinit to be considered for matching
  2440. if (isOverweaving && mg.getName().startsWith(NameMangler.PREFIX)) {
  2441. return false;
  2442. }
  2443. if (mg.getName().startsWith(SWITCH_TABLE_SYNTHETIC_METHOD_PREFIX)
  2444. && Objects.equals(mg.getReturnType().getSignature(), "[I")) {
  2445. // this is a synthetic switch helper, should be skipped (since it's not 'declared')
  2446. return false;
  2447. }
  2448. enclosingShadow = BcelShadow.makeMethodExecution(world, mg, !canMatchBodyShadows);
  2449. } else if (effective.isWeaveBody()) {
  2450. ResolvedMember rm = effective.getEffectiveSignature();
  2451. // Annotations for things with effective signatures are
  2452. // never stored in the effective
  2453. // signature itself - we have to hunt for them. Storing them
  2454. // in the effective signature
  2455. // would mean keeping two sets up to date (no way!!)
  2456. fixParameterNamesForResolvedMember(rm, mg.getMemberView());
  2457. fixAnnotationsForResolvedMember(rm, mg.getMemberView());
  2458. enclosingShadow = BcelShadow.makeShadowForMethod(world, mg, effective.getShadowKind(), rm);
  2459. } else {
  2460. return false;
  2461. }
  2462. }
  2463. if (canMatchBodyShadows) {
  2464. for (InstructionHandle h = mg.getBody().getStart(); h != null; h = h.getNext()) {
  2465. match(mg, h, enclosingShadow, shadowAccumulator);
  2466. }
  2467. }
  2468. // FIXME asc change from string match if we can, rather brittle.
  2469. // this check actually prevents field-exec jps
  2470. if (canMatch(enclosingShadow.getKind())
  2471. && !(mg.getName().charAt(0) == 'a' && mg.getName().startsWith("ajc$interFieldInit"))) {
  2472. if (match(enclosingShadow, shadowAccumulator)) {
  2473. enclosingShadow.init();
  2474. }
  2475. }
  2476. mg.matchedShadows = shadowAccumulator;
  2477. return !shadowAccumulator.isEmpty();
  2478. }
  2479. }
  2480. private boolean matchInit(LazyMethodGen mg, List<BcelShadow> shadowAccumulator) {
  2481. BcelShadow enclosingShadow;
  2482. // XXX the enclosing join point is wrong for things before ignoreMe.
  2483. InstructionHandle superOrThisCall = findSuperOrThisCall(mg);
  2484. // we don't walk bodies of things where it's a wrong constructor thingie
  2485. if (superOrThisCall == null) {
  2486. return false;
  2487. }
  2488. enclosingShadow = BcelShadow.makeConstructorExecution(world, mg, superOrThisCall);
  2489. if (mg.getEffectiveSignature() != null) {
  2490. enclosingShadow.setMatchingSignature(mg.getEffectiveSignature().getEffectiveSignature());
  2491. }
  2492. // walk the body
  2493. boolean beforeSuperOrThisCall = true;
  2494. if (shouldWeaveBody(mg)) {
  2495. if (canMatchBodyShadows) {
  2496. for (InstructionHandle h = mg.getBody().getStart(); h != null; h = h.getNext()) {
  2497. if (h == superOrThisCall) {
  2498. beforeSuperOrThisCall = false;
  2499. continue;
  2500. }
  2501. match(mg, h, beforeSuperOrThisCall ? null : enclosingShadow, shadowAccumulator);
  2502. }
  2503. }
  2504. if (canMatch(Shadow.ConstructorExecution)) {
  2505. match(enclosingShadow, shadowAccumulator);
  2506. }
  2507. }
  2508. // XXX we don't do pre-inits of interfaces
  2509. // now add interface inits
  2510. if (!isThisCall(superOrThisCall)) {
  2511. InstructionHandle curr = enclosingShadow.getRange().getStart();
  2512. for (Iterator<IfaceInitList> i = addedSuperInitializersAsList.iterator(); i.hasNext();) {
  2513. IfaceInitList l = i.next();
  2514. Member ifaceInitSig = AjcMemberMaker.interfaceConstructor(l.onType);
  2515. BcelShadow initShadow = BcelShadow.makeIfaceInitialization(world, mg, ifaceInitSig);
  2516. // insert code in place
  2517. InstructionList inits = genInitInstructions(l.list, false);
  2518. if (match(initShadow, shadowAccumulator) || !inits.isEmpty()) {
  2519. initShadow.initIfaceInitializer(curr);
  2520. initShadow.getRange().insert(inits, Range.OutsideBefore);
  2521. }
  2522. }
  2523. // now we add our initialization code
  2524. InstructionList inits = genInitInstructions(addedThisInitializers, false);
  2525. enclosingShadow.getRange().insert(inits, Range.OutsideBefore);
  2526. }
  2527. // actually, you only need to inline the self constructors that are
  2528. // in a particular group (partition the constructors into groups where
  2529. // members
  2530. // call or are called only by those in the group). Then only inline
  2531. // constructors
  2532. // in groups where at least one initialization jp matched. Future work.
  2533. boolean addedInitialization = match(BcelShadow.makeUnfinishedInitialization(world, mg), initializationShadows);
  2534. addedInitialization |= match(BcelShadow.makeUnfinishedPreinitialization(world, mg), initializationShadows);
  2535. mg.matchedShadows = shadowAccumulator;
  2536. return addedInitialization || !shadowAccumulator.isEmpty();
  2537. }
  2538. private boolean shouldWeaveBody(LazyMethodGen mg) {
  2539. if (mg.isBridgeMethod()) {
  2540. return false;
  2541. }
  2542. if (mg.isAjSynthetic()) {
  2543. return mg.getName().equals("<clinit>");
  2544. }
  2545. AjAttribute.EffectiveSignatureAttribute a = mg.getEffectiveSignature();
  2546. if (a != null) {
  2547. return a.isWeaveBody();
  2548. }
  2549. return true;
  2550. }
  2551. /**
  2552. * first sorts the mungers, then gens the initializers in the right order
  2553. */
  2554. private InstructionList genInitInstructions(List<ConcreteTypeMunger> list, boolean isStatic) {
  2555. list = PartialOrder.sort(list);
  2556. if (list == null) {
  2557. throw new BCException("circularity in inter-types");
  2558. }
  2559. InstructionList ret = new InstructionList();
  2560. for (ConcreteTypeMunger cmunger : list) {
  2561. NewFieldTypeMunger munger = (NewFieldTypeMunger) cmunger.getMunger();
  2562. ResolvedMember initMethod = munger.getInitMethod(cmunger.getAspectType());
  2563. if (!isStatic) {
  2564. ret.append(InstructionConstants.ALOAD_0);
  2565. }
  2566. ret.append(Utility.createInvoke(fact, world, initMethod));
  2567. }
  2568. return ret;
  2569. }
  2570. private void match(LazyMethodGen mg, InstructionHandle ih, BcelShadow enclosingShadow, List<BcelShadow> shadowAccumulator) {
  2571. Instruction i = ih.getInstruction();
  2572. // Exception handlers (pr230817)
  2573. if (canMatch(Shadow.ExceptionHandler) && !Range.isRangeHandle(ih)) {
  2574. Set<InstructionTargeter> targeters = ih.getTargetersCopy();
  2575. // If in Java7 there may be overlapping exception ranges for multi catch - we should recognize that
  2576. for (InstructionTargeter t : targeters) {
  2577. if (t instanceof ExceptionRange) {
  2578. // assert t.getHandler() == ih
  2579. ExceptionRange er = (ExceptionRange) t;
  2580. if (er.getCatchType() == null) {
  2581. continue;
  2582. }
  2583. if (isInitFailureHandler(ih)) {
  2584. return;
  2585. }
  2586. if (!ih.getInstruction().isStoreInstruction() && ih.getInstruction().getOpcode() != Constants.NOP) {
  2587. // If using cobertura, the catch block stats with
  2588. // INVOKESTATIC rather than ASTORE, in order that the ranges
  2589. // for the methodcall and exceptionhandler shadows
  2590. // that occur at this same
  2591. // line, we need to modify the instruction list to
  2592. // split them - adding a
  2593. // NOP before the invokestatic that gets all the targeters
  2594. // that were aimed at the INVOKESTATIC
  2595. mg.getBody().insert(ih, InstructionConstants.NOP);
  2596. InstructionHandle newNOP = ih.getPrev();
  2597. // what about a try..catch that starts at the start
  2598. // of the exception handler? need to only include
  2599. // certain targeters really.
  2600. er.updateTarget(ih, newNOP, mg.getBody());
  2601. for (InstructionTargeter t2 : targeters) {
  2602. newNOP.addTargeter(t2);
  2603. }
  2604. ih.removeAllTargeters();
  2605. match(BcelShadow.makeExceptionHandler(world, er, mg, newNOP, enclosingShadow), shadowAccumulator);
  2606. } else {
  2607. match(BcelShadow.makeExceptionHandler(world, er, mg, ih, enclosingShadow), shadowAccumulator);
  2608. }
  2609. }
  2610. }
  2611. }
  2612. if ((i instanceof FieldInstruction) && (canMatch(Shadow.FieldGet) || canMatch(Shadow.FieldSet))) {
  2613. FieldInstruction fi = (FieldInstruction) i;
  2614. if (fi.opcode == Constants.PUTFIELD || fi.opcode == Constants.PUTSTATIC) {
  2615. // check for sets of constant fields. We first check the
  2616. // previous
  2617. // instruction. If the previous instruction is a LD_WHATEVER
  2618. // (push
  2619. // constant on the stack) then we must resolve the field to
  2620. // determine
  2621. // if it's final. If it is final, then we don't generate a
  2622. // shadow.
  2623. InstructionHandle prevHandle = ih.getPrev();
  2624. Instruction prevI = prevHandle.getInstruction();
  2625. if (Utility.isConstantPushInstruction(prevI)) {
  2626. Member field = BcelWorld.makeFieldJoinPointSignature(clazz, (FieldInstruction) i);
  2627. ResolvedMember resolvedField = field.resolve(world);
  2628. if (resolvedField == null) {
  2629. // we can't find the field, so it's not a join point.
  2630. } else if (Modifier.isFinal(resolvedField.getModifiers())) {
  2631. // it's final, so it's the set of a final constant, so
  2632. // it's
  2633. // not a join point according to 1.0.6 and 1.1.
  2634. } else {
  2635. if (canMatch(Shadow.FieldSet)) {
  2636. matchSetInstruction(mg, ih, enclosingShadow, shadowAccumulator);
  2637. }
  2638. }
  2639. } else {
  2640. if (canMatch(Shadow.FieldSet)) {
  2641. matchSetInstruction(mg, ih, enclosingShadow, shadowAccumulator);
  2642. }
  2643. }
  2644. } else {
  2645. if (canMatch(Shadow.FieldGet)) {
  2646. matchGetInstruction(mg, ih, enclosingShadow, shadowAccumulator);
  2647. }
  2648. }
  2649. } else if (i instanceof InvokeInstruction) {
  2650. InvokeInstruction ii = (InvokeInstruction) i;
  2651. if (ii.getMethodName(clazz.getConstantPool()).equals("<init>")) {
  2652. if (canMatch(Shadow.ConstructorCall)) {
  2653. match(BcelShadow.makeConstructorCall(world, mg, ih, enclosingShadow), shadowAccumulator);
  2654. }
  2655. } else if (ii.opcode == Constants.INVOKESPECIAL) {
  2656. String onTypeName = ii.getClassName(cpg);
  2657. if (onTypeName.equals(mg.getEnclosingClass().getName())) {
  2658. // we are private
  2659. matchInvokeInstruction(mg, ih, ii, enclosingShadow, shadowAccumulator);
  2660. } else {
  2661. // we are a super call, and this is not a join point in
  2662. // AspectJ-1.{0,1}
  2663. }
  2664. } else {
  2665. if (ii.getOpcode()!=Constants.INVOKEDYNAMIC) {
  2666. matchInvokeInstruction(mg, ih, ii, enclosingShadow, shadowAccumulator);
  2667. }
  2668. }
  2669. } else if (world.isJoinpointArrayConstructionEnabled() && i.isArrayCreationInstruction()) {
  2670. if (canMatch(Shadow.ConstructorCall)) {
  2671. if (i.opcode == Constants.ANEWARRAY) {
  2672. // ANEWARRAY arrayInstruction = (ANEWARRAY)i;
  2673. // ObjectType arrayType = i.getLoadClassType(clazz.getConstantPool());
  2674. BcelShadow ctorCallShadow = BcelShadow.makeArrayConstructorCall(world, mg, ih, enclosingShadow);
  2675. match(ctorCallShadow, shadowAccumulator);
  2676. } else if (i.opcode == Constants.NEWARRAY) {
  2677. // NEWARRAY arrayInstruction = (NEWARRAY)i;
  2678. // Type arrayType = i.getType();
  2679. BcelShadow ctorCallShadow = BcelShadow.makeArrayConstructorCall(world, mg, ih, enclosingShadow);
  2680. match(ctorCallShadow, shadowAccumulator);
  2681. } else if (i instanceof MULTIANEWARRAY) {
  2682. // MULTIANEWARRAY arrayInstruction = (MULTIANEWARRAY) i;
  2683. // ObjectType arrayType = arrayInstruction.getLoadClassType(clazz.getConstantPool());
  2684. BcelShadow ctorCallShadow = BcelShadow.makeArrayConstructorCall(world, mg, ih, enclosingShadow);
  2685. match(ctorCallShadow, shadowAccumulator);
  2686. }
  2687. }
  2688. // see pr77166 if you are thinking about implementing this
  2689. // } else if (i instanceof AALOAD ) {
  2690. // AALOAD arrayLoad = (AALOAD)i;
  2691. // Type arrayType = arrayLoad.getType(clazz.getConstantPoolGen());
  2692. // BcelShadow arrayLoadShadow =
  2693. // BcelShadow.makeArrayLoadCall(world,mg,ih,enclosingShadow);
  2694. // match(arrayLoadShadow,shadowAccumulator);
  2695. // } else if (i instanceof AASTORE) {
  2696. // // ... magic required
  2697. } else if (world.isJoinpointSynchronizationEnabled()
  2698. && ((i.getOpcode() == Constants.MONITORENTER) || (i.getOpcode() == Constants.MONITOREXIT))) {
  2699. // if (canMatch(Shadow.Monitoring)) {
  2700. if (i.getOpcode() == Constants.MONITORENTER) {
  2701. BcelShadow monitorEntryShadow = BcelShadow.makeMonitorEnter(world, mg, ih, enclosingShadow);
  2702. match(monitorEntryShadow, shadowAccumulator);
  2703. } else {
  2704. BcelShadow monitorExitShadow = BcelShadow.makeMonitorExit(world, mg, ih, enclosingShadow);
  2705. match(monitorExitShadow, shadowAccumulator);
  2706. }
  2707. // }
  2708. }
  2709. }
  2710. private boolean isInitFailureHandler(InstructionHandle ih) {
  2711. // Skip the astore_0 and aload_0 at the start of the handler and
  2712. // then check if the instruction following these is
  2713. // 'putstatic ajc$initFailureCause'. If it is then we are
  2714. // in the handler we created in AspectClinit.generatePostSyntheticCode()
  2715. InstructionHandle twoInstructionsAway = ih.getNext().getNext();
  2716. if (twoInstructionsAway.getInstruction().opcode == Constants.PUTSTATIC) {
  2717. String name = ((FieldInstruction) twoInstructionsAway.getInstruction()).getFieldName(cpg);
  2718. if (name.equals(NameMangler.INITFAILURECAUSE_FIELD_NAME)) {
  2719. return true;
  2720. }
  2721. }
  2722. return false;
  2723. }
  2724. private void matchSetInstruction(LazyMethodGen mg, InstructionHandle ih, BcelShadow enclosingShadow,
  2725. List<BcelShadow> shadowAccumulator) {
  2726. FieldInstruction fi = (FieldInstruction) ih.getInstruction();
  2727. Member field = BcelWorld.makeFieldJoinPointSignature(clazz, fi);
  2728. // synthetic fields are never join points
  2729. if (field.getName().startsWith(NameMangler.PREFIX)) {
  2730. return;
  2731. }
  2732. ResolvedMember resolvedField = field.resolve(world);
  2733. if (resolvedField == null) {
  2734. // we can't find the field, so it's not a join point.
  2735. return;
  2736. } else if (Modifier.isFinal(resolvedField.getModifiers())
  2737. && Utility.isConstantPushInstruction(ih.getPrev().getInstruction())) {
  2738. // it's the set of a final constant, so it's
  2739. // not a join point according to 1.0.6 and 1.1.
  2740. return;
  2741. } else if (resolvedField.isSynthetic()) {
  2742. // sets of synthetics aren't join points in 1.1
  2743. return;
  2744. } else {
  2745. // Fix for bug 172107 (similar the "get" fix for bug 109728)
  2746. BcelShadow bs = BcelShadow.makeFieldSet(world, resolvedField, mg, ih, enclosingShadow);
  2747. String cname = fi.getClassName(cpg);
  2748. if (!resolvedField.getDeclaringType().getName().equals(cname)) {
  2749. bs.setActualTargetType(cname);
  2750. }
  2751. match(bs, shadowAccumulator);
  2752. }
  2753. }
  2754. private void matchGetInstruction(LazyMethodGen mg, InstructionHandle ih, BcelShadow enclosingShadow,
  2755. List<BcelShadow> shadowAccumulator) {
  2756. FieldInstruction fi = (FieldInstruction) ih.getInstruction();
  2757. Member field = BcelWorld.makeFieldJoinPointSignature(clazz, fi);
  2758. // synthetic fields are never join points
  2759. if (field.getName().startsWith(NameMangler.PREFIX)) {
  2760. return;
  2761. }
  2762. ResolvedMember resolvedField = field.resolve(world);
  2763. if (resolvedField == null) {
  2764. // we can't find the field, so it's not a join point.
  2765. return;
  2766. } else if (resolvedField.isSynthetic()) {
  2767. // sets of synthetics aren't join points in 1.1
  2768. return;
  2769. } else {
  2770. BcelShadow bs = BcelShadow.makeFieldGet(world, resolvedField, mg, ih, enclosingShadow);
  2771. String cname = fi.getClassName(cpg);
  2772. if (!resolvedField.getDeclaringType().getName().equals(cname)) {
  2773. bs.setActualTargetType(cname);
  2774. }
  2775. match(bs, shadowAccumulator);
  2776. }
  2777. }
  2778. /**
  2779. * For some named resolved type, this method looks for a member with a particular name - it should only be used when you truly
  2780. * believe there is only one member with that name in the type as it returns the first one it finds.
  2781. */
  2782. private ResolvedMember findResolvedMemberNamed(ResolvedType type, String methodName) {
  2783. ResolvedMember[] allMethods = type.getDeclaredMethods();
  2784. for (int i = 0; i < allMethods.length; i++) {
  2785. ResolvedMember member = allMethods[i];
  2786. if (member.getName().equals(methodName)) {
  2787. return member;
  2788. }
  2789. }
  2790. return null;
  2791. }
  2792. /**
  2793. * Find the specified member in the specified type.
  2794. *
  2795. * @param type the type to search for the member
  2796. * @param methodName the name of the method to find
  2797. * @param params the method parameters that the discovered method should have
  2798. */
  2799. private ResolvedMember findResolvedMemberNamed(ResolvedType type, String methodName, UnresolvedType[] params) {
  2800. ResolvedMember[] allMethods = type.getDeclaredMethods();
  2801. List<ResolvedMember> candidates = new ArrayList<ResolvedMember>();
  2802. for (int i = 0; i < allMethods.length; i++) {
  2803. ResolvedMember candidate = allMethods[i];
  2804. if (candidate.getName().equals(methodName)) {
  2805. if (candidate.getArity() == params.length) {
  2806. candidates.add(candidate);
  2807. }
  2808. }
  2809. }
  2810. if (candidates.size() == 0) {
  2811. return null;
  2812. } else if (candidates.size() == 1) {
  2813. return candidates.get(0);
  2814. } else {
  2815. // multiple candidates
  2816. for (ResolvedMember candidate : candidates) {
  2817. // These checks will break down with generics... but that would need two ITDs with the same name, same arity and
  2818. // generics
  2819. boolean allOK = true;
  2820. UnresolvedType[] candidateParams = candidate.getParameterTypes();
  2821. for (int p = 0; p < candidateParams.length; p++) {
  2822. if (!candidateParams[p].getErasureSignature().equals(params[p].getErasureSignature())) {
  2823. allOK = false;
  2824. break;
  2825. }
  2826. }
  2827. if (allOK) {
  2828. return candidate;
  2829. }
  2830. }
  2831. }
  2832. return null;
  2833. }
  2834. /**
  2835. * For a given resolvedmember, this will discover the real annotations for it. <b>Should only be used when the resolvedmember is
  2836. * the contents of an effective signature attribute, as thats the only time when the annotations aren't stored directly in the
  2837. * resolvedMember</b>
  2838. *
  2839. * @param rm the sig we want it to pretend to be 'int A.m()' or somesuch ITD like thing
  2840. * @param declaredSig the real sig 'blah.ajc$xxx'
  2841. */
  2842. private void fixParameterNamesForResolvedMember(ResolvedMember rm, ResolvedMember declaredSig) {
  2843. UnresolvedType memberHostType = declaredSig.getDeclaringType();
  2844. String methodName = declaredSig.getName();
  2845. String[] pnames = null;
  2846. if (rm.getKind() == Member.METHOD && !rm.isAbstract()) {
  2847. if (methodName.startsWith("ajc$inlineAccessMethod") || methodName.startsWith("ajc$superDispatch")) {
  2848. ResolvedMember resolvedDooberry = world.resolve(declaredSig);
  2849. pnames = resolvedDooberry.getParameterNames();
  2850. } else {
  2851. ResolvedMember realthing = AjcMemberMaker.interMethodDispatcher(rm.resolve(world), memberHostType).resolve(world);
  2852. ResolvedMember theRealMember = findResolvedMemberNamed(memberHostType.resolve(world), realthing.getName());
  2853. if (theRealMember != null) {
  2854. pnames = theRealMember.getParameterNames();
  2855. // static ITDs don't need any parameter shifting
  2856. if (pnames.length > 0 && pnames[0].equals("ajc$this_")) {
  2857. String[] pnames2 = new String[pnames.length - 1];
  2858. System.arraycopy(pnames, 1, pnames2, 0, pnames2.length);
  2859. pnames = pnames2;
  2860. }
  2861. }
  2862. }
  2863. // i think ctors are missing from here... copy code from below...
  2864. }
  2865. rm.setParameterNames(pnames);
  2866. }
  2867. /**
  2868. * For a given resolvedmember, this will discover the real annotations for it. <b>Should only be used when the resolvedmember is
  2869. * the contents of an effective signature attribute, as thats the only time when the annotations aren't stored directly in the
  2870. * resolvedMember</b>
  2871. *
  2872. * @param rm the sig we want it to pretend to be 'int A.m()' or somesuch ITD like thing
  2873. * @param declaredSig the real sig 'blah.ajc$xxx'
  2874. */
  2875. private void fixAnnotationsForResolvedMember(ResolvedMember rm, ResolvedMember declaredSig) {
  2876. try {
  2877. UnresolvedType memberHostType = declaredSig.getDeclaringType();
  2878. boolean containsKey = mapToAnnotationHolder.containsKey(rm);
  2879. ResolvedMember realAnnotationHolder = mapToAnnotationHolder.get(rm);
  2880. String methodName = declaredSig.getName();
  2881. // FIXME asc shouldnt really rely on string names !
  2882. if (!containsKey) {
  2883. if (rm.getKind() == Member.FIELD) {
  2884. if (methodName.startsWith("ajc$inlineAccessField")) {
  2885. realAnnotationHolder = world.resolve(rm);
  2886. } else {
  2887. ResolvedMember realthing = AjcMemberMaker.interFieldInitializer(rm, memberHostType);
  2888. realAnnotationHolder = world.resolve(realthing);
  2889. }
  2890. } else if (rm.getKind() == Member.METHOD && !rm.isAbstract()) {
  2891. if (methodName.startsWith("ajc$inlineAccessMethod") || methodName.startsWith("ajc$superDispatch")) {
  2892. realAnnotationHolder = world.resolve(declaredSig);
  2893. } else {
  2894. ResolvedMember realthing = AjcMemberMaker.interMethodDispatcher(rm.resolve(world), memberHostType).resolve(world);
  2895. realAnnotationHolder = findResolvedMemberNamed(memberHostType.resolve(world), realthing.getName(),realthing.getParameterTypes());
  2896. if (realAnnotationHolder == null) {
  2897. throw new UnsupportedOperationException(
  2898. "Known limitation in M4 - can't find ITD members when type variable is used as an argument and has upper bound specified");
  2899. }
  2900. }
  2901. } else if (rm.getKind() == Member.CONSTRUCTOR) {
  2902. ResolvedMember realThing = AjcMemberMaker.postIntroducedConstructor(memberHostType.resolve(world),rm.getDeclaringType(), rm.getParameterTypes());
  2903. realAnnotationHolder = world.resolve(realThing);
  2904. // AMC temp guard for M4
  2905. if (realAnnotationHolder == null) {
  2906. throw new UnsupportedOperationException("Known limitation in M4 - can't find ITD members when type variable is used as an argument and has upper bound specified");
  2907. }
  2908. }
  2909. mapToAnnotationHolder.put(rm, realAnnotationHolder);
  2910. }
  2911. ResolvedType[] annotationTypes;
  2912. AnnotationAJ[] annotations;
  2913. if (realAnnotationHolder!=null) {
  2914. annotationTypes = realAnnotationHolder.getAnnotationTypes();
  2915. annotations = realAnnotationHolder.getAnnotations();
  2916. if (annotationTypes==null) {
  2917. annotationTypes = ResolvedType.EMPTY_ARRAY;
  2918. }
  2919. if (annotations==null) {
  2920. annotations = AnnotationAJ.EMPTY_ARRAY;
  2921. }
  2922. } else {
  2923. annotations = AnnotationAJ.EMPTY_ARRAY;
  2924. annotationTypes = ResolvedType.EMPTY_ARRAY;
  2925. }
  2926. rm.setAnnotations(annotations);
  2927. rm.setAnnotationTypes(annotationTypes);
  2928. } catch (UnsupportedOperationException ex) {
  2929. throw ex;
  2930. } catch (Throwable t) {
  2931. // FIXME asc remove this catch after more testing has confirmed the
  2932. // above stuff is OK
  2933. throw new BCException("Unexpectedly went bang when searching for annotations on " + rm, t);
  2934. }
  2935. }
  2936. private void matchInvokeInstruction(LazyMethodGen mg, InstructionHandle ih, InvokeInstruction invoke,
  2937. BcelShadow enclosingShadow, List<BcelShadow> shadowAccumulator) {
  2938. String methodName = invoke.getName(cpg);
  2939. if (methodName.startsWith(NameMangler.PREFIX)) {
  2940. Member jpSig = world.makeJoinPointSignatureForMethodInvocation(clazz, invoke);
  2941. ResolvedMember declaredSig = jpSig.resolve(world);
  2942. // System.err.println(method + ", declaredSig: " +declaredSig);
  2943. if (declaredSig == null) {
  2944. return;
  2945. }
  2946. if (declaredSig.getKind() == Member.FIELD) {
  2947. Shadow.Kind kind;
  2948. if (jpSig.getReturnType().equals(UnresolvedType.VOID)) {
  2949. kind = Shadow.FieldSet;
  2950. } else {
  2951. kind = Shadow.FieldGet;
  2952. }
  2953. if (canMatch(Shadow.FieldGet) || canMatch(Shadow.FieldSet)) {
  2954. match(BcelShadow.makeShadowForMethodCall(world, mg, ih, enclosingShadow, kind, declaredSig), shadowAccumulator);
  2955. }
  2956. } else if (!declaredSig.getName().startsWith(NameMangler.PREFIX)) {
  2957. // 307147 - resolution above may have found the real method directly rather
  2958. // than needing to go through the effective signature attribute
  2959. if (canMatch(Shadow.MethodCall)) {
  2960. match(BcelShadow.makeShadowForMethodCall(world, mg, ih, enclosingShadow, Shadow.MethodCall, declaredSig),
  2961. shadowAccumulator);
  2962. }
  2963. } else {
  2964. AjAttribute.EffectiveSignatureAttribute effectiveSig = declaredSig.getEffectiveSignature();
  2965. if (effectiveSig == null) {
  2966. return;
  2967. }
  2968. // System.err.println("call to inter-type member: " +
  2969. // effectiveSig);
  2970. if (effectiveSig.isWeaveBody()) {
  2971. return;
  2972. }
  2973. ResolvedMember rm = effectiveSig.getEffectiveSignature();
  2974. fixParameterNamesForResolvedMember(rm, declaredSig);
  2975. fixAnnotationsForResolvedMember(rm, declaredSig); // abracadabra
  2976. if (canMatch(effectiveSig.getShadowKind())) {
  2977. match(BcelShadow.makeShadowForMethodCall(world, mg, ih, enclosingShadow, effectiveSig.getShadowKind(), rm),
  2978. shadowAccumulator);
  2979. }
  2980. }
  2981. } else {
  2982. if (canMatch(Shadow.MethodCall)) {
  2983. boolean proceed = true;
  2984. // overweaving needs to ignore some calls added by the previous weave
  2985. if (world.isOverWeaving()) {
  2986. String s = invoke.getClassName(mg.getConstantPool());
  2987. // skip all the inc/dec/isValid/etc
  2988. if (s.length() > 4
  2989. && s.charAt(4) == 'a'
  2990. && (s.equals("org.aspectj.runtime.internal.CFlowCounter")
  2991. || s.equals("org.aspectj.runtime.internal.CFlowStack") || s
  2992. .equals("org.aspectj.runtime.reflect.Factory"))) {
  2993. proceed = false;
  2994. } else {
  2995. if (methodName.equals("aspectOf")) {
  2996. proceed = false;
  2997. }
  2998. }
  2999. }
  3000. if (methodName.startsWith(SWITCH_TABLE_SYNTHETIC_METHOD_PREFIX)) {
  3001. proceed = false;
  3002. }
  3003. if (proceed) {
  3004. match(BcelShadow.makeMethodCall(world, mg, ih, enclosingShadow), shadowAccumulator);
  3005. }
  3006. }
  3007. }
  3008. }
  3009. // static ... so all worlds will share the config for the first one
  3010. // created...
  3011. private static boolean checkedXsetForLowLevelContextCapturing = false;
  3012. private static boolean captureLowLevelContext = false;
  3013. private boolean match(BcelShadow shadow, List<BcelShadow> shadowAccumulator) {
  3014. // Duplicate blocks - one with context one without, seems faster than multiple 'ifs'
  3015. if (captureLowLevelContext) {
  3016. ContextToken shadowMatchToken = CompilationAndWeavingContext.enteringPhase(
  3017. CompilationAndWeavingContext.MATCHING_SHADOW, shadow);
  3018. boolean isMatched = false;
  3019. Shadow.Kind shadowKind = shadow.getKind();
  3020. List<ShadowMunger> candidateMungers = indexedShadowMungers[shadowKind.getKey()];
  3021. // System.out.println("Candidates " + candidateMungers);
  3022. if (candidateMungers != null) {
  3023. for (ShadowMunger munger : candidateMungers) {
  3024. ContextToken mungerMatchToken = CompilationAndWeavingContext.enteringPhase(
  3025. CompilationAndWeavingContext.MATCHING_POINTCUT, munger.getPointcut());
  3026. if (munger.match(shadow, world)) {
  3027. shadow.addMunger(munger);
  3028. isMatched = true;
  3029. if (shadow.getKind() == Shadow.StaticInitialization) {
  3030. clazz.warnOnAddedStaticInitializer(shadow, munger.getSourceLocation());
  3031. }
  3032. }
  3033. CompilationAndWeavingContext.leavingPhase(mungerMatchToken);
  3034. }
  3035. if (isMatched) {
  3036. shadowAccumulator.add(shadow);
  3037. }
  3038. }
  3039. CompilationAndWeavingContext.leavingPhase(shadowMatchToken);
  3040. return isMatched;
  3041. } else {
  3042. boolean isMatched = false;
  3043. Shadow.Kind shadowKind = shadow.getKind();
  3044. List<ShadowMunger> candidateMungers = indexedShadowMungers[shadowKind.getKey()];
  3045. // System.out.println("Candidates at " + shadowKind + " are " + candidateMungers);
  3046. if (candidateMungers != null) {
  3047. for (ShadowMunger munger : candidateMungers) {
  3048. if (munger.match(shadow, world)) {
  3049. shadow.addMunger(munger);
  3050. isMatched = true;
  3051. if (shadow.getKind() == Shadow.StaticInitialization) {
  3052. clazz.warnOnAddedStaticInitializer(shadow, munger.getSourceLocation());
  3053. }
  3054. }
  3055. }
  3056. if (isMatched) {
  3057. shadowAccumulator.add(shadow);
  3058. }
  3059. }
  3060. return isMatched;
  3061. }
  3062. }
  3063. // ----
  3064. private void implement(LazyMethodGen mg) {
  3065. List<BcelShadow> shadows = mg.matchedShadows;
  3066. if (shadows == null) {
  3067. return;
  3068. }
  3069. // We depend on a partial order such that inner shadows are earlier on
  3070. // the list than outer shadows. That's fine. This order is preserved if:
  3071. // A preceeds B iff B.getStart() is LATER THAN A.getStart().
  3072. for (BcelShadow shadow : shadows) {
  3073. ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.IMPLEMENTING_ON_SHADOW,
  3074. shadow);
  3075. shadow.implement();
  3076. CompilationAndWeavingContext.leavingPhase(tok);
  3077. }
  3078. // int ii =
  3079. mg.getMaxLocals();
  3080. mg.matchedShadows = null;
  3081. }
  3082. // ----
  3083. public LazyClassGen getLazyClassGen() {
  3084. return clazz;
  3085. }
  3086. public BcelWorld getWorld() {
  3087. return world;
  3088. }
  3089. public void setReweavableMode(boolean mode) {
  3090. inReweavableMode = mode;
  3091. }
  3092. public boolean getReweavableMode() {
  3093. return inReweavableMode;
  3094. }
  3095. @Override
  3096. public String toString() {
  3097. return "BcelClassWeaver instance for : " + clazz;
  3098. }
  3099. }