326 if (symbol.getUseCount() > SharedScopeCall.FAST_SCOPE_GET_THRESHOLD && !isOptimisticOrRestOf()) {
327 method.loadCompilerConstant(SCOPE);
328 // As shared scope vars are only used in non-optimistic compilation, we switch from using TypeBounds to
329 // just a single definitive type, resultBounds.widest.
330 loadSharedScopeVar(resultBounds.widest, symbol, flags);
331 } else {
332 new LoadFastScopeVar(identNode, resultBounds, flags).emit();
333 }
334 } else {
335 //slow scope load, we have no proto depth
336 new LoadScopeVar(identNode, resultBounds, flags).emit();
337 }
338
339 return method;
340 }
341
342 // Any access to LET and CONST variables before their declaration must throw ReferenceError.
343 // This is called the temporal dead zone (TDZ). See https://gist.github.com/rwaldron/f0807a758aa03bcdd58a
344 private void checkTemporalDeadZone(final IdentNode identNode) {
345 if (identNode.isDead()) {
346 method.load(identNode.getSymbol().getName());
347 method.invoke(ScriptRuntime.THROW_REFERENCE_ERROR);
348 }
349 }
350
351 private boolean isRestOf() {
352 return continuationEntryPoints != null;
353 }
354
355 private boolean isOptimisticOrRestOf() {
356 return useOptimisticTypes() || isRestOf();
357 }
358
359 private boolean isCurrentContinuationEntryPoint(final int programPoint) {
360 return isRestOf() && getCurrentContinuationEntryPoint() == programPoint;
361 }
362
363 private int[] getContinuationEntryPoints() {
364 return isRestOf() ? continuationEntryPoints : null;
365 }
366
367 private int getCurrentContinuationEntryPoint() {
770 }.emit(baseAlreadyOnStack ? 2 : 0);
771 return false;
772 }
773
774 @Override
775 public boolean enterFunctionNode(final FunctionNode functionNode) {
776 // function nodes will always leave a constructed function object on stack, no need to load the symbol
777 // separately as in enterDefault()
778 lc.pop(functionNode);
779 functionNode.accept(codegen);
780 // NOTE: functionNode.accept() will produce a different FunctionNode that we discard. This incidentally
781 // doesn't cause problems as we're never touching FunctionNode again after it's visited here - codegen
782 // is the last element in the compilation pipeline, the AST it produces is not used externally. So, we
783 // re-push the original functionNode.
784 lc.push(functionNode);
785 return false;
786 }
787
788 @Override
789 public boolean enterASSIGN(final BinaryNode binaryNode) {
790 loadASSIGN(binaryNode);
791 return false;
792 }
793
794 @Override
795 public boolean enterASSIGN_ADD(final BinaryNode binaryNode) {
796 loadASSIGN_ADD(binaryNode);
797 return false;
798 }
799
800 @Override
801 public boolean enterASSIGN_BIT_AND(final BinaryNode binaryNode) {
802 loadASSIGN_BIT_AND(binaryNode);
803 return false;
804 }
805
806 @Override
807 public boolean enterASSIGN_BIT_OR(final BinaryNode binaryNode) {
808 loadASSIGN_BIT_OR(binaryNode);
809 return false;
810 }
811
812 @Override
813 public boolean enterASSIGN_BIT_XOR(final BinaryNode binaryNode) {
814 loadASSIGN_BIT_XOR(binaryNode);
815 return false;
816 }
817
818 @Override
819 public boolean enterASSIGN_DIV(final BinaryNode binaryNode) {
820 loadASSIGN_DIV(binaryNode);
821 return false;
822 }
823
824 @Override
825 public boolean enterASSIGN_MOD(final BinaryNode binaryNode) {
826 loadASSIGN_MOD(binaryNode);
827 return false;
828 }
829
830 @Override
831 public boolean enterASSIGN_MUL(final BinaryNode binaryNode) {
832 loadASSIGN_MUL(binaryNode);
833 return false;
834 }
835
836 @Override
837 public boolean enterASSIGN_SAR(final BinaryNode binaryNode) {
838 loadASSIGN_SAR(binaryNode);
839 return false;
840 }
841
842 @Override
843 public boolean enterASSIGN_SHL(final BinaryNode binaryNode) {
844 loadASSIGN_SHL(binaryNode);
845 return false;
846 }
847
848 @Override
849 public boolean enterASSIGN_SHR(final BinaryNode binaryNode) {
850 loadASSIGN_SHR(binaryNode);
851 return false;
852 }
853
854 @Override
855 public boolean enterASSIGN_SUB(final BinaryNode binaryNode) {
856 loadASSIGN_SUB(binaryNode);
857 return false;
858 }
859
860 @Override
861 public boolean enterCallNode(final CallNode callNode) {
862 return loadCallNode(callNode, resultBounds);
863 }
864
865 @Override
866 public boolean enterLiteralNode(final LiteralNode<?> literalNode) {
867 loadLiteral(literalNode, resultBounds);
868 return false;
869 }
870
871 @Override
872 public boolean enterTernaryNode(final TernaryNode ternaryNode) {
873 loadTernaryNode(ternaryNode, resultBounds);
874 return false;
875 }
1045 @Override
1046 public boolean enterObjectNode(final ObjectNode objectNode) {
1047 loadObjectNode(objectNode);
1048 return false;
1049 }
1050
1051 @Override
1052 public boolean enterRuntimeNode(final RuntimeNode runtimeNode) {
1053 loadRuntimeNode(runtimeNode);
1054 return false;
1055 }
1056
1057 @Override
1058 public boolean enterNEW(final UnaryNode unaryNode) {
1059 loadNEW(unaryNode);
1060 return false;
1061 }
1062
1063 @Override
1064 public boolean enterDECINC(final UnaryNode unaryNode) {
1065 loadDECINC(unaryNode);
1066 return false;
1067 }
1068
1069 @Override
1070 public boolean enterJoinPredecessorExpression(final JoinPredecessorExpression joinExpr) {
1071 loadExpression(joinExpr.getExpression(), resultBounds);
1072 return false;
1073 }
1074
1075 @Override
1076 public boolean enterGetSplitState(final GetSplitState getSplitState) {
1077 method.loadScope();
1078 method.invoke(Scope.GET_SPLIT_STATE);
1079 return false;
1080 }
1081
1082 @Override
1083 public boolean enterDefault(final Node otherNode) {
1084 // Must have handled all expressions that can legally be encountered.
|
326 if (symbol.getUseCount() > SharedScopeCall.FAST_SCOPE_GET_THRESHOLD && !isOptimisticOrRestOf()) {
327 method.loadCompilerConstant(SCOPE);
328 // As shared scope vars are only used in non-optimistic compilation, we switch from using TypeBounds to
329 // just a single definitive type, resultBounds.widest.
330 loadSharedScopeVar(resultBounds.widest, symbol, flags);
331 } else {
332 new LoadFastScopeVar(identNode, resultBounds, flags).emit();
333 }
334 } else {
335 //slow scope load, we have no proto depth
336 new LoadScopeVar(identNode, resultBounds, flags).emit();
337 }
338
339 return method;
340 }
341
342 // Any access to LET and CONST variables before their declaration must throw ReferenceError.
343 // This is called the temporal dead zone (TDZ). See https://gist.github.com/rwaldron/f0807a758aa03bcdd58a
344 private void checkTemporalDeadZone(final IdentNode identNode) {
345 if (identNode.isDead()) {
346 method.load(identNode.getSymbol().getName()).invoke(ScriptRuntime.THROW_REFERENCE_ERROR);
347 }
348 }
349
350 // Runtime check for assignment to ES6 const
351 private void checkAssignTarget(final Expression expression) {
352 if (expression instanceof IdentNode && ((IdentNode)expression).getSymbol().isConst()) {
353 method.load(((IdentNode)expression).getSymbol().getName()).invoke(ScriptRuntime.THROW_CONST_TYPE_ERROR);
354 }
355 }
356
357 private boolean isRestOf() {
358 return continuationEntryPoints != null;
359 }
360
361 private boolean isOptimisticOrRestOf() {
362 return useOptimisticTypes() || isRestOf();
363 }
364
365 private boolean isCurrentContinuationEntryPoint(final int programPoint) {
366 return isRestOf() && getCurrentContinuationEntryPoint() == programPoint;
367 }
368
369 private int[] getContinuationEntryPoints() {
370 return isRestOf() ? continuationEntryPoints : null;
371 }
372
373 private int getCurrentContinuationEntryPoint() {
776 }.emit(baseAlreadyOnStack ? 2 : 0);
777 return false;
778 }
779
780 @Override
781 public boolean enterFunctionNode(final FunctionNode functionNode) {
782 // function nodes will always leave a constructed function object on stack, no need to load the symbol
783 // separately as in enterDefault()
784 lc.pop(functionNode);
785 functionNode.accept(codegen);
786 // NOTE: functionNode.accept() will produce a different FunctionNode that we discard. This incidentally
787 // doesn't cause problems as we're never touching FunctionNode again after it's visited here - codegen
788 // is the last element in the compilation pipeline, the AST it produces is not used externally. So, we
789 // re-push the original functionNode.
790 lc.push(functionNode);
791 return false;
792 }
793
794 @Override
795 public boolean enterASSIGN(final BinaryNode binaryNode) {
796 checkAssignTarget(binaryNode.lhs());
797 loadASSIGN(binaryNode);
798 return false;
799 }
800
801 @Override
802 public boolean enterASSIGN_ADD(final BinaryNode binaryNode) {
803 checkAssignTarget(binaryNode.lhs());
804 loadASSIGN_ADD(binaryNode);
805 return false;
806 }
807
808 @Override
809 public boolean enterASSIGN_BIT_AND(final BinaryNode binaryNode) {
810 checkAssignTarget(binaryNode.lhs());
811 loadASSIGN_BIT_AND(binaryNode);
812 return false;
813 }
814
815 @Override
816 public boolean enterASSIGN_BIT_OR(final BinaryNode binaryNode) {
817 checkAssignTarget(binaryNode.lhs());
818 loadASSIGN_BIT_OR(binaryNode);
819 return false;
820 }
821
822 @Override
823 public boolean enterASSIGN_BIT_XOR(final BinaryNode binaryNode) {
824 checkAssignTarget(binaryNode.lhs());
825 loadASSIGN_BIT_XOR(binaryNode);
826 return false;
827 }
828
829 @Override
830 public boolean enterASSIGN_DIV(final BinaryNode binaryNode) {
831 checkAssignTarget(binaryNode.lhs());
832 loadASSIGN_DIV(binaryNode);
833 return false;
834 }
835
836 @Override
837 public boolean enterASSIGN_MOD(final BinaryNode binaryNode) {
838 checkAssignTarget(binaryNode.lhs());
839 loadASSIGN_MOD(binaryNode);
840 return false;
841 }
842
843 @Override
844 public boolean enterASSIGN_MUL(final BinaryNode binaryNode) {
845 checkAssignTarget(binaryNode.lhs());
846 loadASSIGN_MUL(binaryNode);
847 return false;
848 }
849
850 @Override
851 public boolean enterASSIGN_SAR(final BinaryNode binaryNode) {
852 checkAssignTarget(binaryNode.lhs());
853 loadASSIGN_SAR(binaryNode);
854 return false;
855 }
856
857 @Override
858 public boolean enterASSIGN_SHL(final BinaryNode binaryNode) {
859 checkAssignTarget(binaryNode.lhs());
860 loadASSIGN_SHL(binaryNode);
861 return false;
862 }
863
864 @Override
865 public boolean enterASSIGN_SHR(final BinaryNode binaryNode) {
866 checkAssignTarget(binaryNode.lhs());
867 loadASSIGN_SHR(binaryNode);
868 return false;
869 }
870
871 @Override
872 public boolean enterASSIGN_SUB(final BinaryNode binaryNode) {
873 checkAssignTarget(binaryNode.lhs());
874 loadASSIGN_SUB(binaryNode);
875 return false;
876 }
877
878 @Override
879 public boolean enterCallNode(final CallNode callNode) {
880 return loadCallNode(callNode, resultBounds);
881 }
882
883 @Override
884 public boolean enterLiteralNode(final LiteralNode<?> literalNode) {
885 loadLiteral(literalNode, resultBounds);
886 return false;
887 }
888
889 @Override
890 public boolean enterTernaryNode(final TernaryNode ternaryNode) {
891 loadTernaryNode(ternaryNode, resultBounds);
892 return false;
893 }
1063 @Override
1064 public boolean enterObjectNode(final ObjectNode objectNode) {
1065 loadObjectNode(objectNode);
1066 return false;
1067 }
1068
1069 @Override
1070 public boolean enterRuntimeNode(final RuntimeNode runtimeNode) {
1071 loadRuntimeNode(runtimeNode);
1072 return false;
1073 }
1074
1075 @Override
1076 public boolean enterNEW(final UnaryNode unaryNode) {
1077 loadNEW(unaryNode);
1078 return false;
1079 }
1080
1081 @Override
1082 public boolean enterDECINC(final UnaryNode unaryNode) {
1083 checkAssignTarget(unaryNode.getExpression());
1084 loadDECINC(unaryNode);
1085 return false;
1086 }
1087
1088 @Override
1089 public boolean enterJoinPredecessorExpression(final JoinPredecessorExpression joinExpr) {
1090 loadExpression(joinExpr.getExpression(), resultBounds);
1091 return false;
1092 }
1093
1094 @Override
1095 public boolean enterGetSplitState(final GetSplitState getSplitState) {
1096 method.loadScope();
1097 method.invoke(Scope.GET_SPLIT_STATE);
1098 return false;
1099 }
1100
1101 @Override
1102 public boolean enterDefault(final Node otherNode) {
1103 // Must have handled all expressions that can legally be encountered.
|