Skip to content

Commit

Permalink
Add byte code expressions for arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
nileema committed Dec 3, 2015
1 parent 0141317 commit 0030752
Show file tree
Hide file tree
Showing 11 changed files with 586 additions and 73 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/*
* Licensed 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 com.facebook.presto.byteCode;

import com.google.common.collect.ImmutableMap;

import javax.annotation.Nullable;

import java.util.Map;

import static com.facebook.presto.byteCode.ArrayOpCode.AType.T_BOOLEAN;
import static com.facebook.presto.byteCode.ArrayOpCode.AType.T_BYTE;
import static com.facebook.presto.byteCode.ArrayOpCode.AType.T_CHAR;
import static com.facebook.presto.byteCode.ArrayOpCode.AType.T_DOUBLE;
import static com.facebook.presto.byteCode.ArrayOpCode.AType.T_FLOAT;
import static com.facebook.presto.byteCode.ArrayOpCode.AType.T_INT;
import static com.facebook.presto.byteCode.ArrayOpCode.AType.T_LONG;
import static com.facebook.presto.byteCode.ArrayOpCode.AType.T_SHORT;
import static com.facebook.presto.byteCode.OpCode.AALOAD;
import static com.facebook.presto.byteCode.OpCode.AASTORE;
import static com.facebook.presto.byteCode.OpCode.BALOAD;
import static com.facebook.presto.byteCode.OpCode.BASTORE;
import static com.facebook.presto.byteCode.OpCode.CALOAD;
import static com.facebook.presto.byteCode.OpCode.CASTORE;
import static com.facebook.presto.byteCode.OpCode.DALOAD;
import static com.facebook.presto.byteCode.OpCode.DASTORE;
import static com.facebook.presto.byteCode.OpCode.FALOAD;
import static com.facebook.presto.byteCode.OpCode.FASTORE;
import static com.facebook.presto.byteCode.OpCode.IALOAD;
import static com.facebook.presto.byteCode.OpCode.IASTORE;
import static com.facebook.presto.byteCode.OpCode.LALOAD;
import static com.facebook.presto.byteCode.OpCode.LASTORE;
import static com.facebook.presto.byteCode.OpCode.SALOAD;
import static com.facebook.presto.byteCode.OpCode.SASTORE;
import static java.util.Objects.requireNonNull;

public enum ArrayOpCode
{
NOT_PRIMITIVE(null, AALOAD, AASTORE, null),
BYTE(byte.class, BALOAD, BASTORE, T_BYTE),
BOOLEAN(boolean.class, BALOAD, BASTORE, T_BOOLEAN),
CHAR(char.class, CALOAD, CASTORE, T_CHAR),
SHORT(short.class, SALOAD, SASTORE, T_SHORT),
INT(int.class, IALOAD, IASTORE, T_INT),
LONG(long.class, LALOAD, LASTORE, T_LONG),
FLOAT(float.class, FALOAD, FASTORE, T_FLOAT),
DOUBLE(double.class, DALOAD, DASTORE, T_DOUBLE);

private final OpCode load;
private final OpCode store;
private final AType atype;
private final Class<?> type;

private static final Map<Class<?>, ArrayOpCode> arrayOpCodeMap = initializeArrayOpCodeMap();

ArrayOpCode(@Nullable Class<?> clazz, OpCode load, OpCode store, @Nullable AType atype)
{
this.type = clazz;
this.load = requireNonNull(load, "load is null");
this.store = requireNonNull(store, "store is null");
this.atype = atype;
}

public OpCode getLoad()
{
return load;
}

public OpCode getStore()
{
return store;
}

public int getAtype()
{
return atype.getType();
}

public Class<?> getType()
{
return type;
}

public static ArrayOpCode getArrayOpCode(ParameterizedType type)
{
if (!type.isPrimitive()) {
return NOT_PRIMITIVE;
}
ArrayOpCode arrayOpCode = arrayOpCodeMap.get(type.getPrimitiveType());
if (arrayOpCode == null) {
throw new IllegalArgumentException("unsupported primitive type " + type);
}
return arrayOpCode;
}

static Map<Class<?>, ArrayOpCode> initializeArrayOpCodeMap()
{
ImmutableMap.Builder<Class<?>, ArrayOpCode> builder = ImmutableMap.<Class<?>, ArrayOpCode>builder();
for (ArrayOpCode arrayOpCode : values()) {
if (arrayOpCode.getType() != null) {
builder.put(arrayOpCode.getType(), arrayOpCode);
}
}
return builder.build();
}

enum AType
{
T_BOOLEAN(4),
T_CHAR(5),
T_FLOAT(6),
T_DOUBLE(7),
T_BYTE(8),
T_SHORT(9),
T_INT(10),
T_LONG(11);

private final int type;

AType(int type)
{
this.type = type;
}

int getType()
{
return type;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Licensed 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 com.facebook.presto.byteCode.expression;

import com.facebook.presto.byteCode.ByteCodeBlock;
import com.facebook.presto.byteCode.ByteCodeNode;
import com.facebook.presto.byteCode.MethodGenerationContext;
import com.google.common.collect.ImmutableList;

import java.util.List;

import static com.facebook.presto.byteCode.OpCode.ARRAYLENGTH;
import static com.facebook.presto.byteCode.ParameterizedType.type;
import static java.util.Objects.requireNonNull;

class ArrayLengthByteCodeExpression
extends ByteCodeExpression
{
private final ByteCodeExpression instance;

public ArrayLengthByteCodeExpression(ByteCodeExpression instance)
{
super(type(int.class));
this.instance = requireNonNull(instance, "instance is null");
}

@Override
public ByteCodeNode getByteCode(MethodGenerationContext generationContext)
{
return new ByteCodeBlock()
.append(instance.getByteCode(generationContext))
.append(ARRAYLENGTH);
}

@Override
protected String formatOneLine()
{
return instance + ".length";
}

@Override
public List<ByteCodeNode> getChildNodes()
{
return ImmutableList.<ByteCodeNode>of();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,21 @@ public final ByteCodeExpression getElement(ByteCodeExpression index)
return new GetElementByteCodeExpression(this, index);
}

public final ByteCodeExpression setElement(int index, ByteCodeExpression value)
{
return new SetArrayElementByteCodeExpression(this, constantInt(index), value);
}

public final ByteCodeExpression setElement(ByteCodeExpression index, ByteCodeExpression value)
{
return new SetArrayElementByteCodeExpression(this, index, value);
}

public final ByteCodeExpression length()
{
return new ArrayLengthByteCodeExpression(this);
}

public final ByteCodeExpression ret()
{
return new ReturnByteCodeExpression(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,34 @@ public static ByteCodeExpression newInstance(
return new NewInstanceByteCodeExpression(type, parameterTypes, parameters);
}

//
// Array
//
public static ByteCodeExpression newArray(ParameterizedType type, int length)
{
return new NewArrayByteCodeExpression(type, length);
}

public static ByteCodeExpression newArray(ParameterizedType type, ByteCodeExpression length)
{
return new NewArrayByteCodeExpression(type, length);
}

public static ByteCodeExpression length(ByteCodeExpression instance)
{
return new ArrayLengthByteCodeExpression(instance);
}

public static ByteCodeExpression get(ByteCodeExpression instance, ByteCodeExpression index)
{
return new GetElementByteCodeExpression(instance, index);
}

public static ByteCodeExpression set(ByteCodeExpression instance, ByteCodeExpression index, ByteCodeExpression value)
{
return new SetArrayElementByteCodeExpression(instance, index, value);
}

//
// Invoke static method
//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,12 @@
import com.facebook.presto.byteCode.ByteCodeBlock;
import com.facebook.presto.byteCode.ByteCodeNode;
import com.facebook.presto.byteCode.MethodGenerationContext;
import com.facebook.presto.byteCode.OpCode;
import com.facebook.presto.byteCode.ParameterizedType;
import com.facebook.presto.byteCode.instruction.InstructionNode;
import com.google.common.collect.ImmutableList;

import java.util.List;

import static com.facebook.presto.byteCode.ArrayOpCode.getArrayOpCode;
import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Objects.requireNonNull;

Expand All @@ -38,15 +37,17 @@ public GetElementByteCodeExpression(ByteCodeExpression instance, ByteCodeExpress
super(instance.getType().getArrayComponentType());
this.instance = requireNonNull(instance, "instance is null");
this.index = requireNonNull(index, "index is null");

checkArgument(index.getType().getPrimitiveType() == int.class, "index must be int type, but is " + index.getType());
this.arrayLoadInstruction = arrayLoadInstruction(instance.getType().getArrayComponentType());
this.arrayLoadInstruction = getArrayOpCode(instance.getType().getArrayComponentType()).getLoad();
}

@Override
public ByteCodeNode getByteCode(MethodGenerationContext generationContext)
{
return new ByteCodeBlock()
.append(instance.getByteCode(generationContext)).append(index)
.append(instance.getByteCode(generationContext))
.append(index)
.append(arrayLoadInstruction);
}

Expand All @@ -59,37 +60,6 @@ protected String formatOneLine()
@Override
public List<ByteCodeNode> getChildNodes()
{
return ImmutableList.<ByteCodeNode>of(instance, index);
}

private static InstructionNode arrayLoadInstruction(ParameterizedType componentType)
{
Class<?> primitiveType = componentType.getPrimitiveType();
if (primitiveType == null) {
return OpCode.AALOAD;
}

if (primitiveType == byte.class || primitiveType == boolean.class) {
return OpCode.BALOAD;
}
if (primitiveType == char.class) {
return OpCode.CALOAD;
}
if (primitiveType == short.class) {
return OpCode.SALOAD;
}
if (primitiveType == int.class) {
return OpCode.IALOAD;
}
if (primitiveType == long.class) {
return OpCode.LALOAD;
}
if (primitiveType == float.class) {
return OpCode.FALOAD;
}
if (primitiveType == double.class) {
return OpCode.DALOAD;
}
throw new IllegalArgumentException("Unsupported array type: " + primitiveType);
return ImmutableList.<ByteCodeNode>of(index);
}
}
Loading

0 comments on commit 0030752

Please sign in to comment.