painless: Make field stores not box; use GeneratorAdapter.invokeDynmaic for consistency with other method calls
This commit is contained in:
parent
c183e4b6eb
commit
604bcd9320
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Licensed to Elasticsearch under one or more contributor
|
||||||
|
* license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright
|
||||||
|
* ownership. Elasticsearch licenses this file to you under
|
||||||
|
* the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.elasticsearch.painless.node;
|
||||||
|
|
||||||
|
import org.elasticsearch.painless.Definition.Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The superclass for all LDef* (link) nodes that store or return a DEF. (Internal only.)
|
||||||
|
*/
|
||||||
|
abstract class ADefLink extends ALink {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of the original type that was pushed on stack, set by {@link EChain} during analyze.
|
||||||
|
* This value is only used for writing the 'store' bytecode, otherwise ignored.
|
||||||
|
*/
|
||||||
|
Type storeValueType = null;
|
||||||
|
|
||||||
|
ADefLink(final int line, final String location, final int size) {
|
||||||
|
super(line, location, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -222,8 +222,17 @@ public final class EChain extends AExpression {
|
||||||
private void analyzeWrite(final CompilerSettings settings, final Definition definition, final Variables variables) {
|
private void analyzeWrite(final CompilerSettings settings, final Definition definition, final Variables variables) {
|
||||||
final ALink last = links.get(links.size() - 1);
|
final ALink last = links.get(links.size() - 1);
|
||||||
|
|
||||||
expression.expected = last.after;
|
// If the store node is a DEF node, we remove the cast to DEF from the expression
|
||||||
expression.analyze(settings, definition, variables);
|
// and promote the real type to it:
|
||||||
|
if (last instanceof ADefLink) {
|
||||||
|
final ADefLink lastDef = (ADefLink) last;
|
||||||
|
expression.analyze(settings, definition, variables);
|
||||||
|
lastDef.storeValueType = expression.expected = expression.actual;
|
||||||
|
} else {
|
||||||
|
// otherwise we adapt the type of the expression to the store type
|
||||||
|
expression.expected = last.after;
|
||||||
|
expression.analyze(settings, definition, variables);
|
||||||
|
}
|
||||||
expression = expression.cast(settings, definition, variables);
|
expression = expression.cast(settings, definition, variables);
|
||||||
|
|
||||||
statement = true;
|
statement = true;
|
||||||
|
|
|
@ -59,9 +59,6 @@ public final class LCall extends ALink {
|
||||||
method = statik ? struct.functions.get(name) : struct.methods.get(name);
|
method = statik ? struct.functions.get(name) : struct.methods.get(name);
|
||||||
|
|
||||||
if (method != null) {
|
if (method != null) {
|
||||||
final Definition.Type[] types = new Definition.Type[method.arguments.size()];
|
|
||||||
method.arguments.toArray(types);
|
|
||||||
|
|
||||||
if (method.arguments.size() != arguments.size()) {
|
if (method.arguments.size() != arguments.size()) {
|
||||||
throw new IllegalArgumentException(error("When calling [" + name + "] on type [" + struct.name + "]" +
|
throw new IllegalArgumentException(error("When calling [" + name + "] on type [" + struct.name + "]" +
|
||||||
" expected [" + method.arguments.size() + "] arguments, but found [" + arguments.size() + "]."));
|
" expected [" + method.arguments.size() + "] arguments, but found [" + arguments.size() + "]."));
|
||||||
|
@ -70,7 +67,7 @@ public final class LCall extends ALink {
|
||||||
for (int argument = 0; argument < arguments.size(); ++argument) {
|
for (int argument = 0; argument < arguments.size(); ++argument) {
|
||||||
final AExpression expression = arguments.get(argument);
|
final AExpression expression = arguments.get(argument);
|
||||||
|
|
||||||
expression.expected = types[argument];
|
expression.expected = method.arguments.get(argument);
|
||||||
expression.analyze(settings, definition, variables);
|
expression.analyze(settings, definition, variables);
|
||||||
arguments.set(argument, expression.cast(settings, definition, variables));
|
arguments.set(argument, expression.cast(settings, definition, variables));
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ import static org.elasticsearch.painless.WriterConstants.DEF_BOOTSTRAP_HANDLE;
|
||||||
/**
|
/**
|
||||||
* Represents an array load/store or shortcut on a def type. (Internal only.)
|
* Represents an array load/store or shortcut on a def type. (Internal only.)
|
||||||
*/
|
*/
|
||||||
final class LDefArray extends ALink {
|
final class LDefArray extends ADefLink {
|
||||||
|
|
||||||
AExpression index;
|
AExpression index;
|
||||||
|
|
||||||
|
@ -61,13 +61,16 @@ final class LDefArray extends ALink {
|
||||||
@Override
|
@Override
|
||||||
void load(final CompilerSettings settings, final Definition definition, final GeneratorAdapter adapter) {
|
void load(final CompilerSettings settings, final Definition definition, final GeneratorAdapter adapter) {
|
||||||
final String desc = Type.getMethodDescriptor(after.type, definition.defType.type, index.actual.type);
|
final String desc = Type.getMethodDescriptor(after.type, definition.defType.type, index.actual.type);
|
||||||
adapter.visitInvokeDynamicInsn("arrayLoad", desc, DEF_BOOTSTRAP_HANDLE, DefBootstrap.ARRAY_LOAD);
|
adapter.invokeDynamic("arrayLoad", desc, DEF_BOOTSTRAP_HANDLE, DefBootstrap.ARRAY_LOAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void store(final CompilerSettings settings, final Definition definition, final GeneratorAdapter adapter) {
|
void store(final CompilerSettings settings, final Definition definition, final GeneratorAdapter adapter) {
|
||||||
|
if (storeValueType == null) {
|
||||||
|
throw new IllegalStateException(error("Illegal tree structure."));
|
||||||
|
}
|
||||||
final String desc = Type.getMethodDescriptor(definition.voidType.type, definition.defType.type,
|
final String desc = Type.getMethodDescriptor(definition.voidType.type, definition.defType.type,
|
||||||
index.actual.type, definition.defType.type);
|
index.actual.type, storeValueType.type);
|
||||||
adapter.visitInvokeDynamicInsn("arrayStore", desc, DEF_BOOTSTRAP_HANDLE, DefBootstrap.ARRAY_STORE);
|
adapter.invokeDynamic("arrayStore", desc, DEF_BOOTSTRAP_HANDLE, DefBootstrap.ARRAY_STORE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ import static org.elasticsearch.painless.WriterConstants.DEF_BOOTSTRAP_HANDLE;
|
||||||
/**
|
/**
|
||||||
* Represents a method call made on a def type. (Internal only.)
|
* Represents a method call made on a def type. (Internal only.)
|
||||||
*/
|
*/
|
||||||
final class LDefCall extends ALink {
|
final class LDefCall extends ADefLink {
|
||||||
|
|
||||||
final String name;
|
final String name;
|
||||||
final List<AExpression> arguments;
|
final List<AExpression> arguments;
|
||||||
|
@ -84,7 +84,7 @@ final class LDefCall extends ALink {
|
||||||
// return value
|
// return value
|
||||||
signature.append(after.type.getDescriptor());
|
signature.append(after.type.getDescriptor());
|
||||||
|
|
||||||
adapter.visitInvokeDynamicInsn(name, signature.toString(), DEF_BOOTSTRAP_HANDLE, DefBootstrap.METHOD_CALL);
|
adapter.invokeDynamic(name, signature.toString(), DEF_BOOTSTRAP_HANDLE, DefBootstrap.METHOD_CALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -31,7 +31,7 @@ import static org.elasticsearch.painless.WriterConstants.DEF_BOOTSTRAP_HANDLE;
|
||||||
/**
|
/**
|
||||||
* Represents a field load/store or shortcut on a def type. (Internal only.)
|
* Represents a field load/store or shortcut on a def type. (Internal only.)
|
||||||
*/
|
*/
|
||||||
final class LDefField extends ALink {
|
final class LDefField extends ADefLink {
|
||||||
|
|
||||||
final String value;
|
final String value;
|
||||||
|
|
||||||
|
@ -57,12 +57,15 @@ final class LDefField extends ALink {
|
||||||
@Override
|
@Override
|
||||||
void load(final CompilerSettings settings, final Definition definition, final GeneratorAdapter adapter) {
|
void load(final CompilerSettings settings, final Definition definition, final GeneratorAdapter adapter) {
|
||||||
final String desc = Type.getMethodDescriptor(after.type, definition.defType.type);
|
final String desc = Type.getMethodDescriptor(after.type, definition.defType.type);
|
||||||
adapter.visitInvokeDynamicInsn(value, desc, DEF_BOOTSTRAP_HANDLE, DefBootstrap.LOAD);
|
adapter.invokeDynamic(value, desc, DEF_BOOTSTRAP_HANDLE, DefBootstrap.LOAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void store(final CompilerSettings settings, final Definition definition, final GeneratorAdapter adapter) {
|
void store(final CompilerSettings settings, final Definition definition, final GeneratorAdapter adapter) {
|
||||||
final String desc = Type.getMethodDescriptor(definition.voidType.type, definition.defType.type, definition.defType.type);
|
if (storeValueType == null) {
|
||||||
adapter.visitInvokeDynamicInsn(value, desc, DEF_BOOTSTRAP_HANDLE, DefBootstrap.STORE);
|
throw new IllegalStateException(error("Illegal tree structure."));
|
||||||
|
}
|
||||||
|
final String desc = Type.getMethodDescriptor(definition.voidType.type, definition.defType.type, storeValueType.type);
|
||||||
|
adapter.invokeDynamic(value, desc, DEF_BOOTSTRAP_HANDLE, DefBootstrap.STORE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue