StackValue.java 40.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * Copyright 2010-2012 JetBrains s.r.o.
 *
 * 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.
 */

17 18
package org.jetbrains.jet.codegen;

19
import com.intellij.psi.tree.IElementType;
20
import org.jetbrains.annotations.NotNull;
21
import org.jetbrains.annotations.Nullable;
22
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethod;
23
import org.jetbrains.jet.lang.descriptors.*;
24
import org.jetbrains.jet.lang.psi.JetExpression;
25
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
26
import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType;
27
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
28 29 30
import org.jetbrains.jet.lexer.JetTokens;
import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
31 32
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
33
import org.objectweb.asm.commons.Method;
34

35 36
import java.util.List;

37 38
/**
 * @author yole
A
Alex Tkachman 已提交
39
 * @author alex.tkachman
40 41
 */
public abstract class StackValue {
42
    public final Type type;
D
Dmitry Jemerov 已提交
43 44 45

    public StackValue(Type type) {
        this.type = type;
46 47 48 49 50 51 52 53 54
    }

    public static void valueOf(InstructionAdapter instructionAdapter, final Type type) {
        if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
            return;
        }
        if (type == Type.VOID_TYPE) {
            instructionAdapter.aconst(null);
        } else {
55
            Type boxed = JetTypeMapper.boxType(type);
56 57
            instructionAdapter.invokestatic(boxed.getInternalName(), "valueOf", "(" + type.getDescriptor() + ")" + boxed.getDescriptor());
        }
D
Dmitry Jemerov 已提交
58 59
    }

60 61
    public abstract void put(Type type, InstructionAdapter v);

62
    public void store(InstructionAdapter v) {
63 64 65
        throw new UnsupportedOperationException("cannot store to value " + this);
    }

66
    public void dupReceiver(InstructionAdapter v) {
67 68
    }

A
Alex Tkachman 已提交
69 70 71 72
    public int receiverSize() {
        return 0;
    }

73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
    public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
        if (this.type == Type.BOOLEAN_TYPE) {
            put(Type.BOOLEAN_TYPE, v);
            if (jumpIfFalse) {
                v.ifeq(label);
            }
            else {
                v.ifne(label);
            }
        }
        else {
            throw new UnsupportedOperationException("can't generate a cond jump for a non-boolean value");
        }
    }

D
Dmitry Jemerov 已提交
88
    public static StackValue local(int index, Type type) {
89 90 91
        return new Local(index, type);
    }

A
Alex Tkachman 已提交
92 93 94 95
    public static StackValue shared(int index, Type type) {
        return new Shared(index, type);
    }

96
    public static StackValue onStack(Type type) {
97
        return type == Type.VOID_TYPE ? none() : new OnStack(type);
98 99
    }

D
Dmitry Jemerov 已提交
100 101
    public static StackValue constant(Object value, Type type) {
        return new Constant(value, type);
102 103
    }

104
    public static StackValue cmp(IElementType opToken, Type type) {
D
Dmitry Jemerov 已提交
105
        return type.getSort() == Type.OBJECT ? new ObjectCompare(opToken, type) : new NumberCompare(opToken, type);
106 107
    }

D
Dmitry Jemerov 已提交
108 109 110 111
    public static StackValue not(StackValue stackValue) {
        return new Invert(stackValue);
    }

A
Alex Tkachman 已提交
112 113
    public static StackValue arrayElement(Type type, boolean unbox) {
        return new ArrayElement(type, unbox);
114 115
    }

116 117
    public static StackValue collectionElement(Type type, ResolvedCall<FunctionDescriptor> getter, ResolvedCall<FunctionDescriptor> setter, ExpressionCodegen codegen) {
        return new CollectionElement(type, getter, setter, codegen);
D
Dmitry Jemerov 已提交
118 119
    }

120 121 122
    public static StackValue field(Type type, String owner, String name, boolean isStatic) {
        return new Field(type, owner, name, isStatic);
    }
123

124 125
    public static Property property(String name, String methodOwner, String methodOwnerParam, Type type, boolean isStatic, boolean isInterface, boolean isSuper, Method getter, Method setter, int invokeOpcode) {
        return new Property(name, methodOwner, methodOwnerParam, getter, setter, isStatic, isInterface, isSuper, type, invokeOpcode);
126 127
    }

128 129 130 131
    public static StackValue expression(Type type, JetExpression expression, ExpressionCodegen generator) {
        return new Expression(type, expression, generator);
    }

