LCOV - app.info - js/src/methodjit/RematInfo.h

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-04-07 | 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          341492 :     static StateRemat FromInt32(int32_t i32) {
          70                 :         StateRemat sr;
          71          341492 :         sr.offset_ = i32;
          72                 :         return sr;
          73                 :     }
          74          112918 :     static StateRemat FromRegister(RegisterID reg) {
          75                 :         StateRemat sr;
          76          112918 :         sr.reg_ = reg;
          77          112918 :         JS_ASSERT(sr.inRegister());
          78                 :         return sr;
          79                 :     }
          80            1325 :     static StateRemat FromAddress(Address address) {
          81            1325 :         JS_ASSERT(address.base == JSFrameReg);
          82                 :         StateRemat sr;
          83            1325 :         sr.offset_ = address.offset;
          84            1325 :         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          454067 :     bool inRegister() const { return offset_ >= 0 &&
          98          454067 :                                      offset_ <= int32_t(JSC::MacroAssembler::TotalRegisters); }
          99            2847 :     bool inMemory() const {
         100                 :         return offset_ >= int32_t(sizeof(StackFrame)) ||
         101            2847 :                offset_ < 0;
         102                 :     }
         103                 :
         104          119946 :     int32_t toInt32() const { return offset_; }
         105             343 :     Address address() const {
         106             343 :         JS_ASSERT(inMemory());
         107             343 :         return Address(JSFrameReg, offset_);
         108                 :     }
         109          341149 :     RegisterID reg() const {
         110          341149 :         JS_ASSERT(inRegister());
         111          341149 :         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           27339 :     static ValueRemat FromConstant(const Value &v) {
         137                 :         ValueRemat vr;
         138           27339 :         vr.isConstant_ = true;
         139           27339 :         vr.isFPRegister_ = false;
         140           27339 :         vr.u.v_ = v;
         141                 :         return vr;
         142                 :     }
         143            1463 :     static ValueRemat FromFPRegister(FPRegisterID fpreg) {
         144                 :         ValueRemat vr;
         145            1463 :         vr.isConstant_ = false;
         146            1463 :         vr.isFPRegister_ = true;
         147            1463 :         vr.u.fpreg_ = fpreg;
         148                 :         return vr;
         149                 :     }
         150           42714 :     static ValueRemat FromKnownType(JSValueType type, RegisterID dataReg) {
         151                 :         ValueRemat vr;
         152           42714 :         vr.isConstant_ = false;
         153           42714 :         vr.isFPRegister_ = false;
         154           42714 :         vr.u.s.type.knownType_ = type;
         155           42714 :         vr.u.s.isTypeKnown_ = true;
         156           42714 :         vr.u.s.dataRemat_ = StateRemat::FromRegister(dataReg).toInt32();
         157                 :
         158                 :         // Assert bitfields are okay.
         159           42714 :         JS_ASSERT(vr.dataReg() == dataReg);
         160                 :         return vr;
         161                 :     }
         162           32913 :     static ValueRemat FromRegisters(RegisterID typeReg, RegisterID dataReg) {
         163                 :         ValueRemat vr;
         164           32913 :         vr.isConstant_ = false;
         165           32913 :         vr.isFPRegister_ = false;
         166           32913 :         vr.u.s.isTypeKnown_ = false;
         167           32913 :         vr.u.s.type.typeRemat_ = StateRemat::FromRegister(typeReg).toInt32();
         168           32913 :         vr.u.s.dataRemat_ = StateRemat::FromRegister(dataReg).toInt32();
         169                 :
         170                 :         // Assert bitfields are okay.
         171           32913 :         JS_ASSERT(vr.dataReg() == dataReg);
         172           32913 :         JS_ASSERT(vr.typeReg() == typeReg);
         173                 :         return vr;
         174                 :     }
         175                 :
         176            2843 :     FPRegisterID fpReg() const {
         177            2843 :         JS_ASSERT(isFPRegister());
         178            2843 :         return u.fpreg_;
         179                 :     }
         180          228662 :     RegisterID dataReg() const {
         181          228662 :         JS_ASSERT(!isConstant() && !isFPRegister());
         182          228662 :         return dataRemat().reg();
         183                 :     }
         184          111651 :     RegisterID typeReg() const {
         185          111651 :         JS_ASSERT(!isTypeKnown());
         186          111651 :         return typeRemat().reg();
         187                 :     }
         188                 :
         189         1182007 :     bool isConstant() const { return isConstant_; }
         190          856988 :     bool isFPRegister() const { return isFPRegister_; }
         191          477463 :     bool isTypeKnown() const { return isConstant() || isFPRegister() || u.s.isTypeKnown_; }
         192                 :
         193          228662 :     StateRemat dataRemat() const {
         194          228662 :         JS_ASSERT(!isConstant());
         195          228662 :         return StateRemat::FromInt32(u.s.dataRemat_);
         196                 :     }
         197          111651 :     StateRemat typeRemat() const {
         198          111651 :         JS_ASSERT(!isTypeKnown());
         199          111651 :         return StateRemat::FromInt32(u.s.type.typeRemat_);
         200                 :     }
         201           21930 :     Value value() const {
         202           21930 :         JS_ASSERT(isConstant());
         203           21930 :         return u.v_;
         204                 :     }
         205           50460 :     JSValueType knownType() const {
         206           50460 :         JS_ASSERT(isTypeKnown());
         207           50460 :         if (isConstant()) {
         208            3609 :             const Value v = value();
         209            3609 :             if (v.isDouble())
         210             221 :                 return JSVAL_TYPE_DOUBLE;
         211            3388 :             return v.extractNonDoubleType();
         212                 :         }
         213           46851 :         if (isFPRegister())
         214               0 :             return JSVAL_TYPE_DOUBLE;
         215           46851 :         return u.s.type.knownType_;
         216                 :     }
         217            1003 :     bool isType(JSValueType type_) const {
         218            1003 :         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         3563460 :     void setRegister(RegisterID reg) {
         260         3563460 :         reg_ = reg;
         261         3563460 :         location_ = PhysLoc_Register;
         262         3563460 :     }
         263                 :
         264        59150309 :     RegisterID reg() const {
         265        59150309 :         JS_ASSERT(inRegister());
         266        59150309 :         return reg_;
         267                 :     }
         268                 :
         269           23702 :     void setFPRegister(FPRegisterID reg) {
         270           23702 :         fpreg_ = reg;
         271           23702 :         location_ = PhysLoc_FPRegister;
         272           23702 :     }
         273                 :
         274          473654 :     FPRegisterID fpreg() const {
         275          473654 :         JS_ASSERT(inFPRegister());
         276          473654 :         return fpreg_;
         277                 :     }
         278                 :
         279         4927172 :     void setMemory() {
         280         4927172 :         location_ = PhysLoc_Memory;
         281         4927172 :         sync_ = SYNCED;
         282         4927172 :     }
         283                 :
         284                 : #ifdef DEBUG
         285        20415484 :     void invalidate() {
         286        20415484 :         location_ = PhysLoc_Invalid;
         287        20415484 :     }
         288                 : #else
         289                 :     void invalidate() {}
         290                 : #endif
         291                 :
         292         3542238 :     void setConstant() { location_ = PhysLoc_Constant; }
         293                 :
         294        75486938 :     bool isConstant() const {
         295        75486938 :         JS_ASSERT(location_ != PhysLoc_Invalid);
         296        75486938 :         return location_ == PhysLoc_Constant;
         297                 :     }
         298                 :
         299       920729061 :     bool inRegister() const {
         300       920729061 :         JS_ASSERT(location_ != PhysLoc_Invalid);
         301       920729061 :         return location_ == PhysLoc_Register;
         302                 :     }
         303                 :
         304       412879474 :     bool inFPRegister() const {
         305       412879474 :         JS_ASSERT(location_ != PhysLoc_Invalid);
         306       412879474 :         return location_ == PhysLoc_FPRegister;
         307                 :     }
         308                 :
         309         5287891 :     bool inMemory() const {
         310         5287891 :         JS_ASSERT(location_ != PhysLoc_Invalid);
         311         5287891 :         return location_ == PhysLoc_Memory;
         312                 :     }
         313                 :
         314        30331898 :     bool synced() const { return sync_ == SYNCED; }
         315         2007153 :     void sync() {
         316         2007153 :         JS_ASSERT(!synced());
         317         2007153 :         sync_ = SYNCED;
         318         2007153 :     }
         319         7685554 :     void unsync() {
         320         7685554 :         sync_ = UNSYNCED;
         321         7685554 :     }
         322                 :
         323           89635 :     void inherit(const RematInfo &other) {
         324                 :         JS_STATIC_ASSERT(sizeof(RegisterID) == sizeof(FPRegisterID));
         325           89635 :         reg_ = other.reg_;
         326           89635 :         location_ = other.location_;
         327           89635 :     }
         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         2967756 :     MaybeRegister()
         352         2967756 :       : reg_((T)0), set(false)
         353         2967756 :     { }
         354                 :
         355          178131 :     MaybeRegister(T reg)
         356          178131 :       : reg_(reg), set(true)
         357          178131 :     { }
         358                 :
         359         8016089 :     inline T reg() const { JS_ASSERT(set); return reg_; }
         360         2118494 :     inline void setReg(T r) { reg_ = r; set = true; }
         361         4265648 :     inline bool isSet() const { return set; }
         362                 :
         363          107557 :     MaybeRegister<T> & operator =(const MaybeRegister<T> &other) {
         364          107557 :         set = other.set;
         365          107557 :         reg_ = other.reg_;
         366          107557 :         return *this;
         367                 :     }
         368                 :
         369         2116159 :     MaybeRegister<T> & operator =(T r) {
         370         2116159 :         setReg(r);
         371         2116159 :         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         4773250 :     MaybeJump()
         386         4773250 :       : set(false)
         387         4773250 :     { }
         388                 :
         389           19238 :     inline Jump getJump() const { JS_ASSERT(set); return jump; }
         390         2793667 :     inline Jump get() const { JS_ASSERT(set); return jump; }
         391         2792681 :     inline void setJump(const Jump &j) { jump = j; set = true; }
         392         3897256 :     inline bool isSet() const { return set; }
         393                 :
         394         2575361 :     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