| 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/assembler.h" | 6 #include "vm/assembler.h" |
| 7 #include "vm/intrinsifier.h" | 7 #include "vm/intrinsifier.h" |
| 8 #include "vm/flags.h" | 8 #include "vm/flags.h" |
| 9 #include "vm/object.h" | 9 #include "vm/object.h" |
| 10 #include "vm/symbols.h" | 10 #include "vm/symbols.h" |
| 11 | 11 |
| 12 namespace dart { | 12 namespace dart { |
| 13 | 13 |
| 14 DEFINE_FLAG(bool, intrinsify, true, "Instrinsify when possible"); | 14 DEFINE_FLAG(bool, intrinsify, true, "Instrinsify when possible"); |
| 15 DECLARE_FLAG(bool, throw_on_javascript_int_overflow); | 15 DECLARE_FLAG(bool, throw_on_javascript_int_overflow); |
| 16 | 16 |
| 17 static bool CompareNames(const Library& lib, | |
| 18 const char* test_name, | |
| 19 const char* name) { | |
| 20 static const char* kPrivateGetterPrefix = "get:_"; | |
| 21 static const char* kPrivateSetterPrefix = "set:_"; | |
| 22 | |
| 23 if (test_name[0] == '_') { | |
| 24 if (name[0] != '_') { | |
| 25 return false; | |
| 26 } | |
| 27 } else if (strncmp(test_name, | |
| 28 kPrivateGetterPrefix, | |
| 29 strlen(kPrivateGetterPrefix)) == 0) { | |
| 30 if (strncmp(name, | |
| 31 kPrivateGetterPrefix, | |
| 32 strlen(kPrivateGetterPrefix)) != 0) { | |
| 33 return false; | |
| 34 } | |
| 35 } else if (strncmp(test_name, | |
| 36 kPrivateSetterPrefix, | |
| 37 strlen(kPrivateSetterPrefix)) == 0) { | |
| 38 if (strncmp(name, | |
| 39 kPrivateSetterPrefix, | |
| 40 strlen(kPrivateSetterPrefix)) != 0) { | |
| 41 return false; | |
| 42 } | |
| 43 } else { | |
| 44 return (strcmp(test_name, name) == 0); | |
| 45 } | |
| 46 | |
| 47 // Check if the private class is member of the library and matches | |
| 48 // the test_class_name. | |
| 49 const String& test_str = String::Handle(String::New(test_name)); | |
| 50 const String& test_str_with_key = String::Handle( | |
| 51 String::Concat(test_str, String::Handle(lib.private_key()))); | |
| 52 if (strcmp(test_str_with_key.ToCString(), name) == 0) { | |
| 53 return true; | |
| 54 } | |
| 55 | |
| 56 return false; | |
| 57 } | |
| 58 | |
| 59 | |
| 60 // Returns true if the function matches function_name and class_name, with | |
| 61 // special recognition of corelib private classes. | |
| 62 static bool TestFunction(const Library& lib, | |
| 63 const Function& function, | |
| 64 const char* function_class_name, | |
| 65 const char* function_name, | |
| 66 const char* test_class_name, | |
| 67 const char* test_function_name) { | |
| 68 // If test_function_name starts with a '.' we use that to indicate | |
| 69 // that it is a named constructor in the class. Therefore, if | |
| 70 // the class matches and the rest of the method name starting with | |
| 71 // the dot matches, we have found a match. | |
| 72 // We do not store the entire factory constructor name with the class | |
| 73 // (e.g: _GrowableList.withData) because the actual function name | |
| 74 // that we see here includes the private key. | |
| 75 if (test_function_name[0] == '.') { | |
| 76 function_name = strstr(function_name, "."); | |
| 77 if (function_name == NULL) { | |
| 78 return false; | |
| 79 } | |
| 80 } | |
| 81 return CompareNames(lib, test_class_name, function_class_name) && | |
| 82 CompareNames(lib, test_function_name, function_name); | |
| 83 } | |
| 84 | |
| 85 | |
| 86 bool Intrinsifier::CanIntrinsify(const Function& function) { | 17 bool Intrinsifier::CanIntrinsify(const Function& function) { |
| 87 if (!FLAG_intrinsify) return false; | 18 if (!FLAG_intrinsify) return false; |
| 88 if (function.IsClosureFunction()) return false; | 19 if (function.IsClosureFunction()) return false; |
| 89 // Can occur because of compile-all flag. | 20 // Can occur because of compile-all flag. |
| 90 if (function.is_external()) return false; | 21 if (function.is_external()) return false; |
| 91 return function.is_intrinsic(); | 22 return function.is_intrinsic(); |
| 92 } | 23 } |
| 93 | 24 |
| 94 | 25 |
| 95 void Intrinsifier::InitializeState() { | 26 void Intrinsifier::InitializeState() { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 120 } \ | 51 } \ |
| 121 func = cls.LookupFunctionAllowPrivate(str); \ | 52 func = cls.LookupFunctionAllowPrivate(str); \ |
| 122 } \ | 53 } \ |
| 123 ASSERT(!func.IsNull()); \ | 54 ASSERT(!func.IsNull()); \ |
| 124 func.set_is_intrinsic(true); | 55 func.set_is_intrinsic(true); |
| 125 | 56 |
| 126 // Set up all core lib functions that can be intrisified. | 57 // Set up all core lib functions that can be intrisified. |
| 127 lib = Library::CoreLibrary(); | 58 lib = Library::CoreLibrary(); |
| 128 ASSERT(!lib.IsNull()); | 59 ASSERT(!lib.IsNull()); |
| 129 CORE_LIB_INTRINSIC_LIST(SETUP_FUNCTION); | 60 CORE_LIB_INTRINSIC_LIST(SETUP_FUNCTION); |
| 130 | 61 CORE_INTEGER_LIB_INTRINSIC_LIST(SETUP_FUNCTION); |
| 131 // Integer intrinsics are in the core library, but we don't want to intrinsify | |
| 132 // when Smi > 32 bits if we are looking for javascript integer overflow. | |
| 133 if (!FLAG_throw_on_javascript_int_overflow || (Smi::kBits < 32)) { | |
| 134 CORE_INTEGER_LIB_INTRINSIC_LIST(SETUP_FUNCTION); | |
| 135 } | |
| 136 | 62 |
| 137 // Set up all math lib functions that can be intrisified. | 63 // Set up all math lib functions that can be intrisified. |
| 138 lib = Library::MathLibrary(); | 64 lib = Library::MathLibrary(); |
| 139 ASSERT(!lib.IsNull()); | 65 ASSERT(!lib.IsNull()); |
| 140 MATH_LIB_INTRINSIC_LIST(SETUP_FUNCTION); | 66 MATH_LIB_INTRINSIC_LIST(SETUP_FUNCTION); |
| 141 | 67 |
| 142 // Set up all dart:typed_data lib functions that can be intrisified. | 68 // Set up all dart:typed_data lib functions that can be intrisified. |
| 143 lib = Library::TypedDataLibrary(); | 69 lib = Library::TypedDataLibrary(); |
| 144 ASSERT(!lib.IsNull()); | 70 ASSERT(!lib.IsNull()); |
| 145 TYPED_DATA_LIB_INTRINSIC_LIST(SETUP_FUNCTION); | 71 TYPED_DATA_LIB_INTRINSIC_LIST(SETUP_FUNCTION); |
| 146 | 72 |
| 147 // Setup all dart:profiler lib functions that can be intrinsified. | 73 // Setup all dart:profiler lib functions that can be intrinsified. |
| 148 lib = Library::ProfilerLibrary(); | 74 lib = Library::ProfilerLibrary(); |
| 149 ASSERT(!lib.IsNull()); | 75 ASSERT(!lib.IsNull()); |
| 150 PROFILER_LIB_INTRINSIC_LIST(SETUP_FUNCTION); | 76 PROFILER_LIB_INTRINSIC_LIST(SETUP_FUNCTION); |
| 151 | 77 |
| 152 #undef SETUP_FUNCTION | 78 #undef SETUP_FUNCTION |
| 153 } | 79 } |
| 154 | 80 |
| 155 | 81 |
| 156 void Intrinsifier::Intrinsify(const Function& function, Assembler* assembler) { | 82 void Intrinsifier::Intrinsify(const Function& function, Assembler* assembler) { |
| 157 if (!CanIntrinsify(function)) return; | 83 if (!CanIntrinsify(function)) return; |
| 158 | 84 |
| 159 const char* function_name = String::Handle(function.name()).ToCString(); | 85 #define EMIT_CASE(test_class_name, test_function_name, enum_name, fp) \ |
| 160 const Class& function_class = Class::Handle(function.Owner()); | 86 case MethodRecognizer::k##enum_name: \ |
| 161 const char* class_name = String::Handle(function_class.Name()).ToCString(); | 87 ASSERT(function.CheckSourceFingerprint(fp)); \ |
| 162 const Library& lib = Library::Handle(function_class.library()); | 88 assembler->Comment("Intrinsic"); \ |
| 89 enum_name(assembler); \ |
| 90 break; |
| 163 | 91 |
| 164 #define FIND_INTRINSICS(test_class_name, test_function_name, destination, fp) \ | 92 if (FLAG_throw_on_javascript_int_overflow && (Smi::kBits >= 32)) { |
| 165 if (TestFunction(lib, function, \ | 93 // Integer intrinsics are in the core library, but we don't want to |
| 166 class_name, function_name, \ | 94 // intrinsify when Smi > 32 bits if we are looking for javascript integer |
| 167 #test_class_name, #test_function_name)) { \ | 95 // overflow. |
| 168 ASSERT(function.CheckSourceFingerprint(fp)); \ | 96 switch (function.recognized_kind()) { |
| 169 assembler->Comment("Intrinsic"); \ | 97 CORE_LIB_INTRINSIC_LIST(EMIT_CASE); |
| 170 destination(assembler); \ | 98 MATH_LIB_INTRINSIC_LIST(EMIT_CASE); |
| 171 return; \ | 99 TYPED_DATA_LIB_INTRINSIC_LIST(EMIT_CASE); |
| 172 } \ | 100 PROFILER_LIB_INTRINSIC_LIST(EMIT_CASE); |
| 173 | 101 default: |
| 174 if (lib.raw() == Library::CoreLibrary()) { | 102 break; |
| 175 CORE_LIB_INTRINSIC_LIST(FIND_INTRINSICS); | |
| 176 if (!FLAG_throw_on_javascript_int_overflow || (Smi::kBits < 32)) { | |
| 177 CORE_INTEGER_LIB_INTRINSIC_LIST(FIND_INTRINSICS); | |
| 178 } | 103 } |
| 179 } else if (lib.raw() == Library::TypedDataLibrary()) { | 104 } else { |
| 180 TYPED_DATA_LIB_INTRINSIC_LIST(FIND_INTRINSICS); | 105 switch (function.recognized_kind()) { |
| 181 } else if (lib.raw() == Library::MathLibrary()) { | 106 CORE_LIB_INTRINSIC_LIST(EMIT_CASE); |
| 182 MATH_LIB_INTRINSIC_LIST(FIND_INTRINSICS); | 107 CORE_INTEGER_LIB_INTRINSIC_LIST(EMIT_CASE); |
| 183 } else if (lib.raw() == Library::ProfilerLibrary()) { | 108 MATH_LIB_INTRINSIC_LIST(EMIT_CASE); |
| 184 PROFILER_LIB_INTRINSIC_LIST(FIND_INTRINSICS); | 109 TYPED_DATA_LIB_INTRINSIC_LIST(EMIT_CASE); |
| 110 PROFILER_LIB_INTRINSIC_LIST(EMIT_CASE); |
| 111 default: |
| 112 UNREACHABLE(); |
| 113 break; |
| 114 } |
| 185 } | 115 } |
| 186 #undef FIND_INTRINSICS | 116 #undef EMIT_INTRINSIC |
| 187 } | 117 } |
| 188 | 118 |
| 189 } // namespace dart | 119 } // namespace dart |
| OLD | NEW |