132 133 134
    private static void box(final Type type, final Type toType, InstructionAdapter v) {
        // TODO handle toType correctly
        if (type == Type.INT_TYPE || (JetTypeMapper.isIntPrimitive(type) && toType.getInternalName().equals("java/lang/Integer"))) {
D
Dmitry Jemerov 已提交
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
            v.invokestatic("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
        }
        else if (type == Type.BOOLEAN_TYPE) {
            v.invokestatic("java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;");
        }
        else if (type == Type.CHAR_TYPE) {
            v.invokestatic("java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");
        }
        else if (type == Type.SHORT_TYPE) {
            v.invokestatic("java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");
        }
        else if (type == Type.LONG_TYPE) {
            v.invokestatic("java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");
        }
        else if (type == Type.BYTE_TYPE) {
            v.invokestatic("java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");
        }
        else if (type == Type.FLOAT_TYPE) {
            v.invokestatic("java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");
        }
        else if (type == Type.DOUBLE_TYPE) {
            v.invokestatic("java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");
        }
    }

160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
    private static void unbox(final Type type, InstructionAdapter v) {
        if (type == Type.INT_TYPE) {
            v.invokevirtual("java/lang/Number", "intValue", "()I");
        }
        else if (type == Type.BOOLEAN_TYPE) {
            v.invokevirtual("java/lang/Boolean", "booleanValue", "()Z");
        }
        else if (type == Type.CHAR_TYPE) {
            v.invokevirtual("java/lang/Character", "charValue", "()C");
        }
        else if (type == Type.SHORT_TYPE) {
            v.invokevirtual("java/lang/Number", "shortValue", "()S");
        }
        else if (type == Type.LONG_TYPE) {
            v.invokevirtual("java/lang/Number", "longValue", "()J");
        }
        else if (type == Type.BYTE_TYPE) {
            v.invokevirtual("java/lang/Number", "byteValue", "()B");
        }
        else if (type == Type.FLOAT_TYPE) {
            v.invokevirtual("java/lang/Number", "floatValue", "()F");
        }
        else if (type == Type.DOUBLE_TYPE) {
            v.invokevirtual("java/lang/Number", "doubleValue", "()D");
        }
    }

M
Maxim Shafirov 已提交
187
    public void upcast(Type type, InstructionAdapter v) {
M
Maxim Shafirov 已提交
188 189 190 191 192
        if (type.equals(this.type)) return;

        if (type.getSort() == Type.OBJECT && this.type.getSort() == Type.OBJECT) {
            v.checkcast(type);
        }
M
Maxim Shafirov 已提交
193 194 195 196 197 198 199 200
        else {
            coerce(type, v);
        }
    }

    protected void coerce(Type type, InstructionAdapter v) {
        if (type.equals(this.type)) return;

A
Alex Tkachman 已提交
201 202 203 204 205 206 207 208
        if (type.getSort() == Type.VOID && this.type.getSort() != Type.VOID) {
            if(this.type.getSize() == 1)
                v.pop();
            else
                v.pop2();
        }
        else if (type.getSort() != Type.VOID && this.type.getSort() == Type.VOID) {
            if(type.getSort() == Type.OBJECT)
209
                v.visitFieldInsn(Opcodes.GETSTATIC, "jet/Tuple0", "INSTANCE", "Ljet/Tuple0;");
A
Alex Tkachman 已提交
210 211 212 213 214 215 216 217 218
            else if(type == Type.LONG_TYPE)
                v.lconst(0);
            else if(type == Type.FLOAT_TYPE)
                v.fconst(0);
            else if(type == Type.DOUBLE_TYPE)
                v.dconst(0);
            else
                v.iconst(0);
        }
A
Alex Tkachman 已提交
219
        else if (type.getSort() == Type.OBJECT && this.type.equals(JetTypeMapper.TYPE_OBJECT) || type.getSort() == Type.ARRAY) {
220
                v.checkcast(type);
M
Maxim Shafirov 已提交
221
        }
M
Maxim Shafirov 已提交
222
        else if (type.getSort() == Type.OBJECT) {
223 224 225 226 227
            if(this.type.getSort() == Type.OBJECT && !type.equals(JetTypeMapper.TYPE_OBJECT)) {
                v.checkcast(type);
            }
            else
                box(this.type, type, v);
D
Dmitry Jemerov 已提交
228
        }
229
        else if (this.type.getSort() == Type.OBJECT && type.getSort() <= Type.DOUBLE) {
M
Maxim Shafirov 已提交
230
            if (this.type.equals(JetTypeMapper.TYPE_OBJECT)) {
231
                if (type.getSort() == Type.BOOLEAN) {
232
                    v.checkcast(JvmPrimitiveType.BOOLEAN.getWrapper().getAsmType());
233
                }
A
Alex Tkachman 已提交
234
                else if (type.getSort() == Type.CHAR) {
235
                    v.checkcast(JvmPrimitiveType.CHAR.getWrapper().getAsmType());
A
Alex Tkachman 已提交
236
                }
237
                else {
A
Alex Tkachman 已提交
238
                    v.checkcast(JetTypeMapper.JL_NUMBER_TYPE);
239
                }
M
Maxim Shafirov 已提交
240
            }
241 242
            unbox(type, v);
        }
M
Maxim Shafirov 已提交
243
        else {
D
Dmitry Jemerov 已提交
244 245 246 247
            v.cast(this.type, type);
        }
    }

D
Dmitry Jemerov 已提交
248 249 250
    protected void putAsBoolean(InstructionAdapter v) {
        Label ifTrue = new Label();
        Label end = new Label();
251
        condJump(ifTrue, false, v);
D
Dmitry Jemerov 已提交
252 253 254 255 256 257 258
        v.iconst(0);
        v.goTo(end);
        v.mark(ifTrue);
        v.iconst(1);
        v.mark(end);
    }

259 260 261
    public static StackValue none() {
        return None.INSTANCE;
    }
A
Alex Tkachman 已提交
262 263 264 265 266

    public static StackValue fieldForSharedVar(Type type, String name, String fieldName) {
        return new FieldForSharedVar(type, name, fieldName);
    }

267 268 269 270
    public static StackValue composed(StackValue prefix, StackValue suffix) {
        return new Composed(prefix, suffix);
    }

271 272 273 274
    public static StackValue thisOrOuter(ExpressionCodegen codegen, ClassDescriptor descriptor) {
        return new ThisOuter(codegen, descriptor);
    }

A
Alex Tkachman 已提交
275 276 277 278 279 280 281 282
    public static StackValue postIncrement(int index, int increment) {
        return new PostIncrement(index, increment);
    }

    public static StackValue preIncrement(int index, int increment) {
        return new PreIncrement(index, increment);
    }

283 284 285 286 287 288
    public static StackValue receiver(ResolvedCall<? extends CallableDescriptor> resolvedCall, StackValue receiver, ExpressionCodegen codegen, @Nullable CallableMethod callableMethod) {
        if(resolvedCall.getThisObject().exists() || resolvedCall.getReceiverArgument().exists())
            return new CallReceiver(resolvedCall, receiver, codegen, callableMethod);
        return receiver;
    }

289 290 291 292 293 294 295 296
    private static class None extends StackValue {
        public static None INSTANCE = new None();
        private None() {
            super(Type.VOID_TYPE);
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
A
Alex Tkachman 已提交
297
            coerce(type, v);
298 299 300
        }
    }

301
    public static class Local extends StackValue {
302
        final int index;
303

D
Dmitry Jemerov 已提交
304
        public Local(int index, Type type) {
D
Dmitry Jemerov 已提交
305
            super(type);
306 307 308 309 310
            this.index = index;
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
D
Dmitry Jemerov 已提交
311
            v.load(index, this.type);
D
Dmitry Jemerov 已提交
312
            coerce(type, v);
D
Dmitry Jemerov 已提交
313
            // TODO unbox
314
        }
315 316

        @Override
317
        public void store(InstructionAdapter v) {
318
            v.store(index, this.type);
319
        }
320 321 322 323
    }

    public static class OnStack extends StackValue {
        public OnStack(Type type) {
D
Dmitry Jemerov 已提交
324
            super(type);
325 326 327 328
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
329 330 331 332 333 334 335 336 337 338 339
            if (type == Type.VOID_TYPE && this.type != Type.VOID_TYPE) {
                if (this.type.getSize() == 2) {
                    v.pop2();
                }
                else {
                    v.pop();
                }
            }
            else {
                coerce(type, v);
            }
340 341 342 343 344 345
        }
    }

    public static class Constant extends StackValue {
        private final Object value;

D
Dmitry Jemerov 已提交
346 347
        public Constant(Object value, Type type) {
            super(type);
348 349 350 351 352
            this.value = value;
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
A
Alex Tkachman 已提交
353 354 355 356 357 358 359 360 361 362 363 364 365
            if(value instanceof Integer)
                v.iconst((Integer) value);
            else
            if(value instanceof Long)
                v.lconst((Long) value);
            else
            if(value instanceof Float)
                v.fconst((Float) value);
            else
            if(value instanceof Double)
                v.dconst((Double) value);
            else
                v.aconst(value);
D
Dmitry Jemerov 已提交
366
            coerce(type, v);
367
        }
368 369

        @Override
370
        public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
D
Dmitry Jemerov 已提交
371
            if (value instanceof Boolean) {
A
Alex Tkachman 已提交
372
                boolean boolValue = (Boolean) value;
373 374 375
                if (boolValue ^ jumpIfFalse) {
                    v.goTo(label);
                }
D
Dmitry Jemerov 已提交
376 377 378 379
            }
            else {
                throw new UnsupportedOperationException("don't know how to generate this condjump");
            }
380 381 382
        }
    }

