1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=4 sw=4 et tw=99:
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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
17 * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
20 * The Initial Developer of the Original Code is
21 * Brendan Eich <brendan@mozilla.org>
24 * David Anderson <danderson@mozilla.com>
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.
38 * ***** END LICENSE BLOCK ***** */
40 #if !defined jsjaeger_remat_h__ && defined JS_METHODJIT
41 #define jsjaeger_remat_h__
44 #include "MachineRegs.h"
45 #include "assembler/assembler/MacroAssembler.h"
50 // Lightweight, union-able components of FrameEntry.
52 typedef JSC::MacroAssembler::RegisterID RegisterID;
53 typedef JSC::MacroAssembler::Address Address;
55 static const int32 CONSTANT = -int(UINT16_LIMIT * sizeof(Value));
57 // This union encodes the fastest rematerialization of a non-constant
58 // value. The |offset| field can be used to recover information
59 // without this struct's helpers:
60 // 1) A value in (CONSTANT, 0) is an argument slot.
61 // 2) A value in [0, fp) is a register ID.
62 // 3) A value in [fp, inf) is a local slot.
68 static StateRemat FromInt32(int32 i32) {
73 static StateRemat FromRegister(RegisterID reg) {
76 JS_ASSERT(sr.inRegister());
79 static StateRemat FromAddress(Address address) {
80 JS_ASSERT(address.base == JSFrameReg);
82 sr.offset_ = address.offset;
83 JS_ASSERT(sr.inMemory());
87 // Minimum number of bits needed to compactly store the int32
88 // representation in a struct or union. This prevents bloating the IC
89 // structs by an extra 8 bytes in some cases. 16 bits are needed to encode
91 // ((UINT16_LIMIT - 1) * sizeof(Value) + sizeof(JSStackFrame),
92 // And an extra bit for the sign on arguments.
93 #define MIN_STATE_REMAT_BITS 21
95 bool isConstant() const { return offset_ == CONSTANT; }
96 bool inRegister() const { return offset_ >= 0 &&
97 offset_ <= int32(JSC::MacroAssembler::TotalRegisters); }
98 bool inMemory() const {
99 return offset_ >= int32(sizeof(JSStackFrame)) ||
103 int32 toInt32() const { return offset_; }
104 Address address() const {
105 JS_ASSERT(inMemory());
106 return Address(JSFrameReg, offset_);
108 RegisterID reg() const {
109 JS_ASSERT(inRegister());
114 /* Lightweight version of FrameEntry. */
116 typedef JSC::MacroAssembler::RegisterID RegisterID;
121 JSValueType knownType_;
123 int32 dataRemat_ : MIN_STATE_REMAT_BITS;
124 bool isTypeKnown_ : 1;
128 bool isConstant_ : 1;
129 bool isDataSynced : 1;
130 bool isTypeSynced : 1;
132 static ValueRemat FromConstant(const Value &v) {
134 vr.isConstant_ = true;
135 vr.u.v_ = Jsvalify(v);
138 static ValueRemat FromKnownType(JSValueType type, RegisterID dataReg) {
140 vr.isConstant_ = false;
141 vr.u.s.type.knownType_ = type;
142 vr.u.s.isTypeKnown_ = true;
143 vr.u.s.dataRemat_ = StateRemat::FromRegister(dataReg).toInt32();
145 // Assert bitfields are okay.
146 JS_ASSERT(vr.dataReg() == dataReg);
149 static ValueRemat FromRegisters(RegisterID typeReg, RegisterID dataReg) {
151 vr.isConstant_ = false;
152 vr.u.s.isTypeKnown_ = false;
153 vr.u.s.type.typeRemat_ = StateRemat::FromRegister(typeReg).toInt32();
154 vr.u.s.dataRemat_ = StateRemat::FromRegister(dataReg).toInt32();
156 // Assert bitfields are okay.
157 JS_ASSERT(vr.dataReg() == dataReg);
158 JS_ASSERT(vr.typeReg() == typeReg);
162 RegisterID dataReg() const {
163 JS_ASSERT(!isConstant());
164 return dataRemat().reg();
166 RegisterID typeReg() const {
167 JS_ASSERT(!isTypeKnown());
168 return typeRemat().reg();
171 bool isConstant() const { return isConstant_; }
172 bool isTypeKnown() const { return isConstant() || u.s.isTypeKnown_; }
174 StateRemat dataRemat() const {
175 JS_ASSERT(!isConstant());
176 return StateRemat::FromInt32(u.s.dataRemat_);
178 StateRemat typeRemat() const {
179 JS_ASSERT(!isTypeKnown());
180 return StateRemat::FromInt32(u.s.type.typeRemat_);
182 Value value() const {
183 JS_ASSERT(isConstant());
184 return Valueify(u.v_);
186 JSValueType knownType() const {
187 JS_ASSERT(isTypeKnown());
189 const Value v = value();
191 return JSVAL_TYPE_DOUBLE;
192 return v.extractNonDoubleType();
194 return u.s.type.knownType_;
196 bool isType(JSValueType type_) const {
197 return isTypeKnown() && knownType() == type_;
202 * Describes how to rematerialize a value during compilation.
205 typedef JSC::MacroAssembler::RegisterID RegisterID;
217 /* Physical location. */
220 * Backing bits are in memory. No fast remat.
224 /* Backing bits are known at compile time. */
227 /* Backing bits are in a register. */
230 /* Backing bits are invalid/unknown. */
234 void setRegister(RegisterID reg) {
236 location_ = PhysLoc_Register;
239 RegisterID reg() const {
240 JS_ASSERT(inRegister());
245 location_ = PhysLoc_Memory;
250 location_ = PhysLoc_Invalid;
253 void setConstant() { location_ = PhysLoc_Constant; }
255 bool isConstant() const { return location_ == PhysLoc_Constant; }
256 bool inRegister() const { return location_ == PhysLoc_Register; }
257 bool inMemory() const { return location_ == PhysLoc_Memory; }
258 bool synced() const { return sync_ == SYNCED; }
260 JS_ASSERT(!synced());
267 void inherit(const RematInfo &other) {
269 location_ = other.location_;
273 /* Set if location is PhysLoc_Register. */
283 } /* namespace mjit */