src/jdk/nashorn/internal/codegen/CodeGenerator.java

changeset 1720
c09b105e7be5
parent 1552
b0888b955b31
child 1959
61ffdd1b89f2
child 1975
64034f7f4f5e
equal deleted inserted replaced
1719:95b8a01d3b52 1720:c09b105e7be5
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);
1718 return false; 1716 return false;
1719 } 1717 }
1720 enterStatement(expressionStatement); 1718 enterStatement(expressionStatement);
1721 1719
1722 loadAndDiscard(expressionStatement.getExpression()); 1720 loadAndDiscard(expressionStatement.getExpression());
1723 assert method.getStackSize() == 0; 1721 assert method.getStackSize() == 0 : "stack not empty in " + expressionStatement;
1724 1722
1725 return false; 1723 return false;
1726 } 1724 }
1727 1725
1728 @Override 1726 @Override
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);
3645 } 3632 }
3646 3633
3647 private void loadMinusOne() { 3634 private void loadMinusOne() {
3648 if (type.isInteger()) { 3635 if (type.isInteger()) {
3649 method.load(isIncrement ? 1 : -1); 3636 method.load(isIncrement ? 1 : -1);
3650 } else if (type.isLong()) {
3651 method.load(isIncrement ? 1L : -1L);
3652 } else { 3637 } else {
3653 method.load(isIncrement ? 1.0 : -1.0); 3638 method.load(isIncrement ? 1.0 : -1.0);
3654 } 3639 }
3655 } 3640 }
3656 3641
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 }

mercurial