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

Side by Side Diff: runtime/vm/intermediate_language.cc

Issue 468793004: VM: Improve performance of method recognizer and unify the it with the intrinsifier. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 4 months 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 | « runtime/vm/intermediate_language.h ('k') | runtime/vm/intrinsifier.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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/intermediate_language.h" 5 #include "vm/intermediate_language.h"
6 6
7 #include "vm/bigint_operations.h" 7 #include "vm/bigint_operations.h"
8 #include "vm/bit_vector.h" 8 #include "vm/bit_vector.h"
9 #include "vm/cpu.h" 9 #include "vm/cpu.h"
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
11 #include "vm/flow_graph_allocator.h" 11 #include "vm/flow_graph_allocator.h"
12 #include "vm/flow_graph_builder.h" 12 #include "vm/flow_graph_builder.h"
13 #include "vm/flow_graph_compiler.h" 13 #include "vm/flow_graph_compiler.h"
14 #include "vm/flow_graph_optimizer.h" 14 #include "vm/flow_graph_optimizer.h"
15 #include "vm/flow_graph_range_analysis.h" 15 #include "vm/flow_graph_range_analysis.h"
16 #include "vm/locations.h" 16 #include "vm/locations.h"
17 #include "vm/method_recognizer.h"
17 #include "vm/object.h" 18 #include "vm/object.h"
18 #include "vm/object_store.h" 19 #include "vm/object_store.h"
19 #include "vm/os.h" 20 #include "vm/os.h"
20 #include "vm/resolver.h" 21 #include "vm/resolver.h"
21 #include "vm/scopes.h" 22 #include "vm/scopes.h"
22 #include "vm/stub_code.h" 23 #include "vm/stub_code.h"
23 #include "vm/symbols.h" 24 #include "vm/symbols.h"
24 25
25 #include "vm/il_printer.h" 26 #include "vm/il_printer.h"
26 27
(...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after
478 CatchBlockEntryInstr* GraphEntryInstr::GetCatchEntry(intptr_t index) { 479 CatchBlockEntryInstr* GraphEntryInstr::GetCatchEntry(intptr_t index) {
479 // TODO(fschneider): Sort the catch entries by catch_try_index to avoid 480 // TODO(fschneider): Sort the catch entries by catch_try_index to avoid
480 // searching. 481 // searching.
481 for (intptr_t i = 0; i < catch_entries_.length(); ++i) { 482 for (intptr_t i = 0; i < catch_entries_.length(); ++i) {
482 if (catch_entries_[i]->catch_try_index() == index) return catch_entries_[i]; 483 if (catch_entries_[i]->catch_try_index() == index) return catch_entries_[i];
483 } 484 }
484 return NULL; 485 return NULL;
485 } 486 }
486 487
487 488
488 static bool StartsWith(const String& name, const char* prefix, intptr_t n) {
489 ASSERT(name.IsOneByteString());
490
491 if (name.Length() < n) {
492 return false;
493 }
494
495 for (intptr_t i = 0; i < n; i++) {
496 if (name.CharAt(i) != prefix[i]) {
497 return false;
498 }
499 }
500
501 return true;
502 }
503
504
505 static bool CompareNames(const Library& lib,
506 const char* test_name,
507 const String& name) {
508 ASSERT(Library::kPrivateIdentifierStart == '_');
509 const char* kPrivateGetterPrefix = "get:_";
510 const char* kPrivateSetterPrefix = "set:_";
511
512 if (test_name[0] == Library::kPrivateIdentifierStart) {
513 if (name.CharAt(0) != Library::kPrivateIdentifierStart) {
514 return false;
515 }
516 } else if (strncmp(test_name,
517 kPrivateGetterPrefix,
518 strlen(kPrivateGetterPrefix)) == 0) {
519 if (!StartsWith(name, kPrivateGetterPrefix, strlen(kPrivateGetterPrefix))) {
520 return false;
521 }
522 } else if (strncmp(test_name,
523 kPrivateSetterPrefix,
524 strlen(kPrivateSetterPrefix)) == 0) {
525 if (!StartsWith(name, kPrivateSetterPrefix, strlen(kPrivateSetterPrefix))) {
526 return false;
527 }
528 } else {
529 // Compare without mangling.
530 return name.Equals(test_name);
531 }
532
533 // Both names are private. Mangle test_name before comparison.
534 // Check if this is a constructor (e.g., List,), in which case the mangler
535 // needs some help (see comment in Library::PrivateName).
536 String& test_name_symbol = String::Handle();
537 if (test_name[strlen(test_name) - 1] == '.') {
538 test_name_symbol = Symbols::New(test_name, strlen(test_name) - 1);
539 test_name_symbol = lib.PrivateName(test_name_symbol);
540 test_name_symbol = String::Concat(test_name_symbol, Symbols::Dot());
541 } else {
542 test_name_symbol = Symbols::New(test_name);
543 test_name_symbol = lib.PrivateName(test_name_symbol);
544 }
545 return test_name_symbol.Equals(name);
546 }
547
548
549 static bool IsRecognizedLibrary(const Library& library) {
550 // List of libraries where methods can be recognized.
551 return (library.raw() == Library::CoreLibrary())
552 || (library.raw() == Library::MathLibrary())
553 || (library.raw() == Library::TypedDataLibrary())
554 || (library.raw() == Library::InternalLibrary());
555 }
556
557
558 MethodRecognizer::Kind MethodRecognizer::RecognizeKind(
559 const Function& function) {
560 if (!function.is_recognized()) {
561 return kUnknown;
562 }
563
564 const Class& function_class = Class::Handle(function.Owner());
565 const Library& lib = Library::Handle(function_class.library());
566 const String& function_name = String::Handle(function.name());
567 const String& class_name = String::Handle(function_class.Name());
568
569 #define RECOGNIZE_FUNCTION(test_class_name, test_function_name, enum_name, fp) \
570 if (CompareNames(lib, #test_function_name, function_name) && \
571 CompareNames(lib, #test_class_name, class_name)) { \
572 ASSERT(function.CheckSourceFingerprint(fp)); \
573 return k##enum_name; \
574 }
575 RECOGNIZED_LIST(RECOGNIZE_FUNCTION)
576 #undef RECOGNIZE_FUNCTION
577 UNREACHABLE();
578 return kUnknown;
579 }
580
581
582 bool MethodRecognizer::AlwaysInline(const Function& function) {
583 const Class& function_class = Class::Handle(function.Owner());
584 const Library& lib = Library::Handle(function_class.library());
585 if (!IsRecognizedLibrary(lib)) {
586 return false;
587 }
588
589 const String& function_name = String::Handle(function.name());
590 const String& class_name = String::Handle(function_class.Name());
591
592 #define RECOGNIZE_FUNCTION(test_class_name, test_function_name, enum_name, fp) \
593 if (CompareNames(lib, #test_function_name, function_name) && \
594 CompareNames(lib, #test_class_name, class_name)) { \
595 ASSERT(function.CheckSourceFingerprint(fp)); \
596 return true; \
597 }
598 INLINE_WHITE_LIST(RECOGNIZE_FUNCTION)
599 #undef RECOGNIZE_FUNCTION
600 return false;
601 }
602
603
604 bool MethodRecognizer::PolymorphicTarget(const Function& function) {
605 const Class& function_class = Class::Handle(function.Owner());
606 const Library& lib = Library::Handle(function_class.library());
607 if (!IsRecognizedLibrary(lib)) {
608 return false;
609 }
610
611 const String& function_name = String::Handle(function.name());
612 const String& class_name = String::Handle(function_class.Name());
613
614 #define RECOGNIZE_FUNCTION(test_class_name, test_function_name, enum_name, fp) \
615 if (CompareNames(lib, #test_function_name, function_name) && \
616 CompareNames(lib, #test_class_name, class_name)) { \
617 ASSERT(function.CheckSourceFingerprint(fp)); \
618 return true; \
619 }
620 POLYMORPHIC_TARGET_LIST(RECOGNIZE_FUNCTION)
621 #undef RECOGNIZE_FUNCTION
622 return false;
623 }
624
625
626 const char* MethodRecognizer::KindToCString(Kind kind) {
627 #define KIND_TO_STRING(class_name, function_name, enum_name, fp) \
628 if (kind == k##enum_name) return #enum_name;
629 RECOGNIZED_LIST(KIND_TO_STRING)
630 #undef KIND_TO_STRING
631 return "?";
632 }
633
634
635 void MethodRecognizer::InitializeState() {
636 GrowableArray<Library*> libs(3);
637 libs.Add(&Library::ZoneHandle(Library::CoreLibrary()));
638 libs.Add(&Library::ZoneHandle(Library::MathLibrary()));
639 libs.Add(&Library::ZoneHandle(Library::TypedDataLibrary()));
640 Function& func = Function::Handle();
641
642 #define SET_IS_RECOGNIZED(class_name, function_name, dest, fp) \
643 func = Library::GetFunction(libs, #class_name, #function_name); \
644 if (func.IsNull()) { \
645 OS::PrintErr("Missing %s::%s\n", #class_name, #function_name); \
646 UNREACHABLE(); \
647 } \
648 ASSERT(func.CheckSourceFingerprint(fp)); \
649 func.set_is_recognized(true); \
650
651 RECOGNIZED_LIST(SET_IS_RECOGNIZED);
652
653 #undef SET_IS_RECOGNIZED
654 }
655
656 // ==== Support for visiting flow graphs. 489 // ==== Support for visiting flow graphs.
657 490
658 #define DEFINE_ACCEPT(ShortName) \ 491 #define DEFINE_ACCEPT(ShortName) \
659 void ShortName##Instr::Accept(FlowGraphVisitor* visitor) { \ 492 void ShortName##Instr::Accept(FlowGraphVisitor* visitor) { \
660 visitor->Visit##ShortName(this); \ 493 visitor->Visit##ShortName(this); \
661 } 494 }
662 495
663 FOR_EACH_INSTRUCTION(DEFINE_ACCEPT) 496 FOR_EACH_INSTRUCTION(DEFINE_ACCEPT)
664 497
665 #undef DEFINE_ACCEPT 498 #undef DEFINE_ACCEPT
(...skipping 1803 matching lines...) Expand 10 before | Expand all | Expand 10 after
2469 return MakeCallSummary(); 2302 return MakeCallSummary();
2470 } 2303 }
2471 2304
2472 2305
2473 void StaticCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2306 void StaticCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2474 const ICData* call_ic_data = NULL; 2307 const ICData* call_ic_data = NULL;
2475 if (!FLAG_propagate_ic_data || !compiler->is_optimizing()) { 2308 if (!FLAG_propagate_ic_data || !compiler->is_optimizing()) {
2476 const Array& arguments_descriptor = 2309 const Array& arguments_descriptor =
2477 Array::Handle(ArgumentsDescriptor::New(ArgumentCount(), 2310 Array::Handle(ArgumentsDescriptor::New(ArgumentCount(),
2478 argument_names())); 2311 argument_names()));
2479 // TODO(srdjan): Improve performance of function recognition.
2480 MethodRecognizer::Kind recognized_kind = 2312 MethodRecognizer::Kind recognized_kind =
2481 MethodRecognizer::RecognizeKind(function()); 2313 MethodRecognizer::RecognizeKind(function());
2482 int num_args_checked = 0; 2314 int num_args_checked = 0;
2483 if ((recognized_kind == MethodRecognizer::kMathMin) || 2315 if ((recognized_kind == MethodRecognizer::kMathMin) ||
2484 (recognized_kind == MethodRecognizer::kMathMax)) { 2316 (recognized_kind == MethodRecognizer::kMathMax)) {
2485 num_args_checked = 2; 2317 num_args_checked = 2;
2486 } 2318 }
2487 call_ic_data = compiler->GetOrAddStaticCallICData(deopt_id(), 2319 call_ic_data = compiler->GetOrAddStaticCallICData(deopt_id(),
2488 function(), 2320 function(),
2489 arguments_descriptor, 2321 arguments_descriptor,
(...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after
2970 case Token::kTRUNCDIV: return 0; 2802 case Token::kTRUNCDIV: return 0;
2971 case Token::kMOD: return 1; 2803 case Token::kMOD: return 1;
2972 default: UNIMPLEMENTED(); return -1; 2804 default: UNIMPLEMENTED(); return -1;
2973 } 2805 }
2974 } 2806 }
2975 2807
2976 2808
2977 #undef __ 2809 #undef __
2978 2810
2979 } // namespace dart 2811 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language.h ('k') | runtime/vm/intrinsifier.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698