001 /* 002 * Copyright 2010-2013 JetBrains s.r.o. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.jetbrains.jet.codegen; 018 019 import com.google.common.collect.Lists; 020 import com.google.common.collect.Maps; 021 import com.intellij.openapi.editor.Document; 022 import com.intellij.openapi.progress.ProcessCanceledException; 023 import com.intellij.psi.PsiElement; 024 import com.intellij.psi.tree.IElementType; 025 import com.intellij.util.ArrayUtil; 026 import com.intellij.util.Function; 027 import com.intellij.util.containers.Stack; 028 import org.jetbrains.annotations.NotNull; 029 import org.jetbrains.annotations.Nullable; 030 import org.jetbrains.jet.codegen.binding.CalculatedClosure; 031 import org.jetbrains.jet.codegen.binding.CodegenBinding; 032 import org.jetbrains.jet.codegen.binding.MutableClosure; 033 import org.jetbrains.jet.codegen.context.*; 034 import org.jetbrains.jet.codegen.inline.InlineCodegen; 035 import org.jetbrains.jet.codegen.inline.NameGenerator; 036 import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethod; 037 import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodSignature; 038 import org.jetbrains.jet.codegen.state.GenerationState; 039 import org.jetbrains.jet.codegen.state.JetTypeMapper; 040 import org.jetbrains.jet.lang.descriptors.*; 041 import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; 042 import org.jetbrains.jet.lang.evaluate.EvaluatePackage; 043 import org.jetbrains.jet.lang.psi.*; 044 import org.jetbrains.jet.lang.resolve.BindingContext; 045 import org.jetbrains.jet.lang.resolve.DescriptorUtils; 046 import org.jetbrains.jet.lang.resolve.calls.model.*; 047 import org.jetbrains.jet.lang.resolve.calls.util.CallMaker; 048 import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; 049 import org.jetbrains.jet.lang.resolve.constants.IntegerValueConstant; 050 import org.jetbrains.jet.lang.resolve.constants.IntegerValueTypeConstant; 051 import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants; 052 import org.jetbrains.jet.lang.resolve.java.JvmAbi; 053 import org.jetbrains.jet.lang.resolve.java.descriptor.SamConstructorDescriptor; 054 import org.jetbrains.jet.lang.resolve.name.Name; 055 import org.jetbrains.jet.lang.resolve.scopes.receivers.*; 056 import org.jetbrains.jet.lang.types.JetType; 057 import org.jetbrains.jet.lang.types.checker.JetTypeChecker; 058 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 059 import org.jetbrains.jet.lexer.JetTokens; 060 import org.jetbrains.jet.renderer.DescriptorRenderer; 061 import org.jetbrains.org.objectweb.asm.Label; 062 import org.jetbrains.org.objectweb.asm.MethodVisitor; 063 import org.jetbrains.org.objectweb.asm.Type; 064 import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; 065 import org.jetbrains.org.objectweb.asm.commons.Method; 066 067 import java.util.*; 068 069 import static org.jetbrains.jet.codegen.AsmUtil.*; 070 import static org.jetbrains.jet.codegen.JvmCodegenUtil.*; 071 import static org.jetbrains.jet.codegen.binding.CodegenBinding.*; 072 import static org.jetbrains.jet.lang.resolve.BindingContext.*; 073 import static org.jetbrains.jet.lang.resolve.BindingContextUtils.getNotNull; 074 import static org.jetbrains.jet.lang.resolve.BindingContextUtils.isVarCapturedInClosure; 075 import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.*; 076 import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KotlinSyntheticClass; 077 import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER; 078 import static org.jetbrains.org.objectweb.asm.Opcodes.*; 079 080 public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implements LocalLookup, ParentCodegenAware { 081 private static final Set<DeclarationDescriptor> INTEGRAL_RANGES = KotlinBuiltIns.getInstance().getIntegralRanges(); 082 083 private int myLastLineNumber = -1; 084 085 public final InstructionAdapter v; 086 final MethodVisitor methodVisitor; 087 final FrameMap myFrameMap; 088 final JetTypeMapper typeMapper; 089 090 private final GenerationState state; 091 private final Type returnType; 092 093 private final BindingContext bindingContext; 094 private final MethodContext context; 095 private final CodegenStatementVisitor statementVisitor; 096 097 private final Stack<BlockStackElement> blockStackElements = new Stack<BlockStackElement>(); 098 099 @Nullable 100 private final MemberCodegen<?> parentCodegen; 101 102 /* 103 * When we create a temporary variable to hold some value not to compute it many times 104 * we put it into this map to emit access to that variable instead of evaluating the whole expression 105 */ 106 final Map<JetElement, StackValue> tempVariables = Maps.newHashMap(); 107 108 private final TailRecursionCodegen tailRecursionCodegen; 109 110 public final CallGenerator defaultCallGenerator; 111 112 public CalculatedClosure generateObjectLiteral(GenerationState state, JetObjectLiteralExpression literal) { 113 JetObjectDeclaration objectDeclaration = literal.getObjectDeclaration(); 114 115 Type asmType = asmTypeForAnonymousClass(bindingContext, objectDeclaration); 116 ClassBuilder classBuilder = state.getFactory().newVisitor(asmType, literal.getContainingFile()); 117 118 ClassDescriptor classDescriptor = bindingContext.get(CLASS, objectDeclaration); 119 assert classDescriptor != null; 120 121 ClassContext objectContext = context.intoAnonymousClass(classDescriptor, this); 122 123 new ImplementationBodyCodegen(objectDeclaration, objectContext, classBuilder, state, getParentCodegen()).generate(); 124 125 return bindingContext.get(CLOSURE, classDescriptor); 126 } 127 128 static class BlockStackElement { 129 } 130 131 static class LoopBlockStackElement extends BlockStackElement { 132 final Label continueLabel; 133 final Label breakLabel; 134 public final JetSimpleNameExpression targetLabel; 135 136 LoopBlockStackElement(Label breakLabel, Label continueLabel, JetSimpleNameExpression targetLabel) { 137 this.breakLabel = breakLabel; 138 this.continueLabel = continueLabel; 139 this.targetLabel = targetLabel; 140 } 141 } 142 143 static class FinallyBlockStackElement extends BlockStackElement { 144 List<Label> gaps = new ArrayList<Label>(); 145 146 final JetTryExpression expression; 147 148 FinallyBlockStackElement(JetTryExpression expression) { 149 this.expression = expression; 150 } 151 152 private void addGapLabel(Label label){ 153 gaps.add(label); 154 } 155 } 156 157 public ExpressionCodegen( 158 @NotNull MethodVisitor v, 159 @NotNull FrameMap myMap, 160 @NotNull Type returnType, 161 @NotNull MethodContext context, 162 @NotNull GenerationState state, 163 @Nullable MemberCodegen<?> parentCodegen 164 ) { 165 this.myFrameMap = myMap; 166 this.parentCodegen = parentCodegen; 167 this.typeMapper = state.getTypeMapper(); 168 this.returnType = returnType; 169 this.state = state; 170 this.methodVisitor = v; 171 this.v = new InstructionAdapter(methodVisitor); 172 this.bindingContext = state.getBindingContext(); 173 this.context = context; 174 this.statementVisitor = new CodegenStatementVisitor(this); 175 this.tailRecursionCodegen = new TailRecursionCodegen(context, this, this.v, state); 176 this.defaultCallGenerator = new CallGenerator.DefaultCallGenerator(this); 177 } 178 179 public GenerationState getState() { 180 return state; 181 } 182 183 @NotNull 184 private StackValue castToRequiredTypeOfInterfaceIfNeeded( 185 StackValue inner, 186 @NotNull ClassDescriptor provided, 187 @NotNull ClassDescriptor required 188 ) { 189 if (!isInterface(provided) && isInterface(required)) { 190 inner.put(OBJECT_TYPE, v); 191 Type type = asmType(required.getDefaultType()); 192 v.checkcast(type); 193 return StackValue.onStack(type); 194 } 195 196 return inner; 197 } 198 199 public BindingContext getBindingContext() { 200 return bindingContext; 201 } 202 203 @Nullable 204 @Override 205 public MemberCodegen<?> getParentCodegen() { 206 return parentCodegen; 207 } 208 209 public StackValue genQualified(StackValue receiver, JetElement selector) { 210 return genQualified(receiver, selector, this); 211 } 212 213 private StackValue genQualified(StackValue receiver, JetElement selector, JetVisitor<StackValue, StackValue> visitor) { 214 if (tempVariables.containsKey(selector)) { 215 throw new IllegalStateException("Inconsistent state: expression saved to a temporary variable is a selector"); 216 } 217 if (!(selector instanceof JetBlockExpression)) { 218 markLineNumber(selector); 219 } 220 try { 221 if (selector instanceof JetExpression) { 222 JetExpression expression = (JetExpression) selector; 223 SamType samType = bindingContext.get(CodegenBinding.SAM_VALUE, expression); 224 if (samType != null) { 225 return genSamInterfaceValue(expression, samType, visitor); 226 } 227 } 228 229 return selector.accept(visitor, receiver); 230 } 231 catch (ProcessCanceledException e) { 232 throw e; 233 } 234 catch (CompilationException e) { 235 throw e; 236 } 237 catch (Throwable error) { 238 String message = error.getMessage(); 239 throw new CompilationException(message != null ? message : "null", error, selector); 240 } 241 } 242 243 public StackValue gen(JetElement expr) { 244 StackValue tempVar = tempVariables.get(expr); 245 return tempVar != null ? tempVar : genQualified(StackValue.none(), expr); 246 } 247 248 public void gen(JetElement expr, Type type) { 249 StackValue value = gen(expr); 250 value.put(type, v); 251 } 252 253 public void genToJVMStack(JetExpression expr) { 254 gen(expr, expressionType(expr)); 255 } 256 257 private StackValue genStatement(JetElement statement) { 258 return genQualified(StackValue.none(), statement, statementVisitor); 259 } 260 261 @Override 262 public StackValue visitClass(@NotNull JetClass klass, StackValue data) { 263 return visitClassOrObject(klass); 264 } 265 266 private StackValue visitClassOrObject(JetClassOrObject declaration) { 267 ClassDescriptor descriptor = bindingContext.get(CLASS, declaration); 268 assert descriptor != null; 269 270 Type asmType = asmTypeForAnonymousClass(bindingContext, declaration); 271 ClassBuilder classBuilder = state.getFactory().newVisitor(asmType, declaration.getContainingFile()); 272 273 ClassContext objectContext = context.intoAnonymousClass(descriptor, this); 274 new ImplementationBodyCodegen(declaration, objectContext, classBuilder, state, getParentCodegen()).generate(); 275 276 return StackValue.none(); 277 } 278 279 @Override 280 public StackValue visitObjectDeclaration(@NotNull JetObjectDeclaration declaration, StackValue data) { 281 return visitClassOrObject(declaration); 282 } 283 284 @Override 285 public StackValue visitExpression(@NotNull JetExpression expression, StackValue receiver) { 286 throw new UnsupportedOperationException("Codegen for " + expression + " is not yet implemented"); 287 } 288 289 @Override 290 public StackValue visitSuperExpression(@NotNull JetSuperExpression expression, StackValue data) { 291 return StackValue.thisOrOuter(this, getSuperCallLabelTarget(expression), true, true); 292 } 293 294 @NotNull 295 private ClassDescriptor getSuperCallLabelTarget(JetSuperExpression expression) { 296 PsiElement labelPsi = bindingContext.get(LABEL_TARGET, expression.getTargetLabel()); 297 ClassDescriptor labelTarget = (ClassDescriptor) bindingContext.get(DECLARATION_TO_DESCRIPTOR, labelPsi); 298 DeclarationDescriptor descriptor = bindingContext.get(REFERENCE_TARGET, expression.getInstanceReference()); 299 // "super<descriptor>@labelTarget" 300 if (labelTarget != null) { 301 return labelTarget; 302 } 303 assert descriptor instanceof ClassDescriptor : "Don't know how to generate super-call to not a class"; 304 return getParentContextSubclassOf((ClassDescriptor) descriptor, context).getThisDescriptor(); 305 } 306 307 @NotNull 308 private Type asmType(@NotNull JetType type) { 309 return typeMapper.mapType(type); 310 } 311 312 @NotNull 313 public Type expressionType(JetExpression expression) { 314 JetType type = bindingContext.get(EXPRESSION_TYPE, expression); 315 return type == null ? Type.VOID_TYPE : asmType(type); 316 } 317 318 @NotNull 319 public ResolvedCall<?> resolvedCall(JetExpression expression) { 320 ResolvedCall<?> resolvedCall = bindingContext.get(RESOLVED_CALL, expression); 321 assert resolvedCall != null : "Unresolved call: " + expression.getText(); 322 return resolvedCall; 323 } 324 325 @Override 326 public StackValue visitParenthesizedExpression(@NotNull JetParenthesizedExpression expression, StackValue receiver) { 327 return genQualified(receiver, expression.getExpression()); 328 } 329 330 @Override 331 public StackValue visitAnnotatedExpression(@NotNull JetAnnotatedExpression expression, StackValue receiver) { 332 return genQualified(receiver, expression.getBaseExpression()); 333 } 334 335 private static boolean isEmptyExpression(@Nullable JetElement expr) { 336 if (expr == null) { 337 return true; 338 } 339 if (expr instanceof JetBlockExpression) { 340 JetBlockExpression blockExpression = (JetBlockExpression) expr; 341 List<JetElement> statements = blockExpression.getStatements(); 342 if (statements.size() == 0 || statements.size() == 1 && isEmptyExpression(statements.get(0))) { 343 return true; 344 } 345 } 346 return false; 347 } 348 349 @Override 350 public StackValue visitIfExpression(@NotNull JetIfExpression expression, StackValue receiver) { 351 return generateIfExpression(expression, false); 352 } 353 354 /* package */ StackValue generateIfExpression(JetIfExpression expression, boolean isStatement) { 355 Type asmType = isStatement ? Type.VOID_TYPE : expressionType(expression); 356 StackValue condition = gen(expression.getCondition()); 357 358 JetExpression thenExpression = expression.getThen(); 359 JetExpression elseExpression = expression.getElse(); 360 361 if (isEmptyExpression(thenExpression)) { 362 if (isEmptyExpression(elseExpression)) { 363 condition.put(asmType, v); 364 return StackValue.onStack(asmType); 365 } 366 return generateSingleBranchIf(condition, expression, elseExpression, false, isStatement); 367 } 368 else { 369 if (isEmptyExpression(elseExpression)) { 370 return generateSingleBranchIf(condition, expression, thenExpression, true, isStatement); 371 } 372 } 373 374 Label elseLabel = new Label(); 375 condition.condJump(elseLabel, true, v); // == 0, i.e. false 376 377 Label end = new Label(); 378 379 gen(thenExpression, asmType); 380 381 v.goTo(end); 382 v.mark(elseLabel); 383 384 gen(elseExpression, asmType); 385 386 markLineNumber(expression); 387 v.mark(end); 388 389 return StackValue.onStack(asmType); 390 } 391 392 @Override 393 public StackValue visitWhileExpression(@NotNull JetWhileExpression expression, StackValue receiver) { 394 Label condition = new Label(); 395 v.mark(condition); 396 397 Label end = new Label(); 398 blockStackElements.push(new LoopBlockStackElement(end, condition, targetLabel(expression))); 399 400 StackValue conditionValue = gen(expression.getCondition()); 401 conditionValue.condJump(end, true, v); 402 403 JetExpression body = expression.getBody(); 404 if (body != null) { 405 gen(body, Type.VOID_TYPE); 406 } 407 408 v.goTo(condition); 409 410 v.mark(end); 411 412 blockStackElements.pop(); 413 414 return StackValue.onStack(Type.VOID_TYPE); 415 } 416 417 418 @Override 419 public StackValue visitDoWhileExpression(@NotNull JetDoWhileExpression expression, StackValue receiver) { 420 Label continueLabel = new Label(); 421 v.mark(continueLabel); 422 423 Label breakLabel = new Label(); 424 425 blockStackElements.push(new LoopBlockStackElement(breakLabel, continueLabel, targetLabel(expression))); 426 427 JetExpression body = expression.getBody(); 428 JetExpression condition = expression.getCondition(); 429 StackValue conditionValue; 430 431 if (body instanceof JetBlockExpression) { 432 // If body's a block, it can contain variable declarations which may be used in the condition of a do-while loop. 433 // We handle this case separately because otherwise such variable will be out of the frame map after the block ends 434 List<JetElement> doWhileStatements = ((JetBlockExpression) body).getStatements(); 435 436 List<JetElement> statements = new ArrayList<JetElement>(doWhileStatements.size() + 1); 437 statements.addAll(doWhileStatements); 438 statements.add(condition); 439 440 conditionValue = generateBlock(statements, true); 441 } 442 else { 443 if (body != null) { 444 gen(body, Type.VOID_TYPE); 445 } 446 447 conditionValue = gen(condition); 448 } 449 450 conditionValue.condJump(continueLabel, false, v); 451 v.mark(breakLabel); 452 453 blockStackElements.pop(); 454 return StackValue.none(); 455 } 456 457 @Override 458 public StackValue visitForExpression(@NotNull JetForExpression forExpression, StackValue receiver) { 459 // Is it a "1..2" or so 460 RangeCodegenUtil.BinaryCall binaryCall = RangeCodegenUtil.getRangeAsBinaryCall(forExpression); 461 if (binaryCall != null) { 462 ResolvedCall<?> resolvedCall = bindingContext.get(RESOLVED_CALL, binaryCall.op); 463 if (resolvedCall != null) { 464 if (RangeCodegenUtil.isOptimizableRangeTo(resolvedCall.getResultingDescriptor())) { 465 generateForLoop(new ForInRangeLiteralLoopGenerator(forExpression, binaryCall)); 466 return StackValue.none(); 467 } 468 } 469 } 470 471 JetExpression loopRange = forExpression.getLoopRange(); 472 JetType loopRangeType = bindingContext.get(EXPRESSION_TYPE, loopRange); 473 assert loopRangeType != null; 474 Type asmLoopRangeType = asmType(loopRangeType); 475 if (asmLoopRangeType.getSort() == Type.ARRAY) { 476 generateForLoop(new ForInArrayLoopGenerator(forExpression)); 477 return StackValue.none(); 478 } 479 480 if (RangeCodegenUtil.isRange(loopRangeType)) { 481 generateForLoop(new ForInRangeInstanceLoopGenerator(forExpression)); 482 return StackValue.none(); 483 } 484 485 if (RangeCodegenUtil.isProgression(loopRangeType)) { 486 generateForLoop(new ForInProgressionExpressionLoopGenerator(forExpression)); 487 return StackValue.none(); 488 } 489 490 generateForLoop(new IteratorForLoopGenerator(forExpression)); 491 return StackValue.none(); 492 } 493 494 private OwnerKind contextKind() { 495 return context.getContextKind(); 496 } 497 498 private void generateForLoop(AbstractForLoopGenerator generator) { 499 Label loopExit = new Label(); 500 Label loopEntry = new Label(); 501 Label continueLabel = new Label(); 502 503 generator.beforeLoop(); 504 generator.checkEmptyLoop(loopExit); 505 506 v.mark(loopEntry); 507 generator.checkPreCondition(loopExit); 508 509 generator.beforeBody(); 510 blockStackElements.push(new LoopBlockStackElement(loopExit, continueLabel, targetLabel(generator.forExpression))); 511 generator.body(); 512 blockStackElements.pop(); 513 v.mark(continueLabel); 514 generator.afterBody(loopExit); 515 516 v.goTo(loopEntry); 517 518 v.mark(loopExit); 519 generator.afterLoop(); 520 } 521 522 private abstract class AbstractForLoopGenerator { 523 524 // for (e : E in c) {...} 525 protected final JetForExpression forExpression; 526 private final Label bodyStart = new Label(); 527 private final Label bodyEnd = new Label(); 528 private final List<Runnable> leaveVariableTasks = Lists.newArrayList(); 529 530 protected final JetType elementType; 531 protected final Type asmElementType; 532 533 protected int loopParameterVar; 534 535 private AbstractForLoopGenerator(@NotNull JetForExpression forExpression) { 536 this.forExpression = forExpression; 537 this.elementType = getElementType(forExpression); 538 this.asmElementType = asmType(elementType); 539 } 540 541 @NotNull 542 private JetType getElementType(JetForExpression forExpression) { 543 JetExpression loopRange = forExpression.getLoopRange(); 544 assert loopRange != null; 545 ResolvedCall<FunctionDescriptor> nextCall = getNotNull(bindingContext, 546 LOOP_RANGE_NEXT_RESOLVED_CALL, loopRange, 547 "No next() function " + DiagnosticUtils.atLocation(loopRange)); 548 //noinspection ConstantConditions 549 return nextCall.getResultingDescriptor().getReturnType(); 550 } 551 552 public void beforeLoop() { 553 JetParameter loopParameter = forExpression.getLoopParameter(); 554 if (loopParameter != null) { 555 // E e = tmp<iterator>.next() 556 final VariableDescriptor parameterDescriptor = bindingContext.get(VALUE_PARAMETER, loopParameter); 557 @SuppressWarnings("ConstantConditions") final Type asmTypeForParameter = asmType(parameterDescriptor.getType()); 558 loopParameterVar = myFrameMap.enter(parameterDescriptor, asmTypeForParameter); 559 scheduleLeaveVariable(new Runnable() { 560 @Override 561 public void run() { 562 myFrameMap.leave(parameterDescriptor); 563 v.visitLocalVariable(parameterDescriptor.getName().asString(), 564 asmTypeForParameter.getDescriptor(), null, 565 bodyStart, bodyEnd, 566 loopParameterVar); 567 } 568 }); 569 } 570 else { 571 JetMultiDeclaration multiParameter = forExpression.getMultiParameter(); 572 assert multiParameter != null; 573 574 // E tmp<e> = tmp<iterator>.next() 575 loopParameterVar = createLoopTempVariable(asmElementType); 576 } 577 } 578 579 public abstract void checkEmptyLoop(@NotNull Label loopExit); 580 581 public abstract void checkPreCondition(@NotNull Label loopExit); 582 583 public void beforeBody() { 584 v.mark(bodyStart); 585 586 assignToLoopParameter(); 587 588 if (forExpression.getLoopParameter() == null) { 589 JetMultiDeclaration multiParameter = forExpression.getMultiParameter(); 590 assert multiParameter != null; 591 592 generateMultiVariables(multiParameter.getEntries()); 593 } 594 } 595 596 private void generateMultiVariables(List<JetMultiDeclarationEntry> entries) { 597 for (JetMultiDeclarationEntry variableDeclaration : entries) { 598 final VariableDescriptor componentDescriptor = bindingContext.get(VARIABLE, variableDeclaration); 599 600 @SuppressWarnings("ConstantConditions") final Type componentAsmType = asmType(componentDescriptor.getReturnType()); 601 final int componentVarIndex = myFrameMap.enter(componentDescriptor, componentAsmType); 602 scheduleLeaveVariable(new Runnable() { 603 @Override 604 public void run() { 605 myFrameMap.leave(componentDescriptor); 606 v.visitLocalVariable(componentDescriptor.getName().asString(), 607 componentAsmType.getDescriptor(), null, 608 bodyStart, bodyEnd, 609 componentVarIndex); 610 } 611 }); 612 613 ResolvedCall<FunctionDescriptor> resolvedCall = bindingContext.get(COMPONENT_RESOLVED_CALL, variableDeclaration); 614 assert resolvedCall != null : "Resolved call is null for " + variableDeclaration.getText(); 615 Call call = makeFakeCall(new TransientReceiver(elementType)); 616 invokeFunction(call, StackValue.local(loopParameterVar, asmElementType), resolvedCall); 617 618 v.store(componentVarIndex, componentAsmType); 619 } 620 } 621 622 protected abstract void assignToLoopParameter(); 623 624 protected abstract void increment(@NotNull Label loopExit); 625 626 public void body() { 627 JetExpression body = forExpression.getBody(); 628 if (body != null) { 629 gen(body, Type.VOID_TYPE); 630 } 631 } 632 633 private void scheduleLeaveVariable(Runnable runnable) { 634 leaveVariableTasks.add(runnable); 635 } 636 637 protected int createLoopTempVariable(final Type type) { 638 int varIndex = myFrameMap.enterTemp(type); 639 scheduleLeaveVariable(new Runnable() { 640 @Override 641 public void run() { 642 myFrameMap.leaveTemp(type); 643 } 644 }); 645 return varIndex; 646 } 647 648 public void afterBody(@NotNull Label loopExit) { 649 increment(loopExit); 650 651 v.mark(bodyEnd); 652 } 653 654 public void afterLoop() { 655 for (Runnable task : Lists.reverse(leaveVariableTasks)) { 656 task.run(); 657 } 658 } 659 660 // This method consumes range/progression from stack 661 // The result is stored to local variable 662 protected void generateRangeOrProgressionProperty(Type loopRangeType, String getterName, Type elementType, int varToStore) { 663 Type boxedType = boxType(elementType); 664 v.invokevirtual(loopRangeType.getInternalName(), getterName, "()" + boxedType.getDescriptor()); 665 StackValue.coerce(boxedType, elementType, v); 666 v.store(varToStore, elementType); 667 } 668 } 669 670 private class IteratorForLoopGenerator extends AbstractForLoopGenerator { 671 672 private int iteratorVarIndex; 673 private final ResolvedCall<FunctionDescriptor> iteratorCall; 674 private final ResolvedCall<FunctionDescriptor> nextCall; 675 private final Type asmTypeForIterator; 676 677 private IteratorForLoopGenerator(@NotNull JetForExpression forExpression) { 678 super(forExpression); 679 680 JetExpression loopRange = forExpression.getLoopRange(); 681 assert loopRange != null; 682 this.iteratorCall = getNotNull(bindingContext, 683 LOOP_RANGE_ITERATOR_RESOLVED_CALL, loopRange, 684 "No .iterator() function " + DiagnosticUtils.atLocation(loopRange)); 685 686 JetType iteratorType = iteratorCall.getResultingDescriptor().getReturnType(); 687 assert iteratorType != null; 688 this.asmTypeForIterator = asmType(iteratorType); 689 690 this.nextCall = getNotNull(bindingContext, 691 LOOP_RANGE_NEXT_RESOLVED_CALL, loopRange, 692 "No next() function " + DiagnosticUtils.atLocation(loopRange)); 693 } 694 695 @Override 696 public void beforeLoop() { 697 super.beforeLoop(); 698 699 // Iterator<E> tmp<iterator> = c.iterator() 700 701 iteratorVarIndex = createLoopTempVariable(asmTypeForIterator); 702 703 Call call = bindingContext.get(LOOP_RANGE_ITERATOR_CALL, forExpression.getLoopRange()); 704 invokeFunction(call, StackValue.none(), iteratorCall); 705 v.store(iteratorVarIndex, asmTypeForIterator); 706 } 707 708 @Override 709 public void checkEmptyLoop(@NotNull Label loopExit) { 710 } 711 712 @Override 713 public void checkPreCondition(@NotNull Label loopExit) { 714 // tmp<iterator>.hasNext() 715 716 JetExpression loopRange = forExpression.getLoopRange(); 717 @SuppressWarnings("ConstantConditions") ResolvedCall<FunctionDescriptor> hasNextCall = getNotNull(bindingContext, 718 LOOP_RANGE_HAS_NEXT_RESOLVED_CALL, loopRange, 719 "No hasNext() function " + DiagnosticUtils.atLocation(loopRange)); 720 @SuppressWarnings("ConstantConditions") Call fakeCall = makeFakeCall(new TransientReceiver(iteratorCall.getResultingDescriptor().getReturnType())); 721 invokeFunction(fakeCall, StackValue.local(iteratorVarIndex, asmTypeForIterator), hasNextCall); 722 723 JetType type = hasNextCall.getResultingDescriptor().getReturnType(); 724 assert type != null && JetTypeChecker.INSTANCE.isSubtypeOf(type, KotlinBuiltIns.getInstance().getBooleanType()); 725 726 Type asmType = asmType(type); 727 StackValue.coerce(asmType, Type.BOOLEAN_TYPE, v); 728 v.ifeq(loopExit); 729 } 730 731 @Override 732 protected void assignToLoopParameter() { 733 @SuppressWarnings("ConstantConditions") Call fakeCall = 734 makeFakeCall(new TransientReceiver(iteratorCall.getResultingDescriptor().getReturnType())); 735 invokeFunction(fakeCall, StackValue.local(iteratorVarIndex, asmTypeForIterator), nextCall); 736 //noinspection ConstantConditions 737 v.store(loopParameterVar, asmType(nextCall.getResultingDescriptor().getReturnType())); 738 } 739 740 @Override 741 protected void increment(@NotNull Label loopExit) { 742 } 743 } 744 745 private class ForInArrayLoopGenerator extends AbstractForLoopGenerator { 746 private int indexVar; 747 private int arrayVar; 748 private final JetType loopRangeType; 749 750 private ForInArrayLoopGenerator(@NotNull JetForExpression forExpression) { 751 super(forExpression); 752 loopRangeType = bindingContext.get(EXPRESSION_TYPE, forExpression.getLoopRange()); 753 } 754 755 @Override 756 public void beforeLoop() { 757 super.beforeLoop(); 758 759 indexVar = createLoopTempVariable(Type.INT_TYPE); 760 761 JetExpression loopRange = forExpression.getLoopRange(); 762 StackValue value = gen(loopRange); 763 Type asmLoopRangeType = asmType(loopRangeType); 764 if (value instanceof StackValue.Local && value.type.equals(asmLoopRangeType)) { 765 arrayVar = ((StackValue.Local) value).index; // no need to copy local variable into another variable 766 } 767 else { 768 arrayVar = createLoopTempVariable(OBJECT_TYPE); 769 value.put(asmLoopRangeType, v); 770 v.store(arrayVar, OBJECT_TYPE); 771 } 772 773 v.iconst(0); 774 v.store(indexVar, Type.INT_TYPE); 775 } 776 777 @Override 778 public void checkEmptyLoop(@NotNull Label loopExit) { 779 } 780 781 @Override 782 public void checkPreCondition(@NotNull Label loopExit) { 783 v.load(indexVar, Type.INT_TYPE); 784 v.load(arrayVar, OBJECT_TYPE); 785 v.arraylength(); 786 v.ificmpge(loopExit); 787 } 788 789 @Override 790 protected void assignToLoopParameter() { 791 Type arrayElParamType; 792 if (KotlinBuiltIns.getInstance().isArray(loopRangeType)) { 793 arrayElParamType = boxType(asmElementType); 794 } 795 else { 796 arrayElParamType = asmElementType; 797 } 798 799 v.load(arrayVar, OBJECT_TYPE); 800 v.load(indexVar, Type.INT_TYPE); 801 v.aload(arrayElParamType); 802 StackValue.onStack(arrayElParamType).put(asmElementType, v); 803 v.store(loopParameterVar, asmElementType); 804 } 805 806 @Override 807 protected void increment(@NotNull Label loopExit) { 808 v.iinc(indexVar, 1); 809 } 810 } 811 812 private abstract class AbstractForInProgressionOrRangeLoopGenerator extends AbstractForLoopGenerator { 813 protected int endVar; 814 815 // For integer progressions instead of comparing loopParameterVar with endVar at the beginning of an iteration we check whether 816 // loopParameterVar == finalVar at the end of the iteration (and also if there should be any iterations at all, before the loop) 817 protected final boolean isIntegerProgression; 818 819 private AbstractForInProgressionOrRangeLoopGenerator(@NotNull JetForExpression forExpression) { 820 super(forExpression); 821 822 switch (asmElementType.getSort()) { 823 case Type.INT: 824 case Type.BYTE: 825 case Type.SHORT: 826 case Type.CHAR: 827 case Type.LONG: 828 isIntegerProgression = true; 829 break; 830 831 case Type.DOUBLE: 832 case Type.FLOAT: 833 isIntegerProgression = false; 834 break; 835 836 default: 837 throw new IllegalStateException("Unexpected range element type: " + asmElementType); 838 } 839 } 840 841 @Override 842 public void beforeLoop() { 843 super.beforeLoop(); 844 845 endVar = createLoopTempVariable(asmElementType); 846 } 847 848 // Index of the local variable holding the actual last value of the loop parameter. 849 // For ranges it equals end, for progressions it's a function of start, end and increment 850 protected abstract int getFinalVar(); 851 852 protected void checkPostCondition(@NotNull Label loopExit) { 853 int finalVar = getFinalVar(); 854 assert isIntegerProgression && finalVar != -1 : 855 "Post-condition should be checked only in case of integer progressions, finalVar = " + finalVar; 856 857 v.load(loopParameterVar, asmElementType); 858 v.load(finalVar, asmElementType); 859 if (asmElementType.getSort() == Type.LONG) { 860 v.lcmp(); 861 v.ifeq(loopExit); 862 } 863 else { 864 v.ificmpeq(loopExit); 865 } 866 } 867 } 868 869 private abstract class AbstractForInRangeLoopGenerator extends AbstractForInProgressionOrRangeLoopGenerator { 870 private AbstractForInRangeLoopGenerator(@NotNull JetForExpression forExpression) { 871 super(forExpression); 872 } 873 874 @Override 875 public void beforeLoop() { 876 super.beforeLoop(); 877 878 storeRangeStartAndEnd(); 879 } 880 881 protected abstract void storeRangeStartAndEnd(); 882 883 @Override 884 protected int getFinalVar() { 885 return endVar; 886 } 887 888 @Override 889 public void checkPreCondition(@NotNull Label loopExit) { 890 if (isIntegerProgression) return; 891 892 v.load(loopParameterVar, asmElementType); 893 v.load(endVar, asmElementType); 894 895 v.cmpg(asmElementType); 896 v.ifgt(loopExit); 897 } 898 899 @Override 900 public void checkEmptyLoop(@NotNull Label loopExit) { 901 if (!isIntegerProgression) return; 902 903 v.load(loopParameterVar, asmElementType); 904 v.load(endVar, asmElementType); 905 if (asmElementType.getSort() == Type.LONG) { 906 v.lcmp(); 907 v.ifgt(loopExit); 908 } 909 else { 910 v.ificmpgt(loopExit); 911 } 912 } 913 914 @Override 915 protected void assignToLoopParameter() { 916 } 917 918 @Override 919 protected void increment(@NotNull Label loopExit) { 920 if (isIntegerProgression) { 921 checkPostCondition(loopExit); 922 } 923 924 if (asmElementType == Type.INT_TYPE) { 925 v.iinc(loopParameterVar, 1); 926 } 927 else { 928 v.load(loopParameterVar, asmElementType); 929 genIncrement(asmElementType, 1, v); 930 v.store(loopParameterVar, asmElementType); 931 } 932 } 933 } 934 935 private class ForInRangeLiteralLoopGenerator extends AbstractForInRangeLoopGenerator { 936 private final RangeCodegenUtil.BinaryCall rangeCall; 937 938 private ForInRangeLiteralLoopGenerator( 939 @NotNull JetForExpression forExpression, 940 @NotNull RangeCodegenUtil.BinaryCall rangeCall 941 ) { 942 super(forExpression); 943 this.rangeCall = rangeCall; 944 } 945 946 @Override 947 protected void storeRangeStartAndEnd() { 948 gen(rangeCall.left, asmElementType); 949 v.store(loopParameterVar, asmElementType); 950 951 gen(rangeCall.right, asmElementType); 952 v.store(endVar, asmElementType); 953 } 954 } 955 956 private class ForInRangeInstanceLoopGenerator extends AbstractForInRangeLoopGenerator { 957 private ForInRangeInstanceLoopGenerator(@NotNull JetForExpression forExpression) { 958 super(forExpression); 959 } 960 961 @Override 962 protected void storeRangeStartAndEnd() { 963 JetType loopRangeType = bindingContext.get(EXPRESSION_TYPE, forExpression.getLoopRange()); 964 assert loopRangeType != null; 965 Type asmLoopRangeType = asmType(loopRangeType); 966 gen(forExpression.getLoopRange(), asmLoopRangeType); 967 v.dup(); 968 969 generateRangeOrProgressionProperty(asmLoopRangeType, "getStart", asmElementType, loopParameterVar); 970 generateRangeOrProgressionProperty(asmLoopRangeType, "getEnd", asmElementType, endVar); 971 } 972 } 973 974 private class ForInProgressionExpressionLoopGenerator extends AbstractForInProgressionOrRangeLoopGenerator { 975 private int incrementVar; 976 private Type incrementType; 977 978 private int finalVar; 979 980 private ForInProgressionExpressionLoopGenerator(@NotNull JetForExpression forExpression) { 981 super(forExpression); 982 } 983 984 @Override 985 protected int getFinalVar() { 986 return finalVar; 987 } 988 989 @Override 990 public void beforeLoop() { 991 super.beforeLoop(); 992 993 incrementVar = createLoopTempVariable(asmElementType); 994 995 JetType loopRangeType = bindingContext.get(EXPRESSION_TYPE, forExpression.getLoopRange()); 996 assert loopRangeType != null; 997 Type asmLoopRangeType = asmType(loopRangeType); 998 999 Collection<VariableDescriptor> incrementProp = loopRangeType.getMemberScope().getProperties(Name.identifier("increment")); 1000 assert incrementProp.size() == 1 : loopRangeType + " " + incrementProp.size(); 1001 incrementType = asmType(incrementProp.iterator().next().getType()); 1002 1003 gen(forExpression.getLoopRange(), asmLoopRangeType); 1004 v.dup(); 1005 v.dup(); 1006 1007 generateRangeOrProgressionProperty(asmLoopRangeType, "getStart", asmElementType, loopParameterVar); 1008 generateRangeOrProgressionProperty(asmLoopRangeType, "getEnd", asmElementType, endVar); 1009 generateRangeOrProgressionProperty(asmLoopRangeType, "getIncrement", incrementType, incrementVar); 1010 1011 storeFinalVar(); 1012 } 1013 1014 private void storeFinalVar() { 1015 if (!isIntegerProgression) { 1016 finalVar = -1; 1017 return; 1018 } 1019 1020 v.load(loopParameterVar, asmElementType); 1021 v.load(endVar, asmElementType); 1022 v.load(incrementVar, incrementType); 1023 1024 Type methodParamType = asmElementType.getSort() == Type.LONG ? Type.LONG_TYPE : Type.INT_TYPE; 1025 v.invokestatic("kotlin/internal/InternalPackage", "getProgressionFinalElement", 1026 Type.getMethodDescriptor(methodParamType, methodParamType, methodParamType, methodParamType)); 1027 1028 finalVar = createLoopTempVariable(asmElementType); 1029 v.store(finalVar, asmElementType); 1030 } 1031 1032 @Override 1033 public void checkPreCondition(@NotNull Label loopExit) { 1034 if (isIntegerProgression) return; 1035 1036 v.load(loopParameterVar, asmElementType); 1037 v.load(endVar, asmElementType); 1038 v.load(incrementVar, incrementType); 1039 1040 Label negativeIncrement = new Label(); 1041 Label afterIf = new Label(); 1042 1043 if (incrementType.getSort() == Type.DOUBLE) { 1044 v.dconst(0.0); 1045 } 1046 else { 1047 v.fconst(0.0f); 1048 } 1049 v.cmpl(incrementType); 1050 v.ifle(negativeIncrement); // if increment < 0, jump 1051 1052 // increment > 0 1053 v.cmpg(asmElementType); // if loop parameter is NaN, exit from loop, as well 1054 v.ifgt(loopExit); 1055 v.goTo(afterIf); 1056 1057 // increment < 0 1058 v.mark(negativeIncrement); 1059 v.cmpl(asmElementType); // if loop parameter is NaN, exit from loop, as well 1060 v.iflt(loopExit); 1061 v.mark(afterIf); 1062 } 1063 1064 @Override 1065 public void checkEmptyLoop(@NotNull Label loopExit) { 1066 if (!isIntegerProgression) return; 1067 1068 v.load(loopParameterVar, asmElementType); 1069 v.load(endVar, asmElementType); 1070 v.load(incrementVar, incrementType); 1071 1072 Label negativeIncrement = new Label(); 1073 Label afterIf = new Label(); 1074 1075 if (asmElementType.getSort() == Type.LONG) { 1076 v.lconst(0L); 1077 v.lcmp(); 1078 v.ifle(negativeIncrement); // if increment < 0, jump 1079 1080 // increment > 0 1081 v.lcmp(); 1082 v.ifgt(loopExit); 1083 v.goTo(afterIf); 1084 1085 // increment < 0 1086 v.mark(negativeIncrement); 1087 v.lcmp(); 1088 v.iflt(loopExit); 1089 v.mark(afterIf); 1090 } 1091 else { 1092 v.ifle(negativeIncrement); // if increment < 0, jump 1093 1094 // increment > 0 1095 v.ificmpgt(loopExit); 1096 v.goTo(afterIf); 1097 1098 // increment < 0 1099 v.mark(negativeIncrement); 1100 v.ificmplt(loopExit); 1101 v.mark(afterIf); 1102 } 1103 } 1104 1105 @Override 1106 protected void assignToLoopParameter() { 1107 } 1108 1109 @Override 1110 protected void increment(@NotNull Label loopExit) { 1111 if (isIntegerProgression) { 1112 checkPostCondition(loopExit); 1113 } 1114 1115 v.load(loopParameterVar, asmElementType); 1116 v.load(incrementVar, asmElementType); 1117 v.add(asmElementType); 1118 1119 if (asmElementType == Type.BYTE_TYPE || asmElementType == Type.SHORT_TYPE || asmElementType == Type.CHAR_TYPE) { 1120 StackValue.coerce(Type.INT_TYPE, asmElementType, v); 1121 } 1122 1123 v.store(loopParameterVar, asmElementType); 1124 } 1125 } 1126 1127 1128 @Override 1129 public StackValue visitBreakExpression(@NotNull JetBreakExpression expression, StackValue receiver) { 1130 return generateBreakOrContinueExpression(expression, true); 1131 } 1132 1133 @Override 1134 public StackValue visitContinueExpression(@NotNull JetContinueExpression expression, StackValue receiver) { 1135 return generateBreakOrContinueExpression(expression, false); 1136 } 1137 1138 @NotNull 1139 private StackValue generateBreakOrContinueExpression(@NotNull JetExpressionWithLabel expression, boolean isBreak) { 1140 assert expression instanceof JetContinueExpression || expression instanceof JetBreakExpression; 1141 1142 if (!blockStackElements.isEmpty()) { 1143 BlockStackElement stackElement = blockStackElements.peek(); 1144 1145 if (stackElement instanceof FinallyBlockStackElement) { 1146 FinallyBlockStackElement finallyBlockStackElement = (FinallyBlockStackElement) stackElement; 1147 //noinspection ConstantConditions 1148 genFinallyBlockOrGoto(finallyBlockStackElement, null); 1149 } 1150 else if (stackElement instanceof LoopBlockStackElement) { 1151 LoopBlockStackElement loopBlockStackElement = (LoopBlockStackElement) stackElement; 1152 JetSimpleNameExpression labelElement = expression.getTargetLabel(); 1153 //noinspection ConstantConditions 1154 if (labelElement == null || 1155 loopBlockStackElement.targetLabel != null && 1156 labelElement.getReferencedName().equals(loopBlockStackElement.targetLabel.getReferencedName())) { 1157 v.goTo(isBreak ? loopBlockStackElement.breakLabel : loopBlockStackElement.continueLabel); 1158 return StackValue.none(); 1159 } 1160 } 1161 else { 1162 throw new UnsupportedOperationException("Wrong BlockStackElement in processing stack"); 1163 } 1164 1165 blockStackElements.pop(); 1166 StackValue result = generateBreakOrContinueExpression(expression, isBreak); 1167 blockStackElements.push(stackElement); 1168 return result; 1169 } 1170 1171 throw new UnsupportedOperationException("Target label for break/continue not found"); 1172 } 1173 1174 private StackValue generateSingleBranchIf( 1175 StackValue condition, 1176 JetIfExpression ifExpression, 1177 JetExpression expression, 1178 boolean inverse, 1179 boolean isStatement 1180 ) { 1181 Label elseLabel = new Label(); 1182 condition.condJump(elseLabel, inverse, v); 1183 1184 if (isStatement) { 1185 gen(expression, Type.VOID_TYPE); 1186 v.mark(elseLabel); 1187 return StackValue.none(); 1188 } 1189 else { 1190 Type type = expressionType(expression); 1191 Type targetType = type.equals(UNIT_TYPE) ? type : OBJECT_TYPE; 1192 1193 gen(expression, targetType); 1194 1195 Label end = new Label(); 1196 v.goTo(end); 1197 1198 markLineNumber(ifExpression); 1199 v.mark(elseLabel); 1200 StackValue.putUnitInstance(v); 1201 1202 v.mark(end); 1203 return StackValue.onStack(targetType); 1204 } 1205 } 1206 1207 @Override 1208 public StackValue visitConstantExpression(@NotNull JetConstantExpression expression, StackValue receiver) { 1209 CompileTimeConstant<?> compileTimeValue = getCompileTimeConstant(expression, bindingContext); 1210 assert compileTimeValue != null; 1211 return StackValue.constant(compileTimeValue.getValue(), expressionType(expression)); 1212 } 1213 1214 @Nullable 1215 public static CompileTimeConstant getCompileTimeConstant(@NotNull JetExpression expression, @NotNull BindingContext bindingContext) { 1216 CompileTimeConstant<?> compileTimeValue = bindingContext.get(COMPILE_TIME_VALUE, expression); 1217 if (compileTimeValue instanceof IntegerValueTypeConstant) { 1218 JetType expectedType = bindingContext.get(EXPRESSION_TYPE, expression); 1219 return EvaluatePackage.createCompileTimeConstantWithType((IntegerValueTypeConstant) compileTimeValue, expectedType); 1220 } 1221 return compileTimeValue; 1222 } 1223 1224 @Override 1225 public StackValue visitStringTemplateExpression(@NotNull JetStringTemplateExpression expression, StackValue receiver) { 1226 StringBuilder constantValue = new StringBuilder(""); 1227 JetStringTemplateEntry[] entries = expression.getEntries(); 1228 1229 if (entries.length == 1 && entries[0] instanceof JetStringTemplateEntryWithExpression) { 1230 JetExpression expr = entries[0].getExpression(); 1231 return genToString(v, gen(expr), expressionType(expr)); 1232 } 1233 1234 for (JetStringTemplateEntry entry : entries) { 1235 if (entry instanceof JetLiteralStringTemplateEntry) { 1236 constantValue.append(entry.getText()); 1237 } 1238 else if (entry instanceof JetEscapeStringTemplateEntry) { 1239 constantValue.append(((JetEscapeStringTemplateEntry) entry).getUnescapedValue()); 1240 } 1241 else { 1242 constantValue = null; 1243 break; 1244 } 1245 } 1246 if (constantValue != null) { 1247 Type type = expressionType(expression); 1248 return StackValue.constant(constantValue.toString(), type); 1249 } 1250 else { 1251 genStringBuilderConstructor(v); 1252 for (JetStringTemplateEntry entry : entries) { 1253 if (entry instanceof JetStringTemplateEntryWithExpression) { 1254 invokeAppend(entry.getExpression()); 1255 } 1256 else { 1257 String text = entry instanceof JetEscapeStringTemplateEntry 1258 ? ((JetEscapeStringTemplateEntry) entry).getUnescapedValue() 1259 : entry.getText(); 1260 v.aconst(text); 1261 genInvokeAppendMethod(v, JAVA_STRING_TYPE); 1262 } 1263 } 1264 v.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;"); 1265 return StackValue.onStack(AsmTypeConstants.JAVA_STRING_TYPE); 1266 } 1267 } 1268 1269 @Override 1270 public StackValue visitBlockExpression(@NotNull JetBlockExpression expression, StackValue receiver) { 1271 List<JetElement> statements = expression.getStatements(); 1272 JetType unitType = KotlinBuiltIns.getInstance().getUnitType(); 1273 boolean lastStatementIsExpression = !unitType.equals(bindingContext.get(EXPRESSION_TYPE, expression)); 1274 return generateBlock(statements, lastStatementIsExpression); 1275 } 1276 1277 @Override 1278 public StackValue visitNamedFunction(@NotNull JetNamedFunction function, StackValue data) { 1279 assert data == StackValue.none(); 1280 1281 if (JetPsiUtil.isScriptDeclaration(function)) { 1282 return StackValue.none(); 1283 } 1284 1285 StackValue closure = genClosure(function, null, KotlinSyntheticClass.Kind.LOCAL_FUNCTION); 1286 DeclarationDescriptor descriptor = bindingContext.get(DECLARATION_TO_DESCRIPTOR, function); 1287 int index = lookupLocalIndex(descriptor); 1288 closure.put(OBJECT_TYPE, v); 1289 v.store(index, OBJECT_TYPE); 1290 return StackValue.none(); 1291 } 1292 1293 @Override 1294 public StackValue visitFunctionLiteralExpression(@NotNull JetFunctionLiteralExpression expression, StackValue receiver) { 1295 if (Boolean.TRUE.equals(bindingContext.get(BLOCK, expression))) { 1296 return gen(expression.getFunctionLiteral().getBodyExpression()); 1297 } 1298 else { 1299 return genClosure(expression.getFunctionLiteral(), null, KotlinSyntheticClass.Kind.ANONYMOUS_FUNCTION); 1300 } 1301 } 1302 1303 @NotNull 1304 private StackValue genClosure( 1305 JetDeclarationWithBody declaration, 1306 @Nullable SamType samType, 1307 @NotNull KotlinSyntheticClass.Kind kind 1308 ) { 1309 FunctionDescriptor descriptor = bindingContext.get(FUNCTION, declaration); 1310 assert descriptor != null : "Function is not resolved to descriptor: " + declaration.getText(); 1311 1312 ClosureCodegen closureCodegen = new ClosureCodegen( 1313 state, declaration, descriptor, samType, context, kind, this, 1314 new FunctionGenerationStrategy.FunctionDefault(state, descriptor, declaration), parentCodegen 1315 ); 1316 closureCodegen.gen(); 1317 1318 return closureCodegen.putInstanceOnStack(v, this); 1319 } 1320 1321 @Override 1322 public StackValue visitObjectLiteralExpression(@NotNull JetObjectLiteralExpression expression, StackValue receiver) { 1323 CalculatedClosure closure = this.generateObjectLiteral(state, expression); 1324 1325 ConstructorDescriptor constructorDescriptor = bindingContext.get(CONSTRUCTOR, expression.getObjectDeclaration()); 1326 assert constructorDescriptor != null; 1327 CallableMethod constructor = typeMapper.mapToCallableMethod(constructorDescriptor); 1328 1329 Type type = bindingContext.get(ASM_TYPE, constructorDescriptor.getContainingDeclaration()); 1330 assert type != null; 1331 1332 v.anew(type); 1333 v.dup(); 1334 1335 pushClosureOnStack(closure, false, defaultCallGenerator); 1336 1337 JetDelegatorToSuperCall superCall = closure.getSuperCall(); 1338 if (superCall != null) { 1339 ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext 1340 .get(REFERENCE_TARGET, superCall.getCalleeExpression().getConstructorReferenceExpression()); 1341 assert superConstructor != null; 1342 CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor); 1343 Type[] argumentTypes = superCallable.getAsmMethod().getArgumentTypes(); 1344 ResolvedCall<?> resolvedCall = resolvedCall(superCall.getCalleeExpression()); 1345 pushMethodArgumentsWithoutCallReceiver(resolvedCall, Arrays.asList(argumentTypes), false, defaultCallGenerator); 1346 } 1347 1348 v.invokespecial(type.getInternalName(), "<init>", constructor.getAsmMethod().getDescriptor()); 1349 return StackValue.onStack(type); 1350 } 1351 1352 public void pushClosureOnStack(@Nullable CalculatedClosure closure, boolean ignoreThisAndReceiver, @NotNull CallGenerator callGenerator) { 1353 if (closure != null) { 1354 int paramIndex = 0; 1355 if (!ignoreThisAndReceiver) { 1356 ClassDescriptor captureThis = closure.getCaptureThis(); 1357 if (captureThis != null) { 1358 StackValue thisOrOuter = generateThisOrOuter(captureThis, false); 1359 1360 assert !isPrimitive(thisOrOuter.type) : "This or outer should be non primitive: " + thisOrOuter.type; 1361 callGenerator.putCapturedValueOnStack(thisOrOuter, thisOrOuter.type, paramIndex++); 1362 } 1363 1364 JetType captureReceiver = closure.getCaptureReceiverType(); 1365 if (captureReceiver != null) { 1366 Type asmType = typeMapper.mapType(captureReceiver); 1367 StackValue.Local capturedReceiver = StackValue.local(context.isStatic() ? 0 : 1, asmType); 1368 callGenerator.putCapturedValueOnStack(capturedReceiver, capturedReceiver.type, paramIndex++); 1369 } 1370 } 1371 1372 for (Map.Entry<DeclarationDescriptor, EnclosedValueDescriptor> entry : closure.getCaptureVariables().entrySet()) { 1373 Type sharedVarType = typeMapper.getSharedVarType(entry.getKey()); 1374 if (sharedVarType == null) { 1375 sharedVarType = typeMapper.mapType((VariableDescriptor) entry.getKey()); 1376 } 1377 StackValue capturedVar = entry.getValue().getOuterValue(this); 1378 callGenerator.putCapturedValueOnStack(capturedVar, sharedVarType, paramIndex++); 1379 } 1380 } 1381 } 1382 1383 private StackValue generateBlock(List<JetElement> statements, boolean lastStatementIsExpression) { 1384 Label blockEnd = new Label(); 1385 1386 List<Function<StackValue, Void>> leaveTasks = Lists.newArrayList(); 1387 1388 StackValue answer = StackValue.none(); 1389 1390 for (Iterator<JetElement> iterator = statements.iterator(); iterator.hasNext(); ) { 1391 JetElement statement = iterator.next(); 1392 1393 if (statement instanceof JetNamedDeclaration) { 1394 JetNamedDeclaration declaration = (JetNamedDeclaration) statement; 1395 if (JetPsiUtil.isScriptDeclaration(declaration)) { 1396 continue; 1397 } 1398 } 1399 1400 if (statement instanceof JetMultiDeclaration) { 1401 JetMultiDeclaration multiDeclaration = (JetMultiDeclaration) statement; 1402 for (JetMultiDeclarationEntry entry : multiDeclaration.getEntries()) { 1403 generateLocalVariableDeclaration(entry, blockEnd, leaveTasks); 1404 } 1405 } 1406 1407 if (statement instanceof JetVariableDeclaration) { 1408 generateLocalVariableDeclaration((JetVariableDeclaration) statement, blockEnd, leaveTasks); 1409 } 1410 1411 if (statement instanceof JetNamedFunction) { 1412 generateLocalFunctionDeclaration((JetNamedFunction) statement, leaveTasks); 1413 } 1414 1415 boolean isExpression = !iterator.hasNext() && lastStatementIsExpression; 1416 1417 StackValue result = isExpression ? gen(statement) : genStatement(statement); 1418 1419 if (!iterator.hasNext()) { 1420 answer = result; 1421 } 1422 else { 1423 result.put(Type.VOID_TYPE, v); 1424 } 1425 } 1426 1427 v.mark(blockEnd); 1428 1429 for (Function<StackValue, Void> task : Lists.reverse(leaveTasks)) { 1430 task.fun(answer); 1431 } 1432 1433 return answer; 1434 } 1435 1436 private void generateLocalVariableDeclaration( 1437 @NotNull JetVariableDeclaration variableDeclaration, 1438 final @NotNull Label blockEnd, 1439 @NotNull List<Function<StackValue, Void>> leaveTasks 1440 ) { 1441 final VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, variableDeclaration); 1442 assert variableDescriptor != null; 1443 1444 final Label scopeStart = new Label(); 1445 v.mark(scopeStart); 1446 1447 final Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor); 1448 final Type type = sharedVarType != null ? sharedVarType : asmType(variableDescriptor.getType()); 1449 int index = myFrameMap.enter(variableDescriptor, type); 1450 1451 if (sharedVarType != null) { 1452 v.anew(sharedVarType); 1453 v.dup(); 1454 v.invokespecial(sharedVarType.getInternalName(), "<init>", "()V"); 1455 v.store(index, OBJECT_TYPE); 1456 } 1457 1458 leaveTasks.add(new Function<StackValue, Void>() { 1459 @Override 1460 public Void fun(StackValue answer) { 1461 int index = myFrameMap.leave(variableDescriptor); 1462 1463 if (sharedVarType != null) { 1464 if (answer instanceof StackValue.Shared && index == ((StackValue.Shared) answer).getIndex()) { 1465 ((StackValue.Shared) answer).releaseOnPut(); 1466 } 1467 else { 1468 v.aconst(null); 1469 v.store(index, OBJECT_TYPE); 1470 } 1471 } 1472 v.visitLocalVariable(variableDescriptor.getName().asString(), type.getDescriptor(), null, scopeStart, blockEnd, 1473 index); 1474 return null; 1475 } 1476 }); 1477 } 1478 1479 private void generateLocalFunctionDeclaration( 1480 @NotNull JetNamedFunction namedFunction, 1481 @NotNull List<Function<StackValue, Void>> leaveTasks 1482 ) { 1483 final DeclarationDescriptor descriptor = bindingContext.get(DECLARATION_TO_DESCRIPTOR, namedFunction); 1484 myFrameMap.enter(descriptor, OBJECT_TYPE); 1485 1486 leaveTasks.add(new Function<StackValue, Void>() { 1487 @Override 1488 public Void fun(StackValue value) { 1489 myFrameMap.leave(descriptor); 1490 return null; 1491 } 1492 }); 1493 } 1494 1495 private void markLineNumber(@NotNull JetElement statement) { 1496 Document document = statement.getContainingFile().getViewProvider().getDocument(); 1497 if (document != null) { 1498 int lineNumber = document.getLineNumber(statement.getTextRange().getStartOffset()); // 0-based 1499 if (lineNumber == myLastLineNumber) { 1500 return; 1501 } 1502 myLastLineNumber = lineNumber; 1503 1504 Label label = new Label(); 1505 v.visitLabel(label); 1506 v.visitLineNumber(lineNumber + 1, label); // 1-based 1507 } 1508 } 1509 1510 private void doFinallyOnReturn() { 1511 if(!blockStackElements.isEmpty()) { 1512 BlockStackElement stackElement = blockStackElements.peek(); 1513 if (stackElement instanceof FinallyBlockStackElement) { 1514 FinallyBlockStackElement finallyBlockStackElement = (FinallyBlockStackElement) stackElement; 1515 genFinallyBlockOrGoto(finallyBlockStackElement, null); 1516 } 1517 else if (stackElement instanceof LoopBlockStackElement) { 1518 1519 } else { 1520 throw new UnsupportedOperationException("Wrong BlockStackElement in processing stack"); 1521 } 1522 1523 blockStackElements.pop(); 1524 doFinallyOnReturn(); 1525 blockStackElements.push(stackElement); 1526 } 1527 } 1528 1529 private boolean hasFinallyBLocks() { 1530 for (BlockStackElement element : blockStackElements) { 1531 if (element instanceof FinallyBlockStackElement) { 1532 return true; 1533 } 1534 } 1535 return false; 1536 } 1537 1538 private void genFinallyBlockOrGoto( 1539 @Nullable FinallyBlockStackElement finallyBlockStackElement, 1540 @Nullable Label tryCatchBlockEnd 1541 ) { 1542 1543 if (finallyBlockStackElement != null) { 1544 assert finallyBlockStackElement.gaps.size() % 2 == 0 : "Finally block gaps are inconsistent"; 1545 1546 BlockStackElement topOfStack = blockStackElements.pop(); 1547 assert topOfStack == finallyBlockStackElement : "Top element of stack doesn't equals processing finally block"; 1548 1549 JetTryExpression jetTryExpression = finallyBlockStackElement.expression; 1550 Label finallyStart = new Label(); 1551 v.mark(finallyStart); 1552 finallyBlockStackElement.addGapLabel(finallyStart); 1553 1554 //noinspection ConstantConditions 1555 gen(jetTryExpression.getFinallyBlock().getFinalExpression(), Type.VOID_TYPE); 1556 } 1557 1558 if (tryCatchBlockEnd != null) { 1559 v.goTo(tryCatchBlockEnd); 1560 } 1561 1562 if (finallyBlockStackElement != null) { 1563 Label finallyEnd = new Label(); 1564 v.mark(finallyEnd); 1565 finallyBlockStackElement.addGapLabel(finallyEnd); 1566 1567 blockStackElements.push(finallyBlockStackElement); 1568 } 1569 } 1570 1571 @Override 1572 public StackValue visitReturnExpression(@NotNull JetReturnExpression expression, StackValue receiver) { 1573 JetExpression returnedExpression = expression.getReturnedExpression(); 1574 if (returnedExpression != null) { 1575 gen(returnedExpression, returnType); 1576 boolean hasFinallyBLocks = hasFinallyBLocks(); 1577 if (hasFinallyBLocks) { 1578 int returnValIndex = myFrameMap.enterTemp(returnType); 1579 StackValue.local(returnValIndex, returnType).store(returnType, v); 1580 doFinallyOnReturn(); 1581 StackValue.local(returnValIndex, returnType).put(returnType, v); 1582 myFrameMap.leaveTemp(returnType); 1583 } 1584 v.areturn(returnType); 1585 } 1586 else { 1587 doFinallyOnReturn(); 1588 v.visitInsn(RETURN); 1589 } 1590 return StackValue.none(); 1591 } 1592 1593 public void returnExpression(JetExpression expr) { 1594 StackValue lastValue = gen(expr); 1595 1596 if (!endsWithReturn(expr)) { 1597 lastValue.put(returnType, v); 1598 v.areturn(returnType); 1599 } 1600 } 1601 1602 private static boolean endsWithReturn(JetElement bodyExpression) { 1603 if (bodyExpression instanceof JetBlockExpression) { 1604 List<JetElement> statements = ((JetBlockExpression) bodyExpression).getStatements(); 1605 return statements.size() > 0 && statements.get(statements.size() - 1) instanceof JetReturnExpression; 1606 } 1607 1608 return bodyExpression instanceof JetReturnExpression; 1609 } 1610 1611 @Override 1612 public StackValue visitSimpleNameExpression(@NotNull JetSimpleNameExpression expression, StackValue receiver) { 1613 ResolvedCall<?> resolvedCall = bindingContext.get(RESOLVED_CALL, expression); 1614 1615 DeclarationDescriptor descriptor; 1616 if (resolvedCall == null) { 1617 descriptor = bindingContext.get(REFERENCE_TARGET, expression); 1618 } 1619 else { 1620 if (resolvedCall instanceof VariableAsFunctionResolvedCall) { 1621 VariableAsFunctionResolvedCall call = (VariableAsFunctionResolvedCall) resolvedCall; 1622 resolvedCall = call.getVariableCall(); 1623 } 1624 receiver = StackValue.receiver(resolvedCall, receiver, this, null); 1625 descriptor = resolvedCall.getResultingDescriptor(); 1626 } 1627 1628 //if (descriptor instanceof VariableAsFunctionDescriptor) { 1629 // descriptor = ((VariableAsFunctionDescriptor) descriptor).getVariableDescriptor(); 1630 //} 1631 1632 assert descriptor != null : "Couldn't find descriptor for '" + expression.getText() + "'"; 1633 descriptor = descriptor.getOriginal(); 1634 1635 if (descriptor instanceof CallableMemberDescriptor) { 1636 CallableMemberDescriptor memberDescriptor = DescriptorUtils.unwrapFakeOverride((CallableMemberDescriptor) descriptor); 1637 1638 IntrinsicMethod intrinsic = state.getIntrinsics().getIntrinsic(memberDescriptor); 1639 if (intrinsic != null) { 1640 Type returnType = typeMapper.mapType(memberDescriptor); 1641 intrinsic.generate(this, v, returnType, expression, Collections.<JetExpression>emptyList(), receiver); 1642 return StackValue.onStack(returnType); 1643 } 1644 } 1645 1646 if (descriptor instanceof PropertyDescriptor) { 1647 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; 1648 1649 boolean directToField = 1650 expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER && contextKind() != OwnerKind.TRAIT_IMPL; 1651 JetExpression r = getReceiverForSelector(expression); 1652 boolean isSuper = r instanceof JetSuperExpression; 1653 propertyDescriptor = accessiblePropertyDescriptor(propertyDescriptor); 1654 StackValue.Property iValue = 1655 intermediateValueForProperty(propertyDescriptor, directToField, isSuper ? (JetSuperExpression) r : null); 1656 if (directToField) { 1657 receiver = StackValue.receiverWithoutReceiverArgument(receiver); 1658 } 1659 1660 //pop receiver via put(VOID_TYPE) in case of access to backing field that moved to outer class!!! 1661 receiver.put(!iValue.isPropertyWithBackingFieldInOuterClass() ? receiver.type : Type.VOID_TYPE, v); 1662 1663 return iValue; 1664 } 1665 1666 if (descriptor instanceof ClassDescriptor) { 1667 ClassDescriptor classDescriptor = (ClassDescriptor) descriptor; 1668 if (classDescriptor.getKind() == ClassKind.OBJECT) { 1669 return StackValue.singleton(classDescriptor, typeMapper); 1670 } 1671 if (classDescriptor.getKind() == ClassKind.ENUM_ENTRY) { 1672 DeclarationDescriptor enumClass = classDescriptor.getContainingDeclaration(); 1673 assert DescriptorUtils.isEnumClass(enumClass) : "Enum entry should be declared in enum class: " + descriptor; 1674 Type type = typeMapper.mapType((ClassDescriptor) enumClass); 1675 return StackValue.field(type, type, descriptor.getName().asString(), true); 1676 } 1677 ClassDescriptor classObjectDescriptor = classDescriptor.getClassObjectDescriptor(); 1678 assert classObjectDescriptor != null : "Class object is not found for " + descriptor; 1679 return StackValue.singleton(classObjectDescriptor, typeMapper); 1680 } 1681 1682 if (descriptor instanceof TypeParameterDescriptor) { 1683 TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor; 1684 v.invokevirtual("jet/TypeInfo", "getClassObject", "()Ljava/lang/Object;"); 1685 JetType type = typeParameterDescriptor.getClassObjectType(); 1686 assert type != null; 1687 v.checkcast(asmType(type)); 1688 1689 return StackValue.onStack(OBJECT_TYPE); 1690 } 1691 1692 StackValue localOrCaptured = findLocalOrCapturedValue(descriptor); 1693 if (localOrCaptured != null) { 1694 return localOrCaptured; 1695 } 1696 1697 if (descriptor instanceof ValueParameterDescriptor && descriptor.getContainingDeclaration() instanceof ScriptDescriptor) { 1698 ScriptDescriptor scriptDescriptor = (ScriptDescriptor) descriptor.getContainingDeclaration(); 1699 Type scriptClassType = asmTypeForScriptDescriptor(bindingContext, scriptDescriptor); 1700 ValueParameterDescriptor valueParameterDescriptor = (ValueParameterDescriptor) descriptor; 1701 ClassDescriptor scriptClass = bindingContext.get(CLASS_FOR_SCRIPT, scriptDescriptor); 1702 StackValue script = StackValue.thisOrOuter(this, scriptClass, false, false); 1703 script.put(script.type, v); 1704 Type fieldType = typeMapper.mapType(valueParameterDescriptor); 1705 return StackValue.field(fieldType, scriptClassType, valueParameterDescriptor.getName().getIdentifier(), false); 1706 } 1707 1708 throw new UnsupportedOperationException("don't know how to generate reference " + descriptor); 1709 } 1710 1711 @Nullable 1712 public StackValue findLocalOrCapturedValue(@NotNull DeclarationDescriptor descriptor) { 1713 int index = lookupLocalIndex(descriptor); 1714 if (index >= 0) { 1715 return stackValueForLocal(descriptor, index); 1716 } 1717 1718 StackValue value = context.lookupInContext(descriptor, StackValue.local(0, OBJECT_TYPE), state, false); 1719 if (value == null) return null; 1720 1721 if (context.isSpecialStackValue(value)) { 1722 return value; 1723 } 1724 1725 if (value instanceof StackValue.Composed) { 1726 StackValue.Composed composed = (StackValue.Composed) value; 1727 composed.prefix.put(OBJECT_TYPE, v); 1728 value = composed.suffix; 1729 } 1730 1731 if (value instanceof StackValue.FieldForSharedVar) { 1732 StackValue.FieldForSharedVar fieldForSharedVar = (StackValue.FieldForSharedVar) value; 1733 Type sharedType = StackValue.sharedTypeForType(value.type); 1734 v.visitFieldInsn(GETFIELD, fieldForSharedVar.owner.getInternalName(), fieldForSharedVar.name, 1735 sharedType.getDescriptor()); 1736 } 1737 1738 return value; 1739 } 1740 1741 1742 private StackValue stackValueForLocal(DeclarationDescriptor descriptor, int index) { 1743 if (descriptor instanceof VariableDescriptor) { 1744 Type sharedVarType = typeMapper.getSharedVarType(descriptor); 1745 JetType outType = ((VariableDescriptor) descriptor).getType(); 1746 if (sharedVarType != null) { 1747 return StackValue.shared(index, asmType(outType)); 1748 } 1749 else { 1750 return StackValue.local(index, asmType(outType)); 1751 } 1752 } 1753 else { 1754 return StackValue.local(index, OBJECT_TYPE); 1755 } 1756 } 1757 1758 @Override 1759 public boolean lookupLocal(DeclarationDescriptor descriptor) { 1760 return lookupLocalIndex(descriptor) != -1; 1761 } 1762 1763 public int lookupLocalIndex(DeclarationDescriptor descriptor) { 1764 return myFrameMap.getIndex(descriptor); 1765 } 1766 1767 @Nullable 1768 private static JetType getPropertyDelegateType(@NotNull PropertyDescriptor descriptor, @NotNull BindingContext bindingContext) { 1769 PropertyGetterDescriptor getter = descriptor.getGetter(); 1770 if (getter != null) { 1771 Call call = bindingContext.get(DELEGATED_PROPERTY_CALL, getter); 1772 return call != null ? call.getExplicitReceiver().getType() : null; 1773 } 1774 return null; 1775 } 1776 1777 @NotNull 1778 public StackValue.Property intermediateValueForProperty( 1779 @NotNull PropertyDescriptor propertyDescriptor, 1780 boolean forceField, 1781 @Nullable JetSuperExpression superExpression 1782 ) { 1783 return intermediateValueForProperty(propertyDescriptor, forceField, superExpression, MethodKind.GENERAL); 1784 } 1785 1786 public StackValue.Property intermediateValueForProperty( 1787 @NotNull PropertyDescriptor propertyDescriptor, 1788 boolean forceField, 1789 @Nullable JetSuperExpression superExpression, 1790 @NotNull MethodKind methodKind 1791 ) { 1792 DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); 1793 1794 boolean isBackingFieldInAnotherClass = AsmUtil.isPropertyWithBackingFieldInOuterClass(propertyDescriptor); 1795 boolean isStatic = containingDeclaration instanceof PackageFragmentDescriptor; 1796 boolean isSuper = superExpression != null; 1797 boolean isInsideClass = isCallInsideSameClassAsDeclared(propertyDescriptor, context); 1798 1799 JetType delegateType = getPropertyDelegateType(propertyDescriptor, bindingContext); 1800 boolean isDelegatedProperty = delegateType != null; 1801 1802 CallableMethod callableGetter = null; 1803 CallableMethod callableSetter = null; 1804 1805 boolean skipPropertyAccessors = forceField && !isBackingFieldInAnotherClass; 1806 1807 CodegenContext backingFieldContext = context.getParentContext(); 1808 1809 if (isBackingFieldInAnotherClass && forceField) { 1810 //delegate call to classObject owner : OWNER 1811 backingFieldContext = context.findParentContextWithDescriptor(containingDeclaration.getContainingDeclaration()); 1812 int flags = AsmUtil.getVisibilityForSpecialPropertyBackingField(propertyDescriptor, isDelegatedProperty); 1813 skipPropertyAccessors = (flags & ACC_PRIVATE) == 0 || methodKind == MethodKind.SYNTHETIC_ACCESSOR || methodKind == MethodKind.INITIALIZER; 1814 if (!skipPropertyAccessors) { 1815 propertyDescriptor = (PropertyDescriptor) backingFieldContext.getAccessor(propertyDescriptor, true, delegateType); 1816 } 1817 isStatic = true; 1818 } 1819 1820 if (!skipPropertyAccessors) { 1821 if (couldUseDirectAccessToProperty(propertyDescriptor, true, isInsideClass, isDelegatedProperty, context)) { 1822 callableGetter = null; 1823 } 1824 else { 1825 if (isSuper && !isInterface(containingDeclaration)) { 1826 ClassDescriptor owner = getSuperCallLabelTarget(superExpression); 1827 CodegenContext c = context.findParentContextWithDescriptor(owner); 1828 assert c != null : "Couldn't find a context for a super-call: " + propertyDescriptor; 1829 if (c != context.getParentContext()) { 1830 propertyDescriptor = (PropertyDescriptor) c.getAccessor(propertyDescriptor); 1831 } 1832 } 1833 1834 propertyDescriptor = accessiblePropertyDescriptor(propertyDescriptor); 1835 1836 PropertyGetterDescriptor getter = propertyDescriptor.getGetter(); 1837 if (getter != null) { 1838 callableGetter = typeMapper.mapToCallableMethod(getter, isSuper || MethodKind.SYNTHETIC_ACCESSOR == methodKind, context); 1839 } 1840 } 1841 1842 if (propertyDescriptor.isVar()) { 1843 PropertySetterDescriptor setter = propertyDescriptor.getSetter(); 1844 if (setter != null) { 1845 if (couldUseDirectAccessToProperty(propertyDescriptor, false, isInsideClass, isDelegatedProperty, context)) { 1846 callableSetter = null; 1847 } 1848 else { 1849 callableSetter = typeMapper.mapToCallableMethod(setter, isSuper || MethodKind.SYNTHETIC_ACCESSOR == methodKind, context); 1850 } 1851 } 1852 } 1853 } 1854 1855 Type owner; 1856 CallableMethod callableMethod = callableGetter != null ? callableGetter : callableSetter; 1857 1858 propertyDescriptor = DescriptorUtils.unwrapFakeOverride(propertyDescriptor); 1859 if (callableMethod == null) { 1860 owner = typeMapper.mapOwner(isBackingFieldInAnotherClass ? propertyDescriptor.getContainingDeclaration() : propertyDescriptor, 1861 isCallInsideSameModuleAsDeclared(propertyDescriptor, context)); 1862 } 1863 else { 1864 owner = callableMethod.getOwner(); 1865 } 1866 1867 String name; 1868 if (propertyDescriptor.getContainingDeclaration() == backingFieldContext.getContextDescriptor()) { 1869 assert backingFieldContext instanceof FieldOwnerContext : "Actual context is " + backingFieldContext + " but should be instance of FieldOwnerContext" ; 1870 name = ((FieldOwnerContext) backingFieldContext).getFieldName(propertyDescriptor, isDelegatedProperty); 1871 } else { 1872 name = JvmAbi.getDefaultPropertyName(propertyDescriptor.getName(), isDelegatedProperty, propertyDescriptor.getReceiverParameter() != null); 1873 } 1874 1875 return StackValue.property(propertyDescriptor, owner, 1876 typeMapper.mapType(isDelegatedProperty && forceField ? delegateType : propertyDescriptor.getOriginal().getType()), 1877 isStatic, name, callableGetter, callableSetter, state); 1878 1879 } 1880 1881 @Override 1882 public StackValue visitCallExpression(@NotNull JetCallExpression expression, StackValue receiver) { 1883 JetExpression callee = expression.getCalleeExpression(); 1884 assert callee != null; 1885 1886 ResolvedCall<?> resolvedCall = resolvedCall(callee); 1887 CallableDescriptor funDescriptor = resolvedCall.getResultingDescriptor(); 1888 1889 if (!(funDescriptor instanceof FunctionDescriptor)) { 1890 throw new UnsupportedOperationException("unknown type of callee descriptor: " + funDescriptor); 1891 } 1892 1893 funDescriptor = accessibleFunctionDescriptor((FunctionDescriptor) funDescriptor); 1894 1895 if (funDescriptor instanceof ConstructorDescriptor) { 1896 return generateNewCall(expression, resolvedCall, receiver); 1897 } 1898 1899 Call call = bindingContext.get(CALL, expression.getCalleeExpression()); 1900 if (funDescriptor.getOriginal() instanceof SamConstructorDescriptor) { 1901 //noinspection ConstantConditions 1902 SamType samType = SamType.create(funDescriptor.getReturnType()); 1903 assert samType != null : "SamType is not created for SAM constructor: " + funDescriptor; 1904 return invokeSamConstructor(expression, resolvedCall, samType); 1905 } 1906 1907 return invokeFunction(call, receiver, resolvedCall); 1908 } 1909 1910 @NotNull 1911 private StackValue invokeSamConstructor( 1912 @NotNull JetCallExpression expression, 1913 @NotNull ResolvedCall<?> resolvedCall, 1914 @NotNull SamType samType 1915 ) { 1916 List<ResolvedValueArgument> arguments = resolvedCall.getValueArgumentsByIndex(); 1917 if (arguments == null) { 1918 throw new IllegalStateException("Failed to arrange value arguments by index: " + resolvedCall.getResultingDescriptor()); 1919 } 1920 ResolvedValueArgument argument = arguments.get(0); 1921 if (!(argument instanceof ExpressionValueArgument)) { 1922 throw new IllegalStateException( 1923 "argument of SAM constructor is " + argument.getClass().getName() + " " + expression.getText()); 1924 } 1925 ValueArgument valueArgument = ((ExpressionValueArgument) argument).getValueArgument(); 1926 assert valueArgument != null : "getValueArgument() is null for " + expression.getText(); 1927 JetExpression argumentExpression = valueArgument.getArgumentExpression(); 1928 assert argumentExpression != null : "getArgumentExpression() is null for " + expression.getText(); 1929 1930 return genSamInterfaceValue(argumentExpression, samType, this); 1931 } 1932 1933 @NotNull 1934 private StackValue genSamInterfaceValue( 1935 @NotNull JetExpression expression, 1936 @NotNull SamType samType, 1937 @NotNull JetVisitor<StackValue, StackValue> visitor 1938 ) { 1939 if (expression instanceof JetFunctionLiteralExpression) { 1940 return genClosure(((JetFunctionLiteralExpression) expression).getFunctionLiteral(), samType, 1941 KotlinSyntheticClass.Kind.SAM_LAMBDA); 1942 } 1943 1944 Type asmType = state.getSamWrapperClasses().getSamWrapperClass(samType, expression.getContainingJetFile()); 1945 1946 v.anew(asmType); 1947 v.dup(); 1948 1949 Type functionType = typeMapper.mapType(samType.getKotlinFunctionType()); 1950 expression.accept(visitor, StackValue.none()).put(functionType, v); 1951 1952 Label ifNonNull = new Label(); 1953 Label afterAll = new Label(); 1954 1955 v.dup(); 1956 v.ifnonnull(ifNonNull); 1957 1958 // if null: pop function value and wrapper objects, put null 1959 v.pop(); 1960 v.pop2(); 1961 v.aconst(null); 1962 v.goTo(afterAll); 1963 1964 v.mark(ifNonNull); 1965 v.invokespecial(asmType.getInternalName(), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, functionType)); 1966 1967 v.mark(afterAll); 1968 return StackValue.onStack(asmType); 1969 } 1970 1971 @NotNull 1972 private PropertyDescriptor accessiblePropertyDescriptor(PropertyDescriptor propertyDescriptor) { 1973 return context.accessiblePropertyDescriptor(propertyDescriptor); 1974 } 1975 1976 @NotNull 1977 protected FunctionDescriptor accessibleFunctionDescriptor(FunctionDescriptor fd) { 1978 return context.accessibleFunctionDescriptor(fd); 1979 } 1980 1981 @NotNull 1982 public StackValue invokeFunction(Call call, StackValue receiver, ResolvedCall<?> resolvedCall) { 1983 if (resolvedCall instanceof VariableAsFunctionResolvedCall) { 1984 return invokeFunction(call, receiver, ((VariableAsFunctionResolvedCall) resolvedCall).getFunctionCall()); 1985 } 1986 1987 FunctionDescriptor fd = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); 1988 JetSuperExpression superCallExpression = getSuperCallExpression(call); 1989 boolean superCall = superCallExpression != null; 1990 1991 if (superCall && !isInterface(fd.getContainingDeclaration())) { 1992 ClassDescriptor owner = getSuperCallLabelTarget(superCallExpression); 1993 CodegenContext c = context.findParentContextWithDescriptor(owner); 1994 assert c != null : "Couldn't find a context for a super-call: " + fd; 1995 if (c != context.getParentContext()) { 1996 fd = (FunctionDescriptor) c.getAccessor(fd); 1997 } 1998 } 1999 2000 Callable callable = resolveToCallable(accessibleFunctionDescriptor(fd), superCall); 2001 2002 if (callable instanceof CallableMethod) { 2003 CallableMethod callableMethod = (CallableMethod) callable; 2004 invokeMethodWithArguments(call, callableMethod, resolvedCall, receiver); 2005 //noinspection ConstantConditions 2006 Type returnType = typeMapper.mapReturnType(resolvedCall.getResultingDescriptor()); 2007 StackValue.coerce(callableMethod.getReturnType(), returnType, v); 2008 return StackValue.onStack(returnType); 2009 } 2010 else { 2011 receiver = StackValue.receiver(resolvedCall, receiver, this, null); 2012 2013 List<JetExpression> args = new ArrayList<JetExpression>(); 2014 for (ValueArgument argument : call.getValueArguments()) { 2015 args.add(argument.getArgumentExpression()); 2016 } 2017 2018 Type returnType = typeMapper.mapType(resolvedCall.getResultingDescriptor()); 2019 2020 ((IntrinsicMethod) callable).generate(this, v, returnType, call.getCallElement(), args, receiver); 2021 return StackValue.onStack(returnType); 2022 } 2023 } 2024 2025 @Nullable 2026 private static JetSuperExpression getSuperCallExpression(@NotNull Call call) { 2027 ReceiverValue explicitReceiver = call.getExplicitReceiver(); 2028 if (explicitReceiver instanceof ExpressionReceiver) { 2029 JetExpression receiverExpression = ((ExpressionReceiver) explicitReceiver).getExpression(); 2030 if (receiverExpression instanceof JetSuperExpression) { 2031 return (JetSuperExpression) receiverExpression; 2032 } 2033 } 2034 return null; 2035 } 2036 2037 // Find the first parent of the current context which corresponds to a subclass of a given class 2038 @NotNull 2039 private static CodegenContext getParentContextSubclassOf(ClassDescriptor descriptor, CodegenContext context) { 2040 CodegenContext c = context; 2041 while (true) { 2042 if (c instanceof ClassContext && DescriptorUtils.isSubclass(c.getThisDescriptor(), descriptor)) { 2043 return c; 2044 } 2045 c = c.getParentContext(); 2046 assert c != null; 2047 } 2048 } 2049 2050 @NotNull 2051 Callable resolveToCallable(@NotNull FunctionDescriptor fd, boolean superCall) { 2052 IntrinsicMethod intrinsic = state.getIntrinsics().getIntrinsic(fd); 2053 if (intrinsic != null) { 2054 return intrinsic; 2055 } 2056 2057 return resolveToCallableMethod(fd, superCall, context); 2058 } 2059 2060 @NotNull 2061 private CallableMethod resolveToCallableMethod(@NotNull FunctionDescriptor fd, boolean superCall, @NotNull CodegenContext context) { 2062 SimpleFunctionDescriptor originalOfSamAdapter = (SimpleFunctionDescriptor) SamCodegenUtil.getOriginalIfSamAdapter(fd); 2063 return typeMapper.mapToCallableMethod(originalOfSamAdapter != null ? originalOfSamAdapter : fd, superCall, context); 2064 } 2065 2066 public void invokeMethodWithArguments( 2067 @Nullable Call call, 2068 @NotNull CallableMethod callableMethod, 2069 @NotNull ResolvedCall<?> resolvedCall, 2070 @NotNull StackValue receiver 2071 ) { 2072 CallableDescriptor descriptor = resolvedCall.getResultingDescriptor(); 2073 JetElement callElement = call != null ? call.getCallElement() : null; 2074 2075 CallGenerator callGenerator = getOrCreateCallGenerator(descriptor, callElement); 2076 2077 if (resolvedCall instanceof VariableAsFunctionResolvedCall) { 2078 resolvedCall = ((VariableAsFunctionResolvedCall) resolvedCall).getFunctionCall(); 2079 } 2080 2081 assert callGenerator == defaultCallGenerator || !tailRecursionCodegen.isTailRecursion(resolvedCall) : 2082 "Tail recursive method couldn't be inlined " + descriptor; 2083 2084 int mask = pushMethodArgumentsWithCallReceiver(receiver, resolvedCall, callableMethod, false, callGenerator); 2085 2086 if (tailRecursionCodegen.isTailRecursion(resolvedCall)) { 2087 tailRecursionCodegen.generateTailRecursion(resolvedCall); 2088 return; 2089 } 2090 2091 boolean callDefault = mask != 0; 2092 if (callDefault) { 2093 callGenerator.putValueIfNeeded(null, Type.INT_TYPE, StackValue.constant(mask, Type.INT_TYPE)); 2094 } 2095 2096 callGenerator.genCall(callableMethod, resolvedCall, callDefault, this); 2097 } 2098 2099 @NotNull 2100 protected CallGenerator getOrCreateCallGenerator(@NotNull CallableDescriptor descriptor, @Nullable JetElement callElement) { 2101 boolean isInline = state.isInlineEnabled() && 2102 descriptor instanceof SimpleFunctionDescriptor && 2103 ((SimpleFunctionDescriptor) descriptor).getInlineStrategy().isInline(); 2104 2105 return !isInline || callElement == null ? defaultCallGenerator : 2106 new InlineCodegen(this, state, (SimpleFunctionDescriptor) DescriptorUtils.unwrapFakeOverride( 2107 (CallableMemberDescriptor) descriptor.getOriginal()), callElement); 2108 } 2109 2110 public void generateFromResolvedCall(@NotNull ReceiverValue descriptor, @NotNull Type type) { 2111 if (descriptor instanceof ClassReceiver) { 2112 Type exprType = asmType(descriptor.getType()); 2113 ClassReceiver classReceiver = (ClassReceiver) descriptor; 2114 ClassDescriptor classReceiverDeclarationDescriptor = classReceiver.getDeclarationDescriptor(); 2115 if (DescriptorUtils.isClassObject(classReceiverDeclarationDescriptor)) { 2116 if (context.getContextDescriptor() instanceof FunctionDescriptor && 2117 classReceiverDeclarationDescriptor == context.getContextDescriptor().getContainingDeclaration()) { 2118 v.load(0, OBJECT_TYPE); 2119 } 2120 else { 2121 FieldInfo info = FieldInfo.createForSingleton(classReceiverDeclarationDescriptor, typeMapper); 2122 v.getstatic(info.getOwnerInternalName(), info.getFieldName(), info.getFieldType().getDescriptor()); 2123 } 2124 StackValue.onStack(exprType).put(type, v); 2125 } 2126 else { 2127 StackValue.thisOrOuter(this, classReceiverDeclarationDescriptor, false, false).put(type, v); 2128 } 2129 } 2130 else if (descriptor instanceof ScriptReceiver) { 2131 // SCRIPT: generate script 2132 generateScript((ScriptReceiver) descriptor); 2133 } 2134 else if (descriptor instanceof ExtensionReceiver) { 2135 ExtensionReceiver extensionReceiver = (ExtensionReceiver) descriptor; 2136 generateReceiver(extensionReceiver.getDeclarationDescriptor()).put(type, v); 2137 } 2138 else if (descriptor instanceof ExpressionReceiver) { 2139 ExpressionReceiver expressionReceiver = (ExpressionReceiver) descriptor; 2140 JetExpression expr = expressionReceiver.getExpression(); 2141 gen(expr, type); 2142 } 2143 else { 2144 throw new UnsupportedOperationException("Unsupported receiver type: " + descriptor); 2145 } 2146 } 2147 2148 @Nullable 2149 private static JetExpression getReceiverForSelector(PsiElement expression) { 2150 if (expression.getParent() instanceof JetDotQualifiedExpression && !isReceiver(expression)) { 2151 JetDotQualifiedExpression parent = (JetDotQualifiedExpression) expression.getParent(); 2152 return parent.getReceiverExpression(); 2153 } 2154 return null; 2155 } 2156 2157 private StackValue generateReceiver(DeclarationDescriptor provided) { 2158 if (context.getCallableDescriptorWithReceiver() == provided) { 2159 return context.getReceiverExpression(typeMapper); 2160 } 2161 2162 return context.lookupInContext(provided, StackValue.local(0, OBJECT_TYPE), state, false); 2163 } 2164 2165 // SCRIPT: generate script, move to ScriptingUtil 2166 private void generateScript(@NotNull ScriptReceiver receiver) { 2167 CodegenContext cur = context; 2168 StackValue result = StackValue.local(0, OBJECT_TYPE); 2169 boolean inStartConstructorContext = cur instanceof ConstructorContext; 2170 while (cur != null) { 2171 if (!inStartConstructorContext) { 2172 cur = getNotNullParentContextForMethod(cur); 2173 } 2174 2175 if (cur instanceof ScriptContext) { 2176 ScriptContext scriptContext = (ScriptContext) cur; 2177 2178 Type currentScriptType = asmTypeForScriptDescriptor(bindingContext, scriptContext.getScriptDescriptor()); 2179 if (scriptContext.getScriptDescriptor() == receiver.getDeclarationDescriptor()) { 2180 result.put(currentScriptType, v); 2181 } 2182 else { 2183 Type classType = asmTypeForScriptDescriptor(bindingContext, receiver.getDeclarationDescriptor()); 2184 String fieldName = scriptContext.getScriptFieldName(receiver.getDeclarationDescriptor()); 2185 result.put(currentScriptType, v); 2186 StackValue.field(classType, currentScriptType, fieldName, false).put(classType, v); 2187 } 2188 return; 2189 } 2190 2191 result = cur.getOuterExpression(result, false); 2192 2193 if (inStartConstructorContext) { 2194 cur = getNotNullParentContextForMethod(cur); 2195 inStartConstructorContext = false; 2196 } 2197 2198 cur = cur.getParentContext(); 2199 } 2200 2201 throw new UnsupportedOperationException(); 2202 } 2203 2204 @NotNull 2205 public StackValue generateThisOrOuter(@NotNull ClassDescriptor calleeContainingClass, boolean isSuper) { 2206 boolean isSingleton = calleeContainingClass.getKind().isSingleton(); 2207 if (isSingleton) { 2208 if (context.hasThisDescriptor() && context.getThisDescriptor().equals(calleeContainingClass)) { 2209 return StackValue.local(0, typeMapper.mapType(calleeContainingClass)); 2210 } 2211 else { 2212 return StackValue.singleton(calleeContainingClass, typeMapper); 2213 } 2214 } 2215 2216 CodegenContext cur = context; 2217 Type type = asmType(calleeContainingClass.getDefaultType()); 2218 StackValue result = StackValue.local(0, type); 2219 boolean inStartConstructorContext = cur instanceof ConstructorContext; 2220 while (cur != null) { 2221 ClassDescriptor thisDescriptor = cur.getThisDescriptor(); 2222 2223 if (!isSuper && thisDescriptor == calleeContainingClass) { 2224 return result; 2225 } 2226 2227 if (isSuper && DescriptorUtils.isSubclass(thisDescriptor, calleeContainingClass)) { 2228 return castToRequiredTypeOfInterfaceIfNeeded(result, thisDescriptor, calleeContainingClass); 2229 } 2230 2231 //for constructor super call we should access to outer instance through parameter in locals, in other cases through field for captured outer 2232 if (inStartConstructorContext) { 2233 result = cur.getOuterExpression(result, false); 2234 cur = getNotNullParentContextForMethod(cur); 2235 inStartConstructorContext = false; 2236 } 2237 else { 2238 cur = getNotNullParentContextForMethod(cur); 2239 result = cur.getOuterExpression(result, false); 2240 } 2241 2242 cur = cur.getParentContext(); 2243 } 2244 2245 throw new UnsupportedOperationException(); 2246 } 2247 2248 @NotNull 2249 private static CodegenContext getNotNullParentContextForMethod(CodegenContext cur) { 2250 if (cur instanceof MethodContext) { 2251 cur = cur.getParentContext(); 2252 } 2253 assert cur != null; 2254 return cur; 2255 } 2256 2257 2258 private static boolean isReceiver(PsiElement expression) { 2259 PsiElement parent = expression.getParent(); 2260 if (parent instanceof JetQualifiedExpression) { 2261 JetExpression receiverExpression = ((JetQualifiedExpression) parent).getReceiverExpression(); 2262 return expression == receiverExpression; 2263 } 2264 return false; 2265 } 2266 2267 public int pushMethodArgumentsWithCallReceiver( 2268 @Nullable StackValue receiver, 2269 @NotNull ResolvedCall<?> resolvedCall, 2270 @NotNull CallableMethod callableMethod, 2271 boolean skipLast, 2272 @NotNull CallGenerator callGenerator 2273 ) { 2274 CallableDescriptor descriptor = resolvedCall.getResultingDescriptor(); 2275 2276 if (!(descriptor instanceof ConstructorDescriptor)) { // otherwise already 2277 receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod); 2278 receiver.put(receiver.type, v); 2279 } 2280 2281 callGenerator.putHiddenParams(); 2282 2283 return pushMethodArgumentsWithoutCallReceiver(resolvedCall, callableMethod.getValueParameterTypes(), skipLast, callGenerator); 2284 } 2285 2286 public int pushMethodArgumentsWithoutCallReceiver( 2287 @NotNull ResolvedCall<?> resolvedCall, 2288 List<Type> valueParameterTypes, 2289 boolean skipLast, 2290 @NotNull CallGenerator callGenerator 2291 ) { 2292 List<ResolvedValueArgument> valueArguments = resolvedCall.getValueArgumentsByIndex(); 2293 CallableDescriptor fd = resolvedCall.getResultingDescriptor(); 2294 if (valueArguments == null) { 2295 throw new IllegalStateException("Failed to arrange value arguments by index: " + fd); 2296 } 2297 List<ValueParameterDescriptor> valueParameters = fd.getValueParameters(); 2298 2299 if (valueParameters.size() != valueArguments.size()) { 2300 throw new IllegalStateException("Parameters and arguments size mismatch: " + valueParameters.size() + " != " + valueArguments.size()); 2301 } 2302 2303 int mask = 0; 2304 2305 for (Iterator<ValueParameterDescriptor> iterator = valueParameters.iterator(); iterator.hasNext(); ) { 2306 ValueParameterDescriptor valueParameter = iterator.next(); 2307 if (skipLast && !iterator.hasNext()) { 2308 continue; 2309 } 2310 2311 ResolvedValueArgument resolvedValueArgument = valueArguments.get(valueParameter.getIndex()); 2312 Type parameterType = valueParameterTypes.get(valueParameter.getIndex()); 2313 if (resolvedValueArgument instanceof ExpressionValueArgument) { 2314 ValueArgument valueArgument = ((ExpressionValueArgument) resolvedValueArgument).getValueArgument(); 2315 assert valueArgument != null; 2316 JetExpression argumentExpression = valueArgument.getArgumentExpression(); 2317 assert argumentExpression != null : valueArgument.asElement().getText(); 2318 2319 callGenerator.genValueAndPut(valueParameter, argumentExpression, parameterType); 2320 } else if (resolvedValueArgument instanceof DefaultValueArgument) { 2321 pushDefaultValueOnStack(parameterType, v); 2322 mask |= (1 << valueParameter.getIndex()); 2323 callGenerator.afterParameterPut(parameterType, null, valueParameter); 2324 } 2325 else if (resolvedValueArgument instanceof VarargValueArgument) { 2326 VarargValueArgument valueArgument = (VarargValueArgument) resolvedValueArgument; 2327 genVarargs(valueParameter, valueArgument); 2328 callGenerator.afterParameterPut(parameterType, null, valueParameter); 2329 } 2330 else { 2331 throw new UnsupportedOperationException(); 2332 } 2333 } 2334 return mask; 2335 } 2336 2337 public void genVarargs(ValueParameterDescriptor valueParameterDescriptor, VarargValueArgument valueArgument) { 2338 JetType outType = valueParameterDescriptor.getType(); 2339 2340 Type type = asmType(outType); 2341 assert type.getSort() == Type.ARRAY; 2342 Type elementType = correctElementType(type); 2343 List<ValueArgument> arguments = valueArgument.getArguments(); 2344 int size = arguments.size(); 2345 2346 boolean hasSpread = false; 2347 for (int i = 0; i != size; ++i) { 2348 if (arguments.get(i).getSpreadElement() != null) { 2349 hasSpread = true; 2350 break; 2351 } 2352 } 2353 2354 if (hasSpread) { 2355 if (size == 1) { 2356 gen(arguments.get(0).getArgumentExpression(), type); 2357 } 2358 else { 2359 String owner = "kotlin/jvm/internal/SpreadBuilder"; 2360 v.anew(Type.getObjectType(owner)); 2361 v.dup(); 2362 v.invokespecial(owner, "<init>", "()V"); 2363 for (int i = 0; i != size; ++i) { 2364 v.dup(); 2365 ValueArgument argument = arguments.get(i); 2366 if (argument.getSpreadElement() != null) { 2367 gen(argument.getArgumentExpression(), OBJECT_TYPE); 2368 v.invokevirtual(owner, "addSpread", "(Ljava/lang/Object;)V"); 2369 } 2370 else { 2371 gen(argument.getArgumentExpression(), elementType); 2372 v.invokevirtual(owner, "add", "(Ljava/lang/Object;)Z"); 2373 v.pop(); 2374 } 2375 } 2376 v.dup(); 2377 v.invokevirtual(owner, "size", "()I"); 2378 v.newarray(elementType); 2379 v.invokevirtual(owner, "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;"); 2380 v.checkcast(type); 2381 } 2382 } 2383 else { 2384 v.iconst(arguments.size()); 2385 v.newarray(elementType); 2386 for (int i = 0; i != size; ++i) { 2387 v.dup(); 2388 v.iconst(i); 2389 gen(arguments.get(i).getArgumentExpression(), elementType); 2390 StackValue.arrayElement(elementType).store(elementType, v); 2391 } 2392 } 2393 } 2394 2395 public int indexOfLocal(JetReferenceExpression lhs) { 2396 DeclarationDescriptor declarationDescriptor = bindingContext.get(REFERENCE_TARGET, lhs); 2397 if (isVarCapturedInClosure(bindingContext, declarationDescriptor)) { 2398 return -1; 2399 } 2400 return lookupLocalIndex(declarationDescriptor); 2401 } 2402 2403 @Override 2404 public StackValue visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression, StackValue data) { 2405 // TODO: properties 2406 FunctionDescriptor functionDescriptor = bindingContext.get(FUNCTION, expression); 2407 assert functionDescriptor != null : "Callable reference is not resolved to descriptor: " + expression.getText(); 2408 2409 CallableReferenceGenerationStrategy strategy = 2410 new CallableReferenceGenerationStrategy(state, functionDescriptor, resolvedCall(expression.getCallableReference())); 2411 ClosureCodegen closureCodegen = new ClosureCodegen(state, expression, functionDescriptor, null, context, 2412 KotlinSyntheticClass.Kind.CALLABLE_REFERENCE_WRAPPER, 2413 this, strategy, getParentCodegen()); 2414 2415 closureCodegen.gen(); 2416 2417 return closureCodegen.putInstanceOnStack(v, this); 2418 } 2419 2420 private static class CallableReferenceGenerationStrategy extends FunctionGenerationStrategy.CodegenBased<FunctionDescriptor> { 2421 private final ResolvedCall<?> resolvedCall; 2422 private final FunctionDescriptor referencedFunction; 2423 2424 public CallableReferenceGenerationStrategy( 2425 @NotNull GenerationState state, 2426 @NotNull FunctionDescriptor functionDescriptor, 2427 @NotNull ResolvedCall<?> resolvedCall 2428 ) { 2429 super(state, functionDescriptor); 2430 this.resolvedCall = resolvedCall; 2431 this.referencedFunction = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); 2432 } 2433 2434 @Override 2435 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { 2436 /* 2437 Here we need to put the arguments from our locals to the stack and invoke the referenced method. Since invocation 2438 of methods is highly dependent on expressions, we create a fake call expression. Then we create a new instance of 2439 ExpressionCodegen and, in order for it to generate code correctly, we save to its 'tempVariables' field every 2440 argument of our fake expression, pointing it to the corresponding index in our locals. This way generation of 2441 every argument boils down to calling LOAD with the corresponding index 2442 */ 2443 2444 JetCallExpression fakeExpression = constructFakeFunctionCall(); 2445 final List<? extends ValueArgument> fakeArguments = fakeExpression.getValueArguments(); 2446 2447 final ReceiverValue thisObject = computeAndSaveReceiver(signature, codegen, referencedFunction.getExpectedThisObject()); 2448 final ReceiverValue extensionReceiver = computeAndSaveReceiver(signature, codegen, referencedFunction.getReceiverParameter()); 2449 computeAndSaveArguments(fakeArguments, codegen); 2450 2451 ResolvedCall<CallableDescriptor> fakeResolvedCall = new DelegatingResolvedCall<CallableDescriptor>(resolvedCall) { 2452 @NotNull 2453 @Override 2454 public ReceiverValue getReceiverArgument() { 2455 return extensionReceiver; 2456 } 2457 2458 @NotNull 2459 @Override 2460 public ReceiverValue getThisObject() { 2461 return thisObject; 2462 } 2463 2464 @NotNull 2465 @Override 2466 public List<ResolvedValueArgument> getValueArgumentsByIndex() { 2467 List<ResolvedValueArgument> result = new ArrayList<ResolvedValueArgument>(fakeArguments.size()); 2468 for (ValueArgument argument : fakeArguments) { 2469 result.add(new ExpressionValueArgument(argument)); 2470 } 2471 return result; 2472 } 2473 }; 2474 2475 StackValue result; 2476 Type returnType = codegen.returnType; 2477 if (referencedFunction instanceof ConstructorDescriptor) { 2478 if (returnType.getSort() == Type.ARRAY) { 2479 //noinspection ConstantConditions 2480 codegen.generateNewArray(fakeExpression, referencedFunction.getReturnType()); 2481 result = StackValue.onStack(returnType); 2482 } 2483 else { 2484 result = codegen.generateConstructorCall(fakeResolvedCall, StackValue.none(), returnType); 2485 } 2486 } 2487 else { 2488 Call call = CallMaker.makeCall(fakeExpression, NO_RECEIVER, null, fakeExpression, fakeArguments); 2489 result = codegen.invokeFunction(call, StackValue.none(), fakeResolvedCall); 2490 } 2491 2492 InstructionAdapter v = codegen.v; 2493 result.put(returnType, v); 2494 v.areturn(returnType); 2495 } 2496 2497 @NotNull 2498 private JetCallExpression constructFakeFunctionCall() { 2499 StringBuilder fakeFunctionCall = new StringBuilder("callableReferenceFakeCall("); 2500 for (Iterator<ValueParameterDescriptor> iterator = referencedFunction.getValueParameters().iterator(); iterator.hasNext(); ) { 2501 ValueParameterDescriptor descriptor = iterator.next(); 2502 fakeFunctionCall.append("p").append(descriptor.getIndex()); 2503 if (iterator.hasNext()) { 2504 fakeFunctionCall.append(", "); 2505 } 2506 } 2507 fakeFunctionCall.append(")"); 2508 return (JetCallExpression) JetPsiFactory.createExpression(state.getProject(), fakeFunctionCall.toString()); 2509 } 2510 2511 private void computeAndSaveArguments(@NotNull List<? extends ValueArgument> fakeArguments, @NotNull ExpressionCodegen codegen) { 2512 for (ValueParameterDescriptor parameter : callableDescriptor.getValueParameters()) { 2513 ValueArgument fakeArgument = fakeArguments.get(parameter.getIndex()); 2514 Type type = state.getTypeMapper().mapType(parameter); 2515 int localIndex = codegen.myFrameMap.getIndex(parameter); 2516 codegen.tempVariables.put(fakeArgument.getArgumentExpression(), StackValue.local(localIndex, type)); 2517 } 2518 } 2519 2520 @NotNull 2521 private ReceiverValue computeAndSaveReceiver( 2522 @NotNull JvmMethodSignature signature, 2523 @NotNull ExpressionCodegen codegen, 2524 @Nullable ReceiverParameterDescriptor receiver 2525 ) { 2526 if (receiver == null) return NO_RECEIVER; 2527 2528 JetExpression receiverExpression = JetPsiFactory.createExpression(state.getProject(), "callableReferenceFakeReceiver"); 2529 codegen.tempVariables.put(receiverExpression, receiverParameterStackValue(signature)); 2530 return new ExpressionReceiver(receiverExpression, receiver.getType()); 2531 } 2532 2533 @NotNull 2534 private static StackValue.Local receiverParameterStackValue(@NotNull JvmMethodSignature signature) { 2535 // 0 is this (the callable reference class), 1 is the invoke() method's first parameter 2536 return StackValue.local(1, signature.getAsmMethod().getArgumentTypes()[0]); 2537 } 2538 } 2539 2540 @Override 2541 public StackValue visitDotQualifiedExpression(@NotNull JetDotQualifiedExpression expression, StackValue receiver) { 2542 StackValue receiverValue = StackValue.none(); 2543 return genQualified(receiverValue, expression.getSelectorExpression()); 2544 } 2545 2546 @Override 2547 public StackValue visitSafeQualifiedExpression(@NotNull JetSafeQualifiedExpression expression, StackValue unused) { 2548 JetExpression receiver = expression.getReceiverExpression(); 2549 JetExpression selector = expression.getSelectorExpression(); 2550 Type type = boxType(expressionType(expression)); 2551 Type receiverType = expressionType(receiver); 2552 2553 gen(receiver, receiverType); 2554 2555 if (isPrimitive(receiverType)) { 2556 StackValue propValue = genQualified(StackValue.onStack(receiverType), selector); 2557 propValue.put(type, v); 2558 2559 return StackValue.onStack(type); 2560 } 2561 2562 Label ifnull = new Label(); 2563 Label end = new Label(); 2564 v.dup(); 2565 v.ifnull(ifnull); 2566 StackValue propValue = genQualified(StackValue.onStack(receiverType), selector); 2567 propValue.put(type, v); 2568 v.goTo(end); 2569 2570 v.mark(ifnull); 2571 v.pop(); 2572 if (!type.equals(Type.VOID_TYPE)) { 2573 v.aconst(null); 2574 } 2575 v.mark(end); 2576 2577 return StackValue.onStack(type); 2578 } 2579 2580 @Override 2581 public StackValue visitBinaryExpression(@NotNull JetBinaryExpression expression, StackValue receiver) { 2582 JetSimpleNameExpression reference = expression.getOperationReference(); 2583 IElementType opToken = reference.getReferencedNameElementType(); 2584 if (opToken == JetTokens.EQ) { 2585 return generateAssignmentExpression(expression); 2586 } 2587 else if (JetTokens.AUGMENTED_ASSIGNMENTS.contains(opToken)) { 2588 return generateAugmentedAssignment(expression); 2589 } 2590 else if (opToken == JetTokens.ANDAND) { 2591 return generateBooleanAnd(expression); 2592 } 2593 else if (opToken == JetTokens.OROR) { 2594 return generateBooleanOr(expression); 2595 } 2596 else if (opToken == JetTokens.EQEQ || opToken == JetTokens.EXCLEQ || 2597 opToken == JetTokens.EQEQEQ || opToken == JetTokens.EXCLEQEQEQ) { 2598 return generateEquals(expression.getLeft(), expression.getRight(), opToken); 2599 } 2600 else if (opToken == JetTokens.LT || opToken == JetTokens.LTEQ || 2601 opToken == JetTokens.GT || opToken == JetTokens.GTEQ) { 2602 return generateComparison(expression, receiver); 2603 } 2604 else if (opToken == JetTokens.ELVIS) { 2605 return generateElvis(expression); 2606 } 2607 else if (opToken == JetTokens.IN_KEYWORD || opToken == JetTokens.NOT_IN) { 2608 return generateIn(StackValue.expression(Type.INT_TYPE, expression.getLeft(), this), expression.getRight(), reference); 2609 } 2610 else { 2611 ResolvedCall<?> resolvedCall = resolvedCall(reference); 2612 FunctionDescriptor descriptor = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); 2613 2614 Callable callable = resolveToCallable(descriptor, false); 2615 if (callable instanceof IntrinsicMethod) { 2616 Type returnType = typeMapper.mapType(descriptor); 2617 ((IntrinsicMethod) callable).generate(this, v, returnType, expression, 2618 Arrays.asList(expression.getLeft(), expression.getRight()), receiver); 2619 return StackValue.onStack(returnType); 2620 } 2621 2622 Call call = bindingContext.get(CALL, reference); 2623 return invokeFunction(call, receiver, resolvedCall); 2624 } 2625 } 2626 2627 private StackValue generateIn(StackValue leftValue, JetExpression rangeExpression, JetSimpleNameExpression operationReference) { 2628 JetExpression deparenthesized = JetPsiUtil.deparenthesize(rangeExpression); 2629 if (isIntRangeExpr(deparenthesized)) { 2630 genInIntRange(leftValue, (JetBinaryExpression) deparenthesized); 2631 } 2632 else { 2633 invokeFunction( 2634 bindingContext.get(CALL, operationReference), 2635 StackValue.none(), 2636 resolvedCall(operationReference) 2637 ); 2638 } 2639 if (operationReference.getReferencedNameElementType() == JetTokens.NOT_IN) { 2640 genInvertBoolean(v); 2641 } 2642 return StackValue.onStack(Type.BOOLEAN_TYPE); 2643 } 2644 2645 private void genInIntRange(StackValue leftValue, JetBinaryExpression rangeExpression) { 2646 v.iconst(1); 2647 // 1 2648 leftValue.put(Type.INT_TYPE, v); 2649 // 1 l 2650 v.dup2(); 2651 // 1 l 1 l 2652 2653 //noinspection ConstantConditions 2654 gen(rangeExpression.getLeft(), Type.INT_TYPE); 2655 // 1 l 1 l r 2656 Label lok = new Label(); 2657 v.ificmpge(lok); 2658 // 1 l 1 2659 v.pop(); 2660 v.iconst(0); 2661 v.mark(lok); 2662 // 1 l c 2663 v.dupX2(); 2664 // c 1 l c 2665 v.pop(); 2666 // c 1 l 2667 2668 gen(rangeExpression.getRight(), Type.INT_TYPE); 2669 // c 1 l r 2670 Label rok = new Label(); 2671 v.ificmple(rok); 2672 // c 1 2673 v.pop(); 2674 v.iconst(0); 2675 v.mark(rok); 2676 // c c 2677 2678 v.and(Type.INT_TYPE); 2679 } 2680 2681 private StackValue generateBooleanAnd(JetBinaryExpression expression) { 2682 gen(expression.getLeft(), Type.BOOLEAN_TYPE); 2683 Label ifFalse = new Label(); 2684 v.ifeq(ifFalse); 2685 gen(expression.getRight(), Type.BOOLEAN_TYPE); 2686 Label end = new Label(); 2687 v.goTo(end); 2688 v.mark(ifFalse); 2689 v.iconst(0); 2690 v.mark(end); 2691 return StackValue.onStack(Type.BOOLEAN_TYPE); 2692 } 2693 2694 private StackValue generateBooleanOr(JetBinaryExpression expression) { 2695 gen(expression.getLeft(), Type.BOOLEAN_TYPE); 2696 Label ifTrue = new Label(); 2697 v.ifne(ifTrue); 2698 gen(expression.getRight(), Type.BOOLEAN_TYPE); 2699 Label end = new Label(); 2700 v.goTo(end); 2701 v.mark(ifTrue); 2702 v.iconst(1); 2703 v.mark(end); 2704 return StackValue.onStack(Type.BOOLEAN_TYPE); 2705 } 2706 2707 private StackValue generateEquals(JetExpression left, JetExpression right, IElementType opToken) { 2708 Type leftType = expressionType(left); 2709 Type rightType = expressionType(right); 2710 2711 if (JetPsiUtil.isNullConstant(left)) { 2712 return genCmpWithNull(right, rightType, opToken); 2713 } 2714 2715 if (JetPsiUtil.isNullConstant(right)) { 2716 return genCmpWithNull(left, leftType, opToken); 2717 } 2718 2719 if (isIntZero(left, leftType) && isIntPrimitive(rightType)) { 2720 return genCmpWithZero(right, rightType, opToken); 2721 } 2722 2723 if (isIntZero(right, rightType) && isIntPrimitive(leftType)) { 2724 return genCmpWithZero(left, leftType, opToken); 2725 } 2726 2727 if (isPrimitive(leftType) != isPrimitive(rightType)) { 2728 leftType = boxType(leftType); 2729 gen(left, leftType); 2730 rightType = boxType(rightType); 2731 gen(right, rightType); 2732 } 2733 else { 2734 gen(left, leftType); 2735 gen(right, rightType); 2736 } 2737 2738 return genEqualsForExpressionsOnStack(v, opToken, leftType, rightType); 2739 } 2740 2741 private boolean isIntZero(JetExpression expr, Type exprType) { 2742 CompileTimeConstant<?> exprValue = getCompileTimeConstant(expr, bindingContext); 2743 return isIntPrimitive(exprType) && exprValue != null && Integer.valueOf(0).equals(exprValue.getValue()); 2744 } 2745 2746 private StackValue genCmpWithZero(JetExpression exp, Type expType, IElementType opToken) { 2747 v.iconst(1); 2748 gen(exp, expType); 2749 Label ok = new Label(); 2750 if (JetTokens.EQEQ == opToken || JetTokens.EQEQEQ == opToken) { 2751 v.ifeq(ok); 2752 } 2753 else { 2754 v.ifne(ok); 2755 } 2756 v.pop(); 2757 v.iconst(0); 2758 v.mark(ok); 2759 return StackValue.onStack(Type.BOOLEAN_TYPE); 2760 } 2761 2762 private StackValue genCmpWithNull(JetExpression exp, Type expType, IElementType opToken) { 2763 v.iconst(1); 2764 gen(exp, boxType(expType)); 2765 Label ok = new Label(); 2766 if (JetTokens.EQEQ == opToken || JetTokens.EQEQEQ == opToken) { 2767 v.ifnull(ok); 2768 } 2769 else { 2770 v.ifnonnull(ok); 2771 } 2772 v.pop(); 2773 v.iconst(0); 2774 v.mark(ok); 2775 return StackValue.onStack(Type.BOOLEAN_TYPE); 2776 } 2777 2778 private StackValue generateElvis(JetBinaryExpression expression) { 2779 Type exprType = expressionType(expression); 2780 Type leftType = expressionType(expression.getLeft()); 2781 2782 gen(expression.getLeft(), leftType); 2783 2784 if (isPrimitive(leftType)) { 2785 return StackValue.onStack(leftType); 2786 } 2787 2788 v.dup(); 2789 Label ifNull = new Label(); 2790 v.ifnull(ifNull); 2791 StackValue.onStack(leftType).put(exprType, v); 2792 Label end = new Label(); 2793 v.goTo(end); 2794 v.mark(ifNull); 2795 v.pop(); 2796 gen(expression.getRight(), exprType); 2797 v.mark(end); 2798 2799 return StackValue.onStack(exprType); 2800 } 2801 2802 private StackValue generateComparison(JetBinaryExpression expression, StackValue receiver) { 2803 ResolvedCall<?> resolvedCall = resolvedCall(expression.getOperationReference()); 2804 FunctionDescriptor descriptor = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); 2805 2806 JetExpression left = expression.getLeft(); 2807 JetExpression right = expression.getRight(); 2808 Callable callable = resolveToCallable(descriptor, false); 2809 2810 Type type; 2811 if (callable instanceof IntrinsicMethod) { 2812 // Compare two primitive values 2813 type = comparisonOperandType(expressionType(left), expressionType(right)); 2814 StackValue recv = gen(left); 2815 recv.put(type, v); 2816 gen(right, type); 2817 } 2818 else { 2819 Call call = bindingContext.get(CALL, expression.getOperationReference()); 2820 StackValue result = invokeFunction(call, receiver, resolvedCall); 2821 type = Type.INT_TYPE; 2822 result.put(type, v); 2823 v.iconst(0); 2824 } 2825 return StackValue.cmp(expression.getOperationToken(), type); 2826 } 2827 2828 private StackValue generateAssignmentExpression(JetBinaryExpression expression) { 2829 StackValue stackValue = gen(expression.getLeft()); 2830 JetExpression right = expression.getRight(); 2831 assert right != null : expression.getText(); 2832 gen(right, stackValue.type); 2833 stackValue.store(stackValue.type, v); 2834 return StackValue.none(); 2835 } 2836 2837 private StackValue generateAugmentedAssignment(JetBinaryExpression expression) { 2838 ResolvedCall<?> resolvedCall = resolvedCall(expression.getOperationReference()); 2839 FunctionDescriptor descriptor = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); 2840 Callable callable = resolveToCallable(descriptor, false); 2841 JetExpression lhs = expression.getLeft(); 2842 Type lhsType = expressionType(lhs); 2843 2844 boolean keepReturnValue; 2845 if (Boolean.TRUE.equals(bindingContext.get(VARIABLE_REASSIGNMENT, expression))) { 2846 if (callable instanceof IntrinsicMethod) { 2847 StackValue value = gen(lhs); // receiver 2848 value.dupReceiver(v); // receiver receiver 2849 value.put(lhsType, v); // receiver lhs 2850 ((IntrinsicMethod) callable).generate(this, v, typeMapper.mapType(descriptor), expression, 2851 Collections.singletonList(expression.getRight()), StackValue.onStack(lhsType)); 2852 value.store(lhsType, v); 2853 return StackValue.none(); 2854 } 2855 else { 2856 keepReturnValue = true; 2857 } 2858 } 2859 else { 2860 keepReturnValue = !KotlinBuiltIns.getInstance().getUnitType().equals(descriptor.getReturnType()); 2861 } 2862 2863 callAugAssignMethod(expression, resolvedCall, (CallableMethod) callable, lhsType, keepReturnValue); 2864 2865 return StackValue.none(); 2866 } 2867 2868 private void callAugAssignMethod( 2869 @NotNull JetBinaryExpression expression, 2870 @NotNull ResolvedCall<?> resolvedCall, 2871 @NotNull CallableMethod callable, 2872 @NotNull Type lhsType, 2873 boolean keepReturnValue 2874 ) { 2875 Call call = bindingContext.get(CALL, expression.getOperationReference()); 2876 assert call != null : "Call should be not null for operation reference in " + expression.getText(); 2877 2878 StackValue value = gen(expression.getLeft()); 2879 if (keepReturnValue) { 2880 value.dupReceiver(v); 2881 } 2882 value.put(lhsType, v); 2883 StackValue receiver = StackValue.onStack(lhsType); 2884 2885 invokeMethodWithArguments(call, callable, resolvedCall, receiver); 2886 2887 if (keepReturnValue) { 2888 value.store(callable.getReturnType(), v); 2889 } 2890 } 2891 2892 public void invokeAppend(JetExpression expr) { 2893 if (expr instanceof JetBinaryExpression) { 2894 JetBinaryExpression binaryExpression = (JetBinaryExpression) expr; 2895 if (binaryExpression.getOperationToken() == JetTokens.PLUS) { 2896 JetExpression left = binaryExpression.getLeft(); 2897 JetExpression right = binaryExpression.getRight(); 2898 Type leftType = expressionType(left); 2899 Type rightType = expressionType(right); 2900 2901 if (leftType.equals(JAVA_STRING_TYPE) && rightType.equals(JAVA_STRING_TYPE)) { 2902 invokeAppend(left); 2903 invokeAppend(right); 2904 return; 2905 } 2906 } 2907 } 2908 Type exprType = expressionType(expr); 2909 gen(expr, exprType); 2910 genInvokeAppendMethod(v, exprType.getSort() == Type.ARRAY ? OBJECT_TYPE : exprType); 2911 } 2912 2913 @Nullable 2914 private static JetSimpleNameExpression targetLabel(JetExpression expression) { 2915 if (expression.getParent() instanceof JetLabeledExpression) { 2916 return ((JetLabeledExpression) expression.getParent()).getTargetLabel(); 2917 } 2918 return null; 2919 } 2920 2921 @Override 2922 public StackValue visitLabeledExpression( 2923 @NotNull JetLabeledExpression expression, StackValue receiver 2924 ) { 2925 return genQualified(receiver, expression.getBaseExpression()); 2926 } 2927 2928 @Override 2929 public StackValue visitPrefixExpression(@NotNull JetPrefixExpression expression, StackValue receiver) { 2930 DeclarationDescriptor op = bindingContext.get(REFERENCE_TARGET, expression.getOperationReference()); 2931 assert op instanceof FunctionDescriptor : String.valueOf(op); 2932 Callable callable = resolveToCallable((FunctionDescriptor) op, false); 2933 if (callable instanceof IntrinsicMethod) { 2934 Type returnType = typeMapper.mapType((FunctionDescriptor) op); 2935 ((IntrinsicMethod) callable).generate(this, v, returnType, expression, 2936 Collections.singletonList(expression.getBaseExpression()), receiver); 2937 return StackValue.onStack(returnType); 2938 } 2939 2940 DeclarationDescriptor cls = op.getContainingDeclaration(); 2941 ResolvedCall<?> resolvedCall = resolvedCall(expression.getOperationReference()); 2942 2943 if (isPrimitiveNumberClassDescriptor(cls) || !(op.getName().asString().equals("inc") || op.getName().asString().equals("dec"))) { 2944 Call call = bindingContext.get(CALL, expression.getOperationReference()); 2945 return invokeFunction(call, receiver, resolvedCall); 2946 } 2947 2948 CallableMethod callableMethod = (CallableMethod) callable; 2949 2950 StackValue value = gen(expression.getBaseExpression()); 2951 value.dupReceiver(v); 2952 value.dupReceiver(v); 2953 2954 Type type = expressionType(expression.getBaseExpression()); 2955 value.put(type, v); 2956 callableMethod.invokeWithNotNullAssertion(v, state, resolvedCall); 2957 2958 value.store(callableMethod.getReturnType(), v); 2959 value.put(type, v); 2960 return StackValue.onStack(type); 2961 } 2962 2963 @Override 2964 public StackValue visitPostfixExpression(@NotNull JetPostfixExpression expression, StackValue receiver) { 2965 if (expression.getOperationReference().getReferencedNameElementType() == JetTokens.EXCLEXCL) { 2966 StackValue base = genQualified(receiver, expression.getBaseExpression()); 2967 if (isPrimitive(base.type)) { 2968 return base; 2969 } 2970 base.put(base.type, v); 2971 v.dup(); 2972 Label ok = new Label(); 2973 v.ifnonnull(ok); 2974 v.invokestatic("kotlin/jvm/internal/Intrinsics", "throwNpe", "()V"); 2975 v.mark(ok); 2976 return StackValue.onStack(base.type); 2977 } 2978 2979 DeclarationDescriptor op = bindingContext.get(REFERENCE_TARGET, expression.getOperationReference()); 2980 if (!(op instanceof FunctionDescriptor)) { 2981 throw new UnsupportedOperationException("Don't know how to generate this postfix expression: " + op); 2982 } 2983 2984 Type asmType = expressionType(expression); 2985 DeclarationDescriptor cls = op.getContainingDeclaration(); 2986 2987 int increment; 2988 if (op.getName().asString().equals("inc")) { 2989 increment = 1; 2990 } 2991 else if (op.getName().asString().equals("dec")) { 2992 increment = -1; 2993 } 2994 else { 2995 throw new UnsupportedOperationException("Unsupported postfix operation: " + op); 2996 } 2997 2998 boolean isPrimitiveNumberClassDescriptor = isPrimitiveNumberClassDescriptor(cls); 2999 if (isPrimitiveNumberClassDescriptor) { 3000 JetExpression operand = expression.getBaseExpression(); 3001 if (operand instanceof JetReferenceExpression && asmType == Type.INT_TYPE) { 3002 int index = indexOfLocal((JetReferenceExpression) operand); 3003 if (index >= 0) { 3004 return StackValue.postIncrement(index, increment); 3005 } 3006 } 3007 } 3008 3009 StackValue value = gen(expression.getBaseExpression()); 3010 value.dupReceiver(v); 3011 3012 Type type = expressionType(expression.getBaseExpression()); 3013 value.put(type, v); // old value 3014 3015 pushReceiverAndValueViaDup(value, type); // receiver and new value 3016 3017 Type storeType; 3018 if (isPrimitiveNumberClassDescriptor) { 3019 genIncrement(asmType, increment, v); 3020 storeType = type; 3021 } 3022 else { 3023 ResolvedCall<?> resolvedCall = resolvedCall(expression.getOperationReference()); 3024 Callable callable = resolveToCallable((FunctionDescriptor) op, false); 3025 CallableMethod callableMethod = (CallableMethod) callable; 3026 callableMethod.invokeWithNotNullAssertion(v, state, resolvedCall); 3027 storeType = callableMethod.getReturnType(); 3028 } 3029 3030 value.store(storeType, v); 3031 return StackValue.onStack(asmType); // old value 3032 } 3033 3034 private void pushReceiverAndValueViaDup(StackValue value, Type type) { 3035 switch (value.receiverSize()) { 3036 case 0: 3037 dup(v, type); 3038 break; 3039 3040 case 1: 3041 if (type.getSize() == 2) { 3042 v.dup2X1(); 3043 } 3044 else { 3045 v.dupX1(); 3046 } 3047 break; 3048 3049 case 2: 3050 if (type.getSize() == 2) { 3051 v.dup2X2(); 3052 } 3053 else { 3054 v.dupX2(); 3055 } 3056 break; 3057 3058 case -1: 3059 throw new UnsupportedOperationException(); 3060 } 3061 } 3062 3063 @Override 3064 public StackValue visitProperty(@NotNull JetProperty property, StackValue receiver) { 3065 final JetExpression initializer = property.getInitializer(); 3066 if (initializer == null) { 3067 return StackValue.none(); 3068 } 3069 initializeLocalVariable(property, new Function<VariableDescriptor, Void>() { 3070 @Override 3071 public Void fun(VariableDescriptor descriptor) { 3072 Type varType = asmType(descriptor.getType()); 3073 gen(initializer, varType); 3074 return null; 3075 } 3076 }); 3077 return StackValue.none(); 3078 } 3079 3080 @Override 3081 public StackValue visitMultiDeclaration(@NotNull JetMultiDeclaration multiDeclaration, StackValue receiver) { 3082 JetExpression initializer = multiDeclaration.getInitializer(); 3083 if (initializer == null) return StackValue.none(); 3084 3085 JetType initializerType = bindingContext.get(EXPRESSION_TYPE, initializer); 3086 assert initializerType != null; 3087 3088 Type initializerAsmType = asmType(initializerType); 3089 3090 final TransientReceiver initializerAsReceiver = new TransientReceiver(initializerType); 3091 3092 int tempVarIndex = myFrameMap.enterTemp(initializerAsmType); 3093 3094 gen(initializer, initializerAsmType); 3095 v.store(tempVarIndex, initializerAsmType); 3096 final StackValue.Local local = StackValue.local(tempVarIndex, initializerAsmType); 3097 3098 for (final JetMultiDeclarationEntry variableDeclaration : multiDeclaration.getEntries()) { 3099 initializeLocalVariable(variableDeclaration, new Function<VariableDescriptor, Void>() { 3100 @Override 3101 public Void fun(VariableDescriptor descriptor) { 3102 ResolvedCall<FunctionDescriptor> resolvedCall = bindingContext.get(COMPONENT_RESOLVED_CALL, variableDeclaration); 3103 assert resolvedCall != null : "Resolved call is null for " + variableDeclaration.getText(); 3104 Call call = makeFakeCall(initializerAsReceiver); 3105 invokeFunction(call, local, resolvedCall); 3106 return null; 3107 } 3108 }); 3109 } 3110 3111 if (initializerAsmType.getSort() == Type.OBJECT || initializerAsmType.getSort() == Type.ARRAY) { 3112 v.aconst(null); 3113 v.store(tempVarIndex, initializerAsmType); 3114 } 3115 myFrameMap.leaveTemp(initializerAsmType); 3116 3117 return StackValue.none(); 3118 } 3119 3120 private void initializeLocalVariable( 3121 @NotNull JetVariableDeclaration variableDeclaration, 3122 @NotNull Function<VariableDescriptor, Void> generateInitializer 3123 ) { 3124 VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, variableDeclaration); 3125 3126 if (JetPsiUtil.isScriptDeclaration(variableDeclaration)) { 3127 return; 3128 } 3129 int index = lookupLocalIndex(variableDescriptor); 3130 3131 if (index < 0) { 3132 throw new IllegalStateException("Local variable not found for " + variableDescriptor); 3133 } 3134 3135 Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor); 3136 assert variableDescriptor != null; 3137 3138 Type varType = asmType(variableDescriptor.getType()); 3139 3140 // SCRIPT: Variable at the top of the script is generated as field 3141 if (JetPsiUtil.isScriptDeclaration(variableDeclaration)) { 3142 generateInitializer.fun(variableDescriptor); 3143 JetScript scriptPsi = JetPsiUtil.getScript(variableDeclaration); 3144 assert scriptPsi != null; 3145 Type scriptClassType = asmTypeForScriptPsi(bindingContext, scriptPsi); 3146 v.putfield(scriptClassType.getInternalName(), variableDeclaration.getName(), varType.getDescriptor()); 3147 } 3148 else if (sharedVarType == null) { 3149 generateInitializer.fun(variableDescriptor); 3150 v.store(index, varType); 3151 } 3152 else { 3153 v.load(index, OBJECT_TYPE); 3154 generateInitializer.fun(variableDescriptor); 3155 v.putfield(sharedVarType.getInternalName(), "element", 3156 sharedVarType.equals(OBJECT_REF_TYPE) ? "Ljava/lang/Object;" : varType.getDescriptor()); 3157 } 3158 } 3159 3160 @NotNull 3161 private StackValue generateNewCall( 3162 @NotNull JetCallExpression expression, 3163 @NotNull ResolvedCall<?> resolvedCall, 3164 @NotNull StackValue receiver 3165 ) { 3166 Type type = expressionType(expression); 3167 if (type.getSort() == Type.ARRAY) { 3168 generateNewArray(expression); 3169 return StackValue.onStack(type); 3170 } 3171 3172 return generateConstructorCall(resolvedCall, receiver, type); 3173 } 3174 3175 @NotNull 3176 private StackValue generateConstructorCall(@NotNull ResolvedCall<?> resolvedCall, @NotNull StackValue receiver, @NotNull Type type) { 3177 v.anew(type); 3178 v.dup(); 3179 3180 receiver = StackValue.receiver(resolvedCall, receiver, this, null); 3181 receiver.put(receiver.type, v); 3182 3183 ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor(); 3184 MutableClosure closure = bindingContext.get(CLOSURE, constructorDescriptor.getContainingDeclaration()); 3185 3186 //Resolved call to local class constructor doesn't have resolvedCall.getThisObject() and resolvedCall.getReceiverArgument() 3187 //so we need generate closure on stack 3188 //See StackValue.receiver for more info 3189 pushClosureOnStack(closure, resolvedCall.getThisObject().exists() || resolvedCall.getReceiverArgument().exists(), 3190 defaultCallGenerator); 3191 3192 ConstructorDescriptor originalOfSamAdapter = (ConstructorDescriptor) SamCodegenUtil.getOriginalIfSamAdapter(constructorDescriptor); 3193 CallableMethod method = typeMapper.mapToCallableMethod(originalOfSamAdapter == null ? constructorDescriptor : originalOfSamAdapter); 3194 invokeMethodWithArguments(null, method, resolvedCall, StackValue.none()); 3195 3196 return StackValue.onStack(type); 3197 } 3198 3199 public void generateNewArray(@NotNull JetCallExpression expression) { 3200 JetType arrayType = bindingContext.get(EXPRESSION_TYPE, expression); 3201 assert arrayType != null : "Array instantiation isn't type checked: " + expression.getText(); 3202 3203 generateNewArray(expression, arrayType); 3204 } 3205 3206 private void generateNewArray(@NotNull JetCallExpression expression, @NotNull JetType arrayType) { 3207 List<JetExpression> args = new ArrayList<JetExpression>(); 3208 for (ValueArgument va : expression.getValueArguments()) { 3209 args.add(va.getArgumentExpression()); 3210 } 3211 args.addAll(expression.getFunctionLiteralArguments()); 3212 3213 boolean isArray = KotlinBuiltIns.getInstance().isArray(arrayType); 3214 if (!isArray && args.size() != 1) { 3215 throw new CompilationException("primitive array constructor requires one argument", null, expression); 3216 } 3217 3218 if (isArray) { 3219 gen(args.get(0), Type.INT_TYPE); 3220 v.newarray(boxType(asmType(arrayType.getArguments().get(0).getType()))); 3221 } 3222 else { 3223 Type type = typeMapper.mapType(arrayType); 3224 gen(args.get(0), Type.INT_TYPE); 3225 v.newarray(correctElementType(type)); 3226 } 3227 3228 if (args.size() == 2) { 3229 int sizeIndex = myFrameMap.enterTemp(Type.INT_TYPE); 3230 int indexIndex = myFrameMap.enterTemp(Type.INT_TYPE); 3231 3232 v.dup(); 3233 v.arraylength(); 3234 v.store(sizeIndex, Type.INT_TYPE); 3235 3236 v.iconst(0); 3237 v.store(indexIndex, Type.INT_TYPE); 3238 3239 gen(args.get(1), FUNCTION1_TYPE); 3240 3241 Label begin = new Label(); 3242 Label end = new Label(); 3243 v.visitLabel(begin); 3244 v.load(indexIndex, Type.INT_TYPE); 3245 v.load(sizeIndex, Type.INT_TYPE); 3246 v.ificmpge(end); 3247 3248 v.dup2(); 3249 v.load(indexIndex, Type.INT_TYPE); 3250 v.invokestatic("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;"); 3251 v.invokeinterface(FUNCTION1_TYPE.getInternalName(), "invoke", "(Ljava/lang/Object;)Ljava/lang/Object;"); 3252 v.load(indexIndex, Type.INT_TYPE); 3253 v.iinc(indexIndex, 1); 3254 v.swap(); 3255 v.astore(OBJECT_TYPE); 3256 3257 v.goTo(begin); 3258 v.visitLabel(end); 3259 v.pop(); 3260 3261 myFrameMap.leaveTemp(Type.INT_TYPE); 3262 myFrameMap.leaveTemp(Type.INT_TYPE); 3263 } 3264 } 3265 3266 @Override 3267 public StackValue visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression, StackValue receiver) { 3268 JetExpression array = expression.getArrayExpression(); 3269 JetType type = bindingContext.get(EXPRESSION_TYPE, array); 3270 Type arrayType = expressionType(array); 3271 List<JetExpression> indices = expression.getIndexExpressions(); 3272 FunctionDescriptor operationDescriptor = (FunctionDescriptor) bindingContext.get(REFERENCE_TARGET, expression); 3273 assert operationDescriptor != null; 3274 if (arrayType.getSort() == Type.ARRAY && 3275 indices.size() == 1 && 3276 operationDescriptor.getValueParameters().get(0).getType().equals(KotlinBuiltIns.getInstance().getIntType())) { 3277 gen(array, arrayType); 3278 for (JetExpression index : indices) { 3279 gen(index, Type.INT_TYPE); 3280 } 3281 assert type != null; 3282 if (KotlinBuiltIns.getInstance().isArray(type)) { 3283 JetType elementType = type.getArguments().get(0).getType(); 3284 return StackValue.arrayElement(boxType(asmType(elementType))); 3285 } 3286 else { 3287 return StackValue.arrayElement(correctElementType(arrayType)); 3288 } 3289 } 3290 else { 3291 ResolvedCall<FunctionDescriptor> resolvedSetCall = bindingContext.get(INDEXED_LVALUE_SET, expression); 3292 ResolvedCall<FunctionDescriptor> resolvedGetCall = bindingContext.get(INDEXED_LVALUE_GET, expression); 3293 3294 boolean isGetter = "get".equals(operationDescriptor.getName().asString()); 3295 3296 ResolvedCall<FunctionDescriptor> resolvedCall = isGetter ? resolvedGetCall : resolvedSetCall; 3297 assert resolvedCall != null : "couldn't find resolved call: " + expression.getText(); 3298 3299 Callable callable = resolveToCallable(operationDescriptor, false); 3300 Method asmMethod = resolveToCallableMethod(operationDescriptor, false, context).getAsmMethod(); 3301 Type[] argumentTypes = asmMethod.getArgumentTypes(); 3302 3303 if (callable instanceof CallableMethod) { 3304 boolean skipLast = !isGetter; 3305 pushMethodArgumentsWithCallReceiver(receiver, resolvedCall, (CallableMethod) callable, skipLast, defaultCallGenerator); 3306 } 3307 else { 3308 gen(array, arrayType); // intrinsic method 3309 3310 int index = operationDescriptor.getReceiverParameter() != null ? 1 : 0; 3311 3312 for (JetExpression jetExpression : expression.getIndexExpressions()) { 3313 gen(jetExpression, argumentTypes[index]); 3314 index++; 3315 } 3316 } 3317 3318 Type elementType = isGetter ? asmMethod.getReturnType() : ArrayUtil.getLastElement(argumentTypes); 3319 return StackValue.collectionElement(elementType, resolvedGetCall, resolvedSetCall, this, state); 3320 } 3321 } 3322 3323 @Override 3324 public StackValue visitThrowExpression(@NotNull JetThrowExpression expression, StackValue receiver) { 3325 gen(expression.getThrownExpression(), JAVA_THROWABLE_TYPE); 3326 v.athrow(); 3327 return StackValue.none(); 3328 } 3329 3330 @Override 3331 public StackValue visitThisExpression(@NotNull JetThisExpression expression, StackValue receiver) { 3332 DeclarationDescriptor descriptor = bindingContext.get(REFERENCE_TARGET, expression.getInstanceReference()); 3333 if (descriptor instanceof ClassDescriptor) { 3334 return StackValue.thisOrOuter(this, (ClassDescriptor) descriptor, false, true); 3335 } 3336 else { 3337 if (descriptor instanceof CallableDescriptor) { 3338 return generateReceiver(descriptor); 3339 } 3340 throw new UnsupportedOperationException("neither this nor receiver"); 3341 } 3342 } 3343 3344 @Override 3345 public StackValue visitTryExpression(@NotNull JetTryExpression expression, StackValue receiver) { 3346 return generateTryExpression(expression, false); 3347 } 3348 3349 public StackValue generateTryExpression(JetTryExpression expression, boolean isStatement) { 3350 /* 3351 The "returned" value of try expression with no finally is either the last expression in the try block or the last expression in the catch block 3352 (or blocks). 3353 */ 3354 JetFinallySection finallyBlock = expression.getFinallyBlock(); 3355 FinallyBlockStackElement finallyBlockStackElement = null; 3356 if (finallyBlock != null) { 3357 finallyBlockStackElement = new FinallyBlockStackElement(expression); 3358 blockStackElements.push(finallyBlockStackElement); 3359 } 3360 3361 JetType jetType = bindingContext.get(EXPRESSION_TYPE, expression); 3362 assert jetType != null; 3363 Type expectedAsmType = isStatement ? Type.VOID_TYPE : asmType(jetType); 3364 3365 Label tryStart = new Label(); 3366 v.mark(tryStart); 3367 v.nop(); // prevent verify error on empty try 3368 3369 gen(expression.getTryBlock(), expectedAsmType); 3370 3371 int savedValue = -1; 3372 if (!isStatement) { 3373 savedValue = myFrameMap.enterTemp(expectedAsmType); 3374 v.store(savedValue, expectedAsmType); 3375 } 3376 3377 Label tryEnd = new Label(); 3378 v.mark(tryEnd); 3379 3380 //do it before finally block generation 3381 List<Label> tryBlockRegions = getCurrentCatchIntervals(finallyBlockStackElement, tryStart, tryEnd); 3382 3383 Label end = new Label(); 3384 3385 genFinallyBlockOrGoto(finallyBlockStackElement, end); 3386 3387 List<JetCatchClause> clauses = expression.getCatchClauses(); 3388 for (int i = 0, size = clauses.size(); i < size; i++) { 3389 JetCatchClause clause = clauses.get(i); 3390 3391 Label clauseStart = new Label(); 3392 v.mark(clauseStart); 3393 3394 VariableDescriptor descriptor = bindingContext.get(VALUE_PARAMETER, clause.getCatchParameter()); 3395 assert descriptor != null; 3396 Type descriptorType = asmType(descriptor.getType()); 3397 myFrameMap.enter(descriptor, descriptorType); 3398 int index = lookupLocalIndex(descriptor); 3399 v.store(index, descriptorType); 3400 3401 gen(clause.getCatchBody(), expectedAsmType); 3402 3403 if (!isStatement) { 3404 v.store(savedValue, expectedAsmType); 3405 } 3406 3407 myFrameMap.leave(descriptor); 3408 3409 genFinallyBlockOrGoto(finallyBlockStackElement, i != size - 1 || finallyBlock != null ? end : null); 3410 3411 generateExceptionTable(clauseStart, tryBlockRegions, descriptorType.getInternalName()); 3412 } 3413 3414 3415 //for default catch clause 3416 if (finallyBlock != null) { 3417 Label defaultCatchStart = new Label(); 3418 v.mark(defaultCatchStart); 3419 int savedException = myFrameMap.enterTemp(JAVA_THROWABLE_TYPE); 3420 v.store(savedException, JAVA_THROWABLE_TYPE); 3421 Label defaultCatchEnd = new Label(); 3422 v.mark(defaultCatchEnd); 3423 3424 //do it before finally block generation 3425 //javac also generates entry in exception table for default catch clause too!!!! so defaultCatchEnd as end parameter 3426 List<Label> defaultCatchRegions = getCurrentCatchIntervals(finallyBlockStackElement, tryStart, defaultCatchEnd); 3427 3428 3429 genFinallyBlockOrGoto(finallyBlockStackElement, null); 3430 3431 v.load(savedException, JAVA_THROWABLE_TYPE); 3432 myFrameMap.leaveTemp(JAVA_THROWABLE_TYPE); 3433 3434 v.athrow(); 3435 3436 generateExceptionTable(defaultCatchStart, defaultCatchRegions, null); 3437 } 3438 3439 markLineNumber(expression); 3440 v.mark(end); 3441 3442 if (!isStatement) { 3443 v.load(savedValue, expectedAsmType); 3444 myFrameMap.leaveTemp(expectedAsmType); 3445 } 3446 3447 if (finallyBlock != null) { 3448 blockStackElements.pop(); 3449 } 3450 3451 return StackValue.onStack(expectedAsmType); 3452 } 3453 3454 private void generateExceptionTable(@NotNull Label catchStart, @NotNull List<Label> catchedRegions, @Nullable String exception) { 3455 for (int i = 0; i < catchedRegions.size(); i += 2) { 3456 Label startRegion = catchedRegions.get(i); 3457 Label endRegion = catchedRegions.get(i+1); 3458 v.visitTryCatchBlock(startRegion, endRegion, catchStart, exception); 3459 } 3460 } 3461 3462 @NotNull 3463 private static List<Label> getCurrentCatchIntervals( 3464 @Nullable FinallyBlockStackElement finallyBlockStackElement, 3465 @NotNull Label blockStart, 3466 @NotNull Label blockEnd 3467 ) { 3468 List<Label> gapsInBlock = 3469 finallyBlockStackElement != null ? new ArrayList<Label>(finallyBlockStackElement.gaps) : Collections.<Label>emptyList(); 3470 assert gapsInBlock.size() % 2 == 0; 3471 List<Label> blockRegions = new ArrayList<Label>(gapsInBlock.size() + 2); 3472 blockRegions.add(blockStart); 3473 blockRegions.addAll(gapsInBlock); 3474 blockRegions.add(blockEnd); 3475 return blockRegions; 3476 } 3477 3478 @Override 3479 public StackValue visitBinaryWithTypeRHSExpression(@NotNull JetBinaryExpressionWithTypeRHS expression, StackValue receiver) { 3480 JetSimpleNameExpression operationSign = expression.getOperationReference(); 3481 IElementType opToken = operationSign.getReferencedNameElementType(); 3482 if (opToken == JetTokens.COLON) { 3483 return gen(expression.getLeft()); 3484 } 3485 else { 3486 JetTypeReference typeReference = expression.getRight(); 3487 JetType rightType = bindingContext.get(TYPE, typeReference); 3488 assert rightType != null; 3489 Type rightTypeAsm = boxType(asmType(rightType)); 3490 JetExpression left = expression.getLeft(); 3491 DeclarationDescriptor descriptor = rightType.getConstructor().getDeclarationDescriptor(); 3492 if (descriptor instanceof ClassDescriptor || descriptor instanceof TypeParameterDescriptor) { 3493 StackValue value = genQualified(receiver, left); 3494 value.put(boxType(value.type), v); 3495 3496 if (opToken != JetTokens.AS_SAFE) { 3497 if (!JvmCodegenUtil.isNullableType(rightType)) { 3498 v.dup(); 3499 Label nonnull = new Label(); 3500 v.ifnonnull(nonnull); 3501 JetType leftType = bindingContext.get(EXPRESSION_TYPE, left); 3502 assert leftType != null; 3503 throwNewException("kotlin/TypeCastException", DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(leftType) + 3504 " cannot be cast to " + 3505 DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(rightType)); 3506 v.mark(nonnull); 3507 } 3508 } 3509 else { 3510 v.dup(); 3511 v.instanceOf(rightTypeAsm); 3512 Label ok = new Label(); 3513 v.ifne(ok); 3514 v.pop(); 3515 v.aconst(null); 3516 v.mark(ok); 3517 } 3518 3519 v.checkcast(rightTypeAsm); 3520 return StackValue.onStack(rightTypeAsm); 3521 } 3522 else { 3523 throw new UnsupportedOperationException("Don't know how to handle non-class types in as/as? : " + descriptor); 3524 } 3525 } 3526 } 3527 3528 @Override 3529 public StackValue visitIsExpression(@NotNull JetIsExpression expression, StackValue receiver) { 3530 StackValue match = StackValue.expression(OBJECT_TYPE, expression.getLeftHandSide(), this); 3531 return generateIsCheck(match, expression.getTypeRef(), expression.isNegated()); 3532 } 3533 3534 private StackValue generateExpressionMatch(StackValue expressionToMatch, JetExpression patternExpression) { 3535 if (expressionToMatch != null) { 3536 Type subjectType = expressionToMatch.type; 3537 expressionToMatch.put(subjectType, v); 3538 JetType condJetType = bindingContext.get(EXPRESSION_TYPE, patternExpression); 3539 Type condType; 3540 if (isNumberPrimitive(subjectType) || subjectType.getSort() == Type.BOOLEAN) { 3541 assert condJetType != null; 3542 condType = asmType(condJetType); 3543 if (!(isNumberPrimitive(condType) || condType.getSort() == Type.BOOLEAN)) { 3544 subjectType = boxType(subjectType); 3545 expressionToMatch.coerceTo(subjectType, v); 3546 } 3547 } 3548 else { 3549 condType = OBJECT_TYPE; 3550 } 3551 gen(patternExpression, condType); 3552 return genEqualsForExpressionsOnStack(v, JetTokens.EQEQ, subjectType, condType); 3553 } 3554 else { 3555 return gen(patternExpression); 3556 } 3557 } 3558 3559 private StackValue generateIsCheck(StackValue expressionToMatch, JetTypeReference typeReference, boolean negated) { 3560 JetType jetType = bindingContext.get(TYPE, typeReference); 3561 generateInstanceOf(expressionToMatch, jetType, false); 3562 StackValue value = StackValue.onStack(Type.BOOLEAN_TYPE); 3563 return negated ? StackValue.not(value) : value; 3564 } 3565 3566 private void generateInstanceOf(StackValue expressionToGen, JetType jetType, boolean leaveExpressionOnStack) { 3567 expressionToGen.put(OBJECT_TYPE, v); 3568 if (leaveExpressionOnStack) { 3569 v.dup(); 3570 } 3571 Type type = boxType(asmType(jetType)); 3572 if (jetType.isNullable()) { 3573 Label nope = new Label(); 3574 Label end = new Label(); 3575 3576 v.dup(); 3577 v.ifnull(nope); 3578 v.instanceOf(type); 3579 v.goTo(end); 3580 v.mark(nope); 3581 v.pop(); 3582 v.iconst(1); 3583 v.mark(end); 3584 } 3585 else { 3586 v.instanceOf(type); 3587 } 3588 } 3589 3590 @Override 3591 public StackValue visitWhenExpression(@NotNull JetWhenExpression expression, StackValue receiver) { 3592 return generateWhenExpression(expression, false); 3593 } 3594 3595 public StackValue generateWhenExpression(JetWhenExpression expression, boolean isStatement) { 3596 JetExpression expr = expression.getSubjectExpression(); 3597 Type subjectType = expressionType(expr); 3598 3599 Type resultType = isStatement ? Type.VOID_TYPE : expressionType(expression); 3600 3601 if (canSwitchBeUsedIn(expression, subjectType)) { 3602 return generateSwitch(expression, subjectType, resultType, isStatement); 3603 } 3604 3605 int subjectLocal = expr != null ? myFrameMap.enterTemp(subjectType) : -1; 3606 if (subjectLocal != -1) { 3607 gen(expr, subjectType); 3608 tempVariables.put(expr, StackValue.local(subjectLocal, subjectType)); 3609 v.store(subjectLocal, subjectType); 3610 } 3611 3612 Label end = new Label(); 3613 boolean hasElse = JetPsiUtil.checkWhenExpressionHasSingleElse(expression); 3614 3615 Label nextCondition = null; 3616 for (JetWhenEntry whenEntry : expression.getEntries()) { 3617 if (nextCondition != null) { 3618 v.mark(nextCondition); 3619 } 3620 nextCondition = new Label(); 3621 FrameMap.Mark mark = myFrameMap.mark(); 3622 Label thisEntry = new Label(); 3623 if (!whenEntry.isElse()) { 3624 JetWhenCondition[] conditions = whenEntry.getConditions(); 3625 for (int i = 0; i < conditions.length; i++) { 3626 StackValue conditionValue = generateWhenCondition(subjectType, subjectLocal, conditions[i]); 3627 conditionValue.condJump(nextCondition, true, v); 3628 if (i < conditions.length - 1) { 3629 v.goTo(thisEntry); 3630 v.mark(nextCondition); 3631 nextCondition = new Label(); 3632 } 3633 } 3634 } 3635 3636 v.visitLabel(thisEntry); 3637 gen(whenEntry.getExpression(), resultType); 3638 mark.dropTo(); 3639 if (!whenEntry.isElse()) { 3640 v.goTo(end); 3641 } 3642 } 3643 if (!hasElse && nextCondition != null) { 3644 v.mark(nextCondition); 3645 if (!isStatement) { 3646 putUnitInstanceOntoStackForNonExhaustiveWhen(expression); 3647 } 3648 } 3649 3650 markLineNumber(expression); 3651 v.mark(end); 3652 3653 myFrameMap.leaveTemp(subjectType); 3654 tempVariables.remove(expr); 3655 return StackValue.onStack(resultType); 3656 } 3657 3658 private void putUnitInstanceOntoStackForNonExhaustiveWhen(@NotNull JetWhenExpression expression) { 3659 if (Boolean.TRUE.equals(bindingContext.get(EXHAUSTIVE_WHEN, expression))) { 3660 // when() is supposed to be exhaustive 3661 throwNewException("kotlin/NoWhenBranchMatchedException"); 3662 } 3663 else { 3664 // non-exhaustive when() with no else -> Unit must be expected 3665 StackValue.putUnitInstance(v); 3666 } 3667 } 3668 3669 private StackValue generateWhenCondition(Type subjectType, int subjectLocal, JetWhenCondition condition) { 3670 if (condition instanceof JetWhenConditionInRange) { 3671 JetWhenConditionInRange conditionInRange = (JetWhenConditionInRange) condition; 3672 return generateIn(StackValue.local(subjectLocal, subjectType), 3673 conditionInRange.getRangeExpression(), 3674 conditionInRange.getOperationReference()); 3675 } 3676 StackValue.Local match = subjectLocal == -1 ? null : StackValue.local(subjectLocal, subjectType); 3677 if (condition instanceof JetWhenConditionIsPattern) { 3678 JetWhenConditionIsPattern patternCondition = (JetWhenConditionIsPattern) condition; 3679 return generateIsCheck(match, patternCondition.getTypeRef(), patternCondition.isNegated()); 3680 } 3681 else if (condition instanceof JetWhenConditionWithExpression) { 3682 JetExpression patternExpression = ((JetWhenConditionWithExpression) condition).getExpression(); 3683 return generateExpressionMatch(match, patternExpression); 3684 } 3685 else { 3686 throw new UnsupportedOperationException("unsupported kind of when condition"); 3687 } 3688 } 3689 3690 private StackValue generateSwitch(@NotNull JetWhenExpression expression, @NotNull Type subjectType, @NotNull Type resultType, boolean isStatement) { 3691 JetType subjectJetType = bindingContext.get(EXPRESSION_TYPE, expression.getSubjectExpression()); 3692 assert subjectJetType != null : "Subject expression in when should not be null"; 3693 3694 Map<Integer, Label> transitions = Maps.newTreeMap(); 3695 3696 Label[] entryLabels = new Label[expression.getEntries().size()]; 3697 int entryLabelsCounter = 0; 3698 3699 Label elseLabel = new Label(); 3700 Label endLabel = new Label(); 3701 boolean hasElse = expression.getElseExpression() != null; 3702 3703 for (JetWhenEntry entry : expression.getEntries()) { 3704 Label entryLabel = new Label(); 3705 3706 for (JetWhenCondition condition : entry.getConditions()) { 3707 assert condition instanceof JetWhenConditionWithExpression : "Condition should be instance of JetWhenConditionWithExpression"; 3708 3709 JetExpression conditionExpression = ((JetWhenConditionWithExpression) condition).getExpression(); 3710 assert conditionExpression != null : "Condition expression in when should not be bull"; 3711 3712 CompileTimeConstant constant = getCompileTimeConstant(conditionExpression, bindingContext); 3713 assert doesConstantFitForSwitch(constant) : "Condition should be a constant in when for generating switch-instruction"; 3714 3715 int value = (constant.getValue() instanceof Number) 3716 ? ((Number) constant.getValue()).intValue() 3717 : ((Character) constant.getValue()).charValue(); 3718 3719 if (!transitions.containsKey(value)) { 3720 transitions.put(value, entryLabel); 3721 } 3722 } 3723 3724 if (entry.isElse()) { 3725 elseLabel = entryLabel; 3726 } 3727 3728 entryLabels[entryLabelsCounter++] = entryLabel; 3729 } 3730 3731 gen(expression.getSubjectExpression(), subjectType); 3732 generateSwitchInstructionByTransitionsTable( 3733 transitions, 3734 //if there is no else-entry and it's statement then default --- endLabel 3735 (hasElse || !isStatement) ? elseLabel : endLabel 3736 ); 3737 3738 //resolving entries' labels 3739 int i = 0; 3740 for (JetWhenEntry entry : expression.getEntries()) { 3741 v.visitLabel(entryLabels[i++]); 3742 3743 FrameMap.Mark mark = myFrameMap.mark(); 3744 gen(entry.getExpression(), resultType); 3745 mark.dropTo(); 3746 3747 if (!entry.isElse()) { 3748 v.goTo(endLabel); 3749 } 3750 } 3751 3752 //there is no else-entry but this is not statement, so we should return Unit 3753 if (!hasElse && !isStatement) { 3754 v.visitLabel(elseLabel); 3755 putUnitInstanceOntoStackForNonExhaustiveWhen(expression); 3756 } 3757 3758 markLineNumber(expression); 3759 v.mark(endLabel); 3760 3761 return StackValue.onStack(resultType); 3762 } 3763 3764 private void generateSwitchInstructionByTransitionsTable(@NotNull Map<Integer, Label> transitions, @NotNull Label defaultLabel) { 3765 int[] keys = new int[transitions.size()]; 3766 Label[] labels = new Label[transitions.size()]; 3767 int i = 0; 3768 3769 for (Map.Entry<Integer, Label> transition : transitions.entrySet()) { 3770 keys[i] = transition.getKey(); 3771 labels[i] = transition.getValue(); 3772 3773 i++; 3774 } 3775 3776 int nlabels = keys.length; 3777 int hi = keys[nlabels - 1]; 3778 int lo = keys[0]; 3779 3780 /* 3781 * Heuristic estimation if it's better to use tableswitch or lookupswitch. 3782 * From OpenJDK sources 3783 */ 3784 long table_space_cost = 4 + ((long) hi - lo + 1); // words 3785 long table_time_cost = 3; // comparisons 3786 long lookup_space_cost = 3 + 2 * (long) nlabels; 3787 long lookup_time_cost = nlabels; 3788 3789 boolean useTableSwitch = nlabels > 0 && 3790 table_space_cost + 3 * table_time_cost <= 3791 lookup_space_cost + 3 * lookup_time_cost; 3792 3793 if (!useTableSwitch) { 3794 v.lookupswitch(defaultLabel, keys, labels); 3795 return; 3796 } 3797 3798 Label[] sparseLabels = new Label[hi - lo + 1]; 3799 Arrays.fill(sparseLabels, defaultLabel); 3800 3801 for (i = 0; i < keys.length; i++) { 3802 sparseLabels[keys[i] - lo] = labels[i]; 3803 } 3804 3805 v.tableswitch(lo, hi, defaultLabel, sparseLabels); 3806 } 3807 3808 private static boolean doesConstantFitForSwitch(@Nullable CompileTimeConstant constant) { 3809 return (constant instanceof IntegerValueConstant); 3810 } 3811 3812 private boolean canSwitchBeUsedIn(@NotNull JetWhenExpression expression, @NotNull Type subjectType) { 3813 int typeSort = subjectType.getSort(); 3814 3815 if (typeSort != Type.INT && typeSort != Type.CHAR && typeSort != Type.SHORT && typeSort != Type.BYTE) { 3816 return false; 3817 } 3818 3819 for (JetWhenEntry entry : expression.getEntries()) { 3820 for (JetWhenCondition condition : entry.getConditions()) { 3821 if (!(condition instanceof JetWhenConditionWithExpression)) { 3822 return false; 3823 } 3824 3825 //ensure that expression is constant 3826 JetExpression patternExpression = ((JetWhenConditionWithExpression) condition).getExpression(); 3827 3828 assert patternExpression != null : "expression in when should not be null"; 3829 3830 CompileTimeConstant constant = getCompileTimeConstant(patternExpression, bindingContext); 3831 if (!doesConstantFitForSwitch(constant)) { 3832 return false; 3833 } 3834 } 3835 } 3836 3837 return true; 3838 } 3839 3840 private boolean isIntRangeExpr(JetExpression rangeExpression) { 3841 if (rangeExpression instanceof JetBinaryExpression) { 3842 JetBinaryExpression binaryExpression = (JetBinaryExpression) rangeExpression; 3843 if (binaryExpression.getOperationReference().getReferencedNameElementType() == JetTokens.RANGE) { 3844 JetType jetType = bindingContext.get(EXPRESSION_TYPE, rangeExpression); 3845 assert jetType != null; 3846 DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor(); 3847 return INTEGRAL_RANGES.contains(descriptor); 3848 } 3849 } 3850 return false; 3851 } 3852 3853 private void throwNewException(@NotNull String className) { 3854 throwNewException(className, null); 3855 } 3856 3857 private void throwNewException(@NotNull String className, @Nullable String message) { 3858 v.anew(Type.getObjectType(className)); 3859 v.dup(); 3860 if (message != null) { 3861 v.visitLdcInsn(message); 3862 v.invokespecial(className, "<init>", "(Ljava/lang/String;)V"); 3863 } 3864 else { 3865 v.invokespecial(className, "<init>", "()V"); 3866 } 3867 v.athrow(); 3868 } 3869 3870 private Call makeFakeCall(ReceiverValue initializerAsReceiver) { 3871 JetSimpleNameExpression fake = JetPsiFactory.createSimpleName(state.getProject(), "fake"); 3872 return CallMaker.makeCall(fake, initializerAsReceiver); 3873 } 3874 3875 @Override 3876 public String toString() { 3877 return context.getContextDescriptor().toString(); 3878 } 3879 3880 @NotNull 3881 public FrameMap getFrameMap() { 3882 return myFrameMap; 3883 } 3884 3885 @NotNull 3886 public MethodContext getContext() { 3887 return context; 3888 } 3889 3890 @NotNull 3891 public NameGenerator getInlineNameGenerator() { 3892 NameGenerator nameGenerator = getParentCodegen().getInlineNameGenerator(); 3893 Name name = context.getContextDescriptor().getName(); 3894 return nameGenerator.subGenerator((name.isSpecial() ? "$special" : name.asString()) + "$$inlined" ); 3895 } 3896 }