LCOV - code coverage report
Current view: top level - js/src/jit - BaselineFrame.h (source / functions) Hit Total Coverage
Test: output.info Lines: 144 201 71.6 %
Date: 2017-07-14 16:53:18 Functions: 52 69 75.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef jit_BaselineFrame_h
       8             : #define jit_BaselineFrame_h
       9             : 
      10             : #include "jit/JitFrames.h"
      11             : #include "vm/Stack.h"
      12             : 
      13             : namespace js {
      14             : namespace jit {
      15             : 
      16             : struct BaselineDebugModeOSRInfo;
      17             : 
      18             : // The stack looks like this, fp is the frame pointer:
      19             : //
      20             : // fp+y   arguments
      21             : // fp+x   JitFrameLayout (frame header)
      22             : // fp  => saved frame pointer
      23             : // fp-x   BaselineFrame
      24             : //        locals
      25             : //        stack values
      26             : 
      27             : class BaselineFrame
      28             : {
      29             :   public:
      30             :     enum Flags : uint32_t {
      31             :         // The frame has a valid return value. See also InterpreterFrame::HAS_RVAL.
      32             :         HAS_RVAL         = 1 << 0,
      33             : 
      34             :         // An initial environment has been pushed on the environment chain for
      35             :         // function frames that need a CallObject or eval frames that need a
      36             :         // VarEnvironmentObject.
      37             :         HAS_INITIAL_ENV  = 1 << 2,
      38             : 
      39             :         // Frame has an arguments object, argsObj_.
      40             :         HAS_ARGS_OBJ     = 1 << 4,
      41             : 
      42             :         // See InterpreterFrame::PREV_UP_TO_DATE.
      43             :         PREV_UP_TO_DATE  = 1 << 5,
      44             : 
      45             :         // Frame has execution observed by a Debugger.
      46             :         //
      47             :         // See comment above 'isDebuggee' in jscompartment.h for explanation of
      48             :         // invariants of debuggee compartments, scripts, and frames.
      49             :         DEBUGGEE         = 1 << 6,
      50             : 
      51             :         // (1 << 7 and 1 << 8 are unused)
      52             : 
      53             :         // Frame has over-recursed on an early check.
      54             :         OVER_RECURSED    = 1 << 9,
      55             : 
      56             :         // Frame has a BaselineRecompileInfo stashed in the scratch value
      57             :         // slot. See PatchBaselineFramesForDebugMode.
      58             :         HAS_DEBUG_MODE_OSR_INFO = 1 << 10,
      59             : 
      60             :         // This flag is intended for use whenever the frame is settled on a
      61             :         // native code address without a corresponding ICEntry. In this case,
      62             :         // the frame contains an explicit bytecode offset for frame iterators.
      63             :         //
      64             :         // There can also be an override pc if the frame has had its
      65             :         // environment chain unwound to a pc during exception handling that is
      66             :         // different from its current pc.
      67             :         //
      68             :         // This flag should never be set when we're executing JIT code.
      69             :         HAS_OVERRIDE_PC = 1 << 11,
      70             : 
      71             :         // If set, we're handling an exception for this frame. This is set for
      72             :         // debug mode OSR sanity checking when it handles corner cases which
      73             :         // only arise during exception handling.
      74             :         HANDLING_EXCEPTION = 1 << 12,
      75             : 
      76             :         // If set, this frame has been on the stack when
      77             :         // |js::SavedStacks::saveCurrentStack| was called, and so there is a
      78             :         // |js::SavedFrame| object cached for this frame.
      79             :         HAS_CACHED_SAVED_FRAME = 1 << 13
      80             :     };
      81             : 
      82             :   protected: // Silence Clang warning about unused private fields.
      83             :     // We need to split the Value into 2 fields of 32 bits, otherwise the C++
      84             :     // compiler may add some padding between the fields.
      85             : 
      86             :     union {
      87             :         struct {
      88             :             uint32_t loScratchValue_;
      89             :             uint32_t hiScratchValue_;
      90             :         };
      91             :         BaselineDebugModeOSRInfo* debugModeOSRInfo_;
      92             :     };
      93             :     uint32_t loReturnValue_;              // If HAS_RVAL, the frame's return value.
      94             :     uint32_t hiReturnValue_;
      95             :     uint32_t frameSize_;
      96             :     JSObject* envChain_;                  // Environment chain (always initialized).
      97             :     ArgumentsObject* argsObj_;            // If HAS_ARGS_OBJ, the arguments object.
      98             :     uint32_t overrideOffset_;             // If HAS_OVERRIDE_PC, the bytecode offset.
      99             :     uint32_t flags_;
     100             : 
     101             :   public:
     102             :     // Distance between the frame pointer and the frame header (return address).
     103             :     // This is the old frame pointer saved in the prologue.
     104             :     static const uint32_t FramePointerOffset = sizeof(void*);
     105             : 
     106             :     MOZ_MUST_USE bool initForOsr(InterpreterFrame* fp, uint32_t numStackValues);
     107             : 
     108        6971 :     uint32_t frameSize() const {
     109        6971 :         return frameSize_;
     110             :     }
     111           0 :     void setFrameSize(uint32_t frameSize) {
     112           0 :         frameSize_ = frameSize;
     113           0 :     }
     114             :     inline uint32_t* addressOfFrameSize() {
     115             :         return &frameSize_;
     116             :     }
     117       16063 :     JSObject* environmentChain() const {
     118       16063 :         return envChain_;
     119             :     }
     120           0 :     void setEnvironmentChain(JSObject* envChain) {
     121           0 :         envChain_ = envChain;
     122           0 :     }
     123             :     inline JSObject** addressOfEnvironmentChain() {
     124             :         return &envChain_;
     125             :     }
     126             : 
     127             :     inline Value* addressOfScratchValue() {
     128             :         return reinterpret_cast<Value*>(&loScratchValue_);
     129             :     }
     130             : 
     131             :     template <typename SpecificEnvironment>
     132             :     inline void pushOnEnvironmentChain(SpecificEnvironment& env);
     133             :     template <typename SpecificEnvironment>
     134             :     inline void popOffEnvironmentChain();
     135             :     inline void replaceInnermostEnvironment(EnvironmentObject& env);
     136             : 
     137      233502 :     CalleeToken calleeToken() const {
     138      233502 :         uint8_t* pointer = (uint8_t*)this + Size() + offsetOfCalleeToken();
     139      233502 :         return *(CalleeToken*)pointer;
     140             :     }
     141          27 :     void replaceCalleeToken(CalleeToken token) {
     142          27 :         uint8_t* pointer = (uint8_t*)this + Size() + offsetOfCalleeToken();
     143          27 :         *(CalleeToken*)pointer = token;
     144          27 :     }
     145          91 :     bool isConstructing() const {
     146          91 :         return CalleeTokenIsConstructing(calleeToken());
     147             :     }
     148      208912 :     JSScript* script() const {
     149      208912 :         return ScriptFromCalleeToken(calleeToken());
     150             :     }
     151        9703 :     JSFunction* callee() const {
     152        9703 :         return CalleeTokenToFunction(calleeToken());
     153             :     }
     154             :     Value calleev() const {
     155             :         return ObjectValue(*callee());
     156             :     }
     157        6971 :     size_t numValueSlots() const {
     158        6971 :         size_t size = frameSize();
     159             : 
     160        6971 :         MOZ_ASSERT(size >= BaselineFrame::FramePointerOffset + BaselineFrame::Size());
     161        6971 :         size -= BaselineFrame::FramePointerOffset + BaselineFrame::Size();
     162             : 
     163        6971 :         MOZ_ASSERT((size % sizeof(Value)) == 0);
     164        6971 :         return size / sizeof(Value);
     165             :     }
     166        2387 :     Value* valueSlot(size_t slot) const {
     167        2387 :         MOZ_ASSERT(slot < numValueSlots());
     168        2387 :         return (Value*)this - (slot + 1);
     169             :     }
     170             : 
     171        7982 :     Value& unaliasedFormal(unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING) const {
     172        7982 :         MOZ_ASSERT(i < numFormalArgs());
     173        7982 :         MOZ_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals() &&
     174             :                                      !script()->formalIsAliased(i));
     175        7982 :         return argv()[i];
     176             :     }
     177             : 
     178          16 :     Value& unaliasedActual(unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING) const {
     179          16 :         MOZ_ASSERT(i < numActualArgs());
     180          16 :         MOZ_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals());
     181          16 :         MOZ_ASSERT_IF(checkAliasing && i < numFormalArgs(), !script()->formalIsAliased(i));
     182          16 :         return argv()[i];
     183             :     }
     184             : 
     185          13 :     Value& unaliasedLocal(uint32_t i) const {
     186          13 :         MOZ_ASSERT(i < script()->nfixed());
     187          13 :         return *valueSlot(i);
     188             :     }
     189             : 
     190         756 :     unsigned numActualArgs() const {
     191         756 :         return *(size_t*)(reinterpret_cast<const uint8_t*>(this) +
     192         756 :                              BaselineFrame::Size() +
     193        1512 :                              offsetOfNumActualArgs());
     194             :     }
     195        8676 :     unsigned numFormalArgs() const {
     196        8676 :         return script()->functionNonDelazifying()->nargs();
     197             :     }
     198          37 :     Value& thisArgument() const {
     199          37 :         MOZ_ASSERT(isFunctionFrame());
     200             :         return *(Value*)(reinterpret_cast<const uint8_t*>(this) +
     201          37 :                          BaselineFrame::Size() +
     202          37 :                          offsetOfThis());
     203             :     }
     204        8622 :     Value* argv() const {
     205             :         return (Value*)(reinterpret_cast<const uint8_t*>(this) +
     206        8622 :                          BaselineFrame::Size() +
     207        8622 :                          offsetOfArg(0));
     208             :     }
     209             : 
     210             :   private:
     211           0 :     Value* evalNewTargetAddress() const {
     212           0 :         MOZ_ASSERT(isEvalFrame());
     213           0 :         MOZ_ASSERT(script()->isDirectEvalInFunction());
     214             :         return (Value*)(reinterpret_cast<const uint8_t*>(this) +
     215           0 :                         BaselineFrame::Size() +
     216           0 :                         offsetOfEvalNewTarget());
     217             :     }
     218             : 
     219             :   public:
     220          64 :     Value newTarget() const {
     221          64 :         if (isEvalFrame())
     222           0 :             return *evalNewTargetAddress();
     223          64 :         MOZ_ASSERT(isFunctionFrame());
     224          64 :         if (callee()->isArrow())
     225           0 :             return callee()->getExtendedSlot(FunctionExtended::ARROW_NEWTARGET_SLOT);
     226          64 :         if (isConstructing()) {
     227           0 :             return *(Value*)(reinterpret_cast<const uint8_t*>(this) +
     228           0 :                              BaselineFrame::Size() +
     229           0 :                              offsetOfArg(Max(numFormalArgs(), numActualArgs())));
     230             :         }
     231          64 :         return UndefinedValue();
     232             :     }
     233             : 
     234          29 :     bool hasReturnValue() const {
     235          29 :         return flags_ & HAS_RVAL;
     236             :     }
     237           2 :     MutableHandleValue returnValue() {
     238           2 :         if (!hasReturnValue())
     239           1 :             addressOfReturnValue()->setUndefined();
     240           2 :         return MutableHandleValue::fromMarkedLocation(addressOfReturnValue());
     241             :     }
     242           1 :     void setReturnValue(const Value& v) {
     243           1 :         returnValue().set(v);
     244           1 :         flags_ |= HAS_RVAL;
     245           1 :     }
     246           3 :     inline Value* addressOfReturnValue() {
     247           3 :         return reinterpret_cast<Value*>(&loReturnValue_);
     248             :     }
     249             : 
     250           0 :     bool hasInitialEnvironment() const {
     251           0 :         return flags_ & HAS_INITIAL_ENV;
     252             :     }
     253             : 
     254             :     inline CallObject& callObj() const;
     255             : 
     256           0 :     void setFlags(uint32_t flags) {
     257           0 :         flags_ = flags;
     258           0 :     }
     259             :     uint32_t* addressOfFlags() {
     260             :         return &flags_;
     261             :     }
     262             : 
     263             :     inline MOZ_MUST_USE bool pushLexicalEnvironment(JSContext* cx, Handle<LexicalScope*> scope);
     264             :     inline MOZ_MUST_USE bool freshenLexicalEnvironment(JSContext* cx);
     265             :     inline MOZ_MUST_USE bool recreateLexicalEnvironment(JSContext* cx);
     266             : 
     267             :     MOZ_MUST_USE bool initFunctionEnvironmentObjects(JSContext* cx);
     268             :     MOZ_MUST_USE bool pushVarEnvironment(JSContext* cx, HandleScope scope);
     269             : 
     270          50 :     void initArgsObjUnchecked(ArgumentsObject& argsobj) {
     271          50 :         flags_ |= HAS_ARGS_OBJ;
     272          50 :         argsObj_ = &argsobj;
     273          50 :     }
     274          50 :     void initArgsObj(ArgumentsObject& argsobj) {
     275          50 :         MOZ_ASSERT(script()->needsArgsObj());
     276          50 :         initArgsObjUnchecked(argsobj);
     277          50 :     }
     278          27 :     bool hasArgsObj() const {
     279          27 :         return flags_ & HAS_ARGS_OBJ;
     280             :     }
     281           0 :     ArgumentsObject& argsObj() const {
     282           0 :         MOZ_ASSERT(hasArgsObj());
     283           0 :         MOZ_ASSERT(script()->needsArgsObj());
     284           0 :         return *argsObj_;
     285             :     }
     286             : 
     287           0 :     bool prevUpToDate() const {
     288           0 :         return flags_ & PREV_UP_TO_DATE;
     289             :     }
     290           0 :     void setPrevUpToDate() {
     291           0 :         flags_ |= PREV_UP_TO_DATE;
     292           0 :     }
     293           0 :     void unsetPrevUpToDate() {
     294           0 :         flags_ &= ~PREV_UP_TO_DATE;
     295           0 :     }
     296             : 
     297         169 :     bool isDebuggee() const {
     298         169 :         return flags_ & DEBUGGEE;
     299             :     }
     300           0 :     void setIsDebuggee() {
     301           0 :         flags_ |= DEBUGGEE;
     302           0 :     }
     303             :     inline void unsetIsDebuggee();
     304             : 
     305      117390 :     bool isHandlingException() const {
     306      117390 :         return flags_ & HANDLING_EXCEPTION;
     307             :     }
     308        1993 :     void setIsHandlingException() {
     309        1993 :         flags_ |= HANDLING_EXCEPTION;
     310        1993 :     }
     311        1993 :     void unsetIsHandlingException() {
     312        1993 :         flags_ &= ~HANDLING_EXCEPTION;
     313        1993 :     }
     314             : 
     315         775 :     bool hasCachedSavedFrame() const {
     316         775 :         return flags_ & HAS_CACHED_SAVED_FRAME;
     317             :     }
     318         471 :     void setHasCachedSavedFrame() {
     319         471 :         flags_ |= HAS_CACHED_SAVED_FRAME;
     320         471 :     }
     321             : 
     322          12 :     bool overRecursed() const {
     323          12 :         return flags_ & OVER_RECURSED;
     324             :     }
     325             : 
     326           0 :     void setOverRecursed() {
     327           0 :         flags_ |= OVER_RECURSED;
     328           0 :     }
     329             : 
     330           0 :     BaselineDebugModeOSRInfo* debugModeOSRInfo() {
     331           0 :         MOZ_ASSERT(flags_ & HAS_DEBUG_MODE_OSR_INFO);
     332           0 :         return debugModeOSRInfo_;
     333             :     }
     334             : 
     335        1993 :     BaselineDebugModeOSRInfo* getDebugModeOSRInfo() {
     336        1993 :         if (flags_ & HAS_DEBUG_MODE_OSR_INFO)
     337           0 :             return debugModeOSRInfo();
     338        1993 :         return nullptr;
     339             :     }
     340             : 
     341           0 :     void setDebugModeOSRInfo(BaselineDebugModeOSRInfo* info) {
     342           0 :         flags_ |= HAS_DEBUG_MODE_OSR_INFO;
     343           0 :         debugModeOSRInfo_ = info;
     344           0 :     }
     345             : 
     346             :     void deleteDebugModeOSRInfo();
     347             : 
     348             :     // See the HAS_OVERRIDE_PC comment.
     349       11695 :     bool hasOverridePc() const {
     350       11695 :         return flags_ & HAS_OVERRIDE_PC;
     351             :     }
     352             : 
     353           0 :     jsbytecode* overridePc() const {
     354           0 :         MOZ_ASSERT(hasOverridePc());
     355           0 :         return script()->offsetToPC(overrideOffset_);
     356             :     }
     357             : 
     358        7623 :     jsbytecode* maybeOverridePc() const {
     359        7623 :         if (hasOverridePc())
     360           0 :             return overridePc();
     361        7623 :         return nullptr;
     362             :     }
     363             : 
     364        2071 :     void setOverridePc(jsbytecode* pc) {
     365        2071 :         flags_ |= HAS_OVERRIDE_PC;
     366        2071 :         overrideOffset_ = script()->pcToOffset(pc);
     367        2071 :     }
     368             : 
     369        1993 :     void clearOverridePc() {
     370        1993 :         flags_ &= ~HAS_OVERRIDE_PC;
     371        1993 :     }
     372             : 
     373             :     void trace(JSTracer* trc, JitFrameIterator& frame);
     374             : 
     375           0 :     bool isGlobalFrame() const {
     376           0 :         return script()->isGlobalCode();
     377             :     }
     378           0 :     bool isModuleFrame() const {
     379           0 :         return script()->module();
     380             :     }
     381         277 :     bool isEvalFrame() const {
     382         277 :         return script()->isForEval();
     383             :     }
     384             :     bool isStrictEvalFrame() const {
     385             :         return isEvalFrame() && script()->strict();
     386             :     }
     387             :     bool isNonStrictEvalFrame() const {
     388             :         return isEvalFrame() && !script()->strict();
     389             :     }
     390             :     bool isNonGlobalEvalFrame() const;
     391             :     bool isNonStrictDirectEvalFrame() const {
     392             :         return isNonStrictEvalFrame() && isNonGlobalEvalFrame();
     393             :     }
     394       14769 :     bool isFunctionFrame() const {
     395       14769 :         return CalleeTokenIsFunction(calleeToken());
     396             :     }
     397          12 :     bool isDebuggerEvalFrame() const {
     398          12 :         return false;
     399             :     }
     400             : 
     401          78 :     JitFrameLayout* framePrefix() const {
     402          78 :         uint8_t* fp = (uint8_t*)this + Size() + FramePointerOffset;
     403          78 :         return (JitFrameLayout*)fp;
     404             :     }
     405             : 
     406             :     // Methods below are used by the compiler.
     407      234219 :     static size_t offsetOfCalleeToken() {
     408      234219 :         return FramePointerOffset + js::jit::JitFrameLayout::offsetOfCalleeToken();
     409             :     }
     410         961 :     static size_t offsetOfThis() {
     411         961 :         return FramePointerOffset + js::jit::JitFrameLayout::offsetOfThis();
     412             :     }
     413           0 :     static size_t offsetOfEvalNewTarget() {
     414           0 :         return FramePointerOffset + js::jit::JitFrameLayout::offsetOfEvalNewTarget();
     415             :     }
     416       11628 :     static size_t offsetOfArg(size_t index) {
     417       11628 :         return FramePointerOffset + js::jit::JitFrameLayout::offsetOfActualArg(index);
     418             :     }
     419         819 :     static size_t offsetOfNumActualArgs() {
     420         819 :         return FramePointerOffset + js::jit::JitFrameLayout::offsetOfNumActualArgs();
     421             :     }
     422      350544 :     static size_t Size() {
     423      350544 :         return sizeof(BaselineFrame);
     424             :     }
     425             : 
     426             :     // The reverseOffsetOf methods below compute the offset relative to the
     427             :     // frame's base pointer. Since the stack grows down, these offsets are
     428             :     // negative.
     429        4677 :     static int reverseOffsetOfFrameSize() {
     430        4677 :         return -int(Size()) + offsetof(BaselineFrame, frameSize_);
     431             :     }
     432         423 :     static int reverseOffsetOfScratchValue() {
     433         423 :         return -int(Size()) + offsetof(BaselineFrame, loScratchValue_);
     434             :     }
     435        2640 :     static int reverseOffsetOfEnvironmentChain() {
     436        2640 :         return -int(Size()) + offsetof(BaselineFrame, envChain_);
     437             :     }
     438           4 :     static int reverseOffsetOfArgsObj() {
     439           4 :         return -int(Size()) + offsetof(BaselineFrame, argsObj_);
     440             :     }
     441        7990 :     static int reverseOffsetOfFlags() {
     442        7990 :         return -int(Size()) + offsetof(BaselineFrame, flags_);
     443             :     }
     444         487 :     static int reverseOffsetOfReturnValue() {
     445         487 :         return -int(Size()) + offsetof(BaselineFrame, loReturnValue_);
     446             :     }
     447       13223 :     static int reverseOffsetOfLocal(size_t index) {
     448       13223 :         return -int(Size()) - (index + 1) * sizeof(Value);
     449             :     }
     450             : };
     451             : 
     452             : // Ensure the frame is 8-byte aligned (required on ARM).
     453             : JS_STATIC_ASSERT(((sizeof(BaselineFrame) + BaselineFrame::FramePointerOffset) % 8) == 0);
     454             : 
     455             : } // namespace jit
     456             : } // namespace js
     457             : 
     458             : #endif /* jit_BaselineFrame_h */

Generated by: LCOV version 1.13