D
Float  
Dmitry Jemerov 已提交
383
    private static class NumberCompare extends StackValue {
D
Dmitry Jemerov 已提交
384
        protected final IElementType opToken;
D
Dmitry Jemerov 已提交
385
        private final Type operandType;
386

D
Dmitry Jemerov 已提交
387 388
        public NumberCompare(IElementType opToken, Type operandType) {
            super(Type.BOOLEAN_TYPE);
389
            this.opToken = opToken;
D
Dmitry Jemerov 已提交
390
            this.operandType = operandType;
391 392 393 394
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
395 396 397
            if (type == Type.VOID_TYPE) {
                return;
            }
398
            if (type != Type.BOOLEAN_TYPE) {
399
                throw new UnsupportedOperationException("don't know how to put a compare as a non-boolean type " + type);
400
            }
D
Dmitry Jemerov 已提交
401
            putAsBoolean(v);
402 403 404
        }

        @Override
405
        public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
406
            int opcode;
407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
            if (opToken == JetTokens.EQEQ) {
                opcode = jumpIfFalse ? Opcodes.IFNE : Opcodes.IFEQ;
            }
            else if (opToken == JetTokens.EXCLEQ) {
                opcode = jumpIfFalse ? Opcodes.IFEQ : Opcodes.IFNE;
            }
            else if (opToken == JetTokens.GT) {
                opcode = jumpIfFalse ? Opcodes.IFLE : Opcodes.IFGT;
            }
            else if (opToken == JetTokens.GTEQ) {
                opcode = jumpIfFalse ? Opcodes.IFLT : Opcodes.IFGE;
            }
            else if (opToken == JetTokens.LT) {
                opcode = jumpIfFalse ? Opcodes.IFGE : Opcodes.IFLT;
            }
            else if (opToken == JetTokens.LTEQ) {
                opcode = jumpIfFalse ? Opcodes.IFGT : Opcodes.IFLE;
            }
425 426 427
            else {
                throw new UnsupportedOperationException("don't know how to generate this condjump");
            }
D
Dmitry Jemerov 已提交
428
            if (operandType == Type.FLOAT_TYPE || operandType == Type.DOUBLE_TYPE) {
D
Float  
Dmitry Jemerov 已提交
429
                if (opToken == JetTokens.GT || opToken == JetTokens.GTEQ) {
D
Dmitry Jemerov 已提交
430
                    v.cmpg(operandType);
D
Float  
Dmitry Jemerov 已提交
431 432
                }
                else {
D
Dmitry Jemerov 已提交
433
                    v.cmpl(operandType);
D
Float  
Dmitry Jemerov 已提交
434 435
                }
            }
D
Dmitry Jemerov 已提交
436
            else if (operandType == Type.LONG_TYPE) {
D
Dmitry Jemerov 已提交
437 438
                v.lcmp();
            }
D
Float  
Dmitry Jemerov 已提交
439 440 441
            else {
                opcode += (Opcodes.IF_ICMPEQ - Opcodes.IFEQ);
            }
442
            v.visitJumpInsn(opcode, label);
443
        }
