LCOV - code coverage report
Current view: top level - js/src/jit - BaselineFrameInfo.h (source / functions) Hit Total Coverage
Test: output.info Lines: 131 142 92.3 %
Date: 2017-07-14 16:53:18 Functions: 38 41 92.7 %
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_BaselineFrameInfo_h
       8             : #define jit_BaselineFrameInfo_h
       9             : 
      10             : #include "mozilla/Alignment.h"
      11             : 
      12             : #include "jit/BaselineFrame.h"
      13             : #include "jit/FixedList.h"
      14             : #include "jit/MacroAssembler.h"
      15             : #include "jit/SharedICRegisters.h"
      16             : 
      17             : namespace js {
      18             : namespace jit {
      19             : 
      20             : struct BytecodeInfo;
      21             : 
      22             : // FrameInfo overview.
      23             : //
      24             : // FrameInfo is used by the compiler to track values stored in the frame. This
      25             : // includes locals, arguments and stack values. Locals and arguments are always
      26             : // fully synced. Stack values can either be synced, stored as constant, stored in
      27             : // a Value register or refer to a local slot. Syncing a StackValue ensures it's
      28             : // stored on the stack, e.g. kind == Stack.
      29             : //
      30             : // To see how this works, consider the following statement:
      31             : //
      32             : //    var y = x + 9;
      33             : //
      34             : // Here two values are pushed: StackValue(LocalSlot(0)) and StackValue(Int32Value(9)).
      35             : // Only when we reach the ADD op, code is generated to load the operands directly
      36             : // into the right operand registers and sync all other stack values.
      37             : //
      38             : // For stack values, the following invariants hold (and are checked between ops):
      39             : //
      40             : // (1) If a value is synced (kind == Stack), all values below it must also be synced.
      41             : //     In other words, values with kind other than Stack can only appear on top of the
      42             : //     abstract stack.
      43             : //
      44             : // (2) When we call a stub or IC, all values still on the stack must be synced.
      45             : 
      46             : // Represents a value pushed on the stack. Note that StackValue is not used for
      47             : // locals or arguments since these are always fully synced.
      48             : class StackValue
      49             : {
      50             :   public:
      51             :     enum Kind {
      52             :         Constant,
      53             :         Register,
      54             :         Stack,
      55             :         LocalSlot,
      56             :         ArgSlot,
      57             :         ThisSlot,
      58             :         EvalNewTargetSlot
      59             : #ifdef DEBUG
      60             :         // In debug builds, assert Kind is initialized.
      61             :         , Uninitialized
      62             : #endif
      63             :     };
      64             : 
      65             :   private:
      66             :     Kind kind_;
      67             : 
      68             :     union {
      69             :         struct {
      70             :             Value v;
      71             :         } constant;
      72             :         struct {
      73             :             mozilla::AlignedStorage2<ValueOperand> reg;
      74             :         } reg;
      75             :         struct {
      76             :             uint32_t slot;
      77             :         } local;
      78             :         struct {
      79             :             uint32_t slot;
      80             :         } arg;
      81             :     } data;
      82             : 
      83             :     JSValueType knownType_;
      84             : 
      85             :   public:
      86             :     StackValue() {
      87             :         reset();
      88             :     }
      89             : 
      90      697544 :     Kind kind() const {
      91      697544 :         return kind_;
      92             :     }
      93             :     bool hasKnownType() const {
      94             :         return knownType_ != JSVAL_TYPE_UNKNOWN;
      95             :     }
      96        3067 :     bool hasKnownType(JSValueType type) const {
      97        3067 :         MOZ_ASSERT(type != JSVAL_TYPE_UNKNOWN);
      98        3067 :         return knownType_ == type;
      99             :     }
     100        3067 :     bool isKnownBoolean() const {
     101        3067 :         return hasKnownType(JSVAL_TYPE_BOOLEAN);
     102             :     }
     103             :     JSValueType knownType() const {
     104             :         MOZ_ASSERT(hasKnownType());
     105             :         return knownType_;
     106             :     }
     107       85138 :     void reset() {
     108             : #ifdef DEBUG
     109       85138 :         kind_ = Uninitialized;
     110       85138 :         knownType_ = JSVAL_TYPE_UNKNOWN;
     111             : #endif
     112       85138 :     }
     113        7223 :     Value constant() const {
     114        7223 :         MOZ_ASSERT(kind_ == Constant);
     115        7223 :         return data.constant.v;
     116             :     }
     117       91687 :     ValueOperand reg() const {
     118       91687 :         MOZ_ASSERT(kind_ == Register);
     119       91687 :         return *data.reg.reg.addr();
     120             :     }
     121        5535 :     uint32_t localSlot() const {
     122        5535 :         MOZ_ASSERT(kind_ == LocalSlot);
     123        5535 :         return data.local.slot;
     124             :     }
     125        2778 :     uint32_t argSlot() const {
     126        2778 :         MOZ_ASSERT(kind_ == ArgSlot);
     127        2778 :         return data.arg.slot;
     128             :     }
     129             : 
     130        7109 :     void setConstant(const Value& v) {
     131        7109 :         kind_ = Constant;
     132        7109 :         data.constant.v = v;
     133        7109 :         knownType_ = v.isDouble() ? JSVAL_TYPE_DOUBLE : v.extractNonDoubleType();
     134        7109 :     }
     135       25854 :     void setRegister(const ValueOperand& val, JSValueType knownType = JSVAL_TYPE_UNKNOWN) {
     136       25854 :         kind_ = Register;
     137       25854 :         *data.reg.reg.addr() = val;
     138       25854 :         knownType_ = knownType;
     139       25854 :     }
     140        5535 :     void setLocalSlot(uint32_t slot) {
     141        5535 :         kind_ = LocalSlot;
     142        5535 :         data.local.slot = slot;
     143        5535 :         knownType_ = JSVAL_TYPE_UNKNOWN;
     144        5535 :     }
     145        2776 :     void setArgSlot(uint32_t slot) {
     146        2776 :         kind_ = ArgSlot;
     147        2776 :         data.arg.slot = slot;
     148        2776 :         knownType_ = JSVAL_TYPE_UNKNOWN;
     149        2776 :     }
     150         924 :     void setThis() {
     151         924 :         kind_ = ThisSlot;
     152         924 :         knownType_ = JSVAL_TYPE_UNKNOWN;
     153         924 :     }
     154           0 :     void setEvalNewTarget() {
     155           0 :         kind_ = EvalNewTargetSlot;
     156           0 :         knownType_ = JSVAL_TYPE_UNKNOWN;
     157           0 :     }
     158      113901 :     void setStack() {
     159      113901 :         kind_ = Stack;
     160      113901 :         knownType_ = JSVAL_TYPE_UNKNOWN;
     161      113901 :     }
     162             : };
     163             : 
     164             : enum StackAdjustment { AdjustStack, DontAdjustStack };
     165             : 
     166             : class FrameInfo
     167             : {
     168             :     JSScript* script;
     169             :     MacroAssembler& masm;
     170             : 
     171             :     FixedList<StackValue> stack;
     172             :     size_t spIndex;
     173             : 
     174             :   public:
     175         628 :     FrameInfo(JSScript* script, MacroAssembler& masm)
     176         628 :       : script(script),
     177             :         masm(masm),
     178             :         stack(),
     179         628 :         spIndex(0)
     180         628 :     { }
     181             : 
     182             :     MOZ_MUST_USE bool init(TempAllocator& alloc);
     183             : 
     184       22764 :     size_t nlocals() const {
     185       22764 :         return script->nfixed();
     186             :     }
     187        2889 :     size_t nargs() const {
     188        2889 :         return script->functionNonDelazifying()->nargs();
     189             :     }
     190             : 
     191             :   private:
     192       42659 :     inline StackValue* rawPush() {
     193       42659 :         StackValue* val = &stack[spIndex++];
     194       42659 :         val->reset();
     195       42659 :         return val;
     196             :     }
     197             : 
     198             :   public:
     199      944183 :     inline size_t stackDepth() const {
     200      944183 :         return spIndex;
     201             :     }
     202        6493 :     inline void setStackDepth(uint32_t newDepth) {
     203        6493 :         if (newDepth <= stackDepth()) {
     204        6261 :             spIndex = newDepth;
     205             :         } else {
     206         232 :             uint32_t diff = newDepth - stackDepth();
     207         486 :             for (uint32_t i = 0; i < diff; i++) {
     208         254 :                 StackValue* val = rawPush();
     209         254 :                 val->setStack();
     210             :             }
     211             : 
     212         232 :             MOZ_ASSERT(spIndex == newDepth);
     213             :         }
     214        6493 :     }
     215      265680 :     inline StackValue* peek(int32_t index) const {
     216      265680 :         MOZ_ASSERT(index < 0);
     217      265680 :         return const_cast<StackValue*>(&stack[spIndex + index]);
     218             :     }
     219             : 
     220             :     inline void pop(StackAdjustment adjust = AdjustStack);
     221             :     inline void popn(uint32_t n, StackAdjustment adjust = AdjustStack);
     222        7109 :     inline void push(const Value& val) {
     223        7109 :         StackValue* sv = rawPush();
     224        7109 :         sv->setConstant(val);
     225        7109 :     }
     226       25850 :     inline void push(const ValueOperand& val, JSValueType knownType=JSVAL_TYPE_UNKNOWN) {
     227       25850 :         StackValue* sv = rawPush();
     228       25850 :         sv->setRegister(val, knownType);
     229       25850 :     }
     230        5535 :     inline void pushLocal(uint32_t local) {
     231        5535 :         MOZ_ASSERT(local < nlocals());
     232        5535 :         StackValue* sv = rawPush();
     233        5535 :         sv->setLocalSlot(local);
     234        5535 :     }
     235        2776 :     inline void pushArg(uint32_t arg) {
     236        2776 :         StackValue* sv = rawPush();
     237        2776 :         sv->setArgSlot(arg);
     238        2776 :     }
     239         924 :     inline void pushThis() {
     240         924 :         StackValue* sv = rawPush();
     241         924 :         sv->setThis();
     242         924 :     }
     243           0 :     inline void pushEvalNewTarget() {
     244           0 :         MOZ_ASSERT(script->isForEval());
     245           0 :         StackValue* sv = rawPush();
     246           0 :         sv->setEvalNewTarget();
     247           0 :     }
     248             : 
     249         211 :     inline void pushScratchValue() {
     250         211 :         masm.pushValue(addressOfScratchValue());
     251         211 :         StackValue* sv = rawPush();
     252         211 :         sv->setStack();
     253         211 :     }
     254        8356 :     inline Address addressOfLocal(size_t local) const {
     255        8356 :         MOZ_ASSERT(local < nlocals());
     256        8356 :         return Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfLocal(local));
     257             :     }
     258        2889 :     Address addressOfArg(size_t arg) const {
     259        2889 :         MOZ_ASSERT(arg < nargs());
     260        2889 :         return Address(BaselineFrameReg, BaselineFrame::offsetOfArg(arg));
     261             :     }
     262         924 :     Address addressOfThis() const {
     263         924 :         return Address(BaselineFrameReg, BaselineFrame::offsetOfThis());
     264             :     }
     265           0 :     Address addressOfEvalNewTarget() const {
     266           0 :         return Address(BaselineFrameReg, BaselineFrame::offsetOfEvalNewTarget());
     267             :     }
     268         690 :     Address addressOfCalleeToken() const {
     269         690 :         return Address(BaselineFrameReg, BaselineFrame::offsetOfCalleeToken());
     270             :     }
     271        2638 :     Address addressOfEnvironmentChain() const {
     272        2638 :         return Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfEnvironmentChain());
     273             :     }
     274        7981 :     Address addressOfFlags() const {
     275        7981 :         return Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFlags());
     276             :     }
     277         480 :     Address addressOfReturnValue() const {
     278         480 :         return Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfReturnValue());
     279             :     }
     280           4 :     Address addressOfArgsObj() const {
     281           4 :         return Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfArgsObj());
     282             :     }
     283        4809 :     Address addressOfStackValue(const StackValue* value) const {
     284        4809 :         MOZ_ASSERT(value->kind() == StackValue::Stack);
     285        4809 :         size_t slot = value - &stack[0];
     286        4809 :         MOZ_ASSERT(slot < stackDepth());
     287        4809 :         return Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfLocal(nlocals() + slot));
     288             :     }
     289         422 :     Address addressOfScratchValue() const {
     290         422 :         return Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfScratchValue());
     291             :     }
     292             : 
     293             :     void popValue(ValueOperand dest);
     294             : 
     295             :     void sync(StackValue* val);
     296             :     void syncStack(uint32_t uses);
     297             :     uint32_t numUnsyncedSlots();
     298             :     void popRegsAndSync(uint32_t uses);
     299             : 
     300         892 :     inline void assertSyncedStack() const {
     301         892 :         MOZ_ASSERT_IF(stackDepth() > 0, peek(-1)->kind() == StackValue::Stack);
     302         892 :     }
     303             : 
     304             : #ifdef DEBUG
     305             :     // Assert the state is valid before excuting "pc".
     306             :     void assertValidState(const BytecodeInfo& info);
     307             : #else
     308             :     inline void assertValidState(const BytecodeInfo& info) {}
     309             : #endif
     310             : };
     311             : 
     312             : } // namespace jit
     313             : } // namespace js
     314             : 
     315             : #endif /* jit_BaselineFrameInfo_h */

Generated by: LCOV version 1.13