OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 "vm/code_generator.h" | 5 #include "vm/code_generator.h" |
6 | 6 |
7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
8 #include "vm/ast.h" | 8 #include "vm/ast.h" |
9 #include "vm/code_patcher.h" | 9 #include "vm/code_patcher.h" |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
(...skipping 1008 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1019 StackFrame* caller_frame = iterator.NextFrame(); | 1019 StackFrame* caller_frame = iterator.NextFrame(); |
1020 ASSERT(caller_frame != NULL); | 1020 ASSERT(caller_frame != NULL); |
1021 OS::PrintErr("StaticCallMissHandler at %#" Px | 1021 OS::PrintErr("StaticCallMissHandler at %#" Px |
1022 " target %s (%" Pd ", %" Pd ")\n", | 1022 " target %s (%" Pd ", %" Pd ")\n", |
1023 caller_frame->pc(), target.ToCString(), cids[0], cids[1]); | 1023 caller_frame->pc(), target.ToCString(), cids[0], cids[1]); |
1024 } | 1024 } |
1025 arguments.SetReturn(target); | 1025 arguments.SetReturn(target); |
1026 } | 1026 } |
1027 | 1027 |
1028 | 1028 |
1029 #if !defined(TARGET_ARCH_DBC) | |
1030 static bool IsSingleTarget(Zone* zone, | |
1031 intptr_t lower_cid, | |
1032 intptr_t upper_cid, | |
1033 const Function& target, | |
1034 const String& name) { | |
1035 Class& cls = Class::Handle(zone); | |
1036 ClassTable* table = Isolate::Current()->class_table(); | |
siva
2016/08/30 23:54:53
why not pass the isolate down to this function as
rmacnak
2016/08/31 16:42:57
Done.
| |
1037 Function& other_target = Function::Handle(zone); | |
1038 for (intptr_t cid = lower_cid; cid <= upper_cid; cid++) { | |
1039 if (!table->HasValidClassAt(cid)) continue; | |
1040 cls = table->At(cid); | |
1041 if (cls.is_abstract()) continue; | |
1042 if (!cls.is_allocated()) continue; | |
1043 other_target = Resolver::ResolveDynamicAnyArgs(zone, cls, name, | |
1044 false /* allow_add */); | |
1045 if (other_target.raw() != target.raw()) { | |
1046 return false; | |
1047 } | |
1048 } | |
1049 return true; | |
1050 } | |
1051 #endif | |
1052 | |
1053 | |
1054 // Handle a miss of a single target cache. | |
1055 // Arg0: Receiver. | |
1056 // Returns: the ICData used to continue with a polymorphic call. | |
1057 DEFINE_RUNTIME_ENTRY(SingleTargetMiss, 1) { | |
1058 #if defined(TARGET_ARCH_DBC) | |
1059 // DBC does not use switchable calls. | |
1060 UNREACHABLE(); | |
1061 #else | |
1062 const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0)); | |
1063 | |
1064 DartFrameIterator iterator; | |
1065 StackFrame* caller_frame = iterator.NextFrame(); | |
1066 ASSERT(caller_frame->IsDartFrame()); | |
1067 const Code& caller_code = Code::Handle(zone, caller_frame->LookupDartCode()); | |
1068 const Function& caller_function = | |
1069 Function::Handle(zone, caller_frame->LookupDartFunction()); | |
1070 | |
1071 SingleTargetCache& cache = SingleTargetCache::Handle(zone); | |
1072 cache ^= CodePatcher::GetSwitchableCallDataAt(caller_frame->pc(), | |
1073 caller_code); | |
1074 Code& old_target_code = Code::Handle(zone, cache.target()); | |
1075 Function& old_target = Function::Handle(zone); | |
1076 old_target ^= old_target_code.owner(); | |
1077 | |
1078 // We lost the original ICData when we patched to the monomorphic case. | |
1079 const String& name = String::Handle(zone, old_target.name()); | |
1080 ASSERT(!old_target.HasOptionalParameters()); | |
1081 const Array& descriptor = Array::Handle(zone, | |
1082 ArgumentsDescriptor::New(old_target.num_fixed_parameters())); | |
1083 const ICData& ic_data = | |
1084 ICData::Handle(zone, ICData::New(caller_function, | |
1085 name, | |
1086 descriptor, | |
1087 Thread::kNoDeoptId, | |
1088 1, /* args_tested */ | |
1089 false /* static_call */)); | |
1090 | |
1091 // Maybe add the new target. | |
1092 Class& cls = Class::Handle(zone, receiver.clazz()); | |
1093 ArgumentsDescriptor args_desc(descriptor); | |
1094 Function& target_function = Function::Handle(zone, | |
1095 Resolver::ResolveDynamicForReceiverClass(cls, | |
1096 name, | |
1097 args_desc)); | |
1098 if (target_function.IsNull()) { | |
1099 target_function = InlineCacheMissHelper(receiver, descriptor, name); | |
1100 } | |
1101 if (target_function.IsNull()) { | |
1102 ASSERT(!FLAG_lazy_dispatchers); | |
1103 } else { | |
1104 ic_data.AddReceiverCheck(receiver.GetClassId(), target_function); | |
1105 } | |
1106 | |
1107 if (old_target.raw() == target_function.raw()) { | |
1108 intptr_t lower, upper; | |
1109 if (receiver.GetClassId() < cache.lower_limit()) { | |
1110 lower = receiver.GetClassId(); | |
1111 upper = cache.upper_limit(); | |
1112 } else { | |
1113 lower = cache.lower_limit(); | |
1114 upper = receiver.GetClassId(); | |
1115 } | |
1116 | |
1117 if (IsSingleTarget(zone, lower, upper, target_function, name)) { | |
1118 cache.set_lower_limit(lower); | |
1119 cache.set_upper_limit(upper); | |
1120 // Return the ICData. The single target stub will jump to continue in the | |
1121 // IC call stub. | |
1122 arguments.SetReturn(ic_data); | |
1123 return; | |
1124 } | |
1125 } | |
1126 | |
1127 // Call site is not single target, switch to call using ICData. | |
1128 const Code& stub = | |
1129 Code::Handle(zone, StubCode::ICCallThroughCode_entry()->code()); | |
1130 ASSERT(!Isolate::Current()->compilation_allowed()); | |
1131 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), | |
1132 caller_code, | |
1133 ic_data, | |
1134 stub); | |
1135 | |
1136 // Return the ICData. The single target stub will jump to continue in the | |
1137 // IC call stub. | |
1138 arguments.SetReturn(ic_data); | |
1139 #endif | |
1140 } | |
1141 | |
1142 | |
1029 // Handle a miss of a megamorphic cache. | 1143 // Handle a miss of a megamorphic cache. |
Florian Schneider
2016/08/30 20:42:34
Comment: s/megamorphic/monomorphic/
rmacnak
2016/08/31 16:42:56
Done.
| |
1030 // Arg0: Receiver. | 1144 // Arg0: Receiver. |
1031 // Returns: the ICData used to continue with a polymorphic call. | 1145 // Returns: the ICData used to continue with a polymorphic call. |
1032 DEFINE_RUNTIME_ENTRY(MonomorphicMiss, 1) { | 1146 DEFINE_RUNTIME_ENTRY(MonomorphicMiss, 1) { |
1033 #if defined(TARGET_ARCH_DBC) | 1147 #if defined(TARGET_ARCH_DBC) |
1034 // DBC does not use switchable calls. | 1148 // DBC does not use switchable calls. |
1035 UNREACHABLE(); | 1149 UNREACHABLE(); |
1036 #else | 1150 #else |
1037 const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0)); | 1151 const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0)); |
1038 | 1152 |
1039 DartFrameIterator iterator; | 1153 DartFrameIterator iterator; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1077 args_desc)); | 1191 args_desc)); |
1078 if (target_function.IsNull()) { | 1192 if (target_function.IsNull()) { |
1079 target_function = InlineCacheMissHelper(receiver, descriptor, name); | 1193 target_function = InlineCacheMissHelper(receiver, descriptor, name); |
1080 } | 1194 } |
1081 if (target_function.IsNull()) { | 1195 if (target_function.IsNull()) { |
1082 ASSERT(!FLAG_lazy_dispatchers); | 1196 ASSERT(!FLAG_lazy_dispatchers); |
1083 } else { | 1197 } else { |
1084 ic_data.AddReceiverCheck(receiver.GetClassId(), target_function); | 1198 ic_data.AddReceiverCheck(receiver.GetClassId(), target_function); |
1085 } | 1199 } |
1086 | 1200 |
1201 if (old_target.raw() == target_function.raw()) { | |
1202 intptr_t lower, upper; | |
1203 if (old_expected_cid.Value() < receiver.GetClassId()) { | |
1204 lower = old_expected_cid.Value(); | |
1205 upper = receiver.GetClassId(); | |
1206 } else { | |
1207 lower = receiver.GetClassId(); | |
1208 upper = old_expected_cid.Value(); | |
1209 } | |
1210 | |
1211 if (IsSingleTarget(zone, lower, upper, target_function, name)) { | |
1212 const SingleTargetCache& cache = | |
1213 SingleTargetCache::Handle(SingleTargetCache::New()); | |
1214 const Code& code = Code::Handle(target_function.CurrentCode()); | |
1215 cache.set_target(code); | |
1216 cache.set_entry_point(code.UncheckedEntryPoint()); | |
1217 cache.set_lower_limit(lower); | |
1218 cache.set_upper_limit(upper); | |
1219 const Code& stub = Code::Handle(zone, | |
1220 StubCode::SingleTargetCall_entry()->code()); | |
1221 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), | |
1222 caller_code, | |
1223 cache, | |
1224 stub); | |
1225 // Return the ICData. The miss stub will jump to continue in the IC call | |
1226 // stub. | |
1227 arguments.SetReturn(ic_data); | |
1228 return; | |
1229 } | |
1230 } | |
1231 | |
1087 // Patch to call through stub. | 1232 // Patch to call through stub. |
1088 const Code& stub = | 1233 const Code& stub = |
1089 Code::Handle(zone, StubCode::ICCallThroughCode_entry()->code()); | 1234 Code::Handle(zone, StubCode::ICCallThroughCode_entry()->code()); |
1090 ASSERT(!Isolate::Current()->compilation_allowed()); | 1235 ASSERT(!Isolate::Current()->compilation_allowed()); |
1091 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), | 1236 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), |
1092 caller_code, | 1237 caller_code, |
1093 ic_data, | 1238 ic_data, |
1094 stub); | 1239 stub); |
1095 | 1240 |
1096 // Return the ICData. The miss stub will jump to continue in the IC lookup | 1241 // Return the ICData. The miss stub will jump to continue in the IC lookup |
(...skipping 973 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2070 const intptr_t elm_size = old_data.ElementSizeInBytes(); | 2215 const intptr_t elm_size = old_data.ElementSizeInBytes(); |
2071 const TypedData& new_data = | 2216 const TypedData& new_data = |
2072 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); | 2217 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); |
2073 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); | 2218 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); |
2074 typed_data_cell.SetAt(0, new_data); | 2219 typed_data_cell.SetAt(0, new_data); |
2075 arguments.SetReturn(new_data); | 2220 arguments.SetReturn(new_data); |
2076 } | 2221 } |
2077 | 2222 |
2078 | 2223 |
2079 } // namespace dart | 2224 } // namespace dart |
OLD | NEW |