444
    }
D
Dmitry Jemerov 已提交
445

D
Dmitry Jemerov 已提交
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466
    private static class ObjectCompare extends NumberCompare {
        public ObjectCompare(IElementType opToken, Type operandType) {
            super(opToken, operandType);
        }

        @Override
        public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
            int opcode;
            if (opToken == JetTokens.EQEQEQ) {
                opcode = jumpIfFalse ? Opcodes.IF_ACMPNE : Opcodes.IF_ACMPEQ;
            }
            else if (opToken == JetTokens.EXCLEQEQEQ) {
                opcode = jumpIfFalse ? Opcodes.IF_ACMPEQ : Opcodes.IF_ACMPNE;
            }
            else {
                throw new UnsupportedOperationException("don't know how to generate this condjump");
            }
            v.visitJumpInsn(opcode, label);
        }
    }

D
Dmitry Jemerov 已提交
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
    private static class Invert extends StackValue {
        private StackValue myOperand;

        private Invert(StackValue operand) {
            super(operand.type);
            myOperand = operand;
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
            if (type != Type.BOOLEAN_TYPE) {
                throw new UnsupportedOperationException("don't know how to put a compare as a non-boolean type");
            }
            putAsBoolean(v);
        }

        @Override
484 485
        public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
            myOperand.condJump(label, !jumpIfFalse, v);
D
Dmitry Jemerov 已提交
486 487
        }
    }
488 489

    private static class ArrayElement extends StackValue {
A
Alex Tkachman 已提交
490
        private Type boxed;
491

A
Alex Tkachman 已提交
492
        public ArrayElement(Type type, boolean unbox) {
493
            super(type);
A
Alex Tkachman 已提交
494
            this.boxed = unbox ? JetTypeMapper.boxType(type) : type;
495 496 497 498
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
A
Alex Tkachman 已提交
499 500
            v.aload(boxed);    // assumes array and index are on the stack
            onStack(boxed).coerce(type, v);
501 502 503
        }

        @Override
504
        public void store(InstructionAdapter v) {
A
Alex Tkachman 已提交
505 506
            onStack(type).coerce(boxed, v);
            v.astore(boxed);
507
        }
508 509

        @Override
510 511
        public void dupReceiver(InstructionAdapter v) {
            v.dup2();   // array and index
512
        }
A
Alex Tkachman 已提交
513 514 515 516

        public int receiverSize() {
            return 2;
        }
517 518
    }

