OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |