Chromium Code Reviews| 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 |