186 private static final Call CREATE_REWRITE_EXCEPTION_REST_OF = CompilerConstants.staticCallNoLookup(RewriteException.class, |
186 private static final Call CREATE_REWRITE_EXCEPTION_REST_OF = CompilerConstants.staticCallNoLookup(RewriteException.class, |
187 "create", RewriteException.class, UnwarrantedOptimismException.class, Object[].class, String[].class, int[].class); |
187 "create", RewriteException.class, UnwarrantedOptimismException.class, Object[].class, String[].class, int[].class); |
188 |
188 |
189 private static final Call ENSURE_INT = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class, |
189 private static final Call ENSURE_INT = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class, |
190 "ensureInt", int.class, Object.class, int.class); |
190 "ensureInt", int.class, Object.class, int.class); |
191 private static final Call ENSURE_LONG = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class, |
|
192 "ensureLong", long.class, Object.class, int.class); |
|
193 private static final Call ENSURE_NUMBER = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class, |
191 private static final Call ENSURE_NUMBER = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class, |
194 "ensureNumber", double.class, Object.class, int.class); |
192 "ensureNumber", double.class, Object.class, int.class); |
195 |
193 |
196 private static final Call CREATE_FUNCTION_OBJECT = CompilerConstants.staticCallNoLookup(ScriptFunction.class, |
194 private static final Call CREATE_FUNCTION_OBJECT = CompilerConstants.staticCallNoLookup(ScriptFunction.class, |
197 "create", ScriptFunction.class, Object[].class, int.class, ScriptObject.class); |
195 "create", ScriptFunction.class, Object[].class, int.class, ScriptObject.class); |
2233 * |
2231 * |
2234 * @param arrayLiteralNode the array of contents |
2232 * @param arrayLiteralNode the array of contents |
2235 * @param arrayType the type of the array, e.g. ARRAY_NUMBER or ARRAY_OBJECT |
2233 * @param arrayType the type of the array, e.g. ARRAY_NUMBER or ARRAY_OBJECT |
2236 */ |
2234 */ |
2237 private void loadArray(final ArrayLiteralNode arrayLiteralNode, final ArrayType arrayType) { |
2235 private void loadArray(final ArrayLiteralNode arrayLiteralNode, final ArrayType arrayType) { |
2238 assert arrayType == Type.INT_ARRAY || arrayType == Type.LONG_ARRAY || arrayType == Type.NUMBER_ARRAY || arrayType == Type.OBJECT_ARRAY; |
2236 assert arrayType == Type.INT_ARRAY || arrayType == Type.NUMBER_ARRAY || arrayType == Type.OBJECT_ARRAY; |
2239 |
2237 |
2240 final Expression[] nodes = arrayLiteralNode.getValue(); |
2238 final Expression[] nodes = arrayLiteralNode.getValue(); |
2241 final Object presets = arrayLiteralNode.getPresets(); |
2239 final Object presets = arrayLiteralNode.getPresets(); |
2242 final int[] postsets = arrayLiteralNode.getPostsets(); |
2240 final int[] postsets = arrayLiteralNode.getPostsets(); |
2243 final List<Splittable.SplitRange> ranges = arrayLiteralNode.getSplitRanges(); |
2241 final List<Splittable.SplitRange> ranges = arrayLiteralNode.getSplitRanges(); |
2381 if(!resultBounds.canBeNarrowerThan(Type.OBJECT)) { |
2379 if(!resultBounds.canBeNarrowerThan(Type.OBJECT)) { |
2382 method.load((Integer)value); |
2380 method.load((Integer)value); |
2383 method.convert(Type.OBJECT); |
2381 method.convert(Type.OBJECT); |
2384 } else if(!resultBounds.canBeNarrowerThan(Type.NUMBER)) { |
2382 } else if(!resultBounds.canBeNarrowerThan(Type.NUMBER)) { |
2385 method.load(((Integer)value).doubleValue()); |
2383 method.load(((Integer)value).doubleValue()); |
2386 } else if(!resultBounds.canBeNarrowerThan(Type.LONG)) { |
|
2387 method.load(((Integer)value).longValue()); |
|
2388 } else { |
2384 } else { |
2389 method.load((Integer)value); |
2385 method.load((Integer)value); |
2390 } |
|
2391 } else if (value instanceof Long) { |
|
2392 if(!resultBounds.canBeNarrowerThan(Type.OBJECT)) { |
|
2393 method.load((Long)value); |
|
2394 method.convert(Type.OBJECT); |
|
2395 } else if(!resultBounds.canBeNarrowerThan(Type.NUMBER)) { |
|
2396 method.load(((Long)value).doubleValue()); |
|
2397 } else { |
|
2398 method.load((Long)value); |
|
2399 } |
2386 } |
2400 } else if (value instanceof Double) { |
2387 } else if (value instanceof Double) { |
2401 if(!resultBounds.canBeNarrowerThan(Type.OBJECT)) { |
2388 if(!resultBounds.canBeNarrowerThan(Type.OBJECT)) { |
2402 method.load((Double)value); |
2389 method.load((Double)value); |
2403 method.convert(Type.OBJECT); |
2390 method.convert(Type.OBJECT); |
4028 } |
4013 } |
4029 }.store(); |
4014 }.store(); |
4030 } |
4015 } |
4031 |
4016 |
4032 private void loadASSIGN_SHR(final BinaryNode binaryNode) { |
4017 private void loadASSIGN_SHR(final BinaryNode binaryNode) { |
4033 new BinarySelfAssignment(binaryNode) { |
4018 new SelfModifyingStore<BinaryNode>(binaryNode, binaryNode.lhs()) { |
4034 @Override |
4019 @Override |
4035 protected void op() { |
4020 protected void evaluate() { |
4036 doSHR(); |
4021 new OptimisticOperation(assignNode, new TypeBounds(Type.INT, Type.NUMBER)) { |
4037 } |
4022 @Override |
4038 |
4023 void loadStack() { |
|
4024 assert assignNode.getWidestOperandType() == Type.INT; |
|
4025 if (isRhsZero(binaryNode)) { |
|
4026 loadExpressionAsType(binaryNode.lhs(), Type.INT); |
|
4027 } else { |
|
4028 loadBinaryOperands(binaryNode.lhs(), binaryNode.rhs(), TypeBounds.INT, true, false); |
|
4029 method.shr(); |
|
4030 } |
|
4031 } |
|
4032 |
|
4033 @Override |
|
4034 void consumeStack() { |
|
4035 if (isOptimistic(binaryNode)) { |
|
4036 toUint32Optimistic(binaryNode.getProgramPoint()); |
|
4037 } else { |
|
4038 toUint32Double(); |
|
4039 } |
|
4040 } |
|
4041 }.emit(getOptimisticIgnoreCountForSelfModifyingExpression(binaryNode.lhs())); |
|
4042 method.convert(assignNode.getType()); |
|
4043 } |
4039 }.store(); |
4044 }.store(); |
4040 } |
4045 } |
4041 |
4046 |
4042 private void doSHR() { |
4047 private void doSHR(final BinaryNode binaryNode) { |
4043 // TODO: make SHR optimistic |
4048 new OptimisticOperation(binaryNode, new TypeBounds(Type.INT, Type.NUMBER)) { |
4044 method.shr(); |
4049 @Override |
4045 toUint(); |
4050 void loadStack() { |
4046 } |
4051 if (isRhsZero(binaryNode)) { |
4047 |
4052 loadExpressionAsType(binaryNode.lhs(), Type.INT); |
4048 private void toUint() { |
4053 } else { |
4049 JSType.TO_UINT32_I.invoke(method); |
4054 loadBinaryOperands(binaryNode); |
|
4055 method.shr(); |
|
4056 } |
|
4057 } |
|
4058 |
|
4059 @Override |
|
4060 void consumeStack() { |
|
4061 if (isOptimistic(binaryNode)) { |
|
4062 toUint32Optimistic(binaryNode.getProgramPoint()); |
|
4063 } else { |
|
4064 toUint32Double(); |
|
4065 } |
|
4066 } |
|
4067 }.emit(); |
|
4068 |
|
4069 } |
|
4070 |
|
4071 private void toUint32Optimistic(final int programPoint) { |
|
4072 method.load(programPoint); |
|
4073 JSType.TO_UINT32_OPTIMISTIC.invoke(method); |
|
4074 } |
|
4075 |
|
4076 private void toUint32Double() { |
|
4077 JSType.TO_UINT32_DOUBLE.invoke(method); |
4050 } |
4078 } |
4051 |
4079 |
4052 private void loadASSIGN_SUB(final BinaryNode binaryNode) { |
4080 private void loadASSIGN_SUB(final BinaryNode binaryNode) { |
4053 new BinaryOptimisticSelfAssignment(binaryNode) { |
4081 new BinaryOptimisticSelfAssignment(binaryNode) { |
4054 @Override |
4082 @Override |
4082 operandBounds = new TypeBounds(node.getType(), Type.NUMBER); |
4110 operandBounds = new TypeBounds(node.getType(), Type.NUMBER); |
4083 } else { |
4111 } else { |
4084 // Non-optimistic, non-FP subtraction or multiplication. Allow them to overflow. |
4112 // Non-optimistic, non-FP subtraction or multiplication. Allow them to overflow. |
4085 operandBounds = new TypeBounds(Type.narrowest(node.getWidestOperandType(), |
4113 operandBounds = new TypeBounds(Type.narrowest(node.getWidestOperandType(), |
4086 numericBounds.widest), Type.NUMBER); |
4114 numericBounds.widest), Type.NUMBER); |
4087 forceConversionSeparation = node.getWidestOperationType().narrowerThan(numericBounds.widest); |
4115 forceConversionSeparation = true; |
4088 } |
4116 } |
4089 } |
4117 } |
4090 loadBinaryOperands(node.lhs(), node.rhs(), operandBounds, false, forceConversionSeparation); |
4118 loadBinaryOperands(node.lhs(), node.rhs(), operandBounds, false, forceConversionSeparation); |
4091 } |
4119 } |
4092 |
4120 |
4184 loadBinaryOperands(binaryNode); |
4212 loadBinaryOperands(binaryNode); |
4185 method.shl(); |
4213 method.shl(); |
4186 } |
4214 } |
4187 |
4215 |
4188 private void loadSHR(final BinaryNode binaryNode) { |
4216 private void loadSHR(final BinaryNode binaryNode) { |
4189 // Optimize x >>> 0 to (uint)x |
4217 doSHR(binaryNode); |
4190 if (isRhsZero(binaryNode)) { |
|
4191 loadExpressionAsType(binaryNode.lhs(), Type.INT); |
|
4192 toUint(); |
|
4193 } else { |
|
4194 loadBinaryOperands(binaryNode); |
|
4195 doSHR(); |
|
4196 } |
|
4197 } |
4218 } |
4198 |
4219 |
4199 private void loadSUB(final BinaryNode binaryNode, final TypeBounds resultBounds) { |
4220 private void loadSUB(final BinaryNode binaryNode, final TypeBounds resultBounds) { |
4200 new BinaryArith() { |
4221 new BinaryArith() { |
4201 @Override |
4222 @Override |
4462 } else { |
4483 } else { |
4463 method.dynamicSet(node.getName(), flags, false); |
4484 method.dynamicSet(node.getName(), flags, false); |
4464 } |
4485 } |
4465 } else { |
4486 } else { |
4466 final Type storeType = assignNode.getType(); |
4487 final Type storeType = assignNode.getType(); |
|
4488 assert storeType != Type.LONG; |
4467 if (symbol.hasSlotFor(storeType)) { |
4489 if (symbol.hasSlotFor(storeType)) { |
4468 // Only emit a convert for a store known to be live; converts for dead stores can |
4490 // Only emit a convert for a store known to be live; converts for dead stores can |
4469 // give us an unnecessary ClassCastException. |
4491 // give us an unnecessary ClassCastException. |
4470 method.convert(storeType); |
4492 method.convert(storeType); |
4471 } |
4493 } |
4846 final Type optimisticType = getOptimisticCoercedType(); |
4868 final Type optimisticType = getOptimisticCoercedType(); |
4847 if(!optimisticType.isObject()) { |
4869 if(!optimisticType.isObject()) { |
4848 method.load(optimistic.getProgramPoint()); |
4870 method.load(optimistic.getProgramPoint()); |
4849 if(optimisticType.isInteger()) { |
4871 if(optimisticType.isInteger()) { |
4850 method.invoke(ENSURE_INT); |
4872 method.invoke(ENSURE_INT); |
4851 } else if(optimisticType.isLong()) { |
|
4852 method.invoke(ENSURE_LONG); |
|
4853 } else if(optimisticType.isNumber()) { |
4873 } else if(optimisticType.isNumber()) { |
4854 method.invoke(ENSURE_NUMBER); |
4874 method.invoke(ENSURE_NUMBER); |
4855 } else { |
4875 } else { |
4856 throw new AssertionError(optimisticType); |
4876 throw new AssertionError(optimisticType); |
4857 } |
4877 } |