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

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

Issue 2279563002: AOT: Single target stub. (Closed)
Patch Set: add offset assertions Created 4 years, 3 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/assembler_x64.cc ('k') | runtime/vm/dart.cc » ('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) 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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/assembler_x64.cc ('k') | runtime/vm/dart.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698