Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
michael@0 | 2 | * vim: set ts=8 sts=4 et sw=4 tw=99: |
michael@0 | 3 | * This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 6 | |
michael@0 | 7 | #include "jit/TypePolicy.h" |
michael@0 | 8 | |
michael@0 | 9 | #include "jit/Lowering.h" |
michael@0 | 10 | #include "jit/MIR.h" |
michael@0 | 11 | #include "jit/MIRGraph.h" |
michael@0 | 12 | |
michael@0 | 13 | using namespace js; |
michael@0 | 14 | using namespace js::jit; |
michael@0 | 15 | |
michael@0 | 16 | using JS::DoubleNaNValue; |
michael@0 | 17 | |
michael@0 | 18 | static void |
michael@0 | 19 | EnsureOperandNotFloat32(TempAllocator &alloc, MInstruction *def, unsigned op) |
michael@0 | 20 | { |
michael@0 | 21 | MDefinition *in = def->getOperand(op); |
michael@0 | 22 | if (in->type() == MIRType_Float32) { |
michael@0 | 23 | MToDouble *replace = MToDouble::New(alloc, in); |
michael@0 | 24 | def->block()->insertBefore(def, replace); |
michael@0 | 25 | def->replaceOperand(op, replace); |
michael@0 | 26 | } |
michael@0 | 27 | } |
michael@0 | 28 | |
michael@0 | 29 | MDefinition * |
michael@0 | 30 | BoxInputsPolicy::boxAt(TempAllocator &alloc, MInstruction *at, MDefinition *operand) |
michael@0 | 31 | { |
michael@0 | 32 | if (operand->isUnbox()) |
michael@0 | 33 | return operand->toUnbox()->input(); |
michael@0 | 34 | return alwaysBoxAt(alloc, at, operand); |
michael@0 | 35 | } |
michael@0 | 36 | |
michael@0 | 37 | MDefinition * |
michael@0 | 38 | BoxInputsPolicy::alwaysBoxAt(TempAllocator &alloc, MInstruction *at, MDefinition *operand) |
michael@0 | 39 | { |
michael@0 | 40 | MDefinition *boxedOperand = operand; |
michael@0 | 41 | // Replace Float32 by double |
michael@0 | 42 | if (operand->type() == MIRType_Float32) { |
michael@0 | 43 | MInstruction *replace = MToDouble::New(alloc, operand); |
michael@0 | 44 | at->block()->insertBefore(at, replace); |
michael@0 | 45 | boxedOperand = replace; |
michael@0 | 46 | } |
michael@0 | 47 | MBox *box = MBox::New(alloc, boxedOperand); |
michael@0 | 48 | at->block()->insertBefore(at, box); |
michael@0 | 49 | return box; |
michael@0 | 50 | } |
michael@0 | 51 | |
michael@0 | 52 | bool |
michael@0 | 53 | BoxInputsPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins) |
michael@0 | 54 | { |
michael@0 | 55 | for (size_t i = 0, e = ins->numOperands(); i < e; i++) { |
michael@0 | 56 | MDefinition *in = ins->getOperand(i); |
michael@0 | 57 | if (in->type() == MIRType_Value) |
michael@0 | 58 | continue; |
michael@0 | 59 | ins->replaceOperand(i, boxAt(alloc, ins, in)); |
michael@0 | 60 | } |
michael@0 | 61 | return true; |
michael@0 | 62 | } |
michael@0 | 63 | |
michael@0 | 64 | bool |
michael@0 | 65 | ArithPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins) |
michael@0 | 66 | { |
michael@0 | 67 | if (specialization_ == MIRType_None) |
michael@0 | 68 | return BoxInputsPolicy::adjustInputs(alloc, ins); |
michael@0 | 69 | |
michael@0 | 70 | JS_ASSERT(ins->type() == MIRType_Double || ins->type() == MIRType_Int32 || ins->type() == MIRType_Float32); |
michael@0 | 71 | |
michael@0 | 72 | for (size_t i = 0, e = ins->numOperands(); i < e; i++) { |
michael@0 | 73 | MDefinition *in = ins->getOperand(i); |
michael@0 | 74 | if (in->type() == ins->type()) |
michael@0 | 75 | continue; |
michael@0 | 76 | |
michael@0 | 77 | MInstruction *replace; |
michael@0 | 78 | |
michael@0 | 79 | // If the input is a string or an object, the conversion is not |
michael@0 | 80 | // possible, at least, we can't specialize. So box the input. |
michael@0 | 81 | if (in->type() == MIRType_Object || in->type() == MIRType_String || |
michael@0 | 82 | (in->type() == MIRType_Undefined && specialization_ == MIRType_Int32)) |
michael@0 | 83 | { |
michael@0 | 84 | in = boxAt(alloc, ins, in); |
michael@0 | 85 | } |
michael@0 | 86 | |
michael@0 | 87 | if (ins->type() == MIRType_Double) |
michael@0 | 88 | replace = MToDouble::New(alloc, in); |
michael@0 | 89 | else if (ins->type() == MIRType_Float32) |
michael@0 | 90 | replace = MToFloat32::New(alloc, in); |
michael@0 | 91 | else |
michael@0 | 92 | replace = MToInt32::New(alloc, in); |
michael@0 | 93 | |
michael@0 | 94 | ins->block()->insertBefore(ins, replace); |
michael@0 | 95 | ins->replaceOperand(i, replace); |
michael@0 | 96 | } |
michael@0 | 97 | |
michael@0 | 98 | return true; |
michael@0 | 99 | } |
michael@0 | 100 | |
michael@0 | 101 | bool |
michael@0 | 102 | ComparePolicy::adjustInputs(TempAllocator &alloc, MInstruction *def) |
michael@0 | 103 | { |
michael@0 | 104 | JS_ASSERT(def->isCompare()); |
michael@0 | 105 | MCompare *compare = def->toCompare(); |
michael@0 | 106 | |
michael@0 | 107 | // Convert Float32 operands to doubles |
michael@0 | 108 | for (size_t i = 0; i < 2; i++) { |
michael@0 | 109 | MDefinition *in = def->getOperand(i); |
michael@0 | 110 | if (in->type() == MIRType_Float32) { |
michael@0 | 111 | MInstruction *replace = MToDouble::New(alloc, in); |
michael@0 | 112 | def->block()->insertBefore(def, replace); |
michael@0 | 113 | def->replaceOperand(i, replace); |
michael@0 | 114 | } |
michael@0 | 115 | } |
michael@0 | 116 | |
michael@0 | 117 | // Box inputs to get value |
michael@0 | 118 | if (compare->compareType() == MCompare::Compare_Unknown || |
michael@0 | 119 | compare->compareType() == MCompare::Compare_Value) |
michael@0 | 120 | { |
michael@0 | 121 | return BoxInputsPolicy::adjustInputs(alloc, def); |
michael@0 | 122 | } |
michael@0 | 123 | |
michael@0 | 124 | // Compare_Boolean specialization is done for "Anything === Bool" |
michael@0 | 125 | // If the LHS is boolean, we set the specialization to Compare_Int32. |
michael@0 | 126 | // This matches other comparisons of the form bool === bool and |
michael@0 | 127 | // generated code of Compare_Int32 is more efficient. |
michael@0 | 128 | if (compare->compareType() == MCompare::Compare_Boolean && |
michael@0 | 129 | def->getOperand(0)->type() == MIRType_Boolean) |
michael@0 | 130 | { |
michael@0 | 131 | compare->setCompareType(MCompare::Compare_Int32MaybeCoerceBoth); |
michael@0 | 132 | } |
michael@0 | 133 | |
michael@0 | 134 | // Compare_Boolean specialization is done for "Anything === Bool" |
michael@0 | 135 | // As of previous line Anything can't be Boolean |
michael@0 | 136 | if (compare->compareType() == MCompare::Compare_Boolean) { |
michael@0 | 137 | // Unbox rhs that is definitely Boolean |
michael@0 | 138 | MDefinition *rhs = def->getOperand(1); |
michael@0 | 139 | if (rhs->type() != MIRType_Boolean) { |
michael@0 | 140 | if (rhs->type() != MIRType_Value) |
michael@0 | 141 | rhs = boxAt(alloc, def, rhs); |
michael@0 | 142 | MInstruction *unbox = MUnbox::New(alloc, rhs, MIRType_Boolean, MUnbox::Infallible); |
michael@0 | 143 | def->block()->insertBefore(def, unbox); |
michael@0 | 144 | def->replaceOperand(1, unbox); |
michael@0 | 145 | } |
michael@0 | 146 | |
michael@0 | 147 | JS_ASSERT(def->getOperand(0)->type() != MIRType_Boolean); |
michael@0 | 148 | JS_ASSERT(def->getOperand(1)->type() == MIRType_Boolean); |
michael@0 | 149 | return true; |
michael@0 | 150 | } |
michael@0 | 151 | |
michael@0 | 152 | // Compare_StrictString specialization is done for "Anything === String" |
michael@0 | 153 | // If the LHS is string, we set the specialization to Compare_String. |
michael@0 | 154 | if (compare->compareType() == MCompare::Compare_StrictString && |
michael@0 | 155 | def->getOperand(0)->type() == MIRType_String) |
michael@0 | 156 | { |
michael@0 | 157 | compare->setCompareType(MCompare::Compare_String); |
michael@0 | 158 | } |
michael@0 | 159 | |
michael@0 | 160 | // Compare_StrictString specialization is done for "Anything === String" |
michael@0 | 161 | // As of previous line Anything can't be String |
michael@0 | 162 | if (compare->compareType() == MCompare::Compare_StrictString) { |
michael@0 | 163 | // Unbox rhs that is definitely String |
michael@0 | 164 | MDefinition *rhs = def->getOperand(1); |
michael@0 | 165 | if (rhs->type() != MIRType_String) { |
michael@0 | 166 | if (rhs->type() != MIRType_Value) |
michael@0 | 167 | rhs = boxAt(alloc, def, rhs); |
michael@0 | 168 | MInstruction *unbox = MUnbox::New(alloc, rhs, MIRType_String, MUnbox::Infallible); |
michael@0 | 169 | def->block()->insertBefore(def, unbox); |
michael@0 | 170 | def->replaceOperand(1, unbox); |
michael@0 | 171 | } |
michael@0 | 172 | |
michael@0 | 173 | JS_ASSERT(def->getOperand(0)->type() != MIRType_String); |
michael@0 | 174 | JS_ASSERT(def->getOperand(1)->type() == MIRType_String); |
michael@0 | 175 | return true; |
michael@0 | 176 | } |
michael@0 | 177 | |
michael@0 | 178 | if (compare->compareType() == MCompare::Compare_Undefined || |
michael@0 | 179 | compare->compareType() == MCompare::Compare_Null) |
michael@0 | 180 | { |
michael@0 | 181 | // Nothing to do for undefined and null, lowering handles all types. |
michael@0 | 182 | return true; |
michael@0 | 183 | } |
michael@0 | 184 | |
michael@0 | 185 | // Convert all inputs to the right input type |
michael@0 | 186 | MIRType type = compare->inputType(); |
michael@0 | 187 | JS_ASSERT(type == MIRType_Int32 || type == MIRType_Double || |
michael@0 | 188 | type == MIRType_Object || type == MIRType_String || type == MIRType_Float32); |
michael@0 | 189 | for (size_t i = 0; i < 2; i++) { |
michael@0 | 190 | MDefinition *in = def->getOperand(i); |
michael@0 | 191 | if (in->type() == type) |
michael@0 | 192 | continue; |
michael@0 | 193 | |
michael@0 | 194 | MInstruction *replace; |
michael@0 | 195 | |
michael@0 | 196 | // See BinaryArithPolicy::adjustInputs for an explanation of the following |
michael@0 | 197 | if (in->type() == MIRType_Object || in->type() == MIRType_String || |
michael@0 | 198 | in->type() == MIRType_Undefined) |
michael@0 | 199 | { |
michael@0 | 200 | in = boxAt(alloc, def, in); |
michael@0 | 201 | } |
michael@0 | 202 | |
michael@0 | 203 | switch (type) { |
michael@0 | 204 | case MIRType_Double: { |
michael@0 | 205 | MToDouble::ConversionKind convert = MToDouble::NumbersOnly; |
michael@0 | 206 | if (compare->compareType() == MCompare::Compare_DoubleMaybeCoerceLHS && i == 0) |
michael@0 | 207 | convert = MToDouble::NonNullNonStringPrimitives; |
michael@0 | 208 | else if (compare->compareType() == MCompare::Compare_DoubleMaybeCoerceRHS && i == 1) |
michael@0 | 209 | convert = MToDouble::NonNullNonStringPrimitives; |
michael@0 | 210 | if (in->type() == MIRType_Null || |
michael@0 | 211 | (in->type() == MIRType_Boolean && convert == MToDouble::NumbersOnly)) |
michael@0 | 212 | { |
michael@0 | 213 | in = boxAt(alloc, def, in); |
michael@0 | 214 | } |
michael@0 | 215 | replace = MToDouble::New(alloc, in, convert); |
michael@0 | 216 | break; |
michael@0 | 217 | } |
michael@0 | 218 | case MIRType_Float32: { |
michael@0 | 219 | MToFloat32::ConversionKind convert = MToFloat32::NumbersOnly; |
michael@0 | 220 | if (compare->compareType() == MCompare::Compare_DoubleMaybeCoerceLHS && i == 0) |
michael@0 | 221 | convert = MToFloat32::NonNullNonStringPrimitives; |
michael@0 | 222 | else if (compare->compareType() == MCompare::Compare_DoubleMaybeCoerceRHS && i == 1) |
michael@0 | 223 | convert = MToFloat32::NonNullNonStringPrimitives; |
michael@0 | 224 | if (in->type() == MIRType_Null || |
michael@0 | 225 | (in->type() == MIRType_Boolean && convert == MToFloat32::NumbersOnly)) |
michael@0 | 226 | { |
michael@0 | 227 | in = boxAt(alloc, def, in); |
michael@0 | 228 | } |
michael@0 | 229 | replace = MToFloat32::New(alloc, in, convert); |
michael@0 | 230 | break; |
michael@0 | 231 | } |
michael@0 | 232 | case MIRType_Int32: { |
michael@0 | 233 | MacroAssembler::IntConversionInputKind convert = MacroAssembler::IntConversion_NumbersOnly; |
michael@0 | 234 | if (compare->compareType() == MCompare::Compare_Int32MaybeCoerceBoth || |
michael@0 | 235 | (compare->compareType() == MCompare::Compare_Int32MaybeCoerceLHS && i == 0) || |
michael@0 | 236 | (compare->compareType() == MCompare::Compare_Int32MaybeCoerceRHS && i == 1)) |
michael@0 | 237 | { |
michael@0 | 238 | convert = MacroAssembler::IntConversion_NumbersOrBoolsOnly; |
michael@0 | 239 | } |
michael@0 | 240 | if (convert == MacroAssembler::IntConversion_NumbersOnly) { |
michael@0 | 241 | if (in->type() != MIRType_Int32 && in->type() != MIRType_Value) |
michael@0 | 242 | in = boxAt(alloc, def, in); |
michael@0 | 243 | } else { |
michael@0 | 244 | MOZ_ASSERT(convert == MacroAssembler::IntConversion_NumbersOrBoolsOnly); |
michael@0 | 245 | if (in->type() != MIRType_Int32 && |
michael@0 | 246 | in->type() != MIRType_Boolean && |
michael@0 | 247 | in->type() != MIRType_Value) |
michael@0 | 248 | { |
michael@0 | 249 | in = boxAt(alloc, def, in); |
michael@0 | 250 | } |
michael@0 | 251 | } |
michael@0 | 252 | replace = MToInt32::New(alloc, in, convert); |
michael@0 | 253 | break; |
michael@0 | 254 | } |
michael@0 | 255 | case MIRType_Object: |
michael@0 | 256 | replace = MUnbox::New(alloc, in, MIRType_Object, MUnbox::Infallible); |
michael@0 | 257 | break; |
michael@0 | 258 | case MIRType_String: |
michael@0 | 259 | replace = MUnbox::New(alloc, in, MIRType_String, MUnbox::Infallible); |
michael@0 | 260 | break; |
michael@0 | 261 | default: |
michael@0 | 262 | MOZ_ASSUME_UNREACHABLE("Unknown compare specialization"); |
michael@0 | 263 | } |
michael@0 | 264 | |
michael@0 | 265 | def->block()->insertBefore(def, replace); |
michael@0 | 266 | def->replaceOperand(i, replace); |
michael@0 | 267 | } |
michael@0 | 268 | |
michael@0 | 269 | return true; |
michael@0 | 270 | } |
michael@0 | 271 | |
michael@0 | 272 | bool |
michael@0 | 273 | TypeBarrierPolicy::adjustInputs(TempAllocator &alloc, MInstruction *def) |
michael@0 | 274 | { |
michael@0 | 275 | MTypeBarrier *ins = def->toTypeBarrier(); |
michael@0 | 276 | MIRType inputType = ins->getOperand(0)->type(); |
michael@0 | 277 | MIRType outputType = ins->type(); |
michael@0 | 278 | |
michael@0 | 279 | // Input and output type are already in accordance. |
michael@0 | 280 | if (inputType == outputType) |
michael@0 | 281 | return true; |
michael@0 | 282 | |
michael@0 | 283 | // Output is a value, currently box the input. |
michael@0 | 284 | if (outputType == MIRType_Value) { |
michael@0 | 285 | // XXX: Possible optimization: decrease resultTypeSet to only include |
michael@0 | 286 | // the inputType. This will remove the need for boxing. |
michael@0 | 287 | JS_ASSERT(inputType != MIRType_Value); |
michael@0 | 288 | ins->replaceOperand(0, boxAt(alloc, ins, ins->getOperand(0))); |
michael@0 | 289 | return true; |
michael@0 | 290 | } |
michael@0 | 291 | |
michael@0 | 292 | // Input is a value. Unbox the input to the requested type. |
michael@0 | 293 | if (inputType == MIRType_Value) { |
michael@0 | 294 | JS_ASSERT(outputType != MIRType_Value); |
michael@0 | 295 | |
michael@0 | 296 | // We can't unbox a value to null/undefined/lazyargs. So keep output |
michael@0 | 297 | // also a value. |
michael@0 | 298 | if (IsNullOrUndefined(outputType) || outputType == MIRType_MagicOptimizedArguments) { |
michael@0 | 299 | JS_ASSERT(ins->defUseCount() == 0); |
michael@0 | 300 | ins->setResultType(MIRType_Value); |
michael@0 | 301 | return true; |
michael@0 | 302 | } |
michael@0 | 303 | |
michael@0 | 304 | MUnbox *unbox = MUnbox::New(alloc, ins->getOperand(0), outputType, MUnbox::TypeBarrier); |
michael@0 | 305 | ins->block()->insertBefore(ins, unbox); |
michael@0 | 306 | ins->replaceOperand(0, unbox); |
michael@0 | 307 | return true; |
michael@0 | 308 | } |
michael@0 | 309 | |
michael@0 | 310 | // In the remaining cases we will alway bail. OutputType doesn't matter. |
michael@0 | 311 | // Take inputType so we can use redefine during lowering. |
michael@0 | 312 | JS_ASSERT(ins->alwaysBails()); |
michael@0 | 313 | ins->setResultType(inputType); |
michael@0 | 314 | |
michael@0 | 315 | return true; |
michael@0 | 316 | } |
michael@0 | 317 | |
michael@0 | 318 | bool |
michael@0 | 319 | TestPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins) |
michael@0 | 320 | { |
michael@0 | 321 | MDefinition *op = ins->getOperand(0); |
michael@0 | 322 | switch (op->type()) { |
michael@0 | 323 | case MIRType_Value: |
michael@0 | 324 | case MIRType_Null: |
michael@0 | 325 | case MIRType_Undefined: |
michael@0 | 326 | case MIRType_Boolean: |
michael@0 | 327 | case MIRType_Int32: |
michael@0 | 328 | case MIRType_Double: |
michael@0 | 329 | case MIRType_Float32: |
michael@0 | 330 | case MIRType_Object: |
michael@0 | 331 | break; |
michael@0 | 332 | |
michael@0 | 333 | case MIRType_String: |
michael@0 | 334 | { |
michael@0 | 335 | MStringLength *length = MStringLength::New(alloc, op); |
michael@0 | 336 | ins->block()->insertBefore(ins, length); |
michael@0 | 337 | ins->replaceOperand(0, length); |
michael@0 | 338 | break; |
michael@0 | 339 | } |
michael@0 | 340 | |
michael@0 | 341 | default: |
michael@0 | 342 | ins->replaceOperand(0, boxAt(alloc, ins, op)); |
michael@0 | 343 | break; |
michael@0 | 344 | } |
michael@0 | 345 | return true; |
michael@0 | 346 | } |
michael@0 | 347 | |
michael@0 | 348 | bool |
michael@0 | 349 | BitwisePolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins) |
michael@0 | 350 | { |
michael@0 | 351 | if (specialization_ == MIRType_None) |
michael@0 | 352 | return BoxInputsPolicy::adjustInputs(alloc, ins); |
michael@0 | 353 | |
michael@0 | 354 | JS_ASSERT(ins->type() == specialization_); |
michael@0 | 355 | JS_ASSERT(specialization_ == MIRType_Int32 || specialization_ == MIRType_Double); |
michael@0 | 356 | |
michael@0 | 357 | // This policy works for both unary and binary bitwise operations. |
michael@0 | 358 | for (size_t i = 0, e = ins->numOperands(); i < e; i++) { |
michael@0 | 359 | MDefinition *in = ins->getOperand(i); |
michael@0 | 360 | if (in->type() == MIRType_Int32) |
michael@0 | 361 | continue; |
michael@0 | 362 | |
michael@0 | 363 | // See BinaryArithPolicy::adjustInputs for an explanation of the following |
michael@0 | 364 | if (in->type() == MIRType_Object || in->type() == MIRType_String) |
michael@0 | 365 | in = boxAt(alloc, ins, in); |
michael@0 | 366 | |
michael@0 | 367 | MInstruction *replace = MTruncateToInt32::New(alloc, in); |
michael@0 | 368 | ins->block()->insertBefore(ins, replace); |
michael@0 | 369 | ins->replaceOperand(i, replace); |
michael@0 | 370 | } |
michael@0 | 371 | |
michael@0 | 372 | return true; |
michael@0 | 373 | } |
michael@0 | 374 | |
michael@0 | 375 | bool |
michael@0 | 376 | PowPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins) |
michael@0 | 377 | { |
michael@0 | 378 | JS_ASSERT(specialization_ == MIRType_Int32 || specialization_ == MIRType_Double); |
michael@0 | 379 | |
michael@0 | 380 | // Input must be a double. |
michael@0 | 381 | if (!DoublePolicy<0>::staticAdjustInputs(alloc, ins)) |
michael@0 | 382 | return false; |
michael@0 | 383 | |
michael@0 | 384 | // Power may be an int32 or a double. Integers receive a faster path. |
michael@0 | 385 | if (specialization_ == MIRType_Double) |
michael@0 | 386 | return DoublePolicy<1>::staticAdjustInputs(alloc, ins); |
michael@0 | 387 | return IntPolicy<1>::staticAdjustInputs(alloc, ins); |
michael@0 | 388 | } |
michael@0 | 389 | |
michael@0 | 390 | template <unsigned Op> |
michael@0 | 391 | bool |
michael@0 | 392 | StringPolicy<Op>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins) |
michael@0 | 393 | { |
michael@0 | 394 | MDefinition *in = ins->getOperand(Op); |
michael@0 | 395 | if (in->type() == MIRType_String) |
michael@0 | 396 | return true; |
michael@0 | 397 | |
michael@0 | 398 | if (in->type() != MIRType_Value) |
michael@0 | 399 | in = boxAt(alloc, ins, in); |
michael@0 | 400 | |
michael@0 | 401 | MUnbox *replace = MUnbox::New(alloc, in, MIRType_String, MUnbox::Fallible); |
michael@0 | 402 | ins->block()->insertBefore(ins, replace); |
michael@0 | 403 | ins->replaceOperand(Op, replace); |
michael@0 | 404 | return true; |
michael@0 | 405 | } |
michael@0 | 406 | |
michael@0 | 407 | template bool StringPolicy<0>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins); |
michael@0 | 408 | template bool StringPolicy<1>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins); |
michael@0 | 409 | template bool StringPolicy<2>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins); |
michael@0 | 410 | |
michael@0 | 411 | template <unsigned Op> |
michael@0 | 412 | bool |
michael@0 | 413 | ConvertToStringPolicy<Op>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins) |
michael@0 | 414 | { |
michael@0 | 415 | MDefinition *in = ins->getOperand(Op); |
michael@0 | 416 | if (in->type() == MIRType_String) |
michael@0 | 417 | return true; |
michael@0 | 418 | |
michael@0 | 419 | MInstruction *replace; |
michael@0 | 420 | if (in->mightBeType(MIRType_Object)) { |
michael@0 | 421 | if (in->type() != MIRType_Value) |
michael@0 | 422 | in = boxAt(alloc, ins, in); |
michael@0 | 423 | |
michael@0 | 424 | replace = MUnbox::New(alloc, in, MIRType_String, MUnbox::Fallible); |
michael@0 | 425 | } else { |
michael@0 | 426 | // TODO remove these two lines once 966957 has landed |
michael@0 | 427 | EnsureOperandNotFloat32(alloc, ins, Op); |
michael@0 | 428 | in = ins->getOperand(Op); |
michael@0 | 429 | replace = MToString::New(alloc, in); |
michael@0 | 430 | } |
michael@0 | 431 | |
michael@0 | 432 | ins->block()->insertBefore(ins, replace); |
michael@0 | 433 | ins->replaceOperand(Op, replace); |
michael@0 | 434 | return true; |
michael@0 | 435 | } |
michael@0 | 436 | |
michael@0 | 437 | template bool ConvertToStringPolicy<0>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins); |
michael@0 | 438 | template bool ConvertToStringPolicy<1>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins); |
michael@0 | 439 | |
michael@0 | 440 | template <unsigned Op> |
michael@0 | 441 | bool |
michael@0 | 442 | IntPolicy<Op>::staticAdjustInputs(TempAllocator &alloc, MInstruction *def) |
michael@0 | 443 | { |
michael@0 | 444 | MDefinition *in = def->getOperand(Op); |
michael@0 | 445 | if (in->type() == MIRType_Int32) |
michael@0 | 446 | return true; |
michael@0 | 447 | |
michael@0 | 448 | if (in->type() != MIRType_Value) |
michael@0 | 449 | in = boxAt(alloc, def, in); |
michael@0 | 450 | |
michael@0 | 451 | MUnbox *replace = MUnbox::New(alloc, in, MIRType_Int32, MUnbox::Fallible); |
michael@0 | 452 | def->block()->insertBefore(def, replace); |
michael@0 | 453 | def->replaceOperand(Op, replace); |
michael@0 | 454 | return true; |
michael@0 | 455 | } |
michael@0 | 456 | |
michael@0 | 457 | template bool IntPolicy<0>::staticAdjustInputs(TempAllocator &alloc, MInstruction *def); |
michael@0 | 458 | template bool IntPolicy<1>::staticAdjustInputs(TempAllocator &alloc, MInstruction *def); |
michael@0 | 459 | template bool IntPolicy<2>::staticAdjustInputs(TempAllocator &alloc, MInstruction *def); |
michael@0 | 460 | |
michael@0 | 461 | template <unsigned Op> |
michael@0 | 462 | bool |
michael@0 | 463 | ConvertToInt32Policy<Op>::staticAdjustInputs(TempAllocator &alloc, MInstruction *def) |
michael@0 | 464 | { |
michael@0 | 465 | MDefinition *in = def->getOperand(Op); |
michael@0 | 466 | if (in->type() == MIRType_Int32) |
michael@0 | 467 | return true; |
michael@0 | 468 | |
michael@0 | 469 | MToInt32 *replace = MToInt32::New(alloc, in); |
michael@0 | 470 | def->block()->insertBefore(def, replace); |
michael@0 | 471 | def->replaceOperand(Op, replace); |
michael@0 | 472 | return true; |
michael@0 | 473 | } |
michael@0 | 474 | |
michael@0 | 475 | template bool ConvertToInt32Policy<0>::staticAdjustInputs(TempAllocator &alloc, MInstruction *def); |
michael@0 | 476 | |
michael@0 | 477 | template <unsigned Op> |
michael@0 | 478 | bool |
michael@0 | 479 | DoublePolicy<Op>::staticAdjustInputs(TempAllocator &alloc, MInstruction *def) |
michael@0 | 480 | { |
michael@0 | 481 | MDefinition *in = def->getOperand(Op); |
michael@0 | 482 | if (in->type() == MIRType_Double) |
michael@0 | 483 | return true; |
michael@0 | 484 | |
michael@0 | 485 | // Force a bailout. Objects may be effectful; strings are currently unhandled. |
michael@0 | 486 | if (in->type() == MIRType_Object || in->type() == MIRType_String) { |
michael@0 | 487 | MBox *box = MBox::New(alloc, in); |
michael@0 | 488 | def->block()->insertBefore(def, box); |
michael@0 | 489 | |
michael@0 | 490 | MUnbox *unbox = MUnbox::New(alloc, box, MIRType_Double, MUnbox::Fallible); |
michael@0 | 491 | def->block()->insertBefore(def, unbox); |
michael@0 | 492 | def->replaceOperand(Op, unbox); |
michael@0 | 493 | return true; |
michael@0 | 494 | } |
michael@0 | 495 | |
michael@0 | 496 | MToDouble *replace = MToDouble::New(alloc, in); |
michael@0 | 497 | def->block()->insertBefore(def, replace); |
michael@0 | 498 | def->replaceOperand(Op, replace); |
michael@0 | 499 | return true; |
michael@0 | 500 | } |
michael@0 | 501 | |
michael@0 | 502 | template bool DoublePolicy<0>::staticAdjustInputs(TempAllocator &alloc, MInstruction *def); |
michael@0 | 503 | template bool DoublePolicy<1>::staticAdjustInputs(TempAllocator &alloc, MInstruction *def); |
michael@0 | 504 | |
michael@0 | 505 | template <unsigned Op> |
michael@0 | 506 | bool |
michael@0 | 507 | Float32Policy<Op>::staticAdjustInputs(TempAllocator &alloc, MInstruction *def) |
michael@0 | 508 | { |
michael@0 | 509 | MDefinition *in = def->getOperand(Op); |
michael@0 | 510 | if (in->type() == MIRType_Float32) |
michael@0 | 511 | return true; |
michael@0 | 512 | |
michael@0 | 513 | // Force a bailout. Objects may be effectful; strings are currently unhandled. |
michael@0 | 514 | if (in->type() == MIRType_Object || in->type() == MIRType_String) { |
michael@0 | 515 | MToDouble *toDouble = MToDouble::New(alloc, in); |
michael@0 | 516 | def->block()->insertBefore(def, toDouble); |
michael@0 | 517 | |
michael@0 | 518 | MBox *box = MBox::New(alloc, toDouble); |
michael@0 | 519 | def->block()->insertBefore(def, box); |
michael@0 | 520 | |
michael@0 | 521 | MUnbox *unbox = MUnbox::New(alloc, box, MIRType_Double, MUnbox::Fallible); |
michael@0 | 522 | def->block()->insertBefore(def, unbox); |
michael@0 | 523 | |
michael@0 | 524 | MToFloat32 *toFloat32 = MToFloat32::New(alloc, unbox); |
michael@0 | 525 | def->block()->insertBefore(def, toFloat32); |
michael@0 | 526 | |
michael@0 | 527 | def->replaceOperand(Op, unbox); |
michael@0 | 528 | |
michael@0 | 529 | return true; |
michael@0 | 530 | } |
michael@0 | 531 | |
michael@0 | 532 | MToFloat32 *replace = MToFloat32::New(alloc, in); |
michael@0 | 533 | def->block()->insertBefore(def, replace); |
michael@0 | 534 | def->replaceOperand(Op, replace); |
michael@0 | 535 | return true; |
michael@0 | 536 | } |
michael@0 | 537 | |
michael@0 | 538 | template bool Float32Policy<0>::staticAdjustInputs(TempAllocator &alloc, MInstruction *def); |
michael@0 | 539 | template bool Float32Policy<1>::staticAdjustInputs(TempAllocator &alloc, MInstruction *def); |
michael@0 | 540 | template bool Float32Policy<2>::staticAdjustInputs(TempAllocator &alloc, MInstruction *def); |
michael@0 | 541 | |
michael@0 | 542 | template <unsigned Op> |
michael@0 | 543 | bool |
michael@0 | 544 | NoFloatPolicy<Op>::staticAdjustInputs(TempAllocator &alloc, MInstruction *def) |
michael@0 | 545 | { |
michael@0 | 546 | EnsureOperandNotFloat32(alloc, def, Op); |
michael@0 | 547 | return true; |
michael@0 | 548 | } |
michael@0 | 549 | |
michael@0 | 550 | template bool NoFloatPolicy<0>::staticAdjustInputs(TempAllocator &alloc, MInstruction *def); |
michael@0 | 551 | template bool NoFloatPolicy<1>::staticAdjustInputs(TempAllocator &alloc, MInstruction *def); |
michael@0 | 552 | template bool NoFloatPolicy<2>::staticAdjustInputs(TempAllocator &alloc, MInstruction *def); |
michael@0 | 553 | template bool NoFloatPolicy<3>::staticAdjustInputs(TempAllocator &alloc, MInstruction *def); |
michael@0 | 554 | |
michael@0 | 555 | template <unsigned Op> |
michael@0 | 556 | bool |
michael@0 | 557 | BoxPolicy<Op>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins) |
michael@0 | 558 | { |
michael@0 | 559 | MDefinition *in = ins->getOperand(Op); |
michael@0 | 560 | if (in->type() == MIRType_Value) |
michael@0 | 561 | return true; |
michael@0 | 562 | |
michael@0 | 563 | ins->replaceOperand(Op, boxAt(alloc, ins, in)); |
michael@0 | 564 | return true; |
michael@0 | 565 | } |
michael@0 | 566 | |
michael@0 | 567 | template bool BoxPolicy<0>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins); |
michael@0 | 568 | template bool BoxPolicy<1>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins); |
michael@0 | 569 | template bool BoxPolicy<2>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins); |
michael@0 | 570 | |
michael@0 | 571 | template <unsigned Op, MIRType Type> |
michael@0 | 572 | bool |
michael@0 | 573 | BoxExceptPolicy<Op, Type>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins) |
michael@0 | 574 | { |
michael@0 | 575 | MDefinition *in = ins->getOperand(Op); |
michael@0 | 576 | if (in->type() == Type) |
michael@0 | 577 | return true; |
michael@0 | 578 | return BoxPolicy<Op>::staticAdjustInputs(alloc, ins); |
michael@0 | 579 | } |
michael@0 | 580 | |
michael@0 | 581 | template bool BoxExceptPolicy<0, MIRType_String>::staticAdjustInputs(TempAllocator &alloc, |
michael@0 | 582 | MInstruction *ins); |
michael@0 | 583 | template bool BoxExceptPolicy<1, MIRType_String>::staticAdjustInputs(TempAllocator &alloc, |
michael@0 | 584 | MInstruction *ins); |
michael@0 | 585 | template bool BoxExceptPolicy<2, MIRType_String>::staticAdjustInputs(TempAllocator &alloc, |
michael@0 | 586 | MInstruction *ins); |
michael@0 | 587 | |
michael@0 | 588 | bool |
michael@0 | 589 | ToDoublePolicy::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins) |
michael@0 | 590 | { |
michael@0 | 591 | MDefinition *in = ins->getOperand(0); |
michael@0 | 592 | if (in->type() != MIRType_Object && in->type() != MIRType_String) |
michael@0 | 593 | return true; |
michael@0 | 594 | |
michael@0 | 595 | in = boxAt(alloc, ins, in); |
michael@0 | 596 | ins->replaceOperand(0, in); |
michael@0 | 597 | return true; |
michael@0 | 598 | } |
michael@0 | 599 | |
michael@0 | 600 | bool |
michael@0 | 601 | ToInt32Policy::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins) |
michael@0 | 602 | { |
michael@0 | 603 | JS_ASSERT(ins->isToInt32()); |
michael@0 | 604 | |
michael@0 | 605 | MDefinition *in = ins->getOperand(0); |
michael@0 | 606 | switch (in->type()) { |
michael@0 | 607 | case MIRType_Object: |
michael@0 | 608 | case MIRType_String: |
michael@0 | 609 | case MIRType_Undefined: |
michael@0 | 610 | // Objects might be effectful. Undefined coerces to NaN, not int32. |
michael@0 | 611 | in = boxAt(alloc, ins, in); |
michael@0 | 612 | ins->replaceOperand(0, in); |
michael@0 | 613 | break; |
michael@0 | 614 | default: |
michael@0 | 615 | break; |
michael@0 | 616 | } |
michael@0 | 617 | |
michael@0 | 618 | return true; |
michael@0 | 619 | } |
michael@0 | 620 | |
michael@0 | 621 | template <unsigned Op> |
michael@0 | 622 | bool |
michael@0 | 623 | ObjectPolicy<Op>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins) |
michael@0 | 624 | { |
michael@0 | 625 | MDefinition *in = ins->getOperand(Op); |
michael@0 | 626 | if (in->type() == MIRType_Object || in->type() == MIRType_Slots || |
michael@0 | 627 | in->type() == MIRType_Elements) |
michael@0 | 628 | { |
michael@0 | 629 | return true; |
michael@0 | 630 | } |
michael@0 | 631 | |
michael@0 | 632 | if (in->type() != MIRType_Value) |
michael@0 | 633 | in = boxAt(alloc, ins, in); |
michael@0 | 634 | |
michael@0 | 635 | MUnbox *replace = MUnbox::New(alloc, in, MIRType_Object, MUnbox::Fallible); |
michael@0 | 636 | ins->block()->insertBefore(ins, replace); |
michael@0 | 637 | ins->replaceOperand(Op, replace); |
michael@0 | 638 | return true; |
michael@0 | 639 | } |
michael@0 | 640 | |
michael@0 | 641 | template bool ObjectPolicy<0>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins); |
michael@0 | 642 | template bool ObjectPolicy<1>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins); |
michael@0 | 643 | template bool ObjectPolicy<2>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins); |
michael@0 | 644 | template bool ObjectPolicy<3>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins); |
michael@0 | 645 | |
michael@0 | 646 | bool |
michael@0 | 647 | CallPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins) |
michael@0 | 648 | { |
michael@0 | 649 | MCall *call = ins->toCall(); |
michael@0 | 650 | |
michael@0 | 651 | MDefinition *func = call->getFunction(); |
michael@0 | 652 | if (func->type() != MIRType_Object) { |
michael@0 | 653 | // If the function is impossible to call, |
michael@0 | 654 | // bail out by causing a subsequent unbox to fail. |
michael@0 | 655 | if (func->type() != MIRType_Value) |
michael@0 | 656 | func = boxAt(alloc, call, func); |
michael@0 | 657 | |
michael@0 | 658 | MInstruction *unbox = MUnbox::New(alloc, func, MIRType_Object, MUnbox::Fallible); |
michael@0 | 659 | call->block()->insertBefore(call, unbox); |
michael@0 | 660 | call->replaceFunction(unbox); |
michael@0 | 661 | } |
michael@0 | 662 | |
michael@0 | 663 | for (uint32_t i = 0; i < call->numStackArgs(); i++) |
michael@0 | 664 | EnsureOperandNotFloat32(alloc, call, MCall::IndexOfStackArg(i)); |
michael@0 | 665 | |
michael@0 | 666 | return true; |
michael@0 | 667 | } |
michael@0 | 668 | |
michael@0 | 669 | bool |
michael@0 | 670 | CallSetElementPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins) |
michael@0 | 671 | { |
michael@0 | 672 | // The first operand should be an object. |
michael@0 | 673 | SingleObjectPolicy::adjustInputs(alloc, ins); |
michael@0 | 674 | |
michael@0 | 675 | // Box the index and value operands. |
michael@0 | 676 | for (size_t i = 1, e = ins->numOperands(); i < e; i++) { |
michael@0 | 677 | MDefinition *in = ins->getOperand(i); |
michael@0 | 678 | if (in->type() == MIRType_Value) |
michael@0 | 679 | continue; |
michael@0 | 680 | ins->replaceOperand(i, boxAt(alloc, ins, in)); |
michael@0 | 681 | } |
michael@0 | 682 | return true; |
michael@0 | 683 | } |
michael@0 | 684 | |
michael@0 | 685 | bool |
michael@0 | 686 | InstanceOfPolicy::adjustInputs(TempAllocator &alloc, MInstruction *def) |
michael@0 | 687 | { |
michael@0 | 688 | // Box first operand if it isn't object |
michael@0 | 689 | if (def->getOperand(0)->type() != MIRType_Object) |
michael@0 | 690 | BoxPolicy<0>::staticAdjustInputs(alloc, def); |
michael@0 | 691 | |
michael@0 | 692 | return true; |
michael@0 | 693 | } |
michael@0 | 694 | |
michael@0 | 695 | bool |
michael@0 | 696 | StoreTypedArrayPolicy::adjustValueInput(TempAllocator &alloc, MInstruction *ins, int arrayType, |
michael@0 | 697 | MDefinition *value, int valueOperand) |
michael@0 | 698 | { |
michael@0 | 699 | MDefinition *curValue = value; |
michael@0 | 700 | // First, ensure the value is int32, boolean, double or Value. |
michael@0 | 701 | // The conversion is based on TypedArrayObjectTemplate::setElementTail. |
michael@0 | 702 | switch (value->type()) { |
michael@0 | 703 | case MIRType_Int32: |
michael@0 | 704 | case MIRType_Double: |
michael@0 | 705 | case MIRType_Float32: |
michael@0 | 706 | case MIRType_Boolean: |
michael@0 | 707 | case MIRType_Value: |
michael@0 | 708 | break; |
michael@0 | 709 | case MIRType_Null: |
michael@0 | 710 | value->setImplicitlyUsedUnchecked(); |
michael@0 | 711 | value = MConstant::New(alloc, Int32Value(0)); |
michael@0 | 712 | ins->block()->insertBefore(ins, value->toInstruction()); |
michael@0 | 713 | break; |
michael@0 | 714 | case MIRType_Undefined: |
michael@0 | 715 | value->setImplicitlyUsedUnchecked(); |
michael@0 | 716 | value = MConstant::New(alloc, DoubleNaNValue()); |
michael@0 | 717 | ins->block()->insertBefore(ins, value->toInstruction()); |
michael@0 | 718 | break; |
michael@0 | 719 | case MIRType_Object: |
michael@0 | 720 | case MIRType_String: |
michael@0 | 721 | value = boxAt(alloc, ins, value); |
michael@0 | 722 | break; |
michael@0 | 723 | default: |
michael@0 | 724 | MOZ_ASSUME_UNREACHABLE("Unexpected type"); |
michael@0 | 725 | } |
michael@0 | 726 | |
michael@0 | 727 | if (value != curValue) { |
michael@0 | 728 | ins->replaceOperand(valueOperand, value); |
michael@0 | 729 | curValue = value; |
michael@0 | 730 | } |
michael@0 | 731 | |
michael@0 | 732 | JS_ASSERT(value->type() == MIRType_Int32 || |
michael@0 | 733 | value->type() == MIRType_Boolean || |
michael@0 | 734 | value->type() == MIRType_Double || |
michael@0 | 735 | value->type() == MIRType_Float32 || |
michael@0 | 736 | value->type() == MIRType_Value); |
michael@0 | 737 | |
michael@0 | 738 | switch (arrayType) { |
michael@0 | 739 | case ScalarTypeDescr::TYPE_INT8: |
michael@0 | 740 | case ScalarTypeDescr::TYPE_UINT8: |
michael@0 | 741 | case ScalarTypeDescr::TYPE_INT16: |
michael@0 | 742 | case ScalarTypeDescr::TYPE_UINT16: |
michael@0 | 743 | case ScalarTypeDescr::TYPE_INT32: |
michael@0 | 744 | case ScalarTypeDescr::TYPE_UINT32: |
michael@0 | 745 | if (value->type() != MIRType_Int32) { |
michael@0 | 746 | value = MTruncateToInt32::New(alloc, value); |
michael@0 | 747 | ins->block()->insertBefore(ins, value->toInstruction()); |
michael@0 | 748 | } |
michael@0 | 749 | break; |
michael@0 | 750 | case ScalarTypeDescr::TYPE_UINT8_CLAMPED: |
michael@0 | 751 | // IonBuilder should have inserted ClampToUint8. |
michael@0 | 752 | JS_ASSERT(value->type() == MIRType_Int32); |
michael@0 | 753 | break; |
michael@0 | 754 | case ScalarTypeDescr::TYPE_FLOAT32: |
michael@0 | 755 | if (LIRGenerator::allowFloat32Optimizations()) { |
michael@0 | 756 | if (value->type() != MIRType_Float32) { |
michael@0 | 757 | value = MToFloat32::New(alloc, value); |
michael@0 | 758 | ins->block()->insertBefore(ins, value->toInstruction()); |
michael@0 | 759 | } |
michael@0 | 760 | break; |
michael@0 | 761 | } |
michael@0 | 762 | // Fallthrough: if the LIRGenerator cannot directly store Float32, it will expect the |
michael@0 | 763 | // stored value to be a double. |
michael@0 | 764 | case ScalarTypeDescr::TYPE_FLOAT64: |
michael@0 | 765 | if (value->type() != MIRType_Double) { |
michael@0 | 766 | value = MToDouble::New(alloc, value); |
michael@0 | 767 | ins->block()->insertBefore(ins, value->toInstruction()); |
michael@0 | 768 | } |
michael@0 | 769 | break; |
michael@0 | 770 | default: |
michael@0 | 771 | MOZ_ASSUME_UNREACHABLE("Invalid array type"); |
michael@0 | 772 | } |
michael@0 | 773 | |
michael@0 | 774 | if (value != curValue) { |
michael@0 | 775 | ins->replaceOperand(valueOperand, value); |
michael@0 | 776 | curValue = value; |
michael@0 | 777 | } |
michael@0 | 778 | return true; |
michael@0 | 779 | } |
michael@0 | 780 | |
michael@0 | 781 | bool |
michael@0 | 782 | StoreTypedArrayPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins) |
michael@0 | 783 | { |
michael@0 | 784 | MStoreTypedArrayElement *store = ins->toStoreTypedArrayElement(); |
michael@0 | 785 | JS_ASSERT(store->elements()->type() == MIRType_Elements); |
michael@0 | 786 | JS_ASSERT(store->index()->type() == MIRType_Int32); |
michael@0 | 787 | |
michael@0 | 788 | return adjustValueInput(alloc, ins, store->arrayType(), store->value(), 2); |
michael@0 | 789 | } |
michael@0 | 790 | |
michael@0 | 791 | bool |
michael@0 | 792 | StoreTypedArrayHolePolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins) |
michael@0 | 793 | { |
michael@0 | 794 | MStoreTypedArrayElementHole *store = ins->toStoreTypedArrayElementHole(); |
michael@0 | 795 | JS_ASSERT(store->elements()->type() == MIRType_Elements); |
michael@0 | 796 | JS_ASSERT(store->index()->type() == MIRType_Int32); |
michael@0 | 797 | JS_ASSERT(store->length()->type() == MIRType_Int32); |
michael@0 | 798 | |
michael@0 | 799 | return adjustValueInput(alloc, ins, store->arrayType(), store->value(), 3); |
michael@0 | 800 | } |
michael@0 | 801 | |
michael@0 | 802 | bool |
michael@0 | 803 | StoreTypedArrayElementStaticPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins) |
michael@0 | 804 | { |
michael@0 | 805 | MStoreTypedArrayElementStatic *store = ins->toStoreTypedArrayElementStatic(); |
michael@0 | 806 | |
michael@0 | 807 | return ConvertToInt32Policy<0>::staticAdjustInputs(alloc, ins) && |
michael@0 | 808 | adjustValueInput(alloc, ins, store->viewType(), store->value(), 1); |
michael@0 | 809 | } |
michael@0 | 810 | |
michael@0 | 811 | bool |
michael@0 | 812 | ClampPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins) |
michael@0 | 813 | { |
michael@0 | 814 | MDefinition *in = ins->toClampToUint8()->input(); |
michael@0 | 815 | |
michael@0 | 816 | switch (in->type()) { |
michael@0 | 817 | case MIRType_Int32: |
michael@0 | 818 | case MIRType_Double: |
michael@0 | 819 | case MIRType_Value: |
michael@0 | 820 | break; |
michael@0 | 821 | default: |
michael@0 | 822 | ins->replaceOperand(0, boxAt(alloc, ins, in)); |
michael@0 | 823 | break; |
michael@0 | 824 | } |
michael@0 | 825 | |
michael@0 | 826 | return true; |
michael@0 | 827 | } |
michael@0 | 828 | |
michael@0 | 829 | bool |
michael@0 | 830 | FilterTypeSetPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins) |
michael@0 | 831 | { |
michael@0 | 832 | MOZ_ASSERT(ins->numOperands() == 1); |
michael@0 | 833 | |
michael@0 | 834 | // Do nothing if already same type. |
michael@0 | 835 | if (ins->type() == ins->getOperand(0)->type()) |
michael@0 | 836 | return true; |
michael@0 | 837 | |
michael@0 | 838 | // Box input if ouput type is MIRType_Value |
michael@0 | 839 | if (ins->type() == MIRType_Value) { |
michael@0 | 840 | ins->replaceOperand(0, boxAt(alloc, ins, ins->getOperand(0))); |
michael@0 | 841 | return true; |
michael@0 | 842 | } |
michael@0 | 843 | |
michael@0 | 844 | // For simplicity just mark output type as MIRType_Value if input type |
michael@0 | 845 | // is MIRType_Value. It should be possible to unbox, but we need to |
michael@0 | 846 | // add extra code for Undefined/Null. |
michael@0 | 847 | if (ins->getOperand(0)->type() == MIRType_Value) { |
michael@0 | 848 | ins->setResultType(MIRType_Value); |
michael@0 | 849 | return true; |
michael@0 | 850 | } |
michael@0 | 851 | |
michael@0 | 852 | // In all other cases we will definitely bail, since types don't |
michael@0 | 853 | // correspond. Just box and mark output as MIRType_Value. |
michael@0 | 854 | ins->replaceOperand(0, boxAt(alloc, ins, ins->getOperand(0))); |
michael@0 | 855 | ins->setResultType(MIRType_Value); |
michael@0 | 856 | |
michael@0 | 857 | return true; |
michael@0 | 858 | } |