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

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

Issue 484693003: Improve polymorphic inlining of int/int double/double operations. (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
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/intrinsifier.h"
16 #include "vm/locations.h" 17 #include "vm/locations.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"
(...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after
470 CatchBlockEntryInstr* GraphEntryInstr::GetCatchEntry(intptr_t index) { 471 CatchBlockEntryInstr* GraphEntryInstr::GetCatchEntry(intptr_t index) {
471 // TODO(fschneider): Sort the catch entries by catch_try_index to avoid 472 // TODO(fschneider): Sort the catch entries by catch_try_index to avoid
472 // searching. 473 // searching.
473 for (intptr_t i = 0; i < catch_entries_.length(); ++i) { 474 for (intptr_t i = 0; i < catch_entries_.length(); ++i) {
474 if (catch_entries_[i]->catch_try_index() == index) return catch_entries_[i]; 475 if (catch_entries_[i]->catch_try_index() == index) return catch_entries_[i];
475 } 476 }
476 return NULL; 477 return NULL;
477 } 478 }
478 479
479 480
480 static bool StartsWith(const String& name, const char* prefix, intptr_t n) {
481 ASSERT(name.IsOneByteString());
482
483 if (name.Length() < n) {
484 return false;
485 }
486
487 for (intptr_t i = 0; i < n; i++) {
488 if (name.CharAt(i) != prefix[i]) {
489 return false;
490 }
491 }
492
493 return true;
494 }
495
496
497 static bool CompareNames(const Library& lib,
498 const char* test_name,
499 const String& name) {
500 ASSERT(Library::kPrivateIdentifierStart == '_');
501 const char* kPrivateGetterPrefix = "get:_";
502 const char* kPrivateSetterPrefix = "set:_";
503
504 if (test_name[0] == Library::kPrivateIdentifierStart) {
505 if (name.CharAt(0) != Library::kPrivateIdentifierStart) {
506 return false;
507 }
508 } else if (strncmp(test_name,
509 kPrivateGetterPrefix,
510 strlen(kPrivateGetterPrefix)) == 0) {
511 if (!StartsWith(name, kPrivateGetterPrefix, strlen(kPrivateGetterPrefix))) {
512 return false;
513 }
514 } else if (strncmp(test_name,
515 kPrivateSetterPrefix,
516 strlen(kPrivateSetterPrefix)) == 0) {
517 if (!StartsWith(name, kPrivateSetterPrefix, strlen(kPrivateSetterPrefix))) {
518 return false;
519 }
520 } else {
521 // Compare without mangling.
522 return name.Equals(test_name);
523 }
524
525 // Both names are private. Mangle test_name before comparison.
526 // Check if this is a constructor (e.g., List,), in which case the mangler
527 // needs some help (see comment in Library::PrivateName).
528 String& test_name_symbol = String::Handle();
529 if (test_name[strlen(test_name) - 1] == '.') {
530 test_name_symbol = Symbols::New(test_name, strlen(test_name) - 1);
531 test_name_symbol = lib.PrivateName(test_name_symbol);
532 test_name_symbol = String::Concat(test_name_symbol, Symbols::Dot());
533 } else {
534 test_name_symbol = Symbols::New(test_name);
535 test_name_symbol = lib.PrivateName(test_name_symbol);
536 }
537 return test_name_symbol.Equals(name);
538 }
539
540
541 static bool IsRecognizedLibrary(const Library& library) {
542 // List of libraries where methods can be recognized.
543 return (library.raw() == Library::CoreLibrary())
544 || (library.raw() == Library::MathLibrary())
545 || (library.raw() == Library::TypedDataLibrary())
546 || (library.raw() == Library::InternalLibrary());
547 }
548
549
550 MethodRecognizer::Kind MethodRecognizer::RecognizeKind( 481 MethodRecognizer::Kind MethodRecognizer::RecognizeKind(
551 const Function& function) { 482 const Function& function) {
552 if (!function.is_recognized()) { 483 if (!function.is_recognized()) {
553 return kUnknown; 484 return kUnknown;
554 } 485 }
555 486
556 const Class& function_class = Class::Handle(function.Owner()); 487 const Class& function_class = Class::Handle(function.Owner());
557 const Library& lib = Library::Handle(function_class.library()); 488 const Library& lib = Library::Handle(function_class.library());
558 const String& function_name = String::Handle(function.name()); 489 const char* function_name = String::Handle(function.name()).ToCString();
srdjan 2014/08/18 18:04:49 ToCString is expensive, should not be used in perf
Florian Schneider 2014/08/18 18:22:57 The reason was that I use the existing comparison
559 const String& class_name = String::Handle(function_class.Name()); 490 const char* class_name = String::Handle(function_class.Name()).ToCString();
560 491
561 #define RECOGNIZE_FUNCTION(test_class_name, test_function_name, enum_name, fp) \ 492 #define RECOGNIZE_FUNCTION(test_class_name, test_function_name, enum_name, fp) \
562 if (CompareNames(lib, #test_function_name, function_name) && \ 493 if (Intrinsifier::TestFunction(lib, class_name, function_name, \
563 CompareNames(lib, #test_class_name, class_name)) { \ 494 #test_class_name, #test_function_name)) { \
564 ASSERT(function.CheckSourceFingerprint(fp)); \ 495 ASSERT(function.CheckSourceFingerprint(fp)); \
565 return k##enum_name; \ 496 return k##enum_name; \
566 } 497 }
567 RECOGNIZED_LIST(RECOGNIZE_FUNCTION) 498 RECOGNIZED_LIST(RECOGNIZE_FUNCTION)
568 #undef RECOGNIZE_FUNCTION 499 #undef RECOGNIZE_FUNCTION
569 UNREACHABLE(); 500 UNREACHABLE();
570 return kUnknown; 501 return kUnknown;
571 } 502 }
572 503
573 504
505 static bool IsRecognizedLibrary(const Library& library) {
506 // List of libraries where methods can be recognized.
507 return (library.raw() == Library::CoreLibrary())
508 || (library.raw() == Library::MathLibrary())
509 || (library.raw() == Library::TypedDataLibrary())
510 || (library.raw() == Library::InternalLibrary());
511 }
512
513
574 bool MethodRecognizer::AlwaysInline(const Function& function) { 514 bool MethodRecognizer::AlwaysInline(const Function& function) {
575 const Class& function_class = Class::Handle(function.Owner()); 515 const Class& function_class = Class::Handle(function.Owner());
576 const Library& lib = Library::Handle(function_class.library()); 516 const Library& lib = Library::Handle(function_class.library());
577 if (!IsRecognizedLibrary(lib)) { 517 if (!IsRecognizedLibrary(lib)) {
578 return false; 518 return false;
579 } 519 }
580 520
581 const String& function_name = String::Handle(function.name()); 521 const char* function_name = String::Handle(function.name()).ToCString();
582 const String& class_name = String::Handle(function_class.Name()); 522 const char* class_name = String::Handle(function_class.Name()).ToCString();
583 523
584 #define RECOGNIZE_FUNCTION(test_class_name, test_function_name, enum_name, fp) \ 524 #define RECOGNIZE_FUNCTION(test_class_name, test_function_name, enum_name, fp) \
585 if (CompareNames(lib, #test_function_name, function_name) && \ 525 if (Intrinsifier::TestFunction(lib, class_name, function_name, \
586 CompareNames(lib, #test_class_name, class_name)) { \ 526 #test_class_name, #test_function_name)) { \
587 ASSERT(function.CheckSourceFingerprint(fp)); \ 527 ASSERT(function.CheckSourceFingerprint(fp)); \
588 return true; \ 528 return true; \
589 } 529 }
590 INLINE_WHITE_LIST(RECOGNIZE_FUNCTION) 530 INLINE_WHITE_LIST(RECOGNIZE_FUNCTION)
591 #undef RECOGNIZE_FUNCTION 531 #undef RECOGNIZE_FUNCTION
592 return false; 532 return false;
593 } 533 }
594 534
595 535
596 bool MethodRecognizer::PolymorphicTarget(const Function& function) { 536 bool MethodRecognizer::PolymorphicTarget(const Function& function) {
597 const Class& function_class = Class::Handle(function.Owner()); 537 const Class& function_class = Class::Handle(function.Owner());
598 const Library& lib = Library::Handle(function_class.library()); 538 const Library& lib = Library::Handle(function_class.library());
599 if (!IsRecognizedLibrary(lib)) { 539 if (!IsRecognizedLibrary(lib)) {
600 return false; 540 return false;
601 } 541 }
602 542
603 const String& function_name = String::Handle(function.name()); 543 const char* function_name = String::Handle(function.name()).ToCString();
604 const String& class_name = String::Handle(function_class.Name()); 544 const char* class_name = String::Handle(function_class.Name()).ToCString();
605 545
606 #define RECOGNIZE_FUNCTION(test_class_name, test_function_name, enum_name, fp) \ 546 #define RECOGNIZE_FUNCTION(test_class_name, test_function_name, enum_name, fp) \
607 if (CompareNames(lib, #test_function_name, function_name) && \ 547 if (Intrinsifier::TestFunction(lib, class_name, function_name, \
608 CompareNames(lib, #test_class_name, class_name)) { \ 548 #test_class_name, #test_function_name)) { \
609 ASSERT(function.CheckSourceFingerprint(fp)); \ 549 ASSERT(function.CheckSourceFingerprint(fp)); \
610 return true; \ 550 return true; \
611 } 551 }
612 POLYMORPHIC_TARGET_LIST(RECOGNIZE_FUNCTION) 552 POLYMORPHIC_TARGET_LIST(RECOGNIZE_FUNCTION)
613 #undef RECOGNIZE_FUNCTION 553 #undef RECOGNIZE_FUNCTION
614 return false; 554 return false;
615 } 555 }
616 556
617 557
618 const char* MethodRecognizer::KindToCString(Kind kind) { 558 const char* MethodRecognizer::KindToCString(Kind kind) {
(...skipping 1846 matching lines...) Expand 10 before | Expand all | Expand 10 after
2465 void StaticCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2405 void StaticCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2466 const ICData* call_ic_data = NULL; 2406 const ICData* call_ic_data = NULL;
2467 if (!FLAG_propagate_ic_data || !compiler->is_optimizing()) { 2407 if (!FLAG_propagate_ic_data || !compiler->is_optimizing()) {
2468 const Array& arguments_descriptor = 2408 const Array& arguments_descriptor =
2469 Array::Handle(ArgumentsDescriptor::New(ArgumentCount(), 2409 Array::Handle(ArgumentsDescriptor::New(ArgumentCount(),
2470 argument_names())); 2410 argument_names()));
2471 // TODO(srdjan): Improve performance of function recognition. 2411 // TODO(srdjan): Improve performance of function recognition.
2472 MethodRecognizer::Kind recognized_kind = 2412 MethodRecognizer::Kind recognized_kind =
2473 MethodRecognizer::RecognizeKind(function()); 2413 MethodRecognizer::RecognizeKind(function());
2474 int num_args_checked = 0; 2414 int num_args_checked = 0;
2475 if ((recognized_kind == MethodRecognizer::kMathMin) || 2415 switch (recognized_kind) {
2476 (recognized_kind == MethodRecognizer::kMathMax)) { 2416 case MethodRecognizer::kDoubleFromInteger:
2477 num_args_checked = 2; 2417 num_args_checked = 1;
2418 break;
2419 case MethodRecognizer::kMathMin:
2420 case MethodRecognizer::kMathMax:
2421 num_args_checked = 2;
2422 break;
2423 default:
2424 break;
2478 } 2425 }
2479 call_ic_data = compiler->GetOrAddStaticCallICData(deopt_id(), 2426 call_ic_data = compiler->GetOrAddStaticCallICData(deopt_id(),
2480 function(), 2427 function(),
2481 arguments_descriptor, 2428 arguments_descriptor,
2482 num_args_checked); 2429 num_args_checked);
2483 } else { 2430 } else {
2484 call_ic_data = &ICData::ZoneHandle(ic_data()->raw()); 2431 call_ic_data = &ICData::ZoneHandle(ic_data()->raw());
2485 } 2432 }
2486 if (!compiler->is_optimizing()) { 2433 if (!compiler->is_optimizing()) {
2487 // Some static calls can be optimized by the optimizing compiler (e.g. sqrt) 2434 // Some static calls can be optimized by the optimizing compiler (e.g. sqrt)
(...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after
2962 case Token::kTRUNCDIV: return 0; 2909 case Token::kTRUNCDIV: return 0;
2963 case Token::kMOD: return 1; 2910 case Token::kMOD: return 1;
2964 default: UNIMPLEMENTED(); return -1; 2911 default: UNIMPLEMENTED(); return -1;
2965 } 2912 }
2966 } 2913 }
2967 2914
2968 2915
2969 #undef __ 2916 #undef __
2970 2917
2971 } // namespace dart 2918 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698