D
Dmitry Jemerov 已提交
519
    private static class CollectionElement extends StackValue {
520 521
        private final Callable getter;
        private final Callable setter;
522
        private final ExpressionCodegen codegen;
523
        private final FrameMap frame;
524 525 526 527
        private final ResolvedCall<FunctionDescriptor> resolvedGetCall;
        private final ResolvedCall<FunctionDescriptor> resolvedSetCall;
        private final FunctionDescriptor setterDescriptor;
        private final FunctionDescriptor getterDescriptor;
D
Dmitry Jemerov 已提交
528

529
        public CollectionElement(Type type, ResolvedCall<FunctionDescriptor> resolvedGetCall, ResolvedCall<FunctionDescriptor> resolvedSetCall, ExpressionCodegen codegen) {
D
Dmitry Jemerov 已提交
530
            super(type);
531 532 533 534
            this.resolvedGetCall = resolvedGetCall;
            this.resolvedSetCall = resolvedSetCall;
            this.setterDescriptor = resolvedSetCall == null ? null : resolvedSetCall.getResultingDescriptor();
            this.getterDescriptor = resolvedGetCall == null ? null : resolvedGetCall.getResultingDescriptor();
535 536
            this.setter = resolvedSetCall == null ? null : codegen.resolveToCallable(setterDescriptor, false);
            this.getter = resolvedGetCall == null ? null : codegen.resolveToCallable(getterDescriptor, false);
537 538
            this.codegen = codegen;
            this.frame = codegen.myFrameMap;
D
Dmitry Jemerov 已提交
539 540 541 542 543 544 545
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
            if (getter == null) {
                throw new UnsupportedOperationException("no getter specified");
            }
546 547 548 549
            if(getter instanceof CallableMethod)
                ((CallableMethod)getter).invoke(v);
            else
                ((IntrinsicMethod)getter).generate(codegen, v, null, null, null, null);
A
Alex Tkachman 已提交
550
            coerce(type, v);
D
Dmitry Jemerov 已提交
551 552 553 554 555 556 557
        }

        @Override
        public void store(InstructionAdapter v) {
            if (setter == null) {
                throw new UnsupportedOperationException("no setter specified");
            }
558 559 560 561 562 563 564 565 566 567 568
            if(setter instanceof CallableMethod) {
                CallableMethod method = (CallableMethod) setter;
                method.invoke(v);
                Type returnType = method.getSignature().getAsmMethod().getReturnType();
                if(returnType != Type.VOID_TYPE) {
                    if(returnType.getSize() == 2)
                        v.pop2();
                    else
                        v.pop();
                }
            }
569 570
            else
                ((IntrinsicMethod)setter).generate(codegen, v, null, null, null, null);
D
Dmitry Jemerov 已提交
571 572
        }

A
Alex Tkachman 已提交
573
        public int receiverSize() {
574
            if(isStandardStack(resolvedGetCall, 1) && isStandardStack(resolvedSetCall, 2)) {
A
Alex Tkachman 已提交
575 576 577 578 579 580 581
                return 2;
            }
            else {
                return -1;
            }
        }

D
Dmitry Jemerov 已提交
582
        @Override
583
        public void dupReceiver(InstructionAdapter v) {
584
            if(isStandardStack(resolvedGetCall, 1) && isStandardStack(resolvedSetCall, 2)) {
585
                v.dup2();   // collection and index
D
Dmitry Jemerov 已提交
586 587
            }
            else {
588 589
                int size = 0;
                int lastIndex = frame.enterTemp();
590 591
                frame.leaveTemp();
                
592 593 594 595
                // indexes
                List<ValueParameterDescriptor> valueParameters = resolvedGetCall.getResultingDescriptor().getValueParameters();
                int firstParamIndex = -1;
                for(int i = valueParameters.size()-1; i >= 0; --i) {
596
                    Type type = codegen.typeMapper.mapType(valueParameters.get(i).getType());
597
                    int sz = type.getSize();
598 599
                    frame.enterTemp(sz);
                    lastIndex += sz;
600 601 602 603 604 605 606 607 608 609 610 611 612
                    size += sz;
                    v.store((firstParamIndex = lastIndex)-sz, type);
                }

                List<TypeParameterDescriptor> typeParameters = resolvedGetCall.getResultingDescriptor().getTypeParameters();
                int firstTypeParamIndex = -1;
                for(int i = typeParameters.size()-1; i >= 0; --i)  {
                    if(typeParameters.get(i).isReified()) {
                        frame.enterTemp();
                        lastIndex++;
                        size++;
                        v.store(firstTypeParamIndex = lastIndex-1, JetTypeMapper.TYPE_OBJECT);
                    }
613 614
                }

615 616 617 618 619 620 621 622 623 624 625 626 627 628
                ReceiverDescriptor receiverParameter = resolvedGetCall.getReceiverArgument();
                int receiverIndex = -1;
                if(receiverParameter.exists()) {
                    Type type = codegen.typeMapper.mapType(receiverParameter.getType());
                    int sz = type.getSize();
                    frame.enterTemp(sz);
                    lastIndex += sz;
                    size += sz;
                    v.store((receiverIndex = lastIndex)-sz, type);
                }

                ReceiverDescriptor thisObject = resolvedGetCall.getThisObject();
                int thisIndex = -1;
                if(thisObject.exists()) {
629 630
                    frame.enterTemp();
                    lastIndex++;
631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656
                    size++;
                    v.store((thisIndex = lastIndex)-1, JetTypeMapper.TYPE_OBJECT);
                }
                
                // for setter

                int  realReceiverIndex;
                Type realReceiverType;
                if(thisIndex != -1) {
                    if(receiverIndex != -1) {
                        realReceiverIndex = receiverIndex;
                        realReceiverType =  codegen.typeMapper.mapType(receiverParameter.getType());
                    }
                    else {
                        realReceiverIndex = thisIndex;
                        realReceiverType = JetTypeMapper.TYPE_OBJECT;
                    }
                }
                else {
                    if(receiverIndex != -1) {
                        realReceiverType =  codegen.typeMapper.mapType(receiverParameter.getType());
                        realReceiverIndex = receiverIndex;
                    }
                    else {
                        throw new UnsupportedOperationException();
                    }
657 658
                }

659 660
                if(resolvedSetCall.getThisObject().exists()) {
                    if(resolvedSetCall.getReceiverArgument().exists()) {
661
                        codegen.generateFromResolvedCall(resolvedSetCall.getThisObject(), JetTypeMapper.TYPE_OBJECT);
662 663 664 665 666 667 668 669 670 671
                    }
                    v.load(realReceiverIndex - realReceiverType.getSize(), realReceiverType);
                }
                else {
                    if(resolvedSetCall.getReceiverArgument().exists()) {
                        v.load(realReceiverIndex - realReceiverType.getSize(), realReceiverType);
                    }
                    else {
                        throw new UnsupportedOperationException();
                    }
672 673
                }

674 675
                int index = firstParamIndex;
                for(int i = 0; i != valueParameters.size(); ++i) {
676
                    Type type = codegen.typeMapper.mapType(valueParameters.get(i).getType());
677 678 679
                    int sz = type.getSize();
                    v.load(index-sz, type);
                    index -= sz;
680 681
                }

682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703
                // restoring original
                if(thisIndex != -1) {
                    v.load(thisIndex-1, JetTypeMapper.TYPE_OBJECT);
                }
                
                if(receiverIndex != -1) {
                    Type type = codegen.typeMapper.mapType(receiverParameter.getType());
                    v.load(receiverIndex-type.getSize(), type);
                }

                if(firstTypeParamIndex != -1) {
                    index = firstTypeParamIndex;
                    for(int i = 0; i != typeParameters.size(); ++i)  {
                        if(typeParameters.get(i).isReified()) {
                            v.load(index-1, JetTypeMapper.TYPE_OBJECT);
                            index--;
                        }
                    }
                }
                
                index = firstParamIndex;
                for(int i = 0; i != valueParameters.size(); ++i) {
704
                    Type type = codegen.typeMapper.mapType(valueParameters.get(i).getType());
705 706 707
                    int sz = type.getSize();
                    v.load(index-sz, type);
                    index -= sz;
708 709 710
                }

                frame.leaveTemp(size);
D
Dmitry Jemerov 已提交
711 712
            }
        }
713

714
        private boolean isStandardStack(ResolvedCall call, int valueParamsSize) {
A
Alex Tkachman 已提交
715 716 717
            if(call == null)
                return true;

718 719 720 721 722
            for (TypeParameterDescriptor typeParameterDescriptor : call.getResultingDescriptor().getTypeParameters()) {
                if(typeParameterDescriptor.isReified())
                    return false;
            }

723 724
            List<ValueParameterDescriptor> valueParameters = call.getResultingDescriptor().getValueParameters();
            if(valueParameters.size() != valueParamsSize)
725 726
                return false;

727
            for (ValueParameterDescriptor valueParameter : valueParameters) {
728
                if (codegen.typeMapper.mapType(valueParameter.getType()).getSize() != 1)
729 730 731
                    return false;
            }

732 733 734 735 736 737 738 739 740 741
            if(call.getThisObject().exists()) {
                if(call.getReceiverArgument().exists())
                    return false;
            }
            else {
                if(codegen.typeMapper.mapType(call.getResultingDescriptor().getReceiverParameter().getType()).getSize() != 1)
                    return false;
            }

            return true;
742
        }
D
Dmitry Jemerov 已提交
743 744
    }

