js/src/jit/BaselineFrameInfo.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/jit/BaselineFrameInfo.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,183 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99:
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#include "jit/BaselineFrameInfo.h"
    1.11 +
    1.12 +#ifdef DEBUG
    1.13 +# include "jit/BytecodeAnalysis.h"
    1.14 +#endif
    1.15 +
    1.16 +using namespace js;
    1.17 +using namespace js::jit;
    1.18 +
    1.19 +bool
    1.20 +FrameInfo::init(TempAllocator &alloc)
    1.21 +{
    1.22 +    // One slot is always needed for this/arguments type checks.
    1.23 +    size_t nstack = Max(script->nslots() - script->nfixed(), size_t(1));
    1.24 +    if (!stack.init(alloc, nstack))
    1.25 +        return false;
    1.26 +
    1.27 +    return true;
    1.28 +}
    1.29 +
    1.30 +void
    1.31 +FrameInfo::sync(StackValue *val)
    1.32 +{
    1.33 +    switch (val->kind()) {
    1.34 +      case StackValue::Stack:
    1.35 +        break;
    1.36 +      case StackValue::LocalSlot:
    1.37 +        masm.pushValue(addressOfLocal(val->localSlot()));
    1.38 +        break;
    1.39 +      case StackValue::ArgSlot:
    1.40 +        masm.pushValue(addressOfArg(val->argSlot()));
    1.41 +        break;
    1.42 +      case StackValue::ThisSlot:
    1.43 +        masm.pushValue(addressOfThis());
    1.44 +        break;
    1.45 +      case StackValue::Register:
    1.46 +        masm.pushValue(val->reg());
    1.47 +        break;
    1.48 +      case StackValue::Constant:
    1.49 +        masm.pushValue(val->constant());
    1.50 +        break;
    1.51 +      default:
    1.52 +        MOZ_ASSUME_UNREACHABLE("Invalid kind");
    1.53 +    }
    1.54 +
    1.55 +    val->setStack();
    1.56 +}
    1.57 +
    1.58 +void
    1.59 +FrameInfo::syncStack(uint32_t uses)
    1.60 +{
    1.61 +    JS_ASSERT(uses <= stackDepth());
    1.62 +
    1.63 +    uint32_t depth = stackDepth() - uses;
    1.64 +
    1.65 +    for (uint32_t i = 0; i < depth; i++) {
    1.66 +        StackValue *current = &stack[i];
    1.67 +        sync(current);
    1.68 +    }
    1.69 +}
    1.70 +
    1.71 +uint32_t
    1.72 +FrameInfo::numUnsyncedSlots()
    1.73 +{
    1.74 +    // Start at the bottom, find the first value that's not synced.
    1.75 +    uint32_t i = 0;
    1.76 +    for (; i < stackDepth(); i++) {
    1.77 +        if (peek(-int32_t(i + 1))->kind() == StackValue::Stack)
    1.78 +            break;
    1.79 +    }
    1.80 +    return i;
    1.81 +}
    1.82 +
    1.83 +void
    1.84 +FrameInfo::popValue(ValueOperand dest)
    1.85 +{
    1.86 +    StackValue *val = peek(-1);
    1.87 +
    1.88 +    switch (val->kind()) {
    1.89 +      case StackValue::Constant:
    1.90 +        masm.moveValue(val->constant(), dest);
    1.91 +        break;
    1.92 +      case StackValue::LocalSlot:
    1.93 +        masm.loadValue(addressOfLocal(val->localSlot()), dest);
    1.94 +        break;
    1.95 +      case StackValue::ArgSlot:
    1.96 +        masm.loadValue(addressOfArg(val->argSlot()), dest);
    1.97 +        break;
    1.98 +      case StackValue::ThisSlot:
    1.99 +        masm.loadValue(addressOfThis(), dest);
   1.100 +        break;
   1.101 +      case StackValue::Stack:
   1.102 +        masm.popValue(dest);
   1.103 +        break;
   1.104 +      case StackValue::Register:
   1.105 +        masm.moveValue(val->reg(), dest);
   1.106 +        break;
   1.107 +      default:
   1.108 +        MOZ_ASSUME_UNREACHABLE("Invalid kind");
   1.109 +    }
   1.110 +
   1.111 +    // masm.popValue already adjusted the stack pointer, don't do it twice.
   1.112 +    pop(DontAdjustStack);
   1.113 +}
   1.114 +
   1.115 +void
   1.116 +FrameInfo::popRegsAndSync(uint32_t uses)
   1.117 +{
   1.118 +    // x86 has only 3 Value registers. Only support 2 regs here for now,
   1.119 +    // so that there's always a scratch Value register for reg -> reg
   1.120 +    // moves.
   1.121 +    JS_ASSERT(uses > 0);
   1.122 +    JS_ASSERT(uses <= 2);
   1.123 +    JS_ASSERT(uses <= stackDepth());
   1.124 +
   1.125 +    syncStack(uses);
   1.126 +
   1.127 +    switch (uses) {
   1.128 +      case 1:
   1.129 +        popValue(R0);
   1.130 +        break;
   1.131 +      case 2: {
   1.132 +        // If the second value is in R1, move it to R2 so that it's not
   1.133 +        // clobbered by the first popValue.
   1.134 +        StackValue *val = peek(-2);
   1.135 +        if (val->kind() == StackValue::Register && val->reg() == R1) {
   1.136 +            masm.moveValue(R1, R2);
   1.137 +            val->setRegister(R2);
   1.138 +        }
   1.139 +        popValue(R1);
   1.140 +        popValue(R0);
   1.141 +        break;
   1.142 +      }
   1.143 +      default:
   1.144 +        MOZ_ASSUME_UNREACHABLE("Invalid uses");
   1.145 +    }
   1.146 +}
   1.147 +
   1.148 +#ifdef DEBUG
   1.149 +void
   1.150 +FrameInfo::assertValidState(const BytecodeInfo &info)
   1.151 +{
   1.152 +    // Check stack depth.
   1.153 +    JS_ASSERT(stackDepth() == info.stackDepth);
   1.154 +
   1.155 +    // Start at the bottom, find the first value that's not synced.
   1.156 +    uint32_t i = 0;
   1.157 +    for (; i < stackDepth(); i++) {
   1.158 +        if (stack[i].kind() != StackValue::Stack)
   1.159 +            break;
   1.160 +    }
   1.161 +
   1.162 +    // Assert all values on top of it are also not synced.
   1.163 +    for (; i < stackDepth(); i++)
   1.164 +        JS_ASSERT(stack[i].kind() != StackValue::Stack);
   1.165 +
   1.166 +    // Assert every Value register is used by at most one StackValue.
   1.167 +    // R2 is used as scratch register by the compiler and FrameInfo,
   1.168 +    // so it shouldn't be used for StackValues.
   1.169 +    bool usedR0 = false, usedR1 = false;
   1.170 +
   1.171 +    for (i = 0; i < stackDepth(); i++) {
   1.172 +        if (stack[i].kind() == StackValue::Register) {
   1.173 +            ValueOperand reg = stack[i].reg();
   1.174 +            if (reg == R0) {
   1.175 +                JS_ASSERT(!usedR0);
   1.176 +                usedR0 = true;
   1.177 +            } else if (reg == R1) {
   1.178 +                JS_ASSERT(!usedR1);
   1.179 +                usedR1 = true;
   1.180 +            } else {
   1.181 +                MOZ_ASSUME_UNREACHABLE("Invalid register");
   1.182 +            }
   1.183 +        }
   1.184 +    }
   1.185 +}
   1.186 +#endif

mercurial