001 /* 002 * Copyright 2010-2013 JetBrains s.r.o. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.jetbrains.jet.codegen; 018 019 import com.google.common.collect.Lists; 020 import com.google.common.collect.Maps; 021 import com.intellij.openapi.editor.Document; 022 import com.intellij.openapi.progress.ProcessCanceledException; 023 import com.intellij.psi.PsiElement; 024 import com.intellij.psi.tree.IElementType; 025 import com.intellij.util.ArrayUtil; 026 import com.intellij.util.Function; 027 import com.intellij.util.containers.Stack; 028 import org.jetbrains.annotations.NotNull; 029 import org.jetbrains.annotations.Nullable; 030 import org.jetbrains.asm4.Label; 031 import org.jetbrains.asm4.MethodVisitor; 032 import org.jetbrains.asm4.Type; 033 import org.jetbrains.asm4.commons.InstructionAdapter; 034 import org.jetbrains.asm4.commons.Method; 035 import org.jetbrains.jet.codegen.binding.CalculatedClosure; 036 import org.jetbrains.jet.codegen.binding.CodegenBinding; 037 import org.jetbrains.jet.codegen.binding.MutableClosure; 038 import org.jetbrains.jet.codegen.context.*; 039 import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethod; 040 import org.jetbrains.jet.codegen.signature.JvmMethodSignature; 041 import org.jetbrains.jet.codegen.state.GenerationState; 042 import org.jetbrains.jet.codegen.state.JetTypeMapper; 043 import org.jetbrains.jet.lang.descriptors.*; 044 import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; 045 import org.jetbrains.jet.lang.evaluate.EvaluatePackage; 046 import org.jetbrains.jet.lang.psi.*; 047 import org.jetbrains.jet.lang.resolve.BindingContext; 048 import org.jetbrains.jet.lang.resolve.DescriptorUtils; 049 import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastReceiver; 050 import org.jetbrains.jet.lang.resolve.calls.model.*; 051 import org.jetbrains.jet.lang.resolve.calls.util.CallMaker; 052 import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor; 053 import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; 054 import org.jetbrains.jet.lang.resolve.constants.IntegerValueTypeConstant; 055 import org.jetbrains.jet.lang.resolve.constants.IntegerValueTypeConstructor; 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 083 private static final String CLASS_NO_PATTERN_MATCHED_EXCEPTION = "jet/NoPatternMatchedException"; 084 private static final String CLASS_TYPE_CAST_EXCEPTION = "jet/TypeCastException"; 085 public static final Set<DeclarationDescriptor> INTEGRAL_RANGES = KotlinBuiltIns.getInstance().getIntegralRanges(); 086 087 private int myLastLineNumber = -1; 088 089 final InstructionAdapter v; 090 final MethodVisitor methodVisitor; 091 final FrameMap myFrameMap; 092 final JetTypeMapper typeMapper; 093 094 private final GenerationState state; 095 private final Type returnType; 096 097 private final BindingContext bindingContext; 098 final MethodContext context; 099 private final CodegenStatementVisitor statementVisitor; 100 101 private final Stack<BlockStackElement> blockStackElements = new Stack<BlockStackElement>(); 102 103 @Nullable 104 private final MemberCodegen parentCodegen; 105 106 /* 107 * When we create a temporary variable to hold some value not to compute it many times 108 * we put it into this map to emit access to that variable instead of evaluating the whole expression 109 */ 110 private final Map<JetElement, StackValue.Local> tempVariables = Maps.newHashMap(); 111 @NotNull 112 private final TailRecursionCodegen tailRecursionCodegen; 113 114 public CalculatedClosure generateObjectLiteral(GenerationState state, JetObjectLiteralExpression literal) { 115 JetObjectDeclaration objectDeclaration = literal.getObjectDeclaration(); 116 117 Type asmType = asmTypeForAnonymousClass(bindingContext, objectDeclaration); 118 ClassBuilder classBuilder = state.getFactory().newVisitor(asmType, literal.getContainingFile()); 119 120 ClassDescriptor classDescriptor = bindingContext.get(CLASS, objectDeclaration); 121 assert classDescriptor != null; 122 123 //noinspection SuspiciousMethodCalls 124 CalculatedClosure closure = bindingContext.get(CLOSURE, classDescriptor); 125 126 ClassContext objectContext = context.intoAnonymousClass(classDescriptor, this); 127 ImplementationBodyCodegen implementationBodyCodegen = 128 new ImplementationBodyCodegen(objectDeclaration, objectContext, classBuilder, state, getParentCodegen()); 129 130 implementationBodyCodegen.generate(); 131 132 return closure; 133 } 134 135 static class BlockStackElement { 136 } 137 138 static class LoopBlockStackElement extends BlockStackElement { 139 final Label continueLabel; 140 final Label breakLabel; 141 public final JetSimpleNameExpression targetLabel; 142 143 LoopBlockStackElement(Label breakLabel, Label continueLabel, JetSimpleNameExpression targetLabel) { 144 this.breakLabel = breakLabel; 145 this.continueLabel = continueLabel; 146 this.targetLabel = targetLabel; 147 } 148 } 149 150 static class FinallyBlockStackElement extends BlockStackElement { 151 List<Label> gaps = new ArrayList<Label>(); 152 153 final JetTryExpression expression; 154 155 FinallyBlockStackElement(JetTryExpression expression) { 156 this.expression = expression; 157 } 158 159 private void addGapLabel(Label label){ 160 gaps.add(label); 161 } 162 } 163 164 public ExpressionCodegen( 165 @NotNull MethodVisitor v, 166 @NotNull FrameMap myMap, 167 @NotNull Type returnType, 168 @NotNull MethodContext context, 169 @NotNull GenerationState state, 170 @Nullable MemberCodegen parentCodegen 171 ) { 172 this.myFrameMap = myMap; 173 this.parentCodegen = parentCodegen; 174 this.typeMapper = state.getTypeMapper(); 175 this.returnType = returnType; 176 this.state = state; 177 this.methodVisitor = v; 178 this.v = new InstructionAdapter(methodVisitor); 179 this.bindingContext = state.getBindingContext(); 180 this.context = context; 181 this.statementVisitor = new CodegenStatementVisitor(this); 182 this.tailRecursionCodegen = new TailRecursionCodegen(context, this, this.v, state); 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); 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("jet/runtime/ProgressionUtil", "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(JET_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.getCompileTimeConstantForNumberType((IntegerValueTypeConstructor) compileTimeValue.getValue(), 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, closure); 1332 1333 Type type = bindingContext.get(ASM_TYPE, constructorDescriptor.getContainingDeclaration()); 1334 assert type != null; 1335 1336 v.anew(type); 1337 v.dup(); 1338 Method cons = constructor.getSignature().getAsmMethod(); 1339 1340 pushClosureOnStack(closure, false); 1341 1342 JetDelegatorToSuperCall superCall = closure.getSuperCall(); 1343 if (superCall != null) { 1344 ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, 1345 superCall 1346 .getCalleeExpression() 1347 .getConstructorReferenceExpression()); 1348 assert superConstructor != null; 1349 //noinspection SuspiciousMethodCalls 1350 CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor); 1351 Type[] argumentTypes = superCallable.getSignature().getAsmMethod().getArgumentTypes(); 1352 ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, superCall.getCalleeExpression()); 1353 assert resolvedCall != null; 1354 pushMethodArguments(resolvedCall, Arrays.asList(argumentTypes)); 1355 } 1356 1357 v.invokespecial(type.getInternalName(), "<init>", cons.getDescriptor()); 1358 return StackValue.onStack(type); 1359 } 1360 1361 protected void pushClosureOnStack(CalculatedClosure closure, boolean ignoreThisAndReceiver) { 1362 if (closure != null) { 1363 if (!ignoreThisAndReceiver) { 1364 ClassDescriptor captureThis = closure.getCaptureThis(); 1365 if (captureThis != null) { 1366 generateThisOrOuter(captureThis, false).put(OBJECT_TYPE, v); 1367 } 1368 1369 JetType captureReceiver = closure.getCaptureReceiverType(); 1370 if (captureReceiver != null) { 1371 v.load(context.isStatic() ? 0 : 1, typeMapper.mapType(captureReceiver)); 1372 } 1373 } 1374 1375 for (Map.Entry<DeclarationDescriptor, EnclosedValueDescriptor> entry : closure.getCaptureVariables().entrySet()) { 1376 //if (entry.getKey() instanceof VariableDescriptor && !(entry.getKey() instanceof PropertyDescriptor)) { 1377 Type sharedVarType = typeMapper.getSharedVarType(entry.getKey()); 1378 if (sharedVarType == null) { 1379 sharedVarType = typeMapper.mapType((VariableDescriptor) entry.getKey()); 1380 } 1381 entry.getValue().getOuterValue(this).put(sharedVarType, v); 1382 //} 1383 } 1384 } 1385 } 1386 1387 private StackValue generateBlock(List<JetElement> statements, boolean lastStatementIsExpression) { 1388 Label blockEnd = new Label(); 1389 1390 List<Function<StackValue, Void>> leaveTasks = Lists.newArrayList(); 1391 1392 StackValue answer = StackValue.none(); 1393 1394 for (Iterator<JetElement> iterator = statements.iterator(); iterator.hasNext(); ) { 1395 JetElement statement = iterator.next(); 1396 1397 if (statement instanceof JetNamedDeclaration) { 1398 JetNamedDeclaration declaration = (JetNamedDeclaration) statement; 1399 if (JetPsiUtil.isScriptDeclaration(declaration)) { 1400 continue; 1401 } 1402 } 1403 1404 if (statement instanceof JetMultiDeclaration) { 1405 JetMultiDeclaration multiDeclaration = (JetMultiDeclaration) statement; 1406 for (JetMultiDeclarationEntry entry : multiDeclaration.getEntries()) { 1407 generateLocalVariableDeclaration(entry, blockEnd, leaveTasks); 1408 } 1409 } 1410 1411 if (statement instanceof JetVariableDeclaration) { 1412 generateLocalVariableDeclaration((JetVariableDeclaration) statement, blockEnd, leaveTasks); 1413 } 1414 1415 if (statement instanceof JetNamedFunction) { 1416 generateLocalFunctionDeclaration((JetNamedFunction) statement, leaveTasks); 1417 } 1418 1419 boolean isExpression = !iterator.hasNext() && lastStatementIsExpression; 1420 1421 StackValue result = isExpression ? gen(statement) : genStatement(statement); 1422 1423 if (!iterator.hasNext()) { 1424 answer = result; 1425 } 1426 else { 1427 result.put(Type.VOID_TYPE, v); 1428 } 1429 } 1430 1431 v.mark(blockEnd); 1432 1433 for (Function<StackValue, Void> task : Lists.reverse(leaveTasks)) { 1434 task.fun(answer); 1435 } 1436 1437 return answer; 1438 } 1439 1440 private void generateLocalVariableDeclaration( 1441 @NotNull JetVariableDeclaration variableDeclaration, 1442 final @NotNull Label blockEnd, 1443 @NotNull List<Function<StackValue, Void>> leaveTasks 1444 ) { 1445 final VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, variableDeclaration); 1446 assert variableDescriptor != null; 1447 1448 final Label scopeStart = new Label(); 1449 v.mark(scopeStart); 1450 1451 final Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor); 1452 final Type type = sharedVarType != null ? sharedVarType : asmType(variableDescriptor.getType()); 1453 int index = myFrameMap.enter(variableDescriptor, type); 1454 1455 if (sharedVarType != null) { 1456 v.anew(sharedVarType); 1457 v.dup(); 1458 v.invokespecial(sharedVarType.getInternalName(), "<init>", "()V"); 1459 v.store(index, OBJECT_TYPE); 1460 } 1461 1462 leaveTasks.add(new Function<StackValue, Void>() { 1463 @Override 1464 public Void fun(StackValue answer) { 1465 int index = myFrameMap.leave(variableDescriptor); 1466 1467 if (sharedVarType != null) { 1468 if (answer instanceof StackValue.Shared && index == ((StackValue.Shared) answer).getIndex()) { 1469 ((StackValue.Shared) answer).releaseOnPut(); 1470 } 1471 else { 1472 v.aconst(null); 1473 v.store(index, OBJECT_TYPE); 1474 } 1475 } 1476 v.visitLocalVariable(variableDescriptor.getName().asString(), type.getDescriptor(), null, scopeStart, blockEnd, 1477 index); 1478 return null; 1479 } 1480 }); 1481 } 1482 1483 private void generateLocalFunctionDeclaration( 1484 @NotNull JetNamedFunction namedFunction, 1485 @NotNull List<Function<StackValue, Void>> leaveTasks 1486 ) { 1487 final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, namedFunction); 1488 myFrameMap.enter(descriptor, OBJECT_TYPE); 1489 1490 leaveTasks.add(new Function<StackValue, Void>() { 1491 @Override 1492 public Void fun(StackValue value) { 1493 myFrameMap.leave(descriptor); 1494 return null; 1495 } 1496 }); 1497 } 1498 1499 private void markLineNumber(@NotNull JetElement statement) { 1500 Document document = statement.getContainingFile().getViewProvider().getDocument(); 1501 if (document != null) { 1502 int lineNumber = document.getLineNumber(statement.getTextRange().getStartOffset()); // 0-based 1503 if (lineNumber == myLastLineNumber) { 1504 return; 1505 } 1506 myLastLineNumber = lineNumber; 1507 1508 Label label = new Label(); 1509 v.visitLabel(label); 1510 v.visitLineNumber(lineNumber + 1, label); // 1-based 1511 } 1512 } 1513 1514 private void doFinallyOnReturn() { 1515 if(!blockStackElements.isEmpty()) { 1516 BlockStackElement stackElement = blockStackElements.peek(); 1517 if (stackElement instanceof FinallyBlockStackElement) { 1518 FinallyBlockStackElement finallyBlockStackElement = (FinallyBlockStackElement) stackElement; 1519 genFinallyBlockOrGoto(finallyBlockStackElement, null); 1520 } 1521 else if (stackElement instanceof LoopBlockStackElement) { 1522 1523 } else { 1524 throw new UnsupportedOperationException("Wrong BlockStackElement in processing stack"); 1525 } 1526 1527 blockStackElements.pop(); 1528 doFinallyOnReturn(); 1529 blockStackElements.push(stackElement); 1530 } 1531 } 1532 1533 private void genFinallyBlockOrGoto( 1534 @Nullable FinallyBlockStackElement finallyBlockStackElement, 1535 @Nullable Label tryCatchBlockEnd 1536 ) { 1537 1538 if (finallyBlockStackElement != null) { 1539 assert finallyBlockStackElement.gaps.size() % 2 == 0 : "Finally block gaps are inconsistent"; 1540 1541 BlockStackElement topOfStack = blockStackElements.pop(); 1542 assert topOfStack == finallyBlockStackElement : "Top element of stack doesn't equals processing finally block"; 1543 1544 JetTryExpression jetTryExpression = finallyBlockStackElement.expression; 1545 Label finallyStart = new Label(); 1546 v.mark(finallyStart); 1547 finallyBlockStackElement.addGapLabel(finallyStart); 1548 1549 //noinspection ConstantConditions 1550 gen(jetTryExpression.getFinallyBlock().getFinalExpression(), Type.VOID_TYPE); 1551 } 1552 1553 if (tryCatchBlockEnd != null) { 1554 v.goTo(tryCatchBlockEnd); 1555 } 1556 1557 if (finallyBlockStackElement != null) { 1558 Label finallyEnd = new Label(); 1559 v.mark(finallyEnd); 1560 finallyBlockStackElement.addGapLabel(finallyEnd); 1561 1562 blockStackElements.push(finallyBlockStackElement); 1563 } 1564 } 1565 1566 @Override 1567 public StackValue visitReturnExpression(@NotNull JetReturnExpression expression, StackValue receiver) { 1568 JetExpression returnedExpression = expression.getReturnedExpression(); 1569 if (returnedExpression != null) { 1570 gen(returnedExpression, returnType); 1571 doFinallyOnReturn(); 1572 v.areturn(returnType); 1573 } 1574 else { 1575 doFinallyOnReturn(); 1576 v.visitInsn(RETURN); 1577 } 1578 return StackValue.none(); 1579 } 1580 1581 public void returnExpression(JetExpression expr) { 1582 StackValue lastValue = gen(expr); 1583 1584 if (!endsWithReturn(expr)) { 1585 lastValue.put(returnType, v); 1586 v.areturn(returnType); 1587 } 1588 } 1589 1590 private static boolean endsWithReturn(JetElement bodyExpression) { 1591 if (bodyExpression instanceof JetBlockExpression) { 1592 List<JetElement> statements = ((JetBlockExpression) bodyExpression).getStatements(); 1593 return statements.size() > 0 && statements.get(statements.size() - 1) instanceof JetReturnExpression; 1594 } 1595 1596 return bodyExpression instanceof JetReturnExpression; 1597 } 1598 1599 @Override 1600 public StackValue visitSimpleNameExpression(@NotNull JetSimpleNameExpression expression, StackValue receiver) { 1601 ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression); 1602 1603 DeclarationDescriptor descriptor; 1604 if (resolvedCall == null) { 1605 descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression); 1606 } 1607 else { 1608 if (resolvedCall instanceof VariableAsFunctionResolvedCall) { 1609 VariableAsFunctionResolvedCall call = (VariableAsFunctionResolvedCall) resolvedCall; 1610 resolvedCall = call.getVariableCall(); 1611 } 1612 receiver = StackValue.receiver(resolvedCall, receiver, this, null); 1613 descriptor = resolvedCall.getResultingDescriptor(); 1614 } 1615 1616 //if (descriptor instanceof VariableAsFunctionDescriptor) { 1617 // descriptor = ((VariableAsFunctionDescriptor) descriptor).getVariableDescriptor(); 1618 //} 1619 1620 assert descriptor != null : "Couldn't find descriptor for '" + expression.getText() + "'"; 1621 descriptor = descriptor.getOriginal(); 1622 1623 if (descriptor instanceof CallableMemberDescriptor) { 1624 CallableMemberDescriptor memberDescriptor = unwrapFakeOverride((CallableMemberDescriptor) descriptor); 1625 1626 IntrinsicMethod intrinsic = state.getIntrinsics().getIntrinsic(memberDescriptor); 1627 if (intrinsic != null) { 1628 Type returnType = typeMapper.mapType(memberDescriptor); 1629 intrinsic.generate(this, v, returnType, expression, Collections.<JetExpression>emptyList(), receiver); 1630 return StackValue.onStack(returnType); 1631 } 1632 } 1633 1634 int index = lookupLocalIndex(descriptor); 1635 if (index >= 0) { 1636 return stackValueForLocal(descriptor, index); 1637 } 1638 1639 if (descriptor instanceof PropertyDescriptor) { 1640 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; 1641 1642 boolean directToField = 1643 expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER && contextKind() != OwnerKind.TRAIT_IMPL; 1644 JetExpression r = getReceiverForSelector(expression); 1645 boolean isSuper = r instanceof JetSuperExpression; 1646 propertyDescriptor = accessiblePropertyDescriptor(propertyDescriptor); 1647 StackValue.Property iValue = 1648 intermediateValueForProperty(propertyDescriptor, directToField, isSuper ? (JetSuperExpression) r : null); 1649 if (directToField) { 1650 receiver = StackValue.receiverWithoutReceiverArgument(receiver); 1651 } 1652 1653 //pop receiver via put(VOID_TYPE) in case of access to backing field that moved to outer class!!! 1654 receiver.put(!iValue.isPropertyWithBackingFieldInOuterClass() ? receiver.type : Type.VOID_TYPE, v); 1655 1656 return iValue; 1657 } 1658 1659 if (descriptor instanceof ClassDescriptor) { 1660 ClassDescriptor classDescriptor = (ClassDescriptor) descriptor; 1661 if (classDescriptor.getKind() == ClassKind.OBJECT) { 1662 return StackValue.singleton(classDescriptor, typeMapper); 1663 } 1664 if (classDescriptor.getKind() == ClassKind.ENUM_ENTRY) { 1665 DeclarationDescriptor enumClass = classDescriptor.getContainingDeclaration(); 1666 assert DescriptorUtils.isEnumClass(enumClass) : "Enum entry should be declared in enum class: " + descriptor; 1667 Type type = typeMapper.mapType((ClassDescriptor) enumClass); 1668 return StackValue.field(type, type, descriptor.getName().asString(), true); 1669 } 1670 ClassDescriptor classObjectDescriptor = classDescriptor.getClassObjectDescriptor(); 1671 assert classObjectDescriptor != null : "Class object is not found for " + descriptor; 1672 return StackValue.singleton(classObjectDescriptor, typeMapper); 1673 } 1674 1675 if (descriptor instanceof TypeParameterDescriptor) { 1676 TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor; 1677 v.invokevirtual("jet/TypeInfo", "getClassObject", "()Ljava/lang/Object;"); 1678 JetType type = typeParameterDescriptor.getClassObjectType(); 1679 assert type != null; 1680 v.checkcast(asmType(type)); 1681 1682 return StackValue.onStack(OBJECT_TYPE); 1683 } 1684 1685 StackValue value = context.lookupInContext(descriptor, StackValue.local(0, OBJECT_TYPE), state, false); 1686 if (value != null) { 1687 1688 if (value instanceof StackValue.Composed) { 1689 StackValue.Composed composed = (StackValue.Composed) value; 1690 composed.prefix.put(OBJECT_TYPE, v); 1691 value = composed.suffix; 1692 } 1693 1694 if (value instanceof StackValue.FieldForSharedVar) { 1695 StackValue.FieldForSharedVar fieldForSharedVar = (StackValue.FieldForSharedVar) value; 1696 Type sharedType = StackValue.sharedTypeForType(value.type); 1697 v.visitFieldInsn(GETFIELD, fieldForSharedVar.owner.getInternalName(), fieldForSharedVar.name, 1698 sharedType.getDescriptor()); 1699 } 1700 1701 return value; 1702 } 1703 1704 if (descriptor instanceof ValueParameterDescriptor && descriptor.getContainingDeclaration() instanceof ScriptDescriptor) { 1705 ScriptDescriptor scriptDescriptor = (ScriptDescriptor) descriptor.getContainingDeclaration(); 1706 assert scriptDescriptor != null; 1707 Type scriptClassType = asmTypeForScriptDescriptor(bindingContext, scriptDescriptor); 1708 ValueParameterDescriptor valueParameterDescriptor = (ValueParameterDescriptor) descriptor; 1709 ClassDescriptor scriptClass = bindingContext.get(CLASS_FOR_SCRIPT, scriptDescriptor); 1710 StackValue script = StackValue.thisOrOuter(this, scriptClass, false); 1711 script.put(script.type, v); 1712 Type fieldType = typeMapper.mapType(valueParameterDescriptor); 1713 return StackValue.field(fieldType, scriptClassType, valueParameterDescriptor.getName().getIdentifier(), false); 1714 } 1715 1716 throw new UnsupportedOperationException("don't know how to generate reference " + descriptor); 1717 } 1718 1719 private StackValue stackValueForLocal(DeclarationDescriptor descriptor, int index) { 1720 if (descriptor instanceof VariableDescriptor) { 1721 Type sharedVarType = typeMapper.getSharedVarType(descriptor); 1722 JetType outType = ((VariableDescriptor) descriptor).getType(); 1723 if (sharedVarType != null) { 1724 return StackValue.shared(index, asmType(outType)); 1725 } 1726 else { 1727 return StackValue.local(index, asmType(outType)); 1728 } 1729 } 1730 else { 1731 return StackValue.local(index, OBJECT_TYPE); 1732 } 1733 } 1734 1735 @Override 1736 public boolean lookupLocal(DeclarationDescriptor descriptor) { 1737 return lookupLocalIndex(descriptor) != -1; 1738 } 1739 1740 public int lookupLocalIndex(DeclarationDescriptor descriptor) { 1741 return myFrameMap.getIndex(descriptor); 1742 } 1743 1744 @Nullable 1745 private static JetType getPropertyDelegateType(@NotNull PropertyDescriptor descriptor, @NotNull BindingContext bindingContext) { 1746 PropertyGetterDescriptor getter = descriptor.getGetter(); 1747 if (getter != null) { 1748 Call call = bindingContext.get(BindingContext.DELEGATED_PROPERTY_CALL, getter); 1749 return call != null ? call.getExplicitReceiver().getType() : null; 1750 } 1751 return null; 1752 } 1753 1754 @NotNull 1755 public StackValue.Property intermediateValueForProperty( 1756 @NotNull PropertyDescriptor propertyDescriptor, 1757 boolean forceField, 1758 @Nullable JetSuperExpression superExpression 1759 ) { 1760 return intermediateValueForProperty(propertyDescriptor, forceField, superExpression, MethodKind.GENERAL); 1761 } 1762 1763 public StackValue.Property intermediateValueForProperty( 1764 @NotNull PropertyDescriptor propertyDescriptor, 1765 boolean forceField, 1766 @Nullable JetSuperExpression superExpression, 1767 @NotNull MethodKind methodKind 1768 ) { 1769 JetTypeMapper typeMapper = state.getTypeMapper(); 1770 1771 DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); 1772 1773 boolean isBackingFieldInAnotherClass = AsmUtil.isPropertyWithBackingFieldInOuterClass(propertyDescriptor); 1774 boolean isStatic = containingDeclaration instanceof PackageFragmentDescriptor; 1775 boolean isSuper = superExpression != null; 1776 boolean isInsideClass = isCallInsideSameClassAsDeclared(propertyDescriptor, context); 1777 boolean isInsideModule = isCallInsideSameModuleAsDeclared(propertyDescriptor, context); 1778 1779 JetType delegateType = getPropertyDelegateType(propertyDescriptor, state.getBindingContext()); 1780 boolean isDelegatedProperty = delegateType != null; 1781 1782 1783 CallableMethod callableGetter = null; 1784 CallableMethod callableSetter = null; 1785 1786 boolean skipPropertyAccessors = forceField && !isBackingFieldInAnotherClass; 1787 1788 CodegenContext backingFieldContext = context.getParentContext(); 1789 1790 if (isBackingFieldInAnotherClass && forceField) { 1791 //delegate call to classObject owner : OWNER 1792 backingFieldContext = context.findParentContextWithDescriptor(containingDeclaration.getContainingDeclaration()); 1793 int flags = AsmUtil.getVisibilityForSpecialPropertyBackingField(propertyDescriptor, isDelegatedProperty); 1794 skipPropertyAccessors = (flags & ACC_PRIVATE) == 0 || methodKind == MethodKind.SYNTHETIC_ACCESSOR || methodKind == MethodKind.INITIALIZER; 1795 if (!skipPropertyAccessors) { 1796 //noinspection ConstantConditions 1797 propertyDescriptor = (PropertyDescriptor) backingFieldContext.getAccessor(propertyDescriptor, true, delegateType); 1798 } 1799 isStatic = true; 1800 } 1801 1802 if (!skipPropertyAccessors) { 1803 if (couldUseDirectAccessToProperty(propertyDescriptor, true, isInsideClass, isDelegatedProperty)) { 1804 callableGetter = null; 1805 } 1806 else { 1807 if (isSuper && !isInterface(containingDeclaration)) { 1808 ClassDescriptor owner = getSuperCallLabelTarget(superExpression, state.getBindingContext(), context); 1809 CodegenContext c = context.findParentContextWithDescriptor(owner); 1810 assert c != null : "Couldn't find a context for a super-call: " + propertyDescriptor; 1811 if (c != context.getParentContext()) { 1812 propertyDescriptor = (PropertyDescriptor) c.getAccessor(propertyDescriptor); 1813 } 1814 } 1815 1816 propertyDescriptor = accessiblePropertyDescriptor(propertyDescriptor); 1817 1818 PropertyGetterDescriptor getter = propertyDescriptor.getGetter(); 1819 if (getter != null) { 1820 callableGetter = typeMapper.mapToCallableMethod( 1821 getter, isSuper || MethodKind.SYNTHETIC_ACCESSOR == methodKind, isInsideClass, isInsideModule, 1822 OwnerKind.IMPLEMENTATION); 1823 } 1824 } 1825 1826 if (propertyDescriptor.isVar()) { 1827 PropertySetterDescriptor setter = propertyDescriptor.getSetter(); 1828 if (setter != null) { 1829 if (couldUseDirectAccessToProperty(propertyDescriptor, false, isInsideClass, isDelegatedProperty)) { 1830 callableSetter = null; 1831 } 1832 else { 1833 callableSetter = typeMapper.mapToCallableMethod( 1834 setter, isSuper || MethodKind.SYNTHETIC_ACCESSOR == methodKind, isInsideClass, isInsideModule, 1835 OwnerKind.IMPLEMENTATION); 1836 } 1837 } 1838 } 1839 } 1840 1841 Type owner; 1842 CallableMethod callableMethod = callableGetter != null ? callableGetter : callableSetter; 1843 1844 propertyDescriptor = unwrapFakeOverride(propertyDescriptor); 1845 if (callableMethod == null) { 1846 owner = typeMapper.getOwner(isBackingFieldInAnotherClass ? propertyDescriptor.getContainingDeclaration() : propertyDescriptor, 1847 context.getContextKind(), isInsideModule); 1848 } 1849 else { 1850 owner = callableMethod.getOwner(); 1851 } 1852 1853 String name; 1854 //noinspection ConstantConditions 1855 if (propertyDescriptor.getContainingDeclaration() == backingFieldContext.getContextDescriptor()) { 1856 assert backingFieldContext instanceof FieldOwnerContext : "Actual context is " + backingFieldContext + " but should be instance of FieldOwnerContext" ; 1857 name = ((FieldOwnerContext) backingFieldContext).getFieldName(propertyDescriptor, isDelegatedProperty); 1858 } else { 1859 name = JvmAbi.getDefaultPropertyName(propertyDescriptor.getName(), isDelegatedProperty, propertyDescriptor.getReceiverParameter() != null); 1860 } 1861 1862 return StackValue.property(propertyDescriptor, owner, 1863 typeMapper.mapType(isDelegatedProperty && forceField ? delegateType : propertyDescriptor.getOriginal().getType()), 1864 isStatic, name, callableGetter, callableSetter, state); 1865 1866 } 1867 1868 @Override 1869 public StackValue visitCallExpression(@NotNull JetCallExpression expression, StackValue receiver) { 1870 JetExpression callee = expression.getCalleeExpression(); 1871 assert callee != null; 1872 1873 ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, callee); 1874 if (resolvedCall == null) { 1875 throw new CompilationException("Cannot resolve: " + callee.getText(), null, expression); 1876 } 1877 1878 DeclarationDescriptor funDescriptor = resolvedCall.getResultingDescriptor(); 1879 1880 if (!(funDescriptor instanceof FunctionDescriptor)) { 1881 throw new UnsupportedOperationException("unknown type of callee descriptor: " + funDescriptor); 1882 } 1883 1884 funDescriptor = accessibleFunctionDescriptor((FunctionDescriptor) funDescriptor); 1885 1886 if (funDescriptor instanceof ConstructorDescriptor) { 1887 return generateNewCall(expression, resolvedCall, receiver); 1888 } 1889 1890 Call call = bindingContext.get(CALL, expression.getCalleeExpression()); 1891 if (funDescriptor instanceof SimpleFunctionDescriptor) { 1892 SimpleFunctionDescriptor original = ((SimpleFunctionDescriptor) funDescriptor).getOriginal(); 1893 if (original instanceof SamConstructorDescriptor) { 1894 return invokeSamConstructor(expression, resolvedCall, ((SamConstructorDescriptor) original).getBaseForSynthesized()); 1895 } 1896 } 1897 1898 return invokeFunction(call, receiver, resolvedCall); 1899 } 1900 1901 private StackValue invokeSamConstructor( 1902 JetCallExpression expression, 1903 ResolvedCall<? extends CallableDescriptor> resolvedCall, 1904 JavaClassDescriptor samInterface 1905 ) { 1906 ResolvedValueArgument argument = resolvedCall.getValueArgumentsByIndex().get(0); 1907 if (!(argument instanceof ExpressionValueArgument)) { 1908 throw new IllegalStateException( 1909 "argument of SAM constructor is " + argument.getClass().getName() + " " + expression.getText()); 1910 } 1911 ValueArgument valueArgument = ((ExpressionValueArgument) argument).getValueArgument(); 1912 assert valueArgument != null : "getValueArgument() is null for " + expression.getText(); 1913 JetExpression argumentExpression = valueArgument.getArgumentExpression(); 1914 assert argumentExpression != null : "getArgumentExpression() is null for " + expression.getText(); 1915 1916 return genSamInterfaceValue(argumentExpression, samInterface, this); 1917 } 1918 1919 private StackValue genSamInterfaceValue( 1920 @NotNull JetExpression expression, 1921 @NotNull JavaClassDescriptor samInterface, 1922 @NotNull JetVisitor<StackValue, StackValue> visitor 1923 ) { 1924 if (expression instanceof JetFunctionLiteralExpression) { 1925 return genClosure(((JetFunctionLiteralExpression) expression).getFunctionLiteral(), samInterface); 1926 } 1927 else { 1928 Type asmType = state.getSamWrapperClasses().getSamWrapperClass(samInterface, (JetFile) expression.getContainingFile()); 1929 1930 v.anew(asmType); 1931 v.dup(); 1932 1933 @SuppressWarnings("ConstantConditions") 1934 Type functionType = typeMapper.mapType(samInterface.getFunctionTypeForSamInterface()); 1935 expression.accept(visitor, StackValue.none()).put(functionType, v); 1936 1937 Label ifNonNull = new Label(); 1938 Label afterAll = new Label(); 1939 1940 v.dup(); 1941 v.ifnonnull(ifNonNull); 1942 1943 // if null: pop function value and wrapper objects, put null 1944 v.pop(); 1945 v.pop2(); 1946 v.aconst(null); 1947 v.goTo(afterAll); 1948 1949 v.mark(ifNonNull); 1950 v.invokespecial(asmType.getInternalName(), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, functionType)); 1951 1952 v.mark(afterAll); 1953 return StackValue.onStack(asmType); 1954 } 1955 } 1956 1957 @NotNull 1958 private PropertyDescriptor accessiblePropertyDescriptor(PropertyDescriptor propertyDescriptor) { 1959 return context.accessiblePropertyDescriptor(propertyDescriptor); 1960 } 1961 1962 @NotNull 1963 protected FunctionDescriptor accessibleFunctionDescriptor(FunctionDescriptor fd) { 1964 return context.accessibleFunctionDescriptor(fd); 1965 } 1966 1967 @NotNull 1968 public StackValue invokeFunction( 1969 Call call, 1970 StackValue receiver, 1971 ResolvedCall<? extends CallableDescriptor> resolvedCall 1972 ) { 1973 if (resolvedCall instanceof VariableAsFunctionResolvedCall) { 1974 return invokeFunction(call, receiver, ((VariableAsFunctionResolvedCall) resolvedCall).getFunctionCall()); 1975 } 1976 1977 FunctionDescriptor fd = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); 1978 JetSuperExpression superCallExpression = getSuperCallExpression(call); 1979 boolean superCall = superCallExpression != null; 1980 1981 if (superCall && !isInterface(fd.getContainingDeclaration())) { 1982 ClassDescriptor owner = getSuperCallLabelTarget(superCallExpression); 1983 CodegenContext c = context.findParentContextWithDescriptor(owner); 1984 assert c != null : "Couldn't find a context for a super-call: " + fd; 1985 if (c != context.getParentContext()) { 1986 fd = (FunctionDescriptor) c.getAccessor(fd); 1987 } 1988 } 1989 1990 Callable callable = resolveToCallable(accessibleFunctionDescriptor(fd), superCall); 1991 1992 if (callable instanceof CallableMethod) { 1993 CallableMethod callableMethod = (CallableMethod) callable; 1994 Type calleeType = callableMethod.getGenerateCalleeType(); 1995 if (calleeType != null) { 1996 assert !callableMethod.isNeedsThis() : "Method should have a receiver: " + resolvedCall.getResultingDescriptor(); 1997 gen(call.getCalleeExpression(), calleeType); 1998 } 1999 } 2000 2001 return invokeFunctionWithCalleeOnStack(call, receiver, resolvedCall, callable); 2002 } 2003 2004 @NotNull 2005 private StackValue invokeFunctionWithCalleeOnStack( 2006 @NotNull Call call, 2007 @NotNull StackValue receiver, 2008 @NotNull ResolvedCall<? extends CallableDescriptor> resolvedCall, 2009 @NotNull Callable callable 2010 ) { 2011 if (callable instanceof CallableMethod) { 2012 CallableMethod callableMethod = (CallableMethod) callable; 2013 invokeMethodWithArguments(callableMethod, resolvedCall, receiver); 2014 //noinspection ConstantConditions 2015 Type returnType = typeMapper.mapReturnType(resolvedCall.getResultingDescriptor().getReturnType()); 2016 StackValue.coerce(callableMethod.getSignature().getAsmMethod().getReturnType(), returnType, v); 2017 return StackValue.onStack(returnType); 2018 } 2019 else { 2020 receiver = StackValue.receiver(resolvedCall, receiver, this, null); 2021 2022 List<JetExpression> args = new ArrayList<JetExpression>(); 2023 for (ValueArgument argument : call.getValueArguments()) { 2024 args.add(argument.getArgumentExpression()); 2025 } 2026 2027 Type returnType = typeMapper.mapType(resolvedCall.getResultingDescriptor()); 2028 2029 ((IntrinsicMethod) callable).generate(this, v, returnType, call.getCallElement(), args, receiver); 2030 return StackValue.onStack(returnType); 2031 } 2032 } 2033 2034 @Nullable 2035 private static JetSuperExpression getSuperCallExpression(@NotNull Call call) { 2036 ReceiverValue explicitReceiver = call.getExplicitReceiver(); 2037 if (explicitReceiver instanceof ExpressionReceiver) { 2038 JetExpression receiverExpression = ((ExpressionReceiver) explicitReceiver).getExpression(); 2039 if (receiverExpression instanceof JetSuperExpression) { 2040 return (JetSuperExpression) receiverExpression; 2041 } 2042 } 2043 return null; 2044 } 2045 2046 // Find the first parent of the current context which corresponds to a subclass of a given class 2047 @NotNull 2048 private static CodegenContext getParentContextSubclassOf(ClassDescriptor descriptor, CodegenContext context) { 2049 CodegenContext c = context; 2050 while (true) { 2051 if (c instanceof ClassContext && DescriptorUtils.isSubclass(c.getThisDescriptor(), descriptor)) { 2052 return c; 2053 } 2054 c = c.getParentContext(); 2055 assert c != null; 2056 } 2057 } 2058 2059 @NotNull 2060 Callable resolveToCallable(@NotNull FunctionDescriptor fd, boolean superCall) { 2061 IntrinsicMethod intrinsic = state.getIntrinsics().getIntrinsic(fd); 2062 if (intrinsic != null) { 2063 return intrinsic; 2064 } 2065 2066 return resolveToCallableMethod(fd, superCall, context); 2067 } 2068 2069 @NotNull 2070 private CallableMethod resolveToCallableMethod(@NotNull FunctionDescriptor fd, boolean superCall, @NotNull CodegenContext context) { 2071 if (isCallAsFunctionObject(fd)) { 2072 return typeMapper.mapToFunctionInvokeCallableMethod(createInvoke(fd)); 2073 } 2074 else { 2075 SimpleFunctionDescriptor originalOfSamAdapter = (SimpleFunctionDescriptor) SamCodegenUtil.getOriginalIfSamAdapter(fd); 2076 return typeMapper.mapToCallableMethod(originalOfSamAdapter != null ? originalOfSamAdapter : fd, superCall, 2077 isCallInsideSameClassAsDeclared(fd, context), 2078 isCallInsideSameModuleAsDeclared(fd, context), 2079 OwnerKind.IMPLEMENTATION); 2080 } 2081 } 2082 2083 private static boolean isCallAsFunctionObject(FunctionDescriptor fd) { 2084 if (fd instanceof ExpressionAsFunctionDescriptor) { 2085 JetExpression deparenthesize = JetPsiUtil.deparenthesize(((ExpressionAsFunctionDescriptor) fd).getExpression()); 2086 return !(deparenthesize instanceof JetCallableReferenceExpression || deparenthesize instanceof JetFunctionLiteralExpression); 2087 } 2088 return false; 2089 } 2090 2091 2092 public void invokeMethodWithArguments( 2093 @NotNull CallableMethod callableMethod, 2094 @NotNull ResolvedCall<? extends CallableDescriptor> resolvedCall, 2095 @NotNull StackValue receiver 2096 ) { 2097 if (resolvedCall instanceof VariableAsFunctionResolvedCall) { 2098 resolvedCall = ((VariableAsFunctionResolvedCall) resolvedCall).getFunctionCall(); 2099 } 2100 2101 if (!(resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor)) { // otherwise already 2102 receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod); 2103 receiver.put(receiver.type, v); 2104 } 2105 2106 pushArgumentsAndInvoke(resolvedCall, callableMethod); 2107 } 2108 2109 private void pushArgumentsAndInvoke(@NotNull ResolvedCall<?> resolvedCall, @NotNull CallableMethod callable) { 2110 int mask = pushMethodArguments(resolvedCall, callable.getValueParameterTypes()); 2111 2112 if (tailRecursionCodegen.isTailRecursion(resolvedCall)) { 2113 tailRecursionCodegen.generateTailRecursion(resolvedCall); 2114 return; 2115 } 2116 2117 if (mask == 0) { 2118 callable.invokeWithNotNullAssertion(v, state, resolvedCall); 2119 } 2120 else { 2121 callable.invokeDefaultWithNotNullAssertion(v, state, resolvedCall, mask); 2122 } 2123 } 2124 2125 private void genThisAndReceiverFromResolvedCall( 2126 StackValue receiver, 2127 ResolvedCall<? extends CallableDescriptor> resolvedCall, 2128 CallableMethod callableMethod 2129 ) { 2130 receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod); 2131 receiver.put(receiver.type, v); 2132 } 2133 2134 public void generateFromResolvedCall(@NotNull ReceiverValue descriptor, @NotNull Type type) { 2135 if (descriptor instanceof ClassReceiver) { 2136 Type exprType = asmType(descriptor.getType()); 2137 ClassReceiver classReceiver = (ClassReceiver) descriptor; 2138 ClassDescriptor classReceiverDeclarationDescriptor = classReceiver.getDeclarationDescriptor(); 2139 if (DescriptorUtils.isClassObject(classReceiverDeclarationDescriptor)) { 2140 if (context.getContextDescriptor() instanceof FunctionDescriptor && 2141 classReceiverDeclarationDescriptor == context.getContextDescriptor().getContainingDeclaration()) { 2142 v.load(0, OBJECT_TYPE); 2143 } 2144 else { 2145 FieldInfo info = FieldInfo.createForSingleton(classReceiverDeclarationDescriptor, typeMapper); 2146 v.getstatic(info.getOwnerInternalName(), info.getFieldName(), info.getFieldType().getDescriptor()); 2147 } 2148 StackValue.onStack(exprType).put(type, v); 2149 } 2150 else { 2151 StackValue.thisOrOuter(this, classReceiverDeclarationDescriptor, false).put(type, v); 2152 } 2153 } 2154 else if (descriptor instanceof ScriptReceiver) { 2155 generateScript((ScriptReceiver) descriptor); 2156 } 2157 else if (descriptor instanceof ExtensionReceiver) { 2158 ExtensionReceiver extensionReceiver = (ExtensionReceiver) descriptor; 2159 generateReceiver(extensionReceiver.getDeclarationDescriptor()).put(type, v); 2160 } 2161 else if (descriptor instanceof ExpressionReceiver) { 2162 ExpressionReceiver expressionReceiver = (ExpressionReceiver) descriptor; 2163 JetExpression expr = expressionReceiver.getExpression(); 2164 gen(expr, type); 2165 } 2166 else if (descriptor instanceof AutoCastReceiver) { 2167 AutoCastReceiver autoCastReceiver = (AutoCastReceiver) descriptor; 2168 Type originalType = asmType(autoCastReceiver.getOriginal().getType()); 2169 generateFromResolvedCall(autoCastReceiver.getOriginal(), originalType); 2170 StackValue.onStack(originalType).put(type, v); 2171 } 2172 else { 2173 throw new UnsupportedOperationException("Unsupported receiver type: " + descriptor); 2174 } 2175 } 2176 2177 @Nullable 2178 private static JetExpression getReceiverForSelector(PsiElement expression) { 2179 if (expression.getParent() instanceof JetDotQualifiedExpression && !isReceiver(expression)) { 2180 JetDotQualifiedExpression parent = (JetDotQualifiedExpression) expression.getParent(); 2181 return parent.getReceiverExpression(); 2182 } 2183 return null; 2184 } 2185 2186 private StackValue generateReceiver(DeclarationDescriptor provided) { 2187 if (context.getCallableDescriptorWithReceiver() == provided) { 2188 return context.getReceiverExpression(typeMapper); 2189 } 2190 2191 return context.lookupInContext(provided, StackValue.local(0, OBJECT_TYPE), state, false); 2192 } 2193 2194 private void generateScript(@NotNull ScriptReceiver receiver) { 2195 CodegenContext cur = context; 2196 StackValue result = StackValue.local(0, OBJECT_TYPE); 2197 boolean inStartConstructorContext = cur instanceof ConstructorContext; 2198 while (cur != null) { 2199 if (!inStartConstructorContext) { 2200 cur = getNotNullParentContextForMethod(cur); 2201 } 2202 2203 if (cur instanceof ScriptContext) { 2204 ScriptContext scriptContext = (ScriptContext) cur; 2205 2206 Type currentScriptType = asmTypeForScriptDescriptor(bindingContext, scriptContext.getScriptDescriptor()); 2207 if (scriptContext.getScriptDescriptor() == receiver.getDeclarationDescriptor()) { 2208 result.put(currentScriptType, v); 2209 } 2210 else { 2211 Type classType = asmTypeForScriptDescriptor(bindingContext, receiver.getDeclarationDescriptor()); 2212 String fieldName = getParentScriptCodegen().getScriptFieldName(receiver.getDeclarationDescriptor()); 2213 result.put(currentScriptType, v); 2214 StackValue.field(classType, currentScriptType, fieldName, false).put(classType, v); 2215 } 2216 return; 2217 } 2218 2219 result = cur.getOuterExpression(result, false); 2220 2221 if (inStartConstructorContext) { 2222 cur = getNotNullParentContextForMethod(cur); 2223 inStartConstructorContext = false; 2224 } 2225 2226 cur = cur.getParentContext(); 2227 } 2228 2229 throw new UnsupportedOperationException(); 2230 } 2231 2232 public StackValue generateThisOrOuter(@NotNull ClassDescriptor calleeContainingClass, boolean isSuper) { 2233 boolean isSingleton = calleeContainingClass.getKind().isSingleton(); 2234 if (isSingleton) { 2235 if (context.hasThisDescriptor() && context.getThisDescriptor().equals(calleeContainingClass)) { 2236 return StackValue.local(0, typeMapper.mapType(calleeContainingClass)); 2237 } 2238 else { 2239 return StackValue.singleton(calleeContainingClass, typeMapper); 2240 } 2241 } 2242 2243 CodegenContext cur = context; 2244 Type type = asmType(calleeContainingClass.getDefaultType()); 2245 StackValue result = StackValue.local(0, type); 2246 boolean inStartConstructorContext = cur instanceof ConstructorContext; 2247 while (cur != null) { 2248 ClassDescriptor thisDescriptor = cur.getThisDescriptor(); 2249 if (!isSuper && thisDescriptor.equals(calleeContainingClass) 2250 || isSuper && DescriptorUtils.isSubclass(thisDescriptor, calleeContainingClass)) { 2251 return castToRequiredTypeOfInterfaceIfNeeded(result, thisDescriptor, calleeContainingClass); 2252 } 2253 2254 //for constructor super call we should access to outer instance through parameter in locals, in other cases through field for captured outer 2255 if (inStartConstructorContext) { 2256 result = cur.getOuterExpression(result, false); 2257 cur = getNotNullParentContextForMethod(cur); 2258 inStartConstructorContext = false; 2259 } 2260 else { 2261 cur = getNotNullParentContextForMethod(cur); 2262 result = cur.getOuterExpression(result, false); 2263 } 2264 2265 cur = cur.getParentContext(); 2266 } 2267 2268 throw new UnsupportedOperationException(); 2269 } 2270 2271 @NotNull 2272 private static CodegenContext getNotNullParentContextForMethod(CodegenContext cur) { 2273 if (cur instanceof MethodContext) { 2274 cur = cur.getParentContext(); 2275 } 2276 assert cur != null; 2277 return cur; 2278 } 2279 2280 2281 private static boolean isReceiver(PsiElement expression) { 2282 PsiElement parent = expression.getParent(); 2283 if (parent instanceof JetQualifiedExpression) { 2284 JetExpression receiverExpression = ((JetQualifiedExpression) parent).getReceiverExpression(); 2285 return expression == receiverExpression; 2286 } 2287 return false; 2288 } 2289 2290 private int pushMethodArguments(@NotNull ResolvedCall resolvedCall, List<Type> valueParameterTypes) { 2291 @SuppressWarnings("unchecked") 2292 List<ResolvedValueArgument> valueArguments = resolvedCall.getValueArgumentsByIndex(); 2293 CallableDescriptor fd = resolvedCall.getResultingDescriptor(); 2294 2295 if (fd.getValueParameters().size() != valueArguments.size()) { 2296 throw new IllegalStateException(); 2297 } 2298 2299 int mask = 0; 2300 2301 for (ValueParameterDescriptor valueParameter : fd.getValueParameters()) { 2302 ResolvedValueArgument resolvedValueArgument = valueArguments.get(valueParameter.getIndex()); 2303 Type parameterType = valueParameterTypes.get(valueParameter.getIndex()); 2304 if (resolvedValueArgument instanceof ExpressionValueArgument) { 2305 ValueArgument valueArgument = ((ExpressionValueArgument) resolvedValueArgument).getValueArgument(); 2306 assert valueArgument != null; 2307 JetExpression argumentExpression = valueArgument.getArgumentExpression(); 2308 assert argumentExpression != null : valueArgument.asElement().getText(); 2309 2310 gen(argumentExpression, parameterType); 2311 } 2312 else if (resolvedValueArgument instanceof DefaultValueArgument) { 2313 pushDefaultValueOnStack(parameterType, v); 2314 mask |= (1 << valueParameter.getIndex()); 2315 } 2316 else if (resolvedValueArgument instanceof VarargValueArgument) { 2317 VarargValueArgument valueArgument = (VarargValueArgument) resolvedValueArgument; 2318 genVarargs(valueParameter, valueArgument); 2319 } 2320 else { 2321 throw new UnsupportedOperationException(); 2322 } 2323 } 2324 return mask; 2325 } 2326 2327 public void genVarargs(ValueParameterDescriptor valueParameterDescriptor, VarargValueArgument valueArgument) { 2328 JetType outType = valueParameterDescriptor.getType(); 2329 2330 Type type = asmType(outType); 2331 assert type.getSort() == Type.ARRAY; 2332 Type elementType = correctElementType(type); 2333 List<ValueArgument> arguments = valueArgument.getArguments(); 2334 int size = arguments.size(); 2335 2336 boolean hasSpread = false; 2337 for (int i = 0; i != size; ++i) { 2338 if (arguments.get(i).getSpreadElement() != null) { 2339 hasSpread = true; 2340 break; 2341 } 2342 } 2343 2344 if (hasSpread) { 2345 if (size == 1) { 2346 gen(arguments.get(0).getArgumentExpression(), type); 2347 } 2348 else { 2349 String owner = "jet/runtime/Intrinsics$SpreadBuilder"; 2350 v.anew(Type.getObjectType(owner)); 2351 v.dup(); 2352 v.invokespecial(owner, "<init>", "()V"); 2353 for (int i = 0; i != size; ++i) { 2354 v.dup(); 2355 ValueArgument argument = arguments.get(i); 2356 if (argument.getSpreadElement() != null) { 2357 gen(argument.getArgumentExpression(), OBJECT_TYPE); 2358 v.invokevirtual(owner, "addSpread", "(Ljava/lang/Object;)V"); 2359 } 2360 else { 2361 gen(argument.getArgumentExpression(), elementType); 2362 v.invokevirtual(owner, "add", "(Ljava/lang/Object;)Z"); 2363 v.pop(); 2364 } 2365 } 2366 v.dup(); 2367 v.invokevirtual(owner, "size", "()I"); 2368 v.newarray(elementType); 2369 v.invokevirtual(owner, "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;"); 2370 v.checkcast(type); 2371 } 2372 } 2373 else { 2374 v.iconst(arguments.size()); 2375 v.newarray(elementType); 2376 for (int i = 0; i != size; ++i) { 2377 v.dup(); 2378 v.iconst(i); 2379 gen(arguments.get(i).getArgumentExpression(), elementType); 2380 StackValue.arrayElement(elementType, false).store(elementType, v); 2381 } 2382 } 2383 } 2384 2385 public int pushMethodArguments(JetCallElement expression, List<Type> valueParameterTypes) { 2386 ResolvedCall<? extends CallableDescriptor> resolvedCall = 2387 bindingContext.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression()); 2388 if (resolvedCall != null) { 2389 return pushMethodArguments(resolvedCall, valueParameterTypes); 2390 } 2391 else { 2392 List<? extends ValueArgument> args = expression.getValueArguments(); 2393 for (int i = 0, argsSize = args.size(); i < argsSize; i++) { 2394 ValueArgument arg = args.get(i); 2395 gen(arg.getArgumentExpression(), valueParameterTypes.get(i)); 2396 } 2397 return 0; 2398 } 2399 } 2400 2401 @NotNull 2402 public Type expressionType(JetExpression expr) { 2403 return typeMapper.expressionType(expr); 2404 } 2405 2406 public int indexOfLocal(JetReferenceExpression lhs) { 2407 DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, lhs); 2408 if (isVarCapturedInClosure(bindingContext, declarationDescriptor)) { 2409 return -1; 2410 } 2411 return lookupLocalIndex(declarationDescriptor); 2412 } 2413 2414 @Override 2415 public StackValue visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression, StackValue data) { 2416 // TODO: properties 2417 FunctionDescriptor functionDescriptor = bindingContext.get(FUNCTION, expression); 2418 assert functionDescriptor != null : "Callable reference is not resolved to descriptor: " + expression.getText(); 2419 2420 ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(RESOLVED_CALL, expression.getCallableReference()); 2421 assert resolvedCall != null : "Callable reference is not resolved: " + functionDescriptor + " " + expression.getText(); 2422 2423 JetType kFunctionType = bindingContext.get(EXPRESSION_TYPE, expression); 2424 assert kFunctionType != null : "Callable reference is not type checked: " + expression.getText(); 2425 ClassDescriptor kFunctionImpl = functionTypeToImpl(kFunctionType); 2426 assert kFunctionImpl != null : "Impl type is not found for the function type: " + kFunctionType; 2427 2428 Type closureSuperClass = typeMapper.mapType(kFunctionImpl); 2429 2430 CallableReferenceGenerationStrategy strategy = new CallableReferenceGenerationStrategy(state, functionDescriptor, resolvedCall); 2431 ClosureCodegen closureCodegen = new ClosureCodegen(state, expression, functionDescriptor, null, closureSuperClass, context, this, 2432 strategy, getParentCodegen()); 2433 2434 closureCodegen.gen(); 2435 2436 return closureCodegen.putInstanceOnStack(v, this); 2437 } 2438 2439 private static class CallableReferenceGenerationStrategy extends FunctionGenerationStrategy.CodegenBased<FunctionDescriptor> { 2440 private final ResolvedCall<? extends CallableDescriptor> resolvedCall; 2441 private final FunctionDescriptor referencedFunction; 2442 2443 public CallableReferenceGenerationStrategy( 2444 @NotNull GenerationState state, 2445 @NotNull FunctionDescriptor functionDescriptor, 2446 @NotNull ResolvedCall<? extends CallableDescriptor> resolvedCall 2447 ) { 2448 super(state, functionDescriptor); 2449 this.resolvedCall = resolvedCall; 2450 this.referencedFunction = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); 2451 } 2452 2453 @Override 2454 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { 2455 /* 2456 Here we need to put the arguments from our locals to the stack and invoke the referenced method. Since invocation 2457 of methods is highly dependent on expressions, we create a fake call expression. Then we create a new instance of 2458 ExpressionCodegen and, in order for it to generate code correctly, we save to its 'tempVariables' field every 2459 argument of our fake expression, pointing it to the corresponding index in our locals. This way generation of 2460 every argument boils down to calling LOAD with the corresponding index 2461 */ 2462 2463 JetCallExpression fakeExpression = constructFakeFunctionCall(); 2464 final List<? extends ValueArgument> fakeArguments = fakeExpression.getValueArguments(); 2465 2466 final ReceiverValue thisObject = computeAndSaveReceiver(signature, codegen, referencedFunction.getExpectedThisObject()); 2467 final ReceiverValue extensionReceiver = computeAndSaveReceiver(signature, codegen, referencedFunction.getReceiverParameter()); 2468 computeAndSaveArguments(fakeArguments, codegen); 2469 2470 ResolvedCall<CallableDescriptor> fakeResolvedCall = new DelegatingResolvedCall<CallableDescriptor>(resolvedCall) { 2471 @NotNull 2472 @Override 2473 public ReceiverValue getReceiverArgument() { 2474 return extensionReceiver; 2475 } 2476 2477 @NotNull 2478 @Override 2479 public ReceiverValue getThisObject() { 2480 return thisObject; 2481 } 2482 2483 @NotNull 2484 @Override 2485 public List<ResolvedValueArgument> getValueArgumentsByIndex() { 2486 List<ResolvedValueArgument> result = new ArrayList<ResolvedValueArgument>(fakeArguments.size()); 2487 for (ValueArgument argument : fakeArguments) { 2488 result.add(new ExpressionValueArgument(argument)); 2489 } 2490 return result; 2491 } 2492 }; 2493 2494 StackValue result; 2495 Type returnType = codegen.returnType; 2496 if (referencedFunction instanceof ConstructorDescriptor) { 2497 if (returnType.getSort() == Type.ARRAY) { 2498 //noinspection ConstantConditions 2499 codegen.generateNewArray(fakeExpression, referencedFunction.getReturnType()); 2500 result = StackValue.onStack(returnType); 2501 } 2502 else { 2503 result = codegen.generateConstructorCall(fakeResolvedCall, StackValue.none(), returnType); 2504 } 2505 } 2506 else { 2507 Call call = CallMaker.makeCall(fakeExpression, NO_RECEIVER, null, fakeExpression, fakeArguments); 2508 Callable callable = codegen.resolveToCallable(codegen.accessibleFunctionDescriptor(referencedFunction), false); 2509 StackValue receiver = generateCallee(codegen, callable); 2510 if (extensionReceiver.exists()) { 2511 receiver = StackValue.composed(receiver, receiverParameterStackValue(signature)); 2512 } 2513 result = codegen.invokeFunctionWithCalleeOnStack(call, receiver, fakeResolvedCall, callable); 2514 } 2515 2516 InstructionAdapter v = codegen.v; 2517 result.put(returnType, v); 2518 v.areturn(returnType); 2519 } 2520 2521 @NotNull 2522 private StackValue generateCallee(@NotNull ExpressionCodegen codegen, @NotNull Callable callable) { 2523 if (!(callable instanceof CallableMethod) || ((CallableMethod) callable).getGenerateCalleeType() == null) { 2524 return StackValue.none(); 2525 } 2526 2527 // If referenced method is a CallableMethod with generateCalleeType != null, this means it's some kind of a closure 2528 // (e.g. a local named function) and a non-trivial callee should be generated before calling invoke() 2529 2530 BindingContext bindingContext = codegen.bindingContext; 2531 ClassDescriptor closureClassOfReferenced = bindingContext.get(CLASS_FOR_FUNCTION, referencedFunction); 2532 MutableClosure closureOfReferenced = bindingContext.get(CLOSURE, closureClassOfReferenced); 2533 assert closureOfReferenced != null : 2534 "Function mapped to CallableMethod with generateCalleeType != null must be a closure: " + referencedFunction; 2535 if (isConst(closureOfReferenced)) { 2536 // This is an optimization: we can obtain an instance of a const closure simply by GETSTATIC ...$instance 2537 // (instead of passing this instance to the constructor and storing as a field) 2538 Type asmType = asmTypeForAnonymousClass(bindingContext, referencedFunction); 2539 codegen.v.getstatic(asmType.getInternalName(), JvmAbi.INSTANCE_FIELD, asmType.getDescriptor()); 2540 return StackValue.onStack(asmType); 2541 } 2542 else { 2543 Type asmCallRefType = asmTypeForAnonymousClass(bindingContext, callableDescriptor); 2544 return codegen.context.lookupInContext(referencedFunction, StackValue.local(0, asmCallRefType), state, false); 2545 } 2546 } 2547 2548 @NotNull 2549 private JetCallExpression constructFakeFunctionCall() { 2550 StringBuilder fakeFunctionCall = new StringBuilder("callableReferenceFakeCall("); 2551 for (Iterator<ValueParameterDescriptor> iterator = referencedFunction.getValueParameters().iterator(); iterator.hasNext(); ) { 2552 ValueParameterDescriptor descriptor = iterator.next(); 2553 fakeFunctionCall.append("p").append(descriptor.getIndex()); 2554 if (iterator.hasNext()) { 2555 fakeFunctionCall.append(", "); 2556 } 2557 } 2558 fakeFunctionCall.append(")"); 2559 return (JetCallExpression) JetPsiFactory.createExpression(state.getProject(), fakeFunctionCall.toString()); 2560 } 2561 2562 private void computeAndSaveArguments(@NotNull List<? extends ValueArgument> fakeArguments, @NotNull ExpressionCodegen codegen) { 2563 for (ValueParameterDescriptor parameter : callableDescriptor.getValueParameters()) { 2564 ValueArgument fakeArgument = fakeArguments.get(parameter.getIndex()); 2565 Type type = state.getTypeMapper().mapType(parameter); 2566 int localIndex = codegen.myFrameMap.getIndex(parameter); 2567 codegen.tempVariables.put(fakeArgument.getArgumentExpression(), StackValue.local(localIndex, type)); 2568 } 2569 } 2570 2571 @NotNull 2572 private ReceiverValue computeAndSaveReceiver( 2573 @NotNull JvmMethodSignature signature, 2574 @NotNull ExpressionCodegen codegen, 2575 @Nullable ReceiverParameterDescriptor receiver 2576 ) { 2577 if (receiver == null) return NO_RECEIVER; 2578 2579 JetExpression receiverExpression = JetPsiFactory.createExpression(state.getProject(), "callableReferenceFakeReceiver"); 2580 codegen.tempVariables.put(receiverExpression, receiverParameterStackValue(signature)); 2581 return new ExpressionReceiver(receiverExpression, receiver.getType()); 2582 } 2583 2584 @NotNull 2585 private static StackValue.Local receiverParameterStackValue(@NotNull JvmMethodSignature signature) { 2586 // 0 is this (the callable reference class), 1 is the invoke() method's first parameter 2587 return StackValue.local(1, signature.getAsmMethod().getArgumentTypes()[0]); 2588 } 2589 } 2590 2591 @Override 2592 public StackValue visitDotQualifiedExpression(@NotNull JetDotQualifiedExpression expression, StackValue receiver) { 2593 StackValue receiverValue = StackValue.none(); 2594 return genQualified(receiverValue, expression.getSelectorExpression()); 2595 } 2596 2597 @Override 2598 public StackValue visitSafeQualifiedExpression(@NotNull JetSafeQualifiedExpression expression, StackValue unused) { 2599 JetExpression receiver = expression.getReceiverExpression(); 2600 JetExpression selector = expression.getSelectorExpression(); 2601 Type type = boxType(expressionType(expression)); 2602 Type receiverType = expressionType(receiver); 2603 2604 gen(receiver, receiverType); 2605 2606 if (isPrimitive(receiverType)) { 2607 StackValue propValue = genQualified(StackValue.onStack(receiverType), selector); 2608 propValue.put(type, v); 2609 2610 return StackValue.onStack(type); 2611 } 2612 2613 Label ifnull = new Label(); 2614 Label end = new Label(); 2615 v.dup(); 2616 v.ifnull(ifnull); 2617 StackValue propValue = genQualified(StackValue.onStack(receiverType), selector); 2618 propValue.put(type, v); 2619 v.goTo(end); 2620 2621 v.mark(ifnull); 2622 v.pop(); 2623 if (!type.equals(Type.VOID_TYPE)) { 2624 v.aconst(null); 2625 } 2626 v.mark(end); 2627 2628 return StackValue.onStack(type); 2629 } 2630 2631 @Override 2632 public StackValue visitBinaryExpression(@NotNull JetBinaryExpression expression, StackValue receiver) { 2633 JetSimpleNameExpression reference = expression.getOperationReference(); 2634 IElementType opToken = reference.getReferencedNameElementType(); 2635 if (opToken == JetTokens.EQ) { 2636 return generateAssignmentExpression(expression); 2637 } 2638 else if (JetTokens.AUGMENTED_ASSIGNMENTS.contains(opToken)) { 2639 return generateAugmentedAssignment(expression); 2640 } 2641 else if (opToken == JetTokens.ANDAND) { 2642 return generateBooleanAnd(expression); 2643 } 2644 else if (opToken == JetTokens.OROR) { 2645 return generateBooleanOr(expression); 2646 } 2647 else if (opToken == JetTokens.EQEQ || opToken == JetTokens.EXCLEQ || 2648 opToken == JetTokens.EQEQEQ || opToken == JetTokens.EXCLEQEQEQ) { 2649 return generateEquals(expression.getLeft(), expression.getRight(), opToken); 2650 } 2651 else if (opToken == JetTokens.LT || opToken == JetTokens.LTEQ || 2652 opToken == JetTokens.GT || opToken == JetTokens.GTEQ) { 2653 return generateComparison(expression, receiver); 2654 } 2655 else if (opToken == JetTokens.ELVIS) { 2656 return generateElvis(expression); 2657 } 2658 else if (opToken == JetTokens.IN_KEYWORD || opToken == JetTokens.NOT_IN) { 2659 return generateIn(expression); 2660 } 2661 else { 2662 ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, reference); 2663 Call call = bindingContext.get(BindingContext.CALL, reference); 2664 2665 DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, reference); 2666 assert op instanceof FunctionDescriptor : String.valueOf(op); 2667 Callable callable = resolveToCallable((FunctionDescriptor) op, false); 2668 if (callable instanceof IntrinsicMethod) { 2669 //noinspection ConstantConditions 2670 Type returnType = typeMapper.mapType(resolvedCall.getResultingDescriptor()); 2671 ((IntrinsicMethod) callable).generate(this, v, returnType, expression, 2672 Arrays.asList(expression.getLeft(), expression.getRight()), receiver); 2673 return StackValue.onStack(returnType); 2674 } 2675 else { 2676 return invokeFunction(call, receiver, resolvedCall); 2677 } 2678 } 2679 } 2680 2681 private StackValue generateIn(JetBinaryExpression expression) { 2682 boolean inverted = expression.getOperationReference().getReferencedNameElementType() == JetTokens.NOT_IN; 2683 if (isIntRangeExpr(expression.getRight())) { 2684 StackValue leftValue = StackValue.expression(Type.INT_TYPE, expression.getLeft(), this); 2685 JetBinaryExpression rangeExpression = (JetBinaryExpression) expression.getRight(); 2686 getInIntRange(leftValue, rangeExpression, inverted); 2687 } 2688 else { 2689 invokeFunctionByReference(expression.getOperationReference()); 2690 if (inverted) { 2691 genInvertBoolean(v); 2692 } 2693 } 2694 return StackValue.onStack(Type.BOOLEAN_TYPE); 2695 } 2696 2697 private void getInIntRange(StackValue leftValue, JetBinaryExpression rangeExpression, boolean inverted) { 2698 v.iconst(1); 2699 // 1 2700 leftValue.put(Type.INT_TYPE, v); 2701 // 1 l 2702 v.dup2(); 2703 // 1 l 1 l 2704 2705 //noinspection ConstantConditions 2706 gen(rangeExpression.getLeft(), Type.INT_TYPE); 2707 // 1 l 1 l r 2708 Label lok = new Label(); 2709 v.ificmpge(lok); 2710 // 1 l 1 2711 v.pop(); 2712 v.iconst(0); 2713 v.mark(lok); 2714 // 1 l c 2715 v.dupX2(); 2716 // c 1 l c 2717 v.pop(); 2718 // c 1 l 2719 2720 gen(rangeExpression.getRight(), Type.INT_TYPE); 2721 // c 1 l r 2722 Label rok = new Label(); 2723 v.ificmple(rok); 2724 // c 1 2725 v.pop(); 2726 v.iconst(0); 2727 v.mark(rok); 2728 // c c 2729 2730 v.and(Type.INT_TYPE); 2731 if (inverted) { 2732 genInvertBoolean(v); 2733 } 2734 } 2735 2736 private StackValue generateBooleanAnd(JetBinaryExpression expression) { 2737 gen(expression.getLeft(), Type.BOOLEAN_TYPE); 2738 Label ifFalse = new Label(); 2739 v.ifeq(ifFalse); 2740 gen(expression.getRight(), Type.BOOLEAN_TYPE); 2741 Label end = new Label(); 2742 v.goTo(end); 2743 v.mark(ifFalse); 2744 v.iconst(0); 2745 v.mark(end); 2746 return StackValue.onStack(Type.BOOLEAN_TYPE); 2747 } 2748 2749 private StackValue generateBooleanOr(JetBinaryExpression expression) { 2750 gen(expression.getLeft(), Type.BOOLEAN_TYPE); 2751 Label ifTrue = new Label(); 2752 v.ifne(ifTrue); 2753 gen(expression.getRight(), Type.BOOLEAN_TYPE); 2754 Label end = new Label(); 2755 v.goTo(end); 2756 v.mark(ifTrue); 2757 v.iconst(1); 2758 v.mark(end); 2759 return StackValue.onStack(Type.BOOLEAN_TYPE); 2760 } 2761 2762 private StackValue generateEquals(JetExpression left, JetExpression right, IElementType opToken) { 2763 Type leftType = expressionType(left); 2764 Type rightType = expressionType(right); 2765 2766 if (JetPsiUtil.isNullConstant(left)) { 2767 return genCmpWithNull(right, rightType, opToken); 2768 } 2769 2770 if (JetPsiUtil.isNullConstant(right)) { 2771 return genCmpWithNull(left, leftType, opToken); 2772 } 2773 2774 if (isIntZero(left, leftType) && isIntPrimitive(rightType)) { 2775 return genCmpWithZero(right, rightType, opToken); 2776 } 2777 2778 if (isIntZero(right, rightType) && isIntPrimitive(leftType)) { 2779 return genCmpWithZero(left, leftType, opToken); 2780 } 2781 2782 if (isPrimitive(leftType) != isPrimitive(rightType)) { 2783 leftType = boxType(leftType); 2784 gen(left, leftType); 2785 rightType = boxType(rightType); 2786 gen(right, rightType); 2787 } 2788 else { 2789 gen(left, leftType); 2790 gen(right, rightType); 2791 } 2792 2793 return genEqualsForExpressionsOnStack(v, opToken, leftType, rightType); 2794 } 2795 2796 private boolean isIntZero(JetExpression expr, Type exprType) { 2797 CompileTimeConstant<?> exprValue = getCompileTimeConstant(expr, bindingContext); 2798 return isIntPrimitive(exprType) && exprValue != null && exprValue.getValue().equals(0); 2799 } 2800 2801 private StackValue genCmpWithZero(JetExpression exp, Type expType, IElementType opToken) { 2802 v.iconst(1); 2803 gen(exp, expType); 2804 Label ok = new Label(); 2805 if (JetTokens.EQEQ == opToken || JetTokens.EQEQEQ == opToken) { 2806 v.ifeq(ok); 2807 } 2808 else { 2809 v.ifne(ok); 2810 } 2811 v.pop(); 2812 v.iconst(0); 2813 v.mark(ok); 2814 return StackValue.onStack(Type.BOOLEAN_TYPE); 2815 } 2816 2817 private StackValue genCmpWithNull(JetExpression exp, Type expType, IElementType opToken) { 2818 v.iconst(1); 2819 gen(exp, boxType(expType)); 2820 Label ok = new Label(); 2821 if (JetTokens.EQEQ == opToken || JetTokens.EQEQEQ == opToken) { 2822 v.ifnull(ok); 2823 } 2824 else { 2825 v.ifnonnull(ok); 2826 } 2827 v.pop(); 2828 v.iconst(0); 2829 v.mark(ok); 2830 return StackValue.onStack(Type.BOOLEAN_TYPE); 2831 } 2832 2833 private StackValue generateElvis(JetBinaryExpression expression) { 2834 Type exprType = expressionType(expression); 2835 Type leftType = expressionType(expression.getLeft()); 2836 2837 gen(expression.getLeft(), leftType); 2838 2839 if (isPrimitive(leftType)) { 2840 return StackValue.onStack(leftType); 2841 } 2842 2843 v.dup(); 2844 Label ifNull = new Label(); 2845 v.ifnull(ifNull); 2846 StackValue.onStack(leftType).put(exprType, v); 2847 Label end = new Label(); 2848 v.goTo(end); 2849 v.mark(ifNull); 2850 v.pop(); 2851 gen(expression.getRight(), exprType); 2852 v.mark(end); 2853 2854 return StackValue.onStack(exprType); 2855 } 2856 2857 private StackValue generateComparison(JetBinaryExpression expression, StackValue receiver) { 2858 DeclarationDescriptor target = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); 2859 assert target instanceof FunctionDescriptor : "compareTo target should be a function: " + target; 2860 FunctionDescriptor descriptor = (FunctionDescriptor) target; 2861 2862 JetExpression left = expression.getLeft(); 2863 JetExpression right = expression.getRight(); 2864 Callable callable = resolveToCallable(descriptor, false); 2865 2866 Type type; 2867 if (callable instanceof IntrinsicMethod) { 2868 // Compare two primitive values 2869 type = comparisonOperandType(expressionType(left), expressionType(right)); 2870 StackValue recv = gen(left); 2871 recv.put(type, v); 2872 gen(right, type); 2873 } 2874 else { 2875 ResolvedCall<? extends CallableDescriptor> resolvedCall = 2876 bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference()); 2877 Call call = bindingContext.get(BindingContext.CALL, expression.getOperationReference()); 2878 StackValue result = invokeFunction(call, receiver, resolvedCall); 2879 type = Type.INT_TYPE; 2880 result.put(type, v); 2881 v.iconst(0); 2882 } 2883 return StackValue.cmp(expression.getOperationToken(), type); 2884 } 2885 2886 private StackValue generateAssignmentExpression(JetBinaryExpression expression) { 2887 StackValue stackValue = gen(expression.getLeft()); 2888 JetExpression right = expression.getRight(); 2889 assert right != null : expression.getText(); 2890 gen(right, stackValue.type); 2891 stackValue.store(stackValue.type, v); 2892 return StackValue.none(); 2893 } 2894 2895 private StackValue generateAugmentedAssignment(JetBinaryExpression expression) { 2896 DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); 2897 assert op instanceof FunctionDescriptor : String.valueOf(op); 2898 Callable callable = resolveToCallable((FunctionDescriptor) op, false); 2899 JetExpression lhs = expression.getLeft(); 2900 2901 // if (lhs instanceof JetArrayAccessExpression) { 2902 // JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) lhs; 2903 // if (arrayAccessExpression.getIndexExpressions().size() != 1) { 2904 // throw new UnsupportedOperationException("Augmented assignment with multi-index"); 2905 // } 2906 // } 2907 2908 Type lhsType = expressionType(lhs); 2909 //noinspection ConstantConditions 2910 if (bindingContext.get(BindingContext.VARIABLE_REASSIGNMENT, expression)) { 2911 if (callable instanceof IntrinsicMethod) { 2912 StackValue value = gen(lhs); // receiver 2913 value.dupReceiver(v); // receiver receiver 2914 value.put(lhsType, v); // receiver lhs 2915 IntrinsicMethod intrinsic = (IntrinsicMethod) callable; 2916 JetExpression right = expression.getRight(); 2917 assert right != null; 2918 Type returnType = typeMapper.mapType((FunctionDescriptor) op); 2919 intrinsic.generate(this, v, returnType, expression, Collections.singletonList(right), StackValue.onStack(lhsType)); 2920 value.store(lhsType, v); 2921 } 2922 else { 2923 callAugAssignMethod(expression, (CallableMethod) callable, lhsType, true); 2924 } 2925 } 2926 else { 2927 JetType type = ((FunctionDescriptor) op).getReturnType(); 2928 assert type != null; 2929 boolean keepReturnValue = !type.equals(KotlinBuiltIns.getInstance().getUnitType()); 2930 callAugAssignMethod(expression, (CallableMethod) callable, lhsType, keepReturnValue); 2931 } 2932 2933 return StackValue.none(); 2934 } 2935 2936 private void callAugAssignMethod(JetBinaryExpression expression, CallableMethod callable, Type lhsType, boolean keepReturnValue) { 2937 ResolvedCall<? extends CallableDescriptor> resolvedCall = 2938 bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference()); 2939 assert resolvedCall != null; 2940 2941 StackValue value = gen(expression.getLeft()); 2942 if (keepReturnValue) { 2943 value.dupReceiver(v); 2944 } 2945 value.put(lhsType, v); 2946 StackValue receiver = StackValue.onStack(lhsType); 2947 2948 if (!(resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor)) { // otherwise already 2949 receiver = StackValue.receiver(resolvedCall, receiver, this, callable); 2950 receiver.put(receiver.type, v); 2951 } 2952 2953 pushArgumentsAndInvoke(resolvedCall, callable); 2954 2955 if (keepReturnValue) { 2956 value.store(callable.getReturnType(), v); 2957 } 2958 } 2959 2960 public void invokeAppend(JetExpression expr) { 2961 if (expr instanceof JetBinaryExpression) { 2962 JetBinaryExpression binaryExpression = (JetBinaryExpression) expr; 2963 if (binaryExpression.getOperationToken() == JetTokens.PLUS) { 2964 JetExpression left = binaryExpression.getLeft(); 2965 JetExpression right = binaryExpression.getRight(); 2966 Type leftType = expressionType(left); 2967 Type rightType = expressionType(right); 2968 2969 if (leftType.equals(JAVA_STRING_TYPE) && rightType.equals(JAVA_STRING_TYPE)) { 2970 invokeAppend(left); 2971 invokeAppend(right); 2972 return; 2973 } 2974 } 2975 } 2976 Type exprType = expressionType(expr); 2977 gen(expr, exprType); 2978 genInvokeAppendMethod(v, exprType.getSort() == Type.ARRAY ? OBJECT_TYPE : exprType); 2979 } 2980 2981 @Nullable 2982 private static JetSimpleNameExpression targetLabel(JetExpression expression) { 2983 if (expression.getParent() instanceof JetPrefixExpression) { 2984 JetPrefixExpression parent = (JetPrefixExpression) expression.getParent(); 2985 JetSimpleNameExpression operationSign = parent.getOperationReference(); 2986 if (JetTokens.LABELS.contains(operationSign.getReferencedNameElementType())) { 2987 return operationSign; 2988 } 2989 } 2990 return null; 2991 } 2992 2993 @Override 2994 public StackValue visitPrefixExpression(@NotNull JetPrefixExpression expression, StackValue receiver) { 2995 JetSimpleNameExpression operationSign = expression.getOperationReference(); 2996 if (JetTokens.LABELS.contains(operationSign.getReferencedNameElementType())) { 2997 return genQualified(receiver, expression.getBaseExpression()); 2998 } 2999 3000 DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); 3001 assert op instanceof FunctionDescriptor : String.valueOf(op); 3002 Callable callable = resolveToCallable((FunctionDescriptor) op, false); 3003 if (callable instanceof IntrinsicMethod) { 3004 Type returnType = typeMapper.mapType((FunctionDescriptor) op); 3005 ((IntrinsicMethod) callable).generate(this, v, returnType, expression, 3006 Collections.singletonList(expression.getBaseExpression()), receiver); 3007 return StackValue.onStack(returnType); 3008 } 3009 3010 DeclarationDescriptor cls = op.getContainingDeclaration(); 3011 ResolvedCall<? extends CallableDescriptor> resolvedCall = 3012 bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference()); 3013 assert resolvedCall != null; 3014 3015 if (isPrimitiveNumberClassDescriptor(cls) || !(op.getName().asString().equals("inc") || op.getName().asString().equals("dec"))) { 3016 Call call = bindingContext.get(BindingContext.CALL, expression.getOperationReference()); 3017 return invokeFunction(call, receiver, resolvedCall); 3018 } 3019 3020 CallableMethod callableMethod = (CallableMethod) callable; 3021 3022 StackValue value = gen(expression.getBaseExpression()); 3023 value.dupReceiver(v); 3024 value.dupReceiver(v); 3025 3026 Type type = expressionType(expression.getBaseExpression()); 3027 value.put(type, v); 3028 callableMethod.invokeWithNotNullAssertion(v, state, resolvedCall); 3029 3030 value.store(callableMethod.getReturnType(), v); 3031 value.put(type, v); 3032 return StackValue.onStack(type); 3033 } 3034 3035 @Override 3036 public StackValue visitPostfixExpression(@NotNull JetPostfixExpression expression, StackValue receiver) { 3037 if (expression.getOperationReference().getReferencedNameElementType() == JetTokens.EXCLEXCL) { 3038 StackValue base = genQualified(receiver, expression.getBaseExpression()); 3039 if (isPrimitive(base.type)) { 3040 return base; 3041 } 3042 base.put(base.type, v); 3043 v.dup(); 3044 Label ok = new Label(); 3045 v.ifnonnull(ok); 3046 v.invokestatic("jet/runtime/Intrinsics", "throwNpe", "()V"); 3047 v.mark(ok); 3048 return StackValue.onStack(base.type); 3049 } 3050 3051 DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); 3052 if (!(op instanceof FunctionDescriptor)) { 3053 throw new UnsupportedOperationException("Don't know how to generate this postfix expression: " + op); 3054 } 3055 3056 Type asmType = expressionType(expression); 3057 DeclarationDescriptor cls = op.getContainingDeclaration(); 3058 3059 int increment; 3060 if (op.getName().asString().equals("inc")) { 3061 increment = 1; 3062 } 3063 else if (op.getName().asString().equals("dec")) { 3064 increment = -1; 3065 } 3066 else { 3067 throw new UnsupportedOperationException("Unsupported postfix operation: " + op); 3068 } 3069 3070 boolean isPrimitiveNumberClassDescriptor = isPrimitiveNumberClassDescriptor(cls); 3071 if (isPrimitiveNumberClassDescriptor) { 3072 JetExpression operand = expression.getBaseExpression(); 3073 if (operand instanceof JetReferenceExpression && asmType == Type.INT_TYPE) { 3074 int index = indexOfLocal((JetReferenceExpression) operand); 3075 if (index >= 0) { 3076 return StackValue.postIncrement(index, increment); 3077 } 3078 } 3079 } 3080 3081 StackValue value = gen(expression.getBaseExpression()); 3082 value.dupReceiver(v); 3083 3084 Type type = expressionType(expression.getBaseExpression()); 3085 value.put(type, v); // old value 3086 3087 pushReceiverAndValueViaDup(value, type); // receiver and new value 3088 3089 Type storeType; 3090 if (isPrimitiveNumberClassDescriptor) { 3091 genIncrement(asmType, increment, v); 3092 storeType = type; 3093 } 3094 else { 3095 ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference()); 3096 assert resolvedCall != null; 3097 Callable callable = resolveToCallable((FunctionDescriptor) op, false); 3098 CallableMethod callableMethod = (CallableMethod) callable; 3099 callableMethod.invokeWithNotNullAssertion(v, state, resolvedCall); 3100 storeType = callableMethod.getReturnType(); 3101 } 3102 3103 value.store(storeType, v); 3104 return StackValue.onStack(asmType); // old value 3105 } 3106 3107 private void pushReceiverAndValueViaDup(StackValue value, Type type) { 3108 switch (value.receiverSize()) { 3109 case 0: 3110 dup(v, type); 3111 break; 3112 3113 case 1: 3114 if (type.getSize() == 2) { 3115 v.dup2X1(); 3116 } 3117 else { 3118 v.dupX1(); 3119 } 3120 break; 3121 3122 case 2: 3123 if (type.getSize() == 2) { 3124 v.dup2X2(); 3125 } 3126 else { 3127 v.dupX2(); 3128 } 3129 break; 3130 3131 case -1: 3132 throw new UnsupportedOperationException(); 3133 } 3134 } 3135 3136 @Override 3137 public StackValue visitProperty(@NotNull JetProperty property, StackValue receiver) { 3138 final JetExpression initializer = property.getInitializer(); 3139 if (initializer == null) { 3140 return StackValue.none(); 3141 } 3142 initializeLocalVariable(property, new Function<VariableDescriptor, Void>() { 3143 @Override 3144 public Void fun(VariableDescriptor descriptor) { 3145 Type varType = asmType(descriptor.getType()); 3146 gen(initializer, varType); 3147 return null; 3148 } 3149 }); 3150 return StackValue.none(); 3151 } 3152 3153 @Override 3154 public StackValue visitMultiDeclaration(@NotNull JetMultiDeclaration multiDeclaration, StackValue receiver) { 3155 JetExpression initializer = multiDeclaration.getInitializer(); 3156 if (initializer == null) return StackValue.none(); 3157 3158 JetType initializerType = bindingContext.get(EXPRESSION_TYPE, initializer); 3159 assert initializerType != null; 3160 3161 Type initializerAsmType = asmType(initializerType); 3162 3163 final TransientReceiver initializerAsReceiver = new TransientReceiver(initializerType); 3164 3165 int tempVarIndex = myFrameMap.enterTemp(initializerAsmType); 3166 3167 gen(initializer, initializerAsmType); 3168 v.store(tempVarIndex, initializerAsmType); 3169 final StackValue.Local local = StackValue.local(tempVarIndex, initializerAsmType); 3170 3171 for (final JetMultiDeclarationEntry variableDeclaration : multiDeclaration.getEntries()) { 3172 initializeLocalVariable(variableDeclaration, new Function<VariableDescriptor, Void>() { 3173 @Override 3174 public Void fun(VariableDescriptor descriptor) { 3175 ResolvedCall<FunctionDescriptor> resolvedCall = 3176 bindingContext.get(BindingContext.COMPONENT_RESOLVED_CALL, variableDeclaration); 3177 assert resolvedCall != null : "Resolved call is null for " + variableDeclaration.getText(); 3178 Call call = makeFakeCall(initializerAsReceiver); 3179 invokeFunction(call, local, resolvedCall); 3180 return null; 3181 } 3182 }); 3183 } 3184 3185 if(initializerAsmType.getSort() == Type.OBJECT || initializerAsmType.getSort() == Type.ARRAY) { 3186 v.aconst(null); 3187 v.store(tempVarIndex, initializerAsmType); 3188 } 3189 myFrameMap.leaveTemp(initializerAsmType); 3190 3191 return StackValue.none(); 3192 } 3193 3194 private void initializeLocalVariable( 3195 @NotNull JetVariableDeclaration variableDeclaration, 3196 @NotNull Function<VariableDescriptor, Void> generateInitializer 3197 ) { 3198 3199 VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, variableDeclaration); 3200 3201 if (JetPsiUtil.isScriptDeclaration(variableDeclaration)) { 3202 return; 3203 } 3204 int index = lookupLocalIndex(variableDescriptor); 3205 3206 if (index < 0) { 3207 throw new IllegalStateException("Local variable not found for " + variableDescriptor); 3208 } 3209 3210 Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor); 3211 assert variableDescriptor != null; 3212 3213 Type varType = asmType(variableDescriptor.getType()); 3214 3215 if (JetPsiUtil.isScriptDeclaration(variableDeclaration)) { 3216 generateInitializer.fun(variableDescriptor); 3217 JetScript scriptPsi = JetPsiUtil.getScript(variableDeclaration); 3218 assert scriptPsi != null; 3219 Type scriptClassType = asmTypeForScriptPsi(bindingContext, scriptPsi); 3220 v.putfield(scriptClassType.getInternalName(), variableDeclaration.getName(), varType.getDescriptor()); 3221 } 3222 else if (sharedVarType == null) { 3223 generateInitializer.fun(variableDescriptor); 3224 v.store(index, varType); 3225 } 3226 else { 3227 v.load(index, OBJECT_TYPE); 3228 generateInitializer.fun(variableDescriptor); 3229 v.putfield(sharedVarType.getInternalName(), "ref", 3230 sharedVarType == JET_SHARED_VAR_TYPE ? "Ljava/lang/Object;" : varType.getDescriptor()); 3231 } 3232 } 3233 3234 @NotNull 3235 private StackValue generateNewCall( 3236 @NotNull JetCallExpression expression, 3237 @NotNull ResolvedCall<? extends CallableDescriptor> resolvedCall, 3238 @NotNull StackValue receiver 3239 ) { 3240 Type type = expressionType(expression); 3241 if (type.getSort() == Type.ARRAY) { 3242 generateNewArray(expression); 3243 return StackValue.onStack(type); 3244 } 3245 3246 return generateConstructorCall(resolvedCall, receiver, type); 3247 } 3248 3249 @NotNull 3250 private StackValue generateConstructorCall( 3251 @NotNull ResolvedCall<? extends CallableDescriptor> resolvedCall, 3252 @NotNull StackValue receiver, 3253 @NotNull Type type 3254 ) { 3255 v.anew(type); 3256 v.dup(); 3257 3258 receiver = StackValue.receiver(resolvedCall, receiver, this, null); 3259 receiver.put(receiver.type, v); 3260 3261 ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor(); 3262 MutableClosure closure = bindingContext.get(CLOSURE, constructorDescriptor.getContainingDeclaration()); 3263 3264 ClassDescriptor descriptor = getExpectedThisObjectForConstructorCall(constructorDescriptor, closure); 3265 if (receiver.type.getSort() != Type.VOID && descriptor == null) { 3266 v.pop(); 3267 } 3268 3269 //Resolved call to local class constructor doesn't have resolvedCall.getThisObject() and resolvedCall.getReceiverArgument() 3270 //so we need generate closure on stack 3271 //See StackValue.receiver for more info 3272 pushClosureOnStack(closure, resolvedCall.getThisObject().exists() || resolvedCall.getReceiverArgument().exists()); 3273 3274 ConstructorDescriptor originalOfSamAdapter = (ConstructorDescriptor) SamCodegenUtil.getOriginalIfSamAdapter(constructorDescriptor); 3275 CallableMethod method = typeMapper.mapToCallableMethod(originalOfSamAdapter == null ? constructorDescriptor : originalOfSamAdapter); 3276 invokeMethodWithArguments(method, resolvedCall, StackValue.none()); 3277 3278 return StackValue.onStack(type); 3279 } 3280 3281 public void generateNewArray(@NotNull JetCallExpression expression) { 3282 JetType arrayType = bindingContext.get(EXPRESSION_TYPE, expression); 3283 assert arrayType != null : "Array instantiation isn't type checked: " + expression.getText(); 3284 3285 generateNewArray(expression, arrayType); 3286 } 3287 3288 private void generateNewArray(@NotNull JetCallExpression expression, @NotNull JetType arrayType) { 3289 List<JetExpression> args = new ArrayList<JetExpression>(); 3290 for (ValueArgument va : expression.getValueArguments()) { 3291 args.add(va.getArgumentExpression()); 3292 } 3293 args.addAll(expression.getFunctionLiteralArguments()); 3294 3295 boolean isArray = KotlinBuiltIns.getInstance().isArray(arrayType); 3296 if (!isArray && args.size() != 1) { 3297 throw new CompilationException("primitive array constructor requires one argument", null, expression); 3298 } 3299 3300 if (isArray) { 3301 gen(args.get(0), Type.INT_TYPE); 3302 v.newarray(boxType(asmType(arrayType.getArguments().get(0).getType()))); 3303 } 3304 else { 3305 Type type = typeMapper.mapType(arrayType); 3306 gen(args.get(0), Type.INT_TYPE); 3307 v.newarray(correctElementType(type)); 3308 } 3309 3310 if (args.size() == 2) { 3311 int sizeIndex = myFrameMap.enterTemp(Type.INT_TYPE); 3312 int indexIndex = myFrameMap.enterTemp(Type.INT_TYPE); 3313 3314 v.dup(); 3315 v.arraylength(); 3316 v.store(sizeIndex, Type.INT_TYPE); 3317 3318 v.iconst(0); 3319 v.store(indexIndex, Type.INT_TYPE); 3320 3321 gen(args.get(1), JET_FUNCTION1_TYPE); 3322 3323 Label begin = new Label(); 3324 Label end = new Label(); 3325 v.visitLabel(begin); 3326 v.load(indexIndex, Type.INT_TYPE); 3327 v.load(sizeIndex, Type.INT_TYPE); 3328 v.ificmpge(end); 3329 3330 v.dup2(); 3331 v.load(indexIndex, Type.INT_TYPE); 3332 v.invokestatic("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;"); 3333 v.invokeinterface("jet/Function1", "invoke", "(Ljava/lang/Object;)Ljava/lang/Object;"); 3334 v.load(indexIndex, Type.INT_TYPE); 3335 v.iinc(indexIndex, 1); 3336 v.swap(); 3337 v.astore(OBJECT_TYPE); 3338 3339 v.goTo(begin); 3340 v.visitLabel(end); 3341 v.pop(); 3342 3343 myFrameMap.leaveTemp(Type.INT_TYPE); 3344 myFrameMap.leaveTemp(Type.INT_TYPE); 3345 } 3346 } 3347 3348 @Override 3349 public StackValue visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression, StackValue receiver) { 3350 JetExpression array = expression.getArrayExpression(); 3351 JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, array); 3352 Type arrayType = asmTypeOrVoid(type); 3353 List<JetExpression> indices = expression.getIndexExpressions(); 3354 FunctionDescriptor operationDescriptor = (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, expression); 3355 assert operationDescriptor != null; 3356 if (arrayType.getSort() == Type.ARRAY && 3357 indices.size() == 1 && 3358 operationDescriptor.getValueParameters().get(0).getType().equals(KotlinBuiltIns.getInstance().getIntType())) { 3359 gen(array, arrayType); 3360 for (JetExpression index : indices) { 3361 gen(index, Type.INT_TYPE); 3362 } 3363 assert type != null; 3364 if (KotlinBuiltIns.getInstance().isArray(type)) { 3365 JetType elementType = type.getArguments().get(0).getType(); 3366 Type notBoxed = asmType(elementType); 3367 return StackValue.arrayElement(notBoxed, true); 3368 } 3369 else { 3370 return StackValue.arrayElement(correctElementType(arrayType), false); 3371 } 3372 } 3373 else { 3374 ResolvedCall<FunctionDescriptor> resolvedSetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_SET, expression); 3375 ResolvedCall<FunctionDescriptor> resolvedGetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_GET, expression); 3376 3377 boolean isGetter = "get".equals(operationDescriptor.getName().asString()); 3378 3379 ResolvedCall<FunctionDescriptor> resolvedCall = isGetter ? resolvedGetCall : resolvedSetCall; 3380 assert resolvedCall != null : "couldn't find resolved call: " + expression.getText(); 3381 3382 Callable callable = resolveToCallable(operationDescriptor, false); 3383 if (callable instanceof CallableMethod) { 3384 genThisAndReceiverFromResolvedCall(receiver, resolvedCall, (CallableMethod) callable); 3385 } 3386 else { 3387 gen(array, arrayType); // intrinsic method 3388 } 3389 3390 int index = operationDescriptor.getReceiverParameter() != null ? 1 : 0; 3391 3392 Method asmMethod = resolveToCallableMethod(operationDescriptor, false, context).getSignature().getAsmMethod(); 3393 Type[] argumentTypes = asmMethod.getArgumentTypes(); 3394 for (JetExpression jetExpression : expression.getIndexExpressions()) { 3395 gen(jetExpression, argumentTypes[index]); 3396 index++; 3397 } 3398 3399 Type elementType = isGetter ? asmMethod.getReturnType() : ArrayUtil.getLastElement(argumentTypes); 3400 return StackValue.collectionElement(elementType, resolvedGetCall, resolvedSetCall, this, state); 3401 } 3402 } 3403 3404 @Override 3405 public StackValue visitThrowExpression(@NotNull JetThrowExpression expression, StackValue receiver) { 3406 gen(expression.getThrownExpression(), JAVA_THROWABLE_TYPE); 3407 v.athrow(); 3408 return StackValue.none(); 3409 } 3410 3411 @Override 3412 public StackValue visitThisExpression(@NotNull JetThisExpression expression, StackValue receiver) { 3413 DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference()); 3414 if (descriptor instanceof ClassDescriptor) { 3415 return StackValue.thisOrOuter(this, (ClassDescriptor) descriptor, false); 3416 } 3417 else { 3418 if (descriptor instanceof CallableDescriptor) { 3419 return generateReceiver(descriptor); 3420 } 3421 throw new UnsupportedOperationException("neither this nor receiver"); 3422 } 3423 } 3424 3425 @Override 3426 public StackValue visitTryExpression(@NotNull JetTryExpression expression, StackValue receiver) { 3427 return generateTryExpression(expression, false); 3428 } 3429 3430 public StackValue generateTryExpression(JetTryExpression expression, boolean isStatement) { 3431 /* 3432 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 3433 (or blocks). 3434 */ 3435 JetFinallySection finallyBlock = expression.getFinallyBlock(); 3436 FinallyBlockStackElement finallyBlockStackElement = null; 3437 if (finallyBlock != null) { 3438 finallyBlockStackElement = new FinallyBlockStackElement(expression); 3439 blockStackElements.push(finallyBlockStackElement); 3440 } 3441 3442 JetType jetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression); 3443 assert jetType != null; 3444 Type expectedAsmType = isStatement ? Type.VOID_TYPE : asmType(jetType); 3445 3446 Label tryStart = new Label(); 3447 v.mark(tryStart); 3448 v.nop(); // prevent verify error on empty try 3449 3450 gen(expression.getTryBlock(), expectedAsmType); 3451 3452 int savedValue = -1; 3453 if (!isStatement) { 3454 savedValue = myFrameMap.enterTemp(expectedAsmType); 3455 v.store(savedValue, expectedAsmType); 3456 } 3457 3458 Label tryEnd = new Label(); 3459 v.mark(tryEnd); 3460 3461 //do it before finally block generation 3462 List<Label> tryBlockRegions = getCurrentCatchIntervals(finallyBlockStackElement, tryStart, tryEnd); 3463 3464 Label end = new Label(); 3465 3466 genFinallyBlockOrGoto(finallyBlockStackElement, end); 3467 3468 List<JetCatchClause> clauses = expression.getCatchClauses(); 3469 for (int i = 0, size = clauses.size(); i < size; i++) { 3470 JetCatchClause clause = clauses.get(i); 3471 3472 Label clauseStart = new Label(); 3473 v.mark(clauseStart); 3474 3475 VariableDescriptor descriptor = bindingContext.get(BindingContext.VALUE_PARAMETER, clause.getCatchParameter()); 3476 assert descriptor != null; 3477 Type descriptorType = asmType(descriptor.getType()); 3478 myFrameMap.enter(descriptor, descriptorType); 3479 int index = lookupLocalIndex(descriptor); 3480 v.store(index, descriptorType); 3481 3482 gen(clause.getCatchBody(), expectedAsmType); 3483 3484 if (!isStatement) { 3485 v.store(savedValue, expectedAsmType); 3486 } 3487 3488 myFrameMap.leave(descriptor); 3489 3490 genFinallyBlockOrGoto(finallyBlockStackElement, i != size - 1 || finallyBlock != null ? end : null); 3491 3492 generateExceptionTable(clauseStart, tryBlockRegions, descriptorType.getInternalName()); 3493 } 3494 3495 3496 //for default catch clause 3497 if (finallyBlock != null) { 3498 Label defaultCatchStart = new Label(); 3499 v.mark(defaultCatchStart); 3500 int savedException = myFrameMap.enterTemp(JAVA_THROWABLE_TYPE); 3501 v.store(savedException, JAVA_THROWABLE_TYPE); 3502 Label defaultCatchEnd = new Label(); 3503 v.mark(defaultCatchEnd); 3504 3505 //do it before finally block generation 3506 //javac also generates entry in exception table for default catch clause too!!!! so defaultCatchEnd as end parameter 3507 List<Label> defaultCatchRegions = getCurrentCatchIntervals(finallyBlockStackElement, tryStart, defaultCatchEnd); 3508 3509 3510 genFinallyBlockOrGoto(finallyBlockStackElement, null); 3511 3512 v.load(savedException, JAVA_THROWABLE_TYPE); 3513 myFrameMap.leaveTemp(JAVA_THROWABLE_TYPE); 3514 3515 v.athrow(); 3516 3517 generateExceptionTable(defaultCatchStart, defaultCatchRegions, null); 3518 } 3519 3520 markLineNumber(expression); 3521 v.mark(end); 3522 3523 if (!isStatement) { 3524 v.load(savedValue, expectedAsmType); 3525 myFrameMap.leaveTemp(expectedAsmType); 3526 } 3527 3528 if (finallyBlock != null) { 3529 blockStackElements.pop(); 3530 } 3531 3532 return StackValue.onStack(expectedAsmType); 3533 } 3534 3535 private void generateExceptionTable(@NotNull Label catchStart, @NotNull List<Label> catchedRegions, @Nullable String exception) { 3536 for (int i = 0; i < catchedRegions.size(); i += 2) { 3537 Label startRegion = catchedRegions.get(i); 3538 Label endRegion = catchedRegions.get(i+1); 3539 v.visitTryCatchBlock(startRegion, endRegion, catchStart, exception); 3540 } 3541 } 3542 3543 @NotNull 3544 private static List<Label> getCurrentCatchIntervals( 3545 @Nullable FinallyBlockStackElement finallyBlockStackElement, 3546 @NotNull Label blockStart, 3547 @NotNull Label blockEnd 3548 ) { 3549 List<Label> gapsInBlock = 3550 finallyBlockStackElement != null ? new ArrayList<Label>(finallyBlockStackElement.gaps) : Collections.<Label>emptyList(); 3551 assert gapsInBlock.size() % 2 == 0; 3552 List<Label> blockRegions = new ArrayList<Label>(gapsInBlock.size() + 2); 3553 blockRegions.add(blockStart); 3554 blockRegions.addAll(gapsInBlock); 3555 blockRegions.add(blockEnd); 3556 return blockRegions; 3557 } 3558 3559 @Override 3560 public StackValue visitBinaryWithTypeRHSExpression(@NotNull JetBinaryExpressionWithTypeRHS expression, StackValue receiver) { 3561 JetSimpleNameExpression operationSign = expression.getOperationReference(); 3562 IElementType opToken = operationSign.getReferencedNameElementType(); 3563 if (opToken == JetTokens.COLON) { 3564 return gen(expression.getLeft()); 3565 } 3566 else { 3567 JetTypeReference typeReference = expression.getRight(); 3568 JetType rightType = bindingContext.get(BindingContext.TYPE, typeReference); 3569 assert rightType != null; 3570 Type rightTypeAsm = boxType(asmType(rightType)); 3571 JetExpression left = expression.getLeft(); 3572 DeclarationDescriptor descriptor = rightType.getConstructor().getDeclarationDescriptor(); 3573 if (descriptor instanceof ClassDescriptor || descriptor instanceof TypeParameterDescriptor) { 3574 StackValue value = genQualified(receiver, left); 3575 value.put(boxType(value.type), v); 3576 3577 if (opToken != JetTokens.AS_SAFE) { 3578 if (!CodegenUtil.isNullableType(rightType)) { 3579 v.dup(); 3580 Label nonnull = new Label(); 3581 v.ifnonnull(nonnull); 3582 JetType leftType = bindingContext.get(BindingContext.EXPRESSION_TYPE, left); 3583 assert leftType != null; 3584 throwNewException(CLASS_TYPE_CAST_EXCEPTION, DescriptorRenderer.TEXT.renderType(leftType) + 3585 " cannot be cast to " + 3586 DescriptorRenderer.TEXT.renderType(rightType)); 3587 v.mark(nonnull); 3588 } 3589 } 3590 else { 3591 v.dup(); 3592 v.instanceOf(rightTypeAsm); 3593 Label ok = new Label(); 3594 v.ifne(ok); 3595 v.pop(); 3596 v.aconst(null); 3597 v.mark(ok); 3598 } 3599 3600 v.checkcast(rightTypeAsm); 3601 return StackValue.onStack(rightTypeAsm); 3602 } 3603 else { 3604 throw new UnsupportedOperationException("Don't know how to handle non-class types in as/as? : " + descriptor); 3605 } 3606 } 3607 } 3608 3609 @Override 3610 public StackValue visitIsExpression(@NotNull JetIsExpression expression, StackValue receiver) { 3611 StackValue match = StackValue.expression(OBJECT_TYPE, expression.getLeftHandSide(), this); 3612 return generateIsCheck(match, expression.getTypeRef(), expression.isNegated()); 3613 } 3614 3615 private StackValue generateExpressionMatch(StackValue expressionToMatch, JetExpression patternExpression) { 3616 if (expressionToMatch != null) { 3617 Type subjectType = expressionToMatch.type; 3618 expressionToMatch.dupReceiver(v); 3619 expressionToMatch.put(subjectType, v); 3620 JetType condJetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, patternExpression); 3621 Type condType; 3622 if (isNumberPrimitive(subjectType) || subjectType.getSort() == Type.BOOLEAN) { 3623 assert condJetType != null; 3624 condType = asmType(condJetType); 3625 if (!(isNumberPrimitive(condType) || condType.getSort() == Type.BOOLEAN)) { 3626 subjectType = boxType(subjectType); 3627 expressionToMatch.coerceTo(subjectType, v); 3628 } 3629 } 3630 else { 3631 condType = OBJECT_TYPE; 3632 } 3633 gen(patternExpression, condType); 3634 return genEqualsForExpressionsOnStack(v, JetTokens.EQEQ, subjectType, condType); 3635 } 3636 else { 3637 return gen(patternExpression); 3638 } 3639 } 3640 3641 private StackValue generateIsCheck(StackValue expressionToMatch, JetTypeReference typeReference, boolean negated) { 3642 JetType jetType = bindingContext.get(BindingContext.TYPE, typeReference); 3643 expressionToMatch.dupReceiver(v); 3644 generateInstanceOf(expressionToMatch, jetType, false); 3645 StackValue value = StackValue.onStack(Type.BOOLEAN_TYPE); 3646 return negated ? StackValue.not(value) : value; 3647 } 3648 3649 private void generateInstanceOf(StackValue expressionToGen, JetType jetType, boolean leaveExpressionOnStack) { 3650 expressionToGen.put(OBJECT_TYPE, v); 3651 if (leaveExpressionOnStack) { 3652 v.dup(); 3653 } 3654 Type type = boxType(asmType(jetType)); 3655 if (jetType.isNullable()) { 3656 Label nope = new Label(); 3657 Label end = new Label(); 3658 3659 v.dup(); 3660 v.ifnull(nope); 3661 v.instanceOf(type); 3662 v.goTo(end); 3663 v.mark(nope); 3664 v.pop(); 3665 v.iconst(1); 3666 v.mark(end); 3667 } 3668 else { 3669 v.instanceOf(type); 3670 } 3671 } 3672 3673 @Override 3674 public StackValue visitWhenExpression(@NotNull JetWhenExpression expression, StackValue receiver) { 3675 return generateWhenExpression(expression, false); 3676 } 3677 3678 public StackValue generateWhenExpression(JetWhenExpression expression, boolean isStatement) { 3679 JetExpression expr = expression.getSubjectExpression(); 3680 JetType subjectJetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expr); 3681 Type subjectType = asmTypeOrVoid(subjectJetType); 3682 Type resultType = isStatement ? Type.VOID_TYPE : expressionType(expression); 3683 int subjectLocal = expr != null ? myFrameMap.enterTemp(subjectType) : -1; 3684 if (subjectLocal != -1) { 3685 gen(expr, subjectType); 3686 tempVariables.put(expr, StackValue.local(subjectLocal, subjectType)); 3687 v.store(subjectLocal, subjectType); 3688 } 3689 3690 Label end = new Label(); 3691 boolean hasElse = JetPsiUtil.checkWhenExpressionHasSingleElse(expression); 3692 3693 Label nextCondition = null; 3694 for (JetWhenEntry whenEntry : expression.getEntries()) { 3695 if (nextCondition != null) { 3696 v.mark(nextCondition); 3697 } 3698 nextCondition = new Label(); 3699 FrameMap.Mark mark = myFrameMap.mark(); 3700 Label thisEntry = new Label(); 3701 if (!whenEntry.isElse()) { 3702 JetWhenCondition[] conditions = whenEntry.getConditions(); 3703 for (int i = 0; i < conditions.length; i++) { 3704 StackValue conditionValue = generateWhenCondition(subjectType, subjectLocal, conditions[i]); 3705 conditionValue.condJump(nextCondition, true, v); 3706 if (i < conditions.length - 1) { 3707 v.goTo(thisEntry); 3708 v.mark(nextCondition); 3709 nextCondition = new Label(); 3710 } 3711 } 3712 } 3713 3714 v.visitLabel(thisEntry); 3715 gen(whenEntry.getExpression(), resultType); 3716 mark.dropTo(); 3717 if (!whenEntry.isElse()) { 3718 v.goTo(end); 3719 } 3720 } 3721 if (!hasElse && nextCondition != null) { 3722 v.mark(nextCondition); 3723 if (!isStatement) { 3724 // a result is expected 3725 if (Boolean.TRUE.equals(bindingContext.get(BindingContext.EXHAUSTIVE_WHEN, expression))) { 3726 // when() is supposed to be exhaustive 3727 throwNewException(CLASS_NO_PATTERN_MATCHED_EXCEPTION); 3728 } 3729 else { 3730 // non-exhaustive when() with no else -> Unit must be expected 3731 StackValue.putUnitInstance(v); 3732 } 3733 } 3734 } 3735 3736 markLineNumber(expression); 3737 v.mark(end); 3738 3739 myFrameMap.leaveTemp(subjectType); 3740 tempVariables.remove(expr); 3741 return StackValue.onStack(resultType); 3742 } 3743 3744 private StackValue generateWhenCondition(Type subjectType, int subjectLocal, JetWhenCondition condition) { 3745 if (condition instanceof JetWhenConditionInRange) { 3746 JetWhenConditionInRange conditionInRange = (JetWhenConditionInRange) condition; 3747 JetExpression rangeExpression = conditionInRange.getRangeExpression(); 3748 while (rangeExpression instanceof JetParenthesizedExpression) { 3749 rangeExpression = ((JetParenthesizedExpression) rangeExpression).getExpression(); 3750 } 3751 JetSimpleNameExpression operationReference = conditionInRange.getOperationReference(); 3752 boolean inverted = operationReference.getReferencedNameElementType() == JetTokens.NOT_IN; 3753 if (isIntRangeExpr(rangeExpression)) { 3754 getInIntRange(new StackValue.Local(subjectLocal, subjectType), (JetBinaryExpression) rangeExpression, inverted); 3755 } 3756 else { 3757 //FunctionDescriptor op = 3758 // (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, conditionInRange.getOperationReference()); 3759 //genToJVMStack(rangeExpression); 3760 //new StackValue.Local(subjectLocal, subjectType).put(OBJECT_TYPE, v); 3761 //invokeFunctionNoParams(op, Type.BOOLEAN_TYPE, v); 3762 invokeFunctionByReference(operationReference); 3763 if (inverted) { 3764 genInvertBoolean(v); 3765 } 3766 } 3767 return StackValue.onStack(Type.BOOLEAN_TYPE); 3768 } 3769 StackValue.Local match = subjectLocal == -1 ? null : StackValue.local(subjectLocal, subjectType); 3770 if (condition instanceof JetWhenConditionIsPattern) { 3771 JetWhenConditionIsPattern patternCondition = (JetWhenConditionIsPattern) condition; 3772 return generateIsCheck(match, patternCondition.getTypeRef(), patternCondition.isNegated()); 3773 } 3774 else if (condition instanceof JetWhenConditionWithExpression) { 3775 JetExpression patternExpression = ((JetWhenConditionWithExpression) condition).getExpression(); 3776 return generateExpressionMatch(match, patternExpression); 3777 } 3778 else { 3779 throw new UnsupportedOperationException("unsupported kind of when condition"); 3780 } 3781 } 3782 3783 private void invokeFunctionByReference(JetSimpleNameExpression operationReference) { 3784 ResolvedCall<? extends CallableDescriptor> resolvedCall = 3785 bindingContext.get(RESOLVED_CALL, operationReference); 3786 Call call = bindingContext.get(CALL, operationReference); 3787 invokeFunction(call, StackValue.none(), resolvedCall); 3788 } 3789 3790 private boolean isIntRangeExpr(JetExpression rangeExpression) { 3791 if (rangeExpression instanceof JetBinaryExpression) { 3792 JetBinaryExpression binaryExpression = (JetBinaryExpression) rangeExpression; 3793 if (binaryExpression.getOperationReference().getReferencedNameElementType() == JetTokens.RANGE) { 3794 JetType jetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, rangeExpression); 3795 assert jetType != null; 3796 DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor(); 3797 return INTEGRAL_RANGES.contains(descriptor); 3798 } 3799 } 3800 return false; 3801 } 3802 3803 private void throwNewException(@NotNull String className) { 3804 throwNewException(className, null); 3805 } 3806 3807 private void throwNewException(@NotNull String className, @Nullable String message) { 3808 v.anew(Type.getObjectType(className)); 3809 v.dup(); 3810 if (message != null) { 3811 v.visitLdcInsn(message); 3812 v.invokespecial(className, "<init>", "(Ljava/lang/String;)V"); 3813 } 3814 else { 3815 v.invokespecial(className, "<init>", "()V"); 3816 } 3817 v.athrow(); 3818 } 3819 3820 private Call makeFakeCall(ReceiverValue initializerAsReceiver) { 3821 JetSimpleNameExpression fake = JetPsiFactory.createSimpleName(state.getProject(), "fake"); 3822 return CallMaker.makeCall(fake, initializerAsReceiver); 3823 } 3824 3825 @Override 3826 public String toString() { 3827 return context.getContextDescriptor().toString(); 3828 } 3829 3830 @NotNull 3831 private ScriptCodegen getParentScriptCodegen() { 3832 MemberCodegen codegen = parentCodegen; 3833 while (codegen != null) { 3834 if (codegen instanceof ScriptCodegen) { 3835 return (ScriptCodegen) codegen; 3836 } 3837 codegen = codegen.getParentCodegen(); 3838 } 3839 throw new IllegalStateException("Script codegen should be present in codegen tree"); 3840 } 3841 }