• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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 /*
18  * This file contains codegen and support common to all supported
19  * X86 variants.  It is included by:
20  *
21  *        Codegen-$(TARGET_ARCH_VARIANT).c
22  *
23  * which combines this common code with specific support found in the
24  * applicable directory below this one.
25  */
26 
27 extern X86LIR *loadConstant(CompilationUnit *cUnit, int rDest, int value);
28 extern X86LIR *loadWordDisp(CompilationUnit *cUnit, int rBase,
29                             int displacement, int rDest);
30 extern void dvmCompilerFlushAllRegs(CompilationUnit *cUnit);
31 extern void storeWordDisp(CompilationUnit *cUnit, int rBase,
32                           int displacement, int rSrc);
33 extern X86LIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc);
34 
35 static int opcodeCoverage[kNumPackedOpcodes];
36 static intptr_t templateEntryOffsets[TEMPLATE_LAST_MARK];
37 
38 #if 0   // Avoid compiler warnings when x86 disabled during development
39 /*
40  * Bail to the interpreter.  Will not return to this trace.
41  * On entry, rPC must be set correctly.
42  */
43 static void genPuntToInterp(CompilationUnit *cUnit, unsigned int offset)
44 {
45     dvmCompilerFlushAllRegs(cUnit);
46     loadConstant(cUnit, rPC, (int)(cUnit->method->insns + offset));
47     loadWordDisp(cUnit, rEBP, 0, rECX);  // Get glue
48     loadWordDisp(cUnit, rECX,
49                  offsetof(Thread, jitToInterpEntries.dvmJitToInterpPunt),
50                  rEAX);
51     opReg(cUnit, kOpUncondBr, rEAX);
52 }
53 
54 static void genInterpSingleStep(CompilationUnit *cUnit, MIR *mir)
55 {
56     int flags = dexGetFlagsFromOpcode(mir->dalvikInsn.opcode);
57     int flagsToCheck = kInstrCanBranch | kInstrCanSwitch | kInstrCanReturn |
58                        kInstrCanThrow;
59 
60     //If already optimized out, just ignore
61     if (mir->dalvikInsn.opcode == OP_NOP)
62         return;
63 
64     //Ugly, but necessary.  Flush all Dalvik regs so Interp can find them
65     dvmCompilerFlushAllRegs(cUnit);
66 
67     if ((mir->next == NULL) || (flags & flagsToCheck)) {
68        genPuntToInterp(cUnit, mir->offset);
69        return;
70     }
71     int entryAddr = offsetof(Thread,
72                              jitToInterpEntries.dvmJitToInterpSingleStep);
73     loadWordDisp(cUnit, rEBP, 0, rECX);  // Get glue
74     loadWordDisp(cUnit, rECX, entryAddr, rEAX); // rEAX<- entry address
75     /* rPC = dalvik pc */
76     loadConstant(cUnit, rPC, (int) (cUnit->method->insns + mir->offset));
77     /* rECX = dalvik pc of following instruction */
78     loadConstant(cUnit, rECX, (int) (cUnit->method->insns + mir->next->offset));
79     /* Pass on the stack */
80     storeWordDisp(cUnit, rESP, OUT_ARG0, rECX);
81     opReg(cUnit, kOpCall, rEAX);
82 }
83 #endif
84 
85 /*
86  * The following are the first-level codegen routines that analyze the format
87  * of each bytecode then either dispatch special purpose codegen routines
88  * or produce corresponding Thumb instructions directly.
89  */
90 
91 #if 0
92 static bool handleFmt10t_Fmt20t_Fmt30t(CompilationUnit *cUnit, MIR *mir,
93                                        BasicBlock *bb, X86LIR *labelList)
94 {
95     /* For OP_GOTO, OP_GOTO_16, and OP_GOTO_32 */
96     return true;
97 }
98 
99 static bool handleFmt10x(CompilationUnit *cUnit, MIR *mir)
100 {
101     return true;
102 }
103 
104 static bool handleFmt11n_Fmt31i(CompilationUnit *cUnit, MIR *mir)
105 {
106     return true;
107 }
108 
109 static bool handleFmt21h(CompilationUnit *cUnit, MIR *mir)
110 {
111     return true;
112 }
113 
114 static bool handleFmt20bc(CompilationUnit *cUnit, MIR *mir)
115 {
116     return true;
117 }
118 
119 static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
120 {
121     return true;
122 }
123 
124 static bool handleFmt11x(CompilationUnit *cUnit, MIR *mir)
125 {
126     return true;
127 }
128 
129 static bool handleFmt12x(CompilationUnit *cUnit, MIR *mir)
130 {
131     return true;
132 }
133 
134 static bool handleFmt21s(CompilationUnit *cUnit, MIR *mir)
135 {
136     return true;
137 }
138 
139 static bool handleFmt21t(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
140                          X86LIR *labelList)
141 {
142     return true;
143 }
144 
145 static bool handleFmt22b_Fmt22s(CompilationUnit *cUnit, MIR *mir)
146 {
147     return true;
148 }
149 
150 static bool handleFmt22c(CompilationUnit *cUnit, MIR *mir)
151 {
152     return true;
153 }
154 
155 static bool handleFmt22cs(CompilationUnit *cUnit, MIR *mir)
156 {
157     return true;
158 }
159 
160 static bool handleFmt22t(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
161                          X86LIR *labelList)
162 {
163     return true;
164 }
165 
166 static bool handleFmt22x_Fmt32x(CompilationUnit *cUnit, MIR *mir)
167 {
168     return true;
169 }
170 
171 static bool handleFmt23x(CompilationUnit *cUnit, MIR *mir)
172 {
173     return true;
174 }
175 
176 static bool handleFmt31t(CompilationUnit *cUnit, MIR *mir)
177 {
178     return true;
179 }
180 
181 static bool handleFmt35c_3rc(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
182                              X86LIR *labelList)
183 {
184     return true;
185 }
186 
187 static bool handleFmt35ms_3rms(CompilationUnit *cUnit, MIR *mir,
188                                BasicBlock *bb, X86LIR *labelList)
189 {
190     return true;
191 }
192 
193 /*
194  * NOTE: Handles both range and non-range versions (arguments
195  * have already been normalized by this point).
196  */
197 static bool handleExecuteInline(CompilationUnit *cUnit, MIR *mir)
198 {
199     return true;
200 }
201 
202 static bool handleFmt51l(CompilationUnit *cUnit, MIR *mir)
203 {
204     return true;
205 }
206 #endif
207 
208 
dvmCompilerMIR2LIR(CompilationUnit * cUnit)209 void dvmCompilerMIR2LIR(CompilationUnit *cUnit)
210 {
211 }
212 
213 /* Accept the work and start compiling */
dvmCompilerDoWork(CompilerWorkOrder * work)214 bool dvmCompilerDoWork(CompilerWorkOrder *work)
215 {
216     JitTraceDescription *desc;
217     bool res;
218 
219     if (gDvmJit.codeCacheFull) {
220         return false;
221     }
222 
223     switch (work->kind) {
224         case kWorkOrderTrace:
225             /* Start compilation with maximally allowed trace length */
226             desc = (JitTraceDescription *)work->info;
227             res = dvmCompileTrace(desc, JIT_MAX_TRACE_LEN, &work->result,
228                                   work->bailPtr, 0 /* no hints */);
229             break;
230         case kWorkOrderTraceDebug: {
231             bool oldPrintMe = gDvmJit.printMe;
232             gDvmJit.printMe = true;
233             /* Start compilation with maximally allowed trace length */
234             desc = (JitTraceDescription *)work->info;
235             res = dvmCompileTrace(desc, JIT_MAX_TRACE_LEN, &work->result,
236                                   work->bailPtr, 0 /* no hints */);
237             gDvmJit.printMe = oldPrintMe;
238             break;
239         }
240         default:
241             res = false;
242             ALOGE("Jit: unknown work order type");
243             assert(0);  // Bail if debug build, discard otherwise
244     }
245     return res;
246 }
247 
248 /* Architectural-specific debugging helpers go here */
dvmCompilerArchDump(void)249 void dvmCompilerArchDump(void)
250 {
251     /* Print compiled opcode in this VM instance */
252     int i, start, streak;
253     char buf[1024];
254 
255     streak = i = 0;
256     buf[0] = 0;
257     while (opcodeCoverage[i] == 0 && i < kNumPackedOpcodes) {
258         i++;
259     }
260     if (i == kNumPackedOpcodes) {
261         return;
262     }
263     for (start = i++, streak = 1; i < kNumPackedOpcodes; i++) {
264         if (opcodeCoverage[i]) {
265             streak++;
266         } else {
267             if (streak == 1) {
268                 sprintf(buf+strlen(buf), "%x,", start);
269             } else {
270                 sprintf(buf+strlen(buf), "%x-%x,", start, start + streak - 1);
271             }
272             streak = 0;
273             while (opcodeCoverage[i] == 0 && i < kNumPackedOpcodes) {
274                 i++;
275             }
276             if (i < kNumPackedOpcodes) {
277                 streak = 1;
278                 start = i;
279             }
280         }
281     }
282     if (streak) {
283         if (streak == 1) {
284             sprintf(buf+strlen(buf), "%x", start);
285         } else {
286             sprintf(buf+strlen(buf), "%x-%x", start, start + streak - 1);
287         }
288     }
289     if (strlen(buf)) {
290         ALOGD("dalvik.vm.jit.op = %s", buf);
291     }
292 }
293 
294 /* Common initialization routine for an architecture family */
dvmCompilerArchInit()295 bool dvmCompilerArchInit()
296 {
297     return dvmCompilerArchVariantInit();
298 }
299 
dvmCompilerGetInterpretTemplate()300 void *dvmCompilerGetInterpretTemplate()
301 {
302       return (void*) ((int)gDvmJit.codeCache +
303                       templateEntryOffsets[TEMPLATE_INTERPRET]);
304 }
305 
dvmCompilerGetInterpretTemplateSet()306 JitInstructionSetType dvmCompilerGetInterpretTemplateSet()
307 {
308     return DALVIK_JIT_X86;
309 }
310 
dvmCompilerInitializeRegAlloc(CompilationUnit * cUnit)311 void dvmCompilerInitializeRegAlloc(CompilationUnit *cUnit)
312 {
313 }
314