| 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/code_generator.h" | 5 #include "vm/code_generator.h" |
| 6 | 6 |
| 7 #include "vm/code_index_table.h" | 7 #include "vm/code_index_table.h" |
| 8 #include "vm/code_patcher.h" | 8 #include "vm/code_patcher.h" |
| 9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
| 10 #include "vm/dart_api_impl.h" | 10 #include "vm/dart_api_impl.h" |
| (...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 489 | 489 |
| 490 // Gets called from debug stub when code reaches a breakpoint. | 490 // Gets called from debug stub when code reaches a breakpoint. |
| 491 DEFINE_RUNTIME_ENTRY(BreakpointDynamicHandler, 0) { | 491 DEFINE_RUNTIME_ENTRY(BreakpointDynamicHandler, 0) { |
| 492 ASSERT(arguments.Count() == | 492 ASSERT(arguments.Count() == |
| 493 kBreakpointDynamicHandlerRuntimeEntry.argument_count()); | 493 kBreakpointDynamicHandlerRuntimeEntry.argument_count()); |
| 494 ASSERT(isolate->debugger() != NULL); | 494 ASSERT(isolate->debugger() != NULL); |
| 495 isolate->debugger()->BreakpointCallback(); | 495 isolate->debugger()->BreakpointCallback(); |
| 496 } | 496 } |
| 497 | 497 |
| 498 | 498 |
| 499 // Handles inline cache misses by updating the IC data array of the call | 499 static RawFunction* InlineCacheMissHandler( |
| 500 // site. | 500 Isolate* isolate, const GrowableArray<const Instance*>& args) { |
| 501 // Arg0: Receiver object. | 501 const Instance& receiver = *args[0]; |
| 502 // Returns: target function with compiled code or 0. | |
| 503 // Modifies the instance call to hold the updated IC data array. | |
| 504 DEFINE_RUNTIME_ENTRY(InlineCacheMissHandler, 1) { | |
| 505 ASSERT(arguments.Count() == | |
| 506 kInlineCacheMissHandlerRuntimeEntry.argument_count()); | |
| 507 const Instance& receiver = Instance::CheckedHandle(arguments.At(0)); | |
| 508 const Code& target_code = | 502 const Code& target_code = |
| 509 Code::Handle(ResolveCompileInstanceCallTarget(isolate, receiver)); | 503 Code::Handle(ResolveCompileInstanceCallTarget(isolate, receiver)); |
| 510 if (target_code.IsNull()) { | 504 if (target_code.IsNull()) { |
| 511 // Let the megamorphic stub handle special cases: NoSuchMethod, | 505 // Let the megamorphic stub handle special cases: NoSuchMethod, |
| 512 // closure calls. | 506 // closure calls. |
| 513 if (FLAG_trace_ic) { | 507 if (FLAG_trace_ic) { |
| 514 OS::Print("InlineCacheMissHandler NULL code for receiver: %s\n", | 508 OS::Print("InlineCacheMissHandler NULL code for receiver: %s\n", |
| 515 receiver.ToCString()); | 509 receiver.ToCString()); |
| 516 } | 510 } |
| 517 arguments.SetReturn(target_code); | 511 return Function::null(); |
| 518 return; | |
| 519 } | 512 } |
| 520 const Function& target_function = | 513 const Function& target_function = |
| 521 Function::Handle(target_code.function()); | 514 Function::Handle(target_code.function()); |
| 522 ASSERT(!target_function.IsNull()); | 515 ASSERT(!target_function.IsNull()); |
| 523 if (receiver.IsNull()) { | 516 if (receiver.IsNull()) { |
| 524 // Null dispatch is slow (e.g., (null).toCString()). The only | 517 // Null dispatch is slow (e.g., (null).toCString()). The only |
| 525 // fast execution with null receiver is the "==" operator. | 518 // fast execution with null receiver is the "==" operator. |
| 526 // Special handling so that we do not pollute the inline cache with null | 519 // Special handling so that we do not pollute the inline cache with null |
| 527 // classes. | 520 // classes. |
| 528 arguments.SetReturn(target_function); | |
| 529 if (FLAG_trace_ic) { | 521 if (FLAG_trace_ic) { |
| 530 OS::Print("InlineCacheMissHandler Null receiver target %s\n", | 522 OS::Print("InlineCacheMissHandler Null receiver target %s\n", |
| 531 target_function.ToCString()); | 523 target_function.ToCString()); |
| 532 } | 524 } |
| 533 return; | 525 return target_function.raw(); |
| 534 } | 526 } |
| 535 DartFrameIterator iterator; | 527 DartFrameIterator iterator; |
| 536 DartFrame* caller_frame = iterator.NextFrame(); | 528 DartFrame* caller_frame = iterator.NextFrame(); |
| 537 ICData ic_data(Array::Handle( | 529 ICData ic_data(Array::Handle( |
| 538 CodePatcher::GetInstanceCallIcDataAt(caller_frame->pc()))); | 530 CodePatcher::GetInstanceCallIcDataAt(caller_frame->pc()))); |
| 531 |
| 532 #if defined(DEBUG) |
| 533 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 534 GrowableArray<const Class*> classes; |
| 535 Function& target = Function::Handle(); |
| 536 ic_data.GetCheckAt(i, &classes, &target); |
| 537 bool matches = true; |
| 538 for (intptr_t k = 0; k < classes.length(); k++) { |
| 539 if (classes[k]->raw() != args[k]->clazz()) { |
| 540 matches = false; |
| 541 break; |
| 542 } |
| 543 } |
| 544 // Do not add an entry twice! |
| 545 ASSERT(!matches); |
| 546 } |
| 547 #endif // DEBUG |
| 548 |
| 539 GrowableArray<const Class*> classes; | 549 GrowableArray<const Class*> classes; |
| 540 classes.Add(&Class::ZoneHandle(receiver.clazz())); | 550 ASSERT(ic_data.NumberOfArgumentsChecked() == args.length()); |
| 551 for (intptr_t i = 0; i < args.length(); i++) { |
| 552 classes.Add(&Class::ZoneHandle(args[i]->clazz())); |
| 553 } |
| 541 ic_data.AddCheck(classes, target_function); | 554 ic_data.AddCheck(classes, target_function); |
| 542 CodePatcher::SetInstanceCallIcDataAt(caller_frame->pc(), | 555 CodePatcher::SetInstanceCallIcDataAt(caller_frame->pc(), |
| 543 Array::ZoneHandle(ic_data.data())); | 556 Array::ZoneHandle(ic_data.data())); |
| 544 arguments.SetReturn(target_function); | |
| 545 if (FLAG_trace_ic) { | 557 if (FLAG_trace_ic) { |
| 546 OS::Print("InlineCacheMissHandler call at 0x%x' adding <%s> -> <%s>\n", | 558 OS::Print("InlineCacheMissHandler %d call at 0x%x' adding <%s> -> <%s>\n", |
| 559 args.length(), |
| 547 caller_frame->pc(), | 560 caller_frame->pc(), |
| 548 Class::Handle(receiver.clazz()).ToCString(), | 561 Class::Handle(receiver.clazz()).ToCString(), |
| 549 target_function.ToCString()); | 562 target_function.ToCString()); |
| 550 } | 563 } |
| 564 return target_function.raw(); |
| 565 } |
| 566 |
| 567 |
| 568 // Handles inline cache misses by updating the IC data array of the call |
| 569 // site. |
| 570 // Arg0: Receiver object. |
| 571 // Returns: target function with compiled code or null. |
| 572 // Modifies the instance call to hold the updated IC data array. |
| 573 DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerOneArg, 1) { |
| 574 ASSERT(arguments.Count() == |
| 575 kInlineCacheMissHandlerOneArgRuntimeEntry.argument_count()); |
| 576 const Instance& receiver = Instance::CheckedHandle(arguments.At(0)); |
| 577 GrowableArray<const Instance*> args; |
| 578 args.Add(&receiver); |
| 579 const Function& result = |
| 580 Function::Handle(InlineCacheMissHandler(isolate, args)); |
| 581 arguments.SetReturn(result); |
| 582 } |
| 583 |
| 584 |
| 585 // Handles inline cache misses by updating the IC data array of the call |
| 586 // site. |
| 587 // Arg0: Receiver object. |
| 588 // Arg1: Argument after receiver. |
| 589 // Returns: target function with compiled code or null. |
| 590 // Modifies the instance call to hold the updated IC data array. |
| 591 DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerTwoArgs, 2) { |
| 592 ASSERT(arguments.Count() == |
| 593 kInlineCacheMissHandlerTwoArgsRuntimeEntry.argument_count()); |
| 594 const Instance& receiver = Instance::CheckedHandle(arguments.At(0)); |
| 595 const Instance& other = Instance::CheckedHandle(arguments.At(1)); |
| 596 GrowableArray<const Instance*> args; |
| 597 args.Add(&receiver); |
| 598 args.Add(&other); |
| 599 const Function& result = |
| 600 Function::Handle(InlineCacheMissHandler(isolate, args)); |
| 601 arguments.SetReturn(result); |
| 551 } | 602 } |
| 552 | 603 |
| 553 | 604 |
| 554 static RawFunction* LookupDynamicFunction(Isolate* isolate, | 605 static RawFunction* LookupDynamicFunction(Isolate* isolate, |
| 555 const Class& in_cls, | 606 const Class& in_cls, |
| 556 const String& name) { | 607 const String& name) { |
| 557 Class& cls = Class::Handle(); | 608 Class& cls = Class::Handle(); |
| 558 // For lookups treat null as an instance of class Object. | 609 // For lookups treat null as an instance of class Object. |
| 559 if (in_cls.IsNullClass()) { | 610 if (in_cls.IsNullClass()) { |
| 560 cls = isolate->object_store()->object_class(); | 611 cls = isolate->object_store()->object_class(); |
| (...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1038 } | 1089 } |
| 1039 } | 1090 } |
| 1040 } | 1091 } |
| 1041 // The cache is null terminated, therefore the loop above should never | 1092 // The cache is null terminated, therefore the loop above should never |
| 1042 // terminate by itself. | 1093 // terminate by itself. |
| 1043 UNREACHABLE(); | 1094 UNREACHABLE(); |
| 1044 return Code::null(); | 1095 return Code::null(); |
| 1045 } | 1096 } |
| 1046 | 1097 |
| 1047 } // namespace dart | 1098 } // namespace dart |
| OLD | NEW |