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 1128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1139 ic_data, | 1139 ic_data, |
1140 stub); | 1140 stub); |
1141 | 1141 |
1142 // Return the ICData. The single target stub will jump to continue in the | 1142 // Return the ICData. The single target stub will jump to continue in the |
1143 // IC call stub. | 1143 // IC call stub. |
1144 arguments.SetReturn(ic_data); | 1144 arguments.SetReturn(ic_data); |
1145 #endif | 1145 #endif |
1146 } | 1146 } |
1147 | 1147 |
1148 | 1148 |
| 1149 DEFINE_RUNTIME_ENTRY(UnlinkedCall, 2) { |
| 1150 #if defined(TARGET_ARCH_DBC) |
| 1151 // DBC does not use switchable calls. |
| 1152 UNREACHABLE(); |
| 1153 #else |
| 1154 const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0)); |
| 1155 const UnlinkedCall& unlinked = |
| 1156 UnlinkedCall::CheckedHandle(zone, arguments.ArgAt(1)); |
| 1157 |
| 1158 DartFrameIterator iterator; |
| 1159 StackFrame* caller_frame = iterator.NextFrame(); |
| 1160 ASSERT(caller_frame->IsDartFrame()); |
| 1161 const Code& caller_code = |
| 1162 Code::Handle(zone, caller_frame->LookupDartCode()); |
| 1163 const Function& caller_function = |
| 1164 Function::Handle(zone, caller_frame->LookupDartFunction()); |
| 1165 |
| 1166 const String& name = String::Handle(zone, unlinked.target_name()); |
| 1167 const Array& descriptor = Array::Handle(zone, unlinked.args_descriptor()); |
| 1168 const ICData& ic_data = |
| 1169 ICData::Handle(zone, ICData::New(caller_function, |
| 1170 name, |
| 1171 descriptor, |
| 1172 Thread::kNoDeoptId, |
| 1173 1, /* args_tested */ |
| 1174 false /* static_call */)); |
| 1175 |
| 1176 Class& cls = Class::Handle(zone, receiver.clazz()); |
| 1177 ArgumentsDescriptor args_desc(descriptor); |
| 1178 Function& target_function = Function::Handle(zone, |
| 1179 Resolver::ResolveDynamicForReceiverClass(cls, |
| 1180 name, |
| 1181 args_desc)); |
| 1182 if (target_function.IsNull()) { |
| 1183 target_function = InlineCacheMissHelper(receiver, descriptor, name); |
| 1184 } |
| 1185 if (target_function.IsNull()) { |
| 1186 ASSERT(!FLAG_lazy_dispatchers); |
| 1187 } else { |
| 1188 ic_data.AddReceiverCheck(receiver.GetClassId(), target_function); |
| 1189 } |
| 1190 |
| 1191 if (!target_function.IsNull() && |
| 1192 !target_function.HasOptionalParameters()) { |
| 1193 // Patch to monomorphic call. |
| 1194 ASSERT(target_function.HasCode()); |
| 1195 const Code& target_code = |
| 1196 Code::Handle(zone, target_function.CurrentCode()); |
| 1197 const Smi& expected_cid = |
| 1198 Smi::Handle(zone, Smi::New(receiver.GetClassId())); |
| 1199 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code, |
| 1200 expected_cid, target_code); |
| 1201 |
| 1202 // Return the ICData. The miss stub will jump to continue in the IC call |
| 1203 // stub. |
| 1204 arguments.SetReturn(ic_data); |
| 1205 return; |
| 1206 } |
| 1207 |
| 1208 // Patch to call through stub. |
| 1209 const Code& stub = |
| 1210 Code::Handle(zone, StubCode::ICCallThroughCode_entry()->code()); |
| 1211 ASSERT(!Isolate::Current()->compilation_allowed()); |
| 1212 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), |
| 1213 caller_code, |
| 1214 ic_data, |
| 1215 stub); |
| 1216 |
| 1217 // Return the ICData. The miss stub will jump to continue in the IC lookup |
| 1218 // stub. |
| 1219 arguments.SetReturn(ic_data); |
| 1220 #endif // !DBC |
| 1221 } |
| 1222 |
| 1223 |
1149 // Handle a miss of a megamorphic cache. | 1224 // Handle a miss of a megamorphic cache. |
1150 // Arg0: Receiver. | 1225 // Arg0: Receiver. |
1151 // Returns: the ICData used to continue with a polymorphic call. | 1226 // Returns: the ICData used to continue with a polymorphic call. |
1152 DEFINE_RUNTIME_ENTRY(MonomorphicMiss, 1) { | 1227 DEFINE_RUNTIME_ENTRY(MonomorphicMiss, 1) { |
1153 #if defined(TARGET_ARCH_DBC) | 1228 #if defined(TARGET_ARCH_DBC) |
1154 // DBC does not use switchable calls. | 1229 // DBC does not use switchable calls. |
1155 UNREACHABLE(); | 1230 UNREACHABLE(); |
1156 #else | 1231 #else |
1157 const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0)); | 1232 const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0)); |
1158 | 1233 |
(...skipping 1062 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2221 const intptr_t elm_size = old_data.ElementSizeInBytes(); | 2296 const intptr_t elm_size = old_data.ElementSizeInBytes(); |
2222 const TypedData& new_data = | 2297 const TypedData& new_data = |
2223 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); | 2298 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); |
2224 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); | 2299 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); |
2225 typed_data_cell.SetAt(0, new_data); | 2300 typed_data_cell.SetAt(0, new_data); |
2226 arguments.SetReturn(new_data); | 2301 arguments.SetReturn(new_data); |
2227 } | 2302 } |
2228 | 2303 |
2229 | 2304 |
2230 } // namespace dart | 2305 } // namespace dart |
OLD | NEW |