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