示例#1
0
    /**
     * Compile and finish executing a function.
     * We don't actually replace the interpreter frame.  Instead, this
     * routine JIT-compiles the current method and then calls the result
     * of that.  The JIT-ted version returns to here and the interpreter
     * then immediately exits, returning the result of the JIT-ted version,
     * which is returned here.
     */
    bool OSR::execute(MethodEnv *env, Atom* interp_frame,
                      MethodSignaturep ms, const uint8_t* osr_pc, Atom* result)
    {
        BaseExecMgr* exec = BaseExecMgr::exec(env);
        OSR osr(osr_pc, interp_frame);

#ifdef AVMPLUS_VERBOSE
        if (env->method->pool()->isVerbose(VB_execpolicy)) {
            env->core()->console << "execpolicy jit hot-loop " <<
                    env->method << " osr_pc=" <<
                    int(osr_pc - ms->abc_code_start()) <<
                    "\n";
        }
#endif
        // compile the method with an OSR entry point
        AvmAssert(!env->method->hasFailedJit());
        exec->verifyJit(env->method, ms, env->toplevel(), env->abcEnv(), &osr);
        env->_implGPR = env->method->_implGPR;

        if (env->method->hasFailedJit()) {
            // Clean up OSR object explicitly, as there is no destructor.
            mmfx_delete(osr.jit_frame_state);
            return false;
        }

        // Save current_osr.  It will be set to NULL in adjust_frame(),
        // once we have initialized the JIT frame from it.
        exec->current_osr = &osr;
        int fakeArgc = ms->requiredParamCount();
        *result = exec->endCoerce(env, fakeArgc, (uint32_t*)interp_frame, ms);
        return true;
    }
示例#2
0
文件: DomainEnv.cpp 项目: bsdf/trx
DomainEnv::~DomainEnv()
{
    mmfx_delete(m_globalMemoryScratch);
}
示例#3
0
    /**
     * This function is called by JIT code if OSR has been requested
     * if (exec->current_osr != 0).  This function fills the JIT frame locals
     * to match the interpreter frame.  The JIT code looks like this:
     *
     *   if (*(&exec->current_osr)) {
     *     adjustFrame(...);
     *     goto loop_entry
     *   }
     */
    void OSR::adjustFrame(MethodFrame* jitMethodFrame, CallStackNode *callStack,
                             FramePtr jitFramePointer,  uint8_t *jitFrameTags)
    {
        MethodEnv* env = jitMethodFrame->env();
        BaseExecMgr* exec = BaseExecMgr::exec(env);
        OSR *osr = exec->current_osr;
        AvmAssert(osr && "should not have gotten here");
        Atom* interpFramePointer = osr->interp_frame;

        MethodSignaturep ms = env->method->getMethodSignature();
        int nLocals = ms->local_count();
        int stackBase = nLocals + ms->max_scope();
        FrameState* frameState = osr->jit_frame_state;
        int scopeTop = nLocals + frameState->scopeDepth;
        int stackTop = stackBase + frameState->stackDepth;

        // OSR has been requested.

#ifdef AVMPLUS_VERBOSE
        if (env->method->pool()->isVerbose(VB_interp)) {
            env->core()->console <<
                    "osr-adjust_frame " << env->method->method_id() <<
                    " " << env->method <<
                    " scopeTop=" << scopeTop <<
                    " stackTop=" << stackTop <<
                    "\n";
        }
#endif

        // Patch the JIT frame local variable slots and the scope slots in use to match the interpreter state.
        for (int i = 0; i < scopeTop; i++)
            unboxSlot(frameState, env, interpFramePointer, jitFramePointer, jitFrameTags, i);

        // zero out stack area for unused scopes:
        if (scopeTop < stackBase) {
            void* p = ((char*) jitFramePointer + (scopeTop << VARSHIFT(env->method)));
            size_t nbytes = (stackBase - scopeTop) << VARSHIFT(env->method);
            VMPI_memset(p, 0, nbytes);
        }

        // Patch operand stack slots:
        for (int i = stackBase; i < stackTop; i++)
            unboxSlot(frameState, env, interpFramePointer, jitFramePointer, jitFrameTags, i);

        MethodFrame *interpreterMethodFrame = jitMethodFrame->next;
        jitMethodFrame->dxns = interpreterMethodFrame->dxns;
        jitMethodFrame->next = interpreterMethodFrame->next;

        // Clean up non-local OSR parameterization data:
        mmfx_delete(frameState);
        exec->current_osr = NULL;

#ifdef DEBUGGER
        // Call debugEnter if necessary, since the jit code won't.
        // We can safely pass NULL for &eip here, because OSR is disabled
        // for methods with catch blocks.
        if (callStack)
            env->debugEnter(jitFrameTags, callStack, jitFramePointer, NULL);
#else
        (void) callStack;
#endif
    }
