• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #if 0
18 
19 /*
20  * Rebuild the interpreter frame then punt to the interpreter to execute
21  * instruction at specified PC.
22  *
23  * Currently parameters are passed to the current frame, so we just need to
24  * grow the stack save area above it, fill certain fields in StackSaveArea and
25  * Thread that are skipped during whole-method invocation (specified below),
26  * then return to the interpreter.
27  *
28  * StackSaveArea:
29  *  - prevSave
30  *  - prevFrame
31  *  - savedPc
32  *  - returnAddr
33  *  - method
34  *
35  * Thread:
36  *  - method
37  *  - methodClassDex
38  *  - curFrame
39  */
40 static void genMethodInflateAndPunt(CompilationUnit *cUnit, MIR *mir,
41                                     BasicBlock *bb)
42 {
43     int oldStackSave = r0;
44     int newStackSave = r1;
45     int oldFP = r2;
46     int savedPC = r3;
47     int currentPC = r4PC;
48     int returnAddr = r7;
49     int method = r8;
50     int pDvmDex = r9;
51 
52     /*
53      * TODO: check whether to raise the stack overflow exception when growing
54      * the stack save area.
55      */
56 
57     /* Send everything to home location */
58     dvmCompilerFlushAllRegs(cUnit);
59 
60     /* oldStackSave = r5FP + sizeof(current frame) */
61     opRegRegImm(cUnit, kOpAdd, oldStackSave, r5FP,
62                 cUnit->method->registersSize * 4);
63     /* oldFP = oldStackSave + sizeof(stackSaveArea) */
64     opRegRegImm(cUnit, kOpAdd, oldFP, oldStackSave, sizeof(StackSaveArea));
65     /* newStackSave = r5FP - sizeof(StackSaveArea) */
66     opRegRegImm(cUnit, kOpSub, newStackSave, r5FP, sizeof(StackSaveArea));
67 
68     loadWordDisp(cUnit, r13sp, 0, savedPC);
69     loadConstant(cUnit, currentPC, (int) (cUnit->method->insns + mir->offset));
70     loadConstant(cUnit, method, (int) cUnit->method);
71     loadConstant(cUnit, pDvmDex, (int) cUnit->method->clazz->pDvmDex);
72 #ifdef EASY_GDB
73     /* newStackSave->prevSave = oldStackSave */
74     storeWordDisp(cUnit, newStackSave, offsetof(StackSaveArea, prevSave),
75                   oldStackSave);
76 #endif
77     /* newStackSave->prevSave = oldStackSave */
78     storeWordDisp(cUnit, newStackSave, offsetof(StackSaveArea, prevFrame),
79                   oldFP);
80     /* newStackSave->savedPc = savedPC */
81     storeWordDisp(cUnit, newStackSave, offsetof(StackSaveArea, savedPc),
82                   savedPC);
83     /* return address */
84     loadConstant(cUnit, returnAddr, 0);
85     storeWordDisp(cUnit, newStackSave, offsetof(StackSaveArea, returnAddr),
86                   returnAddr);
87     /* newStackSave->method = method */
88     storeWordDisp(cUnit, newStackSave, offsetof(StackSaveArea, method), method);
89     /* thread->method = method */
90     storeWordDisp(cUnit, r6SELF, offsetof(InterpSaveState, method), method);
91     /* thread->interpSave.curFrame = current FP */
92     storeWordDisp(cUnit, r6SELF, offsetof(Thread, interpSave.curFrame), r5FP);
93     /* thread->methodClassDex = pDvmDex */
94     storeWordDisp(cUnit, r6SELF, offsetof(InterpSaveState, methodClassDex),
95                   pDvmDex);
96     /* Restore the stack pointer */
97     opRegImm(cUnit, kOpAdd, r13sp, 16);
98     genPuntToInterp(cUnit, mir->offset);
99 }
100 
101 /*
102  * The following are the first-level codegen routines that analyze the format
103  * of each bytecode then either dispatch special purpose codegen routines
104  * or produce corresponding Thumb instructions directly.
105  *
106  * TODO - most them are just pass-through to the trace-based versions for now
107  */
108 static bool handleMethodFmt10t_Fmt20t_Fmt30t(CompilationUnit *cUnit, MIR *mir,
109                                              BasicBlock *bb, ArmLIR *labelList)
110 {
111     /* backward branch? */
112     bool backwardBranch = (bb->taken->startOffset <= mir->offset);
113 
114     if (backwardBranch && gDvmJit.genSuspendPoll) {
115         genSuspendPoll(cUnit, mir);
116     }
117 
118     /* For OP_GOTO, OP_GOTO_16, and OP_GOTO_32 */
119     genUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
120     return false;
121 }
122 
123 static bool handleMethodFmt10x(CompilationUnit *cUnit, MIR *mir)
124 {
125     Opcode dalvikOpcode = mir->dalvikInsn.opcode;
126     switch (dalvikOpcode) {
127         case OP_RETURN_VOID:
128             return false;
129         default:
130             return handleFmt10x(cUnit, mir);
131     }
132 }
133 
134 static bool handleMethodFmt11n_Fmt31i(CompilationUnit *cUnit, MIR *mir)
135 {
136     return handleFmt11n_Fmt31i(cUnit, mir);
137 }
138 
139 static bool handleMethodFmt11x(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
140                                ArmLIR *labelList)
141 {
142     Opcode dalvikOpcode = mir->dalvikInsn.opcode;
143     switch (dalvikOpcode) {
144         case OP_THROW:
145             genMethodInflateAndPunt(cUnit, mir, bb);
146             return false;
147         default:
148             return handleFmt11x(cUnit, mir);
149     }
150 }
151 
152 static bool handleMethodFmt12x(CompilationUnit *cUnit, MIR *mir)
153 {
154     return handleFmt12x(cUnit, mir);
155 }
156 
157 static bool handleMethodFmt20bc(CompilationUnit *cUnit, MIR *mir)
158 {
159     return handleFmt20bc(cUnit, mir);
160 }
161 
162 static bool handleMethodFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
163 {
164     return handleFmt21c_Fmt31c(cUnit, mir);
165 }
166 
167 static bool handleMethodFmt21h(CompilationUnit *cUnit, MIR *mir)
168 {
169     return handleFmt21h(cUnit, mir);
170 }
171 
172 static bool handleMethodFmt21s(CompilationUnit *cUnit, MIR *mir)
173 {
174     return handleFmt21s(cUnit, mir);
175 }
176 
177 static bool handleMethodFmt21t(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
178                                ArmLIR *labelList)
179 {
180     return handleFmt21t(cUnit, mir, bb, labelList);
181 }
182 
183 static bool handleMethodFmt22b_Fmt22s(CompilationUnit *cUnit, MIR *mir)
184 {
185     return handleFmt22b_Fmt22s(cUnit, mir);
186 }
187 
188 static bool handleMethodFmt22c(CompilationUnit *cUnit, MIR *mir)
189 {
190     return handleFmt22c(cUnit, mir);
191 }
192 
193 static bool handleMethodFmt22cs(CompilationUnit *cUnit, MIR *mir)
194 {
195     return handleFmt22cs(cUnit, mir);
196 }
197 
198 static bool handleMethodFmt22t(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
199                                ArmLIR *labelList)
200 {
201     return handleFmt22t(cUnit, mir, bb, labelList);
202 }
203 
204 static bool handleMethodFmt22x_Fmt32x(CompilationUnit *cUnit, MIR *mir)
205 {
206     return handleFmt22x_Fmt32x(cUnit, mir);
207 }
208 
209 static bool handleMethodFmt23x(CompilationUnit *cUnit, MIR *mir)
210 {
211     return handleFmt23x(cUnit, mir);
212 }
213 
214 static bool handleMethodFmt31t(CompilationUnit *cUnit, MIR *mir)
215 {
216     return handleFmt31t(cUnit, mir);
217 }
218 
219 static bool handleMethodFmt35c_3rc(CompilationUnit *cUnit, MIR *mir,
220                                        BasicBlock *bb, ArmLIR *labelList)
221 {
222     return handleFmt35c_3rc(cUnit, mir, bb, labelList);
223 }
224 
225 static bool handleMethodFmt35ms_3rms(CompilationUnit *cUnit, MIR *mir,
226                                      BasicBlock *bb, ArmLIR *labelList)
227 {
228     return handleFmt35ms_3rms(cUnit, mir, bb, labelList);
229 }
230 
231 static bool handleMethodExecuteInline(CompilationUnit *cUnit, MIR *mir)
232 {
233     return handleExecuteInline(cUnit, mir);
234 }
235 
236 static bool handleMethodFmt51l(CompilationUnit *cUnit, MIR *mir)
237 {
238     return handleFmt51l(cUnit, mir);
239 }
240 
241 /* Handle the content in each basic block */
242 static bool methodBlockCodeGen(CompilationUnit *cUnit, BasicBlock *bb)
243 {
244     MIR *mir;
245     ArmLIR *labelList = (ArmLIR *) cUnit->blockLabelList;
246     int blockId = bb->id;
247 
248     cUnit->curBlock = bb;
249     labelList[blockId].operands[0] = bb->startOffset;
250 
251     /* Insert the block label */
252     labelList[blockId].opcode = kArmPseudoNormalBlockLabel;
253     dvmCompilerAppendLIR(cUnit, (LIR *) &labelList[blockId]);
254 
255     dvmCompilerClobberAllRegs(cUnit);
256     dvmCompilerResetNullCheck(cUnit);
257 
258     ArmLIR *headLIR = NULL;
259 
260     if (bb->blockType == kEntryBlock) {
261         /* r0 = callsitePC */
262         opImm(cUnit, kOpPush, (1 << r0 | 1 << r1 | 1 << r5FP | 1 << r14lr));
263         opRegImm(cUnit, kOpSub, r5FP,
264                  sizeof(StackSaveArea) + cUnit->method->registersSize * 4);
265 
266     } else if (bb->blockType == kExitBlock) {
267         /* No need to pop r0 and r1 */
268         opRegImm(cUnit, kOpAdd, r13sp, 8);
269         opImm(cUnit, kOpPop, (1 << r5FP | 1 << r15pc));
270     }
271 
272     for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
273 
274         dvmCompilerResetRegPool(cUnit);
275         if (gDvmJit.disableOpt & (1 << kTrackLiveTemps)) {
276             dvmCompilerClobberAllRegs(cUnit);
277         }
278 
279         if (gDvmJit.disableOpt & (1 << kSuppressLoads)) {
280             dvmCompilerResetDefTracking(cUnit);
281         }
282 
283         Opcode dalvikOpcode = mir->dalvikInsn.opcode;
284         InstructionFormat dalvikFormat =
285             dexGetFormatFromOpcode(dalvikOpcode);
286 
287         ArmLIR *boundaryLIR;
288 
289         /*
290          * Don't generate the boundary LIR unless we are debugging this
291          * trace or we need a scheduling barrier.
292          */
293         if (headLIR == NULL || cUnit->printMe == true) {
294             boundaryLIR =
295                 newLIR2(cUnit, kArmPseudoDalvikByteCodeBoundary,
296                         mir->offset,
297                         (int) dvmCompilerGetDalvikDisassembly(
298                             &mir->dalvikInsn, ""));
299             /* Remember the first LIR for this block */
300             if (headLIR == NULL) {
301                 headLIR = boundaryLIR;
302                 /* Set the first boundaryLIR as a scheduling barrier */
303                 headLIR->defMask = ENCODE_ALL;
304             }
305         }
306 
307         /* Don't generate the SSA annotation unless verbose mode is on */
308         if (cUnit->printMe && mir->ssaRep) {
309             char *ssaString = dvmCompilerGetSSAString(cUnit, mir->ssaRep);
310             newLIR1(cUnit, kArmPseudoSSARep, (int) ssaString);
311         }
312 
313         bool notHandled;
314         switch (dalvikFormat) {
315             case kFmt10t:
316             case kFmt20t:
317             case kFmt30t:
318                 notHandled = handleMethodFmt10t_Fmt20t_Fmt30t(cUnit, mir, bb,
319                                                               labelList);
320                 break;
321             case kFmt10x:
322                 notHandled = handleMethodFmt10x(cUnit, mir);
323                 break;
324             case kFmt11n:
325             case kFmt31i:
326                 notHandled = handleMethodFmt11n_Fmt31i(cUnit, mir);
327                 break;
328             case kFmt11x:
329                 notHandled = handleMethodFmt11x(cUnit, mir, bb, labelList);
330                 break;
331             case kFmt12x:
332                 notHandled = handleMethodFmt12x(cUnit, mir);
333                 break;
334             case kFmt20bc:
335                 notHandled = handleMethodFmt20bc(cUnit, mir);
336                 break;
337             case kFmt21c:
338             case kFmt31c:
339                 notHandled = handleMethodFmt21c_Fmt31c(cUnit, mir);
340                 break;
341             case kFmt21h:
342                 notHandled = handleMethodFmt21h(cUnit, mir);
343                 break;
344             case kFmt21s:
345                 notHandled = handleMethodFmt21s(cUnit, mir);
346                 break;
347             case kFmt21t:
348                 notHandled = handleMethodFmt21t(cUnit, mir, bb, labelList);
349                 break;
350             case kFmt22b:
351             case kFmt22s:
352                 notHandled = handleMethodFmt22b_Fmt22s(cUnit, mir);
353                 break;
354             case kFmt22c:
355                 notHandled = handleMethodFmt22c(cUnit, mir);
356                 break;
357             case kFmt22cs:
358                 notHandled = handleMethodFmt22cs(cUnit, mir);
359                 break;
360             case kFmt22t:
361                 notHandled = handleMethodFmt22t(cUnit, mir, bb, labelList);
362                 break;
363             case kFmt22x:
364             case kFmt32x:
365                 notHandled = handleMethodFmt22x_Fmt32x(cUnit, mir);
366                 break;
367             case kFmt23x:
368                 notHandled = handleMethodFmt23x(cUnit, mir);
369                 break;
370             case kFmt31t:
371                 notHandled = handleMethodFmt31t(cUnit, mir);
372                 break;
373             case kFmt3rc:
374             case kFmt35c:
375                 notHandled = handleMethodFmt35c_3rc(cUnit, mir, bb, labelList);
376                 break;
377             case kFmt3rms:
378             case kFmt35ms:
379                 notHandled = handleMethodFmt35ms_3rms(cUnit, mir, bb,
380                                                       labelList);
381                 break;
382             case kFmt35mi:
383             case kFmt3rmi:
384                 notHandled = handleMethodExecuteInline(cUnit, mir);
385                 break;
386             case kFmt51l:
387                 notHandled = handleMethodFmt51l(cUnit, mir);
388                 break;
389             default:
390                 notHandled = true;
391                 break;
392         }
393 
394         /* FIXME - to be implemented */
395         if (notHandled == true && dalvikOpcode >= kNumPackedOpcodes) {
396             notHandled = false;
397         }
398 
399         if (notHandled) {
400             ALOGE("%#06x: Opcode %#x (%s) / Fmt %d not handled",
401                  mir->offset,
402                  dalvikOpcode, dexGetOpcodeName(dalvikOpcode),
403                  dalvikFormat);
404             dvmCompilerAbort(cUnit);
405             break;
406         }
407     }
408 
409     if (headLIR) {
410         /*
411          * Eliminate redundant loads/stores and delay stores into later
412          * slots
413          */
414         dvmCompilerApplyLocalOptimizations(cUnit, (LIR *) headLIR,
415                                            cUnit->lastLIRInsn);
416 
417         /*
418          * Generate an unconditional branch to the fallthrough block.
419          */
420         if (bb->fallThrough) {
421             genUnconditionalBranch(cUnit,
422                                    &labelList[bb->fallThrough->id]);
423         }
424     }
425     return false;
426 }
427 
428 void dvmCompilerMethodMIR2LIR(CompilationUnit *cUnit)
429 {
430     // FIXME - enable method compilation for selected routines here
431     if (strcmp(cUnit->method->name, "add")) return;
432 
433     /* Used to hold the labels of each block */
434     cUnit->blockLabelList =
435         (void *) dvmCompilerNew(sizeof(ArmLIR) * cUnit->numBlocks, true);
436 
437     dvmCompilerDataFlowAnalysisDispatcher(cUnit, methodBlockCodeGen,
438                                           kPreOrderDFSTraversal,
439                                           false /* isIterative */);
440 
441     dvmCompilerApplyGlobalOptimizations(cUnit);
442 
443     // FIXME - temporarily enable verbose printing for all methods
444     cUnit->printMe = true;
445 
446 #if defined(WITH_SELF_VERIFICATION)
447     selfVerificationBranchInsertPass(cUnit);
448 #endif
449 }
450 
451 #else
452 
dvmCompilerMethodMIR2LIR(CompilationUnit * cUnit)453 void dvmCompilerMethodMIR2LIR(CompilationUnit *cUnit) {
454     // Method-based JIT not supported for ARM.
455 }
456 
457 #endif
458