Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(310)

Side by Side Diff: runtime/vm/kernel_to_il.cc

Issue 2901533002: [kernel] Stream everything. Replace .kernel_function with .kernel_offset (Closed)
Patch Set: Fixed assert issues; small refactorings. Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include <set> 5 #include <set>
6 6
7 #include "vm/kernel_to_il.h" 7 #include "vm/kernel_to_il.h"
8 8
9 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/intermediate_language.h" 10 #include "vm/intermediate_language.h"
(...skipping 12 matching lines...) Expand all
23 DECLARE_FLAG(bool, support_externalizable_strings); 23 DECLARE_FLAG(bool, support_externalizable_strings);
24 24
25 namespace kernel { 25 namespace kernel {
26 26
27 #define Z (zone_) 27 #define Z (zone_)
28 #define H (translation_helper_) 28 #define H (translation_helper_)
29 #define T (type_translator_) 29 #define T (type_translator_)
30 #define I Isolate::Current() 30 #define I Isolate::Current()
31 31
32 32
33 static void DiscoverEnclosingElements(Zone* zone,
34 const Function& function,
35 Function* outermost_function,
36 TreeNode** outermost_node,
37 Class** klass) {
38 // Find out if there is an enclosing kernel class (which will be used to
39 // resolve type parameters).
40 *outermost_function = function.raw();
41 while (outermost_function->parent_function() != Object::null()) {
42 *outermost_function = outermost_function->parent_function();
43 }
44 *outermost_node =
45 static_cast<TreeNode*>(outermost_function->kernel_function());
46 if (*outermost_node != NULL) {
47 TreeNode* parent = NULL;
48 if ((*outermost_node)->IsProcedure()) {
49 parent = Procedure::Cast(*outermost_node)->parent();
50 } else if ((*outermost_node)->IsConstructor()) {
51 parent = Constructor::Cast(*outermost_node)->parent();
52 } else if ((*outermost_node)->IsField()) {
53 parent = Field::Cast(*outermost_node)->parent();
54 }
55 if (parent != NULL && parent->IsClass()) *klass = Class::Cast(parent);
56 }
57 }
58
59
60 static bool IsStaticInitializer(const Function& function, Zone* zone) {
61 return (function.kind() == RawFunction::kImplicitStaticFinalGetter) &&
62 dart::String::Handle(zone, function.name())
63 .StartsWith(Symbols::InitPrefix());
64 }
65
66
67 Fragment& Fragment::operator+=(const Fragment& other) { 33 Fragment& Fragment::operator+=(const Fragment& other) {
68 if (entry == NULL) { 34 if (entry == NULL) {
69 entry = other.entry; 35 entry = other.entry;
70 current = other.current; 36 current = other.current;
71 } else if (current != NULL && other.entry != NULL) { 37 } else if (current != NULL && other.entry != NULL) {
72 current->LinkTo(other.entry); 38 current->LinkTo(other.entry);
73 current = other.current; 39 current = other.current;
74 } 40 }
75 return *this; 41 return *this;
76 } 42 }
(...skipping 600 matching lines...) Expand 10 before | Expand all | Expand 10 after
677 if (named->length() == 0) return Array::ZoneHandle(Z); 643 if (named->length() == 0) return Array::ZoneHandle(Z);
678 644
679 const Array& names = 645 const Array& names =
680 Array::ZoneHandle(Z, Array::New(named->length(), Heap::kOld)); 646 Array::ZoneHandle(Z, Array::New(named->length(), Heap::kOld));
681 for (intptr_t i = 0; i < named->length(); ++i) { 647 for (intptr_t i = 0; i < named->length(); ++i) {
682 names.SetAt(i, DartSymbol((*named)[i]->name())); 648 names.SetAt(i, DartSymbol((*named)[i]->name()));
683 } 649 }
684 return names; 650 return names;
685 } 651 }
686 652
687 ConstantEvaluator::ConstantEvaluator(FlowGraphBuilder* builder,
688 Zone* zone,
689 TranslationHelper* h,
690 DartTypeTranslator* type_translator)
691 : builder_(builder),
692 isolate_(Isolate::Current()),
693 zone_(zone),
694 translation_helper_(*h),
695 type_translator_(*type_translator),
696 script_(Script::Handle(
697 zone,
698 builder == NULL ? Script::null()
699 : builder_->parsed_function_->function().script())),
700 result_(Instance::Handle(zone)) {}
701
702
703 Instance& ConstantEvaluator::EvaluateExpression(Expression* expression) {
704 if (!GetCachedConstant(expression, &result_)) {
705 expression->AcceptExpressionVisitor(this);
706 CacheConstantValue(expression, result_);
707 }
708 // We return a new `ZoneHandle` here on purpose: The intermediate language
709 // instructions do not make a copy of the handle, so we do it.
710 return Instance::ZoneHandle(Z, result_.raw());
711 }
712
713
714 Object& ConstantEvaluator::EvaluateExpressionSafe(Expression* expression) {
715 LongJumpScope jump;
716 if (setjmp(*jump.Set()) == 0) {
717 return EvaluateExpression(expression);
718 } else {
719 Thread* thread = H.thread();
720 Error& error = Error::Handle(Z);
721 error = thread->sticky_error();
722 thread->clear_sticky_error();
723 return error;
724 }
725 }
726
727
728 Instance& ConstantEvaluator::EvaluateConstructorInvocation(
729 ConstructorInvocation* node) {
730 if (!GetCachedConstant(node, &result_)) {
731 VisitConstructorInvocation(node);
732 CacheConstantValue(node, result_);
733 }
734 // We return a new `ZoneHandle` here on purpose: The intermediate language
735 // instructions do not make a copy of the handle, so we do it.
736 return Instance::ZoneHandle(Z, result_.raw());
737 }
738
739
740 Instance& ConstantEvaluator::EvaluateListLiteral(ListLiteral* node) {
741 if (!GetCachedConstant(node, &result_)) {
742 VisitListLiteral(node);
743 CacheConstantValue(node, result_);
744 }
745 // We return a new `ZoneHandle` here on purpose: The intermediate language
746 // instructions do not make a copy of the handle, so we do it.
747 return Instance::ZoneHandle(Z, result_.raw());
748 }
749
750
751 Instance& ConstantEvaluator::EvaluateMapLiteral(MapLiteral* node) {
752 if (!GetCachedConstant(node, &result_)) {
753 VisitMapLiteral(node);
754 CacheConstantValue(node, result_);
755 }
756 // We return a new `ZoneHandle` here on purpose: The intermediate language
757 // instructions do not make a copy of the handle, so we do it.
758 return Instance::ZoneHandle(Z, result_.raw());
759 }
760
761
762 void ConstantEvaluator::VisitBigintLiteral(BigintLiteral* node) {
763 const dart::String& value = H.DartString(node->value());
764 result_ = Integer::New(value, Heap::kOld);
765 result_ = H.Canonicalize(result_);
766 }
767
768
769 void ConstantEvaluator::VisitBoolLiteral(BoolLiteral* node) {
770 result_ = Bool::Get(node->value()).raw();
771 }
772
773
774 void ConstantEvaluator::VisitDoubleLiteral(DoubleLiteral* node) {
775 result_ = Double::New(H.DartString(node->value()), Heap::kOld);
776 result_ = H.Canonicalize(result_);
777 }
778
779
780 void ConstantEvaluator::VisitIntLiteral(IntLiteral* node) {
781 result_ = Integer::New(node->value(), Heap::kOld);
782 result_ = H.Canonicalize(result_);
783 }
784
785
786 void ConstantEvaluator::VisitNullLiteral(NullLiteral* node) {
787 result_ = Instance::null();
788 }
789
790
791 void ConstantEvaluator::VisitStringLiteral(StringLiteral* node) {
792 result_ = H.DartSymbol(node->value()).raw();
793 }
794
795
796 void ConstantEvaluator::VisitTypeLiteral(TypeLiteral* node) {
797 const AbstractType& type = T.TranslateType(node->type());
798 if (type.IsMalformed()) {
799 H.ReportError("Malformed type literal in constant expression.");
800 }
801 result_ = type.raw();
802 }
803
804
805 RawObject* ConstantEvaluator::EvaluateConstConstructorCall(
806 const dart::Class& type_class,
807 const TypeArguments& type_arguments,
808 const Function& constructor,
809 const Object& argument) {
810 // Factories have one extra argument: the type arguments.
811 // Constructors have 1 extra arguments: receiver.
812 const int kNumArgs = 1;
813 const int kNumExtraArgs = 1;
814 const int num_arguments = kNumArgs + kNumExtraArgs;
815 const Array& arg_values =
816 Array::Handle(Z, Array::New(num_arguments, Heap::kOld));
817 Instance& instance = Instance::Handle(Z);
818 if (!constructor.IsFactory()) {
819 instance = Instance::New(type_class, Heap::kOld);
820 if (!type_arguments.IsNull()) {
821 ASSERT(type_arguments.IsInstantiated());
822 instance.SetTypeArguments(
823 TypeArguments::Handle(Z, type_arguments.Canonicalize()));
824 }
825 arg_values.SetAt(0, instance);
826 } else {
827 // Prepend type_arguments to list of arguments to factory.
828 ASSERT(type_arguments.IsZoneHandle());
829 arg_values.SetAt(0, type_arguments);
830 }
831 arg_values.SetAt((0 + kNumExtraArgs), argument);
832 const Array& args_descriptor = Array::Handle(
833 Z, ArgumentsDescriptor::New(num_arguments, Object::empty_array()));
834 const Object& result = Object::Handle(
835 Z, DartEntry::InvokeFunction(constructor, arg_values, args_descriptor));
836 ASSERT(!result.IsError());
837 if (constructor.IsFactory()) {
838 // The factory method returns the allocated object.
839 instance ^= result.raw();
840 }
841 return H.Canonicalize(instance);
842 }
843
844
845 bool ConstantEvaluator::GetCachedConstant(TreeNode* node, Instance* value) {
846 if (builder_ == NULL) return false;
847
848 const Function& function = builder_->parsed_function_->function();
849 if (function.kind() == RawFunction::kImplicitStaticFinalGetter) {
850 // Don't cache constants in initializer expressions. They get
851 // evaluated only once.
852 return false;
853 }
854
855 bool is_present = false;
856 ASSERT(!script_.InVMHeap());
857 if (script_.compile_time_constants() == Array::null()) {
858 return false;
859 }
860 KernelConstantsMap constants(script_.compile_time_constants());
861 *value ^= constants.GetOrNull(node->kernel_offset(), &is_present);
862 // Mutator compiler thread may add constants while background compiler
863 // is running, and thus change the value of 'compile_time_constants';
864 // do not assert that 'compile_time_constants' has not changed.
865 constants.Release();
866 if (FLAG_compiler_stats && is_present) {
867 H.thread()->compiler_stats()->num_const_cache_hits++;
868 }
869 return is_present;
870 }
871
872
873 void ConstantEvaluator::CacheConstantValue(TreeNode* node,
874 const Instance& value) {
875 ASSERT(Thread::Current()->IsMutatorThread());
876
877 if (builder_ == NULL) return;
878
879 const Function& function = builder_->parsed_function_->function();
880 if (function.kind() == RawFunction::kImplicitStaticFinalGetter) {
881 // Don't cache constants in initializer expressions. They get
882 // evaluated only once.
883 return;
884 }
885 const intptr_t kInitialConstMapSize = 16;
886 ASSERT(!script_.InVMHeap());
887 if (script_.compile_time_constants() == Array::null()) {
888 const Array& array = Array::Handle(
889 HashTables::New<KernelConstantsMap>(kInitialConstMapSize, Heap::kNew));
890 script_.set_compile_time_constants(array);
891 }
892 KernelConstantsMap constants(script_.compile_time_constants());
893 constants.InsertNewOrGetValue(node->kernel_offset(), value);
894 script_.set_compile_time_constants(constants.Release());
895 }
896
897
898 void ConstantEvaluator::VisitSymbolLiteral(SymbolLiteral* node) {
899 const dart::String& symbol_value = H.DartSymbol(node->value());
900
901 const dart::Class& symbol_class =
902 dart::Class::ZoneHandle(Z, I->object_store()->symbol_class());
903 ASSERT(!symbol_class.IsNull());
904 const Function& symbol_constructor = Function::ZoneHandle(
905 Z, symbol_class.LookupConstructor(Symbols::SymbolCtor()));
906 ASSERT(!symbol_constructor.IsNull());
907 result_ ^= EvaluateConstConstructorCall(
908 symbol_class, TypeArguments::Handle(Z), symbol_constructor, symbol_value);
909 }
910
911
912 void ConstantEvaluator::VisitListLiteral(ListLiteral* node) {
913 DartType* types[] = {node->type()};
914 const TypeArguments& type_arguments = T.TranslateTypeArguments(types, 1);
915
916 intptr_t length = node->expressions().length();
917 const Array& const_list =
918 Array::ZoneHandle(Z, Array::New(length, Heap::kOld));
919 const_list.SetTypeArguments(type_arguments);
920 for (intptr_t i = 0; i < length; i++) {
921 const Instance& expression = EvaluateExpression(node->expressions()[i]);
922 const_list.SetAt(i, expression);
923 }
924 const_list.MakeImmutable();
925 result_ = H.Canonicalize(const_list);
926 }
927
928
929 void ConstantEvaluator::VisitMapLiteral(MapLiteral* node) {
930 DartType* types[] = {node->key_type(), node->value_type()};
931 const TypeArguments& type_arguments = T.TranslateTypeArguments(types, 2);
932
933 intptr_t length = node->entries().length();
934
935 Array& const_kv_array =
936 Array::ZoneHandle(Z, Array::New(2 * length, Heap::kOld));
937 for (intptr_t i = 0; i < length; i++) {
938 const_kv_array.SetAt(2 * i + 0,
939 EvaluateExpression(node->entries()[i]->key()));
940 const_kv_array.SetAt(2 * i + 1,
941 EvaluateExpression(node->entries()[i]->value()));
942 }
943
944 const_kv_array.MakeImmutable();
945 const_kv_array ^= H.Canonicalize(const_kv_array);
946
947 const dart::Class& map_class = dart::Class::Handle(
948 Z, dart::Library::LookupCoreClass(Symbols::ImmutableMap()));
949 ASSERT(!map_class.IsNull());
950 ASSERT(map_class.NumTypeArguments() == 2);
951
952 const dart::Field& field = dart::Field::Handle(
953 Z, map_class.LookupInstanceFieldAllowPrivate(H.DartSymbol("_kvPairs")));
954 ASSERT(!field.IsNull());
955
956 // NOTE: This needs to be kept in sync with `runtime/lib/immutable_map.dart`!
957 result_ = Instance::New(map_class, Heap::kOld);
958 ASSERT(!result_.IsNull());
959 result_.SetTypeArguments(type_arguments);
960 result_.SetField(field, const_kv_array);
961 result_ = H.Canonicalize(result_);
962 }
963
964
965 void ConstantEvaluator::VisitConstructorInvocation(
966 ConstructorInvocation* node) {
967 Arguments* kernel_arguments = node->arguments();
968
969 const Function& constructor = Function::Handle(
970 Z, H.LookupConstructorByKernelConstructor(node->target()));
971 dart::Class& klass = dart::Class::Handle(Z, constructor.Owner());
972
973 // Build the type arguments vector (if necessary).
974 const TypeArguments* type_arguments =
975 TranslateTypeArguments(constructor, &klass, kernel_arguments);
976
977 // Prepare either the instance or the type argument vector for the constructor
978 // call.
979 Instance* receiver = NULL;
980 const TypeArguments* type_arguments_argument = NULL;
981 if (!constructor.IsFactory()) {
982 receiver = &Instance::ZoneHandle(Z, Instance::New(klass, Heap::kOld));
983 if (type_arguments != NULL) {
984 receiver->SetTypeArguments(*type_arguments);
985 }
986 } else {
987 type_arguments_argument = type_arguments;
988 }
989
990 const Object& result = RunFunction(constructor, kernel_arguments, receiver,
991 type_arguments_argument);
992 if (constructor.IsFactory()) {
993 // Factories return the new object.
994 result_ ^= result.raw();
995 result_ = H.Canonicalize(result_);
996 } else {
997 ASSERT(!receiver->IsNull());
998 result_ = H.Canonicalize(*receiver);
999 }
1000 }
1001
1002
1003 void ConstantEvaluator::VisitMethodInvocation(MethodInvocation* node) {
1004 Arguments* kernel_arguments = node->arguments();
1005
1006 // Dart does not support generic methods yet.
1007 ASSERT(kernel_arguments->types().length() == 0);
1008
1009 const Instance& receiver = EvaluateExpression(node->receiver());
1010 dart::Class& klass = dart::Class::Handle(
1011 Z, isolate_->class_table()->At(receiver.GetClassId()));
1012 ASSERT(!klass.IsNull());
1013
1014 // Search the superclass chain for the selector.
1015 Function& function = Function::Handle(Z);
1016 const dart::String& method_name = H.DartMethodName(node->name());
1017 while (!klass.IsNull()) {
1018 function = klass.LookupDynamicFunctionAllowPrivate(method_name);
1019 if (!function.IsNull()) break;
1020 klass = klass.SuperClass();
1021 }
1022
1023 // The frontend should guarantee that [MethodInvocation]s inside constant
1024 // expressions are always valid.
1025 ASSERT(!function.IsNull());
1026
1027 // Run the method and canonicalize the result.
1028 const Object& result = RunFunction(function, kernel_arguments, &receiver);
1029 result_ ^= result.raw();
1030 result_ = H.Canonicalize(result_);
1031 }
1032
1033
1034 void ConstantEvaluator::VisitStaticGet(StaticGet* node) {
1035 NameIndex target = node->target();
1036 if (H.IsField(target)) {
1037 const dart::Field& field =
1038 dart::Field::Handle(Z, H.LookupFieldByKernelField(target));
1039 if (field.StaticValue() == Object::sentinel().raw() ||
1040 field.StaticValue() == Object::transition_sentinel().raw()) {
1041 field.EvaluateInitializer();
1042 result_ = field.StaticValue();
1043 result_ = H.Canonicalize(result_);
1044 field.SetStaticValue(result_, true);
1045 } else {
1046 result_ = field.StaticValue();
1047 }
1048 } else if (H.IsProcedure(target)) {
1049 const Function& function =
1050 Function::ZoneHandle(Z, H.LookupStaticMethodByKernelProcedure(target));
1051
1052 if (H.IsMethod(target)) {
1053 Function& closure_function =
1054 Function::ZoneHandle(Z, function.ImplicitClosureFunction());
1055 closure_function.set_kernel_function(function.kernel_function());
1056 result_ = closure_function.ImplicitStaticClosure();
1057 result_ = H.Canonicalize(result_);
1058 } else if (H.IsGetter(target)) {
1059 UNIMPLEMENTED();
1060 } else {
1061 UNIMPLEMENTED();
1062 }
1063 }
1064 }
1065
1066
1067 void ConstantEvaluator::VisitVariableGet(VariableGet* node) {
1068 // When we see a [VariableGet] the corresponding [VariableDeclaration] must've
1069 // been executed already. It therefore must have a constant object associated
1070 // with it.
1071 LocalVariable* variable = builder_->LookupVariable(node->variable());
1072 ASSERT(variable->IsConst());
1073 result_ = variable->ConstValue()->raw();
1074 }
1075
1076
1077 void ConstantEvaluator::VisitLet(Let* node) {
1078 VariableDeclaration* variable = node->variable();
1079 LocalVariable* local = builder_->LookupVariable(variable);
1080 local->SetConstValue(EvaluateExpression(variable->initializer()));
1081 node->body()->AcceptExpressionVisitor(this);
1082 }
1083
1084
1085 void ConstantEvaluator::VisitStaticInvocation(StaticInvocation* node) {
1086 const Function& function = Function::ZoneHandle(
1087 Z, H.LookupStaticMethodByKernelProcedure(node->procedure()));
1088 dart::Class& klass = dart::Class::Handle(Z, function.Owner());
1089
1090 // Build the type arguments vector (if necessary).
1091 const TypeArguments* type_arguments =
1092 TranslateTypeArguments(function, &klass, node->arguments());
1093
1094 const Object& result =
1095 RunFunction(function, node->arguments(), NULL, type_arguments);
1096 result_ ^= result.raw();
1097 result_ = H.Canonicalize(result_);
1098 }
1099
1100
1101 void ConstantEvaluator::VisitStringConcatenation(StringConcatenation* node) {
1102 intptr_t length = node->expressions().length();
1103
1104 bool all_string = true;
1105 const Array& strings = Array::Handle(Z, Array::New(length));
1106 for (intptr_t i = 0; i < length; i++) {
1107 EvaluateExpression(node->expressions()[i]);
1108 strings.SetAt(i, result_);
1109 all_string = all_string && result_.IsString();
1110 }
1111 if (all_string) {
1112 result_ = dart::String::ConcatAll(strings, Heap::kOld);
1113 result_ = H.Canonicalize(result_);
1114 } else {
1115 // Get string interpolation function.
1116 const dart::Class& cls = dart::Class::Handle(
1117 Z, dart::Library::LookupCoreClass(Symbols::StringBase()));
1118 ASSERT(!cls.IsNull());
1119 const Function& func = Function::Handle(
1120 Z, cls.LookupStaticFunction(
1121 dart::Library::PrivateCoreLibName(Symbols::Interpolate())));
1122 ASSERT(!func.IsNull());
1123
1124 // Build argument array to pass to the interpolation function.
1125 const Array& interpolate_arg = Array::Handle(Z, Array::New(1, Heap::kOld));
1126 interpolate_arg.SetAt(0, strings);
1127
1128 // Run and canonicalize.
1129 const Object& result =
1130 RunFunction(func, interpolate_arg, Array::null_array());
1131 result_ = H.Canonicalize(dart::String::Cast(result));
1132 }
1133 }
1134
1135
1136 void ConstantEvaluator::VisitConditionalExpression(
1137 ConditionalExpression* node) {
1138 if (EvaluateBooleanExpression(node->condition())) {
1139 EvaluateExpression(node->then());
1140 } else {
1141 EvaluateExpression(node->otherwise());
1142 }
1143 }
1144
1145
1146 void ConstantEvaluator::VisitLogicalExpression(LogicalExpression* node) {
1147 if (node->op() == LogicalExpression::kAnd) {
1148 if (EvaluateBooleanExpression(node->left())) {
1149 EvaluateBooleanExpression(node->right());
1150 }
1151 } else {
1152 ASSERT(node->op() == LogicalExpression::kOr);
1153 if (!EvaluateBooleanExpression(node->left())) {
1154 EvaluateBooleanExpression(node->right());
1155 }
1156 }
1157 }
1158
1159
1160 void ConstantEvaluator::VisitNot(Not* node) {
1161 result_ ^= Bool::Get(!EvaluateBooleanExpression(node->expression())).raw();
1162 }
1163
1164
1165 void ConstantEvaluator::VisitPropertyGet(PropertyGet* node) {
1166 StringIndex string_index = node->name()->string_index();
1167 if (H.StringEquals(string_index, "length")) {
1168 node->receiver()->AcceptExpressionVisitor(this);
1169 if (result_.IsString()) {
1170 const dart::String& str =
1171 dart::String::Handle(Z, dart::String::RawCast(result_.raw()));
1172 result_ = Integer::New(str.Length());
1173 } else {
1174 H.ReportError(
1175 "Constant expressions can only call "
1176 "'length' on string constants.");
1177 }
1178 } else {
1179 VisitDefaultExpression(node);
1180 }
1181 }
1182
1183
1184 const TypeArguments* ConstantEvaluator::TranslateTypeArguments(
1185 const Function& target,
1186 dart::Class* target_klass,
1187 Arguments* kernel_arguments) {
1188 List<DartType>& kernel_type_arguments = kernel_arguments->types();
1189
1190 const TypeArguments* type_arguments = NULL;
1191 if (kernel_type_arguments.length() > 0) {
1192 type_arguments = &T.TranslateInstantiatedTypeArguments(
1193 *target_klass, kernel_type_arguments.raw_array(),
1194 kernel_type_arguments.length());
1195
1196 if (!(type_arguments->IsNull() || type_arguments->IsInstantiated())) {
1197 H.ReportError("Type must be constant in const constructor.");
1198 }
1199 } else if (target.IsFactory() && type_arguments == NULL) {
1200 // All factories take a type arguments vector as first argument (independent
1201 // of whether the class is generic or not).
1202 type_arguments = &TypeArguments::ZoneHandle(Z, TypeArguments::null());
1203 }
1204 return type_arguments;
1205 }
1206
1207
1208 const Object& ConstantEvaluator::RunFunction(const Function& function,
1209 Arguments* kernel_arguments,
1210 const Instance* receiver,
1211 const TypeArguments* type_args) {
1212 // We do not support generic methods yet.
1213 ASSERT((receiver == NULL) || (type_args == NULL));
1214 intptr_t extra_arguments =
1215 (receiver != NULL ? 1 : 0) + (type_args != NULL ? 1 : 0);
1216
1217 // Build up arguments.
1218 const Array& arguments = Array::ZoneHandle(
1219 Z, Array::New(extra_arguments + kernel_arguments->count()));
1220 const Array& names =
1221 Array::ZoneHandle(Z, Array::New(kernel_arguments->named().length()));
1222 intptr_t pos = 0;
1223 if (receiver != NULL) {
1224 arguments.SetAt(pos++, *receiver);
1225 }
1226 if (type_args != NULL) {
1227 arguments.SetAt(pos++, *type_args);
1228 }
1229 for (intptr_t i = 0; i < kernel_arguments->positional().length(); i++) {
1230 EvaluateExpression(kernel_arguments->positional()[i]);
1231 arguments.SetAt(pos++, result_);
1232 }
1233 for (intptr_t i = 0; i < kernel_arguments->named().length(); i++) {
1234 NamedExpression* named_expression = kernel_arguments->named()[i];
1235 EvaluateExpression(named_expression->expression());
1236 arguments.SetAt(pos++, result_);
1237 names.SetAt(i, H.DartSymbol(named_expression->name()));
1238 }
1239 return RunFunction(function, arguments, names);
1240 }
1241
1242
1243 const Object& ConstantEvaluator::RunFunction(const Function& function,
1244 const Array& arguments,
1245 const Array& names) {
1246 const Array& args_descriptor =
1247 Array::Handle(Z, ArgumentsDescriptor::New(arguments.Length(), names));
1248 const Object& result = Object::Handle(
1249 Z, DartEntry::InvokeFunction(function, arguments, args_descriptor));
1250 if (result.IsError()) {
1251 H.ReportError(Error::Cast(result), "error evaluating constant constructor");
1252 }
1253 return result;
1254 }
1255
1256 653
1257 FlowGraphBuilder::FlowGraphBuilder( 654 FlowGraphBuilder::FlowGraphBuilder(
1258 TreeNode* node, 655 intptr_t kernel_offset,
1259 ParsedFunction* parsed_function, 656 ParsedFunction* parsed_function,
1260 const ZoneGrowableArray<const ICData*>& ic_data_array, 657 const ZoneGrowableArray<const ICData*>& ic_data_array,
1261 InlineExitCollector* exit_collector, 658 InlineExitCollector* exit_collector,
1262 intptr_t osr_id, 659 intptr_t osr_id,
1263 intptr_t first_block_id) 660 intptr_t first_block_id)
1264 : translation_helper_(Thread::Current()), 661 : translation_helper_(Thread::Current()),
1265 zone_(translation_helper_.zone()), 662 zone_(translation_helper_.zone()),
1266 node_(node), 663 kernel_offset_(kernel_offset),
1267 parsed_function_(parsed_function), 664 parsed_function_(parsed_function),
1268 osr_id_(osr_id), 665 osr_id_(osr_id),
1269 ic_data_array_(ic_data_array), 666 ic_data_array_(ic_data_array),
1270 exit_collector_(exit_collector), 667 exit_collector_(exit_collector),
1271 next_block_id_(first_block_id), 668 next_block_id_(first_block_id),
1272 next_function_id_(0), 669 next_function_id_(0),
1273 context_depth_(0), 670 context_depth_(0),
1274 loop_depth_(0), 671 loop_depth_(0),
1275 try_depth_(0), 672 try_depth_(0),
1276 catch_depth_(0), 673 catch_depth_(0),
1277 for_in_depth_(0), 674 for_in_depth_(0),
1278 stack_(NULL), 675 stack_(NULL),
1279 pending_argument_count_(0), 676 pending_argument_count_(0),
1280 graph_entry_(NULL), 677 graph_entry_(NULL),
1281 scopes_(NULL), 678 scopes_(NULL),
1282 breakable_block_(NULL), 679 breakable_block_(NULL),
1283 switch_block_(NULL), 680 switch_block_(NULL),
1284 try_finally_block_(NULL), 681 try_finally_block_(NULL),
1285 try_catch_block_(NULL), 682 try_catch_block_(NULL),
1286 next_used_try_index_(0), 683 next_used_try_index_(0),
1287 catch_block_(NULL), 684 catch_block_(NULL),
1288 type_translator_(&translation_helper_, 685 type_translator_(&translation_helper_,
1289 &active_class_, 686 &active_class_,
1290 /* finalize= */ true), 687 /* finalize= */ true),
1291 constant_evaluator_(this, zone_, &translation_helper_, &type_translator_),
1292 streaming_flow_graph_builder_(NULL) { 688 streaming_flow_graph_builder_(NULL) {
1293 Script& script = Script::Handle(Z, parsed_function->function().script()); 689 Script& script = Script::Handle(Z, parsed_function->function().script());
1294 H.SetStringOffsets(TypedData::Handle(Z, script.kernel_string_offsets())); 690 H.SetStringOffsets(TypedData::Handle(Z, script.kernel_string_offsets()));
1295 H.SetStringData(TypedData::Handle(Z, script.kernel_string_data())); 691 H.SetStringData(TypedData::Handle(Z, script.kernel_string_data()));
1296 H.SetCanonicalNames(TypedData::Handle(Z, script.kernel_canonical_names())); 692 H.SetCanonicalNames(TypedData::Handle(Z, script.kernel_canonical_names()));
1297 } 693 }
1298 694
1299 695
1300 FlowGraphBuilder::~FlowGraphBuilder() { 696 FlowGraphBuilder::~FlowGraphBuilder() {
1301 if (streaming_flow_graph_builder_ != NULL) { 697 if (streaming_flow_graph_builder_ != NULL) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1336 JoinEntryInstr* entry = BuildJoinEntry(); 732 JoinEntryInstr* entry = BuildJoinEntry();
1337 instructions += Goto(entry); 733 instructions += Goto(entry);
1338 instructions = Fragment(instructions.entry, entry); 734 instructions = Fragment(instructions.entry, entry);
1339 } 735 }
1340 736
1341 Statement* finalizer = try_finally_block_->finalizer(); 737 Statement* finalizer = try_finally_block_->finalizer();
1342 intptr_t finalizer_kernel_offset = 738 intptr_t finalizer_kernel_offset =
1343 try_finally_block_->finalizer_kernel_offset(); 739 try_finally_block_->finalizer_kernel_offset();
1344 try_finally_block_ = try_finally_block_->outer(); 740 try_finally_block_ = try_finally_block_->outer();
1345 if (finalizer != NULL) { 741 if (finalizer != NULL) {
1346 // This will potentially have exceptional cases as described in 742 UNREACHABLE();
1347 // [VisitTryFinally] and will handle them.
1348 instructions += TranslateStatement(finalizer);
1349 } else { 743 } else {
1350 instructions += streaming_flow_graph_builder_->BuildStatementAt( 744 instructions += streaming_flow_graph_builder_->BuildStatementAt(
1351 finalizer_kernel_offset); 745 finalizer_kernel_offset);
1352 } 746 }
1353 747
1354 // We only need to make sure that if the finalizer ended normally, we 748 // We only need to make sure that if the finalizer ended normally, we
1355 // continue towards the next outer try-finally. 749 // continue towards the next outer try-finally.
1356 if (!instructions.is_open()) break; 750 if (!instructions.is_open()) break;
1357 } 751 }
1358 752
1359 if (instructions.is_open() && target_context_depth != -1) { 753 if (instructions.is_open() && target_context_depth != -1) {
1360 // A target context depth of -1 indicates that the code after this 754 // A target context depth of -1 indicates that the code after this
1361 // will not care about the context chain so we can leave it any way we 755 // will not care about the context chain so we can leave it any way we
1362 // want after the last finalizer. That is used when returning. 756 // want after the last finalizer. That is used when returning.
1363 instructions += AdjustContextTo(target_context_depth); 757 instructions += AdjustContextTo(target_context_depth);
1364 } 758 }
1365 759
1366 try_finally_block_ = saved_block; 760 try_finally_block_ = saved_block;
1367 try_catch_block_ = saved_try_catch_block; 761 try_catch_block_ = saved_try_catch_block;
1368 context_depth_ = saved_depth; 762 context_depth_ = saved_depth;
1369 try_depth_ = saved_try_depth; 763 try_depth_ = saved_try_depth;
1370 764
1371 return instructions; 765 return instructions;
1372 } 766 }
1373 767
1374 768
1375 Fragment FlowGraphBuilder::EnterScope(TreeNode* node, bool* new_context) {
1376 return EnterScope(node->kernel_offset(), new_context);
1377 }
1378
1379
1380 Fragment FlowGraphBuilder::EnterScope(intptr_t kernel_offset, 769 Fragment FlowGraphBuilder::EnterScope(intptr_t kernel_offset,
1381 bool* new_context) { 770 bool* new_context) {
1382 Fragment instructions; 771 Fragment instructions;
1383 const intptr_t context_size = 772 const intptr_t context_size =
1384 scopes_->scopes.Lookup(kernel_offset)->num_context_variables(); 773 scopes_->scopes.Lookup(kernel_offset)->num_context_variables();
1385 if (context_size > 0) { 774 if (context_size > 0) {
1386 instructions += PushContext(context_size); 775 instructions += PushContext(context_size);
1387 instructions += Drop(); 776 instructions += Drop();
1388 if (new_context != NULL) { 777 if (new_context != NULL) {
1389 *new_context = true; 778 *new_context = true;
1390 } 779 }
1391 } 780 }
1392 return instructions; 781 return instructions;
1393 } 782 }
1394 783
1395 784
1396 Fragment FlowGraphBuilder::ExitScope(TreeNode* node) {
1397 return ExitScope(node->kernel_offset());
1398 }
1399
1400
1401 Fragment FlowGraphBuilder::ExitScope(intptr_t kernel_offset) { 785 Fragment FlowGraphBuilder::ExitScope(intptr_t kernel_offset) {
1402 Fragment instructions; 786 Fragment instructions;
1403 const intptr_t context_size = 787 const intptr_t context_size =
1404 scopes_->scopes.Lookup(kernel_offset)->num_context_variables(); 788 scopes_->scopes.Lookup(kernel_offset)->num_context_variables();
1405 if (context_size > 0) { 789 if (context_size > 0) {
1406 instructions += PopContext(); 790 instructions += PopContext();
1407 } 791 }
1408 return instructions; 792 return instructions;
1409 } 793 }
1410 794
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1461 #ifdef DEBUG 845 #ifdef DEBUG
1462 Function& function = 846 Function& function =
1463 Function::Handle(Z, parsed_function_->function().raw()); 847 Function::Handle(Z, parsed_function_->function().raw());
1464 while (function.IsClosureFunction()) { 848 while (function.IsClosureFunction()) {
1465 function = function.parent_function(); 849 function = function.parent_function();
1466 } 850 }
1467 ASSERT(function.IsFactory()); 851 ASSERT(function.IsFactory());
1468 #endif 852 #endif
1469 instructions += LoadLocal(scopes_->type_arguments_variable); 853 instructions += LoadLocal(scopes_->type_arguments_variable);
1470 } else if (scopes_->this_variable != NULL && 854 } else if (scopes_->this_variable != NULL &&
1471 active_class_.kernel_class != NULL && 855 active_class_.class_type_parameters > 0) {
1472 active_class_.kernel_class->type_parameters().length() > 0) {
1473 ASSERT(!parsed_function_->function().IsFactory()); 856 ASSERT(!parsed_function_->function().IsFactory());
1474 intptr_t type_arguments_field_offset = 857 intptr_t type_arguments_field_offset =
1475 active_class_.klass->type_arguments_field_offset(); 858 active_class_.klass->type_arguments_field_offset();
1476 ASSERT(type_arguments_field_offset != dart::Class::kNoTypeArguments); 859 ASSERT(type_arguments_field_offset != dart::Class::kNoTypeArguments);
1477 860
1478 instructions += LoadLocal(scopes_->this_variable); 861 instructions += LoadLocal(scopes_->this_variable);
1479 instructions += LoadField(type_arguments_field_offset); 862 instructions += LoadField(type_arguments_field_offset);
1480 } else { 863 } else {
1481 instructions += NullConstant(); 864 instructions += NullConstant();
1482 } 865 }
(...skipping 902 matching lines...) Expand 10 before | Expand all | Expand 10 after
2385 parsed_function_->Bailout("kernel::FlowGraphBuilder", reason); 1768 parsed_function_->Bailout("kernel::FlowGraphBuilder", reason);
2386 } 1769 }
2387 } 1770 }
2388 1771
2389 1772
2390 FlowGraph* FlowGraphBuilder::BuildGraph() { 1773 FlowGraph* FlowGraphBuilder::BuildGraph() {
2391 const Function& function = parsed_function_->function(); 1774 const Function& function = parsed_function_->function();
2392 1775
2393 if (function.IsConstructorClosureFunction()) return NULL; 1776 if (function.IsConstructorClosureFunction()) return NULL;
2394 1777
2395 TreeNode* library_node = node_;
2396 if (node_ != NULL) {
2397 const Function* parent = &function;
2398 while (true) {
2399 library_node = static_cast<kernel::TreeNode*>(parent->kernel_function());
2400 while (library_node != NULL && !library_node->IsLibrary()) {
2401 if (library_node->IsMember()) {
2402 library_node = Member::Cast(library_node)->parent();
2403 } else if (library_node->IsClass()) {
2404 library_node = Class::Cast(library_node)->parent();
2405 break;
2406 } else {
2407 library_node = NULL;
2408 break;
2409 }
2410 }
2411 if (library_node != NULL) break;
2412 parent = &Function::Handle(parent->parent_function());
2413 }
2414 }
2415 if (streaming_flow_graph_builder_ != NULL) { 1778 if (streaming_flow_graph_builder_ != NULL) {
2416 delete streaming_flow_graph_builder_; 1779 delete streaming_flow_graph_builder_;
2417 streaming_flow_graph_builder_ = NULL; 1780 streaming_flow_graph_builder_ = NULL;
2418 } 1781 }
2419 if (library_node != NULL && library_node->IsLibrary()) {
2420 Library* library = Library::Cast(library_node);
2421 streaming_flow_graph_builder_ = new StreamingFlowGraphBuilder(
2422 this, library->kernel_data(), library->kernel_data_size());
2423 }
2424 1782
2425 dart::Class& klass = 1783 Script& script = Script::Handle(Z, function.script());
2426 dart::Class::Handle(zone_, parsed_function_->function().Owner()); 1784 streaming_flow_graph_builder_ = new StreamingFlowGraphBuilder(
1785 this, script.kernel_data(), script.kernel_data_size());
2427 1786
2428 Function& outermost_function = Function::Handle(Z); 1787 return streaming_flow_graph_builder_->BuildGraph(kernel_offset_);
2429 TreeNode* outermost_node = NULL;
2430 Class* kernel_class = NULL;
2431 DiscoverEnclosingElements(Z, function, &outermost_function, &outermost_node,
2432 &kernel_class);
2433
2434 // Mark that we are using [klass]/[kernell_klass] as active class. Resolving
2435 // of type parameters will get resolved via [kernell_klass] unless we are
2436 // nested inside a static factory in which case we will use [member].
2437 ActiveClassScope active_class_scope(&active_class_, kernel_class, &klass);
2438 Member* member = ((outermost_node != NULL) && outermost_node->IsMember())
2439 ? Member::Cast(outermost_node)
2440 : NULL;
2441 ActiveMemberScope active_member(&active_class_, member);
2442
2443 // The IR builder will create its own local variables and scopes, and it
2444 // will not need an AST. The code generator will assume that there is a
2445 // local variable stack slot allocated for the current context and (I
2446 // think) that the runtime will expect it to be at a fixed offset which
2447 // requires allocating an unused expression temporary variable.
2448 scopes_ = parsed_function_->EnsureKernelScopes();
2449
2450 switch (function.kind()) {
2451 case RawFunction::kClosureFunction:
2452 case RawFunction::kRegularFunction:
2453 case RawFunction::kGetterFunction:
2454 case RawFunction::kSetterFunction: {
2455 FunctionNode* kernel_function = node_->IsProcedure()
2456 ? Procedure::Cast(node_)->function()
2457 : FunctionNode::Cast(node_);
2458 return function.IsImplicitClosureFunction()
2459 ? BuildGraphOfImplicitClosureFunction(kernel_function,
2460 function)
2461 : BuildGraphOfFunction(kernel_function);
2462 }
2463 case RawFunction::kConstructor: {
2464 bool is_factory = function.IsFactory();
2465 if (is_factory) {
2466 Procedure* procedure = Procedure::Cast(node_);
2467 FunctionNode* function = procedure->function();
2468 return BuildGraphOfFunction(function, NULL);
2469 } else {
2470 Constructor* constructor = Constructor::Cast(node_);
2471 FunctionNode* function = constructor->function();
2472 return BuildGraphOfFunction(function, constructor);
2473 }
2474 }
2475 case RawFunction::kImplicitGetter:
2476 case RawFunction::kImplicitStaticFinalGetter:
2477 case RawFunction::kImplicitSetter: {
2478 Field* field = Field::Cast(node_);
2479 return IsStaticInitializer(function, Z)
2480 ? BuildGraphOfStaticFieldInitializer(field)
2481 : BuildGraphOfFieldAccessor(field, scopes_->setter_value);
2482 }
2483 case RawFunction::kMethodExtractor:
2484 return BuildGraphOfMethodExtractor(function);
2485 case RawFunction::kNoSuchMethodDispatcher:
2486 return BuildGraphOfNoSuchMethodDispatcher(function);
2487 case RawFunction::kInvokeFieldDispatcher:
2488 return BuildGraphOfInvokeFieldDispatcher(function);
2489 case RawFunction::kSignatureFunction:
2490 case RawFunction::kIrregexpFunction:
2491 break;
2492 }
2493 UNREACHABLE();
2494 return NULL;
2495 } 1788 }
2496 1789
2497 1790
2498 FlowGraph* FlowGraphBuilder::BuildGraphOfFunction(FunctionNode* function, 1791 Fragment FlowGraphBuilder::NativeFunctionBody(intptr_t first_positional_offset,
2499 Constructor* constructor) {
2500 const Function& dart_function = parsed_function_->function();
2501 TargetEntryInstr* normal_entry = BuildTargetEntry();
2502 graph_entry_ =
2503 new (Z) GraphEntryInstr(*parsed_function_, normal_entry, osr_id_);
2504
2505 SetupDefaultParameterValues(function);
2506
2507 Fragment body;
2508 if (!dart_function.is_native()) body += CheckStackOverflowInPrologue();
2509 intptr_t context_size =
2510 parsed_function_->node_sequence()->scope()->num_context_variables();
2511 if (context_size > 0) {
2512 body += PushContext(context_size);
2513 LocalVariable* context = MakeTemporary();
2514
2515 // Copy captured parameters from the stack into the context.
2516 LocalScope* scope = parsed_function_->node_sequence()->scope();
2517 intptr_t parameter_count = dart_function.NumParameters();
2518 intptr_t parameter_index = parsed_function_->first_parameter_index();
2519 for (intptr_t i = 0; i < parameter_count; ++i, --parameter_index) {
2520 LocalVariable* variable = scope->VariableAt(i);
2521 if (variable->is_captured()) {
2522 // There is no LocalVariable describing the on-stack parameter so
2523 // create one directly and use the same type.
2524 LocalVariable* parameter = new (Z)
2525 LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
2526 Symbols::TempParam(), variable->type());
2527 parameter->set_index(parameter_index);
2528 // Mark the stack variable so it will be ignored by the code for
2529 // try/catch.
2530 parameter->set_is_captured_parameter(true);
2531
2532 // Copy the parameter from the stack to the context. Overwrite it
2533 // with a null constant on the stack so the original value is
2534 // eligible for garbage collection.
2535 body += LoadLocal(context);
2536 body += LoadLocal(parameter);
2537 body += StoreInstanceField(TokenPosition::kNoSource,
2538 Context::variable_offset(variable->index()));
2539 body += NullConstant();
2540 body += StoreLocal(TokenPosition::kNoSource, parameter);
2541 body += Drop();
2542 }
2543 }
2544 body += Drop(); // The context.
2545 }
2546 if (constructor != NULL) {
2547 // TODO(27590): Currently the [VariableDeclaration]s from the
2548 // initializers will be visible inside the entire body of the constructor.
2549 // We should make a separate scope for them.
2550 Class* kernel_class = Class::Cast(constructor->parent());
2551 body += TranslateInitializers(kernel_class, &constructor->initializers());
2552 }
2553
2554 // The specification defines the result of `a == b` to be:
2555 //
2556 // a) if either side is `null` then the result is `identical(a, b)`.
2557 // b) else the result is `a.operator==(b)`
2558 //
2559 // For user-defined implementations of `operator==` we need therefore
2560 // implement the handling of a).
2561 //
2562 // The default `operator==` implementation in `Object` is implemented in terms
2563 // of identical (which we assume here!) which means that case a) is actually
2564 // included in b). So we just use the normal implementation in the body.
2565 if ((dart_function.NumParameters() == 2) &&
2566 (dart_function.name() == Symbols::EqualOperator().raw()) &&
2567 (dart_function.Owner() != I->object_store()->object_class())) {
2568 LocalVariable* parameter =
2569 LookupVariable(function->positional_parameters()[0]);
2570
2571 TargetEntryInstr* null_entry;
2572 TargetEntryInstr* non_null_entry;
2573
2574 body += LoadLocal(parameter);
2575 body += BranchIfNull(&null_entry, &non_null_entry);
2576
2577 // The argument was `null` and the receiver is not the null class (we only
2578 // go into this branch for user-defined == operators) so we can return
2579 // false.
2580 Fragment null_fragment(null_entry);
2581 null_fragment += Constant(Bool::False());
2582 null_fragment += Return(dart_function.end_token_pos());
2583
2584 body = Fragment(body.entry, non_null_entry);
2585 }
2586
2587 // If we run in checked mode, we have to check the type of the passed
2588 // arguments.
2589 if (I->type_checks()) {
2590 List<VariableDeclaration>& positional = function->positional_parameters();
2591 List<VariableDeclaration>& named = function->named_parameters();
2592
2593 for (intptr_t i = 0; i < positional.length(); i++) {
2594 VariableDeclaration* variable = positional[i];
2595 body += LoadLocal(LookupVariable(variable));
2596 body += CheckVariableTypeInCheckedMode(variable);
2597 body += Drop();
2598 }
2599 for (intptr_t i = 0; i < named.length(); i++) {
2600 VariableDeclaration* variable = named[i];
2601 body += LoadLocal(LookupVariable(variable));
2602 body += CheckVariableTypeInCheckedMode(variable);
2603 body += Drop();
2604 }
2605 }
2606
2607 if (FLAG_causal_async_stacks &&
2608 (dart_function.IsAsyncFunction() || dart_function.IsAsyncGenerator())) {
2609 LocalScope* scope = parsed_function_->node_sequence()->scope();
2610 // :async_stack_trace = _asyncStackTraceHelper(:async_op);
2611 const dart::Library& async_lib =
2612 dart::Library::Handle(dart::Library::AsyncLibrary());
2613 const Function& target = Function::ZoneHandle(
2614 Z,
2615 async_lib.LookupFunctionAllowPrivate(Symbols::AsyncStackTraceHelper()));
2616 ASSERT(!target.IsNull());
2617
2618 // TODO(johnmccutchan): Why does this have the null value?
2619 LocalVariable* async_op =
2620 scope->child()->LookupVariable(Symbols::AsyncOperation(), false);
2621 ASSERT(async_op != NULL);
2622 ASSERT(async_op->is_captured());
2623 body += LoadLocal(async_op);
2624 body += PushArgument();
2625 body += StaticCall(TokenPosition::kNoSource, target, 1);
2626 LocalVariable* async_stack_trace_var =
2627 scope->LookupVariable(Symbols::AsyncStackTraceVar(), false);
2628 ASSERT(async_stack_trace_var != NULL);
2629 body += StoreLocal(TokenPosition::kNoSource, async_stack_trace_var);
2630 body += Drop();
2631 }
2632
2633 if (dart_function.is_native()) {
2634 body += NativeFunctionBody(function, dart_function);
2635 } else if (function->body() != NULL) {
2636 body += TranslateStatement(function->body());
2637 }
2638 if (body.is_open()) {
2639 body += NullConstant();
2640 body += Return(dart_function.end_token_pos());
2641 }
2642
2643 // If functions body contains any yield points build switch statement that
2644 // selects a continuation point based on the value of :await_jump_var.
2645 if (!yield_continuations_.is_empty()) {
2646 // The code we are building will be executed right after we enter
2647 // the function and before any nested contexts are allocated.
2648 // Reset current context_depth_ to match this.
2649 const intptr_t current_context_depth = context_depth_;
2650 context_depth_ = scopes_->yield_jump_variable->owner()->context_level();
2651
2652 // Prepend an entry corresponding to normal entry to the function.
2653 yield_continuations_.InsertAt(
2654 0, YieldContinuation(new (Z) DropTempsInstr(0, NULL),
2655 CatchClauseNode::kInvalidTryIndex));
2656 yield_continuations_[0].entry->LinkTo(body.entry);
2657
2658 // Build a switch statement.
2659 Fragment dispatch;
2660
2661 // Load :await_jump_var into a temporary.
2662 dispatch += LoadLocal(scopes_->yield_jump_variable);
2663 dispatch += StoreLocal(TokenPosition::kNoSource, scopes_->switch_variable);
2664 dispatch += Drop();
2665
2666 BlockEntryInstr* block = NULL;
2667 for (intptr_t i = 0; i < yield_continuations_.length(); i++) {
2668 if (i == 1) {
2669 // This is not a normal entry but a resumption. Restore
2670 // :current_context_var from :await_ctx_var.
2671 // Note: after this point context_depth_ does not match current context
2672 // depth so we should not access any local variables anymore.
2673 dispatch += LoadLocal(scopes_->yield_context_variable);
2674 dispatch += StoreLocal(TokenPosition::kNoSource,
2675 parsed_function_->current_context_var());
2676 dispatch += Drop();
2677 }
2678 if (i == (yield_continuations_.length() - 1)) {
2679 // We reached the last possility, no need to build more ifs.
2680 // Continue to the last continuation.
2681 // Note: continuations start with nop DropTemps instruction
2682 // which acts like an anchor, so we need to skip it.
2683 block->set_try_index(yield_continuations_[i].try_index);
2684 dispatch <<= yield_continuations_[i].entry->next();
2685 break;
2686 }
2687
2688 // Build comparison:
2689 //
2690 // if (:await_ctx_var == i) {
2691 // -> yield_continuations_[i]
2692 // } else ...
2693 //
2694 TargetEntryInstr* then;
2695 TargetEntryInstr* otherwise;
2696 dispatch += LoadLocal(scopes_->switch_variable);
2697 dispatch += IntConstant(i);
2698 dispatch += BranchIfStrictEqual(&then, &otherwise);
2699
2700 // True branch is linked to appropriate continuation point.
2701 // Note: continuations start with nop DropTemps instruction
2702 // which acts like an anchor, so we need to skip it.
2703 then->LinkTo(yield_continuations_[i].entry->next());
2704 then->set_try_index(yield_continuations_[i].try_index);
2705 // False branch will contain the next comparison.
2706 dispatch = Fragment(dispatch.entry, otherwise);
2707 block = otherwise;
2708 }
2709 body = dispatch;
2710
2711 context_depth_ = current_context_depth;
2712 }
2713
2714 if (FLAG_causal_async_stacks &&
2715 (dart_function.IsAsyncClosure() || dart_function.IsAsyncGenClosure())) {
2716 // The code we are building will be executed right after we enter
2717 // the function and before any nested contexts are allocated.
2718 // Reset current context_depth_ to match this.
2719 const intptr_t current_context_depth = context_depth_;
2720 context_depth_ = scopes_->yield_jump_variable->owner()->context_level();
2721
2722 Fragment instructions;
2723 LocalScope* scope = parsed_function_->node_sequence()->scope();
2724
2725 const Function& target = Function::ZoneHandle(
2726 Z, I->object_store()->async_set_thread_stack_trace());
2727 ASSERT(!target.IsNull());
2728
2729 // Fetch and load :async_stack_trace
2730 LocalVariable* async_stack_trace_var =
2731 scope->LookupVariable(Symbols::AsyncStackTraceVar(), false);
2732 ASSERT((async_stack_trace_var != NULL) &&
2733 async_stack_trace_var->is_captured());
2734 instructions += LoadLocal(async_stack_trace_var);
2735 instructions += PushArgument();
2736
2737 // Call _asyncSetThreadStackTrace
2738 instructions += StaticCall(TokenPosition::kNoSource, target, 1);
2739 instructions += Drop();
2740
2741 body = instructions + body;
2742 context_depth_ = current_context_depth;
2743 }
2744
2745 if (NeedsDebugStepCheck(dart_function, function->position())) {
2746 // If a switch was added above: Start the switch by injecting a debuggable
2747 // safepoint so stepping over an await works.
2748 // If not, still start the body with a debuggable safepoint to ensure
2749 // breaking on a method always happens, even if there are no
2750 // assignments/calls/runtimecalls in the first basic block.
2751 // Place this check at the last parameter to ensure parameters
2752 // are in scope in the debugger at method entry.
2753 const int num_params = dart_function.NumParameters();
2754 TokenPosition check_pos = TokenPosition::kNoSource;
2755 if (num_params > 0) {
2756 LocalScope* scope = parsed_function_->node_sequence()->scope();
2757 const LocalVariable& parameter = *scope->VariableAt(num_params - 1);
2758 check_pos = parameter.token_pos();
2759 }
2760 if (!check_pos.IsDebugPause()) {
2761 // No parameters or synthetic parameters.
2762 check_pos = function->position();
2763 ASSERT(check_pos.IsDebugPause());
2764 }
2765 body = DebugStepCheck(check_pos) + body;
2766 }
2767
2768 normal_entry->LinkTo(body.entry);
2769
2770 // When compiling for OSR, use a depth first search to prune instructions
2771 // unreachable from the OSR entry. Catch entries are always considered
2772 // reachable, even if they become unreachable after OSR.
2773 if (osr_id_ != Compiler::kNoOSRDeoptId) {
2774 BitVector* block_marks = new (Z) BitVector(Z, next_block_id_);
2775 bool found = graph_entry_->PruneUnreachable(graph_entry_, NULL, osr_id_,
2776 block_marks);
2777 ASSERT(found);
2778 }
2779 return new (Z) FlowGraph(*parsed_function_, graph_entry_, next_block_id_ - 1);
2780 }
2781
2782
2783 Fragment FlowGraphBuilder::NativeFunctionBody(FunctionNode* kernel_function,
2784 const Function& function) { 1792 const Function& function) {
2785 ASSERT(function.is_native()); 1793 ASSERT(function.is_native());
2786 // We explicitly build the graph for native functions in the same way that the 1794 // We explicitly build the graph for native functions in the same way that the
2787 // from-source backend does. We should find a way to have a single component 1795 // from-source backend does. We should find a way to have a single component
2788 // to build these graphs so that this code is not duplicated. 1796 // to build these graphs so that this code is not duplicated.
2789 1797
2790 Fragment body; 1798 Fragment body;
2791 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function); 1799 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function);
2792 switch (kind) { 1800 switch (kind) {
2793 case MethodRecognizer::kObjectEquals: 1801 case MethodRecognizer::kObjectEquals:
2794 body += LoadLocal(scopes_->this_variable); 1802 body += LoadLocal(scopes_->this_variable);
2795 body += LoadLocal( 1803 body += LoadLocal(LookupVariable(first_positional_offset));
2796 LookupVariable(kernel_function->positional_parameters()[0]));
2797 body += StrictCompare(Token::kEQ_STRICT); 1804 body += StrictCompare(Token::kEQ_STRICT);
2798 break; 1805 break;
2799 case MethodRecognizer::kStringBaseLength: 1806 case MethodRecognizer::kStringBaseLength:
2800 case MethodRecognizer::kStringBaseIsEmpty: 1807 case MethodRecognizer::kStringBaseIsEmpty:
2801 // Depending on FLAG_support_externalizable_strings, treat string length 1808 // Depending on FLAG_support_externalizable_strings, treat string length
2802 // loads as mutable so that the class check that precedes them will not be 1809 // loads as mutable so that the class check that precedes them will not be
2803 // hoisted. This is unsafe because string externalization can change the 1810 // hoisted. This is unsafe because string externalization can change the
2804 // class. 1811 // class.
2805 body += LoadLocal(scopes_->this_variable); 1812 body += LoadLocal(scopes_->this_variable);
2806 body += LoadNativeField(MethodRecognizer::kStringBaseLength, 1813 body += LoadNativeField(MethodRecognizer::kStringBaseLength,
(...skipping 17 matching lines...) Expand all
2824 LoadNativeField(kind, Array::length_offset(), 1831 LoadNativeField(kind, Array::length_offset(),
2825 Type::ZoneHandle(Z, Type::SmiType()), kSmiCid, true); 1832 Type::ZoneHandle(Z, Type::SmiType()), kSmiCid, true);
2826 break; 1833 break;
2827 case MethodRecognizer::kTypedDataLength: 1834 case MethodRecognizer::kTypedDataLength:
2828 body += LoadLocal(scopes_->this_variable); 1835 body += LoadLocal(scopes_->this_variable);
2829 body += 1836 body +=
2830 LoadNativeField(kind, TypedData::length_offset(), 1837 LoadNativeField(kind, TypedData::length_offset(),
2831 Type::ZoneHandle(Z, Type::SmiType()), kSmiCid, true); 1838 Type::ZoneHandle(Z, Type::SmiType()), kSmiCid, true);
2832 break; 1839 break;
2833 case MethodRecognizer::kClassIDgetID: 1840 case MethodRecognizer::kClassIDgetID:
2834 body += LoadLocal( 1841 body += LoadLocal(LookupVariable(first_positional_offset));
2835 LookupVariable(kernel_function->positional_parameters()[0]));
2836 body += LoadClassId(); 1842 body += LoadClassId();
2837 break; 1843 break;
2838 case MethodRecognizer::kGrowableArrayCapacity: 1844 case MethodRecognizer::kGrowableArrayCapacity:
2839 body += LoadLocal(scopes_->this_variable); 1845 body += LoadLocal(scopes_->this_variable);
2840 body += LoadField(Array::data_offset(), kArrayCid); 1846 body += LoadField(Array::data_offset(), kArrayCid);
2841 body += LoadNativeField(MethodRecognizer::kObjectArrayLength, 1847 body += LoadNativeField(MethodRecognizer::kObjectArrayLength,
2842 Array::length_offset(), 1848 Array::length_offset(),
2843 Type::ZoneHandle(Z, Type::SmiType()), kSmiCid); 1849 Type::ZoneHandle(Z, Type::SmiType()), kSmiCid);
2844 break; 1850 break;
2845 case MethodRecognizer::kObjectArrayAllocate: 1851 case MethodRecognizer::kObjectArrayAllocate:
2846 body += LoadLocal(scopes_->type_arguments_variable); 1852 body += LoadLocal(scopes_->type_arguments_variable);
2847 body += LoadLocal( 1853 body += LoadLocal(LookupVariable(first_positional_offset));
2848 LookupVariable(kernel_function->positional_parameters()[0]));
2849 body += CreateArray(); 1854 body += CreateArray();
2850 break; 1855 break;
2851 case MethodRecognizer::kBigint_getDigits: 1856 case MethodRecognizer::kBigint_getDigits:
2852 body += LoadLocal(scopes_->this_variable); 1857 body += LoadLocal(scopes_->this_variable);
2853 body += LoadNativeField(kind, Bigint::digits_offset(), 1858 body += LoadNativeField(kind, Bigint::digits_offset(),
2854 Object::dynamic_type(), kTypedDataUint32ArrayCid); 1859 Object::dynamic_type(), kTypedDataUint32ArrayCid);
2855 break; 1860 break;
2856 case MethodRecognizer::kBigint_getUsed: 1861 case MethodRecognizer::kBigint_getUsed:
2857 body += LoadLocal(scopes_->this_variable); 1862 body += LoadLocal(scopes_->this_variable);
2858 body += LoadNativeField(kind, Bigint::used_offset(), 1863 body += LoadNativeField(kind, Bigint::used_offset(),
2859 Type::ZoneHandle(Z, Type::SmiType()), kSmiCid); 1864 Type::ZoneHandle(Z, Type::SmiType()), kSmiCid);
2860 break; 1865 break;
2861 case MethodRecognizer::kLinkedHashMap_getIndex: 1866 case MethodRecognizer::kLinkedHashMap_getIndex:
2862 body += LoadLocal(scopes_->this_variable); 1867 body += LoadLocal(scopes_->this_variable);
2863 body += LoadNativeField(kind, LinkedHashMap::index_offset(), 1868 body += LoadNativeField(kind, LinkedHashMap::index_offset(),
2864 Object::dynamic_type(), kDynamicCid); 1869 Object::dynamic_type(), kDynamicCid);
2865 break; 1870 break;
2866 case MethodRecognizer::kLinkedHashMap_setIndex: 1871 case MethodRecognizer::kLinkedHashMap_setIndex:
2867 body += LoadLocal(scopes_->this_variable); 1872 body += LoadLocal(scopes_->this_variable);
2868 body += LoadLocal( 1873 body += LoadLocal(LookupVariable(first_positional_offset));
2869 LookupVariable(kernel_function->positional_parameters()[0]));
2870 body += StoreInstanceField(TokenPosition::kNoSource, 1874 body += StoreInstanceField(TokenPosition::kNoSource,
2871 LinkedHashMap::index_offset()); 1875 LinkedHashMap::index_offset());
2872 body += NullConstant(); 1876 body += NullConstant();
2873 break; 1877 break;
2874 case MethodRecognizer::kLinkedHashMap_getData: 1878 case MethodRecognizer::kLinkedHashMap_getData:
2875 body += LoadLocal(scopes_->this_variable); 1879 body += LoadLocal(scopes_->this_variable);
2876 body += LoadNativeField(kind, LinkedHashMap::data_offset(), 1880 body += LoadNativeField(kind, LinkedHashMap::data_offset(),
2877 Object::dynamic_type(), kArrayCid); 1881 Object::dynamic_type(), kArrayCid);
2878 break; 1882 break;
2879 case MethodRecognizer::kLinkedHashMap_setData: 1883 case MethodRecognizer::kLinkedHashMap_setData:
2880 body += LoadLocal(scopes_->this_variable); 1884 body += LoadLocal(scopes_->this_variable);
2881 body += LoadLocal( 1885 body += LoadLocal(LookupVariable(first_positional_offset));
2882 LookupVariable(kernel_function->positional_parameters()[0]));
2883 body += StoreInstanceField(TokenPosition::kNoSource, 1886 body += StoreInstanceField(TokenPosition::kNoSource,
2884 LinkedHashMap::data_offset()); 1887 LinkedHashMap::data_offset());
2885 body += NullConstant(); 1888 body += NullConstant();
2886 break; 1889 break;
2887 case MethodRecognizer::kLinkedHashMap_getHashMask: 1890 case MethodRecognizer::kLinkedHashMap_getHashMask:
2888 body += LoadLocal(scopes_->this_variable); 1891 body += LoadLocal(scopes_->this_variable);
2889 body += LoadNativeField(kind, LinkedHashMap::hash_mask_offset(), 1892 body += LoadNativeField(kind, LinkedHashMap::hash_mask_offset(),
2890 Type::ZoneHandle(Z, Type::SmiType()), kSmiCid); 1893 Type::ZoneHandle(Z, Type::SmiType()), kSmiCid);
2891 break; 1894 break;
2892 case MethodRecognizer::kLinkedHashMap_setHashMask: 1895 case MethodRecognizer::kLinkedHashMap_setHashMask:
2893 body += LoadLocal(scopes_->this_variable); 1896 body += LoadLocal(scopes_->this_variable);
2894 body += LoadLocal( 1897 body += LoadLocal(LookupVariable(first_positional_offset));
2895 LookupVariable(kernel_function->positional_parameters()[0]));
2896 body += StoreInstanceField(TokenPosition::kNoSource, 1898 body += StoreInstanceField(TokenPosition::kNoSource,
2897 LinkedHashMap::hash_mask_offset(), 1899 LinkedHashMap::hash_mask_offset(),
2898 kNoStoreBarrier); 1900 kNoStoreBarrier);
2899 body += NullConstant(); 1901 body += NullConstant();
2900 break; 1902 break;
2901 case MethodRecognizer::kLinkedHashMap_getUsedData: 1903 case MethodRecognizer::kLinkedHashMap_getUsedData:
2902 body += LoadLocal(scopes_->this_variable); 1904 body += LoadLocal(scopes_->this_variable);
2903 body += LoadNativeField(kind, LinkedHashMap::used_data_offset(), 1905 body += LoadNativeField(kind, LinkedHashMap::used_data_offset(),
2904 Type::ZoneHandle(Z, Type::SmiType()), kSmiCid); 1906 Type::ZoneHandle(Z, Type::SmiType()), kSmiCid);
2905 break; 1907 break;
2906 case MethodRecognizer::kLinkedHashMap_setUsedData: 1908 case MethodRecognizer::kLinkedHashMap_setUsedData:
2907 body += LoadLocal(scopes_->this_variable); 1909 body += LoadLocal(scopes_->this_variable);
2908 body += LoadLocal( 1910 body += LoadLocal(LookupVariable(first_positional_offset));
2909 LookupVariable(kernel_function->positional_parameters()[0]));
2910 body += StoreInstanceField(TokenPosition::kNoSource, 1911 body += StoreInstanceField(TokenPosition::kNoSource,
2911 LinkedHashMap::used_data_offset(), 1912 LinkedHashMap::used_data_offset(),
2912 kNoStoreBarrier); 1913 kNoStoreBarrier);
2913 body += NullConstant(); 1914 body += NullConstant();
2914 break; 1915 break;
2915 case MethodRecognizer::kLinkedHashMap_getDeletedKeys: 1916 case MethodRecognizer::kLinkedHashMap_getDeletedKeys:
2916 body += LoadLocal(scopes_->this_variable); 1917 body += LoadLocal(scopes_->this_variable);
2917 body += LoadNativeField(kind, LinkedHashMap::deleted_keys_offset(), 1918 body += LoadNativeField(kind, LinkedHashMap::deleted_keys_offset(),
2918 Type::ZoneHandle(Z, Type::SmiType()), kSmiCid); 1919 Type::ZoneHandle(Z, Type::SmiType()), kSmiCid);
2919 break; 1920 break;
2920 case MethodRecognizer::kLinkedHashMap_setDeletedKeys: 1921 case MethodRecognizer::kLinkedHashMap_setDeletedKeys:
2921 body += LoadLocal(scopes_->this_variable); 1922 body += LoadLocal(scopes_->this_variable);
2922 body += LoadLocal( 1923 body += LoadLocal(LookupVariable(first_positional_offset));
2923 LookupVariable(kernel_function->positional_parameters()[0]));
2924 body += StoreInstanceField(TokenPosition::kNoSource, 1924 body += StoreInstanceField(TokenPosition::kNoSource,
2925 LinkedHashMap::deleted_keys_offset(), 1925 LinkedHashMap::deleted_keys_offset(),
2926 kNoStoreBarrier); 1926 kNoStoreBarrier);
2927 body += NullConstant(); 1927 body += NullConstant();
2928 break; 1928 break;
2929 case MethodRecognizer::kBigint_getNeg: 1929 case MethodRecognizer::kBigint_getNeg:
2930 body += LoadLocal(scopes_->this_variable); 1930 body += LoadLocal(scopes_->this_variable);
2931 body += LoadNativeField(kind, Bigint::neg_offset(), 1931 body += LoadNativeField(kind, Bigint::neg_offset(),
2932 Type::ZoneHandle(Z, Type::BoolType()), kBoolCid); 1932 Type::ZoneHandle(Z, Type::BoolType()), kBoolCid);
2933 break; 1933 break;
2934 default: { 1934 default: {
2935 dart::String& name = dart::String::ZoneHandle(Z, function.native_name()); 1935 dart::String& name = dart::String::ZoneHandle(Z, function.native_name());
2936 body += NativeCall(&name, &function); 1936 body += NativeCall(&name, &function);
2937 break; 1937 break;
2938 } 1938 }
2939 } 1939 }
2940 return body + Return(TokenPosition::kNoSource); 1940 return body + Return(TokenPosition::kNoSource);
2941 } 1941 }
2942 1942
2943 1943
2944 FlowGraph* FlowGraphBuilder::BuildGraphOfFieldAccessor(
2945 Field* kernel_field,
2946 LocalVariable* setter_value) {
2947 const Function& function = parsed_function_->function();
2948
2949 bool is_setter = function.IsImplicitSetterFunction();
2950 bool is_method = !function.IsStaticFunction();
2951 dart::Field& field = dart::Field::ZoneHandle(
2952 Z, H.LookupFieldByKernelField(kernel_field->canonical_name()));
2953
2954 TargetEntryInstr* normal_entry = BuildTargetEntry();
2955 graph_entry_ = new (Z)
2956 GraphEntryInstr(*parsed_function_, normal_entry, Compiler::kNoOSRDeoptId);
2957
2958 Fragment body(normal_entry);
2959 if (is_setter) {
2960 if (is_method) {
2961 body += LoadLocal(scopes_->this_variable);
2962 body += LoadLocal(setter_value);
2963 body += StoreInstanceFieldGuarded(field, false);
2964 } else {
2965 body += LoadLocal(setter_value);
2966 body += StoreStaticField(TokenPosition::kNoSource, field);
2967 }
2968 body += NullConstant();
2969 } else if (is_method) {
2970 body += LoadLocal(scopes_->this_variable);
2971 body += LoadField(field);
2972 } else if (field.is_const()) {
2973 // If the parser needs to know the value of an uninitialized constant field
2974 // it will set the value to the transition sentinel (used to detect circular
2975 // initialization) and then call the implicit getter. Thus, the getter
2976 // cannot contain the InitStaticField instruction that normal static getters
2977 // contain because it would detect spurious circular initialization when it
2978 // checks for the transition sentinel.
2979 Expression* initializer = kernel_field->initializer();
2980 ASSERT(initializer != NULL);
2981 body += Constant(constant_evaluator_.EvaluateExpression(initializer));
2982 } else {
2983 // The field always has an initializer because static fields without
2984 // initializers are initialized eagerly and do not have implicit getters.
2985 ASSERT(field.has_initializer());
2986 body += Constant(field);
2987 body += InitStaticField(field);
2988 body += Constant(field);
2989 body += LoadStaticField();
2990 }
2991 body += Return(TokenPosition::kNoSource);
2992
2993 return new (Z) FlowGraph(*parsed_function_, graph_entry_, next_block_id_ - 1);
2994 }
2995
2996
2997 FlowGraph* FlowGraphBuilder::BuildGraphOfStaticFieldInitializer(
2998 Field* kernel_field) {
2999 ASSERT(kernel_field->IsStatic());
3000
3001 Expression* initializer = kernel_field->initializer();
3002
3003 TargetEntryInstr* normal_entry = BuildTargetEntry();
3004 graph_entry_ = new (Z)
3005 GraphEntryInstr(*parsed_function_, normal_entry, Compiler::kNoOSRDeoptId);
3006
3007 Fragment body(normal_entry);
3008 body += CheckStackOverflowInPrologue();
3009 if (kernel_field->IsConst()) {
3010 body += Constant(constant_evaluator_.EvaluateExpression(initializer));
3011 } else {
3012 body += TranslateExpression(initializer);
3013 }
3014 body += Return(TokenPosition::kNoSource);
3015
3016 return new (Z) FlowGraph(*parsed_function_, graph_entry_, next_block_id_ - 1);
3017 }
3018
3019
3020 Fragment FlowGraphBuilder::BuildImplicitClosureCreation( 1944 Fragment FlowGraphBuilder::BuildImplicitClosureCreation(
3021 const Function& target) { 1945 const Function& target) {
3022 Fragment fragment; 1946 Fragment fragment;
3023 const dart::Class& closure_class = 1947 const dart::Class& closure_class =
3024 dart::Class::ZoneHandle(Z, I->object_store()->closure_class()); 1948 dart::Class::ZoneHandle(Z, I->object_store()->closure_class());
3025 fragment += AllocateObject(closure_class, target); 1949 fragment += AllocateObject(closure_class, target);
3026 LocalVariable* closure = MakeTemporary(); 1950 LocalVariable* closure = MakeTemporary();
3027 1951
3028 // Allocate a context that closes over `this`. 1952 // Allocate a context that closes over `this`.
3029 fragment += AllocateContext(1); 1953 fragment += AllocateContext(1);
(...skipping 27 matching lines...) Expand all
3057 } 1981 }
3058 1982
3059 1983
3060 Fragment FlowGraphBuilder::GuardFieldClass(const dart::Field& field, 1984 Fragment FlowGraphBuilder::GuardFieldClass(const dart::Field& field,
3061 intptr_t deopt_id) { 1985 intptr_t deopt_id) {
3062 return Fragment(new (Z) GuardFieldClassInstr(Pop(), field, deopt_id)); 1986 return Fragment(new (Z) GuardFieldClassInstr(Pop(), field, deopt_id));
3063 } 1987 }
3064 1988
3065 1989
3066 Fragment FlowGraphBuilder::CheckVariableTypeInCheckedMode( 1990 Fragment FlowGraphBuilder::CheckVariableTypeInCheckedMode(
3067 VariableDeclaration* variable) {
3068 if (I->type_checks()) {
3069 const AbstractType& dst_type = T.TranslateType(variable->type());
3070 if (dst_type.IsMalformed()) {
3071 return ThrowTypeError();
3072 }
3073 return CheckAssignableInCheckedMode(dst_type,
3074 H.DartSymbol(variable->name()));
3075 }
3076 return Fragment();
3077 }
3078
3079 Fragment FlowGraphBuilder::CheckVariableTypeInCheckedMode(
3080 const AbstractType& dst_type, 1991 const AbstractType& dst_type,
3081 const dart::String& name_symbol) { 1992 const dart::String& name_symbol) {
3082 if (I->type_checks()) { 1993 if (I->type_checks()) {
3083 if (dst_type.IsMalformed()) { 1994 if (dst_type.IsMalformed()) {
3084 return ThrowTypeError(); 1995 return ThrowTypeError();
3085 } 1996 }
3086 return CheckAssignableInCheckedMode(dst_type, name_symbol); 1997 return CheckAssignableInCheckedMode(dst_type, name_symbol);
3087 } 1998 }
3088 return Fragment(); 1999 return Fragment();
3089 } 2000 }
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
3213 GraphEntryInstr(*parsed_function_, normal_entry, Compiler::kNoOSRDeoptId); 2124 GraphEntryInstr(*parsed_function_, normal_entry, Compiler::kNoOSRDeoptId);
3214 Fragment body(normal_entry); 2125 Fragment body(normal_entry);
3215 body += CheckStackOverflowInPrologue(); 2126 body += CheckStackOverflowInPrologue();
3216 body += BuildImplicitClosureCreation(function); 2127 body += BuildImplicitClosureCreation(function);
3217 body += Return(TokenPosition::kNoSource); 2128 body += Return(TokenPosition::kNoSource);
3218 2129
3219 return new (Z) FlowGraph(*parsed_function_, graph_entry_, next_block_id_ - 1); 2130 return new (Z) FlowGraph(*parsed_function_, graph_entry_, next_block_id_ - 1);
3220 } 2131 }
3221 2132
3222 2133
3223 FlowGraph* FlowGraphBuilder::BuildGraphOfImplicitClosureFunction(
3224 FunctionNode* kernel_function,
3225 const Function& function) {
3226 const Function& target = Function::ZoneHandle(Z, function.parent_function());
3227
3228 TargetEntryInstr* normal_entry = BuildTargetEntry();
3229 graph_entry_ = new (Z)
3230 GraphEntryInstr(*parsed_function_, normal_entry, Compiler::kNoOSRDeoptId);
3231 SetupDefaultParameterValues(kernel_function);
3232
3233 Fragment body(normal_entry);
3234 body += CheckStackOverflowInPrologue();
3235
3236 // Load all the arguments.
3237 if (!target.is_static()) {
3238 // The context has a fixed shape: a single variable which is the
3239 // closed-over receiver.
3240 body += LoadLocal(parsed_function_->current_context_var());
3241 body += LoadField(Context::variable_offset(0));
3242 body += PushArgument();
3243 }
3244 intptr_t positional_argument_count =
3245 kernel_function->positional_parameters().length();
3246 for (intptr_t i = 0; i < positional_argument_count; i++) {
3247 body +=
3248 LoadLocal(LookupVariable(kernel_function->positional_parameters()[i]));
3249 body += PushArgument();
3250 }
3251 intptr_t named_argument_count = kernel_function->named_parameters().length();
3252 Array& argument_names = Array::ZoneHandle(Z);
3253 if (named_argument_count > 0) {
3254 argument_names = Array::New(named_argument_count);
3255 for (intptr_t i = 0; i < named_argument_count; i++) {
3256 VariableDeclaration* variable = kernel_function->named_parameters()[i];
3257 body += LoadLocal(LookupVariable(variable));
3258 body += PushArgument();
3259 argument_names.SetAt(i, H.DartSymbol(variable->name()));
3260 }
3261 }
3262 // Forward them to the target.
3263 intptr_t argument_count = positional_argument_count + named_argument_count;
3264 if (!target.is_static()) ++argument_count;
3265 body += StaticCall(TokenPosition::kNoSource, target, argument_count,
3266 argument_names);
3267
3268 // Return the result.
3269 body += Return(kernel_function->end_position());
3270
3271 return new (Z) FlowGraph(*parsed_function_, graph_entry_, next_block_id_ - 1);
3272 }
3273
3274
3275 FlowGraph* FlowGraphBuilder::BuildGraphOfNoSuchMethodDispatcher( 2134 FlowGraph* FlowGraphBuilder::BuildGraphOfNoSuchMethodDispatcher(
3276 const Function& function) { 2135 const Function& function) {
3277 // This function is specialized for a receiver class, a method name, and 2136 // This function is specialized for a receiver class, a method name, and
3278 // the arguments descriptor at a call site. 2137 // the arguments descriptor at a call site.
3279 2138
3280 TargetEntryInstr* normal_entry = BuildTargetEntry(); 2139 TargetEntryInstr* normal_entry = BuildTargetEntry();
3281 graph_entry_ = new (Z) 2140 graph_entry_ = new (Z)
3282 GraphEntryInstr(*parsed_function_, normal_entry, Compiler::kNoOSRDeoptId); 2141 GraphEntryInstr(*parsed_function_, normal_entry, Compiler::kNoOSRDeoptId);
3283 2142
3284 // The backend will expect an array of default values for all the named 2143 // The backend will expect an array of default values for all the named
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
3453 body += InstanceCall(TokenPosition::kMinSource, Symbols::Call(), 2312 body += InstanceCall(TokenPosition::kMinSource, Symbols::Call(),
3454 Token::kILLEGAL, descriptor.Count(), argument_names); 2313 Token::kILLEGAL, descriptor.Count(), argument_names);
3455 } 2314 }
3456 2315
3457 body += Return(TokenPosition::kNoSource); 2316 body += Return(TokenPosition::kNoSource);
3458 2317
3459 return new (Z) FlowGraph(*parsed_function_, graph_entry_, next_block_id_ - 1); 2318 return new (Z) FlowGraph(*parsed_function_, graph_entry_, next_block_id_ - 1);
3460 } 2319 }
3461 2320
3462 2321
3463 void FlowGraphBuilder::SetupDefaultParameterValues(FunctionNode* function) {
3464 intptr_t num_optional_parameters =
3465 parsed_function_->function().NumOptionalParameters();
3466 if (num_optional_parameters > 0) {
3467 ZoneGrowableArray<const Instance*>* default_values =
3468 new ZoneGrowableArray<const Instance*>(Z, num_optional_parameters);
3469
3470 if (parsed_function_->function().HasOptionalNamedParameters()) {
3471 ASSERT(!parsed_function_->function().HasOptionalPositionalParameters());
3472 for (intptr_t i = 0; i < num_optional_parameters; i++) {
3473 VariableDeclaration* variable = function->named_parameters()[i];
3474 Instance* default_value;
3475 if (variable->initializer() != NULL) {
3476 default_value =
3477 &constant_evaluator_.EvaluateExpression(variable->initializer());
3478 } else {
3479 default_value = &Instance::ZoneHandle(Z, Instance::null());
3480 }
3481 default_values->Add(default_value);
3482 }
3483 } else {
3484 ASSERT(parsed_function_->function().HasOptionalPositionalParameters());
3485 intptr_t required = function->required_parameter_count();
3486 for (intptr_t i = 0; i < num_optional_parameters; i++) {
3487 VariableDeclaration* variable =
3488 function->positional_parameters()[required + i];
3489 Instance* default_value;
3490 if (variable->initializer() != NULL) {
3491 default_value =
3492 &constant_evaluator_.EvaluateExpression(variable->initializer());
3493 } else {
3494 default_value = &Instance::ZoneHandle(Z, Instance::null());
3495 }
3496 default_values->Add(default_value);
3497 }
3498 }
3499 parsed_function_->set_default_parameter_values(default_values);
3500 }
3501 }
3502
3503
3504 TargetEntryInstr* FlowGraphBuilder::BuildTargetEntry() { 2322 TargetEntryInstr* FlowGraphBuilder::BuildTargetEntry() {
3505 return new (Z) TargetEntryInstr(AllocateBlockId(), CurrentTryIndex()); 2323 return new (Z) TargetEntryInstr(AllocateBlockId(), CurrentTryIndex());
3506 } 2324 }
3507 2325
3508 2326
3509 JoinEntryInstr* FlowGraphBuilder::BuildJoinEntry(intptr_t try_index) { 2327 JoinEntryInstr* FlowGraphBuilder::BuildJoinEntry(intptr_t try_index) {
3510 return new (Z) JoinEntryInstr(AllocateBlockId(), try_index); 2328 return new (Z) JoinEntryInstr(AllocateBlockId(), try_index);
3511 } 2329 }
3512 2330
3513 2331
3514 JoinEntryInstr* FlowGraphBuilder::BuildJoinEntry() { 2332 JoinEntryInstr* FlowGraphBuilder::BuildJoinEntry() {
3515 return new (Z) JoinEntryInstr(AllocateBlockId(), CurrentTryIndex()); 2333 return new (Z) JoinEntryInstr(AllocateBlockId(), CurrentTryIndex());
3516 } 2334 }
3517 2335
3518
3519 Fragment FlowGraphBuilder::TranslateFieldInitializer(NameIndex canonical_name,
3520 Expression* init) {
3521 dart::Field& field =
3522 dart::Field::ZoneHandle(Z, H.LookupFieldByKernelField(canonical_name));
3523 if (init->IsNullLiteral()) {
3524 field.RecordStore(Object::null_object());
3525 return Fragment();
3526 }
3527 Fragment instructions;
3528 instructions += LoadLocal(scopes_->this_variable);
3529 instructions += TranslateExpression(init);
3530 instructions += StoreInstanceFieldGuarded(field, true);
3531 return instructions;
3532 }
3533
3534
3535 Fragment FlowGraphBuilder::TranslateInitializers(
3536 Class* kernel_class,
3537 List<Initializer>* initializers) {
3538 Fragment instructions;
3539
3540 // These come from:
3541 // class A {
3542 // var x = (expr);
3543 // }
3544 for (intptr_t i = 0; i < kernel_class->fields().length(); i++) {
3545 Field* kernel_field = kernel_class->fields()[i];
3546 Expression* init = kernel_field->initializer();
3547 if (!kernel_field->IsStatic() && init != NULL) {
3548 EnterScope(kernel_field);
3549 instructions +=
3550 TranslateFieldInitializer(kernel_field->canonical_name(), init);
3551 ExitScope(kernel_field);
3552 }
3553 }
3554
3555 // These to come from:
3556 // class A {
3557 // var x;
3558 // var y;
3559 // A(this.x) : super(expr), y = (expr);
3560 // }
3561 for (intptr_t i = 0; i < initializers->length(); i++) {
3562 Initializer* initializer = (*initializers)[i];
3563 if (initializer->IsFieldInitializer()) {
3564 FieldInitializer* init = FieldInitializer::Cast(initializer);
3565 instructions += TranslateFieldInitializer(init->field(), init->value());
3566 } else if (initializer->IsSuperInitializer()) {
3567 SuperInitializer* init = SuperInitializer::Cast(initializer);
3568
3569 instructions += LoadLocal(scopes_->this_variable);
3570 instructions += PushArgument();
3571
3572 ASSERT(init->arguments()->types().length() == 0);
3573 Array& argument_names = Array::ZoneHandle(Z);
3574 instructions += TranslateArguments(init->arguments(), &argument_names);
3575
3576 const Function& target = Function::ZoneHandle(
3577 Z, H.LookupConstructorByKernelConstructor(init->target()));
3578 intptr_t argument_count = init->arguments()->count() + 1;
3579 instructions += StaticCall(TokenPosition::kNoSource, target,
3580 argument_count, argument_names);
3581 instructions += Drop();
3582 } else if (initializer->IsRedirectingInitializer()) {
3583 RedirectingInitializer* init = RedirectingInitializer::Cast(initializer);
3584
3585 instructions += LoadLocal(scopes_->this_variable);
3586 instructions += PushArgument();
3587
3588 ASSERT(init->arguments()->types().length() == 0);
3589 Array& argument_names = Array::ZoneHandle(Z);
3590 instructions += TranslateArguments(init->arguments(), &argument_names);
3591
3592 const Function& target = Function::ZoneHandle(
3593 Z, H.LookupConstructorByKernelConstructor(init->target()));
3594 intptr_t argument_count = init->arguments()->count() + 1;
3595 instructions += StaticCall(TokenPosition::kNoSource, target,
3596 argument_count, argument_names);
3597 instructions += Drop();
3598 } else if (initializer->IsLocalInitializer()) {
3599 // The other initializers following this one might read the variable. This
3600 // is used e.g. for evaluating the arguments to a super call first, run
3601 // normal field initializers next and then make the actual super call:
3602 //
3603 // The frontend converts
3604 //
3605 // class A {
3606 // var x;
3607 // A(a, b) : super(a + b), x = 2*b {}
3608 // }
3609 //
3610 // to
3611 //
3612 // class A {
3613 // var x;
3614 // A(a, b) : tmp = a + b, x = 2*b, super(tmp) {}
3615 // }
3616 //
3617 // (This is strictly speaking not what one should do in terms of the
3618 // specification but that is how it is currently implemented.)
3619 LocalInitializer* init = LocalInitializer::Cast(initializer);
3620
3621 VariableDeclaration* declaration = init->variable();
3622 LocalVariable* variable = LookupVariable(declaration);
3623 Expression* initializer = init->variable()->initializer();
3624 ASSERT(initializer != NULL);
3625 ASSERT(!declaration->IsConst());
3626
3627 instructions += TranslateExpression(initializer);
3628 instructions += StoreLocal(TokenPosition::kNoSource, variable);
3629 instructions += Drop();
3630
3631 fragment_ = instructions;
3632 } else {
3633 UNIMPLEMENTED();
3634 }
3635 }
3636 return instructions;
3637 }
3638
3639
3640 Fragment FlowGraphBuilder::TranslateStatement(Statement* statement) {
3641 #ifdef DEBUG
3642 intptr_t original_context_depth = context_depth_;
3643 #endif
3644
3645 // TODO(jensj): VariableDeclaration doesn't necessarily have a tag.
3646 if (statement->can_stream() &&
3647 statement->Type() != Node::kTypeVariableDeclaration) {
3648 fragment_ = streaming_flow_graph_builder_->BuildStatementAt(
3649 statement->kernel_offset());
3650 } else {
3651 statement->AcceptStatementVisitor(this);
3652 }
3653 DEBUG_ASSERT(context_depth_ == original_context_depth);
3654 return fragment_;
3655 }
3656
3657
3658 Fragment FlowGraphBuilder::TranslateCondition(Expression* expression,
3659 bool* negate) {
3660 *negate = expression->IsNot();
3661 Fragment instructions;
3662 if (*negate) {
3663 instructions += TranslateExpression(Not::Cast(expression)->expression());
3664 } else {
3665 instructions += TranslateExpression(expression);
3666 }
3667 instructions += CheckBooleanInCheckedMode();
3668 return instructions;
3669 }
3670
3671
3672 Fragment FlowGraphBuilder::TranslateExpression(Expression* expression) {
3673 if (expression->can_stream()) {
3674 fragment_ = streaming_flow_graph_builder_->BuildExpressionAt(
3675 expression->kernel_offset());
3676 } else {
3677 expression->AcceptExpressionVisitor(this);
3678 }
3679 return fragment_;
3680 }
3681
3682
3683 ArgumentArray FlowGraphBuilder::GetArguments(int count) { 2336 ArgumentArray FlowGraphBuilder::GetArguments(int count) {
3684 ArgumentArray arguments = 2337 ArgumentArray arguments =
3685 new (Z) ZoneGrowableArray<PushArgumentInstr*>(Z, count); 2338 new (Z) ZoneGrowableArray<PushArgumentInstr*>(Z, count);
3686 arguments->SetLength(count); 2339 arguments->SetLength(count);
3687 for (intptr_t i = count - 1; i >= 0; --i) { 2340 for (intptr_t i = count - 1; i >= 0; --i) {
3688 ASSERT(stack_->definition()->IsPushArgument()); 2341 ASSERT(stack_->definition()->IsPushArgument());
3689 ASSERT(!stack_->definition()->HasSSATemp()); 2342 ASSERT(!stack_->definition()->HasSSATemp());
3690 arguments->data()[i] = stack_->definition()->AsPushArgument(); 2343 arguments->data()[i] = stack_->definition()->AsPushArgument();
3691 Drop(); 2344 Drop();
3692 } 2345 }
3693 pending_argument_count_ -= count; 2346 pending_argument_count_ -= count;
3694 ASSERT(pending_argument_count_ >= 0); 2347 ASSERT(pending_argument_count_ >= 0);
3695 return arguments; 2348 return arguments;
3696 } 2349 }
3697 2350
3698 2351
3699 #define STREAM_EXPRESSION_IF_POSSIBLE(node) \ 2352 #define STREAM_EXPRESSION_IF_POSSIBLE(node) \
3700 if (node->can_stream()) { \ 2353 if (node->can_stream()) { \
3701 fragment_ = streaming_flow_graph_builder_->BuildExpressionAt( \ 2354 fragment_ = streaming_flow_graph_builder_->BuildExpressionAt( \
3702 node->kernel_offset()); \ 2355 node->kernel_offset()); \
3703 return; \ 2356 return; \
3704 } 2357 }
3705 2358
3706 2359
3707 void FlowGraphBuilder::VisitInvalidExpression(InvalidExpression* node) {
3708 fragment_ =
3709 streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset());
3710 }
3711
3712
3713 void FlowGraphBuilder::VisitNullLiteral(NullLiteral* node) {
3714 fragment_ =
3715 streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset());
3716 }
3717
3718
3719 void FlowGraphBuilder::VisitBoolLiteral(BoolLiteral* node) {
3720 fragment_ =
3721 streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset());
3722 }
3723
3724
3725 void FlowGraphBuilder::VisitIntLiteral(IntLiteral* node) {
3726 fragment_ =
3727 streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset());
3728 }
3729
3730
3731 void FlowGraphBuilder::VisitBigintLiteral(BigintLiteral* node) {
3732 fragment_ =
3733 streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset());
3734 }
3735
3736
3737 void FlowGraphBuilder::VisitDoubleLiteral(DoubleLiteral* node) {
3738 fragment_ =
3739 streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset());
3740 }
3741
3742
3743 void FlowGraphBuilder::VisitStringLiteral(StringLiteral* node) {
3744 fragment_ =
3745 streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset());
3746 }
3747
3748
3749 void FlowGraphBuilder::VisitSymbolLiteral(SymbolLiteral* node) {
3750 fragment_ =
3751 streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset());
3752 }
3753
3754
3755 AbstractType& DartTypeTranslator::TranslateType(DartType* node) { 2360 AbstractType& DartTypeTranslator::TranslateType(DartType* node) {
3756 node->AcceptDartTypeVisitor(this); 2361 node->AcceptDartTypeVisitor(this);
3757 2362
3758 // We return a new `ZoneHandle` here on purpose: The intermediate language 2363 // We return a new `ZoneHandle` here on purpose: The intermediate language
3759 // instructions do not make a copy of the handle, so we do it. 2364 // instructions do not make a copy of the handle, so we do it.
3760 return AbstractType::ZoneHandle(Z, result_.raw()); 2365 return AbstractType::ZoneHandle(Z, result_.raw());
3761 } 2366 }
3762 2367
3763 2368
3764 AbstractType& DartTypeTranslator::TranslateTypeWithoutFinalization( 2369 AbstractType& DartTypeTranslator::TranslateTypeWithoutFinalization(
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
4044 } 2649 }
4045 type = Type::New(klass, TypeArguments::Handle(Z, klass.type_parameters()), 2650 type = Type::New(klass, TypeArguments::Handle(Z, klass.type_parameters()),
4046 klass.token_pos()); 2651 klass.token_pos());
4047 if (klass.is_type_finalized()) { 2652 if (klass.is_type_finalized()) {
4048 type ^= ClassFinalizer::FinalizeType(klass, type); 2653 type ^= ClassFinalizer::FinalizeType(klass, type);
4049 klass.SetCanonicalType(type); 2654 klass.SetCanonicalType(type);
4050 } 2655 }
4051 return type; 2656 return type;
4052 } 2657 }
4053 2658
4054 void FlowGraphBuilder::VisitTypeLiteral(TypeLiteral* node) {
4055 STREAM_EXPRESSION_IF_POSSIBLE(node);
4056
4057 const AbstractType& type = T.TranslateType(node->type());
4058 if (type.IsMalformed()) H.ReportError("Malformed type literal");
4059
4060 Fragment instructions;
4061 if (type.IsInstantiated()) {
4062 instructions += Constant(type);
4063 } else {
4064 if (!type.IsInstantiated(kCurrentClass)) {
4065 instructions += LoadInstantiatorTypeArguments();
4066 } else {
4067 instructions += NullConstant();
4068 }
4069 if (!type.IsInstantiated(kFunctions)) {
4070 instructions += LoadFunctionTypeArguments();
4071 } else {
4072 instructions += NullConstant();
4073 }
4074 instructions += InstantiateType(type);
4075 }
4076 fragment_ = instructions;
4077 }
4078
4079
4080 void FlowGraphBuilder::VisitVariableGet(VariableGet* node) {
4081 fragment_ =
4082 streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset());
4083 }
4084
4085
4086 void FlowGraphBuilder::VisitVariableSet(VariableSet* node) {
4087 STREAM_EXPRESSION_IF_POSSIBLE(node);
4088
4089 Fragment instructions = TranslateExpression(node->expression());
4090 if (NeedsDebugStepCheck(stack_, node->position())) {
4091 instructions = DebugStepCheck(node->position()) + instructions;
4092 }
4093 instructions += CheckVariableTypeInCheckedMode(node->variable());
4094 instructions +=
4095 StoreLocal(node->position(), LookupVariable(node->variable()));
4096 fragment_ = instructions;
4097 }
4098
4099
4100 void FlowGraphBuilder::VisitStaticGet(StaticGet* node) {
4101 STREAM_EXPRESSION_IF_POSSIBLE(node);
4102
4103 // A StaticGet will always have a kernel_offset, except for the StaticGet that
4104 // was manually created for _getMainClosure in dart:_builtin. Compile that
4105 // one specially here.
4106 const dart::Library& builtin =
4107 dart::Library::Handle(Z, I->object_store()->builtin_library());
4108 const Object& main =
4109 Object::Handle(Z, builtin.LookupObjectAllowPrivate(dart::String::Handle(
4110 Z, dart::String::New("main"))));
4111 if (main.IsField()) {
4112 UNIMPLEMENTED();
4113 } else if (main.IsFunction()) {
4114 const Function& function = Function::Cast(main);
4115 if (function.kind() == RawFunction::kRegularFunction) {
4116 const Function& closure_function =
4117 Function::Handle(Z, function.ImplicitClosureFunction());
4118 closure_function.set_kernel_function(function.kernel_function());
4119 const Instance& closure =
4120 Instance::ZoneHandle(Z, closure_function.ImplicitStaticClosure());
4121 fragment_ = Constant(closure);
4122 } else {
4123 UNIMPLEMENTED();
4124 }
4125 } else {
4126 UNIMPLEMENTED();
4127 }
4128 }
4129
4130
4131 void FlowGraphBuilder::VisitStaticSet(StaticSet* node) {
4132 STREAM_EXPRESSION_IF_POSSIBLE(node);
4133
4134 NameIndex target = node->target();
4135 if (H.IsField(target)) {
4136 const dart::Field& field =
4137 dart::Field::ZoneHandle(Z, H.LookupFieldByKernelField(target));
4138 const AbstractType& dst_type = AbstractType::ZoneHandle(Z, field.type());
4139 Fragment instructions = TranslateExpression(node->expression());
4140 if (NeedsDebugStepCheck(stack_, node->position())) {
4141 instructions = DebugStepCheck(node->position()) + instructions;
4142 }
4143 instructions += CheckAssignableInCheckedMode(
4144 dst_type, dart::String::ZoneHandle(Z, field.name()));
4145 LocalVariable* variable = MakeTemporary();
4146 instructions += LoadLocal(variable);
4147 fragment_ = instructions + StoreStaticField(node->position(), field);
4148 } else {
4149 ASSERT(H.IsProcedure(target));
4150
4151 // Evaluate the expression on the right hand side.
4152 Fragment instructions = TranslateExpression(node->expression());
4153 LocalVariable* variable = MakeTemporary();
4154
4155 // Prepare argument.
4156 instructions += LoadLocal(variable);
4157 instructions += PushArgument();
4158
4159 // Invoke the setter function.
4160 const Function& function =
4161 Function::ZoneHandle(Z, H.LookupStaticMethodByKernelProcedure(target));
4162 instructions += StaticCall(node->position(), function, 1);
4163
4164 // Drop the unused result & leave the stored value on the stack.
4165 fragment_ = instructions + Drop();
4166 }
4167 }
4168
4169
4170 void FlowGraphBuilder::VisitPropertyGet(PropertyGet* node) {
4171 STREAM_EXPRESSION_IF_POSSIBLE(node);
4172
4173 Fragment instructions = TranslateExpression(node->receiver());
4174 instructions += PushArgument();
4175 const dart::String& getter_name = H.DartGetterName(node->name());
4176 fragment_ = instructions +
4177 InstanceCall(node->position(), getter_name, Token::kGET, 1);
4178 }
4179
4180
4181 void FlowGraphBuilder::VisitPropertySet(PropertySet* node) {
4182 STREAM_EXPRESSION_IF_POSSIBLE(node);
4183
4184 Fragment instructions(NullConstant());
4185 LocalVariable* variable = MakeTemporary();
4186 instructions += TranslateExpression(node->receiver());
4187 instructions += PushArgument();
4188 instructions += TranslateExpression(node->value());
4189 instructions += StoreLocal(TokenPosition::kNoSource, variable);
4190 instructions += PushArgument();
4191
4192 const dart::String& setter_name = H.DartSetterName(node->name());
4193 instructions += InstanceCall(node->position(), setter_name, Token::kSET, 2);
4194 fragment_ = instructions + Drop();
4195 }
4196
4197
4198 void FlowGraphBuilder::VisitDirectPropertyGet(DirectPropertyGet* node) {
4199 STREAM_EXPRESSION_IF_POSSIBLE(node);
4200
4201 Function& target = Function::ZoneHandle(Z);
4202 NameIndex kernel_name = node->target();
4203 if (H.IsProcedure(kernel_name)) {
4204 if (H.IsGetter(kernel_name)) {
4205 target = LookupMethodByMember(kernel_name, H.DartGetterName(kernel_name));
4206 } else {
4207 target = LookupMethodByMember(kernel_name, H.DartMethodName(kernel_name));
4208 target = target.ImplicitClosureFunction();
4209 ASSERT(!target.IsNull());
4210 fragment_ = BuildImplicitClosureCreation(target);
4211 return;
4212 }
4213 } else {
4214 ASSERT(H.IsField(kernel_name));
4215 const dart::String& getter_name = H.DartGetterName(kernel_name);
4216 target = LookupMethodByMember(kernel_name, getter_name);
4217 ASSERT(target.IsGetterFunction() || target.IsImplicitGetterFunction());
4218 }
4219
4220 Fragment instructions = TranslateExpression(node->receiver());
4221 instructions += PushArgument();
4222 fragment_ = instructions + StaticCall(node->position(), target, 1);
4223 }
4224
4225
4226 void FlowGraphBuilder::VisitDirectPropertySet(DirectPropertySet* node) {
4227 STREAM_EXPRESSION_IF_POSSIBLE(node);
4228
4229 const dart::String& method_name = H.DartSetterName(node->target());
4230 const Function& target = Function::ZoneHandle(
4231 Z, LookupMethodByMember(node->target(), method_name));
4232 ASSERT(target.IsSetterFunction() || target.IsImplicitSetterFunction());
4233
4234 Fragment instructions(NullConstant());
4235 LocalVariable* value = MakeTemporary();
4236 instructions += TranslateExpression(node->receiver());
4237 instructions += PushArgument();
4238 instructions += TranslateExpression(node->value());
4239 instructions += StoreLocal(TokenPosition::kNoSource, value);
4240 instructions += PushArgument();
4241 instructions += StaticCall(node->position(), target, 2);
4242
4243 fragment_ = instructions + Drop();
4244 }
4245
4246
4247 void FlowGraphBuilder::VisitStaticInvocation(StaticInvocation* node) {
4248 STREAM_EXPRESSION_IF_POSSIBLE(node);
4249
4250 const Function& target = Function::ZoneHandle(
4251 Z, H.LookupStaticMethodByKernelProcedure(node->procedure()));
4252 const dart::Class& klass = dart::Class::ZoneHandle(Z, target.Owner());
4253 intptr_t argument_count = node->arguments()->count();
4254 if (target.IsGenerativeConstructor() || target.IsFactory()) {
4255 // The VM requires a TypeArguments object as first parameter for
4256 // every factory constructor.
4257 ++argument_count;
4258 }
4259
4260 List<NamedExpression>& named = node->arguments()->named();
4261 const Array& argument_names = H.ArgumentNames(&named);
4262
4263 // The frontend ensures we the [StaticInvocation] has matching arguments.
4264 ASSERT(target.AreValidArguments(argument_count, argument_names, NULL));
4265
4266 Fragment instructions;
4267 LocalVariable* instance_variable = NULL;
4268
4269 // If we cross the Kernel -> VM core library boundary, a [StaticInvocation]
4270 // can appear, but the thing we're calling is not a static method, but a
4271 // factory constructor.
4272 // The `H.LookupStaticmethodByKernelProcedure` will potentially resolve to the
4273 // forwarded constructor.
4274 // In that case we'll make an instance and pass it as first argument.
4275 //
4276 // TODO(27590): Get rid of this after we're using core libraries compiled
4277 // into Kernel.
4278 if (target.IsGenerativeConstructor()) {
4279 if (klass.NumTypeArguments() > 0) {
4280 List<DartType>& kernel_type_arguments = node->arguments()->types();
4281 const TypeArguments& type_arguments =
4282 T.TranslateInstantiatedTypeArguments(
4283 klass, kernel_type_arguments.raw_array(),
4284 kernel_type_arguments.length());
4285 instructions += TranslateInstantiatedTypeArguments(type_arguments);
4286 instructions += PushArgument();
4287 instructions += AllocateObject(klass, 1);
4288 } else {
4289 instructions += AllocateObject(klass, 0);
4290 }
4291
4292 instance_variable = MakeTemporary();
4293
4294 instructions += LoadLocal(instance_variable);
4295 instructions += PushArgument();
4296 } else if (target.IsFactory()) {
4297 // The VM requires currently a TypeArguments object as first parameter for
4298 // every factory constructor :-/ !
4299 //
4300 // TODO(27590): Get rid of this after we're using core libraries compiled
4301 // into Kernel.
4302 List<DartType>& kernel_type_arguments = node->arguments()->types();
4303
4304 const TypeArguments& type_arguments = T.TranslateInstantiatedTypeArguments(
4305 klass, kernel_type_arguments.raw_array(),
4306 kernel_type_arguments.length());
4307
4308 instructions += TranslateInstantiatedTypeArguments(type_arguments);
4309 instructions += PushArgument();
4310 } else {
4311 // TODO(28109) Support generic methods in the VM or reify them away.
4312 }
4313
4314 // Special case identical(x, y) call.
4315 // TODO(27590) consider moving this into the inliner and force inline it
4316 // there.
4317 if (klass.IsTopLevel() && (klass.library() == dart::Library::CoreLibrary()) &&
4318 (target.name() == Symbols::Identical().raw())) {
4319 ASSERT(argument_count == 2);
4320
4321 List<Expression>& positional = node->arguments()->positional();
4322 for (intptr_t i = 0; i < positional.length(); ++i) {
4323 instructions += TranslateExpression(positional[i]);
4324 }
4325 instructions += StrictCompare(Token::kEQ_STRICT, /*number_check=*/true);
4326 } else {
4327 instructions += TranslateArguments(node->arguments(), NULL);
4328 instructions +=
4329 StaticCall(node->position(), target, argument_count, argument_names);
4330
4331 if (target.IsGenerativeConstructor()) {
4332 // Drop the result of the constructor call and leave [instance_variable]
4333 // on top-of-stack.
4334 instructions += Drop();
4335 }
4336 }
4337
4338 fragment_ = instructions;
4339 }
4340
4341
4342 static bool IsNumberLiteral(Node* node) {
4343 return node->IsIntLiteral() || node->IsDoubleLiteral();
4344 }
4345
4346 template <class Invocation>
4347 bool FlowGraphBuilder::RecognizeComparisonWithNull(Token::Kind token_kind,
4348 Invocation* node) {
4349 if (token_kind == Token::kEQ || token_kind == Token::kNE) {
4350 if (node->arguments()->positional().length() != 1) return false;
4351 Fragment instructions;
4352 Expression* left = node->receiver();
4353 Expression* right = node->arguments()->positional()[0];
4354 if (left->IsNullLiteral() || right->IsNullLiteral()) {
4355 instructions += TranslateExpression(left);
4356 instructions += TranslateExpression(right);
4357 Token::Kind strict_cmp_kind =
4358 token_kind == Token::kEQ ? Token::kEQ_STRICT : Token::kNE_STRICT;
4359 fragment_ = instructions + StrictCompare(strict_cmp_kind,
4360 /*number_check = */ true);
4361 return true;
4362 }
4363 }
4364 return false;
4365 }
4366
4367
4368 void FlowGraphBuilder::VisitMethodInvocation(MethodInvocation* node) {
4369 STREAM_EXPRESSION_IF_POSSIBLE(node);
4370
4371 const dart::String& name = H.DartMethodName(node->name());
4372 const intptr_t argument_count = node->arguments()->count() + 1;
4373 const Token::Kind token_kind = MethodKind(name);
4374 if (IsNumberLiteral(node->receiver())) {
4375 if ((argument_count == 1) && (token_kind == Token::kNEGATE)) {
4376 const Object& result = constant_evaluator_.EvaluateExpressionSafe(node);
4377 if (!result.IsError()) {
4378 fragment_ = Constant(result);
4379 return;
4380 }
4381 } else if ((argument_count == 2) &&
4382 Token::IsBinaryArithmeticOperator(token_kind) &&
4383 IsNumberLiteral(node->arguments()->positional()[0])) {
4384 const Object& result = constant_evaluator_.EvaluateExpressionSafe(node);
4385 if (!result.IsError()) {
4386 fragment_ = Constant(result);
4387 return;
4388 }
4389 }
4390 }
4391
4392 if (RecognizeComparisonWithNull(token_kind, node)) return;
4393
4394 Fragment instructions = TranslateExpression(node->receiver());
4395 instructions += PushArgument();
4396
4397 // TODO(28109) Support generic methods in the VM or reify them away.
4398 Array& argument_names = Array::ZoneHandle(Z);
4399 instructions += TranslateArguments(node->arguments(), &argument_names);
4400
4401 intptr_t num_args_checked = 1;
4402 // If we have a special operation (e.g. +/-/==) we mark both arguments as
4403 // to be checked.
4404 if (token_kind != Token::kILLEGAL) {
4405 ASSERT(argument_count <= 2);
4406 num_args_checked = argument_count;
4407 }
4408
4409 fragment_ = instructions + InstanceCall(node->position(), name, token_kind,
4410 argument_count, argument_names,
4411 num_args_checked);
4412 // Later optimization passes assume that result of a x.[]=(...) call is not
4413 // used. We must guarantee this invariant because violation will lead to an
4414 // illegal IL once we replace x.[]=(...) with a sequence that does not
4415 // actually produce any value. See http://dartbug.com/29135 for more details.
4416 if (name.raw() == Symbols::AssignIndexToken().raw()) {
4417 fragment_ += Drop();
4418 fragment_ += NullConstant();
4419 }
4420 }
4421
4422
4423 void FlowGraphBuilder::VisitDirectMethodInvocation(
4424 DirectMethodInvocation* node) {
4425 STREAM_EXPRESSION_IF_POSSIBLE(node);
4426
4427 const dart::String& method_name = H.DartProcedureName(node->target());
4428 const Token::Kind token_kind = MethodKind(method_name);
4429
4430 if (RecognizeComparisonWithNull(token_kind, node)) return;
4431
4432 const Function& target = Function::ZoneHandle(
4433 Z, LookupMethodByMember(node->target(), method_name));
4434
4435 intptr_t argument_count = node->arguments()->count() + 1;
4436 Array& argument_names = Array::ZoneHandle(Z);
4437
4438 // TODO(28109) Support generic methods in the VM or reify them away.
4439 Fragment instructions = TranslateExpression(node->receiver());
4440 instructions += PushArgument();
4441 instructions += TranslateArguments(node->arguments(), &argument_names);
4442 fragment_ = instructions + StaticCall(node->position(), target,
4443 argument_count, argument_names);
4444 }
4445
4446
4447 void FlowGraphBuilder::VisitConstructorInvocation(ConstructorInvocation* node) {
4448 STREAM_EXPRESSION_IF_POSSIBLE(node);
4449
4450 if (node->is_const()) {
4451 fragment_ =
4452 Constant(constant_evaluator_.EvaluateConstructorInvocation(node));
4453 return;
4454 }
4455
4456 dart::Class& klass = dart::Class::ZoneHandle(
4457 Z, H.LookupClassByKernelClass(H.EnclosingName(node->target())));
4458
4459 Fragment instructions;
4460
4461 // Check for malbounded-ness of type.
4462 if (I->type_checks()) {
4463 List<DartType>& kernel_type_arguments = node->arguments()->types();
4464 const TypeArguments& type_arguments = T.TranslateTypeArguments(
4465 kernel_type_arguments.raw_array(), kernel_type_arguments.length());
4466
4467 AbstractType& type = AbstractType::Handle(
4468 Z, Type::New(klass, type_arguments, TokenPosition::kNoSource));
4469 type = ClassFinalizer::FinalizeType(klass, type);
4470
4471 if (type.IsMalbounded()) {
4472 // Evaluate expressions for correctness.
4473 List<Expression>& positional = node->arguments()->positional();
4474 List<NamedExpression>& named = node->arguments()->named();
4475 for (intptr_t i = 0; i < positional.length(); ++i) {
4476 instructions += TranslateExpression(positional[i]);
4477 instructions += Drop();
4478 }
4479 for (intptr_t i = 0; i < named.length(); ++i) {
4480 instructions += TranslateExpression(named[i]->expression());
4481 instructions += Drop();
4482 }
4483
4484 // Throw an error & keep the [Value] on the stack.
4485 instructions += ThrowTypeError();
4486
4487 // Bail out early.
4488 fragment_ = instructions;
4489 return;
4490 }
4491 }
4492
4493 if (klass.NumTypeArguments() > 0) {
4494 List<DartType>& kernel_type_arguments = node->arguments()->types();
4495 const TypeArguments& type_arguments = T.TranslateInstantiatedTypeArguments(
4496 klass, kernel_type_arguments.raw_array(),
4497 kernel_type_arguments.length());
4498 if (!klass.IsGeneric()) {
4499 Type& type = Type::ZoneHandle(Z, T.ReceiverType(klass).raw());
4500
4501 // TODO(27590): Can we move this code into [ReceiverType]?
4502 type ^= ClassFinalizer::FinalizeType(*active_class_.klass, type,
4503 ClassFinalizer::kFinalize);
4504 ASSERT(!type.IsMalformedOrMalbounded());
4505
4506 TypeArguments& canonicalized_type_arguments =
4507 TypeArguments::ZoneHandle(Z, type.arguments());
4508 canonicalized_type_arguments =
4509 canonicalized_type_arguments.Canonicalize();
4510 instructions += Constant(canonicalized_type_arguments);
4511 } else {
4512 instructions += TranslateInstantiatedTypeArguments(type_arguments);
4513 }
4514
4515 instructions += PushArgument();
4516 instructions += AllocateObject(klass, 1);
4517 } else {
4518 instructions += AllocateObject(klass, 0);
4519 }
4520 LocalVariable* variable = MakeTemporary();
4521
4522 instructions += LoadLocal(variable);
4523 instructions += PushArgument();
4524
4525 Array& argument_names = Array::ZoneHandle(Z);
4526 instructions += TranslateArguments(node->arguments(), &argument_names);
4527
4528 const Function& target = Function::ZoneHandle(
4529 Z, H.LookupConstructorByKernelConstructor(klass, node->target()));
4530 intptr_t argument_count = node->arguments()->count() + 1;
4531 instructions +=
4532 StaticCall(node->position(), target, argument_count, argument_names);
4533 fragment_ = instructions + Drop();
4534 }
4535
4536
4537 void FlowGraphBuilder::VisitIsExpression(IsExpression* node) {
4538 STREAM_EXPRESSION_IF_POSSIBLE(node);
4539
4540 Fragment instructions = TranslateExpression(node->operand());
4541
4542 // The VM does not like an instanceOf call with a dynamic type. We need to
4543 // special case this situation.
4544 const Type& object_type = Type::Handle(Z, Type::ObjectType());
4545 const AbstractType& type = T.TranslateType(node->type());
4546 if (type.IsMalformed()) {
4547 instructions += Drop();
4548 instructions += ThrowTypeError();
4549 fragment_ = instructions;
4550 return;
4551 }
4552
4553 if (type.IsInstantiated() &&
4554 object_type.IsSubtypeOf(type, NULL, NULL, Heap::kOld)) {
4555 // Evaluate the expression on the left but ignore it's result.
4556 instructions += Drop();
4557
4558 // Let condition be always true.
4559 instructions += Constant(Bool::True());
4560 } else {
4561 instructions += PushArgument();
4562
4563 // See if simple instanceOf is applicable.
4564 if (dart::FlowGraphBuilder::SimpleInstanceOfType(type)) {
4565 instructions += Constant(type);
4566 instructions += PushArgument(); // Type.
4567 instructions += InstanceCall(
4568 node->position(),
4569 dart::Library::PrivateCoreLibName(Symbols::_simpleInstanceOf()),
4570 Token::kIS, 2, 2); // 2 checked arguments.
4571 fragment_ = instructions;
4572 return;
4573 }
4574
4575 if (!type.IsInstantiated(kCurrentClass)) {
4576 instructions += LoadInstantiatorTypeArguments();
4577 } else {
4578 instructions += NullConstant();
4579 }
4580 instructions += PushArgument(); // Instantiator type arguments.
4581
4582 if (!type.IsInstantiated(kFunctions)) {
4583 instructions += LoadFunctionTypeArguments();
4584 } else {
4585 instructions += NullConstant();
4586 }
4587 instructions += PushArgument(); // Function type arguments.
4588
4589 instructions += Constant(type);
4590 instructions += PushArgument(); // Type.
4591
4592 instructions +=
4593 InstanceCall(node->position(),
4594 dart::Library::PrivateCoreLibName(Symbols::_instanceOf()),
4595 Token::kIS, 4);
4596 }
4597
4598 fragment_ = instructions;
4599 }
4600
4601
4602 void FlowGraphBuilder::VisitAsExpression(AsExpression* node) {
4603 STREAM_EXPRESSION_IF_POSSIBLE(node);
4604
4605 Fragment instructions = TranslateExpression(node->operand());
4606
4607 // The VM does not like an Object_as call with a dynamic type. We need to
4608 // special case this situation.
4609 const Type& object_type = Type::Handle(Z, Type::ObjectType());
4610 const AbstractType& type = T.TranslateType(node->type());
4611 if (type.IsMalformed()) {
4612 instructions += Drop();
4613 instructions += ThrowTypeError();
4614 fragment_ = instructions;
4615 return;
4616 }
4617
4618 if (type.IsInstantiated() &&
4619 object_type.IsSubtypeOf(type, NULL, NULL, Heap::kOld)) {
4620 // We already evaluated the operand on the left and just leave it there as
4621 // the result of the `obj as dynamic` expression.
4622 } else {
4623 instructions += PushArgument();
4624
4625 if (!type.IsInstantiated(kCurrentClass)) {
4626 instructions += LoadInstantiatorTypeArguments();
4627 } else {
4628 instructions += NullConstant();
4629 }
4630 instructions += PushArgument(); // Instantiator type arguments.
4631
4632 if (!type.IsInstantiated(kFunctions)) {
4633 instructions += LoadFunctionTypeArguments();
4634 } else {
4635 instructions += NullConstant();
4636 }
4637 instructions += PushArgument(); // Function type arguments.
4638
4639 instructions += Constant(type);
4640 instructions += PushArgument(); // Type.
4641
4642 instructions += InstanceCall(
4643 node->position(), dart::Library::PrivateCoreLibName(Symbols::_as()),
4644 Token::kAS, 4);
4645 }
4646
4647 fragment_ = instructions;
4648 }
4649
4650
4651 void FlowGraphBuilder::VisitConditionalExpression(ConditionalExpression* node) {
4652 STREAM_EXPRESSION_IF_POSSIBLE(node);
4653
4654 bool negate;
4655 Fragment instructions = TranslateCondition(node->condition(), &negate);
4656
4657 TargetEntryInstr* then_entry;
4658 TargetEntryInstr* otherwise_entry;
4659 instructions += BranchIfTrue(&then_entry, &otherwise_entry, negate);
4660
4661 Value* top = stack_;
4662 Fragment then_fragment(then_entry);
4663 then_fragment += TranslateExpression(node->then());
4664 then_fragment += StoreLocal(TokenPosition::kNoSource,
4665 parsed_function_->expression_temp_var());
4666 then_fragment += Drop();
4667 ASSERT(stack_ == top);
4668
4669 Fragment otherwise_fragment(otherwise_entry);
4670 otherwise_fragment += TranslateExpression(node->otherwise());
4671 otherwise_fragment += StoreLocal(TokenPosition::kNoSource,
4672 parsed_function_->expression_temp_var());
4673 otherwise_fragment += Drop();
4674 ASSERT(stack_ == top);
4675
4676 JoinEntryInstr* join = BuildJoinEntry();
4677 then_fragment += Goto(join);
4678 otherwise_fragment += Goto(join);
4679
4680 fragment_ = Fragment(instructions.entry, join) +
4681 LoadLocal(parsed_function_->expression_temp_var());
4682 }
4683
4684
4685 void FlowGraphBuilder::VisitLogicalExpression(LogicalExpression* node) {
4686 STREAM_EXPRESSION_IF_POSSIBLE(node);
4687
4688 bool negate;
4689 Fragment instructions = TranslateCondition(node->left(), &negate);
4690 TargetEntryInstr* right_entry;
4691 TargetEntryInstr* constant_entry;
4692
4693 if (node->op() == LogicalExpression::kAnd) {
4694 instructions += BranchIfTrue(&right_entry, &constant_entry, negate);
4695 } else {
4696 instructions += BranchIfTrue(&constant_entry, &right_entry, negate);
4697 }
4698
4699 Value* top = stack_;
4700 Fragment right_fragment(right_entry);
4701 right_fragment += TranslateCondition(node->right(), &negate);
4702 right_fragment += Constant(Bool::True());
4703 right_fragment +=
4704 StrictCompare(negate ? Token::kNE_STRICT : Token::kEQ_STRICT);
4705 right_fragment += StoreLocal(TokenPosition::kNoSource,
4706 parsed_function_->expression_temp_var());
4707 right_fragment += Drop();
4708
4709 ASSERT(top == stack_);
4710 Fragment constant_fragment(constant_entry);
4711 constant_fragment +=
4712 Constant(Bool::Get(node->op() == LogicalExpression::kOr));
4713 constant_fragment += StoreLocal(TokenPosition::kNoSource,
4714 parsed_function_->expression_temp_var());
4715 constant_fragment += Drop();
4716
4717 JoinEntryInstr* join = BuildJoinEntry();
4718 right_fragment += Goto(join);
4719 constant_fragment += Goto(join);
4720
4721 fragment_ = Fragment(instructions.entry, join) +
4722 LoadLocal(parsed_function_->expression_temp_var());
4723 }
4724
4725
4726 void FlowGraphBuilder::VisitNot(Not* node) {
4727 STREAM_EXPRESSION_IF_POSSIBLE(node);
4728
4729 Fragment instructions = TranslateExpression(node->expression());
4730 instructions += CheckBooleanInCheckedMode();
4731 instructions += BooleanNegate();
4732 fragment_ = instructions;
4733 }
4734
4735
4736 void FlowGraphBuilder::VisitThisExpression(ThisExpression* node) {
4737 fragment_ =
4738 streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset());
4739 }
4740
4741
4742 void FlowGraphBuilder::VisitStringConcatenation(StringConcatenation* node) {
4743 STREAM_EXPRESSION_IF_POSSIBLE(node);
4744
4745 List<Expression>& expressions = node->expressions();
4746
4747 Fragment instructions;
4748
4749 if (node->expressions().length() == 1) {
4750 instructions += TranslateExpression(node->expressions()[0]);
4751 instructions += StringInterpolateSingle(node->position());
4752 } else {
4753 // The type arguments for CreateArray.
4754 instructions += Constant(TypeArguments::ZoneHandle(Z));
4755 instructions += IntConstant(expressions.length());
4756 instructions += CreateArray();
4757 LocalVariable* array = MakeTemporary();
4758
4759 for (intptr_t i = 0; i < node->expressions().length(); i++) {
4760 instructions += LoadLocal(array);
4761 instructions += IntConstant(i);
4762 instructions += TranslateExpression(node->expressions()[i]);
4763 instructions += StoreIndexed(kArrayCid);
4764 instructions += Drop();
4765 }
4766
4767 instructions += StringInterpolate(node->position());
4768 }
4769 fragment_ = instructions;
4770 }
4771
4772
4773 void FlowGraphBuilder::VisitListLiteral(ListLiteral* node) {
4774 STREAM_EXPRESSION_IF_POSSIBLE(node);
4775
4776 if (node->is_const()) {
4777 fragment_ = Constant(constant_evaluator_.EvaluateListLiteral(node));
4778 return;
4779 }
4780
4781 DartType* types[] = {node->type()};
4782 const TypeArguments& type_arguments = T.TranslateTypeArguments(types, 1);
4783
4784 // The type argument for the factory call.
4785 Fragment instructions = TranslateInstantiatedTypeArguments(type_arguments);
4786 instructions += PushArgument();
4787 List<Expression>& expressions = node->expressions();
4788 if (expressions.length() == 0) {
4789 instructions += Constant(Object::empty_array());
4790 } else {
4791 // The type arguments for CreateArray.
4792 instructions += Constant(TypeArguments::ZoneHandle(Z));
4793 instructions += IntConstant(expressions.length());
4794 instructions += CreateArray();
4795
4796 LocalVariable* array = MakeTemporary();
4797 for (intptr_t i = 0; i < expressions.length(); ++i) {
4798 instructions += LoadLocal(array);
4799 instructions += IntConstant(i);
4800 instructions += TranslateExpression(expressions[i]);
4801 instructions += StoreIndexed(kArrayCid);
4802 instructions += Drop();
4803 }
4804 }
4805 instructions += PushArgument(); // The array.
4806
4807 const dart::Class& factory_class =
4808 dart::Class::Handle(Z, dart::Library::LookupCoreClass(Symbols::List()));
4809 const Function& factory_method = Function::ZoneHandle(
4810 Z, factory_class.LookupFactory(
4811 dart::Library::PrivateCoreLibName(Symbols::ListLiteralFactory())));
4812 fragment_ = instructions + StaticCall(node->position(), factory_method, 2);
4813 }
4814
4815
4816 void FlowGraphBuilder::VisitMapLiteral(MapLiteral* node) {
4817 STREAM_EXPRESSION_IF_POSSIBLE(node);
4818
4819 if (node->is_const()) {
4820 fragment_ = Constant(constant_evaluator_.EvaluateMapLiteral(node));
4821 return;
4822 }
4823
4824 const dart::Class& map_class =
4825 dart::Class::Handle(Z, dart::Library::LookupCoreClass(Symbols::Map()));
4826 const Function& factory_method = Function::ZoneHandle(
4827 Z, map_class.LookupFactory(
4828 dart::Library::PrivateCoreLibName(Symbols::MapLiteralFactory())));
4829
4830 DartType* types[] = {node->key_type(), node->value_type()};
4831 const TypeArguments& type_arguments = T.TranslateTypeArguments(types, 2);
4832
4833 // The type argument for the factory call `new Map<K, V>._fromLiteral(List)`.
4834 Fragment instructions = TranslateInstantiatedTypeArguments(type_arguments);
4835 instructions += PushArgument();
4836
4837 List<MapEntry>& entries = node->entries();
4838 if (entries.length() == 0) {
4839 instructions += Constant(Object::empty_array());
4840 } else {
4841 // The type arguments for `new List<X>(int len)`.
4842 instructions += Constant(TypeArguments::ZoneHandle(Z));
4843
4844 // We generate a list of tuples, i.e. [key1, value1, ..., keyN, valueN].
4845 instructions += IntConstant(2 * entries.length());
4846 instructions += CreateArray();
4847
4848 LocalVariable* array = MakeTemporary();
4849 for (intptr_t i = 0; i < entries.length(); ++i) {
4850 instructions += LoadLocal(array);
4851 instructions += IntConstant(2 * i);
4852 instructions += TranslateExpression(entries[i]->key());
4853 instructions += StoreIndexed(kArrayCid);
4854 instructions += Drop();
4855
4856 instructions += LoadLocal(array);
4857 instructions += IntConstant(2 * i + 1);
4858 instructions += TranslateExpression(entries[i]->value());
4859 instructions += StoreIndexed(kArrayCid);
4860 instructions += Drop();
4861 }
4862 }
4863 instructions += PushArgument(); // The array.
4864
4865 fragment_ = instructions + StaticCall(node->position(), factory_method, 2);
4866 }
4867
4868
4869 void FlowGraphBuilder::VisitFunctionExpression(FunctionExpression* node) {
4870 fragment_ = TranslateFunctionNode(node->function(), node);
4871 }
4872
4873
4874 void FlowGraphBuilder::VisitLet(Let* node) {
4875 STREAM_EXPRESSION_IF_POSSIBLE(node);
4876
4877 Fragment instructions = TranslateStatement(node->variable());
4878 instructions += TranslateExpression(node->body());
4879 fragment_ = instructions;
4880 }
4881
4882
4883 void FlowGraphBuilder::VisitThrow(Throw* node) {
4884 STREAM_EXPRESSION_IF_POSSIBLE(node);
4885
4886 Fragment instructions;
4887
4888 instructions += TranslateExpression(node->expression());
4889 if (NeedsDebugStepCheck(stack_, node->position())) {
4890 instructions = DebugStepCheck(node->position()) + instructions;
4891 }
4892 instructions += PushArgument();
4893 instructions += ThrowException(node->position());
4894 ASSERT(instructions.is_closed());
4895
4896 fragment_ = instructions;
4897 }
4898
4899
4900 void FlowGraphBuilder::VisitRethrow(Rethrow* node) {
4901 fragment_ =
4902 streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset());
4903 }
4904
4905
4906 Fragment FlowGraphBuilder::TranslateArguments(Arguments* node,
4907 Array* argument_names) {
4908 Fragment instructions;
4909
4910 List<Expression>& positional = node->positional();
4911 for (intptr_t i = 0; i < positional.length(); ++i) {
4912 instructions += TranslateExpression(positional[i]);
4913 instructions += PushArgument();
4914 }
4915
4916 List<NamedExpression>& named = node->named();
4917 if (argument_names != NULL) {
4918 *argument_names = H.ArgumentNames(&named).raw();
4919 }
4920 for (intptr_t i = 0; i < named.length(); ++i) {
4921 NamedExpression* named_expression = named[i];
4922 instructions += TranslateExpression(named_expression->expression());
4923 instructions += PushArgument();
4924 }
4925 return instructions;
4926 }
4927
4928 #define STREAM_STATEMENT_IF_POSSIBLE(node) \
4929 if (node->can_stream()) { \
4930 fragment_ = streaming_flow_graph_builder_->BuildStatementAt( \
4931 node->kernel_offset()); \
4932 return; \
4933 }
4934
4935
4936 void FlowGraphBuilder::VisitInvalidStatement(InvalidStatement* node) {
4937 fragment_ =
4938 streaming_flow_graph_builder_->BuildStatementAt(node->kernel_offset());
4939 }
4940
4941
4942 void FlowGraphBuilder::VisitEmptyStatement(EmptyStatement* node) {
4943 fragment_ =
4944 streaming_flow_graph_builder_->BuildStatementAt(node->kernel_offset());
4945 }
4946
4947
4948 void FlowGraphBuilder::VisitBlock(Block* node) {
4949 STREAM_STATEMENT_IF_POSSIBLE(node);
4950
4951 Fragment instructions;
4952
4953 instructions += EnterScope(node);
4954 List<Statement>& statements = node->statements();
4955 for (intptr_t i = 0; (i < statements.length()) && instructions.is_open();
4956 ++i) {
4957 instructions += TranslateStatement(statements[i]);
4958 }
4959 instructions += ExitScope(node);
4960
4961 fragment_ = instructions;
4962 }
4963
4964
4965 void FlowGraphBuilder::VisitReturnStatement(ReturnStatement* node) {
4966 STREAM_STATEMENT_IF_POSSIBLE(node);
4967
4968 bool inside_try_finally = try_finally_block_ != NULL;
4969
4970 Fragment instructions = node->expression() == NULL
4971 ? NullConstant()
4972 : TranslateExpression(node->expression());
4973 if (instructions.is_open()) {
4974 if (inside_try_finally) {
4975 ASSERT(scopes_->finally_return_variable != NULL);
4976 const Function& function = parsed_function_->function();
4977 if (NeedsDebugStepCheck(function, node->position())) {
4978 instructions += DebugStepCheck(node->position());
4979 }
4980 instructions +=
4981 StoreLocal(node->position(), scopes_->finally_return_variable);
4982 instructions += Drop();
4983 instructions += TranslateFinallyFinalizers(NULL, -1);
4984 if (instructions.is_open()) {
4985 instructions += LoadLocal(scopes_->finally_return_variable);
4986 instructions += Return(TokenPosition::kNoSource);
4987 }
4988 } else {
4989 instructions += Return(node->position());
4990 }
4991 } else {
4992 Pop();
4993 }
4994 fragment_ = instructions;
4995 }
4996
4997
4998 void FlowGraphBuilder::VisitExpressionStatement(ExpressionStatement* node) {
4999 STREAM_STATEMENT_IF_POSSIBLE(node);
5000
5001 Fragment instructions = TranslateExpression(node->expression());
5002 instructions += Drop();
5003 fragment_ = instructions;
5004 }
5005
5006
5007 void FlowGraphBuilder::VisitVariableDeclaration(VariableDeclaration* node) {
5008 LocalVariable* variable = LookupVariable(node);
5009 Expression* initializer = node->initializer();
5010
5011 Fragment instructions;
5012 if (initializer == NULL) {
5013 instructions += NullConstant();
5014 } else {
5015 if (node->IsConst()) {
5016 const Instance& constant_value =
5017 constant_evaluator_.EvaluateExpression(initializer);
5018 variable->SetConstValue(constant_value);
5019 instructions += Constant(constant_value);
5020 } else {
5021 instructions += TranslateExpression(initializer);
5022 instructions += CheckVariableTypeInCheckedMode(node);
5023 }
5024 }
5025 // Use position of equal sign if it exists. If the equal sign does not exist
5026 // use the position of the identifier.
5027 TokenPosition debug_position =
5028 Utils::Maximum(node->position(), node->equals_position());
5029 if (NeedsDebugStepCheck(stack_, debug_position)) {
5030 instructions = DebugStepCheck(debug_position) + instructions;
5031 }
5032 instructions += StoreLocal(node->position(), variable);
5033 instructions += Drop();
5034 fragment_ = instructions;
5035 }
5036
5037
5038 void FlowGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* node) {
5039 Fragment instructions = DebugStepCheck(node->position());
5040 instructions += TranslateFunctionNode(node->function(), node);
5041 instructions +=
5042 StoreLocal(node->position(), LookupVariable(node->variable()));
5043 instructions += Drop();
5044 fragment_ = instructions;
5045 }
5046
5047
5048 void FlowGraphBuilder::VisitIfStatement(IfStatement* node) {
5049 STREAM_STATEMENT_IF_POSSIBLE(node);
5050
5051 bool negate;
5052 Fragment instructions = TranslateCondition(node->condition(), &negate);
5053 TargetEntryInstr* then_entry;
5054 TargetEntryInstr* otherwise_entry;
5055 instructions += BranchIfTrue(&then_entry, &otherwise_entry, negate);
5056
5057 Fragment then_fragment(then_entry);
5058 then_fragment += TranslateStatement(node->then());
5059
5060 Fragment otherwise_fragment(otherwise_entry);
5061 otherwise_fragment += TranslateStatement(node->otherwise());
5062
5063 if (then_fragment.is_open()) {
5064 if (otherwise_fragment.is_open()) {
5065 JoinEntryInstr* join = BuildJoinEntry();
5066 then_fragment += Goto(join);
5067 otherwise_fragment += Goto(join);
5068 fragment_ = Fragment(instructions.entry, join);
5069 } else {
5070 fragment_ = Fragment(instructions.entry, then_fragment.current);
5071 }
5072 } else if (otherwise_fragment.is_open()) {
5073 fragment_ = Fragment(instructions.entry, otherwise_fragment.current);
5074 } else {
5075 fragment_ = instructions.closed();
5076 }
5077 }
5078
5079
5080 void FlowGraphBuilder::VisitWhileStatement(WhileStatement* node) {
5081 STREAM_STATEMENT_IF_POSSIBLE(node);
5082
5083 ++loop_depth_;
5084 bool negate;
5085 Fragment condition = TranslateCondition(node->condition(), &negate);
5086 TargetEntryInstr* body_entry;
5087 TargetEntryInstr* loop_exit;
5088 condition += BranchIfTrue(&body_entry, &loop_exit, negate);
5089
5090 Fragment body(body_entry);
5091 body += TranslateStatement(node->body());
5092
5093 Instruction* entry;
5094 if (body.is_open()) {
5095 JoinEntryInstr* join = BuildJoinEntry();
5096 body += Goto(join);
5097
5098 Fragment loop(join);
5099 loop += CheckStackOverflow();
5100 loop += condition;
5101 entry = new (Z) GotoInstr(join);
5102 } else {
5103 entry = condition.entry;
5104 }
5105
5106
5107 fragment_ = Fragment(entry, loop_exit);
5108 --loop_depth_;
5109 }
5110
5111
5112 void FlowGraphBuilder::VisitDoStatement(DoStatement* node) {
5113 STREAM_STATEMENT_IF_POSSIBLE(node);
5114
5115 ++loop_depth_;
5116 Fragment body = TranslateStatement(node->body());
5117
5118 if (body.is_closed()) {
5119 fragment_ = body;
5120 --loop_depth_;
5121 return;
5122 }
5123
5124 bool negate;
5125 JoinEntryInstr* join = BuildJoinEntry();
5126 Fragment loop(join);
5127 loop += CheckStackOverflow();
5128 loop += body;
5129 loop += TranslateCondition(node->condition(), &negate);
5130 TargetEntryInstr* loop_repeat;
5131 TargetEntryInstr* loop_exit;
5132 loop += BranchIfTrue(&loop_repeat, &loop_exit, negate);
5133
5134 Fragment repeat(loop_repeat);
5135 repeat += Goto(join);
5136
5137 fragment_ = Fragment(new (Z) GotoInstr(join), loop_exit);
5138 --loop_depth_;
5139 }
5140
5141
5142 void FlowGraphBuilder::VisitForStatement(ForStatement* node) {
5143 STREAM_STATEMENT_IF_POSSIBLE(node);
5144
5145 Fragment declarations;
5146
5147 bool new_context = false;
5148 declarations += EnterScope(node, &new_context);
5149
5150 List<VariableDeclaration>& variables = node->variables();
5151 for (intptr_t i = 0; i < variables.length(); ++i) {
5152 declarations += TranslateStatement(variables[i]);
5153 }
5154
5155 ++loop_depth_;
5156 bool negate = false;
5157 Fragment condition = node->condition() == NULL
5158 ? Constant(Bool::True())
5159 : TranslateCondition(node->condition(), &negate);
5160 TargetEntryInstr* body_entry;
5161 TargetEntryInstr* loop_exit;
5162 condition += BranchIfTrue(&body_entry, &loop_exit, negate);
5163
5164 Fragment body(body_entry);
5165 body += TranslateStatement(node->body());
5166
5167 if (body.is_open()) {
5168 // We allocated a fresh context before the loop which contains captured
5169 // [ForStatement] variables. Before jumping back to the loop entry we clone
5170 // the context object (at same depth) which ensures the next iteration of
5171 // the body gets a fresh set of [ForStatement] variables (with the old
5172 // (possibly updated) values).
5173 if (new_context) body += CloneContext();
5174
5175 List<Expression>& updates = node->updates();
5176 for (intptr_t i = 0; i < updates.length(); ++i) {
5177 body += TranslateExpression(updates[i]);
5178 body += Drop();
5179 }
5180 JoinEntryInstr* join = BuildJoinEntry();
5181 declarations += Goto(join);
5182 body += Goto(join);
5183
5184 Fragment loop(join);
5185 loop += CheckStackOverflow();
5186 loop += condition;
5187 } else {
5188 declarations += condition;
5189 }
5190
5191 Fragment loop(declarations.entry, loop_exit);
5192 --loop_depth_;
5193
5194 loop += ExitScope(node);
5195
5196 fragment_ = loop;
5197 }
5198
5199
5200 void FlowGraphBuilder::VisitForInStatement(ForInStatement* node) {
5201 STREAM_STATEMENT_IF_POSSIBLE(node);
5202
5203 Fragment instructions = TranslateExpression(node->iterable());
5204 instructions += PushArgument();
5205
5206 const dart::String& iterator_getter = dart::String::ZoneHandle(
5207 Z, dart::Field::GetterSymbol(Symbols::Iterator()));
5208 instructions += InstanceCall(node->iterable()->position(), iterator_getter,
5209 Token::kGET, 1);
5210 LocalVariable* iterator = scopes_->iterator_variables[for_in_depth_];
5211 instructions += StoreLocal(TokenPosition::kNoSource, iterator);
5212 instructions += Drop();
5213
5214 ++for_in_depth_;
5215 ++loop_depth_;
5216 Fragment condition = LoadLocal(iterator);
5217 condition += PushArgument();
5218 condition += InstanceCall(node->iterable()->position(), Symbols::MoveNext(),
5219 Token::kILLEGAL, 1);
5220 TargetEntryInstr* body_entry;
5221 TargetEntryInstr* loop_exit;
5222 condition += BranchIfTrue(&body_entry, &loop_exit);
5223
5224 Fragment body(body_entry);
5225 body += EnterScope(node);
5226 body += LoadLocal(iterator);
5227 body += PushArgument();
5228 const dart::String& current_getter = dart::String::ZoneHandle(
5229 Z, dart::Field::GetterSymbol(Symbols::Current()));
5230 body += InstanceCall(node->position(), current_getter, Token::kGET, 1);
5231 body +=
5232 StoreLocal(TokenPosition::kNoSource, LookupVariable(node->variable()));
5233 body += Drop();
5234 body += TranslateStatement(node->body());
5235 body += ExitScope(node);
5236
5237 if (body.is_open()) {
5238 JoinEntryInstr* join = BuildJoinEntry();
5239 instructions += Goto(join);
5240 body += Goto(join);
5241
5242 Fragment loop(join);
5243 loop += CheckStackOverflow();
5244 loop += condition;
5245 } else {
5246 instructions += condition;
5247 }
5248
5249 fragment_ = Fragment(instructions.entry, loop_exit);
5250 --loop_depth_;
5251 --for_in_depth_;
5252 }
5253
5254
5255 void FlowGraphBuilder::VisitLabeledStatement(LabeledStatement* node) {
5256 STREAM_STATEMENT_IF_POSSIBLE(node);
5257
5258 // There can be serveral cases:
5259 //
5260 // * the body contains a break
5261 // * the body doesn't contain a break
5262 //
5263 // * translating the body results in a closed fragment
5264 // * translating the body results in a open fragment
5265 //
5266 // => We will only know which case we are in after the body has been
5267 // traversed.
5268
5269 BreakableBlock block(this);
5270 Fragment instructions = TranslateStatement(node->body());
5271 if (block.HadJumper()) {
5272 if (instructions.is_open()) {
5273 instructions += Goto(block.destination());
5274 }
5275 fragment_ = Fragment(instructions.entry, block.destination());
5276 } else {
5277 fragment_ = instructions;
5278 }
5279 }
5280
5281
5282 void FlowGraphBuilder::VisitBreakStatement(BreakStatement* node) {
5283 fragment_ =
5284 streaming_flow_graph_builder_->BuildStatementAt(node->kernel_offset());
5285 }
5286
5287
5288 void FlowGraphBuilder::VisitSwitchStatement(SwitchStatement* node) {
5289 STREAM_STATEMENT_IF_POSSIBLE(node);
5290
5291 SwitchBlock block(this, node->cases().length());
5292
5293 // Instead of using a variable we should reuse the expression on the stack,
5294 // since it won't be assigned again, we don't need phi nodes.
5295 Fragment head_instructions = TranslateExpression(node->condition());
5296 head_instructions +=
5297 StoreLocal(TokenPosition::kNoSource, scopes_->switch_variable);
5298 head_instructions += Drop();
5299
5300 // Phase 1: Generate bodies and try to find out whether a body will be target
5301 // of a jump due to:
5302 // * `continue case_label`
5303 // * `case e1: case e2: body`
5304 Fragment* body_fragments = new Fragment[node->cases().length()];
5305
5306 intptr_t num_cases = node->cases().length();
5307 for (intptr_t i = 0; i < num_cases; i++) {
5308 SwitchCase* switch_case = node->cases()[i];
5309 Fragment& body_fragment = body_fragments[i] =
5310 TranslateStatement(switch_case->body());
5311
5312 if (body_fragment.entry == NULL) {
5313 // Make a NOP in order to ensure linking works properly.
5314 body_fragment = NullConstant();
5315 body_fragment += Drop();
5316 }
5317
5318 // The Dart language specification mandates fall-throughs in [SwitchCase]es
5319 // to be runtime errors.
5320 if (!switch_case->is_default() && body_fragment.is_open() &&
5321 (i < (node->cases().length() - 1))) {
5322 const dart::Class& klass = dart::Class::ZoneHandle(
5323 Z, dart::Library::LookupCoreClass(Symbols::FallThroughError()));
5324 ASSERT(!klass.IsNull());
5325 const Function& constructor = Function::ZoneHandle(
5326 Z, klass.LookupConstructorAllowPrivate(
5327 H.DartSymbol("FallThroughError._create")));
5328 ASSERT(!constructor.IsNull());
5329 const dart::String& url = H.DartString(
5330 parsed_function_->function().ToLibNamePrefixedQualifiedCString(),
5331 Heap::kOld);
5332
5333 // Create instance of _FallThroughError
5334 body_fragment += AllocateObject(klass, 0);
5335 LocalVariable* instance = MakeTemporary();
5336
5337 // Call _FallThroughError._create constructor.
5338 body_fragment += LoadLocal(instance);
5339 body_fragment += PushArgument(); // this
5340
5341 body_fragment += Constant(url);
5342 body_fragment += PushArgument(); // url
5343
5344 body_fragment += NullConstant();
5345 body_fragment += PushArgument(); // line
5346
5347 body_fragment += StaticCall(TokenPosition::kNoSource, constructor, 3);
5348 body_fragment += Drop();
5349
5350 // Throw the exception
5351 body_fragment += PushArgument();
5352 body_fragment += ThrowException(TokenPosition::kNoSource);
5353 body_fragment += Drop();
5354 }
5355
5356 // If there is an implicit fall-through we have one [SwitchCase] and
5357 // multiple expressions, e.g.
5358 //
5359 // switch(expr) {
5360 // case a:
5361 // case b:
5362 // <stmt-body>
5363 // }
5364 //
5365 // This means that the <stmt-body> will have more than 1 incoming edge (one
5366 // from `a == expr` and one from `a != expr && b == expr`). The
5367 // `block.Destination()` records the additional jump.
5368 if (switch_case->expressions().length() > 1) {
5369 block.DestinationDirect(i);
5370 }
5371 }
5372
5373 // Phase 2: Generate everything except the real bodies:
5374 // * jump directly to a body (if there is no jumper)
5375 // * jump to a wrapper block which jumps to the body (if there is a jumper)
5376 Fragment current_instructions = head_instructions;
5377 for (intptr_t i = 0; i < num_cases; i++) {
5378 SwitchCase* switch_case = node->cases()[i];
5379
5380 if (switch_case->is_default()) {
5381 ASSERT(i == (node->cases().length() - 1));
5382
5383 // Evaluate the conditions for the default [SwitchCase] just for the
5384 // purpose of potentially triggering a compile-time error.
5385 for (intptr_t k = 0; k < switch_case->expressions().length(); k++) {
5386 constant_evaluator_.EvaluateExpression(switch_case->expressions()[k]);
5387 }
5388
5389 if (block.HadJumper(i)) {
5390 // There are several branches to the body, so we will make a goto to
5391 // the join block (and prepend a join instruction to the real body).
5392 JoinEntryInstr* join = block.DestinationDirect(i);
5393 current_instructions += Goto(join);
5394
5395 current_instructions = Fragment(current_instructions.entry, join);
5396 current_instructions += body_fragments[i];
5397 } else {
5398 current_instructions += body_fragments[i];
5399 }
5400 } else {
5401 JoinEntryInstr* body_join = NULL;
5402 if (block.HadJumper(i)) {
5403 body_join = block.DestinationDirect(i);
5404 body_fragments[i] = Fragment(body_join) + body_fragments[i];
5405 }
5406
5407 for (intptr_t j = 0; j < switch_case->expressions().length(); j++) {
5408 TargetEntryInstr* then;
5409 TargetEntryInstr* otherwise;
5410
5411 Expression* expression = switch_case->expressions()[j];
5412 current_instructions +=
5413 Constant(constant_evaluator_.EvaluateExpression(expression));
5414 current_instructions += PushArgument();
5415 current_instructions += LoadLocal(scopes_->switch_variable);
5416 current_instructions += PushArgument();
5417 current_instructions += InstanceCall(
5418 expression->position(), Symbols::EqualOperator(), Token::kEQ,
5419 /*argument_count=*/2,
5420 /*num_args_checked=*/2);
5421 current_instructions += BranchIfTrue(&then, &otherwise);
5422
5423 Fragment then_fragment(then);
5424
5425 if (body_join != NULL) {
5426 // There are several branches to the body, so we will make a goto to
5427 // the join block (the real body has already been prepended with a
5428 // join instruction).
5429 then_fragment += Goto(body_join);
5430 } else {
5431 // There is only a signle branch to the body, so we will just append
5432 // the body fragment.
5433 then_fragment += body_fragments[i];
5434 }
5435
5436 current_instructions = Fragment(otherwise);
5437 }
5438 }
5439 }
5440
5441 bool has_no_default =
5442 num_cases > 0 && !node->cases()[num_cases - 1]->is_default();
5443 if (has_no_default) {
5444 // There is no default, which means we have an open [current_instructions]
5445 // (which is a [TargetEntryInstruction] for the last "otherwise" branch).
5446 //
5447 // Furthermore the last [SwitchCase] can be open as well. If so, we need
5448 // to join these two.
5449 Fragment& last_body = body_fragments[node->cases().length() - 1];
5450 if (last_body.is_open()) {
5451 ASSERT(current_instructions.is_open());
5452 ASSERT(current_instructions.current->IsTargetEntry());
5453
5454 // Join the last "otherwise" branch and the last [SwitchCase] fragment.
5455 JoinEntryInstr* join = BuildJoinEntry();
5456 current_instructions += Goto(join);
5457 last_body += Goto(join);
5458
5459 current_instructions = Fragment(join);
5460 }
5461 } else {
5462 // All non-default cases will be closed (i.e. break/continue/throw/return)
5463 // So it is fine to just let more statements after the switch append to the
5464 // default case.
5465 }
5466
5467 delete[] body_fragments;
5468
5469 fragment_ = Fragment(head_instructions.entry, current_instructions.current);
5470 }
5471
5472
5473 void FlowGraphBuilder::VisitContinueSwitchStatement(
5474 ContinueSwitchStatement* node) {
5475 fragment_ =
5476 streaming_flow_graph_builder_->BuildStatementAt(node->kernel_offset());
5477 }
5478
5479
5480 void FlowGraphBuilder::VisitAssertStatement(AssertStatement* node) {
5481 STREAM_STATEMENT_IF_POSSIBLE(node);
5482
5483 if (!I->asserts()) {
5484 fragment_ = Fragment();
5485 return;
5486 }
5487
5488 TargetEntryInstr* then;
5489 TargetEntryInstr* otherwise;
5490
5491 Fragment instructions;
5492 // Asserts can be of the following two kinds:
5493 //
5494 // * `assert(expr)`
5495 // * `assert(() { ... })`
5496 //
5497 // The call to `_AssertionError._evaluateAssertion()` will take care of both
5498 // and returns a boolean.
5499 instructions += TranslateExpression(node->condition());
5500 instructions += PushArgument();
5501 instructions += EvaluateAssertion();
5502 instructions += CheckBooleanInCheckedMode();
5503 instructions += Constant(Bool::True());
5504 instructions += BranchIfEqual(&then, &otherwise, false);
5505
5506 const dart::Class& klass = dart::Class::ZoneHandle(
5507 Z, dart::Library::LookupCoreClass(Symbols::AssertionError()));
5508 ASSERT(!klass.IsNull());
5509 const Function& constructor =
5510 Function::ZoneHandle(Z, klass.LookupConstructorAllowPrivate(
5511 H.DartSymbol("_AssertionError._create")));
5512 ASSERT(!constructor.IsNull());
5513
5514 const dart::String& url = H.DartString(
5515 parsed_function_->function().ToLibNamePrefixedQualifiedCString(),
5516 Heap::kOld);
5517
5518 // Create instance of _AssertionError
5519 Fragment otherwise_fragment(otherwise);
5520 otherwise_fragment += AllocateObject(klass, 0);
5521 LocalVariable* instance = MakeTemporary();
5522
5523 // Call _AssertionError._create constructor.
5524 otherwise_fragment += LoadLocal(instance);
5525 otherwise_fragment += PushArgument(); // this
5526
5527 otherwise_fragment += Constant(H.DartString("<no message>", Heap::kOld));
5528 otherwise_fragment += PushArgument(); // failedAssertion
5529
5530 otherwise_fragment += Constant(url);
5531 otherwise_fragment += PushArgument(); // url
5532
5533 otherwise_fragment += IntConstant(0);
5534 otherwise_fragment += PushArgument(); // line
5535
5536 otherwise_fragment += IntConstant(0);
5537 otherwise_fragment += PushArgument(); // column
5538
5539 otherwise_fragment +=
5540 node->message() != NULL
5541 ? TranslateExpression(node->message())
5542 : Constant(H.DartString("<no message>", Heap::kOld));
5543 otherwise_fragment += PushArgument(); // message
5544
5545 otherwise_fragment += StaticCall(TokenPosition::kNoSource, constructor, 6);
5546 otherwise_fragment += Drop();
5547
5548 // Throw _AssertionError exception.
5549 otherwise_fragment += PushArgument();
5550 otherwise_fragment += ThrowException(TokenPosition::kNoSource);
5551 otherwise_fragment += Drop();
5552
5553 fragment_ = Fragment(instructions.entry, then);
5554 }
5555
5556
5557 void FlowGraphBuilder::VisitTryFinally(TryFinally* node) {
5558 STREAM_STATEMENT_IF_POSSIBLE(node);
5559
5560 InlineBailout("kernel::FlowgraphBuilder::VisitTryFinally");
5561
5562 // There are 5 different cases where we need to execute the finally block:
5563 //
5564 // a) 1/2/3th case: Special control flow going out of `node->body()`:
5565 //
5566 // * [BreakStatement] transfers control to a [LabledStatement]
5567 // * [ContinueSwitchStatement] transfers control to a [SwitchCase]
5568 // * [ReturnStatement] returns a value
5569 //
5570 // => All three cases will automatically append all finally blocks
5571 // between the branching point and the destination (so we don't need to
5572 // do anything here).
5573 //
5574 // b) 4th case: Translating the body resulted in an open fragment (i.e. body
5575 // executes without any control flow out of it)
5576 //
5577 // => We are responsible for jumping out of the body to a new block (with
5578 // different try index) and execute the finalizer.
5579 //
5580 // c) 5th case: An exception occured inside the body.
5581 //
5582 // => We are responsible for catching it, executing the finally block and
5583 // rethrowing the exception.
5584 intptr_t try_handler_index = AllocateTryIndex();
5585 Fragment try_body = TryCatch(try_handler_index);
5586 JoinEntryInstr* after_try = BuildJoinEntry();
5587
5588 // Fill in the body of the try.
5589 ++try_depth_;
5590 {
5591 TryFinallyBlock tfb(this, node->finalizer(), -1);
5592 TryCatchBlock tcb(this, try_handler_index);
5593 try_body += TranslateStatement(node->body());
5594 }
5595 --try_depth_;
5596
5597 if (try_body.is_open()) {
5598 // Please note: The try index will be on level out of this block,
5599 // thereby ensuring if there's an exception in the finally block we
5600 // won't run it twice.
5601 JoinEntryInstr* finally_entry = BuildJoinEntry();
5602
5603 try_body += Goto(finally_entry);
5604
5605 Fragment finally_body(finally_entry);
5606 finally_body += TranslateStatement(node->finalizer());
5607 finally_body += Goto(after_try);
5608 }
5609
5610 // Fill in the body of the catch.
5611 ++catch_depth_;
5612 const Array& handler_types = Array::ZoneHandle(Z, Array::New(1, Heap::kOld));
5613 handler_types.SetAt(0, Object::dynamic_type());
5614 // Note: rethrow will actually force mark the handler as needing a stacktrace.
5615 Fragment finally_body = CatchBlockEntry(handler_types, try_handler_index,
5616 /* needs_stacktrace = */ false);
5617 finally_body += TranslateStatement(node->finalizer());
5618 if (finally_body.is_open()) {
5619 finally_body += LoadLocal(CurrentException());
5620 finally_body += PushArgument();
5621 finally_body += LoadLocal(CurrentStackTrace());
5622 finally_body += PushArgument();
5623 finally_body +=
5624 RethrowException(TokenPosition::kNoSource, try_handler_index);
5625 Drop();
5626 }
5627 --catch_depth_;
5628
5629 fragment_ = Fragment(try_body.entry, after_try);
5630 }
5631
5632
5633 void FlowGraphBuilder::VisitTryCatch(class TryCatch* node) {
5634 STREAM_STATEMENT_IF_POSSIBLE(node);
5635
5636 InlineBailout("kernel::FlowgraphBuilder::VisitTryCatch");
5637
5638 intptr_t try_handler_index = AllocateTryIndex();
5639 Fragment try_body = TryCatch(try_handler_index);
5640 JoinEntryInstr* after_try = BuildJoinEntry();
5641
5642 // Fill in the body of the try.
5643 ++try_depth_;
5644 {
5645 TryCatchBlock block(this, try_handler_index);
5646 try_body += TranslateStatement(node->body());
5647 try_body += Goto(after_try);
5648 }
5649 --try_depth_;
5650
5651 ++catch_depth_;
5652 const Array& handler_types =
5653 Array::ZoneHandle(Z, Array::New(node->catches().length(), Heap::kOld));
5654 bool needs_stacktrace = false;
5655 for (intptr_t i = 0; i < node->catches().length(); i++) {
5656 if (node->catches()[i]->stack_trace() != NULL) {
5657 needs_stacktrace = true;
5658 break;
5659 }
5660 }
5661 Fragment catch_body =
5662 CatchBlockEntry(handler_types, try_handler_index, needs_stacktrace);
5663 // Fill in the body of the catch.
5664 for (intptr_t i = 0; i < node->catches().length(); i++) {
5665 Catch* catch_clause = node->catches()[i];
5666
5667 Fragment catch_handler_body;
5668
5669 catch_handler_body += EnterScope(catch_clause);
5670
5671 if (catch_clause->exception() != NULL) {
5672 catch_handler_body += LoadLocal(CurrentException());
5673 catch_handler_body += StoreLocal(
5674 TokenPosition::kNoSource, LookupVariable(catch_clause->exception()));
5675 catch_handler_body += Drop();
5676 }
5677 if (catch_clause->stack_trace() != NULL) {
5678 catch_handler_body += LoadLocal(CurrentStackTrace());
5679 catch_handler_body +=
5680 StoreLocal(TokenPosition::kNoSource,
5681 LookupVariable(catch_clause->stack_trace()));
5682 catch_handler_body += Drop();
5683 }
5684 AbstractType* type_guard = NULL;
5685 if (catch_clause->guard() != NULL &&
5686 !catch_clause->guard()->IsDynamicType()) {
5687 type_guard = &T.TranslateType(catch_clause->guard());
5688 handler_types.SetAt(i, *type_guard);
5689 } else {
5690 handler_types.SetAt(i, Object::dynamic_type());
5691 }
5692
5693 {
5694 CatchBlock block(this, CurrentException(), CurrentStackTrace(),
5695 try_handler_index);
5696
5697 catch_handler_body += TranslateStatement(catch_clause->body());
5698
5699 // Note: ExitScope adjusts context_depth_ so even if catch_handler_body
5700 // is closed we still need to execute ExitScope for its side effect.
5701 catch_handler_body += ExitScope(catch_clause);
5702 if (catch_handler_body.is_open()) {
5703 catch_handler_body += Goto(after_try);
5704 }
5705 }
5706
5707 if (type_guard != NULL) {
5708 if (type_guard->IsMalformed()) {
5709 catch_body += ThrowTypeError();
5710 catch_body += Drop();
5711 } else {
5712 catch_body += LoadLocal(CurrentException());
5713 catch_body += PushArgument(); // exception
5714 catch_body += NullConstant();
5715 catch_body += PushArgument(); // instantiator type arguments
5716 catch_body += NullConstant();
5717 catch_body += PushArgument(); // function type arguments
5718 catch_body += Constant(*type_guard);
5719 catch_body += PushArgument(); // guard type
5720 catch_body += InstanceCall(
5721 TokenPosition::kNoSource,
5722 dart::Library::PrivateCoreLibName(Symbols::_instanceOf()),
5723 Token::kIS, 4);
5724
5725 TargetEntryInstr* catch_entry;
5726 TargetEntryInstr* next_catch_entry;
5727 catch_body += BranchIfTrue(&catch_entry, &next_catch_entry);
5728
5729 Fragment(catch_entry) + catch_handler_body;
5730 catch_body = Fragment(next_catch_entry);
5731 }
5732 } else {
5733 catch_body += catch_handler_body;
5734 }
5735 }
5736
5737 // In case the last catch body was not handling the exception and branching to
5738 // after the try block, we will rethrow the exception (i.e. no default catch
5739 // handler).
5740 if (catch_body.is_open()) {
5741 catch_body += LoadLocal(CurrentException());
5742 catch_body += PushArgument();
5743 catch_body += LoadLocal(CurrentStackTrace());
5744 catch_body += PushArgument();
5745 catch_body += RethrowException(TokenPosition::kNoSource, try_handler_index);
5746 Drop();
5747 }
5748 --catch_depth_;
5749
5750 fragment_ = Fragment(try_body.entry, after_try);
5751 }
5752
5753
5754 void FlowGraphBuilder::VisitYieldStatement(YieldStatement* node) {
5755 STREAM_STATEMENT_IF_POSSIBLE(node);
5756
5757 ASSERT(node->is_native()); // Must have been desugared.
5758 // Setup yield/continue point:
5759 //
5760 // ...
5761 // :await_jump_var = index;
5762 // :await_ctx_var = :current_context_var
5763 // return <expr>
5764 //
5765 // Continuation<index>:
5766 // Drop(1)
5767 // ...
5768 //
5769 // BuildGraphOfFunction will create a dispatch that jumps to
5770 // Continuation<:await_jump_var> upon entry to the function.
5771 //
5772 Fragment instructions = IntConstant(yield_continuations_.length() + 1);
5773 instructions +=
5774 StoreLocal(TokenPosition::kNoSource, scopes_->yield_jump_variable);
5775 instructions += Drop();
5776 instructions += LoadLocal(parsed_function_->current_context_var());
5777 instructions +=
5778 StoreLocal(TokenPosition::kNoSource, scopes_->yield_context_variable);
5779 instructions += Drop();
5780 instructions += TranslateExpression(node->expression());
5781 instructions += Return(TokenPosition::kNoSource);
5782
5783 // Note: DropTempsInstr serves as an anchor instruction. It will not
5784 // be linked into the resulting graph.
5785 DropTempsInstr* anchor = new (Z) DropTempsInstr(0, NULL);
5786 yield_continuations_.Add(YieldContinuation(anchor, CurrentTryIndex()));
5787
5788 Fragment continuation(instructions.entry, anchor);
5789
5790 if (parsed_function_->function().IsAsyncClosure() ||
5791 parsed_function_->function().IsAsyncGenClosure()) {
5792 // If function is async closure or async gen closure it takes three
5793 // parameters where the second and the third are exception and stack_trace.
5794 // Check if exception is non-null and rethrow it.
5795 //
5796 // :async_op([:result, :exception, :stack_trace]) {
5797 // ...
5798 // Continuation<index>:
5799 // if (:exception != null) rethrow(:exception, :stack_trace);
5800 // ...
5801 // }
5802 //
5803 LocalScope* scope = parsed_function_->node_sequence()->scope();
5804 LocalVariable* exception_var = scope->VariableAt(2);
5805 LocalVariable* stack_trace_var = scope->VariableAt(3);
5806 ASSERT(exception_var->name().raw() == Symbols::ExceptionParameter().raw());
5807 ASSERT(stack_trace_var->name().raw() ==
5808 Symbols::StackTraceParameter().raw());
5809
5810 TargetEntryInstr* no_error;
5811 TargetEntryInstr* error;
5812
5813 continuation += LoadLocal(exception_var);
5814 continuation += BranchIfNull(&no_error, &error);
5815
5816 Fragment rethrow(error);
5817 rethrow += LoadLocal(exception_var);
5818 rethrow += PushArgument();
5819 rethrow += LoadLocal(stack_trace_var);
5820 rethrow += PushArgument();
5821 rethrow +=
5822 RethrowException(node->position(), CatchClauseNode::kInvalidTryIndex);
5823 Drop();
5824
5825
5826 continuation = Fragment(continuation.entry, no_error);
5827 }
5828
5829 fragment_ = continuation;
5830 }
5831
5832
5833 Fragment FlowGraphBuilder::TranslateFunctionNode(FunctionNode* node,
5834 TreeNode* parent) {
5835 // The VM has a per-isolate table of functions indexed by the enclosing
5836 // function and token position.
5837 Function& function = Function::ZoneHandle(Z);
5838 for (intptr_t i = 0; i < scopes_->function_scopes.length(); ++i) {
5839 if (scopes_->function_scopes[i].kernel_offset != node->kernel_offset()) {
5840 continue;
5841 }
5842
5843 TokenPosition position = node->position();
5844 if (parent->IsFunctionDeclaration()) {
5845 position = FunctionDeclaration::Cast(parent)->position();
5846 }
5847 if (!position.IsReal()) {
5848 // Positions has to be unique in regards to the parent.
5849 // A non-real at this point is probably -1, we cannot blindly use that
5850 // as others might use it too. Create a new dummy non-real TokenPosition.
5851 position = TokenPosition(i).ToSynthetic();
5852 }
5853
5854 // NOTE: This is not TokenPosition in the general sense!
5855 function = I->LookupClosureFunction(parsed_function_->function(), position);
5856 if (function.IsNull()) {
5857 const dart::String* name;
5858 if (parent->IsFunctionExpression()) {
5859 name = &Symbols::AnonymousClosure();
5860 } else {
5861 ASSERT(parent->IsFunctionDeclaration());
5862 name = &H.DartSymbol(
5863 FunctionDeclaration::Cast(parent)->variable()->name());
5864 }
5865 // NOTE: This is not TokenPosition in the general sense!
5866 function = Function::NewClosureFunction(
5867 *name, parsed_function_->function(), position);
5868
5869 function.set_is_debuggable(node->dart_async_marker() ==
5870 FunctionNode::kSync);
5871 switch (node->dart_async_marker()) {
5872 case FunctionNode::kSyncStar:
5873 function.set_modifier(RawFunction::kSyncGen);
5874 break;
5875 case FunctionNode::kAsync:
5876 function.set_modifier(RawFunction::kAsync);
5877 function.set_is_inlinable(!FLAG_causal_async_stacks);
5878 break;
5879 case FunctionNode::kAsyncStar:
5880 function.set_modifier(RawFunction::kAsyncGen);
5881 function.set_is_inlinable(!FLAG_causal_async_stacks);
5882 break;
5883 default:
5884 // no special modifier
5885 break;
5886 }
5887 function.set_is_generated_body(node->async_marker() ==
5888 FunctionNode::kSyncYielding);
5889 if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
5890 function.set_is_inlinable(!FLAG_causal_async_stacks);
5891 }
5892
5893 function.set_end_token_pos(node->end_position());
5894 LocalScope* scope = scopes_->function_scopes[i].scope;
5895 const ContextScope& context_scope =
5896 ContextScope::Handle(Z, scope->PreserveOuterScope(context_depth_));
5897 function.set_context_scope(context_scope);
5898 function.set_kernel_function(node);
5899 KernelReader::SetupFunctionParameters(H, T, dart::Class::Handle(Z),
5900 function, node,
5901 false, // is_method
5902 true); // is_closure
5903 // Finalize function type.
5904 Type& signature_type = Type::Handle(Z, function.SignatureType());
5905 signature_type ^=
5906 ClassFinalizer::FinalizeType(*active_class_.klass, signature_type);
5907 function.SetSignatureType(signature_type);
5908
5909 I->AddClosureFunction(function);
5910 }
5911 break;
5912 }
5913
5914 const dart::Class& closure_class =
5915 dart::Class::ZoneHandle(Z, I->object_store()->closure_class());
5916 ASSERT(!closure_class.IsNull());
5917 Fragment instructions = AllocateObject(closure_class, function);
5918 LocalVariable* closure = MakeTemporary();
5919
5920 // TODO(27590): Generic closures need type arguments.
5921
5922 // Store the function and the context in the closure.
5923 instructions += LoadLocal(closure);
5924 instructions += Constant(function);
5925 instructions +=
5926 StoreInstanceField(TokenPosition::kNoSource, Closure::function_offset());
5927
5928 instructions += LoadLocal(closure);
5929 instructions += LoadLocal(parsed_function_->current_context_var());
5930 instructions +=
5931 StoreInstanceField(TokenPosition::kNoSource, Closure::context_offset());
5932
5933 return instructions;
5934 }
5935
5936
5937 RawObject* EvaluateMetadata(const dart::Field& metadata_field) { 2659 RawObject* EvaluateMetadata(const dart::Field& metadata_field) {
2660 // TODO(jensj)
Kevin Millikin (Google) 2017/06/12 12:01:51 TODO what?
jensj 2017/06/13 13:42:14 (as below)
5938 LongJumpScope jump; 2661 LongJumpScope jump;
5939 if (setjmp(*jump.Set()) == 0) { 2662 if (setjmp(*jump.Set()) == 0) {
5940 Thread* thread = Thread::Current(); 2663 Thread* thread = Thread::Current();
5941 Zone* zone_ = thread->zone(); 2664 Zone* zone_ = thread->zone();
5942
5943 TreeNode* kernel_node =
5944 reinterpret_cast<TreeNode*>(metadata_field.kernel_field());
5945 List<Expression>* metadata_expressions = NULL;
5946 if (kernel_node->IsClass()) {
5947 metadata_expressions = &Class::Cast(kernel_node)->annotations();
5948 } else if (kernel_node->IsProcedure()) {
5949 metadata_expressions = &Procedure::Cast(kernel_node)->annotations();
5950 } else if (kernel_node->IsField()) {
5951 metadata_expressions = &Field::Cast(kernel_node)->annotations();
5952 } else if (kernel_node->IsConstructor()) {
5953 metadata_expressions = &Constructor::Cast(kernel_node)->annotations();
5954 } else {
5955 FATAL1("No support for metadata on this type of kernel node %p\n",
5956 kernel_node);
5957 }
5958
5959 TranslationHelper helper(thread); 2665 TranslationHelper helper(thread);
5960 Script& script = Script::Handle(Z, metadata_field.Script()); 2666 Script& script = Script::Handle(Z, metadata_field.Script());
5961 helper.SetStringOffsets( 2667 helper.SetStringOffsets(
5962 TypedData::Handle(Z, script.kernel_string_offsets())); 2668 TypedData::Handle(Z, script.kernel_string_offsets()));
5963 helper.SetStringData(TypedData::Handle(Z, script.kernel_string_data())); 2669 helper.SetStringData(TypedData::Handle(Z, script.kernel_string_data()));
5964 helper.SetCanonicalNames( 2670 helper.SetCanonicalNames(
5965 TypedData::Handle(Z, script.kernel_canonical_names())); 2671 TypedData::Handle(Z, script.kernel_canonical_names()));
5966 DartTypeTranslator type_translator(&helper, NULL, true);
5967 ConstantEvaluator constant_evaluator(/* flow_graph_builder = */ NULL, Z,
5968 &helper, &type_translator);
5969 2672
5970 const Array& metadata_values = 2673 StreamingFlowGraphBuilder streaming_flow_graph_builder(
5971 Array::Handle(Z, Array::New(metadata_expressions->length())); 2674 &helper, zone_, script.kernel_data(), script.kernel_data_size());
5972 2675 return streaming_flow_graph_builder.EvaluateMetadata(
5973 for (intptr_t i = 0; i < metadata_expressions->length(); i++) { 2676 metadata_field.kernel_offset());
5974 const Instance& value =
5975 constant_evaluator.EvaluateExpression((*metadata_expressions)[i]);
5976 metadata_values.SetAt(i, value);
5977 }
5978
5979 return metadata_values.raw();
5980 } else { 2677 } else {
5981 Thread* thread = Thread::Current(); 2678 Thread* thread = Thread::Current();
5982 Error& error = Error::Handle(); 2679 Error& error = Error::Handle();
5983 error = thread->sticky_error(); 2680 error = thread->sticky_error();
5984 thread->clear_sticky_error(); 2681 thread->clear_sticky_error();
5985 return error.raw(); 2682 return error.raw();
5986 } 2683 }
5987 } 2684 }
5988 2685
5989 2686
5990 RawObject* BuildParameterDescriptor(const Function& function) { 2687 RawObject* BuildParameterDescriptor(const Function& function) {
2688 // TODO(jensj)
Kevin Millikin (Google) 2017/06/12 12:01:51 TODO what?
jensj 2017/06/13 13:42:14 Should have been ``` // TODO(jensj): Delete this
5991 LongJumpScope jump; 2689 LongJumpScope jump;
5992 if (setjmp(*jump.Set()) == 0) { 2690 if (setjmp(*jump.Set()) == 0) {
5993 TreeNode* kernel_node =
5994 reinterpret_cast<TreeNode*>(function.kernel_function());
5995 FunctionNode* function_node = NULL;
5996 if (kernel_node->IsProcedure()) {
5997 function_node = Procedure::Cast(kernel_node)->function();
5998 } else if (kernel_node->IsConstructor()) {
5999 function_node = Constructor::Cast(kernel_node)->function();
6000 } else if (kernel_node->IsFunctionNode()) {
6001 function_node = FunctionNode::Cast(kernel_node);
6002 } else {
6003 UNIMPLEMENTED();
6004 return NULL;
6005 }
6006
6007 Thread* thread = Thread::Current(); 2691 Thread* thread = Thread::Current();
6008 Zone* zone_ = thread->zone(); 2692 Zone* zone_ = thread->zone();
6009 TranslationHelper helper(thread); 2693 TranslationHelper helper(thread);
6010 Script& script = Script::Handle(Z, function.script()); 2694 Script& script = Script::Handle(Z, function.script());
6011 helper.SetStringOffsets( 2695 helper.SetStringOffsets(
6012 TypedData::Handle(Z, script.kernel_string_offsets())); 2696 TypedData::Handle(Z, script.kernel_string_offsets()));
6013 helper.SetStringData(TypedData::Handle(Z, script.kernel_string_data())); 2697 helper.SetStringData(TypedData::Handle(Z, script.kernel_string_data()));
6014 helper.SetCanonicalNames( 2698 helper.SetCanonicalNames(
6015 TypedData::Handle(Z, script.kernel_canonical_names())); 2699 TypedData::Handle(Z, script.kernel_canonical_names()));
6016 DartTypeTranslator type_translator(&helper, NULL, true);
6017 ConstantEvaluator constant_evaluator(/* flow_graph_builder = */ NULL, Z,
6018 &helper, &type_translator);
6019 2700
6020 const intptr_t positional_count = 2701 StreamingFlowGraphBuilder streaming_flow_graph_builder(
6021 function_node->positional_parameters().length(); 2702 &helper, zone_, script.kernel_data(), script.kernel_data_size());
6022 const intptr_t param_count = 2703 return streaming_flow_graph_builder.BuildParameterDescriptor(
6023 positional_count + function_node->named_parameters().length(); 2704 function.kernel_offset());
6024 const Array& param_descriptor = Array::Handle(
6025 Array::New(param_count * Parser::kParameterEntrySize, Heap::kOld));
6026 for (intptr_t i = 0; i < param_count; ++i) {
6027 const intptr_t entry_start = i * Parser::kParameterEntrySize;
6028
6029 VariableDeclaration* variable;
6030 if (i < positional_count) {
6031 variable = function_node->positional_parameters()[i];
6032 } else {
6033 variable = function_node->named_parameters()[i - positional_count];
6034 }
6035
6036 param_descriptor.SetAt(
6037 entry_start + Parser::kParameterIsFinalOffset,
6038 variable->IsFinal() ? Bool::True() : Bool::False());
6039
6040 if (variable->initializer() != NULL) {
6041 param_descriptor.SetAt(
6042 entry_start + Parser::kParameterDefaultValueOffset,
6043 constant_evaluator.EvaluateExpression(variable->initializer()));
6044 } else {
6045 param_descriptor.SetAt(
6046 entry_start + Parser::kParameterDefaultValueOffset,
6047 Object::null_instance());
6048 }
6049
6050 param_descriptor.SetAt(entry_start + Parser::kParameterMetadataOffset,
6051 /* Issue(28434): Missing parameter metadata. */
6052 Object::null_instance());
6053 }
6054 return param_descriptor.raw();
6055 } else { 2705 } else {
6056 Thread* thread = Thread::Current(); 2706 Thread* thread = Thread::Current();
6057 Error& error = Error::Handle(); 2707 Error& error = Error::Handle();
6058 error = thread->sticky_error(); 2708 error = thread->sticky_error();
6059 thread->clear_sticky_error(); 2709 thread->clear_sticky_error();
6060 return error.raw(); 2710 return error.raw();
6061 } 2711 }
6062 } 2712 }
6063 2713
6064 2714
6065 } // namespace kernel 2715 } // namespace kernel
6066 } // namespace dart 2716 } // namespace dart
6067 2717
6068 #endif // !defined(DART_PRECOMPILED_RUNTIME) 2718 #endif // !defined(DART_PRECOMPILED_RUNTIME)
OLDNEW
« pkg/kernel/binary.md ('K') | « runtime/vm/kernel_to_il.h ('k') | runtime/vm/object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698