LCOV - code coverage report
Current view: top level - js/src/jit - BaselineFrameInfo.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 83 95 87.4 %
Date: 2017-07-14 16:53:18 Functions: 7 7 100.0 %
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             : #include "jit/BaselineFrameInfo.h"
       8             : 
       9             : #ifdef DEBUG
      10             : # include "jit/BytecodeAnalysis.h"
      11             : #endif
      12             : 
      13             : #include "jit/BaselineFrameInfo-inl.h"
      14             : #include "jit/MacroAssembler-inl.h"
      15             : 
      16             : using namespace js;
      17             : using namespace js::jit;
      18             : 
      19             : bool
      20         628 : FrameInfo::init(TempAllocator& alloc)
      21             : {
      22             :     // An extra slot is needed for global scopes because INITGLEXICAL (stack
      23             :     // depth 1) is compiled as a SETPROP (stack depth 2) on the global lexical
      24             :     // scope.
      25         628 :     size_t extra = script->isGlobalCode() ? 1 : 0;
      26         628 :     size_t nstack = Max(script->nslots() - script->nfixed(), size_t(MinJITStackSize)) + extra;
      27         628 :     if (!stack.init(alloc, nstack))
      28           0 :         return false;
      29             : 
      30         628 :     return true;
      31             : }
      32             : 
      33             : void
      34      113436 : FrameInfo::sync(StackValue* val)
      35             : {
      36      113436 :     switch (val->kind()) {
      37             :       case StackValue::Stack:
      38       93842 :         break;
      39             :       case StackValue::LocalSlot:
      40        2009 :         masm.pushValue(addressOfLocal(val->localSlot()));
      41        2009 :         break;
      42             :       case StackValue::ArgSlot:
      43        1098 :         masm.pushValue(addressOfArg(val->argSlot()));
      44        1098 :         break;
      45             :       case StackValue::ThisSlot:
      46           0 :         masm.pushValue(addressOfThis());
      47           0 :         break;
      48             :       case StackValue::EvalNewTargetSlot:
      49           0 :         MOZ_ASSERT(script->isForEval());
      50           0 :         masm.pushValue(addressOfEvalNewTarget());
      51           0 :         break;
      52             :       case StackValue::Register:
      53       12469 :         masm.pushValue(val->reg());
      54       12469 :         break;
      55             :       case StackValue::Constant:
      56        4018 :         masm.pushValue(val->constant());
      57        4018 :         break;
      58             :       default:
      59           0 :         MOZ_CRASH("Invalid kind");
      60             :     }
      61             : 
      62      113436 :     val->setStack();
      63      113436 : }
      64             : 
      65             : void
      66       62395 : FrameInfo::syncStack(uint32_t uses)
      67             : {
      68       62395 :     MOZ_ASSERT(uses <= stackDepth());
      69             : 
      70       62395 :     uint32_t depth = stackDepth() - uses;
      71             : 
      72      175831 :     for (uint32_t i = 0; i < depth; i++) {
      73      113436 :         StackValue* current = &stack[i];
      74      113436 :         sync(current);
      75             :     }
      76       62395 : }
      77             : 
      78             : uint32_t
      79      122358 : FrameInfo::numUnsyncedSlots()
      80             : {
      81             :     // Start at the bottom, find the first value that's not synced.
      82      122358 :     uint32_t i = 0;
      83      329850 :     for (; i < stackDepth(); i++) {
      84      162984 :         if (peek(-int32_t(i + 1))->kind() == StackValue::Stack)
      85       59238 :             break;
      86             :     }
      87      122358 :     return i;
      88             : }
      89             : 
      90             : void
      91       22544 : FrameInfo::popValue(ValueOperand dest)
      92             : {
      93       22544 :     StackValue* val = peek(-1);
      94             : 
      95       22544 :     switch (val->kind()) {
      96             :       case StackValue::Constant:
      97        2176 :         masm.moveValue(val->constant(), dest);
      98        2176 :         break;
      99             :       case StackValue::LocalSlot:
     100        3410 :         masm.loadValue(addressOfLocal(val->localSlot()), dest);
     101        3410 :         break;
     102             :       case StackValue::ArgSlot:
     103        1649 :         masm.loadValue(addressOfArg(val->argSlot()), dest);
     104        1649 :         break;
     105             :       case StackValue::ThisSlot:
     106         707 :         masm.loadValue(addressOfThis(), dest);
     107         707 :         break;
     108             :       case StackValue::EvalNewTargetSlot:
     109           0 :         masm.loadValue(addressOfEvalNewTarget(), dest);
     110           0 :         break;
     111             :       case StackValue::Stack:
     112        4248 :         masm.popValue(dest);
     113        4248 :         break;
     114             :       case StackValue::Register:
     115       10354 :         masm.moveValue(val->reg(), dest);
     116       10354 :         break;
     117             :       default:
     118           0 :         MOZ_CRASH("Invalid kind");
     119             :     }
     120             : 
     121             :     // masm.popValue already adjusted the stack pointer, don't do it twice.
     122       22544 :     pop(DontAdjustStack);
     123       22544 : }
     124             : 
     125             : void
     126       16455 : FrameInfo::popRegsAndSync(uint32_t uses)
     127             : {
     128             :     // x86 has only 3 Value registers. Only support 2 regs here for now,
     129             :     // so that there's always a scratch Value register for reg -> reg
     130             :     // moves.
     131       16455 :     MOZ_ASSERT(uses > 0);
     132       16455 :     MOZ_ASSERT(uses <= 2);
     133       16455 :     MOZ_ASSERT(uses <= stackDepth());
     134             : 
     135       16455 :     syncStack(uses);
     136             : 
     137       16455 :     switch (uses) {
     138             :       case 1:
     139       11182 :         popValue(R0);
     140       11182 :         break;
     141             :       case 2: {
     142             :         // If the second value is in R1, move it to R2 so that it's not
     143             :         // clobbered by the first popValue.
     144        5273 :         StackValue* val = peek(-2);
     145        5273 :         if (val->kind() == StackValue::Register && val->reg() == R1) {
     146           4 :             masm.moveValue(R1, R2);
     147           4 :             val->setRegister(R2);
     148             :         }
     149        5273 :         popValue(R1);
     150        5273 :         popValue(R0);
     151        5273 :         break;
     152             :       }
     153             :       default:
     154           0 :         MOZ_CRASH("Invalid uses");
     155             :     }
     156       16455 : }
     157             : 
     158             : #ifdef DEBUG
     159             : void
     160       61179 : FrameInfo::assertValidState(const BytecodeInfo& info)
     161             : {
     162             :     // Check stack depth.
     163       61179 :     MOZ_ASSERT(stackDepth() == info.stackDepth);
     164             : 
     165             :     // Start at the bottom, find the first value that's not synced.
     166       61179 :     uint32_t i = 0;
     167      211349 :     for (; i < stackDepth(); i++) {
     168      113393 :         if (stack[i].kind() != StackValue::Stack)
     169       38308 :             break;
     170             :     }
     171             : 
     172             :     // Assert all values on top of it are also not synced.
     173      164925 :     for (; i < stackDepth(); i++)
     174       51873 :         MOZ_ASSERT(stack[i].kind() != StackValue::Stack);
     175             : 
     176             :     // Assert every Value register is used by at most one StackValue.
     177             :     // R2 is used as scratch register by the compiler and FrameInfo,
     178             :     // so it shouldn't be used for StackValues.
     179       61179 :     bool usedR0 = false, usedR1 = false;
     180             : 
     181      188137 :     for (i = 0; i < stackDepth(); i++) {
     182      126958 :         if (stack[i].kind() == StackValue::Register) {
     183       30878 :             ValueOperand reg = stack[i].reg();
     184       30878 :             if (reg == R0) {
     185       26617 :                 MOZ_ASSERT(!usedR0);
     186       26617 :                 usedR0 = true;
     187        4261 :             } else if (reg == R1) {
     188        4261 :                 MOZ_ASSERT(!usedR1);
     189        4261 :                 usedR1 = true;
     190             :             } else {
     191           0 :                 MOZ_CRASH("Invalid register");
     192             :             }
     193             :         }
     194             :     }
     195       61179 : }
     196             : #endif

Generated by: LCOV version 1.13