js/src/jit/BaselineFrameInfo.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial