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