1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/jit/TypePolicy.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,348 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef jit_TypePolicy_h 1.11 +#define jit_TypePolicy_h 1.12 + 1.13 +#include "jit/IonAllocPolicy.h" 1.14 +#include "jit/IonTypes.h" 1.15 + 1.16 +namespace js { 1.17 +namespace jit { 1.18 + 1.19 +class MInstruction; 1.20 +class MDefinition; 1.21 + 1.22 +// A type policy directs the type analysis phases, which insert conversion, 1.23 +// boxing, unboxing, and type changes as necessary. 1.24 +class TypePolicy 1.25 +{ 1.26 + public: 1.27 + // Analyze the inputs of the instruction and perform one of the following 1.28 + // actions for each input: 1.29 + // * Nothing; the input already type-checks. 1.30 + // * If untyped, optionally ask the input to try and specialize its value. 1.31 + // * Replace the operand with a conversion instruction. 1.32 + // * Insert an unconditional deoptimization (no conversion possible). 1.33 + virtual bool adjustInputs(TempAllocator &alloc, MInstruction *def) = 0; 1.34 +}; 1.35 + 1.36 +class BoxInputsPolicy : public TypePolicy 1.37 +{ 1.38 + protected: 1.39 + static MDefinition *boxAt(TempAllocator &alloc, MInstruction *at, MDefinition *operand); 1.40 + 1.41 + public: 1.42 + static MDefinition *alwaysBoxAt(TempAllocator &alloc, MInstruction *at, MDefinition *operand); 1.43 + virtual bool adjustInputs(TempAllocator &alloc, MInstruction *def); 1.44 +}; 1.45 + 1.46 +class ArithPolicy : public BoxInputsPolicy 1.47 +{ 1.48 + protected: 1.49 + // Specifies three levels of specialization: 1.50 + // - < Value. This input is expected and required. 1.51 + // - == Any. Inputs are probably primitive. 1.52 + // - == None. This op should not be specialized. 1.53 + MIRType specialization_; 1.54 + 1.55 + public: 1.56 + bool adjustInputs(TempAllocator &alloc, MInstruction *def); 1.57 +}; 1.58 + 1.59 +class BitwisePolicy : public BoxInputsPolicy 1.60 +{ 1.61 + protected: 1.62 + // Specifies three levels of specialization: 1.63 + // - < Value. This input is expected and required. 1.64 + // - == Any. Inputs are probably primitive. 1.65 + // - == None. This op should not be specialized. 1.66 + MIRType specialization_; 1.67 + 1.68 + public: 1.69 + bool adjustInputs(TempAllocator &alloc, MInstruction *def); 1.70 + 1.71 + MIRType specialization() const { 1.72 + return specialization_; 1.73 + } 1.74 +}; 1.75 + 1.76 +class ComparePolicy : public BoxInputsPolicy 1.77 +{ 1.78 + bool adjustInputs(TempAllocator &alloc, MInstruction *def); 1.79 +}; 1.80 + 1.81 +// Policy for MTest instructions. 1.82 +class TestPolicy : public BoxInputsPolicy 1.83 +{ 1.84 + public: 1.85 + bool adjustInputs(TempAllocator &alloc, MInstruction *ins); 1.86 +}; 1.87 + 1.88 +class TypeBarrierPolicy : public BoxInputsPolicy 1.89 +{ 1.90 + public: 1.91 + bool adjustInputs(TempAllocator &alloc, MInstruction *ins); 1.92 +}; 1.93 + 1.94 +class CallPolicy : public BoxInputsPolicy 1.95 +{ 1.96 + public: 1.97 + bool adjustInputs(TempAllocator &alloc, MInstruction *def); 1.98 +}; 1.99 + 1.100 +// Policy for MPow. First operand Double; second Double or Int32. 1.101 +class PowPolicy : public BoxInputsPolicy 1.102 +{ 1.103 + MIRType specialization_; 1.104 + 1.105 + public: 1.106 + PowPolicy(MIRType specialization) 1.107 + : specialization_(specialization) 1.108 + { } 1.109 + 1.110 + bool adjustInputs(TempAllocator &alloc, MInstruction *ins); 1.111 +}; 1.112 + 1.113 +// Expect a string for operand Op. If the input is a Value, it is unboxed. 1.114 +template <unsigned Op> 1.115 +class StringPolicy : public BoxInputsPolicy 1.116 +{ 1.117 + public: 1.118 + static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *def); 1.119 + bool adjustInputs(TempAllocator &alloc, MInstruction *def) { 1.120 + return staticAdjustInputs(alloc, def); 1.121 + } 1.122 +}; 1.123 + 1.124 +// Expect a string for operand Op. Else a ToString instruction is inserted. 1.125 +template <unsigned Op> 1.126 +class ConvertToStringPolicy : public BoxInputsPolicy 1.127 +{ 1.128 + public: 1.129 + static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *def); 1.130 + bool adjustInputs(TempAllocator &alloc, MInstruction *def) { 1.131 + return staticAdjustInputs(alloc, def); 1.132 + } 1.133 +}; 1.134 + 1.135 +// Expect an Int for operand Op. If the input is a Value, it is unboxed. 1.136 +template <unsigned Op> 1.137 +class IntPolicy : public BoxInputsPolicy 1.138 +{ 1.139 + public: 1.140 + static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *def); 1.141 + bool adjustInputs(TempAllocator &alloc, MInstruction *def) { 1.142 + return staticAdjustInputs(alloc, def); 1.143 + } 1.144 +}; 1.145 + 1.146 +// Expect an Int for operand Op. Else a ToInt32 instruction is inserted. 1.147 +template <unsigned Op> 1.148 +class ConvertToInt32Policy : public BoxInputsPolicy 1.149 +{ 1.150 + public: 1.151 + static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *def); 1.152 + bool adjustInputs(TempAllocator &alloc, MInstruction *def) { 1.153 + return staticAdjustInputs(alloc, def); 1.154 + } 1.155 +}; 1.156 + 1.157 +// Expect a double for operand Op. If the input is a Value, it is unboxed. 1.158 +template <unsigned Op> 1.159 +class DoublePolicy : public BoxInputsPolicy 1.160 +{ 1.161 + public: 1.162 + static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *def); 1.163 + bool adjustInputs(TempAllocator &alloc, MInstruction *def) { 1.164 + return staticAdjustInputs(alloc, def); 1.165 + } 1.166 +}; 1.167 + 1.168 +// Expect a float32 for operand Op. If the input is a Value, it is unboxed. 1.169 +template <unsigned Op> 1.170 +class Float32Policy : public BoxInputsPolicy 1.171 +{ 1.172 + public: 1.173 + static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *def); 1.174 + bool adjustInputs(TempAllocator &alloc, MInstruction *def) { 1.175 + return staticAdjustInputs(alloc, def); 1.176 + } 1.177 +}; 1.178 + 1.179 +// Expect a float32 OR a double for operand Op, but will prioritize Float32 1.180 +// if the result type is set as such. If the input is a Value, it is unboxed. 1.181 +template <unsigned Op> 1.182 +class FloatingPointPolicy : public TypePolicy 1.183 +{ 1.184 + MIRType policyType_; 1.185 + 1.186 + public: 1.187 + bool adjustInputs(TempAllocator &alloc, MInstruction *def) { 1.188 + if (policyType_ == MIRType_Double) 1.189 + return DoublePolicy<Op>::staticAdjustInputs(alloc, def); 1.190 + return Float32Policy<Op>::staticAdjustInputs(alloc, def); 1.191 + } 1.192 + void setPolicyType(MIRType type) { 1.193 + policyType_ = type; 1.194 + } 1.195 +}; 1.196 + 1.197 +template <unsigned Op> 1.198 +class NoFloatPolicy : public TypePolicy 1.199 +{ 1.200 + public: 1.201 + static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *def); 1.202 + bool adjustInputs(TempAllocator &alloc, MInstruction *def) { 1.203 + return staticAdjustInputs(alloc, def); 1.204 + } 1.205 +}; 1.206 + 1.207 +// Box objects or strings as an input to a ToDouble instruction. 1.208 +class ToDoublePolicy : public BoxInputsPolicy 1.209 +{ 1.210 + public: 1.211 + static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *def); 1.212 + bool adjustInputs(TempAllocator &alloc, MInstruction *def) { 1.213 + return staticAdjustInputs(alloc, def); 1.214 + } 1.215 +}; 1.216 + 1.217 +// Box objects, strings and undefined as input to a ToInt32 instruction. 1.218 +class ToInt32Policy : public BoxInputsPolicy 1.219 +{ 1.220 + public: 1.221 + static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *def); 1.222 + bool adjustInputs(TempAllocator &alloc, MInstruction *def) { 1.223 + return staticAdjustInputs(alloc, def); 1.224 + } 1.225 +}; 1.226 + 1.227 +template <unsigned Op> 1.228 +class ObjectPolicy : public BoxInputsPolicy 1.229 +{ 1.230 + public: 1.231 + static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *ins); 1.232 + bool adjustInputs(TempAllocator &alloc, MInstruction *ins) { 1.233 + return staticAdjustInputs(alloc, ins); 1.234 + } 1.235 +}; 1.236 + 1.237 +// Single-object input. If the input is a Value, it is unboxed. If it is 1.238 +// a primitive, we use ValueToNonNullObject. 1.239 +class SingleObjectPolicy : public ObjectPolicy<0> 1.240 +{ }; 1.241 + 1.242 +template <unsigned Op> 1.243 +class BoxPolicy : public BoxInputsPolicy 1.244 +{ 1.245 + public: 1.246 + static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *ins); 1.247 + bool adjustInputs(TempAllocator &alloc, MInstruction *ins) { 1.248 + return staticAdjustInputs(alloc, ins); 1.249 + } 1.250 +}; 1.251 + 1.252 +// Boxes everything except inputs of type Type. 1.253 +template <unsigned Op, MIRType Type> 1.254 +class BoxExceptPolicy : public TypePolicy 1.255 +{ 1.256 + public: 1.257 + static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *ins); 1.258 + bool adjustInputs(TempAllocator &alloc, MInstruction *ins) { 1.259 + return staticAdjustInputs(alloc, ins); 1.260 + } 1.261 +}; 1.262 + 1.263 +// Combine multiple policies. 1.264 +template <class Lhs, class Rhs> 1.265 +class MixPolicy : public TypePolicy 1.266 +{ 1.267 + public: 1.268 + static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *ins) { 1.269 + return Lhs::staticAdjustInputs(alloc, ins) && Rhs::staticAdjustInputs(alloc, ins); 1.270 + } 1.271 + virtual bool adjustInputs(TempAllocator &alloc, MInstruction *ins) { 1.272 + return staticAdjustInputs(alloc, ins); 1.273 + } 1.274 +}; 1.275 + 1.276 +// Combine three policies. 1.277 +template <class Policy1, class Policy2, class Policy3> 1.278 +class Mix3Policy : public TypePolicy 1.279 +{ 1.280 + public: 1.281 + static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *ins) { 1.282 + return Policy1::staticAdjustInputs(alloc, ins) && 1.283 + Policy2::staticAdjustInputs(alloc, ins) && 1.284 + Policy3::staticAdjustInputs(alloc, ins); 1.285 + } 1.286 + virtual bool adjustInputs(TempAllocator &alloc, MInstruction *ins) { 1.287 + return staticAdjustInputs(alloc, ins); 1.288 + } 1.289 +}; 1.290 + 1.291 +class CallSetElementPolicy : public SingleObjectPolicy 1.292 +{ 1.293 + public: 1.294 + bool adjustInputs(TempAllocator &alloc, MInstruction *def); 1.295 +}; 1.296 + 1.297 +// First operand will be boxed to a Value (except for an object) 1.298 +// Second operand (if specified) will forcefully be unboxed to an object 1.299 +class InstanceOfPolicy : public TypePolicy 1.300 +{ 1.301 + public: 1.302 + bool adjustInputs(TempAllocator &alloc, MInstruction *def); 1.303 +}; 1.304 + 1.305 +class StoreTypedArrayPolicy : public BoxInputsPolicy 1.306 +{ 1.307 + protected: 1.308 + bool adjustValueInput(TempAllocator &alloc, MInstruction *ins, int arrayType, MDefinition *value, int valueOperand); 1.309 + 1.310 + public: 1.311 + bool adjustInputs(TempAllocator &alloc, MInstruction *ins); 1.312 +}; 1.313 + 1.314 +class StoreTypedArrayHolePolicy : public StoreTypedArrayPolicy 1.315 +{ 1.316 + public: 1.317 + bool adjustInputs(TempAllocator &alloc, MInstruction *ins); 1.318 +}; 1.319 + 1.320 +class StoreTypedArrayElementStaticPolicy : public StoreTypedArrayPolicy 1.321 +{ 1.322 + public: 1.323 + bool adjustInputs(TempAllocator &alloc, MInstruction *ins); 1.324 +}; 1.325 + 1.326 +// Accepts integers and doubles. Everything else is boxed. 1.327 +class ClampPolicy : public BoxInputsPolicy 1.328 +{ 1.329 + public: 1.330 + bool adjustInputs(TempAllocator &alloc, MInstruction *ins); 1.331 +}; 1.332 + 1.333 +class FilterTypeSetPolicy : public BoxInputsPolicy 1.334 +{ 1.335 + public: 1.336 + bool adjustInputs(TempAllocator &alloc, MInstruction *ins); 1.337 +}; 1.338 + 1.339 +static inline bool 1.340 +CoercesToDouble(MIRType type) 1.341 +{ 1.342 + if (type == MIRType_Undefined || IsFloatingPointType(type)) 1.343 + return true; 1.344 + return false; 1.345 +} 1.346 + 1.347 + 1.348 +} // namespace jit 1.349 +} // namespace js 1.350 + 1.351 +#endif /* jit_TypePolicy_h */