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

Side by Side Diff: vm/code_generator.cc

Issue 8827015: Implement two-argument check inline cache. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: '' Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « vm/code_generator.h ('k') | vm/code_generator_ia32.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 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
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
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
OLDNEW
« no previous file with comments | « vm/code_generator.h ('k') | vm/code_generator_ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698