Flutter Engine
The Flutter Engine
parser.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
5#include "vm/parser.h"
6#include "vm/flags.h"
7
8#if !defined(DART_PRECOMPILED_RUNTIME)
9
11#include "platform/utils.h"
12#include "vm/bit_vector.h"
13#include "vm/bootstrap.h"
14#include "vm/class_finalizer.h"
19#include "vm/dart_api_impl.h"
20#include "vm/dart_entry.h"
21#include "vm/growable_array.h"
22#include "vm/handles.h"
23#include "vm/hash_table.h"
24#include "vm/isolate.h"
25#include "vm/longjump.h"
26#include "vm/native_arguments.h"
27#include "vm/native_entry.h"
28#include "vm/object.h"
29#include "vm/object_store.h"
30#include "vm/os.h"
31#include "vm/regexp_assembler.h"
32#include "vm/resolver.h"
33#include "vm/scopes.h"
34#include "vm/stack_frame.h"
35#include "vm/symbols.h"
36#include "vm/tags.h"
37#include "vm/timeline.h"
38#include "vm/zone.h"
39
40namespace dart {
41
42// Quick access to the current thread, isolate and zone.
43#define T (thread())
44#define I (isolate())
45#define Z (zone())
46
48 : thread_(thread),
49 function_(function),
50 code_(Code::Handle(zone(), function.unoptimized_code())),
51 scope_(nullptr),
52 regexp_compile_data_(nullptr),
53 function_type_arguments_(nullptr),
54 parent_type_arguments_(nullptr),
55 current_context_var_(nullptr),
56 arg_desc_var_(nullptr),
57 expression_temp_var_(nullptr),
58 entry_points_temp_var_(nullptr),
59 finally_return_temp_var_(nullptr),
60 dynamic_closure_call_vars_(nullptr),
61 guarded_fields_(),
62 default_parameter_values_(nullptr),
63 raw_type_arguments_var_(nullptr),
64 first_parameter_index_(),
65 num_stack_locals_(0),
66 have_seen_await_expr_(false),
67 kernel_scopes_(nullptr) {
68 DEBUG_ASSERT(function.IsNotTemporaryScopedHandle());
69 // Every function has a local variable for the current context.
70 LocalVariable* temp = new (zone())
72 Symbols::CurrentContextVar(), Object::dynamic_type());
73 current_context_var_ = temp;
74
76 arg_desc_var_ = new (zone())
77 LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
78 Symbols::ArgDescVar(), Object::dynamic_type());
79 }
80
81 // The code generated by the prologue builder for loading optional arguments
82 // requires the expression temporary variable.
85 }
86}
87
88void ParsedFunction::AddToGuardedFields(const Field* field) const {
89 if ((field->guarded_cid() == kDynamicCid) ||
90 (field->guarded_cid() == kIllegalCid)) {
91 return;
92 }
93
94 const Field** other = guarded_fields_.Lookup(field);
95 if (other != nullptr) {
96 ASSERT(field->Original() == (*other)->Original());
97 // Abort background compilation early if the guarded state of this field
98 // has changed during compilation. We will not be able to commit
99 // the resulting code anyway.
101 if (!(*other)->IsConsistentWith(*field)) {
103 DeoptId::kNone, "Field's guarded state changed during compilation");
104 }
105 }
106 return;
107 }
108
109 // Note: the list of guarded fields must contain copies during optimizing
110 // compilation because we will look at their guarded_cid when copying
111 // the array of guarded fields from callee into the caller during
112 // inlining.
113 ASSERT(field->IsOriginal() ==
115 guarded_fields_.Insert(&Field::ZoneHandle(Z, field->ptr()));
116}
117
118void ParsedFunction::Bailout(const char* origin, const char* reason) const {
120 function_.token_pos(), Report::AtLocation,
121 "%s Bailout in %s: %s", origin,
122 String::Handle(function_.name()).ToCString(), reason);
123 UNREACHABLE();
124}
125
127 if (kernel_scopes_ == nullptr) {
129 kernel_scopes_ = builder.BuildScopes();
130 }
131 return kernel_scopes_;
132}
133
136 LocalVariable* temp =
137 new (Z) LocalVariable(function_.token_pos(), function_.token_pos(),
138 Symbols::ExprTemp(), Object::dynamic_type());
139 ASSERT(temp != nullptr);
141 }
143 return expression_temp_var();
144}
145
148 LocalVariable* temp = new (Z)
149 LocalVariable(function_.token_pos(), function_.token_pos(),
150 Symbols::EntryPointsTemp(), Object::dynamic_type());
151 ASSERT(temp != nullptr);
153 }
155 return entry_points_temp_var();
156}
157
160 LocalVariable* temp =
161 new (Z) LocalVariable(function_.token_pos(), function_.token_pos(),
162 Symbols::FinallyRetVal(), Object::dynamic_type());
163 ASSERT(temp != nullptr);
164 temp->set_is_final();
165 if (is_async) {
166 temp->set_is_captured();
167 }
169 }
171}
172
174 RegExpCompileData* regexp_compile_data) {
175 ASSERT(regexp_compile_data_ == nullptr);
176 ASSERT(regexp_compile_data != nullptr);
177 regexp_compile_data_ = regexp_compile_data;
178}
179
181 ASSERT(!function().IsIrregexpFunction());
182 LocalScope* scope = this->scope();
183 const intptr_t num_fixed_params = function().num_fixed_parameters();
184 const intptr_t num_opt_params = function().NumOptionalParameters();
185 const intptr_t num_params = num_fixed_params + num_opt_params;
186 const bool copy_parameters = function().MakesCopyOfParameters();
187
188 // Before we start allocating indices to variables, we'll setup the
189 // parameters array, which can be used to access the raw parameters (i.e. not
190 // the potentially variables which are in the context)
191
192 raw_parameters_ = new (Z) ZoneGrowableArray<LocalVariable*>(Z, num_params);
193 for (intptr_t param = 0; param < num_params; ++param) {
194 LocalVariable* variable = ParameterVariable(param);
195 LocalVariable* raw_parameter = variable;
196 if (variable->is_captured()) {
198 tmp = Symbols::FromConcat(T, Symbols::OriginalParam(), variable->name());
199
201 tmp, variable->kernel_offset()) == nullptr);
202 raw_parameter = new LocalVariable(
203 variable->declaration_token_pos(), variable->token_pos(), tmp,
204 variable->static_type(), variable->kernel_offset(),
205 variable->inferred_type(), variable->inferred_arg_type(),
206 variable->inferred_arg_value());
207 raw_parameter->set_annotations_offset(variable->annotations_offset());
208 if (variable->is_explicit_covariant_parameter()) {
210 }
211 if (variable->needs_covariant_check_in_method()) {
213 }
214 raw_parameter->set_type_check_mode(variable->type_check_mode());
215 if (copy_parameters) {
216 bool ok = scope->AddVariable(raw_parameter);
217 ASSERT(ok);
218
219 // Currently our optimizer cannot prove liveness of variables properly
220 // when a function has try/catch. It therefore makes the conservative
221 // estimate that all [LocalVariable]s in the frame are live and spills
222 // them before call sites (in some shape or form).
223 //
224 // Since we are guaranteed to not need that, we tell the try/catch
225 // sync moves mechanism not to care about this variable.
226 //
227 // Receiver (this variable) is an exception from this rule because
228 // it is immutable and we don't reload captured it from the context but
229 // instead use raw_parameter to access it. This means we must still
230 // consider it when emitting the catch entry moves.
231 const bool is_receiver_var =
232 function().HasThisParameter() && receiver_var_ == variable;
233 if (!is_receiver_var) {
234 raw_parameter->set_is_captured_parameter(true);
235 }
236
237 } else {
238 raw_parameter->set_index(
239 VariableIndex(function().NumParameters() - param));
240 }
241 }
242 raw_parameters_->Add(raw_parameter);
243 }
244 if (function_type_arguments_ != nullptr) {
245 LocalVariable* raw_type_args_parameter = function_type_arguments_;
246 if (function_type_arguments_->is_captured()) {
248 tmp = Symbols::FromConcat(T, Symbols::OriginalParam(),
249 function_type_arguments_->name());
250
252 tmp, function_type_arguments_->kernel_offset()) == nullptr);
253 raw_type_args_parameter =
254 new LocalVariable(function_type_arguments_->declaration_token_pos(),
255 function_type_arguments_->token_pos(), tmp,
256 function_type_arguments_->static_type(),
257 function_type_arguments_->kernel_offset());
258 bool ok = scope->AddVariable(raw_type_args_parameter);
259 ASSERT(ok);
260 }
261 raw_type_arguments_var_ = raw_type_args_parameter;
262 }
263
264 // The copy parameters implementation will still write to local variables
265 // which we assign indices as with the old CopyParams implementation.
266 VariableIndex first_local_index;
267 {
268 // Compute start indices to parameters and locals, and the number of
269 // parameters to copy.
270 if (!copy_parameters) {
271 ASSERT(suspend_state_var() == nullptr);
272 first_parameter_index_ = VariableIndex(num_params);
273 first_local_index = VariableIndex(0);
274 } else {
275 // :suspend_state variable is inserted at the fixed slot
276 // before the copied parameters.
277 const intptr_t reserved_var_slot_count =
278 (suspend_state_var() != nullptr) ? 1 : 0;
279 first_parameter_index_ = VariableIndex(-reserved_var_slot_count);
280 first_local_index =
281 VariableIndex(first_parameter_index_.value() - num_params);
282 }
283 }
284
285 // Allocate parameters and local variables, either in the local frame or
286 // in the context(s).
287 bool found_captured_variables = false;
288 VariableIndex next_free_index = scope->AllocateVariables(
289 function(), first_parameter_index_, num_params, first_local_index,
290 nullptr, &found_captured_variables);
291
292 num_stack_locals_ = -next_free_index.value();
293}
294
295void ParsedFunction::AllocateIrregexpVariables(intptr_t num_stack_locals) {
296 ASSERT(function().IsIrregexpFunction());
297 ASSERT(function().NumOptionalParameters() == 0);
298 const intptr_t num_params = function().num_fixed_parameters();
300 // Compute start indices to parameters and locals, and the number of
301 // parameters to copy.
302 first_parameter_index_ = VariableIndex(num_params);
303
304 // Frame indices are relative to the frame pointer and are decreasing.
305 num_stack_locals_ = num_stack_locals;
306}
307
309 const BitVector* covariant_parameters) {
310 ASSERT(covariant_parameters_ == nullptr);
311 ASSERT(covariant_parameters->length() == function_.NumParameters());
312 covariant_parameters_ = covariant_parameters;
313}
314
316 const BitVector* generic_covariant_impl_parameters) {
317 ASSERT(generic_covariant_impl_parameters_ == nullptr);
318 ASSERT(generic_covariant_impl_parameters->length() ==
319 function_.NumParameters());
320 generic_covariant_impl_parameters_ = generic_covariant_impl_parameters;
321}
322
324 ASSERT(covariant_parameters_ != nullptr);
325 ASSERT((i >= 0) && (i < function_.NumParameters()));
326 return covariant_parameters_->Contains(i);
327}
328
330 ASSERT(generic_covariant_impl_parameters_ != nullptr);
331 ASSERT((i >= 0) && (i < function_.NumParameters()));
332 return generic_covariant_impl_parameters_->Contains(i);
333}
334
337 ASSERT(function().IsDynamicClosureCallDispatcher(thread()));
338 if (dynamic_closure_call_vars_ != nullptr) return dynamic_closure_call_vars_;
339 const auto& saved_args_desc =
340 Array::Handle(zone(), function().saved_args_desc());
341 const ArgumentsDescriptor descriptor(saved_args_desc);
342
343 dynamic_closure_call_vars_ =
344 new (zone()) DynamicClosureCallVars(zone(), descriptor.NamedCount());
345
346 auto const pos = function().token_pos();
347 const auto& type_Dynamic = Object::dynamic_type();
348 const auto& type_Function =
350 const auto& type_Smi = Type::ZoneHandle(zone(), Type::SmiType());
351#define INIT_FIELD(Name, TypeName, Symbol) \
352 dynamic_closure_call_vars_->Name = new (zone()) LocalVariable( \
353 pos, pos, Symbols::DynamicCall##Symbol##Var(), type_##TypeName);
355#undef INIT_FIELD
356
357 for (intptr_t i = 0; i < descriptor.NamedCount(); i++) {
358 auto const name = OS::SCreate(
359 zone(), ":dyn_call_named_argument_%" Pd "_parameter_index", i);
360 auto const var = new (zone()) LocalVariable(
362 type_Smi);
363 dynamic_closure_call_vars_->named_argument_parameter_indices.Add(var);
364 }
365
366 return dynamic_closure_call_vars_;
367}
368
369} // namespace dart
370
371#endif // !defined(DART_PRECOMPILED_RUNTIME)
SkPoint pos
static bool ok(int result)
#define UNREACHABLE()
Definition: assert.h:248
#define DEBUG_ASSERT(cond)
Definition: assert.h:321
#define RELEASE_ASSERT(cond)
Definition: assert.h:327
intptr_t NamedCount() const
Definition: dart_entry.h:43
void Insert(typename KeyValueTrait::Pair kv)
Definition: hash_map.h:230
KeyValueTrait::Pair * Lookup(typename KeyValueTrait::Key key) const
Definition: hash_map.h:130
intptr_t length() const
Definition: bit_vector.h:117
bool Contains(intptr_t i) const
Definition: bit_vector.h:91
static CompilerState & Current()
static bool IsBackgroundCompilation()
Definition: compiler.cc:298
static void AbortBackgroundCompilation(intptr_t deopt_id, const char *msg)
Definition: compiler.cc:971
static constexpr intptr_t kNone
Definition: deopt_id.h:27
bool IsOriginal() const
Definition: object.h:4418
FieldPtr Original() const
Definition: object.cc:11739
intptr_t guarded_cid() const
Definition: object.cc:11749
bool PrologueNeedsArgumentsDescriptor() const
Definition: object.cc:11437
intptr_t NumOptionalParameters() const
Definition: object.cc:8868
bool MakesCopyOfParameters() const
Definition: object.h:3514
bool HasOptionalParameters() const
Definition: object.cc:8859
StringPtr name() const
Definition: object.h:2992
TokenPosition token_pos() const
Definition: object.h:3446
ScriptPtr script() const
Definition: object.cc:10881
bool HasThisParameter() const
Definition: object.h:3369
intptr_t num_fixed_parameters() const
Definition: object.cc:8856
intptr_t NumParameters() const
Definition: object.cc:8877
VariableIndex AllocateVariables(const Function &function, VariableIndex first_parameter_index, int num_parameters, VariableIndex first_local_index, LocalScope *context_owner, bool *found_captured_variables)
Definition: scopes.cc:133
bool AddVariable(LocalVariable *variable)
Definition: scopes.cc:57
LocalVariable * LocalLookupVariable(const String &name, intptr_t kernel_offset) const
Definition: scopes.cc:336
CompileType * inferred_type() const
Definition: scopes.h:136
void set_needs_covariant_check_in_method()
Definition: scopes.h:176
intptr_t annotations_offset() const
Definition: scopes.h:121
void set_is_captured()
Definition: scopes.h:144
bool is_captured() const
Definition: scopes.h:143
void set_is_explicit_covariant_parameter()
Definition: scopes.h:171
void set_type_check_mode(TypeCheckMode mode)
Definition: scopes.h:199
TokenPosition declaration_token_pos() const
Definition: scopes.h:118
void set_is_final()
Definition: scopes.h:141
TokenPosition token_pos() const
Definition: scopes.h:117
void set_index(VariableIndex index)
Definition: scopes.h:208
TypeCheckMode type_check_mode() const
Definition: scopes.h:198
const Object * inferred_arg_value() const
Definition: scopes.h:138
void set_annotations_offset(intptr_t offset)
Definition: scopes.h:128
const AbstractType & static_type() const
Definition: scopes.h:134
intptr_t kernel_offset() const
Definition: scopes.h:120
const String & name() const
Definition: scopes.h:119
void set_is_captured_parameter(bool value)
Definition: scopes.h:223
bool needs_covariant_check_in_method() const
Definition: scopes.h:173
CompileType * inferred_arg_type() const
Definition: scopes.h:137
bool is_explicit_covariant_parameter() const
Definition: scopes.h:168
static char * SCreate(Zone *zone, const char *format,...) PRINTF_ATTRIBUTE(2
ObjectPtr ptr() const
Definition: object.h:332
virtual const char * ToCString() const
Definition: object.h:366
static Object & Handle()
Definition: object.h:407
static Object & ZoneHandle()
Definition: object.h:419
void Bailout(const char *origin, const char *reason) const
Definition: parser.cc:118
bool has_entry_points_temp_var() const
Definition: parser.h:171
void SetRegExpCompileData(RegExpCompileData *regexp_compile_data)
Definition: parser.cc:173
LocalVariable * expression_temp_var() const
Definition: parser.h:151
ParsedFunction(Thread *thread, const Function &function)
Definition: parser.cc:47
const Function & function() const
Definition: parser.h:73
int num_stack_locals() const
Definition: parser.h:194
LocalScope * scope() const
Definition: parser.h:76
kernel::ScopeBuildingResult * EnsureKernelScopes()
Definition: parser.cc:126
void AddToGuardedFields(const Field *field) const
Definition: parser.cc:88
LocalVariable * EnsureExpressionTemp()
Definition: parser.cc:134
void set_expression_temp_var(LocalVariable *value)
Definition: parser.h:155
LocalVariable * EnsureEntryPointsTemp()
Definition: parser.cc:146
void EnsureFinallyReturnTemp(bool is_async)
Definition: parser.cc:158
void AllocateIrregexpVariables(intptr_t num_stack_locals)
Definition: parser.cc:295
void set_entry_points_temp_var(LocalVariable *value)
Definition: parser.h:167
LocalVariable * entry_points_temp_var() const
Definition: parser.h:163
bool IsGenericCovariantImplParameter(intptr_t i) const
Definition: parser.cc:329
void SetCovariantParameters(const BitVector *covariant_parameters)
Definition: parser.cc:308
RegExpCompileData * regexp_compile_data() const
Definition: parser.h:83
Zone * zone() const
Definition: parser.h:213
Thread * thread() const
Definition: parser.h:211
void AllocateVariables()
Definition: parser.cc:180
LocalVariable * ParameterVariable(intptr_t i) const
Definition: parser.h:239
void set_finally_return_temp_var(LocalVariable *value)
Definition: parser.h:179
LocalVariable * suspend_state_var() const
Definition: parser.h:103
bool IsCovariantParameter(intptr_t i) const
Definition: parser.cc:323
bool has_expression_temp_var() const
Definition: parser.h:159
bool has_finally_return_temp_var() const
Definition: parser.h:183
void SetGenericCovariantImplParameters(const BitVector *generic_covariant_impl_parameters)
Definition: parser.cc:315
DynamicClosureCallVars * EnsureDynamicClosureCallVars()
Definition: parser.cc:336
static void MessageF(Kind kind, const Script &script, TokenPosition token_pos, bool report_after_token, const char *format,...) PRINTF_ATTRIBUTE(5
Definition: report.cc:123
@ kBailout
Definition: report.h:26
static constexpr bool AtLocation
Definition: report.h:29
static StringPtr FromConcat(Thread *thread, const String &str1, const String &str2)
Definition: symbols.cc:235
static StringPtr New(Thread *thread, const char *cstr)
Definition: symbols.h:723
static TypePtr DartFunctionType()
static TypePtr SmiType()
int value() const
Definition: scopes.h:69
#define ASSERT(E)
Dart_NativeFunction function
Definition: fuchsia.cc:51
Definition: dart_vm.cc:33
const char *const name
@ kIllegalCid
Definition: class_id.h:214
@ kDynamicCid
Definition: class_id.h:253
#define T
Definition: parser.cc:43
#define INIT_FIELD(Name, TypeName, Symbol)
#define Z
Definition: parser.cc:45
#define FOR_EACH_DYNAMIC_CLOSURE_CALL_VARIABLE(V)
Definition: parser.h:273
#define Pd
Definition: globals.h:408
ZoneGrowableArray< LocalVariable * > named_argument_parameter_indices
Definition: parser.h:286