LCOV - app.info - js/src/methodjit/FrameState-inl.h

LCOV - code coverage report
| Current view: | directory - js/src/methodjit - FrameState-inl.h (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 711 | 672 | 94.5 %
| Date: | 2012-07-07 | Functions: | 92 | 89 | 96.7 %

           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 jsjaeger_framestate_inl_h__ && defined JS_METHODJIT
          41                 : #define jsjaeger_framestate_inl_h__
          42                 :
          43                 : #include "methodjit/LoopState.h"
          44                 :
          45                 : namespace js {
          46                 : namespace mjit {
          47                 :
          48                 : inline void
          49         2605591 : FrameState::addToTracker(FrameEntry *fe)
          50                 : {
          51         2605591 :     JS_ASSERT(!fe->isTracked());
          52         2605591 :     fe->track(tracker.nentries);
          53         2605591 :     tracker.add(fe);
          54         2605591 : }
          55                 :
          56                 : inline FrameEntry *
          57        18382137 : FrameState::peek(int32_t depth)
          58                 : {
          59        18382137 :     JS_ASSERT(depth < 0);
          60        18382137 :     JS_ASSERT(a->sp + depth >= a->spBase);
          61        18382137 :     FrameEntry *fe = a->sp + depth;
          62        18382137 :     if (!fe->isTracked()) {
          63          124643 :         addToTracker(fe);
          64          124643 :         fe->resetSynced();
          65                 :     }
          66        18382137 :     return fe;
          67                 : }
          68                 :
          69                 : inline void
          70         2318467 : FrameState::popn(uint32_t n)
          71                 : {
          72         6858047 :     for (uint32_t i = 0; i < n; i++)
          73         4539580 :         pop();
          74         2318467 : }
          75                 :
          76                 : inline bool
          77          743449 : FrameState::haveSameBacking(FrameEntry *lhs, FrameEntry *rhs)
          78                 : {
          79          743449 :     if (lhs->isCopy())
          80          274192 :         lhs = lhs->copyOf();
          81          743449 :     if (rhs->isCopy())
          82           22218 :         rhs = rhs->copyOf();
          83          743449 :     return lhs == rhs;
          84                 : }
          85                 :
          86                 : inline FrameEntry *
          87           18962 : FrameState::getTemporary(uint32_t which)
          88                 : {
          89           18962 :     JS_ASSERT(which < TEMPORARY_LIMIT);
          90                 :
          91           18962 :     FrameEntry *fe = temporaries + which;
          92           18962 :     JS_ASSERT(fe < temporariesTop);
          93                 :
          94           18962 :     return getOrTrack(uint32_t(fe - entries));
          95                 : }
          96                 :
          97                 : inline AnyRegisterID
          98         5708039 : FrameState::allocReg(uint32_t mask)
          99                 : {
         100         5708039 :     if (freeRegs.hasRegInMask(mask)) {
         101         5591453 :         AnyRegisterID reg = freeRegs.takeAnyReg(mask);
         102         5591453 :         modifyReg(reg);
         103         5591453 :         return reg;
         104                 :     }
         105                 :
         106          116586 :     AnyRegisterID reg = evictSomeReg(mask);
         107          116586 :     modifyReg(reg);
         108          116586 :     return reg;
         109                 : }
         110                 :
         111                 : inline JSC::MacroAssembler::RegisterID
         112         4342861 : FrameState::allocReg()
         113                 : {
         114         4342861 :     return allocReg(Registers::AvailRegs).reg();
         115                 : }
         116                 :
         117                 : inline JSC::MacroAssembler::FPRegisterID
         118         1336471 : FrameState::allocFPReg()
         119                 : {
         120         1336471 :     return allocReg(Registers::AvailFPRegs).fpreg();
         121                 : }
         122                 :
         123                 : inline AnyRegisterID
         124         2052439 : FrameState::allocAndLoadReg(FrameEntry *fe, bool fp, RematInfo::RematType type)
         125                 : {
         126         2052439 :     AnyRegisterID reg;
         127         2052439 :     uint32_t mask = fp ? (uint32_t) Registers::AvailFPRegs : (uint32_t) Registers::AvailRegs;
         128                 :
         129                 :     /*
         130                 :      * Decide whether to retroactively mark a register as holding the entry
         131                 :      * at the start of the current loop. We can do this if (a) the register has
         132                 :      * not been touched since the start of the loop (it is in loopRegs), (b)
         133                 :      * the entry has also not been written to or already had a loop register
         134                 :      * assigned, and (c) we are not in an inline call with multiple callees or
         135                 :      * exit points --- we won't pick up the new loop register when restoring.
         136                 :      */
         137         2105980 :     if (loop && freeRegs.hasRegInMask(loop->getLoopRegs() & mask) &&
         138           37039 :         type == RematInfo::DATA && isOuterSlot(fe) && !cc.activeFrameHasMultipleExits() &&
         139           16502 :         fe->lastLoop < loop->headOffset()) {
         140           16201 :         reg = freeRegs.takeAnyReg(loop->getLoopRegs() & mask);
         141           16201 :         regstate(reg).associate(fe, RematInfo::DATA);
         142           16201 :         fe->lastLoop = loop->headOffset();
         143           16201 :         loop->setLoopReg(reg, fe);
         144           16201 :         return reg;
         145                 :     }
         146                 :
         147         2036238 :     if (!freeRegs.empty(mask))
         148         1978689 :         reg = freeRegs.takeAnyReg(mask);
         149                 :     else
         150           57549 :         reg = evictSomeReg(mask);
         151         2036238 :     modifyReg(reg);
         152                 :
         153         2036238 :     if (fp)
         154            1164 :         masm.loadDouble(addressOf(fe), reg.fpreg());
         155         2035074 :     else if (type == RematInfo::TYPE)
         156         1187904 :         masm.loadTypeTag(addressOf(fe), reg.reg());
         157                 :     else
         158          847170 :         masm.loadPayload(addressOf(fe), reg.reg());
         159                 :
         160         2036238 :     regstate(reg).associate(fe, type);
         161         2036238 :     return reg;
         162                 : }
         163                 :
         164                 : inline void
         165         8534373 : FrameState::modifyReg(AnyRegisterID reg)
         166                 : {
         167         8534373 :     if (loop)
         168          865512 :         loop->clearLoopReg(reg);
         169         8534373 : }
         170                 :
         171                 : inline void
         172           11404 : FrameState::convertInt32ToDouble(Assembler &masm, FrameEntry *fe, FPRegisterID fpreg) const
         173                 : {
         174           11404 :     JS_ASSERT(!fe->isConstant());
         175                 :
         176           11404 :     if (fe->isCopy())
         177            2295 :         fe = fe->copyOf();
         178                 :
         179           11404 :     if (fe->data.inRegister())
         180            9393 :         masm.convertInt32ToDouble(fe->data.reg(), fpreg);
         181                 :     else
         182            2011 :         masm.convertInt32ToDouble(masm.payloadOf(addressOf(fe)), fpreg);
         183           11404 : }
         184                 :
         185                 : inline bool
         186               0 : FrameState::peekTypeInRegister(FrameEntry *fe) const
         187                 : {
         188               0 :     if (fe->isCopy())
         189               0 :         fe = fe->copyOf();
         190               0 :     return fe->type.inRegister();
         191                 : }
         192                 :
         193                 : inline void
         194         8842900 : FrameState::pop()
         195                 : {
         196         8842900 :     JS_ASSERT(a->sp > a->spBase);
         197                 :
         198         8842900 :     FrameEntry *fe = --a->sp;
         199         8842900 :     if (!fe->isTracked())
         200           62972 :         return;
         201                 :
         202         8779928 :     forgetAllRegs(fe);
         203         8779928 :     fe->type.invalidate();
         204         8779928 :     fe->data.invalidate();
         205         8779928 :     fe->clear();
         206                 :
         207         8779928 :     extraArray[fe - entries].reset();
         208                 : }
         209                 :
         210                 : inline void
         211         1885388 : FrameState::freeReg(AnyRegisterID reg)
         212                 : {
         213         1885388 :     JS_ASSERT(!regstate(reg).usedBy());
         214                 :
         215         1885388 :     freeRegs.putReg(reg);
         216         1885388 : }
         217                 :
         218                 : inline void
         219         6337359 : FrameState::forgetReg(AnyRegisterID reg)
         220                 : {
         221                 :     /*
         222                 :      * Important: Do not touch the fe here. We can peephole optimize away
         223                 :      * loads and stores by re-using the contents of old FEs.
         224                 :      */
         225         6337359 :     JS_ASSERT_IF(regstate(reg).fe(), !regstate(reg).fe()->isCopy());
         226                 :
         227         6337359 :     if (!regstate(reg).isPinned()) {
         228         5957788 :         regstate(reg).forget();
         229         5957788 :         freeRegs.putReg(reg);
         230                 :     }
         231         6337359 : }
         232                 :
         233                 : inline FrameEntry *
         234         8906643 : FrameState::rawPush()
         235                 : {
         236         8906643 :     JS_ASSERT(a->sp < temporaries);
         237         8906643 :     FrameEntry *fe = a->sp++;
         238                 :
         239         8906643 :     if (!fe->isTracked())
         240         1747478 :         addToTracker(fe);
         241         8906643 :     fe->type.invalidate();
         242         8906643 :     fe->data.invalidate();
         243         8906643 :     fe->clear();
         244                 :
         245         8906643 :     extraArray[fe - entries].reset();
         246                 :
         247         8906643 :     return fe;
         248                 : }
         249                 :
         250                 : inline void
         251         1701689 : FrameState::push(const Value &v)
         252                 : {
         253         1701689 :     FrameEntry *fe = rawPush();
         254         1701689 :     fe->setConstant(v);
         255         1701689 : }
         256                 :
         257                 : inline void
         258         2717700 : FrameState::pushSynced(JSValueType type)
         259                 : {
         260         2717700 :     FrameEntry *fe = rawPush();
         261                 :
         262         2717700 :     fe->resetSynced();
         263         2717700 :     if (type != JSVAL_TYPE_UNKNOWN) {
         264           94420 :         fe->setType(type);
         265           94420 :         if (type == JSVAL_TYPE_DOUBLE)
         266             257 :             masm.ensureInMemoryDouble(addressOf(fe));
         267                 :     }
         268         2717700 : }
         269                 :
         270                 : inline void
         271                 : FrameState::pushSynced(JSValueType type, RegisterID reg)
         272                 : {
         273                 :     FrameEntry *fe = rawPush();
         274                 :
         275                 :     fe->resetUnsynced();
         276                 :     fe->type.sync();
         277                 :     fe->data.sync();
         278                 :     fe->setType(type);
         279                 :     fe->data.setRegister(reg);
         280                 :     regstate(reg).associate(fe, RematInfo::DATA);
         281                 : }
         282                 :
         283                 : inline void
         284          410814 : FrameState::loadIntoRegisters(Address address, bool reuseBase,
         285                 :                               RegisterID *ptypeReg, RegisterID *pdataReg)
         286                 : {
         287                 :
         288                 : #ifdef JS_PUNBOX64
         289                 :
         290                 :     // It's okay if either of these clobbers address.base, since we guarantee
         291                 :     // eviction will not physically clobber. It's also safe, on x64, for
         292                 :     // loadValueAsComponents() to take either type or data regs as address.base.
         293                 :     RegisterID typeReg = allocReg();
         294                 :     RegisterID dataReg = reuseBase ? address.base : allocReg();
         295                 :     masm.loadValueAsComponents(address, typeReg, dataReg);
         296                 :
         297                 : #elif JS_NUNBOX32
         298                 :
         299                 :     // Prevent us from clobbering this reg.
         300          410814 :     bool free = freeRegs.hasReg(address.base);
         301          410814 :     bool needsPin = !free && regstate(address.base).fe();
         302          410814 :     if (free)
         303            2107 :         freeRegs.takeReg(address.base);
         304          410814 :     if (needsPin)
         305            3756 :         pinReg(address.base);
         306                 :
         307          410814 :     RegisterID typeReg = allocReg();
         308                 :
         309          410814 :     masm.loadTypeTag(address, typeReg);
         310                 :
         311                 :     // Allow re-use of the base register. This could avoid a spill, and
         312                 :     // is safe because the following allocReg() won't actually emit any
         313                 :     // writes to the register.
         314          410814 :     if (free)
         315            2107 :         freeRegs.putReg(address.base);
         316          410814 :     if (needsPin)
         317            3756 :         unpinReg(address.base);
         318                 :
         319          410814 :     RegisterID dataReg = reuseBase ? address.base : allocReg();
         320          410814 :     masm.loadPayload(address, dataReg);
         321                 :
         322                 : #endif
         323                 :
         324          410814 :     *ptypeReg = typeReg;
         325          410814 :     *pdataReg = dataReg;
         326          410814 : }
         327                 :
         328                 : inline void
         329          381533 : FrameState::push(Address address, JSValueType knownType, bool reuseBase)
         330                 : {
         331          381533 :     if (knownType == JSVAL_TYPE_DOUBLE) {
         332            1044 :         FPRegisterID fpreg = allocFPReg();
         333            1044 :         masm.moveInt32OrDouble(address, fpreg);
         334            1044 :         pushDouble(fpreg);
         335            1044 :         if (reuseBase)
         336             696 :             freeReg(address.base);
         337            1044 :         return;
         338                 :     }
         339                 :
         340          380489 :     if (knownType != JSVAL_TYPE_UNKNOWN) {
         341           61335 :         RegisterID dataReg = reuseBase ? address.base : allocReg();
         342           61335 :         masm.loadPayload(address, dataReg);
         343           61335 :         pushTypedPayload(knownType, dataReg);
         344           61335 :         return;
         345                 :     }
         346                 :
         347                 :     RegisterID typeReg, dataReg;
         348          319154 :     loadIntoRegisters(address, reuseBase, &typeReg, &dataReg);
         349                 :
         350          319154 :     pushRegs(typeReg, dataReg, JSVAL_TYPE_UNKNOWN);
         351                 : }
         352                 :
         353                 : inline void
         354               0 : FrameState::pushWord(Address address, JSValueType knownType, bool reuseBase)
         355                 : {
         356               0 :     JS_ASSERT(knownType != JSVAL_TYPE_DOUBLE);
         357               0 :     JS_ASSERT(knownType != JSVAL_TYPE_UNKNOWN);
         358                 :
         359               0 :     RegisterID dataReg = reuseBase ? address.base : allocReg();
         360               0 :     masm.loadPtr(address, dataReg);
         361               0 :     pushTypedPayload(knownType, dataReg);
         362               0 : }
         363                 :
         364                 : inline JSC::MacroAssembler::FPRegisterID
         365         1899409 : FrameState::storeRegs(int32_t depth, RegisterID type, RegisterID data, JSValueType knownType)
         366                 : {
         367         1899409 :     FrameEntry *fe = peek(depth);
         368         1899409 :     forgetEntry(fe);
         369         1899409 :     fe->resetUnsynced();
         370                 :
         371                 :     /*
         372                 :      * Even if the type or data gets freed due to knownType or a double result,
         373                 :      * neither register should be clobbered (see Compiler::testBarrier).
         374                 :      */
         375         1899409 :     JS_ASSERT(!freeRegs.hasReg(type) && !freeRegs.hasReg(data));
         376                 :
         377         1899409 :     if (knownType == JSVAL_TYPE_UNKNOWN) {
         378         1779595 :         fe->type.setRegister(type);
         379         1779595 :         fe->data.setRegister(data);
         380         1779595 :         regstate(type).associate(fe, RematInfo::TYPE);
         381         1779595 :         regstate(data).associate(fe, RematInfo::DATA);
         382         1779595 :         return Registers::FPConversionTemp;
         383                 :     }
         384                 :
         385          119814 :     if (knownType == JSVAL_TYPE_DOUBLE) {
         386           10152 :         FPRegisterID fpreg = allocFPReg();
         387           10152 :         masm.moveInt32OrDouble(data, type, addressOf(fe), fpreg);
         388           10152 :         fe->setType(JSVAL_TYPE_DOUBLE);
         389           10152 :         fe->data.setFPRegister(fpreg);
         390           10152 :         regstate(fpreg).associate(fe, RematInfo::DATA);
         391           10152 :         freeReg(type);
         392           10152 :         freeReg(data);
         393           10152 :         return fpreg;
         394                 :     }
         395                 :
         396          109662 :     freeReg(type);
         397          109662 :     fe->setType(knownType);
         398          109662 :     fe->data.setRegister(data);
         399          109662 :     regstate(data).associate(fe, RematInfo::DATA);
         400          109662 :     return Registers::FPConversionTemp;
         401                 : }
         402                 :
         403                 : inline JSC::MacroAssembler::FPRegisterID
         404         1899409 : FrameState::pushRegs(RegisterID type, RegisterID data, JSValueType knownType)
         405                 : {
         406         1899409 :     pushSynced(JSVAL_TYPE_UNKNOWN);
         407         1899409 :     return storeRegs(-1, type, data, knownType);
         408                 : }
         409                 :
         410                 : inline void
         411          147385 : FrameState::reloadEntry(Assembler &masm, Address address, FrameEntry *fe)
         412                 : {
         413          147385 :     if (fe->data.inRegister()) {
         414          146553 :         if (fe->type.inRegister()) {
         415          118719 :             masm.loadValueAsComponents(address, fe->type.reg(), fe->data.reg());
         416                 :         } else {
         417           27834 :             JS_ASSERT(fe->isTypeKnown());
         418           27834 :             masm.loadPayload(address, fe->data.reg());
         419                 :         }
         420                 :     } else {
         421             832 :         JS_ASSERT(fe->data.inFPRegister());
         422             832 :         masm.moveInt32OrDouble(address, fe->data.fpreg());
         423                 :     }
         424          147385 : }
         425                 :
         426                 : inline void
         427          296842 : FrameState::pushTypedPayload(JSValueType type, RegisterID payload)
         428                 : {
         429          296842 :     JS_ASSERT(type != JSVAL_TYPE_DOUBLE);
         430          296842 :     JS_ASSERT(!freeRegs.hasReg(payload));
         431                 :
         432          296842 :     FrameEntry *fe = rawPush();
         433                 :
         434          296842 :     fe->resetUnsynced();
         435          296842 :     fe->setType(type);
         436          296842 :     fe->data.setRegister(payload);
         437          296842 :     regstate(payload).associate(fe, RematInfo::DATA);
         438          296842 : }
         439                 :
         440                 : inline void
         441          562317 : FrameState::pushNumber(RegisterID payload, bool asInt32)
         442                 : {
         443          562317 :     JS_ASSERT(!freeRegs.hasReg(payload));
         444                 :
         445          562317 :     FrameEntry *fe = rawPush();
         446                 :
         447          562317 :     if (asInt32) {
         448          559254 :         if (!fe->type.synced())
         449          251141 :             masm.storeTypeTag(ImmType(JSVAL_TYPE_INT32), addressOf(fe));
         450          559254 :         fe->type.setMemory();
         451                 :     } else {
         452            3063 :         fe->type.setMemory();
         453                 :     }
         454                 :
         455          562317 :     fe->data.unsync();
         456          562317 :     fe->data.setRegister(payload);
         457          562317 :     regstate(payload).associate(fe, RematInfo::DATA);
         458          562317 : }
         459                 :
         460                 : inline void
         461                 : FrameState::pushInt32(RegisterID payload)
         462                 : {
         463                 :     FrameEntry *fe = rawPush();
         464                 :
         465                 :     masm.storeTypeTag(ImmType(JSVAL_TYPE_INT32), addressOf(fe));
         466                 :     fe->type.setMemory();
         467                 :
         468                 :     fe->data.unsync();
         469                 :     fe->data.setRegister(payload);
         470                 :     regstate(payload).associate(fe, RematInfo::DATA);
         471                 : }
         472                 :
         473                 : inline void
         474            4630 : FrameState::pushUntypedPayload(JSValueType type, RegisterID payload)
         475                 : {
         476            4630 :     JS_ASSERT(!freeRegs.hasReg(payload));
         477                 :
         478            4630 :     FrameEntry *fe = rawPush();
         479                 :
         480            4630 :     masm.storeTypeTag(ImmType(type), addressOf(fe));
         481                 :
         482                 :     /* The forceful type sync will assert otherwise. */
         483                 : #ifdef DEBUG
         484            4630 :     fe->type.unsync();
         485                 : #endif
         486            4630 :     fe->type.setMemory();
         487            4630 :     fe->data.unsync();
         488            4630 :     fe->data.setRegister(payload);
         489            4630 :     regstate(payload).associate(fe, RematInfo::DATA);
         490            4630 : }
         491                 :
         492                 : inline void
         493                 : FrameState::pushUntypedValue(const Value &v)
         494                 : {
         495                 :     FrameEntry *fe = rawPush();
         496                 :
         497                 :     masm.storeValue(v, addressOf(fe));
         498                 :
         499                 :     /* The forceful type sync will assert otherwise. */
         500                 : #ifdef DEBUG
         501                 :     fe->type.unsync();
         502                 : #endif
         503                 :     fe->type.setMemory();
         504                 :     fe->data.unsync();
         505                 :     fe->data.setMemory();
         506                 : }
         507                 :
         508                 : inline JSC::MacroAssembler::RegisterID
         509                 : FrameState::tempRegForType(FrameEntry *fe, RegisterID fallback)
         510                 : {
         511                 :     JS_ASSERT(!regstate(fallback).fe());
         512                 :     if (fe->isCopy())
         513                 :         fe = fe->copyOf();
         514                 :
         515                 :     JS_ASSERT(!fe->type.isConstant());
         516                 :
         517                 :     if (fe->type.inRegister())
         518                 :         return fe->type.reg();
         519                 :
         520                 :     /* :XXX: X86 */
         521                 :
         522                 :     masm.loadTypeTag(addressOf(fe), fallback);
         523                 :     return fallback;
         524                 : }
         525                 :
         526                 :
         527                 : inline JSC::MacroAssembler::RegisterID
         528         3287861 : FrameState::tempRegForType(FrameEntry *fe)
         529                 : {
         530         3287861 :     if (fe->isCopy())
         531          414611 :         fe = fe->copyOf();
         532                 :
         533         3287861 :     JS_ASSERT(!fe->type.isConstant());
         534                 :
         535         3287861 :     if (fe->type.inRegister())
         536         2101532 :         return fe->type.reg();
         537                 :
         538                 :     /* :XXX: X86 */
         539                 :
         540         1186329 :     RegisterID reg = allocAndLoadReg(fe, false, RematInfo::TYPE).reg();
         541         1186329 :     fe->type.setRegister(reg);
         542         1186329 :     return reg;
         543                 : }
         544                 :
         545                 : inline void
         546               0 : FrameState::loadTypeIntoReg(const FrameEntry *fe, RegisterID reg)
         547                 : {
         548               0 :     if (fe->isCopy())
         549               0 :         fe = fe->copyOf();
         550                 :
         551               0 :     JS_ASSERT(!fe->type.isConstant());
         552                 :
         553               0 :     if (fe->type.inRegister()) {
         554               0 :         if (fe->type.reg() == reg)
         555               0 :             return;
         556               0 :         masm.move(fe->type.reg(), reg);
         557               0 :         return;
         558                 :     }
         559                 :
         560               0 :     masm.loadTypeTag(addressOf(fe), reg);
         561                 : }
         562                 :
         563                 : inline void
         564                 : FrameState::loadDataIntoReg(const FrameEntry *fe, RegisterID reg)
         565                 : {
         566                 :     if (fe->isCopy())
         567                 :         fe = fe->copyOf();
         568                 :
         569                 :     JS_ASSERT(!fe->data.isConstant());
         570                 :
         571                 :     if (fe->data.inRegister()) {
         572                 :         if (fe->data.reg() == reg)
         573                 :             return;
         574                 :         masm.move(fe->data.reg(), reg);
         575                 :         return;
         576                 :     }
         577                 :
         578                 :     masm.loadPayload(addressOf(fe), reg);
         579                 : }
         580                 :
         581                 : inline JSC::MacroAssembler::RegisterID
         582         2989976 : FrameState::tempRegForData(FrameEntry *fe)
         583                 : {
         584         2989976 :     JS_ASSERT(!fe->isConstant());
         585         2989976 :     JS_ASSERT(!fe->isType(JSVAL_TYPE_DOUBLE));
         586                 :
         587         2989976 :     if (fe->isCopy())
         588          307705 :         fe = fe->copyOf();
         589                 :
         590         2989976 :     if (fe->data.inRegister())
         591         2129156 :         return fe->data.reg();
         592                 :
         593          860820 :     RegisterID reg = allocAndLoadReg(fe, false, RematInfo::DATA).reg();
         594          860820 :     fe->data.setRegister(reg);
         595          860820 :     return reg;
         596                 : }
         597                 :
         598                 : inline void
         599         1095664 : FrameState::forgetMismatchedObject(FrameEntry *fe)
         600                 : {
         601         1095664 :     if (fe->isNotType(JSVAL_TYPE_OBJECT)) {
         602            1055 :         if (fe->isCopied()) {
         603               1 :             syncFe(fe);
         604               1 :             uncopy(fe);
         605               1 :             fe->resetSynced();
         606                 :         } else {
         607            1054 :             syncAndForgetFe(fe);
         608                 :         }
         609            1055 :         fe->clear();
         610                 :     }
         611                 :
         612         1095664 :     if (fe->isConstant()) {
         613           32341 :         RegisterID reg = allocReg();
         614           32341 :         regstate(reg).associate(fe, RematInfo::DATA);
         615                 :
         616           32341 :         masm.move(JSC::MacroAssembler::ImmPtr(&fe->getValue().toObject()), reg);
         617           32341 :         fe->data.setRegister(reg);
         618                 :     }
         619         1095664 : }
         620                 :
         621                 : inline JSC::MacroAssembler::FPRegisterID
         622           23617 : FrameState::tempFPRegForData(FrameEntry *fe)
         623                 : {
         624           23617 :     JS_ASSERT(!fe->isConstant());
         625           23617 :     JS_ASSERT(fe->isType(JSVAL_TYPE_DOUBLE));
         626                 :
         627           23617 :     if (fe->isCopy())
         628            1630 :         fe = fe->copyOf();
         629                 :
         630           23617 :     JS_ASSERT(!fe->data.inRegister());
         631                 :
         632           23617 :     if (fe->data.inFPRegister())
         633           22311 :         return fe->data.fpreg();
         634                 :
         635            1306 :     FPRegisterID reg = allocAndLoadReg(fe, true, RematInfo::DATA).fpreg();
         636            1306 :     fe->data.setFPRegister(reg);
         637            1306 :     return reg;
         638                 : }
         639                 :
         640                 : inline AnyRegisterID
         641            5126 : FrameState::tempRegInMaskForData(FrameEntry *fe, uint32_t mask)
         642                 : {
         643            5126 :     JS_ASSERT(!fe->isConstant());
         644            5126 :     JS_ASSERT_IF(fe->isType(JSVAL_TYPE_DOUBLE), !(mask & ~Registers::AvailFPRegs));
         645            5126 :     JS_ASSERT_IF(!fe->isType(JSVAL_TYPE_DOUBLE), !(mask & ~Registers::AvailRegs));
         646                 :
         647            5126 :     if (fe->isCopy())
         648             593 :         fe = fe->copyOf();
         649                 :
         650            5126 :     AnyRegisterID reg;
         651            5126 :     if (fe->data.inRegister() || fe->data.inFPRegister()) {
         652            4393 :         AnyRegisterID old;
         653            4393 :         if (fe->data.inRegister())
         654            4312 :             old = fe->data.reg();
         655                 :         else
         656              81 :             old = fe->data.fpreg();
         657            4393 :         if (Registers::maskReg(old) & mask)
         658            2569 :             return old;
         659                 :
         660                 :         /* Keep the old register pinned. */
         661            1824 :         regstate(old).forget();
         662            1824 :         reg = allocReg(mask);
         663            1824 :         if (reg.isReg())
         664            1824 :             masm.move(old.reg(), reg.reg());
         665                 :         else
         666               0 :             masm.moveDouble(old.fpreg(), reg.fpreg());
         667            1824 :         freeReg(old);
         668                 :     } else {
         669             733 :         reg = allocReg(mask);
         670             733 :         if (reg.isReg())
         671             733 :             masm.loadPayload(addressOf(fe), reg.reg());
         672                 :         else
         673               0 :             masm.loadDouble(addressOf(fe), reg.fpreg());
         674                 :     }
         675            2557 :     regstate(reg).associate(fe, RematInfo::DATA);
         676            2557 :     if (reg.isReg())
         677            2557 :         fe->data.setRegister(reg.reg());
         678                 :     else
         679               0 :         fe->data.setFPRegister(reg.fpreg());
         680            2557 :     return reg;
         681                 : }
         682                 :
         683                 : inline JSC::MacroAssembler::RegisterID
         684                 : FrameState::tempRegForData(FrameEntry *fe, RegisterID reg, Assembler &masm) const
         685                 : {
         686                 :     JS_ASSERT(!fe->data.isConstant());
         687                 :
         688                 :     if (fe->isCopy())
         689                 :         fe = fe->copyOf();
         690                 :
         691                 :     JS_ASSERT(!fe->data.inFPRegister());
         692                 :
         693                 :     if (fe->data.inRegister()) {
         694                 :         JS_ASSERT(fe->data.reg() != reg);
         695                 :         return fe->data.reg();
         696                 :     } else {
         697                 :         masm.loadPayload(addressOf(fe), reg);
         698                 :         return reg;
         699                 :     }
         700                 : }
         701                 :
         702                 : inline bool
         703          407859 : FrameState::shouldAvoidTypeRemat(FrameEntry *fe)
         704                 : {
         705          407859 :     return !fe->isCopy() && fe->type.inMemory();
         706                 : }
         707                 :
         708                 : inline bool
         709           43244 : FrameState::shouldAvoidDataRemat(FrameEntry *fe)
         710                 : {
         711           43244 :     return !fe->isCopy() && fe->data.inMemory();
         712                 : }
         713                 :
         714                 : inline void
         715           57315 : FrameState::ensureFeSynced(const FrameEntry *fe, Assembler &masm) const
         716                 : {
         717           57315 :     Address to = addressOf(fe);
         718           57315 :     const FrameEntry *backing = fe;
         719           57315 :     if (fe->isCopy())
         720            2916 :         backing = fe->copyOf();
         721                 :
         722           57315 :     if (backing->isType(JSVAL_TYPE_DOUBLE)) {
         723           53093 :         if (fe->data.synced()) {
         724                 :             /* Entries representing known doubles can't be partially synced. */
         725            6954 :             JS_ASSERT(fe->type.synced());
         726            6954 :             return;
         727                 :         }
         728           46139 :         if (backing->isConstant()) {
         729           11296 :             masm.storeValue(backing->getValue(), to);
         730           34843 :         } else if (backing->data.inFPRegister()) {
         731           33902 :             masm.storeDouble(backing->data.fpreg(), to);
         732                 :         } else {
         733                 :             /* Use a temporary so the entry can be synced without allocating a register. */
         734             941 :             JS_ASSERT(backing->data.inMemory() && backing != fe);
         735             941 :             masm.loadDouble(addressOf(backing), Registers::FPConversionTemp);
         736             941 :             masm.storeDouble(Registers::FPConversionTemp, to);
         737                 :         }
         738           46139 :         return;
         739                 :     }
         740                 :
         741                 : #if defined JS_PUNBOX64
         742                 :     /* If we can, sync the type and data in one go. */
         743                 :     if (!fe->data.synced() && !fe->type.synced()) {
         744                 :         if (backing->isConstant())
         745                 :             masm.storeValue(backing->getValue(), to);
         746                 :         else if (backing->isTypeKnown())
         747                 :             masm.storeValueFromComponents(ImmType(backing->getKnownType()), backing->data.reg(), to);
         748                 :         else
         749                 :             masm.storeValueFromComponents(backing->type.reg(), backing->data.reg(), to);
         750                 :         return;
         751                 :     }
         752                 : #endif
         753                 :
         754                 :     /*
         755                 :      * On x86_64, only one of the following two calls will have output,
         756                 :      * and a load will only occur if necessary.
         757                 :      */
         758            4222 :     ensureDataSynced(fe, masm);
         759            4222 :     ensureTypeSynced(fe, masm);
         760                 : }
         761                 :
         762                 : inline void
         763        15480893 : FrameState::ensureTypeSynced(const FrameEntry *fe, Assembler &masm) const
         764                 : {
         765        15480893 :     if (fe->type.synced())
         766         7192970 :         return;
         767                 :
         768         8287923 :     Address to = addressOf(fe);
         769         8287923 :     const FrameEntry *backing = fe;
         770         8287923 :     if (fe->isCopy())
         771         1260843 :         backing = fe->copyOf();
         772                 :
         773                 : #if defined JS_PUNBOX64
         774                 :     /* Attempt to store the entire Value, to prevent a load. */
         775                 :     if (backing->isConstant()) {
         776                 :         masm.storeValue(backing->getValue(), to);
         777                 :         return;
         778                 :     }
         779                 :
         780                 :     if (backing->data.inRegister()) {
         781                 :         RegisterID dreg = backing->data.reg();
         782                 :         if (backing->isTypeKnown())
         783                 :             masm.storeValueFromComponents(ImmType(backing->getKnownType()), dreg, to);
         784                 :         else
         785                 :             masm.storeValueFromComponents(backing->type.reg(), dreg, to);
         786                 :         return;
         787                 :     }
         788                 : #endif
         789                 :
         790                 :     /* Store a double's type bits, even though !isTypeKnown(). */
         791         8287923 :     if (backing->isConstant())
         792         2374485 :         masm.storeTypeTag(ImmTag(backing->getKnownTag()), to);
         793         5913438 :     else if (backing->isTypeKnown())
         794          961850 :         masm.storeTypeTag(ImmType(backing->getKnownType()), to);
         795                 :     else
         796         4951588 :         masm.storeTypeTag(backing->type.reg(), to);
         797                 : }
         798                 :
         799                 : inline void
         800        15688145 : FrameState::ensureDataSynced(const FrameEntry *fe, Assembler &masm) const
         801                 : {
         802        15688145 :     if (fe->data.synced())
         803         6547556 :         return;
         804                 :
         805         9140589 :     Address to = addressOf(fe);
         806         9140589 :     const FrameEntry *backing = fe;
         807         9140589 :     if (fe->isCopy())
         808         1261071 :         backing = fe->copyOf();
         809                 :
         810                 : #if defined JS_PUNBOX64
         811                 :     if (backing->isConstant())
         812                 :         masm.storeValue(backing->getValue(), to);
         813                 :     else if (backing->isTypeKnown())
         814                 :         masm.storeValueFromComponents(ImmType(backing->getKnownType()), backing->data.reg(), to);
         815                 :     else if (backing->type.inRegister())
         816                 :         masm.storeValueFromComponents(backing->type.reg(), backing->data.reg(), to);
         817                 :     else
         818                 :         masm.storePayload(backing->data.reg(), to);
         819                 : #elif defined JS_NUNBOX32
         820         9140589 :     if (backing->isConstant())
         821         2374735 :         masm.storePayload(ImmPayload(backing->getPayload()), to);
         822                 :     else
         823         6765854 :         masm.storePayload(backing->data.reg(), to);
         824                 : #endif
         825                 : }
         826                 :
         827                 : inline void
         828         6504413 : FrameState::syncFe(FrameEntry *fe)
         829                 : {
         830         6504413 :     if (fe->type.synced() && fe->data.synced())
         831         4519413 :         return;
         832                 :
         833         1985000 :     FrameEntry *backing = fe;
         834         1985000 :     if (fe->isCopy())
         835          324525 :         backing = fe->copyOf();
         836                 :
         837         1985000 :     if (backing->isType(JSVAL_TYPE_DOUBLE)) {
         838           12119 :         if (!backing->isConstant())
         839            7757 :             tempFPRegForData(backing);
         840           12119 :         ensureFeSynced(fe, masm);
         841                 :
         842           12119 :         if (!fe->type.synced())
         843           12119 :             fe->type.sync();
         844           12119 :         if (!fe->data.synced())
         845           12119 :             fe->data.sync();
         846           12119 :         return;
         847                 :     }
         848                 :
         849         1972881 :     bool needTypeReg = !fe->type.synced() && backing->type.inMemory();
         850         1972881 :     bool needDataReg = !fe->data.synced() && backing->data.inMemory();
         851                 :
         852                 : #if defined JS_NUNBOX32
         853                 :     /* Determine an ordering that won't spill known regs. */
         854         1972881 :     if (needTypeReg && !needDataReg) {
         855            2735 :         syncData(fe);
         856            2735 :         syncType(fe);
         857                 :     } else {
         858         1970146 :         syncType(fe);
         859         1970146 :         syncData(fe);
         860                 :     }
         861                 : #elif defined JS_PUNBOX64
         862                 :     if (JS_UNLIKELY(needTypeReg && needDataReg)) {
         863                 :         /* Memory-to-memory moves can only occur for copies backed by memory. */
         864                 :         JS_ASSERT(backing != fe);
         865                 :
         866                 :         /* Use ValueReg to do a whole-Value mem-to-mem move. */
         867                 :         masm.loadValue(addressOf(backing), Registers::ValueReg);
         868                 :         masm.storeValue(Registers::ValueReg, addressOf(fe));
         869                 :     } else {
         870                 :         /* Store in case unpinning is necessary. */
         871                 :         MaybeRegisterID pairReg;
         872                 :
         873                 :         /* Get a register if necessary, without clobbering its pair. */
         874                 :         if (needTypeReg) {
         875                 :             if (backing->data.inRegister() && !regstate(backing->data.reg()).isPinned()) {
         876                 :                 pairReg = backing->data.reg();
         877                 :                 pinReg(backing->data.reg());
         878                 :             }
         879                 :             tempRegForType(backing);
         880                 :         } else if (needDataReg) {
         881                 :             if (backing->type.inRegister() && !regstate(backing->type.reg()).isPinned()) {
         882                 :                 pairReg = backing->type.reg();
         883                 :                 pinReg(backing->type.reg());
         884                 :             }
         885                 :             tempRegForData(backing);
         886                 :         }
         887                 :
         888                 :         ensureFeSynced(fe, masm);
         889                 :
         890                 :         if (pairReg.isSet())
         891                 :             unpinReg(pairReg.reg());
         892                 :     }
         893                 :
         894                 :     if (!fe->type.synced())
         895                 :         fe->type.sync();
         896                 :     if (!fe->data.synced())
         897                 :         fe->data.sync();
         898                 : #endif
         899                 : }
         900                 :
         901                 : inline void
         902            3687 : FrameState::syncAndForgetFe(FrameEntry *fe, bool markSynced)
         903                 : {
         904            3687 :     if (markSynced) {
         905            2319 :         if (!fe->type.synced())
         906            1911 :             fe->type.sync();
         907            2319 :         if (!fe->data.synced())
         908            1911 :             fe->data.sync();
         909                 :     }
         910                 :
         911            3687 :     syncFe(fe);
         912            3687 :     forgetAllRegs(fe);
         913            3687 :     fe->type.setMemory();
         914            3687 :     fe->data.setMemory();
         915            3687 : }
         916                 :
         917                 : inline JSC::MacroAssembler::Address
         918           28543 : FrameState::loadNameAddress(const analyze::ScriptAnalysis::NameAccess &access, RegisterID reg)
         919                 : {
         920           28543 :     JS_ASSERT(access.script && access.nesting);
         921                 :
         922           28543 :     masm.move(ImmPtr(access.basePointer()), reg);
         923           28543 :     masm.loadPtr(Address(reg), reg);
         924                 :
         925           28543 :     return Address(reg, access.index * sizeof(Value));
         926                 : }
         927                 :
         928                 : inline JSC::MacroAssembler::Address
         929           28033 : FrameState::loadNameAddress(const analyze::ScriptAnalysis::NameAccess &access)
         930                 : {
         931           28033 :     RegisterID reg = allocReg();
         932           28033 :     return loadNameAddress(access, reg);
         933                 : }
         934                 :
         935                 : inline void
         936           10643 : FrameState::forgetLoopReg(FrameEntry *fe)
         937                 : {
         938                 :     /*
         939                 :      * Don't use a loop register for fe in the active loop, as its underlying
         940                 :      * representation may have changed since the start of the loop.
         941                 :      */
         942           10643 :     if (loop)
         943            8750 :         fe->lastLoop = loop->headOffset();
         944           10643 : }
         945                 :
         946                 : inline void
         947         3211659 : FrameState::syncType(FrameEntry *fe)
         948                 : {
         949         3211659 :     JS_ASSERT(!fe->isType(JSVAL_TYPE_DOUBLE));
         950                 :
         951         3211659 :     FrameEntry *backing = fe;
         952         3211659 :     if (fe->isCopy())
         953          323717 :         backing = fe->copyOf();
         954                 :
         955         3211659 :     if (!fe->type.synced() && backing->type.inMemory())
         956           64292 :         tempRegForType(backing);
         957                 :
         958         3211659 :     ensureTypeSynced(fe, masm);
         959                 :
         960         3211659 :     if (!fe->type.synced())
         961         3016526 :         fe->type.sync();
         962         3211659 : }
         963                 :
         964                 : inline void
         965         3421601 : FrameState::syncData(FrameEntry *fe)
         966                 : {
         967         3421601 :     JS_ASSERT(!fe->isType(JSVAL_TYPE_DOUBLE));
         968                 :
         969         3421601 :     FrameEntry *backing = fe;
         970         3421601 :     if (fe->isCopy())
         971          323717 :         backing = fe->copyOf();
         972                 :
         973         3421601 :     if (!fe->data.synced() && backing->data.inMemory())
         974           82947 :         tempRegForData(backing);
         975                 :
         976         3421601 :     ensureDataSynced(fe, masm);
         977                 :
         978         3421601 :     if (!fe->data.synced())
         979         3017220 :         fe->data.sync();
         980         3421601 : }
         981                 :
         982                 : inline void
         983           40950 : FrameState::fakeSync(FrameEntry *fe)
         984                 : {
         985                 :     /*
         986                 :      * If a frame entry's value will no longer be used, we can mark it as being
         987                 :      * synced without actually performing the sync: the value is not observed.
         988                 :      */
         989           40950 :     if (!fe->data.synced())
         990             909 :         fe->data.sync();
         991           40950 :     if (!fe->type.synced())
         992             686 :         fe->type.sync();
         993           40950 : }
         994                 :
         995                 : inline void
         996             303 : FrameState::forgetType(FrameEntry *fe)
         997                 : {
         998                 :     /*
         999                 :      * The type may have been forgotten with an intervening storeLocal in the
        1000                 :      * presence of eval or closed variables. For defense in depth and to make
        1001                 :      * callers' lives simpler, bail out if the type is not known.
        1002                 :      */
        1003             303 :     if (!fe->isTypeKnown())
        1004               0 :         return;
        1005                 :
        1006                 :     /*
        1007                 :      * Likewise, storeLocal() may have set this FE, with a known type,
        1008                 :      * to be a copy of another FE, which has an unknown type.
        1009                 :      */
        1010             303 :     if (fe->isCopy()) {
        1011               0 :         syncFe(fe);
        1012               0 :         fe->clear();
        1013               0 :         fe->resetSynced();
        1014               0 :         return;
        1015                 :     }
        1016                 :
        1017             303 :     ensureTypeSynced(fe, masm);
        1018             303 :     fe->type.setMemory();
        1019                 : }
        1020                 :
        1021                 : inline void
        1022          128872 : FrameState::learnType(FrameEntry *fe, JSValueType type, bool unsync)
        1023                 : {
        1024          128872 :     JS_ASSERT(!fe->isType(JSVAL_TYPE_DOUBLE));
        1025          128872 :     JS_ASSERT(type != JSVAL_TYPE_UNKNOWN);
        1026                 :
        1027          128872 :     if (fe->isCopy())
        1028               0 :         fe = fe->copyOf();
        1029                 :
        1030          128872 :     if (type == JSVAL_TYPE_DOUBLE)
        1031             810 :         JS_ASSERT(!fe->data.inRegister());
        1032                 :     else
        1033          128062 :         JS_ASSERT(!fe->data.inFPRegister());
        1034                 :
        1035          128872 :     if (fe->type.inRegister())
        1036           29958 :         forgetReg(fe->type.reg());
        1037          128872 :     fe->setType(type);
        1038          128872 :     if (unsync)
        1039           29535 :         fe->type.unsync();
        1040          128872 : }
        1041                 :
        1042                 : inline void
        1043            6034 : FrameState::learnType(FrameEntry *fe, JSValueType type, RegisterID data)
        1044                 : {
        1045            6034 :     JS_ASSERT(!fe->isCopied());
        1046            6034 :     JS_ASSERT(type != JSVAL_TYPE_UNKNOWN && type != JSVAL_TYPE_DOUBLE);
        1047                 :
        1048            6034 :     forgetAllRegs(fe);
        1049            6034 :     fe->clear();
        1050                 :
        1051            6034 :     fe->type.setConstant();
        1052            6034 :     fe->knownType = type;
        1053                 :
        1054            6034 :     fe->data.setRegister(data);
        1055            6034 :     regstate(data).associate(fe, RematInfo::DATA);
        1056                 :
        1057            6034 :     fe->data.unsync();
        1058            6034 :     fe->type.unsync();
        1059            6034 : }
        1060                 :
        1061                 : inline int32_t
        1062        27497040 : FrameState::frameOffset(const FrameEntry *fe, ActiveFrame *a) const
        1063                 : {
        1064                 :     /*
        1065                 :      * The stored frame offsets for analysis temporaries are immediately above
        1066                 :      * the script's normal slots (and will thus be clobbered should a C++ or
        1067                 :      * scripted call push another frame). There must be enough room in the
        1068                 :      * reserved stack space.
        1069                 :      */
        1070                 :     JS_STATIC_ASSERT(StackSpace::STACK_JIT_EXTRA >= TEMPORARY_LIMIT);
        1071                 :
        1072                 :     /* Note: fe == a->sp is allowed for addressOfTop */
        1073        27497040 :     JS_ASSERT(fe >= a->callee_ && fe <= a->sp);
        1074                 :
        1075        27497040 :     if (fe >= a->locals)
        1076        26374245 :         return StackFrame::offsetOfFixed(uint32_t(fe - a->locals));
        1077         1122795 :     if (fe >= a->args)
        1078          629993 :         return StackFrame::offsetOfFormalArg(a->script->function(), uint32_t(fe - a->args));
        1079          492802 :     if (fe == a->this_)
        1080          464202 :         return StackFrame::offsetOfThis(a->script->function());
        1081           28600 :     if (fe == a->callee_)
        1082           28600 :         return StackFrame::offsetOfCallee(a->script->function());
        1083               0 :     JS_NOT_REACHED("Bad fe");
        1084                 :     return 0;
        1085                 : }
        1086                 :
        1087                 : inline JSC::MacroAssembler::Address
        1088        27525316 : FrameState::addressOf(const FrameEntry *fe) const
        1089                 : {
        1090        27525316 :     if (isTemporary(fe)) {
        1091                 :         /*
        1092                 :          * Temporary addresses are common to the outermost loop, and are shared
        1093                 :          * by all active frames.
        1094                 :          */
        1095           28276 :         return Address(JSFrameReg, (loop->temporariesStart + fe - temporaries) * sizeof(Value));
        1096                 :     }
        1097                 :
        1098        27497040 :     ActiveFrame *na = a;
        1099        55180405 :     while (fe < na->callee_)
        1100          186325 :         na = na->parent;
        1101                 :
        1102        27497040 :     int32_t offset = frameOffset(fe, na);
        1103        27497040 :     return Address(JSFrameReg, offset + (na->depth * sizeof(Value)));
        1104                 : }
        1105                 :
        1106                 : inline uint32_t
        1107          627276 : FrameState::frameSlot(ActiveFrame *a, const FrameEntry *fe) const
        1108                 : {
        1109          627276 :     if (isTemporary(fe))
        1110            2511 :         return fe - entries;
        1111                 :
        1112          624765 :     JS_ASSERT(fe >= a->callee_ && fe < a->sp);
        1113                 :
        1114          624765 :     if (fe >= a->locals)
        1115          589230 :         return analyze::LocalSlot(a->script, fe - a->locals);
        1116           35535 :     if (fe >= a->args)
        1117           30536 :         return analyze::ArgSlot(fe - a->args);
        1118            4999 :     if (fe == a->this_)
        1119            4999 :         return analyze::ThisSlot();
        1120               0 :     if (fe == a->callee_)
        1121               0 :         return analyze::CalleeSlot();
        1122               0 :     JS_NOT_REACHED("Bad fe");
        1123                 :     return 0;
        1124                 : }
        1125                 :
        1126                 : inline JSC::MacroAssembler::Address
        1127             209 : FrameState::addressForInlineReturn()
        1128                 : {
        1129             209 :     if (a->callee_->isTracked())
        1130              27 :         discardFe(a->callee_);
        1131             209 :     return addressOf(a->callee_);
        1132                 : }
        1133                 :
        1134                 : inline JSC::MacroAssembler::Address
        1135           11390 : FrameState::addressForDataRemat(const FrameEntry *fe) const
        1136                 : {
        1137           11390 :     if (fe->isCopy() && !fe->data.synced())
        1138            4042 :         fe = fe->copyOf();
        1139           11390 :     JS_ASSERT(fe->data.synced());
        1140           11390 :     return addressOf(fe);
        1141                 : }
        1142                 :
        1143                 : inline JSC::MacroAssembler::Jump
        1144                 : FrameState::testNull(Assembler::Condition cond, FrameEntry *fe)
        1145                 : {
        1146                 :     JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
        1147                 :     if (shouldAvoidTypeRemat(fe))
        1148                 :         return masm.testNull(cond, addressOf(fe));
        1149                 :     return masm.testNull(cond, tempRegForType(fe));
        1150                 : }
        1151                 :
        1152                 : inline JSC::MacroAssembler::Jump
        1153                 : FrameState::testUndefined(Assembler::Condition cond, FrameEntry *fe)
        1154                 : {
        1155                 :     JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
        1156                 :     if (shouldAvoidTypeRemat(fe))
        1157                 :         return masm.testUndefined(cond, addressOf(fe));
        1158                 :     return masm.testUndefined(cond, tempRegForType(fe));
        1159                 : }
        1160                 :
        1161                 : inline JSC::MacroAssembler::Jump
        1162           47131 : FrameState::testInt32(Assembler::Condition cond, FrameEntry *fe)
        1163                 : {
        1164           47131 :     JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
        1165           47131 :     if (shouldAvoidTypeRemat(fe))
        1166            4565 :         return masm.testInt32(cond, addressOf(fe));
        1167           42566 :     return masm.testInt32(cond, tempRegForType(fe));
        1168                 : }
        1169                 :
        1170                 : inline JSC::MacroAssembler::Jump
        1171            4509 : FrameState::testPrimitive(Assembler::Condition cond, FrameEntry *fe)
        1172                 : {
        1173            4509 :     JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
        1174            4509 :     if (shouldAvoidTypeRemat(fe))
        1175             334 :         return masm.testPrimitive(cond, addressOf(fe));
        1176            4175 :     return masm.testPrimitive(cond, tempRegForType(fe));
        1177                 : }
        1178                 :
        1179                 : inline JSC::MacroAssembler::Jump
        1180           69429 : FrameState::testObject(Assembler::Condition cond, FrameEntry *fe)
        1181                 : {
        1182           69429 :     JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
        1183           69429 :     if (shouldAvoidTypeRemat(fe))
        1184            4296 :         return masm.testObject(cond, addressOf(fe));
        1185           65133 :     return masm.testObject(cond, tempRegForType(fe));
        1186                 : }
        1187                 :
        1188                 : inline JSC::MacroAssembler::Jump
        1189                 : FrameState::testGCThing(FrameEntry *fe)
        1190                 : {
        1191                 :     if (shouldAvoidTypeRemat(fe))
        1192                 :         return masm.testGCThing(addressOf(fe));
        1193                 :     return masm.testGCThing(tempRegForType(fe));
        1194                 : }
        1195                 :
        1196                 : inline JSC::MacroAssembler::Jump
        1197            8940 : FrameState::testDouble(Assembler::Condition cond, FrameEntry *fe)
        1198                 : {
        1199            8940 :     JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
        1200            8940 :     if (shouldAvoidTypeRemat(fe))
        1201               0 :         return masm.testDouble(cond, addressOf(fe));
        1202            8940 :     return masm.testDouble(cond, tempRegForType(fe));
        1203                 : }
        1204                 :
        1205                 : inline JSC::MacroAssembler::Jump
        1206           70526 : FrameState::testBoolean(Assembler::Condition cond, FrameEntry *fe)
        1207                 : {
        1208           70526 :     JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
        1209           70526 :     if (shouldAvoidTypeRemat(fe))
        1210           68459 :         return masm.testBoolean(cond, addressOf(fe));
        1211            2067 :     return masm.testBoolean(cond, tempRegForType(fe));
        1212                 : }
        1213                 :
        1214                 : inline JSC::MacroAssembler::Jump
        1215            1057 : FrameState::testString(Assembler::Condition cond, FrameEntry *fe)
        1216                 : {
        1217            1057 :     JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
        1218            1057 :     if (shouldAvoidTypeRemat(fe))
        1219               7 :         return masm.testString(cond, addressOf(fe));
        1220            1050 :     return masm.testString(cond, tempRegForType(fe));
        1221                 : }
        1222                 :
        1223                 : inline FrameEntry *
        1224         3261575 : FrameState::getOrTrack(uint32_t index)
        1225                 : {
        1226         3261575 :     FrameEntry *fe = &entries[index];
        1227         3261575 :     if (!fe->isTracked()) {
        1228          730370 :         addToTracker(fe);
        1229          730370 :         fe->resetSynced();
        1230                 :     }
        1231         3261575 :     return fe;
        1232                 : }
        1233                 :
        1234                 : inline FrameEntry *
        1235         1741192 : FrameState::getStack(uint32_t slot)
        1236                 : {
        1237         1741192 :     if (slot >= uint32_t(a->sp - a->spBase))
        1238            3451 :         return NULL;
        1239         1737741 :     return getOrTrack(uint32_t(a->spBase + slot - entries));
        1240                 : }
        1241                 :
        1242                 : inline FrameEntry *
        1243          719809 : FrameState::getLocal(uint32_t slot)
        1244                 : {
        1245          719809 :     JS_ASSERT(slot < a->script->nslots);
        1246          719809 :     return getOrTrack(uint32_t(a->locals + slot - entries));
        1247                 : }
        1248                 :
        1249                 : inline FrameEntry *
        1250          198923 : FrameState::getArg(uint32_t slot)
        1251                 : {
        1252          198923 :     JS_ASSERT(slot < a->script->function()->nargs);
        1253          198923 :     return getOrTrack(uint32_t(a->args + slot - entries));
        1254                 : }
        1255                 :
        1256                 : inline FrameEntry *
        1257          146017 : FrameState::getThis()
        1258                 : {
        1259          146017 :     return getOrTrack(uint32_t(a->this_ - entries));
        1260                 : }
        1261                 :
        1262                 : inline FrameEntry *
        1263          222912 : FrameState::getSlotEntry(uint32_t slot)
        1264                 : {
        1265          222912 :     JS_ASSERT(slot < analyze::TotalSlots(a->script));
        1266          222912 :     return getOrTrack(uint32_t(a->callee_ + slot - entries));
        1267                 : }
        1268                 :
        1269                 : inline FrameEntry *
        1270            3733 : FrameState::getCallee()
        1271                 : {
        1272                 :     // Callee can only be used in function code, and it's always an object.
        1273            3733 :     JS_ASSERT(a->script->function());
        1274            3733 :     FrameEntry *fe = a->callee_;
        1275            3733 :     if (!fe->isTracked()) {
        1276            3100 :         addToTracker(fe);
        1277            3100 :         fe->resetSynced();
        1278            3100 :         fe->setType(JSVAL_TYPE_OBJECT);
        1279                 :     }
        1280            3733 :     return fe;
        1281                 : }
        1282                 :
        1283                 : inline void
        1284          344335 : FrameState::unpinKilledReg(AnyRegisterID reg)
        1285                 : {
        1286          344335 :     regstate(reg).unpinUnsafe();
        1287          344335 :     freeRegs.putReg(reg);
        1288          344335 : }
        1289                 :
        1290                 : inline void
        1291        12944737 : FrameState::forgetAllRegs(FrameEntry *fe)
        1292                 : {
        1293        12944737 :     if (fe->isCopy())
        1294         4263824 :         return;
        1295         8680913 :     if (fe->type.inRegister())
        1296         1345173 :         forgetReg(fe->type.reg());
        1297         8680913 :     if (fe->data.inRegister())
        1298         1663863 :         forgetReg(fe->data.reg());
        1299         8680913 :     if (fe->data.inFPRegister())
        1300           12105 :         forgetReg(fe->data.fpreg());
        1301                 : }
        1302                 :
        1303                 : inline void
        1304          336834 : FrameState::swapInTracker(FrameEntry *lhs, FrameEntry *rhs)
        1305                 : {
        1306          336834 :     uint32_t li = lhs->trackerIndex();
        1307          336834 :     uint32_t ri = rhs->trackerIndex();
        1308          336834 :     JS_ASSERT(tracker[li] == lhs);
        1309          336834 :     JS_ASSERT(tracker[ri] == rhs);
        1310          336834 :     tracker.entries[ri] = lhs;
        1311          336834 :     tracker.entries[li] = rhs;
        1312          336834 :     lhs->index_ = ri;
        1313          336834 :     rhs->index_ = li;
        1314          336834 : }
        1315                 :
        1316                 : inline void
        1317          365136 : FrameState::dup()
        1318                 : {
        1319          365136 :     dupAt(-1);
        1320          365136 : }
        1321                 :
        1322                 : inline void
        1323          358296 : FrameState::dup2()
        1324                 : {
        1325          358296 :     FrameEntry *lhs = peek(-2);
        1326          358296 :     FrameEntry *rhs = peek(-1);
        1327          358296 :     pushCopyOf(lhs);
        1328          358296 :     pushCopyOf(rhs);
        1329          358296 : }
        1330                 :
        1331                 : inline void
        1332         2513030 : FrameState::dupAt(int32_t n)
        1333                 : {
        1334         2513030 :     JS_ASSERT(n < 0);
        1335         2513030 :     FrameEntry *fe = peek(n);
        1336         2513030 :     pushCopyOf(fe);
        1337         2513030 : }
        1338                 :
        1339                 : inline void
        1340             240 : FrameState::syncAt(int32_t n)
        1341                 : {
        1342             240 :     JS_ASSERT(n < 0);
        1343             240 :     FrameEntry *fe = peek(n);
        1344             240 :     syncFe(fe);
        1345             240 : }
        1346                 :
        1347                 : inline void
        1348          432200 : FrameState::pushLocal(uint32_t n)
        1349                 : {
        1350          432200 :     FrameEntry *fe = getLocal(n);
        1351          432200 :     if (!a->analysis->slotEscapes(analyze::LocalSlot(a->script, n))) {
        1352          178894 :         pushCopyOf(fe);
        1353                 :     } else {
        1354                 : #ifdef DEBUG
        1355                 :         /*
        1356                 :          * We really want to assert on local variables, but in the presence of
        1357                 :          * SETLOCAL equivocation of stack slots, and let expressions, just
        1358                 :          * weakly assert on the fixed local vars.
        1359                 :          */
        1360          253306 :         if (fe->isTracked() && n < a->script->nfixed)
        1361          204544 :             JS_ASSERT(fe->data.inMemory());
        1362                 : #endif
        1363          253306 :         if (n >= a->script->nfixed)
        1364           48762 :             syncFe(fe);
        1365          253306 :         JSValueType type = fe->isTypeKnown() ? fe->getKnownType() : JSVAL_TYPE_UNKNOWN;
        1366          253306 :         push(addressOf(fe), type);
        1367                 :     }
        1368          432200 : }
        1369                 :
        1370                 : inline void
        1371          194167 : FrameState::pushArg(uint32_t n)
        1372                 : {
        1373          194167 :     FrameEntry *fe = getArg(n);
        1374          194167 :     if (!a->analysis->slotEscapes(analyze::ArgSlot(n))) {
        1375           94792 :         pushCopyOf(fe);
        1376                 :     } else {
        1377                 : #ifdef DEBUG
        1378           99375 :         if (fe->isTracked())
        1379           99375 :             JS_ASSERT(fe->data.inMemory());
        1380                 : #endif
        1381           99375 :         JSValueType type = fe->isTypeKnown() ? fe->getKnownType() : JSVAL_TYPE_UNKNOWN;
        1382           99375 :         push(addressOf(fe), type);
        1383                 :     }
        1384          194167 : }
        1385                 :
        1386                 : inline void
        1387            3733 : FrameState::pushCallee()
        1388                 : {
        1389            3733 :     FrameEntry *fe = getCallee();
        1390            3733 :     pushCopyOf(fe);
        1391            3733 : }
        1392                 :
        1393                 : inline void
        1394          107788 : FrameState::pushThis()
        1395                 : {
        1396          107788 :     FrameEntry *fe = getThis();
        1397          107788 :     pushCopyOf(fe);
        1398          107788 : }
        1399                 :
        1400                 : void
        1401           35416 : FrameState::learnThisIsObject(bool unsync)
        1402                 : {
        1403                 :     // If the 'this' object is a copy, this must be an inline frame, in which
        1404                 :     // case we will trigger recompilation if the 'this' entry isn't actually
        1405                 :     // an object (thus, it is OK to modify the backing directly).
        1406           35416 :     FrameEntry *fe = getThis();
        1407           35416 :     if (fe->isCopy())
        1408              41 :         fe = fe->copyOf();
        1409           35416 :     learnType(fe, JSVAL_TYPE_OBJECT, unsync);
        1410           35416 : }
        1411                 :
        1412                 : void
        1413             160 : FrameState::setThis(RegisterID reg)
        1414                 : {
        1415             160 :     FrameEntry *fe = getThis();
        1416             160 :     JS_ASSERT(!fe->isCopy());
        1417             160 :     learnType(fe, JSVAL_TYPE_OBJECT, reg);
        1418             160 : }
        1419                 :
        1420                 : void
        1421            1849 : FrameState::syncThis()
        1422                 : {
        1423            1849 :     FrameEntry *fe = getThis();
        1424            1849 :     syncFe(fe);
        1425            1849 : }
        1426                 :
        1427                 : inline bool
        1428          370299 : FrameState::isConstructorThis(const FrameEntry *fe) const
        1429                 : {
        1430          370299 :     return isThis(fe) && cc.constructing();
        1431                 : }
        1432                 :
        1433                 : inline void
        1434           28997 : FrameState::leaveBlock(uint32_t n)
        1435                 : {
        1436           28997 :     popn(n);
        1437           28997 : }
        1438                 :
        1439                 : inline void
        1440           21203 : FrameState::enterBlock(uint32_t n)
        1441                 : {
        1442                 :     /* expect that tracker has 0 entries, for now. */
        1443           21203 :     JS_ASSERT(!tracker.nentries);
        1444           21203 :     JS_ASSERT(uint32_t(a->sp + n - a->locals) <= a->script->nslots);
        1445                 :
        1446           21203 :     a->sp += n;
        1447           21203 : }
        1448                 :
        1449                 : inline void
        1450                 : FrameState::eviscerate(FrameEntry *fe)
        1451                 : {
        1452                 :     forgetAllRegs(fe);
        1453                 :     fe->resetUnsynced();
        1454                 : }
        1455                 :
        1456                 : inline StateRemat
        1457            5692 : FrameState::dataRematInfo(const FrameEntry *fe) const
        1458                 : {
        1459            5692 :     if (fe->isCopy())
        1460            2272 :         fe = fe->copyOf();
        1461                 :
        1462            5692 :     if (fe->data.inRegister())
        1463            4373 :         return StateRemat::FromRegister(fe->data.reg());
        1464                 :
        1465            1319 :     JS_ASSERT(fe->data.synced());
        1466            1319 :     return StateRemat::FromAddress(addressOf(fe));
        1467                 : }
        1468                 :
        1469                 : inline void
        1470          201211 : FrameState::giveOwnRegs(FrameEntry *fe)
        1471                 : {
        1472          201211 :     JS_ASSERT(!fe->isConstant());
        1473          201211 :     JS_ASSERT(fe == peek(-1));
        1474                 :
        1475          201211 :     if (!fe->isCopy())
        1476          201079 :         return;
        1477                 :
        1478             132 :     RegisterID data = copyDataIntoReg(fe);
        1479             132 :     if (fe->isTypeKnown()) {
        1480               0 :         JSValueType type = fe->getKnownType();
        1481               0 :         pop();
        1482               0 :         pushTypedPayload(type, data);
        1483                 :     } else {
        1484             132 :         RegisterID type = copyTypeIntoReg(fe);
        1485             132 :         pop();
        1486             132 :         pushRegs(type, data, JSVAL_TYPE_UNKNOWN);
        1487                 :     }
        1488                 : }
        1489                 :
        1490                 : inline void
        1491         1299118 : FrameState::loadDouble(RegisterID t, RegisterID d, FrameEntry *fe, FPRegisterID fpreg,
        1492                 :                        Assembler &masm) const
        1493                 : {
        1494                 : #ifdef JS_CPU_X86
        1495         1299118 :     masm.fastLoadDouble(d, t, fpreg);
        1496                 : #else
        1497                 :     loadDouble(fe, fpreg, masm);
        1498                 : #endif
        1499         1299118 : }
        1500                 :
        1501                 : inline bool
        1502           19838 : FrameState::tryFastDoubleLoad(FrameEntry *fe, FPRegisterID fpReg, Assembler &masm) const
        1503                 : {
        1504                 : #ifdef JS_CPU_X86
        1505           19838 :     if (!fe->isCopy() && fe->type.inRegister() && fe->data.inRegister()) {
        1506           12801 :         masm.fastLoadDouble(fe->data.reg(), fe->type.reg(), fpReg);
        1507           12801 :         return true;
        1508                 :     }
        1509                 : #endif
        1510            7037 :     return false;
        1511                 : }
        1512                 :
        1513                 : inline void
        1514           17023 : FrameState::loadDouble(FrameEntry *fe, FPRegisterID fpReg, Assembler &masm) const
        1515                 : {
        1516           17023 :     if (fe->isCopy()) {
        1517            2815 :         FrameEntry *backing = fe->copyOf();
        1518            2815 :         if (tryFastDoubleLoad(fe, fpReg, masm))
        1519               0 :             return;
        1520            2815 :         fe = backing;
        1521                 :     }
        1522                 :
        1523           17023 :     if (tryFastDoubleLoad(fe, fpReg, masm))
        1524           12801 :         return;
        1525                 :
        1526            4222 :     ensureFeSynced(fe, masm);
        1527            4222 :     masm.loadDouble(addressOf(fe), fpReg);
        1528                 : }
        1529                 :
        1530                 : class PinRegAcrossSyncAndKill
        1531                 : {
        1532                 :     typedef JSC::MacroAssembler::RegisterID RegisterID;
        1533                 :     FrameState &frame;
        1534                 :     MaybeRegisterID maybeReg;
        1535                 :   public:
        1536          159050 :     PinRegAcrossSyncAndKill(FrameState &frame, RegisterID reg)
        1537          159050 :       : frame(frame), maybeReg(reg)
        1538                 :     {
        1539          159050 :         frame.pinReg(reg);
        1540          159050 :     }
        1541          150793 :     PinRegAcrossSyncAndKill(FrameState &frame, MaybeRegisterID maybeReg)
        1542          150793 :       : frame(frame), maybeReg(maybeReg)
        1543                 :     {
        1544          150793 :         if (maybeReg.isSet())
        1545          112877 :             frame.pinReg(maybeReg.reg());
        1546          150793 :     }
        1547          309843 :     ~PinRegAcrossSyncAndKill() {
        1548          309843 :         if (maybeReg.isSet())
        1549          271927 :             frame.unpinKilledReg(maybeReg.reg());
        1550          309843 :     }
        1551                 : };
        1552                 :
        1553                 : } /* namespace mjit */
        1554                 : } /* namespace js */
        1555                 :
        1556                 : #endif /* include */
        1557                 :

Generated by: LCOV version 1.7