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