| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 // Class for intrinsifying functions. | 4 // Class for intrinsifying functions. |
| 5 | 5 |
| 6 #include "vm/intrinsifier.h" | 6 #include "vm/intrinsifier.h" |
| 7 #include "vm/flags.h" | 7 #include "vm/flags.h" |
| 8 #include "vm/object.h" | 8 #include "vm/object.h" |
| 9 #include "vm/symbols.h" |
| 9 | 10 |
| 10 namespace dart { | 11 namespace dart { |
| 11 | 12 |
| 12 DEFINE_FLAG(bool, intrinsify, true, "Instrinsify when possible"); | 13 DEFINE_FLAG(bool, intrinsify, true, "Instrinsify when possible"); |
| 13 | 14 |
| 14 | 15 |
| 15 static bool CompareNames(const char* test_name, const char* name) { | 16 static bool CompareNames(const Library& lib, |
| 17 const char* test_name, |
| 18 const char* name) { |
| 16 static const char* kPrivateGetterPrefix = "get:_"; | 19 static const char* kPrivateGetterPrefix = "get:_"; |
| 17 static const char* kPrivateSetterPrefix = "set:_"; | 20 static const char* kPrivateSetterPrefix = "set:_"; |
| 18 | 21 |
| 19 if (test_name[0] == '_') { | 22 if (test_name[0] == '_') { |
| 20 if (name[0] != '_') { | 23 if (name[0] != '_') { |
| 21 return false; | 24 return false; |
| 22 } | 25 } |
| 23 } else if (strncmp(test_name, | 26 } else if (strncmp(test_name, |
| 24 kPrivateGetterPrefix, | 27 kPrivateGetterPrefix, |
| 25 strlen(kPrivateGetterPrefix)) == 0) { | 28 strlen(kPrivateGetterPrefix)) == 0) { |
| 26 if (strncmp(name, | 29 if (strncmp(name, |
| 27 kPrivateGetterPrefix, | 30 kPrivateGetterPrefix, |
| 28 strlen(kPrivateGetterPrefix)) != 0) { | 31 strlen(kPrivateGetterPrefix)) != 0) { |
| 29 return false; | 32 return false; |
| 30 } | 33 } |
| 31 } else if (strncmp(test_name, | 34 } else if (strncmp(test_name, |
| 32 kPrivateSetterPrefix, | 35 kPrivateSetterPrefix, |
| 33 strlen(kPrivateSetterPrefix)) == 0) { | 36 strlen(kPrivateSetterPrefix)) == 0) { |
| 34 if (strncmp(name, | 37 if (strncmp(name, |
| 35 kPrivateSetterPrefix, | 38 kPrivateSetterPrefix, |
| 36 strlen(kPrivateSetterPrefix)) != 0) { | 39 strlen(kPrivateSetterPrefix)) != 0) { |
| 37 return false; | 40 return false; |
| 38 } | 41 } |
| 39 } else { | 42 } else { |
| 40 return (strcmp(test_name, name) == 0); | 43 return (strcmp(test_name, name) == 0); |
| 41 } | 44 } |
| 42 | 45 |
| 43 // Check if the private class is member of core or scalarlist and matches | 46 // Check if the private class is member of the library and matches |
| 44 // the test_class_name. | 47 // the test_class_name. |
| 45 const Library& core_lib = Library::Handle(Library::CoreLibrary()); | 48 const String& test_str = String::Handle(String::New(test_name)); |
| 46 const Library& scalarlist_lib = | 49 const String& test_str_with_key = String::Handle( |
| 47 Library::Handle(Library::ScalarlistLibrary()); | 50 String::Concat(test_str, String::Handle(lib.private_key()))); |
| 48 String& test_str = String::Handle(String::New(test_name)); | |
| 49 String& test_str_with_key = String::Handle(); | |
| 50 test_str_with_key = | |
| 51 String::Concat(test_str, String::Handle(core_lib.private_key())); | |
| 52 if (strcmp(test_str_with_key.ToCString(), name) == 0) { | |
| 53 return true; | |
| 54 } | |
| 55 test_str_with_key = | |
| 56 String::Concat(test_str, String::Handle(scalarlist_lib.private_key())); | |
| 57 if (strcmp(test_str_with_key.ToCString(), name) == 0) { | 51 if (strcmp(test_str_with_key.ToCString(), name) == 0) { |
| 58 return true; | 52 return true; |
| 59 } | 53 } |
| 60 | 54 |
| 61 return false; | 55 return false; |
| 62 } | 56 } |
| 63 | 57 |
| 64 | 58 |
| 65 // Returns true if the function matches function_name and class_name, with | 59 // Returns true if the function matches function_name and class_name, with |
| 66 // special recognition of corelib private classes. | 60 // special recognition of corelib private classes. |
| 67 static bool TestFunction(const Function& function, | 61 static bool TestFunction(const Library& lib, |
| 62 const Function& function, |
| 68 const char* function_class_name, | 63 const char* function_class_name, |
| 69 const char* function_name, | 64 const char* function_name, |
| 70 const char* test_class_name, | 65 const char* test_class_name, |
| 71 const char* test_function_name) { | 66 const char* test_function_name) { |
| 72 // If test_function_name starts with a '.' we use that to indicate | 67 return CompareNames(lib, test_class_name, function_class_name) && |
| 73 // that it is a named constructor in the class. Therefore, if | 68 CompareNames(lib, test_function_name, function_name); |
| 74 // the class matches and the rest of the method name starting with | |
| 75 // the dot matches, we have found a match. | |
| 76 if (test_function_name[0] == '.') { | |
| 77 function_name = strstr(function_name, "."); | |
| 78 if (function_name == NULL) { | |
| 79 return false; | |
| 80 } | |
| 81 } | |
| 82 return CompareNames(test_class_name, function_class_name) && | |
| 83 CompareNames(test_function_name, function_name); | |
| 84 } | 69 } |
| 85 | 70 |
| 86 | 71 |
| 87 bool Intrinsifier::CanIntrinsify(const Function& function) { | 72 bool Intrinsifier::CanIntrinsify(const Function& function) { |
| 88 if (!FLAG_intrinsify) return false; | 73 if (!FLAG_intrinsify) return false; |
| 89 if (function.IsClosureFunction()) return false; | 74 if (function.IsClosureFunction()) return false; |
| 90 // Can occur because of compile-all flag. | 75 // Can occur because of compile-all flag. |
| 91 if (function.is_external()) return false; | 76 if (function.is_external()) return false; |
| 92 // Intrinsic kind is set lazily below. | 77 return function.is_intrinsic(); |
| 93 if (function.intrinsic_kind() == Function::kIsIntrinsic) return true; | 78 } |
| 94 if (function.intrinsic_kind() == Function::kIsNotIntrinsic) return false; | 79 |
| 95 // Closure functions may have different arguments. | 80 |
| 96 const char* function_name = String::Handle(function.name()).ToCString(); | 81 void Intrinsifier::InitializeState() { |
| 97 const Class& function_class = Class::Handle(function.Owner()); | 82 Library& lib = Library::Handle(); |
| 98 // Only core, math and scalarlist library methods can be intrinsified. | 83 Class& cls = Class::Handle(); |
| 99 if ((function_class.library() != Library::CoreLibrary()) && | 84 Function& func = Function::Handle(); |
| 100 (function_class.library() != Library::MathLibrary()) && | 85 String& str = String::Handle(); |
| 101 (function_class.library() != Library::ScalarlistLibrary())) { | 86 |
| 102 return false; | 87 #define SETUP_FUNCTION(class_name, function_name, destination, fp) \ |
| 103 } | 88 if (strcmp(#class_name, "::") == 0) { \ |
| 104 const char* class_name = String::Handle(function_class.Name()).ToCString(); | 89 str = String::New(#function_name); \ |
| 105 #define FIND_INTRINSICS(test_class_name, test_function_name, destination, fp) \ | 90 func = lib.LookupFunctionAllowPrivate(str); \ |
| 106 if (TestFunction(function, \ | 91 } else { \ |
| 107 class_name, function_name, \ | 92 str = String::New(#class_name); \ |
| 108 #test_class_name, #test_function_name)) { \ | 93 cls = lib.LookupClassAllowPrivate(str); \ |
| 109 function.set_intrinsic_kind(Function::kIsIntrinsic); \ | 94 ASSERT(!cls.IsNull()); \ |
| 110 return true; \ | 95 str = String::New(#function_name); \ |
| 96 func = cls.LookupFunctionAllowPrivate(str); \ |
| 111 } \ | 97 } \ |
| 98 ASSERT(!func.IsNull()); \ |
| 99 func.set_is_intrinsic(true); \ |
| 112 | 100 |
| 113 INTRINSIC_LIST(FIND_INTRINSICS); | 101 // Set up all core lib functions that can be intrisified. |
| 114 #undef FIND_INTRINSICS | 102 lib = Library::CoreLibrary(); |
| 115 function.set_intrinsic_kind(Function::kIsNotIntrinsic); | 103 CORE_LIB_INTRINSIC_LIST(SETUP_FUNCTION); |
| 116 return false; | 104 |
| 105 // Set up all math lib functions that can be intrisified. |
| 106 lib = Library::MathLibrary(); |
| 107 MATH_LIB_INTRINSIC_LIST(SETUP_FUNCTION); |
| 108 |
| 109 // Set up all scalar list lib functions that can be intrisified. |
| 110 lib = Library::ScalarlistLibrary(); |
| 111 SCALARLIST_LIB_INTRINSIC_LIST(SETUP_FUNCTION); |
| 112 |
| 113 #undef SETUP_FUNCTION |
| 117 } | 114 } |
| 118 | 115 |
| 119 | 116 |
| 120 bool Intrinsifier::Intrinsify(const Function& function, Assembler* assembler) { | 117 bool Intrinsifier::Intrinsify(const Function& function, Assembler* assembler) { |
| 121 if (!CanIntrinsify(function)) return false; | 118 if (!CanIntrinsify(function)) return false; |
| 119 |
| 122 const char* function_name = String::Handle(function.name()).ToCString(); | 120 const char* function_name = String::Handle(function.name()).ToCString(); |
| 123 const Class& function_class = Class::Handle(function.Owner()); | 121 const Class& function_class = Class::Handle(function.Owner()); |
| 124 const char* class_name = String::Handle(function_class.Name()).ToCString(); | 122 const char* class_name = String::Handle(function_class.Name()).ToCString(); |
| 123 const Library& lib = Library::Handle(function_class.library()); |
| 124 |
| 125 #define FIND_INTRINSICS(test_class_name, test_function_name, destination, fp) \ | 125 #define FIND_INTRINSICS(test_class_name, test_function_name, destination, fp) \ |
| 126 if (TestFunction(function, \ | 126 if (TestFunction(lib, function, \ |
| 127 class_name, function_name, \ | 127 class_name, function_name, \ |
| 128 #test_class_name, #test_function_name)) { \ | 128 #test_class_name, #test_function_name)) { \ |
| 129 ASSERT(function.CheckSourceFingerprint(fp)); \ | 129 ASSERT(function.CheckSourceFingerprint(fp)); \ |
| 130 return destination(assembler); \ | 130 return destination(assembler); \ |
| 131 } \ | 131 } \ |
| 132 | 132 |
| 133 INTRINSIC_LIST(FIND_INTRINSICS); | 133 if (lib.raw() == Library::CoreLibrary()) { |
| 134 CORE_LIB_INTRINSIC_LIST(FIND_INTRINSICS); |
| 135 } else if (lib.raw() == Library::ScalarlistLibrary()) { |
| 136 SCALARLIST_LIB_INTRINSIC_LIST(FIND_INTRINSICS); |
| 137 } else if (lib.raw() == Library::MathLibrary()) { |
| 138 MATH_LIB_INTRINSIC_LIST(FIND_INTRINSICS); |
| 139 } |
| 140 return false; |
| 141 |
| 134 #undef FIND_INTRINSICS | 142 #undef FIND_INTRINSICS |
| 135 return false; | |
| 136 } | 143 } |
| 137 | 144 |
| 138 } // namespace dart | 145 } // namespace dart |
| OLD | NEW |