示例#4
0
文件: exec-osr.cpp 项目: bsdf/trx
    /**
     * This function detects if OSR has been requested or if this is a
     * subsequent normal call.  In the latter case it has no side effect and
     * returns false and control flow is supposed to proceed normally.
     * If OSR is in the works, then it fills the JIT frame locals to match the
     * interpreter frame.  Then it returns true, which indicates to the
     * generated code to jump to the OSR entry point.
     *
     * The JIT code looks like this:
     *
     *   if (adjust_frame(...))
     *     goto loop_entry
     */
    int32_t OSR::adjustFrame(MethodFrame* jitMethodFrame,
                             CallStackNode *callStack,
                             FramePtr jitFramePointer,
                             uint8_t *jitFrameTags)
    {
        MethodEnv* env = jitMethodFrame->env();
        BaseExecMgr* exec = BaseExecMgr::exec(env);
        OSR *osr = exec->current_osr;
        if (!osr) {
            // No OSR has been requested.
            // We are at the beginning of a normal AS method call.
            // Indicate proceeding with normal control flow.
            return 0;
        }
        Atom* interpFramePointer = osr->interp_frame;

        MethodSignaturep ms = env->method->getMethodSignature();
        int nLocals = ms->local_count();
        int stackBase = nLocals + ms->max_scope();
        FrameState* frameState = osr->jit_frame_state;
        int scopeTop = nLocals + frameState->scopeDepth;
        int stackTop = stackBase + frameState->stackDepth;

        // OSR has been requested.

#ifdef AVMPLUS_VERBOSE
        if (env->method->pool()->isVerbose(VB_interp)) {
            env->core()->console <<
                    "osr-adjust_frame " << env->method->method_id() <<
                    " " << env->method <<
                    " scopeTop=" << scopeTop <<
                    " stackTop=" << stackTop <<
                    "\n";
        }
#endif

        // Patch the JIT frame local variable slots and the scope slots in use to match the interpreter state.
        for (int i = 0; i < scopeTop; i++)
            unboxSlot(frameState, env, interpFramePointer, jitFramePointer, jitFrameTags, i);

        // zero out stack area for unused scopes:
        if (scopeTop < stackBase) {
            void* p = ((char*) jitFramePointer + scopeTop * VARSIZE);
            size_t nbytes = (stackBase - scopeTop) * VARSIZE;
            VMPI_memset(p, 0, nbytes);
        }

        // Patch operand stack slots:
        for (int i = stackBase; i < stackTop; i++)
            unboxSlot(frameState, env, interpFramePointer, jitFramePointer, jitFrameTags, i);

        MethodFrame *interpreterMethodFrame = jitMethodFrame->next;
        jitMethodFrame->dxns = interpreterMethodFrame->dxns;
        jitMethodFrame->next = interpreterMethodFrame->next;

        // Clean up non-local OSR parameterization data:
        mmfx_delete(frameState);
        exec->current_osr = NULL;

#ifdef DEBUGGER
        // Call debugEnter if necessary, since the jit code won't.
        // We can safely pass NULL for &eip here, because OSR is disabled
        // for methods with catch blocks.
        if (callStack)
            env->debugEnter(jitFrameTags, callStack, jitFramePointer, NULL);
#else
        (void) callStack;
#endif

        // Indicate taking a shortcut from the call site
        // to the OSR entry point instead of normal control flow:
        return 1;
    }