| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 import '../compiler.dart' show Compiler; | 5 import '../compiler.dart' show Compiler; |
| 6 import '../constants/constant_system.dart'; | 6 import '../constants/constant_system.dart'; |
| 7 import '../constants/values.dart'; | 7 import '../constants/values.dart'; |
| 8 import '../elements/elements.dart'; | 8 import '../elements/elements.dart'; |
| 9 import '../js_backend/js_backend.dart'; | 9 import '../js_backend/js_backend.dart'; |
| 10 import '../types/types.dart'; | 10 import '../types/types.dart'; |
| 11 import '../universe/call_structure.dart'; | 11 import '../universe/call_structure.dart'; |
| 12 import '../universe/selector.dart'; | 12 import '../universe/selector.dart'; |
| 13 import '../world.dart' show ClosedWorld; | 13 import '../world.dart' show ClosedWorld; |
| 14 import 'nodes.dart'; | 14 import 'nodes.dart'; |
| 15 import 'types.dart'; | 15 import 'types.dart'; |
| 16 | 16 |
| 17 /** | 17 /** |
| 18 * [InvokeDynamicSpecializer] and its subclasses are helpers to | 18 * [InvokeDynamicSpecializer] and its subclasses are helpers to |
| 19 * optimize intercepted dynamic calls. It knows what input types | 19 * optimize intercepted dynamic calls. It knows what input types |
| 20 * would be beneficial for performance, and how to change a invoke | 20 * would be beneficial for performance, and how to change a invoke |
| 21 * dynamic to a builtin instruction (e.g. HIndex, HBitNot). | 21 * dynamic to a builtin instruction (e.g. HIndex, HBitNot). |
| 22 */ | 22 */ |
| 23 class InvokeDynamicSpecializer { | 23 class InvokeDynamicSpecializer { |
| 24 const InvokeDynamicSpecializer(); | 24 const InvokeDynamicSpecializer(); |
| 25 | 25 |
| 26 TypeMask computeTypeFromInputTypes( | 26 TypeMask computeTypeFromInputTypes( |
| 27 HInvokeDynamic instruction, Compiler compiler) { | 27 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 28 return TypeMaskFactory.inferredTypeForSelector( | 28 return TypeMaskFactory.inferredTypeForSelector( |
| 29 instruction.selector, instruction.mask, compiler); | 29 instruction.selector, instruction.mask, compiler); |
| 30 } | 30 } |
| 31 | 31 |
| 32 HInstruction tryConvertToBuiltin( | 32 HInstruction tryConvertToBuiltin( |
| 33 HInvokeDynamic instruction, Compiler compiler) { | 33 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 34 return null; | 34 return null; |
| 35 } | 35 } |
| 36 | 36 |
| 37 void clearAllSideEffects(HInstruction instruction) { | 37 void clearAllSideEffects(HInstruction instruction) { |
| 38 instruction.sideEffects.clearAllSideEffects(); | 38 instruction.sideEffects.clearAllSideEffects(); |
| 39 instruction.sideEffects.clearAllDependencies(); | 39 instruction.sideEffects.clearAllDependencies(); |
| 40 instruction.setUseGvn(); | 40 instruction.setUseGvn(); |
| 41 } | 41 } |
| 42 | 42 |
| 43 Operation operation(ConstantSystem constantSystem) => null; | 43 Operation operation(ConstantSystem constantSystem) => null; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 78 } | 78 } |
| 79 } | 79 } |
| 80 return const InvokeDynamicSpecializer(); | 80 return const InvokeDynamicSpecializer(); |
| 81 } | 81 } |
| 82 } | 82 } |
| 83 | 83 |
| 84 class IndexAssignSpecializer extends InvokeDynamicSpecializer { | 84 class IndexAssignSpecializer extends InvokeDynamicSpecializer { |
| 85 const IndexAssignSpecializer(); | 85 const IndexAssignSpecializer(); |
| 86 | 86 |
| 87 HInstruction tryConvertToBuiltin( | 87 HInstruction tryConvertToBuiltin( |
| 88 HInvokeDynamic instruction, Compiler compiler) { | 88 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 89 if (instruction.inputs[1].isMutableIndexable(compiler)) { | 89 if (instruction.inputs[1].isMutableIndexable(closedWorld)) { |
| 90 if (!instruction.inputs[2].isInteger(compiler) && | 90 if (!instruction.inputs[2].isInteger(closedWorld) && |
| 91 compiler.options.enableTypeAssertions) { | 91 compiler.options.enableTypeAssertions) { |
| 92 // We want the right checked mode error. | 92 // We want the right checked mode error. |
| 93 return null; | 93 return null; |
| 94 } | 94 } |
| 95 return new HIndexAssign(instruction.inputs[1], instruction.inputs[2], | 95 return new HIndexAssign(instruction.inputs[1], instruction.inputs[2], |
| 96 instruction.inputs[3], instruction.selector); | 96 instruction.inputs[3], instruction.selector); |
| 97 } | 97 } |
| 98 return null; | 98 return null; |
| 99 } | 99 } |
| 100 } | 100 } |
| 101 | 101 |
| 102 class IndexSpecializer extends InvokeDynamicSpecializer { | 102 class IndexSpecializer extends InvokeDynamicSpecializer { |
| 103 const IndexSpecializer(); | 103 const IndexSpecializer(); |
| 104 | 104 |
| 105 HInstruction tryConvertToBuiltin( | 105 HInstruction tryConvertToBuiltin( |
| 106 HInvokeDynamic instruction, Compiler compiler) { | 106 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 107 if (!instruction.inputs[1].isIndexablePrimitive(compiler)) return null; | 107 if (!instruction.inputs[1].isIndexablePrimitive(closedWorld)) return null; |
| 108 if (!instruction.inputs[2].isInteger(compiler) && | 108 if (!instruction.inputs[2].isInteger(closedWorld) && |
| 109 compiler.options.enableTypeAssertions) { | 109 compiler.options.enableTypeAssertions) { |
| 110 // We want the right checked mode error. | 110 // We want the right checked mode error. |
| 111 return null; | 111 return null; |
| 112 } | 112 } |
| 113 TypeMask receiverType = | 113 TypeMask receiverType = |
| 114 instruction.getDartReceiver(compiler).instructionType; | 114 instruction.getDartReceiver(compiler).instructionType; |
| 115 TypeMask type = TypeMaskFactory.inferredTypeForSelector( | 115 TypeMask type = TypeMaskFactory.inferredTypeForSelector( |
| 116 instruction.selector, receiverType, compiler); | 116 instruction.selector, receiverType, compiler); |
| 117 return new HIndex(instruction.inputs[1], instruction.inputs[2], | 117 return new HIndex(instruction.inputs[1], instruction.inputs[2], |
| 118 instruction.selector, type); | 118 instruction.selector, type); |
| 119 } | 119 } |
| 120 } | 120 } |
| 121 | 121 |
| 122 class BitNotSpecializer extends InvokeDynamicSpecializer { | 122 class BitNotSpecializer extends InvokeDynamicSpecializer { |
| 123 const BitNotSpecializer(); | 123 const BitNotSpecializer(); |
| 124 | 124 |
| 125 UnaryOperation operation(ConstantSystem constantSystem) { | 125 UnaryOperation operation(ConstantSystem constantSystem) { |
| 126 return constantSystem.bitNot; | 126 return constantSystem.bitNot; |
| 127 } | 127 } |
| 128 | 128 |
| 129 TypeMask computeTypeFromInputTypes( | 129 TypeMask computeTypeFromInputTypes( |
| 130 HInvokeDynamic instruction, Compiler compiler) { | 130 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 131 // All bitwise operations on primitive types either produce an | 131 // All bitwise operations on primitive types either produce an |
| 132 // integer or throw an error. | 132 // integer or throw an error. |
| 133 JavaScriptBackend backend = compiler.backend; | 133 if (instruction.inputs[1].isPrimitiveOrNull(closedWorld)) { |
| 134 if (instruction.inputs[1].isPrimitiveOrNull(compiler)) { | 134 return closedWorld.commonMasks.uint32Type; |
| 135 return backend.uint32Type; | |
| 136 } | 135 } |
| 137 return super.computeTypeFromInputTypes(instruction, compiler); | 136 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
| 138 } | 137 } |
| 139 | 138 |
| 140 HInstruction tryConvertToBuiltin( | 139 HInstruction tryConvertToBuiltin( |
| 141 HInvokeDynamic instruction, Compiler compiler) { | 140 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 142 HInstruction input = instruction.inputs[1]; | 141 HInstruction input = instruction.inputs[1]; |
| 143 if (input.isNumber(compiler)) { | 142 if (input.isNumber(closedWorld)) { |
| 144 return new HBitNot(input, instruction.selector, | 143 return new HBitNot(input, instruction.selector, |
| 145 computeTypeFromInputTypes(instruction, compiler)); | 144 computeTypeFromInputTypes(instruction, compiler, closedWorld)); |
| 146 } | 145 } |
| 147 return null; | 146 return null; |
| 148 } | 147 } |
| 149 } | 148 } |
| 150 | 149 |
| 151 class UnaryNegateSpecializer extends InvokeDynamicSpecializer { | 150 class UnaryNegateSpecializer extends InvokeDynamicSpecializer { |
| 152 const UnaryNegateSpecializer(); | 151 const UnaryNegateSpecializer(); |
| 153 | 152 |
| 154 UnaryOperation operation(ConstantSystem constantSystem) { | 153 UnaryOperation operation(ConstantSystem constantSystem) { |
| 155 return constantSystem.negate; | 154 return constantSystem.negate; |
| 156 } | 155 } |
| 157 | 156 |
| 158 TypeMask computeTypeFromInputTypes( | 157 TypeMask computeTypeFromInputTypes( |
| 159 HInvokeDynamic instruction, Compiler compiler) { | 158 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 160 TypeMask operandType = instruction.inputs[1].instructionType; | 159 TypeMask operandType = instruction.inputs[1].instructionType; |
| 161 if (instruction.inputs[1].isNumberOrNull(compiler)) return operandType; | 160 if (instruction.inputs[1].isNumberOrNull(closedWorld)) return operandType; |
| 162 return super.computeTypeFromInputTypes(instruction, compiler); | 161 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
| 163 } | 162 } |
| 164 | 163 |
| 165 HInstruction tryConvertToBuiltin( | 164 HInstruction tryConvertToBuiltin( |
| 166 HInvokeDynamic instruction, Compiler compiler) { | 165 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 167 HInstruction input = instruction.inputs[1]; | 166 HInstruction input = instruction.inputs[1]; |
| 168 if (input.isNumber(compiler)) { | 167 if (input.isNumber(closedWorld)) { |
| 169 return new HNegate(input, instruction.selector, input.instructionType); | 168 return new HNegate(input, instruction.selector, input.instructionType); |
| 170 } | 169 } |
| 171 return null; | 170 return null; |
| 172 } | 171 } |
| 173 } | 172 } |
| 174 | 173 |
| 175 abstract class BinaryArithmeticSpecializer extends InvokeDynamicSpecializer { | 174 abstract class BinaryArithmeticSpecializer extends InvokeDynamicSpecializer { |
| 176 const BinaryArithmeticSpecializer(); | 175 const BinaryArithmeticSpecializer(); |
| 177 | 176 |
| 178 TypeMask computeTypeFromInputTypes( | 177 TypeMask computeTypeFromInputTypes( |
| 179 HInvokeDynamic instruction, Compiler compiler) { | 178 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 180 HInstruction left = instruction.inputs[1]; | 179 HInstruction left = instruction.inputs[1]; |
| 181 HInstruction right = instruction.inputs[2]; | 180 HInstruction right = instruction.inputs[2]; |
| 182 JavaScriptBackend backend = compiler.backend; | 181 if (left.isIntegerOrNull(closedWorld) && |
| 183 if (left.isIntegerOrNull(compiler) && right.isIntegerOrNull(compiler)) { | 182 right.isIntegerOrNull(closedWorld)) { |
| 184 return backend.intType; | 183 return closedWorld.commonMasks.intType; |
| 185 } | 184 } |
| 186 if (left.isNumberOrNull(compiler)) { | 185 if (left.isNumberOrNull(closedWorld)) { |
| 187 if (left.isDoubleOrNull(compiler) || right.isDoubleOrNull(compiler)) { | 186 if (left.isDoubleOrNull(closedWorld) || |
| 188 return backend.doubleType; | 187 right.isDoubleOrNull(closedWorld)) { |
| 188 return closedWorld.commonMasks.doubleType; |
| 189 } | 189 } |
| 190 return backend.numType; | 190 return closedWorld.commonMasks.numType; |
| 191 } | 191 } |
| 192 return super.computeTypeFromInputTypes(instruction, compiler); | 192 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
| 193 } | 193 } |
| 194 | 194 |
| 195 bool isBuiltin(HInvokeDynamic instruction, Compiler compiler) { | 195 bool isBuiltin(HInvokeDynamic instruction, ClosedWorld closedWorld) { |
| 196 return instruction.inputs[1].isNumber(compiler) && | 196 return instruction.inputs[1].isNumber(closedWorld) && |
| 197 instruction.inputs[2].isNumber(compiler); | 197 instruction.inputs[2].isNumber(closedWorld); |
| 198 } | 198 } |
| 199 | 199 |
| 200 HInstruction tryConvertToBuiltin( | 200 HInstruction tryConvertToBuiltin( |
| 201 HInvokeDynamic instruction, Compiler compiler) { | 201 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 202 if (isBuiltin(instruction, compiler)) { | 202 if (isBuiltin(instruction, closedWorld)) { |
| 203 HInstruction builtin = newBuiltinVariant(instruction, compiler); | 203 HInstruction builtin = |
| 204 newBuiltinVariant(instruction, compiler, closedWorld); |
| 204 if (builtin != null) return builtin; | 205 if (builtin != null) return builtin; |
| 205 // Even if there is no builtin equivalent instruction, we know | 206 // Even if there is no builtin equivalent instruction, we know |
| 206 // the instruction does not have any side effect, and that it | 207 // the instruction does not have any side effect, and that it |
| 207 // can be GVN'ed. | 208 // can be GVN'ed. |
| 208 clearAllSideEffects(instruction); | 209 clearAllSideEffects(instruction); |
| 209 } | 210 } |
| 210 return null; | 211 return null; |
| 211 } | 212 } |
| 212 | 213 |
| 213 bool inputsArePositiveIntegers(HInstruction instruction, Compiler compiler) { | 214 bool inputsArePositiveIntegers( |
| 215 HInstruction instruction, ClosedWorld closedWorld) { |
| 214 HInstruction left = instruction.inputs[1]; | 216 HInstruction left = instruction.inputs[1]; |
| 215 HInstruction right = instruction.inputs[2]; | 217 HInstruction right = instruction.inputs[2]; |
| 216 return left.isPositiveIntegerOrNull(compiler) && | 218 return left.isPositiveIntegerOrNull(closedWorld) && |
| 217 right.isPositiveIntegerOrNull(compiler); | 219 right.isPositiveIntegerOrNull(closedWorld); |
| 218 } | 220 } |
| 219 | 221 |
| 220 bool inputsAreUInt31(HInstruction instruction, Compiler compiler) { | 222 bool inputsAreUInt31(HInstruction instruction, ClosedWorld closedWorld) { |
| 221 HInstruction left = instruction.inputs[1]; | 223 HInstruction left = instruction.inputs[1]; |
| 222 HInstruction right = instruction.inputs[2]; | 224 HInstruction right = instruction.inputs[2]; |
| 223 return left.isUInt31(compiler) && right.isUInt31(compiler); | 225 return left.isUInt31(closedWorld) && right.isUInt31(closedWorld); |
| 224 } | 226 } |
| 225 | 227 |
| 226 HInstruction newBuiltinVariant(HInvokeDynamic instruction, Compiler compiler); | 228 HInstruction newBuiltinVariant( |
| 229 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld); |
| 227 | 230 |
| 228 Selector renameToOptimizedSelector( | 231 Selector renameToOptimizedSelector( |
| 229 String name, Selector selector, Compiler compiler) { | 232 String name, Selector selector, Compiler compiler) { |
| 230 if (selector.name == name) return selector; | 233 if (selector.name == name) return selector; |
| 231 JavaScriptBackend backend = compiler.backend; | 234 JavaScriptBackend backend = compiler.backend; |
| 232 return new Selector.call( | 235 return new Selector.call( |
| 233 new Name(name, backend.helpers.interceptorsLibrary), | 236 new Name(name, backend.helpers.interceptorsLibrary), |
| 234 new CallStructure(selector.argumentCount)); | 237 new CallStructure(selector.argumentCount)); |
| 235 } | 238 } |
| 236 } | 239 } |
| 237 | 240 |
| 238 class AddSpecializer extends BinaryArithmeticSpecializer { | 241 class AddSpecializer extends BinaryArithmeticSpecializer { |
| 239 const AddSpecializer(); | 242 const AddSpecializer(); |
| 240 | 243 |
| 241 TypeMask computeTypeFromInputTypes( | 244 TypeMask computeTypeFromInputTypes( |
| 242 HInvokeDynamic instruction, Compiler compiler) { | 245 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 243 if (inputsAreUInt31(instruction, compiler)) { | 246 if (inputsAreUInt31(instruction, closedWorld)) { |
| 244 JavaScriptBackend backend = compiler.backend; | 247 return closedWorld.commonMasks.uint32Type; |
| 245 return backend.uint32Type; | |
| 246 } | 248 } |
| 247 if (inputsArePositiveIntegers(instruction, compiler)) { | 249 if (inputsArePositiveIntegers(instruction, closedWorld)) { |
| 248 JavaScriptBackend backend = compiler.backend; | 250 return closedWorld.commonMasks.positiveIntType; |
| 249 return backend.positiveIntType; | |
| 250 } | 251 } |
| 251 return super.computeTypeFromInputTypes(instruction, compiler); | 252 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
| 252 } | 253 } |
| 253 | 254 |
| 254 BinaryOperation operation(ConstantSystem constantSystem) { | 255 BinaryOperation operation(ConstantSystem constantSystem) { |
| 255 return constantSystem.add; | 256 return constantSystem.add; |
| 256 } | 257 } |
| 257 | 258 |
| 258 HInstruction newBuiltinVariant( | 259 HInstruction newBuiltinVariant( |
| 259 HInvokeDynamic instruction, Compiler compiler) { | 260 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 260 return new HAdd(instruction.inputs[1], instruction.inputs[2], | 261 return new HAdd( |
| 261 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); | 262 instruction.inputs[1], |
| 263 instruction.inputs[2], |
| 264 instruction.selector, |
| 265 computeTypeFromInputTypes(instruction, compiler, closedWorld)); |
| 262 } | 266 } |
| 263 } | 267 } |
| 264 | 268 |
| 265 class DivideSpecializer extends BinaryArithmeticSpecializer { | 269 class DivideSpecializer extends BinaryArithmeticSpecializer { |
| 266 const DivideSpecializer(); | 270 const DivideSpecializer(); |
| 267 | 271 |
| 268 BinaryOperation operation(ConstantSystem constantSystem) { | 272 BinaryOperation operation(ConstantSystem constantSystem) { |
| 269 return constantSystem.divide; | 273 return constantSystem.divide; |
| 270 } | 274 } |
| 271 | 275 |
| 272 TypeMask computeTypeFromInputTypes( | 276 TypeMask computeTypeFromInputTypes( |
| 273 HInstruction instruction, Compiler compiler) { | 277 HInstruction instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 274 HInstruction left = instruction.inputs[1]; | 278 HInstruction left = instruction.inputs[1]; |
| 275 JavaScriptBackend backend = compiler.backend; | 279 if (left.isNumberOrNull(closedWorld)) { |
| 276 if (left.isNumberOrNull(compiler)) { | 280 return closedWorld.commonMasks.doubleType; |
| 277 return backend.doubleType; | |
| 278 } | 281 } |
| 279 return super.computeTypeFromInputTypes(instruction, compiler); | 282 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
| 280 } | 283 } |
| 281 | 284 |
| 282 HInstruction newBuiltinVariant( | 285 HInstruction newBuiltinVariant( |
| 283 HInvokeDynamic instruction, Compiler compiler) { | 286 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 284 JavaScriptBackend backend = compiler.backend; | |
| 285 return new HDivide(instruction.inputs[1], instruction.inputs[2], | 287 return new HDivide(instruction.inputs[1], instruction.inputs[2], |
| 286 instruction.selector, backend.doubleType); | 288 instruction.selector, closedWorld.commonMasks.doubleType); |
| 287 } | 289 } |
| 288 } | 290 } |
| 289 | 291 |
| 290 class ModuloSpecializer extends BinaryArithmeticSpecializer { | 292 class ModuloSpecializer extends BinaryArithmeticSpecializer { |
| 291 const ModuloSpecializer(); | 293 const ModuloSpecializer(); |
| 292 | 294 |
| 293 TypeMask computeTypeFromInputTypes( | 295 TypeMask computeTypeFromInputTypes( |
| 294 HInvokeDynamic instruction, Compiler compiler) { | 296 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 295 if (inputsArePositiveIntegers(instruction, compiler)) { | 297 if (inputsArePositiveIntegers(instruction, closedWorld)) { |
| 296 JavaScriptBackend backend = compiler.backend; | 298 return closedWorld.commonMasks.positiveIntType; |
| 297 return backend.positiveIntType; | |
| 298 } | 299 } |
| 299 return super.computeTypeFromInputTypes(instruction, compiler); | 300 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
| 300 } | 301 } |
| 301 | 302 |
| 302 BinaryOperation operation(ConstantSystem constantSystem) { | 303 BinaryOperation operation(ConstantSystem constantSystem) { |
| 303 return constantSystem.modulo; | 304 return constantSystem.modulo; |
| 304 } | 305 } |
| 305 | 306 |
| 306 HInstruction newBuiltinVariant( | 307 HInstruction newBuiltinVariant( |
| 307 HInvokeDynamic instruction, Compiler compiler) { | 308 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 308 // Modulo cannot be mapped to the native operator (different semantics). | 309 // Modulo cannot be mapped to the native operator (different semantics). |
| 309 // TODO(sra): For non-negative values we can use JavaScript's %. | 310 // TODO(sra): For non-negative values we can use JavaScript's %. |
| 310 return null; | 311 return null; |
| 311 } | 312 } |
| 312 } | 313 } |
| 313 | 314 |
| 314 class MultiplySpecializer extends BinaryArithmeticSpecializer { | 315 class MultiplySpecializer extends BinaryArithmeticSpecializer { |
| 315 const MultiplySpecializer(); | 316 const MultiplySpecializer(); |
| 316 | 317 |
| 317 BinaryOperation operation(ConstantSystem constantSystem) { | 318 BinaryOperation operation(ConstantSystem constantSystem) { |
| 318 return constantSystem.multiply; | 319 return constantSystem.multiply; |
| 319 } | 320 } |
| 320 | 321 |
| 321 TypeMask computeTypeFromInputTypes( | 322 TypeMask computeTypeFromInputTypes( |
| 322 HInvokeDynamic instruction, Compiler compiler) { | 323 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 323 if (inputsArePositiveIntegers(instruction, compiler)) { | 324 if (inputsArePositiveIntegers(instruction, closedWorld)) { |
| 324 JavaScriptBackend backend = compiler.backend; | 325 return closedWorld.commonMasks.positiveIntType; |
| 325 return backend.positiveIntType; | |
| 326 } | 326 } |
| 327 return super.computeTypeFromInputTypes(instruction, compiler); | 327 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
| 328 } | 328 } |
| 329 | 329 |
| 330 HInstruction newBuiltinVariant( | 330 HInstruction newBuiltinVariant( |
| 331 HInvokeDynamic instruction, Compiler compiler) { | 331 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 332 return new HMultiply(instruction.inputs[1], instruction.inputs[2], | 332 return new HMultiply( |
| 333 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); | 333 instruction.inputs[1], |
| 334 instruction.inputs[2], |
| 335 instruction.selector, |
| 336 computeTypeFromInputTypes(instruction, compiler, closedWorld)); |
| 334 } | 337 } |
| 335 } | 338 } |
| 336 | 339 |
| 337 class SubtractSpecializer extends BinaryArithmeticSpecializer { | 340 class SubtractSpecializer extends BinaryArithmeticSpecializer { |
| 338 const SubtractSpecializer(); | 341 const SubtractSpecializer(); |
| 339 | 342 |
| 340 BinaryOperation operation(ConstantSystem constantSystem) { | 343 BinaryOperation operation(ConstantSystem constantSystem) { |
| 341 return constantSystem.subtract; | 344 return constantSystem.subtract; |
| 342 } | 345 } |
| 343 | 346 |
| 344 HInstruction newBuiltinVariant( | 347 HInstruction newBuiltinVariant( |
| 345 HInvokeDynamic instruction, Compiler compiler) { | 348 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 346 return new HSubtract(instruction.inputs[1], instruction.inputs[2], | 349 return new HSubtract( |
| 347 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); | 350 instruction.inputs[1], |
| 351 instruction.inputs[2], |
| 352 instruction.selector, |
| 353 computeTypeFromInputTypes(instruction, compiler, closedWorld)); |
| 348 } | 354 } |
| 349 } | 355 } |
| 350 | 356 |
| 351 class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer { | 357 class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer { |
| 352 const TruncatingDivideSpecializer(); | 358 const TruncatingDivideSpecializer(); |
| 353 | 359 |
| 354 BinaryOperation operation(ConstantSystem constantSystem) { | 360 BinaryOperation operation(ConstantSystem constantSystem) { |
| 355 return constantSystem.truncatingDivide; | 361 return constantSystem.truncatingDivide; |
| 356 } | 362 } |
| 357 | 363 |
| 358 TypeMask computeTypeFromInputTypes( | 364 TypeMask computeTypeFromInputTypes( |
| 359 HInvokeDynamic instruction, Compiler compiler) { | 365 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 360 JavaScriptBackend backend = compiler.backend; | 366 if (hasUint31Result(instruction, closedWorld)) { |
| 361 if (hasUint31Result(instruction, compiler)) { | 367 return closedWorld.commonMasks.uint31Type; |
| 362 return backend.uint31Type; | |
| 363 } | 368 } |
| 364 if (inputsArePositiveIntegers(instruction, compiler)) { | 369 if (inputsArePositiveIntegers(instruction, closedWorld)) { |
| 365 return backend.positiveIntType; | 370 return closedWorld.commonMasks.positiveIntType; |
| 366 } | 371 } |
| 367 return super.computeTypeFromInputTypes(instruction, compiler); | 372 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
| 368 } | 373 } |
| 369 | 374 |
| 370 bool isNotZero(HInstruction instruction, Compiler compiler) { | 375 bool isNotZero(HInstruction instruction) { |
| 371 if (!instruction.isConstantInteger()) return false; | 376 if (!instruction.isConstantInteger()) return false; |
| 372 HConstant rightConstant = instruction; | 377 HConstant rightConstant = instruction; |
| 373 IntConstantValue intConstant = rightConstant.constant; | 378 IntConstantValue intConstant = rightConstant.constant; |
| 374 int count = intConstant.primitiveValue; | 379 int count = intConstant.primitiveValue; |
| 375 return count != 0; | 380 return count != 0; |
| 376 } | 381 } |
| 377 | 382 |
| 378 bool isTwoOrGreater(HInstruction instruction, Compiler compiler) { | 383 bool isTwoOrGreater(HInstruction instruction) { |
| 379 if (!instruction.isConstantInteger()) return false; | 384 if (!instruction.isConstantInteger()) return false; |
| 380 HConstant rightConstant = instruction; | 385 HConstant rightConstant = instruction; |
| 381 IntConstantValue intConstant = rightConstant.constant; | 386 IntConstantValue intConstant = rightConstant.constant; |
| 382 int count = intConstant.primitiveValue; | 387 int count = intConstant.primitiveValue; |
| 383 return count >= 2; | 388 return count >= 2; |
| 384 } | 389 } |
| 385 | 390 |
| 386 bool hasUint31Result(HInstruction instruction, Compiler compiler) { | 391 bool hasUint31Result(HInstruction instruction, ClosedWorld closedWorld) { |
| 387 HInstruction left = instruction.inputs[1]; | 392 HInstruction left = instruction.inputs[1]; |
| 388 HInstruction right = instruction.inputs[2]; | 393 HInstruction right = instruction.inputs[2]; |
| 389 if (right.isPositiveInteger(compiler)) { | 394 if (right.isPositiveInteger(closedWorld)) { |
| 390 if (left.isUInt31(compiler) && isNotZero(right, compiler)) { | 395 if (left.isUInt31(closedWorld) && isNotZero(right)) { |
| 391 return true; | 396 return true; |
| 392 } | 397 } |
| 393 if (left.isUInt32(compiler) && isTwoOrGreater(right, compiler)) { | 398 if (left.isUInt32(closedWorld) && isTwoOrGreater(right)) { |
| 394 return true; | 399 return true; |
| 395 } | 400 } |
| 396 } | 401 } |
| 397 return false; | 402 return false; |
| 398 } | 403 } |
| 399 | 404 |
| 400 HInstruction tryConvertToBuiltin( | 405 HInstruction tryConvertToBuiltin( |
| 401 HInvokeDynamic instruction, Compiler compiler) { | 406 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 402 HInstruction right = instruction.inputs[2]; | 407 HInstruction right = instruction.inputs[2]; |
| 403 if (isBuiltin(instruction, compiler)) { | 408 if (isBuiltin(instruction, closedWorld)) { |
| 404 if (right.isPositiveInteger(compiler) && isNotZero(right, compiler)) { | 409 if (right.isPositiveInteger(closedWorld) && isNotZero(right)) { |
| 405 if (hasUint31Result(instruction, compiler)) { | 410 if (hasUint31Result(instruction, closedWorld)) { |
| 406 return newBuiltinVariant(instruction, compiler); | 411 return newBuiltinVariant(instruction, compiler, closedWorld); |
| 407 } | 412 } |
| 408 // We can call _tdivFast because the rhs is a 32bit integer | 413 // We can call _tdivFast because the rhs is a 32bit integer |
| 409 // and not 0, nor -1. | 414 // and not 0, nor -1. |
| 410 instruction.selector = renameToOptimizedSelector( | 415 instruction.selector = renameToOptimizedSelector( |
| 411 '_tdivFast', instruction.selector, compiler); | 416 '_tdivFast', instruction.selector, compiler); |
| 412 } | 417 } |
| 413 clearAllSideEffects(instruction); | 418 clearAllSideEffects(instruction); |
| 414 } | 419 } |
| 415 return null; | 420 return null; |
| 416 } | 421 } |
| 417 | 422 |
| 418 HInstruction newBuiltinVariant( | 423 HInstruction newBuiltinVariant( |
| 419 HInvokeDynamic instruction, Compiler compiler) { | 424 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 420 return new HTruncatingDivide(instruction.inputs[1], instruction.inputs[2], | 425 return new HTruncatingDivide( |
| 421 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); | 426 instruction.inputs[1], |
| 427 instruction.inputs[2], |
| 428 instruction.selector, |
| 429 computeTypeFromInputTypes(instruction, compiler, closedWorld)); |
| 422 } | 430 } |
| 423 } | 431 } |
| 424 | 432 |
| 425 abstract class BinaryBitOpSpecializer extends BinaryArithmeticSpecializer { | 433 abstract class BinaryBitOpSpecializer extends BinaryArithmeticSpecializer { |
| 426 const BinaryBitOpSpecializer(); | 434 const BinaryBitOpSpecializer(); |
| 427 | 435 |
| 428 TypeMask computeTypeFromInputTypes( | 436 TypeMask computeTypeFromInputTypes( |
| 429 HInvokeDynamic instruction, Compiler compiler) { | 437 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 430 // All bitwise operations on primitive types either produce an | 438 // All bitwise operations on primitive types either produce an |
| 431 // integer or throw an error. | 439 // integer or throw an error. |
| 432 HInstruction left = instruction.inputs[1]; | 440 HInstruction left = instruction.inputs[1]; |
| 433 JavaScriptBackend backend = compiler.backend; | 441 if (left.isPrimitiveOrNull(closedWorld)) { |
| 434 if (left.isPrimitiveOrNull(compiler)) { | 442 return closedWorld.commonMasks.uint32Type; |
| 435 return backend.uint32Type; | |
| 436 } | 443 } |
| 437 return super.computeTypeFromInputTypes(instruction, compiler); | 444 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
| 438 } | 445 } |
| 439 | 446 |
| 440 bool argumentLessThan32(HInstruction instruction) { | 447 bool argumentLessThan32(HInstruction instruction) { |
| 441 if (!instruction.isConstantInteger()) return false; | 448 if (!instruction.isConstantInteger()) return false; |
| 442 HConstant rightConstant = instruction; | 449 HConstant rightConstant = instruction; |
| 443 IntConstantValue intConstant = rightConstant.constant; | 450 IntConstantValue intConstant = rightConstant.constant; |
| 444 int count = intConstant.primitiveValue; | 451 int count = intConstant.primitiveValue; |
| 445 return count >= 0 && count <= 31; | 452 return count >= 0 && count <= 31; |
| 446 } | 453 } |
| 447 | 454 |
| 448 bool isPositive(HInstruction instruction, Compiler compiler) { | 455 bool isPositive(HInstruction instruction, ClosedWorld closedWorld) { |
| 449 // TODO: We should use the value range analysis. Currently, ranges | 456 // TODO: We should use the value range analysis. Currently, ranges |
| 450 // are discarded just after the analysis. | 457 // are discarded just after the analysis. |
| 451 return instruction.isPositiveInteger(compiler); | 458 return instruction.isPositiveInteger(closedWorld); |
| 452 } | 459 } |
| 453 } | 460 } |
| 454 | 461 |
| 455 class ShiftLeftSpecializer extends BinaryBitOpSpecializer { | 462 class ShiftLeftSpecializer extends BinaryBitOpSpecializer { |
| 456 const ShiftLeftSpecializer(); | 463 const ShiftLeftSpecializer(); |
| 457 | 464 |
| 458 BinaryOperation operation(ConstantSystem constantSystem) { | 465 BinaryOperation operation(ConstantSystem constantSystem) { |
| 459 return constantSystem.shiftLeft; | 466 return constantSystem.shiftLeft; |
| 460 } | 467 } |
| 461 | 468 |
| 462 HInstruction tryConvertToBuiltin( | 469 HInstruction tryConvertToBuiltin( |
| 463 HInvokeDynamic instruction, Compiler compiler) { | 470 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 464 HInstruction left = instruction.inputs[1]; | 471 HInstruction left = instruction.inputs[1]; |
| 465 HInstruction right = instruction.inputs[2]; | 472 HInstruction right = instruction.inputs[2]; |
| 466 if (left.isNumber(compiler)) { | 473 if (left.isNumber(closedWorld)) { |
| 467 if (argumentLessThan32(right)) { | 474 if (argumentLessThan32(right)) { |
| 468 return newBuiltinVariant(instruction, compiler); | 475 return newBuiltinVariant(instruction, compiler, closedWorld); |
| 469 } | 476 } |
| 470 // Even if there is no builtin equivalent instruction, we know | 477 // Even if there is no builtin equivalent instruction, we know |
| 471 // the instruction does not have any side effect, and that it | 478 // the instruction does not have any side effect, and that it |
| 472 // can be GVN'ed. | 479 // can be GVN'ed. |
| 473 clearAllSideEffects(instruction); | 480 clearAllSideEffects(instruction); |
| 474 if (isPositive(right, compiler)) { | 481 if (isPositive(right, closedWorld)) { |
| 475 instruction.selector = renameToOptimizedSelector( | 482 instruction.selector = renameToOptimizedSelector( |
| 476 '_shlPositive', instruction.selector, compiler); | 483 '_shlPositive', instruction.selector, compiler); |
| 477 } | 484 } |
| 478 } | 485 } |
| 479 return null; | 486 return null; |
| 480 } | 487 } |
| 481 | 488 |
| 482 HInstruction newBuiltinVariant( | 489 HInstruction newBuiltinVariant( |
| 483 HInvokeDynamic instruction, Compiler compiler) { | 490 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 484 return new HShiftLeft(instruction.inputs[1], instruction.inputs[2], | 491 return new HShiftLeft( |
| 485 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); | 492 instruction.inputs[1], |
| 493 instruction.inputs[2], |
| 494 instruction.selector, |
| 495 computeTypeFromInputTypes(instruction, compiler, closedWorld)); |
| 486 } | 496 } |
| 487 } | 497 } |
| 488 | 498 |
| 489 class ShiftRightSpecializer extends BinaryBitOpSpecializer { | 499 class ShiftRightSpecializer extends BinaryBitOpSpecializer { |
| 490 const ShiftRightSpecializer(); | 500 const ShiftRightSpecializer(); |
| 491 | 501 |
| 492 TypeMask computeTypeFromInputTypes( | 502 TypeMask computeTypeFromInputTypes( |
| 493 HInvokeDynamic instruction, Compiler compiler) { | 503 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 494 HInstruction left = instruction.inputs[1]; | 504 HInstruction left = instruction.inputs[1]; |
| 495 if (left.isUInt32(compiler)) return left.instructionType; | 505 if (left.isUInt32(closedWorld)) return left.instructionType; |
| 496 return super.computeTypeFromInputTypes(instruction, compiler); | 506 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
| 497 } | 507 } |
| 498 | 508 |
| 499 HInstruction tryConvertToBuiltin( | 509 HInstruction tryConvertToBuiltin( |
| 500 HInvokeDynamic instruction, Compiler compiler) { | 510 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 501 HInstruction left = instruction.inputs[1]; | 511 HInstruction left = instruction.inputs[1]; |
| 502 HInstruction right = instruction.inputs[2]; | 512 HInstruction right = instruction.inputs[2]; |
| 503 if (left.isNumber(compiler)) { | 513 if (left.isNumber(closedWorld)) { |
| 504 if (argumentLessThan32(right) && isPositive(left, compiler)) { | 514 if (argumentLessThan32(right) && isPositive(left, closedWorld)) { |
| 505 return newBuiltinVariant(instruction, compiler); | 515 return newBuiltinVariant(instruction, compiler, closedWorld); |
| 506 } | 516 } |
| 507 // Even if there is no builtin equivalent instruction, we know | 517 // Even if there is no builtin equivalent instruction, we know |
| 508 // the instruction does not have any side effect, and that it | 518 // the instruction does not have any side effect, and that it |
| 509 // can be GVN'ed. | 519 // can be GVN'ed. |
| 510 clearAllSideEffects(instruction); | 520 clearAllSideEffects(instruction); |
| 511 if (isPositive(right, compiler) && isPositive(left, compiler)) { | 521 if (isPositive(right, closedWorld) && isPositive(left, closedWorld)) { |
| 512 instruction.selector = renameToOptimizedSelector( | 522 instruction.selector = renameToOptimizedSelector( |
| 513 '_shrBothPositive', instruction.selector, compiler); | 523 '_shrBothPositive', instruction.selector, compiler); |
| 514 } else if (isPositive(left, compiler) && right.isNumber(compiler)) { | 524 } else if (isPositive(left, closedWorld) && right.isNumber(closedWorld)) { |
| 515 instruction.selector = renameToOptimizedSelector( | 525 instruction.selector = renameToOptimizedSelector( |
| 516 '_shrReceiverPositive', instruction.selector, compiler); | 526 '_shrReceiverPositive', instruction.selector, compiler); |
| 517 } else if (isPositive(right, compiler)) { | 527 } else if (isPositive(right, closedWorld)) { |
| 518 instruction.selector = renameToOptimizedSelector( | 528 instruction.selector = renameToOptimizedSelector( |
| 519 '_shrOtherPositive', instruction.selector, compiler); | 529 '_shrOtherPositive', instruction.selector, compiler); |
| 520 } | 530 } |
| 521 } | 531 } |
| 522 return null; | 532 return null; |
| 523 } | 533 } |
| 524 | 534 |
| 525 HInstruction newBuiltinVariant( | 535 HInstruction newBuiltinVariant( |
| 526 HInvokeDynamic instruction, Compiler compiler) { | 536 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 527 return new HShiftRight(instruction.inputs[1], instruction.inputs[2], | 537 return new HShiftRight( |
| 528 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); | 538 instruction.inputs[1], |
| 539 instruction.inputs[2], |
| 540 instruction.selector, |
| 541 computeTypeFromInputTypes(instruction, compiler, closedWorld)); |
| 529 } | 542 } |
| 530 | 543 |
| 531 BinaryOperation operation(ConstantSystem constantSystem) { | 544 BinaryOperation operation(ConstantSystem constantSystem) { |
| 532 return constantSystem.shiftRight; | 545 return constantSystem.shiftRight; |
| 533 } | 546 } |
| 534 } | 547 } |
| 535 | 548 |
| 536 class BitOrSpecializer extends BinaryBitOpSpecializer { | 549 class BitOrSpecializer extends BinaryBitOpSpecializer { |
| 537 const BitOrSpecializer(); | 550 const BitOrSpecializer(); |
| 538 | 551 |
| 539 BinaryOperation operation(ConstantSystem constantSystem) { | 552 BinaryOperation operation(ConstantSystem constantSystem) { |
| 540 return constantSystem.bitOr; | 553 return constantSystem.bitOr; |
| 541 } | 554 } |
| 542 | 555 |
| 543 TypeMask computeTypeFromInputTypes( | 556 TypeMask computeTypeFromInputTypes( |
| 544 HInvokeDynamic instruction, Compiler compiler) { | 557 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 545 HInstruction left = instruction.inputs[1]; | 558 HInstruction left = instruction.inputs[1]; |
| 546 HInstruction right = instruction.inputs[2]; | 559 HInstruction right = instruction.inputs[2]; |
| 547 JavaScriptBackend backend = compiler.backend; | 560 if (left.isUInt31(closedWorld) && right.isUInt31(closedWorld)) { |
| 548 if (left.isUInt31(compiler) && right.isUInt31(compiler)) { | 561 return closedWorld.commonMasks.uint31Type; |
| 549 return backend.uint31Type; | |
| 550 } | 562 } |
| 551 return super.computeTypeFromInputTypes(instruction, compiler); | 563 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
| 552 } | 564 } |
| 553 | 565 |
| 554 HInstruction newBuiltinVariant( | 566 HInstruction newBuiltinVariant( |
| 555 HInvokeDynamic instruction, Compiler compiler) { | 567 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 556 return new HBitOr(instruction.inputs[1], instruction.inputs[2], | 568 return new HBitOr( |
| 557 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); | 569 instruction.inputs[1], |
| 570 instruction.inputs[2], |
| 571 instruction.selector, |
| 572 computeTypeFromInputTypes(instruction, compiler, closedWorld)); |
| 558 } | 573 } |
| 559 } | 574 } |
| 560 | 575 |
| 561 class BitAndSpecializer extends BinaryBitOpSpecializer { | 576 class BitAndSpecializer extends BinaryBitOpSpecializer { |
| 562 const BitAndSpecializer(); | 577 const BitAndSpecializer(); |
| 563 | 578 |
| 564 BinaryOperation operation(ConstantSystem constantSystem) { | 579 BinaryOperation operation(ConstantSystem constantSystem) { |
| 565 return constantSystem.bitAnd; | 580 return constantSystem.bitAnd; |
| 566 } | 581 } |
| 567 | 582 |
| 568 TypeMask computeTypeFromInputTypes( | 583 TypeMask computeTypeFromInputTypes( |
| 569 HInvokeDynamic instruction, Compiler compiler) { | 584 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 570 HInstruction left = instruction.inputs[1]; | 585 HInstruction left = instruction.inputs[1]; |
| 571 HInstruction right = instruction.inputs[2]; | 586 HInstruction right = instruction.inputs[2]; |
| 572 JavaScriptBackend backend = compiler.backend; | 587 if (left.isPrimitiveOrNull(closedWorld) && |
| 573 if (left.isPrimitiveOrNull(compiler) && | 588 (left.isUInt31(closedWorld) || right.isUInt31(closedWorld))) { |
| 574 (left.isUInt31(compiler) || right.isUInt31(compiler))) { | 589 return closedWorld.commonMasks.uint31Type; |
| 575 return backend.uint31Type; | |
| 576 } | 590 } |
| 577 return super.computeTypeFromInputTypes(instruction, compiler); | 591 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
| 578 } | 592 } |
| 579 | 593 |
| 580 HInstruction newBuiltinVariant( | 594 HInstruction newBuiltinVariant( |
| 581 HInvokeDynamic instruction, Compiler compiler) { | 595 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 582 return new HBitAnd(instruction.inputs[1], instruction.inputs[2], | 596 return new HBitAnd( |
| 583 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); | 597 instruction.inputs[1], |
| 598 instruction.inputs[2], |
| 599 instruction.selector, |
| 600 computeTypeFromInputTypes(instruction, compiler, closedWorld)); |
| 584 } | 601 } |
| 585 } | 602 } |
| 586 | 603 |
| 587 class BitXorSpecializer extends BinaryBitOpSpecializer { | 604 class BitXorSpecializer extends BinaryBitOpSpecializer { |
| 588 const BitXorSpecializer(); | 605 const BitXorSpecializer(); |
| 589 | 606 |
| 590 BinaryOperation operation(ConstantSystem constantSystem) { | 607 BinaryOperation operation(ConstantSystem constantSystem) { |
| 591 return constantSystem.bitXor; | 608 return constantSystem.bitXor; |
| 592 } | 609 } |
| 593 | 610 |
| 594 TypeMask computeTypeFromInputTypes( | 611 TypeMask computeTypeFromInputTypes( |
| 595 HInvokeDynamic instruction, Compiler compiler) { | 612 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 596 HInstruction left = instruction.inputs[1]; | 613 HInstruction left = instruction.inputs[1]; |
| 597 HInstruction right = instruction.inputs[2]; | 614 HInstruction right = instruction.inputs[2]; |
| 598 JavaScriptBackend backend = compiler.backend; | 615 if (left.isUInt31(closedWorld) && right.isUInt31(closedWorld)) { |
| 599 if (left.isUInt31(compiler) && right.isUInt31(compiler)) { | 616 return closedWorld.commonMasks.uint31Type; |
| 600 return backend.uint31Type; | |
| 601 } | 617 } |
| 602 return super.computeTypeFromInputTypes(instruction, compiler); | 618 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
| 603 } | 619 } |
| 604 | 620 |
| 605 HInstruction newBuiltinVariant( | 621 HInstruction newBuiltinVariant( |
| 606 HInvokeDynamic instruction, Compiler compiler) { | 622 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 607 return new HBitXor(instruction.inputs[1], instruction.inputs[2], | 623 return new HBitXor( |
| 608 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); | 624 instruction.inputs[1], |
| 625 instruction.inputs[2], |
| 626 instruction.selector, |
| 627 computeTypeFromInputTypes(instruction, compiler, closedWorld)); |
| 609 } | 628 } |
| 610 } | 629 } |
| 611 | 630 |
| 612 abstract class RelationalSpecializer extends InvokeDynamicSpecializer { | 631 abstract class RelationalSpecializer extends InvokeDynamicSpecializer { |
| 613 const RelationalSpecializer(); | 632 const RelationalSpecializer(); |
| 614 | 633 |
| 615 TypeMask computeTypeFromInputTypes( | 634 TypeMask computeTypeFromInputTypes( |
| 616 HInvokeDynamic instruction, Compiler compiler) { | 635 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 617 JavaScriptBackend backend = compiler.backend; | 636 if (instruction.inputs[1].isPrimitiveOrNull(closedWorld)) { |
| 618 if (instruction.inputs[1].isPrimitiveOrNull(compiler)) { | 637 return closedWorld.commonMasks.boolType; |
| 619 return backend.boolType; | |
| 620 } | 638 } |
| 621 return super.computeTypeFromInputTypes(instruction, compiler); | 639 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); |
| 622 } | 640 } |
| 623 | 641 |
| 624 HInstruction tryConvertToBuiltin( | 642 HInstruction tryConvertToBuiltin( |
| 625 HInvokeDynamic instruction, Compiler compiler) { | 643 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 626 HInstruction left = instruction.inputs[1]; | 644 HInstruction left = instruction.inputs[1]; |
| 627 HInstruction right = instruction.inputs[2]; | 645 HInstruction right = instruction.inputs[2]; |
| 628 if (left.isNumber(compiler) && right.isNumber(compiler)) { | 646 if (left.isNumber(closedWorld) && right.isNumber(closedWorld)) { |
| 629 return newBuiltinVariant(instruction, compiler); | 647 return newBuiltinVariant(instruction, closedWorld); |
| 630 } | 648 } |
| 631 return null; | 649 return null; |
| 632 } | 650 } |
| 633 | 651 |
| 634 HInstruction newBuiltinVariant(HInvokeDynamic instruction, Compiler compiler); | 652 HInstruction newBuiltinVariant( |
| 653 HInvokeDynamic instruction, ClosedWorld closedWorld); |
| 635 } | 654 } |
| 636 | 655 |
| 637 class EqualsSpecializer extends RelationalSpecializer { | 656 class EqualsSpecializer extends RelationalSpecializer { |
| 638 const EqualsSpecializer(); | 657 const EqualsSpecializer(); |
| 639 | 658 |
| 640 HInstruction tryConvertToBuiltin( | 659 HInstruction tryConvertToBuiltin( |
| 641 HInvokeDynamic instruction, Compiler compiler) { | 660 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 642 HInstruction left = instruction.inputs[1]; | 661 HInstruction left = instruction.inputs[1]; |
| 643 HInstruction right = instruction.inputs[2]; | 662 HInstruction right = instruction.inputs[2]; |
| 644 TypeMask instructionType = left.instructionType; | 663 TypeMask instructionType = left.instructionType; |
| 645 if (right.isConstantNull() || left.isPrimitiveOrNull(compiler)) { | 664 if (right.isConstantNull() || left.isPrimitiveOrNull(closedWorld)) { |
| 646 return newBuiltinVariant(instruction, compiler); | 665 return newBuiltinVariant(instruction, closedWorld); |
| 647 } | 666 } |
| 648 ClosedWorld world = compiler.closedWorld; | |
| 649 JavaScriptBackend backend = compiler.backend; | |
| 650 Iterable<Element> matches = | 667 Iterable<Element> matches = |
| 651 world.allFunctions.filter(instruction.selector, instructionType); | 668 closedWorld.allFunctions.filter(instruction.selector, instructionType); |
| 652 // This test relies the on `Object.==` and `Interceptor.==` always being | 669 // This test relies the on `Object.==` and `Interceptor.==` always being |
| 653 // implemented because if the selector matches by subtype, it still will be | 670 // implemented because if the selector matches by subtype, it still will be |
| 654 // a regular object or an interceptor. | 671 // a regular object or an interceptor. |
| 655 if (matches.every(backend.isDefaultEqualityImplementation)) { | 672 if (matches |
| 656 return newBuiltinVariant(instruction, compiler); | 673 .every(closedWorld.backendClasses.isDefaultEqualityImplementation)) { |
| 674 return newBuiltinVariant(instruction, closedWorld); |
| 657 } | 675 } |
| 658 return null; | 676 return null; |
| 659 } | 677 } |
| 660 | 678 |
| 661 BinaryOperation operation(ConstantSystem constantSystem) { | 679 BinaryOperation operation(ConstantSystem constantSystem) { |
| 662 return constantSystem.equal; | 680 return constantSystem.equal; |
| 663 } | 681 } |
| 664 | 682 |
| 665 HInstruction newBuiltinVariant( | 683 HInstruction newBuiltinVariant( |
| 666 HInvokeDynamic instruction, Compiler compiler) { | 684 HInvokeDynamic instruction, ClosedWorld closedWorld) { |
| 667 JavaScriptBackend backend = compiler.backend; | |
| 668 return new HIdentity(instruction.inputs[1], instruction.inputs[2], | 685 return new HIdentity(instruction.inputs[1], instruction.inputs[2], |
| 669 instruction.selector, backend.boolType); | 686 instruction.selector, closedWorld.commonMasks.boolType); |
| 670 } | 687 } |
| 671 } | 688 } |
| 672 | 689 |
| 673 class LessSpecializer extends RelationalSpecializer { | 690 class LessSpecializer extends RelationalSpecializer { |
| 674 const LessSpecializer(); | 691 const LessSpecializer(); |
| 675 | 692 |
| 676 BinaryOperation operation(ConstantSystem constantSystem) { | 693 BinaryOperation operation(ConstantSystem constantSystem) { |
| 677 return constantSystem.less; | 694 return constantSystem.less; |
| 678 } | 695 } |
| 679 | 696 |
| 680 HInstruction newBuiltinVariant( | 697 HInstruction newBuiltinVariant( |
| 681 HInvokeDynamic instruction, Compiler compiler) { | 698 HInvokeDynamic instruction, ClosedWorld closedWorld) { |
| 682 JavaScriptBackend backend = compiler.backend; | |
| 683 return new HLess(instruction.inputs[1], instruction.inputs[2], | 699 return new HLess(instruction.inputs[1], instruction.inputs[2], |
| 684 instruction.selector, backend.boolType); | 700 instruction.selector, closedWorld.commonMasks.boolType); |
| 685 } | 701 } |
| 686 } | 702 } |
| 687 | 703 |
| 688 class GreaterSpecializer extends RelationalSpecializer { | 704 class GreaterSpecializer extends RelationalSpecializer { |
| 689 const GreaterSpecializer(); | 705 const GreaterSpecializer(); |
| 690 | 706 |
| 691 BinaryOperation operation(ConstantSystem constantSystem) { | 707 BinaryOperation operation(ConstantSystem constantSystem) { |
| 692 return constantSystem.greater; | 708 return constantSystem.greater; |
| 693 } | 709 } |
| 694 | 710 |
| 695 HInstruction newBuiltinVariant( | 711 HInstruction newBuiltinVariant( |
| 696 HInvokeDynamic instruction, Compiler compiler) { | 712 HInvokeDynamic instruction, ClosedWorld closedWorld) { |
| 697 JavaScriptBackend backend = compiler.backend; | |
| 698 return new HGreater(instruction.inputs[1], instruction.inputs[2], | 713 return new HGreater(instruction.inputs[1], instruction.inputs[2], |
| 699 instruction.selector, backend.boolType); | 714 instruction.selector, closedWorld.commonMasks.boolType); |
| 700 } | 715 } |
| 701 } | 716 } |
| 702 | 717 |
| 703 class GreaterEqualSpecializer extends RelationalSpecializer { | 718 class GreaterEqualSpecializer extends RelationalSpecializer { |
| 704 const GreaterEqualSpecializer(); | 719 const GreaterEqualSpecializer(); |
| 705 | 720 |
| 706 BinaryOperation operation(ConstantSystem constantSystem) { | 721 BinaryOperation operation(ConstantSystem constantSystem) { |
| 707 return constantSystem.greaterEqual; | 722 return constantSystem.greaterEqual; |
| 708 } | 723 } |
| 709 | 724 |
| 710 HInstruction newBuiltinVariant( | 725 HInstruction newBuiltinVariant( |
| 711 HInvokeDynamic instruction, Compiler compiler) { | 726 HInvokeDynamic instruction, ClosedWorld closedWorld) { |
| 712 JavaScriptBackend backend = compiler.backend; | |
| 713 return new HGreaterEqual(instruction.inputs[1], instruction.inputs[2], | 727 return new HGreaterEqual(instruction.inputs[1], instruction.inputs[2], |
| 714 instruction.selector, backend.boolType); | 728 instruction.selector, closedWorld.commonMasks.boolType); |
| 715 } | 729 } |
| 716 } | 730 } |
| 717 | 731 |
| 718 class LessEqualSpecializer extends RelationalSpecializer { | 732 class LessEqualSpecializer extends RelationalSpecializer { |
| 719 const LessEqualSpecializer(); | 733 const LessEqualSpecializer(); |
| 720 | 734 |
| 721 BinaryOperation operation(ConstantSystem constantSystem) { | 735 BinaryOperation operation(ConstantSystem constantSystem) { |
| 722 return constantSystem.lessEqual; | 736 return constantSystem.lessEqual; |
| 723 } | 737 } |
| 724 | 738 |
| 725 HInstruction newBuiltinVariant( | 739 HInstruction newBuiltinVariant( |
| 726 HInvokeDynamic instruction, Compiler compiler) { | 740 HInvokeDynamic instruction, ClosedWorld closedWorld) { |
| 727 JavaScriptBackend backend = compiler.backend; | |
| 728 return new HLessEqual(instruction.inputs[1], instruction.inputs[2], | 741 return new HLessEqual(instruction.inputs[1], instruction.inputs[2], |
| 729 instruction.selector, backend.boolType); | 742 instruction.selector, closedWorld.commonMasks.boolType); |
| 730 } | 743 } |
| 731 } | 744 } |
| 732 | 745 |
| 733 class CodeUnitAtSpecializer extends InvokeDynamicSpecializer { | 746 class CodeUnitAtSpecializer extends InvokeDynamicSpecializer { |
| 734 const CodeUnitAtSpecializer(); | 747 const CodeUnitAtSpecializer(); |
| 735 | 748 |
| 736 BinaryOperation operation(ConstantSystem constantSystem) { | 749 BinaryOperation operation(ConstantSystem constantSystem) { |
| 737 return constantSystem.codeUnitAt; | 750 return constantSystem.codeUnitAt; |
| 738 } | 751 } |
| 739 | 752 |
| 740 HInstruction tryConvertToBuiltin( | 753 HInstruction tryConvertToBuiltin( |
| 741 HInvokeDynamic instruction, Compiler compiler) { | 754 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 742 // TODO(sra): Implement a builtin HCodeUnitAt instruction and the same index | 755 // TODO(sra): Implement a builtin HCodeUnitAt instruction and the same index |
| 743 // bounds checking optimizations as for HIndex. | 756 // bounds checking optimizations as for HIndex. |
| 744 HInstruction receiver = instruction.getDartReceiver(compiler); | 757 HInstruction receiver = instruction.getDartReceiver(compiler); |
| 745 if (receiver.isStringOrNull(compiler)) { | 758 if (receiver.isStringOrNull(closedWorld)) { |
| 746 // Even if there is no builtin equivalent instruction, we know | 759 // Even if there is no builtin equivalent instruction, we know |
| 747 // String.codeUnitAt does not have any side effect (other than throwing), | 760 // String.codeUnitAt does not have any side effect (other than throwing), |
| 748 // and that it can be GVN'ed. | 761 // and that it can be GVN'ed. |
| 749 clearAllSideEffects(instruction); | 762 clearAllSideEffects(instruction); |
| 750 } | 763 } |
| 751 return null; | 764 return null; |
| 752 } | 765 } |
| 753 } | 766 } |
| 754 | 767 |
| 755 class RoundSpecializer extends InvokeDynamicSpecializer { | 768 class RoundSpecializer extends InvokeDynamicSpecializer { |
| 756 const RoundSpecializer(); | 769 const RoundSpecializer(); |
| 757 | 770 |
| 758 UnaryOperation operation(ConstantSystem constantSystem) { | 771 UnaryOperation operation(ConstantSystem constantSystem) { |
| 759 return constantSystem.round; | 772 return constantSystem.round; |
| 760 } | 773 } |
| 761 | 774 |
| 762 HInstruction tryConvertToBuiltin( | 775 HInstruction tryConvertToBuiltin( |
| 763 HInvokeDynamic instruction, Compiler compiler) { | 776 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { |
| 764 HInstruction receiver = instruction.getDartReceiver(compiler); | 777 HInstruction receiver = instruction.getDartReceiver(compiler); |
| 765 if (receiver.isNumberOrNull(compiler)) { | 778 if (receiver.isNumberOrNull(closedWorld)) { |
| 766 // Even if there is no builtin equivalent instruction, we know the | 779 // Even if there is no builtin equivalent instruction, we know the |
| 767 // instruction does not have any side effect, and that it can be GVN'ed. | 780 // instruction does not have any side effect, and that it can be GVN'ed. |
| 768 clearAllSideEffects(instruction); | 781 clearAllSideEffects(instruction); |
| 769 } | 782 } |
| 770 return null; | 783 return null; |
| 771 } | 784 } |
| 772 } | 785 } |
| OLD | NEW |