1 /*
2 * Copyright (C) 2012 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 /*! \file Lower.cpp
19 \brief This file implements the high-level wrapper for lowering
20
21 */
22
23 //#include "uthash.h"
24 #include "libdex/DexOpcodes.h"
25 #include "libdex/DexFile.h"
26 #include <math.h>
27 #include <sys/mman.h>
28 #include "Translator.h"
29 #include "Lower.h"
30 #include "enc_wrapper.h"
31 #include "vm/mterp/Mterp.h"
32 #include "NcgHelper.h"
33 #include "libdex/DexCatch.h"
34 #include "compiler/CompilerIR.h"
35
36 //statistics for optimization
37 int num_removed_nullCheck;
38
39 PhysicalReg scratchRegs[4];
40
41 LowOp* ops[BUFFER_SIZE];
42 LowOp* op;
43 u2* rPC; //PC pointer to bytecode
44 u2 inst; //current bytecode
45 int offsetPC/*offset in bytecode*/, offsetNCG/*byte offset in native code*/;
46 int ncg_rPC;
47 //! map from PC in bytecode to PC in native code
48 int mapFromBCtoNCG[BYTECODE_SIZE_PER_METHOD]; //initially mapped to -1
49 char* streamStart = NULL; //start of the Pure CodeItem?, not include the global symbols
50 char* streamCode = NULL; //start of the Pure CodeItem?, not include the global symbols
51 char* streamMethodStart; //start of the method
52 char* stream; //current stream pointer
53 int lowOpTimeStamp = 0;
54 Method* currentMethod = NULL;
55 int currentExceptionBlockIdx = -1;
56 LowOpBlockLabel* traceLabelList = NULL;
57 BasicBlock* traceCurrentBB = NULL;
58 MIR* traceCurrentMIR = NULL;
59 bool scheduling_is_on = false;
60
61 int common_invokeMethodNoRange();
62 int common_invokeMethodRange();
63 int common_invokeArgsDone(ArgsDoneType, bool);
64
65 //data section of .ia32:
66 char globalData[128];
67
68 char strClassCastException[] = "Ljava/lang/ClassCastException;";
69 char strInstantiationError[] = "Ljava/lang/InstantiationError;";
70 char strInternalError[] = "Ljava/lang/InternalError;";
71 char strFilledNewArrayNotImpl[] = "filled-new-array only implemented for 'int'";
72 char strArithmeticException[] = "Ljava/lang/ArithmeticException;";
73 char strArrayIndexException[] = "Ljava/lang/ArrayIndexOutOfBoundsException;";
74 char strArrayStoreException[] = "Ljava/lang/ArrayStoreException;";
75 char strDivideByZero[] = "divide by zero";
76 char strNegativeArraySizeException[] = "Ljava/lang/NegativeArraySizeException;";
77 char strNoSuchMethodError[] = "Ljava/lang/NoSuchMethodError;";
78 char strNullPointerException[] = "Ljava/lang/NullPointerException;";
79 char strStringIndexOutOfBoundsException[] = "Ljava/lang/StringIndexOutOfBoundsException;";
80
81 int LstrClassCastExceptionPtr, LstrInstantiationErrorPtr, LstrInternalError, LstrFilledNewArrayNotImpl;
82 int LstrArithmeticException, LstrArrayIndexException, LstrArrayStoreException, LstrStringIndexOutOfBoundsException;
83 int LstrDivideByZero, LstrNegativeArraySizeException, LstrNoSuchMethodError, LstrNullPointerException;
84 int LdoubNeg, LvaluePosInfLong, LvalueNegInfLong, LvalueNanLong, LshiftMask, Lvalue64, L64bits, LintMax, LintMin;
85
initConstDataSec()86 void initConstDataSec() {
87 char* tmpPtr = globalData;
88
89 LdoubNeg = (int)tmpPtr;
90 *((u4*)tmpPtr) = 0x00000000;
91 tmpPtr += sizeof(u4);
92 *((u4*)tmpPtr) = 0x80000000;
93 tmpPtr += sizeof(u4);
94
95 LvaluePosInfLong = (int)tmpPtr;
96 *((u4*)tmpPtr) = 0xFFFFFFFF;
97 tmpPtr += sizeof(u4);
98 *((u4*)tmpPtr) = 0x7FFFFFFF;
99 tmpPtr += sizeof(u4);
100
101 LvalueNegInfLong = (int)tmpPtr;
102 *((u4*)tmpPtr) = 0x00000000;
103 tmpPtr += sizeof(u4);
104 *((u4*)tmpPtr) = 0x80000000;
105 tmpPtr += sizeof(u4);
106
107 LvalueNanLong = (int)tmpPtr;
108 *((u4*)tmpPtr) = 0;
109 tmpPtr += sizeof(u4);
110 *((u4*)tmpPtr) = 0;
111 tmpPtr += sizeof(u4);
112
113 LshiftMask = (int)tmpPtr;
114 *((u4*)tmpPtr) = 0x3f;
115 tmpPtr += sizeof(u4);
116 *((u4*)tmpPtr) = 0;
117 tmpPtr += sizeof(u4);
118
119 Lvalue64 = (int)tmpPtr;
120 *((u4*)tmpPtr) = 0x40;
121 tmpPtr += sizeof(u4);
122 *((u4*)tmpPtr) = 0;
123 tmpPtr += sizeof(u4);
124
125 L64bits = (int)tmpPtr;
126 *((u4*)tmpPtr) = 0xFFFFFFFF;
127 tmpPtr += sizeof(u4);
128 *((u4*)tmpPtr) = 0xFFFFFFFF;
129 tmpPtr += sizeof(u4);
130
131 LintMin = (int)tmpPtr;
132 *((u4*)tmpPtr) = 0x80000000;
133 tmpPtr += sizeof(u4);
134
135 LintMax = (int)tmpPtr;
136 *((u4*)tmpPtr) = 0x7FFFFFFF;
137 tmpPtr += sizeof(u4);
138
139 LstrClassCastExceptionPtr = (int)strClassCastException;
140 LstrInstantiationErrorPtr = (int)strInstantiationError;
141 LstrInternalError = (int)strInternalError;
142 LstrFilledNewArrayNotImpl = (int)strFilledNewArrayNotImpl;
143 LstrArithmeticException = (int)strArithmeticException;
144 LstrArrayIndexException = (int)strArrayIndexException;
145 LstrArrayStoreException = (int)strArrayStoreException;
146 LstrDivideByZero = (int)strDivideByZero;
147 LstrNegativeArraySizeException = (int)strNegativeArraySizeException;
148 LstrNoSuchMethodError = (int)strNoSuchMethodError;
149 LstrNullPointerException = (int)strNullPointerException;
150 LstrStringIndexOutOfBoundsException = (int)strStringIndexOutOfBoundsException;
151 }
152
153 //declarations of functions used in this file
154 int spill_reg(int reg, bool isPhysical);
155 int unspill_reg(int reg, bool isPhysical);
156
157 int const_string_resolve();
158 int sget_sput_resolve();
159 int new_instance_needinit();
160 int new_instance_abstract();
161 int invoke_virtual_resolve();
162 int invoke_direct_resolve();
163 int invoke_static_resolve();
164 int filled_new_array_notimpl();
165 int resolve_class2(
166 int startLR/*logical register index*/, bool isPhysical, int indexReg/*const pool index*/,
167 bool indexPhysical,
168 int thirdArg);
169 int resolve_method2(
170 int startLR/*logical register index*/, bool isPhysical, int indexReg/*const pool index*/,
171 bool indexPhysical,
172 int thirdArg/*VIRTUAL*/);
173 int resolve_inst_field2(
174 int startLR/*logical register index*/, bool isPhysical,
175 int indexReg/*const pool index*/,
176 bool indexPhysical);
177 int resolve_static_field2(
178 int startLR/*logical register index*/, bool isPhysical,
179 int indexReg/*const pool index*/,
180 bool indexPhysical);
181
182 int invokeMethodNoRange_1_helper();
183 int invokeMethodNoRange_2_helper();
184 int invokeMethodNoRange_3_helper();
185 int invokeMethodNoRange_4_helper();
186 int invokeMethodNoRange_5_helper();
187 int invokeMethodRange_helper();
188
189 int invoke_virtual_helper();
190 int invoke_virtual_quick_helper();
191 int invoke_static_helper();
192 int invoke_direct_helper();
193 int new_instance_helper();
194 int sget_sput_helper(int flag);
195 int aput_obj_helper();
196 int aget_helper(int flag);
197 int aput_helper(int flag);
198 int monitor_enter_helper();
199 int monitor_exit_helper();
200 int throw_helper();
201 int const_string_helper();
202 int array_length_helper();
203 int invoke_super_helper();
204 int invoke_interface_helper();
205 int iget_iput_helper(int flag);
206 int check_cast_helper(bool instance);
207 int new_array_helper();
208
209 int common_returnFromMethod();
210
211 /*!
212 \brief dump helper functions
213
214 */
performCGWorklist()215 int performCGWorklist() {
216 filled_new_array_notimpl();
217 freeShortMap();
218 const_string_resolve();
219 freeShortMap();
220
221 resolve_class2(PhysicalReg_EAX, true, PhysicalReg_EAX, true, 0);
222 freeShortMap();
223 resolve_method2(PhysicalReg_EAX, true, PhysicalReg_EAX, true, METHOD_VIRTUAL);
224 freeShortMap();
225 resolve_method2(PhysicalReg_EAX, true, PhysicalReg_EAX, true, METHOD_DIRECT);
226 freeShortMap();
227 resolve_method2(PhysicalReg_EAX, true, PhysicalReg_EAX, true, METHOD_STATIC);
228 freeShortMap();
229 resolve_inst_field2(PhysicalReg_EAX, true, PhysicalReg_EAX, true);
230 freeShortMap();
231 resolve_static_field2(PhysicalReg_EAX, true, PhysicalReg_EAX, true);
232 freeShortMap();
233 throw_exception_message(PhysicalReg_ECX, PhysicalReg_EAX, true, PhysicalReg_Null, true);
234 freeShortMap();
235 throw_exception(PhysicalReg_ECX, PhysicalReg_EAX, PhysicalReg_Null, true);
236 freeShortMap();
237 new_instance_needinit();
238 freeShortMap();
239 return 0;
240 }
241
242 int aput_object_count;
243 int common_periodicChecks_entry();
244 int common_periodicChecks4();
245 /*!
246 \brief for debugging purpose, dump the sequence of native code for each bytecode
247
248 */
ncgMethodFake(Method * method)249 int ncgMethodFake(Method* method) {
250 //to measure code size expansion, no need to patch up labels
251 methodDataWorklist = NULL;
252 globalShortWorklist = NULL;
253 globalNCGWorklist = NULL;
254 streamMethodStart = stream;
255
256 //initialize mapFromBCtoNCG
257 memset(&mapFromBCtoNCG[0], -1, BYTECODE_SIZE_PER_METHOD * sizeof(mapFromBCtoNCG[0]));
258 unsigned int i;
259 u2* rStart = (u2*)malloc(5*sizeof(u2));
260 if(rStart == NULL) {
261 ALOGE("Memory allocation failed");
262 return -1;
263 }
264 rPC = rStart;
265 method->insns = rStart;
266 for(i = 0; i < 5; i++) *rPC++ = 0;
267 for(i = 0; i < 256; i++) {
268 rPC = rStart;
269 //modify the opcode
270 char* tmp = (char*)rStart;
271 *tmp++ = i;
272 *tmp = i;
273 inst = FETCH(0);
274 char* tmpStart = stream;
275 lowerByteCode(method); //use inst, rPC, method, modify rPC
276 int size_in_u2 = rPC - rStart;
277 if(stream - tmpStart > 0)
278 ALOGI("LOWER bytecode %x size in u2: %d ncg size in byte: %d", i, size_in_u2, stream - tmpStart);
279 }
280 exit(0);
281 }
282
existATryBlock(Method * method,int startPC,int endPC)283 bool existATryBlock(Method* method, int startPC, int endPC) {
284 const DexCode* pCode = dvmGetMethodCode(method);
285 u4 triesSize = pCode->triesSize;
286 const DexTry* pTries = dexGetTries(pCode);
287 unsigned int i;
288 for (i = 0; i < triesSize; i++) {
289 const DexTry* pTry = &pTries[i];
290 u4 start = pTry->startAddr; //offsetPC
291 u4 end = start + pTry->insnCount;
292 //if [start, end] overlaps with [startPC, endPC] returns true
293 if((int)end < startPC || (int)start > endPC) { //no overlap
294 } else {
295 return true;
296 }
297 }
298 return false;
299 }
300
301 int mm_bytecode_size = 0;
302 int mm_ncg_size = 0;
303 int mm_relocation_size = 0;
304 int mm_map_size = 0;
resetCodeSize()305 void resetCodeSize() {
306 mm_bytecode_size = 0;
307 mm_ncg_size = 0;
308 mm_relocation_size = 0;
309 mm_map_size = 0;
310 }
311
bytecodeIsRemoved(const Method * method,u4 bytecodeOffset)312 bool bytecodeIsRemoved(const Method* method, u4 bytecodeOffset) {
313 if(gDvm.executionMode == kExecutionModeNcgO0) return false;
314 u4 ncgOff = mapFromBCtoNCG[bytecodeOffset];
315 int k = bytecodeOffset+1;
316 u2 insnsSize = dvmGetMethodInsnsSize(method);
317 while(k < insnsSize) {
318 if(mapFromBCtoNCG[k] < 0) {
319 k++;
320 continue;
321 }
322 if(mapFromBCtoNCG[k] == (int)ncgOff) return true;
323 return false;
324 }
325 return false;
326 }
327
328 int invoke_super_nsm();
329 void init_common(const char* curFileName, DvmDex *pDvmDex, bool forNCG); //forward declaration
330 void initGlobalMethods(); //forward declaration
331
332 //called once when compiler thread starts up
initJIT(const char * curFileName,DvmDex * pDvmDex)333 void initJIT(const char* curFileName, DvmDex *pDvmDex) {
334 init_common(curFileName, pDvmDex, false);
335 }
336
init_common(const char * curFileName,DvmDex * pDvmDex,bool forNCG)337 void init_common(const char* curFileName, DvmDex *pDvmDex, bool forNCG) {
338 if(!gDvm.constInit) {
339 globalMapNum = 0;
340 globalMap = NULL;
341 initConstDataSec();
342 gDvm.constInit = true;
343 }
344
345 //for initJIT: stream is already set
346 if(!gDvm.commonInit) {
347 initGlobalMethods();
348 gDvm.commonInit = true;
349 }
350 }
351
initGlobalMethods()352 void initGlobalMethods() {
353 dump_x86_inst = false; /* DEBUG */
354 // generate native code for function ncgGetEIP
355 insertLabel("ncgGetEIP", false);
356 move_mem_to_reg(OpndSize_32, 0, PhysicalReg_ESP, true, PhysicalReg_EDX, true);
357 x86_return();
358
359 //generate code for common labels
360 //jumps within a helper function is treated as short labels
361 globalShortMap = NULL;
362 common_periodicChecks_entry();
363 freeShortMap();
364 common_periodicChecks4();
365 freeShortMap();
366 //common_invokeMethodNoRange();
367 //common_invokeMethodRange();
368
369 if(dump_x86_inst) ALOGI("ArgsDone_Normal start");
370 common_invokeArgsDone(ArgsDone_Normal, false);
371 freeShortMap();
372 if(dump_x86_inst) ALOGI("ArgsDone_Native start");
373 common_invokeArgsDone(ArgsDone_Native, false);
374 freeShortMap();
375 if(dump_x86_inst) ALOGI("ArgsDone_Full start");
376 common_invokeArgsDone(ArgsDone_Full, true/*isJitFull*/);
377 if(dump_x86_inst) ALOGI("ArgsDone_Full end");
378 freeShortMap();
379
380 common_backwardBranch();
381 freeShortMap();
382 common_exceptionThrown();
383 freeShortMap();
384 common_errNullObject();
385 freeShortMap();
386 common_errArrayIndex();
387 freeShortMap();
388 common_errArrayStore();
389 freeShortMap();
390 common_errNegArraySize();
391 freeShortMap();
392 common_errNoSuchMethod();
393 freeShortMap();
394 common_errDivideByZero();
395 freeShortMap();
396 common_gotoBail();
397 freeShortMap();
398 common_gotoBail_0();
399 freeShortMap();
400 invoke_super_nsm();
401 freeShortMap();
402
403 performCGWorklist(); //generate code for helper functions
404 performLabelWorklist(); //it is likely that the common labels will jump to other common labels
405
406 dump_x86_inst = false;
407 }
408
409 ExecutionMode origMode;
410 //when to update streamMethodStart
lowerByteCodeJit(const Method * method,const u2 * codePtr,MIR * mir)411 bool lowerByteCodeJit(const Method* method, const u2* codePtr, MIR* mir) {
412 rPC = (u2*)codePtr;
413 inst = FETCH(0);
414 traceCurrentMIR = mir;
415 int retCode = lowerByteCode(method);
416 traceCurrentMIR = NULL;
417 freeShortMap();
418 if(retCode >= 0) return false; //handled
419 return true; //not handled
420 }
421
startOfBasicBlock(BasicBlock * bb)422 void startOfBasicBlock(BasicBlock* bb) {
423 traceCurrentBB = bb;
424 if(gDvm.executionMode == kExecutionModeNcgO0) {
425 isScratchPhysical = true;
426 } else {
427 isScratchPhysical = false;
428 }
429 }
430
startOfTrace(const Method * method,LowOpBlockLabel * labelList,int exceptionBlockId,CompilationUnit * cUnit)431 void startOfTrace(const Method* method, LowOpBlockLabel* labelList, int exceptionBlockId,
432 CompilationUnit *cUnit) {
433 origMode = gDvm.executionMode;
434 gDvm.executionMode = kExecutionModeNcgO1;
435 if(gDvm.executionMode == kExecutionModeNcgO0) {
436 isScratchPhysical = true;
437 } else {
438 isScratchPhysical = false;
439 }
440 currentMethod = (Method*)method;
441 currentExceptionBlockIdx = exceptionBlockId;
442 methodDataWorklist = NULL;
443 globalShortWorklist = NULL;
444 globalNCGWorklist = NULL;
445
446 streamMethodStart = stream;
447 //initialize mapFromBCtoNCG
448 memset(&mapFromBCtoNCG[0], -1, BYTECODE_SIZE_PER_METHOD * sizeof(mapFromBCtoNCG[0]));
449 traceLabelList = labelList;
450 if(gDvm.executionMode == kExecutionModeNcgO1)
451 startOfTraceO1(method, labelList, exceptionBlockId, cUnit);
452 }
453
endOfTrace(bool freeOnly)454 void endOfTrace(bool freeOnly) {
455 if(freeOnly) {
456 freeLabelWorklist();
457 freeNCGWorklist();
458 freeDataWorklist();
459 freeChainingWorklist();
460 }
461 else {
462 performLabelWorklist();
463 performNCGWorklist(); //handle forward jump (GOTO, IF)
464 performDataWorklist(); //handle SWITCH & FILL_ARRAY_DATA
465 performChainingWorklist();
466 }
467 if(gDvm.executionMode == kExecutionModeNcgO1) {
468 endOfTraceO1();
469 }
470 gDvm.executionMode = origMode;
471 }
472
473 ///////////////////////////////////////////////////////////////////
474 //!
475 //! each bytecode is translated to a sequence of machine codes
lowerByteCode(const Method * method)476 int lowerByteCode(const Method* method) { //inputs: rPC & inst & stream & streamMethodStart
477 /* offsetPC is used in O1 code generator, where it is defined as the sequence number
478 use a local version to avoid overwriting */
479 int offsetPC = rPC - (u2*)method->insns;
480
481 if(dump_x86_inst)
482 ALOGI("LOWER bytecode %x at offsetPC %x offsetNCG %x @%p",
483 INST_INST(inst), offsetPC, stream - streamMethodStart, stream);
484
485 //update mapFromBCtoNCG
486 offsetNCG = stream - streamMethodStart;
487 if(offsetPC >= BYTECODE_SIZE_PER_METHOD) ALOGE("offsetPC %d exceeds BYTECODE_SIZE_PER_METHOD", offsetPC);
488 mapFromBCtoNCG[offsetPC] = offsetNCG;
489 #if defined(ENABLE_TRACING) && defined(TRACING_OPTION2)
490 insertMapWorklist(offsetPC, mapFromBCtoNCG[offsetPC], 1);
491 #endif
492 //return number of LowOps generated
493 switch (INST_INST(inst)) {
494 case OP_NOP:
495 return op_nop();
496 case OP_MOVE:
497 case OP_MOVE_OBJECT:
498 return op_move();
499 case OP_MOVE_FROM16:
500 case OP_MOVE_OBJECT_FROM16:
501 return op_move_from16();
502 case OP_MOVE_16:
503 case OP_MOVE_OBJECT_16:
504 return op_move_16();
505 case OP_MOVE_WIDE:
506 return op_move_wide();
507 case OP_MOVE_WIDE_FROM16:
508 return op_move_wide_from16();
509 case OP_MOVE_WIDE_16:
510 return op_move_wide_16();
511 case OP_MOVE_RESULT:
512 case OP_MOVE_RESULT_OBJECT:
513 return op_move_result();
514 case OP_MOVE_RESULT_WIDE:
515 return op_move_result_wide();
516 case OP_MOVE_EXCEPTION:
517 return op_move_exception();
518 case OP_RETURN_VOID:
519 case OP_RETURN_VOID_BARRIER:
520 return op_return_void();
521 case OP_RETURN:
522 case OP_RETURN_OBJECT:
523 return op_return();
524 case OP_RETURN_WIDE:
525 return op_return_wide();
526 case OP_CONST_4:
527 return op_const_4();
528 case OP_CONST_16:
529 return op_const_16();
530 case OP_CONST:
531 return op_const();
532 case OP_CONST_HIGH16:
533 return op_const_high16();
534 case OP_CONST_WIDE_16:
535 return op_const_wide_16();
536 case OP_CONST_WIDE_32:
537 return op_const_wide_32();
538 case OP_CONST_WIDE:
539 return op_const_wide();
540 case OP_CONST_WIDE_HIGH16:
541 return op_const_wide_high16();
542 case OP_CONST_STRING:
543 return op_const_string();
544 case OP_CONST_STRING_JUMBO:
545 return op_const_string_jumbo();
546 case OP_CONST_CLASS:
547 return op_const_class();
548 case OP_MONITOR_ENTER:
549 return op_monitor_enter();
550 case OP_MONITOR_EXIT:
551 return op_monitor_exit();
552 case OP_CHECK_CAST:
553 return op_check_cast();
554 case OP_INSTANCE_OF:
555 return op_instance_of();
556 case OP_ARRAY_LENGTH:
557 return op_array_length();
558 case OP_NEW_INSTANCE:
559 return op_new_instance();
560 case OP_NEW_ARRAY:
561 return op_new_array();
562 case OP_FILLED_NEW_ARRAY:
563 return op_filled_new_array();
564 case OP_FILLED_NEW_ARRAY_RANGE:
565 return op_filled_new_array_range();
566 case OP_FILL_ARRAY_DATA:
567 return op_fill_array_data();
568 case OP_THROW:
569 return op_throw();
570 case OP_THROW_VERIFICATION_ERROR:
571 return op_throw_verification_error();
572 case OP_GOTO:
573 return op_goto();
574 case OP_GOTO_16:
575 return op_goto_16();
576 case OP_GOTO_32:
577 return op_goto_32();
578 case OP_PACKED_SWITCH:
579 return op_packed_switch();
580 case OP_SPARSE_SWITCH:
581 return op_sparse_switch();
582 case OP_CMPL_FLOAT:
583 return op_cmpl_float();
584 case OP_CMPG_FLOAT:
585 return op_cmpg_float();
586 case OP_CMPL_DOUBLE:
587 return op_cmpl_double();
588 case OP_CMPG_DOUBLE:
589 return op_cmpg_double();
590 case OP_CMP_LONG:
591 return op_cmp_long();
592 case OP_IF_EQ:
593 return op_if_eq();
594 case OP_IF_NE:
595 return op_if_ne();
596 case OP_IF_LT:
597 return op_if_lt();
598 case OP_IF_GE:
599 return op_if_ge();
600 case OP_IF_GT:
601 return op_if_gt();
602 case OP_IF_LE:
603 return op_if_le();
604 case OP_IF_EQZ:
605 return op_if_eqz();
606 case OP_IF_NEZ:
607 return op_if_nez();
608 case OP_IF_LTZ:
609 return op_if_ltz();
610 case OP_IF_GEZ:
611 return op_if_gez();
612 case OP_IF_GTZ:
613 return op_if_gtz();
614 case OP_IF_LEZ:
615 return op_if_lez();
616 case OP_AGET:
617 return op_aget();
618 case OP_AGET_WIDE:
619 return op_aget_wide();
620 case OP_AGET_OBJECT:
621 return op_aget_object();
622 case OP_AGET_BOOLEAN:
623 return op_aget_boolean();
624 case OP_AGET_BYTE:
625 return op_aget_byte();
626 case OP_AGET_CHAR:
627 return op_aget_char();
628 case OP_AGET_SHORT:
629 return op_aget_short();
630 case OP_APUT:
631 return op_aput();
632 case OP_APUT_WIDE:
633 return op_aput_wide();
634 case OP_APUT_OBJECT:
635 return op_aput_object();
636 case OP_APUT_BOOLEAN:
637 return op_aput_boolean();
638 case OP_APUT_BYTE:
639 return op_aput_byte();
640 case OP_APUT_CHAR:
641 return op_aput_char();
642 case OP_APUT_SHORT:
643 return op_aput_short();
644 case OP_IGET:
645 case OP_IGET_VOLATILE:
646 return op_iget();
647 case OP_IGET_WIDE:
648 return op_iget_wide(false); // isVolatile==false
649 case OP_IGET_WIDE_VOLATILE:
650 return op_iget_wide(true); // isVolatile==true
651 case OP_IGET_OBJECT:
652 case OP_IGET_OBJECT_VOLATILE:
653 return op_iget_object();
654 case OP_IGET_BOOLEAN:
655 return op_iget_boolean();
656 case OP_IGET_BYTE:
657 return op_iget_byte();
658 case OP_IGET_CHAR:
659 return op_iget_char();
660 case OP_IGET_SHORT:
661 return op_iget_short();
662 case OP_IPUT:
663 case OP_IPUT_VOLATILE:
664 return op_iput();
665 case OP_IPUT_WIDE:
666 return op_iput_wide(false); // isVolatile==false
667 case OP_IPUT_WIDE_VOLATILE:
668 return op_iput_wide(true); // isVolatile==true
669 case OP_IPUT_OBJECT:
670 case OP_IPUT_OBJECT_VOLATILE:
671 return op_iput_object();
672 case OP_IPUT_BOOLEAN:
673 return op_iput_boolean();
674 case OP_IPUT_BYTE:
675 return op_iput_byte();
676 case OP_IPUT_CHAR:
677 return op_iput_char();
678 case OP_IPUT_SHORT:
679 return op_iput_short();
680 case OP_SGET:
681 case OP_SGET_VOLATILE:
682 return op_sget();
683 case OP_SGET_WIDE:
684 return op_sget_wide(false); // isVolatile==false
685 case OP_SGET_WIDE_VOLATILE:
686 return op_sget_wide(true); // isVolatile==true
687 case OP_SGET_OBJECT:
688 case OP_SGET_OBJECT_VOLATILE:
689 return op_sget_object();
690 case OP_SGET_BOOLEAN:
691 return op_sget_boolean();
692 case OP_SGET_BYTE:
693 return op_sget_byte();
694 case OP_SGET_CHAR:
695 return op_sget_char();
696 case OP_SGET_SHORT:
697 return op_sget_short();
698 case OP_SPUT:
699 case OP_SPUT_VOLATILE:
700 return op_sput(false);
701 case OP_SPUT_WIDE:
702 return op_sput_wide(false); // isVolatile==false
703 case OP_SPUT_WIDE_VOLATILE:
704 return op_sput_wide(true); // isVolatile==true
705 case OP_SPUT_OBJECT:
706 case OP_SPUT_OBJECT_VOLATILE:
707 return op_sput_object();
708 case OP_SPUT_BOOLEAN:
709 return op_sput_boolean();
710 case OP_SPUT_BYTE:
711 return op_sput_byte();
712 case OP_SPUT_CHAR:
713 return op_sput_char();
714 case OP_SPUT_SHORT:
715 return op_sput_short();
716 case OP_INVOKE_VIRTUAL:
717 return op_invoke_virtual();
718 case OP_INVOKE_SUPER:
719 return op_invoke_super();
720 case OP_INVOKE_DIRECT:
721 return op_invoke_direct();
722 case OP_INVOKE_STATIC:
723 return op_invoke_static();
724 case OP_INVOKE_INTERFACE:
725 return op_invoke_interface();
726 case OP_INVOKE_VIRTUAL_RANGE:
727 return op_invoke_virtual_range();
728 case OP_INVOKE_SUPER_RANGE:
729 return op_invoke_super_range();
730 case OP_INVOKE_DIRECT_RANGE:
731 return op_invoke_direct_range();
732 case OP_INVOKE_STATIC_RANGE:
733 return op_invoke_static_range();
734 case OP_INVOKE_INTERFACE_RANGE:
735 return op_invoke_interface_range();
736 case OP_NEG_INT:
737 return op_neg_int();
738 case OP_NOT_INT:
739 return op_not_int();
740 case OP_NEG_LONG:
741 return op_neg_long();
742 case OP_NOT_LONG:
743 return op_not_long();
744 case OP_NEG_FLOAT:
745 return op_neg_float();
746 case OP_NEG_DOUBLE:
747 return op_neg_double();
748 case OP_INT_TO_LONG:
749 return op_int_to_long();
750 case OP_INT_TO_FLOAT:
751 return op_int_to_float();
752 case OP_INT_TO_DOUBLE:
753 return op_int_to_double();
754 case OP_LONG_TO_INT:
755 return op_long_to_int();
756 case OP_LONG_TO_FLOAT:
757 return op_long_to_float();
758 case OP_LONG_TO_DOUBLE:
759 return op_long_to_double();
760 case OP_FLOAT_TO_INT:
761 return op_float_to_int();
762 case OP_FLOAT_TO_LONG:
763 return op_float_to_long();
764 case OP_FLOAT_TO_DOUBLE:
765 return op_float_to_double();
766 case OP_DOUBLE_TO_INT:
767 return op_double_to_int();
768 case OP_DOUBLE_TO_LONG:
769 return op_double_to_long();
770 case OP_DOUBLE_TO_FLOAT:
771 return op_double_to_float();
772 case OP_INT_TO_BYTE:
773 return op_int_to_byte();
774 case OP_INT_TO_CHAR:
775 return op_int_to_char();
776 case OP_INT_TO_SHORT:
777 return op_int_to_short();
778 case OP_ADD_INT:
779 return op_add_int();
780 case OP_SUB_INT:
781 return op_sub_int();
782 case OP_MUL_INT:
783 return op_mul_int();
784 case OP_DIV_INT:
785 return op_div_int();
786 case OP_REM_INT:
787 return op_rem_int();
788 case OP_AND_INT:
789 return op_and_int();
790 case OP_OR_INT:
791 return op_or_int();
792 case OP_XOR_INT:
793 return op_xor_int();
794 case OP_SHL_INT:
795 return op_shl_int();
796 case OP_SHR_INT:
797 return op_shr_int();
798 case OP_USHR_INT:
799 return op_ushr_int();
800 case OP_ADD_LONG:
801 return op_add_long();
802 case OP_SUB_LONG:
803 return op_sub_long();
804 case OP_MUL_LONG:
805 return op_mul_long();
806 case OP_DIV_LONG:
807 return op_div_long();
808 case OP_REM_LONG:
809 return op_rem_long();
810 case OP_AND_LONG:
811 return op_and_long();
812 case OP_OR_LONG:
813 return op_or_long();
814 case OP_XOR_LONG:
815 return op_xor_long();
816 case OP_SHL_LONG:
817 return op_shl_long();
818 case OP_SHR_LONG:
819 return op_shr_long();
820 case OP_USHR_LONG:
821 return op_ushr_long();
822 case OP_ADD_FLOAT:
823 return op_add_float();
824 case OP_SUB_FLOAT:
825 return op_sub_float();
826 case OP_MUL_FLOAT:
827 return op_mul_float();
828 case OP_DIV_FLOAT:
829 return op_div_float();
830 case OP_REM_FLOAT:
831 return op_rem_float();
832 case OP_ADD_DOUBLE:
833 return op_add_double();
834 case OP_SUB_DOUBLE:
835 return op_sub_double();
836 case OP_MUL_DOUBLE:
837 return op_mul_double();
838 case OP_DIV_DOUBLE:
839 return op_div_double();
840 case OP_REM_DOUBLE:
841 return op_rem_double();
842 case OP_ADD_INT_2ADDR:
843 return op_add_int_2addr();
844 case OP_SUB_INT_2ADDR:
845 return op_sub_int_2addr();
846 case OP_MUL_INT_2ADDR:
847 return op_mul_int_2addr();
848 case OP_DIV_INT_2ADDR:
849 return op_div_int_2addr();
850 case OP_REM_INT_2ADDR:
851 return op_rem_int_2addr();
852 case OP_AND_INT_2ADDR:
853 return op_and_int_2addr();
854 case OP_OR_INT_2ADDR:
855 return op_or_int_2addr();
856 case OP_XOR_INT_2ADDR:
857 return op_xor_int_2addr();
858 case OP_SHL_INT_2ADDR:
859 return op_shl_int_2addr();
860 case OP_SHR_INT_2ADDR:
861 return op_shr_int_2addr();
862 case OP_USHR_INT_2ADDR:
863 return op_ushr_int_2addr();
864 case OP_ADD_LONG_2ADDR:
865 return op_add_long_2addr();
866 case OP_SUB_LONG_2ADDR:
867 return op_sub_long_2addr();
868 case OP_MUL_LONG_2ADDR:
869 return op_mul_long_2addr();
870 case OP_DIV_LONG_2ADDR:
871 return op_div_long_2addr();
872 case OP_REM_LONG_2ADDR:
873 return op_rem_long_2addr();
874 case OP_AND_LONG_2ADDR:
875 return op_and_long_2addr();
876 case OP_OR_LONG_2ADDR:
877 return op_or_long_2addr();
878 case OP_XOR_LONG_2ADDR:
879 return op_xor_long_2addr();
880 case OP_SHL_LONG_2ADDR:
881 return op_shl_long_2addr();
882 case OP_SHR_LONG_2ADDR:
883 return op_shr_long_2addr();
884 case OP_USHR_LONG_2ADDR:
885 return op_ushr_long_2addr();
886 case OP_ADD_FLOAT_2ADDR:
887 return op_add_float_2addr();
888 case OP_SUB_FLOAT_2ADDR:
889 return op_sub_float_2addr();
890 case OP_MUL_FLOAT_2ADDR:
891 return op_mul_float_2addr();
892 case OP_DIV_FLOAT_2ADDR:
893 return op_div_float_2addr();
894 case OP_REM_FLOAT_2ADDR:
895 return op_rem_float_2addr();
896 case OP_ADD_DOUBLE_2ADDR:
897 return op_add_double_2addr();
898 case OP_SUB_DOUBLE_2ADDR:
899 return op_sub_double_2addr();
900 case OP_MUL_DOUBLE_2ADDR:
901 return op_mul_double_2addr();
902 case OP_DIV_DOUBLE_2ADDR:
903 return op_div_double_2addr();
904 case OP_REM_DOUBLE_2ADDR:
905 return op_rem_double_2addr();
906 case OP_ADD_INT_LIT16:
907 return op_add_int_lit16();
908 case OP_RSUB_INT:
909 return op_rsub_int();
910 case OP_MUL_INT_LIT16:
911 return op_mul_int_lit16();
912 case OP_DIV_INT_LIT16:
913 return op_div_int_lit16();
914 case OP_REM_INT_LIT16:
915 return op_rem_int_lit16();
916 case OP_AND_INT_LIT16:
917 return op_and_int_lit16();
918 case OP_OR_INT_LIT16:
919 return op_or_int_lit16();
920 case OP_XOR_INT_LIT16:
921 return op_xor_int_lit16();
922 case OP_ADD_INT_LIT8:
923 return op_add_int_lit8();
924 case OP_RSUB_INT_LIT8:
925 return op_rsub_int_lit8();
926 case OP_MUL_INT_LIT8:
927 return op_mul_int_lit8();
928 case OP_DIV_INT_LIT8:
929 return op_div_int_lit8();
930 case OP_REM_INT_LIT8:
931 return op_rem_int_lit8();
932 case OP_AND_INT_LIT8:
933 return op_and_int_lit8();
934 case OP_OR_INT_LIT8:
935 return op_or_int_lit8();
936 case OP_XOR_INT_LIT8:
937 return op_xor_int_lit8();
938 case OP_SHL_INT_LIT8:
939 return op_shl_int_lit8();
940 case OP_SHR_INT_LIT8:
941 return op_shr_int_lit8();
942 case OP_USHR_INT_LIT8:
943 return op_ushr_int_lit8();
944 case OP_EXECUTE_INLINE:
945 return op_execute_inline(false);
946 case OP_EXECUTE_INLINE_RANGE:
947 return op_execute_inline(true);
948 case OP_BREAKPOINT:
949 ALOGE("found bytecode OP_BREAKPOINT");
950 dvmAbort();
951 case OP_INVOKE_OBJECT_INIT_RANGE:
952 return op_invoke_object_init_range();
953 case OP_IGET_QUICK:
954 return op_iget_quick();
955 case OP_IGET_WIDE_QUICK:
956 return op_iget_wide_quick();
957 case OP_IGET_OBJECT_QUICK:
958 return op_iget_object_quick();
959 case OP_IPUT_QUICK:
960 return op_iput_quick();
961 case OP_IPUT_WIDE_QUICK:
962 return op_iput_wide_quick();
963 case OP_IPUT_OBJECT_QUICK:
964 return op_iput_object_quick();
965 case OP_INVOKE_VIRTUAL_QUICK:
966 return op_invoke_virtual_quick();
967 case OP_INVOKE_VIRTUAL_QUICK_RANGE:
968 return op_invoke_virtual_quick_range();
969 case OP_INVOKE_SUPER_QUICK:
970 return op_invoke_super_quick();
971 case OP_INVOKE_SUPER_QUICK_RANGE:
972 return op_invoke_super_quick_range();
973 }
974
975 ALOGE("No JIT support for bytecode %x at offsetPC %x",
976 INST_INST(inst), offsetPC);
977 return -1;
978 }
op_nop()979 int op_nop() {
980 rPC++;
981 return 0;
982 }
983