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

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

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