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