Produced by Araxis Merge on 9/25/2018 2:13:07 PM Central Daylight Time. See www.araxis.com for information about Merge. This report uses XHTML and CSS2, and is best viewed with a modern standards-compliant browser. For optimum results when printing this report, use landscape orientation and enable printing of background images and colours in your browser.
# | Location | File | Last Modified |
---|---|---|---|
1 | build 3.zip\build 3\MHLTH_YS_137_Source\JavaScript\resources\javaJDF-1.8.0\src\com\sun\tools\javac\jvm | Gen.java | Mon Jan 22 14:47:06 2018 UTC |
2 | build 3.zip\build 3\MHLTH_YS_137_Source\JavaScript\resources\javaJDF-1.8.0\src\com\sun\tools\javac\jvm | Gen.java | Wed Sep 12 16:49:51 2018 UTC |
Description | Between Files 1 and 2 |
|
---|---|---|
Text Blocks | Lines | |
Unchanged | 3 | 5072 |
Changed | 2 | 4 |
Inserted | 0 | 0 |
Removed | 0 | 0 |
Whitespace | |
---|---|
Character case | Differences in character case are significant |
Line endings | Differences in line endings (CR and LF characters) are ignored |
CR/LF characters | Not shown in the comparison detail |
No regular expressions were active.
1 | /* | |
2 | * Copyrig ht (c) 199 9, 2015, O racle and/ or its aff iliates. A ll rights reserved. | |
3 | * DO NOT ALTER OR R EMOVE COPY RIGHT NOTI CES OR THI S FILE HEA DER. | |
4 | * | |
5 | * This co de is free software; you can r edistribut e it and/o r modify i t | |
6 | * under t he terms o f the GNU General Pu blic Licen se version 2 only, a s | |
7 | * publish ed by the Free Softw are Founda tion. Ora cle design ates this | |
8 | * particu lar file a s subject to the "Cl asspath" e xception a s provided | |
9 | * by Orac le in the LICENSE fi le that ac companied this code. | |
10 | * | |
11 | * This co de is dist ributed in the hope that it wi ll be usef ul, but WI THOUT | |
12 | * ANY WAR RANTY; wit hout even the implie d warranty of MERCHA NTABILITY or | |
13 | * FITNESS FOR A PAR TICULAR PU RPOSE. Se e the GNU General Pu blic Licen se | |
14 | * version 2 for mor e details (a copy is included in the LIC ENSE file that | |
15 | * accompa nied this code). | |
16 | * | |
17 | * You sho uld have r eceived a copy of th e GNU Gene ral Public License v ersion | |
18 | * 2 along with this work; if not, write to the Fr ee Softwar e Foundati on, | |
19 | * Inc., 5 1 Franklin St, Fifth Floor, Bo ston, MA 0 2110-1301 USA. | |
20 | * | |
21 | * Please contact Or acle, 500 Oracle Par kway, Redw ood Shores , CA 94065 USA | |
22 | * or visi t www.orac le.com if you need a dditional informatio n or have any | |
23 | * questio ns. | |
24 | */ | |
25 | ||
26 | package co m.sun.tool s.javac.jv m; | |
27 | ||
28 | import jav a.util.*; | |
29 | ||
30 | import com .sun.tools .javac.tre e.TreeInfo .PosKind; | |
31 | import com .sun.tools .javac.uti l.*; | |
32 | import com .sun.tools .javac.uti l.JCDiagno stic.Diagn osticPosit ion; | |
33 | import com .sun.tools .javac.uti l.List; | |
34 | import com .sun.tools .javac.cod e.*; | |
35 | import com .sun.tools .javac.cod e.Attribut e.TypeComp ound; | |
36 | import com .sun.tools .javac.cod e.Symbol.V arSymbol; | |
37 | import com .sun.tools .javac.com p.*; | |
38 | import com .sun.tools .javac.tre e.*; | |
39 | ||
40 | import com .sun.tools .javac.cod e.Symbol.* ; | |
41 | import com .sun.tools .javac.cod e.Type.*; | |
42 | import com .sun.tools .javac.jvm .Code.*; | |
43 | import com .sun.tools .javac.jvm .Items.*; | |
44 | import com .sun.tools .javac.tre e.EndPosTa ble; | |
45 | import com .sun.tools .javac.tre e.JCTree.* ; | |
46 | ||
47 | import sta tic com.su n.tools.ja vac.code.F lags.*; | |
48 | import sta tic com.su n.tools.ja vac.code.K inds.*; | |
49 | import sta tic com.su n.tools.ja vac.code.T ypeTag.*; | |
50 | import sta tic com.su n.tools.ja vac.jvm.By teCodes.*; | |
51 | import sta tic com.su n.tools.ja vac.jvm.CR TFlags.*; | |
52 | import sta tic com.su n.tools.ja vac.main.O ption.*; | |
53 | import sta tic com.su n.tools.ja vac.tree.J CTree.Tag. *; | |
54 | ||
55 | /** This p ass maps f lat Java ( i.e. witho ut inner c lasses) to bytecodes . | |
56 | * | |
57 | * <p><b> This is NO T part of any suppor ted API. | |
58 | * If you write cod e that dep ends on th is, you do so at you r own risk . | |
59 | * This c ode and it s internal interface s are subj ect to cha nge or | |
60 | * deleti on without notice.</ b> | |
61 | */ | |
62 | public cla ss Gen ext ends JCTre e.Visitor { | |
63 | protec ted static final Con text.Key<G en> genKey = | |
64 | ne w Context. Key<Gen>() ; | |
65 | ||
66 | privat e final Lo g log; | |
67 | privat e final Sy mtab syms; | |
68 | privat e final Ch eck chk; | |
69 | privat e final Re solve rs; | |
70 | privat e final Tr eeMaker ma ke; | |
71 | privat e final Na mes names; | |
72 | privat e final Ta rget targe t; | |
73 | privat e final Ty pe stringB ufferType; | |
74 | privat e final Ma p<Type,Sym bol> strin gBufferApp end; | |
75 | privat e Name acc essDollar; | |
76 | privat e final Ty pes types; | |
77 | privat e final Lo wer lower; | |
78 | privat e final Fl ow flow; | |
79 | ||
80 | /** Sw itch: GJ m ode? | |
81 | */ | |
82 | privat e final bo olean allo wGenerics; | |
83 | ||
84 | /** Se t when Mir anda metho d stubs ar e to be ge nerated. * / | |
85 | privat e final bo olean gene rateIproxi es; | |
86 | ||
87 | /** Fo rmat of st ackmap tab les to be generated. */ | |
88 | privat e final Co de.StackMa pFormat st ackMap; | |
89 | ||
90 | /** A type that serves as the expect ed type fo r all meth od express ions. | |
91 | */ | |
92 | privat e final Ty pe methodT ype; | |
93 | ||
94 | public static Ge n instance (Context c ontext) { | |
95 | Ge n instance = context .get(genKe y); | |
96 | if (instance == null) | |
97 | instance = new Gen (context); | |
98 | re turn insta nce; | |
99 | } | |
100 | ||
101 | /** Co nstant poo l, reset b y genClass . | |
102 | */ | |
103 | privat e Pool poo l; | |
104 | ||
105 | privat e final bo olean type AnnoAssert s; | |
106 | ||
107 | protec ted Gen(Co ntext cont ext) { | |
108 | co ntext.put( genKey, th is); | |
109 | ||
110 | na mes = Name s.instance (context); | |
111 | lo g = Log.in stance(con text); | |
112 | sy ms = Symta b.instance (context); | |
113 | ch k = Check. instance(c ontext); | |
114 | rs = Resolve .instance( context); | |
115 | ma ke = TreeM aker.insta nce(contex t); | |
116 | ta rget = Tar get.instan ce(context ); | |
117 | ty pes = Type s.instance (context); | |
118 | me thodType = new Metho dType(null , null, nu ll, syms.m ethodClass ); | |
119 | al lowGeneric s = Source .instance( context).a llowGeneri cs(); | |
120 | st ringBuffer Type = tar get.useStr ingBuilder () | |
121 | ? syms.s tringBuild erType | |
122 | : syms.s tringBuffe rType; | |
123 | st ringBuffer Append = n ew HashMap <Type,Symb ol>(); | |
124 | ac cessDollar = names. | |
125 | fromStri ng("access " + target .synthetic NameChar() ); | |
126 | fl ow = Flow. instance(c ontext); | |
127 | lo wer = Lowe r.instance (context); | |
128 | ||
129 | Op tions opti ons = Opti ons.instan ce(context ); | |
130 | li neDebugInf o = | |
131 | options. isUnset(G_ CUSTOM) || | |
132 | options. isSet(G_CU STOM, "lin es"); | |
133 | va rDebugInfo = | |
134 | options. isUnset(G_ CUSTOM) | |
135 | ? option s.isSet(G) | |
136 | : option s.isSet(G_ CUSTOM, "v ars"); | |
137 | ge nCrt = opt ions.isSet (XJCOV); | |
138 | de bugCode = options.is Set("debug code"); | |
139 | al lowInvoked ynamic = t arget.hasI nvokedynam ic() || op tions.isSe t("invoked ynamic"); | |
140 | po ol = new P ool(types) ; | |
141 | ty peAnnoAsse rts = opti ons.isSet( "TypeAnnot ationAsser ts"); | |
142 | ||
143 | ge nerateIpro xies = | |
144 | target.r equiresIpr oxy() || | |
145 | options. isSet("mir anda"); | |
146 | ||
147 | if (target.g enerateSta ckMapTable ()) { | |
148 | // ignor e cldc bec ause we ca nnot have both stack map format s | |
149 | this.sta ckMap = St ackMapForm at.JSR202; | |
150 | } else { | |
151 | if (targ et.generat eCLDCStack map()) { | |
152 | this .stackMap = StackMap Format.CLD C; | |
153 | } else { | |
154 | this .stackMap = StackMap Format.NON E; | |
155 | } | |
156 | } | |
157 | ||
158 | // by defaul t, avoid j sr's for s imple fina lizers | |
159 | in t setjsrli mit = 50; | |
160 | St ring jsrli mitString = options. get("jsrli mit"); | |
161 | if (jsrlimit String != null) { | |
162 | try { | |
163 | setj srlimit = Integer.pa rseInt(jsr limitStrin g); | |
164 | } catch (NumberFor matExcepti on ex) { | |
165 | // i gnore ill- formed num bers for j srlimit | |
166 | } | |
167 | } | |
168 | th is.jsrlimi t = setjsr limit; | |
169 | th is.useJsrL ocally = f alse; // r eset in vi sitTry | |
170 | } | |
171 | ||
172 | /** Sw itches | |
173 | */ | |
174 | privat e final bo olean line DebugInfo; | |
175 | privat e final bo olean varD ebugInfo; | |
176 | privat e final bo olean genC rt; | |
177 | privat e final bo olean debu gCode; | |
178 | privat e final bo olean allo wInvokedyn amic; | |
179 | ||
180 | /** De fault limi t of (appr oximate) s ize of fin alizer to inline. | |
181 | * Ze ro means a lways use jsr. 100 or greater means nev er use | |
182 | * js r. | |
183 | */ | |
184 | privat e final in t jsrlimit ; | |
185 | ||
186 | /** Tr ue if jsr is used. | |
187 | */ | |
188 | privat e boolean useJsrLoca lly; | |
189 | ||
190 | /** Co de buffer, set by ge nMethod. | |
191 | */ | |
192 | privat e Code cod e; | |
193 | ||
194 | /** It ems struct ure, set b y genMetho d. | |
195 | */ | |
196 | privat e Items it ems; | |
197 | ||
198 | /** En vironment for symbol lookup, s et by genC lass | |
199 | */ | |
200 | privat e Env<Attr Context> a ttrEnv; | |
201 | ||
202 | /** Th e top leve l tree. | |
203 | */ | |
204 | privat e JCCompil ationUnit toplevel; | |
205 | ||
206 | /** Th e number o f code-gen errors in this clas s. | |
207 | */ | |
208 | privat e int nerr s = 0; | |
209 | ||
210 | /** An object co ntaining m appings of syntax tr ees to the ir | |
211 | * en ding sourc e position s. | |
212 | */ | |
213 | EndPos Table endP osTable; | |
214 | ||
215 | /** Ge nerate cod e to load an integer constant. | |
216 | * @p aram n The integ er to be l oaded. | |
217 | */ | |
218 | void l oadIntCons t(int n) { | |
219 | it ems.makeIm mediateIte m(syms.int Type, n).l oad(); | |
220 | } | |
221 | ||
222 | /** Th e opcode t hat loads a zero con stant of a given typ e code. | |
223 | * @p aram tc The given type code (@see Byte Code). | |
224 | */ | |
225 | public static in t zero(int tc) { | |
226 | sw itch(tc) { | |
227 | ca se INTcode : case BYT Ecode: cas e SHORTcod e: case CH ARcode: | |
228 | return i const_0; | |
229 | ca se LONGcod e: | |
230 | return l const_0; | |
231 | ca se FLOATco de: | |
232 | return f const_0; | |
233 | ca se DOUBLEc ode: | |
234 | return d const_0; | |
235 | de fault: | |
236 | throw ne w Assertio nError("ze ro"); | |
237 | } | |
238 | } | |
239 | ||
240 | /** Th e opcode t hat loads a one cons tant of a given type code. | |
241 | * @p aram tc The given type code (@see Byte Code). | |
242 | */ | |
243 | public static in t one(int tc) { | |
244 | re turn zero( tc) + 1; | |
245 | } | |
246 | ||
247 | /** Ge nerate cod e to load -1 of the given type code (eit her int or long). | |
248 | * @p aram tc The given type code (@see Byte Code). | |
249 | */ | |
250 | void e mitMinusOn e(int tc) { | |
251 | if (tc == LO NGcode) { | |
252 | items.ma keImmediat eItem(syms .longType, new Long( -1)).load( ); | |
253 | } else { | |
254 | code.emi top0(icons t_m1); | |
255 | } | |
256 | } | |
257 | ||
258 | /** Co nstruct a symbol to reflect th e qualifyi ng type th at should | |
259 | * ap pear in th e byte cod e as per J LS 13.1. | |
260 | * | |
261 | * Fo r {@litera l target > = 1.2}: Cl one a meth od with th e qualifie r as owner (except | |
262 | * fo r those ca ses where we need to work arou nd VM bugs ). | |
263 | * | |
264 | * Fo r {@litera l target < = 1.1}: If qualified variable or method is defined in a | |
265 | * no n-accessib le class, clone it w ith the qu alifier cl ass as own er. | |
266 | * | |
267 | * @p aram sym The acce ssed symbo l | |
268 | * @p aram site The qual ifier's ty pe. | |
269 | */ | |
270 | Symbol binaryQua lifier(Sym bol sym, T ype site) { | |
271 | ||
272 | if (site.has Tag(ARRAY) ) { | |
273 | if (sym == syms.le ngthVar || | |
274 | sym. owner != s yms.arrayC lass) | |
275 | retu rn sym; | |
276 | // array clone can be qualif ied by the array typ e in later targets | |
277 | Symbol q ualifier = target.ar rayBinaryC ompatibili ty() | |
278 | ? ne w ClassSym bol(Flags. PUBLIC, si te.tsym.na me, | |
279 | site, syms.noSym bol) | |
280 | : sy ms.objectT ype.tsym; | |
281 | return s ym.clone(q ualifier); | |
282 | } | |
283 | ||
284 | if (sym.owne r == site. tsym || | |
285 | (sym.fla gs() & (ST ATIC | SYN THETIC)) = = (STATIC | SYNTHETI C)) { | |
286 | return s ym; | |
287 | } | |
288 | if (!target. obeyBinary Compatibil ity()) | |
289 | return r s.isAccess ible(attrE nv, (TypeS ymbol)sym. owner) | |
290 | ? sy m | |
291 | : sy m.clone(si te.tsym); | |
292 | ||
293 | if (!target. interfaceF ieldsBinar yCompatibi lity()) { | |
294 | if ((sym .owner.fla gs() & INT ERFACE) != 0 && sym. kind == VA R) | |
295 | retu rn sym; | |
296 | } | |
297 | ||
298 | // leave alo ne methods inherited from Obje ct | |
299 | // JLS 13.1. | |
300 | if (sym.owne r == syms. objectType .tsym) | |
301 | return s ym; | |
302 | ||
303 | if (!target. interfaceO bjectOverr idesBinary Compatibil ity()) { | |
304 | if ((sym .owner.fla gs() & INT ERFACE) != 0 && | |
305 | syms .objectTyp e.tsym.mem bers().loo kup(sym.na me).scope != null) | |
306 | retu rn sym; | |
307 | } | |
308 | ||
309 | re turn sym.c lone(site. tsym); | |
310 | } | |
311 | ||
312 | /** In sert a ref erence to given type in the co nstant poo l, | |
313 | * ch ecking for an array with too m any dimens ions; | |
314 | * re turn the r eference's index. | |
315 | * @p aram type The type for which a referen ce is inse rted. | |
316 | */ | |
317 | int ma keRef(Diag nosticPosi tion pos, Type type) { | |
318 | ch eckDimensi on(pos, ty pe); | |
319 | if (type.isA nnotated() ) { | |
320 | // Treat annotated types sep arately - we don't w ant | |
321 | // to co llapse all of them - at least for annota ted | |
322 | // excep tions. | |
323 | // TODO: review th is. | |
324 | return p ool.put((O bject)type ); | |
325 | } else { | |
326 | return p ool.put(ty pe.hasTag( CLASS) ? ( Object)typ e.tsym : ( Object)typ e); | |
327 | } | |
328 | } | |
329 | ||
330 | /** Ch eck if the given typ e is an ar ray with t oo many di mensions. | |
331 | */ | |
332 | privat e void che ckDimensio n(Diagnost icPosition pos, Type t) { | |
333 | sw itch (t.ge tTag()) { | |
334 | ca se METHOD: | |
335 | checkDim ension(pos , t.getRet urnType()) ; | |
336 | for (Lis t<Type> ar gs = t.get ParameterT ypes(); ar gs.nonEmpt y(); args = args.tai l) | |
337 | chec kDimension (pos, args .head); | |
338 | break; | |
339 | ca se ARRAY: | |
340 | if (type s.dimensio ns(t) > Cl assFile.MA X_DIMENSIO NS) { | |
341 | log. error(pos, "limit.di mensions") ; | |
342 | nerr s++; | |
343 | } | |
344 | break; | |
345 | de fault: | |
346 | break; | |
347 | } | |
348 | } | |
349 | ||
350 | /** Cr eate a tem pory varia ble. | |
351 | * @p aram type The vari able's typ e. | |
352 | */ | |
353 | LocalI tem makeTe mp(Type ty pe) { | |
354 | Va rSymbol v = new VarS ymbol(Flag s.SYNTHETI C, | |
355 | name s.empty, | |
356 | type , | |
357 | env. enclMethod .sym); | |
358 | co de.newLoca l(v); | |
359 | re turn items .makeLocal Item(v); | |
360 | } | |
361 | ||
362 | /** Ge nerate cod e to call a non-priv ate method or constr uctor. | |
363 | * @p aram pos Pos ition to b e used for error rep orting. | |
364 | * @p aram site The type of w hich the m ethod is a member. | |
365 | * @p aram name The method's name. | |
366 | * @p aram argty pes The method's argument t ypes. | |
367 | * @p aram isSta tic A f lag that i ndicates w hether we call a | |
368 | * sta tic or ins tance meth od. | |
369 | */ | |
370 | void c allMethod( Diagnostic Position p os, | |
371 | Type site, Name name , List<Typ e> argtype s, | |
372 | boolean is Static) { | |
373 | Sy mbol msym = rs. | |
374 | resolveI nternalMet hod(pos, a ttrEnv, si te, name, argtypes, null); | |
375 | if (isStatic ) items.ma keStaticIt em(msym).i nvoke(); | |
376 | el se items.m akeMemberI tem(msym, name == na mes.init). invoke(); | |
377 | } | |
378 | ||
379 | /** Is the given method de finition a n access m ethod | |
380 | * re sulting fr om a quali fied super ? This is signified by an odd | |
381 | * ac cess code. | |
382 | */ | |
383 | privat e boolean isAccessSu per(JCMeth odDecl enc lMethod) { | |
384 | re turn | |
385 | (enclMet hod.mods.f lags & SYN THETIC) != 0 && | |
386 | isOddAcc essName(en clMethod.n ame); | |
387 | } | |
388 | ||
389 | /** Do es given n ame start with "acce ss$" and e nd in an o dd digit? | |
390 | */ | |
391 | privat e boolean isOddAcces sName(Name name) { | |
392 | re turn | |
393 | name.sta rtsWith(ac cessDollar ) && | |
394 | (name.ge tByteAt(na me.getByte Length() - 1) & 1) = = 1; | |
395 | } | |
396 | ||
397 | /* ******* ********** ********** ********** ********** ********** ********** ***** | |
398 | * Non-loc al exits | |
399 | ********* ********** ********** ********** ********** ********** ********** ****/ | |
400 | ||
401 | /** Ge nerate cod e to invok e the fina lizer asso ciated wit h given | |
402 | * en vironment. | |
403 | * An y calls to finalizer s are appe nded to th e environm ents `cont ' chain. | |
404 | * Ma rk beginni ng of gap in catch a ll range f or finaliz er. | |
405 | */ | |
406 | void g enFinalize r(Env<GenC ontext> en v) { | |
407 | if (code.isA live() && env.info.f inalize != null) | |
408 | env.info .finalize. gen(); | |
409 | } | |
410 | ||
411 | /** Ge nerate cod e to call all finali zers of st ructures a borted by | |
412 | * a non-local | |
413 | * ex it. Retur n target e nvironment of the no n-local ex it. | |
414 | * @p aram targe t The tree repr esenting t he structu re that's aborted | |
415 | * @p aram env The environme nt current at the no n-local ex it. | |
416 | */ | |
417 | Env<Ge nContext> unwind(JCT ree target , Env<GenC ontext> en v) { | |
418 | En v<GenConte xt> env1 = env; | |
419 | wh ile (true) { | |
420 | genFinal izer(env1) ; | |
421 | if (env1 .tree == t arget) bre ak; | |
422 | env1 = e nv1.next; | |
423 | } | |
424 | re turn env1; | |
425 | } | |
426 | ||
427 | /** Ma rk end of gap in cat ch-all ran ge for fin alizer. | |
428 | * @p aram env the envir onment whi ch might c ontain the finalizer | |
429 | * (if it do es, env.in fo.gaps != null). | |
430 | */ | |
431 | void e ndFinalize rGap(Env<G enContext> env) { | |
432 | if (env.info .gaps != n ull && env .info.gaps .length() % 2 == 1) | |
433 | env.info .gaps.appe nd(code.cu rCP()); | |
434 | } | |
435 | ||
436 | /** Ma rk end of all gaps i n catch-al l ranges f or finaliz ers of env ironments | |
437 | * ly ing betwee n, and inc luding to two enviro nments. | |
438 | * @p aram from the mos t deeply n ested envi ronment to mark | |
439 | * @p aram to the lea st deeply nested env ironment t o mark | |
440 | */ | |
441 | void e ndFinalize rGaps(Env< GenContext > from, En v<GenConte xt> to) { | |
442 | En v<GenConte xt> last = null; | |
443 | wh ile (last != to) { | |
444 | endFinal izerGap(fr om); | |
445 | last = f rom; | |
446 | from = f rom.next; | |
447 | } | |
448 | } | |
449 | ||
450 | /** Do any of th e structur es aborted by a non- local exit have | |
451 | * fi nalizers t hat requir e an empty stack? | |
452 | * @p aram targe t The tree repr esenting t he structu re that's aborted | |
453 | * @p aram env The environme nt current at the no n-local ex it. | |
454 | */ | |
455 | boolea n hasFinal ly(JCTree target, En v<GenConte xt> env) { | |
456 | wh ile (env.t ree != tar get) { | |
457 | if (env. tree.hasTa g(TRY) && env.info.f inalize.ha sFinalizer ()) | |
458 | retu rn true; | |
459 | env = en v.next; | |
460 | } | |
461 | re turn false ; | |
462 | } | |
463 | ||
464 | /* ******* ********** ********** ********** ********** ********** ********** ***** | |
465 | * Normali zing class -members. | |
466 | ********* ********** ********** ********** ********** ********** ********** ****/ | |
467 | ||
468 | /** Di stribute m ember init ializer co de into co nstructors and {@cod e <clinit> } | |
469 | * me thod. | |
470 | * @p aram defs Th e list of class memb er declara tions. | |
471 | * @p aram c Th e enclosin g class. | |
472 | */ | |
473 | List<J CTree> nor malizeDefs (List<JCTr ee> defs, ClassSymbo l c) { | |
474 | Li stBuffer<J CStatement > initCode = new Lis tBuffer<JC Statement> (); | |
475 | Li stBuffer<A ttribute.T ypeCompoun d> initTAs = new Lis tBuffer<At tribute.Ty peCompound >(); | |
476 | Li stBuffer<J CStatement > clinitCo de = new L istBuffer< JCStatemen t>(); | |
477 | Li stBuffer<A ttribute.T ypeCompoun d> clinitT As = new L istBuffer< Attribute. TypeCompou nd>(); | |
478 | Li stBuffer<J CTree> met hodDefs = new ListBu ffer<JCTre e>(); | |
479 | // Sort defi nitions in to three l istbuffers : | |
480 | // - initCo de for ins tance init ializers | |
481 | // - clinit Code for c lass initi alizers | |
482 | // - method Defs for m ethod defi nitions | |
483 | fo r (List<JC Tree> l = defs; l.no nEmpty(); l = l.tail ) { | |
484 | JCTree d ef = l.hea d; | |
485 | switch ( def.getTag ()) { | |
486 | case BLO CK: | |
487 | JCBl ock block = (JCBlock )def; | |
488 | if ( (block.fla gs & STATI C) != 0) | |
489 | clinitCode .append(bl ock); | |
490 | else if ((bloc k.flags & SYNTHETIC) == 0) | |
491 | initCode.a ppend(bloc k); | |
492 | brea k; | |
493 | case MET HODDEF: | |
494 | meth odDefs.app end(def); | |
495 | brea k; | |
496 | case
|
|
497 | JCVa riableDecl vdef = (J CVariableD ecl) def; | |
498 | VarS ymbol sym = vdef.sym ; | |
499 | chec kDimension (vdef.pos( ), sym.typ e); | |
500 | if ( vdef.init != null) { | |
501 | if ((sym.f lags() & S TATIC) == 0) { | |
502 | // Alw ays initia lize insta nce variab les. | |
503 | JCStat ement init = make.at (vdef.pos( )). | |
504 | As signment(s ym, vdef.i nit); | |
505 | initCo de.append( init); | |
506 | endPos Table.repl aceTree(vd ef, init); | |
507 | initTA s.addAll(g etAndRemov eNonFieldT As(sym)); | |
508 | } else if (sym.getCo nstValue() == null) { | |
509 | // Ini tialize cl ass (stati c) variabl es only if | |
510 | // the y are not compile-ti me constan ts. | |
511 | JCStat ement init = make.at (vdef.pos) . | |
512 | As signment(s ym, vdef.i nit); | |
513 | clinit Code.appen d(init); | |
514 | endPos Table.repl aceTree(vd ef, init); | |
515 | clinit TAs.addAll (getAndRem oveNonFiel dTAs(sym)) ; | |
516 | } else { | |
517 | checkS tringConst ant(vdef.i nit.pos(), sym.getCo nstValue() ); | |
518 | /* if the init c ontains a reference to an exte rnal class , add it t o the | |
519 | * con stant's po ol | |
520 | */ | |
521 | vdef.i nit.accept (classRefe renceVisit or); | |
522 | } | |
523 | } | |
524 | brea k; | |
525 | default: | |
526 | Asse rt.error() ; | |
527 | } | |
528 | } | |
529 | // Insert an y instance initializ ers into a ll constru ctors. | |
530 | if (initCode .length() != 0) { | |
531 | List<JCS tatement> inits = in itCode.toL ist(); | |
532 | initTAs. addAll(c.g etInitType Attributes ()); | |
533 | List<Att ribute.Typ eCompound> initTAlis t = initTA s.toList() ; | |
534 | for (JCT ree t : me thodDefs) { | |
535 | norm alizeMetho d((JCMetho dDecl)t, i nits, init TAlist); | |
536 | } | |
537 | } | |
538 | // If there are class initialize rs, create a <clinit > method | |
539 | // that cont ains them as its bod y. | |
540 | if (clinitCo de.length( ) != 0) { | |
541 | MethodSy mbol clini t = new Me thodSymbol ( | |
542 | STAT IC | (c.fl ags() & ST RICTFP), | |
543 | name s.clinit, | |
544 | new MethodType ( | |
545 | List.<Type >nil(), sy ms.voidTyp e, | |
546 | List.<Type >nil(), sy ms.methodC lass), | |
547 | c); | |
548 | c.member s().enter( clinit); | |
549 | List<JCS tatement> clinitStat s = clinit Code.toLis t(); | |
550 | JCBlock block = ma ke.at(clin itStats.he ad.pos()). Block(0, c linitStats ); | |
551 | block.en dpos = Tre eInfo.endP os(clinitS tats.last( )); | |
552 | methodDe fs.append( make.Metho dDef(clini t, block)) ; | |
553 | ||
554 | if (!cli nitTAs.isE mpty()) | |
555 | clin it.appendU niqueTypeA ttributes( clinitTAs. toList()); | |
556 | if (!c.g etClassIni tTypeAttri butes().is Empty()) | |
557 | clin it.appendU niqueTypeA ttributes( c.getClass InitTypeAt tributes() ); | |
558 | } | |
559 | // Return al l method d efinitions . | |
560 | re turn metho dDefs.toLi st(); | |
561 | } | |
562 | ||
563 | privat e List<Att ribute.Typ eCompound> getAndRem oveNonFiel dTAs(VarSy mbol sym) { | |
564 | Li st<TypeCom pound> tas = sym.get RawTypeAtt ributes(); | |
565 | Li stBuffer<A ttribute.T ypeCompoun d> fieldTA s = new Li stBuffer<A ttribute.T ypeCompoun d>(); | |
566 | Li stBuffer<A ttribute.T ypeCompoun d> nonfiel dTAs = new ListBuffe r<Attribut e.TypeComp ound>(); | |
567 | fo r (TypeCom pound ta : tas) { | |
568 | if (ta.g etPosition ().type == TargetTyp e.FIELD) { | |
569 | fiel dTAs.add(t a); | |
570 | } else { | |
571 | if ( typeAnnoAs serts) { | |
572 | Assert.err or("Type a nnotation does not h ave a vali d positior "); | |
573 | } | |
574 | ||
575 | nonf ieldTAs.ad d(ta); | |
576 | } | |
577 | } | |
578 | sy m.setTypeA ttributes( fieldTAs.t oList()); | |
579 | re turn nonfi eldTAs.toL ist(); | |
580 | } | |
581 | ||
582 | /** Ch eck a cons tant value and repor t if it is a string that is | |
583 | * to o large. | |
584 | */ | |
585 | privat e void che ckStringCo nstant(Dia gnosticPos ition pos, Object co nstValue) { | |
586 | if (nerrs != 0 || // o nly compla in about a long stri ng once | |
587 | constVal ue == null || | |
588 | !(constV alue insta nceof Stri ng) || | |
589 | ((String )constValu e).length( ) < Pool.M AX_STRING_ LENGTH) | |
590 | return; | |
591 | lo g.error(po s, "limit. string"); | |
592 | ne rrs++; | |
593 | } | |
594 | ||
595 | /** In sert insta nce initia lizer code into init ial constr uctor. | |
596 | * @p aram md The t ree potent ially repr esenting a | |
597 | * const ructor's d efinition. | |
598 | * @p aram initC ode The l ist of ins tance init ializer st atements. | |
599 | * @p aram initT As Type a nnotations from the initialize r expressi on. | |
600 | */ | |
601 | void n ormalizeMe thod(JCMet hodDecl md , List<JCS tatement> initCode, List<TypeC ompound> i nitTAs) { | |
602 | if (md.name == names.i nit && Tre eInfo.isIn itialConst ructor(md) ) { | |
603 | // We ar e seeing a construct or that do es not cal l another | |
604 | // const ructor of the same c lass. | |
605 | List<JCS tatement> stats = md .body.stat s; | |
606 | ListBuff er<JCState ment> news tats = new ListBuffe r<JCStatem ent>(); | |
607 | ||
608 | if (stat s.nonEmpty ()) { | |
609 | // C opy initia lizers of synthetic variables generated in | |
610 | // t he transla tion of in ner classe s. | |
611 | whil e (TreeInf o.isSynthe ticInit(st ats.head)) { | |
612 | newstats.a ppend(stat s.head); | |
613 | stats = st ats.tail; | |
614 | } | |
615 | // C opy superc lass const ructor cal l | |
616 | news tats.appen d(stats.he ad); | |
617 | stat s = stats. tail; | |
618 | // C opy remain ing synthe tic initia lizers. | |
619 | whil e (stats.n onEmpty() && | |
620 | TreeInf o.isSynthe ticInit(st ats.head)) { | |
621 | newstats.a ppend(stat s.head); | |
622 | stats = st ats.tail; | |
623 | } | |
624 | // N ow insert the initia lizer code . | |
625 | news tats.appen dList(init Code); | |
626 | // A nd copy al l remainin g statemen ts. | |
627 | whil e (stats.n onEmpty()) { | |
628 | newstats.a ppend(stat s.head); | |
629 | stats = st ats.tail; | |
630 | } | |
631 | } | |
632 | md.body. stats = ne wstats.toL ist(); | |
633 | if (md.b ody.endpos == Positi on.NOPOS) | |
634 | md.b ody.endpos = TreeInf o.endPos(m d.body.sta ts.last()) ; | |
635 | ||
636 | md.sym.a ppendUniqu eTypeAttri butes(init TAs); | |
637 | } | |
638 | } | |
639 | ||
640 | /* ******* ********** ********** ********** ********** ********** ********** * | |
641 | * Adding miranda me thods | |
642 | ********* ********** ********** ********** ********** ********** ********** / | |
643 | ||
644 | /** Ad d abstract methods f or all met hods defin ed in one of | |
645 | * th e interfac es of a gi ven class, | |
646 | * pr ovided the y are not already im plemented in the cla ss. | |
647 | * | |
648 | * @p aram c The clas s whose in terfaces a re searche d for meth ods | |
649 | * for whic h Miranda methods sh ould be ad ded. | |
650 | */ | |
651 | void i mplementIn terfaceMet hods(Class Symbol c) { | |
652 | im plementInt erfaceMeth ods(c, c); | |
653 | } | |
654 | ||
655 | /** Ad d abstract methods f or all met hods defin ed in one of | |
656 | * th e interfac es of a gi ven class, | |
657 | * pr ovided the y are not already im plemented in the cla ss. | |
658 | * | |
659 | * @p aram c The clas s whose in terfaces a re searche d for meth ods | |
660 | * for whic h Miranda methods sh ould be ad ded. | |
661 | * @p aram site The clas s in which a definit ion may be needed. | |
662 | */ | |
663 | void i mplementIn terfaceMet hods(Class Symbol c, ClassSymbo l site) { | |
664 | fo r (List<Ty pe> l = ty pes.interf aces(c.typ e); l.nonE mpty(); l = l.tail) { | |
665 | ClassSym bol i = (C lassSymbol )l.head.ts ym; | |
666 | for (Sco pe.Entry e = i.membe rs().elems ; | |
667 | e ! = null; | |
668 | e = e.sibling ) | |
669 | { | |
670 | if ( e.sym.kind == MTH && (e.sym.fl ags() & ST ATIC) == 0 ) | |
671 | { | |
672 | MethodSymb ol absMeth = (Method Symbol)e.s ym; | |
673 | MethodSymb ol implMet h = absMet h.binaryIm plementati on(site, t ypes); | |
674 | if (implMe th == null ) | |
675 | addAbs tractMetho d(site, ab sMeth); | |
676 | else if (( implMeth.f lags() & I PROXY) != 0) | |
677 | adjust AbstractMe thod(site, implMeth, absMeth); | |
678 | } | |
679 | } | |
680 | implemen tInterface Methods(i, site); | |
681 | } | |
682 | } | |
683 | ||
684 | /** Ad d an abstr act method s to a cla ss | |
685 | * wh ich implic itly imple ments a me thod defin ed in some interface | |
686 | * im plemented by the cla ss. These methods ar e called " Miranda me thods". | |
687 | * En ter the ne wly create d method i nto its en closing cl ass scope. | |
688 | * No te that it is not en tered into the class tree, as the emitte r | |
689 | * do esn't need to see it there to emit an ab stract met hod. | |
690 | * | |
691 | * @p aram c The clas s to which the Miran da method is added. | |
692 | * @p aram m The inte rface meth od symbol for which a Miranda method | |
693 | * is added . | |
694 | */ | |
695 | privat e void add AbstractMe thod(Class Symbol c, | |
696 | Metho dSymbol m) { | |
697 | Me thodSymbol absMeth = new Metho dSymbol( | |
698 | m.flags( ) | IPROXY | SYNTHET IC, m.name , | |
699 | m.type, // was c.t ype.member Type(m), b ut now onl y !generic s supporte d | |
700 | c); | |
701 | c. members(). enter(absM eth); // a dd to symb ol table | |
702 | } | |
703 | ||
704 | privat e void adj ustAbstrac tMethod(Cl assSymbol c, | |
705 | Me thodSymbol pm, | |
706 | Me thodSymbol im) { | |
707 | Me thodType p mt = (Meth odType)pm. type; | |
708 | Ty pe imt = t ypes.membe rType(c.ty pe, im); | |
709 | pm t.thrown = chk.inter sect(pmt.g etThrownTy pes(), imt .getThrown Types()); | |
710 | } | |
711 | ||
712 | /* ******* ********** ********** ********** ********** ********** ********** ***** | |
713 | * Travers al methods | |
714 | ********* ********** ********** ********** ********** ********** ********** ****/ | |
715 | ||
716 | /** Vi sitor argu ment: The current en vironment. | |
717 | */ | |
718 | Env<Ge nContext> env; | |
719 | ||
720 | /** Vi sitor argu ment: The expected t ype (proto type). | |
721 | */ | |
722 | Type p t; | |
723 | ||
724 | /** Vi sitor resu lt: The it em represe nting the computed v alue. | |
725 | */ | |
726 | Item r esult; | |
727 | ||
728 | /** Vi sitor meth od: genera te code fo r a defini tion, catc hing and r eporting | |
729 | * an y completi on failure s. | |
730 | * @p aram tree The def inition to be visite d. | |
731 | * @p aram env The env ironment c urrent at the defini tion. | |
732 | */ | |
733 | public void genD ef(JCTree tree, Env< GenContext > env) { | |
734 | En v<GenConte xt> prevEn v = this.e nv; | |
735 | tr y { | |
736 | this.env = env; | |
737 | tree.acc ept(this); | |
738 | } catch (Com pletionFai lure ex) { | |
739 | chk.comp letionErro r(tree.pos (), ex); | |
740 | } finally { | |
741 | this.env = prevEnv ; | |
742 | } | |
743 | } | |
744 | ||
745 | /** De rived visi tor method : check wh ether Char acterRange Table | |
746 | * sh ould be em itted, if so, put a new entry into CRTab le | |
747 | * an d call met hod to gen erate byte code. | |
748 | * If not, just call meth od to gene rate bytec ode. | |
749 | * @s ee #gen Stat(JCTre e, Env) | |
750 | * | |
751 | * @p aram tree The t ree to be visited. | |
752 | * @p aram env The e nvironment to use. | |
753 | * @p aram crtF lags The C haracterRa ngeTable f lags | |
754 | * indic ating type of the en try. | |
755 | */ | |
756 | public void genS tat(JCTree tree, Env <GenContex t> env, in t crtFlags ) { | |
757 | if (!genCrt) { | |
758 | genStat( tree, env) ; | |
759 | return; | |
760 | } | |
761 | in t startpc = code.cur CP(); | |
762 | ge nStat(tree , env); | |
763 | if (tree.has Tag(Tag.BL OCK)) crtF lags |= CR T_BLOCK; | |
764 | co de.crt.put (tree, crt Flags, sta rtpc, code .curCP()); | |
765 | } | |
766 | ||
767 | /** De rived visi tor method : generate code for a statemen t. | |
768 | */ | |
769 | public void genS tat(JCTree tree, Env <GenContex t> env) { | |
770 | if (code.isA live()) { | |
771 | code.sta tBegin(tre e.pos); | |
772 | genDef(t ree, env); | |
773 | } else if (env.info. isSwitch & & tree.has Tag(
|
|
774 | // varia bles whose declarati ons are in a switch | |
775 | // can b e used eve n if the d ecl is unr eachable. | |
776 | code.new Local(((JC VariableDe cl) tree). sym); | |
777 | } | |
778 | } | |
779 | ||
780 | /** De rived visi tor method : check wh ether Char acterRange Table | |
781 | * sh ould be em itted, if so, put a new entry into CRTab le | |
782 | * an d call met hod to gen erate byte code. | |
783 | * If not, just call meth od to gene rate bytec ode. | |
784 | * @s ee #gen Stats(List , Env) | |
785 | * | |
786 | * @p aram tree s The l ist of tre es to be v isited. | |
787 | * @p aram env The e nvironment to use. | |
788 | * @p aram crtF lags The C haracterRa ngeTable f lags | |
789 | * indic ating type of the en try. | |
790 | */ | |
791 | public void genS tats(List< JCStatemen t> trees, Env<GenCon text> env, int crtFl ags) { | |
792 | if (!genCrt) { | |
793 | genStats (trees, en v); | |
794 | return; | |
795 | } | |
796 | if (trees.le ngth() == 1) { // mark one statem ent with t he flags | |
797 | genStat( trees.head , env, crt Flags | CR T_STATEMEN T); | |
798 | } else { | |
799 | int star tpc = code .curCP(); | |
800 | genStats (trees, en v); | |
801 | code.crt .put(trees , crtFlags , startpc, code.curC P()); | |
802 | } | |
803 | } | |
804 | ||
805 | /** De rived visi tor method : generate code for a list of statements . | |
806 | */ | |
807 | public void genS tats(List< ? extends JCTree> tr ees, Env<G enContext> env) { | |
808 | fo r (List<? extends JC Tree> l = trees; l.n onEmpty(); l = l.tai l) | |
809 | genStat( l.head, en v, CRT_STA TEMENT); | |
810 | } | |
811 | ||
812 | /** De rived visi tor method : check wh ether Char acterRange Table | |
813 | * sh ould be em itted, if so, put a new entry into CRTab le | |
814 | * an d call met hod to gen erate byte code. | |
815 | * If not, just call meth od to gene rate bytec ode. | |
816 | * @s ee #gen Cond(JCTre e,boolean) | |
817 | * | |
818 | * @p aram tree The t ree to be visited. | |
819 | * @p aram crtF lags The C haracterRa ngeTable f lags | |
820 | * indic ating type of the en try. | |
821 | */ | |
822 | public CondItem genCond(JC Tree tree, int crtFl ags) { | |
823 | if (!genCrt) return ge nCond(tree , false); | |
824 | in t startpc = code.cur CP(); | |
825 | Co ndItem ite m = genCon d(tree, (c rtFlags & CRT_FLOW_C ONTROLLER) != 0); | |
826 | co de.crt.put (tree, crt Flags, sta rtpc, code .curCP()); | |
827 | re turn item; | |
828 | } | |
829 | ||
830 | /** De rived visi tor method : generate code for a boolean | |
831 | * ex pression i n a contro l-flow con text. | |
832 | * @p aram _tree T he express ion to be visited. | |
833 | * @p aram markB ranches Th e flag to indicate t hat the co ndition is | |
834 | * a flow contr oller so p roduced co nditions | |
835 | * sh ould conta in a prope r tree to generate | |
836 | * Ch aracterRan geTable br anches for them. | |
837 | */ | |
838 | public CondItem genCond(JC Tree _tree , boolean markBranch es) { | |
839 | JC Tree inner _tree = Tr eeInfo.ski pParens(_t ree); | |
840 | if (inner_tr ee.hasTag( CONDEXPR)) { | |
841 | JCCondit ional tree = (JCCond itional)in ner_tree; | |
842 | CondItem cond = ge nCond(tree .cond, CRT _FLOW_CONT ROLLER); | |
843 | if (cond .isTrue()) { | |
844 | code .resolve(c ond.trueJu mps); | |
845 | Cond Item resul t = genCon d(tree.tru epart, CRT _FLOW_TARG ET); | |
846 | if ( markBranch es) result .tree = tr ee.truepar t; | |
847 | retu rn result; | |
848 | } | |
849 | if (cond .isFalse() ) { | |
850 | code .resolve(c ond.falseJ umps); | |
851 | Cond Item resul t = genCon d(tree.fal separt, CR T_FLOW_TAR GET); | |
852 | if ( markBranch es) result .tree = tr ee.falsepa rt; | |
853 | retu rn result; | |
854 | } | |
855 | Chain se condJumps = cond.jum pFalse(); | |
856 | code.res olve(cond. trueJumps) ; | |
857 | CondItem first = g enCond(tre e.truepart , CRT_FLOW _TARGET); | |
858 | if (mark Branches) first.tree = tree.tr uepart; | |
859 | Chain fa lseJumps = first.jum pFalse(); | |
860 | code.res olve(first .trueJumps ); | |
861 | Chain tr ueJumps = code.branc h(goto_); | |
862 | code.res olve(secon dJumps); | |
863 | CondItem second = genCond(tr ee.falsepa rt, CRT_FL OW_TARGET) ; | |
864 | CondItem result = items.make CondItem(s econd.opco de, | |
865 | Co de.mergeCh ains(trueJ umps, seco nd.trueJum ps), | |
866 | Co de.mergeCh ains(false Jumps, sec ond.falseJ umps)); | |
867 | if (mark Branches) result.tre e = tree.f alsepart; | |
868 | return r esult; | |
869 | } else { | |
870 | CondItem result = genExpr(_t ree, syms. booleanTyp e).mkCond( ); | |
871 | if (mark Branches) result.tre e = _tree; | |
872 | return r esult; | |
873 | } | |
874 | } | |
875 | ||
876 | /** Vi sitor clas s for expr essions wh ich might be constan t expressi ons. | |
877 | * Th is class i s a subset of TreeSc anner. Int ended to v isit trees pruned by | |
878 | * Lo wer as lon g as const ant expres sions look ing for re ferences t o any | |
879 | * Cl assSymbol. Any such reference will be ad ded to the constant pool so | |
880 | * au tomated to ols can de tect class dependenc ies better . | |
881 | */ | |
882 | class ClassRefer enceVisito r extends JCTree.Vis itor { | |
883 | ||
884 | @O verride | |
885 | pu blic void visitTree( JCTree tre e) {} | |
886 | ||
887 | @O verride | |
888 | pu blic void visitBinar y(JCBinary tree) { | |
889 | tree.lhs .accept(th is); | |
890 | tree.rhs .accept(th is); | |
891 | } | |
892 | ||
893 | @O verride | |
894 | pu blic void visitSelec t(JCFieldA ccess tree ) { | |
895 | if (tree .selected. type.hasTa g(CLASS)) { | |
896 | make Ref(tree.s elected.po s(), tree. selected.t ype); | |
897 | } | |
898 | } | |
899 | ||
900 | @O verride | |
901 | pu blic void visitIdent (JCIdent t ree) { | |
902 | if (tree .sym.owner instanceo f ClassSym bol) { | |
903 | pool .put(tree. sym.owner) ; | |
904 | } | |
905 | } | |
906 | ||
907 | @O verride | |
908 | pu blic void visitCondi tional(JCC onditional tree) { | |
909 | tree.con d.accept(t his); | |
910 | tree.tru epart.acce pt(this); | |
911 | tree.fal separt.acc ept(this); | |
912 | } | |
913 | ||
914 | @O verride | |
915 | pu blic void visitUnary (JCUnary t ree) { | |
916 | tree.arg .accept(th is); | |
917 | } | |
918 | ||
919 | @O verride | |
920 | pu blic void visitParen s(JCParens tree) { | |
921 | tree.exp r.accept(t his); | |
922 | } | |
923 | ||
924 | @O verride | |
925 | pu blic void visitTypeC ast(JCType Cast tree) { | |
926 | tree.exp r.accept(t his); | |
927 | } | |
928 | } | |
929 | ||
930 | privat e ClassRef erenceVisi tor classR eferenceVi sitor = ne w ClassRef erenceVisi tor(); | |
931 | ||
932 | /** Vi sitor meth od: genera te code fo r an expre ssion, cat ching and reporting | |
933 | * an y completi on failure s. | |
934 | * @p aram tree The exp ression to be visite d. | |
935 | * @p aram pt The exp ression's expected t ype (proto -type). | |
936 | */ | |
937 | public Item genE xpr(JCTree tree, Typ e pt) { | |
938 | Ty pe prevPt = this.pt; | |
939 | tr y { | |
940 | if (tree .type.cons tValue() ! = null) { | |
941 | // S hort circu it any exp ressions w hich are c onstants | |
942 | tree .accept(cl assReferen ceVisitor) ; | |
943 | chec kStringCon stant(tree .pos(), tr ee.type.co nstValue() ); | |
944 | resu lt = items .makeImmed iateItem(t ree.type, tree.type. constValue ()); | |
945 | } else { | |
946 | this .pt = pt; | |
947 | tree .accept(th is); | |
948 | } | |
949 | return r esult.coer ce(pt); | |
950 | } catch (Com pletionFai lure ex) { | |
951 | chk.comp letionErro r(tree.pos (), ex); | |
952 | code.sta te.stacksi ze = 1; | |
953 | return i tems.makeS tackItem(p t); | |
954 | } finally { | |
955 | this.pt = prevPt; | |
956 | } | |
957 | } | |
958 | ||
959 | /** De rived visi tor method : generate code for a list of method arg uments. | |
960 | * @p aram trees The ar gument exp ressions t o be visit ed. | |
961 | * @p aram pts The ex pression's expected types (i.e . the form al paramet er | |
962 | * types of the inv oked metho d). | |
963 | */ | |
964 | public void genA rgs(List<J CExpressio n> trees, List<Type> pts) { | |
965 | fo r (List<JC Expression > l = tree s; l.nonEm pty(); l = l.tail) { | |
966 | genExpr( l.head, pt s.head).lo ad(); | |
967 | pts = pt s.tail; | |
968 | } | |
969 | // require l ists be of same leng th | |
970 | As sert.check (pts.isEmp ty()); | |
971 | } | |
972 | ||
973 | /* ******* ********** ********** ********** ********** ********** ********** ***** | |
974 | * Visitor methods f or stateme nts and de finitions | |
975 | ********* ********** ********** ********** ********** ********** ********** ****/ | |
976 | ||
977 | /** Th rown when the byte c ode size e xceeds lim it. | |
978 | */ | |
979 | public static cl ass CodeSi zeOverflow extends R untimeExce ption { | |
980 | pr ivate stat ic final l ong serial VersionUID = 0; | |
981 | pu blic CodeS izeOverflo w() {} | |
982 | } | |
983 | ||
984 | public void visi tMethodDef (JCMethodD ecl tree) { | |
985 | // Create a new local environmen t that poi nts pack a t method | |
986 | // definitio n. | |
987 | En v<GenConte xt> localE nv = env.d up(tree); | |
988 | lo calEnv.enc lMethod = tree; | |
989 | // The expec ted type o f every re turn state ment in th is method | |
990 | // is the me thod's ret urn type. | |
991 | th is.pt = tr ee.sym.era sure(types ).getRetur nType(); | |
992 | ||
993 | ch eckDimensi on(tree.po s(), tree. sym.erasur e(types)); | |
994 | ge nMethod(tr ee, localE nv, false) ; | |
995 | } | |
996 | //where | |
997 | /* * Generate code for a method. | |
998 | * @param t ree Th e tree rep resenting the method definitio n. | |
999 | * @param e nv Th e environm ent curren t for the method bod y. | |
1000 | * @param f atcode A flag that indicates whether al l jumps ar e | |
1001 | * wi thin 32K. We first invoke thi s method u nder | |
1002 | * th e assumpti on that fa tcode == f alse, i.e. all | |
1003 | * ju mps are wi thin 32K. If this f ails, fatc ode | |
1004 | * is set to tr ue and we try again. | |
1005 | * / | |
1006 | vo id genMeth od(JCMetho dDecl tree , Env<GenC ontext> en v, boolean fatcode) { | |
1007 | MethodSy mbol meth = tree.sym ; | |
1008 | int extr as = 0; | |
1009 | // Count up extra parameters | |
1010 | if (meth .isConstru ctor()) { | |
1011 | extr as++; | |
1012 | if ( meth.enclC lass().isI nner() && | |
1013 | !meth.encl Class().is Static()) { | |
1014 | extras++; | |
1015 | } | |
1016 | } else i f ((tree.m ods.flags & STATIC) == 0) { | |
1017 | extr as++; | |
1018 | } | |
1019 | // System.err .println(" Generating " + meth + " in " + meth.owne r); //DEBU G | |
1020 | if (Code .width(typ es.erasure (env.enclM ethod.sym. type).getP arameterTy pes()) + e xtras > | |
1021 | Clas sFile.MAX_ PARAMETERS ) { | |
1022 | log. error(tree .pos(), "l imit.param eters"); | |
1023 | nerr s++; | |
1024 | } | |
1025 | ||
1026 | else if (tree.body != null) { | |
1027 | // C reate a ne w code str ucture and initializ e it. | |
1028 | int startpcCrt = initCod e(tree, en v, fatcode ); | |
1029 | ||
1030 | try { | |
1031 | genStat(tr ee.body, e nv); | |
1032 | } ca tch (CodeS izeOverflo w e) { | |
1033 | // Failed due to cod e limit, t ry again w ith jsr/re t | |
1034 | startpcCrt = initCod e(tree, en v, fatcode ); | |
1035 | genStat(tr ee.body, e nv); | |
1036 | } | |
1037 | ||
1038 | if ( code.state .stacksize != 0) { | |
1039 | log.error( tree.body. pos(), "st ack.sim.er ror", tree ); | |
1040 | throw new AssertionE rror(); | |
1041 | } | |
1042 | ||
1043 | // I f last sta tement cou ld complet e normally , insert a | |
1044 | // r eturn at t he end. | |
1045 | if ( code.isAli ve()) { | |
1046 | code.statB egin(TreeI nfo.endPos (tree.body )); | |
1047 | if (env.en clMethod = = null || | |
1048 | env.en clMethod.s ym.type.ge tReturnTyp e().hasTag (VOID)) { | |
1049 | code.e mitop0(ret urn_); | |
1050 | } else { | |
1051 | // som etime dead code seem s alive (4 415991); | |
1052 | // gen erate a sm all loop i nstead | |
1053 | int st artpc = co de.entryPo int(); | |
1054 | CondIt em c = ite ms.makeCon dItem(goto _); | |
1055 | code.r esolve(c.j umpTrue(), startpc); | |
1056 | } | |
1057 | } | |
1058 | if ( genCrt) | |
1059 | code.crt.p ut(tree.bo dy, | |
1060 | CRT_BLO CK, | |
1061 | startpc Crt, | |
1062 | code.cu rCP()); | |
1063 | ||
1064 | code .endScopes (0); | |
1065 | ||
1066 | // I f we excee ded limits , panic | |
1067 | if ( code.check Limits(tre e.pos(), l og)) { | |
1068 | nerrs++; | |
1069 | return; | |
1070 | } | |
1071 | ||
1072 | // I f we gener ated short code but got a long jump, do it again | |
1073 | // w ith fatCod e = true. | |
1074 | if ( !fatcode & & code.fat code) genM ethod(tree , env, tru e); | |
1075 | ||
1076 | // C lean up | |
1077 | if(s tackMap == StackMapF ormat.JSR2 02) { | |
1078 | code.lastF rame = nul l; | |
1079 | code.frame BeforeLast = null; | |
1080 | } | |
1081 | ||
1082 | // C ompress ex ception ta ble | |
1083 | code .compressC atchTable( ); | |
1084 | ||
1085 | // F ill in typ e annotati on positio ns for exc eption par ameters | |
1086 | code .fillExcep tionParame terPositio ns(); | |
1087 | } | |
1088 | } | |
1089 | ||
1090 | pr ivate int initCode(J CMethodDec l tree, En v<GenConte xt> env, b oolean fat code) { | |
1091 | MethodSy mbol meth = tree.sym ; | |
1092 | ||
1093 | // Creat e a new co de structu re. | |
1094 | meth.cod e = code = new Code( meth, | |
1095 | fatcode, | |
1096 | lineDebugI nfo ? topl evel.lineM ap : null, | |
1097 | varDebugIn fo, | |
1098 | stackMap, | |
1099 | debugCode, | |
1100 | genCrt ? n ew CRTable (tree, env .toplevel. endPositio ns) | |
1101 | : n ull, | |
1102 | syms, | |
1103 | types, | |
1104 | pool); | |
1105 | items = new Items( pool, code , syms, ty pes); | |
1106 | if (code .debugCode ) { | |
1107 | Syst em.err.pri ntln(meth + " for bo dy " + tre e); | |
1108 | } | |
1109 | ||
1110 | // If me thod is no t static, create a n ew local v ariable ad dress | |
1111 | // for ` this'. | |
1112 | if ((tre e.mods.fla gs & STATI C) == 0) { | |
1113 | Type selfType = meth.own er.type; | |
1114 | if ( meth.isCon structor() && selfTy pe != syms .objectTyp e) | |
1115 | selfType = Uninitial izedType.u ninitializ edThis(sel fType); | |
1116 | code .setDefine d( | |
1117 | code.n ewLocal( | |
1118 | ne w VarSymbo l(FINAL, n ames._this , selfType , meth.own er))); | |
1119 | } | |
1120 | ||
1121 | // Mark all parame ters as de fined from the begin ning of | |
1122 | // the m ethod. | |
1123 | for (Lis t<JCVariab leDecl> l = tree.par ams; l.non Empty(); l = l.tail) { | |
1124 | chec kDimension (l.head.po s(), l.hea d.sym.type ); | |
1125 | code .setDefine d(code.new Local(l.he ad.sym)); | |
1126 | } | |
1127 | ||
1128 | // Get r eady to ge nerate cod e for meth od body. | |
1129 | int star tpcCrt = g enCrt ? co de.curCP() : 0; | |
1130 | code.ent ryPoint(); | |
1131 | ||
1132 | // Suppr ess initia l stackmap | |
1133 | code.pen dingStackM ap = false ; | |
1134 | ||
1135 | return s tartpcCrt; | |
1136 | } | |
1137 | ||
1138 | public void visi tVarDef(JC VariableDe cl tree) { | |
1139 | Va rSymbol v = tree.sym ; | |
1140 | co de.newLoca l(v); | |
1141 | if (tree.ini t != null) { | |
1142 | checkStr ingConstan t(tree.ini t.pos(), v .getConstV alue()); | |
1143 | if (v.ge tConstValu e() == nul l || varDe bugInfo) { | |
1144 | genE xpr(tree.i nit, v.era sure(types )).load(); | |
1145 | item s.makeLoca lItem(v).s tore(); | |
1146 | } | |
1147 | } | |
1148 | ch eckDimensi on(tree.po s(), v.typ e); | |
1149 | } | |
1150 | ||
1151 | public void visi tSkip(JCSk ip tree) { | |
1152 | } | |
1153 | ||
1154 | public void visi tBlock(JCB lock tree) { | |
1155 | in t limit = code.nextr eg; | |
1156 | En v<GenConte xt> localE nv = env.d up(tree, n ew GenCont ext()); | |
1157 | ge nStats(tre e.stats, l ocalEnv); | |
1158 | // End the s cope of al l block-lo cal variab les in var iable info . | |
1159 | if (!env.tre e.hasTag(M ETHODDEF)) { | |
1160 | code.sta tBegin(tre e.endpos); | |
1161 | code.end Scopes(lim it); | |
1162 | code.pen dingStatPo s = Positi on.NOPOS; | |
1163 | } | |
1164 | } | |
1165 | ||
1166 | public void visi tDoLoop(JC DoWhileLoo p tree) { | |
1167 | ge nLoop(tree , tree.bod y, tree.co nd, List.< JCExpressi onStatemen t>nil(), f alse); | |
1168 | } | |
1169 | ||
1170 | public void visi tWhileLoop (JCWhileLo op tree) { | |
1171 | ge nLoop(tree , tree.bod y, tree.co nd, List.< JCExpressi onStatemen t>nil(), t rue); | |
1172 | } | |
1173 | ||
1174 | public void visi tForLoop(J CForLoop t ree) { | |
1175 | in t limit = code.nextr eg; | |
1176 | ge nStats(tre e.init, en v); | |
1177 | ge nLoop(tree , tree.bod y, tree.co nd, tree.s tep, true) ; | |
1178 | co de.endScop es(limit); | |
1179 | } | |
1180 | //wher e | |
1181 | /* * Generate code for a loop. | |
1182 | * @param l oop The tree r epresentin g the loop . | |
1183 | * @param b ody The loop's body. | |
1184 | * @param c ond The loop's controlin g conditio n. | |
1185 | * @param s tep "Step" sta tements to be insert ed at end of | |
1186 | * each itera tion. | |
1187 | * @param t estFirst True if th e loop tes t belongs before the body. | |
1188 | * / | |
1189 | pr ivate void genLoop(J CStatement loop, | |
1190 | J CStatement body, | |
1191 | J CExpressio n cond, | |
1192 | L ist<JCExpr essionStat ement> ste p, | |
1193 | b oolean tes tFirst) { | |
1194 | Env<GenC ontext> lo opEnv = en v.dup(loop , new GenC ontext()); | |
1195 | int star tpc = code .entryPoin t(); | |
1196 | if (test First) { / /while or for loop | |
1197 | Cond Item c; | |
1198 | if ( cond != nu ll) { | |
1199 | code.statB egin(cond. pos); | |
1200 | c = genCon d(TreeInfo .skipParen s(cond), C RT_FLOW_CO NTROLLER); | |
1201 | } el se { | |
1202 | c = items. makeCondIt em(goto_); | |
1203 | } | |
1204 | Chai n loopDone = c.jumpF alse(); | |
1205 | code .resolve(c .trueJumps ); | |
1206 | genS tat(body, loopEnv, C RT_STATEME NT | CRT_F LOW_TARGET ); | |
1207 | code .resolve(l oopEnv.inf o.cont); | |
1208 | genS tats(step, loopEnv); | |
1209 | code .resolve(c ode.branch (goto_), s tartpc); | |
1210 | code .resolve(l oopDone); | |
1211 | } else { | |
1212 | genS tat(body, loopEnv, C RT_STATEME NT | CRT_F LOW_TARGET ); | |
1213 | code .resolve(l oopEnv.inf o.cont); | |
1214 | genS tats(step, loopEnv); | |
1215 | Cond Item c; | |
1216 | if ( cond != nu ll) { | |
1217 | code.statB egin(cond. pos); | |
1218 | c = genCon d(TreeInfo .skipParen s(cond), C RT_FLOW_CO NTROLLER); | |
1219 | } el se { | |
1220 | c = items. makeCondIt em(goto_); | |
1221 | } | |
1222 | code .resolve(c .jumpTrue( ), startpc ); | |
1223 | code .resolve(c .falseJump s); | |
1224 | } | |
1225 | code.res olve(loopE nv.info.ex it); | |
1226 | if (loop Env.info.e xit != nul l) { | |
1227 | loop Env.info.e xit.state. defined.ex cludeFrom( code.nextr eg); | |
1228 | } | |
1229 | } | |
1230 | ||
1231 | public void visi tForeachLo op(JCEnhan cedForLoop tree) { | |
1232 | th row new As sertionErr or(); // s hould have been remo ved by Low er. | |
1233 | } | |
1234 | ||
1235 | public void visi tLabelled( JCLabeledS tatement t ree) { | |
1236 | En v<GenConte xt> localE nv = env.d up(tree, n ew GenCont ext()); | |
1237 | ge nStat(tree .body, loc alEnv, CRT _STATEMENT ); | |
1238 | co de.resolve (localEnv. info.exit) ; | |
1239 | } | |
1240 | ||
1241 | public void visi tSwitch(JC Switch tre e) { | |
1242 | in t limit = code.nextr eg; | |
1243 | As sert.check (!tree.sel ector.type .hasTag(CL ASS)); | |
1244 | in t startpcC rt = genCr t ? code.c urCP() : 0 ; | |
1245 | It em sel = g enExpr(tre e.selector , syms.int Type); | |
1246 | Li st<JCCase> cases = t ree.cases; | |
1247 | if (cases.is Empty()) { | |
1248 | // We ar e seeing: switch <s el> {} | |
1249 | sel.load ().drop(); | |
1250 | if (genC rt) | |
1251 | code .crt.put(T reeInfo.sk ipParens(t ree.select or), | |
1252 | C RT_FLOW_CO NTROLLER, startpcCrt , code.cur CP()); | |
1253 | } else { | |
1254 | // We ar e seeing a nonempty switch. | |
1255 | sel.load (); | |
1256 | if (genC rt) | |
1257 | code .crt.put(T reeInfo.sk ipParens(t ree.select or), | |
1258 | C RT_FLOW_CO NTROLLER, startpcCrt , code.cur CP()); | |
1259 | Env<GenC ontext> sw itchEnv = env.dup(tr ee, new Ge nContext() ); | |
1260 | switchEn v.info.isS witch = tr ue; | |
1261 | ||
1262 | // Compu te number of labels and minimu m and maxi mum label values. | |
1263 | // For e ach case, store its label in a n array. | |
1264 | int lo = Integer.M AX_VALUE; // minimu m label. | |
1265 | int hi = Integer.M IN_VALUE; // maximu m label. | |
1266 | int nlab els = 0; // numb er of labe ls. | |
1267 | ||
1268 | int[] la bels = new int[cases .length()] ; // the label arra y. | |
1269 | int defa ultIndex = -1; / / the inde x of the d efault cla use. | |
1270 | ||
1271 | List<JCC ase> l = c ases; | |
1272 | for (int i = 0; i < labels.l ength; i++ ) { | |
1273 | if ( l.head.pat != null) { | |
1274 | int val = ((Number)l .head.pat. type.const Value()).i ntValue(); | |
1275 | labels[i] = val; | |
1276 | if (val < lo) lo = v al; | |
1277 | if (hi < v al) hi = v al; | |
1278 | nlabels++; | |
1279 | } el se { | |
1280 | Assert.che ck(default Index == - 1); | |
1281 | defaultInd ex = i; | |
1282 | } | |
1283 | l = l.tail; | |
1284 | } | |
1285 | ||
1286 | // Deter mine wheth er to issu e a tables witch or a lookupswi tch | |
1287 | // instr uction. | |
1288 | long tab le_space_c ost = 4 + ((long) hi - lo + 1) ; // words | |
1289 | long tab le_time_co st = 3; // compariso ns | |
1290 | long loo kup_space_ cost = 3 + 2 * (long ) nlabels; | |
1291 | long loo kup_time_c ost = nlab els; | |
1292 | int opco de = | |
1293 | nlab els > 0 && | |
1294 | tabl e_space_co st + 3 * t able_time_ cost <= | |
1295 | look up_space_c ost + 3 * lookup_tim e_cost | |
1296 | ? | |
1297 | tabl eswitch : lookupswit ch; | |
1298 | ||
1299 | int star tpc = code .curCP(); // the position o f the sele ctor opera tion | |
1300 | code.emi top0(opcod e); | |
1301 | code.ali gn(4); | |
1302 | int tabl eBase = co de.curCP() ; // the start of t he jump ta ble | |
1303 | int[] of fsets = nu ll; // a ta ble of off sets for a lookupswi tch | |
1304 | code.emi t4(-1); // leav e space fo r default offset | |
1305 | if (opco de == tabl eswitch) { | |
1306 | code .emit4(lo) ; // mini mum label | |
1307 | code .emit4(hi) ; // maxi mum label | |
1308 | for (long i = lo; i <= h i; i++) { // leave space for jump table | |
1309 | code.emit4 (-1); | |
1310 | } | |
1311 | } else { | |
1312 | code .emit4(nla bels); // number of labels | |
1313 | for (int i = 0 ; i < nlab els; i++) { | |
1314 | code.emit4 (-1); code .emit4(-1) ; // leave space for lookup ta ble | |
1315 | } | |
1316 | offs ets = new int[labels .length]; | |
1317 | } | |
1318 | Code.Sta te stateSw itch = cod e.state.du p(); | |
1319 | code.mar kDead(); | |
1320 | ||
1321 | // For e ach case d o: | |
1322 | l = case s; | |
1323 | for (int i = 0; i < labels.l ength; i++ ) { | |
1324 | JCCa se c = l.h ead; | |
1325 | l = l.tail; | |
1326 | ||
1327 | int pc = code. entryPoint (stateSwit ch); | |
1328 | // I nsert offs et directl y into cod e or else into the | |
1329 | // o ffsets tab le. | |
1330 | if ( i != defau ltIndex) { | |
1331 | if (opcode == tables witch) { | |
1332 | code.p ut4( | |
1333 | ta bleBase + 4 * (label s[i] - lo + 3), | |
1334 | pc - startpc ); | |
1335 | } else { | |
1336 | offset s[i] = pc - startpc; | |
1337 | } | |
1338 | } el se { | |
1339 | code.put4( tableBase, pc - star tpc); | |
1340 | } | |
1341 | ||
1342 | // G enerate co de for the statement s in this case. | |
1343 | genS tats(c.sta ts, switch Env, CRT_F LOW_TARGET ); | |
1344 | } | |
1345 | ||
1346 | // Resol ve all bre aks. | |
1347 | code.res olve(switc hEnv.info. exit); | |
1348 | ||
1349 | // If we have not set the de fault offs et, we do so now. | |
1350 | if (code .get4(tabl eBase) == -1) { | |
1351 | code .put4(tabl eBase, cod e.entryPoi nt(stateSw itch) - st artpc); | |
1352 | } | |
1353 | ||
1354 | if (opco de == tabl eswitch) { | |
1355 | // L et any unf illed slot s point to the defau lt case. | |
1356 | int defaultOff set = code .get4(tabl eBase); | |
1357 | for (long i = lo; i <= h i; i++) { | |
1358 | int t = (i nt)(tableB ase + 4 * (i - lo + 3)); | |
1359 | if (code.g et4(t) == -1) | |
1360 | code.p ut4(t, def aultOffset ); | |
1361 | } | |
1362 | } else { | |
1363 | // S ort non-de fault offs ets and co py into lo okup table . | |
1364 | if ( defaultInd ex >= 0) | |
1365 | for (int i = default Index; i < labels.le ngth - 1; i++) { | |
1366 | labels [i] = labe ls[i+1]; | |
1367 | offset s[i] = off sets[i+1]; | |
1368 | } | |
1369 | if ( nlabels > 0) | |
1370 | qsort2(lab els, offse ts, 0, nla bels - 1); | |
1371 | for (int i = 0 ; i < nlab els; i++) { | |
1372 | int caseid x = tableB ase + 8 * (i + 1); | |
1373 | code.put4( caseidx, l abels[i]); | |
1374 | code.put4( caseidx + 4, offsets [i]); | |
1375 | } | |
1376 | } | |
1377 | } | |
1378 | co de.endScop es(limit); | |
1379 | } | |
1380 | //where | |
1381 | /* * Sort (in t) arrays of keys an d values | |
1382 | * / | |
1383 | sta tic void q sort2(int[ ] keys, in t[] values , int lo, int hi) { | |
1384 | int i = lo; | |
1385 | int j = hi; | |
1386 | int pivo t = keys[( i+j)/2]; | |
1387 | do { | |
1388 | whil e (keys[i] < pivot) i++; | |
1389 | whil e (pivot < keys[j]) j--; | |
1390 | if ( i <= j) { | |
1391 | int temp1 = keys[i]; | |
1392 | keys[i] = keys[j]; | |
1393 | keys[j] = temp1; | |
1394 | int temp2 = values[i ]; | |
1395 | values[i] = values[j ]; | |
1396 | values[j] = temp2; | |
1397 | i++; | |
1398 | j--; | |
1399 | } | |
1400 | } while (i <= j); | |
1401 | if (lo < j) qsort2 (keys, val ues, lo, j ); | |
1402 | if (i < hi) qsort2 (keys, val ues, i, hi ); | |
1403 | } | |
1404 | ||
1405 | public void visi tSynchroni zed(JCSync hronized t ree) { | |
1406 | in t limit = code.nextr eg; | |
1407 | // Generate code to ev aluate loc k and save in tempor ary variab le. | |
1408 | fi nal LocalI tem lockVa r = makeTe mp(syms.ob jectType); | |
1409 | ge nExpr(tree .lock, tre e.lock.typ e).load(). duplicate( ); | |
1410 | lo ckVar.stor e(); | |
1411 | ||
1412 | // Generate code to en ter monito r. | |
1413 | co de.emitop0 (monitoren ter); | |
1414 | co de.state.l ock(lockVa r.reg); | |
1415 | ||
1416 | // Generate code for a try state ment with given body , no catch clauses | |
1417 | // in a new environmen t with the "exit-mon itor" oper ation as f inalizer. | |
1418 | fi nal Env<Ge nContext> syncEnv = env.dup(tr ee, new Ge nContext() ); | |
1419 | sy ncEnv.info .finalize = new GenF inalizer() { | |
1420 | void gen () { | |
1421 | genL ast(); | |
1422 | Asse rt.check(s yncEnv.inf o.gaps.len gth() % 2 == 0); | |
1423 | sync Env.info.g aps.append (code.curC P()); | |
1424 | } | |
1425 | void gen Last() { | |
1426 | if ( code.isAli ve()) { | |
1427 | lockVar.lo ad(); | |
1428 | code.emito p0(monitor exit); | |
1429 | code.state .unlock(lo ckVar.reg) ; | |
1430 | } | |
1431 | } | |
1432 | }; | |
1433 | sy ncEnv.info .gaps = ne w ListBuff er<Integer >(); | |
1434 | ge nTry(tree. body, List .<JCCatch> nil(), syn cEnv); | |
1435 | co de.endScop es(limit); | |
1436 | } | |
1437 | ||
1438 | public void visi tTry(final JCTry tre e) { | |
1439 | // Generate code for a try state ment with given body and catch clauses, | |
1440 | // in a new environmen t which ca lls the fi nally bloc k if there is one. | |
1441 | fi nal Env<Ge nContext> tryEnv = e nv.dup(tre e, new Gen Context()) ; | |
1442 | fi nal Env<Ge nContext> oldEnv = e nv; | |
1443 | if (!useJsrL ocally) { | |
1444 | useJsrLo cally = | |
1445 | (sta ckMap == S tackMapFor mat.NONE) && | |
1446 | (jsr limit <= 0 || | |
1447 | jsrl imit < 100 && | |
1448 | esti mateCodeCo mplexity(t ree.finali zer)>jsrli mit); | |
1449 | } | |
1450 | tr yEnv.info. finalize = new GenFi nalizer() { | |
1451 | void gen () { | |
1452 | if ( useJsrLoca lly) { | |
1453 | if (tree.f inalizer ! = null) { | |
1454 | Code.S tate jsrSt ate = code .state.dup (); | |
1455 | jsrSta te.push(Co de.jsrRetu rnValue); | |
1456 | tryEnv .info.cont = | |
1457 | ne w Chain(co de.emitJum p(jsr), | |
1458 | tr yEnv.info. cont, | |
1459 | js rState); | |
1460 | } | |
1461 | Assert.che ck(tryEnv. info.gaps. length() % 2 == 0); | |
1462 | tryEnv.inf o.gaps.app end(code.c urCP()); | |
1463 | } el se { | |
1464 | Assert.che ck(tryEnv. info.gaps. length() % 2 == 0); | |
1465 | tryEnv.inf o.gaps.app end(code.c urCP()); | |
1466 | genLast(); | |
1467 | } | |
1468 | } | |
1469 | void gen Last() { | |
1470 | if ( tree.final izer != nu ll) | |
1471 | genStat(tr ee.finaliz er, oldEnv , CRT_BLOC K); | |
1472 | } | |
1473 | boolean hasFinaliz er() { | |
1474 | retu rn tree.fi nalizer != null; | |
1475 | } | |
1476 | }; | |
1477 | tr yEnv.info. gaps = new ListBuffe r<Integer> (); | |
1478 | ge nTry(tree. body, tree .catchers, tryEnv); | |
1479 | } | |
1480 | //wher e | |
1481 | /* * Generate code for a try or s ynchronize d statemen t | |
1482 | * @param b ody T he body of the try o r synchron ized state ment. | |
1483 | * @param c atchers T he lis of catch clau ses. | |
1484 | * @param e nv t he environ ment curre nt for the body. | |
1485 | * / | |
1486 | vo id genTry( JCTree bod y, List<JC Catch> cat chers, Env <GenContex t> env) { | |
1487 | int limi t = code.n extreg; | |
1488 | int star tpc = code .curCP(); | |
1489 | Code.Sta te stateTr y = code.s tate.dup() ; | |
1490 | genStat( body, env, CRT_BLOCK ); | |
1491 | int endp c = code.c urCP(); | |
1492 | boolean hasFinaliz er = | |
1493 | env. info.final ize != nul l && | |
1494 | env. info.final ize.hasFin alizer(); | |
1495 | List<Int eger> gaps = env.inf o.gaps.toL ist(); | |
1496 | code.sta tBegin(Tre eInfo.endP os(body)); | |
1497 | genFinal izer(env); | |
1498 | code.sta tBegin(Tre eInfo.endP os(env.tre e)); | |
1499 | Chain ex itChain = code.branc h(goto_); | |
1500 | endFinal izerGap(en v); | |
1501 | if (star tpc != end pc) for (L ist<JCCatc h> l = cat chers; l.n onEmpty(); l = l.tai l) { | |
1502 | // s tart off w ith except ion on sta ck | |
1503 | code .entryPoin t(stateTry , l.head.p aram.sym.t ype); | |
1504 | genC atch(l.hea d, env, st artpc, end pc, gaps); | |
1505 | genF inalizer(e nv); | |
1506 | if ( hasFinaliz er || l.ta il.nonEmpt y()) { | |
1507 | code.statB egin(TreeI nfo.endPos (env.tree) ); | |
1508 | exitChain = Code.mer geChains(e xitChain, | |
1509 | c ode.branch (goto_)); | |
1510 | } | |
1511 | endF inalizerGa p(env); | |
1512 | } | |
1513 | if (hasF inalizer) { | |
1514 | // C reate a ne w register segement to avoid a llocating | |
1515 | // t he same va riables in finalizer s and othe r statemen ts. | |
1516 | code .newRegSeg ment(); | |
1517 | ||
1518 | // A dd a catch -all claus e. | |
1519 | ||
1520 | // s tart off w ith except ion on sta ck | |
1521 | int catchallpc = code.en tryPoint(s tateTry, s yms.throwa bleType); | |
1522 | ||
1523 | // R egister al l exceptio n ranges f or catch a ll clause. | |
1524 | // T he range o f the catc h all clau se is from the begin ning | |
1525 | // o f the try or synchro nized bloc k until th e present | |
1526 | // c ode pointe r excludin g all gaps in the cu rrent | |
1527 | // e nvironment 's GenCont ext. | |
1528 | int startseg = startpc; | |
1529 | whil e (env.inf o.gaps.non Empty()) { | |
1530 | int endseg = env.inf o.gaps.nex t().intVal ue(); | |
1531 | registerCa tch(body.p os(), star tseg, ends eg, | |
1532 | catcha llpc, 0); | |
1533 | startseg = env.info. gaps.next( ).intValue (); | |
1534 | } | |
1535 | code .statBegin (TreeInfo. finalizerP os(env.tre e, PosKind .FIRST_STA T_POS)); | |
1536 | code .markStatB egin(); | |
1537 | ||
1538 | Item excVar = makeTemp(s yms.throwa bleType); | |
1539 | excV ar.store() ; | |
1540 | genF inalizer(e nv); | |
1541 | code .resolvePe nding(); | |
1542 | code .statBegin (TreeInfo. finalizerP os(env.tre e, PosKind .END_POS)) ; | |
1543 | code .markStatB egin(); | |
1544 | ||
1545 | excV ar.load(); | |
1546 | regi sterCatch( body.pos() , startseg , | |
1547 | env.info.g aps.next() .intValue( ), | |
1548 | catchallpc , 0); | |
1549 | code .emitop0(a throw); | |
1550 | code .markDead( ); | |
1551 | ||
1552 | // I f there ar e jsr's to this fina lizer, ... | |
1553 | if ( env.info.c ont != nul l) { | |
1554 | // Resolve all jsr's . | |
1555 | code.resol ve(env.inf o.cont); | |
1556 | ||
1557 | // Mark st atement li ne number | |
1558 | code.statB egin(TreeI nfo.finali zerPos(env .tree, Pos Kind.FIRST _STAT_POS) ); | |
1559 | code.markS tatBegin() ; | |
1560 | ||
1561 | // Save re turn addre ss. | |
1562 | LocalItem retVar = m akeTemp(sy ms.throwab leType); | |
1563 | retVar.sto re(); | |
1564 | ||
1565 | // Generat e finalize r code. | |
1566 | env.info.f inalize.ge nLast(); | |
1567 | ||
1568 | // Return. | |
1569 | code.emito p1w(ret, r etVar.reg) ; | |
1570 | code.markD ead(); | |
1571 | } | |
1572 | } | |
1573 | // Resol ve all bre aks. | |
1574 | code.res olve(exitC hain); | |
1575 | ||
1576 | code.end Scopes(lim it); | |
1577 | } | |
1578 | ||
1579 | /* * Generate code for a catch cl ause. | |
1580 | * @param t ree Th e catch cl ause. | |
1581 | * @param e nv Th e environm ent curren t in the e nclosing t ry. | |
1582 | * @param s tartpc St art pc of try-block. | |
1583 | * @param e ndpc En d pc of tr y-block. | |
1584 | * / | |
1585 | vo id genCatc h(JCCatch tree, | |
1586 | Env<GenC ontext> en v, | |
1587 | int star tpc, int e ndpc, | |
1588 | List<Int eger> gaps ) { | |
1589 | if (star tpc != end pc) { | |
1590 | List <JCExpress ion> subCl auses = Tr eeInfo.isM ultiCatch( tree) ? | |
1591 | ((JCTy peUnion)tr ee.param.v artype).al ternatives : | |
1592 | List.o f(tree.par am.vartype ); | |
1593 | whil e (gaps.no nEmpty()) { | |
1594 | for (JCExp ression su bCatch : s ubClauses) { | |
1595 | int ca tchType = makeRef(tr ee.pos(), subCatch.t ype); | |
1596 | int en d = gaps.h ead.intVal ue(); | |
1597 | regist erCatch(tr ee.pos(), | |
1598 | st artpc, en d, code.cu rCP(), | |
1599 | ca tchType); | |
1600 | if (su bCatch.typ e.isAnnota ted()) { | |
1601 | fo r (Attribu te.TypeCom pound tc : | |
1602 | sub Catch.type .getAnnota tionMirror s()) { | |
1603 | tc.posit ion.type_i ndex = cat chType; | |
1604 | } | |
1605 | } | |
1606 | } | |
1607 | gaps = gap s.tail; | |
1608 | startpc = gaps.head. intValue() ; | |
1609 | gaps = gap s.tail; | |
1610 | } | |
1611 | if ( startpc < endpc) { | |
1612 | for (JCExp ression su bCatch : s ubClauses) { | |
1613 | int ca tchType = makeRef(tr ee.pos(), subCatch.t ype); | |
1614 | regist erCatch(tr ee.pos(), | |
1615 | st artpc, end pc, code.c urCP(), | |
1616 | ca tchType); | |
1617 | if (su bCatch.typ e.isAnnota ted()) { | |
1618 | fo r (Attribu te.TypeCom pound tc : | |
1619 | sub Catch.type .getAnnota tionMirror s()) { | |
1620 | tc.posit ion.type_i ndex = cat chType; | |
1621 | } | |
1622 | } | |
1623 | } | |
1624 | } | |
1625 | VarS ymbol expa ram = tree .param.sym ; | |
1626 | code .statBegin (tree.pos) ; | |
1627 | code .markStatB egin(); | |
1628 | int limit = co de.nextreg ; | |
1629 | int exlocal = code.newLo cal(expara m); | |
1630 | item s.makeLoca lItem(expa ram).store (); | |
1631 | code .statBegin (TreeInfo. firstStatP os(tree.bo dy)); | |
1632 | genS tat(tree.b ody, env, CRT_BLOCK) ; | |
1633 | code .endScopes (limit); | |
1634 | code .statBegin (TreeInfo. endPos(tre e.body)); | |
1635 | } | |
1636 | } | |
1637 | ||
1638 | /* * Register a catch c lause in t he "Except ions" code -attribute . | |
1639 | * / | |
1640 | vo id registe rCatch(Dia gnosticPos ition pos, | |
1641 | int startpc, int endpc, | |
1642 | int handler_p c, int cat ch_type) { | |
1643 | char sta rtpc1 = (c har)startp c; | |
1644 | char end pc1 = (cha r)endpc; | |
1645 | char han dler_pc1 = (char)han dler_pc; | |
1646 | if (star tpc1 == st artpc && | |
1647 | endp c1 == endp c && | |
1648 | hand ler_pc1 == handler_p c) { | |
1649 | code .addCatch( startpc1, endpc1, ha ndler_pc1, | |
1650 | (char)catc h_type); | |
1651 | } else { | |
1652 | if ( !useJsrLoc ally && !t arget.gene rateStackM apTable()) { | |
1653 | useJsrLoca lly = true ; | |
1654 | throw new CodeSizeOv erflow(); | |
1655 | } el se { | |
1656 | log.error( pos, "limi t.code.too .large.for .try.stmt" ); | |
1657 | nerrs++; | |
1658 | } | |
1659 | } | |
1660 | } | |
1661 | ||
1662 | /** Ve ry roughly estimate the number of instru ctions nee ded for | |
1663 | * th e given tr ee. | |
1664 | */ | |
1665 | int es timateCode Complexity (JCTree tr ee) { | |
1666 | if (tree == null) retu rn 0; | |
1667 | cl ass Comple xityScanne r extends TreeScanne r { | |
1668 | int comp lexity = 0 ; | |
1669 | public v oid scan(J CTree tree ) { | |
1670 | if ( complexity > jsrlimi t) return; | |
1671 | supe r.scan(tre e); | |
1672 | } | |
1673 | public v oid visitC lassDef(JC ClassDecl tree) {} | |
1674 | public v oid visitD oLoop(JCDo WhileLoop tree) | |
1675 | { su per.visitD oLoop(tree ); complex ity++; } | |
1676 | public v oid visitW hileLoop(J CWhileLoop tree) | |
1677 | { su per.visitW hileLoop(t ree); comp lexity++; } | |
1678 | public v oid visitF orLoop(JCF orLoop tre e) | |
1679 | { su per.visitF orLoop(tre e); comple xity++; } | |
1680 | public v oid visitS witch(JCSw itch tree) | |
1681 | { su per.visitS witch(tree ); complex ity+=5; } | |
1682 | public v oid visitC ase(JCCase tree) | |
1683 | { su per.visitC ase(tree); complexit y++; } | |
1684 | public v oid visitS ynchronize d(JCSynchr onized tre e) | |
1685 | { su per.visitS ynchronize d(tree); c omplexity+ =6; } | |
1686 | public v oid visitT ry(JCTry t ree) | |
1687 | { su per.visitT ry(tree); | |
1688 | if (tree.fin alizer != null) comp lexity+=6; } | |
1689 | public v oid visitC atch(JCCat ch tree) | |
1690 | { su per.visitC atch(tree) ; complexi ty+=2; } | |
1691 | public v oid visitC onditional (JCConditi onal tree) | |
1692 | { su per.visitC onditional (tree); co mplexity+= 2; } | |
1693 | public v oid visitI f(JCIf tre e) | |
1694 | { su per.visitI f(tree); c omplexity+ =2; } | |
1695 | // note: for break , continue , and retu rn we don' t take unw ind() into account. | |
1696 | public v oid visitB reak(JCBre ak tree) | |
1697 | { su per.visitB reak(tree) ; complexi ty+=1; } | |
1698 | public v oid visitC ontinue(JC Continue t ree) | |
1699 | { su per.visitC ontinue(tr ee); compl exity+=1; } | |
1700 | public v oid visitR eturn(JCRe turn tree) | |
1701 | { su per.visitR eturn(tree ); complex ity+=1; } | |
1702 | public v oid visitT hrow(JCThr ow tree) | |
1703 | { su per.visitT hrow(tree) ; complexi ty+=1; } | |
1704 | public v oid visitA ssert(JCAs sert tree) | |
1705 | { su per.visitA ssert(tree ); complex ity+=5; } | |
1706 | public v oid visitA pply(JCMet hodInvocat ion tree) | |
1707 | { su per.visitA pply(tree) ; complexi ty+=2; } | |
1708 | public v oid visitN ewClass(JC NewClass t ree) | |
1709 | { sc an(tree.en cl); scan( tree.args) ; complexi ty+=2; } | |
1710 | public v oid visitN ewArray(JC NewArray t ree) | |
1711 | { su per.visitN ewArray(tr ee); compl exity+=5; } | |
1712 | public v oid visitA ssign(JCAs sign tree) | |
1713 | { su per.visitA ssign(tree ); complex ity+=1; } | |
1714 | public v oid visitA ssignop(JC AssignOp t ree) | |
1715 | { su per.visitA ssignop(tr ee); compl exity+=2; } | |
1716 | public v oid visitU nary(JCUna ry tree) | |
1717 | { co mplexity+= 1; | |
1718 | if (tree.typ e.constVal ue() == nu ll) super. visitUnary (tree); } | |
1719 | public v oid visitB inary(JCBi nary tree) | |
1720 | { co mplexity+= 1; | |
1721 | if (tree.typ e.constVal ue() == nu ll) super. visitBinar y(tree); } | |
1722 | public v oid visitT ypeTest(JC InstanceOf tree) | |
1723 | { su per.visitT ypeTest(tr ee); compl exity+=1; } | |
1724 | public v oid visitI ndexed(JCA rrayAccess tree) | |
1725 | { su per.visitI ndexed(tre e); comple xity+=1; } | |
1726 | public v oid visitS elect(JCFi eldAccess tree) | |
1727 | { su per.visitS elect(tree ); | |
1728 | if (tree.sym .kind == V AR) comple xity+=1; } | |
1729 | public v oid visitI dent(JCIde nt tree) { | |
1730 | if ( tree.sym.k ind == VAR ) { | |
1731 | complexity +=1; | |
1732 | if (tree.t ype.constV alue() == null && | |
1733 | tree.s ym.owner.k ind == TYP ) | |
1734 | comple xity+=1; | |
1735 | } | |
1736 | } | |
1737 | public v oid visitL iteral(JCL iteral tre e) | |
1738 | { co mplexity+= 1; } | |
1739 | public v oid visitT ree(JCTree tree) {} | |
1740 | public v oid visitW ildcard(JC Wildcard t ree) { | |
1741 | thro w new Asse rtionError (this.getC lass().get Name()); | |
1742 | } | |
1743 | } | |
1744 | Co mplexitySc anner scan ner = new Complexity Scanner(); | |
1745 | tr ee.accept( scanner); | |
1746 | re turn scann er.complex ity; | |
1747 | } | |
1748 | ||
1749 | public void visi tIf(JCIf t ree) { | |
1750 | in t limit = code.nextr eg; | |
1751 | Ch ain thenEx it = null; | |
1752 | Co ndItem c = genCond(T reeInfo.sk ipParens(t ree.cond), | |
1753 | C RT_FLOW_CO NTROLLER); | |
1754 | Ch ain elseCh ain = c.ju mpFalse(); | |
1755 | if (!c.isFal se()) { | |
1756 | code.res olve(c.tru eJumps); | |
1757 | genStat( tree.thenp art, env, CRT_STATEM ENT | CRT_ FLOW_TARGE T); | |
1758 | thenExit = code.br anch(goto_ ); | |
1759 | } | |
1760 | if (elseChai n != null) { | |
1761 | code.res olve(elseC hain); | |
1762 | if (tree .elsepart != null) { | |
1763 | genS tat(tree.e lsepart, e nv,CRT_STA TEMENT | C RT_FLOW_TA RGET); | |
1764 | } | |
1765 | } | |
1766 | co de.resolve (thenExit) ; | |
1767 | co de.endScop es(limit); | |
1768 | } | |
1769 | ||
1770 | public void visi tExec(JCEx pressionSt atement tr ee) { | |
1771 | // Optimize x++ to ++x and x-- t o --x. | |
1772 | JC Expression e = tree. expr; | |
1773 | sw itch (e.ge tTag()) { | |
1774 | case POS TINC: | |
1775 | ((JC Unary) e). setTag(PRE INC); | |
1776 | brea k; | |
1777 | case POS TDEC: | |
1778 | ((JC Unary) e). setTag(PRE DEC); | |
1779 | brea k; | |
1780 | } | |
1781 | ge nExpr(tree .expr, tre e.expr.typ e).drop(); | |
1782 | } | |
1783 | ||
1784 | public void visi tBreak(JCB reak tree) { | |
1785 | En v<GenConte xt> target Env = unwi nd(tree.ta rget, env) ; | |
1786 | As sert.check (code.stat e.stacksiz e == 0); | |
1787 | ta rgetEnv.in fo.addExit (code.bran ch(goto_)) ; | |
1788 | en dFinalizer Gaps(env, targetEnv) ; | |
1789 | } | |
1790 | ||
1791 | public void visi tContinue( JCContinue tree) { | |
1792 | En v<GenConte xt> target Env = unwi nd(tree.ta rget, env) ; | |
1793 | As sert.check (code.stat e.stacksiz e == 0); | |
1794 | ta rgetEnv.in fo.addCont (code.bran ch(goto_)) ; | |
1795 | en dFinalizer Gaps(env, targetEnv) ; | |
1796 | } | |
1797 | ||
1798 | public void visi tReturn(JC Return tre e) { | |
1799 | in t limit = code.nextr eg; | |
1800 | fi nal Env<Ge nContext> targetEnv; | |
1801 | ||
1802 | /* Save and then resto re the loc ation of t he return in case a finally | |
1803 | * is expand ed (with u nwind()) i n the midd le of our bytecodes. | |
1804 | * / | |
1805 | in t tmpPos = code.pend ingStatPos ; | |
1806 | if (tree.exp r != null) { | |
1807 | Item r = genExpr(t ree.expr, pt).load() ; | |
1808 | if (hasF inally(env .enclMetho d, env)) { | |
1809 | r = makeTemp(p t); | |
1810 | r.st ore(); | |
1811 | } | |
1812 | targetEn v = unwind (env.enclM ethod, env ); | |
1813 | code.pen dingStatPo s = tmpPos ; | |
1814 | r.load() ; | |
1815 | code.emi top0(iretu rn + Code. truncate(C ode.typeco de(pt))); | |
1816 | } else { | |
1817 | targetEn v = unwind (env.enclM ethod, env ); | |
1818 | code.pen dingStatPo s = tmpPos ; | |
1819 | code.emi top0(retur n_); | |
1820 | } | |
1821 | en dFinalizer Gaps(env, targetEnv) ; | |
1822 | co de.endScop es(limit); | |
1823 | } | |
1824 | ||
1825 | public void visi tThrow(JCT hrow tree) { | |
1826 | ge nExpr(tree .expr, tre e.expr.typ e).load(); | |
1827 | co de.emitop0 (athrow); | |
1828 | } | |
1829 | ||
1830 | /* ******* ********** ********** ********** ********** ********** ********** ***** | |
1831 | * Visitor methods f or express ions | |
1832 | ********* ********** ********** ********** ********** ********** ********** ****/ | |
1833 | ||
1834 | public void visi tApply(JCM ethodInvoc ation tree ) { | |
1835 | se tTypeAnnot ationPosit ions(tree. pos); | |
1836 | // Generate code for m ethod. | |
1837 | It em m = gen Expr(tree. meth, meth odType); | |
1838 | // Generate code for a ll argumen ts, where the expect ed types a re | |
1839 | // the param eters of t he method' s external type (tha t is, any implicit | |
1840 | // outer ins tance of a super(... ) call app ears as fi rst parame ter). | |
1841 | Me thodSymbol msym = (M ethodSymbo l)TreeInfo .symbol(tr ee.meth); | |
1842 | ge nArgs(tree .args, | |
1843 | msym .externalT ype(types) .getParame terTypes() ); | |
1844 | if (!msym.is Dynamic()) { | |
1845 | code.sta tBegin(tre e.pos); | |
1846 | } | |
1847 | re sult = m.i nvoke(); | |
1848 | } | |
1849 | ||
1850 | public void visi tCondition al(JCCondi tional tre e) { | |
1851 | Ch ain thenEx it = null; | |
1852 | Co ndItem c = genCond(t ree.cond, CRT_FLOW_C ONTROLLER) ; | |
1853 | Ch ain elseCh ain = c.ju mpFalse(); | |
1854 | if (!c.isFal se()) { | |
1855 | code.res olve(c.tru eJumps); | |
1856 | int star tpc = genC rt ? code. curCP() : 0; | |
1857 | genExpr( tree.truep art, pt).l oad(); | |
1858 | code.sta te.forceSt ackTop(tre e.type); | |
1859 | if (genC rt) code.c rt.put(tre e.truepart , CRT_FLOW _TARGET, | |
1860 | sta rtpc, code .curCP()); | |
1861 | thenExit = code.br anch(goto_ ); | |
1862 | } | |
1863 | if (elseChai n != null) { | |
1864 | code.res olve(elseC hain); | |
1865 | int star tpc = genC rt ? code. curCP() : 0; | |
1866 | genExpr( tree.false part, pt). load(); | |
1867 | code.sta te.forceSt ackTop(tre e.type); | |
1868 | if (genC rt) code.c rt.put(tre e.falsepar t, CRT_FLO W_TARGET, | |
1869 | sta rtpc, code .curCP()); | |
1870 | } | |
1871 | co de.resolve (thenExit) ; | |
1872 | re sult = ite ms.makeSta ckItem(pt) ; | |
1873 | } | |
1874 | ||
1875 | privat e void set TypeAnnota tionPositi ons(int tr eePos) { | |
1876 | Me thodSymbol meth = co de.meth; | |
1877 | bo olean init OrClinit = code.meth .getKind() == javax. lang.model .element.E lementKind .CONSTRUCT OR | |
1878 | || c ode.meth.g etKind() = = javax.la ng.model.e lement.Ele mentKind.S TATIC_INIT ; | |
1879 | ||
1880 | fo r (Attribu te.TypeCom pound ta : meth.getR awTypeAttr ibutes()) { | |
1881 | if (ta.h asUnknownP osition()) | |
1882 | ta.t ryFixPosit ion(); | |
1883 | ||
1884 | if (ta.p osition.ma tchesPos(t reePos)) | |
1885 | ta.p osition.up datePosOff set(code.c p); | |
1886 | } | |
1887 | ||
1888 | if (!initOrC linit) | |
1889 | return; | |
1890 | ||
1891 | fo r (Attribu te.TypeCom pound ta : meth.owne r.getRawTy peAttribut es()) { | |
1892 | if (ta.h asUnknownP osition()) | |
1893 | ta.t ryFixPosit ion(); | |
1894 | ||
1895 | if (ta.p osition.ma tchesPos(t reePos)) | |
1896 | ta.p osition.up datePosOff set(code.c p); | |
1897 | } | |
1898 | ||
1899 | Cl assSymbol clazz = me th.enclCla ss(); | |
1900 | fo r (Symbol s : new co m.sun.tool s.javac.mo del.Filter edMemberLi st(clazz.m embers())) { | |
1901 | if (!s.g etKind().i sField()) | |
1902 | cont inue; | |
1903 | ||
1904 | for (Att ribute.Typ eCompound ta : s.get RawTypeAtt ributes()) { | |
1905 | if ( ta.hasUnkn ownPositio n()) | |
1906 | ta.tryFixP osition(); | |
1907 | ||
1908 | if ( ta.positio n.matchesP os(treePos )) | |
1909 | ta.positio n.updatePo sOffset(co de.cp); | |
1910 | } | |
1911 | } | |
1912 | } | |
1913 | ||
1914 | public void visi tNewClass( JCNewClass tree) { | |
1915 | // Enclosing instances or anonym ous classe s should h ave been e liminated | |
1916 | // by now. | |
1917 | As sert.check (tree.encl == null & & tree.def == null); | |
1918 | se tTypeAnnot ationPosit ions(tree. pos); | |
1919 | ||
1920 | co de.emitop2 (new_, mak eRef(tree. pos(), tre e.type)); | |
1921 | co de.emitop0 (dup); | |
1922 | ||
1923 | // Generate code for a ll argumen ts, where the expect ed types a re | |
1924 | // the param eters of t he constru ctor's ext ernal type (that is, | |
1925 | // any impli cit outer instance a ppears as first para meter). | |
1926 | ge nArgs(tree .args, tre e.construc tor.extern alType(typ es).getPar ameterType s()); | |
1927 | ||
1928 | it ems.makeMe mberItem(t ree.constr uctor, tru e).invoke( ); | |
1929 | re sult = ite ms.makeSta ckItem(tre e.type); | |
1930 | } | |
1931 | ||
1932 | public void visi tNewArray( JCNewArray tree) { | |
1933 | se tTypeAnnot ationPosit ions(tree. pos); | |
1934 | ||
1935 | if (tree.ele ms != null ) { | |
1936 | Type ele mtype = ty pes.elemty pe(tree.ty pe); | |
1937 | loadIntC onst(tree. elems.leng th()); | |
1938 | Item arr = makeNew Array(tree .pos(), tr ee.type, 1 ); | |
1939 | int i = 0; | |
1940 | for (Lis t<JCExpres sion> l = tree.elems ; l.nonEmp ty(); l = l.tail) { | |
1941 | arr. duplicate( ); | |
1942 | load IntConst(i ); | |
1943 | i++; | |
1944 | genE xpr(l.head , elemtype ).load(); | |
1945 | item s.makeInde xedItem(el emtype).st ore(); | |
1946 | } | |
1947 | result = arr; | |
1948 | } else { | |
1949 | for (Lis t<JCExpres sion> l = tree.dims; l.nonEmpt y(); l = l .tail) { | |
1950 | genE xpr(l.head , syms.int Type).load (); | |
1951 | } | |
1952 | result = makeNewAr ray(tree.p os(), tree .type, tre e.dims.len gth()); | |
1953 | } | |
1954 | } | |
1955 | //where | |
1956 | /* * Generate code to c reate an a rray with given elem ent type a nd number | |
1957 | * of dimen sions. | |
1958 | * / | |
1959 | It em makeNew Array(Diag nosticPosi tion pos, Type type, int ndims ) { | |
1960 | Type ele mtype = ty pes.elemty pe(type); | |
1961 | if (type s.dimensio ns(type) > ClassFile .MAX_DIMEN SIONS) { | |
1962 | log. error(pos, "limit.di mensions") ; | |
1963 | nerr s++; | |
1964 | } | |
1965 | int elem code = Cod e.arraycod e(elemtype ); | |
1966 | if (elem code == 0 || (elemco de == 1 && ndims == 1)) { | |
1967 | code .emitAnewa rray(makeR ef(pos, el emtype), t ype); | |
1968 | } else i f (elemcod e == 1) { | |
1969 | code .emitMulti anewarray( ndims, mak eRef(pos, type), typ e); | |
1970 | } else { | |
1971 | code .emitNewar ray(elemco de, type); | |
1972 | } | |
1973 | return i tems.makeS tackItem(t ype); | |
1974 | } | |
1975 | ||
1976 | public void visi tParens(JC Parens tre e) { | |
1977 | re sult = gen Expr(tree. expr, tree .expr.type ); | |
1978 | } | |
1979 | ||
1980 | public void visi tAssign(JC Assign tre e) { | |
1981 | It em l = gen Expr(tree. lhs, tree. lhs.type); | |
1982 | ge nExpr(tree .rhs, tree .lhs.type) .load(); | |
1983 | re sult = ite ms.makeAss ignItem(l) ; | |
1984 | } | |
1985 | ||
1986 | public void visi tAssignop( JCAssignOp tree) { | |
1987 | Op eratorSymb ol operato r = (Opera torSymbol) tree.oper ator; | |
1988 | It em l; | |
1989 | if (operator .opcode == string_ad d) { | |
1990 | // Gener ate code t o make a s tring buff er | |
1991 | makeStri ngBuffer(t ree.pos()) ; | |
1992 | ||
1993 | // Gener ate code f or first s tring, pos sibly save one | |
1994 | // copy under buff er | |
1995 | l = genE xpr(tree.l hs, tree.l hs.type); | |
1996 | if (l.wi dth() > 0) { | |
1997 | code .emitop0(d up_x1 + 3 * (l.width () - 1)); | |
1998 | } | |
1999 | ||
2000 | // Load first stri ng and app end to buf fer. | |
2001 | l.load() ; | |
2002 | appendSt ring(tree. lhs); | |
2003 | ||
2004 | // Appen d all othe r strings to buffer. | |
2005 | appendSt rings(tree .rhs); | |
2006 | ||
2007 | // Conve rt buffer to string. | |
2008 | bufferTo String(tre e.pos()); | |
2009 | } else { | |
2010 | // Gener ate code f or first e xpression | |
2011 | l = genE xpr(tree.l hs, tree.l hs.type); | |
2012 | ||
2013 | // If we have an i ncrement o f -32768 t o +32767 o f a local | |
2014 | // int v ariable we can use a n incr ins truction i nstead of | |
2015 | // proce eding furt her. | |
2016 | if ((tre e.hasTag(P LUS_ASG) | | tree.has Tag(MINUS_ ASG)) && | |
2017 | l in stanceof L ocalItem & & | |
2018 | tree .lhs.type. getTag().i sSubRangeO f(INT) && | |
2019 | tree .rhs.type. getTag().i sSubRangeO f(INT) && | |
2020 | tree .rhs.type. constValue () != null ) { | |
2021 | int ival = ((N umber) tre e.rhs.type .constValu e()).intVa lue(); | |
2022 | if ( tree.hasTa g(MINUS_AS G)) ival = -ival; | |
2023 | ((Lo calItem)l) .incr(ival ); | |
2024 | resu lt = l; | |
2025 | retu rn; | |
2026 | } | |
2027 | // Other wise, dupl icate expr ession, lo ad one cop y | |
2028 | // and c omplete bi nary opera tion. | |
2029 | l.duplic ate(); | |
2030 | l.coerce (operator. type.getPa rameterTyp es().head) .load(); | |
2031 | complete Binop(tree .lhs, tree .rhs, oper ator).coer ce(tree.lh s.type); | |
2032 | } | |
2033 | re sult = ite ms.makeAss ignItem(l) ; | |
2034 | } | |
2035 | ||
2036 | public void visi tUnary(JCU nary tree) { | |
2037 | Op eratorSymb ol operato r = (Opera torSymbol) tree.opera tor; | |
2038 | if (tree.has Tag(NOT)) { | |
2039 | CondItem od = genC ond(tree.a rg, false) ; | |
2040 | result = od.negate (); | |
2041 | } else { | |
2042 | Item od = genExpr( tree.arg, operator.t ype.getPar ameterType s().head); | |
2043 | switch ( tree.getTa g()) { | |
2044 | case POS : | |
2045 | resu lt = od.lo ad(); | |
2046 | brea k; | |
2047 | case NEG : | |
2048 | resu lt = od.lo ad(); | |
2049 | code .emitop0(o perator.op code); | |
2050 | brea k; | |
2051 | case COM PL: | |
2052 | resu lt = od.lo ad(); | |
2053 | emit MinusOne(o d.typecode ); | |
2054 | code .emitop0(o perator.op code); | |
2055 | brea k; | |
2056 | case PRE INC: case PREDEC: | |
2057 | od.d uplicate() ; | |
2058 | if ( od instanc eof LocalI tem && | |
2059 | (operator. opcode == iadd || op erator.opc ode == isu b)) { | |
2060 | ((LocalIte m)od).incr (tree.hasT ag(PREINC) ? 1 : -1) ; | |
2061 | result = o d; | |
2062 | } el se { | |
2063 | od.load(); | |
2064 | code.emito p0(one(od. typecode)) ; | |
2065 | code.emito p0(operato r.opcode); | |
2066 | // Perform narrowing primitive conversio n if byte, | |
2067 | // char, o r short. Fix for 43 04655. | |
2068 | if (od.typ ecode != I NTcode && | |
2069 | Code.t runcate(od .typecode) == INTcod e) | |
2070 | code.emi top0(int2b yte + od.t ypecode - BYTEcode); | |
2071 | result = i tems.makeA ssignItem( od); | |
2072 | } | |
2073 | brea k; | |
2074 | case POS TINC: case POSTDEC: | |
2075 | od.d uplicate() ; | |
2076 | if ( od instanc eof LocalI tem && | |
2077 | (operator. opcode == iadd || op erator.opc ode == isu b)) { | |
2078 | Item res = od.load() ; | |
2079 | ((LocalIte m)od).incr (tree.hasT ag(POSTINC ) ? 1 : -1 ); | |
2080 | result = r es; | |
2081 | } el se { | |
2082 | Item res = od.load() ; | |
2083 | od.stash(o d.typecode ); | |
2084 | code.emito p0(one(od. typecode)) ; | |
2085 | code.emito p0(operato r.opcode); | |
2086 | // Perform narrowing primitive conversio n if byte, | |
2087 | // char, o r short. Fix for 43 04655. | |
2088 | if (od.typ ecode != I NTcode && | |
2089 | Code.t runcate(od .typecode) == INTcod e) | |
2090 | code.emi top0(int2b yte + od.t ypecode - BYTEcode); | |
2091 | od.store() ; | |
2092 | result = r es; | |
2093 | } | |
2094 | brea k; | |
2095 | case NUL LCHK: | |
2096 | resu lt = od.lo ad(); | |
2097 | code .emitop0(d up); | |
2098 | genN ullCheck(t ree.pos()) ; | |
2099 | brea k; | |
2100 | default: | |
2101 | Asse rt.error() ; | |
2102 | } | |
2103 | } | |
2104 | } | |
2105 | ||
2106 | /** Ge nerate a n ull check from the o bject valu e at stack top. */ | |
2107 | privat e void gen NullCheck( Diagnostic Position p os) { | |
2108 | ca llMethod(p os, syms.o bjectType, names.get Class, | |
2109 | L ist.<Type> nil(), fal se); | |
2110 | co de.emitop0 (pop); | |
2111 | } | |
2112 | ||
2113 | public void visi tBinary(JC Binary tre e) { | |
2114 | Op eratorSymb ol operato r = (Opera torSymbol) tree.opera tor; | |
2115 | if (operator .opcode == string_ad d) { | |
2116 | // Creat e a string buffer. | |
2117 | makeStri ngBuffer(t ree.pos()) ; | |
2118 | // Appen d all stri ngs to buf fer. | |
2119 | appendSt rings(tree ); | |
2120 | // Conve rt buffer to string. | |
2121 | bufferTo String(tre e.pos()); | |
2122 | result = items.mak eStackItem (syms.stri ngType); | |
2123 | } else if (t ree.hasTag (AND)) { | |
2124 | CondItem lcond = g enCond(tre e.lhs, CRT _FLOW_CONT ROLLER); | |
2125 | if (!lco nd.isFalse ()) { | |
2126 | Chai n falseJum ps = lcond .jumpFalse (); | |
2127 | code .resolve(l cond.trueJ umps); | |
2128 | Cond Item rcond = genCond (tree.rhs, CRT_FLOW_ TARGET); | |
2129 | resu lt = items . | |
2130 | makeCondIt em(rcond.o pcode, | |
2131 | rcond.t rueJumps, | |
2132 | Code.me rgeChains( falseJumps , | |
2133 | rcond.fals eJumps)); | |
2134 | } else { | |
2135 | resu lt = lcond ; | |
2136 | } | |
2137 | } else if (t ree.hasTag (OR)) { | |
2138 | CondItem lcond = g enCond(tre e.lhs, CRT _FLOW_CONT ROLLER); | |
2139 | if (!lco nd.isTrue( )) { | |
2140 | Chai n trueJump s = lcond. jumpTrue() ; | |
2141 | code .resolve(l cond.false Jumps); | |
2142 | Cond Item rcond = genCond (tree.rhs, CRT_FLOW_ TARGET); | |
2143 | resu lt = items . | |
2144 | makeCondIt em(rcond.o pcode, | |
2145 | Code.me rgeChains( trueJumps, rcond.tru eJumps), | |
2146 | rcond.f alseJumps) ; | |
2147 | } else { | |
2148 | resu lt = lcond ; | |
2149 | } | |
2150 | } else { | |
2151 | Item od = genExpr( tree.lhs, operator.t ype.getPar ameterType s().head); | |
2152 | od.load( ); | |
2153 | result = completeB inop(tree. lhs, tree. rhs, opera tor); | |
2154 | } | |
2155 | } | |
2156 | //where | |
2157 | /* * Make a n ew string buffer. | |
2158 | * / | |
2159 | vo id makeStr ingBuffer( Diagnostic Position p os) { | |
2160 | code.emi top2(new_, makeRef(p os, string BufferType )); | |
2161 | code.emi top0(dup); | |
2162 | callMeth od( | |
2163 | pos, stringBuf ferType, n ames.init, List.<Typ e>nil(), f alse); | |
2164 | } | |
2165 | ||
2166 | /* * Append v alue (on t os) to str ing buffer (on tos - 1). | |
2167 | * / | |
2168 | vo id appendS tring(JCTr ee tree) { | |
2169 | Type t = tree.type .baseType( ); | |
2170 | if (!t.i sPrimitive () && t.ts ym != syms .stringTyp e.tsym) { | |
2171 | t = syms.objec tType; | |
2172 | } | |
2173 | items.ma keMemberIt em(getStri ngBufferAp pend(tree, t), false ).invoke() ; | |
2174 | } | |
2175 | Sy mbol getSt ringBuffer Append(JCT ree tree, Type t) { | |
2176 | Assert.c heckNull(t .constValu e()); | |
2177 | Symbol m ethod = st ringBuffer Append.get (t); | |
2178 | if (meth od == null ) { | |
2179 | meth od = rs.re solveInter nalMethod( tree.pos() , | |
2180 | attrEnv, | |
2181 | stringBuff erType, | |
2182 | names.appe nd, | |
2183 | List.of(t) , | |
2184 | null); | |
2185 | stri ngBufferAp pend.put(t , method); | |
2186 | } | |
2187 | return m ethod; | |
2188 | } | |
2189 | ||
2190 | /* * Add all strings in tree to s tring buff er. | |
2191 | * / | |
2192 | vo id appendS trings(JCT ree tree) { | |
2193 | tree = T reeInfo.sk ipParens(t ree); | |
2194 | if (tree .hasTag(PL US) && tre e.type.con stValue() == null) { | |
2195 | JCBi nary op = (JCBinary) tree; | |
2196 | if ( op.operato r.kind == MTH && | |
2197 | ((Operator Symbol) op .operator) .opcode == string_ad d) { | |
2198 | appendStri ngs(op.lhs ); | |
2199 | appendStri ngs(op.rhs ); | |
2200 | return; | |
2201 | } | |
2202 | } | |
2203 | genExpr( tree, tree .type).loa d(); | |
2204 | appendSt ring(tree) ; | |
2205 | } | |
2206 | ||
2207 | /* * Convert string buf fer on tos to string . | |
2208 | * / | |
2209 | vo id bufferT oString(Di agnosticPo sition pos ) { | |
2210 | callMeth od( | |
2211 | pos, | |
2212 | stri ngBufferTy pe, | |
2213 | name s.toString , | |
2214 | List .<Type>nil (), | |
2215 | fals e); | |
2216 | } | |
2217 | ||
2218 | /* * Complete generatin g code for operation , with lef t operand | |
2219 | * already on stack. | |
2220 | * @param l hs T he tree re presenting the left operand. | |
2221 | * @param r hs T he tree re presenting the right operand. | |
2222 | * @param o perator T he operato r symbol. | |
2223 | * / | |
2224 | It em complet eBinop(JCT ree lhs, J CTree rhs, OperatorS ymbol oper ator) { | |
2225 | MethodTy pe optype = (MethodT ype)operat or.type; | |
2226 | int opco de = opera tor.opcode ; | |
2227 | if (opco de >= if_i cmpeq && o pcode <= i f_icmple & & | |
2228 | rhs. type.const Value() in stanceof N umber && | |
2229 | ((Nu mber) rhs. type.const Value()).i ntValue() == 0) { | |
2230 | opco de = opcod e + (ifeq - if_icmpe q); | |
2231 | } else i f (opcode >= if_acmp eq && opco de <= if_a cmpne && | |
2232 | TreeInf o.isNull(r hs)) { | |
2233 | opco de = opcod e + (if_ac mp_null - if_acmpeq) ; | |
2234 | } else { | |
2235 | // T he expecte d type of the right operand is | |
2236 | // t he second parameter type of th e operator , except f or | |
2237 | // s hifts with long shif tcount, wh ere we con vert the o pcode | |
2238 | // t o a short shift and the expect ed type to int. | |
2239 | Type rtype = o perator.er asure(type s).getPara meterTypes ().tail.he ad; | |
2240 | if ( opcode >= ishll && o pcode <= l ushrl) { | |
2241 | opcode = o pcode + (i shl - ishl l); | |
2242 | rtype = sy ms.intType ; | |
2243 | } | |
2244 | // G enerate co de for rig ht operand and load. | |
2245 | genE xpr(rhs, r type).load (); | |
2246 | // I f there ar e two cons ecutive op code instr uctions, | |
2247 | // e mit the fi rst now. | |
2248 | if ( opcode >= (1 << preS hift)) { | |
2249 | code.emito p0(opcode >> preShif t); | |
2250 | opcode = o pcode & 0x FF; | |
2251 | } | |
2252 | } | |
2253 | if (opco de >= ifeq && opcode <= if_acm pne || | |
2254 | opco de == if_a cmp_null | | opcode = = if_acmp_ nonnull) { | |
2255 | retu rn items.m akeCondIte m(opcode); | |
2256 | } else { | |
2257 | code .emitop0(o pcode); | |
2258 | retu rn items.m akeStackIt em(optype. restype); | |
2259 | } | |
2260 | } | |
2261 | ||
2262 | public void visi tTypeCast( JCTypeCast tree) { | |
2263 | se tTypeAnnot ationPosit ions(tree. pos); | |
2264 | re sult = gen Expr(tree. expr, tree .clazz.typ e).load(); | |
2265 | // Additiona l code is only neede d if we ca st to a re ference ty pe | |
2266 | // which is not static ally a sup ertype of the expres sion's typ e. | |
2267 | // For basic types, th e coerce(. ..) in gen Expr(...) will do | |
2268 | // the conve rsion. | |
2269 | if (!tree.cl azz.type.i sPrimitive () && | |
2270 | types.as Super(tree .expr.type , tree.cla zz.type.ts ym) == nul l) { | |
2271 | code.emi top2(check cast, make Ref(tree.p os(), tree .clazz.typ e)); | |
2272 | } | |
2273 | } | |
2274 | ||
2275 | public void visi tWildcard( JCWildcard tree) { | |
2276 | th row new As sertionErr or(this.ge tClass().g etName()); | |
2277 | } | |
2278 | ||
2279 | public void visi tTypeTest( JCInstance Of tree) { | |
2280 | se tTypeAnnot ationPosit ions(tree. pos); | |
2281 | ge nExpr(tree .expr, tre e.expr.typ e).load(); | |
2282 | co de.emitop2 (instanceo f_, makeRe f(tree.pos (), tree.c lazz.type) ); | |
2283 | re sult = ite ms.makeSta ckItem(sym s.booleanT ype); | |
2284 | } | |
2285 | ||
2286 | public void visi tIndexed(J CArrayAcce ss tree) { | |
2287 | ge nExpr(tree .indexed, tree.index ed.type).l oad(); | |
2288 | ge nExpr(tree .index, sy ms.intType ).load(); | |
2289 | re sult = ite ms.makeInd exedItem(t ree.type); | |
2290 | } | |
2291 | ||
2292 | public void visi tIdent(JCI dent tree) { | |
2293 | Sy mbol sym = tree.sym; | |
2294 | if (tree.nam e == names ._this || tree.name == names._ super) { | |
2295 | Item res = tree.na me == name s._this | |
2296 | ? it ems.makeTh isItem() | |
2297 | : it ems.makeSu perItem(); | |
2298 | if (sym. kind == MT H) { | |
2299 | // G enerate co de to addr ess the co nstructor. | |
2300 | res. load(); | |
2301 | res = items.ma keMemberIt em(sym, tr ue); | |
2302 | } | |
2303 | result = res; | |
2304 | } else if (s ym.kind == VAR && sy m.owner.ki nd == MTH) { | |
2305 | result = items.mak eLocalItem ((VarSymbo l)sym); | |
2306 | } else if (i sInvokeDyn amic(sym)) { | |
2307 | result = items.mak eDynamicIt em(sym); | |
2308 | } else if (( sym.flags( ) & STATIC ) != 0) { | |
2309 | if (!isA ccessSuper (env.enclM ethod)) | |
2310 | sym = binaryQu alifier(sy m, env.enc lClass.typ e); | |
2311 | result = items.mak eStaticIte m(sym); | |
2312 | } else { | |
2313 | items.ma keThisItem ().load(); | |
2314 | sym = bi naryQualif ier(sym, e nv.enclCla ss.type); | |
2315 | result = items.mak eMemberIte m(sym, (sy m.flags() & PRIVATE) != 0); | |
2316 | } | |
2317 | } | |
2318 | ||
2319 | public void visi tSelect(JC FieldAcces s tree) { | |
2320 | Sy mbol sym = tree.sym; | |
2321 | ||
2322 | if (tree.nam e == names ._class) { | |
2323 | Assert.c heck(targe t.hasClass Literals() ); | |
2324 | code.emi tLdc(makeR ef(tree.po s(), tree. selected.t ype)); | |
2325 | result = items.mak eStackItem (pt); | |
2326 | return; | |
2327 | } | |
2328 | ||
2329 | Sy mbol ssym = TreeInfo .symbol(tr ee.selecte d); | |
2330 | ||
2331 | // Are we se lecting vi a super? | |
2332 | bo olean sele ctSuper = | |
2333 | ssym != null && (s sym.kind = = TYP || s sym.name = = names._s uper); | |
2334 | ||
2335 | // Are we ac cessing a member of the superc lass in an access me thod | |
2336 | // resulting from a qu alified su per? | |
2337 | bo olean acce ssSuper = isAccessSu per(env.en clMethod); | |
2338 | ||
2339 | It em base = (selectSup er) | |
2340 | ? items. makeSuperI tem() | |
2341 | : genExp r(tree.sel ected, tre e.selected .type); | |
2342 | ||
2343 | if (sym.kind == VAR && ((VarSymb ol) sym).g etConstVal ue() != nu ll) { | |
2344 | // We ar e seeing a variable that is co nstant but its selec ting | |
2345 | // expre ssion is n ot. | |
2346 | if ((sym .flags() & STATIC) ! = 0) { | |
2347 | if ( !selectSup er && (ssy m == null || ssym.ki nd != TYP) ) | |
2348 | base = bas e.load(); | |
2349 | base .drop(); | |
2350 | } else { | |
2351 | base .load(); | |
2352 | genN ullCheck(t ree.select ed.pos()); | |
2353 | } | |
2354 | result = items. | |
2355 | make ImmediateI tem(sym.ty pe, ((VarS ymbol) sym ).getConst Value()); | |
2356 | } else { | |
2357 | if (isIn vokeDynami c(sym)) { | |
2358 | resu lt = items .makeDynam icItem(sym ); | |
2359 | retu rn; | |
2360 | } else { | |
2361 | sym = binaryQu alifier(sy m, tree.se lected.typ e); | |
2362 | } | |
2363 | if ((sym .flags() & STATIC) ! = 0) { | |
2364 | if ( !selectSup er && (ssy m == null || ssym.ki nd != TYP) ) | |
2365 | base = bas e.load(); | |
2366 | base .drop(); | |
2367 | resu lt = items .makeStati cItem(sym) ; | |
2368 | } else { | |
2369 | base .load(); | |
2370 | if ( sym == sym s.lengthVa r) { | |
2371 | code.emito p0(arrayle ngth); | |
2372 | result = i tems.makeS tackItem(s yms.intTyp e); | |
2373 | } el se { | |
2374 | result = i tems. | |
2375 | makeMe mberItem(s ym, | |
2376 | ( sym.flags( ) & PRIVAT E) != 0 || | |
2377 | s electSuper || access Super); | |
2378 | } | |
2379 | } | |
2380 | } | |
2381 | } | |
2382 | ||
2383 | public boolean i sInvokeDyn amic(Symbo l sym) { | |
2384 | re turn sym.k ind == MTH && ((Meth odSymbol)s ym).isDyna mic(); | |
2385 | } | |
2386 | ||
2387 | public void visi tLiteral(J CLiteral t ree) { | |
2388 | if (tree.typ e.hasTag(B OT)) { | |
2389 | code.emi top0(acons t_null); | |
2390 | if (type s.dimensio ns(pt) > 1 ) { | |
2391 | code .emitop2(c heckcast, makeRef(tr ee.pos(), pt)); | |
2392 | resu lt = items .makeStack Item(pt); | |
2393 | } else { | |
2394 | resu lt = items .makeStack Item(tree. type); | |
2395 | } | |
2396 | } | |
2397 | el se | |
2398 | result = items.mak eImmediate Item(tree. type, tree .value); | |
2399 | } | |
2400 | ||
2401 | public void visi tLetExpr(L etExpr tre e) { | |
2402 | in t limit = code.nextr eg; | |
2403 | ge nStats(tre e.defs, en v); | |
2404 | re sult = gen Expr(tree. expr, tree .expr.type ).load(); | |
2405 | co de.endScop es(limit); | |
2406 | } | |
2407 | ||
2408 | privat e void gen erateRefer encesToPru nedTree(Cl assSymbol classSymbo l, Pool po ol) { | |
2409 | Li st<JCTree> prunedInf o = lower. prunedTree .get(class Symbol); | |
2410 | if (prunedIn fo != null ) { | |
2411 | for (JCT ree pruned Tree: prun edInfo) { | |
2412 | prun edTree.acc ept(classR eferenceVi sitor); | |
2413 | } | |
2414 | } | |
2415 | } | |
2416 | ||
2417 | /* ******* ********** ********** ********** ********** ********** ********** ***** | |
2418 | * main me thod | |
2419 | ********* ********** ********** ********** ********** ********** ********** ****/ | |
2420 | ||
2421 | /** Ge nerate cod e for a cl ass defini tion. | |
2422 | * @p aram env The attri bution env ironment t hat belong s to the | |
2423 | * outermost class con taining th is class d efinition. | |
2424 | * We need t his for re solving so me additio nal symbol s. | |
2425 | * @p aram cdef The tree representi ng the cla ss definit ion. | |
2426 | * @r eturn True if c ode is gen erated wit h no error s. | |
2427 | */ | |
2428 | public boolean g enClass(En v<AttrCont ext> env, JCClassDec l cdef) { | |
2429 | tr y { | |
2430 | attrEnv = env; | |
2431 | ClassSym bol c = cd ef.sym; | |
2432 | this.top level = en v.toplevel ; | |
2433 | this.end PosTable = toplevel. endPositio ns; | |
2434 | // If th is is a cl ass defini tion requi ring Miran da methods , | |
2435 | // add t hem. | |
2436 | if (gene rateIproxi es && | |
2437 | (c.f lags() & ( INTERFACE| ABSTRACT)) == ABSTRA CT | |
2438 | && ! allowGener ics // no Miranda me thods avai lable with generics | |
2439 | ) | |
2440 | impl ementInter faceMethod s(c); | |
2441 | c.pool = pool; | |
2442 | pool.res et(); | |
2443 | /* metho d normaliz eDefs() ca n add refe rences to external c lasses int o the cons tant pool | |
2444 | * so it should be called af ter pool.r eset() | |
2445 | */ | |
2446 | cdef.def s = normal izeDefs(cd ef.defs, c ); | |
2447 | generate References ToPrunedTr ee(c, pool ); | |
2448 | Env<GenC ontext> lo calEnv = | |
2449 | new Env<GenCon text>(cdef , new GenC ontext()); | |
2450 | localEnv .toplevel = env.topl evel; | |
2451 | localEnv .enclClass = cdef; | |
2452 | ||
2453 | for (Lis t<JCTree> l = cdef.d efs; l.non Empty(); l = l.tail) { | |
2454 | genD ef(l.head, localEnv) ; | |
2455 | } | |
2456 | if (pool .numEntrie s() > Pool .MAX_ENTRI ES) { | |
2457 | log. error(cdef .pos(), "l imit.pool" ); | |
2458 | nerr s++; | |
2459 | } | |
2460 | if (nerr s != 0) { | |
2461 | // i f errors, discard co de | |
2462 | for (List<JCTr ee> l = cd ef.defs; l .nonEmpty( ); l = l.t ail) { | |
2463 | if (l.head .hasTag(ME THODDEF)) | |
2464 | ((JCMe thodDecl) l.head).sy m.code = n ull; | |
2465 | } | |
2466 | } | |
2467 | cdef.def s = List.n il(); // d iscard tre es | |
2468 | return n errs == 0; | |
2469 | } finally { | |
2470 | // note: this meth od does NO T support recursion. | |
2471 | attrEnv = null; | |
2472 | this.env = null; | |
2473 | toplevel = null; | |
2474 | endPosTa ble = null ; | |
2475 | nerrs = 0; | |
2476 | } | |
2477 | } | |
2478 | ||
2479 | /* ******* ********** ********** ********** ********** ********** ********** ***** | |
2480 | * Auxilia ry classes | |
2481 | ********* ********** ********** ********** ********** ********** ********** ****/ | |
2482 | ||
2483 | /** An abstract class for finalizer generation . | |
2484 | */ | |
2485 | abstra ct class G enFinalize r { | |
2486 | /* * Generate code to c lean up wh en unwindi ng. */ | |
2487 | ab stract voi d gen(); | |
2488 | ||
2489 | /* * Generate code to c lean up at last. */ | |
2490 | ab stract voi d genLast( ); | |
2491 | ||
2492 | /* * Does thi s finalize r have som e nontrivi al cleanup to perfor m? */ | |
2493 | bo olean hasF inalizer() { return true; } | |
2494 | } | |
2495 | ||
2496 | /** co de generat ion contex ts, | |
2497 | * to be used a s type par ameter for environme nts. | |
2498 | */ | |
2499 | static class Gen Context { | |
2500 | ||
2501 | /* * A chain for all un resolved j umps that exit the c urrent env ironment. | |
2502 | * / | |
2503 | Ch ain exit = null; | |
2504 | ||
2505 | /* * A chain for all un resolved j umps that continue i n the | |
2506 | * current environmen t. | |
2507 | * / | |
2508 | Ch ain cont = null; | |
2509 | ||
2510 | /* * A closur e that gen erates the finalizer of the cu rrent envi ronment. | |
2511 | * Only set for Synch ronized an d Try cont exts. | |
2512 | * / | |
2513 | Ge nFinalizer finalize = null; | |
2514 | ||
2515 | /* * Is this a switch s tatement? If so, al locate reg isters | |
2516 | * even when the varia ble declar ation is u nreachable . | |
2517 | * / | |
2518 | bo olean isSw itch = fal se; | |
2519 | ||
2520 | /* * A list b uffer cont aining all gaps in t he finaliz er range, | |
2521 | * where a catch all exception should not apply. | |
2522 | * / | |
2523 | Li stBuffer<I nteger> ga ps = null; | |
2524 | ||
2525 | /* * Add give n chain to exit chai n. | |
2526 | * / | |
2527 | vo id addExit (Chain c) { | |
2528 | exit = C ode.mergeC hains(c, e xit); | |
2529 | } | |
2530 | ||
2531 | /* * Add give n chain to cont chai n. | |
2532 | * / | |
2533 | vo id addCont (Chain c) { | |
2534 | cont = C ode.mergeC hains(c, c ont); | |
2535 | } | |
2536 | } | |
2537 | ||
2538 | } |
Araxis Merge (but not the data content of this report) is Copyright © 1993-2016 Araxis Ltd (www.araxis.com). All rights reserved.