LCOV - code coverage report
Current view: directory - js/src/methodjit - RematInfo.h (source / functions) Found Hit Coverage
Test: app.info Lines: 146 145 99.3 %
Date: 2012-06-02 Functions: 51 51 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 jsjaeger_remat_h__ && defined JS_METHODJIT
      41                 : #define jsjaeger_remat_h__
      42                 : 
      43                 : #include "jscntxt.h"
      44                 : #include "MachineRegs.h"
      45                 : #include "assembler/assembler/MacroAssembler.h"
      46                 : #include "vm/Stack.h"
      47                 : 
      48                 : namespace js {
      49                 : namespace mjit {
      50                 : 
      51                 : // Lightweight, union-able components of FrameEntry.
      52                 : struct StateRemat {
      53                 :     typedef JSC::MacroAssembler::RegisterID RegisterID;
      54                 :     typedef JSC::MacroAssembler::Address Address;
      55                 : 
      56                 :     static const int32_t CONSTANT = -int(UINT16_LIMIT * sizeof(Value));
      57                 : 
      58                 :     // This union encodes the fastest rematerialization of a non-constant
      59                 :     // value. The |offset| field can be used to recover information
      60                 :     // without this struct's helpers:
      61                 :     //  1) A value in (CONSTANT, 0) is an argument slot.
      62                 :     //  2) A value in [0, fp) is a register ID.
      63                 :     //  3) A value in [fp, inf) is a local slot.
      64                 :     union {
      65                 :         RegisterID  reg_;
      66                 :         int32_t     offset_;
      67                 :     };
      68                 : 
      69          500164 :     static StateRemat FromInt32(int32_t i32) {
      70                 :         StateRemat sr;
      71          500164 :         sr.offset_ = i32;
      72                 :         return sr;
      73                 :     }
      74          154845 :     static StateRemat FromRegister(RegisterID reg) {
      75                 :         StateRemat sr;
      76          154845 :         sr.reg_ = reg;
      77          154845 :         JS_ASSERT(sr.inRegister());
      78                 :         return sr;
      79                 :     }
      80            1319 :     static StateRemat FromAddress(Address address) {
      81            1319 :         JS_ASSERT(address.base == JSFrameReg);
      82                 :         StateRemat sr;
      83            1319 :         sr.offset_ = address.offset;
      84            1319 :         JS_ASSERT(sr.inMemory());
      85                 :         return sr;
      86                 :     }
      87                 : 
      88                 :     // Minimum number of bits needed to compactly store the int32_t
      89                 :     // representation in a struct or union. This prevents bloating the IC
      90                 :     // structs by an extra 8 bytes in some cases. 16 bits are needed to encode
      91                 :     // the largest local:
      92                 :     //   ((UINT16_LIMIT - 1) * sizeof(Value) + sizeof(StackFrame),
      93                 :     // And an extra bit for the sign on arguments.
      94                 : #define MIN_STATE_REMAT_BITS        21
      95                 : 
      96                 :     bool isConstant() const { return offset_ == CONSTANT; }
      97          654666 :     bool inRegister() const { return offset_ >= 0 &&
      98          654666 :                                      offset_ <= int32_t(JSC::MacroAssembler::TotalRegisters); }
      99            2841 :     bool inMemory() const {
     100                 :         return offset_ >= int32_t(sizeof(StackFrame)) ||
     101            2841 :                offset_ < 0;
     102                 :     }
     103                 : 
     104          161856 :     int32_t toInt32() const { return offset_; }
     105             343 :     Address address() const {
     106             343 :         JS_ASSERT(inMemory());
     107             343 :         return Address(JSFrameReg, offset_);
     108                 :     }
     109          499821 :     RegisterID reg() const {
     110          499821 :         JS_ASSERT(inRegister());
     111          499821 :         return reg_;
     112                 :     }
     113                 : };
     114                 : 
     115                 : /* Lightweight version of FrameEntry. */
     116                 : struct ValueRemat {
     117                 :     typedef JSC::MacroAssembler::RegisterID RegisterID;
     118                 :     typedef JSC::MacroAssembler::FPRegisterID FPRegisterID;
     119                 :     union {
     120                 :         struct {
     121                 :             union {
     122                 :                 int32_t     typeRemat_;
     123                 :                 JSValueType knownType_;
     124                 :             } type;
     125                 :             int32_t dataRemat_   : MIN_STATE_REMAT_BITS;
     126                 :             bool    isTypeKnown_ : 1;
     127                 :         } s;
     128                 :         jsval v_;
     129                 :         FPRegisterID fpreg_;
     130                 :     } u;
     131                 :     bool isConstant_    : 1;
     132                 :     bool isFPRegister_  : 1;
     133                 :     bool isDataSynced   : 1;
     134                 :     bool isTypeSynced   : 1;
     135                 : 
     136           34416 :     static ValueRemat FromConstant(const Value &v) {
     137                 :         ValueRemat vr;
     138           34416 :         vr.isConstant_ = true;
     139           34416 :         vr.isFPRegister_ = false;
     140           34416 :         vr.u.v_ = v;
     141                 :         return vr;
     142                 :     }
     143            1462 :     static ValueRemat FromFPRegister(FPRegisterID fpreg) {
     144                 :         ValueRemat vr;
     145            1462 :         vr.isConstant_ = false;
     146            1462 :         vr.isFPRegister_ = true;
     147            1462 :         vr.u.fpreg_ = fpreg;
     148                 :         return vr;
     149                 :     }
     150           34516 :     static ValueRemat FromKnownType(JSValueType type, RegisterID dataReg) {
     151                 :         ValueRemat vr;
     152           34516 :         vr.isConstant_ = false;
     153           34516 :         vr.isFPRegister_ = false;
     154           34516 :         vr.u.s.type.knownType_ = type;
     155           34516 :         vr.u.s.isTypeKnown_ = true;
     156           34516 :         vr.u.s.dataRemat_ = StateRemat::FromRegister(dataReg).toInt32();
     157                 : 
     158                 :         // Assert bitfields are okay.
     159           34516 :         JS_ASSERT(vr.dataReg() == dataReg);
     160                 :         return vr;
     161                 :     }
     162           57978 :     static ValueRemat FromRegisters(RegisterID typeReg, RegisterID dataReg) {
     163                 :         ValueRemat vr;
     164           57978 :         vr.isConstant_ = false;
     165           57978 :         vr.isFPRegister_ = false;
     166           57978 :         vr.u.s.isTypeKnown_ = false;
     167           57978 :         vr.u.s.type.typeRemat_ = StateRemat::FromRegister(typeReg).toInt32();
     168           57978 :         vr.u.s.dataRemat_ = StateRemat::FromRegister(dataReg).toInt32();
     169                 : 
     170                 :         // Assert bitfields are okay.
     171           57978 :         JS_ASSERT(vr.dataReg() == dataReg);
     172           57978 :         JS_ASSERT(vr.typeReg() == typeReg);
     173                 :         return vr;
     174                 :     }
     175                 : 
     176            2841 :     FPRegisterID fpReg() const {
     177            2841 :         JS_ASSERT(isFPRegister());
     178            2841 :         return u.fpreg_;
     179                 :     }
     180          285951 :     RegisterID dataReg() const {
     181          285951 :         JS_ASSERT(!isConstant() && !isFPRegister());
     182          285951 :         return dataRemat().reg();
     183                 :     }
     184          213034 :     RegisterID typeReg() const {
     185          213034 :         JS_ASSERT(!isTypeKnown());
     186          213034 :         return typeRemat().reg();
     187                 :     }
     188                 : 
     189         1606856 :     bool isConstant() const { return isConstant_; }
     190         1172455 :     bool isFPRegister() const { return isFPRegister_; }
     191          718639 :     bool isTypeKnown() const { return isConstant() || isFPRegister() || u.s.isTypeKnown_; }
     192                 : 
     193          285951 :     StateRemat dataRemat() const {
     194          285951 :         JS_ASSERT(!isConstant());
     195          285951 :         return StateRemat::FromInt32(u.s.dataRemat_);
     196                 :     }
     197          213034 :     StateRemat typeRemat() const {
     198          213034 :         JS_ASSERT(!isTypeKnown());
     199          213034 :         return StateRemat::FromInt32(u.s.type.typeRemat_);
     200                 :     }
     201           39126 :     Value value() const {
     202           39126 :         JS_ASSERT(isConstant());
     203           39126 :         return u.v_;
     204                 :     }
     205           49734 :     JSValueType knownType() const {
     206           49734 :         JS_ASSERT(isTypeKnown());
     207           49734 :         if (isConstant()) {
     208           10491 :             const Value v = value();
     209           10491 :             if (v.isDouble())
     210             221 :                 return JSVAL_TYPE_DOUBLE;
     211           10270 :             return v.extractNonDoubleType();
     212                 :         }
     213           39243 :         if (isFPRegister())
     214               0 :             return JSVAL_TYPE_DOUBLE;
     215           39243 :         return u.s.type.knownType_;
     216                 :     }
     217           11673 :     bool isType(JSValueType type_) const {
     218           11673 :         return isTypeKnown() && knownType() == type_;
     219                 :     }
     220                 : };
     221                 : 
     222                 : /*
     223                 :  * Describes how to rematerialize a value during compilation.
     224                 :  */
     225                 : struct RematInfo {
     226                 :     typedef JSC::MacroAssembler::RegisterID RegisterID;
     227                 :     typedef JSC::MacroAssembler::FPRegisterID FPRegisterID;
     228                 : 
     229                 :     enum SyncState {
     230                 :         SYNCED,
     231                 :         UNSYNCED
     232                 :     };
     233                 : 
     234                 :     enum RematType {
     235                 :         TYPE,
     236                 :         DATA
     237                 :     };
     238                 : 
     239                 :     /* Physical location. */
     240                 :     enum PhysLoc {
     241                 :         /*
     242                 :          * Backing bits are in memory. No fast remat.
     243                 :          */
     244                 :         PhysLoc_Memory = 0,
     245                 : 
     246                 :         /* Backing bits are known at compile time. */
     247                 :         PhysLoc_Constant,
     248                 : 
     249                 :         /* Backing bits are in a general purpose register. */
     250                 :         PhysLoc_Register,
     251                 : 
     252                 :         /* Backing bits are part of a floating point register. */
     253                 :         PhysLoc_FPRegister,
     254                 : 
     255                 :         /* Backing bits are invalid/unknown. */
     256                 :         PhysLoc_Invalid
     257                 :     };
     258                 : 
     259        10459409 :     void setRegister(RegisterID reg) {
     260        10459409 :         reg_ = reg;
     261        10459409 :         location_ = PhysLoc_Register;
     262        10459409 :     }
     263                 : 
     264       135110621 :     RegisterID reg() const {
     265       135110621 :         JS_ASSERT(inRegister());
     266       135110621 :         return reg_;
     267                 :     }
     268                 : 
     269           23702 :     void setFPRegister(FPRegisterID reg) {
     270           23702 :         fpreg_ = reg;
     271           23702 :         location_ = PhysLoc_FPRegister;
     272           23702 :     }
     273                 : 
     274          473919 :     FPRegisterID fpreg() const {
     275          473919 :         JS_ASSERT(inFPRegister());
     276          473919 :         return fpreg_;
     277                 :     }
     278                 : 
     279        11326948 :     void setMemory() {
     280        11326948 :         location_ = PhysLoc_Memory;
     281        11326948 :         sync_ = SYNCED;
     282        11326948 :     }
     283                 : 
     284                 : #ifdef DEBUG
     285        65645894 :     void invalidate() {
     286        65645894 :         location_ = PhysLoc_Invalid;
     287        65645894 :     }
     288                 : #else
     289                 :     void invalidate() {}
     290                 : #endif
     291                 : 
     292         7349451 :     void setConstant() { location_ = PhysLoc_Constant; }
     293                 : 
     294       166848659 :     bool isConstant() const {
     295       166848659 :         JS_ASSERT(location_ != PhysLoc_Invalid);
     296       166848659 :         return location_ == PhysLoc_Constant;
     297                 :     }
     298                 : 
     299      1109781667 :     bool inRegister() const {
     300      1109781667 :         JS_ASSERT(location_ != PhysLoc_Invalid);
     301      1109781667 :         return location_ == PhysLoc_Register;
     302                 :     }
     303                 : 
     304       449677916 :     bool inFPRegister() const {
     305       449677916 :         JS_ASSERT(location_ != PhysLoc_Invalid);
     306       449677916 :         return location_ == PhysLoc_FPRegister;
     307                 :     }
     308                 : 
     309        15798178 :     bool inMemory() const {
     310        15798178 :         JS_ASSERT(location_ != PhysLoc_Invalid);
     311        15798178 :         return location_ == PhysLoc_Memory;
     312                 :     }
     313                 : 
     314        74391675 :     bool synced() const { return sync_ == SYNCED; }
     315         6109344 :     void sync() {
     316         6109344 :         JS_ASSERT(!synced());
     317         6109344 :         sync_ = SYNCED;
     318         6109344 :     }
     319        25270393 :     void unsync() {
     320        25270393 :         sync_ = UNSYNCED;
     321        25270393 :     }
     322                 : 
     323          973326 :     void inherit(const RematInfo &other) {
     324                 :         JS_STATIC_ASSERT(sizeof(RegisterID) == sizeof(FPRegisterID));
     325          973326 :         reg_ = other.reg_;
     326          973326 :         location_ = other.location_;
     327          973326 :     }
     328                 : 
     329                 :   private:
     330                 :     union {
     331                 :         /* Set if location is PhysLoc_Register. */
     332                 :         RegisterID reg_;
     333                 : 
     334                 :         /*
     335                 :          * Set if location is PhysLoc_FPRegister.  This must be the data for a FE,
     336                 :          * and the known type is JSVAL_TYPE_DOUBLE.
     337                 :          */
     338                 :         FPRegisterID fpreg_;
     339                 :     };
     340                 : 
     341                 :     /* Remat source. */
     342                 :     PhysLoc location_;
     343                 : 
     344                 :     /* Sync state. */
     345                 :     SyncState sync_;
     346                 : };
     347                 : 
     348                 : template <class T>
     349                 : class MaybeRegister {
     350                 :   public:
     351         4840942 :     MaybeRegister()
     352         4840942 :       : reg_((T)0), set(false)
     353         4840942 :     { }
     354                 : 
     355          270824 :     MaybeRegister(T reg)
     356          270824 :       : reg_(reg), set(true)
     357          270824 :     { }
     358                 : 
     359        10832865 :     inline T reg() const { JS_ASSERT(set); return reg_; }
     360         3199430 :     inline void setReg(T r) { reg_ = r; set = true; }
     361         6744310 :     inline bool isSet() const { return set; }
     362                 : 
     363          164322 :     MaybeRegister<T> & operator =(const MaybeRegister<T> &other) {
     364          164322 :         set = other.set;
     365          164322 :         reg_ = other.reg_;
     366          164322 :         return *this;
     367                 :     }
     368                 : 
     369         3197076 :     MaybeRegister<T> & operator =(T r) {
     370         3197076 :         setReg(r);
     371         3197076 :         return *this;
     372                 :     }
     373                 : 
     374                 :   private:
     375                 :     T reg_;
     376                 :     bool set;
     377                 : };
     378                 : 
     379                 : typedef MaybeRegister<JSC::MacroAssembler::RegisterID> MaybeRegisterID;
     380                 : typedef MaybeRegister<JSC::MacroAssembler::FPRegisterID> MaybeFPRegisterID;
     381                 : 
     382                 : class MaybeJump {
     383                 :     typedef JSC::MacroAssembler::Jump Jump;
     384                 :   public:
     385         8039523 :     MaybeJump()
     386         8039523 :       : set(false)
     387         8039523 :     { }
     388                 : 
     389           35568 :     inline Jump getJump() const { JS_ASSERT(set); return jump; }
     390         4111735 :     inline Jump get() const { JS_ASSERT(set); return jump; }
     391         4127031 :     inline void setJump(const Jump &j) { jump = j; set = true; }
     392         6628684 :     inline bool isSet() const { return set; }
     393                 : 
     394         3906684 :     inline MaybeJump &operator=(Jump j) { setJump(j); return *this; }
     395                 : 
     396                 :   private:
     397                 :     Jump jump;
     398                 :     bool set;
     399                 : };
     400                 : 
     401                 : } /* namespace mjit */
     402                 : } /* namespace js */
     403                 : 
     404                 : #endif
     405                 : 

Generated by: LCOV version 1.7