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