M
Maxim Shafirov 已提交
745

A
Alex Tkachman 已提交
746 747 748
    static class Field extends StackValue {
        final String owner;
        final String name;
749 750 751 752 753 754 755 756 757 758 759 760
        private final boolean isStatic;

        public Field(Type type, String owner, String name, boolean isStatic) {
            super(type);
            this.owner = owner;
            this.name = name;
            this.isStatic = isStatic;
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
            v.visitFieldInsn(isStatic ? Opcodes.GETSTATIC : Opcodes.GETFIELD, owner, name, this.type.getDescriptor());
761
            coerce(type, v);
762 763 764
        }

        @Override
765
        public void dupReceiver(InstructionAdapter v) {
D
Dmitry Jemerov 已提交
766
            if (!isStatic) {
767
                v.dup();
D
Dmitry Jemerov 已提交
768
            }
769 770
        }

A
Alex Tkachman 已提交
771 772 773 774
        public int receiverSize() {
            return isStatic ? 0 : 1;
        }

775 776
        @Override
        public void store(InstructionAdapter v) {
777 778 779
            v.visitFieldInsn(isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, owner, name, this.type.getDescriptor());
        }
    }
780

781
    static class Property extends StackValue {
782
        @NotNull
783
        private final String name;
784
        @Nullable
785
        private final Method getter;
786
        @Nullable
787
        private final Method setter;
788 789 790 791
        @NotNull
        public final String methodOwner;
        @NotNull
        private final String methodOwnerParam;
792
        private final boolean isStatic;
793
        private final boolean isInterface;
794 795
        private final boolean isSuper;
        private final int invokeOpcode;
796

797
        public Property(@NotNull String name, @NotNull String methodOwner, @NotNull String methodOwnerParam, Method getter, Method setter, boolean aStatic, boolean isInterface, boolean isSuper, Type type, int invokeOpcode) {
798 799
            super(type);
            this.name = name;
800 801
            this.methodOwner = methodOwner;
            this.methodOwnerParam = methodOwnerParam;
802 803
            this.getter = getter;
            this.setter = setter;
804
            isStatic = aStatic;
805
            this.isInterface = isInterface;
A
Alex Tkachman 已提交
806
            this.isSuper = isSuper;
807 808 809 810 811 812
            this.invokeOpcode = invokeOpcode;
            if (invokeOpcode == 0) {
                if (setter != null || getter != null) {
                    throw new IllegalArgumentException();
                }
            }
813 814 815 816
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
A
Alex Tkachman 已提交
817
            if(isSuper && isInterface) {
818
                v.visitMethodInsn(Opcodes.INVOKESTATIC, methodOwner, getter.getName(), getter.getDescriptor().replace("(", "(L" + methodOwnerParam + ";"));
819 820
            }
            else {
A
Alex Tkachman 已提交
821
            if (getter == null) {
822
                v.visitFieldInsn(isStatic ? Opcodes.GETSTATIC : Opcodes.GETFIELD, methodOwner, name, this.type.getDescriptor());
A
Alex Tkachman 已提交
823 824
            }
            else {
825
                v.visitMethodInsn(invokeOpcode, methodOwner, getter.getName(), getter.getDescriptor());
A
Alex Tkachman 已提交
826
            }
827
            }
828
            coerce(type, v);
829 830 831 832
        }

        @Override
        public void store(InstructionAdapter v) {
A
Alex Tkachman 已提交
833
            if(isSuper && isInterface) {
834
                v.visitMethodInsn(Opcodes.INVOKESTATIC, methodOwner, setter.getName(), setter.getDescriptor().replace("(", "(L" + methodOwnerParam + ";"));
835 836
            }
            else {
A
Alex Tkachman 已提交
837
            if (setter == null) {
838
                v.visitFieldInsn(isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, methodOwner, name, this.type.getDescriptor());
A
Alex Tkachman 已提交
839 840
            }
            else {
841
                v.visitMethodInsn(invokeOpcode, methodOwner, setter.getName(), setter.getDescriptor());
A
Alex Tkachman 已提交
842
                }
843 844
            }
        }
845 846

        @Override
847
        public void dupReceiver(InstructionAdapter v) {
848
            if (!isStatic) {
849
                v.dup();
850 851
            }
        }
A
Alex Tkachman 已提交
852 853 854 855

        public int receiverSize() {
            return isStatic ? 0 : 1;
        }
856
    }
