| 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 |