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