857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872

    private static class Expression extends StackValue {
        private final JetExpression expression;
        private final ExpressionCodegen generator;

        public Expression(Type type, JetExpression expression, ExpressionCodegen generator) {
            super(type);
            this.expression = expression;
            this.generator = generator;
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
            generator.gen(expression, type);
        }
    }
A
Alex Tkachman 已提交
873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919

    public static class Shared extends StackValue {
        private final int index;

        public Shared(int index, Type type) {
            super(type);
            this.index = index;
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
            v.load(index, JetTypeMapper.TYPE_OBJECT);
            Type refType = refType(this.type);
            Type sharedType = sharedTypeForType(this.type);
            v.visitFieldInsn(Opcodes.GETFIELD, sharedType.getInternalName(), "ref", refType.getDescriptor());
            StackValue.onStack(refType).coerce(this.type, v);
            StackValue.onStack(this.type).coerce(type, v);
        }

        @Override
        public void store(InstructionAdapter v) {
            v.load(index, JetTypeMapper.TYPE_OBJECT);
            v.swap();
            Type refType = refType(this.type);
            Type sharedType = sharedTypeForType(this.type);
            v.visitFieldInsn(Opcodes.PUTFIELD, sharedType.getInternalName(), "ref", refType.getDescriptor());
        }
    }

    public static Type sharedTypeForType(Type type) {
        switch(type.getSort()) {
            case Type.OBJECT:
            case Type.ARRAY:
                return JetTypeMapper.TYPE_SHARED_VAR;

            case Type.BYTE:
                return JetTypeMapper.TYPE_SHARED_BYTE;

            case Type.SHORT:
                return JetTypeMapper.TYPE_SHARED_SHORT;

            case Type.CHAR:
                return JetTypeMapper.TYPE_SHARED_CHAR;

            case Type.INT:
                return JetTypeMapper.TYPE_SHARED_INT;

A
varargs  
Alex Tkachman 已提交
920 921 922
            case Type.LONG:
                return JetTypeMapper.TYPE_SHARED_LONG;

A
Alex Tkachman 已提交
923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954
            case Type.BOOLEAN:
                return JetTypeMapper.TYPE_SHARED_BOOLEAN;

            case Type.FLOAT:
                return JetTypeMapper.TYPE_SHARED_FLOAT;

            case Type.DOUBLE:
                return JetTypeMapper.TYPE_SHARED_DOUBLE;

            default:
                throw new UnsupportedOperationException();
        }
    }

    public static Type refType(Type type) {
        if(type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY)
            return JetTypeMapper.TYPE_OBJECT;

        return type;
    }

    static class FieldForSharedVar extends StackValue {
        final String owner;
        final String name;

        public FieldForSharedVar(Type type, String owner, String name) {
            super(type);
            this.owner = owner;
            this.name = name;
        }

        @Override
955 956
        public void dupReceiver(InstructionAdapter v) {
            v.dup();
A
Alex Tkachman 已提交
957 958
        }

A
Alex Tkachman 已提交
959 960 961 962
        public int receiverSize() {
            return 1;
        }

A
Alex Tkachman 已提交
963 964 965 966 967 968 969 970 971 972 973 974 975 976
        @Override
        public void put(Type type, InstructionAdapter v) {
            Type sharedType = sharedTypeForType(this.type);
            Type refType = refType(this.type);
            v.visitFieldInsn(Opcodes.GETFIELD, sharedType.getInternalName(), "ref", refType.getDescriptor());
            StackValue.onStack(refType).coerce(this.type, v);
            StackValue.onStack(this.type).coerce(type, v);
        }

        @Override
        public void store(InstructionAdapter v) {
            v.visitFieldInsn(Opcodes.PUTFIELD, sharedTypeForType(type).getInternalName(), "ref", refType(type).getDescriptor());
        }
    }
977

