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