OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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/runtime_entry.h" | 5 #include "vm/runtime_entry.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" |
11 #include "vm/dart_api_impl.h" | 11 #include "vm/dart_api_impl.h" |
12 #include "vm/dart_entry.h" | 12 #include "vm/dart_entry.h" |
13 #include "vm/debugger.h" | 13 #include "vm/debugger.h" |
14 #include "vm/deopt_instructions.h" | 14 #include "vm/deopt_instructions.h" |
15 #include "vm/exceptions.h" | 15 #include "vm/exceptions.h" |
16 #include "vm/flags.h" | 16 #include "vm/flags.h" |
17 #include "vm/object_store.h" | |
18 #include "vm/message.h" | 17 #include "vm/message.h" |
19 #include "vm/message_handler.h" | 18 #include "vm/message_handler.h" |
| 19 #include "vm/object_store.h" |
20 #include "vm/parser.h" | 20 #include "vm/parser.h" |
21 #include "vm/resolver.h" | 21 #include "vm/resolver.h" |
22 #include "vm/service_isolate.h" | 22 #include "vm/service_isolate.h" |
23 #include "vm/stack_frame.h" | 23 #include "vm/stack_frame.h" |
24 #include "vm/symbols.h" | 24 #include "vm/symbols.h" |
25 #include "vm/thread_registry.h" | 25 #include "vm/thread_registry.h" |
26 #include "vm/verifier.h" | 26 #include "vm/verifier.h" |
27 | 27 |
28 namespace dart { | 28 namespace dart { |
29 | 29 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 DECLARE_FLAG(bool, reload_every_back_off); | 85 DECLARE_FLAG(bool, reload_every_back_off); |
86 | 86 |
87 #ifdef DEBUG | 87 #ifdef DEBUG |
88 DEFINE_FLAG(charp, | 88 DEFINE_FLAG(charp, |
89 gc_at_instance_allocation, | 89 gc_at_instance_allocation, |
90 NULL, | 90 NULL, |
91 "Perform a GC before allocation of instances of " | 91 "Perform a GC before allocation of instances of " |
92 "the specified class"); | 92 "the specified class"); |
93 #endif | 93 #endif |
94 | 94 |
95 | |
96 #if defined(TESTING) || defined(DEBUG) | 95 #if defined(TESTING) || defined(DEBUG) |
97 void VerifyOnTransition() { | 96 void VerifyOnTransition() { |
98 Thread* thread = Thread::Current(); | 97 Thread* thread = Thread::Current(); |
99 TransitionGeneratedToVM transition(thread); | 98 TransitionGeneratedToVM transition(thread); |
100 thread->isolate()->heap()->WaitForSweeperTasks(thread); | 99 thread->isolate()->heap()->WaitForSweeperTasks(thread); |
101 SafepointOperationScope safepoint_scope(thread); | 100 SafepointOperationScope safepoint_scope(thread); |
102 VerifyPointersVisitor::VerifyPointers(); | 101 VerifyPointersVisitor::VerifyPointers(); |
103 thread->isolate()->heap()->Verify(); | 102 thread->isolate()->heap()->Verify(); |
104 } | 103 } |
105 #endif | 104 #endif |
106 | 105 |
107 | |
108 // Add function to a class and that class to the class dictionary so that | 106 // Add function to a class and that class to the class dictionary so that |
109 // frame walking can be used. | 107 // frame walking can be used. |
110 const Function& RegisterFakeFunction(const char* name, const Code& code) { | 108 const Function& RegisterFakeFunction(const char* name, const Code& code) { |
111 Thread* thread = Thread::Current(); | 109 Thread* thread = Thread::Current(); |
112 const String& class_name = String::Handle(Symbols::New(thread, "ownerClass")); | 110 const String& class_name = String::Handle(Symbols::New(thread, "ownerClass")); |
113 const Script& script = Script::Handle(); | 111 const Script& script = Script::Handle(); |
114 const Library& lib = Library::Handle(Library::CoreLibrary()); | 112 const Library& lib = Library::Handle(Library::CoreLibrary()); |
115 const Class& owner_class = Class::Handle( | 113 const Class& owner_class = Class::Handle( |
116 Class::New(lib, class_name, script, TokenPosition::kNoSource)); | 114 Class::New(lib, class_name, script, TokenPosition::kNoSource)); |
117 const String& function_name = String::ZoneHandle(Symbols::New(thread, name)); | 115 const String& function_name = String::ZoneHandle(Symbols::New(thread, name)); |
118 const Function& function = Function::ZoneHandle(Function::New( | 116 const Function& function = Function::ZoneHandle(Function::New( |
119 function_name, RawFunction::kRegularFunction, true, false, false, false, | 117 function_name, RawFunction::kRegularFunction, true, false, false, false, |
120 false, owner_class, TokenPosition::kMinSource)); | 118 false, owner_class, TokenPosition::kMinSource)); |
121 const Array& functions = Array::Handle(Array::New(1)); | 119 const Array& functions = Array::Handle(Array::New(1)); |
122 functions.SetAt(0, function); | 120 functions.SetAt(0, function); |
123 owner_class.SetFunctions(functions); | 121 owner_class.SetFunctions(functions); |
124 lib.AddClass(owner_class); | 122 lib.AddClass(owner_class); |
125 function.AttachCode(code); | 123 function.AttachCode(code); |
126 return function; | 124 return function; |
127 } | 125 } |
128 | 126 |
129 | |
130 DEFINE_RUNTIME_ENTRY(TraceFunctionEntry, 1) { | 127 DEFINE_RUNTIME_ENTRY(TraceFunctionEntry, 1) { |
131 const Function& function = Function::CheckedHandle(arguments.ArgAt(0)); | 128 const Function& function = Function::CheckedHandle(arguments.ArgAt(0)); |
132 const String& function_name = String::Handle(function.name()); | 129 const String& function_name = String::Handle(function.name()); |
133 const String& class_name = | 130 const String& class_name = |
134 String::Handle(Class::Handle(function.Owner()).Name()); | 131 String::Handle(Class::Handle(function.Owner()).Name()); |
135 OS::PrintErr("> Entering '%s.%s'\n", class_name.ToCString(), | 132 OS::PrintErr("> Entering '%s.%s'\n", class_name.ToCString(), |
136 function_name.ToCString()); | 133 function_name.ToCString()); |
137 } | 134 } |
138 | 135 |
139 | |
140 DEFINE_RUNTIME_ENTRY(TraceFunctionExit, 1) { | 136 DEFINE_RUNTIME_ENTRY(TraceFunctionExit, 1) { |
141 const Function& function = Function::CheckedHandle(arguments.ArgAt(0)); | 137 const Function& function = Function::CheckedHandle(arguments.ArgAt(0)); |
142 const String& function_name = String::Handle(function.name()); | 138 const String& function_name = String::Handle(function.name()); |
143 const String& class_name = | 139 const String& class_name = |
144 String::Handle(Class::Handle(function.Owner()).Name()); | 140 String::Handle(Class::Handle(function.Owner()).Name()); |
145 OS::PrintErr("< Exiting '%s.%s'\n", class_name.ToCString(), | 141 OS::PrintErr("< Exiting '%s.%s'\n", class_name.ToCString(), |
146 function_name.ToCString()); | 142 function_name.ToCString()); |
147 } | 143 } |
148 | 144 |
149 | |
150 DEFINE_RUNTIME_ENTRY(RangeError, 2) { | 145 DEFINE_RUNTIME_ENTRY(RangeError, 2) { |
151 const Instance& length = Instance::CheckedHandle(arguments.ArgAt(0)); | 146 const Instance& length = Instance::CheckedHandle(arguments.ArgAt(0)); |
152 const Instance& index = Instance::CheckedHandle(arguments.ArgAt(1)); | 147 const Instance& index = Instance::CheckedHandle(arguments.ArgAt(1)); |
153 if (!length.IsInteger()) { | 148 if (!length.IsInteger()) { |
154 // Throw: new ArgumentError.value(length, "length", "is not an integer"); | 149 // Throw: new ArgumentError.value(length, "length", "is not an integer"); |
155 const Array& args = Array::Handle(Array::New(3)); | 150 const Array& args = Array::Handle(Array::New(3)); |
156 args.SetAt(0, length); | 151 args.SetAt(0, length); |
157 args.SetAt(1, Symbols::Length()); | 152 args.SetAt(1, Symbols::Length()); |
158 args.SetAt(2, String::Handle(String::New("is not an integer"))); | 153 args.SetAt(2, String::Handle(String::New("is not an integer"))); |
159 Exceptions::ThrowByType(Exceptions::kArgumentValue, args); | 154 Exceptions::ThrowByType(Exceptions::kArgumentValue, args); |
160 } | 155 } |
161 if (!index.IsInteger()) { | 156 if (!index.IsInteger()) { |
162 // Throw: new ArgumentError.value(index, "index", "is not an integer"); | 157 // Throw: new ArgumentError.value(index, "index", "is not an integer"); |
163 const Array& args = Array::Handle(Array::New(3)); | 158 const Array& args = Array::Handle(Array::New(3)); |
164 args.SetAt(0, index); | 159 args.SetAt(0, index); |
165 args.SetAt(1, Symbols::Index()); | 160 args.SetAt(1, Symbols::Index()); |
166 args.SetAt(2, String::Handle(String::New("is not an integer"))); | 161 args.SetAt(2, String::Handle(String::New("is not an integer"))); |
167 Exceptions::ThrowByType(Exceptions::kArgumentValue, args); | 162 Exceptions::ThrowByType(Exceptions::kArgumentValue, args); |
168 } | 163 } |
169 // Throw: new RangeError.range(index, 0, length, "length"); | 164 // Throw: new RangeError.range(index, 0, length, "length"); |
170 const Array& args = Array::Handle(Array::New(4)); | 165 const Array& args = Array::Handle(Array::New(4)); |
171 args.SetAt(0, index); | 166 args.SetAt(0, index); |
172 args.SetAt(1, Integer::Handle(Integer::New(0))); | 167 args.SetAt(1, Integer::Handle(Integer::New(0))); |
173 args.SetAt(2, length); | 168 args.SetAt(2, length); |
174 args.SetAt(3, Symbols::Length()); | 169 args.SetAt(3, Symbols::Length()); |
175 Exceptions::ThrowByType(Exceptions::kRange, args); | 170 Exceptions::ThrowByType(Exceptions::kRange, args); |
176 } | 171 } |
177 | 172 |
178 | |
179 // Allocation of a fixed length array of given element type. | 173 // Allocation of a fixed length array of given element type. |
180 // This runtime entry is never called for allocating a List of a generic type, | 174 // This runtime entry is never called for allocating a List of a generic type, |
181 // because a prior run time call instantiates the element type if necessary. | 175 // because a prior run time call instantiates the element type if necessary. |
182 // Arg0: array length. | 176 // Arg0: array length. |
183 // Arg1: array type arguments, i.e. vector of 1 type, the element type. | 177 // Arg1: array type arguments, i.e. vector of 1 type, the element type. |
184 // Return value: newly allocated array of length arg0. | 178 // Return value: newly allocated array of length arg0. |
185 DEFINE_RUNTIME_ENTRY(AllocateArray, 2) { | 179 DEFINE_RUNTIME_ENTRY(AllocateArray, 2) { |
186 const Instance& length = Instance::CheckedHandle(arguments.ArgAt(0)); | 180 const Instance& length = Instance::CheckedHandle(arguments.ArgAt(0)); |
187 if (!length.IsInteger()) { | 181 if (!length.IsInteger()) { |
188 // Throw: new ArgumentError.value(length, "length", "is not an integer"); | 182 // Throw: new ArgumentError.value(length, "length", "is not an integer"); |
(...skipping 21 matching lines...) Expand all Loading... |
210 } | 204 } |
211 // Throw: new RangeError.range(length, 0, Array::kMaxElements, "length"); | 205 // Throw: new RangeError.range(length, 0, Array::kMaxElements, "length"); |
212 const Array& args = Array::Handle(Array::New(4)); | 206 const Array& args = Array::Handle(Array::New(4)); |
213 args.SetAt(0, length); | 207 args.SetAt(0, length); |
214 args.SetAt(1, Integer::Handle(Integer::New(0))); | 208 args.SetAt(1, Integer::Handle(Integer::New(0))); |
215 args.SetAt(2, Integer::Handle(Integer::New(Array::kMaxElements))); | 209 args.SetAt(2, Integer::Handle(Integer::New(Array::kMaxElements))); |
216 args.SetAt(3, Symbols::Length()); | 210 args.SetAt(3, Symbols::Length()); |
217 Exceptions::ThrowByType(Exceptions::kRange, args); | 211 Exceptions::ThrowByType(Exceptions::kRange, args); |
218 } | 212 } |
219 | 213 |
220 | |
221 // Helper returning the token position of the Dart caller. | 214 // Helper returning the token position of the Dart caller. |
222 static TokenPosition GetCallerLocation() { | 215 static TokenPosition GetCallerLocation() { |
223 DartFrameIterator iterator(Thread::Current(), | 216 DartFrameIterator iterator(Thread::Current(), |
224 StackFrameIterator::kNoCrossThreadIteration); | 217 StackFrameIterator::kNoCrossThreadIteration); |
225 StackFrame* caller_frame = iterator.NextFrame(); | 218 StackFrame* caller_frame = iterator.NextFrame(); |
226 ASSERT(caller_frame != NULL); | 219 ASSERT(caller_frame != NULL); |
227 return caller_frame->GetTokenPos(); | 220 return caller_frame->GetTokenPos(); |
228 } | 221 } |
229 | 222 |
230 | |
231 // Allocate a new object. | 223 // Allocate a new object. |
232 // Arg0: class of the object that needs to be allocated. | 224 // Arg0: class of the object that needs to be allocated. |
233 // Arg1: type arguments of the object that needs to be allocated. | 225 // Arg1: type arguments of the object that needs to be allocated. |
234 // Return value: newly allocated object. | 226 // Return value: newly allocated object. |
235 DEFINE_RUNTIME_ENTRY(AllocateObject, 2) { | 227 DEFINE_RUNTIME_ENTRY(AllocateObject, 2) { |
236 const Class& cls = Class::CheckedHandle(arguments.ArgAt(0)); | 228 const Class& cls = Class::CheckedHandle(arguments.ArgAt(0)); |
237 | 229 |
238 #ifdef DEBUG | 230 #ifdef DEBUG |
239 if (FLAG_gc_at_instance_allocation != NULL) { | 231 if (FLAG_gc_at_instance_allocation != NULL) { |
240 const String& name = String::Handle(cls.Name()); | 232 const String& name = String::Handle(cls.Name()); |
(...skipping 17 matching lines...) Expand all Loading... |
258 TypeArguments::CheckedHandle(arguments.ArgAt(1)); | 250 TypeArguments::CheckedHandle(arguments.ArgAt(1)); |
259 // Unless null (for a raw type), the type argument vector may be longer than | 251 // Unless null (for a raw type), the type argument vector may be longer than |
260 // necessary due to a type optimization reusing the type argument vector of | 252 // necessary due to a type optimization reusing the type argument vector of |
261 // the instantiator. | 253 // the instantiator. |
262 ASSERT(type_arguments.IsNull() || | 254 ASSERT(type_arguments.IsNull() || |
263 (type_arguments.IsInstantiated() && | 255 (type_arguments.IsInstantiated() && |
264 (type_arguments.Length() >= cls.NumTypeArguments()))); | 256 (type_arguments.Length() >= cls.NumTypeArguments()))); |
265 instance.SetTypeArguments(type_arguments); | 257 instance.SetTypeArguments(type_arguments); |
266 } | 258 } |
267 | 259 |
268 | |
269 // Instantiate type. | 260 // Instantiate type. |
270 // Arg0: uninstantiated type. | 261 // Arg0: uninstantiated type. |
271 // Arg1: instantiator type arguments. | 262 // Arg1: instantiator type arguments. |
272 // Arg2: function type arguments. | 263 // Arg2: function type arguments. |
273 // Return value: instantiated type. | 264 // Return value: instantiated type. |
274 DEFINE_RUNTIME_ENTRY(InstantiateType, 3) { | 265 DEFINE_RUNTIME_ENTRY(InstantiateType, 3) { |
275 AbstractType& type = AbstractType::CheckedHandle(zone, arguments.ArgAt(0)); | 266 AbstractType& type = AbstractType::CheckedHandle(zone, arguments.ArgAt(0)); |
276 const TypeArguments& instantiator_type_arguments = | 267 const TypeArguments& instantiator_type_arguments = |
277 TypeArguments::CheckedHandle(zone, arguments.ArgAt(1)); | 268 TypeArguments::CheckedHandle(zone, arguments.ArgAt(1)); |
278 const TypeArguments& function_type_arguments = | 269 const TypeArguments& function_type_arguments = |
(...skipping 19 matching lines...) Expand all Loading... |
298 } | 289 } |
299 if (type.IsTypeRef()) { | 290 if (type.IsTypeRef()) { |
300 type = TypeRef::Cast(type).type(); | 291 type = TypeRef::Cast(type).type(); |
301 ASSERT(!type.IsTypeRef()); | 292 ASSERT(!type.IsTypeRef()); |
302 ASSERT(type.IsCanonical()); | 293 ASSERT(type.IsCanonical()); |
303 } | 294 } |
304 ASSERT(!type.IsNull() && type.IsInstantiated()); | 295 ASSERT(!type.IsNull() && type.IsInstantiated()); |
305 arguments.SetReturn(type); | 296 arguments.SetReturn(type); |
306 } | 297 } |
307 | 298 |
308 | |
309 // Instantiate type arguments. | 299 // Instantiate type arguments. |
310 // Arg0: uninstantiated type arguments. | 300 // Arg0: uninstantiated type arguments. |
311 // Arg1: instantiator type arguments. | 301 // Arg1: instantiator type arguments. |
312 // Arg2: function type arguments. | 302 // Arg2: function type arguments. |
313 // Return value: instantiated type arguments. | 303 // Return value: instantiated type arguments. |
314 DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 3) { | 304 DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 3) { |
315 TypeArguments& type_arguments = | 305 TypeArguments& type_arguments = |
316 TypeArguments::CheckedHandle(zone, arguments.ArgAt(0)); | 306 TypeArguments::CheckedHandle(zone, arguments.ArgAt(0)); |
317 const TypeArguments& instantiator_type_arguments = | 307 const TypeArguments& instantiator_type_arguments = |
318 TypeArguments::CheckedHandle(zone, arguments.ArgAt(1)); | 308 TypeArguments::CheckedHandle(zone, arguments.ArgAt(1)); |
(...skipping 22 matching lines...) Expand all Loading... |
341 UNREACHABLE(); | 331 UNREACHABLE(); |
342 } | 332 } |
343 } else { | 333 } else { |
344 type_arguments = type_arguments.InstantiateAndCanonicalizeFrom( | 334 type_arguments = type_arguments.InstantiateAndCanonicalizeFrom( |
345 instantiator_type_arguments, function_type_arguments, NULL); | 335 instantiator_type_arguments, function_type_arguments, NULL); |
346 } | 336 } |
347 ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated()); | 337 ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated()); |
348 arguments.SetReturn(type_arguments); | 338 arguments.SetReturn(type_arguments); |
349 } | 339 } |
350 | 340 |
351 | |
352 // Allocate a new context large enough to hold the given number of variables. | 341 // Allocate a new context large enough to hold the given number of variables. |
353 // Arg0: number of variables. | 342 // Arg0: number of variables. |
354 // Return value: newly allocated context. | 343 // Return value: newly allocated context. |
355 DEFINE_RUNTIME_ENTRY(AllocateContext, 1) { | 344 DEFINE_RUNTIME_ENTRY(AllocateContext, 1) { |
356 const Smi& num_variables = Smi::CheckedHandle(zone, arguments.ArgAt(0)); | 345 const Smi& num_variables = Smi::CheckedHandle(zone, arguments.ArgAt(0)); |
357 arguments.SetReturn(Context::Handle(Context::New(num_variables.Value()))); | 346 arguments.SetReturn(Context::Handle(Context::New(num_variables.Value()))); |
358 } | 347 } |
359 | 348 |
360 | |
361 // Make a copy of the given context, including the values of the captured | 349 // Make a copy of the given context, including the values of the captured |
362 // variables. | 350 // variables. |
363 // Arg0: the context to be cloned. | 351 // Arg0: the context to be cloned. |
364 // Return value: newly allocated context. | 352 // Return value: newly allocated context. |
365 DEFINE_RUNTIME_ENTRY(CloneContext, 1) { | 353 DEFINE_RUNTIME_ENTRY(CloneContext, 1) { |
366 const Context& ctx = Context::CheckedHandle(zone, arguments.ArgAt(0)); | 354 const Context& ctx = Context::CheckedHandle(zone, arguments.ArgAt(0)); |
367 Context& cloned_ctx = | 355 Context& cloned_ctx = |
368 Context::Handle(zone, Context::New(ctx.num_variables())); | 356 Context::Handle(zone, Context::New(ctx.num_variables())); |
369 cloned_ctx.set_parent(Context::Handle(ctx.parent())); | 357 cloned_ctx.set_parent(Context::Handle(ctx.parent())); |
370 Object& inst = Object::Handle(zone); | 358 Object& inst = Object::Handle(zone); |
371 for (int i = 0; i < ctx.num_variables(); i++) { | 359 for (int i = 0; i < ctx.num_variables(); i++) { |
372 inst = ctx.At(i); | 360 inst = ctx.At(i); |
373 cloned_ctx.SetAt(i, inst); | 361 cloned_ctx.SetAt(i, inst); |
374 } | 362 } |
375 arguments.SetReturn(cloned_ctx); | 363 arguments.SetReturn(cloned_ctx); |
376 } | 364 } |
377 | 365 |
378 | |
379 // Helper routine for tracing a type check. | 366 // Helper routine for tracing a type check. |
380 static void PrintTypeCheck(const char* message, | 367 static void PrintTypeCheck(const char* message, |
381 const Instance& instance, | 368 const Instance& instance, |
382 const AbstractType& type, | 369 const AbstractType& type, |
383 const TypeArguments& instantiator_type_arguments, | 370 const TypeArguments& instantiator_type_arguments, |
384 const TypeArguments& function_type_arguments, | 371 const TypeArguments& function_type_arguments, |
385 const Bool& result) { | 372 const Bool& result) { |
386 DartFrameIterator iterator(Thread::Current(), | 373 DartFrameIterator iterator(Thread::Current(), |
387 StackFrameIterator::kNoCrossThreadIteration); | 374 StackFrameIterator::kNoCrossThreadIteration); |
388 StackFrame* caller_frame = iterator.NextFrame(); | 375 StackFrame* caller_frame = iterator.NextFrame(); |
(...skipping 24 matching lines...) Expand all Loading... |
413 String::Handle(type.Name()).ToCString(), caller_frame->pc()); | 400 String::Handle(type.Name()).ToCString(), caller_frame->pc()); |
414 if (!bound_error.IsNull()) { | 401 if (!bound_error.IsNull()) { |
415 OS::Print(" bound error: %s\n", bound_error.ToErrorCString()); | 402 OS::Print(" bound error: %s\n", bound_error.ToErrorCString()); |
416 } | 403 } |
417 } | 404 } |
418 const Function& function = | 405 const Function& function = |
419 Function::Handle(caller_frame->LookupDartFunction()); | 406 Function::Handle(caller_frame->LookupDartFunction()); |
420 OS::PrintErr(" -> Function %s\n", function.ToFullyQualifiedCString()); | 407 OS::PrintErr(" -> Function %s\n", function.ToFullyQualifiedCString()); |
421 } | 408 } |
422 | 409 |
423 | |
424 // This updates the type test cache, an array containing 5-value elements | 410 // This updates the type test cache, an array containing 5-value elements |
425 // (instance class (or function if the instance is a closure), instance type | 411 // (instance class (or function if the instance is a closure), instance type |
426 // arguments, instantiator type arguments, function type arguments, | 412 // arguments, instantiator type arguments, function type arguments, |
427 // and test_result). It can be applied to classes with type arguments in which | 413 // and test_result). It can be applied to classes with type arguments in which |
428 // case it contains just the result of the class subtype test, not including the | 414 // case it contains just the result of the class subtype test, not including the |
429 // evaluation of type arguments. | 415 // evaluation of type arguments. |
430 // This operation is currently very slow (lookup of code is not efficient yet). | 416 // This operation is currently very slow (lookup of code is not efficient yet). |
431 static void UpdateTypeTestCache( | 417 static void UpdateTypeTestCache( |
432 const Instance& instance, | 418 const Instance& instance, |
433 const AbstractType& type, | 419 const AbstractType& type, |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
563 test_type.type_class(), | 549 test_type.type_class(), |
564 String::Handle(Class::Handle(test_type.type_class()).Name()) | 550 String::Handle(Class::Handle(test_type.type_class()).Name()) |
565 .ToCString(), | 551 .ToCString(), |
566 Class::Handle(test_type.type_class()).id(), | 552 Class::Handle(test_type.type_class()).id(), |
567 instantiator_type_arguments.raw(), | 553 instantiator_type_arguments.raw(), |
568 instantiator_type_arguments.ToCString(), function_type_arguments.raw(), | 554 instantiator_type_arguments.ToCString(), function_type_arguments.raw(), |
569 function_type_arguments.ToCString()); | 555 function_type_arguments.ToCString()); |
570 } | 556 } |
571 } | 557 } |
572 | 558 |
573 | |
574 // Check that the given instance is an instance of the given type. | 559 // Check that the given instance is an instance of the given type. |
575 // Tested instance may not be null, because the null test is inlined. | 560 // Tested instance may not be null, because the null test is inlined. |
576 // Arg0: instance being checked. | 561 // Arg0: instance being checked. |
577 // Arg1: type. | 562 // Arg1: type. |
578 // Arg2: type arguments of the instantiator of the type. | 563 // Arg2: type arguments of the instantiator of the type. |
579 // Arg3: type arguments of the function of the type. | 564 // Arg3: type arguments of the function of the type. |
580 // Arg4: SubtypeTestCache. | 565 // Arg4: SubtypeTestCache. |
581 // Return value: true or false, or may throw a type error in checked mode. | 566 // Return value: true or false, or may throw a type error in checked mode. |
582 DEFINE_RUNTIME_ENTRY(Instanceof, 5) { | 567 DEFINE_RUNTIME_ENTRY(Instanceof, 5) { |
583 const Instance& instance = Instance::CheckedHandle(zone, arguments.ArgAt(0)); | 568 const Instance& instance = Instance::CheckedHandle(zone, arguments.ArgAt(0)); |
(...skipping 25 matching lines...) Expand all Loading... |
609 Exceptions::CreateAndThrowTypeError(location, AbstractType::Handle(zone), | 594 Exceptions::CreateAndThrowTypeError(location, AbstractType::Handle(zone), |
610 AbstractType::Handle(zone), | 595 AbstractType::Handle(zone), |
611 Symbols::Empty(), bound_error_message); | 596 Symbols::Empty(), bound_error_message); |
612 UNREACHABLE(); | 597 UNREACHABLE(); |
613 } | 598 } |
614 UpdateTypeTestCache(instance, type, instantiator_type_arguments, | 599 UpdateTypeTestCache(instance, type, instantiator_type_arguments, |
615 function_type_arguments, result, cache); | 600 function_type_arguments, result, cache); |
616 arguments.SetReturn(result); | 601 arguments.SetReturn(result); |
617 } | 602 } |
618 | 603 |
619 | |
620 // Check that the type of the given instance is a subtype of the given type and | 604 // Check that the type of the given instance is a subtype of the given type and |
621 // can therefore be assigned. | 605 // can therefore be assigned. |
622 // Arg0: instance being assigned. | 606 // Arg0: instance being assigned. |
623 // Arg1: type being assigned to. | 607 // Arg1: type being assigned to. |
624 // Arg2: type arguments of the instantiator of the type being assigned to. | 608 // Arg2: type arguments of the instantiator of the type being assigned to. |
625 // Arg3: type arguments of the function of the type being assigned to. | 609 // Arg3: type arguments of the function of the type being assigned to. |
626 // Arg4: name of variable being assigned to. | 610 // Arg4: name of variable being assigned to. |
627 // Arg5: SubtypeTestCache. | 611 // Arg5: SubtypeTestCache. |
628 // Return value: instance if a subtype, otherwise throw a TypeError. | 612 // Return value: instance if a subtype, otherwise throw a TypeError. |
629 DEFINE_RUNTIME_ENTRY(TypeCheck, 6) { | 613 DEFINE_RUNTIME_ENTRY(TypeCheck, 6) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
672 } | 656 } |
673 Exceptions::CreateAndThrowTypeError(location, src_type, dst_type, dst_name, | 657 Exceptions::CreateAndThrowTypeError(location, src_type, dst_type, dst_name, |
674 bound_error_message); | 658 bound_error_message); |
675 UNREACHABLE(); | 659 UNREACHABLE(); |
676 } | 660 } |
677 UpdateTypeTestCache(src_instance, dst_type, instantiator_type_arguments, | 661 UpdateTypeTestCache(src_instance, dst_type, instantiator_type_arguments, |
678 function_type_arguments, Bool::True(), cache); | 662 function_type_arguments, Bool::True(), cache); |
679 arguments.SetReturn(src_instance); | 663 arguments.SetReturn(src_instance); |
680 } | 664 } |
681 | 665 |
682 | |
683 // Report that the type of the given object is not bool in conditional context. | 666 // Report that the type of the given object is not bool in conditional context. |
684 // Throw assertion error if the object is null. (cf. Boolean Conversion | 667 // Throw assertion error if the object is null. (cf. Boolean Conversion |
685 // in language Spec.) | 668 // in language Spec.) |
686 // Arg0: bad object. | 669 // Arg0: bad object. |
687 // Return value: none, throws TypeError or AssertionError. | 670 // Return value: none, throws TypeError or AssertionError. |
688 DEFINE_RUNTIME_ENTRY(NonBoolTypeError, 1) { | 671 DEFINE_RUNTIME_ENTRY(NonBoolTypeError, 1) { |
689 const TokenPosition location = GetCallerLocation(); | 672 const TokenPosition location = GetCallerLocation(); |
690 const Instance& src_instance = | 673 const Instance& src_instance = |
691 Instance::CheckedHandle(zone, arguments.ArgAt(0)); | 674 Instance::CheckedHandle(zone, arguments.ArgAt(0)); |
692 | 675 |
(...skipping 19 matching lines...) Expand all Loading... |
712 const Type& bool_interface = Type::Handle(Type::BoolType()); | 695 const Type& bool_interface = Type::Handle(Type::BoolType()); |
713 const AbstractType& src_type = | 696 const AbstractType& src_type = |
714 AbstractType::Handle(zone, src_instance.GetType(Heap::kNew)); | 697 AbstractType::Handle(zone, src_instance.GetType(Heap::kNew)); |
715 const String& no_bound_error = String::Handle(zone); | 698 const String& no_bound_error = String::Handle(zone); |
716 Exceptions::CreateAndThrowTypeError(location, src_type, bool_interface, | 699 Exceptions::CreateAndThrowTypeError(location, src_type, bool_interface, |
717 Symbols::BooleanExpression(), | 700 Symbols::BooleanExpression(), |
718 no_bound_error); | 701 no_bound_error); |
719 UNREACHABLE(); | 702 UNREACHABLE(); |
720 } | 703 } |
721 | 704 |
722 | |
723 // Report that the type of the type check is malformed or malbounded. | 705 // Report that the type of the type check is malformed or malbounded. |
724 // Arg0: src value. | 706 // Arg0: src value. |
725 // Arg1: name of destination being assigned to. | 707 // Arg1: name of destination being assigned to. |
726 // Arg2: type of destination being assigned to. | 708 // Arg2: type of destination being assigned to. |
727 // Return value: none, throws an exception. | 709 // Return value: none, throws an exception. |
728 DEFINE_RUNTIME_ENTRY(BadTypeError, 3) { | 710 DEFINE_RUNTIME_ENTRY(BadTypeError, 3) { |
729 const TokenPosition location = GetCallerLocation(); | 711 const TokenPosition location = GetCallerLocation(); |
730 const Instance& src_value = Instance::CheckedHandle(zone, arguments.ArgAt(0)); | 712 const Instance& src_value = Instance::CheckedHandle(zone, arguments.ArgAt(0)); |
731 const String& dst_name = String::CheckedHandle(zone, arguments.ArgAt(1)); | 713 const String& dst_name = String::CheckedHandle(zone, arguments.ArgAt(1)); |
732 const AbstractType& dst_type = | 714 const AbstractType& dst_type = |
733 AbstractType::CheckedHandle(zone, arguments.ArgAt(2)); | 715 AbstractType::CheckedHandle(zone, arguments.ArgAt(2)); |
734 const AbstractType& src_type = | 716 const AbstractType& src_type = |
735 AbstractType::Handle(zone, src_value.GetType(Heap::kNew)); | 717 AbstractType::Handle(zone, src_value.GetType(Heap::kNew)); |
736 Exceptions::CreateAndThrowTypeError(location, src_type, dst_type, dst_name, | 718 Exceptions::CreateAndThrowTypeError(location, src_type, dst_type, dst_name, |
737 String::Handle(zone)); | 719 String::Handle(zone)); |
738 UNREACHABLE(); | 720 UNREACHABLE(); |
739 } | 721 } |
740 | 722 |
741 | |
742 DEFINE_RUNTIME_ENTRY(Throw, 1) { | 723 DEFINE_RUNTIME_ENTRY(Throw, 1) { |
743 const Instance& exception = Instance::CheckedHandle(zone, arguments.ArgAt(0)); | 724 const Instance& exception = Instance::CheckedHandle(zone, arguments.ArgAt(0)); |
744 Exceptions::Throw(thread, exception); | 725 Exceptions::Throw(thread, exception); |
745 } | 726 } |
746 | 727 |
747 | |
748 DEFINE_RUNTIME_ENTRY(ReThrow, 2) { | 728 DEFINE_RUNTIME_ENTRY(ReThrow, 2) { |
749 const Instance& exception = Instance::CheckedHandle(zone, arguments.ArgAt(0)); | 729 const Instance& exception = Instance::CheckedHandle(zone, arguments.ArgAt(0)); |
750 const Instance& stacktrace = | 730 const Instance& stacktrace = |
751 Instance::CheckedHandle(zone, arguments.ArgAt(1)); | 731 Instance::CheckedHandle(zone, arguments.ArgAt(1)); |
752 Exceptions::ReThrow(thread, exception, stacktrace); | 732 Exceptions::ReThrow(thread, exception, stacktrace); |
753 } | 733 } |
754 | 734 |
755 | |
756 // Patches static call in optimized code with the target's entry point. | 735 // Patches static call in optimized code with the target's entry point. |
757 // Compiles target if necessary. | 736 // Compiles target if necessary. |
758 DEFINE_RUNTIME_ENTRY(PatchStaticCall, 0) { | 737 DEFINE_RUNTIME_ENTRY(PatchStaticCall, 0) { |
759 DartFrameIterator iterator(thread, | 738 DartFrameIterator iterator(thread, |
760 StackFrameIterator::kNoCrossThreadIteration); | 739 StackFrameIterator::kNoCrossThreadIteration); |
761 StackFrame* caller_frame = iterator.NextFrame(); | 740 StackFrame* caller_frame = iterator.NextFrame(); |
762 ASSERT(caller_frame != NULL); | 741 ASSERT(caller_frame != NULL); |
763 const Code& caller_code = Code::Handle(zone, caller_frame->LookupDartCode()); | 742 const Code& caller_code = Code::Handle(zone, caller_frame->LookupDartCode()); |
764 ASSERT(!caller_code.IsNull()); | 743 ASSERT(!caller_code.IsNull()); |
765 ASSERT(caller_code.is_optimized()); | 744 ASSERT(caller_code.is_optimized()); |
(...skipping 10 matching lines...) Expand all Loading... |
776 THR_Print("PatchStaticCall: patching caller pc %#" Px | 755 THR_Print("PatchStaticCall: patching caller pc %#" Px |
777 "" | 756 "" |
778 " to '%s' new entry point %#" Px " (%s)\n", | 757 " to '%s' new entry point %#" Px " (%s)\n", |
779 caller_frame->pc(), target_function.ToFullyQualifiedCString(), | 758 caller_frame->pc(), target_function.ToFullyQualifiedCString(), |
780 target_code.UncheckedEntryPoint(), | 759 target_code.UncheckedEntryPoint(), |
781 target_code.is_optimized() ? "optimized" : "unoptimized"); | 760 target_code.is_optimized() ? "optimized" : "unoptimized"); |
782 } | 761 } |
783 arguments.SetReturn(target_code); | 762 arguments.SetReturn(target_code); |
784 } | 763 } |
785 | 764 |
786 | |
787 // Result of an invoke may be an unhandled exception, in which case we | 765 // Result of an invoke may be an unhandled exception, in which case we |
788 // rethrow it. | 766 // rethrow it. |
789 static void CheckResultError(const Object& result) { | 767 static void CheckResultError(const Object& result) { |
790 if (result.IsError()) { | 768 if (result.IsError()) { |
791 Exceptions::PropagateError(Error::Cast(result)); | 769 Exceptions::PropagateError(Error::Cast(result)); |
792 } | 770 } |
793 } | 771 } |
794 | 772 |
795 | |
796 #if !defined(TARGET_ARCH_DBC) | 773 #if !defined(TARGET_ARCH_DBC) |
797 // Gets called from debug stub when code reaches a breakpoint | 774 // Gets called from debug stub when code reaches a breakpoint |
798 // set on a runtime stub call. | 775 // set on a runtime stub call. |
799 DEFINE_RUNTIME_ENTRY(BreakpointRuntimeHandler, 0) { | 776 DEFINE_RUNTIME_ENTRY(BreakpointRuntimeHandler, 0) { |
800 if (!FLAG_support_debugger) { | 777 if (!FLAG_support_debugger) { |
801 UNREACHABLE(); | 778 UNREACHABLE(); |
802 return; | 779 return; |
803 } | 780 } |
804 DartFrameIterator iterator(thread, | 781 DartFrameIterator iterator(thread, |
805 StackFrameIterator::kNoCrossThreadIteration); | 782 StackFrameIterator::kNoCrossThreadIteration); |
(...skipping 17 matching lines...) Expand all Loading... |
823 return; | 800 return; |
824 } | 801 } |
825 const Error& error = Error::Handle(isolate->debugger()->PauseBreakpoint()); | 802 const Error& error = Error::Handle(isolate->debugger()->PauseBreakpoint()); |
826 if (!error.IsNull()) { | 803 if (!error.IsNull()) { |
827 Exceptions::PropagateError(error); | 804 Exceptions::PropagateError(error); |
828 UNREACHABLE(); | 805 UNREACHABLE(); |
829 } | 806 } |
830 } | 807 } |
831 #endif // !defined(TARGET_ARCH_DBC) | 808 #endif // !defined(TARGET_ARCH_DBC) |
832 | 809 |
833 | |
834 DEFINE_RUNTIME_ENTRY(SingleStepHandler, 0) { | 810 DEFINE_RUNTIME_ENTRY(SingleStepHandler, 0) { |
835 if (!FLAG_support_debugger) { | 811 if (!FLAG_support_debugger) { |
836 UNREACHABLE(); | 812 UNREACHABLE(); |
837 return; | 813 return; |
838 } | 814 } |
839 const Error& error = | 815 const Error& error = |
840 Error::Handle(zone, isolate->debugger()->PauseStepping()); | 816 Error::Handle(zone, isolate->debugger()->PauseStepping()); |
841 if (!error.IsNull()) { | 817 if (!error.IsNull()) { |
842 Exceptions::PropagateError(error); | 818 Exceptions::PropagateError(error); |
843 UNREACHABLE(); | 819 UNREACHABLE(); |
844 } | 820 } |
845 } | 821 } |
846 | 822 |
847 | |
848 // An instance call of the form o.f(...) could not be resolved. Check if | 823 // An instance call of the form o.f(...) could not be resolved. Check if |
849 // there is a getter with the same name. If so, invoke it. If the value is | 824 // there is a getter with the same name. If so, invoke it. If the value is |
850 // a closure, invoke it with the given arguments. If the value is a | 825 // a closure, invoke it with the given arguments. If the value is a |
851 // non-closure, attempt to invoke "call" on it. | 826 // non-closure, attempt to invoke "call" on it. |
852 static bool ResolveCallThroughGetter(const Instance& receiver, | 827 static bool ResolveCallThroughGetter(const Instance& receiver, |
853 const Class& receiver_class, | 828 const Class& receiver_class, |
854 const String& target_name, | 829 const String& target_name, |
855 const Array& arguments_descriptor, | 830 const Array& arguments_descriptor, |
856 Function* result) { | 831 Function* result) { |
857 // 1. Check if there is a getter with the same name. | 832 // 1. Check if there is a getter with the same name. |
(...skipping 16 matching lines...) Expand all Loading... |
874 if (FLAG_trace_ic) { | 849 if (FLAG_trace_ic) { |
875 OS::PrintErr( | 850 OS::PrintErr( |
876 "InvokeField IC miss: adding <%s> id:%" Pd " -> <%s>\n", | 851 "InvokeField IC miss: adding <%s> id:%" Pd " -> <%s>\n", |
877 Class::Handle(receiver.clazz()).ToCString(), receiver.GetClassId(), | 852 Class::Handle(receiver.clazz()).ToCString(), receiver.GetClassId(), |
878 target_function.IsNull() ? "null" : target_function.ToCString()); | 853 target_function.IsNull() ? "null" : target_function.ToCString()); |
879 } | 854 } |
880 *result = target_function.raw(); | 855 *result = target_function.raw(); |
881 return true; | 856 return true; |
882 } | 857 } |
883 | 858 |
884 | |
885 // Handle other invocations (implicit closures, noSuchMethod). | 859 // Handle other invocations (implicit closures, noSuchMethod). |
886 RawFunction* InlineCacheMissHelper(const Instance& receiver, | 860 RawFunction* InlineCacheMissHelper(const Instance& receiver, |
887 const Array& args_descriptor, | 861 const Array& args_descriptor, |
888 const String& target_name) { | 862 const String& target_name) { |
889 const Class& receiver_class = Class::Handle(receiver.clazz()); | 863 const Class& receiver_class = Class::Handle(receiver.clazz()); |
890 | 864 |
891 Function& result = Function::Handle(); | 865 Function& result = Function::Handle(); |
892 if (!ResolveCallThroughGetter(receiver, receiver_class, target_name, | 866 if (!ResolveCallThroughGetter(receiver, receiver_class, target_name, |
893 args_descriptor, &result)) { | 867 args_descriptor, &result)) { |
894 ArgumentsDescriptor desc(args_descriptor); | 868 ArgumentsDescriptor desc(args_descriptor); |
895 const Function& target_function = | 869 const Function& target_function = |
896 Function::Handle(receiver_class.GetInvocationDispatcher( | 870 Function::Handle(receiver_class.GetInvocationDispatcher( |
897 target_name, args_descriptor, RawFunction::kNoSuchMethodDispatcher, | 871 target_name, args_descriptor, RawFunction::kNoSuchMethodDispatcher, |
898 FLAG_lazy_dispatchers)); | 872 FLAG_lazy_dispatchers)); |
899 if (FLAG_trace_ic) { | 873 if (FLAG_trace_ic) { |
900 OS::PrintErr( | 874 OS::PrintErr( |
901 "NoSuchMethod IC miss: adding <%s> id:%" Pd " -> <%s>\n", | 875 "NoSuchMethod IC miss: adding <%s> id:%" Pd " -> <%s>\n", |
902 Class::Handle(receiver.clazz()).ToCString(), receiver.GetClassId(), | 876 Class::Handle(receiver.clazz()).ToCString(), receiver.GetClassId(), |
903 target_function.IsNull() ? "null" : target_function.ToCString()); | 877 target_function.IsNull() ? "null" : target_function.ToCString()); |
904 } | 878 } |
905 result = target_function.raw(); | 879 result = target_function.raw(); |
906 } | 880 } |
907 // May be null if --no-lazy-dispatchers, in which case dispatch will be | 881 // May be null if --no-lazy-dispatchers, in which case dispatch will be |
908 // handled by InvokeNoSuchMethodDispatcher. | 882 // handled by InvokeNoSuchMethodDispatcher. |
909 ASSERT(!result.IsNull() || !FLAG_lazy_dispatchers); | 883 ASSERT(!result.IsNull() || !FLAG_lazy_dispatchers); |
910 return result.raw(); | 884 return result.raw(); |
911 } | 885 } |
912 | 886 |
913 | |
914 // Perform the subtype and return constant function based on the result. | 887 // Perform the subtype and return constant function based on the result. |
915 static RawFunction* ComputeTypeCheckTarget(const Instance& receiver, | 888 static RawFunction* ComputeTypeCheckTarget(const Instance& receiver, |
916 const AbstractType& type, | 889 const AbstractType& type, |
917 const ArgumentsDescriptor& desc) { | 890 const ArgumentsDescriptor& desc) { |
918 Error& error = Error::Handle(); | 891 Error& error = Error::Handle(); |
919 bool result = receiver.IsInstanceOf(type, Object::null_type_arguments(), | 892 bool result = receiver.IsInstanceOf(type, Object::null_type_arguments(), |
920 Object::null_type_arguments(), &error); | 893 Object::null_type_arguments(), &error); |
921 ASSERT(error.IsNull()); | 894 ASSERT(error.IsNull()); |
922 ObjectStore* store = Isolate::Current()->object_store(); | 895 ObjectStore* store = Isolate::Current()->object_store(); |
923 const Function& target = | 896 const Function& target = |
924 Function::Handle(result ? store->simple_instance_of_true_function() | 897 Function::Handle(result ? store->simple_instance_of_true_function() |
925 : store->simple_instance_of_false_function()); | 898 : store->simple_instance_of_false_function()); |
926 ASSERT(!target.IsNull()); | 899 ASSERT(!target.IsNull()); |
927 return target.raw(); | 900 return target.raw(); |
928 } | 901 } |
929 | 902 |
930 | |
931 static RawFunction* InlineCacheMissHandler( | 903 static RawFunction* InlineCacheMissHandler( |
932 const GrowableArray<const Instance*>& args, // Checked arguments only. | 904 const GrowableArray<const Instance*>& args, // Checked arguments only. |
933 const ICData& ic_data) { | 905 const ICData& ic_data) { |
934 const Instance& receiver = *args[0]; | 906 const Instance& receiver = *args[0]; |
935 ArgumentsDescriptor arguments_descriptor( | 907 ArgumentsDescriptor arguments_descriptor( |
936 Array::Handle(ic_data.arguments_descriptor())); | 908 Array::Handle(ic_data.arguments_descriptor())); |
937 String& function_name = String::Handle(ic_data.target_name()); | 909 String& function_name = String::Handle(ic_data.target_name()); |
938 ASSERT(function_name.IsSymbol()); | 910 ASSERT(function_name.IsSymbol()); |
939 | 911 |
940 Function& target_function = Function::Handle( | 912 Function& target_function = Function::Handle( |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
991 "' " | 963 "' " |
992 "adding <%s> id:%" Pd " -> <%s>\n", | 964 "adding <%s> id:%" Pd " -> <%s>\n", |
993 args.length(), caller_frame->pc(), | 965 args.length(), caller_frame->pc(), |
994 Class::Handle(receiver.clazz()).ToCString(), | 966 Class::Handle(receiver.clazz()).ToCString(), |
995 receiver.GetClassId(), target_function.ToCString()); | 967 receiver.GetClassId(), target_function.ToCString()); |
996 } | 968 } |
997 } | 969 } |
998 return target_function.raw(); | 970 return target_function.raw(); |
999 } | 971 } |
1000 | 972 |
1001 | |
1002 // Handles inline cache misses by updating the IC data array of the call site. | 973 // Handles inline cache misses by updating the IC data array of the call site. |
1003 // Arg0: Receiver object. | 974 // Arg0: Receiver object. |
1004 // Arg1: IC data object. | 975 // Arg1: IC data object. |
1005 // Returns: target function with compiled code or null. | 976 // Returns: target function with compiled code or null. |
1006 // Modifies the instance call to hold the updated IC data array. | 977 // Modifies the instance call to hold the updated IC data array. |
1007 DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerOneArg, 2) { | 978 DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerOneArg, 2) { |
1008 const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0)); | 979 const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0)); |
1009 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1)); | 980 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1)); |
1010 GrowableArray<const Instance*> args(1); | 981 GrowableArray<const Instance*> args(1); |
1011 args.Add(&receiver); | 982 args.Add(&receiver); |
1012 const Function& result = | 983 const Function& result = |
1013 Function::Handle(InlineCacheMissHandler(args, ic_data)); | 984 Function::Handle(InlineCacheMissHandler(args, ic_data)); |
1014 arguments.SetReturn(result); | 985 arguments.SetReturn(result); |
1015 } | 986 } |
1016 | 987 |
1017 | |
1018 // Handles inline cache misses by updating the IC data array of the call site. | 988 // Handles inline cache misses by updating the IC data array of the call site. |
1019 // Arg0: Receiver object. | 989 // Arg0: Receiver object. |
1020 // Arg1: Argument after receiver. | 990 // Arg1: Argument after receiver. |
1021 // Arg2: IC data object. | 991 // Arg2: IC data object. |
1022 // Returns: target function with compiled code or null. | 992 // Returns: target function with compiled code or null. |
1023 // Modifies the instance call to hold the updated IC data array. | 993 // Modifies the instance call to hold the updated IC data array. |
1024 DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerTwoArgs, 3) { | 994 DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerTwoArgs, 3) { |
1025 const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0)); | 995 const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0)); |
1026 const Instance& other = Instance::CheckedHandle(arguments.ArgAt(1)); | 996 const Instance& other = Instance::CheckedHandle(arguments.ArgAt(1)); |
1027 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(2)); | 997 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(2)); |
1028 GrowableArray<const Instance*> args(2); | 998 GrowableArray<const Instance*> args(2); |
1029 args.Add(&receiver); | 999 args.Add(&receiver); |
1030 args.Add(&other); | 1000 args.Add(&other); |
1031 const Function& result = | 1001 const Function& result = |
1032 Function::Handle(InlineCacheMissHandler(args, ic_data)); | 1002 Function::Handle(InlineCacheMissHandler(args, ic_data)); |
1033 arguments.SetReturn(result); | 1003 arguments.SetReturn(result); |
1034 } | 1004 } |
1035 | 1005 |
1036 | |
1037 // Handles a static call in unoptimized code that has one argument type not | 1006 // Handles a static call in unoptimized code that has one argument type not |
1038 // seen before. Compile the target if necessary and update the ICData. | 1007 // seen before. Compile the target if necessary and update the ICData. |
1039 // Arg0: argument. | 1008 // Arg0: argument. |
1040 // Arg1: IC data object. | 1009 // Arg1: IC data object. |
1041 DEFINE_RUNTIME_ENTRY(StaticCallMissHandlerOneArg, 2) { | 1010 DEFINE_RUNTIME_ENTRY(StaticCallMissHandlerOneArg, 2) { |
1042 const Instance& arg = Instance::CheckedHandle(arguments.ArgAt(0)); | 1011 const Instance& arg = Instance::CheckedHandle(arguments.ArgAt(0)); |
1043 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1)); | 1012 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1)); |
1044 // IC data for static call is prepopulated with the statically known target. | 1013 // IC data for static call is prepopulated with the statically known target. |
1045 ASSERT(ic_data.NumberOfChecksIs(1)); | 1014 ASSERT(ic_data.NumberOfChecksIs(1)); |
1046 const Function& target = Function::Handle(ic_data.GetTargetAt(0)); | 1015 const Function& target = Function::Handle(ic_data.GetTargetAt(0)); |
1047 target.EnsureHasCode(); | 1016 target.EnsureHasCode(); |
1048 ASSERT(!target.IsNull() && target.HasCode()); | 1017 ASSERT(!target.IsNull() && target.HasCode()); |
1049 ic_data.AddReceiverCheck(arg.GetClassId(), target, 1); | 1018 ic_data.AddReceiverCheck(arg.GetClassId(), target, 1); |
1050 if (FLAG_trace_ic) { | 1019 if (FLAG_trace_ic) { |
1051 DartFrameIterator iterator(thread, | 1020 DartFrameIterator iterator(thread, |
1052 StackFrameIterator::kNoCrossThreadIteration); | 1021 StackFrameIterator::kNoCrossThreadIteration); |
1053 StackFrame* caller_frame = iterator.NextFrame(); | 1022 StackFrame* caller_frame = iterator.NextFrame(); |
1054 ASSERT(caller_frame != NULL); | 1023 ASSERT(caller_frame != NULL); |
1055 OS::PrintErr("StaticCallMissHandler at %#" Px " target %s (%" Pd ")\n", | 1024 OS::PrintErr("StaticCallMissHandler at %#" Px " target %s (%" Pd ")\n", |
1056 caller_frame->pc(), target.ToCString(), arg.GetClassId()); | 1025 caller_frame->pc(), target.ToCString(), arg.GetClassId()); |
1057 } | 1026 } |
1058 arguments.SetReturn(target); | 1027 arguments.SetReturn(target); |
1059 } | 1028 } |
1060 | 1029 |
1061 | |
1062 // Handles a static call in unoptimized code that has two argument types not | 1030 // Handles a static call in unoptimized code that has two argument types not |
1063 // seen before. Compile the target if necessary and update the ICData. | 1031 // seen before. Compile the target if necessary and update the ICData. |
1064 // Arg0: argument 0. | 1032 // Arg0: argument 0. |
1065 // Arg1: argument 1. | 1033 // Arg1: argument 1. |
1066 // Arg2: IC data object. | 1034 // Arg2: IC data object. |
1067 DEFINE_RUNTIME_ENTRY(StaticCallMissHandlerTwoArgs, 3) { | 1035 DEFINE_RUNTIME_ENTRY(StaticCallMissHandlerTwoArgs, 3) { |
1068 const Instance& arg0 = Instance::CheckedHandle(arguments.ArgAt(0)); | 1036 const Instance& arg0 = Instance::CheckedHandle(arguments.ArgAt(0)); |
1069 const Instance& arg1 = Instance::CheckedHandle(arguments.ArgAt(1)); | 1037 const Instance& arg1 = Instance::CheckedHandle(arguments.ArgAt(1)); |
1070 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(2)); | 1038 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(2)); |
1071 // IC data for static call is prepopulated with the statically known target. | 1039 // IC data for static call is prepopulated with the statically known target. |
1072 ASSERT(!ic_data.NumberOfChecksIs(0)); | 1040 ASSERT(!ic_data.NumberOfChecksIs(0)); |
1073 const Function& target = Function::Handle(ic_data.GetTargetAt(0)); | 1041 const Function& target = Function::Handle(ic_data.GetTargetAt(0)); |
1074 target.EnsureHasCode(); | 1042 target.EnsureHasCode(); |
1075 GrowableArray<intptr_t> cids(2); | 1043 GrowableArray<intptr_t> cids(2); |
1076 cids.Add(arg0.GetClassId()); | 1044 cids.Add(arg0.GetClassId()); |
1077 cids.Add(arg1.GetClassId()); | 1045 cids.Add(arg1.GetClassId()); |
1078 ic_data.AddCheck(cids, target); | 1046 ic_data.AddCheck(cids, target); |
1079 if (FLAG_trace_ic) { | 1047 if (FLAG_trace_ic) { |
1080 DartFrameIterator iterator(thread, | 1048 DartFrameIterator iterator(thread, |
1081 StackFrameIterator::kNoCrossThreadIteration); | 1049 StackFrameIterator::kNoCrossThreadIteration); |
1082 StackFrame* caller_frame = iterator.NextFrame(); | 1050 StackFrame* caller_frame = iterator.NextFrame(); |
1083 ASSERT(caller_frame != NULL); | 1051 ASSERT(caller_frame != NULL); |
1084 OS::PrintErr("StaticCallMissHandler at %#" Px " target %s (%" Pd ", %" Pd | 1052 OS::PrintErr("StaticCallMissHandler at %#" Px " target %s (%" Pd ", %" Pd |
1085 ")\n", | 1053 ")\n", |
1086 caller_frame->pc(), target.ToCString(), cids[0], cids[1]); | 1054 caller_frame->pc(), target.ToCString(), cids[0], cids[1]); |
1087 } | 1055 } |
1088 arguments.SetReturn(target); | 1056 arguments.SetReturn(target); |
1089 } | 1057 } |
1090 | 1058 |
1091 | |
1092 #if !defined(TARGET_ARCH_DBC) | 1059 #if !defined(TARGET_ARCH_DBC) |
1093 static bool IsSingleTarget(Isolate* isolate, | 1060 static bool IsSingleTarget(Isolate* isolate, |
1094 Zone* zone, | 1061 Zone* zone, |
1095 intptr_t lower_cid, | 1062 intptr_t lower_cid, |
1096 intptr_t upper_cid, | 1063 intptr_t upper_cid, |
1097 const Function& target, | 1064 const Function& target, |
1098 const String& name) { | 1065 const String& name) { |
1099 Class& cls = Class::Handle(zone); | 1066 Class& cls = Class::Handle(zone); |
1100 ClassTable* table = isolate->class_table(); | 1067 ClassTable* table = isolate->class_table(); |
1101 Function& other_target = Function::Handle(zone); | 1068 Function& other_target = Function::Handle(zone); |
1102 for (intptr_t cid = lower_cid; cid <= upper_cid; cid++) { | 1069 for (intptr_t cid = lower_cid; cid <= upper_cid; cid++) { |
1103 if (!table->HasValidClassAt(cid)) continue; | 1070 if (!table->HasValidClassAt(cid)) continue; |
1104 cls = table->At(cid); | 1071 cls = table->At(cid); |
1105 if (cls.is_abstract()) continue; | 1072 if (cls.is_abstract()) continue; |
1106 if (!cls.is_allocated()) continue; | 1073 if (!cls.is_allocated()) continue; |
1107 other_target = | 1074 other_target = |
1108 Resolver::ResolveDynamicAnyArgs(zone, cls, name, false /* allow_add */); | 1075 Resolver::ResolveDynamicAnyArgs(zone, cls, name, false /* allow_add */); |
1109 if (other_target.raw() != target.raw()) { | 1076 if (other_target.raw() != target.raw()) { |
1110 return false; | 1077 return false; |
1111 } | 1078 } |
1112 } | 1079 } |
1113 return true; | 1080 return true; |
1114 } | 1081 } |
1115 #endif | 1082 #endif |
1116 | 1083 |
1117 | |
1118 // Handle a miss of a single target cache. | 1084 // Handle a miss of a single target cache. |
1119 // Arg0: Receiver. | 1085 // Arg0: Receiver. |
1120 // Returns: the ICData used to continue with a polymorphic call. | 1086 // Returns: the ICData used to continue with a polymorphic call. |
1121 DEFINE_RUNTIME_ENTRY(SingleTargetMiss, 1) { | 1087 DEFINE_RUNTIME_ENTRY(SingleTargetMiss, 1) { |
1122 #if defined(TARGET_ARCH_DBC) | 1088 #if defined(TARGET_ARCH_DBC) |
1123 // DBC does not use switchable calls. | 1089 // DBC does not use switchable calls. |
1124 UNREACHABLE(); | 1090 UNREACHABLE(); |
1125 #else | 1091 #else |
1126 const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0)); | 1092 const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0)); |
1127 | 1093 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1198 ASSERT(!Isolate::Current()->compilation_allowed()); | 1164 ASSERT(!Isolate::Current()->compilation_allowed()); |
1199 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code, ic_data, | 1165 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code, ic_data, |
1200 stub); | 1166 stub); |
1201 | 1167 |
1202 // Return the ICData. The single target stub will jump to continue in the | 1168 // Return the ICData. The single target stub will jump to continue in the |
1203 // IC call stub. | 1169 // IC call stub. |
1204 arguments.SetReturn(ic_data); | 1170 arguments.SetReturn(ic_data); |
1205 #endif | 1171 #endif |
1206 } | 1172 } |
1207 | 1173 |
1208 | |
1209 DEFINE_RUNTIME_ENTRY(UnlinkedCall, 2) { | 1174 DEFINE_RUNTIME_ENTRY(UnlinkedCall, 2) { |
1210 #if defined(TARGET_ARCH_DBC) | 1175 #if defined(TARGET_ARCH_DBC) |
1211 // DBC does not use switchable calls. | 1176 // DBC does not use switchable calls. |
1212 UNREACHABLE(); | 1177 UNREACHABLE(); |
1213 #else | 1178 #else |
1214 const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0)); | 1179 const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0)); |
1215 const UnlinkedCall& unlinked = | 1180 const UnlinkedCall& unlinked = |
1216 UnlinkedCall::CheckedHandle(zone, arguments.ArgAt(1)); | 1181 UnlinkedCall::CheckedHandle(zone, arguments.ArgAt(1)); |
1217 | 1182 |
1218 DartFrameIterator iterator(thread, | 1183 DartFrameIterator iterator(thread, |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1265 ASSERT(!Isolate::Current()->compilation_allowed()); | 1230 ASSERT(!Isolate::Current()->compilation_allowed()); |
1266 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code, ic_data, | 1231 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code, ic_data, |
1267 stub); | 1232 stub); |
1268 | 1233 |
1269 // Return the ICData. The miss stub will jump to continue in the IC lookup | 1234 // Return the ICData. The miss stub will jump to continue in the IC lookup |
1270 // stub. | 1235 // stub. |
1271 arguments.SetReturn(ic_data); | 1236 arguments.SetReturn(ic_data); |
1272 #endif // !DBC | 1237 #endif // !DBC |
1273 } | 1238 } |
1274 | 1239 |
1275 | |
1276 // Handle a miss of a megamorphic cache. | 1240 // Handle a miss of a megamorphic cache. |
1277 // Arg0: Receiver. | 1241 // Arg0: Receiver. |
1278 // Returns: the ICData used to continue with a polymorphic call. | 1242 // Returns: the ICData used to continue with a polymorphic call. |
1279 DEFINE_RUNTIME_ENTRY(MonomorphicMiss, 1) { | 1243 DEFINE_RUNTIME_ENTRY(MonomorphicMiss, 1) { |
1280 #if defined(TARGET_ARCH_DBC) | 1244 #if defined(TARGET_ARCH_DBC) |
1281 // DBC does not use switchable calls. | 1245 // DBC does not use switchable calls. |
1282 UNREACHABLE(); | 1246 UNREACHABLE(); |
1283 #else | 1247 #else |
1284 const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0)); | 1248 const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0)); |
1285 | 1249 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1364 ASSERT(!Isolate::Current()->compilation_allowed()); | 1328 ASSERT(!Isolate::Current()->compilation_allowed()); |
1365 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code, ic_data, | 1329 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code, ic_data, |
1366 stub); | 1330 stub); |
1367 | 1331 |
1368 // Return the ICData. The miss stub will jump to continue in the IC lookup | 1332 // Return the ICData. The miss stub will jump to continue in the IC lookup |
1369 // stub. | 1333 // stub. |
1370 arguments.SetReturn(ic_data); | 1334 arguments.SetReturn(ic_data); |
1371 #endif // !defined(TARGET_ARCH_DBC) | 1335 #endif // !defined(TARGET_ARCH_DBC) |
1372 } | 1336 } |
1373 | 1337 |
1374 | |
1375 // Handle a miss of a megamorphic cache. | 1338 // Handle a miss of a megamorphic cache. |
1376 // Arg0: Receiver. | 1339 // Arg0: Receiver. |
1377 // Arg1: ICData or MegamorphicCache. | 1340 // Arg1: ICData or MegamorphicCache. |
1378 // Arg2: Arguments descriptor array. | 1341 // Arg2: Arguments descriptor array. |
1379 // Returns: target function to call. | 1342 // Returns: target function to call. |
1380 DEFINE_RUNTIME_ENTRY(MegamorphicCacheMissHandler, 3) { | 1343 DEFINE_RUNTIME_ENTRY(MegamorphicCacheMissHandler, 3) { |
1381 #if defined(TARGET_ARCH_DBC) | 1344 #if defined(TARGET_ARCH_DBC) |
1382 // DBC does not use megamorphic calls right now. | 1345 // DBC does not use megamorphic calls right now. |
1383 UNREACHABLE(); | 1346 UNREACHABLE(); |
1384 #else | 1347 #else |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1466 const MegamorphicCache& cache = MegamorphicCache::Cast(ic_data_or_cache); | 1429 const MegamorphicCache& cache = MegamorphicCache::Cast(ic_data_or_cache); |
1467 // Insert function found into cache and return it. | 1430 // Insert function found into cache and return it. |
1468 cache.EnsureCapacity(); | 1431 cache.EnsureCapacity(); |
1469 const Smi& class_id = Smi::Handle(zone, Smi::New(cls.id())); | 1432 const Smi& class_id = Smi::Handle(zone, Smi::New(cls.id())); |
1470 cache.Insert(class_id, target_function); | 1433 cache.Insert(class_id, target_function); |
1471 } | 1434 } |
1472 arguments.SetReturn(target_function); | 1435 arguments.SetReturn(target_function); |
1473 #endif // !defined(TARGET_ARCH_DBC) | 1436 #endif // !defined(TARGET_ARCH_DBC) |
1474 } | 1437 } |
1475 | 1438 |
1476 | |
1477 // Invoke appropriate noSuchMethod or closure from getter. | 1439 // Invoke appropriate noSuchMethod or closure from getter. |
1478 // Arg0: receiver | 1440 // Arg0: receiver |
1479 // Arg1: ICData or MegamorphicCache | 1441 // Arg1: ICData or MegamorphicCache |
1480 // Arg2: arguments descriptor array | 1442 // Arg2: arguments descriptor array |
1481 // Arg3: arguments array | 1443 // Arg3: arguments array |
1482 DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodDispatcher, 4) { | 1444 DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodDispatcher, 4) { |
1483 ASSERT(!FLAG_lazy_dispatchers); | 1445 ASSERT(!FLAG_lazy_dispatchers); |
1484 const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0)); | 1446 const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0)); |
1485 const Object& ic_data_or_cache = Object::Handle(zone, arguments.ArgAt(1)); | 1447 const Object& ic_data_or_cache = Object::Handle(zone, arguments.ArgAt(1)); |
1486 const Array& orig_arguments_desc = | 1448 const Array& orig_arguments_desc = |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1610 cls = cls.SuperClass(); | 1572 cls = cls.SuperClass(); |
1611 } | 1573 } |
1612 } | 1574 } |
1613 | 1575 |
1614 NO_SUCH_METHOD(); | 1576 NO_SUCH_METHOD(); |
1615 | 1577 |
1616 #undef NO_SUCH_METHOD | 1578 #undef NO_SUCH_METHOD |
1617 #undef CLOSURIZE | 1579 #undef CLOSURIZE |
1618 } | 1580 } |
1619 | 1581 |
1620 | |
1621 // Invoke appropriate noSuchMethod function. | 1582 // Invoke appropriate noSuchMethod function. |
1622 // Arg0: receiver (closure object) | 1583 // Arg0: receiver (closure object) |
1623 // Arg1: arguments descriptor array. | 1584 // Arg1: arguments descriptor array. |
1624 // Arg2: arguments array. | 1585 // Arg2: arguments array. |
1625 DEFINE_RUNTIME_ENTRY(InvokeClosureNoSuchMethod, 3) { | 1586 DEFINE_RUNTIME_ENTRY(InvokeClosureNoSuchMethod, 3) { |
1626 const Closure& receiver = Closure::CheckedHandle(arguments.ArgAt(0)); | 1587 const Closure& receiver = Closure::CheckedHandle(arguments.ArgAt(0)); |
1627 const Array& orig_arguments_desc = Array::CheckedHandle(arguments.ArgAt(1)); | 1588 const Array& orig_arguments_desc = Array::CheckedHandle(arguments.ArgAt(1)); |
1628 const Array& orig_arguments = Array::CheckedHandle(arguments.ArgAt(2)); | 1589 const Array& orig_arguments = Array::CheckedHandle(arguments.ArgAt(2)); |
1629 | 1590 |
1630 // For closure the function name is always 'call'. Replace it with the | 1591 // For closure the function name is always 'call'. Replace it with the |
1631 // name of the closurized function so that exception contains more | 1592 // name of the closurized function so that exception contains more |
1632 // relevant information. | 1593 // relevant information. |
1633 const Function& function = Function::Handle(receiver.function()); | 1594 const Function& function = Function::Handle(receiver.function()); |
1634 const String& original_function_name = | 1595 const String& original_function_name = |
1635 String::Handle(function.QualifiedUserVisibleName()); | 1596 String::Handle(function.QualifiedUserVisibleName()); |
1636 const Object& result = Object::Handle(DartEntry::InvokeNoSuchMethod( | 1597 const Object& result = Object::Handle(DartEntry::InvokeNoSuchMethod( |
1637 receiver, original_function_name, orig_arguments, orig_arguments_desc)); | 1598 receiver, original_function_name, orig_arguments, orig_arguments_desc)); |
1638 CheckResultError(result); | 1599 CheckResultError(result); |
1639 arguments.SetReturn(result); | 1600 arguments.SetReturn(result); |
1640 } | 1601 } |
1641 | 1602 |
1642 | |
1643 DEFINE_RUNTIME_ENTRY(StackOverflow, 0) { | 1603 DEFINE_RUNTIME_ENTRY(StackOverflow, 0) { |
1644 #if defined(USING_SIMULATOR) | 1604 #if defined(USING_SIMULATOR) |
1645 uword stack_pos = Simulator::Current()->get_sp(); | 1605 uword stack_pos = Simulator::Current()->get_sp(); |
1646 #else | 1606 #else |
1647 uword stack_pos = Thread::GetCurrentStackPointer(); | 1607 uword stack_pos = Thread::GetCurrentStackPointer(); |
1648 #endif | 1608 #endif |
1649 // Always clear the stack overflow flags. They are meant for this | 1609 // Always clear the stack overflow flags. They are meant for this |
1650 // particular stack overflow runtime call and are not meant to | 1610 // particular stack overflow runtime call and are not meant to |
1651 // persist. | 1611 // persist. |
1652 uword stack_overflow_flags = thread->GetAndClearStackOverflowFlags(); | 1612 uword stack_overflow_flags = thread->GetAndClearStackOverflowFlags(); |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1821 if (!result.IsNull()) { | 1781 if (!result.IsNull()) { |
1822 const Code& code = Code::Cast(result); | 1782 const Code& code = Code::Cast(result); |
1823 uword optimized_entry = | 1783 uword optimized_entry = |
1824 Instructions::UncheckedEntryPoint(code.instructions()); | 1784 Instructions::UncheckedEntryPoint(code.instructions()); |
1825 frame->set_pc(optimized_entry); | 1785 frame->set_pc(optimized_entry); |
1826 frame->set_pc_marker(code.raw()); | 1786 frame->set_pc_marker(code.raw()); |
1827 } | 1787 } |
1828 } | 1788 } |
1829 } | 1789 } |
1830 | 1790 |
1831 | |
1832 DEFINE_RUNTIME_ENTRY(TraceICCall, 2) { | 1791 DEFINE_RUNTIME_ENTRY(TraceICCall, 2) { |
1833 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(0)); | 1792 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(0)); |
1834 const Function& function = Function::CheckedHandle(arguments.ArgAt(1)); | 1793 const Function& function = Function::CheckedHandle(arguments.ArgAt(1)); |
1835 DartFrameIterator iterator(thread, | 1794 DartFrameIterator iterator(thread, |
1836 StackFrameIterator::kNoCrossThreadIteration); | 1795 StackFrameIterator::kNoCrossThreadIteration); |
1837 StackFrame* frame = iterator.NextFrame(); | 1796 StackFrame* frame = iterator.NextFrame(); |
1838 ASSERT(frame != NULL); | 1797 ASSERT(frame != NULL); |
1839 OS::PrintErr("IC call @%#" Px ": ICData: %p cnt:%" Pd " nchecks: %" Pd | 1798 OS::PrintErr("IC call @%#" Px ": ICData: %p cnt:%" Pd " nchecks: %" Pd |
1840 " %s\n", | 1799 " %s\n", |
1841 frame->pc(), ic_data.raw(), function.usage_counter(), | 1800 frame->pc(), ic_data.raw(), function.usage_counter(), |
1842 ic_data.NumberOfChecks(), function.ToFullyQualifiedCString()); | 1801 ic_data.NumberOfChecks(), function.ToFullyQualifiedCString()); |
1843 } | 1802 } |
1844 | 1803 |
1845 | |
1846 // This is called from function that needs to be optimized. | 1804 // This is called from function that needs to be optimized. |
1847 // The requesting function can be already optimized (reoptimization). | 1805 // The requesting function can be already optimized (reoptimization). |
1848 // Returns the Code object where to continue execution. | 1806 // Returns the Code object where to continue execution. |
1849 DEFINE_RUNTIME_ENTRY(OptimizeInvokedFunction, 1) { | 1807 DEFINE_RUNTIME_ENTRY(OptimizeInvokedFunction, 1) { |
1850 #if !defined(DART_PRECOMPILED_RUNTIME) | 1808 #if !defined(DART_PRECOMPILED_RUNTIME) |
1851 const Function& function = Function::CheckedHandle(zone, arguments.ArgAt(0)); | 1809 const Function& function = Function::CheckedHandle(zone, arguments.ArgAt(0)); |
1852 ASSERT(!function.IsNull()); | 1810 ASSERT(!function.IsNull()); |
1853 ASSERT(function.HasCode()); | 1811 ASSERT(function.HasCode()); |
1854 | 1812 |
1855 if (Compiler::CanOptimizeFunction(thread, function)) { | 1813 if (Compiler::CanOptimizeFunction(thread, function)) { |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1902 if (result.IsError()) { | 1860 if (result.IsError()) { |
1903 Exceptions::PropagateError(Error::Cast(result)); | 1861 Exceptions::PropagateError(Error::Cast(result)); |
1904 } | 1862 } |
1905 } | 1863 } |
1906 arguments.SetReturn(function); | 1864 arguments.SetReturn(function); |
1907 #else | 1865 #else |
1908 UNREACHABLE(); | 1866 UNREACHABLE(); |
1909 #endif // !DART_PRECOMPILED_RUNTIME | 1867 #endif // !DART_PRECOMPILED_RUNTIME |
1910 } | 1868 } |
1911 | 1869 |
1912 | |
1913 // The caller must be a static call in a Dart frame, or an entry frame. | 1870 // The caller must be a static call in a Dart frame, or an entry frame. |
1914 // Patch static call to point to valid code's entry point. | 1871 // Patch static call to point to valid code's entry point. |
1915 DEFINE_RUNTIME_ENTRY(FixCallersTarget, 0) { | 1872 DEFINE_RUNTIME_ENTRY(FixCallersTarget, 0) { |
1916 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames, thread, | 1873 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames, thread, |
1917 StackFrameIterator::kNoCrossThreadIteration); | 1874 StackFrameIterator::kNoCrossThreadIteration); |
1918 StackFrame* frame = iterator.NextFrame(); | 1875 StackFrame* frame = iterator.NextFrame(); |
1919 ASSERT(frame != NULL); | 1876 ASSERT(frame != NULL); |
1920 while (frame->IsStubFrame() || frame->IsExitFrame()) { | 1877 while (frame->IsStubFrame() || frame->IsExitFrame()) { |
1921 frame = iterator.NextFrame(); | 1878 frame = iterator.NextFrame(); |
1922 ASSERT(frame != NULL); | 1879 ASSERT(frame != NULL); |
(...skipping 17 matching lines...) Expand all Loading... |
1940 OS::PrintErr("FixCallersTarget: caller %#" Px | 1897 OS::PrintErr("FixCallersTarget: caller %#" Px |
1941 " " | 1898 " " |
1942 "target '%s' -> %#" Px "\n", | 1899 "target '%s' -> %#" Px "\n", |
1943 frame->pc(), target_function.ToFullyQualifiedCString(), | 1900 frame->pc(), target_function.ToFullyQualifiedCString(), |
1944 current_target_code.UncheckedEntryPoint()); | 1901 current_target_code.UncheckedEntryPoint()); |
1945 } | 1902 } |
1946 ASSERT(!current_target_code.IsDisabled()); | 1903 ASSERT(!current_target_code.IsDisabled()); |
1947 arguments.SetReturn(current_target_code); | 1904 arguments.SetReturn(current_target_code); |
1948 } | 1905 } |
1949 | 1906 |
1950 | |
1951 // The caller tried to allocate an instance via an invalidated allocation | 1907 // The caller tried to allocate an instance via an invalidated allocation |
1952 // stub. | 1908 // stub. |
1953 DEFINE_RUNTIME_ENTRY(FixAllocationStubTarget, 0) { | 1909 DEFINE_RUNTIME_ENTRY(FixAllocationStubTarget, 0) { |
1954 #if !defined(DART_PRECOMPILED_RUNTIME) | 1910 #if !defined(DART_PRECOMPILED_RUNTIME) |
1955 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames, thread, | 1911 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames, thread, |
1956 StackFrameIterator::kNoCrossThreadIteration); | 1912 StackFrameIterator::kNoCrossThreadIteration); |
1957 StackFrame* frame = iterator.NextFrame(); | 1913 StackFrame* frame = iterator.NextFrame(); |
1958 ASSERT(frame != NULL); | 1914 ASSERT(frame != NULL); |
1959 while (frame->IsStubFrame() || frame->IsExitFrame()) { | 1915 while (frame->IsStubFrame() || frame->IsExitFrame()) { |
1960 frame = iterator.NextFrame(); | 1916 frame = iterator.NextFrame(); |
(...skipping 23 matching lines...) Expand all Loading... |
1984 " -> %#" Px "\n", | 1940 " -> %#" Px "\n", |
1985 frame->pc(), alloc_class.ToCString(), | 1941 frame->pc(), alloc_class.ToCString(), |
1986 alloc_stub.UncheckedEntryPoint()); | 1942 alloc_stub.UncheckedEntryPoint()); |
1987 } | 1943 } |
1988 arguments.SetReturn(alloc_stub); | 1944 arguments.SetReturn(alloc_stub); |
1989 #else | 1945 #else |
1990 UNREACHABLE(); | 1946 UNREACHABLE(); |
1991 #endif | 1947 #endif |
1992 } | 1948 } |
1993 | 1949 |
1994 | |
1995 const char* DeoptReasonToCString(ICData::DeoptReasonId deopt_reason) { | 1950 const char* DeoptReasonToCString(ICData::DeoptReasonId deopt_reason) { |
1996 switch (deopt_reason) { | 1951 switch (deopt_reason) { |
1997 #define DEOPT_REASON_TO_TEXT(name) \ | 1952 #define DEOPT_REASON_TO_TEXT(name) \ |
1998 case ICData::kDeopt##name: \ | 1953 case ICData::kDeopt##name: \ |
1999 return #name; | 1954 return #name; |
2000 DEOPT_REASONS(DEOPT_REASON_TO_TEXT) | 1955 DEOPT_REASONS(DEOPT_REASON_TO_TEXT) |
2001 #undef DEOPT_REASON_TO_TEXT | 1956 #undef DEOPT_REASON_TO_TEXT |
2002 default: | 1957 default: |
2003 UNREACHABLE(); | 1958 UNREACHABLE(); |
2004 return ""; | 1959 return ""; |
2005 } | 1960 } |
2006 } | 1961 } |
2007 | 1962 |
2008 | |
2009 void DeoptimizeAt(const Code& optimized_code, StackFrame* frame) { | 1963 void DeoptimizeAt(const Code& optimized_code, StackFrame* frame) { |
2010 ASSERT(optimized_code.is_optimized()); | 1964 ASSERT(optimized_code.is_optimized()); |
2011 Thread* thread = Thread::Current(); | 1965 Thread* thread = Thread::Current(); |
2012 Zone* zone = thread->zone(); | 1966 Zone* zone = thread->zone(); |
2013 const Function& function = Function::Handle(zone, optimized_code.function()); | 1967 const Function& function = Function::Handle(zone, optimized_code.function()); |
2014 const Error& error = | 1968 const Error& error = |
2015 Error::Handle(zone, Compiler::EnsureUnoptimizedCode(thread, function)); | 1969 Error::Handle(zone, Compiler::EnsureUnoptimizedCode(thread, function)); |
2016 if (!error.IsNull()) { | 1970 if (!error.IsNull()) { |
2017 Exceptions::PropagateError(error); | 1971 Exceptions::PropagateError(error); |
2018 } | 1972 } |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2070 THR_Print("Lazy deopt scheduled for fp=%" Pp ", pc=%" Pp "\n", | 2024 THR_Print("Lazy deopt scheduled for fp=%" Pp ", pc=%" Pp "\n", |
2071 frame->fp(), deopt_pc); | 2025 frame->fp(), deopt_pc); |
2072 } | 2026 } |
2073 } | 2027 } |
2074 #endif // !DBC | 2028 #endif // !DBC |
2075 | 2029 |
2076 // Mark code as dead (do not GC its embedded objects). | 2030 // Mark code as dead (do not GC its embedded objects). |
2077 optimized_code.set_is_alive(false); | 2031 optimized_code.set_is_alive(false); |
2078 } | 2032 } |
2079 | 2033 |
2080 | |
2081 // Currently checks only that all optimized frames have kDeoptIndex | 2034 // Currently checks only that all optimized frames have kDeoptIndex |
2082 // and unoptimized code has the kDeoptAfter. | 2035 // and unoptimized code has the kDeoptAfter. |
2083 void DeoptimizeFunctionsOnStack() { | 2036 void DeoptimizeFunctionsOnStack() { |
2084 DartFrameIterator iterator(Thread::Current(), | 2037 DartFrameIterator iterator(Thread::Current(), |
2085 StackFrameIterator::kNoCrossThreadIteration); | 2038 StackFrameIterator::kNoCrossThreadIteration); |
2086 StackFrame* frame = iterator.NextFrame(); | 2039 StackFrame* frame = iterator.NextFrame(); |
2087 Code& optimized_code = Code::Handle(); | 2040 Code& optimized_code = Code::Handle(); |
2088 while (frame != NULL) { | 2041 while (frame != NULL) { |
2089 optimized_code = frame->LookupDartCode(); | 2042 optimized_code = frame->LookupDartCode(); |
2090 if (optimized_code.is_optimized()) { | 2043 if (optimized_code.is_optimized()) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2122 ASSERT(cpu_registers_copy != NULL); | 2075 ASSERT(cpu_registers_copy != NULL); |
2123 for (intptr_t i = 0; i < kNumberOfSavedCpuRegisters; i++) { | 2076 for (intptr_t i = 0; i < kNumberOfSavedCpuRegisters; i++) { |
2124 cpu_registers_copy[i] = | 2077 cpu_registers_copy[i] = |
2125 *reinterpret_cast<intptr_t*>(saved_registers_address); | 2078 *reinterpret_cast<intptr_t*>(saved_registers_address); |
2126 saved_registers_address += kWordSize; | 2079 saved_registers_address += kWordSize; |
2127 } | 2080 } |
2128 *cpu_registers = cpu_registers_copy; | 2081 *cpu_registers = cpu_registers_copy; |
2129 } | 2082 } |
2130 #endif | 2083 #endif |
2131 | 2084 |
2132 | |
2133 // Copies saved registers and caller's frame into temporary buffers. | 2085 // Copies saved registers and caller's frame into temporary buffers. |
2134 // Returns the stack size of unoptimized frame. | 2086 // Returns the stack size of unoptimized frame. |
2135 // The calling code must be optimized, but its function may not have | 2087 // The calling code must be optimized, but its function may not have |
2136 // have optimized code if the code is OSR code, or if the code was invalidated | 2088 // have optimized code if the code is OSR code, or if the code was invalidated |
2137 // through class loading/finalization or field guard. | 2089 // through class loading/finalization or field guard. |
2138 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, | 2090 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, |
2139 DeoptimizeCopyFrame, | 2091 DeoptimizeCopyFrame, |
2140 2, | 2092 2, |
2141 uword saved_registers_address, | 2093 uword saved_registers_address, |
2142 uword is_lazy_deopt) { | 2094 uword is_lazy_deopt) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2206 | 2158 |
2207 // Stack size (FP - SP) in bytes. | 2159 // Stack size (FP - SP) in bytes. |
2208 return deopt_context->DestStackAdjustment() * kWordSize; | 2160 return deopt_context->DestStackAdjustment() * kWordSize; |
2209 #else | 2161 #else |
2210 UNREACHABLE(); | 2162 UNREACHABLE(); |
2211 return 0; | 2163 return 0; |
2212 #endif // !DART_PRECOMPILED_RUNTIME | 2164 #endif // !DART_PRECOMPILED_RUNTIME |
2213 } | 2165 } |
2214 END_LEAF_RUNTIME_ENTRY | 2166 END_LEAF_RUNTIME_ENTRY |
2215 | 2167 |
2216 | |
2217 // The stack has been adjusted to fit all values for unoptimized frame. | 2168 // The stack has been adjusted to fit all values for unoptimized frame. |
2218 // Fill the unoptimized frame. | 2169 // Fill the unoptimized frame. |
2219 DEFINE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, 1, uword last_fp) { | 2170 DEFINE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, 1, uword last_fp) { |
2220 #if !defined(DART_PRECOMPILED_RUNTIME) | 2171 #if !defined(DART_PRECOMPILED_RUNTIME) |
2221 Thread* thread = Thread::Current(); | 2172 Thread* thread = Thread::Current(); |
2222 Isolate* isolate = thread->isolate(); | 2173 Isolate* isolate = thread->isolate(); |
2223 StackZone zone(thread); | 2174 StackZone zone(thread); |
2224 HANDLESCOPE(thread); | 2175 HANDLESCOPE(thread); |
2225 | 2176 |
2226 DeoptContext* deopt_context = isolate->deopt_context(); | 2177 DeoptContext* deopt_context = isolate->deopt_context(); |
(...skipping 22 matching lines...) Expand all Loading... |
2249 | 2200 |
2250 deopt_context->set_dest_frame(caller_frame); | 2201 deopt_context->set_dest_frame(caller_frame); |
2251 deopt_context->FillDestFrame(); | 2202 deopt_context->FillDestFrame(); |
2252 | 2203 |
2253 #else | 2204 #else |
2254 UNREACHABLE(); | 2205 UNREACHABLE(); |
2255 #endif // !DART_PRECOMPILED_RUNTIME | 2206 #endif // !DART_PRECOMPILED_RUNTIME |
2256 } | 2207 } |
2257 END_LEAF_RUNTIME_ENTRY | 2208 END_LEAF_RUNTIME_ENTRY |
2258 | 2209 |
2259 | |
2260 // This is the last step in the deoptimization, GC can occur. | 2210 // This is the last step in the deoptimization, GC can occur. |
2261 // Returns number of bytes to remove from the expression stack of the | 2211 // Returns number of bytes to remove from the expression stack of the |
2262 // bottom-most deoptimized frame. Those arguments were artificially injected | 2212 // bottom-most deoptimized frame. Those arguments were artificially injected |
2263 // under return address to keep them discoverable by GC that can occur during | 2213 // under return address to keep them discoverable by GC that can occur during |
2264 // materialization phase. | 2214 // materialization phase. |
2265 DEFINE_RUNTIME_ENTRY(DeoptimizeMaterialize, 0) { | 2215 DEFINE_RUNTIME_ENTRY(DeoptimizeMaterialize, 0) { |
2266 #if !defined(DART_PRECOMPILED_RUNTIME) | 2216 #if !defined(DART_PRECOMPILED_RUNTIME) |
2267 #if defined(DEBUG) | 2217 #if defined(DEBUG) |
2268 { | 2218 { |
2269 // We may rendezvous for a safepoint at entry or GC from the allocations | 2219 // We may rendezvous for a safepoint at entry or GC from the allocations |
2270 // below. Check the stack is walkable. | 2220 // below. Check the stack is walkable. |
2271 ValidateFrames(); | 2221 ValidateFrames(); |
2272 } | 2222 } |
2273 #endif | 2223 #endif |
2274 DeoptContext* deopt_context = isolate->deopt_context(); | 2224 DeoptContext* deopt_context = isolate->deopt_context(); |
2275 intptr_t deopt_arg_count = deopt_context->MaterializeDeferredObjects(); | 2225 intptr_t deopt_arg_count = deopt_context->MaterializeDeferredObjects(); |
2276 isolate->set_deopt_context(NULL); | 2226 isolate->set_deopt_context(NULL); |
2277 delete deopt_context; | 2227 delete deopt_context; |
2278 | 2228 |
2279 // Return value tells deoptimization stub to remove the given number of bytes | 2229 // Return value tells deoptimization stub to remove the given number of bytes |
2280 // from the stack. | 2230 // from the stack. |
2281 arguments.SetReturn(Smi::Handle(Smi::New(deopt_arg_count * kWordSize))); | 2231 arguments.SetReturn(Smi::Handle(Smi::New(deopt_arg_count * kWordSize))); |
2282 #else | 2232 #else |
2283 UNREACHABLE(); | 2233 UNREACHABLE(); |
2284 #endif // !DART_PRECOMPILED_RUNTIME | 2234 #endif // !DART_PRECOMPILED_RUNTIME |
2285 } | 2235 } |
2286 | 2236 |
2287 | |
2288 DEFINE_RUNTIME_ENTRY(RewindPostDeopt, 0) { | 2237 DEFINE_RUNTIME_ENTRY(RewindPostDeopt, 0) { |
2289 #if !defined(DART_PRECOMPILED_RUNTIME) | 2238 #if !defined(DART_PRECOMPILED_RUNTIME) |
2290 #if !defined(PRODUCT) | 2239 #if !defined(PRODUCT) |
2291 isolate->debugger()->RewindPostDeopt(); | 2240 isolate->debugger()->RewindPostDeopt(); |
2292 #endif // !PRODUCT | 2241 #endif // !PRODUCT |
2293 #endif // !DART_PRECOMPILED_RUNTIME | 2242 #endif // !DART_PRECOMPILED_RUNTIME |
2294 UNREACHABLE(); | 2243 UNREACHABLE(); |
2295 } | 2244 } |
2296 | 2245 |
2297 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, | 2246 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, |
2298 BigintCompare, | 2247 BigintCompare, |
2299 2, | 2248 2, |
2300 RawBigint* left, | 2249 RawBigint* left, |
2301 RawBigint* right) { | 2250 RawBigint* right) { |
2302 Thread* thread = Thread::Current(); | 2251 Thread* thread = Thread::Current(); |
2303 StackZone zone(thread); | 2252 StackZone zone(thread); |
2304 HANDLESCOPE(thread); | 2253 HANDLESCOPE(thread); |
2305 const Bigint& big_left = Bigint::Handle(left); | 2254 const Bigint& big_left = Bigint::Handle(left); |
2306 const Bigint& big_right = Bigint::Handle(right); | 2255 const Bigint& big_right = Bigint::Handle(right); |
2307 return big_left.CompareWith(big_right); | 2256 return big_left.CompareWith(big_right); |
2308 } | 2257 } |
2309 END_LEAF_RUNTIME_ENTRY | 2258 END_LEAF_RUNTIME_ENTRY |
2310 | 2259 |
2311 | |
2312 double DartModulo(double left, double right) { | 2260 double DartModulo(double left, double right) { |
2313 double remainder = fmod_ieee(left, right); | 2261 double remainder = fmod_ieee(left, right); |
2314 if (remainder == 0.0) { | 2262 if (remainder == 0.0) { |
2315 // We explicitly switch to the positive 0.0 (just in case it was negative). | 2263 // We explicitly switch to the positive 0.0 (just in case it was negative). |
2316 remainder = +0.0; | 2264 remainder = +0.0; |
2317 } else if (remainder < 0.0) { | 2265 } else if (remainder < 0.0) { |
2318 if (right < 0) { | 2266 if (right < 0) { |
2319 remainder -= right; | 2267 remainder -= right; |
2320 } else { | 2268 } else { |
2321 remainder += right; | 2269 remainder += right; |
2322 } | 2270 } |
2323 } | 2271 } |
2324 return remainder; | 2272 return remainder; |
2325 } | 2273 } |
2326 | 2274 |
2327 | |
2328 // Update global type feedback recorded for a field recording the assignment | 2275 // Update global type feedback recorded for a field recording the assignment |
2329 // of the given value. | 2276 // of the given value. |
2330 // Arg0: Field object; | 2277 // Arg0: Field object; |
2331 // Arg1: Value that is being stored. | 2278 // Arg1: Value that is being stored. |
2332 DEFINE_RUNTIME_ENTRY(UpdateFieldCid, 2) { | 2279 DEFINE_RUNTIME_ENTRY(UpdateFieldCid, 2) { |
2333 const Field& field = Field::CheckedHandle(arguments.ArgAt(0)); | 2280 const Field& field = Field::CheckedHandle(arguments.ArgAt(0)); |
2334 const Object& value = Object::Handle(arguments.ArgAt(1)); | 2281 const Object& value = Object::Handle(arguments.ArgAt(1)); |
2335 field.RecordStore(value); | 2282 field.RecordStore(value); |
2336 } | 2283 } |
2337 | 2284 |
2338 | |
2339 DEFINE_RUNTIME_ENTRY(InitStaticField, 1) { | 2285 DEFINE_RUNTIME_ENTRY(InitStaticField, 1) { |
2340 const Field& field = Field::CheckedHandle(arguments.ArgAt(0)); | 2286 const Field& field = Field::CheckedHandle(arguments.ArgAt(0)); |
2341 field.EvaluateInitializer(); | 2287 field.EvaluateInitializer(); |
2342 } | 2288 } |
2343 | 2289 |
2344 // Use expected function signatures to help MSVC compiler resolve overloading. | 2290 // Use expected function signatures to help MSVC compiler resolve overloading. |
2345 typedef double (*UnaryMathCFunction)(double x); | 2291 typedef double (*UnaryMathCFunction)(double x); |
2346 typedef double (*BinaryMathCFunction)(double x, double y); | 2292 typedef double (*BinaryMathCFunction)(double x, double y); |
2347 | 2293 |
2348 DEFINE_RAW_LEAF_RUNTIME_ENTRY( | 2294 DEFINE_RAW_LEAF_RUNTIME_ENTRY( |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2419 true /* is_float */, | 2365 true /* is_float */, |
2420 reinterpret_cast<RuntimeFunction>(static_cast<UnaryMathCFunction>(&tan))); | 2366 reinterpret_cast<RuntimeFunction>(static_cast<UnaryMathCFunction>(&tan))); |
2421 | 2367 |
2422 DEFINE_RAW_LEAF_RUNTIME_ENTRY( | 2368 DEFINE_RAW_LEAF_RUNTIME_ENTRY( |
2423 LibcAtan, | 2369 LibcAtan, |
2424 1, | 2370 1, |
2425 true /* is_float */, | 2371 true /* is_float */, |
2426 reinterpret_cast<RuntimeFunction>(static_cast<UnaryMathCFunction>(&atan))); | 2372 reinterpret_cast<RuntimeFunction>(static_cast<UnaryMathCFunction>(&atan))); |
2427 | 2373 |
2428 } // namespace dart | 2374 } // namespace dart |
OLD | NEW |