Пример #1
0
CallFrame* CallFrame::trueCallerFrame()
{
    // this -> The callee; this is either an inlined callee in which case it already has
    //    a pointer to the true caller. Otherwise it contains current PC in the machine
    //    caller.
    //
    // machineCaller -> The caller according to the machine, which may be zero or
    //    more frames above the true caller due to inlining.
    
    // Am I an inline call frame? If so, we're done.
    if (isInlineCallFrame())
        return callerFrame();
    
    // I am a machine call frame, so the question is: is my caller a machine call frame
    // that has inlines or a machine call frame that doesn't?
    CallFrame* machineCaller = callerFrame()->removeHostCallFrameFlag();
    if (!machineCaller)
        return 0;
    ASSERT(!machineCaller->isInlineCallFrame());
    
    // Figure out how we want to get the current code location.
    if (hasHostCallFrameFlag() || returnAddressIsInCtiTrampoline(returnPC()))
        return machineCaller->trueCallFrameFromVMCode();
    
    return machineCaller->trueCallFrame(returnPC());
}
Пример #2
0
CallFrame* CallFrame::trueCallerFrameSlow()
{
    // this -> The callee; this is either an inlined callee in which case it already has
    //    a pointer to the true caller. Otherwise it contains current PC in the machine
    //    caller.
    //
    // machineCaller -> The caller according to the machine, which may be zero or
    //    more frames above the true caller due to inlining.
    //
    // trueCaller -> The real caller.
    
    // Am I an inline call frame? If so, we're done.
    if (isInlineCallFrame())
        return callerFrame();
    
    // I am a machine call frame, so the question is: is my caller a machine call frame
    // that has inlines or a machine call frame that doesn't?
    CallFrame* machineCaller = callerFrame()->removeHostCallFrameFlag();
    if (!machineCaller)
        return 0;
    ASSERT(!machineCaller->isInlineCallFrame());
    if (!machineCaller->codeBlock() || !machineCaller->codeBlock()->hasCodeOrigins())
        return machineCaller; // No inlining, so machineCaller == trueCaller
    
    // Figure out where the caller frame would have gone relative to the machine
    // caller, and rematerialize it. Do so for the entire inline stack.
    
    CodeOrigin codeOrigin = machineCaller->codeBlock()->codeOriginForReturn(returnPC());
    
    for (InlineCallFrame* inlineCallFrame = codeOrigin.inlineCallFrame; inlineCallFrame;) {
        InlineCallFrame* nextInlineCallFrame = inlineCallFrame = inlineCallFrame->caller.inlineCallFrame;
        
        CallFrame* inlinedCaller = machineCaller + inlineCallFrame->stackOffset;
        
        JSObject* callee = machineCaller->registers()[inlineCallFrame->calleeVR].function();
        JSCell* calleeAsFunctionCell = getJSFunction(callee);
        ASSERT(calleeAsFunctionCell);
        JSFunction* calleeAsFunction = asFunction(calleeAsFunctionCell);
        
        // Fill in the inlinedCaller
        inlinedCaller->setCodeBlock(machineCaller->codeBlock());
        
        inlinedCaller->setScopeChain(calleeAsFunction->scope());
        if (nextInlineCallFrame)
            inlinedCaller->setCallerFrame(machineCaller + nextInlineCallFrame->stackOffset);
        else
            inlinedCaller->setCallerFrame(machineCaller);
        
        inlinedCaller->setInlineCallFrame(inlineCallFrame);
        inlinedCaller->setArgumentCountIncludingThis(inlineCallFrame->numArgumentsIncludingThis);
        inlinedCaller->setCallee(callee);
        
        inlineCallFrame = nextInlineCallFrame;
    }
    
    return machineCaller + codeOrigin.inlineCallFrame->stackOffset;
}