Ignore:
Timestamp:
Jul 24, 2013, 9:02:07 PM (12 years ago)
Author:
[email protected]
Message:

fourthTier: CallFrame::trueCallFrame() should populate the bytecodeOffset field
when reifying inlined frames..
https://bugs.webkit.org/show_bug.cgi?id=117209.

Reviewed by Geoffrey Garen.

When reifying an inlined frame, we fill in its CodeBlock, and
bytecodeOffset. We also set the InlinedFrame bit in the location field.
This is needed in order to iterate the stack correctly. Here's why:

Let's say we have the following stack trace:

X calls A inlines B inlines C calls D

Based on the above scenario,

  1. D's callerFrame points to A (not C).
  2. A has a codeOriginIndex that points to C.

When iterating the stack (from D back towards X), we will encounter A
twice:

t1. when trying to find C as D's caller.

This is the time when we reify B and C using the
codeOriginIndex in A, and return C as the caller frame of D.

t2. when getting's the reified B's caller.

This time, we don't run the reification process, and
just take A as the caller frame of B.

To discern which treatment of the DFG frame (i.e. A) we need to apply,
we check if the callee is an inlined frame:

If callee is NOT an inlined frame (e.g. frame D), apply treatment t1.
If callee is an inlined frame (e.g. frame B), apply treatment t2.

Why not just reify A by replacing its codeOriginIndex with A's
bytecodeOffset?

We can't do this because D's callerFrame pointer still points to A, and
needs to remain that way because we did not deopt A. It remains a DFG
frame which inlined B and C.

If we replace the codeOriginIndex in A with A's bytecodeOffset, we will
only get to iterate the stack correctly once. If we try to iterate the
stack a second time, we will not have the information from the
codeOriginIndex to tell us that D's caller is actually the inlined C,
and not A.

To recap, when reifying frames for stack iteration purposes, the DFG
frame needs to hold on to its codeOriginIndex. This in turn means the
DFG frame will need to be treated in 2 possible ways, and we need to
know if a callee frame is an inlined frame in order to choose the
correct treatment for the DFG frame.

Other changes:

  • Simplified Interpreter::getCallerInfo().
  • Removed CodeBlock::codeOriginForReturn() and supporting code which is now unneeded.
  • Moved CallFrame location bit encoding from the CodeOrigin to the new CallFrame::Location class.
  • Explicitly tagged inlined frames. This is necessary in order to iterate the stack correctly as explained above.
  • bytecode/CodeBlock.cpp:
  • bytecode/CodeBlock.h:

(JSC::CodeBlock::codeOrigins):
(CodeBlock):
(JSC::CodeBlock::codeOrigin):
(RareData):

  • bytecode/CodeOrigin.h:

(CodeOrigin):

  • dfg/DFGJITCompiler.cpp:

(JSC::DFG::JITCompiler::link):

  • dfg/DFGJITCompiler.h:

(JSC::DFG::JITCompiler::beginCall):

  • interpreter/CallFrame.cpp:

(JSC::CallFrame::trueCallFrame):
(JSC::CallFrame::trueCallerFrame):
(JSC::CallFrame::bytecodeOffsetFromCodeOriginIndex):

  • interpreter/CallFrame.h:

(Location):
(ExecState):
(JSC::ExecState::trueCallerFrame):
(JSC::ExecState::callerFrameNoFlags):

  • interpreter/CallFrameInlines.h:

(JSC::CallFrame::Location::encode):
(JSC::CallFrame::Location::decode):
(JSC::CallFrame::Location::isBytecodeOffset):
(JSC::CallFrame::Location::isCodeOriginIndex):
(JSC::CallFrame::Location::isInlinedFrame):
(JSC::CallFrame::isInlinedFrame):
(JSC::CallFrame::setIsInlinedFrame):
(JSC::CallFrame::hasLocationAsBytecodeOffset):
(JSC::CallFrame::hasLocationAsCodeOriginIndex):
(JSC::CallFrame::locationAsBytecodeOffset):
(JSC::CallFrame::setLocationAsBytecodeOffset):
(JSC::CallFrame::locationAsCodeOriginIndex):

  • interpreter/Interpreter.cpp:

(JSC::getCallerInfo):
(JSC::Interpreter::getStackTrace):
(JSC::Interpreter::findFunctionCallFrameFromVMCode):

  • runtime/Arguments.cpp:

(JSC::Arguments::tearOff):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/bytecode/CodeOrigin.h

    r153209 r153211  
    8989   
    9090    void dump(PrintStream&) const;
    91 
    92     static inline bool isHandle(uint32_t bits) { return !!(bits & handleFlag); }
    93     static inline uint32_t encodeHandle(uint32_t bits)
    94     {
    95         ASSERT(!isHandle(bits));
    96         return bits | handleFlag;
    97     }
    98     static inline uint32_t decodeHandle(uint32_t bits)
    99     {
    100         ASSERT(isHandle(bits));
    101         return bits & ~handleFlag;
    102     }
    103 
    104 private:
    105     static const uint32_t handleFlag = (1 << 31);
    10691};
    10792
     
    133118};
    134119
    135 struct CodeOriginAtCallReturnOffset {
    136     CodeOrigin codeOrigin;
    137     unsigned callReturnOffset;
    138 };
    139 
    140120inline unsigned CodeOrigin::stackOffset() const
    141121{
     
    152132}
    153133   
    154 inline unsigned getCallReturnOffsetForCodeOrigin(CodeOriginAtCallReturnOffset* data)
    155 {
    156     return data->callReturnOffset;
    157 }
    158 
    159134inline ScriptExecutable* CodeOrigin::codeOriginOwner() const
    160135{
Note: See TracChangeset for help on using the changeset viewer.