From 4abe4014d3fa6fcdaff6869ca1d60de15a72d124 Mon Sep 17 00:00:00 2001 From: Andy McFadden Date: Fri, 26 Feb 2010 07:35:20 -0800 Subject: [PATCH] Update a few things in x86-atom. This replaced unuses opcodes EC and EF with C stubs for the breakpoint and execute-inline/range instructions, which were added after the last bunch of stuff we rolled out to eclair open-source. I also rebuilt the "out" dir to pick up the various other changes. --- vm/mterp/config-x86-atom | 7 ++- vm/mterp/out/InterpAsm-x86-atom.S | 90 +++++---------------------- vm/mterp/out/InterpC-x86-atom.c | 124 +++++++++++++++++++++++++++++++++++--- vm/mterp/x86-atom/OP_UNUSED_EC.S | 20 ------ vm/mterp/x86-atom/OP_UNUSED_EF.S | 20 ------ 5 files changed, 137 insertions(+), 124 deletions(-) delete mode 100644 vm/mterp/x86-atom/OP_UNUSED_EC.S delete mode 100644 vm/mterp/x86-atom/OP_UNUSED_EF.S diff --git a/vm/mterp/config-x86-atom b/vm/mterp/config-x86-atom index 2470b3363..a8acc6550 100644 --- a/vm/mterp/config-x86-atom +++ b/vm/mterp/config-x86-atom @@ -266,9 +266,6 @@ op-start x86-atom #op OP_UNUSED_E9 c #op OP_UNUSED_EA c #op OP_UNUSED_EB c -#op OP_UNUSED_EC c -#op OP_UNUSED_ED c -#op OP_UNUSED_EF c #op OP_UNUSED_F1 c #op OP_UNUSED_FC c #op OP_UNUSED_FD c @@ -286,6 +283,10 @@ op-start x86-atom #op OP_XOR_LONG_2ADDR c #op OP_XOR_LONG c +# TODO: provide native implementations +op OP_BREAKPOINT c +op OP_EXECUTE_INLINE_RANGE c + op-end # arch-specific entry point to interpreter diff --git a/vm/mterp/out/InterpAsm-x86-atom.S b/vm/mterp/out/InterpAsm-x86-atom.S index 8b2a694cb..778fa48c9 100644 --- a/vm/mterp/out/InterpAsm-x86-atom.S +++ b/vm/mterp/out/InterpAsm-x86-atom.S @@ -14866,8 +14866,7 @@ OP_IF_LEZ_2f: /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_EC: /* 0xec */ -/* File: x86-atom/OP_UNUSED_EC.S */ +.L_OP_BREAKPOINT: /* 0xec */ /* Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14884,43 +14883,15 @@ OP_IF_LEZ_2f: */ /* - * File: OP_UNUSED_EC.S + * File: stub.S */ -/* File: x86-atom/unused.S */ - /* Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - /* - * File: unused.S - * - * Code: Common code for unused bytecodes. Uses no subtitutions. - * - * For: all unused bytecodes - * - * Description: aborts if executed. - * - * Format: ØØ|op (10x) - * - * Syntax: op - */ - - call common_abort - - - + SAVE_PC_FP_TO_GLUE %edx # save program counter and frame pointer + pushl rGLUE # push parameter glue + call dvmMterp_OP_BREAKPOINT # call c-based implementation + lea 4(%esp), %esp + LOAD_PC_FP_FROM_GLUE # restore program counter and frame pointer + FINISH_A # jump to next instruction /* ------------------------------ */ .balign 64 .L_OP_THROW_VERIFICATION_ERROR: /* 0xed */ @@ -15011,8 +14982,7 @@ OP_IF_LEZ_2f: /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_EF: /* 0xef */ -/* File: x86-atom/OP_UNUSED_EF.S */ +.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */ /* Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -15029,43 +14999,15 @@ OP_IF_LEZ_2f: */ /* - * File: OP_UNUSED_EF.S + * File: stub.S */ -/* File: x86-atom/unused.S */ - /* Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - /* - * File: unused.S - * - * Code: Common code for unused bytecodes. Uses no subtitutions. - * - * For: all unused bytecodes - * - * Description: aborts if executed. - * - * Format: ØØ|op (10x) - * - * Syntax: op - */ - - call common_abort - - - + SAVE_PC_FP_TO_GLUE %edx # save program counter and frame pointer + pushl rGLUE # push parameter glue + call dvmMterp_OP_EXECUTE_INLINE_RANGE # call c-based implementation + lea 4(%esp), %esp + LOAD_PC_FP_FROM_GLUE # restore program counter and frame pointer + FINISH_A # jump to next instruction /* ------------------------------ */ .balign 64 .L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */ diff --git a/vm/mterp/out/InterpC-x86-atom.c b/vm/mterp/out/InterpC-x86-atom.c index 5e1309de5..1a8a61a6c 100644 --- a/vm/mterp/out/InterpC-x86-atom.c +++ b/vm/mterp/out/InterpC-x86-atom.c @@ -302,6 +302,11 @@ static inline void putDoubleToArray(u4* ptr, int idx, double dval) #define INST_INST(_inst) ((_inst) & 0xff) /* + * Replace the opcode (used when handling breakpoints). _opcode is a u1. + */ +#define INST_REPLACE_OP(_inst, _opcode) (((_inst) & 0xff00) | _opcode) + +/* * Extract the "vA, vB" 4-bit registers from the instruction word (_inst is u2). */ #define INST_A(_inst) (((_inst) >> 8) & 0x0f) @@ -338,8 +343,7 @@ static inline void putDoubleToArray(u4* ptr, int idx, double dval) #if defined(WITH_JIT) # define NEED_INTERP_SWITCH(_current) ( \ (_current == INTERP_STD) ? \ - dvmJitDebuggerOrProfilerActive(interpState->jitState) : \ - !dvmJitDebuggerOrProfilerActive(interpState->jitState) ) + dvmJitDebuggerOrProfilerActive() : !dvmJitDebuggerOrProfilerActive() ) #else # define NEED_INTERP_SWITCH(_current) ( \ (_current == INTERP_STD) ? \ @@ -418,6 +422,10 @@ static inline bool checkForNullExportPC(Object* obj, u4* fp, const u2* pc) #define INTERP_TYPE INTERP_STD #define CHECK_DEBUG_AND_PROF() ((void)0) # define CHECK_TRACKED_REFS() ((void)0) +#if defined(WITH_JIT) +#define CHECK_JIT() (0) +#define ABORT_JIT_TSELECT() ((void)0) +#endif /* * In the C mterp stubs, "goto" is a function call followed immediately @@ -536,7 +544,6 @@ static inline bool checkForNullExportPC(Object* obj, u4* fp, const u2* pc) } \ } - /* File: c/opcommon.c */ /* forward declarations of goto targets */ GOTO_TARGET_DECL(filledNewArray, bool methodCallRange); @@ -1185,6 +1192,82 @@ GOTO_TARGET_DECL(exceptionThrown); FINISH(2); +/* File: c/OP_BREAKPOINT.c */ +HANDLE_OPCODE(OP_BREAKPOINT) +#if (INTERP_TYPE == INTERP_DBG) && defined(WITH_DEBUGGER) + { + /* + * Restart this instruction with the original opcode. We do + * this by simply jumping to the handler. + * + * It's probably not necessary to update "inst", but we do it + * for the sake of anything that needs to do disambiguation in a + * common handler with INST_INST. + * + * The breakpoint itself is handled over in updateDebugger(), + * because we need to detect other events (method entry, single + * step) and report them in the same event packet, and we're not + * yet handling those through breakpoint instructions. By the + * time we get here, the breakpoint has already been handled and + * the thread resumed. + */ + u1 originalOpCode = dvmGetOriginalOpCode(pc); + LOGV("+++ break 0x%02x (0x%04x -> 0x%04x)\n", originalOpCode, inst, + INST_REPLACE_OP(inst, originalOpCode)); + inst = INST_REPLACE_OP(inst, originalOpCode); + FINISH_BKPT(originalOpCode); + } +#else + LOGE("Breakpoint hit in non-debug interpreter\n"); + dvmAbort(); +#endif +OP_END + +/* File: c/OP_EXECUTE_INLINE_RANGE.c */ +HANDLE_OPCODE(OP_EXECUTE_INLINE_RANGE /*{vCCCC..v(CCCC+AA-1)}, inline@BBBB*/) + { + u4 arg0, arg1, arg2, arg3; + arg0 = arg1 = arg2 = arg3 = 0; /* placate gcc */ + + EXPORT_PC(); + + vsrc1 = INST_AA(inst); /* #of args */ + ref = FETCH(1); /* inline call "ref" */ + vdst = FETCH(2); /* range base */ + ILOGV("|execute-inline-range args=%d @%d {regs=v%d-v%d}", + vsrc1, ref, vdst, vdst+vsrc1-1); + + assert((vdst >> 16) == 0); // 16-bit type -or- high 16 bits clear + assert(vsrc1 <= 4); + + switch (vsrc1) { + case 4: + arg3 = GET_REGISTER(vdst+3); + /* fall through */ + case 3: + arg2 = GET_REGISTER(vdst+2); + /* fall through */ + case 2: + arg1 = GET_REGISTER(vdst+1); + /* fall through */ + case 1: + arg0 = GET_REGISTER(vdst+0); + /* fall through */ + default: // case 0 + ; + } + +#if INTERP_TYPE == INTERP_DBG + if (!dvmPerformInlineOp4Dbg(arg0, arg1, arg2, arg3, &retval, ref)) + GOTO_exceptionThrown(); +#else + if (!dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref)) + GOTO_exceptionThrown(); +#endif + } + FINISH(3); +OP_END + /* File: c/gotoTargets.c */ /* * C footer. This has some common code shared by the various targets. @@ -1720,6 +1803,10 @@ GOTO_TARGET(returnFromMethod) if (dvmIsBreakFrame(fp)) { /* bail without popping the method frame from stack */ LOGVV("+++ returned into break frame\n"); +#if defined(WITH_JIT) + /* Let the Jit know the return is terminating normally */ + CHECK_JIT(); +#endif GOTO_bail(); } @@ -1764,6 +1851,10 @@ GOTO_TARGET(exceptionThrown) */ PERIODIC_CHECKS(kInterpEntryThrow, 0); +#if defined(WITH_JIT) + // Something threw during trace selection - abort the current trace + ABORT_JIT_TSELECT(); +#endif /* * We save off the exception and clear the exception status. While * processing the exception we might need to load some Throwable @@ -1814,6 +1905,9 @@ GOTO_TARGET(exceptionThrown) * * If we do find a catch block, we want to transfer execution to * that point. + * + * Note this can cause an exception while resolving classes in + * the "catch" blocks. */ catchRelPc = dvmFindCatchBlock(self, pc - curMethod->insns, exception, false, (void*)&fp); @@ -1828,9 +1922,19 @@ GOTO_TARGET(exceptionThrown) * Note we want to do this *after* the call to dvmFindCatchBlock, * because that may need extra stack space to resolve exception * classes (e.g. through a class loader). + * + * It's possible for the stack overflow handling to cause an + * exception (specifically, class resolution in a "catch" block + * during the call above), so we could see the thread's overflow + * flag raised but actually be running in a "nested" interpreter + * frame. We don't allow doubled-up StackOverflowErrors, so + * we can check for this by just looking at the exception type + * in the cleanup function. Also, we won't unroll past the SOE + * point because the more-recent exception will hit a break frame + * as it unrolls to here. */ if (self->stackOverflowed) - dvmCleanupStackOverflow(self); + dvmCleanupStackOverflow(self, exception); if (catchRelPc < 0) { /* falling through to JNI code or off the bottom of the stack */ @@ -1995,10 +2099,11 @@ GOTO_TARGET(invokeMethod, bool methodCallRange, const Method* _methodToCall, bottom = (u1*) newSaveArea - methodToCall->outsSize * sizeof(u4); if (bottom < self->interpStackEnd) { /* stack overflow */ - LOGV("Stack overflow on method call (start=%p end=%p newBot=%p size=%d '%s')\n", + LOGV("Stack overflow on method call (start=%p end=%p newBot=%p(%d) size=%d '%s')\n", self->interpStackStart, self->interpStackEnd, bottom, - self->interpStackSize, methodToCall->name); - dvmHandleStackOverflow(self); + (u1*) fp - bottom, self->interpStackSize, + methodToCall->name); + dvmHandleStackOverflow(self, methodToCall); assert(dvmCheckException(self)); GOTO_exceptionThrown(); } @@ -2073,6 +2178,11 @@ GOTO_TARGET(invokeMethod, bool methodCallRange, const Method* _methodToCall, ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor, methodToCall->name, methodToCall->shorty); +#if defined(WITH_JIT) + /* Allow the Jit to end any pending trace building */ + CHECK_JIT(); +#endif + /* * Jump through native call bridge. Because we leave no * space for locals on native calls, "newFp" points directly diff --git a/vm/mterp/x86-atom/OP_UNUSED_EC.S b/vm/mterp/x86-atom/OP_UNUSED_EC.S deleted file mode 100644 index 15e5675cb..000000000 --- a/vm/mterp/x86-atom/OP_UNUSED_EC.S +++ /dev/null @@ -1,20 +0,0 @@ - /* Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - /* - * File: OP_UNUSED_EC.S - */ - -%include "x86-atom/unused.S" diff --git a/vm/mterp/x86-atom/OP_UNUSED_EF.S b/vm/mterp/x86-atom/OP_UNUSED_EF.S deleted file mode 100644 index f13ad254d..000000000 --- a/vm/mterp/x86-atom/OP_UNUSED_EF.S +++ /dev/null @@ -1,20 +0,0 @@ - /* Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - /* - * File: OP_UNUSED_EF.S - */ - -%include "x86-atom/unused.S" -- 2.11.0