A
Alex Tkachman 已提交
978 979 980
    public static class Composed extends StackValue {
        public final StackValue prefix;
        public final StackValue suffix;
981 982 983 984 985 986 987 988 989 990 991 992

        public Composed(StackValue prefix, StackValue suffix) {
            super(suffix.type);
            this.prefix = prefix;
            this.suffix = suffix;
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
            prefix.put(prefix.type, v);
            suffix.put(type, v);
        }
A
Alex Tkachman 已提交
993 994 995 996 997 998

        @Override
        public void store(InstructionAdapter v) {
            prefix.put(JetTypeMapper.TYPE_OBJECT, v);
            suffix.store(v);
        }
999
    }
1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015

    private static class ThisOuter extends StackValue {
        private ExpressionCodegen codegen;
        private ClassDescriptor descriptor;

        public ThisOuter(ExpressionCodegen codegen, ClassDescriptor descriptor) {
            super(JetTypeMapper.TYPE_OBJECT);
            this.codegen = codegen;
            this.descriptor = descriptor;
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
            codegen.generateThisOrOuter(descriptor);
        }
    }
A
Alex Tkachman 已提交
1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055

    private static class PostIncrement extends StackValue {
        private int index;
        private int increment;

        public PostIncrement(int index, int increment) {
            super(Type.INT_TYPE);
            this.index = index;
            this.increment = increment;
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
            if(!type.equals(Type.VOID_TYPE)) {
                v.load(index, Type.INT_TYPE);
                coerce(type, v);
            }
            v.iinc(index, increment);
        }
    }

    private static class PreIncrement extends StackValue {
        private int index;
        private int increment;

        public PreIncrement(int index, int increment) {
            super(Type.INT_TYPE);
            this.index = index;
            this.increment = increment;
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
            v.iinc(index, increment);
            if(!type.equals(Type.VOID_TYPE)) {
                v.load(index, Type.INT_TYPE);
                coerce(type, v);
            }
        }
    }
1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082

    public static class CallReceiver extends StackValue {
        private ResolvedCall<? extends CallableDescriptor> resolvedCall;
        StackValue receiver;
        private ExpressionCodegen codegen;
        private CallableMethod callableMethod;

        public CallReceiver(ResolvedCall<? extends CallableDescriptor> resolvedCall, StackValue receiver, ExpressionCodegen codegen, CallableMethod callableMethod) {
            super(calcType(resolvedCall, codegen, callableMethod));
            this.resolvedCall = resolvedCall;
            this.receiver = receiver;
            this.codegen = codegen;
            this.callableMethod = callableMethod;
        }

        private static Type calcType(ResolvedCall<? extends CallableDescriptor> resolvedCall, ExpressionCodegen codegen, CallableMethod callableMethod) {
            ReceiverDescriptor thisObject = resolvedCall.getThisObject();
            ReceiverDescriptor receiverArgument = resolvedCall.getReceiverArgument();

            CallableDescriptor descriptor = resolvedCall.getResultingDescriptor();

            if (thisObject.exists()) {
                if(callableMethod != null) {
                    if(receiverArgument.exists()) {
                        return codegen.typeMapper.mapType(callableMethod.getReceiverClass());
                    }
                    else {
A
Alex Tkachman 已提交
1083
                        return codegen.typeMapper.mapType(callableMethod.getThisType());
1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115
                    }
                }
                else {
                    if(receiverArgument.exists()) {
                        return codegen.typeMapper.mapType(descriptor.getReceiverParameter().getType());
                    }
                    else {
                        return codegen.typeMapper.mapType(descriptor.getExpectedThisObject().getType());
                    }
                }
            }
            else {
                if (receiverArgument.exists()) {
                    if(callableMethod != null)
                        return codegen.typeMapper.mapType(callableMethod.getReceiverClass());
                    else
                        return codegen.typeMapper.mapType(descriptor.getReceiverParameter().getType());
                }
                else {
                    return Type.VOID_TYPE;
                }
            }
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
            CallableDescriptor descriptor = resolvedCall.getResultingDescriptor();

            ReceiverDescriptor thisObject = resolvedCall.getThisObject();
            ReceiverDescriptor receiverArgument = resolvedCall.getReceiverArgument();
            if (thisObject.exists()) {
                if(receiverArgument.exists()) {
1116
                    codegen.generateFromResolvedCall(thisObject, callableMethod != null ? Type.getObjectType(callableMethod.getOwner()) : codegen.typeMapper.mapType(descriptor.getExpectedThisObject().getType()));
1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145
                    genReceiver(v, receiverArgument, type, descriptor.getReceiverParameter());
                }
                else {
                    genReceiver(v, thisObject, type, null);
                }
            }
            else {
                if (receiverArgument.exists()) {
                    genReceiver(v, receiverArgument, type, descriptor.getReceiverParameter());
                }
            }
        }

        private void genReceiver(InstructionAdapter v, ReceiverDescriptor receiverArgument, Type type, ReceiverDescriptor receiverParameter) {
            if(receiver == StackValue.none()) {
                if(receiverParameter != null) {
                    Type receiverType = codegen.typeMapper.mapType(receiverParameter.getType());
                    codegen.generateFromResolvedCall(receiverArgument, receiverType);
                    StackValue.onStack(receiverType).put(type, v);
                }
                else {
                    codegen.generateFromResolvedCall(receiverArgument, type);
                }
            }
            else {
                receiver.put(type, v);
            }
        }
    }
1146
}