Chromium Code Reviews| 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 |