LCOV - code coverage report
Current view: directory - js/src/methodjit - ImmutableSync.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 147 146 99.3 %
Date: 2012-06-02 Functions: 15 15 100.0 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  * vim: set ts=4 sw=4 et tw=99:
       3                 :  *
       4                 :  * ***** BEGIN LICENSE BLOCK *****
       5                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       6                 :  *
       7                 :  * The contents of this file are subject to the Mozilla Public License Version
       8                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       9                 :  * the License. You may obtain a copy of the License at
      10                 :  * http://www.mozilla.org/MPL/
      11                 :  *
      12                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      13                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      14                 :  * for the specific language governing rights and limitations under the
      15                 :  * License.
      16                 :  *
      17                 :  * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
      18                 :  * May 28, 2008.
      19                 :  *
      20                 :  * The Initial Developer of the Original Code is
      21                 :  *   Brendan Eich <brendan@mozilla.org>
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   David Anderson <danderson@mozilla.com>
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      28                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : #if defined JS_NUNBOX32
      41                 : 
      42                 : #include "FrameEntry.h"
      43                 : #include "FrameState.h"
      44                 : #include "FrameState-inl.h"
      45                 : #include "ImmutableSync.h"
      46                 : 
      47                 : using namespace js;
      48                 : using namespace js::mjit;
      49                 : 
      50          134091 : ImmutableSync::ImmutableSync()
      51          134091 :   : cx(NULL), entries(NULL), frame(NULL), avail(Registers::AvailRegs), generation(0)
      52                 : {
      53          134091 : }
      54                 : 
      55          134091 : ImmutableSync::~ImmutableSync()
      56                 : {
      57          134091 :     if (cx)
      58          128881 :         cx->free_(entries);
      59          134091 : }
      60                 : 
      61                 : bool
      62          128881 : ImmutableSync::init(JSContext *cx, const FrameState &frame, uint32_t nentries)
      63                 : {
      64          128881 :     this->cx = cx;
      65          128881 :     this->frame = &frame;
      66                 : 
      67          128881 :     entries = (SyncEntry *)OffTheBooks::calloc_(sizeof(SyncEntry) * nentries);
      68          128881 :     return !!entries;
      69                 : }
      70                 : 
      71                 : void
      72          171297 : ImmutableSync::reset(Assembler *masm, Registers avail, FrameEntry *top, FrameEntry *bottom)
      73                 : {
      74          171297 :     this->avail = avail;
      75          171297 :     this->masm = masm;
      76          171297 :     this->top = top;
      77          171297 :     this->bottom = bottom;
      78          171297 :     this->generation++;
      79          171297 :     memset(regs, 0, sizeof(regs));
      80          171297 : }
      81                 : 
      82                 : inline JSC::MacroAssembler::RegisterID
      83          280288 : ImmutableSync::doAllocReg()
      84                 : {
      85          280288 :     if (!avail.empty())
      86          222590 :         return avail.takeAnyReg().reg();
      87                 : 
      88           57698 :     uint32_t lastResort = FrameState::InvalidIndex;
      89           57698 :     uint32_t evictFromFrame = FrameState::InvalidIndex;
      90                 : 
      91                 :     /* Find something to evict. */
      92          129643 :     for (uint32_t i = 0; i < Registers::TotalRegisters; i++) {
      93          127445 :         RegisterID reg = RegisterID(i);
      94          127445 :         if (!(Registers::maskReg(reg) & Registers::AvailRegs))
      95            8708 :             continue;
      96                 : 
      97          118737 :         if (frame->regstate(reg).isPinned())
      98            2305 :             continue;
      99                 : 
     100          116432 :         lastResort = i;
     101                 : 
     102          116432 :         if (!regs[i]) {
     103                 :             /* If the frame does not own this register, take it! */
     104           73501 :             FrameEntry *fe = frame->regstate(reg).usedBy();
     105           73501 :             if (!fe)
     106           23227 :                 return reg;
     107                 : 
     108           50274 :             evictFromFrame = i;
     109                 : 
     110                 :             /*
     111                 :              * If not copied, we can sync and not have to load again later.
     112                 :              * That's about as good as it gets, so just break out now.
     113                 :              */
     114           50274 :             if (!fe->isCopied())
     115           32273 :                 break;
     116                 :         }
     117                 :     }
     118                 : 
     119           34471 :     if (evictFromFrame != FrameState::InvalidIndex) {
     120           33825 :         RegisterID evict = RegisterID(evictFromFrame);
     121           33825 :         FrameEntry *fe = frame->regstate(evict).usedBy();
     122           33825 :         SyncEntry &e = entryFor(fe);
     123           33825 :         if (frame->regstate(evict).type() == RematInfo::TYPE) {
     124           13843 :             JS_ASSERT(!e.typeClobbered);
     125           13843 :             e.typeClobbered = true;
     126                 :         } else {
     127           19982 :             JS_ASSERT(!e.dataClobbered);
     128           19982 :             e.dataClobbered = true;
     129                 :         }
     130           33825 :         return evict;
     131                 :     }
     132                 : 
     133             646 :     JS_ASSERT(lastResort != FrameState::InvalidIndex);
     134             646 :     JS_ASSERT(regs[lastResort]);
     135                 : 
     136             646 :     SyncEntry *e = regs[lastResort];
     137             646 :     RegisterID reg = RegisterID(lastResort);
     138             646 :     if (e->hasDataReg && e->dataReg == reg) {
     139             355 :         e->hasDataReg = false;
     140             291 :     } else if (e->hasTypeReg && e->typeReg == reg) {
     141             291 :         e->hasTypeReg = false;
     142                 :     } else {
     143               0 :         JS_NOT_REACHED("no way");
     144                 :     }
     145                 : 
     146             646 :     return reg;
     147                 : }
     148                 : 
     149                 : JSC::MacroAssembler::RegisterID
     150          280288 : ImmutableSync::allocReg()
     151                 : {
     152          280288 :     RegisterID reg = doAllocReg();
     153          280288 :     JS_ASSERT(!frame->regstate(reg).isPinned());
     154          280288 :     return reg;
     155                 : }
     156                 : 
     157                 : void
     158          595780 : ImmutableSync::freeReg(JSC::MacroAssembler::RegisterID reg)
     159                 : {
     160          595780 :     if (!frame->regstate(reg).isPinned())
     161          593554 :         avail.putReg(reg);
     162          595780 : }
     163                 : 
     164                 : inline ImmutableSync::SyncEntry &
     165          840248 : ImmutableSync::entryFor(FrameEntry *fe)
     166                 : {
     167          840248 :     JS_ASSERT(fe <= top || frame->isTemporary(fe));
     168          840248 :     SyncEntry &e = entries[fe - frame->entries];
     169          840248 :     if (e.generation != generation)
     170          557367 :         e.reset(generation);
     171          840248 :     return e;
     172                 : }
     173                 : 
     174                 : void
     175          806423 : ImmutableSync::sync(FrameEntry *fe)
     176                 : {
     177          806423 :     if (fe->isCopy())
     178          249094 :         syncCopy(fe);
     179                 :     else
     180          557329 :         syncNormal(fe);
     181          806423 : }
     182                 : 
     183                 : bool
     184          500226 : ImmutableSync::shouldSyncType(FrameEntry *fe, SyncEntry &e)
     185                 : {
     186                 :     /* Registers are synced up-front. */
     187          500226 :     return !fe->type.synced() && !fe->type.inRegister();
     188                 : }
     189                 : 
     190                 : bool
     191          557329 : ImmutableSync::shouldSyncData(FrameEntry *fe, SyncEntry &e)
     192                 : {
     193                 :     /* Registers are synced up-front. */
     194          557329 :     return !fe->data.synced() && !fe->data.inRegister();
     195                 : }
     196                 : 
     197                 : JSC::MacroAssembler::RegisterID
     198          164496 : ImmutableSync::ensureTypeReg(FrameEntry *fe, SyncEntry &e)
     199                 : {
     200          164496 :     if (fe->type.inRegister() && !e.typeClobbered)
     201           84113 :         return fe->type.reg();
     202           80383 :     if (e.hasTypeReg)
     203            2344 :         return e.typeReg;
     204           78039 :     e.typeReg = allocReg();
     205           78039 :     e.hasTypeReg = true;
     206           78039 :     regs[e.typeReg] = &e;
     207           78039 :     masm->loadTypeTag(frame->addressOf(fe), e.typeReg);
     208           78039 :     return e.typeReg;
     209                 : }
     210                 : 
     211                 : JSC::MacroAssembler::RegisterID
     212          247283 : ImmutableSync::ensureDataReg(FrameEntry *fe, SyncEntry &e)
     213                 : {
     214          247283 :     if (fe->data.inRegister() && !e.dataClobbered)
     215           37062 :         return fe->data.reg();
     216          210221 :     if (e.hasDataReg)
     217            7972 :         return e.dataReg;
     218          202249 :     e.dataReg = allocReg();
     219          202249 :     e.hasDataReg = true;
     220          202249 :     regs[e.dataReg] = &e;
     221          202249 :     masm->loadPayload(frame->addressOf(fe), e.dataReg);
     222          202249 :     return e.dataReg;
     223                 : }
     224                 : 
     225                 : void
     226          249094 : ImmutableSync::syncCopy(FrameEntry *fe)
     227                 : {
     228          249094 :     JS_ASSERT(fe >= bottom);
     229                 : 
     230          249094 :     FrameEntry *backing = fe->copyOf();
     231          249094 :     SyncEntry &e = entryFor(backing);
     232                 : 
     233          249094 :     JS_ASSERT(!backing->isConstant());
     234                 : 
     235          249094 :     Address addr = frame->addressOf(fe);
     236                 : 
     237          249094 :     if (fe->isTypeKnown() && !fe->isType(JSVAL_TYPE_DOUBLE) && !e.learnedType) {
     238           77531 :         e.learnedType = true;
     239           77531 :         e.type = fe->getKnownType();
     240                 :     }
     241                 : 
     242          249094 :     if (!fe->data.synced())
     243          247003 :         masm->storePayload(ensureDataReg(backing, e), addr);
     244                 : 
     245          249094 :     if (!fe->type.synced()) {
     246          246975 :         if (e.learnedType)
     247           82759 :             masm->storeTypeTag(ImmType(e.type), addr);
     248                 :         else
     249          164216 :             masm->storeTypeTag(ensureTypeReg(backing, e), addr);
     250                 :     }
     251          249094 : }
     252                 : 
     253                 : void
     254          557329 : ImmutableSync::syncNormal(FrameEntry *fe)
     255                 : {
     256          557329 :     SyncEntry &e = entryFor(fe);
     257                 : 
     258          557329 :     Address addr = frame->addressOf(fe);
     259                 : 
     260          557329 :     if (fe->isTypeKnown() && !fe->isType(JSVAL_TYPE_DOUBLE)) {
     261          187838 :         e.learnedType = true;
     262          187838 :         e.type = fe->getKnownType();
     263                 :     }
     264                 : 
     265          557329 :     if (shouldSyncData(fe, e)) {
     266           57383 :         if (fe->isConstant()) {
     267           57103 :             masm->storeValue(fe->getValue(), addr);
     268           57103 :             return;
     269                 :         }
     270             280 :         masm->storePayload(ensureDataReg(fe, e), addr);
     271                 :     }
     272                 : 
     273          500226 :     if (shouldSyncType(fe, e)) {
     274           37405 :         if (e.learnedType)
     275           37125 :             masm->storeTypeTag(ImmType(e.type), addr);
     276                 :         else
     277             280 :             masm->storeTypeTag(ensureTypeReg(fe, e), addr);
     278                 :     }
     279                 : 
     280          500226 :     if (e.hasDataReg) {
     281          201860 :         freeReg(e.dataReg);
     282          201860 :         regs[e.dataReg] = NULL;
     283          719527 :     } else if (!e.dataClobbered &&
     284          278444 :                fe->data.inRegister() &&
     285          142717 :                frame->regstate(fe->data.reg()).usedBy()) {
     286          142717 :         freeReg(fe->data.reg());
     287                 :     }
     288                 : 
     289          500226 :     if (e.hasTypeReg) {
     290           77748 :         freeReg(e.typeReg);
     291           77748 :         regs[e.typeReg] = NULL;
     292         1004722 :     } else if (!e.typeClobbered &&
     293          408789 :                fe->type.inRegister() &&
     294          173455 :                frame->regstate(fe->type.reg()).usedBy()) {
     295          173455 :         freeReg(fe->type.reg());
     296                 :     }
     297                 : }
     298                 : 
     299                 : #endif /* JS_NUNBOX32 */
     300                 : 

Generated by: LCOV version 1.7