Flutter Engine
The Flutter Engine
intrinsifier.cc
Go to the documentation of this 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
3// BSD-style license that can be found in the LICENSE file.
4// Class for intrinsifying functions.
5
7
15#include "vm/cpu.h"
16#include "vm/flags.h"
17#include "vm/object.h"
18#include "vm/parser.h"
19#include "vm/symbols.h"
20
21namespace dart {
22
23DEFINE_FLAG(bool, intrinsify, true, "Instrinsify when possible");
24DEFINE_FLAG(bool, trace_intrinsifier, false, "Trace intrinsifier");
25
26namespace compiler {
27
28bool Intrinsifier::CanIntrinsify(const ParsedFunction& parsed_function) {
29 const Function& function = parsed_function.function();
30
31 if (FLAG_trace_intrinsifier) {
32 THR_Print("CanIntrinsify %s ->", function.ToQualifiedCString());
33 }
34 if (!FLAG_intrinsify) return false;
35 // TODO(regis): We do not need to explicitly filter generic functions here,
36 // unless there are errors we don't detect at link time. Revisit if necessary.
37 if (function.IsClosureFunction()) {
38 if (FLAG_trace_intrinsifier) {
39 THR_Print("No, closure function.\n");
40 }
41 return false;
42 }
43 // Can occur because of compile-all flag.
44 if (function.is_external()) {
45 if (FLAG_trace_intrinsifier) {
46 THR_Print("No, external function.\n");
47 }
48 return false;
49 }
50 if (!function.is_intrinsic()) {
51 if (FLAG_trace_intrinsifier) {
52 THR_Print("No, not intrinsic function.\n");
53 }
54 return false;
55 }
56 switch (function.recognized_kind()) {
57 case MethodRecognizer::kInt64ArrayGetIndexed:
58 case MethodRecognizer::kInt64ArraySetIndexed:
59 case MethodRecognizer::kUint64ArrayGetIndexed:
60 case MethodRecognizer::kUint64ArraySetIndexed:
61 // TODO(ajcbik): consider 32-bit as well.
62 if (target::kBitsPerWord == 64) {
63 break;
64 }
65 if (FLAG_trace_intrinsifier) {
66 THR_Print("No, 64-bit int intrinsic on 32-bit platform.\n");
67 }
68 return false;
69 default:
70 break;
71 }
72 if (FLAG_trace_intrinsifier) {
73 THR_Print("Yes.\n");
74 }
75 return true;
76}
77
79 const char* class_name;
80 const char* function_name;
81};
82
86};
87
88#define DEFINE_INTRINSIC(class_name, function_name, destination, fp) \
89 {#class_name, #function_name},
90
91// clang-format off
96 {nullptr, nullptr},
97};
98
101 {nullptr, nullptr},
102};
103
106 {nullptr, nullptr},
107};
108
111 {nullptr, nullptr},
112};
113// clang-format on
114
116 Thread* thread = Thread::Current();
117 Zone* zone = thread->zone();
118 Library& lib = Library::Handle(zone);
119 Class& cls = Class::Handle(zone);
120 Function& func = Function::Handle(zone);
121 String& str = String::Handle(zone);
122 String& str2 = String::Handle(zone);
123 Error& error = Error::Handle(zone);
124
125 const intptr_t kNumLibs = 4;
126 const LibraryIntrinsicsDesc intrinsics[kNumLibs] = {
133 };
134
135 for (intptr_t i = 0; i < kNumLibs; i++) {
136 lib = intrinsics[i].library.ptr();
137 for (const IntrinsicDesc* intrinsic = intrinsics[i].intrinsics;
138 intrinsic->class_name != nullptr; intrinsic++) {
139 func = Function::null();
140 if (strcmp(intrinsic->class_name, "::") == 0) {
141 str = String::New(intrinsic->function_name);
142 func = lib.LookupFunctionAllowPrivate(str);
143 } else {
144 str = String::New(intrinsic->class_name);
145 cls = lib.LookupClassAllowPrivate(str);
146 ASSERT(FLAG_precompiled_mode || !cls.IsNull());
147 if (!cls.IsNull()) {
148 error = cls.EnsureIsFinalized(thread);
149 if (!error.IsNull()) {
150 OS::PrintErr("%s\n", error.ToErrorCString());
151 }
152 ASSERT(error.IsNull());
153 str = String::New(intrinsic->function_name);
154 if (intrinsic->function_name[0] == '.') {
155 str2 = String::New(intrinsic->class_name);
156 str = String::Concat(str2, str);
157 }
158 func = cls.LookupFunctionAllowPrivate(str);
159 }
160 }
161 if (!func.IsNull()) {
162 func.set_is_intrinsic(true);
163 } else if (!FLAG_precompiled_mode) {
164 FATAL("Intrinsifier failed to find method %s in class %s\n",
165 intrinsic->function_name, intrinsic->class_name);
166 }
167 }
168 }
169#undef SETUP_FUNCTION
170}
171
172// Returns true if fall-through code can be omitted.
173bool Intrinsifier::Intrinsify(const ParsedFunction& parsed_function,
175 if (!CanIntrinsify(parsed_function)) {
176 return false;
177 }
178
179 if (GraphIntrinsifier::GraphIntrinsify(parsed_function, compiler)) {
180 return compiler->intrinsic_slow_path_label()->IsUnused();
181 }
182
183 const Function& function = parsed_function.function();
184#if !defined(HASH_IN_OBJECT_HEADER)
185 // These two are more complicated on 32 bit platforms, where the
186 // identity hash is not stored in the header of the object. We
187 // therefore don't intrinsify them, falling back on the native C++
188 // implementations.
189 if (function.recognized_kind() == MethodRecognizer::kObject_getHash) {
190 return false;
191 }
192#endif
193
194#if !defined(PRODUCT)
195#define EMIT_BREAKPOINT() compiler->assembler()->Breakpoint()
196#else
197#define EMIT_BREAKPOINT()
198#endif
199
200#define EMIT_CASE(class_name, function_name, enum_name, fp) \
201 case MethodRecognizer::k##enum_name: { \
202 compiler->assembler()->Comment("Intrinsic"); \
203 Label normal_ir_body; \
204 const auto size_before = compiler->assembler()->CodeSize(); \
205 AsmIntrinsifier::enum_name(compiler->assembler(), &normal_ir_body); \
206 const auto size_after = compiler->assembler()->CodeSize(); \
207 if (size_before == size_after) return false; \
208 if (function.HasUnboxedParameters()) { \
209 FATAL("Unsupported unboxed parameters in asm intrinsic %s", \
210 function.ToFullyQualifiedCString()); \
211 } \
212 if (function.HasUnboxedReturnValue()) { \
213 FATAL("Unsupported unboxed return value in asm intrinsic %s", \
214 function.ToFullyQualifiedCString()); \
215 } \
216 if (!normal_ir_body.IsBound()) { \
217 EMIT_BREAKPOINT(); \
218 return true; \
219 } \
220 return false; \
221 }
222
223 switch (function.recognized_kind()) {
225 default:
226 break;
227 }
228 switch (function.recognized_kind()) {
230 default:
231 break;
232 }
233
234#undef EMIT_BREAKPOINT
235
236#undef EMIT_INTRINSIC
237 return false;
238}
239
240} // namespace compiler
241} // namespace dart
FunctionPtr LookupFunctionAllowPrivate(const String &name) const
Definition: object.cc:6167
ErrorPtr EnsureIsFinalized(Thread *thread) const
Definition: object.cc:4924
static LibraryPtr CoreLibrary()
Definition: object.cc:14787
ClassPtr LookupClassAllowPrivate(const String &name) const
Definition: object.cc:14113
FunctionPtr LookupFunctionAllowPrivate(const String &name) const
Definition: object.cc:14084
static LibraryPtr InternalLibrary()
Definition: object.cc:14803
static LibraryPtr DeveloperLibrary()
Definition: object.cc:14795
static LibraryPtr TypedDataLibrary()
Definition: object.cc:14825
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
static ObjectPtr null()
Definition: object.h:433
ObjectPtr ptr() const
Definition: object.h:332
bool IsNull() const
Definition: object.h:363
static Object & Handle()
Definition: object.h:407
const Function & function() const
Definition: parser.h:73
static StringPtr New(const char *cstr, Heap::Space space=Heap::kNew)
Definition: object.cc:23698
static StringPtr Concat(const String &str1, const String &str2, Heap::Space space=Heap::kNew)
Definition: object.cc:24037
Zone * zone() const
Definition: thread_state.h:37
static Thread * Current()
Definition: thread.h:362
static bool GraphIntrinsify(const ParsedFunction &parsed_function, FlowGraphCompiler *compiler)
static bool Intrinsify(const ParsedFunction &parsed_function, FlowGraphCompiler *compiler)
#define THR_Print(format,...)
Definition: log.h:20
#define ASSERT(E)
#define FATAL(error)
const uint8_t uint32_t uint32_t GError ** error
Dart_NativeFunction function
Definition: fuchsia.cc:51
#define EMIT_CASE(class_name, function_name, enum_name, fp)
#define DEFINE_INTRINSIC(class_name, function_name, destination, fp)
Definition: intrinsifier.cc:88
static constexpr word kBitsPerWord
Definition: runtime_api.h:291
static const IntrinsicDesc developer_intrinsics[]
static const IntrinsicDesc core_intrinsics[]
Definition: intrinsifier.cc:92
static const IntrinsicDesc internal_intrinsics[]
static const IntrinsicDesc typed_data_intrinsics[]
Definition: intrinsifier.cc:99
Definition: dart_vm.cc:33
DEFINE_FLAG(bool, print_cluster_information, false, "Print information about clusters written to snapshot")
#define CORE_LIB_INTRINSIC_LIST(V)
#define GRAPH_TYPED_DATA_INTRINSICS_LIST(V)
#define INTERNAL_LIB_INTRINSIC_LIST(V)
#define CORE_INTEGER_LIB_INTRINSIC_LIST(V)
#define GRAPH_CORE_INTRINSICS_LIST(V)
#define DEVELOPER_LIB_INTRINSIC_LIST(V)
#define ALL_INTRINSICS_NO_INTEGER_LIB_LIST(V)